@trustify-da/trustify-da-javascript-client 0.3.0-ea.b8af0f8 → 0.3.0-ea.bdb4511
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 +73 -8
- package/dist/package.json +24 -24
- package/dist/src/analysis.d.ts +7 -7
- package/dist/src/analysis.js +3 -2
- package/dist/src/cli.js +51 -2
- package/dist/src/cyclone_dx_sbom.d.ts +14 -1
- package/dist/src/cyclone_dx_sbom.js +43 -8
- package/dist/src/index.d.ts +81 -10
- package/dist/src/index.js +92 -7
- package/dist/src/license/index.d.ts +3 -3
- package/dist/src/license/index.js +4 -1
- package/dist/src/license/license_utils.js +4 -1
- package/dist/src/license/licenses_api.d.ts +2 -2
- package/dist/src/oci_image/images.d.ts +1 -1
- package/dist/src/oci_image/utils.d.ts +5 -5
- package/dist/src/oci_image/utils.js +11 -2
- package/dist/src/provider.d.ts +4 -3
- package/dist/src/provider.js +9 -1
- package/dist/src/providers/base_java.d.ts +14 -12
- package/dist/src/providers/base_java.js +18 -44
- package/dist/src/providers/base_javascript.d.ts +20 -9
- package/dist/src/providers/base_javascript.js +44 -6
- package/dist/src/providers/base_pyproject.d.ts +158 -0
- package/dist/src/providers/base_pyproject.js +322 -0
- package/dist/src/providers/golang_gomodules.d.ts +23 -13
- package/dist/src/providers/golang_gomodules.js +165 -119
- package/dist/src/providers/gomod_parser.d.ts +4 -0
- package/dist/src/providers/gomod_parser.js +16 -0
- package/dist/src/providers/java_gradle.d.ts +19 -0
- package/dist/src/providers/java_gradle.js +116 -2
- 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 +10 -2
- package/dist/src/providers/java_maven.js +165 -1
- package/dist/src/providers/javascript_bun.d.ts +10 -0
- package/dist/src/providers/javascript_bun.js +100 -0
- package/dist/src/providers/javascript_npm.d.ts +6 -0
- package/dist/src/providers/javascript_npm.js +21 -0
- package/dist/src/providers/javascript_pnpm.js +6 -2
- package/dist/src/providers/manifest.d.ts +2 -0
- package/dist/src/providers/manifest.js +22 -4
- package/dist/src/providers/marker_evaluator.d.ts +14 -0
- package/dist/src/providers/marker_evaluator.js +191 -0
- package/dist/src/providers/processors/yarn_berry_processor.d.ts +2 -2
- package/dist/src/providers/processors/yarn_berry_processor.js +88 -5
- package/dist/src/providers/processors/yarn_classic_processor.d.ts +2 -2
- package/dist/src/providers/python_controller.d.ts +5 -1
- package/dist/src/providers/python_controller.js +65 -7
- package/dist/src/providers/python_pip.d.ts +5 -0
- package/dist/src/providers/python_pip.js +6 -6
- package/dist/src/providers/python_pip_pyproject.d.ts +61 -0
- package/dist/src/providers/python_pip_pyproject.js +146 -0
- package/dist/src/providers/python_poetry.d.ts +98 -0
- package/dist/src/providers/python_poetry.js +286 -0
- package/dist/src/providers/python_uv.d.ts +46 -0
- package/dist/src/providers/python_uv.js +269 -0
- package/dist/src/providers/rust_cargo.d.ts +6 -2
- package/dist/src/providers/rust_cargo.js +31 -4
- package/dist/src/providers/tree-sitter-gomod.wasm +0 -0
- package/dist/src/sbom.d.ts +14 -1
- package/dist/src/sbom.js +13 -2
- package/dist/src/tools.d.ts +28 -2
- package/dist/src/tools.js +58 -0
- package/dist/src/workspace.d.ts +9 -0
- package/dist/src/workspace.js +1 -1
- package/package.json +25 -25
package/dist/src/index.d.ts
CHANGED
|
@@ -13,6 +13,15 @@ export function selectTrustifyDABackend(opts?: {
|
|
|
13
13
|
TRUSTIFY_DA_DEBUG?: string | undefined;
|
|
14
14
|
TRUSTIFY_DA_BACKEND_URL?: string | undefined;
|
|
15
15
|
}): string;
|
|
16
|
+
/**
|
|
17
|
+
* Generate a CycloneDX SBOM from a manifest file. No backend HTTP request is made.
|
|
18
|
+
*
|
|
19
|
+
* @param {string} manifestPath - path to the manifest file (e.g. pom.xml, package.json)
|
|
20
|
+
* @param {Options} [opts={}] - optional options (e.g. workspace dir, tool paths)
|
|
21
|
+
* @returns {Promise<object>} parsed CycloneDX SBOM JSON object
|
|
22
|
+
* @throws {Error} if the manifest is unsupported or SBOM generation fails
|
|
23
|
+
*/
|
|
24
|
+
export function generateSbom(manifestPath: string, opts?: Options): Promise<object>;
|
|
16
25
|
export { parseImageRef } from "./oci_image/utils.js";
|
|
17
26
|
export { ImageRef } from "./oci_image/images.js";
|
|
18
27
|
declare namespace _default {
|
|
@@ -21,6 +30,7 @@ declare namespace _default {
|
|
|
21
30
|
export { stackAnalysisBatch };
|
|
22
31
|
export { imageAnalysis };
|
|
23
32
|
export { validateToken };
|
|
33
|
+
export { generateSbom };
|
|
24
34
|
}
|
|
25
35
|
export default _default;
|
|
26
36
|
export type Options = {
|
|
@@ -64,11 +74,13 @@ export type Options = {
|
|
|
64
74
|
TRUSTIFY_DA_CONTINUE_ON_ERROR?: string | undefined;
|
|
65
75
|
batchMetadata?: boolean | undefined;
|
|
66
76
|
TRUSTIFY_DA_BATCH_METADATA?: string | undefined;
|
|
77
|
+
TRUSTIFY_DA_UV_PATH?: string | undefined;
|
|
78
|
+
TRUSTIFY_DA_POETRY_PATH?: string | undefined;
|
|
67
79
|
[key: string]: string | number | boolean | string[] | undefined;
|
|
68
80
|
};
|
|
69
81
|
export type BatchAnalysisMetadata = {
|
|
70
82
|
workspaceRoot: string;
|
|
71
|
-
ecosystem: "javascript" | "cargo" | "unknown";
|
|
83
|
+
ecosystem: "javascript" | "cargo" | "pyproject" | "unknown";
|
|
72
84
|
total: number;
|
|
73
85
|
successful: number;
|
|
74
86
|
failed: number;
|
|
@@ -94,7 +106,7 @@ export type SbomResult = {
|
|
|
94
106
|
* @returns {Promise<import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>}
|
|
95
107
|
* @throws {Error} if no matching provider, failed to get create content, or backend request failed
|
|
96
108
|
*/
|
|
97
|
-
declare function componentAnalysis(manifest: string, opts?: Options): Promise<
|
|
109
|
+
declare function componentAnalysis(manifest: string, opts?: Options): Promise<any>;
|
|
98
110
|
/**
|
|
99
111
|
* @overload
|
|
100
112
|
* @param {string} manifest
|
|
@@ -112,7 +124,7 @@ declare function stackAnalysis(manifest: string, html: true, opts?: Options | un
|
|
|
112
124
|
* @returns {Promise<import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>}
|
|
113
125
|
* @throws {Error}
|
|
114
126
|
*/
|
|
115
|
-
declare function stackAnalysis(manifest: string, html: false, opts?: Options | undefined): Promise<
|
|
127
|
+
declare function stackAnalysis(manifest: string, html: false, opts?: Options | undefined): Promise<any>;
|
|
116
128
|
/**
|
|
117
129
|
* Get stack analysis report for a manifest file.
|
|
118
130
|
* @overload
|
|
@@ -123,24 +135,79 @@ declare function stackAnalysis(manifest: string, html: false, opts?: Options | u
|
|
|
123
135
|
* @throws {Error} if manifest inaccessible, no matching provider, failed to get create content,
|
|
124
136
|
* or backend request failed
|
|
125
137
|
*/
|
|
126
|
-
declare function stackAnalysis(manifest: string, html?: boolean | undefined, opts?: Options | undefined): Promise<string |
|
|
138
|
+
declare function stackAnalysis(manifest: string, html?: boolean | undefined, opts?: Options | undefined): Promise<string | any>;
|
|
139
|
+
/**
|
|
140
|
+
* @overload
|
|
141
|
+
* @param {string} workspaceRoot
|
|
142
|
+
* @param {true} html
|
|
143
|
+
* @param {Options & { batchMetadata: true }} opts
|
|
144
|
+
* @returns {Promise<{ analysis: string, metadata: BatchAnalysisMetadata }>}
|
|
145
|
+
* @throws {Error}
|
|
146
|
+
*/
|
|
147
|
+
declare function stackAnalysisBatch(workspaceRoot: string, html: true, opts: Options & {
|
|
148
|
+
batchMetadata: true;
|
|
149
|
+
}): Promise<{
|
|
150
|
+
analysis: string;
|
|
151
|
+
metadata: BatchAnalysisMetadata;
|
|
152
|
+
}>;
|
|
153
|
+
/**
|
|
154
|
+
* @overload
|
|
155
|
+
* @param {string} workspaceRoot
|
|
156
|
+
* @param {true} html
|
|
157
|
+
* @param {Options & { batchMetadata?: false }} [opts={}]
|
|
158
|
+
* @returns {Promise<string>}
|
|
159
|
+
* @throws {Error}
|
|
160
|
+
*/
|
|
161
|
+
declare function stackAnalysisBatch(workspaceRoot: string, html: true, opts?: (Options & {
|
|
162
|
+
batchMetadata?: false;
|
|
163
|
+
}) | undefined): Promise<string>;
|
|
164
|
+
/**
|
|
165
|
+
* @overload
|
|
166
|
+
* @param {string} workspaceRoot
|
|
167
|
+
* @param {false} html
|
|
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 }>}
|
|
170
|
+
* @throws {Error}
|
|
171
|
+
*/
|
|
172
|
+
declare function stackAnalysisBatch(workspaceRoot: string, html: false, opts: Options & {
|
|
173
|
+
batchMetadata: true;
|
|
174
|
+
}): Promise<{
|
|
175
|
+
analysis: {
|
|
176
|
+
[x: string]: any;
|
|
177
|
+
};
|
|
178
|
+
metadata: BatchAnalysisMetadata;
|
|
179
|
+
}>;
|
|
180
|
+
/**
|
|
181
|
+
* @overload
|
|
182
|
+
* @param {string} workspaceRoot
|
|
183
|
+
* @param {false} html
|
|
184
|
+
* @param {Options & { batchMetadata?: false }} [opts={}]
|
|
185
|
+
* @returns {Promise<Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>>}
|
|
186
|
+
* @throws {Error}
|
|
187
|
+
*/
|
|
188
|
+
declare function stackAnalysisBatch(workspaceRoot: string, html: false, opts?: (Options & {
|
|
189
|
+
batchMetadata?: false;
|
|
190
|
+
}) | undefined): Promise<{
|
|
191
|
+
[x: string]: any;
|
|
192
|
+
}>;
|
|
127
193
|
/**
|
|
128
194
|
* Get stack analysis for all workspace packages/crates (batch).
|
|
129
195
|
* Detects ecosystem from workspace root: Cargo (Cargo.toml + Cargo.lock) or JS/TS (package.json + lock file).
|
|
130
196
|
* SBOMs are generated in parallel (see `batchConcurrency`) unless `continueOnError: false` (fail-fast sequential).
|
|
131
197
|
* With `opts.batchMetadata` / `TRUSTIFY_DA_BATCH_METADATA`, returns `{ analysis, metadata }` including validation and SBOM errors.
|
|
132
198
|
*
|
|
199
|
+
* @overload
|
|
133
200
|
* @param {string} workspaceRoot - Path to workspace root (containing lock file and workspace config)
|
|
134
201
|
* @param {boolean} [html=false] - true returns HTML, false returns JSON report
|
|
135
202
|
* @param {Options} [opts={}] - `batchConcurrency`, discovery ignores, `continueOnError` (default true), `batchMetadata` (default false)
|
|
136
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 }>}
|
|
137
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.
|
|
138
205
|
*/
|
|
139
|
-
declare function stackAnalysisBatch(workspaceRoot: string, html?: boolean, opts?: Options): Promise<string | {
|
|
140
|
-
[x: string]:
|
|
206
|
+
declare function stackAnalysisBatch(workspaceRoot: string, html?: boolean | undefined, opts?: Options | undefined): Promise<string | {
|
|
207
|
+
[x: string]: any;
|
|
141
208
|
} | {
|
|
142
209
|
analysis: string | {
|
|
143
|
-
[x: string]:
|
|
210
|
+
[x: string]: any;
|
|
144
211
|
};
|
|
145
212
|
metadata: BatchAnalysisMetadata;
|
|
146
213
|
}>;
|
|
@@ -162,7 +229,7 @@ declare function imageAnalysis(imageRefs: Array<string>, html: true, opts?: Opti
|
|
|
162
229
|
* @throws {Error}
|
|
163
230
|
*/
|
|
164
231
|
declare function imageAnalysis(imageRefs: Array<string>, html: false, opts?: Options | undefined): Promise<{
|
|
165
|
-
[x: string]:
|
|
232
|
+
[x: string]: any;
|
|
166
233
|
}>;
|
|
167
234
|
/**
|
|
168
235
|
* Get image analysis report for a set of OCI image references.
|
|
@@ -175,7 +242,7 @@ declare function imageAnalysis(imageRefs: Array<string>, html: false, opts?: Opt
|
|
|
175
242
|
* or backend request failed
|
|
176
243
|
*/
|
|
177
244
|
declare function imageAnalysis(imageRefs: Array<string>, html?: boolean | undefined, opts?: Options | undefined): Promise<string | {
|
|
178
|
-
[x: string]:
|
|
245
|
+
[x: string]: any;
|
|
179
246
|
}>;
|
|
180
247
|
/**
|
|
181
248
|
* Validates the Exhort token.
|
|
@@ -184,6 +251,10 @@ declare function imageAnalysis(imageRefs: Array<string>, html?: boolean | undefi
|
|
|
184
251
|
* @throws {Error} if the backend request failed.
|
|
185
252
|
*/
|
|
186
253
|
declare function validateToken(opts?: Options): Promise<object>;
|
|
254
|
+
import { discoverMavenModules } from './providers/java_maven.js';
|
|
255
|
+
import { discoverGradleSubprojects } from './providers/java_gradle.js';
|
|
256
|
+
import { discoverGoWorkspaceModules } from './providers/golang_gomodules.js';
|
|
257
|
+
import { discoverUvWorkspaceMembers } from './providers/python_uv.js';
|
|
187
258
|
import { discoverWorkspacePackages } from './workspace.js';
|
|
188
259
|
import { discoverWorkspaceCrates } from './workspace.js';
|
|
189
260
|
import { validatePackageJson } from './workspace.js';
|
|
@@ -191,5 +262,5 @@ import { resolveWorkspaceDiscoveryIgnore } from './workspace.js';
|
|
|
191
262
|
import { filterManifestPathsByDiscoveryIgnore } from './workspace.js';
|
|
192
263
|
import { resolveContinueOnError } from './batch_opts.js';
|
|
193
264
|
import { resolveBatchMetadata } from './batch_opts.js';
|
|
194
|
-
export { discoverWorkspacePackages, discoverWorkspaceCrates, validatePackageJson, resolveWorkspaceDiscoveryIgnore, filterManifestPathsByDiscoveryIgnore, resolveContinueOnError, resolveBatchMetadata };
|
|
265
|
+
export { discoverMavenModules, discoverGradleSubprojects, discoverGoWorkspaceModules, discoverUvWorkspaceMembers, discoverWorkspacePackages, discoverWorkspaceCrates, validatePackageJson, resolveWorkspaceDiscoveryIgnore, filterManifestPathsByDiscoveryIgnore, resolveContinueOnError, resolveBatchMetadata };
|
|
195
266
|
export { getProjectLicense, findLicenseFilePath, identifyLicense, getLicenseDetails, licensesFromReport, normalizeLicensesResponse, runLicenseCheck, getCompatibility } from "./license/index.js";
|
package/dist/src/index.js
CHANGED
|
@@ -6,14 +6,18 @@ import analysis from './analysis.js';
|
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
import { getCustom } from "./tools.js";
|
|
8
8
|
import { resolveBatchMetadata, resolveContinueOnError } from './batch_opts.js';
|
|
9
|
+
import { discoverMavenModules } from './providers/java_maven.js';
|
|
10
|
+
import { discoverGradleSubprojects } from './providers/java_gradle.js';
|
|
11
|
+
import { discoverGoWorkspaceModules } from './providers/golang_gomodules.js';
|
|
12
|
+
import { discoverUvWorkspaceMembers } from './providers/python_uv.js';
|
|
9
13
|
import { discoverWorkspaceCrates, discoverWorkspacePackages, filterManifestPathsByDiscoveryIgnore, resolveWorkspaceDiscoveryIgnore, validatePackageJson, } from './workspace.js';
|
|
10
14
|
import.meta.dirname;
|
|
11
15
|
import * as url from 'url';
|
|
12
16
|
export { parseImageRef } from "./oci_image/utils.js";
|
|
13
17
|
export { ImageRef } from "./oci_image/images.js";
|
|
14
18
|
export { getProjectLicense, findLicenseFilePath, identifyLicense, getLicenseDetails, licensesFromReport, normalizeLicensesResponse, runLicenseCheck, getCompatibility } from "./license/index.js";
|
|
15
|
-
export default { componentAnalysis, stackAnalysis, stackAnalysisBatch, imageAnalysis, validateToken };
|
|
16
|
-
export { discoverWorkspacePackages, discoverWorkspaceCrates, validatePackageJson, resolveWorkspaceDiscoveryIgnore, filterManifestPathsByDiscoveryIgnore, resolveContinueOnError, resolveBatchMetadata, };
|
|
19
|
+
export default { componentAnalysis, stackAnalysis, stackAnalysisBatch, imageAnalysis, validateToken, generateSbom };
|
|
20
|
+
export { discoverMavenModules, discoverGradleSubprojects, discoverGoWorkspaceModules, discoverUvWorkspaceMembers, discoverWorkspacePackages, discoverWorkspaceCrates, validatePackageJson, resolveWorkspaceDiscoveryIgnore, filterManifestPathsByDiscoveryIgnore, resolveContinueOnError, resolveBatchMetadata, };
|
|
17
21
|
/**
|
|
18
22
|
* @typedef {{
|
|
19
23
|
* TRUSTIFY_DA_CARGO_PATH?: string | undefined,
|
|
@@ -56,13 +60,15 @@ export { discoverWorkspacePackages, discoverWorkspaceCrates, validatePackageJson
|
|
|
56
60
|
* TRUSTIFY_DA_CONTINUE_ON_ERROR?: string | undefined,
|
|
57
61
|
* batchMetadata?: boolean | undefined,
|
|
58
62
|
* TRUSTIFY_DA_BATCH_METADATA?: string | undefined,
|
|
63
|
+
* TRUSTIFY_DA_UV_PATH?: string | undefined,
|
|
64
|
+
* TRUSTIFY_DA_POETRY_PATH?: string | undefined,
|
|
59
65
|
* [key: string]: string | number | boolean | string[] | undefined,
|
|
60
66
|
* }} Options
|
|
61
67
|
*/
|
|
62
68
|
/**
|
|
63
69
|
* @typedef {{
|
|
64
70
|
* workspaceRoot: string,
|
|
65
|
-
* ecosystem: 'javascript' | 'cargo' | 'unknown',
|
|
71
|
+
* ecosystem: 'javascript' | 'cargo' | 'pyproject' | 'unknown',
|
|
66
72
|
* total: number,
|
|
67
73
|
* successful: number,
|
|
68
74
|
* failed: number,
|
|
@@ -169,7 +175,9 @@ async function componentAnalysis(manifest, opts = {}) {
|
|
|
169
175
|
fs.accessSync(manifest, fs.constants.R_OK);
|
|
170
176
|
opts["manifest-type"] = path.basename(manifest);
|
|
171
177
|
let provider = match(manifest, availableProviders, opts); // throws error if no matching provider
|
|
172
|
-
|
|
178
|
+
const result = await analysis.requestComponent(provider, manifest, theUrl, opts); // throws error request sending failed
|
|
179
|
+
result.packageManager = provider.packageManagerName();
|
|
180
|
+
return result;
|
|
173
181
|
}
|
|
174
182
|
/**
|
|
175
183
|
* @overload
|
|
@@ -235,6 +243,22 @@ function buildBatchAnalysisMetadata(root, ecosystem, totalSbomAttempts, successf
|
|
|
235
243
|
errors: [...errors],
|
|
236
244
|
};
|
|
237
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Generate a CycloneDX SBOM from a manifest file. No backend HTTP request is made.
|
|
248
|
+
*
|
|
249
|
+
* @param {string} manifestPath - path to the manifest file (e.g. pom.xml, package.json)
|
|
250
|
+
* @param {Options} [opts={}] - optional options (e.g. workspace dir, tool paths)
|
|
251
|
+
* @returns {Promise<object>} parsed CycloneDX SBOM JSON object
|
|
252
|
+
* @throws {Error} if the manifest is unsupported or SBOM generation fails
|
|
253
|
+
*/
|
|
254
|
+
export async function generateSbom(manifestPath, opts = {}) {
|
|
255
|
+
fs.accessSync(manifestPath, fs.constants.R_OK);
|
|
256
|
+
const result = await generateOneSbom(manifestPath, opts);
|
|
257
|
+
if (!result.ok) {
|
|
258
|
+
throw new Error(`Failed to generate SBOM for ${result.manifestPath}: ${result.reason}`);
|
|
259
|
+
}
|
|
260
|
+
return result.sbom;
|
|
261
|
+
}
|
|
238
262
|
/**
|
|
239
263
|
* @typedef {{ ok: true, purl: string, sbom: object } | { ok: false, manifestPath: string, reason: string }} SbomResult
|
|
240
264
|
*/
|
|
@@ -261,17 +285,45 @@ async function generateOneSbom(manifestPath, workspaceOpts) {
|
|
|
261
285
|
*
|
|
262
286
|
* @param {string} root - Resolved workspace root
|
|
263
287
|
* @param {Options} opts
|
|
264
|
-
* @returns {Promise<{ ecosystem: 'javascript' | 'cargo' | 'unknown', manifestPaths: string[] }>}
|
|
288
|
+
* @returns {Promise<{ ecosystem: 'javascript' | 'cargo' | 'maven' | 'gradle' | 'gomodules' | 'pyproject' | 'unknown', manifestPaths: string[] }>}
|
|
265
289
|
* @private
|
|
266
290
|
*/
|
|
267
291
|
async function detectWorkspaceManifests(root, opts) {
|
|
268
292
|
const cargoToml = path.join(root, 'Cargo.toml');
|
|
269
293
|
const cargoLock = path.join(root, 'Cargo.lock');
|
|
270
294
|
const packageJson = path.join(root, 'package.json');
|
|
295
|
+
const pomXml = path.join(root, 'pom.xml');
|
|
271
296
|
if (fs.existsSync(cargoToml) && fs.existsSync(cargoLock)) {
|
|
272
297
|
return { ecosystem: 'cargo', manifestPaths: await discoverWorkspaceCrates(root, opts) };
|
|
273
298
|
}
|
|
274
|
-
|
|
299
|
+
if (fs.existsSync(pomXml)) {
|
|
300
|
+
const manifestPaths = await discoverMavenModules(root, opts);
|
|
301
|
+
if (manifestPaths.length > 0) {
|
|
302
|
+
return { ecosystem: 'maven', manifestPaths };
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
const hasGradleSettings = fs.existsSync(path.join(root, 'settings.gradle'))
|
|
306
|
+
|| fs.existsSync(path.join(root, 'settings.gradle.kts'));
|
|
307
|
+
if (hasGradleSettings) {
|
|
308
|
+
const manifestPaths = await discoverGradleSubprojects(root, opts);
|
|
309
|
+
if (manifestPaths.length > 0) {
|
|
310
|
+
return { ecosystem: 'gradle', manifestPaths };
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (fs.existsSync(path.join(root, 'go.work'))) {
|
|
314
|
+
const manifestPaths = await discoverGoWorkspaceModules(root, opts);
|
|
315
|
+
if (manifestPaths.length > 0) {
|
|
316
|
+
return { ecosystem: 'gomodules', manifestPaths };
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (fs.existsSync(path.join(root, 'pyproject.toml')) && fs.existsSync(path.join(root, 'uv.lock'))) {
|
|
320
|
+
const manifestPaths = await discoverUvWorkspaceMembers(root, opts);
|
|
321
|
+
if (manifestPaths.length > 0) {
|
|
322
|
+
return { ecosystem: 'pyproject', manifestPaths };
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
const hasJsLock = fs.existsSync(path.join(root, 'bun.lock'))
|
|
326
|
+
|| fs.existsSync(path.join(root, 'pnpm-lock.yaml'))
|
|
275
327
|
|| fs.existsSync(path.join(root, 'yarn.lock'))
|
|
276
328
|
|| fs.existsSync(path.join(root, 'package-lock.json'));
|
|
277
329
|
if (fs.existsSync(packageJson) && hasJsLock) {
|
|
@@ -380,12 +432,45 @@ function batchError(message, wantMetadata, metadata) {
|
|
|
380
432
|
}
|
|
381
433
|
return err;
|
|
382
434
|
}
|
|
435
|
+
/**
|
|
436
|
+
* @overload
|
|
437
|
+
* @param {string} workspaceRoot
|
|
438
|
+
* @param {true} html
|
|
439
|
+
* @param {Options & { batchMetadata: true }} opts
|
|
440
|
+
* @returns {Promise<{ analysis: string, metadata: BatchAnalysisMetadata }>}
|
|
441
|
+
* @throws {Error}
|
|
442
|
+
*/
|
|
443
|
+
/**
|
|
444
|
+
* @overload
|
|
445
|
+
* @param {string} workspaceRoot
|
|
446
|
+
* @param {true} html
|
|
447
|
+
* @param {Options & { batchMetadata?: false }} [opts={}]
|
|
448
|
+
* @returns {Promise<string>}
|
|
449
|
+
* @throws {Error}
|
|
450
|
+
*/
|
|
451
|
+
/**
|
|
452
|
+
* @overload
|
|
453
|
+
* @param {string} workspaceRoot
|
|
454
|
+
* @param {false} html
|
|
455
|
+
* @param {Options & { batchMetadata: true }} opts
|
|
456
|
+
* @returns {Promise<{ analysis: Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>, metadata: BatchAnalysisMetadata }>}
|
|
457
|
+
* @throws {Error}
|
|
458
|
+
*/
|
|
459
|
+
/**
|
|
460
|
+
* @overload
|
|
461
|
+
* @param {string} workspaceRoot
|
|
462
|
+
* @param {false} html
|
|
463
|
+
* @param {Options & { batchMetadata?: false }} [opts={}]
|
|
464
|
+
* @returns {Promise<Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>>}
|
|
465
|
+
* @throws {Error}
|
|
466
|
+
*/
|
|
383
467
|
/**
|
|
384
468
|
* Get stack analysis for all workspace packages/crates (batch).
|
|
385
469
|
* Detects ecosystem from workspace root: Cargo (Cargo.toml + Cargo.lock) or JS/TS (package.json + lock file).
|
|
386
470
|
* SBOMs are generated in parallel (see `batchConcurrency`) unless `continueOnError: false` (fail-fast sequential).
|
|
387
471
|
* With `opts.batchMetadata` / `TRUSTIFY_DA_BATCH_METADATA`, returns `{ analysis, metadata }` including validation and SBOM errors.
|
|
388
472
|
*
|
|
473
|
+
* @overload
|
|
389
474
|
* @param {string} workspaceRoot - Path to workspace root (containing lock file and workspace config)
|
|
390
475
|
* @param {boolean} [html=false] - true returns HTML, false returns JSON report
|
|
391
476
|
* @param {Options} [opts={}] - `batchConcurrency`, discovery ignores, `continueOnError` (default true), `batchMetadata` (default false)
|
|
@@ -416,7 +501,7 @@ async function stackAnalysisBatch(workspaceRoot, html = false, opts = {}) {
|
|
|
416
501
|
}
|
|
417
502
|
}
|
|
418
503
|
if (manifestPaths.length === 0) {
|
|
419
|
-
throw new Error(`No workspace manifests found at ${root}. Ensure Cargo.toml+Cargo.lock or package.json+lock file
|
|
504
|
+
throw new Error(`No workspace manifests found at ${root}. Ensure a supported workspace root exists (Cargo.toml+Cargo.lock, pom.xml, build.gradle, go.work, pyproject.toml+uv.lock, or package.json+lock file).`);
|
|
420
505
|
}
|
|
421
506
|
const workspaceOpts = { ...opts, TRUSTIFY_DA_WORKSPACE_DIR: root };
|
|
422
507
|
const concurrency = resolveBatchConcurrency(opts);
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
* @param {import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport} [analysisResult] - analysis result that includes licenses array from backend
|
|
10
10
|
* @returns {Promise<{ projectLicense: { manifest: Object|null, file: Object|null, mismatch: boolean }, incompatibleDependencies: Array<{ purl: string, licenses: string[], category?: string, reason: string }>, error?: string }>}
|
|
11
11
|
*/
|
|
12
|
-
export function runLicenseCheck(sbomContent: string, manifestPath: string, url: string, opts?: import("../index.js").Options, analysisResult?:
|
|
12
|
+
export function runLicenseCheck(sbomContent: string, manifestPath: string, url: string, opts?: import("../index.js").Options, analysisResult?: any): Promise<{
|
|
13
13
|
projectLicense: {
|
|
14
|
-
manifest:
|
|
15
|
-
file:
|
|
14
|
+
manifest: Object | null;
|
|
15
|
+
file: Object | null;
|
|
16
16
|
mismatch: boolean;
|
|
17
17
|
};
|
|
18
18
|
incompatibleDependencies: Array<{
|
|
@@ -85,11 +85,14 @@ export async function runLicenseCheck(sbomContent, manifestPath, url, opts = {},
|
|
|
85
85
|
continue;
|
|
86
86
|
const status = getCompatibility(projectCategory, entry.category);
|
|
87
87
|
if (status === 'incompatible') {
|
|
88
|
+
const reason = entry.category?.toUpperCase() === 'UNKNOWN'
|
|
89
|
+
? 'License not recognized as a standard SPDX identifier. Manual review recommended to verify compatibility.'
|
|
90
|
+
: 'Dependency license(s) are incompatible with the project license.';
|
|
88
91
|
incompatibleDependencies.push({
|
|
89
92
|
purl,
|
|
90
93
|
licenses: entry.licenses,
|
|
91
94
|
category: entry.category,
|
|
92
|
-
reason
|
|
95
|
+
reason
|
|
93
96
|
});
|
|
94
97
|
}
|
|
95
98
|
}
|
|
@@ -114,9 +114,12 @@ export function getCompatibility(projectCategory, dependencyCategory) {
|
|
|
114
114
|
}
|
|
115
115
|
const proj = projectCategory.toUpperCase();
|
|
116
116
|
const dep = dependencyCategory.toUpperCase();
|
|
117
|
-
if (proj === 'UNKNOWN'
|
|
117
|
+
if (proj === 'UNKNOWN') {
|
|
118
118
|
return 'unknown';
|
|
119
119
|
}
|
|
120
|
+
if (dep === 'UNKNOWN') {
|
|
121
|
+
return 'incompatible';
|
|
122
|
+
}
|
|
120
123
|
const restrictiveness = {
|
|
121
124
|
'PERMISSIVE': 1,
|
|
122
125
|
'WEAK_COPYLEFT': 2,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @param {import('../index.js').Options} [opts={}] - options (proxy, token, TRUSTIFY_DA_BACKEND_URL, etc.)
|
|
7
7
|
* @returns {Promise<Object|null>} License details or null if not found
|
|
8
8
|
*/
|
|
9
|
-
export function getLicenseDetails(spdxId: string, opts?: import("../index.js").Options): Promise<
|
|
9
|
+
export function getLicenseDetails(spdxId: string, opts?: import("../index.js").Options): Promise<Object | null>;
|
|
10
10
|
/**
|
|
11
11
|
* Normalize the LicensesResponse shape (array of LicenseProviderResult) into a map of purl -> license info.
|
|
12
12
|
* Each provider result has { status, summary, packages } where packages is { [purl]: { concluded, evidence } }.
|
|
@@ -28,7 +28,7 @@ export function normalizeLicensesResponse(data: unknown, purls?: string[]): Map<
|
|
|
28
28
|
* @param {string[]} [purls] - optional list of purls to restrict to
|
|
29
29
|
* @returns {Map<string, { licenses: string[], category?: string }>}
|
|
30
30
|
*/
|
|
31
|
-
export function licensesFromReport(analysisReport:
|
|
31
|
+
export function licensesFromReport(analysisReport: any, purls?: string[]): Map<string, {
|
|
32
32
|
licenses: string[];
|
|
33
33
|
category?: string;
|
|
34
34
|
}>;
|
|
@@ -78,7 +78,7 @@ export class ImageRef {
|
|
|
78
78
|
* @param {string} [platform]
|
|
79
79
|
* @param {import("index.js").Options} [opts={}]
|
|
80
80
|
*/
|
|
81
|
-
constructor(image: string, platform?: string, opts?:
|
|
81
|
+
constructor(image: string, platform?: string, opts?: any);
|
|
82
82
|
/** @type {Image} */
|
|
83
83
|
image: Image;
|
|
84
84
|
/** @type {Platform} */
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @param {import("../index.js").Options} [opts={}] - optional various options to pass along the application
|
|
5
5
|
* @returns {{}}
|
|
6
6
|
*/
|
|
7
|
-
export function generateImageSBOM(imageRef:
|
|
7
|
+
export function generateImageSBOM(imageRef: any, opts?: import("../index.js").Options): {};
|
|
8
8
|
/**
|
|
9
9
|
*
|
|
10
10
|
* @param {string} image
|
|
@@ -25,7 +25,7 @@ export function getImagePlatform(opts?: import("../index.js").Options): Platform
|
|
|
25
25
|
* @returns {Object.<string, string>} - The image digests
|
|
26
26
|
* @throws {Error} If the image info is invalid
|
|
27
27
|
*/
|
|
28
|
-
export function getImageDigests(imageRef:
|
|
28
|
+
export function getImageDigests(imageRef: any, opts?: import("../index.js").Options): {
|
|
29
29
|
[x: string]: string;
|
|
30
30
|
};
|
|
31
31
|
export type SyftImageSource = {
|
|
@@ -34,9 +34,9 @@ export type SyftImageSource = {
|
|
|
34
34
|
getVariant: () => string;
|
|
35
35
|
};
|
|
36
36
|
export type SyftImageSourceType = {
|
|
37
|
-
getOs: (arg0:
|
|
38
|
-
getArch: (arg0:
|
|
39
|
-
getVariant: (arg0:
|
|
37
|
+
getOs: (arg0: Object) => string;
|
|
38
|
+
getArch: (arg0: Object) => string;
|
|
39
|
+
getVariant: (arg0: Object) => string;
|
|
40
40
|
};
|
|
41
41
|
import { ImageRef } from './images.js';
|
|
42
42
|
import { Platform } from './platform.js';
|
|
@@ -135,7 +135,7 @@ function execSyft(imageRef, opts = {}) {
|
|
|
135
135
|
function getSyftEnvs(dockerPath, podmanPath) {
|
|
136
136
|
let path = null;
|
|
137
137
|
if (dockerPath && podmanPath) {
|
|
138
|
-
path = `${dockerPath}${
|
|
138
|
+
path = `${dockerPath}${delimiter}${podmanPath}`;
|
|
139
139
|
}
|
|
140
140
|
else if (dockerPath) {
|
|
141
141
|
path = dockerPath;
|
|
@@ -276,7 +276,16 @@ function podmanGetVariant(opts = {}) {
|
|
|
276
276
|
* @returns {string} - The information
|
|
277
277
|
*/
|
|
278
278
|
function dockerPodmanInfo(dockerSupplier, podmanSupplier, opts = {}) {
|
|
279
|
-
|
|
279
|
+
try {
|
|
280
|
+
const result = dockerSupplier(opts);
|
|
281
|
+
if (result) {
|
|
282
|
+
return result;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
catch (_) {
|
|
286
|
+
// docker not available, fall through to podman
|
|
287
|
+
}
|
|
288
|
+
return podmanSupplier(opts);
|
|
280
289
|
}
|
|
281
290
|
/**
|
|
282
291
|
* Gets the digests for an image
|
package/dist/src/provider.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export function match(manifest: string, providers: [Provider], opts?: {
|
|
|
21
21
|
TRUSTIFY_DA_WORKSPACE_DIR?: string;
|
|
22
22
|
}): Provider;
|
|
23
23
|
/** @typedef {{ecosystem: string, contentType: string, content: string}} Provided */
|
|
24
|
-
/** @typedef {{isSupported: function(string): boolean, validateLockFile: function(string, Object): void, provideComponent: function(string, {}): Provided | Promise<Provided>, provideStack: function(string, {}): Provided | Promise<Provided>, readLicenseFromManifest: function(string): string | null}} Provider */
|
|
24
|
+
/** @typedef {{isSupported: function(string): boolean, validateLockFile: function(string, Object): void, provideComponent: function(string, {}): Provided | Promise<Provided>, provideStack: function(string, {}): Provided | Promise<Provided>, readLicenseFromManifest: function(string, Object=): string | null, packageManagerName: function(): string}} Provider */
|
|
25
25
|
/**
|
|
26
26
|
* MUST include all providers here.
|
|
27
27
|
* @type {[Provider]}
|
|
@@ -34,8 +34,9 @@ export type Provided = {
|
|
|
34
34
|
};
|
|
35
35
|
export type Provider = {
|
|
36
36
|
isSupported: (arg0: string) => boolean;
|
|
37
|
-
validateLockFile: (arg0: string, arg1:
|
|
37
|
+
validateLockFile: (arg0: string, arg1: Object) => void;
|
|
38
38
|
provideComponent: (arg0: string, arg1: {}) => Provided | Promise<Provided>;
|
|
39
39
|
provideStack: (arg0: string, arg1: {}) => Provided | Promise<Provided>;
|
|
40
|
-
readLicenseFromManifest: (arg0: string) => string | null;
|
|
40
|
+
readLicenseFromManifest: (arg0: string, arg1: Object | undefined) => string | null;
|
|
41
|
+
packageManagerName: () => string;
|
|
41
42
|
};
|
package/dist/src/provider.js
CHANGED
|
@@ -3,13 +3,17 @@ import golangGomodulesProvider from './providers/golang_gomodules.js';
|
|
|
3
3
|
import Java_gradle_groovy from "./providers/java_gradle_groovy.js";
|
|
4
4
|
import Java_gradle_kotlin from "./providers/java_gradle_kotlin.js";
|
|
5
5
|
import Java_maven from "./providers/java_maven.js";
|
|
6
|
+
import Javascript_bun from './providers/javascript_bun.js';
|
|
6
7
|
import Javascript_npm from './providers/javascript_npm.js';
|
|
7
8
|
import Javascript_pnpm from './providers/javascript_pnpm.js';
|
|
8
9
|
import Javascript_yarn from './providers/javascript_yarn.js';
|
|
9
10
|
import pythonPipProvider from './providers/python_pip.js';
|
|
11
|
+
import Python_pip_pyproject from './providers/python_pip_pyproject.js';
|
|
12
|
+
import Python_poetry from './providers/python_poetry.js';
|
|
13
|
+
import Python_uv from './providers/python_uv.js';
|
|
10
14
|
import rustCargoProvider from './providers/rust_cargo.js';
|
|
11
15
|
/** @typedef {{ecosystem: string, contentType: string, content: string}} Provided */
|
|
12
|
-
/** @typedef {{isSupported: function(string): boolean, validateLockFile: function(string, Object): void, provideComponent: function(string, {}): Provided | Promise<Provided>, provideStack: function(string, {}): Provided | Promise<Provided>, readLicenseFromManifest: function(string): string | null}} Provider */
|
|
16
|
+
/** @typedef {{isSupported: function(string): boolean, validateLockFile: function(string, Object): void, provideComponent: function(string, {}): Provided | Promise<Provided>, provideStack: function(string, {}): Provided | Promise<Provided>, readLicenseFromManifest: function(string, Object=): string | null, packageManagerName: function(): string}} Provider */
|
|
13
17
|
/**
|
|
14
18
|
* MUST include all providers here.
|
|
15
19
|
* @type {[Provider]}
|
|
@@ -18,11 +22,15 @@ export const availableProviders = [
|
|
|
18
22
|
new Java_maven(),
|
|
19
23
|
new Java_gradle_groovy(),
|
|
20
24
|
new Java_gradle_kotlin(),
|
|
25
|
+
new Javascript_bun(),
|
|
21
26
|
new Javascript_pnpm(),
|
|
22
27
|
new Javascript_yarn(),
|
|
23
28
|
new Javascript_npm(),
|
|
24
29
|
golangGomodulesProvider,
|
|
25
30
|
pythonPipProvider,
|
|
31
|
+
new Python_poetry(),
|
|
32
|
+
new Python_uv(),
|
|
33
|
+
new Python_pip_pyproject(),
|
|
26
34
|
rustCargoProvider
|
|
27
35
|
];
|
|
28
36
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ecosystem_maven =
|
|
1
|
+
export type ecosystem_maven = any;
|
|
2
2
|
/** @typedef {import('../provider').Provider} */
|
|
3
3
|
/** @typedef {import('../provider').Provided} Provided */
|
|
4
4
|
/** @typedef {{name: string, version: string}} Package */
|
|
@@ -20,6 +20,11 @@ export default class Base_Java {
|
|
|
20
20
|
CONFLICT_REGEX: RegExp;
|
|
21
21
|
globalBinary: string;
|
|
22
22
|
localWrapper: string;
|
|
23
|
+
/**
|
|
24
|
+
* Returns the package manager name (e.g. mvn, gradle)
|
|
25
|
+
* @returns {string}
|
|
26
|
+
*/
|
|
27
|
+
packageManagerName(): string;
|
|
23
28
|
/**
|
|
24
29
|
* Recursively populates the SBOM instance with the parsed graph
|
|
25
30
|
* @param {string} src - Source dependency to start the calculations from
|
|
@@ -28,6 +33,13 @@ export default class Base_Java {
|
|
|
28
33
|
* @param {Sbom} sbom - The SBOM where the dependencies are being added
|
|
29
34
|
*/
|
|
30
35
|
parseDependencyTree(src: string, srcDepth: number, lines: any[], sbom: Sbom): void;
|
|
36
|
+
/**
|
|
37
|
+
* Calculates how deep in the graph is the given line
|
|
38
|
+
* @param {string} line - line to calculate the depth from
|
|
39
|
+
* @returns {number} The calculated depth
|
|
40
|
+
* @protected
|
|
41
|
+
*/
|
|
42
|
+
protected _getDepth(line: string): number;
|
|
31
43
|
/**
|
|
32
44
|
* Create a PackageURL from any line in a Text Graph dependency tree for a manifest path.
|
|
33
45
|
* @param {string} line - line to parse from a dependencies.txt file
|
|
@@ -57,18 +69,8 @@ export default class Base_Java {
|
|
|
57
69
|
* @returns string
|
|
58
70
|
*/
|
|
59
71
|
selectToolBinary(manifestPath: string, opts: {}): string | null;
|
|
60
|
-
/**
|
|
61
|
-
*
|
|
62
|
-
* @param {string} startingManifest - the path of the manifest from which to start searching for the wrapper
|
|
63
|
-
* @param {string} repoRoot - the root of the repository at which point to stop searching for mvnw, derived via git if unset and then fallsback
|
|
64
|
-
* to the root of the drive the manifest is on (assumes absolute path is given)
|
|
65
|
-
* @returns {string|undefined}
|
|
66
|
-
*/
|
|
67
|
-
traverseForWrapper(startingManifest: string, repoRoot?: string): string | undefined;
|
|
68
|
-
normalizePath(thePath: any): string;
|
|
69
|
-
#private;
|
|
70
72
|
}
|
|
71
|
-
export type Provided =
|
|
73
|
+
export type Provided = any;
|
|
72
74
|
export type Package = {
|
|
73
75
|
name: string;
|
|
74
76
|
version: string;
|