@trustify-da/trustify-da-javascript-client 0.3.0-ea.d71f957 → 0.3.0-ea.d8ec262
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 +56 -2
- package/dist/package.json +2 -2
- package/dist/src/analysis.js +3 -2
- package/dist/src/cli.js +51 -2
- package/dist/src/cyclone_dx_sbom.d.ts +7 -1
- package/dist/src/cyclone_dx_sbom.js +29 -8
- package/dist/src/index.d.ts +74 -3
- package/dist/src/index.js +92 -7
- package/dist/src/oci_image/utils.js +11 -2
- package/dist/src/provider.d.ts +3 -2
- package/dist/src/provider.js +9 -1
- package/dist/src/providers/base_java.d.ts +12 -10
- package/dist/src/providers/base_java.js +18 -44
- package/dist/src/providers/base_javascript.d.ts +11 -0
- package/dist/src/providers/base_javascript.js +10 -3
- 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 +10 -0
- package/dist/src/providers/golang_gomodules.js +65 -8
- package/dist/src/providers/java_gradle.d.ts +19 -0
- package/dist/src/providers/java_gradle.js +116 -2
- package/dist/src/providers/java_maven.d.ts +8 -0
- 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 +1 -0
- package/dist/src/providers/javascript_npm.js +21 -0
- package/dist/src/providers/javascript_pnpm.js +6 -2
- 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.js +6 -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 +5 -5
- 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 +97 -0
- package/dist/src/providers/python_poetry.js +271 -0
- package/dist/src/providers/python_uv.d.ts +55 -0
- package/dist/src/providers/python_uv.js +227 -0
- package/dist/src/providers/rust_cargo.d.ts +5 -1
- package/dist/src/providers/rust_cargo.js +31 -4
- package/dist/src/sbom.d.ts +7 -1
- package/dist/src/sbom.js +4 -2
- package/dist/src/tools.d.ts +26 -0
- 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 +3 -3
package/README.md
CHANGED
|
@@ -224,7 +224,8 @@ $ trustify-da-javascript-client license /path/to/package.json
|
|
|
224
224
|
<li><a href="https://www.javascript.com/">JavaScript</a> - <a href="https://pnpm.io/">pnpm</a></li>
|
|
225
225
|
<li><a href="https://www.javascript.com/">JavaScript</a> - <a href="https://classic.yarnpkg.com/">Yarn Classic</a> / <a href="https://yarnpkg.com/">Yarn Berry</a></li>
|
|
226
226
|
<li><a href="https://go.dev/">Golang</a> - <a href="https://go.dev/blog/using-go-modules/">Go Modules</a></li>
|
|
227
|
-
<li><a href="https://www.python.org/">Python</a> - <a href="https://pypi.org/project/pip/">pip Installer</a
|
|
227
|
+
<li><a href="https://www.python.org/">Python</a> - <a href="https://pypi.org/project/pip/">pip Installer</a> (<code>requirements.txt</code>)</li>
|
|
228
|
+
<li><a href="https://www.python.org/">Python</a> - <a href="https://python-poetry.org/">Poetry</a> / <a href="https://docs.astral.sh/uv/">uv</a> (<code>pyproject.toml</code>)</li>
|
|
228
229
|
<li><a href="https://gradle.org/">Gradle (Groovy and Kotlin DSL)</a> - <a href="https://gradle.org/install/">Gradle Installation</a></li>
|
|
229
230
|
<li><a href="https://www.rust-lang.org/">Rust</a> - <a href="https://doc.rust-lang.org/cargo/">Cargo</a></li>
|
|
230
231
|
</ul>
|
|
@@ -391,7 +392,30 @@ version = "1.10"
|
|
|
391
392
|
log = "0.4" # trustify-da-ignore
|
|
392
393
|
```
|
|
393
394
|
|
|
394
|
-
|
|
395
|
+
|
|
396
|
+
<em>Python pyproject.toml</em> users can add a comment with <code>#exhortignore</code> (or <code># trustify-da-ignore</code>) next to the dependency in <code>pyproject.toml</code>.
|
|
397
|
+
|
|
398
|
+
PEP 621 style (<code>[project]</code> dependencies):
|
|
399
|
+
```toml
|
|
400
|
+
[project]
|
|
401
|
+
dependencies = [
|
|
402
|
+
"flask>=2.0.3",
|
|
403
|
+
"requests>=2.25.1",
|
|
404
|
+
"uvicorn>=0.17.0", #exhortignore
|
|
405
|
+
"click>=8.0.4", # trustify-da-ignore
|
|
406
|
+
]
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Poetry style (<code>[tool.poetry.dependencies]</code>):
|
|
410
|
+
```toml
|
|
411
|
+
[tool.poetry.dependencies]
|
|
412
|
+
flask = "^2.0.3"
|
|
413
|
+
requests = "^2.25.1"
|
|
414
|
+
uvicorn = "^0.17.0" #exhortignore
|
|
415
|
+
click = "^8.0.4" # trustify-da-ignore
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
All of the above examples are valid for marking a package to be ignored
|
|
395
419
|
</li>
|
|
396
420
|
</ul>
|
|
397
421
|
|
|
@@ -421,6 +445,8 @@ let options = {
|
|
|
421
445
|
'TRUSTIFY_DA_PIP3_PATH' : '/path/to/pip3',
|
|
422
446
|
'TRUSTIFY_DA_PYTHON_PATH' : '/path/to/python',
|
|
423
447
|
'TRUSTIFY_DA_PIP_PATH' : '/path/to/pip',
|
|
448
|
+
'TRUSTIFY_DA_UV_PATH' : '/path/to/uv',
|
|
449
|
+
'TRUSTIFY_DA_POETRY_PATH' : '/path/to/poetry',
|
|
424
450
|
'TRUSTIFY_DA_GRADLE_PATH' : '/path/to/gradle',
|
|
425
451
|
'TRUSTIFY_DA_CARGO_PATH' : '/path/to/cargo',
|
|
426
452
|
// Workspace root for monorepos (Cargo, npm/pnpm/yarn); lock file expected here
|
|
@@ -567,6 +593,16 @@ following keys for setting custom paths for the said executables.
|
|
|
567
593
|
<td>TRUSTIFY_DA_CARGO_PATH</td>
|
|
568
594
|
</tr>
|
|
569
595
|
<tr>
|
|
596
|
+
<td><a href="https://docs.astral.sh/uv/">uv</a></td>
|
|
597
|
+
<td><em>uv</em></td>
|
|
598
|
+
<td>TRUSTIFY_DA_UV_PATH</td>
|
|
599
|
+
</tr>
|
|
600
|
+
<tr>
|
|
601
|
+
<td><a href="https://python-poetry.org/">Poetry</a></td>
|
|
602
|
+
<td><em>poetry</em></td>
|
|
603
|
+
<td>TRUSTIFY_DA_POETRY_PATH</td>
|
|
604
|
+
</tr>
|
|
605
|
+
<tr>
|
|
570
606
|
<td>Workspace root (monorepos)</td>
|
|
571
607
|
<td>—</td>
|
|
572
608
|
<td>workspaceDir / TRUSTIFY_DA_WORKSPACE_DIR</td>
|
|
@@ -619,6 +655,24 @@ TRUSTIFY_DA_GO_MVS_LOGIC_ENABLED=false
|
|
|
619
655
|
|
|
620
656
|
#### Python Support
|
|
621
657
|
|
|
658
|
+
The client supports two Python manifest formats:
|
|
659
|
+
|
|
660
|
+
- **`requirements.txt`** — uses pip/pip3 to resolve dependencies
|
|
661
|
+
- **`pyproject.toml`** — uses [uv](https://docs.astral.sh/uv/) or [Poetry](https://python-poetry.org/) to resolve dependencies
|
|
662
|
+
|
|
663
|
+
##### pyproject.toml
|
|
664
|
+
|
|
665
|
+
For `pyproject.toml` projects, the client detects which tool manages the project by checking for lock files:
|
|
666
|
+
- If `poetry.lock` is present and `[tool.poetry]` is defined, **Poetry** is used (`poetry show --tree` and `poetry show --all`)
|
|
667
|
+
- If `uv.lock` is present, **uv** is used (`uv export --format requirements.txt --frozen --no-hashes`)
|
|
668
|
+
- If neither lock file is found, an error is thrown
|
|
669
|
+
|
|
670
|
+
Both PEP 621 (`[project]` dependencies) and Poetry-style (`[tool.poetry.dependencies]`) are supported.
|
|
671
|
+
|
|
672
|
+
Custom executable paths can be set via `TRUSTIFY_DA_UV_PATH` and `TRUSTIFY_DA_POETRY_PATH`.
|
|
673
|
+
|
|
674
|
+
##### requirements.txt
|
|
675
|
+
|
|
622
676
|
By default, For python support, the api assumes that the package is installed using the pip/pip3 binary on the system PATH, or using the customized
|
|
623
677
|
Binaries passed to environment variables. In any case, If the package is not installed , then an error will be thrown.
|
|
624
678
|
|
package/dist/package.json
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"lint": "eslint src test --ext js",
|
|
39
39
|
"lint:fix": "eslint src test --ext js --fix",
|
|
40
40
|
"test": "c8 npm run tests",
|
|
41
|
-
"tests": "mocha --config .mocharc.json
|
|
41
|
+
"tests": "mocha --config .mocharc.json",
|
|
42
42
|
"tests:rep": "mocha --reporter-option maxDiffSize=0 --reporter json > unit-tests-result.json",
|
|
43
43
|
"pretest": "cp node_modules/tree-sitter-requirements/tree-sitter-requirements.wasm src/providers/tree-sitter-requirements.wasm && cp node_modules/tree-sitter-gomod/tree-sitter-gomod.wasm src/providers/tree-sitter-gomod.wasm",
|
|
44
44
|
"precompile": "rm -rf dist",
|
|
@@ -51,11 +51,11 @@
|
|
|
51
51
|
"@cyclonedx/cyclonedx-library": "^6.13.0",
|
|
52
52
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
53
53
|
"fast-glob": "^3.3.3",
|
|
54
|
-
"fast-toml": "^0.5.4",
|
|
55
54
|
"fast-xml-parser": "^5.3.4",
|
|
56
55
|
"help": "^3.0.2",
|
|
57
56
|
"https-proxy-agent": "^7.0.6",
|
|
58
57
|
"js-yaml": "^4.1.1",
|
|
58
|
+
"jsonc-parser": "^3.3.1",
|
|
59
59
|
"micromatch": "^4.0.8",
|
|
60
60
|
"node-fetch": "^3.3.2",
|
|
61
61
|
"p-limit": "^4.0.0",
|
package/dist/src/analysis.js
CHANGED
|
@@ -189,7 +189,7 @@ async function requestImages(imageRefs, url, html = false, opts = {}) {
|
|
|
189
189
|
if (opts['TRUSTIFY_DA_RECOMMENDATIONS_ENABLED'] === 'false') {
|
|
190
190
|
finalUrl.searchParams.append('recommend', 'false');
|
|
191
191
|
}
|
|
192
|
-
const
|
|
192
|
+
const fetchOptions = addProxyAgent({
|
|
193
193
|
method: 'POST',
|
|
194
194
|
headers: {
|
|
195
195
|
'Accept': html ? 'text/html' : 'application/json',
|
|
@@ -197,7 +197,8 @@ async function requestImages(imageRefs, url, html = false, opts = {}) {
|
|
|
197
197
|
...getTokenHeaders(opts)
|
|
198
198
|
},
|
|
199
199
|
body: JSON.stringify(imageSboms),
|
|
200
|
-
});
|
|
200
|
+
}, opts);
|
|
201
|
+
const resp = await fetch(finalUrl, fetchOptions);
|
|
201
202
|
if (resp.status === 200) {
|
|
202
203
|
let result;
|
|
203
204
|
if (!html) {
|
package/dist/src/cli.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
2
3
|
import * as path from "path";
|
|
3
4
|
import yargs from 'yargs';
|
|
4
5
|
import { hideBin } from 'yargs/helpers';
|
|
5
6
|
import { getProjectLicense, getLicenseDetails } from './license/index.js';
|
|
6
|
-
import client, { selectTrustifyDABackend } from './index.js';
|
|
7
|
+
import client, { selectTrustifyDABackend, generateSbom } from './index.js';
|
|
7
8
|
// command for component analysis take manifest type and content
|
|
8
9
|
const component = {
|
|
9
10
|
command: 'component </path/to/manifest>',
|
|
@@ -325,15 +326,63 @@ const license = {
|
|
|
325
326
|
console.log(JSON.stringify(output, null, 2));
|
|
326
327
|
}
|
|
327
328
|
};
|
|
329
|
+
const sbom = {
|
|
330
|
+
command: 'sbom </path/to/manifest> [--output]',
|
|
331
|
+
desc: 'generate a CycloneDX SBOM from a manifest file',
|
|
332
|
+
builder: yargs => yargs.positional('/path/to/manifest', {
|
|
333
|
+
desc: 'manifest path for SBOM generation',
|
|
334
|
+
type: 'string',
|
|
335
|
+
normalize: true,
|
|
336
|
+
}).options({
|
|
337
|
+
output: {
|
|
338
|
+
alias: 'o',
|
|
339
|
+
desc: 'Write SBOM JSON to a file instead of stdout',
|
|
340
|
+
type: 'string',
|
|
341
|
+
normalize: true,
|
|
342
|
+
},
|
|
343
|
+
workspaceDir: {
|
|
344
|
+
alias: 'w',
|
|
345
|
+
desc: 'Workspace root directory (for monorepos; lock file is expected here)',
|
|
346
|
+
type: 'string',
|
|
347
|
+
normalize: true,
|
|
348
|
+
}
|
|
349
|
+
}),
|
|
350
|
+
handler: async (args) => {
|
|
351
|
+
let manifest = args['/path/to/manifest'];
|
|
352
|
+
const opts = args.workspaceDir ? { TRUSTIFY_DA_WORKSPACE_DIR: args.workspaceDir } : {};
|
|
353
|
+
let result;
|
|
354
|
+
try {
|
|
355
|
+
result = await generateSbom(manifest, opts);
|
|
356
|
+
}
|
|
357
|
+
catch (err) {
|
|
358
|
+
console.error(JSON.stringify({ error: `Failed to generate SBOM: ${err.message}` }, null, 2));
|
|
359
|
+
process.exit(1);
|
|
360
|
+
}
|
|
361
|
+
const json = JSON.stringify(result, null, 2);
|
|
362
|
+
if (args.output) {
|
|
363
|
+
try {
|
|
364
|
+
fs.writeFileSync(args.output, json);
|
|
365
|
+
}
|
|
366
|
+
catch (err) {
|
|
367
|
+
console.error(JSON.stringify({ error: `Failed to write output file: ${err.message}` }, null, 2));
|
|
368
|
+
process.exit(1);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
console.log(json);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
};
|
|
328
376
|
// parse and invoke the command
|
|
329
377
|
yargs(hideBin(process.argv))
|
|
330
|
-
.usage(`Usage: ${process.argv[0].includes("node") ? path.parse(process.argv[1]).base : path.parse(process.argv[0]).base} {component|stack|stack-batch|image|validate-token|license}`)
|
|
378
|
+
.usage(`Usage: ${process.argv[0].includes("node") ? path.parse(process.argv[1]).base : path.parse(process.argv[0]).base} {component|stack|stack-batch|image|validate-token|license|sbom}`)
|
|
331
379
|
.command(stack)
|
|
332
380
|
.command(stackBatch)
|
|
333
381
|
.command(component)
|
|
334
382
|
.command(image)
|
|
335
383
|
.command(validateToken)
|
|
336
384
|
.command(license)
|
|
385
|
+
.command(sbom)
|
|
337
386
|
.scriptName('')
|
|
338
387
|
.version(false)
|
|
339
388
|
.demandCommand(1)
|
|
@@ -18,9 +18,14 @@ export default class CycloneDxSbom {
|
|
|
18
18
|
* Adds a dependency relationship between two components in the SBOM
|
|
19
19
|
* @param {PackageURL} sourceRef - The source component (parent)
|
|
20
20
|
* @param {PackageURL} targetRef - The target component (dependency)
|
|
21
|
+
* @param {string} [scope] - Scope of the dependency
|
|
22
|
+
* @param {Array<{alg: string, content: string}>} [targetHashes] - Optional hashes for the target component
|
|
21
23
|
* @return {CycloneDxSbom} The updated SBOM
|
|
22
24
|
*/
|
|
23
|
-
addDependency(sourceRef: PackageURL, targetRef: PackageURL, scope
|
|
25
|
+
addDependency(sourceRef: PackageURL, targetRef: PackageURL, scope?: string, targetHashes?: Array<{
|
|
26
|
+
alg: string;
|
|
27
|
+
content: string;
|
|
28
|
+
}>): CycloneDxSbom;
|
|
24
29
|
/** @param {{}} opts - various options, settings and configuration of application.
|
|
25
30
|
* @return String CycloneDx Sbom json object in a string format
|
|
26
31
|
*/
|
|
@@ -50,6 +55,7 @@ export default class CycloneDxSbom {
|
|
|
50
55
|
version: any;
|
|
51
56
|
scope: any;
|
|
52
57
|
licenses?: any;
|
|
58
|
+
hashes?: any;
|
|
53
59
|
};
|
|
54
60
|
/**
|
|
55
61
|
* This method gets an array of dependencies to be ignored, and remove all of them from CycloneDx Sbom
|
|
@@ -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
|
-
* @
|
|
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
|
-
|
|
44
|
+
const validLicenses = licenseArray
|
|
45
|
+
.map(lic => {
|
|
44
46
|
if (typeof lic === 'string') {
|
|
45
47
|
return { license: { id: lic } };
|
|
46
48
|
}
|
|
47
|
-
|
|
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
|
-
|
|
98
|
-
|
|
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
|
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;
|
|
@@ -124,19 +136,74 @@ declare function stackAnalysis(manifest: string, html: false, opts?: Options | u
|
|
|
124
136
|
* or backend request failed
|
|
125
137
|
*/
|
|
126
138
|
declare function stackAnalysis(manifest: string, html?: boolean | undefined, opts?: Options | undefined): Promise<string | import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport>;
|
|
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]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
|
|
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]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
|
|
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 | {
|
|
206
|
+
declare function stackAnalysisBatch(workspaceRoot: string, html?: boolean | undefined, opts?: Options | undefined): Promise<string | {
|
|
140
207
|
[x: string]: import("@trustify-da/trustify-da-api-model/model/v5/AnalysisReport").AnalysisReport;
|
|
141
208
|
} | {
|
|
142
209
|
analysis: string | {
|
|
@@ -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);
|
|
@@ -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]}
|
|
@@ -37,5 +37,6 @@ export type Provider = {
|
|
|
37
37
|
validateLockFile: (arg0: string, arg1: any) => 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: any | undefined) => string | null;
|
|
41
|
+
packageManagerName: () => string;
|
|
41
42
|
};
|