@cyclonedx/cyclonedx-library 3.0.0 → 5.0.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.
Files changed (49) hide show
  1. package/dist.d/enums/index.d.ts +1 -0
  2. package/dist.d/enums/index.d.ts.map +1 -1
  3. package/dist.d/enums/lifecyclePhase.d.ts +28 -0
  4. package/dist.d/enums/lifecyclePhase.d.ts.map +1 -0
  5. package/dist.d/models/index.d.ts +1 -0
  6. package/dist.d/models/index.d.ts.map +1 -1
  7. package/dist.d/models/lifecycle.d.ts +35 -0
  8. package/dist.d/models/lifecycle.d.ts.map +1 -0
  9. package/dist.d/models/metadata.d.ts +3 -0
  10. package/dist.d/models/metadata.d.ts.map +1 -1
  11. package/dist.d/serialize/json/normalize.d.ts +5 -0
  12. package/dist.d/serialize/json/normalize.d.ts.map +1 -1
  13. package/dist.d/serialize/json/types.d.ts +9 -0
  14. package/dist.d/serialize/json/types.d.ts.map +1 -1
  15. package/dist.d/serialize/xml/normalize.d.ts +5 -0
  16. package/dist.d/serialize/xml/normalize.d.ts.map +1 -1
  17. package/dist.d/spec.d.ts +1 -0
  18. package/dist.d/spec.d.ts.map +1 -1
  19. package/dist.node/enums/index.js +1 -0
  20. package/dist.node/enums/index.js.map +1 -1
  21. package/dist.node/enums/lifecyclePhase.js +32 -0
  22. package/dist.node/enums/lifecyclePhase.js.map +1 -0
  23. package/dist.node/models/index.js +1 -0
  24. package/dist.node/models/index.js.map +1 -1
  25. package/dist.node/models/lifecycle.js +56 -0
  26. package/dist.node/models/lifecycle.js.map +1 -0
  27. package/dist.node/models/metadata.js +2 -0
  28. package/dist.node/models/metadata.js.map +1 -1
  29. package/dist.node/serialize/json/normalize.js +20 -1
  30. package/dist.node/serialize/json/normalize.js.map +1 -1
  31. package/dist.node/serialize/xml/normalize.js +38 -1
  32. package/dist.node/serialize/xml/normalize.js.map +1 -1
  33. package/dist.node/spec.js +12 -7
  34. package/dist.node/spec.js.map +1 -1
  35. package/dist.web/lib.dev.js +187 -16
  36. package/dist.web/lib.dev.js.map +1 -1
  37. package/dist.web/lib.js +1 -1
  38. package/dist.web/lib.js.map +1 -1
  39. package/package.json +11 -9
  40. package/src/enums/index.ts +1 -0
  41. package/src/enums/lifecyclePhase.ts +28 -0
  42. package/src/models/index.ts +1 -0
  43. package/src/models/lifecycle.ts +56 -0
  44. package/src/models/metadata.ts +4 -0
  45. package/src/serialize/json/normalize.ts +23 -0
  46. package/src/serialize/json/types.ts +12 -0
  47. package/src/serialize/xml/normalize.ts +41 -0
  48. package/src/spec.ts +15 -3
  49. package/webpack.config.js +3 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyclonedx/cyclonedx-library",
3
- "version": "3.0.0",
3
+ "version": "5.0.0",
4
4
  "description": "Core functionality of CycloneDX for JavaScript (Node.js or WebBrowser).",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
@@ -77,25 +77,27 @@
77
77
  "xmlbuilder2": "^3.0.2"
78
78
  },
