diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 4d6e7bbd3..fa1027c23 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -364,9 +364,6 @@ jobs: - name: run example run: node -- 'example.${{ matrix.js-type }}' working-directory: ${{ env.EXAMPLE_DIR }} - - name: run deprecated - run: node -- 'deprecated.${{ matrix.js-type }}' - working-directory: ${{ env.EXAMPLE_DIR }} example-TS: needs: [ 'build' ] diff --git a/HISTORY.md b/HISTORY.md index ceb87a93a..419a29323 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -6,6 +6,84 @@ All notable changes to this project will be documented in this file. +* BREAKING changes + * Removed deprecated symbols + * Removed PackageUrl factories + * No longer use external standards' implementations directly +* Removed + * Entrypoint `Builders` (via [#1377]) + * Entrypoint `Factories` (via [#1377]) + * Entrypoint `Utils` (via [#1377]) + * Entrypoint `Contrib/PackageUrl` (via [#1378]) + * Deprecated symbol `Builders` ([#1346] via [#1377]) + * Deprecated symbol `Builders.FromNodePackageJson` ([#1346] via [#1377]) + * Deprecated symbol `Builders.FromNodePackageJson.ToolBuilder` ([#1346] via [#1377]) + Use `Contrib.FromNodePackageJson.Builders.ToolBuilder` instead. + * Deprecated symbol `Builders.FromNodePackageJson.ComponentBuilder` ([#1346] via [#1377]) + Use `Contrib.FromNodePackageJson.Builders.ComponentBuilder` instead. + * Deprecated symbol `Factories` ([#1346] via [#1377]) + * Deprecated symbol `Factories.FromNodePackageJson` ([#1346] via [#1377]) + * Deprecated symbol `Factories.FromNodePackageJson.ExternalReferenceFactory` ([#1346] via [#1377]) + Use `Contrib.FromNodePackageJson.Factories.ExternalReferenceFactory` instead. + * Deprecated symbol `Factories.FromNodePackageJson.PackageUrlFactory` ([#1346] via [#1377]) + Use `packageurl-js` downstream. + * Deprecated symbol `Factories.LicenseFactory` ([#1346], [#1348] via [#1377], [#1378]) + Use `Contrib.License.Factories.LicenseFactory` instead. + * Deprecated symbol `Factories.PackageUrlFactory` ([#1346] via [#1377]) + Use `packageurl-js` downstream. + * Deprecated symbol `Types.NodePackageJson` ([#1346], [#1348] via [#1377], [#1378]) + Use `Contrib.FromNodePackageJson.Types.NodePackageJson` instead. + * Deprecated symbol `Types.assertNodePackageJson` ([#1346] via [#1377]) + Use `Contrib.FromNodePackageJson.Types.assertNodePackageJson` instead. + * Deprecated symbol `Types.isNodePackageJson` ([#1346] via [#1377]) + Use `Contrib.FromNodePackageJson.Types.isNodePackageJson` instead. + * Deprecated symbol `Utils` ([#1346] via [#1377]) + * Deprecated symbol `Utils.BomUtility` ([#1346] via [#1377]) + * Deprecated symbol `Utils.BomUtility.randomSerialNumber` ([#1346] via [#1377]) + Use `Contrib.Bom.Utils.randomSerialNumber` instead. + * Deprecated symbol `Utils.LicenseUtility` ([#1346] via [#1377]) + * Deprecated symbol `Utils.LicenseUtility.FsUtils` ([#1346] via [#1377]) + Use `Contrib.License.Utils.FsUtils` instead. + * Deprecated symbol `Utils.LicenseUtility.PathUtils` ([#1346] via [#1377]) + * Use `Contrib.License.Utils.PathUtils` instead. + * Deprecated symbol `Utils.LicenseUtility.FileAttachment` ([#1346] via [#1377]) + Use `Contrib.License.Utils.FileAttachment` instead. + * Deprecated symbol `Utils.LicenseUtility.ErrorReporter` ([#1346] via [#1377]) + Use `Contrib.License.Utils.ErrorReporter` instead. + * Deprecated symbol `Utils.LicenseUtility.LicenseEvidenceGatherer` ([#1346] via [#1377]) + Use `Contrib.License.Utils.LicenseEvidenceGatherer` instead. + * Deprecated symbol `Utils.NpmjsUtility` ([#1346] via [#1377]) + * Deprecated symbol `Utils.NpmjsUtility.parsePackageIntegrity` ([#1346] via [#1377]) + Use `Contrib.FromNodePackageJson.Utils.parsePackageIntegrity` instead. + * Deprecated symbol `Utils.NpmjsUtility.defaultRegistryMatcher` ([#1346] via [#1377]) + Use `Contrib.FromNodePackageJson.Utils.defaultRegistryMatcher` instead. + * Symbol `Contrib.PackageUrl.Factories.PackageUrlFactory` ([#1348] via [#1378]) + Use `packageurl-js` downstream. + * Symbol `Contrib.FromNodePackageJson.Factories.PackageUrlFactory` ([#1348] via [#1378]) + Use `packageurl-js` downstream. + * Symbol `SPDX.isValidSpdxLicenseExpression` ([#1348] via [#1382]) + Use package `spdx-expression-parse` instead. +* Changed + * `Component.purl` is a `string` now, was `PackaheUrl` ([#1348] via [#1379]) + * Constructor of `Contrib.License.Factories.LicenseFactory` got an injectable argument `spdxExpressionValidate` for validating SPDX License Expressions ([#1348] via [#1382]) + Suggested implementation is `spdx-expression-parse`. +* Dependencies + * Dependency `packageurl-js` became a suggested (optional peer-dependency) library ([#1348] via [#1378]) + You may use it to craft and parse PackageURLs downstream. + * Dependency `spdx-expression-parse` became a suggested (optional peer-dependency) library ([#1348] via [#1382]) + Used as an injectable in `Contrib.License.Factories.LicenseFactory.constructor`. +* Chore + * Set dev-engines in `package.json` ([#1301] via [#1380]) + +[#1301]: https://github.com/CycloneDX/cyclonedx-javascript-library/issues/1301 +[#1346]: https://github.com/CycloneDX/cyclonedx-javascript-library/issues/1346 +[#1348]: https://github.com/CycloneDX/cyclonedx-javascript-library/issues/1348 +[#1377]: https://github.com/CycloneDX/cyclonedx-javascript-library/pull/1377 +[#1378]: https://github.com/CycloneDX/cyclonedx-javascript-library/pull/1378 +[#1379]: https://github.com/CycloneDX/cyclonedx-javascript-library/pull/1379 +[#1380]: https://github.com/CycloneDX/cyclonedx-javascript-library/pull/1380 +[#1382]: https://github.com/CycloneDX/cyclonedx-javascript-library/pull/1382 + ## 9.5.0 -- 2026-03-02 * Added diff --git a/README.md b/README.md index c28795774..6523bc1d5 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,6 @@ written in _TypeScript_ and compiled for the target. * Gather license evidences from files (for _Node.js_ only) * Factories for the following use cases: * Create data models from any license descriptor string - * Create `PackageURL` from `Component` data models * Specific to _Node.js_: create data models from PackageJson-like data structures and derived data * Builders for the following use cases: * Specific to _Node.js_: create deep data models `Tool` or `Component` from PackageJson-like data structures @@ -135,6 +134,12 @@ Some features require optional peer dependencies — see `package.json` for vers * [`libxmljs2`](https://www.npmjs.com/package/libxmljs2) * the system might need to meet the requirements for [`node-gyp`](https://github.com/TooTallNate/node-gyp#installation), in certain cases. +In addition, we have some suggestions for related 3rd-party standards: +* [`packageurl-js`](https://www.npmjs.com/package/packageurl-js) + for crafting and parsing PackageURLs. +* [`spdx-expression-parse`](https://www.npmjs.com/package/spdx-expression-parse) + for validating SPDX License Expressions. + ## Usage See extended [examples]. diff --git a/examples/node/javascript/deprecated.cjs b/examples/node/javascript/deprecated.cjs deleted file mode 100644 index bffbf78e5..000000000 --- a/examples/node/javascript/deprecated.cjs +++ /dev/null @@ -1,60 +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. -*/ - -/** - * Example showcasing the deprecated symbols still work. - * @see https://github.com/CycloneDX/cyclonedx-javascript-library/issues/1350 - */ - -const fs = require('node:fs') -const path = require('node:path') - -const CDX = require('@cyclonedx/cyclonedx-library') -// Full library is available as `CDX`, now. -// Alternative for better tree-shaking on bundling, import only the needed symbols like so: -// const { Bom, Component } = require('@cyclonedx/cyclonedx-library/Models') -// const { ComponentType } = require('@cyclonedx/cyclonedx-library/Enums') - -const dBU1 = CDX.Utils.BomUtility.randomSerialNumber() -console.log(dBU1) - -const dNU1 = CDX.Utils.NpmjsUtility.defaultRegistryMatcher.test('foo') -const dNU2 = CDX.Utils.NpmjsUtility.parsePackageIntegrity('sha1-aSbRsZT7xze47tUTdW3i/Np+pAg=') -console.log(dNU1, dNU2) - -const dLU1 = new CDX.Utils.LicenseUtility.LicenseEvidenceGatherer({fs, path}) -console.log(dLU1) - -/** @type {CDX.Types.NodePackageJson} */ -const dTnpj1 = {} -// const dTnpj2 =CDX.Types.isNodePackageJson(dTnpj1) -try { CDX.Types.assertNodePackageJson(dTnpj1) } catch { /* pass */ } -console.log(dTnpj1) - -const dF1 = new CDX.Factories.PackageUrlFactory('generic') -const dF2 = new CDX.Factories.LicenseFactory() -console.log(dF1, dF2) - -const dFnpj3 = new CDX.Factories.FromNodePackageJson.PackageUrlFactory('npm') -const dFnpj4 = new CDX.Factories.FromNodePackageJson.ExternalReferenceFactory() -console.log(dFnpj3, dFnpj4) - -const dBnpj1 = new CDX.Builders.FromNodePackageJson.ComponentBuilder(dFnpj4, dF2) -const dBnpj2 = new CDX.Builders.FromNodePackageJson.ToolBuilder(dFnpj4) -console.log(dBnpj1, dBnpj2) diff --git a/examples/node/javascript/deprecated.mjs b/examples/node/javascript/deprecated.mjs deleted file mode 100644 index db9ca6261..000000000 --- a/examples/node/javascript/deprecated.mjs +++ /dev/null @@ -1,60 +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. -*/ - -/** - * Example showcasing the deprecated symbols still work. - * @see https://github.com/CycloneDX/cyclonedx-javascript-library/issues/1350 - */ - -import * as fs from 'node:fs' -import * as path from 'node:path' - -import * as CDX from '@cyclonedx/cyclonedx-library' -// Full library is available as `CDX`, now. -// Alternative for better tree-shaking on bundling, import only the needed symbols like so: -// import { Bom, Component } from '@cyclonedx/cyclonedx-library/Models' -// import { ComponentType } from '@cyclonedx/cyclonedx-library/Enums' - -const dBU1 = CDX.Utils.BomUtility.randomSerialNumber() -console.log(dBU1) - -const dNU1 = CDX.Utils.NpmjsUtility.defaultRegistryMatcher.test('foo') -const dNU2 = CDX.Utils.NpmjsUtility.parsePackageIntegrity('sha1-aSbRsZT7xze47tUTdW3i/Np+pAg=') -console.log(dNU1, dNU2) - -const dLU1 = new CDX.Utils.LicenseUtility.LicenseEvidenceGatherer({fs, path}) -console.log(dLU1) - -/** @type {CDX.Types.NodePackageJson} */ -const dTnpj1 = {} -// const dTnpj2 =CDX.Types.isNodePackageJson(dTnpj1) -try { CDX.Types.assertNodePackageJson(dTnpj1) } catch { /* pass */ } -console.log(dTnpj1) - -const dF1 = new CDX.Factories.PackageUrlFactory('generic') -const dF2 = new CDX.Factories.LicenseFactory() -console.log(dF1, dF2) - -const dFnpj3 = new CDX.Factories.FromNodePackageJson.PackageUrlFactory('npm') -const dFnpj4 = new CDX.Factories.FromNodePackageJson.ExternalReferenceFactory() -console.log(dFnpj3, dFnpj4) - -const dBnpj1 = new CDX.Builders.FromNodePackageJson.ComponentBuilder(dFnpj4, dF2) -const dBnpj2 = new CDX.Builders.FromNodePackageJson.ToolBuilder(dFnpj4) -console.log(dBnpj1, dBnpj2) diff --git a/examples/node/javascript/example.cjs b/examples/node/javascript/example.cjs index d69c9f5bb..dec90204b 100644 --- a/examples/node/javascript/example.cjs +++ b/examples/node/javascript/example.cjs @@ -25,8 +25,10 @@ const CDX = require('@cyclonedx/cyclonedx-library') // const { Bom, Component } = require('@cyclonedx/cyclonedx-library/Models') // const { ComponentType } = require('@cyclonedx/cyclonedx-library/Enums') -const lFac = new CDX.Contrib.License.Factories.LicenseFactory() -const purlFac = new CDX.Contrib.PackageUrl.Factories.PackageUrlFactory('generic') +const spdxExpressionParser = require('spdx-expression-parse') + + +const lFac = new CDX.Contrib.License.Factories.LicenseFactory(spdxExpressionParser) const bom = new CDX.Models.Bom() bom.metadata.component = new CDX.Models.Component( @@ -44,7 +46,7 @@ const componentA = new CDX.Models.Component( } ) componentA.licenses.add(lFac.makeFromString('Apache-2.0')) -componentA.purl = purlFac.makeFromComponent(componentA) +componentA.purl = `pkg:generic/${componentA.group}/${componentA.name}@${componentA.version}` bom.components.add(componentA) bom.metadata.component.dependencies.add(componentA.bomRef) diff --git a/examples/node/javascript/example.mjs b/examples/node/javascript/example.mjs index 3b5f92480..e596cc728 100644 --- a/examples/node/javascript/example.mjs +++ b/examples/node/javascript/example.mjs @@ -25,8 +25,10 @@ import * as CDX from '@cyclonedx/cyclonedx-library' // import { Bom, Component } from '@cyclonedx/cyclonedx-library/Models' // import { ComponentType } from '@cyclonedx/cyclonedx-library/Enums' -const lFac = new CDX.Contrib.License.Factories.LicenseFactory() -const purlFac = new CDX.Contrib.PackageUrl.Factories.PackageUrlFactory('generic') +import spdxExpressionParser from 'spdx-expression-parse' + + +const lFac = new CDX.Contrib.License.Factories.LicenseFactory(spdxExpressionParser) const bom = new CDX.Models.Bom() bom.metadata.component = new CDX.Models.Component( @@ -44,7 +46,7 @@ const componentA = new CDX.Models.Component( } ) componentA.licenses.add(lFac.makeFromString('Apache-2.0')) -componentA.purl = purlFac.makeFromComponent(componentA) +componentA.purl = `pkg:generic/${componentA.group}/${componentA.name}@${componentA.version}` bom.components.add(componentA) bom.metadata.component.dependencies.add(componentA.bomRef) diff --git a/examples/node/javascript/package.json b/examples/node/javascript/package.json index afab53392..bc8c9bd7d 100644 --- a/examples/node/javascript/package.json +++ b/examples/node/javascript/package.json @@ -8,6 +8,7 @@ }, "dependencies": { "@cyclonedx/cyclonedx-library": "file:../../..", + "spdx-expression-parse": "^3.0.1||^4", "xmlbuilder2": "^3.0.2||^4.0.0" }, "optionalDependencies": { diff --git a/examples/node/typescript/example.cjs/package.json b/examples/node/typescript/example.cjs/package.json index 5531d618b..1400ca0c8 100644 --- a/examples/node/typescript/example.cjs/package.json +++ b/examples/node/typescript/example.cjs/package.json @@ -8,6 +8,7 @@ }, "dependencies": { "@cyclonedx/cyclonedx-library": "file:../../../..", + "spdx-expression-parse": "^3.0.1||^4", "xmlbuilder2": "^3.0.2||^4.0.0" }, "optionalDependencies": { @@ -18,11 +19,12 @@ }, "devDependencies": { "@types/node": "*", + "@types/spdx-expression-parse": "^3", "typescript": "^3.8 || ^4 || ^5" }, "scripts": { "prebuild": "tsc -b --clean", "build": "tsc -b", - "example": "node dist/example.js && node dist/deprecated.js" + "example": "node dist/example.js" } } diff --git a/examples/node/typescript/example.cjs/src/deprecated.ts b/examples/node/typescript/example.cjs/src/deprecated.ts deleted file mode 100644 index 6a166d0fb..000000000 --- a/examples/node/typescript/example.cjs/src/deprecated.ts +++ /dev/null @@ -1,68 +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. -*/ - -/** - * Example showcasing the deprecated symbols still work. - * @see https://github.com/CycloneDX/cyclonedx-javascript-library/issues/1350 - */ - -import * as fs from 'node:fs' -import * as path from 'node:path' - -import * as CDX from '@cyclonedx/cyclonedx-library' -// Full library is available as `CDX`, now. -// Alternative for better tree-shaking on bundling, import only the needed symbols like so: -// import { Bom, Component } from '@cyclonedx/cyclonedx-library/Models' -// import { ComponentType } from '@cyclonedx/cyclonedx-library/Enums' - -const dBU1 = CDX.Utils.BomUtility.randomSerialNumber() -console.log(dBU1) - -const dNU1 = CDX.Utils.NpmjsUtility.defaultRegistryMatcher.test('foo') -const dNU2 = CDX.Utils.NpmjsUtility.parsePackageIntegrity('sha1-aSbRsZT7xze47tUTdW3i/Np+pAg=') -console.log(dNU1, dNU2) - -type dLU1_T = CDX.Utils.LicenseUtility.LicenseEvidenceGatherer -const fsU: CDX.Utils.LicenseUtility.FsUtils = fs -const pathU: CDX.Utils.LicenseUtility.PathUtils = path -const dLU1: dLU1_T = new CDX.Utils.LicenseUtility.LicenseEvidenceGatherer({fs: fsU, path: pathU}) -console.log(dLU1) - -const dTnpj1: CDX.Types.NodePackageJson = {} -// const dTnpj2 =CDX.Types.isNodePackageJson(dTnpj1) -try { CDX.Types.assertNodePackageJson(dTnpj1) } catch { /* pass */ } -console.log(dTnpj1) - -type dF1_T = CDX.Factories.PackageUrlFactory -type dF2_T = CDX.Factories.LicenseFactory -const dF1: dF1_T = new CDX.Factories.PackageUrlFactory('generic') -const dF2: dF2_T = new CDX.Factories.LicenseFactory() -console.log(dF1, dF2) - -type dFnpj3_T = CDX.Factories.FromNodePackageJson.PackageUrlFactory -const dFnpj3: dFnpj3_T = new CDX.Factories.FromNodePackageJson.PackageUrlFactory('npm') -type dFnpj4_T = CDX.Factories.FromNodePackageJson.ExternalReferenceFactory -const dFnpj4: dFnpj4_T = new CDX.Factories.FromNodePackageJson.ExternalReferenceFactory() -console.log(dFnpj3, dFnpj4) - -type dBnpj1_T = CDX.Builders.FromNodePackageJson.ComponentBuilder -const dBnpj1: dBnpj1_T = new CDX.Builders.FromNodePackageJson.ComponentBuilder(dFnpj4, dF2) -type dBnpj2_T = CDX.Builders.FromNodePackageJson.ToolBuilder -const dBnpj2: dBnpj2_T = new CDX.Builders.FromNodePackageJson.ToolBuilder(dFnpj4) -console.log(dBnpj1, dBnpj2) diff --git a/examples/node/typescript/example.cjs/src/example.ts b/examples/node/typescript/example.cjs/src/example.ts index 1b6a055d8..185750e25 100644 --- a/examples/node/typescript/example.cjs/src/example.ts +++ b/examples/node/typescript/example.cjs/src/example.ts @@ -25,8 +25,10 @@ import * as CDX from '@cyclonedx/cyclonedx-library' // import { Bom, Component } from '@cyclonedx/cyclonedx-library/Models' // import { ComponentType } from '@cyclonedx/cyclonedx-library/Enums' -const lFac = new CDX.Contrib.License.Factories.LicenseFactory() -const purlFac = new CDX.Contrib.PackageUrl.Factories.PackageUrlFactory('generic') +import * as spdxExpressionParser from 'spdx-expression-parse' + + +const lFac = new CDX.Contrib.License.Factories.LicenseFactory(spdxExpressionParser) const bom = new CDX.Models.Bom() bom.metadata.component = new CDX.Models.Component( @@ -44,7 +46,7 @@ const componentA = new CDX.Models.Component( } ) componentA.licenses.add(lFac.makeFromString('Apache-2.0')) -componentA.purl = purlFac.makeFromComponent(componentA) +componentA.purl = `pkg:generic/${componentA.group}/${componentA.name}@${componentA.version}` bom.components.add(componentA) bom.metadata.component.dependencies.add(componentA.bomRef) diff --git a/examples/node/typescript/example.mjs/package.json b/examples/node/typescript/example.mjs/package.json index 6404c5d98..8c0d8057d 100644 --- a/examples/node/typescript/example.mjs/package.json +++ b/examples/node/typescript/example.mjs/package.json @@ -8,6 +8,7 @@ }, "dependencies": { "@cyclonedx/cyclonedx-library": "file:../../../..", + "spdx-expression-parse": "^3.0.1||^4", "xmlbuilder2": "^3.0.2||^4.0.0" }, "optionalDependencies": { @@ -18,11 +19,12 @@ }, "devDependencies": { "@types/node": "*", + "@types/spdx-expression-parse": "^3", "typescript": "^4 || ^5" }, "scripts": { "prebuild": "tsc -b --clean", "build": "tsc -b", - "example": "node dist/example.js && node dist/deprecated.js" + "example": "node dist/example.js" } } diff --git a/examples/node/typescript/example.mjs/src/deprecated.ts b/examples/node/typescript/example.mjs/src/deprecated.ts deleted file mode 100644 index 6a166d0fb..000000000 --- a/examples/node/typescript/example.mjs/src/deprecated.ts +++ /dev/null @@ -1,68 +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. -*/ - -/** - * Example showcasing the deprecated symbols still work. - * @see https://github.com/CycloneDX/cyclonedx-javascript-library/issues/1350 - */ - -import * as fs from 'node:fs' -import * as path from 'node:path' - -import * as CDX from '@cyclonedx/cyclonedx-library' -// Full library is available as `CDX`, now. -// Alternative for better tree-shaking on bundling, import only the needed symbols like so: -// import { Bom, Component } from '@cyclonedx/cyclonedx-library/Models' -// import { ComponentType } from '@cyclonedx/cyclonedx-library/Enums' - -const dBU1 = CDX.Utils.BomUtility.randomSerialNumber() -console.log(dBU1) - -const dNU1 = CDX.Utils.NpmjsUtility.defaultRegistryMatcher.test('foo') -const dNU2 = CDX.Utils.NpmjsUtility.parsePackageIntegrity('sha1-aSbRsZT7xze47tUTdW3i/Np+pAg=') -console.log(dNU1, dNU2) - -type dLU1_T = CDX.Utils.LicenseUtility.LicenseEvidenceGatherer -const fsU: CDX.Utils.LicenseUtility.FsUtils = fs -const pathU: CDX.Utils.LicenseUtility.PathUtils = path -const dLU1: dLU1_T = new CDX.Utils.LicenseUtility.LicenseEvidenceGatherer({fs: fsU, path: pathU}) -console.log(dLU1) - -const dTnpj1: CDX.Types.NodePackageJson = {} -// const dTnpj2 =CDX.Types.isNodePackageJson(dTnpj1) -try { CDX.Types.assertNodePackageJson(dTnpj1) } catch { /* pass */ } -console.log(dTnpj1) - -type dF1_T = CDX.Factories.PackageUrlFactory -type dF2_T = CDX.Factories.LicenseFactory -const dF1: dF1_T = new CDX.Factories.PackageUrlFactory('generic') -const dF2: dF2_T = new CDX.Factories.LicenseFactory() -console.log(dF1, dF2) - -type dFnpj3_T = CDX.Factories.FromNodePackageJson.PackageUrlFactory -const dFnpj3: dFnpj3_T = new CDX.Factories.FromNodePackageJson.PackageUrlFactory('npm') -type dFnpj4_T = CDX.Factories.FromNodePackageJson.ExternalReferenceFactory -const dFnpj4: dFnpj4_T = new CDX.Factories.FromNodePackageJson.ExternalReferenceFactory() -console.log(dFnpj3, dFnpj4) - -type dBnpj1_T = CDX.Builders.FromNodePackageJson.ComponentBuilder -const dBnpj1: dBnpj1_T = new CDX.Builders.FromNodePackageJson.ComponentBuilder(dFnpj4, dF2) -type dBnpj2_T = CDX.Builders.FromNodePackageJson.ToolBuilder -const dBnpj2: dBnpj2_T = new CDX.Builders.FromNodePackageJson.ToolBuilder(dFnpj4) -console.log(dBnpj1, dBnpj2) diff --git a/examples/node/typescript/example.mjs/src/example.ts b/examples/node/typescript/example.mjs/src/example.ts index 2df810501..f10287b78 100644 --- a/examples/node/typescript/example.mjs/src/example.ts +++ b/examples/node/typescript/example.mjs/src/example.ts @@ -25,8 +25,10 @@ import * as CDX from '@cyclonedx/cyclonedx-library' // import { Bom, Component } from '@cyclonedx/cyclonedx-library/Models' // import { ComponentType } from '@cyclonedx/cyclonedx-library/Enums' -const lFac = new CDX.Contrib.License.Factories.LicenseFactory() -const purlFac = new CDX.Contrib.PackageUrl.Factories.PackageUrlFactory('generic') +import spdxExpressionParser from 'spdx-expression-parse' + + +const lFac = new CDX.Contrib.License.Factories.LicenseFactory(spdxExpressionParser) const bom = new CDX.Models.Bom() bom.metadata.component = new CDX.Models.Component( @@ -44,7 +46,7 @@ const componentA = new CDX.Models.Component( } ) componentA.licenses.add(lFac.makeFromString('Apache-2.0')) -componentA.purl = purlFac.makeFromComponent(componentA) +componentA.purl = `pkg:generic/${componentA.group}/${componentA.name}@${componentA.version}` bom.components.add(componentA) bom.metadata.component.dependencies.add(componentA.bomRef) diff --git a/examples/web/parcel/package.json b/examples/web/parcel/package.json index b39226cb4..619fac1f4 100644 --- a/examples/web/parcel/package.json +++ b/examples/web/parcel/package.json @@ -4,13 +4,14 @@ "license": "Apache-2.0", "source": "src/index.html", "dependencies": { - "@cyclonedx/cyclonedx-library": "file:../../.." + "@cyclonedx/cyclonedx-library": "file:../../..", + "spdx-expression-parse": "^3.0.1||^4" }, "devDependencies": { "parcel": "^2" }, "scripts": { - "build": "parcel build --detailed-report", + "build": "parcel build --detailed-report --public-url .", "example": "parcel" } } diff --git a/examples/web/parcel/src/app.js b/examples/web/parcel/src/app.js index 0a024b70a..b87d25556 100644 --- a/examples/web/parcel/src/app.js +++ b/examples/web/parcel/src/app.js @@ -22,8 +22,10 @@ Copyright (c) OWASP Foundation. All Rights Reserved. const CDX = require('@cyclonedx/cyclonedx-library') // full Library is available as `CDX`, now -const lFac = new CDX.Contrib.License.Factories.LicenseFactory() -const purlFac = new CDX.Contrib.PackageUrl.Factories.PackageUrlFactory('generic') +const spdxExpressionParser = require('spdx-expression-parse') + + +const lFac = new CDX.Contrib.License.Factories.LicenseFactory(spdxExpressionParser) const bom = new CDX.Models.Bom() bom.metadata.component = new CDX.Models.Component( @@ -41,7 +43,7 @@ const componentA = new CDX.Models.Component( } ) componentA.licenses.add(lFac.makeFromString('Apache-2.0')) -componentA.purl = purlFac.makeFromComponent(componentA) +componentA.purl = `pkg:generic/${componentA.group}/${componentA.name}@${componentA.version}` bom.components.add(componentA) bom.metadata.component.dependencies.add(componentA.bomRef) diff --git a/examples/web/parcel/src/index.html b/examples/web/parcel/src/index.html index ff2dba6ce..767b18a5b 100644 --- a/examples/web/parcel/src/index.html +++ b/examples/web/parcel/src/index.html @@ -22,7 +22,7 @@ example - +

