@trustify-da/trustify-da-javascript-client 0.3.0-ea.608d6fa → 0.3.0-ea.61444d4

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 (85) hide show
  1. package/README.md +304 -13
  2. package/dist/package.json +31 -23
  3. package/dist/src/analysis.d.ts +28 -5
  4. package/dist/src/analysis.js +78 -13
  5. package/dist/src/batch_opts.d.ts +24 -0
  6. package/dist/src/batch_opts.js +35 -0
  7. package/dist/src/cli.js +276 -5
  8. package/dist/src/cyclone_dx_sbom.d.ts +14 -1
  9. package/dist/src/cyclone_dx_sbom.js +45 -9
  10. package/dist/src/index.d.ts +142 -7
  11. package/dist/src/index.js +355 -6
  12. package/dist/src/license/index.d.ts +3 -3
  13. package/dist/src/license/index.js +4 -1
  14. package/dist/src/license/license_utils.js +4 -1
  15. package/dist/src/license/licenses_api.d.ts +2 -2
  16. package/dist/src/oci_image/images.d.ts +1 -1
  17. package/dist/src/oci_image/images.js +15 -1
  18. package/dist/src/oci_image/utils.d.ts +5 -5
  19. package/dist/src/oci_image/utils.js +11 -2
  20. package/dist/src/provider.d.ts +8 -4
  21. package/dist/src/provider.js +16 -5
  22. package/dist/src/providers/base_java.d.ts +14 -12
  23. package/dist/src/providers/base_java.js +18 -44
  24. package/dist/src/providers/base_javascript.d.ts +37 -10
  25. package/dist/src/providers/base_javascript.js +108 -20
  26. package/dist/src/providers/base_pyproject.d.ts +158 -0
  27. package/dist/src/providers/base_pyproject.js +322 -0
  28. package/dist/src/providers/containerfile_parser.d.ts +5 -0
  29. package/dist/src/providers/containerfile_parser.js +20 -0
  30. package/dist/src/providers/golang_gomodules.d.ts +23 -13
  31. package/dist/src/providers/golang_gomodules.js +207 -120
  32. package/dist/src/providers/gomod_parser.d.ts +4 -0
  33. package/dist/src/providers/gomod_parser.js +16 -0
  34. package/dist/src/providers/java_gradle.d.ts +19 -0
  35. package/dist/src/providers/java_gradle.js +116 -2
  36. package/dist/src/providers/java_gradle_groovy.d.ts +1 -1
  37. package/dist/src/providers/java_gradle_kotlin.d.ts +1 -1
  38. package/dist/src/providers/java_maven.d.ts +10 -2
  39. package/dist/src/providers/java_maven.js +165 -1
  40. package/dist/src/providers/javascript_bun.d.ts +10 -0
  41. package/dist/src/providers/javascript_bun.js +100 -0
  42. package/dist/src/providers/javascript_npm.d.ts +6 -0
  43. package/dist/src/providers/javascript_npm.js +21 -0
  44. package/dist/src/providers/javascript_pnpm.d.ts +1 -1
  45. package/dist/src/providers/javascript_pnpm.js +8 -4
  46. package/dist/src/providers/manifest.d.ts +2 -0
  47. package/dist/src/providers/manifest.js +22 -4
  48. package/dist/src/providers/marker_evaluator.d.ts +14 -0
  49. package/dist/src/providers/marker_evaluator.js +191 -0
  50. package/dist/src/providers/oci_dockerfile.d.ts +51 -0
  51. package/dist/src/providers/oci_dockerfile.js +177 -0
  52. package/dist/src/providers/processors/yarn_berry_processor.d.ts +2 -2
  53. package/dist/src/providers/processors/yarn_berry_processor.js +88 -5
  54. package/dist/src/providers/processors/yarn_classic_processor.d.ts +2 -2
  55. package/dist/src/providers/python_controller.d.ts +5 -1
  56. package/dist/src/providers/python_controller.js +69 -8
  57. package/dist/src/providers/python_pip.d.ts +5 -0
  58. package/dist/src/providers/python_pip.js +6 -6
  59. package/dist/src/providers/python_pip_pyproject.d.ts +61 -0
  60. package/dist/src/providers/python_pip_pyproject.js +146 -0
  61. package/dist/src/providers/python_poetry.d.ts +98 -0
  62. package/dist/src/providers/python_poetry.js +286 -0
  63. package/dist/src/providers/python_uv.d.ts +46 -0
  64. package/dist/src/providers/python_uv.js +269 -0
  65. package/dist/src/providers/rust_cargo.d.ts +12 -3
  66. package/dist/src/providers/rust_cargo.js +115 -21
  67. package/dist/src/providers/tree-sitter-containerfile.wasm +0 -0
  68. package/dist/src/providers/tree-sitter-gomod.wasm +0 -0
  69. package/dist/src/remediate.d.ts +21 -0
  70. package/dist/src/remediate.js +149 -0
  71. package/dist/src/remediation.d.ts +57 -0
  72. package/dist/src/remediation.js +436 -0
  73. package/dist/src/remediation_report.d.ts +40 -0
  74. package/dist/src/remediation_report.js +159 -0
  75. package/dist/src/sbom.d.ts +14 -1
  76. package/dist/src/sbom.js +13 -2
  77. package/dist/src/tools.d.ts +28 -2
  78. package/dist/src/tools.js +58 -0
  79. package/dist/src/updaters/maven_updater.d.ts +26 -0
  80. package/dist/src/updaters/maven_updater.js +322 -0
  81. package/dist/src/updaters/toml_updater.d.ts +33 -0
  82. package/dist/src/updaters/toml_updater.js +244 -0
  83. package/dist/src/workspace.d.ts +70 -0
  84. package/dist/src/workspace.js +256 -0
  85. package/package.json +32 -24
