@cyclonedx/cyclonedx-library 8.3.0 → 8.4.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -79,6 +79,7 @@ written in _TypeScript_ and compiled for the target.
79
79
  * `Vulnerability`, `VulnerabilityRepository`
80
80
  * Utilities for the following use cases:
81
81
  * Generate valid random SerialNumbers for `Bom.serialNumber`
82
+ * Gather license evidences from files (for _Node.js_ only)
82
83
  * Factories for the following use cases:
83
84
  * Create data models from any license descriptor string
84
85
  * Create `PackageURL` from `Component` data models
@@ -0,0 +1,22 @@
1
+ /*!
2
+ This file is part of CycloneDX JavaScript Library.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+
16
+ SPDX-License-Identifier: Apache-2.0
17
+ Copyright (c) OWASP Foundation. All Rights Reserved.
18
+ */
19
+ type MimeType = string;
20
+ export declare function guessMimeTypeForLicenseFile(filename: string): MimeType | undefined;
21
+ export {};
22
+ //# sourceMappingURL=mime.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mime.node.d.ts","sourceRoot":"","sources":["../../src/_helpers/mime.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;EAiBE;AAIF,KAAK,QAAQ,GAAG,MAAM,CAAA;AA8BtB,wBAAgB,2BAA2B,CAAE,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAKnF"}
@@ -17,5 +17,6 @@ SPDX-License-Identifier: Apache-2.0
17
17
  Copyright (c) OWASP Foundation. All Rights Reserved.
18
18
  */
19
19
  export * from './index.common';
20
+ export * as LicenseUtility from './licenseUtility.node';
20
21
  export * as NpmjsUtility from './npmjsUtility.node';
21
22
  //# sourceMappingURL=index.node.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.node.d.ts","sourceRoot":"","sources":["../../src/utils/index.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;EAiBE;AAEF,cAAc,gBAAgB,CAAA;AAI9B,OAAO,KAAK,YAAY,MAAM,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.node.d.ts","sourceRoot":"","sources":["../../src/utils/index.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;EAiBE;AAEF,cAAc,gBAAgB,CAAA;AAI9B,OAAO,KAAK,cAAc,MAAM,uBAAuB,CAAA;AACvD,OAAO,KAAK,YAAY,MAAM,qBAAqB,CAAA"}