see JavaScript Console output for result.

diff --git a/examples/web/webpack/dist/index.html b/examples/web/webpack/dist/index.html deleted file mode 100644 index 31596d46f..000000000 --- a/examples/web/webpack/dist/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - example - - - -

see JavaScript Console output for result.

- - diff --git a/examples/web/webpack/package.json b/examples/web/webpack/package.json index c991fa435..196320561 100644 --- a/examples/web/webpack/package.json +++ b/examples/web/webpack/package.json @@ -3,14 +3,16 @@ "name": "@cyclonedx/cyclonedx-library-examples-web-webpack", "license": "Apache-2.0", "dependencies": { - "@cyclonedx/cyclonedx-library": "file:../../.." + "@cyclonedx/cyclonedx-library": "file:../../..", + "spdx-expression-parse": "^3.0.1||^4" }, "devDependencies": { "webpack": "^5", - "webpack-cli": "^5||^6" + "webpack-cli": "^5||^6", + "webpack-dev-server": "^5" }, "scripts": { "build": "webpack build", - "example": "x-www-browser dist/index.html" + "example": "webpack serve --open --static . --output-path ./dist" } } diff --git a/examples/web/webpack/src/index.js b/examples/web/webpack/src/index.js index 0a024b70a..b87d25556 100644 --- a/examples/web/webpack/src/index.js +++ b/examples/web/webpack/src/index.js @@ -22,8 +22,10 @@ Copyright (c) OWASP Foundation. All Rights Reserved. const CDX = require('@cyclonedx/cyclonedx-library') // full Library is available as `CDX`, now -const lFac = new CDX.Contrib.License.Factories.LicenseFactory() -const purlFac = new CDX.Contrib.PackageUrl.Factories.PackageUrlFactory('generic') +const spdxExpressionParser = require('spdx-expression-parse') + + +const lFac = new CDX.Contrib.License.Factories.LicenseFactory(spdxExpressionParser) const bom = new CDX.Models.Bom() bom.metadata.component = new CDX.Models.Component( @@ -41,7 +43,7 @@ const componentA = new CDX.Models.Component( } ) componentA.licenses.add(lFac.makeFromString('Apache-2.0')) -componentA.purl = purlFac.makeFromComponent(componentA) +componentA.purl = `pkg:generic/${componentA.group}/${componentA.name}@${componentA.version}` bom.components.add(componentA) bom.metadata.component.dependencies.add(componentA.bomRef) diff --git a/package.json b/package.json index 14ef4c0a9..899bf7fcb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cyclonedx/cyclonedx-library", - "version": "9.5.0", + "version": "10.0.0-rc.2", "description": "Core functionality of CycloneDX for JavaScript (Node.js or WebBrowser).", "license": "Apache-2.0", "keywords": [ @@ -79,16 +79,15 @@ "engines": { "node": ">=20.18.0" }, - "dependencies": { - "packageurl-js": "^2.0.1", - "spdx-expression-parse": "^3.0.1 || ^4" - }, + "dependencies": {}, "peerDependencies": { "ajv": "^8.12.0", "ajv-formats": "^3.0.1", "ajv-formats-draft2019": "^1.6.1", "libxmljs2": "^0.35||^0.37", - "xmlbuilder2": "^3.0.2||^4.0.0" + "xmlbuilder2": "^3.0.2||^4.0.0", + "packageurl-js": "*", + "spdx-expression-parse": "*" }, "peerDependenciesMeta": { "ajv": { @@ -105,6 +104,24 @@ }, "xmlbuilder2": { "optional": true + }, + "packageurl-js": { + "optional": true + }, + "spdx-expression-parse": { + "optional": true + } + }, + "devEngines": { + "runtime": { + "name": "node", + "version": ">=20.18.0", + "onFail": "error" + }, + "packageManager": { + "name": "npm", + "version": ">=9", + "onFail": "error" } }, "devDependencies": { @@ -113,6 +130,7 @@ "ajv-formats-draft2019": "^1.6.1", "libxmljs2": "^0.35||^0.37", "xmlbuilder2": "^3.0.2||^4.0.0", + "spdx-expression-parse": "^3.0.1||^4", "@types/mocha": "^10", "@types/node": "ts5.7", "@types/spdx-expression-parse": "^3", @@ -145,18 +163,10 @@ "default": "./dist.node/index.node.js" }, "./package.json": "./package.json", - "./Builders": { - "types": "./dist.d/builders/index.node.d.ts", - "default": "./dist.node/builders/index.node.js" - }, "./Enums": { "types": "./dist.d/enums/index.d.ts", "default": "./dist.node/enums/index.js" }, - "./Factories": { - "types": "./dist.d/factories/index.node.d.ts", - "default": "./dist.node/factories/index.node.js" - }, "./Models": { "types": "./dist.d/models/index.d.ts", "default": "./dist.node/models/index.js" @@ -177,10 +187,6 @@ "types": "./dist.d/types/index.d.ts", "default": "./dist.node/types/index.js" }, - "./Utils": { - "types": "./dist.d/utils/index.node.d.ts", - "default": "./dist.node/utils/index.node.js" - }, "./Validation": { "types": "./dist.d/validation/index.node.d.ts", "default": "./dist.node/validation/index.node.js" @@ -200,10 +206,6 @@ "./Contrib/License": { "types": "./dist.d/contrib/license/index.node.d.ts", "default": "./dist.node/contrib/license/index.node.js" - }, - "./Contrib/PackageUrl": { - "types": "./dist.d/contrib/packageUrl/index.d.ts", - "default": "./dist.node/contrib/packageUrl/index.js" } }, "directories": { diff --git a/src/_optPlug.node/__xmlValidators/libxmljs2.ts b/src/_optPlug.node/__xmlValidators/libxmljs2.ts index 63cadad19..bce1b4224 100644 --- a/src/_optPlug.node/__xmlValidators/libxmljs2.ts +++ b/src/_optPlug.node/__xmlValidators/libxmljs2.ts @@ -20,7 +20,8 @@ Copyright (c) OWASP Foundation. All Rights Reserved. import { readFile } from 'node:fs/promises' import { pathToFileURL } from 'node:url' -import { type ParserOptions, parseXml } from 'libxmljs2' +import type { ParserOptions } from 'libxmljs2' +import { parseXml } from 'libxmljs2' import type { ValidationError } from '../../validation/types' import type { Functionality, Validator } from '../xmlValidator' diff --git a/src/builders/fromNodePackageJson.node.ts b/src/builders/fromNodePackageJson.node.ts deleted file mode 100644 index 9d931195c..000000000 --- a/src/builders/fromNodePackageJson.node.ts +++ /dev/null @@ -1,44 +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. -*/ - -/** - * Node-specifics. - * - * Intended to run on normalized data structures - * based on [PackageJson spec](https://github.com/SchemaStore/schemastore/blob/master/src/schemas/json/package.json) - * and explained by [PackageJson description](https://docs.npmjs.com/cli/v9/configuring-npm/package-json). - * Normalization should be done downstream, for example via [`normalize-package-data`](https://www.npmjs.com/package/normalize-package-data). - */ - -import {ComponentBuilder as _ComponentBuilder, ToolBuilder as _ToolBuilder} from '../contrib/fromNodePackageJson/builders' - - -/** - * Deprecated — Alias of {@link Contrib.FromNodePackageJson.Builders.ToolBuilder}. - * - * @deprecated Use `Contrib.FromNodePackageJson.Builders.ToolBuilder` instead. - */ -export class ToolBuilder extends _ToolBuilder {} - -/** - * Deprecated — Alias of {@link Contrib.FromNodePackageJson.Builders.ComponentBuilder}. - * - * @deprecated Use `Contrib.FromNodePackageJson.Builders.ComponentBuilder` instead. - */ -export class ComponentBuilder extends _ComponentBuilder {} diff --git a/src/builders/index.node.ts b/src/builders/index.node.ts deleted file mode 100644 index 966982a9e..000000000 --- a/src/builders/index.node.ts +++ /dev/null @@ -1,21 +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. -*/ - -/** @deprecated next */ -export * as FromNodePackageJson from './fromNodePackageJson.node' diff --git a/src/contrib/fromNodePackageJson/factories.ts b/src/contrib/fromNodePackageJson/factories.ts index d47b62c48..ba0ef5f4f 100644 --- a/src/contrib/fromNodePackageJson/factories.ts +++ b/src/contrib/fromNodePackageJson/factories.ts @@ -26,19 +26,14 @@ Copyright (c) OWASP Foundation. All Rights Reserved. * Normalization should be done downstream, for example via [`normalize-package-data`](https://www.npmjs.com/package/normalize-package-data). */ -import type { PackageURL } from 'packageurl-js' -import { PurlQualifierNames } from 'packageurl-js' - import { isNotUndefined } from '../../_helpers/notUndefined' import { ExternalReferenceType } from '../../enums/externalReferenceType' import { HashAlgorithm } from '../../enums/hashAlogorithm' -import type { Component } from '../../models/component' import { ExternalReference } from '../../models/externalReference' import { HashDictionary } from '../../models/hash' -import { PackageUrlFactory as PlainPackageUrlFactory } from '../packageUrl/factories' import { tryCanonicalizeGitUrl } from './_helpers/gitUrl' import type { NodePackageJson } from './types' -import { defaultRegistryMatcher, parsePackageIntegrity } from './utils' +import { parsePackageIntegrity } from './utils' /** * Node-specific ExternalReferenceFactory. @@ -130,57 +125,3 @@ export class ExternalReferenceFactory { return undefined } } - -/** - * Node-specific PackageUrlFactory. - * @see {@link https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#npm} - */ -export class PackageUrlFactory extends PlainPackageUrlFactory<'npm'> { - /* eslint-disable-next-line @typescript-eslint/no-inferrable-types -- docs */ - override makeFromComponent (component: Component, sort: boolean = false): PackageURL | undefined { - const purl = super.makeFromComponent(component, sort) - return purl === undefined - ? undefined - : this.#finalizeQualifiers(purl) - } - - /** - * Will strip unnecessary qualifiers according to [PURL-SPECIFICATION](https://github.com/package-url/purl-spec/blob/master/PURL-SPECIFICATION.rst#known-qualifiers-keyvalue-pairs). - *
- * Do not abuse qualifiers: it can be tempting to use many qualifier keys but their usage should be limited - * to the bare minimum for proper package identification to ensure that a purl stays compact and readable - * in most cases. - *
- * - * Therefore: - * - "vcs_url" is stripped, if a "download_url" is given. - * - "download_url" is stripped, if it is NPM's default registry ("registry.npmjs.org") - * - "checksum" is stripped, unless a "download_url" or "vcs_url" is given. - */ - #finalizeQualifiers(purl: PackageURL): PackageURL { - /* eslint-disable no-param-reassign -- intended */ - const qualifiers = new Map(Object.entries(purl.qualifiers ?? {})) - - const downloadUrl = qualifiers.get(PurlQualifierNames.DownloadUrl) - if (downloadUrl !== undefined) { - qualifiers.delete(PurlQualifierNames.VcsUrl) - if (defaultRegistryMatcher.test(downloadUrl)) { - qualifiers.delete(PurlQualifierNames.DownloadUrl) - } - } - if (!qualifiers.has(PurlQualifierNames.DownloadUrl) && !qualifiers.has(PurlQualifierNames.VcsUrl)) { - // nothing to base a checksum on - qualifiers.delete(PurlQualifierNames.Checksum) - } - if (qualifiers.size > 0) { - purl.qualifiers = Object.fromEntries(qualifiers.entries()) - /* @ts-expect-error TS2322 */ - purl.qualifiers.__proto__ = null /* eslint-disable-line no-proto -- intended */ - } else { - purl.qualifiers = undefined - } - - return purl - /* eslint-enable no-param-reassign */ - } -} diff --git a/src/contrib/index.common.ts b/src/contrib/index.common.ts index 6c3872168..eb84f8aa3 100644 --- a/src/contrib/index.common.ts +++ b/src/contrib/index.common.ts @@ -22,4 +22,3 @@ Copyright (c) OWASP Foundation. All Rights Reserved. */ export * as Bom from './bom' -export * as PackageUrl from './packageUrl' diff --git a/src/contrib/license/factories.ts b/src/contrib/license/factories.ts index c218f5bf8..5b6d10f3a 100644 --- a/src/contrib/license/factories.ts +++ b/src/contrib/license/factories.ts @@ -19,9 +19,29 @@ Copyright (c) OWASP Foundation. All Rights Reserved. import type { DisjunctiveLicense, License } from '../../models/license' import { LicenseExpression, NamedLicense, SpdxLicense } from '../../models/license' -import { fixupSpdxId, isValidSpdxLicenseExpression } from '../../spdx' +import { fixupSpdxId } from '../../spdx' + +/** + * SPDX License Expression validation. + * + * A function that is expected to throw an error if the input is not a valid SPDX License Expression. + * + * We suggest one of the following 3rd-party libraries: + * - `spdx-expression-parse@^3.0.1||^4` - {@link https://www.npmjs.com/package/spdx-expression-parse} + * + * @throws {@link Error} + * Throws an error if the input is not a valid SPDX License Expression. + */ +type SpdxExpressionValidate = (data: string) => void export class LicenseFactory { + + readonly #spdxExpressionValidate: SpdxExpressionValidate + + constructor(spdxExpressionValidate: SpdxExpressionValidate) { + this.#spdxExpressionValidate = spdxExpressionValidate + } + makeFromString (value: string): License { try { return this.makeSpdxLicense(value) @@ -43,10 +63,12 @@ export class LicenseFactory { */ makeExpression (value: string | any): LicenseExpression { const expression = String(value) - if (isValidSpdxLicenseExpression(expression)) { - return new LicenseExpression(expression) + try { + this.#spdxExpressionValidate(expression) + } catch (err) { + throw new RangeError('Invalid SPDX license expression', { cause: err }) } - throw new RangeError('Invalid SPDX license expression') + return new LicenseExpression(expression) } makeDisjunctive (value: string): DisjunctiveLicense { diff --git a/src/contrib/packageUrl/factories.ts b/src/contrib/packageUrl/factories.ts deleted file mode 100644 index 8db56d2ff..000000000 --- a/src/contrib/packageUrl/factories.ts +++ /dev/null @@ -1,92 +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. -*/ - -import { PackageURL, PurlQualifierNames } from 'packageurl-js' - -import { ExternalReferenceType } from '../../enums/externalReferenceType' -import type { Component } from '../../models/component' - -export class PackageUrlFactory { - readonly #type: PurlType - - constructor (type: PurlType) { - this.#type = type - } - - get type (): PurlType { - return this.#type - } - - /* eslint-disable-next-line @typescript-eslint/no-inferrable-types -- docs */ - makeFromComponent (component: Component, sort: boolean = false): PackageURL | undefined { - const qualifiers: PackageURL['qualifiers'] = {} - /* @ts-expect-error TS2322 */ - qualifiers.__proto__ = null /* eslint-disable-line no-proto -- intended */ - let subpath: PackageURL['subpath'] = undefined - - // sorting to allow reproducibility: use the last instance for a `extRef.type`, if multiples exist - const extRefs = sort - ? component.externalReferences.sorted() - : component.externalReferences - for (const extRef of extRefs) { - const url = extRef.url.toString() - if (url.length <= 0) { - continue - } - // No further need for validation. - // According to https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst - // there is no formal requirement to a `..._url`. - // Everything is possible: URL-encoded, not encoded, with schema, without schema - /* eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- intended */ - switch (extRef.type) { - case ExternalReferenceType.VCS: - [qualifiers[PurlQualifierNames.VcsUrl], subpath] = url.split('#', 2) - break - case ExternalReferenceType.Distribution: - qualifiers[PurlQualifierNames.DownloadUrl] = url - break - } - } - - const hashes = component.hashes - if (hashes.size > 0) { - qualifiers[PurlQualifierNames.Checksum] = Array.from( - sort - ? hashes.sorted() - : hashes, - ([hashAlgo, hashCont]) => `${hashAlgo.toLowerCase()}:${hashCont.toLowerCase()}` - ).join(',') - } - - try { - // Do not beautify the parameters here, because that is in the domain of PackageURL and its representation. - // No need to convert an empty "subpath" string to `undefined` and such. - return new PackageURL( - this.#type, - component.group, - component.name, - component.version, - qualifiers, - subpath - ) - } catch { - return undefined - } - } -} diff --git a/src/contrib/packageUrl/index.ts b/src/contrib/packageUrl/index.ts deleted file mode 100644 index e898d6e94..000000000 --- a/src/contrib/packageUrl/index.ts +++ /dev/null @@ -1,20 +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. -*/ - -export * as Factories from './factories' diff --git a/src/factories/fromNodePackageJson.node.ts b/src/factories/fromNodePackageJson.node.ts deleted file mode 100644 index 4e3371d09..000000000 --- a/src/factories/fromNodePackageJson.node.ts +++ /dev/null @@ -1,34 +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. -*/ - -import { ExternalReferenceFactory as _ExternalReferenceFactory, PackageUrlFactory as _PackageUrlFactory } from '../contrib/fromNodePackageJson/factories' - -/** - * Deprecated — Alias of {@link Contrib.FromNodePackageJson.Factories.ExternalReferenceFactory}. - * - * @deprecated Use `Contrib.FromNodePackageJson.Factories.ExternalReferenceFactory` instead. - */ -export class ExternalReferenceFactory extends _ExternalReferenceFactory {} - -/** - * Deprecated — Alias of {@link Contrib.FromNodePackageJson.Factories.PackageUrlFactory}. - * - * @deprecated Use `Contrib.FromNodePackageJson.Factories.PackageUrlFactory` instead. - */ -export class PackageUrlFactory extends _PackageUrlFactory {} diff --git a/src/factories/index.common.ts b/src/factories/index.common.ts deleted file mode 100644 index 3fc5f7029..000000000 --- a/src/factories/index.common.ts +++ /dev/null @@ -1,25 +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. -*/ - -// not everything is public, yet - -/** @deprecated next */ -export * from './license' -/** @deprecated next */ -export * from './packageUrl' diff --git a/src/factories/index.node.ts b/src/factories/index.node.ts deleted file mode 100644 index 2df6c8d2a..000000000 --- a/src/factories/index.node.ts +++ /dev/null @@ -1,27 +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. -*/ - -export * from './index.common' - -// region node-specifics - -/** @deprecated next */ -export * as FromNodePackageJson from './fromNodePackageJson.node' - -// endregion node-specifics diff --git a/src/factories/index.web.ts b/src/factories/index.web.ts deleted file mode 100644 index b2beefadf..000000000 --- a/src/factories/index.web.ts +++ /dev/null @@ -1,26 +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. -*/ - -export * from './index.common' - -// region web-specifics - -// ... nothing yet - -// endregion web-specifics diff --git a/src/factories/license.ts b/src/factories/license.ts deleted file mode 100644 index 7765ed4fe..000000000 --- a/src/factories/license.ts +++ /dev/null @@ -1,27 +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. -*/ - -import {LicenseFactory as _LicenseFactory} from '../contrib/license/factories' - -/** - * Deprecated — Alias of {@link Contrib.License.Factories.LicenseFactory}. - * - * @deprecated Use `Contrib.License.Factories.LicenseFactory` instead. - */ -export class LicenseFactory extends _LicenseFactory {} diff --git a/src/factories/packageUrl.ts b/src/factories/packageUrl.ts deleted file mode 100644 index c8ed16131..000000000 --- a/src/factories/packageUrl.ts +++ /dev/null @@ -1,27 +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. -*/ - -import { PackageUrlFactory as _PackageUrlFactory } from '../contrib/packageUrl/factories' - -/** - * Deprecated — Alias of {@link Contrib.PackageUrl.Factories.PackageUrlFactory}. - * - * @deprecated Use `Contrib.PackageUrl.Factories.PackageUrlFactory` instead. - */ -export class PackageUrlFactory extends _PackageUrlFactory {} diff --git a/src/index.node.ts b/src/index.node.ts index d3343da92..7b87e7b3f 100644 --- a/src/index.node.ts +++ b/src/index.node.ts @@ -25,14 +25,9 @@ export * from './index.common' // region node-specifics -/** @deprecated next */ -export * as Builders from './builders/index.node' + export * as Contrib from './contrib/index.node' -/** @deprecated next */ -export * as Factories from './factories/index.node' export * as Serialize from './serialize/index.node' -/** @deprecated next */ -export * as Utils from './utils/index.node' export * as Validation from './validation/index.node' /** diff --git a/src/index.web.ts b/src/index.web.ts index a64a69fa7..a4153f9e5 100644 --- a/src/index.web.ts +++ b/src/index.web.ts @@ -22,11 +22,7 @@ export * from './index.common' // region web-specifics export * as Contrib from './contrib/index.web' -/** @deprecated next */ -export * as Factories from './factories/index.web' export * as Serialize from './serialize/index.web' -/** @deprecated next */ -export * as Utils from './utils/index.web' export * as Validation from './validation/index.web' // endregion web-specifics diff --git a/src/models/component.ts b/src/models/component.ts index a07c96388..45d21dfca 100644 --- a/src/models/component.ts +++ b/src/models/component.ts @@ -17,8 +17,6 @@ SPDX-License-Identifier: Apache-2.0 Copyright (c) OWASP Foundation. All Rights Reserved. */ -import type { PackageURL } from 'packageurl-js' - import type { Comparable } from '../_helpers/sortable' import { SortableComparables } from '../_helpers/sortable' import { treeIteratorSymbol } from '../_helpers/tree' @@ -69,7 +67,7 @@ export class Component implements Comparable { hashes: HashDictionary licenses: LicenseRepository publisher?: string - purl?: PackageURL + purl?: string scope?: ComponentScope supplier?: OrganizationalEntity swid?: SWID @@ -139,7 +137,7 @@ export class Component implements Comparable { return bomRefCompare } if (this.purl !== undefined && other.purl !== undefined) { - return this.purl.toString().localeCompare(other.purl.toString()) + return this.purl.localeCompare(other.purl) } if (this.#cpe !== undefined && other.#cpe !== undefined) { return this.#cpe.localeCompare(other.#cpe) diff --git a/src/spdx.ts b/src/spdx.ts index 85bdb1fe2..4847be9a0 100644 --- a/src/spdx.ts +++ b/src/spdx.ts @@ -17,8 +17,6 @@ SPDX-License-Identifier: Apache-2.0 Copyright (c) OWASP Foundation. All Rights Reserved. */ -import spdxExpressionParse from 'spdx-expression-parse' - /* @ts-expect-error: TS6059 -- this works as long as the file/path is available in dist-package. */ import { enum as _spdxSpecEnum } from '../res/schema/spdx.SNAPSHOT.schema.json' with { type: 'json' } @@ -48,15 +46,3 @@ export function fixupSpdxId (value: string | any): SpdxId | undefined { ? spdxLowerToActual[value.toLowerCase()] : undefined } - -export function isValidSpdxLicenseExpression (value: string | any): boolean { - if (typeof value !== 'string') { - return false - } - try { - spdxExpressionParse(value) - } catch (err) { - return false - } - return true -} diff --git a/src/spec/_protocol.ts b/src/spec/_protocol.ts index b24cf740d..ed30698cd 100644 --- a/src/spec/_protocol.ts +++ b/src/spec/_protocol.ts @@ -18,7 +18,8 @@ Copyright (c) OWASP Foundation. All Rights Reserved. */ import type { ComponentType, ExternalReferenceType, HashAlgorithm, Vulnerability } from '../enums' -import { type HashContent, NamedLicense, SpdxLicense } from '../models' +import type { HashContent } from '../models' +import { NamedLicense, SpdxLicense } from '../models' import type { Format, Version } from './enums' /** @@ -172,7 +173,7 @@ export class _Spec implements _SpecProtocol { supportsProperties (model: any): boolean { switch (true) { case model instanceof NamedLicense || model instanceof SpdxLicense: - return this.#supportsLicenseProperties + return this.#supportsLicenseProperties default: return this.#supportsProperties } diff --git a/src/types/index.ts b/src/types/index.ts index 31d681610..2db668d77 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -17,39 +17,7 @@ SPDX-License-Identifier: Apache-2.0 Copyright (c) OWASP Foundation. All Rights Reserved. */ -import { - assertNodePackageJson as _assertNodePackageJson, - isNodePackageJson as _isNodePackageJson, - type NodePackageJson as _NodePackageJson -} from '../contrib/fromNodePackageJson/types' - - export * from './cpe' export * from './cwe' export * from './integer' export * from './mimeType' - -// region deprecated re-exports - -/** - * Deprecated — TypeAlias of {@link Contrib.FromNodePackageJson.Types.NodePackageJson}. - * - * @deprecated Use `Contrib.FromNodePackageJson.Types.NodePackageJson` instead. - */ -export type NodePackageJson = _NodePackageJson - -/** - * Deprecated — Alias of {@link Contrib.FromNodePackageJson.Types.assertNodePackageJson}. - * - * @deprecated Use `Contrib.FromNodePackageJson.Types.assertNodePackageJson` instead. - */ -export const assertNodePackageJson = _assertNodePackageJson - -/** - * Deprecated — Alias of {@link Contrib.FromNodePackageJson.Types.isNodePackageJson}. - * - * @deprecated Use `Contrib.FromNodePackageJson.Types.isNodePackageJson` instead. - */ -export const isNodePackageJson = _isNodePackageJson - -// endregion deprecated re-exports diff --git a/src/utils/bomUtility.ts b/src/utils/bomUtility.ts deleted file mode 100644 index 9222e160a..000000000 --- a/src/utils/bomUtility.ts +++ /dev/null @@ -1,27 +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. -*/ - -import { randomSerialNumber as _randomSerialNumber } from '../contrib/bom/utils' - -/** - * Deprecated — Alias of {@link Contrib.Bom.Utils.randomSerialNumber}. - * - * @deprecated Use `Contrib.Bom.Utils.randomSerialNumber` instead. - */ -export const randomSerialNumber = _randomSerialNumber diff --git a/src/utils/index.common.ts b/src/utils/index.common.ts deleted file mode 100644 index f4078895a..000000000 --- a/src/utils/index.common.ts +++ /dev/null @@ -1,21 +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. -*/ - -/** @deprecated next */ -export * as BomUtility from './bomUtility' diff --git a/src/utils/index.node.ts b/src/utils/index.node.ts deleted file mode 100644 index d427df44f..000000000 --- a/src/utils/index.node.ts +++ /dev/null @@ -1,29 +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. -*/ - -export * from './index.common' - -// region node-specifics - -/** @deprecated next */ -export * as LicenseUtility from './licenseUtility.node' -/** @deprecated next */ -export * as NpmjsUtility from './npmjsUtility.node' - -// endregion node-specifics diff --git a/src/utils/index.web.ts b/src/utils/index.web.ts deleted file mode 100644 index b2beefadf..000000000 --- a/src/utils/index.web.ts +++ /dev/null @@ -1,26 +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. -*/ - -export * from './index.common' - -// region web-specifics - -// ... nothing yet - -// endregion web-specifics diff --git a/src/utils/licenseUtility.node.ts b/src/utils/licenseUtility.node.ts deleted file mode 100644 index 7e31d89ec..000000000 --- a/src/utils/licenseUtility.node.ts +++ /dev/null @@ -1,64 +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. -*/ - -/** - * This module tries to be as compatible as possible, it only uses basic methods that are known to be working in all FileSystem abstraction-layers. - * In addition, we use type parameters for all `PathLike`s, so downstream users can utilize their implementations accordingly. - * - * @module - */ - -import type { ErrorReporter as _ErrorReporter, FileAttachment as _FileAttachment, FsUtils as _FsUtils, PathUtils as _PathUtils} from '../contrib/license/utils.node'; -import { LicenseEvidenceGatherer as _LicenseEvidenceGatherer } from '../contrib/license/utils.node'; - - -/** - * Deprecated — TypeAlias of {@link Contrib.License.Utils.FsUtils}. - * - * @deprecated Use `Contrib.License.Utils.FsUtils` instead. - */ -export interface FsUtils