@@ -6,10 +6,11 @@ import { PackageURL } from "packageurl-js";
6
6
  * @param type type of package - application or library
7
7
  * @param scope scope of the component - runtime or compile
8
8
  * @param licenses optional license string or array of licenses for the component
9
- * @return {{"bom-ref": string, name, purl: string, type, version, scope, licenses?}}
9
+ * @param hashes optional array of hash objects for the component, e.g. [{alg: "SHA-256", content: "..."}]
10
+ * @return {{"bom-ref": string, name, purl: string, type, version, scope, licenses?, hashes?}}
10
11
  * @private
11
12
  */
12
- function getComponent(component, type, scope, licenses) {
13
+ function getComponent(component, type, scope, licenses, hashes) {
13
14
  let componentObject;
14
15
  if (component instanceof PackageURL) {
15
16
  if (component.namespace) {
@@ -40,12 +41,24 @@ function getComponent(component, type, scope, licenses) {
40
41
  // Add licenses if provided (CycloneDX format). Callers must provide valid SPDX identifiers.
41
42
  if (licenses) {
42
43
  const licenseArray = Array.isArray(licenses) ? licenses : [licenses];
43
- componentObject.licenses = licenseArray.map(lic => {
44
+ const validLicenses = licenseArray
45
+ .map(lic => {
44
46
  if (typeof lic === 'string') {
45
47
  return { license: { id: lic } };
46
48
  }
47
- return lic;
48
- });
49
+ if (typeof lic === 'object' && lic !== null && ('license' in lic || 'expression' in lic)) {
50
+ return lic;
51
+ }
52
+ return null;
53
+ })
54
+ .filter(Boolean);
55
+ if (validLicenses.length > 0) {
56
+ componentObject.licenses = validLicenses;
57
+ }
58
+ }
59
+ // Add hashes if provided (CycloneDX 1.4 format).
60
+ if (hashes && hashes.length > 0) {
61
+ componentObject.hashes = hashes;
49
62
  }
50
63
  return componentObject;
51
64
  }
@@ -86,16 +99,24 @@ export default class CycloneDxSbom {
86
99
  * Adds a dependency relationship between two components in the SBOM
87
100
  * @param {PackageURL} sourceRef - The source component (parent)
88
101
  * @param {PackageURL} targetRef - The target component (dependency)
102
+ * @param {string} [scope] - Scope of the dependency
103
+ * @param {Array<{alg: string, content: string}>} [targetHashes] - Optional hashes for the target component
89
104
  * @return {CycloneDxSbom} The updated SBOM
90
105
  */
91
- addDependency(sourceRef, targetRef, scope) {
106
+ addDependency(sourceRef, targetRef, scope, targetHashes) {
92
107
  const sourcePurl = sourceRef.toString();
93
108
  const targetPurl = targetRef.toString();
94
109
  // Ensure both components exist in the components list
95
110
  [sourceRef, targetRef].forEach((ref, index) => {
96
111
  const purl = index === 0 ? sourcePurl : targetPurl;
97
- if (this.getComponentIndex(purl) < 0) {
98
- this.components.push(getComponent(ref, "library", scope));
112
+ const existingIndex = this.getComponentIndex(purl);
113
+ if (existingIndex < 0) {
114
+ const hashes = index === 1 ? targetHashes : undefined;
115
+ this.components.push(getComponent(ref, "library", scope, undefined, hashes));
116
+ }
117
+ else if (index === 1 && targetHashes && targetHashes.length > 0 && !this.components[existingIndex].hashes) {
118
+ // Update hashes if the component was first seen without them (e.g. as a source)
119
+ this.components[existingIndex].hashes = targetHashes;
99
120
  }
100
121
  });
101
122
  // Ensure source dependency exists
@@ -120,6 +141,7 @@ export default class CycloneDxSbom {
120
141
  getAsJsonString(opts) {
121
142
  let manifestType = opts["manifest-type"];
122
143
  this.setSourceManifest(opts["source-manifest"]);
144
+ const rootPurl = this.rootComponent?.purl;
123
145
  this.sbomObject = {
124
146
  "bomFormat": "CycloneDX",
125
147
  "specVersion": "1.4",
@@ -129,7 +151,7 @@ export default class CycloneDxSbom {
129
151
  "component": this.rootComponent,
130
152
  "properties": new Array()
131
153
  },
132
- "components": this.components,
154
+ "components": this.components.filter(c => c.purl !== rootPurl),
133
155
  "dependencies": this.dependencies
134
156
  };
135
157
  if (this.rootComponent === undefined) {
@@ -241,6 +263,20 @@ export default class CycloneDxSbom {
241
263
  return false;
242
264
  }
243
265
  }
266
+ /**
267
+ * Checks if any entry in the dependsOn list of sourceRef starts with the given purl prefix.
268
+ * @param {PackageURL} sourceRef - The source component
269
+ * @param {string} purlPrefix - The purl prefix to match (e.g. "pkg:npm/minimist@")
270
+ * @return {boolean}
271
+ */
272
+ checkDependsOnByPurlPrefix(sourceRef, purlPrefix) {
273
+ const sourcePurl = sourceRef.toString();
274
+ const depIndex = this.getDependencyIndex(sourcePurl);
275
+ if (depIndex < 0) {
276
+ return false;
277
+ }
278
+ return this.dependencies[depIndex].dependsOn.some(dep => dep.startsWith(purlPrefix));
279
+ }
244
280
  /** Removes the root component from the sbom
245
281
  */
246
282
  removeRootComponent() {
@@ -13,13 +13,25 @@ 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";
27
+ export { extractRemediations } from "./remediation.js";
18
28
  declare namespace _default {
19
29
  export { componentAnalysis };
20
30
  export { stackAnalysis };
31
+ export { stackAnalysisBatch };
21
32
  export { imageAnalysis };
22
33
  export { validateToken };
34
+ export { generateSbom };
23
35
  }
24
36
  export default _default;
25
37
  export type Options = {
@@ -42,18 +54,53 @@ export type Options = {
42
54
  TRUSTIFY_DA_PYTHON_PATH?: string | undefined;
43
55
  TRUSTIFY_DA_PYTHON_VIRTUAL_ENV?: string | undefined;
44
56
  TRUSTIFY_DA_PYTHON3_PATH?: string | undefined;
45
- TRUSTIFY_DA_RECOMMENDATIONS_ENABLED?: string | undefined;
57
+ TRUSTIFY_DA_PROVIDERS?: string | undefined;
58
+ TRUSTIFY_DA_RECOMMEND?: string | undefined;
59
+ TRUSTIFY_DA_SOURCES?: string | undefined;
46
60
  TRUSTIFY_DA_SKOPEO_CONFIG_PATH?: string | undefined;
47
61
  TRUSTIFY_DA_SKOPEO_PATH?: string | undefined;
48
62
  TRUSTIFY_DA_SYFT_CONFIG_PATH?: string | undefined;
49
63
  TRUSTIFY_DA_SYFT_PATH?: string | undefined;
50
64
  TRUSTIFY_DA_YARN_PATH?: string | undefined;
65
+ TRUSTIFY_DA_WORKSPACE_DIR?: string | undefined;
51
66
  TRUSTIFY_DA_LICENSE_CHECK?: string | undefined;
52
67
  MATCH_MANIFEST_VERSIONS?: string | undefined;
53
68
  TRUSTIFY_DA_SOURCE?: string | undefined;
54
69
  TRUSTIFY_DA_TOKEN?: string | undefined;
55
70
  TRUSTIFY_DA_TELEMETRY_ID?: string | undefined;
56
- [key: string]: string | undefined;
71
+ TRUSTIFY_DA_WORKSPACE_DIR?: string | undefined;
72
+ batchConcurrency?: number | undefined;
73
+ TRUSTIFY_DA_BATCH_CONCURRENCY?: string | undefined;
74
+ workspaceDiscoveryIgnore?: string[] | undefined;
75
+ TRUSTIFY_DA_WORKSPACE_DISCOVERY_IGNORE?: string | undefined;
76
+ continueOnError?: boolean | undefined;
77
+ TRUSTIFY_DA_CONTINUE_ON_ERROR?: string | undefined;
78
+ batchMetadata?: boolean | undefined;
79
+ TRUSTIFY_DA_BATCH_METADATA?: string | undefined;
80
+ TRUSTIFY_DA_UV_PATH?: string | undefined;
81
+ TRUSTIFY_DA_POETRY_PATH?: string | undefined;
82
+ [key: string]: string | number | boolean | string[] | undefined;
83
+ };
84
+ export type BatchAnalysisMetadata = {
85
+ workspaceRoot: string;
86
+ ecosystem: "javascript" | "cargo" | "pyproject" | "unknown";
87
+ total: number;
88
+ successful: number;
89
+ failed: number;
90
+ errors: Array<{
91
+ manifestPath: string;
92
+ phase: "validation" | "sbom";
93
+ reason: string;
94
+ }>;
95
+ };
96
+ export type SbomResult = {
97
+ ok: true;
98
+ purl: string;
99
+ sbom: object;
100
+ } | {
101
+ ok: false;
102
+ manifestPath: string;
103
+ reason: string;
57
104
  };
58
105
  /**
59
106
  * Get component analysis report for a manifest content.
@@ -62,7 +109,7 @@ export type Options = {
62
109
  * @returns {Promise<import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>}
63
110
  * @throws {Error} if no matching provider, failed to get create content, or backend request failed
64
111
  */
65
- declare function componentAnalysis(manifest: string, opts?: Options): Promise<import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport>;
112
+ declare function componentAnalysis(manifest: string, opts?: Options): Promise<any>;
66
113
  /**
67
114
  * @overload
68
115
  * @param {string} manifest
@@ -80,7 +127,7 @@ declare function stackAnalysis(manifest: string, html: true, opts?: Options | un
80
127
  * @returns {Promise<import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>}
81
128
  * @throws {Error}
82
129
  */
83
- declare function stackAnalysis(manifest: string, html: false, opts?: Options | undefined): Promise<import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport>;
130
+ declare function stackAnalysis(manifest: string, html: false, opts?: Options | undefined): Promise<any>;
84
131
  /**
85
132
  * Get stack analysis report for a manifest file.
86
133
  * @overload
@@ -91,7 +138,82 @@ declare function stackAnalysis(manifest: string, html: false, opts?: Options | u
91
138
  * @throws {Error} if manifest inaccessible, no matching provider, failed to get create content,
92
139
  * or backend request failed
93
140
  */
94
- declare function stackAnalysis(manifest: string, html?: boolean | undefined, opts?: Options | undefined): Promise<string | import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport>;
141
+ declare function stackAnalysis(manifest: string, html?: boolean | undefined, opts?: Options | undefined): Promise<string | any>;
142
+ /**
143
+ * @overload
144
+ * @param {string} workspaceRoot
145
+ * @param {true} html
146
+ * @param {Options & { batchMetadata: true }} opts
147
+ * @returns {Promise<{ analysis: string, metadata: BatchAnalysisMetadata }>}
148
+ * @throws {Error}
149
+ */
150
+ declare function stackAnalysisBatch(workspaceRoot: string, html: true, opts: Options & {
151
+ batchMetadata: true;
152
+ }): Promise<{
153
+ analysis: string;
154
+ metadata: BatchAnalysisMetadata;
155
+ }>;
156
+ /**
157
+ * @overload
158
+ * @param {string} workspaceRoot
159
+ * @param {true} html
160
+ * @param {Options & { batchMetadata?: false }} [opts={}]
161
+ * @returns {Promise<string>}
162
+ * @throws {Error}
163
+ */
164
+ declare function stackAnalysisBatch(workspaceRoot: string, html: true, opts?: (Options & {
165
+ batchMetadata?: false;
166
+ }) | undefined): Promise<string>;
167
+ /**
168
+ * @overload
169
+ * @param {string} workspaceRoot
170
+ * @param {false} html
171
+ * @param {Options & { batchMetadata: true }} opts
172
+ * @returns {Promise<{ analysis: Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>, metadata: BatchAnalysisMetadata }>}
173
+ * @throws {Error}
174
+ */
175
+ declare function stackAnalysisBatch(workspaceRoot: string, html: false, opts: Options & {
176
+ batchMetadata: true;
177
+ }): Promise<{
178
+ analysis: {
179
+ [x: string]: any;
180
+ };
181
+ metadata: BatchAnalysisMetadata;
182
+ }>;
183
+ /**
184
+ * @overload
185
+ * @param {string} workspaceRoot
186
+ * @param {false} html
187
+ * @param {Options & { batchMetadata?: false }} [opts={}]
188
+ * @returns {Promise<Object.<string, import('@trustify-da/trustify-da-api-model/model/v5/AnalysisReport').AnalysisReport>>}
189
+ * @throws {Error}
190
+ */
191
+ declare function stackAnalysisBatch(workspaceRoot: string, html: false, opts?: (Options & {
192
+ batchMetadata?: false;
193
+ }) | undefined): Promise<{
194
+ [x: string]: any;
195
+ }>;
196
+ /**
197
+ * Get stack analysis for all workspace packages/crates (batch).
198
+ * Detects ecosystem from workspace root: Cargo (Cargo.toml + Cargo.lock) or JS/TS (package.json + lock file).
199
+ * SBOMs are generated in parallel (see `batchConcurrency`) unless `continueOnError: false` (fail-fast sequential).
200
+ * With `opts.batchMetadata` / `TRUSTIFY_DA_BATCH_METADATA`, returns `{ analysis, metadata }` including validation and SBOM errors.
201
+ *
202
+ * @overload
203
+ * @param {string} workspaceRoot - Path to workspace root (containing lock file and workspace config)
204
+ * @param {boolean} [html=false] - true returns HTML, false returns JSON report
205
+ * @param {Options} [opts={}] - `batchConcurrency`, discovery ignores, `continueOnError` (default true), `batchMetadata` (default false)
206
+ * @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 }>}
207
+ * @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.
208
+ */
209
+ declare function stackAnalysisBatch(workspaceRoot: string, html?: boolean | undefined, opts?: Options | undefined): Promise<string | {
210
+ [x: string]: any;
211
+ } | {
212
+ analysis: string | {
213
+ [x: string]: any;
214
+ };
215
+ metadata: BatchAnalysisMetadata;
216
+ }>;
95
217
  /**
96
218
  * @overload
97
219
  * @param {Array<string>} imageRefs
@@ -110,7 +232,7 @@ declare function imageAnalysis(imageRefs: Array<string>, html: true, opts?: Opti
110
232
  * @throws {Error}
111
233
  */
112
234
  declare function imageAnalysis(imageRefs: Array<string>, html: false, opts?: Options | undefined): Promise<{
113
- [x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
235
+ [x: string]: any;
114
236
  }>;
115
237
  /**
116
238
  * Get image analysis report for a set of OCI image references.
@@ -123,7 +245,7 @@ declare function imageAnalysis(imageRefs: Array<string>, html: false, opts?: Opt
123
245
  * or backend request failed
124
246
  */
125
247
  declare function imageAnalysis(imageRefs: Array<string>, html?: boolean | undefined, opts?: Options | undefined): Promise<string | {
126
- [x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
248
+ [x: string]: any;
127
249
  }>;
128
250
  /**
129
251
  * Validates the Exhort token.
@@ -132,4 +254,17 @@ declare function imageAnalysis(imageRefs: Array<string>, html?: boolean | undefi
132
254
  * @throws {Error} if the backend request failed.
133
255
  */
134
256
  declare function validateToken(opts?: Options): Promise<object>;
257
+ import { discoverMavenModules } from './providers/java_maven.js';
258
+ import { discoverGradleSubprojects } from './providers/java_gradle.js';
259
+ import { discoverGoWorkspaceModules } from './providers/golang_gomodules.js';
260
+ import { discoverUvWorkspaceMembers } from './providers/python_uv.js';
261
+ import { discoverWorkspacePackages } from './workspace.js';
262
+ import { discoverWorkspaceCrates } from './workspace.js';
263
+ import { validatePackageJson } from './workspace.js';
264
+ import { resolveWorkspaceDiscoveryIgnore } from './workspace.js';
265
+ import { filterManifestPathsByDiscoveryIgnore } from './workspace.js';
266
+ import { resolveContinueOnError } from './batch_opts.js';
267
+ import { resolveBatchMetadata } from './batch_opts.js';
268
+ export { discoverMavenModules, discoverGradleSubprojects, discoverGoWorkspaceModules, discoverUvWorkspaceMembers, discoverWorkspacePackages, discoverWorkspaceCrates, validatePackageJson, resolveWorkspaceDiscoveryIgnore, filterManifestPathsByDiscoveryIgnore, resolveContinueOnError, resolveBatchMetadata };
135
269
  export { getProjectLicense, findLicenseFilePath, identifyLicense, getLicenseDetails, licensesFromReport, normalizeLicensesResponse, runLicenseCheck, getCompatibility } from "./license/index.js";
270
+ export { generateReport, generateDeduplicationKey } from "./remediation_report.js";