79
79
  "devDependencies": {
80
- "@types/mocha": "^10.0.0",
80
+ "@types/mocha": "^10",
81
81
  "@types/node": "ts5.1",
82
- "@types/spdx-expression-parse": "^3.0.2",
83
- "c8": "^8.0.0",
82
+ "@types/spdx-expression-parse": "^3",
83
+ "c8": "^8",
84
84
  "deepmerge": "^4.2.2",
85
85
  "eslint": "^8.23.0",
86
- "eslint-config-standard-with-typescript": "^35.0.0",
86
+ "eslint-config-standard": "^17.0.0",
87
+ "eslint-config-standard-with-typescript": "^37.0.0",
87
88
  "eslint-plugin-header": "^3.1.1",
88
89
  "eslint-plugin-jsdoc": "^46.2.0",
89
90
  "eslint-plugin-simple-import-sort": "^10.0.0",
90
91
  "eslint-plugin-tsdoc": "^0.2.17",
91
92
  "mocha": "10.2.0",
92
93
  "npm-run-all": "^4.1.5",
93
- "ts-loader": "9.4.3",
94
+ "ts-loader": "9.4.4",
94
95
  "typedoc": "^0.24.4",
95
96
  "typedoc-plugin-missing-exports": "^2.0.0",
96
- "typescript": "5.1.5",
97
- "webpack": "5.88.0",
98
- "webpack-cli": "5.1.4"
97
+ "typescript": "5.1.6",
98
+ "webpack": "5.88.2",
99
+ "webpack-cli": "5.1.4",
100
+ "webpack-node-externals": "^3.0.0"
99
101
  },
100
102
  "browser": "./dist.web/lib.js",
101
103
  "types": "./dist.d/index.node.d.ts",
@@ -22,4 +22,5 @@ export * from './componentScope'
22
22
  export * from './componentType'
23
23
  export * from './externalReferenceType'
24
24
  export * from './hashAlogorithm'
25
+ export * from './lifecyclePhase'
25
26
  export * as Vulnerability from './vulnerability'
@@ -0,0 +1,28 @@
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
+ export enum LifecyclePhase {
21
+ Design = 'design',
22
+ PreBuild = 'pre-build',
23
+ Build = 'build',
24
+ PostBuild = 'post-build',
25
+ Operations = 'operations',
26
+ Discovery = 'discovery',
27
+ Decommission = 'decommission',
28
+ }
@@ -25,6 +25,7 @@ export * from './component'
25
25
  export * from './externalReference'
26
26
  export * from './hash'
27
27
  export * from './license'
28
+ export * from './lifecycle'
28
29
  export * from './metadata'
29
30
  export * from './organizationalContact'
30
31
  export * from './organizationalEntity'
@@ -0,0 +1,56 @@
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 type { Comparable, Sortable } from '../_helpers/sortable'
21
+ import type { LifecyclePhase } from '../enums'
22
+
23
+ export interface OptionalNamedLifecycleProperties {
24
+ description?: NamedLifecycle['description']
25
+ }
26
+
27
+ export class NamedLifecycle implements Comparable<NamedLifecycle> {
28
+ name: string
29
+ description?: string
30
+
31
+ constructor (name: string, op: OptionalNamedLifecycleProperties = {}) {
32
+ this.name = name
33
+ this.description = op.description
34
+ }
35
+
36
+ compare (other: NamedLifecycle): number {
37
+ return this.name.localeCompare(other.name)
38
+ }
39
+ }
40
+
41
+ export type Lifecycle = LifecyclePhase | NamedLifecycle
42
+
43
+ export class LifecycleRepository extends Set<Lifecycle> implements Sortable<Lifecycle> {
44
+ #compareItems (a: Lifecycle, b: Lifecycle): number {
45
+ if (a.constructor === b.constructor) {
46
+ return a instanceof NamedLifecycle
47
+ ? a.compare(b as NamedLifecycle)
48
+ : (a as string).localeCompare(b as string)
49
+ }
50
+ return a.constructor.name.localeCompare(b.constructor.name)
51
+ }
52
+
53
+ sorted (): Lifecycle[] {
54
+ return Array.from(this).sort(this.#compareItems)
55
+ }
56
+ }
@@ -18,12 +18,14 @@ Copyright (c) OWASP Foundation. All Rights Reserved.
18
18
  */
19
19
 
20
20
  import type { Component } from './component'
21
+ import { LifecycleRepository } from './lifecycle'
21
22
  import { OrganizationalContactRepository } from './organizationalContact'