extends _FsUtils

{} - -/** - * Deprecated — TypeAlias of {@link Contrib.License.Utils.PathUtils}. - * - * @deprecated Use `Contrib.License.Utils.PathUtils` instead. - */ -export interface PathUtils

extends _PathUtils

{} - -/** - * Deprecated — TypeAlias of {@link Contrib.License.Utils.FileAttachment}. - * - * @deprecated Use `Contrib.License.Utils.FileAttachment` instead. - */ -export interface FileAttachment

extends _FileAttachment

{} - -/** - * Deprecated — TypeAlias of {@link Contrib.License.Utils.ErrorReporter}. - * - * @deprecated Use `Contrib.License.Utils.ErrorReporter` instead. - */ -export type ErrorReporter = _ErrorReporter - -/** - * Deprecated — Alias of {@link Contrib.License.Utils.LicenseEvidenceGatherer}. - * - * @deprecated Use `Contrib.License.Utils.LicenseEvidenceGatherer` instead. - */ -export class LicenseEvidenceGatherer extends _LicenseEvidenceGatherer {} diff --git a/src/utils/npmjsUtility.node.ts b/src/utils/npmjsUtility.node.ts deleted file mode 100644 index 0b1fce4f3..000000000 --- a/src/utils/npmjsUtility.node.ts +++ /dev/null @@ -1,34 +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. -*/ - -import {defaultRegistryMatcher as _defaultRegistryMatcher, parsePackageIntegrity as _parsePackageIntegrity} from '../contrib/fromNodePackageJson/utils' - -/** - * Deprecated — Alias of {@link Contrib.FromNodePackageJson.Utils.parsePackageIntegrity}. - * - * @deprecated Use `Contrib.FromNodePackageJson.Utils.parsePackageIntegrity` instead. - */ -export const parsePackageIntegrity = _parsePackageIntegrity - -/** - * Deprecated — Alias of {@link Contrib.FromNodePackageJson.Utils.defaultRegistryMatcher}. - * - * @deprecated Use `Contrib.FromNodePackageJson.Utils.defaultRegistryMatcher` instead. - */ -export const defaultRegistryMatcher = _defaultRegistryMatcher diff --git a/tests/_data/models.js b/tests/_data/models.js index 76ba6920d..86962aff0 100644 --- a/tests/_data/models.js +++ b/tests/_data/models.js @@ -17,8 +17,6 @@ SPDX-License-Identifier: Apache-2.0 Copyright (c) OWASP Foundation. All Rights Reserved. */ -const { PackageURL } = require('packageurl-js') - const { Enums, Models, Types } = require('../../') /* eslint-disable jsdoc/no-undefined-types -- something is odd with type detection */ @@ -178,7 +176,7 @@ function createComplexStructure () { ]) }))) component.publisher = 'the publisher' - component.purl = new PackageURL('npm', 'acme', 'dummy-component', '1337-beta', undefined, undefined) + component.purl = 'pkg:npm/acme/dummy-component@1337-beta' component.scope = Enums.ComponentScope.Required component.supplier = new Models.OrganizationalEntity({ name: 'Component Supplier' }) component.supplier.url.add(new URL('https://localhost/componentSupplier-B')) diff --git a/tests/integration/Builders.FromNodePackageJson.ComponentBuilder.test.js b/tests/integration/Contrib.FromNodePackageJson.Builders.ComponentBuilder.node.test.js similarity index 89% rename from tests/integration/Builders.FromNodePackageJson.ComponentBuilder.test.js rename to tests/integration/Contrib.FromNodePackageJson.Builders.ComponentBuilder.node.test.js index f96b5f34f..883e1debe 100644 --- a/tests/integration/Builders.FromNodePackageJson.ComponentBuilder.test.js +++ b/tests/integration/Contrib.FromNodePackageJson.Builders.ComponentBuilder.node.test.js @@ -22,19 +22,18 @@ const assert = require('node:assert') const { suite, test } = require('mocha') const { + Contrib, Enums, Models, - Factories, - Builders: { FromNodePackageJson: { ComponentBuilder } } } = require('../../') -suite('integration: Builders.FromNodePackageJson.ComponentBuilder', () => { +suite('integration: Contrib.FromNodePackageJson.Builders.ComponentBuilder', () => { const salt = Math.random() - const extRefFactory = new Factories.FromNodePackageJson.ExternalReferenceFactory() - const licenseFactory = new Factories.LicenseFactory() + const extRefFactory = new Contrib.FromNodePackageJson.Factories.ExternalReferenceFactory() + const licenseFactory = new Contrib.License.Factories.LicenseFactory() - const sut = new ComponentBuilder(extRefFactory, licenseFactory); + const sut = new Contrib.FromNodePackageJson.Builders.ComponentBuilder(extRefFactory, licenseFactory); [ [ diff --git a/tests/integration/Builders.FromNodePackageJson.ToolBuilders.test.js b/tests/integration/Contrib.FromNodePackageJson.Builders.ToolBuilder.node.test.js similarity index 83% rename from tests/integration/Builders.FromNodePackageJson.ToolBuilders.test.js rename to tests/integration/Contrib.FromNodePackageJson.Builders.ToolBuilder.node.test.js index 0db754405..f87664d85 100644 --- a/tests/integration/Builders.FromNodePackageJson.ToolBuilders.test.js +++ b/tests/integration/Contrib.FromNodePackageJson.Builders.ToolBuilder.node.test.js @@ -22,18 +22,17 @@ const assert = require('node:assert') const { suite, test } = require('mocha') const { + Contrib, Models, - Factories, - Builders: { FromNodePackageJson: { ToolBuilder } } } = require('../../') -suite('integration: Builders.FromNodePackageJson.ToolBuilder', () => { +suite('integration: Contrib.FromNodePackageJson.Builders.ToolBuilder', () => { const salt = Math.random() - const extRefFactory = new Factories.FromNodePackageJson.ExternalReferenceFactory() + const extRefFactory = new Contrib.FromNodePackageJson.Factories.ExternalReferenceFactory() extRefFactory.makeExternalReferences = () => [`FAKE REFERENCES ${salt}`] - const sut = new ToolBuilder(extRefFactory) + const sut = new Contrib.FromNodePackageJson.Builders.ToolBuilder(extRefFactory) const data = { name: '@foo/bar', diff --git a/tests/integration/Factories.FromNodePackageJson.ExternalReferenceFactory.test.js b/tests/integration/Contrib.FromNodePackageJson.Factories.ExternalReferenceFactory.node.test.js similarity index 98% rename from tests/integration/Factories.FromNodePackageJson.ExternalReferenceFactory.test.js rename to tests/integration/Contrib.FromNodePackageJson.Factories.ExternalReferenceFactory.node.test.js index f57be4b42..ecad5d059 100644 --- a/tests/integration/Factories.FromNodePackageJson.ExternalReferenceFactory.test.js +++ b/tests/integration/Contrib.FromNodePackageJson.Factories.ExternalReferenceFactory.node.test.js @@ -24,11 +24,11 @@ const { suite, test } = require('mocha') const { Enums: { ExternalReferenceType, HashAlgorithm }, Models: { ExternalReference, HashDictionary }, - Factories: { FromNodePackageJson: { ExternalReferenceFactory } } + Contrib, } = require('../../') -suite('integration: Factories.FromNodePackageJson.ExternalReferenceFactory', () => { - const sut = new ExternalReferenceFactory() +suite('integration: Contrib.FromNodePackageJson.Factories.ExternalReferenceFactory', () => { + const sut = new Contrib.FromNodePackageJson.Factories.ExternalReferenceFactory() suite('from "homepage"', () => { test('is non-empty string', () => { diff --git a/tests/integration/Factories.LicenseFactory.test.js b/tests/integration/Contrib.License.Factories.LicenseFactory.test.js similarity index 82% rename from tests/integration/Factories.LicenseFactory.test.js rename to tests/integration/Contrib.License.Factories.LicenseFactory.test.js index ebfd52f74..3f454efc9 100644 --- a/tests/integration/Factories.LicenseFactory.test.js +++ b/tests/integration/Contrib.License.Factories.LicenseFactory.test.js @@ -20,15 +20,18 @@ Copyright (c) OWASP Foundation. All Rights Reserved. const assert = require('node:assert') const { suite, test } = require('mocha') +const spdxExpressionValidate = require('spdx-expression-parse') const { - Factories: { LicenseFactory }, + Contrib, Models: { LicenseExpression, NamedLicense, SpdxLicense } } = require('../../') -suite('integration: Factories.LicenseFactory', () => { +suite('integration: Contrib.License.Factories.LicenseFactory', () => { test('makeFromString() -> LicenseExpression', () => { - const sut = new LicenseFactory() + const sut = new Contrib.License.Factories.LicenseFactory( + spdxExpressionValidate + ) const expression = '(MIT OR Apache-2.0)' const license = sut.makeFromString(expression) @@ -38,7 +41,7 @@ suite('integration: Factories.LicenseFactory', () => { }) test('makeFromString() -> NamedLicense', () => { - const sut = new LicenseFactory() + const sut = new Contrib.License.Factories.LicenseFactory() const license = sut.makeFromString('(c) foo bar') @@ -49,7 +52,7 @@ suite('integration: Factories.LicenseFactory', () => { }) test('makeFromString() -> SpdxLicense', () => { - const sut = new LicenseFactory() + const sut = new Contrib.License.Factories.LicenseFactory() const license = sut.makeFromString('MIT') diff --git a/tests/integration/Utils.LicenseUtility.LicenseEvidenceGatherer.node.test.js b/tests/integration/Contrib.License.Utils.LicenseEvidenceGatherer(.test.js similarity index 91% rename from tests/integration/Utils.LicenseUtility.LicenseEvidenceGatherer.node.test.js rename to tests/integration/Contrib.License.Utils.LicenseEvidenceGatherer(.test.js index ded6b551f..12f01a4f4 100644 --- a/tests/integration/Utils.LicenseUtility.LicenseEvidenceGatherer.node.test.js +++ b/tests/integration/Contrib.License.Utils.LicenseEvidenceGatherer(.test.js @@ -26,13 +26,13 @@ const { suite, test } = require('mocha') const { Models: { Attachment }, Enums: { AttachmentEncoding }, - Utils: { LicenseUtility: { LicenseEvidenceGatherer } } + Contrib, } = require('../../') -suite('integration: Utils.LicenseUtility.LicenseEvidenceGatherer', () => { +suite('integration: Contrib.License.Utils.LicenseEvidenceGatherer(', () => { test('no path -> throws', () => { const { fs } = memfs({ '/': {} }) - const leg = new LicenseEvidenceGatherer({ fs }) + const leg = new Contrib.License.Utils.LicenseEvidenceGatherer({ fs }) assert.throws( () => { Array.from( @@ -48,7 +48,7 @@ suite('integration: Utils.LicenseUtility.LicenseEvidenceGatherer', () => { test('no files', () => { const { fs } = memfs({ '/': {} }) - const leg = new LicenseEvidenceGatherer({ fs }) + const leg = new Contrib.License.Utils.LicenseEvidenceGatherer({ fs }) const errors = [] const found = Array.from( leg.getFileAttachments( @@ -66,7 +66,7 @@ suite('integration: Utils.LicenseUtility.LicenseEvidenceGatherer', () => { 'GPL-3.0-or-later.txt': 'GPL-3.0-or-later License text here...' } }) - const leg = new LicenseEvidenceGatherer({ fs }) + const leg = new Contrib.License.Utils.LicenseEvidenceGatherer({ fs }) const found = Array.from( leg.getFileAttachments('/')) assert.deepEqual(found, []) @@ -80,7 +80,7 @@ suite('integration: Utils.LicenseUtility.LicenseEvidenceGatherer', () => { 'GPL-3.0-or-later.txt': 'GPL-3.0-or-later License text here...' } }) - const leg = new LicenseEvidenceGatherer({ fs }) + const leg = new Contrib.License.Utils.LicenseEvidenceGatherer({ fs }) const found = Array.from( leg.getFileAttachments('/')) assert.deepEqual(found, []) @@ -93,7 +93,7 @@ suite('integration: Utils.LicenseUtility.LicenseEvidenceGatherer', () => { `skipped license file ${sep}LICENSE`, { cause: new Error('Custom read error: Access denied!') }) fs.readFileSync = function () { throw expectedError.cause } - const leg = new LicenseEvidenceGatherer({ fs }) + const leg = new Contrib.License.Utils.LicenseEvidenceGatherer({ fs }) const errors = [] const found = Array.from( leg.getFileAttachments( @@ -132,7 +132,7 @@ suite('integration: Utils.LicenseUtility.LicenseEvidenceGatherer', () => { test('finds licenses as expected', () => { const { fs } = memfs({ '/': mockedLicenses }) - const leg = new LicenseEvidenceGatherer({ fs }) + const leg = new Contrib.License.Utils.LicenseEvidenceGatherer({ fs }) const errors = [] const found = Array.from( leg.getFileAttachments( @@ -218,7 +218,7 @@ suite('integration: Utils.LicenseUtility.LicenseEvidenceGatherer', () => { test('does not find licenses in subfolder', () => { const { fs } = memfs({ '/foo': mockedLicenses }) - const leg = new LicenseEvidenceGatherer({ fs }) + const leg = new Contrib.License.Utils.LicenseEvidenceGatherer({ fs }) const found = Array.from( leg.getFileAttachments('/')) assert.deepEqual(found, []) diff --git a/tests/integration/Factories.FromNodePackageJson.PackageUrlFactory.test.js b/tests/integration/Factories.FromNodePackageJson.PackageUrlFactory.test.js deleted file mode 100644 index f97c715df..000000000 --- a/tests/integration/Factories.FromNodePackageJson.PackageUrlFactory.test.js +++ /dev/null @@ -1,301 +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 assert = require('node:assert') - -const { suite, test } = require('mocha') -const { PackageURL } = require('packageurl-js') - -const { - Enums, - Models, - Factories: { FromNodePackageJson: { PackageUrlFactory } } -} = require('../../') - -suite('integration: Factories.FromNodePackageJson.PackageUrlFactory', () => { - const salt = Math.random() - - const sut = new PackageUrlFactory('testing') - - suite('makeFromComponent', () => { - test('no-name-no-purl', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - '' - ) - const expected = undefined - - const actual = sut.makeFromComponent(component) - - assert.strictEqual(actual, expected) - }) - - test('name-group-version', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - group: `@group-${salt}`, - version: `v1+${salt}`, - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('https://foo.bar', Enums.ExternalReferenceType.Website) - ]) - } - ) - const expected = new PackageURL('testing', `@group-${salt}`, `name-${salt}`, `v1+${salt}`, undefined, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('extRef[vcs] -> qualifiers.vcs-url without subpath', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('git+https://foo.bar/repo.git', Enums.ExternalReferenceType.VCS) - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, { vcs_url: 'git+https://foo.bar/repo.git' }, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('extRef[vcs] -> qualifiers.vcs-url with subpath', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('git+https://foo.bar/repo.git#sub/path', Enums.ExternalReferenceType.VCS) - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, { vcs_url: 'git+https://foo.bar/repo.git' }, 'sub/path') - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('extRef[distribution] -> qualifiers.download_url', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('https://foo.bar/download', Enums.ExternalReferenceType.Distribution) - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, { download_url: 'https://foo.bar/download' }, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('extRef[vcs] and extRef[distribution] -> qualifiers.download_url', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('https://foo.bar/download', Enums.ExternalReferenceType.Distribution), - new Models.ExternalReference('git+https://foo.bar/repo.git', Enums.ExternalReferenceType.VCS) - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, { download_url: 'https://foo.bar/download' }, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('extRef[distribution] default repo -> omit', () => { - const downloadUrl = `https://registry.npmjs.org/name-${salt}/-/name-${salt}.tgz` - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference(downloadUrl, Enums.ExternalReferenceType.Distribution) - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, undefined, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('extRef[vcs] and extRef[distribution] default repo -> omit', () => { - const downloadUrl = `https://registry.npmjs.org/name-${salt}/-/name-${salt}.tgz` - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference(downloadUrl, Enums.ExternalReferenceType.Distribution), - new Models.ExternalReference('git+https://foo.bar/repo.git', Enums.ExternalReferenceType.VCS) - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, undefined, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('extRef empty url -> omit', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('', Enums.ExternalReferenceType.VCS), - new Models.ExternalReference('', Enums.ExternalReferenceType.Distribution) - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, undefined, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('hashes and extRef empty url -> omit', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('', Enums.ExternalReferenceType.VCS), - new Models.ExternalReference('', Enums.ExternalReferenceType.Distribution) - ]), - hashes: new Models.HashDictionary([ - [Enums.HashAlgorithm['SHA-256'], 'C3AB8FF13720E8AD9047DD39466B3C8974E592C2FA383D4A3960714CAEF0C4F2'] - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, undefined, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('hashes -> qualifiers.checksum', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('git+https://foo.bar/repo.git', Enums.ExternalReferenceType.VCS) - ]), - hashes: new Models.HashDictionary([ - [Enums.HashAlgorithm['SHA-256'], 'C3AB8FF13720E8AD9047DD39466B3C8974E592C2FA383D4A3960714CAEF0C4F2'] - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, { checksum: 'sha-256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2', vcs_url: 'git+https://foo.bar/repo.git' }, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('sorted hashes', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - 'name', - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('git+https://foo.bar/repo.git', Enums.ExternalReferenceType.VCS) - ]), - hashes: new Models.HashDictionary([ - [Enums.HashAlgorithm['SHA-256'], 'C3AB8FF13720E8AD9047DD39466B3C8974E592C2FA383D4A3960714CAEF0C4F2'], - [Enums.HashAlgorithm.BLAKE3, 'aa51dcd43d5c6c5203ee16906fd6b35db298b9b2e1de3fce81811d4806b76b7d'] - ]) - } - ) - const expectedObject = new PackageURL('testing', undefined, 'name', undefined, - { - // expect sorted hash list - checksum: 'blake3:aa51dcd43d5c6c5203ee16906fd6b35db298b9b2e1de3fce81811d4806b76b7d,sha-256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2', - vcs_url: 'git+https://foo.bar/repo.git' - }, undefined) - // expect objet's keys in alphabetical oder, expect sorted hash list - const expectedString = 'pkg:testing/name?checksum=blake3%3Aaa51dcd43d5c6c5203ee16906fd6b35db298b9b2e1de3fce81811d4806b76b7d%2Csha-256%3Ac3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2&vcs_url=git%2Bhttps%3A%2F%2Ffoo.bar%2Frepo.git' - - const actual = sut.makeFromComponent(component, true) - - assert.deepStrictEqual(actual, expectedObject) - assert.deepStrictEqual(actual.toString(), expectedString) - }) - - test('sorted references', () => { - const component1 = new Models.Component( - Enums.ComponentType.Library, - 'name', - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('https://foo.bar/download-1', Enums.ExternalReferenceType.Distribution), - new Models.ExternalReference('https://foo.bar/download-2', Enums.ExternalReferenceType.Distribution) - ]) - } - ) - const component2 = new Models.Component( - Enums.ComponentType.Library, - 'name', - { - externalReferences: new Models.ExternalReferenceRepository([ - // different order of extRefs - new Models.ExternalReference('https://foo.bar/download-2', Enums.ExternalReferenceType.Distribution), - new Models.ExternalReference('https://foo.bar/download-1', Enums.ExternalReferenceType.Distribution) - ]) - } - ) - const expectedObject = new PackageURL('testing', undefined, 'name', undefined, - { - // expect sorted hash list - download_url: 'https://foo.bar/download-2' - }, undefined) - // expect objet's keys in alphabetical oder, expect sorted hash list - const expectedString = 'pkg:testing/name?download_url=https%3A%2F%2Ffoo.bar%2Fdownload-2' - - const actual1 = sut.makeFromComponent(component1, true) - const actual2 = sut.makeFromComponent(component2, true) - - assert.deepStrictEqual(actual1, expectedObject) - assert.deepStrictEqual(actual1.toString(), expectedString) - assert.deepStrictEqual(actual2, expectedObject) - assert.deepStrictEqual(actual2.toString(), expectedString) - }) - }) -}) diff --git a/tests/integration/Factories.PackageUrlFactory.test.js b/tests/integration/Factories.PackageUrlFactory.test.js deleted file mode 100644 index 4aba9d5d3..000000000 --- a/tests/integration/Factories.PackageUrlFactory.test.js +++ /dev/null @@ -1,227 +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 assert = require('node:assert') - -const { suite, test } = require('mocha') -const { PackageURL } = require('packageurl-js') - -const { - Enums, - Models, - Factories: { PackageUrlFactory } -} = require('../../') - -suite('integration: Factories.PackageUrlFactory', () => { - const salt = Math.random() - - const sut = new PackageUrlFactory('testing') - - suite('makeFromComponent', () => { - test('no-name-no-purl', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - '' - ) - const expected = undefined - - const actual = sut.makeFromComponent(component) - - assert.strictEqual(actual, expected) - }) - - test('name-group-version', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - group: `@group-${salt}`, - version: `v1+${salt}`, - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('https://foo.bar', Enums.ExternalReferenceType.Website) - ]) - } - ) - const expected = new PackageURL('testing', `@group-${salt}`, `name-${salt}`, `v1+${salt}`, {}, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('extRef[vcs] -> qualifiers.vcs-url without subpath', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('git+https://foo.bar/repo.git', Enums.ExternalReferenceType.VCS) - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, { vcs_url: 'git+https://foo.bar/repo.git' }, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('extRef[vcs] -> qualifiers.vcs-url with subpath', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('git+https://foo.bar/repo.git#sub/path', Enums.ExternalReferenceType.VCS) - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, { vcs_url: 'git+https://foo.bar/repo.git' }, 'sub/path') - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('extRef[distribution] -> qualifiers.download_url', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('https://foo.bar/download', Enums.ExternalReferenceType.Distribution) - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, { download_url: 'https://foo.bar/download' }, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('extRef empty url -> omit', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('', Enums.ExternalReferenceType.VCS), - new Models.ExternalReference('', Enums.ExternalReferenceType.Distribution) - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, {}, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('hashes -> qualifiers.checksum', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - `name-${salt}`, - { - hashes: new Models.HashDictionary([ - [Enums.HashAlgorithm['SHA-256'], 'C3AB8FF13720E8AD9047DD39466B3C8974E592C2FA383D4A3960714CAEF0C4F2'] - ]) - } - ) - const expected = new PackageURL('testing', undefined, `name-${salt}`, undefined, { checksum: 'sha-256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2' }, undefined) - - const actual = sut.makeFromComponent(component) - - assert.deepStrictEqual(actual, expected) - }) - - test('sorted hashes', () => { - const component = new Models.Component( - Enums.ComponentType.Library, - 'name', - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('git+https://foo.bar/repo.git', Enums.ExternalReferenceType.VCS), - new Models.ExternalReference('https://foo.bar/download', Enums.ExternalReferenceType.Distribution) - ]), - hashes: new Models.HashDictionary([ - [Enums.HashAlgorithm['SHA-256'], 'C3AB8FF13720E8AD9047DD39466B3C8974E592C2FA383D4A3960714CAEF0C4F2'], - [Enums.HashAlgorithm.BLAKE3, 'aa51dcd43d5c6c5203ee16906fd6b35db298b9b2e1de3fce81811d4806b76b7d'] - ]) - } - ) - const expectedObject = new PackageURL('testing', undefined, 'name', undefined, - { - // expect sorted hash list - checksum: 'blake3:aa51dcd43d5c6c5203ee16906fd6b35db298b9b2e1de3fce81811d4806b76b7d,sha-256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2', - download_url: 'https://foo.bar/download', - vcs_url: 'git+https://foo.bar/repo.git' - }, undefined) - // expect objet's keys in alphabetical oder, expect sorted hash list - const expectedString = 'pkg:testing/name?checksum=blake3%3Aaa51dcd43d5c6c5203ee16906fd6b35db298b9b2e1de3fce81811d4806b76b7d%2Csha-256%3Ac3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2&download_url=https%3A%2F%2Ffoo.bar%2Fdownload&vcs_url=git%2Bhttps%3A%2F%2Ffoo.bar%2Frepo.git' - - const actual = sut.makeFromComponent(component, true) - - assert.deepStrictEqual(actual, expectedObject) - assert.deepStrictEqual(actual.toString(), expectedString) - }) - - test('sorted references', () => { - const component1 = new Models.Component( - Enums.ComponentType.Library, - 'name', - { - externalReferences: new Models.ExternalReferenceRepository([ - new Models.ExternalReference('https://foo.bar/download-1', Enums.ExternalReferenceType.Distribution), - new Models.ExternalReference('git+https://foo.bar/repo.git', Enums.ExternalReferenceType.VCS), - new Models.ExternalReference('https://foo.bar/download-2', Enums.ExternalReferenceType.Distribution) - ]) - } - ) - const component2 = new Models.Component( - Enums.ComponentType.Library, - 'name', - { - externalReferences: new Models.ExternalReferenceRepository([ - // different order of extRefs - new Models.ExternalReference('https://foo.bar/download-2', Enums.ExternalReferenceType.Distribution), - new Models.ExternalReference('git+https://foo.bar/repo.git', Enums.ExternalReferenceType.VCS), - new Models.ExternalReference('https://foo.bar/download-1', Enums.ExternalReferenceType.Distribution) - ]) - } - ) - const expectedObject = new PackageURL('testing', undefined, 'name', undefined, - { - // expect sorted hash list - download_url: 'https://foo.bar/download-2', - vcs_url: 'git+https://foo.bar/repo.git' - }, undefined) - // expect objet's keys in alphabetical oder, expect sorted hash list - const expectedString = 'pkg:testing/name?download_url=https%3A%2F%2Ffoo.bar%2Fdownload-2&vcs_url=git%2Bhttps%3A%2F%2Ffoo.bar%2Frepo.git' - - const actual1 = sut.makeFromComponent(component1, true) - const actual2 = sut.makeFromComponent(component2, true) - - assert.deepStrictEqual(actual1, expectedObject) - assert.deepStrictEqual(actual1.toString(), expectedString) - assert.deepStrictEqual(actual2, expectedObject) - assert.deepStrictEqual(actual2.toString(), expectedString) - }) - }) -}) diff --git a/tests/unit/Utils.BomUtility.spec.js b/tests/unit/Contrib.Bom.Utils.spec.js similarity index 87% rename from tests/unit/Utils.BomUtility.spec.js rename to tests/unit/Contrib.Bom.Utils.spec.js index 9173fb3e2..a58572f35 100644 --- a/tests/unit/Utils.BomUtility.spec.js +++ b/tests/unit/Contrib.Bom.Utils.spec.js @@ -22,19 +22,17 @@ const assert = require('node:assert') const { suite, test } = require('mocha') const { - Utils: { - BomUtility - } + Contrib, } = require('../../') -suite('unit: Utils.BomUtility', () => { +suite('unit: Contrib.Bom.Utils', () => { suite('randomSerialNumber()', () => { test('has correct format according to XSD', () => { - const value = BomUtility.randomSerialNumber() + const value = Contrib.Bom.Utils.randomSerialNumber() assert.match(value, /^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$|^\\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\}$/) }) test('has correct format according to JSON schema', () => { - const value = BomUtility.randomSerialNumber() + const value = Contrib.Bom.Utils.randomSerialNumber() assert.match(value, /^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/) }) }) diff --git a/tests/unit/Builders.FromNodePackageJson.ComponentBuilder.spec.js b/tests/unit/Contrib.FromNodePackageJson.Builders.ComponentBuilder.node.spec.js similarity index 70% rename from tests/unit/Builders.FromNodePackageJson.ComponentBuilder.spec.js rename to tests/unit/Contrib.FromNodePackageJson.Builders.ComponentBuilder.node.spec.js index 3cb820a09..23aeb7b5c 100644 --- a/tests/unit/Builders.FromNodePackageJson.ComponentBuilder.spec.js +++ b/tests/unit/Contrib.FromNodePackageJson.Builders.ComponentBuilder.node.spec.js @@ -22,19 +22,15 @@ const assert = require('node:assert') const { suite, test } = require('mocha') const { - Builders: { FromNodePackageJson: { ComponentBuilder } }, - Factories: { - FromNodePackageJson: { ExternalReferenceFactory }, - LicenseFactory - } + Contrib, } = require('../../') -suite('unit: Builders.FromNodePackageJson.ComponentBuilder', () => { +suite('unit: Contrib.FromNodePackageJson.Builders.ComponentBuilder', () => { test('construct', () => { - const extRefFactory = new ExternalReferenceFactory() - const licenseFactory = new LicenseFactory() + const extRefFactory = new Contrib.FromNodePackageJson.Factories.ExternalReferenceFactory() + const licenseFactory = new Contrib.License.Factories.LicenseFactory() - const actual = new ComponentBuilder(extRefFactory, licenseFactory) + const actual = new Contrib.FromNodePackageJson.Builders.ComponentBuilder(extRefFactory, licenseFactory) assert.strictEqual(actual.extRefFactory, extRefFactory) assert.strictEqual(actual.licenseFactory, licenseFactory) diff --git a/tests/unit/Builders.FromNodePackageJson.ToolBuilder.spec.js b/tests/unit/Contrib.FromNodePackageJson.Builders.ToolBuilder.node.spec.js similarity index 75% rename from tests/unit/Builders.FromNodePackageJson.ToolBuilder.spec.js rename to tests/unit/Contrib.FromNodePackageJson.Builders.ToolBuilder.node.spec.js index 25c20fd81..5dfbe91f9 100644 --- a/tests/unit/Builders.FromNodePackageJson.ToolBuilder.spec.js +++ b/tests/unit/Contrib.FromNodePackageJson.Builders.ToolBuilder.node.spec.js @@ -22,15 +22,14 @@ const assert = require('node:assert') const { suite, test } = require('mocha') const { - Builders: { FromNodePackageJson: { ToolBuilder } }, - Factories: { FromNodePackageJson: { ExternalReferenceFactory } } + Contrib, } = require('../../') -suite('unit: Builders.FromNodePackageJson.ToolBuilder', () => { +suite('unit: Contrib.FromNodePackageJson.Builders.ToolBuilder', () => { test('construct', () => { - const extRefFactory = new ExternalReferenceFactory() + const extRefFactory = new Contrib.FromNodePackageJson.Factories.ExternalReferenceFactory() - const actual = new ToolBuilder(extRefFactory) + const actual = new Contrib.FromNodePackageJson.Builders.ToolBuilder(extRefFactory) assert.strictEqual(actual.extRefFactory, extRefFactory) }) diff --git a/tests/unit/Contrib.FromNodePackageJson.Utils.node.spec.js b/tests/unit/Contrib.FromNodePackageJson.Utils.node.spec.js new file mode 100644 index 000000000..fbcc619ec --- /dev/null +++ b/tests/unit/Contrib.FromNodePackageJson.Utils.node.spec.js @@ -0,0 +1,95 @@ +/*! +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 assert = require('node:assert') + +const { suite, test } = require('mocha') + +const { + Enums: { + HashAlgorithm + }, + Contrib, +} = require('../../') + +suite('unit: Contrib.FromNodePackageJson.Utils', () => { + suite('defaultRegistryMatcher', () => { + test('matches pure domain', () => { + const actual = Contrib.FromNodePackageJson.Utils.defaultRegistryMatcher.test('https://registry.npmjs.org') + assert.strictEqual(actual, true) + }) + test('matches with path', () => { + const actual = Contrib.FromNodePackageJson.Utils.defaultRegistryMatcher.test('https://registry.npmjs.org/foo/bar') + assert.strictEqual(actual, true) + }) + suite('not match unexpected', () => { + for (const c of [ + 'https://my-own=registry.local', + 'https://registry.npmjs.org.uk', + 'https://registry.npmjs.org.uk/foo/bar' + ]) { + test(c, () => { + const actual = Contrib.FromNodePackageJson.Utils.defaultRegistryMatcher.test(c) + assert.strictEqual(actual, false) + }) + } + }) + }) + + suite('unit: parsePackageIntegrity', () => { + suite('as expected', () => { + for (const [c, ...expected] of [ + ['sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==', + HashAlgorithm['SHA-512'], + 'cef8fae53905788b778ba6a3e5b22f243ce38d0406b38a3fb0da1ece0d45d6461aa7d36eda3714769c334522531cc3331b41fb6d9927e2b350a489a1bb1597d8' + ], + ['sha1-Kq5sNclPz7QV2+lfQIuc6R7oRu0=', + HashAlgorithm['SHA-1'], + '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed' + ], + ['sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=', + HashAlgorithm['SHA-256'], + 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' + ], + ['sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC', + HashAlgorithm['SHA-384'], + 'a2a56e01f5d129aa7b7dd81c098e6eca433af91f46a90f0afeec72f6bc7b1cd42519897590fcd0868d70c7827063cc02' + ], + ]) { + test(c, () => { + const actual = Contrib.FromNodePackageJson.Utils.parsePackageIntegrity(c) + assert.deepStrictEqual(actual, expected) + }) + } + }) + suite('fails', () => { + for (const c of [ + 'sha1-Kq5sNclPz7QV2+lfQIuc6R7oRu0', // missing character + 'sha1-Kq5sNclPz7QV2+lfQIuc6R7oRu0==', // additional character + 'sha512-Kq5sNclPz7QV2+lfQIuc6R7oRu0=', // alg and hash dont match + ]) { + test(c, () => { + assert.throws(() => { + Contrib.FromNodePackageJson.Utils.parsePackageIntegrity(c) + }) + }) + } + }) + }) +}) diff --git a/tests/unit/Factories.FromNodePackageJson.PackageUrlFactory.js b/tests/unit/Factories.FromNodePackageJson.PackageUrlFactory.js deleted file mode 100644 index a91c4b1c1..000000000 --- a/tests/unit/Factories.FromNodePackageJson.PackageUrlFactory.js +++ /dev/null @@ -1,86 +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 assert = require('node:assert') - -const { suite, test } = require('mocha') - -const { - Factories: { FromNodePackageJson: { PackageUrlFactory } }, - Enums: { ComponentType, ExternalReferenceType }, - Models: { Component, ExternalReference, ExternalReferenceRepository } -} = require('../../') - -suite('unit: Factories.FromNodePackageJson.PackageUrlFactory', () => { - suite('makeFromComponent()', () => { - test('plain', () => { - const component = new Component(ComponentType.Library, 'testing') - const purlFac = new PackageUrlFactory('npm') - const actual = purlFac.makeFromComponent(component) - assert.deepEqual(actual, 'TODO') - }) - - test('strips default registry from qualifiers', () => { - // see https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst#npm - const component = new Component(ComponentType.Library, 'testing', { - externalReferences: new ExternalReferenceRepository([ - new ExternalReference( - 'https://registry.npmjs.org/@cyclonedx/cyclonedx-library/-/cyclonedx-library-1.0.0-beta.2.tgz', - ExternalReferenceType.Distribution - ) - ]) - }) - const purlFac = new PackageUrlFactory('npm') - const actual = purlFac.makeFromComponent(component) - assert.deepEqual(actual, { - type: 'npm', - name: 'testing', - namespace: undefined, - version: undefined, - qualifiers: undefined, - subpath: undefined - }) - }) - - test('dont strip BA registry from qualifiers', () => { - // regression test for https://github.com/CycloneDX/cyclonedx-javascript-library/issues/1073 - const component = new Component(ComponentType.Library, 'testing', { - externalReferences: new ExternalReferenceRepository([ - new ExternalReference( - 'https://registry.npmjs.org.badactor.net/@cyclonedx/cyclonedx-library/-/cyclonedx-library-1.0.0-beta.2.tgz', - ExternalReferenceType.Distribution - ) - ]) - }) - const purlFac = new PackageUrlFactory('npm') - const actual = purlFac.makeFromComponent(component) - assert.deepEqual(actual, - { - type: 'npm', - name: 'testing', - namespace: undefined, - version: undefined, - qualifiers: { - download_url: 'https://registry.npmjs.org.badactor.net/@cyclonedx/cyclonedx-library/-/cyclonedx-library-1.0.0-beta.2.tgz' - }, - subpath: undefined - }) - }) - }) -}) diff --git a/tests/unit/Factories.PackageUrlFactory.spec.js b/tests/unit/Factories.PackageUrlFactory.spec.js deleted file mode 100644 index a72763ca5..000000000 --- a/tests/unit/Factories.PackageUrlFactory.spec.js +++ /dev/null @@ -1,37 +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 assert = require('node:assert') - -const { suite, test } = require('mocha') - -const { - Factories: { PackageUrlFactory } -} = require('../../') -const { randomString } = require('../_helpers/stringFunctions') - -suite('unit: Factories.PackageUrlFactory', () => { - test('construct', () => { - const type = randomString(5) - - const actual = new PackageUrlFactory(type) - - assert.strictEqual(actual.type, type) - }) -}) diff --git a/tests/unit/Models.Component.spec.js b/tests/unit/Models.Component.spec.js index 7c7fa1e8f..b01d35a87 100644 --- a/tests/unit/Models.Component.spec.js +++ b/tests/unit/Models.Component.spec.js @@ -20,7 +20,6 @@ Copyright (c) OWASP Foundation. All Rights Reserved. const assert = require('node:assert') const { suite, test } = require('mocha') -const { PackageURL } = require('packageurl-js') const { Models: { @@ -62,7 +61,7 @@ suite('unit: Models.Component', () => { const dummyBomRef = new BomRef('testing') const dummyExtRef = new ExternalReference('../', 'other') const dummyLicense = new NamedLicense('mine') - const dummyPurl = new PackageURL('npm', 'ns', 'app', '1.33.7', {}, undefined) + const dummyPurl = 'pkg:npm/ns/app@1.33.7' const dummySupplier = new OrganizationalEntity({ name: 'dummySupplier' }) const dummySWID = new SWID('my-fake-swid', 'foo-bar') const subComponent = new Component('library', 'MySubComponent') diff --git a/tests/unit/Utils.NpmjsUtility.spec.js b/tests/unit/Utils.NpmjsUtility.spec.js deleted file mode 100644 index b05cca8ba..000000000 --- a/tests/unit/Utils.NpmjsUtility.spec.js +++ /dev/null @@ -1,95 +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 assert = require('node:assert') - -const { suite, test } = require('mocha') - -const { - Enums: { - HashAlgorithm - }, - Utils: { - NpmjsUtility - } -} = require('../../') - -suite('unit: Utils.NpmjsUtility.defaultRegistryMatcher', () => { - test('matches pure domain', () => { - const actual = NpmjsUtility.defaultRegistryMatcher.test('https://registry.npmjs.org') - assert.strictEqual(actual, true) - }) - test('matches with path', () => { - const actual = NpmjsUtility.defaultRegistryMatcher.test('https://registry.npmjs.org/foo/bar') - assert.strictEqual(actual, true) - }) - suite('not match unexpected', () => { - for (const c of [ - 'https://my-own=registry.local', - 'https://registry.npmjs.org.uk', - 'https://registry.npmjs.org.uk/foo/bar' - ]) { - test(c, () => { - const actual = NpmjsUtility.defaultRegistryMatcher.test(c) - assert.strictEqual(actual, false) - }) - } - }) -}) - -suite('unit: Utils.NpmjsUtility.parsePackageIntegrity', () => { - suite('as expected', () => { - for (const [c, ...expected] of [ - ['sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==', - HashAlgorithm['SHA-512'], - 'cef8fae53905788b778ba6a3e5b22f243ce38d0406b38a3fb0da1ece0d45d6461aa7d36eda3714769c334522531cc3331b41fb6d9927e2b350a489a1bb1597d8' - ], - ['sha1-Kq5sNclPz7QV2+lfQIuc6R7oRu0=', - HashAlgorithm['SHA-1'], - '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed' - ], - ['sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=', - HashAlgorithm['SHA-256'], - 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' - ], - ['sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC', - HashAlgorithm['SHA-384'], - 'a2a56e01f5d129aa7b7dd81c098e6eca433af91f46a90f0afeec72f6bc7b1cd42519897590fcd0868d70c7827063cc02' - ], - ]) { - test(c, () => { - const actual = NpmjsUtility.parsePackageIntegrity(c) - assert.deepStrictEqual(actual, expected) - }) - } - }) - suite('fails', () => { - for (const c of [ - 'sha1-Kq5sNclPz7QV2+lfQIuc6R7oRu0', // missing character - 'sha1-Kq5sNclPz7QV2+lfQIuc6R7oRu0==', // additional character - 'sha512-Kq5sNclPz7QV2+lfQIuc6R7oRu0=', // alg and hash dont match - ]) { - test(c, () => { - assert.throws(() => { - NpmjsUtility.parsePackageIntegrity(c) - }) - }) - } - }) -})