@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.
Files changed (66) hide show
  1. package/README.md +73 -8
  2. package/dist/package.json +24 -24
  3. package/dist/src/analysis.d.ts +7 -7
  4. package/dist/src/analysis.js +3 -2
  5. package/dist/src/cli.js +51 -2
  6. package/dist/src/cyclone_dx_sbom.d.ts +14 -1
  7. package/dist/src/cyclone_dx_sbom.js +43 -8
  8. package/dist/src/index.d.ts +81 -10
  9. package/dist/src/index.js +92 -7
  10. package/dist/src/license/index.d.ts +3 -3
  11. package/dist/src/license/index.js +4 -1
  12. package/dist/src/license/license_utils.js +4 -1
  13. package/dist/src/license/licenses_api.d.ts +2 -2
  14. package/dist/src/oci_image/images.d.ts +1 -1
  15. package/dist/src/oci_image/utils.d.ts +5 -5
  16. package/dist/src/oci_image/utils.js +11 -2
  17. package/dist/src/provider.d.ts +4 -3
  18. package/dist/src/provider.js +9 -1
  19. package/dist/src/providers/base_java.d.ts +14 -12
  20. package/dist/src/providers/base_java.js +18 -44
  21. package/dist/src/providers/base_javascript.d.ts +20 -9
  22. package/dist/src/providers/base_javascript.js +44 -6
  23. package/dist/src/providers/base_pyproject.d.ts +158 -0
  24. package/dist/src/providers/base_pyproject.js +322 -0
  25. package/dist/src/providers/golang_gomodules.d.ts +23 -13
  26. package/dist/src/providers/golang_gomodules.js +165 -119
  27. package/dist/src/providers/gomod_parser.d.ts +4 -0
  28. package/dist/src/providers/gomod_parser.js +16 -0
  29. package/dist/src/providers/java_gradle.d.ts +19 -0
  30. package/dist/src/providers/java_gradle.js +116 -2
  31. package/dist/src/providers/java_gradle_groovy.d.ts +1 -1
  32. package/dist/src/providers/java_gradle_kotlin.d.ts +1 -1
  33. package/dist/src/providers/java_maven.d.ts +10 -2
  34. package/dist/src/providers/java_maven.js +165 -1
  35. package/dist/src/providers/javascript_bun.d.ts +10 -0
  36. package/dist/src/providers/javascript_bun.js +100 -0
  37. package/dist/src/providers/javascript_npm.d.ts +6 -0
  38. package/dist/src/providers/javascript_npm.js +21 -0
  39. package/dist/src/providers/javascript_pnpm.js +6 -2
  40. package/dist/src/providers/manifest.d.ts +2 -0
  41. package/dist/src/providers/manifest.js +22 -4
  42. package/dist/src/providers/marker_evaluator.d.ts +14 -0
  43. package/dist/src/providers/marker_evaluator.js +191 -0
  44. package/dist/src/providers/processors/yarn_berry_processor.d.ts +2 -2
  45. package/dist/src/providers/processors/yarn_berry_processor.js +88 -5
  46. package/dist/src/providers/processors/yarn_classic_processor.d.ts +2 -2
  47. package/dist/src/providers/python_controller.d.ts +5 -1
  48. package/dist/src/providers/python_controller.js +65 -7
  49. package/dist/src/providers/python_pip.d.ts +5 -0
  50. package/dist/src/providers/python_pip.js +6 -6
  51. package/dist/src/providers/python_pip_pyproject.d.ts +61 -0
  52. package/dist/src/providers/python_pip_pyproject.js +146 -0
  53. package/dist/src/providers/python_poetry.d.ts +98 -0
  54. package/dist/src/providers/python_poetry.js +286 -0
  55. package/dist/src/providers/python_uv.d.ts +46 -0
  56. package/dist/src/providers/python_uv.js +269 -0
  57. package/dist/src/providers/rust_cargo.d.ts +6 -2
  58. package/dist/src/providers/rust_cargo.js +31 -4
  59. package/dist/src/providers/tree-sitter-gomod.wasm +0 -0
  60. package/dist/src/sbom.d.ts +14 -1
  61. package/dist/src/sbom.js +13 -2
  62. package/dist/src/tools.d.ts +28 -2
  63. package/dist/src/tools.js +58 -0
  64. package/dist/src/workspace.d.ts +9 -0
  65. package/dist/src/workspace.js +1 -1
  66. package/package.json +25 -25
@@ -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<import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport>;
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<import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport>;
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 | 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 | 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]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
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]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
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]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
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]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
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
- return await analysis.requestComponent(provider, manifest, theUrl, opts); // throws error request sending failed
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
- const hasJsLock = fs.existsSync(path.join(root, 'pnpm-lock.yaml'))
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 exist.`);
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?: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport): Promise<{
12
+ export function runLicenseCheck(sbomContent: string, manifestPath: string, url: string, opts?: import("../index.js").Options, analysisResult?: any): Promise<{
13
13
  projectLicense: {
14
- manifest: any | null;
15
- file: any | null;
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: 'Dependency license(s) are incompatible with the project license.'
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' || dep === '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<any | null>;
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: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport, purls?: string[]): Map<string, {
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?: import("index.js").Options);
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: import("./images").ImageRef, opts?: import("../index.js").Options): {};
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: import("./images").ImageRef, opts?: import("../index.js").Options): {
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: any) => string;
38
- getArch: (arg0: any) => string;
39
- getVariant: (arg0: any) => string;
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}${File.pathSeparator}${podmanPath}`;
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
- return dockerSupplier(opts) || podmanSupplier(opts);
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
@@ -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: any) => void;
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
  };
@@ -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 = import("../provider").Provider;
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 = import("../provider").Provided;
73
+ export type Provided = any;
72
74
  export type Package = {
73
75
  name: string;
74
76
  version: string;