From 88e1ef2c8cf73506ec87e9b468384cc9eae9b76f Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Sun, 13 Jul 2025 20:03:04 +0200 Subject: [PATCH 1/8] feat: public export of type `PackageJson` Signed-off-by: Jan Kowalleck --- src/_helpers/packageJson.ts | 31 ------------ src/builders/fromNodePackageJson.node.ts | 2 +- src/factories/fromNodePackageJson.node.ts | 2 +- src/types/index.ts | 3 ++ src/types/packageJson.ts | 59 +++++++++++++++++++++++ 5 files changed, 64 insertions(+), 33 deletions(-) create mode 100644 src/types/packageJson.ts 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..997f0702a 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 { PackageJson } from '../types/packageJson' /** * Node-specific ToolBuilder. diff --git a/src/factories/fromNodePackageJson.node.ts b/src/factories/fromNodePackageJson.node.ts index 80073b66d..e7b52338e 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 { PackageJson } from '../types/packageJson' import { defaultRegistryMatcher, parsePackageIntegrity } from '../utils/npmjsUtility.node' import { PackageUrlFactory as PlainPackageUrlFactory } from './packageUrl' diff --git a/src/types/index.ts b/src/types/index.ts index 2db668d77..4d4dc80bf 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 type * from './packageJson' diff --git a/src/types/packageJson.ts b/src/types/packageJson.ts new file mode 100644 index 000000000..fc9f91fba --- /dev/null +++ b/src/types/packageJson.ts @@ -0,0 +1,59 @@ +/*! +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 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 +} + + +/* TODO: write type assertion +export function isPackageJsonNode (value: any): value is PackageJsonNode { + return... +} +*/ From e4b6a51e17dd7fffe70ebe14fb54deb4694ac9ef Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Sun, 13 Jul 2025 20:17:49 +0200 Subject: [PATCH 2/8] docs Signed-off-by: Jan Kowalleck --- HISTORY.md | 5 +++++ src/builders/fromNodePackageJson.node.ts | 6 +++--- src/factories/fromNodePackageJson.node.ts | 12 ++++++------ src/types/{packageJson.ts => nodePackageJson.ts} | 6 +++--- 4 files changed, 17 insertions(+), 12 deletions(-) rename src/types/{packageJson.ts => nodePackageJson.ts} (93%) 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/builders/fromNodePackageJson.node.ts b/src/builders/fromNodePackageJson.node.ts index 997f0702a..db0a88d80 100644 --- a/src/builders/fromNodePackageJson.node.ts +++ b/src/builders/fromNodePackageJson.node.ts @@ -33,7 +33,7 @@ import { Component } from '../models/component' import { ExternalReferenceRepository } from '../models/externalReference' import { LicenseRepository } from '../models/license' import { Tool } from '../models/tool' -import type { PackageJson } from '../types/packageJson' +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 e7b52338e..3c8137880 100644 --- a/src/factories/fromNodePackageJson.node.ts +++ b/src/factories/fromNodePackageJson.node.ts @@ -36,7 +36,7 @@ import { HashAlgorithm } from "../enums/hashAlogorithm"; import type { Component } from '../models/component' import { ExternalReference } from '../models/externalReference' import { HashDictionary } from '../models/hash' -import type { PackageJson } from '../types/packageJson' +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/packageJson.ts b/src/types/nodePackageJson.ts similarity index 93% rename from src/types/packageJson.ts rename to src/types/nodePackageJson.ts index fc9f91fba..a176cc73c 100644 --- a/src/types/packageJson.ts +++ b/src/types/nodePackageJson.ts @@ -25,7 +25,7 @@ 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). */ -export interface PackageJson { +export interface NodePackageJson { name?: string version?: string description?: string @@ -53,7 +53,7 @@ export interface PackageJson { /* TODO: write type assertion -export function isPackageJsonNode (value: any): value is PackageJsonNode { - return... +export function isNodePackageJson (value: any): value is NodePackageJson { + ... } */ From 3a11249fbc65b1dd8120f4cd17738448129cad4d Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Sun, 13 Jul 2025 20:22:16 +0200 Subject: [PATCH 3/8] docs Signed-off-by: Jan Kowalleck --- src/types/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/index.ts b/src/types/index.ts index 4d4dc80bf..e333f7062 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -23,4 +23,4 @@ export * from './integer' export * from './mimeType' // yes, this is node-specific, but who cares - these are just types -export type * from './packageJson' +export type * from './nodePackageJson' From 21e93dd0d4840a20cc97c5a70a3d75484aec250c Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Sun, 13 Jul 2025 21:03:25 +0200 Subject: [PATCH 4/8] wip Signed-off-by: Jan Kowalleck --- src/types/index.ts | 2 +- src/types/nodePackageJson.ts | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/types/index.ts b/src/types/index.ts index e333f7062..2f2e2f09f 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -23,4 +23,4 @@ export * from './integer' export * from './mimeType' // yes, this is node-specific, but who cares - these are just types -export type * from './nodePackageJson' +export * from './nodePackageJson' diff --git a/src/types/nodePackageJson.ts b/src/types/nodePackageJson.ts index a176cc73c..3e1e37c04 100644 --- a/src/types/nodePackageJson.ts +++ b/src/types/nodePackageJson.ts @@ -52,8 +52,7 @@ export interface NodePackageJson { } -/* TODO: write type assertion export function isNodePackageJson (value: any): value is NodePackageJson { - ... + /* TODO: write type assertion -- pullrequests welcome */ + throw new Error("Not implemented") } -*/ From 7a3079f2d0ce69a8dfbac185c08261db5485d72f Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Sun, 13 Jul 2025 21:09:43 +0200 Subject: [PATCH 5/8] wip Signed-off-by: Jan Kowalleck --- src/types/nodePackageJson.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/types/nodePackageJson.ts b/src/types/nodePackageJson.ts index 3e1e37c04..8daf1dfca 100644 --- a/src/types/nodePackageJson.ts +++ b/src/types/nodePackageJson.ts @@ -51,8 +51,12 @@ export interface NodePackageJson { dist?: any // see https://github.com/CycloneDX/cyclonedx-node-npm/issues/1300 } - +/** + * + * + * Not implemented, yet. + * TODO: write type assertion -- pullrequests welcome + */ export function isNodePackageJson (value: any): value is NodePackageJson { - /* TODO: write type assertion -- pullrequests welcome */ throw new Error("Not implemented") } From 92edacc84000ce35f4d58aec93a86504331a3ced Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Sun, 13 Jul 2025 22:49:04 +0200 Subject: [PATCH 6/8] wip Signed-off-by: Jan Kowalleck --- src/types/nodePackageJson.ts | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/types/nodePackageJson.ts b/src/types/nodePackageJson.ts index 8daf1dfca..8afab6be0 100644 --- a/src/types/nodePackageJson.ts +++ b/src/types/nodePackageJson.ts @@ -52,11 +52,35 @@ export interface NodePackageJson { } /** - * * * Not implemented, yet. - * TODO: write type assertion -- pullrequests welcome + * TODO: write type guard -- pull-requests welcome + * + * @alpha */ export function isNodePackageJson (value: any): value is NodePackageJson { - throw new Error("Not implemented") + 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 with qualitative error 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... + */ } From 3771d3635e5c7eb40930ee7231c56b6a1ee5783c Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Sun, 13 Jul 2025 22:49:56 +0200 Subject: [PATCH 7/8] wip Signed-off-by: Jan Kowalleck --- src/types/nodePackageJson.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/nodePackageJson.ts b/src/types/nodePackageJson.ts index 8afab6be0..8c21daee1 100644 --- a/src/types/nodePackageJson.ts +++ b/src/types/nodePackageJson.ts @@ -72,7 +72,7 @@ export function isNodePackageJson (value: any): value is NodePackageJson { * Not implemented, yet. * TODO: write type assertion -- pull-requests welcome * - * @throws {@link Error} on error with qualitative error message + * @throws {@link Error} on error; includes qualitative message * * @alpha */ From 023184a451e97197252d82148f6867e2b438ce48 Mon Sep 17 00:00:00 2001 From: Jan Kowalleck Date: Sun, 13 Jul 2025 22:56:01 +0200 Subject: [PATCH 8/8] wip Signed-off-by: Jan Kowalleck --- src/types/nodePackageJson.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/nodePackageJson.ts b/src/types/nodePackageJson.ts index 8c21daee1..66864118e 100644 --- a/src/types/nodePackageJson.ts +++ b/src/types/nodePackageJson.ts @@ -62,7 +62,7 @@ export function isNodePackageJson (value: any): value is NodePackageJson { throw new Error('Not implemented') /* possible implementation: try { assertNodePackageJson(value) } - catch{ return false } + catch { return false } return true */ }