diff --git a/HISTORY.md b/HISTORY.md index 5dc4ab778..c92e21cca 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -6,6 +6,11 @@ All notable changes to this project will be documented in this file. +* Added + * Public export `types.NodePackageJson`, which is the input type for various factories and builders (via [#1263]) + +[#1263]: https://github.com/CycloneDX/cyclonedx-javascript-library/pull/1263 + ## 8.4.0 -- 2025-06-16 * Fixed diff --git a/src/_helpers/packageJson.ts b/src/_helpers/packageJson.ts index c7bdf6554..c5a03e11e 100644 --- a/src/_helpers/packageJson.ts +++ b/src/_helpers/packageJson.ts @@ -33,34 +33,3 @@ export function splitNameGroup (data: string): [string, string?] { : [data, undefined] } -/** - * Intended to represent 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). - */ -export interface PackageJson { - name?: string - version?: string - description?: string - license?: string - licenses?: Array<{ - type?: string - url?: string - }> - author?: string | { - name?: string - email?: string - } - bugs?: string | { - url?: string - } - homepage?: string - repository?: string | { - type?: string - url?: string - directory?: string - } - // ... to be continued - dist?: any // see https://github.com/CycloneDX/cyclonedx-node-npm/issues/1300 -} diff --git a/src/builders/fromNodePackageJson.node.ts b/src/builders/fromNodePackageJson.node.ts index f94957daf..db0a88d80 100644 --- a/src/builders/fromNodePackageJson.node.ts +++ b/src/builders/fromNodePackageJson.node.ts @@ -26,7 +26,6 @@ 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 { PackageJson } from '../_helpers/packageJson' import { splitNameGroup } from '../_helpers/packageJson' import { ComponentType } from '../enums/componentType' import type * as Factories from '../factories/index.node' @@ -34,6 +33,7 @@ import { Component } from '../models/component' import { ExternalReferenceRepository } from '../models/externalReference' import { LicenseRepository } from '../models/license' import { Tool } from '../models/tool' +import type { NodePackageJson } from '../types/nodePackageJson' /** * Node-specific ToolBuilder. @@ -51,7 +51,7 @@ export class ToolBuilder { // Current implementation does not return `undefined` yet, but it is an option for future implementation. // To prevent future breaking changes, it is declared to return `undefined`. - makeTool (data: PackageJson): Tool | undefined { + makeTool (data: NodePackageJson): Tool | undefined { const [name, vendor] = typeof data.name === 'string' ? splitNameGroup(data.name) : [] @@ -90,7 +90,7 @@ export class ComponentBuilder { return this.#licenseFactory } - makeComponent (data: PackageJson, type: ComponentType = ComponentType.Library): Component | undefined { + makeComponent (data: NodePackageJson, type: ComponentType = ComponentType.Library): Component | undefined { if (typeof data.name !== 'string') { return undefined } diff --git a/src/factories/fromNodePackageJson.node.ts b/src/factories/fromNodePackageJson.node.ts index 80073b66d..3c8137880 100644 --- a/src/factories/fromNodePackageJson.node.ts +++ b/src/factories/fromNodePackageJson.node.ts @@ -31,12 +31,12 @@ import { PurlQualifierNames } from 'packageurl-js' import { tryCanonicalizeGitUrl } from "../_helpers/gitUrl" import { isNotUndefined } from '../_helpers/notUndefined' -import type { PackageJson } from '../_helpers/packageJson' 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 type { NodePackageJson } from '../types/nodePackageJson' import { defaultRegistryMatcher, parsePackageIntegrity } from '../utils/npmjsUtility.node' import { PackageUrlFactory as PlainPackageUrlFactory } from './packageUrl' @@ -44,7 +44,7 @@ import { PackageUrlFactory as PlainPackageUrlFactory } from './packageUrl' * Node-specific ExternalReferenceFactory. */ export class ExternalReferenceFactory { - makeExternalReferences (data: PackageJson): ExternalReference[] { + makeExternalReferences (data: NodePackageJson): ExternalReference[] { const refs: Array = [] try { refs.push(this.makeVcs(data)) } catch { /* pass */ } @@ -55,7 +55,7 @@ export class ExternalReferenceFactory { return refs.filter(isNotUndefined) } - makeVcs (data: PackageJson): ExternalReference | undefined { + makeVcs (data: NodePackageJson): ExternalReference | undefined { /* see https://docs.npmjs.com/cli/v9/configuring-npm/package-json#repositoryc */ const repository = data.repository let url = undefined @@ -78,7 +78,7 @@ export class ExternalReferenceFactory { : new ExternalReference(url.toString(), ExternalReferenceType.VCS, { comment }) } - makeHomepage (data: PackageJson): ExternalReference | undefined { + makeHomepage (data: NodePackageJson): ExternalReference | undefined { /* see https://docs.npmjs.com/cli/v9/configuring-npm/package-json#homepage */ const url = data.homepage return typeof url === 'string' && url.length > 0 @@ -88,7 +88,7 @@ export class ExternalReferenceFactory { : undefined } - makeIssueTracker (data: PackageJson): ExternalReference | undefined { + makeIssueTracker (data: NodePackageJson): ExternalReference | undefined { /* see https://docs.npmjs.com/cli/v9/configuring-npm/package-json#bugs */ const bugs = data.bugs let url = undefined @@ -105,7 +105,7 @@ export class ExternalReferenceFactory { : undefined } - makeDist(data: PackageJson): ExternalReference | undefined { + makeDist(data: NodePackageJson): ExternalReference | undefined { // "dist" might be used in bundled dependencies' manifests. // docs: https://blog.npmjs.org/post/172999548390/new-pgp-machinery /* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- acknowledged */ diff --git a/src/types/index.ts b/src/types/index.ts index 2db668d77..2f2e2f09f 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -21,3 +21,6 @@ export * from './cpe' export * from './cwe' export * from './integer' export * from './mimeType' + +// yes, this is node-specific, but who cares - these are just types +export * from './nodePackageJson' diff --git a/src/types/nodePackageJson.ts b/src/types/nodePackageJson.ts new file mode 100644 index 000000000..66864118e --- /dev/null +++ b/src/types/nodePackageJson.ts @@ -0,0 +1,86 @@ +/*! +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. +*/ + +/** + * Intended to represent 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). + */ +export interface NodePackageJson { + name?: string + version?: string + description?: string + license?: string + licenses?: Array<{ + type?: string + url?: string + }> + author?: string | { + name?: string + email?: string + } + bugs?: string | { + url?: string + } + homepage?: string + repository?: string | { + type?: string + url?: string + directory?: string + } + // ... to be continued + dist?: any // see https://github.com/CycloneDX/cyclonedx-node-npm/issues/1300 +} + +/** + * + * Not implemented, yet. + * TODO: write type guard -- pull-requests welcome + * + * @alpha + */ +export function isNodePackageJson (value: any): value is NodePackageJson { + throw new Error('Not implemented') + /* possible implementation: + try { assertNodePackageJson(value) } + catch { return false } + return true + */ +} + +/** + * + * Not implemented, yet. + * TODO: write type assertion -- pull-requests welcome + * + * @throws {@link Error} on error; includes qualitative message + * + * @alpha + */ +export function assertNodePackageJson (value: any): asserts value is NodePackageJson { + throw new Error('Not implemented') + /* possible implementation: + if ( value === null || value === undefined ) { throw new Error('value not an object') } + if ( !(typeof value.name in ['undefined', 'string']) ) { throw new Error('unexpected name') } + etc... + */ +}