@trustify-da/trustify-da-javascript-client 0.3.0-ea.76e1fef → 0.3.0-ea.7ee4047
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 +199 -11
- package/dist/package.json +30 -26
- package/dist/src/analysis.d.ts +50 -22
- package/dist/src/analysis.js +70 -18
- package/dist/src/cli.js +188 -6
- package/dist/src/config.d.ts +120 -0
- package/dist/src/config.js +260 -0
- package/dist/src/cyclone_dx_sbom.d.ts +13 -0
- package/dist/src/cyclone_dx_sbom.js +50 -4
- package/dist/src/index.d.ts +27 -23
- package/dist/src/index.js +32 -41
- package/dist/src/license/index.d.ts +4 -4
- package/dist/src/license/index.js +13 -7
- package/dist/src/license/license_utils.js +4 -1
- package/dist/src/license/licenses_api.d.ts +3 -3
- package/dist/src/license/licenses_api.js +1 -1
- package/dist/src/oci_image/images.d.ts +1 -1
- package/dist/src/oci_image/images.js +15 -1
- package/dist/src/oci_image/utils.d.ts +5 -5
- package/dist/src/package_version.d.ts +8 -0
- package/dist/src/package_version.js +31 -0
- package/dist/src/provider.d.ts +4 -3
- package/dist/src/provider.js +6 -2
- package/dist/src/providers/base_java.d.ts +67 -3
- package/dist/src/providers/base_java.js +80 -23
- package/dist/src/providers/base_javascript.d.ts +74 -9
- package/dist/src/providers/base_javascript.js +116 -7
- package/dist/src/providers/base_pyproject.d.ts +10 -5
- package/dist/src/providers/base_pyproject.js +7 -0
- package/dist/src/providers/containerfile_parser.d.ts +5 -0
- package/dist/src/providers/containerfile_parser.js +20 -0
- package/dist/src/providers/golang_gomodules.d.ts +2 -1
- package/dist/src/providers/golang_gomodules.js +50 -8
- package/dist/src/providers/java_gradle.d.ts +48 -0
- package/dist/src/providers/java_gradle.js +206 -22
- package/dist/src/providers/java_gradle_groovy.d.ts +1 -1
- package/dist/src/providers/java_gradle_kotlin.d.ts +1 -1
- package/dist/src/providers/java_maven.d.ts +29 -9
- package/dist/src/providers/java_maven.js +176 -10
- package/dist/src/providers/javascript_bun.d.ts +22 -0
- package/dist/src/providers/javascript_bun.js +141 -0
- package/dist/src/providers/javascript_npm.d.ts +19 -1
- package/dist/src/providers/javascript_npm.js +40 -1
- package/dist/src/providers/javascript_pnpm.d.ts +13 -0
- package/dist/src/providers/javascript_pnpm.js +47 -1
- package/dist/src/providers/javascript_yarn.d.ts +12 -0
- package/dist/src/providers/javascript_yarn.js +75 -2
- package/dist/src/providers/manifest.js +6 -3
- package/dist/src/providers/oci_dockerfile.d.ts +51 -0
- package/dist/src/providers/oci_dockerfile.js +177 -0
- package/dist/src/providers/processors/yarn_berry_processor.d.ts +6 -2
- package/dist/src/providers/processors/yarn_berry_processor.js +3 -2
- package/dist/src/providers/processors/yarn_classic_processor.d.ts +6 -2
- package/dist/src/providers/processors/yarn_classic_processor.js +8 -6
- package/dist/src/providers/python_controller.js +61 -4
- package/dist/src/providers/python_pip.d.ts +1 -0
- package/dist/src/providers/python_pip.js +1 -1
- package/dist/src/providers/python_pip_pyproject.js +3 -1
- package/dist/src/providers/python_poetry.d.ts +31 -8
- package/dist/src/providers/python_poetry.js +62 -14
- package/dist/src/providers/python_uv.d.ts +5 -14
- package/dist/src/providers/python_uv.js +50 -2
- package/dist/src/providers/requirements_parser.js +1 -1
- package/dist/src/providers/rust_cargo.d.ts +6 -2
- package/dist/src/providers/rust_cargo.js +101 -33
- package/dist/src/providers/tree-sitter-containerfile.wasm +0 -0
- package/dist/src/remediate.d.ts +107 -0
- package/dist/src/remediate.js +244 -0
- package/dist/src/remediation.d.ts +81 -0
- package/dist/src/remediation.js +475 -0
- package/dist/src/remediation_report.d.ts +23 -0
- package/dist/src/remediation_report.js +180 -0
- package/dist/src/sbom.d.ts +11 -0
- package/dist/src/sbom.js +10 -0
- package/dist/src/tools.d.ts +11 -13
- package/dist/src/tools.js +34 -13
- package/dist/src/updaters/maven_updater.d.ts +58 -0
- package/dist/src/updaters/maven_updater.js +345 -0
- package/dist/src/updaters/toml_updater.d.ts +62 -0
- package/dist/src/updaters/toml_updater.js +276 -0
- package/dist/src/workspace.d.ts +2 -1
- package/dist/src/workspace.js +2 -1
- package/package.json +31 -27
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { load as yamlLoad } from 'js-yaml';
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {{
|
|
6
|
+
* 'group-by'?: 'dependency' | 'bundle',
|
|
7
|
+
* exclude?: string[],
|
|
8
|
+
* labels?: string[],
|
|
9
|
+
* 'branch-prefix'?: string,
|
|
10
|
+
* [key: string]: unknown
|
|
11
|
+
* }} RemediationConfig
|
|
12
|
+
*/
|
|
13
|
+
/** @typedef {{ critical?: number, high?: number, 'license-conflicts'?: number, [key: string]: unknown }} FailOnConfig */
|
|
14
|
+
/** @typedef {{ 'fail-on'?: FailOnConfig, [key: string]: unknown }} CheckConfig */
|
|
15
|
+
/** @typedef {{ format?: string, targets?: string[], [key: string]: unknown }} SbomConfig */
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {{
|
|
18
|
+
* 'backend-url'?: string,
|
|
19
|
+
* providers?: string[] | string,
|
|
20
|
+
* sources?: string[] | string,
|
|
21
|
+
* remediation?: RemediationConfig,
|
|
22
|
+
* check?: CheckConfig,
|
|
23
|
+
* sbom?: SbomConfig,
|
|
24
|
+
* [key: string]: unknown
|
|
25
|
+
* }} FileConfig
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {{
|
|
29
|
+
* backendUrl: string | null,
|
|
30
|
+
* backendUrlSource: 'cli' | 'environment' | 'file' | 'default',
|
|
31
|
+
* providers: string[],
|
|
32
|
+
* sources: string[],
|
|
33
|
+
* groupBy: string,
|
|
34
|
+
* remediation: object,
|
|
35
|
+
* check: object,
|
|
36
|
+
* sbom: object
|
|
37
|
+
* }} ResolvedConfig
|
|
38
|
+
*/
|
|
39
|
+
/** Config file names discovered by walking up the directory tree, in precedence order. */
|
|
40
|
+
export const CONFIG_FILENAMES = ['.trustify-da.yml', '.trustify-da.yaml'];
|
|
41
|
+
function isMapping(value) {
|
|
42
|
+
if (value == null || typeof value !== 'object' || Array.isArray(value)) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
const prototype = Object.getPrototypeOf(value);
|
|
46
|
+
return prototype === Object.prototype || prototype == null;
|
|
47
|
+
}
|
|
48
|
+
function assertMapping(value, field, source) {
|
|
49
|
+
if (!isMapping(value)) {
|
|
50
|
+
throw new Error(`Invalid config file ${source}: ${field} must be a mapping`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function assertString(value, field, source) {
|
|
54
|
+
if (typeof value !== 'string') {
|
|
55
|
+
throw new Error(`Invalid config file ${source}: ${field} must be a string`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function assertStringArray(value, field, source) {
|
|
59
|
+
if (!Array.isArray(value) || value.some(item => typeof item !== 'string')) {
|
|
60
|
+
throw new Error(`Invalid config file ${source}: ${field} must be an array of strings`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function assertStringOrArray(value, field, source) {
|
|
64
|
+
if (typeof value !== 'string') {
|
|
65
|
+
assertStringArray(value, field, source);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Validates all fields in the initial configuration schema. Unknown fields are preserved.
|
|
70
|
+
* @param {unknown} config
|
|
71
|
+
* @param {string} [source]
|
|
72
|
+
* @returns {FileConfig}
|
|
73
|
+
*/
|
|
74
|
+
function validateConfig(config, source = '<config>') {
|
|
75
|
+
assertMapping(config, 'root', source);
|
|
76
|
+
if (config['backend-url'] !== undefined) {
|
|
77
|
+
assertString(config['backend-url'], 'backend-url', source);
|
|
78
|
+
}
|
|
79
|
+
if (config.providers !== undefined) {
|
|
80
|
+
assertStringOrArray(config.providers, 'providers', source);
|
|
81
|
+
}
|
|
82
|
+
if (config.sources !== undefined) {
|
|
83
|
+
assertStringOrArray(config.sources, 'sources', source);
|
|
84
|
+
}
|
|
85
|
+
if (config.remediation !== undefined) {
|
|
86
|
+
assertMapping(config.remediation, 'remediation', source);
|
|
87
|
+
const remediation = config.remediation;
|
|
88
|
+
if (remediation['group-by'] !== undefined && !['dependency', 'bundle'].includes(remediation['group-by'])) {
|
|
89
|
+
throw new Error(`Invalid config file ${source}: remediation.group-by must be dependency or bundle`);
|
|
90
|
+
}
|
|
91
|
+
if (remediation.exclude !== undefined) {
|
|
92
|
+
assertStringArray(remediation.exclude, 'remediation.exclude', source);
|
|
93
|
+
}
|
|
94
|
+
if (remediation.labels !== undefined) {
|
|
95
|
+
assertStringArray(remediation.labels, 'remediation.labels', source);
|
|
96
|
+
}
|
|
97
|
+
if (remediation['branch-prefix'] !== undefined) {
|
|
98
|
+
assertString(remediation['branch-prefix'], 'remediation.branch-prefix', source);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (config.check !== undefined) {
|
|
102
|
+
assertMapping(config.check, 'check', source);
|
|
103
|
+
if (config.check['fail-on'] !== undefined) {
|
|
104
|
+
assertMapping(config.check['fail-on'], 'check.fail-on', source);
|
|
105
|
+
for (const field of ['critical', 'high', 'license-conflicts']) {
|
|
106
|
+
const value = config.check['fail-on'][field];
|
|
107
|
+
if (value !== undefined && (typeof value !== 'number' || !Number.isFinite(value))) {
|
|
108
|
+
throw new Error(`Invalid config file ${source}: check.fail-on.${field} must be a finite number`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (config.sbom !== undefined) {
|
|
114
|
+
assertMapping(config.sbom, 'sbom', source);
|
|
115
|
+
if (config.sbom.format !== undefined) {
|
|
116
|
+
assertString(config.sbom.format, 'sbom.format', source);
|
|
117
|
+
}
|
|
118
|
+
if (config.sbom.targets !== undefined) {
|
|
119
|
+
assertStringArray(config.sbom.targets, 'sbom.targets', source);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return config;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Walks up from `startPath` looking for a `.trustify-da.yml` (or `.yaml`) file,
|
|
126
|
+
* similar to how `.eslintrc` discovery works. If `startPath` points at a file,
|
|
127
|
+
* discovery begins in its containing directory. Within a directory, `.yml` takes
|
|
128
|
+
* precedence over `.yaml`.
|
|
129
|
+
* @param {string} startPath - manifest file or directory to start the search from
|
|
130
|
+
* @returns {string | null} absolute path to the config file, or null if none found
|
|
131
|
+
*/
|
|
132
|
+
function findConfigFile(startPath) {
|
|
133
|
+
let dir = path.resolve(startPath || '.');
|
|
134
|
+
try {
|
|
135
|
+
if (fs.statSync(dir).isFile()) {
|
|
136
|
+
dir = path.dirname(dir);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// startPath may not exist yet — walk up from its resolved location anyway
|
|
141
|
+
}
|
|
142
|
+
// Walk up until the filesystem root (where dirname(dir) === dir)
|
|
143
|
+
for (;;) {
|
|
144
|
+
for (const name of CONFIG_FILENAMES) {
|
|
145
|
+
const candidate = path.join(dir, name);
|
|
146
|
+
try {
|
|
147
|
+
if (fs.statSync(candidate).isFile()) {
|
|
148
|
+
return candidate;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Ignore inaccessible or disappearing candidates and continue discovery.
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const parent = path.dirname(dir);
|
|
156
|
+
if (parent === dir) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
dir = parent;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Discovers and parses `.trustify-da.yml` by walking up from `startPath`.
|
|
164
|
+
* A missing config file is not an error — an empty object is returned so callers
|
|
165
|
+
* can fall back to defaults.
|
|
166
|
+
* @param {string} [startPath] - manifest file or directory to start the search from
|
|
167
|
+
* @returns {FileConfig} the parsed config object, or `{}` when no file is found
|
|
168
|
+
* @throws {Error} when the config file exists but contains malformed YAML
|
|
169
|
+
*/
|
|
170
|
+
export function loadConfig(startPath) {
|
|
171
|
+
const configPath = findConfigFile(startPath);
|
|
172
|
+
if (!configPath) {
|
|
173
|
+
return {};
|
|
174
|
+
}
|
|
175
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
176
|
+
let doc;
|
|
177
|
+
try {
|
|
178
|
+
doc = yamlLoad(content);
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
throw new Error(`Failed to parse config file ${configPath}: ${err.message}`);
|
|
182
|
+
}
|
|
183
|
+
return doc == null ? {} : validateConfig(doc, configPath);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Normalizes a providers/sources value to an array of trimmed strings. Accepts
|
|
187
|
+
* either a YAML array (`[redhat, osv]`) or a comma-separated string (`redhat,osv`).
|
|
188
|
+
* @param {string[] | string | undefined | null} value
|
|
189
|
+
* @returns {string[]}
|
|
190
|
+
*/
|
|
191
|
+
function toArray(value) {
|
|
192
|
+
if (Array.isArray(value)) {
|
|
193
|
+
return value.filter(v => typeof v === 'string' && v.trim()).map(v => v.trim());
|
|
194
|
+
}
|
|
195
|
+
if (typeof value === 'string') {
|
|
196
|
+
return value.split(',').map(v => v.trim()).filter(Boolean);
|
|
197
|
+
}
|
|
198
|
+
return [];
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Returns the first argument that is neither undefined nor null.
|
|
202
|
+
* @param {...unknown} values
|
|
203
|
+
* @returns {unknown}
|
|
204
|
+
*/
|
|
205
|
+
function first(...values) {
|
|
206
|
+
return values.find(v => v != null);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Merges config sources with precedence: CLI flag > environment variable
|
|
210
|
+
* (`TRUSTIFY_DA_*`) > config file > hardcoded default. Providers and sources are
|
|
211
|
+
* normalized to arrays regardless of whether the source used a YAML array or a
|
|
212
|
+
* comma-separated string.
|
|
213
|
+
* @param {FileConfig} [fileConfig={}] - values parsed from `.trustify-da.yml`
|
|
214
|
+
* @param {{ providers?: string, sources?: string, groupBy?: string, backendUrl?: string }} [cliFlags={}]
|
|
215
|
+
* @param {{ [key: string]: string | undefined }} [envVars={}] - typically `process.env`
|
|
216
|
+
* @returns {ResolvedConfig} the resolved, typed config object
|
|
217
|
+
*/
|
|
218
|
+
export function mergeConfig(fileConfig = {}, cliFlags = {}, envVars = {}) {
|
|
219
|
+
const file = validateConfig(fileConfig || {});
|
|
220
|
+
const cli = cliFlags || {};
|
|
221
|
+
const env = envVars || {};
|
|
222
|
+
let backendUrl = null;
|
|
223
|
+
let backendUrlSource = 'default';
|
|
224
|
+
if (cli.backendUrl != null) {
|
|
225
|
+
backendUrl = cli.backendUrl;
|
|
226
|
+
backendUrlSource = 'cli';
|
|
227
|
+
}
|
|
228
|
+
else if (env.TRUSTIFY_DA_BACKEND_URL != null) {
|
|
229
|
+
backendUrl = env.TRUSTIFY_DA_BACKEND_URL;
|
|
230
|
+
backendUrlSource = 'environment';
|
|
231
|
+
}
|
|
232
|
+
else if (file['backend-url'] != null) {
|
|
233
|
+
backendUrl = file['backend-url'];
|
|
234
|
+
backendUrlSource = 'file';
|
|
235
|
+
}
|
|
236
|
+
const groupBy = first(cli.groupBy, env.TRUSTIFY_DA_GROUP_BY, file.remediation?.['group-by']) ?? 'dependency';
|
|
237
|
+
if (!['dependency', 'bundle'].includes(groupBy)) {
|
|
238
|
+
throw new Error(`Invalid group-by value "${groupBy}". Expected dependency or bundle.`);
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
backendUrl,
|
|
242
|
+
backendUrlSource,
|
|
243
|
+
providers: toArray(first(cli.providers, env.TRUSTIFY_DA_PROVIDERS, file.providers)),
|
|
244
|
+
sources: toArray(first(cli.sources, env.TRUSTIFY_DA_SOURCES, file.sources)),
|
|
245
|
+
groupBy,
|
|
246
|
+
remediation: file.remediation ?? {},
|
|
247
|
+
check: file.check ?? {},
|
|
248
|
+
sbom: file.sbom ?? {},
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Loads and merges the project configuration for a target path.
|
|
253
|
+
* @param {string} [startPath] - manifest file or directory to start discovery from
|
|
254
|
+
* @param {{ providers?: string, sources?: string, groupBy?: string, backendUrl?: string }} [cliFlags={}] - explicit options
|
|
255
|
+
* @param {{ [key: string]: string | undefined }} [envVars={}] - typically `process.env`
|
|
256
|
+
* @returns {ResolvedConfig} the resolved, typed config object
|
|
257
|
+
*/
|
|
258
|
+
export function resolveConfig(startPath, cliFlags = {}, envVars = {}) {
|
|
259
|
+
return mergeConfig(loadConfig(startPath), cliFlags, envVars);
|
|
260
|
+
}
|
|
@@ -26,6 +26,19 @@ export default class CycloneDxSbom {
|
|
|
26
26
|
alg: string;
|
|
27
27
|
content: string;
|
|
28
28
|
}>): CycloneDxSbom;
|
|
29
|
+
/**
|
|
30
|
+
* Attach hashes to already-added components by matching their PURL. This is a
|
|
31
|
+
* post-processing step so ecosystem-specific hash sources (e.g. Maven reading
|
|
32
|
+
* the local .m2 cache) can enrich the SBOM without threading their concern
|
|
33
|
+
* through the shared dependency-tree parser. Components without a matching
|
|
34
|
+
* entry, or whose hashes are already set, are left untouched.
|
|
35
|
+
* @param {Map<string, Array<{alg: string, content: string}>>} hashMap - PURL→hashes map
|
|
36
|
+
* @return {CycloneDxSbom} the updated SBOM
|
|
37
|
+
*/
|
|
38
|
+
attachHashes(hashMap: Map<string, Array<{
|
|
39
|
+
alg: string;
|
|
40
|
+
content: string;
|
|
41
|
+
}>>): CycloneDxSbom;
|
|
29
42
|
/** @param {{}} opts - various options, settings and configuration of application.
|
|
30
43
|
* @return String CycloneDx Sbom json object in a string format
|
|
31
44
|
*/
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { EOL } from "os";
|
|
2
2
|
import { PackageURL } from "packageurl-js";
|
|
3
|
+
import { getPackageVersion } from "./package_version.js";
|
|
4
|
+
/**
|
|
5
|
+
* This client's version, read once at module load, used to populate
|
|
6
|
+
* metadata.tools.components[].version in the generated SBOM.
|
|
7
|
+
* @type {string|undefined}
|
|
8
|
+
*/
|
|
9
|
+
const PACKAGE_VERSION = getPackageVersion();
|
|
3
10
|
/**
|
|
4
11
|
*
|
|
5
12
|
* @param component {PackageURL}
|
|
@@ -41,12 +48,20 @@ function getComponent(component, type, scope, licenses, hashes) {
|
|
|
41
48
|
// Add licenses if provided (CycloneDX format). Callers must provide valid SPDX identifiers.
|
|
42
49
|
if (licenses) {
|
|
43
50
|
const licenseArray = Array.isArray(licenses) ? licenses : [licenses];
|
|
44
|
-
|
|
51
|
+
const validLicenses = licenseArray
|
|
52
|
+
.map(lic => {
|
|
45
53
|
if (typeof lic === 'string') {
|
|
46
54
|
return { license: { id: lic } };
|
|
47
55
|
}
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
if (typeof lic === 'object' && lic !== null && ('license' in lic || 'expression' in lic)) {
|
|
57
|
+
return lic;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
})
|
|
61
|
+
.filter(Boolean);
|
|
62
|
+
if (validLicenses.length > 0) {
|
|
63
|
+
componentObject.licenses = validLicenses;
|
|
64
|
+
}
|
|
50
65
|
}
|
|
51
66
|
// Add hashes if provided (CycloneDX 1.4 format).
|
|
52
67
|
if (hashes && hashes.length > 0) {
|
|
@@ -127,6 +142,30 @@ export default class CycloneDxSbom {
|
|
|
127
142
|
}
|
|
128
143
|
return this;
|
|
129
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Attach hashes to already-added components by matching their PURL. This is a
|
|
147
|
+
* post-processing step so ecosystem-specific hash sources (e.g. Maven reading
|
|
148
|
+
* the local .m2 cache) can enrich the SBOM without threading their concern
|
|
149
|
+
* through the shared dependency-tree parser. Components without a matching
|
|
150
|
+
* entry, or whose hashes are already set, are left untouched.
|
|
151
|
+
* @param {Map<string, Array<{alg: string, content: string}>>} hashMap - PURL→hashes map
|
|
152
|
+
* @return {CycloneDxSbom} the updated SBOM
|
|
153
|
+
*/
|
|
154
|
+
attachHashes(hashMap) {
|
|
155
|
+
if (!hashMap || hashMap.size === 0) {
|
|
156
|
+
return this;
|
|
157
|
+
}
|
|
158
|
+
for (const component of this.components) {
|
|
159
|
+
if (component.hashes) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
const hashes = hashMap.get(component.purl);
|
|
163
|
+
if (hashes && hashes.length > 0) {
|
|
164
|
+
component.hashes = hashes;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return this;
|
|
168
|
+
}
|
|
130
169
|
/** @param {{}} opts - various options, settings and configuration of application.
|
|
131
170
|
* @return String CycloneDx Sbom json object in a string format
|
|
132
171
|
*/
|
|
@@ -136,11 +175,18 @@ export default class CycloneDxSbom {
|
|
|
136
175
|
const rootPurl = this.rootComponent?.purl;
|
|
137
176
|
this.sbomObject = {
|
|
138
177
|
"bomFormat": "CycloneDX",
|
|
139
|
-
"specVersion": "1.
|
|
178
|
+
"specVersion": "1.6",
|
|
140
179
|
"version": 1,
|
|
141
180
|
"metadata": {
|
|
142
181
|
"timestamp": new Date(),
|
|
143
182
|
"component": this.rootComponent,
|
|
183
|
+
"tools": {
|
|
184
|
+
"components": [{
|
|
185
|
+
"type": "application",
|
|
186
|
+
"name": "trustify-da-javascript-client",
|
|
187
|
+
"version": PACKAGE_VERSION
|
|
188
|
+
}]
|
|
189
|
+
},
|
|
144
190
|
"properties": new Array()
|
|
145
191
|
},
|
|
146
192
|
"components": this.components.filter(c => c.purl !== rootPurl),
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* 1. Environment Variable
|
|
5
|
-
* 2. (key,value) from opts object
|
|
2
|
+
* Selects the Trustify DA backend URL from opts.TRUSTIFY_DA_BACKEND_URL, then environment
|
|
3
|
+
* variable TRUSTIFY_DA_BACKEND_URL. Options take precedence over environment variables.
|
|
6
4
|
* If TRUSTIFY_DA_BACKEND_URL is not set, the function will throw an error.
|
|
7
5
|
* @param {{TRUSTIFY_DA_DEBUG?: string | undefined; TRUSTIFY_DA_BACKEND_URL?: string | undefined}} [opts={}]
|
|
8
6
|
* @return {string} - The selected Trustify DA backend URL
|
|
@@ -53,7 +51,9 @@ export type Options = {
|
|
|
53
51
|
TRUSTIFY_DA_PYTHON_PATH?: string | undefined;
|
|
54
52
|
TRUSTIFY_DA_PYTHON_VIRTUAL_ENV?: string | undefined;
|
|
55
53
|
TRUSTIFY_DA_PYTHON3_PATH?: string | undefined;
|
|
56
|
-
|
|
54
|
+
TRUSTIFY_DA_PROVIDERS?: string | undefined;
|
|
55
|
+
TRUSTIFY_DA_RECOMMEND?: string | undefined;
|
|
56
|
+
TRUSTIFY_DA_SOURCES?: string | undefined;
|
|
57
57
|
TRUSTIFY_DA_SKOPEO_CONFIG_PATH?: string | undefined;
|
|
58
58
|
TRUSTIFY_DA_SKOPEO_PATH?: string | undefined;
|
|
59
59
|
TRUSTIFY_DA_SYFT_CONFIG_PATH?: string | undefined;
|
|
@@ -61,11 +61,11 @@ export type Options = {
|
|
|
61
61
|
TRUSTIFY_DA_YARN_PATH?: string | undefined;
|
|
62
62
|
TRUSTIFY_DA_WORKSPACE_DIR?: string | undefined;
|
|
63
63
|
TRUSTIFY_DA_LICENSE_CHECK?: string | undefined;
|
|
64
|
+
licenseCheck?: boolean | undefined;
|
|
64
65
|
MATCH_MANIFEST_VERSIONS?: string | undefined;
|
|
65
66
|
TRUSTIFY_DA_SOURCE?: string | undefined;
|
|
66
67
|
TRUSTIFY_DA_TOKEN?: string | undefined;
|
|
67
68
|
TRUSTIFY_DA_TELEMETRY_ID?: string | undefined;
|
|
68
|
-
TRUSTIFY_DA_WORKSPACE_DIR?: string | undefined;
|
|
69
69
|
batchConcurrency?: number | undefined;
|
|
70
70
|
TRUSTIFY_DA_BATCH_CONCURRENCY?: string | undefined;
|
|
71
71
|
workspaceDiscoveryIgnore?: string[] | undefined;
|
|
@@ -103,10 +103,10 @@ export type SbomResult = {
|
|
|
103
103
|
* Get component analysis report for a manifest content.
|
|
104
104
|
* @param {string} manifest - path to the manifest
|
|
105
105
|
* @param {Options} [opts={}] - optional various options to pass along the application
|
|
106
|
-
* @returns {Promise<import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>}
|
|
106
|
+
* @returns {Promise<import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts').AnalysisReport>}
|
|
107
107
|
* @throws {Error} if no matching provider, failed to get create content, or backend request failed
|
|
108
108
|
*/
|
|
109
|
-
declare function componentAnalysis(manifest: string, opts?: Options): Promise<import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport>;
|
|
109
|
+
declare function componentAnalysis(manifest: string, opts?: Options): Promise<import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts").AnalysisReport>;
|
|
110
110
|
/**
|
|
111
111
|
* @overload
|
|
112
112
|
* @param {string} manifest
|
|
@@ -121,21 +121,21 @@ declare function stackAnalysis(manifest: string, html: true, opts?: Options | un
|
|
|
121
121
|
* @param {string} manifest
|
|
122
122
|
* @param {false} html
|
|
123
123
|
* @param {Options} [opts={}]
|
|
124
|
-
* @returns {Promise<import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>}
|
|
124
|
+
* @returns {Promise<import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts').AnalysisReport>}
|
|
125
125
|
* @throws {Error}
|
|
126
126
|
*/
|
|
127
|
-
declare function stackAnalysis(manifest: string, html: false, opts?: Options | undefined): Promise<import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport>;
|
|
127
|
+
declare function stackAnalysis(manifest: string, html: false, opts?: Options | undefined): Promise<import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts").AnalysisReport>;
|
|
128
128
|
/**
|
|
129
129
|
* Get stack analysis report for a manifest file.
|
|
130
130
|
* @overload
|
|
131
131
|
* @param {string} manifest - path for the manifest
|
|
132
132
|
* @param {boolean} [html=false] - true will return a html string, false will return AnalysisReport object.
|
|
133
133
|
* @param {Options} [opts={}] - optional various options to pass along the application
|
|
134
|
-
* @returns {Promise<string|import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>}
|
|
134
|
+
* @returns {Promise<string|import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts').AnalysisReport>}
|
|
135
135
|
* @throws {Error} if manifest inaccessible, no matching provider, failed to get create content,
|
|
136
136
|
* or backend request failed
|
|
137
137
|
*/
|
|
138
|
-
declare function stackAnalysis(manifest: string, html?: boolean | undefined, opts?: Options | undefined): Promise<string | import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport>;
|
|
138
|
+
declare function stackAnalysis(manifest: string, html?: boolean | undefined, opts?: Options | undefined): Promise<string | import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts").AnalysisReport>;
|
|
139
139
|
/**
|
|
140
140
|
* @overload
|
|
141
141
|
* @param {string} workspaceRoot
|
|
@@ -166,14 +166,14 @@ declare function stackAnalysisBatch(workspaceRoot: string, html: true, opts?: (O
|
|
|
166
166
|
* @param {string} workspaceRoot
|
|
167
167
|
* @param {false} html
|
|
168
168
|
* @param {Options & { batchMetadata: true }} opts
|
|
169
|
-
* @returns {Promise<{ analysis: Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>, metadata: BatchAnalysisMetadata }>}
|
|
169
|
+
* @returns {Promise<{ analysis: Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts').AnalysisReport>, metadata: BatchAnalysisMetadata }>}
|
|
170
170
|
* @throws {Error}
|
|
171
171
|
*/
|
|
172
172
|
declare function stackAnalysisBatch(workspaceRoot: string, html: false, opts: Options & {
|
|
173
173
|
batchMetadata: true;
|
|
174
174
|
}): Promise<{
|
|
175
175
|
analysis: {
|
|
176
|
-
[x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
|
|
176
|
+
[x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts").AnalysisReport;
|
|
177
177
|
};
|
|
178
178
|
metadata: BatchAnalysisMetadata;
|
|
179
179
|
}>;
|
|
@@ -182,13 +182,13 @@ declare function stackAnalysisBatch(workspaceRoot: string, html: false, opts: Op
|
|
|
182
182
|
* @param {string} workspaceRoot
|
|
183
183
|
* @param {false} html
|
|
184
184
|
* @param {Options & { batchMetadata?: false }} [opts={}]
|
|
185
|
-
* @returns {Promise<Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>>}
|
|
185
|
+
* @returns {Promise<Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts').AnalysisReport>>}
|
|
186
186
|
* @throws {Error}
|
|
187
187
|
*/
|
|
188
188
|
declare function stackAnalysisBatch(workspaceRoot: string, html: false, opts?: (Options & {
|
|
189
189
|
batchMetadata?: false;
|
|
190
190
|
}) | undefined): Promise<{
|
|
191
|
-
[x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
|
|
191
|
+
[x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts").AnalysisReport;
|
|
192
192
|
}>;
|
|
193
193
|
/**
|
|
194
194
|
* Get stack analysis for all workspace packages/crates (batch).
|
|
@@ -200,14 +200,14 @@ declare function stackAnalysisBatch(workspaceRoot: string, html: false, opts?: (
|
|
|
200
200
|
* @param {string} workspaceRoot - Path to workspace root (containing lock file and workspace config)
|
|
201
201
|
* @param {boolean} [html=false] - true returns HTML, false returns JSON report
|
|
202
202
|
* @param {Options} [opts={}] - `batchConcurrency`, discovery ignores, `continueOnError` (default true), `batchMetadata` (default false)
|
|
203
|
-
* @returns {Promise<string|Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>|{ analysis: string|Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>, metadata: BatchAnalysisMetadata }>}
|
|
203
|
+
* @returns {Promise<string|Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts').AnalysisReport>|{ analysis: string|Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts').AnalysisReport>, metadata: BatchAnalysisMetadata }>}
|
|
204
204
|
* @throws {Error} if workspace root invalid, no manifests found, no packages pass validation, no SBOMs produced, or backend request failed. When `opts.batchMetadata` is set, `error.batchMetadata` may be set on thrown errors.
|
|
205
205
|
*/
|
|
206
206
|
declare function stackAnalysisBatch(workspaceRoot: string, html?: boolean | undefined, opts?: Options | undefined): Promise<string | {
|
|
207
|
-
[x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
|
|
207
|
+
[x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts").AnalysisReport;
|
|
208
208
|
} | {
|
|
209
209
|
analysis: string | {
|
|
210
|
-
[x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
|
|
210
|
+
[x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts").AnalysisReport;
|
|
211
211
|
};
|
|
212
212
|
metadata: BatchAnalysisMetadata;
|
|
213
213
|
}>;
|
|
@@ -225,11 +225,11 @@ declare function imageAnalysis(imageRefs: Array<string>, html: true, opts?: Opti
|
|
|
225
225
|
* @param {Array<string>} imageRefs
|
|
226
226
|
* @param {false} html
|
|
227
227
|
* @param {Options} [opts={}]
|
|
228
|
-
* @returns {Promise<Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>>}
|
|
228
|
+
* @returns {Promise<Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts').AnalysisReport>>}
|
|
229
229
|
* @throws {Error}
|
|
230
230
|
*/
|
|
231
231
|
declare function imageAnalysis(imageRefs: Array<string>, html: false, opts?: Options | undefined): Promise<{
|
|
232
|
-
[x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
|
|
232
|
+
[x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts").AnalysisReport;
|
|
233
233
|
}>;
|
|
234
234
|
/**
|
|
235
235
|
* Get image analysis report for a set of OCI image references.
|
|
@@ -237,12 +237,12 @@ declare function imageAnalysis(imageRefs: Array<string>, html: false, opts?: Opt
|
|
|
237
237
|
* @param {Array<string>} imageRefs - OCI image references
|
|
238
238
|
* @param {boolean} [html=false] - true will return a html string, false will return AnalysisReport
|
|
239
239
|
* @param {Options} [opts={}] - optional various options to pass along the application
|
|
240
|
-
* @returns {Promise<string|Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>>}
|
|
240
|
+
* @returns {Promise<string|Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts').AnalysisReport>>}
|
|
241
241
|
* @throws {Error} if manifest inaccessible, no matching provider, failed to get create content,
|
|
242
242
|
* or backend request failed
|
|
243
243
|
*/
|
|
244
244
|
declare function imageAnalysis(imageRefs: Array<string>, html?: boolean | undefined, opts?: Options | undefined): Promise<string | {
|
|
245
|
-
[x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
|
|
245
|
+
[x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport.ts").AnalysisReport;
|
|
246
246
|
}>;
|
|
247
247
|
/**
|
|
248
248
|
* Validates the Exhort token.
|
|
@@ -264,3 +264,7 @@ import { resolveContinueOnError } from './batch_opts.js';
|
|
|
264
264
|
import { resolveBatchMetadata } from './batch_opts.js';
|
|
265
265
|
export { discoverMavenModules, discoverGradleSubprojects, discoverGoWorkspaceModules, discoverUvWorkspaceMembers, discoverWorkspacePackages, discoverWorkspaceCrates, validatePackageJson, resolveWorkspaceDiscoveryIgnore, filterManifestPathsByDiscoveryIgnore, resolveContinueOnError, resolveBatchMetadata };
|
|
266
266
|
export { getProjectLicense, findLicenseFilePath, identifyLicense, getLicenseDetails, licensesFromReport, normalizeLicensesResponse, runLicenseCheck, getCompatibility } from "./license/index.js";
|
|
267
|
+
export { extractRemediations, maxSeverity } from "./remediation.js";
|
|
268
|
+
export { generateReport, generateDeduplicationKey } from "./remediation_report.js";
|
|
269
|
+
export { loadConfig, mergeConfig, resolveConfig, CONFIG_FILENAMES } from "./config.js";
|
|
270
|
+
export { runRemediation, findManifests } from "./remediate.js";
|