@trustify-da/trustify-da-javascript-client 0.3.0-ea.b8af0f8 → 0.3.0-ea.bbe2094
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -8
- package/dist/package.json +6 -5
- package/dist/src/analysis.js +3 -2
- package/dist/src/cli.js +51 -2
- package/dist/src/cyclone_dx_sbom.d.ts +14 -1
- package/dist/src/cyclone_dx_sbom.js +32 -5
- package/dist/src/index.d.ts +74 -3
- package/dist/src/index.js +89 -6
- package/dist/src/oci_image/utils.js +11 -2
- package/dist/src/provider.js +8 -0
- package/dist/src/providers/base_java.d.ts +0 -9
- package/dist/src/providers/base_java.js +2 -38
- package/dist/src/providers/base_javascript.d.ts +6 -0
- package/dist/src/providers/base_javascript.js +37 -6
- package/dist/src/providers/base_pyproject.d.ts +153 -0
- package/dist/src/providers/base_pyproject.js +315 -0
- package/dist/src/providers/golang_gomodules.d.ts +21 -12
- package/dist/src/providers/golang_gomodules.js +164 -118
- package/dist/src/providers/gomod_parser.d.ts +4 -0
- package/dist/src/providers/gomod_parser.js +16 -0
- package/dist/src/providers/java_gradle.d.ts +19 -0
- package/dist/src/providers/java_gradle.js +116 -2
- package/dist/src/providers/java_maven.d.ts +8 -0
- package/dist/src/providers/java_maven.js +93 -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/manifest.d.ts +2 -0
- package/dist/src/providers/manifest.js +22 -4
- package/dist/src/providers/marker_evaluator.d.ts +14 -0
- package/dist/src/providers/marker_evaluator.js +191 -0
- package/dist/src/providers/processors/yarn_berry_processor.js +88 -5
- package/dist/src/providers/python_controller.d.ts +5 -1
- package/dist/src/providers/python_controller.js +8 -4
- package/dist/src/providers/python_pip.d.ts +4 -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 +75 -0
- package/dist/src/providers/python_poetry.js +238 -0
- package/dist/src/providers/python_uv.d.ts +55 -0
- package/dist/src/providers/python_uv.js +227 -0
- package/dist/src/providers/tree-sitter-gomod.wasm +0 -0
- package/dist/src/sbom.d.ts +14 -1
- package/dist/src/sbom.js +13 -2
- package/dist/src/tools.d.ts +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 +7 -6
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discover all pyproject.toml manifest paths in a uv workspace.
|
|
3
|
+
* Parses `[tool.uv.workspace]` from root pyproject.toml and glob-expands member patterns.
|
|
4
|
+
*
|
|
5
|
+
* @param {string} workspaceRoot - Absolute or relative path to workspace root (must contain pyproject.toml and uv.lock)
|
|
6
|
+
* @param {{ workspaceDiscoveryIgnore?: string[], TRUSTIFY_DA_WORKSPACE_DISCOVERY_IGNORE?: string, [key: string]: unknown }} [opts={}]
|
|
7
|
+
* @returns {Promise<string[]>} Paths to pyproject.toml files (absolute)
|
|
8
|
+
*/
|
|
9
|
+
export function discoverUvWorkspaceMembers(workspaceRoot: string, opts?: {
|
|
10
|
+
workspaceDiscoveryIgnore?: string[];
|
|
11
|
+
TRUSTIFY_DA_WORKSPACE_DISCOVERY_IGNORE?: string;
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
}): Promise<string[]>;
|
|
14
|
+
export default class Python_uv extends Base_pyproject {
|
|
15
|
+
/**
|
|
16
|
+
* @param {string} manifestDir - directory containing the target pyproject.toml
|
|
17
|
+
* @param {string} workspaceDir - workspace root (for resolving editable install paths)
|
|
18
|
+
* @param {object} parsed - parsed pyproject.toml
|
|
19
|
+
* @param {Object} opts
|
|
20
|
+
* @returns {Promise<{directDeps: string[], graph: Map<string, {name: string, version: string, children: string[]}>}>}
|
|
21
|
+
*/
|
|
22
|
+
_getDependencyData(manifestDir: string, workspaceDir: string, parsed: object, opts: any): Promise<{
|
|
23
|
+
directDeps: string[];
|
|
24
|
+
graph: Map<string, {
|
|
25
|
+
name: string;
|
|
26
|
+
version: string;
|
|
27
|
+
children: string[];
|
|
28
|
+
}>;
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Get the uv export output, either from env var or by running the command.
|
|
32
|
+
* @param {string} manifestDir
|
|
33
|
+
* @param {Object} opts
|
|
34
|
+
* @returns {string}
|
|
35
|
+
*/
|
|
36
|
+
_getUvExportOutput(manifestDir: string, opts: any): string;
|
|
37
|
+
/**
|
|
38
|
+
* Parse uv export output into a dependency graph using tree-sitter-requirements
|
|
39
|
+
* for package/version extraction and string parsing for "# via" comments.
|
|
40
|
+
*
|
|
41
|
+
* @param {string} output
|
|
42
|
+
* @param {string} projectName - canonical project name to identify direct deps
|
|
43
|
+
* @param {string} workspaceDir - workspace root (for resolving editable install paths)
|
|
44
|
+
* @returns {Promise<{directDeps: string[], graph: Map<string, {name: string, version: string, children: string[]}>}>}
|
|
45
|
+
*/
|
|
46
|
+
_parseUvExport(output: string, projectName: string, workspaceDir: string): Promise<{
|
|
47
|
+
directDeps: string[];
|
|
48
|
+
graph: Map<string, {
|
|
49
|
+
name: string;
|
|
50
|
+
version: string;
|
|
51
|
+
children: string[];
|
|
52
|
+
}>;
|
|
53
|
+
}>;
|
|
54
|
+
}
|
|
55
|
+
import Base_pyproject from './base_pyproject.js';
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fg from 'fast-glob';
|
|
4
|
+
import { parse as parseToml } from 'smol-toml';
|
|
5
|
+
import { environmentVariableIsPopulated, getCustomPath, invokeCommand } from '../tools.js';
|
|
6
|
+
import { filterManifestPathsByDiscoveryIgnore, resolveWorkspaceDiscoveryIgnore, toManifestGlobPatterns } from '../workspace.js';
|
|
7
|
+
import Base_pyproject from './base_pyproject.js';
|
|
8
|
+
import { evaluateMarker } from './marker_evaluator.js';
|
|
9
|
+
import { getParser, getPinnedVersionQuery } from './requirements_parser.js';
|
|
10
|
+
export default class Python_uv extends Base_pyproject {
|
|
11
|
+
/** @returns {string} */
|
|
12
|
+
_lockFileName() {
|
|
13
|
+
return 'uv.lock';
|
|
14
|
+
}
|
|
15
|
+
/** @returns {string} */
|
|
16
|
+
_cmdName() {
|
|
17
|
+
return 'uv';
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} manifestDir - directory containing the target pyproject.toml
|
|
21
|
+
* @param {string} workspaceDir - workspace root (for resolving editable install paths)
|
|
22
|
+
* @param {object} parsed - parsed pyproject.toml
|
|
23
|
+
* @param {Object} opts
|
|
24
|
+
* @returns {Promise<{directDeps: string[], graph: Map<string, {name: string, version: string, children: string[]}>}>}
|
|
25
|
+
*/
|
|
26
|
+
async _getDependencyData(manifestDir, workspaceDir, parsed, opts) {
|
|
27
|
+
let projectName = this._getProjectName(parsed);
|
|
28
|
+
let uvOutput = this._getUvExportOutput(manifestDir, opts);
|
|
29
|
+
return this._parseUvExport(uvOutput, projectName, workspaceDir);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get the uv export output, either from env var or by running the command.
|
|
33
|
+
* @param {string} manifestDir
|
|
34
|
+
* @param {Object} opts
|
|
35
|
+
* @returns {string}
|
|
36
|
+
*/
|
|
37
|
+
_getUvExportOutput(manifestDir, opts) {
|
|
38
|
+
if (environmentVariableIsPopulated('TRUSTIFY_DA_UV_EXPORT')) {
|
|
39
|
+
return Buffer.from(process.env['TRUSTIFY_DA_UV_EXPORT'], 'base64').toString('ascii');
|
|
40
|
+
}
|
|
41
|
+
let uvBin = getCustomPath('uv', opts);
|
|
42
|
+
return invokeCommand(uvBin, ['export', '--format', 'requirements.txt', '--frozen', '--no-hashes', '--no-dev', '--no-emit-project'], { cwd: manifestDir }).toString();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Parse uv export output into a dependency graph using tree-sitter-requirements
|
|
46
|
+
* for package/version extraction and string parsing for "# via" comments.
|
|
47
|
+
*
|
|
48
|
+
* @param {string} output
|
|
49
|
+
* @param {string} projectName - canonical project name to identify direct deps
|
|
50
|
+
* @param {string} workspaceDir - workspace root (for resolving editable install paths)
|
|
51
|
+
* @returns {Promise<{directDeps: string[], graph: Map<string, {name: string, version: string, children: string[]}>}>}
|
|
52
|
+
*/
|
|
53
|
+
async _parseUvExport(output, projectName, workspaceDir) {
|
|
54
|
+
let [parser, pinnedVersionQuery] = await Promise.all([
|
|
55
|
+
getParser(), getPinnedVersionQuery()
|
|
56
|
+
]);
|
|
57
|
+
let tree = parser.parse(output);
|
|
58
|
+
let root = tree.rootNode;
|
|
59
|
+
let canonProjectName = this._canonicalize(projectName);
|
|
60
|
+
let packages = new Map(); // canonical name -> {name, version, parents: Set}
|
|
61
|
+
let currentPkg = null;
|
|
62
|
+
let collectingVia = false;
|
|
63
|
+
for (let child of root.children) {
|
|
64
|
+
if (child.type === 'global_opt') {
|
|
65
|
+
let optNode = child.children.find(c => c.type === 'option');
|
|
66
|
+
let pathNode = child.children.find(c => c.type === 'path');
|
|
67
|
+
if (optNode?.text === '-e' && pathNode && workspaceDir) {
|
|
68
|
+
let memberDir = path.resolve(workspaceDir, pathNode.text);
|
|
69
|
+
let memberManifest = path.join(memberDir, 'pyproject.toml');
|
|
70
|
+
if (fs.existsSync(memberManifest)) {
|
|
71
|
+
let memberParsed = parseToml(fs.readFileSync(memberManifest, 'utf-8'));
|
|
72
|
+
let name = memberParsed.project?.name || memberParsed.tool?.poetry?.name;
|
|
73
|
+
let version = memberParsed.project?.version || memberParsed.tool?.poetry?.version;
|
|
74
|
+
if (name && version) {
|
|
75
|
+
let key = this._canonicalize(name);
|
|
76
|
+
if (key === canonProjectName) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
currentPkg = { name, version, parents: new Set() };
|
|
80
|
+
packages.set(key, currentPkg);
|
|
81
|
+
collectingVia = false;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
currentPkg = null;
|
|
87
|
+
collectingVia = false;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (child.type === 'requirement') {
|
|
91
|
+
let nameNode = child.children.find(c => c.type === 'package');
|
|
92
|
+
if (!nameNode) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
// Skip packages with non-matching PEP 508 markers, e.g. "pywin32==311 ; sys_platform == 'win32'"
|
|
96
|
+
let markerNode = child.children.find(c => c.type === 'marker_spec');
|
|
97
|
+
if (markerNode) {
|
|
98
|
+
let markerText = markerNode.text.replace(/^\s*;\s*/, '');
|
|
99
|
+
if (!evaluateMarker(markerText)) {
|
|
100
|
+
currentPkg = null;
|
|
101
|
+
collectingVia = false;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
let name = nameNode.text;
|
|
106
|
+
let version = null;
|
|
107
|
+
let versionMatches = pinnedVersionQuery.matches(child);
|
|
108
|
+
if (versionMatches.length > 0) {
|
|
109
|
+
version = versionMatches[0].captures.find(c => c.name === 'version').node.text;
|
|
110
|
+
}
|
|
111
|
+
if (!version) {
|
|
112
|
+
throw new Error(`uv export: package '${name}' has no pinned version`);
|
|
113
|
+
}
|
|
114
|
+
let key = this._canonicalize(name);
|
|
115
|
+
currentPkg = { name, version, parents: new Set() };
|
|
116
|
+
packages.set(key, currentPkg);
|
|
117
|
+
collectingVia = false;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (child.type === 'comment' && currentPkg) {
|
|
121
|
+
let text = child.text.trim();
|
|
122
|
+
let viaSingle = text.match(/^# via ([A-Za-z0-9][A-Za-z0-9._-]*)$/);
|
|
123
|
+
if (viaSingle) {
|
|
124
|
+
currentPkg.parents.add(this._canonicalize(viaSingle[1]));
|
|
125
|
+
collectingVia = false;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (text === '# via') {
|
|
129
|
+
collectingVia = true;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
if (collectingVia) {
|
|
133
|
+
let parentMatch = text.match(/^#\s+([A-Za-z0-9][A-Za-z0-9._-]*)$/);
|
|
134
|
+
if (parentMatch) {
|
|
135
|
+
currentPkg.parents.add(this._canonicalize(parentMatch[1]));
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
collectingVia = false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// Build forward dependency map and extract direct deps in one pass
|
|
143
|
+
let graph = new Map();
|
|
144
|
+
let directDeps = [];
|
|
145
|
+
for (let [key, pkg] of packages) {
|
|
146
|
+
graph.set(key, { name: pkg.name, version: pkg.version, children: [] });
|
|
147
|
+
}
|
|
148
|
+
for (let [childKey, pkg] of packages) {
|
|
149
|
+
for (let parentKey of pkg.parents) {
|
|
150
|
+
if (parentKey === canonProjectName) {
|
|
151
|
+
directDeps.push(childKey);
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
let parentEntry = graph.get(parentKey);
|
|
155
|
+
if (parentEntry) {
|
|
156
|
+
parentEntry.children.push(childKey);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return { directDeps, graph };
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const DEFAULT_UV_DISCOVERY_IGNORE = [
|
|
164
|
+
'**/__pycache__/**',
|
|
165
|
+
'**/.venv/**',
|
|
166
|
+
];
|
|
167
|
+
/**
|
|
168
|
+
* Discover all pyproject.toml manifest paths in a uv workspace.
|
|
169
|
+
* Parses `[tool.uv.workspace]` from root pyproject.toml and glob-expands member patterns.
|
|
170
|
+
*
|
|
171
|
+
* @param {string} workspaceRoot - Absolute or relative path to workspace root (must contain pyproject.toml and uv.lock)
|
|
172
|
+
* @param {{ workspaceDiscoveryIgnore?: string[], TRUSTIFY_DA_WORKSPACE_DISCOVERY_IGNORE?: string, [key: string]: unknown }} [opts={}]
|
|
173
|
+
* @returns {Promise<string[]>} Paths to pyproject.toml files (absolute)
|
|
174
|
+
*/
|
|
175
|
+
export async function discoverUvWorkspaceMembers(workspaceRoot, opts = {}) {
|
|
176
|
+
const root = path.resolve(workspaceRoot);
|
|
177
|
+
const rootPyproject = path.join(root, 'pyproject.toml');
|
|
178
|
+
const uvLock = path.join(root, 'uv.lock');
|
|
179
|
+
if (!fs.existsSync(rootPyproject) || !fs.existsSync(uvLock)) {
|
|
180
|
+
return [];
|
|
181
|
+
}
|
|
182
|
+
let parsed;
|
|
183
|
+
try {
|
|
184
|
+
parsed = parseToml(fs.readFileSync(rootPyproject, 'utf-8'));
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
return [];
|
|
188
|
+
}
|
|
189
|
+
const workspaceConfig = parsed?.tool?.uv?.workspace;
|
|
190
|
+
if (!workspaceConfig) {
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
const memberPatterns = workspaceConfig.members;
|
|
194
|
+
if (!Array.isArray(memberPatterns) || memberPatterns.length === 0) {
|
|
195
|
+
return [];
|
|
196
|
+
}
|
|
197
|
+
const excludePatterns = Array.isArray(workspaceConfig.exclude) ? workspaceConfig.exclude : [];
|
|
198
|
+
const excludeGlobs = excludePatterns
|
|
199
|
+
.filter(p => typeof p === 'string' && p.trim())
|
|
200
|
+
.map(p => `${p.trim()}/pyproject.toml`);
|
|
201
|
+
const ignorePatterns = [...resolveWorkspaceDiscoveryIgnore(opts), ...DEFAULT_UV_DISCOVERY_IGNORE];
|
|
202
|
+
const globOpts = {
|
|
203
|
+
cwd: root,
|
|
204
|
+
absolute: true,
|
|
205
|
+
onlyFiles: true,
|
|
206
|
+
ignore: [...ignorePatterns, ...excludeGlobs],
|
|
207
|
+
followSymbolicLinks: false,
|
|
208
|
+
};
|
|
209
|
+
const patterns = toManifestGlobPatterns(memberPatterns.filter(p => typeof p === 'string'), 'pyproject.toml');
|
|
210
|
+
const manifestPaths = await fg(patterns, globOpts);
|
|
211
|
+
if (!manifestPaths.includes(rootPyproject) && hasProjectMetadata(parsed)) {
|
|
212
|
+
manifestPaths.unshift(rootPyproject);
|
|
213
|
+
}
|
|
214
|
+
return filterManifestPathsByDiscoveryIgnore(manifestPaths, root, ignorePatterns);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* @param {import('smol-toml').TomlTable} parsedPyProject
|
|
218
|
+
* @returns {boolean}
|
|
219
|
+
*/
|
|
220
|
+
function hasProjectMetadata(parsedPyProject) {
|
|
221
|
+
try {
|
|
222
|
+
return typeof parsedPyProject?.project?.name === 'string' && parsedPyProject.project.name.trim() !== '';
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
Binary file
|
package/dist/src/sbom.d.ts
CHANGED
|
@@ -25,9 +25,14 @@ export default class Sbom {
|
|
|
25
25
|
/**
|
|
26
26
|
* @param {component} sourceRef current source Component ( Starting from root component by clients)
|
|
27
27
|
* @param {PackageURL} targetRef current dependency to add to Dependencies list of component sourceRef
|
|
28
|
+
* @param {string} [scope] - Scope of the dependency
|
|
29
|
+
* @param {Array<{alg: string, content: string}>} [targetHashes] - Optional hashes for the target component
|
|
28
30
|
* @return Sbom
|
|
29
31
|
*/
|
|
30
|
-
addDependency(sourceRef: component, targetRef: PackageURL, scope
|
|
32
|
+
addDependency(sourceRef: component, targetRef: PackageURL, scope?: string, targetHashes?: Array<{
|
|
33
|
+
alg: string;
|
|
34
|
+
content: string;
|
|
35
|
+
}>): CycloneDxSbom;
|
|
31
36
|
/**
|
|
32
37
|
* @return String sbom json in a string format
|
|
33
38
|
*/
|
|
@@ -45,6 +50,7 @@ export default class Sbom {
|
|
|
45
50
|
version: any;
|
|
46
51
|
scope: any;
|
|
47
52
|
licenses?: any;
|
|
53
|
+
hashes?: any;
|
|
48
54
|
};
|
|
49
55
|
/** This method gets a component object, and a string name, and checks if the name is a substring of the component' purl.
|
|
50
56
|
* @param {} component to search in its dependencies
|
|
@@ -53,6 +59,13 @@ export default class Sbom {
|
|
|
53
59
|
* @return {boolean}
|
|
54
60
|
*/
|
|
55
61
|
checkIfPackageInsideDependsOnList(component: any, name: string): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Checks if any entry in the dependsOn list of sourceRef starts with the given purl prefix.
|
|
64
|
+
* @param {PackageURL} sourceRef - The source component to check
|
|
65
|
+
* @param {string} purlPrefix - The purl prefix to match (e.g. "pkg:npm/minimist@")
|
|
66
|
+
* @return {boolean}
|
|
67
|
+
*/
|
|
68
|
+
checkDependsOnByPurlPrefix(sourceRef: PackageURL, purlPrefix: string): boolean;
|
|
56
69
|
/** Removes the root component from the sbom
|
|
57
70
|
*/
|
|
58
71
|
removeRootComponent(): void;
|
package/dist/src/sbom.js
CHANGED
|
@@ -43,10 +43,12 @@ export default class Sbom {
|
|
|
43
43
|
/**
|
|
44
44
|
* @param {component} sourceRef current source Component ( Starting from root component by clients)
|
|
45
45
|
* @param {PackageURL} targetRef current dependency to add to Dependencies list of component sourceRef
|
|
46
|
+
* @param {string} [scope] - Scope of the dependency
|
|
47
|
+
* @param {Array<{alg: string, content: string}>} [targetHashes] - Optional hashes for the target component
|
|
46
48
|
* @return Sbom
|
|
47
49
|
*/
|
|
48
|
-
addDependency(sourceRef, targetRef, scope) {
|
|
49
|
-
return this.sbomModel.addDependency(sourceRef, targetRef, scope);
|
|
50
|
+
addDependency(sourceRef, targetRef, scope, targetHashes) {
|
|
51
|
+
return this.sbomModel.addDependency(sourceRef, targetRef, scope, targetHashes);
|
|
50
52
|
}
|
|
51
53
|
/**
|
|
52
54
|
* @return String sbom json in a string format
|
|
@@ -77,6 +79,15 @@ export default class Sbom {
|
|
|
77
79
|
checkIfPackageInsideDependsOnList(component, name) {
|
|
78
80
|
return this.sbomModel.checkIfPackageInsideDependsOnList(component, name);
|
|
79
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Checks if any entry in the dependsOn list of sourceRef starts with the given purl prefix.
|
|
84
|
+
* @param {PackageURL} sourceRef - The source component to check
|
|
85
|
+
* @param {string} purlPrefix - The purl prefix to match (e.g. "pkg:npm/minimist@")
|
|
86
|
+
* @return {boolean}
|
|
87
|
+
*/
|
|
88
|
+
checkDependsOnByPurlPrefix(sourceRef, purlPrefix) {
|
|
89
|
+
return this.sbomModel.checkDependsOnByPurlPrefix(sourceRef, purlPrefix);
|
|
90
|
+
}
|
|
80
91
|
/** Removes the root component from the sbom
|
|
81
92
|
*/
|
|
82
93
|
removeRootComponent() {
|
package/dist/src/tools.d.ts
CHANGED
|
@@ -61,6 +61,32 @@ export function toPurlFromString(strPurl: any): PackageURL | null;
|
|
|
61
61
|
* @param {string} cwd - directory for which to find the root of the git repository.
|
|
62
62
|
*/
|
|
63
63
|
export function getGitRootDir(cwd: string): string | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Normalize a filesystem path, lowercasing on Windows for case-insensitive comparison.
|
|
66
|
+
*
|
|
67
|
+
* @param {string} thePath
|
|
68
|
+
* @returns {string}
|
|
69
|
+
*/
|
|
70
|
+
export function normalizePath(thePath: string): string;
|
|
71
|
+
/**
|
|
72
|
+
* Walk up from `startDir` to `repoRoot` looking for an executable wrapper script.
|
|
73
|
+
*
|
|
74
|
+
* @param {string} startDir - Absolute directory to start from
|
|
75
|
+
* @param {string} wrapperName - Wrapper filename (e.g. `mvnw`, `gradlew`)
|
|
76
|
+
* @param {string} [repoRoot] - Stop boundary (defaults to git root or filesystem root)
|
|
77
|
+
* @returns {string | undefined}
|
|
78
|
+
*/
|
|
79
|
+
export function traverseForWrapper(startDir: string, wrapperName: string, repoRoot?: string): string | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* Resolve a build-tool binary, preferring a wrapper when configured.
|
|
82
|
+
*
|
|
83
|
+
* @param {string} globalBinary - Global binary name (e.g. `mvn`, `gradle`)
|
|
84
|
+
* @param {string} localWrapper - Wrapper filename (e.g. `mvnw`, `gradlew.bat`)
|
|
85
|
+
* @param {string} startDir - Directory from which to start the wrapper search
|
|
86
|
+
* @param {import('./index.js').Options} [opts={}]
|
|
87
|
+
* @returns {string} Path to the resolved binary
|
|
88
|
+
*/
|
|
89
|
+
export function resolveBinary(globalBinary: string, localWrapper: string, startDir: string, opts?: import("./index.js").Options): string;
|
|
64
90
|
/** this method invokes command string in a process in a synchronous way.
|
|
65
91
|
* @param {string} bin - the command to be invoked
|
|
66
92
|
* @param {Array<string>} args - the args to pass to the binary
|
package/dist/src/tools.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { execFileSync } from "child_process";
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
2
4
|
import { EOL } from "os";
|
|
3
5
|
import { HttpsProxyAgent } from "https-proxy-agent";
|
|
4
6
|
import { PackageURL } from "packageurl-js";
|
|
@@ -128,6 +130,62 @@ export function getGitRootDir(cwd) {
|
|
|
128
130
|
return undefined;
|
|
129
131
|
}
|
|
130
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Normalize a filesystem path, lowercasing on Windows for case-insensitive comparison.
|
|
135
|
+
*
|
|
136
|
+
* @param {string} thePath
|
|
137
|
+
* @returns {string}
|
|
138
|
+
*/
|
|
139
|
+
export function normalizePath(thePath) {
|
|
140
|
+
const normalized = path.resolve(thePath).normalize();
|
|
141
|
+
return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Walk up from `startDir` to `repoRoot` looking for an executable wrapper script.
|
|
145
|
+
*
|
|
146
|
+
* @param {string} startDir - Absolute directory to start from
|
|
147
|
+
* @param {string} wrapperName - Wrapper filename (e.g. `mvnw`, `gradlew`)
|
|
148
|
+
* @param {string} [repoRoot] - Stop boundary (defaults to git root or filesystem root)
|
|
149
|
+
* @returns {string | undefined}
|
|
150
|
+
*/
|
|
151
|
+
export function traverseForWrapper(startDir, wrapperName, repoRoot = undefined) {
|
|
152
|
+
const currentDir = normalizePath(startDir);
|
|
153
|
+
repoRoot = repoRoot || getGitRootDir(currentDir) || path.parse(currentDir).root;
|
|
154
|
+
const wrapperPath = path.join(currentDir, wrapperName);
|
|
155
|
+
try {
|
|
156
|
+
fs.accessSync(wrapperPath, fs.constants.X_OK);
|
|
157
|
+
return wrapperPath;
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
const rootDir = path.parse(currentDir).root;
|
|
161
|
+
if (currentDir === repoRoot || currentDir === rootDir) {
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
const parentDir = path.dirname(currentDir);
|
|
165
|
+
if (parentDir === currentDir || parentDir === rootDir) {
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
return traverseForWrapper(parentDir, wrapperName, repoRoot);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Resolve a build-tool binary, preferring a wrapper when configured.
|
|
173
|
+
*
|
|
174
|
+
* @param {string} globalBinary - Global binary name (e.g. `mvn`, `gradle`)
|
|
175
|
+
* @param {string} localWrapper - Wrapper filename (e.g. `mvnw`, `gradlew.bat`)
|
|
176
|
+
* @param {string} startDir - Directory from which to start the wrapper search
|
|
177
|
+
* @param {import('./index.js').Options} [opts={}]
|
|
178
|
+
* @returns {string} Path to the resolved binary
|
|
179
|
+
*/
|
|
180
|
+
export function resolveBinary(globalBinary, localWrapper, startDir, opts = {}) {
|
|
181
|
+
if (getWrapperPreference(globalBinary, opts)) {
|
|
182
|
+
const wrapper = traverseForWrapper(startDir, localWrapper);
|
|
183
|
+
if (wrapper !== undefined) {
|
|
184
|
+
return wrapper;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return getCustomPath(globalBinary, opts);
|
|
188
|
+
}
|
|
131
189
|
/** this method invokes command string in a process in a synchronous way.
|
|
132
190
|
* @param {string} bin - the command to be invoked
|
|
133
191
|
* @param {Array<string>} args - the args to pass to the binary
|
package/dist/src/workspace.d.ts
CHANGED
|
@@ -42,6 +42,15 @@ export function discoverWorkspacePackages(workspaceRoot: string, opts?: {
|
|
|
42
42
|
TRUSTIFY_DA_WORKSPACE_DISCOVERY_IGNORE?: string;
|
|
43
43
|
[key: string]: unknown;
|
|
44
44
|
}): Promise<string[]>;
|
|
45
|
+
/**
|
|
46
|
+
* Convert workspace glob patterns to manifest-file glob patterns,
|
|
47
|
+
* correctly handling negation prefixes.
|
|
48
|
+
*
|
|
49
|
+
* @param {string[]} patterns - Workspace glob patterns (may include negations)
|
|
50
|
+
* @param {string} manifestFileName - e.g. 'package.json' or 'Cargo.toml'
|
|
51
|
+
* @returns {string[]}
|
|
52
|
+
*/
|
|
53
|
+
export function toManifestGlobPatterns(patterns: string[], manifestFileName: string): string[];
|
|
45
54
|
/**
|
|
46
55
|
* Discover all Cargo.toml manifest paths in a Cargo workspace.
|
|
47
56
|
* Uses `cargo metadata` to get workspace members.
|
package/dist/src/workspace.js
CHANGED
|
@@ -172,7 +172,7 @@ function parsePnpmPackages(content) {
|
|
|
172
172
|
* @param {string} manifestFileName - e.g. 'package.json' or 'Cargo.toml'
|
|
173
173
|
* @returns {string[]}
|
|
174
174
|
*/
|
|
175
|
-
function toManifestGlobPatterns(patterns, manifestFileName) {
|
|
175
|
+
export function toManifestGlobPatterns(patterns, manifestFileName) {
|
|
176
176
|
return patterns.map(p => {
|
|
177
177
|
if (p.startsWith('!')) {
|
|
178
178
|
return `!${p.slice(1)}/${manifestFileName}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trustify-da/trustify-da-javascript-client",
|
|
3
|
-
"version": "0.3.0-ea.
|
|
3
|
+
"version": "0.3.0-ea.bbe2094",
|
|
4
4
|
"description": "Code-Ready Dependency Analytics JavaScript API.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/guacsec/trustify-da-javascript-client#README.md",
|
|
@@ -38,31 +38,32 @@
|
|
|
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
|
-
"pretest": "cp node_modules/tree-sitter-requirements/tree-sitter-requirements.wasm src/providers/tree-sitter-requirements.wasm",
|
|
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",
|
|
45
45
|
"compile": "tsc -p tsconfig.json",
|
|
46
46
|
"compile:dev": "tsc -p tsconfig.dev.json",
|
|
47
|
-
"postcompile": "cp node_modules/tree-sitter-requirements/tree-sitter-requirements.wasm dist/src/providers/tree-sitter-requirements.wasm"
|
|
47
|
+
"postcompile": "cp node_modules/tree-sitter-requirements/tree-sitter-requirements.wasm dist/src/providers/tree-sitter-requirements.wasm && cp node_modules/tree-sitter-gomod/tree-sitter-gomod.wasm dist/src/providers/tree-sitter-gomod.wasm"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@babel/core": "^7.23.2",
|
|
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",
|
|
62
62
|
"packageurl-js": "~1.0.2",
|
|
63
63
|
"smol-toml": "^1.6.0",
|
|
64
|
+
"tree-sitter-gomod": "github:strum355/tree-sitter-go-mod#56326f2ad478892ace58ff247a97d492a3cbcdda",
|
|
64
65
|
"tree-sitter-requirements": "github:Strum355/tree-sitter-requirements#d0261ee76b84253997fe70d7d397e78c006c3801",
|
|
65
|
-
"web-tree-sitter": "^0.26.
|
|
66
|
+
"web-tree-sitter": "^0.26.7",
|
|
66
67
|
"yargs": "^18.0.0"
|
|
67
68
|
},
|
|
68
69
|
"devDependencies": {
|