@@ -0,0 +1,55 @@
1
+ /*!
2
+ This file is part of CycloneDX JavaScript Library.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+
16
+ SPDX-License-Identifier: Apache-2.0
17
+ Copyright (c) OWASP Foundation. All Rights Reserved.
18
+ */
19
+ /**
20
+ * 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.
21
+ * In addition, we use type parameters for all `PathLike`s, so downstream users can utilize their implementations accordingly.
22
+ *
23
+ * @module
24
+ */
25
+ import type { Stats } from 'node:fs';
26
+ import { Attachment } from '../models/attachment';
27
+ export interface FsUtils<P extends string> {
28
+ readdirSync: (path: P) => P[];
29
+ readFileSync: (path: P) => Buffer;
30
+ statSync: (path: P) => Stats;
31
+ }
32
+ export interface PathUtils<P extends string> {
33
+ join: (...paths: P[]) => P;
34
+ }
35
+ export interface FileAttachment<P extends string> {
36
+ filePath: P;
37
+ file: P;
38
+ text: Attachment;
39
+ }
40
+ export type ErrorReporter = (e: Error) => any;
41
+ export declare class LicenseEvidenceGatherer<P extends string = string> {
42
+ #private;
43
+ /**
44
+ * `fs` and `path` can be supplied, if any compatibility-layer or drop-in replacement is used.
45
+ *
46
+ * @param options.fs - If omitted, the native `node:fs` is used.
47
+ * @param options.path - If omitted, the native `node:path` is used.
48
+ */
49
+ constructor(options?: {
50
+ fs?: FsUtils<P>;
51
+ path?: PathUtils<P>;
52
+ });
53
+ getFileAttachments(prefixPath: P, onError?: ErrorReporter): Generator<FileAttachment<P>>;
54
+ }
55
+ //# sourceMappingURL=licenseUtility.node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"licenseUtility.node.d.ts","sourceRoot":"","sources":["../../src/utils/licenseUtility.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;EAiBE;AAEF;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAIpC,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAEjD,MAAM,WAAW,OAAO,CAAC,CAAC,SAAS,MAAM;IACvC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,KAAM,CAAC,EAAE,CAAA;IAC9B,YAAY,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAA;IACjC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,KAAK,CAAA;CAC7B;AAED,MAAM,WAAW,SAAS,CAAC,CAAC,SAAS,MAAM;IACzC,IAAI,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;CAC3B;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,MAAM;IAC9C,QAAQ,EAAE,CAAC,CAAA;IACX,IAAI,EAAE,CAAC,CAAA;IACP,IAAI,EAAE,UAAU,CAAA;CACjB;AAID,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,EAAC,KAAK,KAAK,GAAG,CAAA;AAE5C,qBAAa,uBAAuB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;;IAK5D;;;;;OAKG;gBACU,OAAO,GAAE;QAAE,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;KAAO;IAQjE,kBAAkB,CAAE,UAAU,EAAE,CAAC,EAAE,OAAO,GAAE,aAAoB,GAAG,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;CA6BlG"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ /*!
3
+ This file is part of CycloneDX JavaScript Library.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+
17
+ SPDX-License-Identifier: Apache-2.0
18
+ Copyright (c) OWASP Foundation. All Rights Reserved.
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.guessMimeTypeForLicenseFile = guessMimeTypeForLicenseFile;
22
+ const node_path_1 = require("node:path");
23
+ const MIMETYPE_TEXT_PLAIN = 'text/plain';
24
+ const MAP_TEXT_EXTENSION_MIMETYPE = {
25
+ '': MIMETYPE_TEXT_PLAIN,
26
+ '.csv': 'text/csv',
27
+ '.htm': 'text/html',
28
+ '.html': 'text/html',
29
+ '.md': 'text/markdown',
30
+ '.txt': MIMETYPE_TEXT_PLAIN,
31
+ '.rst': 'text/prs.fallenstein.rst',
32
+ '.rtf': 'application/rtf',
33
+ '.xml': 'text/xml',
34
+ '.license': MIMETYPE_TEXT_PLAIN,
35
+ '.licence': MIMETYPE_TEXT_PLAIN,
36
+ };
37
+ const LICENSE_FILENAME_BASE = new Set(['licence', 'license']);
38
+ const LICENSE_FILENAME_EXT = new Set([
39
+ '.apache',
40
+ '.bsd',
41
+ '.gpl',
42
+ '.mit',
43
+ ]);
44
+ function guessMimeTypeForLicenseFile(filename) {
45
+ const { name, ext } = (0, node_path_1.parse)(filename.toLowerCase());
46
+ return LICENSE_FILENAME_BASE.has(name) && LICENSE_FILENAME_EXT.has(ext)
47
+ ? MIMETYPE_TEXT_PLAIN
48
+ : MAP_TEXT_EXTENSION_MIMETYPE[ext];
49
+ }
50
+ //# sourceMappingURL=mime.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mime.node.js","sourceRoot":"","sources":["../../src/_helpers/mime.node.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;EAiBE;;AAkCF,kEAKC;AArCD,yCAA8C;AAI9C,MAAM,mBAAmB,GAAa,YAAY,CAAA;AAElD,MAAM,2BAA2B,GAAuC;IACtE,EAAE,EAAE,mBAAmB;IAEvB,MAAM,EAAE,UAAU;IAClB,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,WAAW;IACpB,KAAK,EAAE,eAAe;IACtB,MAAM,EAAE,mBAAmB;IAC3B,MAAM,EAAE,0BAA0B;IAClC,MAAM,EAAE,iBAAiB;IACzB,MAAM,EAAE,UAAU;IAGlB,UAAU,EAAE,mBAAmB;IAC/B,UAAU,EAAE,mBAAmB;CACvB,CAAA;AAEV,MAAM,qBAAqB,GAA2B,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAA;AACrF,MAAM,oBAAoB,GAA0B,IAAI,GAAG,CAAC;IAC1D,SAAS;IACT,MAAM;IACN,MAAM;IACN,MAAM;CAEP,CAAC,CAAA;AAEF,SAAgB,2BAA2B,CAAE,QAAgB;IAC3D,MAAM,EAAC,IAAI,EAAE,GAAG,EAAC,GAAG,IAAA,iBAAS,EAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;IACrD,OAAO,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC;QACrE,CAAC,CAAC,mBAAmB;QACrB,CAAC,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAA;AACtC,CAAC"}
@@ -54,7 +54,8 @@ var __importStar = (this && this.__importStar) || (function () {
54
54
  };
55
55
  })();
56
56
  Object.defineProperty(exports, "__esModule", { value: true });
57
- exports.NpmjsUtility = void 0;
57
+ exports.NpmjsUtility = exports.LicenseUtility = void 0;
58
58
  __exportStar(require("./index.common"), exports);