22
23
  import type { OrganizationalEntity } from './organizationalEntity'
23
24
  import { ToolRepository } from './tool'
24
25
 
25
26
  export interface OptionalMetadataProperties {
26
27
  timestamp?: Metadata['timestamp']
28
+ lifecycles?: Metadata['lifecycles']
27
29
  tools?: Metadata['tools']
28
30
  authors?: Metadata['authors']
29
31
  component?: Metadata['component']
@@ -33,6 +35,7 @@ export interface OptionalMetadataProperties {
33
35
 
34
36
  export class Metadata {
35
37
  timestamp?: Date
38
+ lifecycles: LifecycleRepository
36
39
  tools: ToolRepository
37
40
  authors: OrganizationalContactRepository
38
41
  component?: Component
@@ -41,6 +44,7 @@ export class Metadata {
41
44
 
42
45
  constructor (op: OptionalMetadataProperties = {}) {
43
46
  this.timestamp = op.timestamp
47
+ this.lifecycles = op.lifecycles ?? new LifecycleRepository()
44
48
  this.tools = op.tools ?? new ToolRepository()
45
49
  this.authors = op.authors ?? new OrganizationalContactRepository()
46
50
  this.component = op.component
@@ -56,6 +56,10 @@ export class Factory {
56
56
  return new ComponentEvidenceNormalizer(this)
57
57
  }
58
58
 
59
+ makeForLifecycle (): LifecycleNormalizer {
60
+ return new LifecycleNormalizer(this)
61
+ }
62
+
59
63
  makeForTool (): ToolNormalizer {
60
64
  return new ToolNormalizer(this)
61
65
  }
@@ -201,6 +205,9 @@ export class MetadataNormalizer extends BaseJsonNormalizer<Models.Metadata> {
201
205
  const orgEntityNormalizer = this._factory.makeForOrganizationalEntity()
202
206
  return {
203
207
  timestamp: data.timestamp?.toISOString(),
208
+ lifecycles: this._factory.spec.supportsMetadataLifecycles && data.lifecycles.size > 0
209
+ ? this._factory.makeForLifecycle().normalizeIterable(data.lifecycles, options)
210
+ : undefined,
204
211
  tools: data.tools.size > 0
205
212
  ? this._factory.makeForTool().normalizeIterable(data.tools, options)
206
213
  : undefined,
@@ -220,6 +227,22 @@ export class MetadataNormalizer extends BaseJsonNormalizer<Models.Metadata> {
220
227
  }
221
228
  }
222
229
 
230
+ export class LifecycleNormalizer extends BaseJsonNormalizer<Models.Lifecycle> {
231
+ normalize (data: Models.Lifecycle, options: NormalizerOptions): Normalized.Lifecycle {
232
+ return data instanceof Models.NamedLifecycle
233
+ ? { name: data.name, description: data.description }
234
+ : { phase: data }
235
+ }
236
+
237
+ normalizeIterable (data: SortableIterable<Models.Lifecycle>, options: NormalizerOptions): Normalized.Lifecycle[] {
238
+ return (
239
+ options.sortLists ?? false
240
+ ? data.sorted()
241
+ : Array.from(data)
242
+ ).map(lc => this.normalize(lc, options))
243
+ }
244
+ }
245
+
223
246
  export class ToolNormalizer extends BaseJsonNormalizer<Models.Tool> {
224
247
  normalize (data: Models.Tool, options: NormalizerOptions): Normalized.Tool {
225
248
  return {
@@ -87,6 +87,7 @@ export namespace Normalized {
87
87
 
88
88
  export interface Metadata {
89
89
  timestamp?: JsonSchema.DateTime
90
+ lifecycles?: Lifecycle[]
90
91
  tools?: Tool[]
91
92
  authors?: OrganizationalContact[]
92
93
  component?: Component
@@ -95,6 +96,17 @@ export namespace Normalized {
95
96
  licenses?: License[]
96
97
  }
97
98
 
99
+ export interface LifecyclePhase {
100
+ phase: Enums.LifecyclePhase
101
+ }
102
+
103
+ export interface NamedLifecycle {
104
+ name: string
105
+ description?: string
106
+ }
107
+
108
+ export type Lifecycle = LifecyclePhase | NamedLifecycle
109
+
98
110
  export interface Tool {
99
111
  vendor?: string
100
112
  name?: string
@@ -48,6 +48,10 @@ export class Factory {
48
48
  return new MetadataNormalizer(this)
49
49
  }
50
50
 
51
+ makeForLifecycle (): LifecycleNormalizer {
52
+ return new LifecycleNormalizer(this)
53
+ }
54
+
51
55
  makeForComponent (): ComponentNormalizer {
52
56
  return new ComponentNormalizer(this)
53
57
  }
@@ -220,6 +224,13 @@ export class BomNormalizer extends BaseXmlNormalizer<Models.Bom> {
220
224
  export class MetadataNormalizer extends BaseXmlNormalizer<Models.Metadata> {
221
225
  normalize (data: Models.Metadata, options: NormalizerOptions, elementName: string): SimpleXml.Element {
222
226
  const orgEntityNormalizer = this._factory.makeForOrganizationalEntity()
227
+ const lifecycles: SimpleXml.Element | undefined = this._factory.spec.supportsMetadataLifecycles && data.lifecycles.size > 0
228
+ ? {
229
+ type: 'element',
230
+ name: 'lifecycles',
231
+ children: this._factory.makeForLifecycle().normalizeIterable(data.lifecycles, options, 'lifecycle')
232
+ }
233
+ : undefined
223
234
  const tools: SimpleXml.Element | undefined = data.tools.size > 0
224
235
  ? {
225
236
  type: 'element',
@@ -239,6 +250,7 @@ export class MetadataNormalizer extends BaseXmlNormalizer<Models.Metadata> {
239
250
  name: elementName,
240
251
  children: [
241
252
  makeOptionalDateTimeElement(data.timestamp, 'timestamp'),
253
+ lifecycles,
242
254
  tools,
243
255
  authors,
244
256
  data.component === undefined
@@ -255,6 +267,35 @@ export class MetadataNormalizer extends BaseXmlNormalizer<Models.Metadata> {
255
267
  }
256
268
  }
257
269
 
270
+ export class LifecycleNormalizer extends BaseXmlNormalizer<Models.Lifecycle> {
271
+ normalize (data: Models.Lifecycle, options: NormalizerOptions, elementName: string): SimpleXml.Element {
272
+ return data instanceof Models.NamedLifecycle
273
+ ? {
274
+ type: 'element',
275
+ name: elementName,
276
+ children: [
277
+ makeTextElement(data.name, 'name'),
278
+ makeOptionalTextElement(data.description, 'description')
279
+ ].filter(isNotUndefined)
280
+ }
281
+ : {
282
+ type: 'element',
283
+ name: elementName,
284
+ children: [
285
+ makeTextElement(data, 'phase')
286
+ ]
287
+ }
288
+ }
289
+
290
+ normalizeIterable (data: SortableIterable<Models.Lifecycle>, options: NormalizerOptions, elementName: string): SimpleXml.Element[] {
291
+ return (
292
+ options.sortLists ?? false
293
+ ? data.sorted()
294
+ : Array.from(data)
295
+ ).map(t => this.normalize(t, options, elementName))
296
+ }
297
+ }
298
+
258
299
  export class ToolNormalizer extends BaseXmlNormalizer<Models.Tool> {
259
300
  normalize (data: Models.Tool, options: NormalizerOptions, elementName: string): SimpleXml.Element {
260
301
  const hashes: SimpleXml.Element | undefined = data.hashes.size > 0
package/src/spec.ts CHANGED
@@ -51,6 +51,7 @@ export interface Protocol {
51
51
  supportsVulnerabilities: boolean
52
52
  supportsVulnerabilityRatingMethod: (rm: Vulnerability.RatingMethod | any) => boolean
53
53
  supportsComponentEvidence: boolean
54
+ supportsMetadataLifecycles: boolean
54
55
  }
55
56
 
56
57
  /**
@@ -71,6 +72,7 @@ class Spec implements Protocol {
71
72
  readonly #supportsProperties: boolean
72
73
  readonly #supportsVulnerabilities: boolean
73
74
  readonly #supportsComponentEvidence: boolean
75
+ readonly #supportsMetadataLifecycles: boolean
74
76
 
75
77
  constructor (
76
78
  version: Version,
@@ -85,7 +87,8 @@ class Spec implements Protocol {
85
87
  supportsProperties: boolean,
86
88
  supportsVulnerabilities: boolean,
87
89
  vulnerabilityRatingMethods: Iterable<Vulnerability.RatingMethod>,
88
- supportsComponentEvidence: boolean
90
+ supportsComponentEvidence: boolean,
91
+ supportsMetadataLifecycles: boolean
89
92
  ) {
90
93
  this.#version = version
91
94
  this.#formats = new Set(formats)
@@ -100,6 +103,7 @@ class Spec implements Protocol {
100
103
  this.#supportsVulnerabilities = supportsVulnerabilities
101
104
  this.#vulnerabilityRatingMethods = new Set(vulnerabilityRatingMethods)
102
105
  this.#supportsComponentEvidence = supportsComponentEvidence
106
+ this.#supportsMetadataLifecycles = supportsMetadataLifecycles
103
107
  }
104
108
 
105
109
  get version (): Version {
@@ -155,6 +159,10 @@ class Spec implements Protocol {
155
159
  get supportsComponentEvidence (): boolean {
156
160
  return this.#supportsComponentEvidence
157
161
  }
162
+
163
+ get supportsMetadataLifecycles (): boolean {
164
+ return this.#supportsMetadataLifecycles
165
+ }
158
166
  }
159
167
 
160
168
  /** Specification v1.2 */
@@ -212,6 +220,7 @@ export const Spec1dot2: Readonly<Protocol> = Object.freeze(new Spec(
212
220
  false,
213
221
  false,
214
222
  [],
223
+ false,
215
224
  false
216
225
  ))
217
226
 
@@ -270,7 +279,8 @@ export const Spec1dot3: Readonly<Protocol> = Object.freeze(new Spec(
270
279
  true,
271
280
  false,
272
281
  [],
273
- true
282
+ true,
283
+ false
274
284
  ))
275
285
 
276
286
  /** Specification v1.4 */
@@ -335,7 +345,8 @@ export const Spec1dot4: Readonly<Protocol> = Object.freeze(new Spec(
335
345
  Vulnerability.RatingMethod.OWASP,
336
346
  Vulnerability.RatingMethod.Other
337
347
  ],
338
- true
348
+ true,
349
+ false
339
350
  ))
340
351
 
341
352
  /** Specification v1.5 */
@@ -429,6 +440,7 @@ export const Spec1dot5: Readonly<Protocol> = Object.freeze(new Spec(
429
440
  Vulnerability.RatingMethod.SSVC,
430
441
  Vulnerability.RatingMethod.Other
431
442
  ],
443
+ true,
432
444
  true
433
445
  ))
434
446
 
package/webpack.config.js CHANGED
@@ -19,6 +19,7 @@ Copyright (c) OWASP Foundation. All Rights Reserved.
19
19
 
20
20
  const path = require('path')
21
21
  const deepmerge = require('deepmerge')
22
+ const nodeExternals = require('webpack-node-externals')
22
23
 
23
24
  /* eslint-disable jsdoc/valid-types */
24
25
 
@@ -55,13 +56,8 @@ const configBase = {
55
56
  type: 'umd'
56
57
  }
57
58
  },
58
- externals: {
59
- ajv: 'ajv',
60
- 'ajv-formats': 'ajv-formats',
61
- 'ajv-formats-draft2019': 'ajv-formats-draft2019',
62
- 'packageurl-js': 'packageurl-js',
63
- 'spdx-expression-parse': 'spdx-expression-parse'
64
- }
59
+ externalsPresets: { node: true },
60
+ externals: [nodeExternals()]
65
61
  }
66
62
 
67
63
  module.exports = [