Skip to content

Commit 2e33d30

Browse files
feat: Metadata.licenses & Metadata.properties (#1020)
--------- Signed-off-by: Augustus Kling <[email protected]> Signed-off-by: Jan Kowalleck <[email protected]> Co-authored-by: Jan Kowalleck <[email protected]>
1 parent dcc53c6 commit 2e33d30

22 files changed

+415
-21
lines changed

CONTRIBUTING.md

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ Run the tests:
3434
npm test
3535
```
3636

37+
See the [dedicated test docs](tests/README.md) for details and advanced instructions.
38+
3739
## Coding standards
3840

3941
Apply coding standards via:

HISTORY.md

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
44

55
## unreleased
66

7+
* Added
8+
* Class `Models.Metadata` got a new property `licenses` ([#1019] via [#1020])
9+
* Class `Models.Metadata` got a new property `properties` ([#1019] via [#1020])
10+
11+
[#1019]: https://github.com/CycloneDX/cyclonedx-javascript-library/issues/1019
12+
[#1020]: https://github.com/CycloneDX/cyclonedx-javascript-library/pull/1020
13+
714
## 6.3.2 -- 2024-02-25
815

916
* Refactor

src/models/metadata.ts

+8
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ Copyright (c) OWASP Foundation. All Rights Reserved.
1818
*/
1919

2020
import type { Component } from './component'
21+
import { LicenseRepository } from './license'
2122
import { LifecycleRepository } from './lifecycle'
2223
import { OrganizationalContactRepository } from './organizationalContact'
2324
import type { OrganizationalEntity } from './organizationalEntity'
25+
import { PropertyRepository } from './property'
2426
import { ToolRepository } from './tool'
2527

2628
export interface OptionalMetadataProperties {
@@ -31,6 +33,8 @@ export interface OptionalMetadataProperties {
3133
component?: Metadata['component']
3234
manufacture?: Metadata['manufacture']
3335
supplier?: Metadata['supplier']
36+
licenses?: Metadata['licenses']
37+
properties?: Metadata['properties']
3438
}
3539

3640
export class Metadata {
@@ -41,6 +45,8 @@ export class Metadata {
4145
component?: Component
4246
manufacture?: OrganizationalEntity
4347
supplier?: OrganizationalEntity
48+
licenses: LicenseRepository
49+
properties: PropertyRepository
4450

4551
constructor (op: OptionalMetadataProperties = {}) {
4652
this.timestamp = op.timestamp
@@ -50,5 +56,7 @@ export class Metadata {
5056
this.component = op.component
5157
this.manufacture = op.manufacture
5258
this.supplier = op.supplier
59+
this.licenses = op.licenses ?? new LicenseRepository()
60+
this.properties = op.properties ?? new PropertyRepository()
5361
}
5462
}

src/serialize/json/normalize.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,13 @@ export class MetadataNormalizer extends BaseJsonNormalizer<Models.Metadata> {
223223
: orgEntityNormalizer.normalize(data.manufacture, options),
224224
supplier: data.supplier === undefined
225225
? undefined
226-
: orgEntityNormalizer.normalize(data.supplier, options)
226+
: orgEntityNormalizer.normalize(data.supplier, options),
227+
licenses: this._factory.spec.supportsMetadataLicenses && data.licenses.size > 0
228+
? this._factory.makeForLicense().normalizeIterable(data.licenses, options)
229+
: undefined,
230+
properties: this._factory.spec.supportsMetadataProperties && data.properties.size > 0
231+
? this._factory.makeForProperty().normalizeIterable(data.properties, options)
232+
: undefined
227233
}
228234
}
229235
}

src/serialize/json/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export namespace Normalized {
9494
manufacture?: OrganizationalEntity
9595
supplier?: OrganizationalEntity
9696
licenses?: License[]
97+
properties?: Property[]
9798
}
9899

99100
export interface LifecyclePhase {

src/serialize/xml/normalize.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,20 @@ export class MetadataNormalizer extends BaseXmlNormalizer<Models.Metadata> {
246246
children: this._factory.makeForOrganizationalContact().normalizeIterable(data.authors, options, 'author')
247247
}
248248
: undefined
249+
const licenses: SimpleXml.Element | undefined = this._factory.spec.supportsMetadataLicenses && data.licenses.size > 0
250+
? {
251+
type: 'element',
252+
name: 'licenses',
253+
children: this._factory.makeForLicense().normalizeIterable(data.licenses, options)
254+
}
255+
: undefined
256+
const properties: SimpleXml.Element | undefined = this._factory.spec.supportsMetadataProperties && data.properties.size > 0
257+
? {
258+
type: 'element',
259+
name: 'properties',
260+
children: this._factory.makeForProperty().normalizeIterable(data.properties, options, 'property')
261+
}
262+
: undefined
249263
return {
250264
type: 'element',
251265
name: elementName,
@@ -262,7 +276,9 @@ export class MetadataNormalizer extends BaseXmlNormalizer<Models.Metadata> {
262276
: orgEntityNormalizer.normalize(data.manufacture, options, 'manufacture'),
263277
data.supplier === undefined
264278
? undefined
265-
: orgEntityNormalizer.normalize(data.supplier, options, 'supplier')
279+
: orgEntityNormalizer.normalize(data.supplier, options, 'supplier'),
280+
licenses,
281+
properties
266282
].filter(isNotUndefined)
267283
}
268284
}

src/spec/_protocol.ts

+16
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ export interface _SpecProtocol {
4343
supportsVulnerabilityRatingMethod: (rm: Vulnerability.RatingMethod | any) => boolean
4444
supportsComponentEvidence: boolean
4545
supportsMetadataLifecycles: boolean
46+
supportsMetadataLicenses: boolean
47+
supportsMetadataProperties: boolean
4648
supportsExternalReferenceHashes: boolean
4749
}
4850

@@ -68,6 +70,8 @@ export class _Spec implements _SpecProtocol {
6870
readonly #supportsVulnerabilities: boolean
6971
readonly #supportsComponentEvidence: boolean
7072
readonly #supportsMetadataLifecycles: boolean
73+
readonly #supportsMetadataLicenses: boolean
74+
readonly #supportsMetadataProperties: boolean
7175
readonly #supportsExternalReferenceHashes: boolean
7276

7377
constructor (
@@ -85,6 +89,8 @@ export class _Spec implements _SpecProtocol {
8589
vulnerabilityRatingMethods: Iterable<Vulnerability.RatingMethod>,
8690
supportsComponentEvidence: boolean,
8791
supportsMetadataLifecycles: boolean,
92+
supportsMetadataLicenses: boolean,
93+
supportsMetadataProperties: boolean,
8894
supportsExternalReferenceHashes: boolean
8995
) {
9096
this.#version = version
@@ -101,6 +107,8 @@ export class _Spec implements _SpecProtocol {
101107
this.#vulnerabilityRatingMethods = new Set(vulnerabilityRatingMethods)
102108
this.#supportsComponentEvidence = supportsComponentEvidence
103109
this.#supportsMetadataLifecycles = supportsMetadataLifecycles
110+
this.#supportsMetadataLicenses = supportsMetadataLicenses
111+
this.#supportsMetadataProperties = supportsMetadataProperties
104112
this.#supportsExternalReferenceHashes = supportsExternalReferenceHashes
105113
}
106114

@@ -167,6 +175,14 @@ export class _Spec implements _SpecProtocol {
167175
return this.#supportsMetadataLifecycles
168176
}
169177

178+
get supportsMetadataLicenses (): boolean {
179+
return this.#supportsMetadataLicenses
180+
}
181+
182+
get supportsMetadataProperties (): boolean {
183+
return this.#supportsMetadataProperties
184+
}
185+
170186
get supportsExternalReferenceHashes (): boolean {
171187
return this.#supportsExternalReferenceHashes
172188
}

src/spec/consts.ts

+8
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ export const Spec1dot2: Readonly<_SpecProtocol> = Object.freeze(new _Spec(
7979
[],
8080
false,
8181
false,
82+
false,
83+
false,
8284
false
8385
))
8486

@@ -139,6 +141,8 @@ export const Spec1dot3: Readonly<_SpecProtocol> = Object.freeze(new _Spec(
139141
[],
140142
true,
141143
false,
144+
true,
145+
true,
142146
true
143147
))
144148

@@ -206,6 +210,8 @@ export const Spec1dot4: Readonly<_SpecProtocol> = Object.freeze(new _Spec(
206210
],
207211
true,
208212
false,
213+
true,
214+
true,
209215
true
210216
))
211217

@@ -302,6 +308,8 @@ export const Spec1dot5: Readonly<_SpecProtocol> = Object.freeze(new _Spec(
302308
],
303309
true,
304310
true,
311+
true,
312+
true,
305313
true
306314
))
307315

tests/README.md

+16-12
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,31 @@
11
# Tests
22

3-
Tests are written in plain JavaScript, and
4-
they are intended to test the build result(`dist.node/` & `dist.web/`),
5-
instead of the source(`src/`).
3+
Tests are written in plain JavaScript.
4+
Tests are intended to test the build result(`dist.node/` & `dist.web/`), instead of the source(`src/`).
65

7-
## Writing tests
8-
9-
Test files must follow the pattern `**.{spec,test}.[cm]?js`,
10-
to be picked up.
6+
The test runner will NOT build the project; you need to do so manually on demand.
7+
See the [dedicated contributing docs](../CONTRIBUTING.md) for details and advanced instructions.
118

12-
## Snapshots
9+
## Writing tests
1310

14-
Some tests check against snapshots.
15-
To update these, set the env var `CJL_TEST_UPDATE_SNAPSHOTS` to a non-falsy value.
11+
Test files must follow the pattern `**.{spec,test}.[cm]?js`, to be picked up.
1612

1713
## Run node tests
1814

19-
Test runner is `mocha`,
20-
configured in [mocharc file](../.mocharc.js).
15+
Test runner is `mocha`, configured in [mocharc file](../.mocharc.js).
2116

2217
```shell
2318
npm test
2419
```
20+
### Snapshots
21+
22+
Some tests check against snapshots.
23+
To update these, set the env var `CJL_TEST_UPDATE_SNAPSHOTS` to a non-falsy value.
24+
25+
like so:
26+
```shell
27+
CJL_TEST_UPDATE_SNAPSHOTS=1 npm test
28+
```
2529

2630
## Run browser tests
2731

tests/_data/models.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,15 @@ module.exports.createComplexStructure = function () {
8787
name: 'Jane "the-other-supplier" Doe'
8888
})
8989
])
90-
})
90+
}),
91+
licenses: new Models.LicenseRepository([
92+
new Models.SpdxLicense('0BSD'),
93+
new Models.NamedLicense('Some license name')
94+
]),
95+
properties: new Models.PropertyRepository([
96+
new Models.Property('a', 'b'),
97+
new Models.Property('cdx:reproducible', 'true')
98+
])
9199
})
92100
})
93101

tests/_data/normalizeResults/json_sortedLists_spec1.3.json

+23-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/_data/normalizeResults/json_sortedLists_spec1.4.json

+23-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/_data/normalizeResults/json_sortedLists_spec1.5.json

+23-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)