@cyclonedx/cyclonedx-library 1.0.0-beta.1
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/LICENSE +201 -0
- package/NOTICE +5 -0
- package/README.md +152 -0
- package/dist.node/_index.node.js +53 -0
- package/dist.node/_index.node.js.map +1 -0
- package/dist.node/enums/attachmentEncoding.js +26 -0
- package/dist.node/enums/attachmentEncoding.js.map +1 -0
- package/dist.node/enums/componentScope.js +28 -0
- package/dist.node/enums/componentScope.js.map +1 -0
- package/dist.node/enums/componentType.js +33 -0
- package/dist.node/enums/componentType.js.map +1 -0
- package/dist.node/enums/externalReferenceType.js +41 -0
- package/dist.node/enums/externalReferenceType.js.map +1 -0
- package/dist.node/enums/hashAlogorithm.js +37 -0
- package/dist.node/enums/hashAlogorithm.js.map +1 -0
- package/dist.node/enums/index.js +40 -0
- package/dist.node/enums/index.js.map +1 -0
- package/dist.node/factories/index.js +36 -0
- package/dist.node/factories/index.js.map +1 -0
- package/dist.node/factories/licenseFactory.js +56 -0
- package/dist.node/factories/licenseFactory.js.map +1 -0
- package/dist.node/helpers/types.js +26 -0
- package/dist.node/helpers/types.js.map +1 -0
- package/dist.node/models/attachment.js +30 -0
- package/dist.node/models/attachment.js.map +1 -0
- package/dist.node/models/bom.js +67 -0
- package/dist.node/models/bom.js.map +1 -0
- package/dist.node/models/bomRef.js +37 -0
- package/dist.node/models/bomRef.js.map +1 -0
- package/dist.node/models/component.js +96 -0
- package/dist.node/models/component.js.map +1 -0
- package/dist.node/models/externalReference.js +40 -0
- package/dist.node/models/externalReference.js.map +1 -0
- package/dist.node/models/hash.js +29 -0
- package/dist.node/models/hash.js.map +1 -0
- package/dist.node/models/index.js +47 -0
- package/dist.node/models/index.js.map +1 -0
- package/dist.node/models/license.js +103 -0
- package/dist.node/models/license.js.map +1 -0
- package/dist.node/models/metadata.js +35 -0
- package/dist.node/models/metadata.js.map +1 -0
- package/dist.node/models/organizationalContact.js +41 -0
- package/dist.node/models/organizationalContact.js.map +1 -0
- package/dist.node/models/organizationalEntity.js +31 -0
- package/dist.node/models/organizationalEntity.js.map +1 -0
- package/dist.node/models/swid.js +58 -0
- package/dist.node/models/swid.js.map +1 -0
- package/dist.node/models/tool.js +45 -0
- package/dist.node/models/tool.js.map +1 -0
- package/dist.node/resources.node.js +55 -0
- package/dist.node/resources.node.js.map +1 -0
- package/dist.node/serialize/_index.node.js +37 -0
- package/dist.node/serialize/_index.node.js.map +1 -0
- package/dist.node/serialize/baseSerializer.js +56 -0
- package/dist.node/serialize/baseSerializer.js.map +1 -0
- package/dist.node/serialize/bomRefDiscriminator.js +66 -0
- package/dist.node/serialize/bomRefDiscriminator.js.map +1 -0
- package/dist.node/serialize/index.js +55 -0
- package/dist.node/serialize/index.js.map +1 -0
- package/dist.node/serialize/json/index.js +47 -0
- package/dist.node/serialize/json/index.js.map +1 -0
- package/dist.node/serialize/json/normalize.js +431 -0
- package/dist.node/serialize/json/normalize.js.map +1 -0
- package/dist.node/serialize/json/types.js +35 -0
- package/dist.node/serialize/json/types.js.map +1 -0
- package/dist.node/serialize/jsonSerializer.js +55 -0
- package/dist.node/serialize/jsonSerializer.js.map +1 -0
- package/dist.node/serialize/types.js +21 -0
- package/dist.node/serialize/types.js.map +1 -0
- package/dist.node/serialize/xml/index.js +47 -0
- package/dist.node/serialize/xml/index.js.map +1 -0
- package/dist.node/serialize/xml/normalize.js +560 -0
- package/dist.node/serialize/xml/normalize.js.map +1 -0
- package/dist.node/serialize/xml/types.js +31 -0
- package/dist.node/serialize/xml/types.js.map +1 -0
- package/dist.node/serialize/xmlBaseSerializer.js +52 -0
- package/dist.node/serialize/xmlBaseSerializer.js.map +1 -0
- package/dist.node/serialize/xmlSerializer.node.js +30 -0
- package/dist.node/serialize/xmlSerializer.node.js.map +1 -0
- package/dist.node/spdx.js +35 -0
- package/dist.node/spdx.js.map +1 -0
- package/dist.node/spec.js +229 -0
- package/dist.node/spec.js.map +1 -0
- package/dist.node/types/cpe.js +28 -0
- package/dist.node/types/cpe.js.map +1 -0
- package/dist.node/types/index.js +39 -0
- package/dist.node/types/index.js.map +1 -0
- package/dist.node/types/integer.js +36 -0
- package/dist.node/types/integer.js.map +1 -0
- package/dist.node/types/mimeType.js +28 -0
- package/dist.node/types/mimeType.js.map +1 -0
- package/dist.node/types/urn.js +28 -0
- package/dist.node/types/urn.js.map +1 -0
- package/dist.web/lib.dev.js +3487 -0
- package/dist.web/lib.dev.js.map +1 -0
- package/dist.web/lib.js +2 -0
- package/dist.web/lib.js.LICENSE.txt +18 -0
- package/libs/universal-node-xml/index.d.ts +33 -0
- package/libs/universal-node-xml/index.js +42 -0
- package/libs/universal-node-xml/stringifiers/helpers.js +17 -0
- package/libs/universal-node-xml/stringifiers/xmlbuilder2.js +51 -0
- package/package.json +86 -0
- package/res/README.md +27 -0
- package/res/bom-1.0.SNAPSHOT.xsd +247 -0
- package/res/bom-1.1.SNAPSHOT.xsd +731 -0
- package/res/bom-1.2-strict.SNAPSHOT.schema.json +1026 -0
- package/res/bom-1.2.SNAPSHOT.schema.json +997 -0
- package/res/bom-1.2.SNAPSHOT.xsd +1418 -0
- package/res/bom-1.3-strict.SNAPSHOT.schema.json +1085 -0
- package/res/bom-1.3.SNAPSHOT.schema.json +1054 -0
- package/res/bom-1.3.SNAPSHOT.xsd +1631 -0
- package/res/bom-1.4.SNAPSHOT.schema.json +1697 -0
- package/res/bom-1.4.SNAPSHOT.xsd +2407 -0
- package/res/jsf-0.82.SNAPSHOT.schema.json +244 -0
- package/res/spdx.SNAPSHOT.schema.json +533 -0
- package/res/spdx.SNAPSHOT.xsd +2639 -0
- package/src/_index.node.ts +31 -0
- package/src/_index.web.ts +27 -0
- package/src/enums/attachmentEncoding.ts +22 -0
- package/src/enums/componentScope.ts +24 -0
- package/src/enums/componentType.ts +29 -0
- package/src/enums/externalReferenceType.ts +37 -0
- package/src/enums/hashAlogorithm.ts +33 -0
- package/src/enums/index.ts +24 -0
- package/src/factories/index.ts +20 -0
- package/src/factories/licenseFactory.ts +62 -0
- package/src/helpers/README.md +3 -0
- package/src/helpers/types.ts +28 -0
- package/src/models/attachment.ts +37 -0
- package/src/models/bom.ts +85 -0
- package/src/models/bomRef.ts +41 -0
- package/src/models/component.ts +136 -0
- package/src/models/externalReference.ts +48 -0
- package/src/models/hash.ts +38 -0
- package/src/models/index.ts +31 -0
- package/src/models/license.ts +133 -0
- package/src/models/metadata.ts +50 -0
- package/src/models/organizationalContact.ts +49 -0
- package/src/models/organizationalEntity.ts +38 -0
- package/src/models/swid.ts +71 -0
- package/src/models/tool.ts +58 -0
- package/src/resources.node.ts +59 -0
- package/src/serialize/_index.node.ts +23 -0
- package/src/serialize/_index.web.ts +23 -0
- package/src/serialize/baseSerializer.ts +52 -0
- package/src/serialize/bomRefDiscriminator.ts +69 -0
- package/src/serialize/index.ts +35 -0
- package/src/serialize/json/index.ts +23 -0
- package/src/serialize/json/normalize.ts +450 -0
- package/src/serialize/json/types.ts +187 -0
- package/src/serialize/jsonSerializer.ts +59 -0
- package/src/serialize/types.ts +38 -0
- package/src/serialize/xml/index.ts +23 -0
- package/src/serialize/xml/normalize.ts +590 -0
- package/src/serialize/xml/types.ts +112 -0
- package/src/serialize/xmlBaseSerializer.ts +52 -0
- package/src/serialize/xmlSerializer.node.ts +35 -0
- package/src/serialize/xmlSerializer.web.ts +89 -0
- package/src/spdx.ts +48 -0
- package/src/spec.ts +289 -0
- package/src/types/cpe.ts +33 -0
- package/src/types/index.ts +23 -0
- package/src/types/integer.ts +50 -0
- package/src/types/mimeType.ts +31 -0
- package/src/types/urn.ts +33 -0
- package/tsconfig.json +108 -0
- package/tsconfig.node.json +8 -0
- package/tsconfig.web.json +5 -0
- package/webpack.config.js +74 -0
|
@@ -0,0 +1,69 @@
|
|
|
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 { BomRef } from '../models'
|
|
21
|
+
|
|
22
|
+
export class BomRefDiscriminator {
|
|
23
|
+
readonly #originalValues: ReadonlyMap<BomRef, string | undefined>
|
|
24
|
+
|
|
25
|
+
readonly #prefix: string
|
|
26
|
+
|
|
27
|
+
constructor (bomRefs: Iterable<BomRef>, prefix: string = 'BomRef') {
|
|
28
|
+
this.#originalValues = new Map(
|
|
29
|
+
Array.from(bomRefs).map(ref => [ref, ref.value])
|
|
30
|
+
)
|
|
31
|
+
this.#prefix = prefix
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
[Symbol.iterator] (): IterableIterator<BomRef> {
|
|
35
|
+
return this.#originalValues.keys()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
discriminate (): void {
|
|
39
|
+
const knownRefValues = new Set<string>()
|
|
40
|
+
for (const [bomRef] of this.#originalValues) {
|
|
41
|
+
let value = bomRef.value
|
|
42
|
+
if (value === undefined || knownRefValues.has(value)) {
|
|
43
|
+
value = this.#makeUniqueId()
|
|
44
|
+
bomRef.value = value
|
|
45
|
+
}
|
|
46
|
+
knownRefValues.add(value)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
reset (): void {
|
|
51
|
+
for (const [bomRef, originalValue] of this.#originalValues) {
|
|
52
|
+
bomRef.value = originalValue
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* generate a string in the format:
|
|
58
|
+
* <prefix>.<some-characters>.<some-characters>
|
|
59
|
+
*/
|
|
60
|
+
#makeUniqueId (): string {
|
|
61
|
+
return `${
|
|
62
|
+
this.#prefix
|
|
63
|
+
}${
|
|
64
|
+
Math.random().toString(32).substring(1)
|
|
65
|
+
}${
|
|
66
|
+
Math.random().toString(32).substring(1)
|
|
67
|
+
}`
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
// not everything is public, yet
|
|
21
|
+
|
|
22
|
+
export * as Types from './types'
|
|
23
|
+
|
|
24
|
+
export * from './baseSerializer'
|
|
25
|
+
// export * from './baseDeserializer' // TODO
|
|
26
|
+
|
|
27
|
+
export * from './bomRefDiscriminator'
|
|
28
|
+
|
|
29
|
+
export * as JSON from './json'
|
|
30
|
+
export * from './jsonSerializer'
|
|
31
|
+
// export * from './jsonDeserializer' // TODO
|
|
32
|
+
|
|
33
|
+
export * as XML from './xml'
|
|
34
|
+
export * from './xmlBaseSerializer'
|
|
35
|
+
// export * from './xmlBaseDeserializer' // TODO
|
|
@@ -0,0 +1,23 @@
|
|
|
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 * as Types from './types'
|
|
21
|
+
|
|
22
|
+
export * as Normalize from './normalize'
|
|
23
|
+
// export * as Denormalize from './denormalize' // TODO
|
|
@@ -0,0 +1,450 @@
|
|
|
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 { isNotUndefined, Stringable } from '../../helpers/types'
|
|
21
|
+
import * as Models from '../../models'
|
|
22
|
+
import { Protocol as Spec, Version as SpecVersion } from '../../spec'
|
|
23
|
+
import { NormalizerOptions } from '../types'
|
|
24
|
+
import { JsonSchema, Normalized } from './types'
|
|
25
|
+
|
|
26
|
+
export class Factory {
|
|
27
|
+
readonly #spec: Spec
|
|
28
|
+
|
|
29
|
+
constructor (spec: Spec) {
|
|
30
|
+
this.#spec = spec
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get spec (): Spec {
|
|
34
|
+
return this.#spec
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
makeForBom (): BomNormalizer {
|
|
38
|
+
return new BomNormalizer(this)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
makeForMetadata (): MetadataNormalizer {
|
|
42
|
+
return new MetadataNormalizer(this)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
makeForComponent (): ComponentNormalizer {
|
|
46
|
+
return new ComponentNormalizer(this)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
makeForTool (): ToolNormalizer {
|
|
50
|
+
return new ToolNormalizer(this)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
makeForOrganizationalContact (): OrganizationalContactNormalizer {
|
|
54
|
+
return new OrganizationalContactNormalizer(this)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
makeForOrganizationalEntity (): OrganizationalEntityNormalizer {
|
|
58
|
+
return new OrganizationalEntityNormalizer(this)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
makeForHash (): HashNormalizer {
|
|
62
|
+
return new HashNormalizer(this)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
makeForLicense (): LicenseNormalizer {
|
|
66
|
+
return new LicenseNormalizer(this)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
makeForSWID (): SWIDNormalizer {
|
|
70
|
+
return new SWIDNormalizer(this)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
makeForExternalReference (): ExternalReferenceNormalizer {
|
|
74
|
+
return new ExternalReferenceNormalizer(this)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
makeForAttachment (): AttachmentNormalizer {
|
|
78
|
+
return new AttachmentNormalizer(this)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
makeForDependencyGraph (): DependencyGraphNormalizer {
|
|
82
|
+
return new DependencyGraphNormalizer(this)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const schemaUrl: ReadonlyMap<SpecVersion, string> = new Map([
|
|
87
|
+
[SpecVersion.v1dot2, 'http://cyclonedx.org/schema/bom-1.2b.schema.json'],
|
|
88
|
+
[SpecVersion.v1dot3, 'http://cyclonedx.org/schema/bom-1.3a.schema.json'],
|
|
89
|
+
[SpecVersion.v1dot4, 'http://cyclonedx.org/schema/bom-1.4.schema.json']
|
|
90
|
+
])
|
|
91
|
+
|
|
92
|
+
interface Normalizer {
|
|
93
|
+
normalize: (data: object, options: NormalizerOptions) => object | undefined
|
|
94
|
+
|
|
95
|
+
normalizeIter?: (data: Iterable<object>, options: NormalizerOptions) => object[]
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
abstract class Base implements Normalizer {
|
|
99
|
+
protected readonly _factory: Factory
|
|
100
|
+
|
|
101
|
+
constructor (factory: Factory) {
|
|
102
|
+
this._factory = factory
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
abstract normalize (data: object, options: NormalizerOptions): object | undefined
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing, @typescript-eslint/strict-boolean-expressions --
|
|
109
|
+
* since empty strings need to be treated as undefined/null
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
export class BomNormalizer extends Base {
|
|
113
|
+
normalize (data: Models.Bom, options: NormalizerOptions): Normalized.Bom {
|
|
114
|
+
return {
|
|
115
|
+
$schema: schemaUrl.get(this._factory.spec.version),
|
|
116
|
+
bomFormat: 'CycloneDX',
|
|
117
|
+
specVersion: this._factory.spec.version,
|
|
118
|
+
version: data.version,
|
|
119
|
+
serialNumber: data.serialNumber,
|
|
120
|
+
metadata: this._factory.makeForMetadata().normalize(data.metadata, options),
|
|
121
|
+
components: data.components.size > 0
|
|
122
|
+
? this._factory.makeForComponent().normalizeIter(data.components, options)
|
|
123
|
+
// spec < 1.4 requires `component` to be array
|
|
124
|
+
: [],
|
|
125
|
+
dependencies: this._factory.spec.supportsDependencyGraph
|
|
126
|
+
? this._factory.makeForDependencyGraph().normalize(data, options)
|
|
127
|
+
: undefined
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export class MetadataNormalizer extends Base {
|
|
133
|
+
normalize (data: Models.Metadata, options: NormalizerOptions): Normalized.Metadata {
|
|
134
|
+
const orgEntityNormalizer = this._factory.makeForOrganizationalEntity()
|
|
135
|
+
return {
|
|
136
|
+
timestamp: data.timestamp?.toISOString(),
|
|
137
|
+
tools: data.tools.size > 0
|
|
138
|
+
? this._factory.makeForTool().normalizeIter(data.tools, options)
|
|
139
|
+
: undefined,
|
|
140
|
+
authors: data.authors.size > 0
|
|
141
|
+
? this._factory.makeForOrganizationalContact().normalizeIter(data.authors, options)
|
|
142
|
+
: undefined,
|
|
143
|
+
component: data.component === undefined
|
|
144
|
+
? undefined
|
|
145
|
+
: this._factory.makeForComponent().normalize(data.component, options),
|
|
146
|
+
manufacture: data.manufacture === undefined
|
|
147
|
+
? undefined
|
|
148
|
+
: orgEntityNormalizer.normalize(data.manufacture, options),
|
|
149
|
+
supplier: data.supplier === undefined
|
|
150
|
+
? undefined
|
|
151
|
+
: orgEntityNormalizer.normalize(data.supplier, options)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export class ToolNormalizer extends Base {
|
|
157
|
+
normalize (data: Models.Tool, options: NormalizerOptions): Normalized.Tool {
|
|
158
|
+
return {
|
|
159
|
+
vendor: data.vendor || undefined,
|
|
160
|
+
name: data.name || undefined,
|
|
161
|
+
version: data.version || undefined,
|
|
162
|
+
hashes: data.hashes.size > 0
|
|
163
|
+
? this._factory.makeForHash().normalizeIter(data.hashes, options)
|
|
164
|
+
: undefined,
|
|
165
|
+
externalReferences: this._factory.spec.supportsToolReferences && data.externalReferences.size > 0
|
|
166
|
+
? this._factory.makeForExternalReference().normalizeIter(data.externalReferences, options)
|
|
167
|
+
: undefined
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
normalizeIter (data: Iterable<Models.Tool>, options: NormalizerOptions): Normalized.Tool[] {
|
|
172
|
+
const tools = Array.from(data)
|
|
173
|
+
if (options.sortLists ?? false) {
|
|
174
|
+
tools.sort(Models.ToolRepository.compareItems)
|
|
175
|
+
}
|
|
176
|
+
return tools.map(t => this.normalize(t, options))
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export class HashNormalizer extends Base {
|
|
181
|
+
normalize ([algorithm, content]: Models.Hash, options: NormalizerOptions): Normalized.Hash | undefined {
|
|
182
|
+
const spec = this._factory.spec
|
|
183
|
+
return spec.supportsHashAlgorithm(algorithm) && spec.supportsHashValue(content)
|
|
184
|
+
? {
|
|
185
|
+
alg: algorithm,
|
|
186
|
+
content: content
|
|
187
|
+
}
|
|
188
|
+
: undefined
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
normalizeIter (data: Iterable<Models.Hash>, options: NormalizerOptions): Normalized.Hash[] {
|
|
192
|
+
const hashes = Array.from(data)
|
|
193
|
+
if (options.sortLists ?? false) {
|
|
194
|
+
hashes.sort(Models.HashRepository.compareItems)
|
|
195
|
+
}
|
|
196
|
+
return hashes.map(h => this.normalize(h, options))
|
|
197
|
+
.filter(isNotUndefined)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export class OrganizationalContactNormalizer extends Base {
|
|
202
|
+
normalize (data: Models.OrganizationalContact, options: NormalizerOptions): Normalized.OrganizationalContact {
|
|
203
|
+
return {
|
|
204
|
+
name: data.name || undefined,
|
|
205
|
+
email: JsonSchema.isIdnEmail(data.email)
|
|
206
|
+
? data.email
|
|
207
|
+
: undefined,
|
|
208
|
+
phone: data.phone || undefined
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
normalizeIter (data: Iterable<Models.OrganizationalContact>, options: NormalizerOptions): Normalized.OrganizationalContact[] {
|
|
213
|
+
const contacts = Array.from(data)
|
|
214
|
+
if (options.sortLists ?? false) {
|
|
215
|
+
contacts.sort(Models.OrganizationalContactRepository.compareItems)
|
|
216
|
+
}
|
|
217
|
+
return contacts.map(c => this.normalize(c, options))
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export class OrganizationalEntityNormalizer extends Base {
|
|
222
|
+
normalize (data: Models.OrganizationalEntity, options: NormalizerOptions): Normalized.OrganizationalEntity {
|
|
223
|
+
const urls = normalizeStringableIter(data.url, options)
|
|
224
|
+
.filter(JsonSchema.isIriReference)
|
|
225
|
+
return {
|
|
226
|
+
name: data.name || undefined,
|
|
227
|
+
/** must comply to {@link https://datatracker.ietf.org/doc/html/rfc3987} */
|
|
228
|
+
url: urls.length > 0
|
|
229
|
+
? urls
|
|
230
|
+
: undefined,
|
|
231
|
+
contact: data.contact.size > 0
|
|
232
|
+
? this._factory.makeForOrganizationalContact().normalizeIter(data.contact, options)
|
|
233
|
+
: undefined
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export class ComponentNormalizer extends Base {
|
|
239
|
+
normalize (data: Models.Component, options: NormalizerOptions): Normalized.Component | undefined {
|
|
240
|
+
return this._factory.spec.supportsComponentType(data.type)
|
|
241
|
+
? {
|
|
242
|
+
type: data.type,
|
|
243
|
+
name: data.name,
|
|
244
|
+
group: data.group || undefined,
|
|
245
|
+
// version fallback to string for spec < 1.4
|
|
246
|
+
version: data.version || '',
|
|
247
|
+
'bom-ref': data.bomRef.value || undefined,
|
|
248
|
+
supplier: data.supplier === undefined
|
|
249
|
+
? undefined
|
|
250
|
+
: this._factory.makeForOrganizationalEntity().normalize(data.supplier, options),
|
|
251
|
+
author: data.author || undefined,
|
|
252
|
+
publisher: data.publisher || undefined,
|
|
253
|
+
description: data.description || undefined,
|
|
254
|
+
scope: data.scope,
|
|
255
|
+
hashes: data.hashes.size > 0
|
|
256
|
+
? this._factory.makeForHash().normalizeIter(data.hashes, options)
|
|
257
|
+
: undefined,
|
|
258
|
+
licenses: data.licenses.size > 0
|
|
259
|
+
? this._factory.makeForLicense().normalizeIter(data.licenses, options)
|
|
260
|
+
: undefined,
|
|
261
|
+
copyright: data.copyright || undefined,
|
|
262
|
+
cpe: data.cpe || undefined,
|
|
263
|
+
purl: data.purl?.toString(),
|
|
264
|
+
swid: data.swid === undefined
|
|
265
|
+
? undefined
|
|
266
|
+
: this._factory.makeForSWID().normalize(data.swid, options),
|
|
267
|
+
externalReferences: data.externalReferences.size > 0
|
|
268
|
+
? this._factory.makeForExternalReference().normalizeIter(data.externalReferences, options)
|
|
269
|
+
: undefined
|
|
270
|
+
}
|
|
271
|
+
: undefined
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
normalizeIter (data: Iterable<Models.Component>, options: NormalizerOptions): Normalized.Component[] {
|
|
275
|
+
const components = Array.from(data)
|
|
276
|
+
if (options.sortLists ?? false) {
|
|
277
|
+
components.sort(Models.ComponentRepository.compareItems)
|
|
278
|
+
}
|
|
279
|
+
return components.map(c => this.normalize(c, options))
|
|
280
|
+
.filter(isNotUndefined)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export class LicenseNormalizer extends Base {
|
|
285
|
+
normalize (data: Models.License, options: NormalizerOptions): Normalized.License {
|
|
286
|
+
switch (true) {
|
|
287
|
+
case data instanceof Models.NamedLicense:
|
|
288
|
+
return this.#normalizeNamedLicense(data as Models.NamedLicense, options)
|
|
289
|
+
case data instanceof Models.SpdxLicense:
|
|
290
|
+
return this.#normalizeSpdxLicense(data as Models.SpdxLicense, options)
|
|
291
|
+
case data instanceof Models.LicenseExpression:
|
|
292
|
+
return this.#normalizeLicenseExpression(data as Models.LicenseExpression)
|
|
293
|
+
default:
|
|
294
|
+
// this case is not expected to happen - and therefore is undocumented
|
|
295
|
+
throw new TypeError('Unexpected LicenseChoice')
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
#normalizeNamedLicense (data: Models.NamedLicense, options: NormalizerOptions): Normalized.NamedLicense {
|
|
300
|
+
return {
|
|
301
|
+
license: {
|
|
302
|
+
name: data.name,
|
|
303
|
+
text: data.text === undefined
|
|
304
|
+
? undefined
|
|
305
|
+
: this._factory.makeForAttachment().normalize(data.text, options),
|
|
306
|
+
url: data.url?.toString()
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
#normalizeSpdxLicense (data: Models.SpdxLicense, options: NormalizerOptions): Normalized.SpdxLicense {
|
|
312
|
+
return {
|
|
313
|
+
license: {
|
|
314
|
+
id: data.id,
|
|
315
|
+
text: data.text === undefined
|
|
316
|
+
? undefined
|
|
317
|
+
: this._factory.makeForAttachment().normalize(data.text, options),
|
|
318
|
+
url: data.url?.toString()
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
#normalizeLicenseExpression (data: Models.LicenseExpression): Normalized.LicenseExpression {
|
|
324
|
+
return {
|
|
325
|
+
expression: data.expression
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
normalizeIter (data: Iterable<Models.License>, options: NormalizerOptions): Normalized.License[] {
|
|
330
|
+
const licenses = Array.from(data)
|
|
331
|
+
if (options.sortLists ?? false) {
|
|
332
|
+
licenses.sort(Models.LicenseRepository.compareItems)
|
|
333
|
+
}
|
|
334
|
+
return licenses.map(c => this.normalize(c, options))
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export class SWIDNormalizer extends Base {
|
|
339
|
+
normalize (data: Models.SWID, options: NormalizerOptions): Normalized.SWID {
|
|
340
|
+
const url = data.url?.toString()
|
|
341
|
+
return {
|
|
342
|
+
tagId: data.tagId,
|
|
343
|
+
name: data.name,
|
|
344
|
+
version: data.version || undefined,
|
|
345
|
+
tagVersion: data.tagVersion,
|
|
346
|
+
patch: data.patch,
|
|
347
|
+
text: data.text === undefined
|
|
348
|
+
? undefined
|
|
349
|
+
: this._factory.makeForAttachment().normalize(data.text, options),
|
|
350
|
+
url: JsonSchema.isIriReference(url)
|
|
351
|
+
? url
|
|
352
|
+
: undefined
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export class ExternalReferenceNormalizer extends Base {
|
|
358
|
+
normalize (data: Models.ExternalReference, options: NormalizerOptions): Normalized.ExternalReference | undefined {
|
|
359
|
+
return this._factory.spec.supportsExternalReferenceType(data.type)
|
|
360
|
+
? {
|
|
361
|
+
url: data.url.toString(),
|
|
362
|
+
type: data.type,
|
|
363
|
+
comment: data.comment || undefined
|
|
364
|
+
}
|
|
365
|
+
: undefined
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
normalizeIter (data: Iterable<Models.ExternalReference>, options: NormalizerOptions): Normalized.ExternalReference[] {
|
|
369
|
+
const refs = Array.from(data)
|
|
370
|
+
if (options.sortLists ?? false) {
|
|
371
|
+
refs.sort(Models.ExternalReferenceRepository.compareItems)
|
|
372
|
+
}
|
|
373
|
+
return refs.map(r => this.normalize(r, options))
|
|
374
|
+
.filter(isNotUndefined)
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export class AttachmentNormalizer extends Base {
|
|
379
|
+
normalize (data: Models.Attachment, options: NormalizerOptions): Normalized.Attachment {
|
|
380
|
+
return {
|
|
381
|
+
content: data.content,
|
|
382
|
+
contentType: data.contentType || undefined,
|
|
383
|
+
encoding: data.encoding
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export class DependencyGraphNormalizer extends Base {
|
|
389
|
+
normalize (data: Models.Bom, options: NormalizerOptions): Normalized.Dependency[] | undefined {
|
|
390
|
+
if (!data.metadata.component?.bomRef.value) {
|
|
391
|
+
// the graph is missing the entry point -> omit the graph
|
|
392
|
+
return undefined
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const allRefs = new Map<Models.BomRef, Models.BomRefRepository>()
|
|
396
|
+
for (const c of data.components) {
|
|
397
|
+
allRefs.set(c.bomRef, new Models.BomRefRepository(c.dependencies))
|
|
398
|
+
}
|
|
399
|
+
allRefs.set(data.metadata.component.bomRef, data.metadata.component.dependencies)
|
|
400
|
+
|
|
401
|
+
const normalized: Normalized.Dependency[] = []
|
|
402
|
+
for (const [ref, deps] of allRefs) {
|
|
403
|
+
const dep = this.#normalizeDependency(ref, deps, allRefs, options)
|
|
404
|
+
if (isNotUndefined(dep)) {
|
|
405
|
+
normalized.push(dep)
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if (options.sortLists ?? false) {
|
|
410
|
+
normalized.sort(({ ref: a }, { ref: b }) => a.localeCompare(b))
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return normalized
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
#normalizeDependency (
|
|
417
|
+
ref: Models.BomRef,
|
|
418
|
+
deps: Models.BomRefRepository,
|
|
419
|
+
allRefs: Map<Models.BomRef, Models.BomRefRepository>,
|
|
420
|
+
options: NormalizerOptions
|
|
421
|
+
): Normalized.Dependency | undefined {
|
|
422
|
+
const bomRef = ref.toString()
|
|
423
|
+
if (bomRef.length === 0) {
|
|
424
|
+
// no value -> cannot render
|
|
425
|
+
return undefined
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const dependsOn: string[] = normalizeStringableIter(
|
|
429
|
+
Array.from(deps).filter(d => allRefs.has(d) && d !== ref),
|
|
430
|
+
options
|
|
431
|
+
).filter(d => d.length > 0)
|
|
432
|
+
|
|
433
|
+
return {
|
|
434
|
+
ref: bomRef,
|
|
435
|
+
dependsOn: dependsOn.length > 0
|
|
436
|
+
? dependsOn
|
|
437
|
+
: undefined
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/* eslint-enable @typescript-eslint/prefer-nullish-coalescing, @typescript-eslint/strict-boolean-expressions */
|
|
443
|
+
|
|
444
|
+
function normalizeStringableIter (data: Iterable<Stringable>, options: NormalizerOptions): string[] {
|
|
445
|
+
const r: string[] = Array.from(data, d => d.toString())
|
|
446
|
+
if (options.sortLists ?? false) {
|
|
447
|
+
r.sort((a, b) => a.localeCompare(b))
|
|
448
|
+
}
|
|
449
|
+
return r
|
|
450
|
+
}
|