From d17c4b1425babae8ab12a456caf821e25f5c1420 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Tue, 2 Jul 2024 18:47:56 +0200 Subject: [PATCH] chore: tool-belts standalone & bump to eslint8 (#1105) - tool-belts as standalone setups/projects - migrate to eslint8 --------- Signed-off-by: Jan Kowalleck --- .c8rc.json | 4 +- .eslintignore | 20 --- .eslintrc.js | 170 ------------------ .github/dependabot.yml | 4 +- .github/workflows/nodejs.yml | 125 ++++++++----- .github/workflows/release.yml | 9 +- .mocharc.js | 4 +- .npmignore | 3 +- .npmrc | 2 + .readthedocs.yaml | 5 +- CONTRIBUTING.md | 2 +- README.md | 2 - eslint.config.mjs | 109 +++++++++++ .../typescript/example.cjs/src/example.ts | 2 + .../typescript/example.mjs/src/example.ts | 2 + package.json | 19 +- src/serialize/xmlSerializer.node.ts | 1 + src/validation/jsonValidator.node.ts | 1 + src/validation/xmlValidator.node.ts | 1 + tools/code-style/.gitignore | 1 + tools/code-style/.npmrc | 2 + tools/code-style/eslint.config.mjs | 163 +++++++++++++++++ tools/code-style/package.json | 24 ++- tools/docs-gen/.gitignore | 3 + tools/docs-gen/.npmrc | 2 + tools/docs-gen/package.json | 10 +- tools/docs-gen/tsdoc.json | 4 + tools/schema-downloader/.gitignore | 1 + tools/schema-downloader/.npmrc | 2 + tools/schema-downloader/download.js | 2 - tools/schema-downloader/eslint.config.mjs | 37 ++++ tools/schema-downloader/package.json | 3 +- tsdoc.json | 2 +- typedoc.json | 2 +- typedoc.node.json | 4 +- typedoc.web.json | 4 +- 36 files changed, 454 insertions(+), 297 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.js create mode 100644 eslint.config.mjs create mode 100644 tools/code-style/eslint.config.mjs create mode 100644 tools/docs-gen/tsdoc.json create mode 100644 tools/schema-downloader/eslint.config.mjs diff --git a/.c8rc.json b/.c8rc.json index 22a947e1d..d557ff7d9 100644 --- a/.c8rc.json +++ b/.c8rc.json @@ -10,10 +10,12 @@ "**/*.cache/**", "{,CI_}reports/**", "test{,s}/**", + "tools/**", "**/{ava,babel,nyc}.config.{js,cjs,mjs}", "**/jest.config.{js,cjs,mjs,ts}", "**/{karma,rollup,webpack}.config.js", - "**/.{eslint,mocha}rc.{js,cjs}" + "**/.{eslint,mocha}rc.{js,cjs,mjs}", + "**/eslint.config.{js,cjs,mjs}" ], "reporter": ["text", "clover", "html"], "reporterOptions": { diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 49a90a7ae..000000000 --- a/.eslintignore +++ /dev/null @@ -1,20 +0,0 @@ -**/node_modules/** - -# generated files: dist and docs -/reports/** -/dist/** -/dist.*/** -/docs/api/** -/docs/_build/** -/docs/.venv/** -/examples/**/dist/** - -/res/schema/ - -!/src/** - -!/tools/schema-downloader/** - - -**/.idea/** -**/.vscode/** diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 44d082341..000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,170 +0,0 @@ -/*! -This file is part of CycloneDX JavaScript Library. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -SPDX-License-Identifier: Apache-2.0 -Copyright (c) OWASP Foundation. All Rights Reserved. -*/ - -const path = require('path') - -/* eslint-disable jsdoc/valid-types */ - -/** - * @type {import('eslint').Linter.Config} - * @see https://eslint.org/ - */ -module.exports = { - root: true, - plugins: [ - /* see https://github.com/lydell/eslint-plugin-simple-import-sort#readme */ - 'simple-import-sort', - /* see https://github.com/Stuk/eslint-plugin-header#readme */ - 'header', - /* see https://github.com/phanect/eslint-plugin-editorconfig */ - 'editorconfig' - ], - env: { - commonjs: true, - browser: true, - node: true - }, - extends: [ - /* see https://github.com/phanect/eslint-plugin-editorconfig */ - 'plugin:editorconfig/all' - ], - rules: { - // region sort imports/exports - /* disable other sorters in favour of `simple-import-sort` */ - 'import/order': 'off', - 'sort-imports': 'off', - /* see https://github.com/lydell/eslint-plugin-simple-import-sort/ */ - 'simple-import-sort/imports': 'error', - 'simple-import-sort/exports': 'error', - // endregion sort imports/exports - // region license-header - /* see https://github.com/Stuk/eslint-plugin-header#readme */ - 'header/header': ['error', path.join(__dirname, '.license-header.js')], - // endregion license-header - // indent is managed by plugin '*standard' - 'editorconfig/indent': 'off' - }, - overrides: [ - { - files: ['*.node.*'], - env: { browser: false, node: true } - }, - { - files: ['*.web.*'], - env: { browser: true, node: false } - }, - { - files: ['*.spec.*', '*.test.*'], - env: { - mocha: true, - node: true, - browser: false // change, when mocha is enabled for browser - } - }, - { - files: ['*.ts'], - plugins: [ - /* see https://github.com/microsoft/tsdoc */ - 'eslint-plugin-tsdoc' - ], - extends: [ - /* see https://github.com/mightyiam/eslint-config-love */ - 'love' - ], - rules: { - // region override rules from plugin 'standard-with-typescript' - /* @see https://typescript-eslint.io/rules/consistent-type-imports/ */ - '@typescript-eslint/consistent-type-imports': ['error', { - /* we need our generated declaration files backward compatible to TS3.8 - * see https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html - */ - fixStyle: 'separate-type-imports' - }], - /* @see https://typescript-eslint.io/rules/unbound-method/ */ - '@typescript-eslint/unbound-method': ['error', { - ignoreStatic: true - }], - // endregion override rules from plugin 'standard-with-typescript' - // region docs - /* see https://github.com/microsoft/tsdoc */ - 'tsdoc/syntax': 'error' - // endregion docs - }, - parserOptions: { - project: path.join(__dirname, 'tsconfig.json') - } - }, - { - files: ['examples/node/typescript/example.cjs/src/*.ts'], - parserOptions: { - project: path.join(__dirname, '/examples/node/typescript/example.cjs/tsconfig.json') - } - }, - { - files: ['examples/node/typescript/example.mjs/src/*.ts'], - parserOptions: { - project: path.join(__dirname, '/examples/node/typescript/example.mjs/tsconfig.json') - } - }, - { - files: ['*.js', '*.mjs', '*.cjs'], - plugins: [ - /* see https://github.com/gajus/eslint-plugin-jsdoc/ */ - 'jsdoc' - ], - extends: [ - /* see https://www.npmjs.com/package/eslint-config-standard */ - 'standard', - /* see https://github.com/gajus/eslint-plugin-jsdoc */ - 'plugin:jsdoc/recommended' - ], - rules: { - /* see https://github.com/gajus/eslint-plugin-jsdoc */ - 'jsdoc/no-undefined-types': 'error', - 'jsdoc/check-tag-names': 0, - 'jsdoc/check-types': 'error', - 'jsdoc/require-hyphen-before-param-description': ['error', 'always'], - 'jsdoc/require-jsdoc': 0, - 'jsdoc/require-param': 0, - 'jsdoc/require-param-description': 0, - 'jsdoc/require-param-name': 'error', - 'jsdoc/require-param-type': 'error', - 'jsdoc/require-property': 0, - 'jsdoc/require-property-description': 0, - 'jsdoc/require-property-name': 'error', - 'jsdoc/require-property-type': 'error', - 'jsdoc/require-returns': 0, - 'jsdoc/require-returns-check': 'error', - 'jsdoc/require-returns-description': 0, - 'jsdoc/require-returns-type': 'error', - 'jsdoc/require-throws': 'error', - 'jsdoc/require-yields': 0, - 'jsdoc/require-yields-check': 'error', - 'jsdoc/sort-tags': 'warn' - // region docs - }, - settings: { - jsdoc: { - /* see https://github.com/gajus/eslint-plugin-jsdoc */ - mode: 'jsdoc' - } - } - } - ] -} diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c999846fb..ec579bf09 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -23,9 +23,11 @@ updates: patterns: - 'eslint' - '@eslint/*' - - '@types/eslint' + - '*-eslint' - 'eslint-*' + - '@types/eslint' - '@types/eslint-*' + - '@types/*-eslint' - '@eslint-community/*' - '@typescript-eslint/*' spdx: diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 601fe1c0c..0794c6e2e 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -95,18 +95,23 @@ jobs: # cache: "npm" # cache-dependency-path: "**/package-lock.json" - name: setup project - run: > - npm i - --ignore-scripts --loglevel=silly - -w tools/code-style --include-workspace-root + run: | + echo "::group::install deps" + npm i --ignore-scripts --loglevel=silly + echo "::endgroup::" + echo "::group::install docs-gen deps" + npm --prefix tools/docs-gen i --ignore-scripts --loglevel=silly + echo "::endgroup::" + echo "::group::install code-style deps" + npm --prefix tools/code-style i --ignore-scripts --loglevel=silly + echo "::endgroup::" - name: make reports dir run: mkdir -p "$REPORTS_DIR" - name: test run: > - npm run -- - test:standard -- + npm run -- test:standard --format checkstyle - --output-file "$REPORTS_DIR/eslint.xml" + --output-file "$PWD/$REPORTS_DIR/eslint.xml" - name: Publish Checkstyle report # see https://github.com/Juuxel/publish-checkstyle-report uses: Juuxel/publish-checkstyle-report@v1 @@ -153,46 +158,62 @@ jobs: with: node-version: ${{ matrix.node-version }} # do not use caching, use fresh version always, since some deps are not pinned -- since this is a library. + - name: bump npm + shell: bash + env: + NODE_VERSION: '${{ matrix.node-version }}' + run: + case "$NODE_VERSION" in + '20' | '18') + npm i -g npm@^10 + ;; + '16') + npm i -g npm@^9 + ;; + '14') + npm i -g npm@^8 + ;; + '14.0.0') + npm i -g npm@^7 + ;; + esac - name: setup project shell: bash env: NODE_VERSION: '${{ matrix.node-version }}' run: | set -ex - dep_constraints='' - dev_requirements=' c8 mocha npm-run-all2 fast-glob ' + + # for the purpose of testing strange setups, + # we need to craft compatible versions by hand, + # and might utilize `npm_config_engine_strict=false` + + dev_constraints=' npm-run-all2 c8 mocha fast-glob ' # as long as npm cannot auto-resolve engine-constraints, we need to help here case "$NODE_VERSION" in '16') - dev_requirements="${dev_requirements/ c8 / c8@^9 }" + dev_constraints="${dev_constraints/ c8 / c8@^9 }" ;; '14') - dev_requirements="${dev_requirements/ c8 / c8@^9 }" - dev_requirements="${dev_requirements/ npm-run-all2 / npm-run-all2@^5 }" + dev_constraints="${dev_constraints/ c8 / c8@^9 }" + dev_constraints="${dev_constraints/ npm-run-all2 / npm-run-all2@^5 }" ;; '14.0.0') - dev_requirements="${dev_requirements/ c8 / c8@^8 }" - dev_requirements="${dev_requirements/ npm-run-all2 / npm-run-all2@^5 }" + dev_constraints="${dev_constraints/ c8 / c8@^8 }" + dev_constraints="${dev_constraints/ npm-run-all2 / npm-run-all2@^5 }" + export npm_config_engine_strict=false ;; esac - echo "::group::install dep_constraints" - ## !! dont install all the dev-packages, especially since some are not runnable on node 14.0.0 - if [[ -n "$dep_constraints" ]] - then - npm add --workspaces=false --ignore-scripts --omit=dev --only=prod --production --loglevel=silly --save $dep_constraints - fi + echo "::group::install prod" + npm_config_engine_strict=false npm i --ignore-scripts --include=optional --omit=dev --only=prod --production --loglevel=silly echo "::endgroup::" - echo "::group::install deps" - npm i --workspaces=false --ignore-scripts --include=optional --omit=dev --only=prod --production --loglevel=silly + echo "::group::install dev" + npm i --ignore-scripts --loglevel=silly --no-save $dev_constraints echo "::endgroup::" - echo "::group::install libxmljs2 " + echo "::group::rebuild libxmljs2" ## rebuild deps for which scripts were ignored, or partially installed - since "ignore-scripts" was used npm rebuild --loglevel=silly libxmljs2 || npm uninstall --no-save libxmljs2 echo "::endgroup::" - echo "::group::install dev_requirements" - ## install the needed dev-deps - npm i --workspaces=false --ignore-scripts --loglevel=silly --no-save $dev_requirements - echo "::endgroup::" - name: fetch build artifact # see https://github.com/actions/download-artifact uses: actions/download-artifact@v4 @@ -236,10 +257,13 @@ jobs: - name: setup library run: | set -ex - ## dont install all the dev-packages, especially since some are not runnable on node 14.0.0 + echo "::group::install prod" npm i --ignore-scripts --omit=optional --omit=dev --loglevel=silly + echo "::endgroup::" + echo "::endgroup::install dev" ## install the needed dev-deps npm i --ignore-scripts --omit=optional --no-save --loglevel=silly mocha c8 npm-run-all2 fast-glob + echo "::endgroup::" - name: fetch build artifact # see https://github.com/actions/download-artifact uses: actions/download-artifact@v4 @@ -251,7 +275,7 @@ jobs: - name: collect coverage if: ${{ failure() || success() }} run: > - npx c8 report + npm exec -- c8 report --reporter clover --reports-dir '${{ env.REPORTS_DIR }}/coverage/no-optional-deps' - name: artifact test reports @@ -279,21 +303,14 @@ jobs: path: ${{ env.REPORTS_DIR }} - name: Run codacy-coverage-reporter env: - CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} + CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} ## see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-using-secrets if: ${{ env.CODACY_PROJECT_TOKEN != '' }} - # see https://github.com/codacy/codacy-coverage-reporter-action/blob/8a27d704d4ea6890aee42477b231c4fbbebac2ae/action.yml#L59 - run: | - set -eux - auth="--project-token '$CODACY_PROJECT_TOKEN'" - reports='' - for report in $REPORTS_DIR/coverage/*/* - do - reports="$reports -r '$report'" - done - bash <(curl -Ls https://raw.githubusercontent.com/codacy/codacy-coverage-reporter/master/get.sh) report $auth $reports --partial -l TypeScript &&\ - bash <(curl -Ls https://raw.githubusercontent.com/codacy/codacy-coverage-reporter/master/get.sh) report $auth $reports --partial -l Javascript &&\ - bash <(curl -Ls https://raw.githubusercontent.com/codacy/codacy-coverage-reporter/master/get.sh) final $auth + # see https://github.com/codacy/codacy-coverage-reporter-action + uses: codacy/codacy-coverage-reporter-action@v1 + with: + project-token: ${{ env.CODACY_PROJECT_TOKEN }} + coverage-reports: ${{ env.REPORTS_DIR }}/coverage/*/* examples-JS: @@ -324,9 +341,13 @@ jobs: - name: setup library run: | set -ex + echo "::group::install" npm i --ignore-scripts --omit=dev --include=optional --loglevel=silly + echo "::endgroup::" + echo "::group::setup libxml2" ## rebuild deps for which scripts were ignored, or partially installed - since "ignore-scripts" was used npm rebuild --loglevel=silly libxmljs2 || npm uninstall --no-save libxmljs2 + echo "::endgroup::" - name: setup example project run: npm i --no-save --loglevel=silly working-directory: ${{ env.EXAMPLE_DIR }} @@ -377,9 +398,13 @@ jobs: - name: setup library run: | set -ex + echo "::group::install" npm i --ignore-scripts --omit=dev --include=optional --loglevel=silly + echo "::endgroup::" + echo "::group::setup libxml2" ## rebuild deps for which scripts were ignored, or partially installed - since "ignore-scripts" was used npm rebuild --loglevel=silly libxmljs2 || npm uninstall --no-save libxmljs2 + echo "::endgroup::" - name: setup example project run: npm i --no-save --loglevel=silly 'typescript@${{ matrix.typescript-version }}' working-directory: ${{ env.EXAMPLE_DIR }} @@ -455,11 +480,13 @@ jobs: # cache: "npm" # cache-dependency-path: "**/package-lock.json" - name: setup project - run: > - npm install - --ignore-scripts --loglevel=silly - -w tools/docs-gen --include-workspace-root + run: | + set -ex + echo "::group::install project" + npm install --ignore-scripts --loglevel=silly + echo "::endgroup::" + echo "::group::install docs-gen" + npm --prefix tools/docs-gen install --ignore-scripts --loglevel=silly + echo "::endgroup::" - name: api-doc ${{ matrix.target }} - run: > - npm run -w tools/docs-gen - api-doc:${{ matrix.target }} + run: npm run api-doc:${{ matrix.target }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3b122fddb..e3bc62e5b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -98,11 +98,10 @@ jobs: uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_ACTIVE_LTS }} - - name: install build tools - run: > - npm install - --ignore-scripts --include=optional --loglevel=silly - -w tools/code-style --include-workspace-root + - name: setup project + run: | + npm install --ignore-scripts --include=optional --loglevel=silly + npm --prefix tools/code-style install --ignore-scripts --loglevel=silly # no explicit npm build. if a build is required, it should be configured as prepublish/prepublishOnly script of npm. - name: login to registries run: | diff --git a/.mocharc.js b/.mocharc.js index 218c0b2a0..fd974868d 100644 --- a/.mocharc.js +++ b/.mocharc.js @@ -17,11 +17,13 @@ SPDX-License-Identifier: Apache-2.0 Copyright (c) OWASP Foundation. All Rights Reserved. */ +/* eslint-disable jsdoc/valid-types */ + /** * mocha config + * @type {import('@types/mocha').Mocha.MochaOptions} * @see {@link https://mochajs.org/#configuring-mocha-nodejs} * @see {@link https://github.com/mochajs/mocha/blob/master/example/config/.mocharc.js example} - * @type {import('@types/mocha').Mocha.MochaOptions} */ module.exports = { timeout: 10000, diff --git a/.npmignore b/.npmignore index 4c6330b20..9087536ee 100644 --- a/.npmignore +++ b/.npmignore @@ -166,8 +166,6 @@ dist !/src/ !/tsconfig.* !/webpack.* -!/typedoc.* -!/tsdoc.json /test/ /tests/ @@ -177,6 +175,7 @@ dist /examples/ /tools/ +eslint.* /reports/ /CI_reports/ diff --git a/.npmrc b/.npmrc index 8f83f7382..147970caf 100644 --- a/.npmrc +++ b/.npmrc @@ -1,3 +1,5 @@ ; see the docs: https://docs.npmjs.com/cli/v9/using-npm/config package-lock=false +engine-strict=true +omit=peer # don't install them automatically; we take cate of them! diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 56b73a6b0..cc72491e2 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -15,8 +15,9 @@ build: # golang: "1.20" jobs: pre_build: - - npm i --ignore-scripts --loglevel=silly -w tools/docs-gen --include-workspace-root - - npm run api-doc + - npm i --ignore-scripts --loglevel=silly + - npm --prefix tools/docs-gen i --ignore-scripts --loglevel=silly + - npm --prefix tools/docs-gen run api-doc # Build documentation in the docs/ directory with Sphinx sphinx: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 172b1585a..a5a474021 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,7 +13,7 @@ it requires node>=18 on dev-time. Install dependencies: ```shell -npm install --workspaces --include-workspace-root +npm run dev-setup ``` The setup will also build the project. diff --git a/README.md b/README.md index 917378d5e..580468e11 100644 --- a/README.md +++ b/README.md @@ -179,8 +179,6 @@ We ship annotated type definitions, so that your IDE and tools may pick up the d There are also pre-rendered documentations hosted on [readthedocs][link_rtfd]. -Additionally, there is a prepared set of configs for [TypeDoc](https://typedoc.org), so that you can build the API documentation from source via `npm run api-doc`. - ## Development & Contributing Feel free to open issues, bug reports or pull requests. diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 000000000..fc6855bcb --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,109 @@ +/*! +This file is part of CycloneDX JavaScript Library. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +SPDX-License-Identifier: Apache-2.0 +Copyright (c) OWASP Foundation. All Rights Reserved. +*/ + +import path from 'node:path' +import { fileURLToPath } from 'node:url' + +import { default as baseCfg, globals } from './tools/code-style/eslint.config.mjs' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) + +/* eslint-disable jsdoc/valid-types */ + +/** + * @type {import('@types/eslint').Linter.FlatConfig[]} + * @see {@link https://eslint.org/} + */ +export default [ + ...baseCfg, + { + files: ['**/*.js'], + languageOptions: { sourceType: 'commonjs' } + }, + { + files: ['{src,tests}/**/*!(.{node,web}).{js,mjs,cjs.ts}'], + languageOptions: { + globals: { + ...globals.browser, + ...globals.node + } + } + }, + { + files: [ + '**/*.{test,spec}.{js,mjs,cjs,ts}', + 'tests/**.{js,mjs,cjs,ts}' + ], + languageOptions: { + globals: globals.mocha + } + }, + { + files: ['src/**/*.ts'], + languageOptions: { + parserOptions: { + project: path.join(__dirname, 'tsconfig.json'), + }, + }, + }, + { + files: ['examples/node/**/*.{js,mjs,cjs,ts}'], + languageOptions: { + globals: globals.node + } + }, + { + files: ['examples/web/*/src/**'], + languageOptions: { + globals: globals.browser + } + }, + { + files: ['examples/node/typescript/example.cjs/src/*.ts'], + languageOptions: { + parserOptions: { + project: path.join(__dirname, 'examples', 'node', 'typescript', 'example.cjs', 'tsconfig.json') + }, + }, + }, + { + files: ['examples/node/typescript/example.mjs/src/*.ts'], + languageOptions: { + parserOptions: { + project: path.join(__dirname, 'examples', 'node', 'typescript', 'example.mjs', 'tsconfig.json' + ) + }, + }, + }, + { + // global ignores must have nothing but a "ignores" property! + // see https://github.com/eslint/eslint/discussions/17429#discussioncomment-6579229 + ignores: [ + 'reports/', + 'dist.*/', + 'docs/api/', + 'docs/_build/', + 'docs/.venv/', + 'examples/**/dist/', + 'res/schema/', + 'tools/', + ], + }, +] diff --git a/examples/node/typescript/example.cjs/src/example.ts b/examples/node/typescript/example.cjs/src/example.ts index 460d2598a..bc38a42fe 100644 --- a/examples/node/typescript/example.cjs/src/example.ts +++ b/examples/node/typescript/example.cjs/src/example.ts @@ -65,6 +65,7 @@ jsonValidator.validate(serializedJson) if (err instanceof CDX.Validation.MissingOptionalDependencyError) { console.info('JSON validation skipped:', err) } else { + /* eslint-disable-next-line @typescript-eslint/only-throw-error -- forward */ throw err } }) @@ -86,6 +87,7 @@ xmlValidator.validate(serializedXML) if (err instanceof CDX.Validation.MissingOptionalDependencyError) { console.info('XML validation skipped:', err) } else { + /* eslint-disable-next-line @typescript-eslint/only-throw-error -- forward */ throw err } }) diff --git a/examples/node/typescript/example.mjs/src/example.ts b/examples/node/typescript/example.mjs/src/example.ts index 8c35056aa..443587fa3 100644 --- a/examples/node/typescript/example.mjs/src/example.ts +++ b/examples/node/typescript/example.mjs/src/example.ts @@ -64,6 +64,7 @@ try { if (err instanceof CDX.Validation.MissingOptionalDependencyError) { console.info('JSON validation skipped:', err) } else { + /* eslint-disable-next-line @typescript-eslint/only-throw-error -- forward */ throw err } } @@ -84,6 +85,7 @@ try { if (err instanceof CDX.Validation.MissingOptionalDependencyError) { console.info('XML validation skipped:', err) } else { + /* eslint-disable-next-line @typescript-eslint/only-throw-error -- forward */ throw err } } diff --git a/package.json b/package.json index 7fb7f0e2d..6689a9c0c 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "fast-glob": "^3.3.1", "mocha": "10.5.2", "npm-run-all2": "^5||^6", - "rimraf": "^5.0.7", + "rimraf": "^4||^5", "ts-loader": "9.5.1", "typescript": "5.4.5", "webpack": "5.92.1", @@ -164,13 +164,10 @@ "test": "./tests", "example": "./examples" }, - "workspaces": [ - "tools/schema-downloader", - "tools/docs-gen", - "tools/code-style" - ], "scripts": { - "dev-setup": "npm install --workspaces --include-workspace-root", + "dev-setup": "npm i && run-p --aggregate-output -lc dev-setup:*", + "dev-setup:code-style": "npm --prefix tools/code-style install", + "dev-setup:docs-gen": "npm --prefix tools/docs-gen install", "prepublish": "npm run build", "prepublishOnly": "run-s -lc build test", "build": "run-p --aggregate-output -l build:*", @@ -180,12 +177,14 @@ "build:web": "webpack build", "prebuild:d": "rimraf dist.d", "build:d": "tsc -b ./tsconfig.d.json", - "cs-fix": "npm run-script -w tools/code-style cs-fix", "test": "run-p --aggregate-output -lc test:*", "test:node": "c8 mocha -p", "test:web": "node -e 'console.log(\"TODO: write web test\")'", "test:lint": "tsc --noEmit", - "test:standard": "npm run-script -w tools/code-style test", - "api-doc": "npm run-script -w tools/docs-gen api-doc" + "test:standard": "npm --prefix tools/code-style exec -- eslint .", + "cs-fix": "npm --prefix tools/code-style exec -- eslint --fix .", + "api-doc": "run-p --aggregate-output -lc api-doc:*", + "api-doc:node": "npm --prefix tools/docs-gen exec -- typedoc --options ./typedoc.node.json", + "api-doc:web": "npm --prefix tools/docs-gen exec -- typedoc --options ./typedoc.web.json" } } diff --git a/src/serialize/xmlSerializer.node.ts b/src/serialize/xmlSerializer.node.ts index bfc6ce056..7b0902a57 100644 --- a/src/serialize/xmlSerializer.node.ts +++ b/src/serialize/xmlSerializer.node.ts @@ -44,6 +44,7 @@ export class XmlSerializer extends XmlBaseSerializer { if (err instanceof OptPlugError) { throw new MissingOptionalDependencyError(err.message, err) } + /* eslint-disable-next-line @typescript-eslint/only-throw-error -- forward */ throw err } } diff --git a/src/validation/jsonValidator.node.ts b/src/validation/jsonValidator.node.ts index 106afff1f..50b39360b 100644 --- a/src/validation/jsonValidator.node.ts +++ b/src/validation/jsonValidator.node.ts @@ -49,6 +49,7 @@ abstract class BaseJsonValidator extends BaseValidator { if (err instanceof OptPlugError) { throw new MissingOptionalDependencyError(err.message, err) } + /* eslint-disable-next-line @typescript-eslint/only-throw-error -- forward */ throw err } } diff --git a/src/validation/xmlValidator.node.ts b/src/validation/xmlValidator.node.ts index ea5c4fc90..322e7772e 100644 --- a/src/validation/xmlValidator.node.ts +++ b/src/validation/xmlValidator.node.ts @@ -43,6 +43,7 @@ export class XmlValidator extends BaseValidator { if (err instanceof OptPlugError) { throw new MissingOptionalDependencyError(err.message, err) } + /* eslint-disable-next-line @typescript-eslint/only-throw-error -- forward */ throw err } } diff --git a/tools/code-style/.gitignore b/tools/code-style/.gitignore index c1b13780e..8c39e53f4 100644 --- a/tools/code-style/.gitignore +++ b/tools/code-style/.gitignore @@ -2,3 +2,4 @@ !/.gitignore !/package.json !/.npmrc +!/eslint.config.mjs diff --git a/tools/code-style/.npmrc b/tools/code-style/.npmrc index 8f83f7382..147970caf 100644 --- a/tools/code-style/.npmrc +++ b/tools/code-style/.npmrc @@ -1,3 +1,5 @@ ; see the docs: https://docs.npmjs.com/cli/v9/using-npm/config package-lock=false +engine-strict=true +omit=peer # don't install them automatically; we take cate of them! diff --git a/tools/code-style/eslint.config.mjs b/tools/code-style/eslint.config.mjs new file mode 100644 index 000000000..33f6db9b5 --- /dev/null +++ b/tools/code-style/eslint.config.mjs @@ -0,0 +1,163 @@ +/*! +This file is part of CycloneDX JavaScript Library. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +SPDX-License-Identifier: Apache-2.0 +Copyright (c) OWASP Foundation. All Rights Reserved. +*/ + +import path from 'node:path' +import { fileURLToPath } from 'node:url' + +import plugin_js from '@eslint/js' +import config_love from 'eslint-config-love' +import plugin_editorconfig from 'eslint-plugin-editorconfig' +import plugin_header from 'eslint-plugin-header' +import plugin_jsdoc from 'eslint-plugin-jsdoc' +import plugin_simpleImportSort from 'eslint-plugin-simple-import-sort' +import plugin_tsdoc from 'eslint-plugin-tsdoc' +import globals from 'globals' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) +const projectRoot = path.dirname(path.dirname(__dirname)) + +/* eslint-disable jsdoc/valid-types */ + +const licenseHeaderFile = path.join(projectRoot, '.license-header.js') + +/** + * @type {import('@types/eslint').Linter.FlatConfig[]} + * @see {@link https://eslint.org/} + */ +export default [ + { + name: 'general', + plugins: { + 'simple-import-sort': plugin_simpleImportSort, + 'header': plugin_header, + 'editorconfig': plugin_editorconfig, + }, + rules: { + ...plugin_editorconfig.configs.all.rules, + 'import/order': 'off', + 'sort-imports': 'off', + 'simple-import-sort/imports': 'error', + 'simple-import-sort/exports': 'error', + 'header/header': ['error', licenseHeaderFile], + 'editorconfig/indent': 'off', + }, + }, + { + files: ['**/*.{js,mjs,cjs}'], + rules: plugin_js.configs.recommended.rules, + }, + { + ...plugin_jsdoc.configs['flat/recommended'], + files: ['**/*.{js,mjs,cjs}'], + }, + { + name: 'jsdoc-override', + files: ['**/*.{js,mjs,cjs}'], + plugins: { + 'jsdoc': plugin_jsdoc, + }, + settings: { + jsdoc: { + mode: 'jsdoc', + }, + }, + rules: { + 'jsdoc/no-undefined-types': 'error', + 'jsdoc/check-tag-names': 0, + 'jsdoc/check-types': 'error', + 'jsdoc/require-hyphen-before-param-description': ['error', 'always'], + 'jsdoc/require-jsdoc': 0, + 'jsdoc/require-param': 0, + 'jsdoc/require-param-description': 0, + 'jsdoc/require-param-name': 'error', + 'jsdoc/require-param-type': 'error', + 'jsdoc/require-property': 0, + 'jsdoc/require-property-description': 0, + 'jsdoc/require-property-name': 'error', + 'jsdoc/require-property-type': 'error', + 'jsdoc/require-returns': 0, + 'jsdoc/require-returns-check': 'error', + 'jsdoc/require-returns-description': 0, + 'jsdoc/require-returns-type': 'error', + 'jsdoc/require-throws': 'error', + 'jsdoc/require-yields': 0, + 'jsdoc/require-yields-check': 'error', + 'jsdoc/sort-tags': 'warn', + } + }, + { + ...config_love, + files: ['**/*.ts'] + }, + { + files: ['**/*.ts'], + plugins: { + 'tsdoc': plugin_tsdoc, + }, + languageOptions: { + parserOptions: { + // override + project: false, + }, + }, + rules: { + '@typescript-eslint/consistent-type-imports': ['error', { + fixStyle: 'separate-type-imports', + }], + '@typescript-eslint/unbound-method': ['error', { + ignoreStatic: true, + }], + 'tsdoc/syntax': 'error', + }, + }, + { + files:[ + '**/eslint.config.{js,mjs,cjs}', + '**/webpack.config.js', + '**/.mocharc.js' + ], + languageOptions: { + globals: globals.node + } + }, + { + files: ['**/*.node.{js,mjs,cjs.ts}'], + languageOptions: { + globals: globals.node + } + }, + { + files: ['**/*.web.{js,mjs,cjs.ts}'], + languageOptions: { + globals: globals.browser + } + }, + { + // global ignores must have nothing but a "ignores" property! + // see https://github.com/eslint/eslint/discussions/17429#discussioncomment-6579229 + ignores: [ + '**/.idea/', + '**/.vscode/', + licenseHeaderFile, + ], + } +] + +export { globals } diff --git a/tools/code-style/package.json b/tools/code-style/package.json index 01e026adc..9fd04d599 100644 --- a/tools/code-style/package.json +++ b/tools/code-style/package.json @@ -6,24 +6,20 @@ "node": ">=20" }, "dependencies": { - "@typescript-eslint/eslint-plugin": "6.21.0", - "@typescript-eslint/parser": "6.21.0", + "@eslint/eslintrc": "3.1.0", + "@eslint/js": "9.6.0", + "@types/eslint": "^8.56.10", "eslint": "8.57.0", - "eslint-config-love": "43.1.0", - "eslint-config-standard": "17.1.0", + "eslint-config-love": "53.0.0", "eslint-plugin-editorconfig": "4.0.3", "eslint-plugin-header": "3.1.1", "eslint-plugin-import": "2.29.1", - "eslint-plugin-jsdoc": "48.2.8", - "eslint-plugin-n": "16.6.2", - "eslint-plugin-promise": "6.2.0", + "eslint-plugin-jsdoc": "48.5.0", + "eslint-plugin-n": "15.7.0", + "eslint-plugin-promise": "6.4.0", "eslint-plugin-simple-import-sort": "12.1.0", "eslint-plugin-tsdoc": "0.3.0", - "@cyclonedx/cyclonedx-library-docs-gen": "file:../docs-gen" - }, - "scripts": { - "test": "cd ../..; eslint .", - "cs-fix": "cd ../..; eslint --fix ." - }, - "workspaces": [] + "globals": "^15.7.0", + "typescript-eslint": "7.14.1" + } } diff --git a/tools/docs-gen/.gitignore b/tools/docs-gen/.gitignore index c1b13780e..e06506567 100644 --- a/tools/docs-gen/.gitignore +++ b/tools/docs-gen/.gitignore @@ -2,3 +2,6 @@ !/.gitignore !/package.json !/.npmrc +!/tsdoc.json +!/typedoc.json +!/typedoc.*.json diff --git a/tools/docs-gen/.npmrc b/tools/docs-gen/.npmrc index 8f83f7382..147970caf 100644 --- a/tools/docs-gen/.npmrc +++ b/tools/docs-gen/.npmrc @@ -1,3 +1,5 @@ ; see the docs: https://docs.npmjs.com/cli/v9/using-npm/config package-lock=false +engine-strict=true +omit=peer # don't install them automatically; we take cate of them! diff --git a/tools/docs-gen/package.json b/tools/docs-gen/package.json index f77a5e28f..f36906500 100644 --- a/tools/docs-gen/package.json +++ b/tools/docs-gen/package.json @@ -6,15 +6,7 @@ "node": ">=20" }, "dependencies": { - "@cyclonedx/cyclonedx-library-docs-gen": "file:", - "npm-run-all2": "^6.1.2", "typedoc": "^0.25.0", "typedoc-plugin-missing-exports": "^2.0.1" - }, - "scripts": { - "api-doc": "run-p --aggregate-output -lc api-doc:*", - "api-doc:node": "typedoc --options ../../typedoc.node.json", - "api-doc:web": "typedoc --options ../../typedoc.web.json" - }, - "workspaces": [] + } } diff --git a/tools/docs-gen/tsdoc.json b/tools/docs-gen/tsdoc.json new file mode 100644 index 000000000..b89839ca2 --- /dev/null +++ b/tools/docs-gen/tsdoc.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", + "extends": ["typedoc/tsdoc.json"] +} diff --git a/tools/schema-downloader/.gitignore b/tools/schema-downloader/.gitignore index c795cedd2..32c6dc6ec 100644 --- a/tools/schema-downloader/.gitignore +++ b/tools/schema-downloader/.gitignore @@ -3,3 +3,4 @@ !/package.json !/download.js !/.npmrc +!/eslint.config.mjs diff --git a/tools/schema-downloader/.npmrc b/tools/schema-downloader/.npmrc index 8f83f7382..147970caf 100644 --- a/tools/schema-downloader/.npmrc +++ b/tools/schema-downloader/.npmrc @@ -1,3 +1,5 @@ ; see the docs: https://docs.npmjs.com/cli/v9/using-npm/config package-lock=false +engine-strict=true +omit=peer # don't install them automatically; we take cate of them! diff --git a/tools/schema-downloader/download.js b/tools/schema-downloader/download.js index ad7acd6d3..0f0221e8d 100644 --- a/tools/schema-downloader/download.js +++ b/tools/schema-downloader/download.js @@ -17,8 +17,6 @@ SPDX-License-Identifier: Apache-2.0 Copyright (c) OWASP Foundation. All Rights Reserved. */ -'use strict' - import { writeFile } from 'node:fs/promises' import { dirname, join } from 'node:path' import { fileURLToPath } from 'node:url' diff --git a/tools/schema-downloader/eslint.config.mjs b/tools/schema-downloader/eslint.config.mjs new file mode 100644 index 000000000..8f2f0c6dd --- /dev/null +++ b/tools/schema-downloader/eslint.config.mjs @@ -0,0 +1,37 @@ +/*! +This file is part of CycloneDX JavaScript Library. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +SPDX-License-Identifier: Apache-2.0 +Copyright (c) OWASP Foundation. All Rights Reserved. +*/ + +import { default as baseCfg, globals } from '../code-style/eslint.config.mjs' + +/* eslint-disable jsdoc/valid-types */ + +/** + * @type {import('@types/eslint').Linter.FlatConfig[]} + * @see {@link https://eslint.org/} + */ +export default [ + ...baseCfg, + { + files: ['**/*.js'], + languageOptions: { + sourceType: 'module', + globals: globals.node, + } + }, +] diff --git a/tools/schema-downloader/package.json b/tools/schema-downloader/package.json index d02046baa..60c8e84d4 100644 --- a/tools/schema-downloader/package.json +++ b/tools/schema-downloader/package.json @@ -9,6 +9,5 @@ }, "engines": { "node": ">=18" - }, - "workspaces": [] + } } diff --git a/tsdoc.json b/tsdoc.json index 2fbc749d8..bdf82516d 100644 --- a/tsdoc.json +++ b/tsdoc.json @@ -1,6 +1,6 @@ { "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", - "extends": ["typedoc/tsdoc.json"], + "extends": ["./tools/docs-gen/tsdoc.json"], "tagDefinitions": [ { "tagName": "@since", diff --git a/typedoc.json b/typedoc.json index b62ef9866..66127b701 100644 --- a/typedoc.json +++ b/typedoc.json @@ -1,6 +1,6 @@ { "$schema": "https://typedoc.org/schema.json", - "tsconfig": "tsconfig.d.json", + "tsconfig": "./tsconfig.d.json", "plugin": [ "typedoc-plugin-missing-exports" ], diff --git a/typedoc.node.json b/typedoc.node.json index fb6dc73f6..3e5533c60 100644 --- a/typedoc.node.json +++ b/typedoc.node.json @@ -1,7 +1,7 @@ { "$schema": "https://typedoc.org/schema.json", "extends": ["./typedoc.json"], - "entryPoints": ["src/index.node.ts"], "name": "CycloneDX JavaScript Library - Node", - "out": "docs/api/typedoc/node/" + "entryPoints": ["./src/index.node.ts"], + "out": "./docs/api/typedoc/node/" } diff --git a/typedoc.web.json b/typedoc.web.json index 680c2fdc3..eec4a32c2 100644 --- a/typedoc.web.json +++ b/typedoc.web.json @@ -1,7 +1,7 @@ { "$schema": "https://typedoc.org/schema.json", "extends": ["./typedoc.json"], - "entryPoints": ["src/index.web.ts"], "name": "CycloneDX JavaScript Library - Web", - "out": "docs/api/typedoc/web/" + "entryPoints": ["./src/index.web.ts"], + "out": "./docs/api/typedoc/web/" }