diff --git a/package-lock.json b/package-lock.json index 78fe85db..e03a3ffa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2163,14 +2163,6 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, - "packageurl-js": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/packageurl-js/-/packageurl-js-0.0.1.tgz", - "integrity": "sha512-hjMzq6XuAxMMiV55UOIhf6byXKR9Fc046ybroGCpjGtJ5EI9QJG9g/ErYoPt0RGUaAr51C6x+pwUG9pXgLnaqg==", - "requires": { - "urijs": "^1.19.1" - } - }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -2180,11 +2172,6 @@ "callsites": "^3.0.0" } }, - "parse-packagejson-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-packagejson-name/-/parse-packagejson-name-1.0.1.tgz", - "integrity": "sha1-q1syLNOMh7SgFiBoPMpWrXTABqA=" - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2250,11 +2237,6 @@ "fast-diff": "^1.1.2" } }, - "prettify-xml": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/prettify-xml/-/prettify-xml-1.2.0.tgz", - "integrity": "sha1-Rtzx7oqNi3PbMLfgbvJtyc8/bxg=" - }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -2804,11 +2786,6 @@ "punycode": "^2.1.0" } }, - "urijs": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.2.tgz", - "integrity": "sha512-s/UIq9ap4JPZ7H1EB5ULo/aOUbWqfDi7FKzMC2Nz+0Si8GiT1rIEaprt8hy3Vy2Ex2aJPpOQv4P4DuOZ+K1c6w==" - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index c24df245..26007a3e 100644 --- a/package.json +++ b/package.json @@ -81,9 +81,6 @@ "node-fetch": "^2.6.0", "node-persist": "^3.0.5", "ora": "^4.0.3", - "packageurl-js": "^0.0.1", - "parse-packagejson-name": "^1.0.1", - "prettify-xml": "^1.2.0", "read-installed": "~4.0.3", "spdx-license-ids": "^3.0.5", "ssri": "^6.0.0", diff --git a/src/CycloneDX/CycloneDXSbomCreator.ts b/src/CycloneDX/CycloneDXSbomCreator.ts index 25d6155b..928b4545 100644 --- a/src/CycloneDX/CycloneDXSbomCreator.ts +++ b/src/CycloneDX/CycloneDXSbomCreator.ts @@ -1,5 +1,3 @@ -/// -/// /// /// /* @@ -21,8 +19,6 @@ import { Options } from './Options'; import uuidv4 from 'uuid/v4'; import builder from 'xmlbuilder'; import readInstalled from 'read-installed'; -import PackageURL from 'packageurl-js'; -import parsePackageJsonName from 'parse-packagejson-name'; import * as ssri from 'ssri'; import * as fs from 'fs'; import { LicenseContent } from './Types/LicenseContent'; @@ -31,6 +27,7 @@ import { ExternalReference } from './Types/ExternalReference'; import { Hash } from './Types/Hash'; import spdxLicensesNonDeprecated = require('spdx-license-ids'); import spdxLicensesDeprecated = require('spdx-license-ids/deprecated'); +import { toPurl } from './Helpers/Helpers'; export class CycloneDXSbomCreator { readonly licenseFilenames: Array = [ @@ -113,11 +110,11 @@ export class CycloneDXSbomCreator { return; } if (!isRootPkg) { - const pkgIdentifier = parsePackageJsonName(pkg.name); - const group: string = pkgIdentifier.scope == null ? '' : `@${pkgIdentifier.scope}`; + const pkgIdentifier = this.parsePackageJsonName(pkg.name); + const group: string = pkgIdentifier.scope == undefined ? '' : `@${pkgIdentifier.scope}`; const name: string = pkgIdentifier.fullName as string; const version: string = pkg.version as string; - const purl: string = new PackageURL('npm', group, name, version, null, null).toString(); + const purl: string = toPurl(name, version, group); const description: GenericDescription = { '#cdata': pkg.description }; const component: Component = { @@ -302,4 +299,31 @@ export class CycloneDXSbomCreator { } return undefined; } + + private parsePackageJsonName(name: string): Result { + const result: Result = { + scope: undefined, + fullName: '', + projectName: '', + moduleName: '', + }; + + const regexp = new RegExp(/^(?:@([^/]+)\/)?(([^\.]+)(?:\.(.*))?)$/); + + const matches = name.match(regexp); + if (matches) { + result.scope = matches[1] || undefined; + result.fullName = matches[2] || matches[0]; + result.projectName = matches[3] === matches[2] ? undefined : matches[3]; + result.moduleName = matches[4] || matches[2] || undefined; + } + return result; + } +} + +interface Result { + scope?: string; + fullName: string; + projectName?: string; + moduleName?: string; } diff --git a/src/CycloneDX/Helpers/Helpers.ts b/src/CycloneDX/Helpers/Helpers.ts new file mode 100644 index 00000000..2adc7c41 --- /dev/null +++ b/src/CycloneDX/Helpers/Helpers.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020-present Sonatype, Inc. + * + * 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. + */ + +export const toPurl = (name: string, version: string, group = ''): string => { + if (group != '') { + return `pkg:npm/${encodeURIComponent(group)}/${name}@${version}`; + } + return `pkg:npm/${name}@${version}`; +}; diff --git a/src/CycloneDX/typings/packageurl-js/index.d.ts b/src/CycloneDX/typings/packageurl-js/index.d.ts deleted file mode 100644 index acbac5d5..00000000 --- a/src/CycloneDX/typings/packageurl-js/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'packageurl-js';