59
+ exports.LicenseUtility = __importStar(require("./licenseUtility.node"));
59
60
  exports.NpmjsUtility = __importStar(require("./npmjsUtility.node"));
60
61
  //# sourceMappingURL=index.node.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.node.js","sourceRoot":"","sources":["../../src/utils/index.node.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;EAiBE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEF,iDAA8B;AAI9B,oEAAmD"}
1
+ {"version":3,"file":"index.node.js","sourceRoot":"","sources":["../../src/utils/index.node.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;EAiBE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEF,iDAA8B;AAI9B,wEAAuD;AACvD,oEAAmD"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ /*!
3
+ This file is part of CycloneDX JavaScript Library.
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
16
+
17
+ SPDX-License-Identifier: Apache-2.0
18
+ Copyright (c) OWASP Foundation. All Rights Reserved.
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.LicenseEvidenceGatherer = void 0;
22
+ const mime_node_1 = require("../_helpers/mime.node");
23
+ const attachmentEncoding_1 = require("../enums/attachmentEncoding");
24
+ const attachment_1 = require("../models/attachment");
25
+ const LICENSE_FILENAME_PATTERN = /^(?:UN)?LICEN[CS]E|.\.LICEN[CS]E$|^NOTICE$/i;
26
+ class LicenseEvidenceGatherer {
27
+ #fs;
28
+ #path;
29
+ constructor(options = {}) {
30
+ this.#fs = options.fs ?? require('node:fs');
31
+ this.#path = options.path ?? require('node:path');
32
+ }
33
+ *getFileAttachments(prefixPath, onError = noop) {
34
+ const files = this.#fs.readdirSync(prefixPath);
35
+ for (const file of files) {
36
+ if (!LICENSE_FILENAME_PATTERN.test(file)) {
37
+ continue;
38
+ }
39
+ const filePath = this.#path.join(prefixPath, file);
40
+ if (!this.#fs.statSync(filePath).isFile()) {
41
+ continue;
42
+ }
43
+ const contentType = (0, mime_node_1.guessMimeTypeForLicenseFile)(file);
44
+ if (contentType === undefined) {
45
+ continue;
46
+ }
47
+ try {
48
+ yield { filePath, file, text: new attachment_1.Attachment(this.#fs.readFileSync(filePath)
49
+ .toString('base64'), { contentType, encoding: attachmentEncoding_1.AttachmentEncoding.Base64 }) };
50
+ }
51
+ catch (cause) {
52
+ onError(new Error(`skipped license file ${filePath}`, { cause }));
53
+ }
54
+ }
55
+ }
56
+ }
57
+ exports.LicenseEvidenceGatherer = LicenseEvidenceGatherer;
58
+ function noop() { }
59
+ //# sourceMappingURL=licenseUtility.node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"licenseUtility.node.js","sourceRoot":"","sources":["../../src/utils/licenseUtility.node.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;EAiBE;;;AAWF,qDAAmE;AACnE,oEAAgE;AAChE,qDAAiD;AAkBjD,MAAM,wBAAwB,GAAG,6CAA6C,CAAA;AAI9E,MAAa,uBAAuB;IACzB,GAAG,CAAY;IACf,KAAK,CAAc;IAS5B,YAAa,UAAoD,EAAE;QAEjE,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,EAAE,IAAI,OAAO,CAAC,SAAS,CAAC,CAAA;QAC3C,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC,CAAA;IAEnD,CAAC;IAGD,CAAE,kBAAkB,CAAE,UAAa,EAAE,UAAyB,IAAI;QAChE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,CAAA;QAC9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzC,SAAQ;YACV,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;YAClD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;gBAG1C,SAAQ;YACV,CAAC;YACD,MAAM,WAAW,GAAG,IAAA,uCAA2B,EAAC,IAAI,CAAC,CAAA;YACrD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;gBAC9B,SAAQ;YACV,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,uBAAU,CAGxC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC;yBAC1B,QAAQ,CAAC,QAAQ,CAAC,EACvB,EAAE,WAAW,EAAE,QAAQ,EAAE,uCAAkB,CAAC,MAAM,EAAE,CACrD,EAAE,CAAA;YACP,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,KAAK,CAAC,wBAAwB,QAAQ,EAAE,EAAE,EAAC,KAAK,EAAC,CAAC,CAAC,CAAA;YACjE,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAhDD,0DAgDC;AAGD,SAAS,IAAI,KAAU,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyclonedx/cyclonedx-library",
3
- "version": "8.3.0",
3
+ "version": "8.4.0-rc.0",
4
4
  "description": "Core functionality of CycloneDX for JavaScript (Node.js or WebBrowser).",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -97,6 +97,7 @@
97
97
  "c8": "^10",
98
98
  "deepmerge": "^4.2.2",
99
99
  "fast-glob": "^3.3.1",
100
+ "memfs": "4.17.2",
100
101
  "mocha": "11.5.0",
101
102
  "npm-run-all2": "^8",
102
103
  "rimraf": "^6",
@@ -106,12 +107,15 @@
106
107
  "webpack-cli": "6.0.1",
107
108
  "webpack-node-externals": "3.0.0"
108
109
  },
109
- "browser": "./dist.web/lib.js",
110
110
  "types": "./dist.d/index.node.d.ts",
111
+ "browser": "./dist.web/lib.js",
111
112
  "main": "./dist.node/index.node.js",
112
113
  "exports": {
113
114
  ".": {
114
- "types": "./dist.d/index.node.d.ts",
115
+ "types": {
116
+ "browser": "./dist.d/index.web.d.ts",
117
+ "default": "./dist.d/index.node.d.ts"
118
+ },
115
119
  "browser": "./dist.web/lib.js",
116
120
  "default": "./dist.node/index.node.js"
117
121
  },
@@ -187,7 +191,7 @@
187
191
  "test:lint": "tsc --noEmit",
188
192
  "test:standard": "npm --prefix tools/code-style exec -- eslint .",
189
193
  "cs-fix": "npm --prefix tools/code-style exec -- eslint --fix .",
190
- "api-doc": "run-p --aggregate-output -lc api-doc:*",
194
+ "api-doc": "run-p --aggregate-output -lc api-doc:\\*",
191
195
  "api-doc:node": "npm --prefix tools/docs-gen exec -- typedoc --options ./typedoc.node.json",
192
196
  "api-doc:web": "npm --prefix tools/docs-gen exec -- typedoc --options ./typedoc.web.json"
193
197
  }
@@ -0,0 +1,57 @@
1
+ /*!
2
+ This file is part of CycloneDX JavaScript Library.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+
16
+ SPDX-License-Identifier: Apache-2.0
17
+ Copyright (c) OWASP Foundation. All Rights Reserved.
18
+ */
19
+
20
+ import { parse as parsePath } from 'node:path'
21
+
22
+ type MimeType = string
23
+
24
+ const MIMETYPE_TEXT_PLAIN: MimeType = 'text/plain'
25
+
26
+ const MAP_TEXT_EXTENSION_MIMETYPE: Readonly<Record<string, MimeType>> = {
27
+ '': MIMETYPE_TEXT_PLAIN,
28
+ // https://www.iana.org/assignments/media-types/media-types.xhtml
29
+ '.csv': 'text/csv',
30
+ '.htm': 'text/html',
31
+ '.html': 'text/html',
32
+ '.md': 'text/markdown',
33
+ '.txt': MIMETYPE_TEXT_PLAIN,
34
+ '.rst': 'text/prs.fallenstein.rst',
35
+ '.rtf': 'application/rtf', // our scope is text, yes, but RTF is binary - so we should base64 encode it ...
36
+ '.xml': 'text/xml', // not `application/xml` -- our scope is text!
37
+ // add more mime types above this line. pull-requests welcome!
38
+ // license-specific files
39
+ '.license': MIMETYPE_TEXT_PLAIN,
40
+ '.licence': MIMETYPE_TEXT_PLAIN,
41
+ } as const
42
+
43
+ const LICENSE_FILENAME_BASE: Readonly<Set<string>> = new Set(['licence', 'license'])
44
+ const LICENSE_FILENAME_EXT: Readonly<Set<string>> = new Set([
45
+ '.apache',
46
+ '.bsd',
47
+ '.gpl',
48
+ '.mit',
49
+ // to be continued ... pullrequests welcome
50
+ ])
51
+
52
+ export function guessMimeTypeForLicenseFile (filename: string): MimeType | undefined {
53
+ const {name, ext} = parsePath(filename.toLowerCase())
54
+ return LICENSE_FILENAME_BASE.has(name) && LICENSE_FILENAME_EXT.has(ext)
55
+ ? MIMETYPE_TEXT_PLAIN
56
+ : MAP_TEXT_EXTENSION_MIMETYPE[ext]
57
+ }
@@ -21,6 +21,7 @@ export * from './index.common'
21
21
 
22
22
  // region node-specifics
23
23
 
24
+ export * as LicenseUtility from './licenseUtility.node'
24
25
  export * as NpmjsUtility from './npmjsUtility.node'
25
26
 
26
27
  // endregion node-specifics
@@ -0,0 +1,104 @@
1
+ /*!
2
+ This file is part of CycloneDX JavaScript Library.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+
16
+ SPDX-License-Identifier: Apache-2.0
17
+ Copyright (c) OWASP Foundation. All Rights Reserved.
18
+ */
19
+
20
+ /**
21
+ * 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.
22
+ * In addition, we use type parameters for all `PathLike`s, so downstream users can utilize their implementations accordingly.
23
+ *
24
+ * @module
25
+ */
26
+
27
+ import type { Stats } from 'node:fs'
28
+
29
+ import { guessMimeTypeForLicenseFile } from '../_helpers/mime.node'
30
+ import { AttachmentEncoding } from '../enums/attachmentEncoding'
31
+ import { Attachment } from '../models/attachment'
32
+
33
+ export interface FsUtils<P extends string> {
34
+ readdirSync: (path: P ) => P[]
35
+ readFileSync: (path: P) => Buffer
36
+ statSync: (path: P) => Stats
37
+ }
38
+
39
+ export interface PathUtils<P extends string> {
40
+ join: (...paths: P[]) => P
41
+ }
42
+
43
+ export interface FileAttachment<P extends string> {
44
+ filePath: P
45
+ file: P
46
+ text: Attachment
47
+ }
48
+
49
+ const LICENSE_FILENAME_PATTERN = /^(?:UN)?LICEN[CS]E|.\.LICEN[CS]E$|^NOTICE$/i
50
+
51
+ export type ErrorReporter = (e:Error) => any
52
+
53
+ export class LicenseEvidenceGatherer<P extends string = string> {
54
+ readonly #fs: FsUtils<P>
55
+ readonly #path: PathUtils<P>
56
+
57
+ /* eslint-disable tsdoc/syntax -- we want to use the dot-syntax - https://github.com/microsoft/tsdoc/issues/19 */
58
+ /**
59
+ * `fs` and `path` can be supplied, if any compatibility-layer or drop-in replacement is used.
60
+ *
61
+ * @param options.fs - If omitted, the native `node:fs` is used.
62
+ * @param options.path - If omitted, the native `node:path` is used.
63
+ */
64
+ constructor (options: { fs?: FsUtils<P>, path?: PathUtils<P> } = {}) {
65
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports -- needed */
66
+ this.#fs = options.fs ?? require('node:fs')
67
+ this.#path = options.path ?? require('node:path')
68
+ /* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports */
69
+ }
70
+ /* eslint-enable tsdoc/syntax */
71
+
72
+ * getFileAttachments (prefixPath: P, onError: ErrorReporter = noop): Generator<FileAttachment<P>> {
73
+ const files = this.#fs.readdirSync(prefixPath) // may throw
74
+ for (const file of files) {
75
+ if (!LICENSE_FILENAME_PATTERN.test(file)) {
76
+ continue
77
+ }
78
+ const filePath = this.#path.join(prefixPath, file)
79
+ if (!this.#fs.statSync(filePath).isFile()) {
80
+ // Ignore all directories - they are not files :-)
81
+ // Don't follow symlinks for security reasons!
82
+ continue
83
+ }
84
+ const contentType = guessMimeTypeForLicenseFile(file)
85
+ if (contentType === undefined) {
86
+ continue
87
+ }
88
+ try {
89
+ yield { filePath, file, text: new Attachment(
90
+ // since we cannot be sure weather the file content is text-only, or maybe binary,
91
+ // we tend to base64 everything, regardless of the detected encoding.
92
+ this.#fs.readFileSync(filePath) // may throw
93
+ .toString('base64'),
94
+ { contentType, encoding: AttachmentEncoding.Base64 }
95
+ ) }
96
+ } catch (cause) {
97
+ onError(new Error(`skipped license file ${filePath}`, {cause}))
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+ /* eslint-disable-next-line @typescript-eslint/no-empty-function -- ack */
104
+ function noop ():void {}
package/tsconfig.json CHANGED
@@ -102,7 +102,8 @@
102
102
 
103
103
  /* Completeness */
104
104
  "skipDefaultLibCheck": false, /* Skip type checking .d.ts files that are included with TypeScript. */
105
- "skipLibCheck": false /* Skip type checking all .d.ts files. */
105
+ // needed for https://github.com/oozcitak/util/issues/13
106
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */
106
107
  },
107
108
  "exclude": [
108
109
  "node_modules",