@cyclonedx/cdxgen 12.2.0 → 12.3.0
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 +242 -90
- package/bin/audit.js +191 -0
- package/bin/cdxgen.js +532 -168
- package/bin/convert.js +99 -0
- package/bin/evinse.js +23 -0
- package/bin/repl.js +339 -8
- package/bin/sign.js +8 -0
- package/bin/validate.js +8 -0
- package/bin/verify.js +8 -0
- package/data/container-knowledge-index.json +125 -0
- package/data/gtfobins-index.json +6296 -0
- package/data/lolbas-index.json +150 -0
- package/data/queries-darwin.json +63 -3
- package/data/queries-win.json +45 -3
- package/data/queries.json +74 -2
- package/data/rules/chrome-extensions.yaml +240 -0
- package/data/rules/ci-permissions.yaml +478 -18
- package/data/rules/container-risk.yaml +270 -0
- package/data/rules/obom-runtime.yaml +891 -0
- package/data/rules/package-integrity.yaml +49 -0
- package/data/spdx-export.schema.json +6794 -0
- package/data/spdx-model-v3.0.1.jsonld +15999 -0
- package/lib/audit/index.js +1924 -0
- package/lib/audit/index.poku.js +1488 -0
- package/lib/audit/progress.js +137 -0
- package/lib/audit/progress.poku.js +188 -0
- package/lib/audit/reporters.js +618 -0
- package/lib/audit/scoring.js +310 -0
- package/lib/audit/scoring.poku.js +341 -0
- package/lib/audit/targets.js +260 -0
- package/lib/audit/targets.poku.js +331 -0
- package/lib/cli/index.js +276 -68
- package/lib/cli/index.poku.js +368 -0
- package/lib/helpers/analyzer.js +1052 -5
- package/lib/helpers/analyzer.poku.js +301 -0
- package/lib/helpers/annotationFormatter.js +49 -0
- package/lib/helpers/annotationFormatter.poku.js +44 -0
- package/lib/helpers/bomUtils.js +36 -0
- package/lib/helpers/bomUtils.poku.js +51 -0
- package/lib/helpers/caxa.js +2 -2
- package/lib/helpers/chromextutils.js +1153 -0
- package/lib/helpers/chromextutils.poku.js +493 -0
- package/lib/helpers/ciParsers/githubActions.js +1632 -45
- package/lib/helpers/ciParsers/githubActions.poku.js +853 -1
- package/lib/helpers/containerRisk.js +186 -0
- package/lib/helpers/containerRisk.poku.js +52 -0
- package/lib/helpers/depsUtils.js +16 -0
- package/lib/helpers/depsUtils.poku.js +58 -1
- package/lib/helpers/display.js +245 -61
- package/lib/helpers/display.poku.js +162 -2
- package/lib/helpers/exportUtils.js +123 -0
- package/lib/helpers/exportUtils.poku.js +60 -0
- package/lib/helpers/formulationParsers.js +69 -0
- package/lib/helpers/formulationParsers.poku.js +44 -0
- package/lib/helpers/gtfobins.js +189 -0
- package/lib/helpers/gtfobins.poku.js +49 -0
- package/lib/helpers/lolbas.js +267 -0
- package/lib/helpers/lolbas.poku.js +39 -0
- package/lib/helpers/osqueryTransform.js +84 -0
- package/lib/helpers/osqueryTransform.poku.js +49 -0
- package/lib/helpers/provenanceUtils.js +193 -0
- package/lib/helpers/provenanceUtils.poku.js +145 -0
- package/lib/helpers/pylockutils.js +281 -0
- package/lib/helpers/pylockutils.poku.js +48 -0
- package/lib/helpers/registryProvenance.js +793 -0
- package/lib/helpers/registryProvenance.poku.js +452 -0
- package/lib/helpers/remote/dependency-track.js +84 -0
- package/lib/helpers/remote/dependency-track.poku.js +119 -0
- package/lib/helpers/source.js +1267 -0
- package/lib/helpers/source.poku.js +771 -0
- package/lib/helpers/spdxUtils.js +97 -0
- package/lib/helpers/spdxUtils.poku.js +70 -0
- package/lib/helpers/table.js +384 -0
- package/lib/helpers/table.poku.js +186 -0
- package/lib/helpers/unicodeScan.js +147 -0
- package/lib/helpers/unicodeScan.poku.js +45 -0
- package/lib/helpers/utils.js +882 -136
- package/lib/helpers/utils.poku.js +995 -91
- package/lib/managers/binary.js +29 -5
- package/lib/managers/docker.js +179 -52
- package/lib/managers/docker.poku.js +327 -28
- package/lib/managers/oci.js +107 -23
- package/lib/managers/oci.poku.js +132 -0
- package/lib/server/openapi.yaml +50 -0
- package/lib/server/server.js +228 -331
- package/lib/server/server.poku.js +220 -5
- package/lib/stages/postgen/annotator.js +7 -0
- package/lib/stages/postgen/annotator.poku.js +40 -0
- package/lib/stages/postgen/auditBom.js +20 -5
- package/lib/stages/postgen/auditBom.poku.js +1729 -67
- package/lib/stages/postgen/postgen.js +40 -0
- package/lib/stages/postgen/postgen.poku.js +47 -0
- package/lib/stages/postgen/ruleEngine.js +80 -2
- package/lib/stages/postgen/spdxConverter.js +796 -0
- package/lib/stages/postgen/spdxConverter.poku.js +341 -0
- package/lib/validator/bomValidator.js +232 -0
- package/lib/validator/bomValidator.poku.js +70 -0
- package/lib/validator/complianceRules.js +70 -7
- package/lib/validator/complianceRules.poku.js +30 -0
- package/lib/validator/reporters/annotations.js +2 -2
- package/lib/validator/reporters/console.js +13 -2
- package/lib/validator/reporters.poku.js +13 -0
- package/package.json +10 -8
- package/types/bin/audit.d.ts +3 -0
- package/types/bin/audit.d.ts.map +1 -0
- package/types/bin/convert.d.ts +3 -0
- package/types/bin/convert.d.ts.map +1 -0
- package/types/bin/repl.d.ts.map +1 -1
- package/types/lib/audit/index.d.ts +115 -0
- package/types/lib/audit/index.d.ts.map +1 -0
- package/types/lib/audit/progress.d.ts +27 -0
- package/types/lib/audit/progress.d.ts.map +1 -0
- package/types/lib/audit/reporters.d.ts +35 -0
- package/types/lib/audit/reporters.d.ts.map +1 -0
- package/types/lib/audit/scoring.d.ts +35 -0
- package/types/lib/audit/scoring.d.ts.map +1 -0
- package/types/lib/audit/targets.d.ts +63 -0
- package/types/lib/audit/targets.d.ts.map +1 -0
- package/types/lib/cli/index.d.ts +8 -0
- package/types/lib/cli/index.d.ts.map +1 -1
- package/types/lib/helpers/analyzer.d.ts +13 -0
- package/types/lib/helpers/analyzer.d.ts.map +1 -1
- package/types/lib/helpers/annotationFormatter.d.ts +23 -0
- package/types/lib/helpers/annotationFormatter.d.ts.map +1 -0
- package/types/lib/helpers/bomUtils.d.ts +5 -0
- package/types/lib/helpers/bomUtils.d.ts.map +1 -0
- package/types/lib/helpers/chromextutils.d.ts +97 -0
- package/types/lib/helpers/chromextutils.d.ts.map +1 -0
- package/types/lib/helpers/ciParsers/githubActions.d.ts +3 -8
- package/types/lib/helpers/ciParsers/githubActions.d.ts.map +1 -1
- package/types/lib/helpers/containerRisk.d.ts +17 -0
- package/types/lib/helpers/containerRisk.d.ts.map +1 -0
- package/types/lib/helpers/depsUtils.d.ts.map +1 -1
- package/types/lib/helpers/display.d.ts +4 -1
- package/types/lib/helpers/display.d.ts.map +1 -1
- package/types/lib/helpers/exportUtils.d.ts +40 -0
- package/types/lib/helpers/exportUtils.d.ts.map +1 -0
- package/types/lib/helpers/formulationParsers.d.ts.map +1 -1
- package/types/lib/helpers/gtfobins.d.ts +17 -0
- package/types/lib/helpers/gtfobins.d.ts.map +1 -0
- package/types/lib/helpers/lolbas.d.ts +16 -0
- package/types/lib/helpers/lolbas.d.ts.map +1 -0
- package/types/lib/helpers/osqueryTransform.d.ts +7 -0
- package/types/lib/helpers/osqueryTransform.d.ts.map +1 -0
- package/types/lib/helpers/provenanceUtils.d.ts +90 -0
- package/types/lib/helpers/provenanceUtils.d.ts.map +1 -0
- package/types/lib/helpers/pylockutils.d.ts +51 -0
- package/types/lib/helpers/pylockutils.d.ts.map +1 -0
- package/types/lib/helpers/registryProvenance.d.ts +17 -0
- package/types/lib/helpers/registryProvenance.d.ts.map +1 -0
- package/types/lib/helpers/remote/dependency-track.d.ts +16 -0
- package/types/lib/helpers/remote/dependency-track.d.ts.map +1 -0
- package/types/lib/helpers/source.d.ts +141 -0
- package/types/lib/helpers/source.d.ts.map +1 -0
- package/types/lib/helpers/spdxUtils.d.ts +2 -0
- package/types/lib/helpers/spdxUtils.d.ts.map +1 -0
- package/types/lib/helpers/table.d.ts +6 -0
- package/types/lib/helpers/table.d.ts.map +1 -0
- package/types/lib/helpers/unicodeScan.d.ts +46 -0
- package/types/lib/helpers/unicodeScan.d.ts.map +1 -0
- package/types/lib/helpers/utils.d.ts +30 -11
- package/types/lib/helpers/utils.d.ts.map +1 -1
- package/types/lib/managers/binary.d.ts.map +1 -1
- package/types/lib/managers/docker.d.ts.map +1 -1
- package/types/lib/managers/oci.d.ts.map +1 -1
- package/types/lib/server/server.d.ts +0 -35
- package/types/lib/server/server.d.ts.map +1 -1
- package/types/lib/stages/postgen/annotator.d.ts.map +1 -1
- package/types/lib/stages/postgen/auditBom.d.ts.map +1 -1
- package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
- package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -1
- package/types/lib/stages/postgen/spdxConverter.d.ts +11 -0
- package/types/lib/stages/postgen/spdxConverter.d.ts.map +1 -0
- package/types/lib/validator/bomValidator.d.ts +1 -0
- package/types/lib/validator/bomValidator.d.ts.map +1 -1
- package/types/lib/validator/complianceRules.d.ts.map +1 -1
- package/types/lib/validator/reporters/console.d.ts.map +1 -1
- package/types/bin/dependencies.d.ts +0 -3
- package/types/bin/dependencies.d.ts.map +0 -1
- package/types/bin/licenses.d.ts +0 -3
- package/types/bin/licenses.d.ts.map +0 -1
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
|
|
3
|
+
const PYLOCK_FILE_REGEX = /^pylock(\.[^.]+)?\.toml$/;
|
|
4
|
+
const DEFAULT_PYPI_REGISTRIES = new Set([
|
|
5
|
+
"https://pypi.org/simple",
|
|
6
|
+
"https://pypi.org/simple/",
|
|
7
|
+
]);
|
|
8
|
+
|
|
9
|
+
const PYLOCK_TOP_LEVEL_KEYS = [
|
|
10
|
+
"lock-version",
|
|
11
|
+
"environments",
|
|
12
|
+
"requires-python",
|
|
13
|
+
"extras",
|
|
14
|
+
"dependency-groups",
|
|
15
|
+
"default-groups",
|
|
16
|
+
"created-by",
|
|
17
|
+
"tool",
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const PYLOCK_PACKAGE_CUSTOM_KEYS = [
|
|
21
|
+
"marker",
|
|
22
|
+
"index",
|
|
23
|
+
"dependencies",
|
|
24
|
+
"extras",
|
|
25
|
+
"dependency-groups",
|
|
26
|
+
"attestation-identities",
|
|
27
|
+
"tool",
|
|
28
|
+
"vcs",
|
|
29
|
+
"directory",
|
|
30
|
+
"archive",
|
|
31
|
+
"sdist",
|
|
32
|
+
"wheels",
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Check whether a file name conforms to pylock naming.
|
|
37
|
+
*
|
|
38
|
+
* @param {string} lockFilePath lock file path
|
|
39
|
+
* @returns {boolean} true if this is a pylock file
|
|
40
|
+
*/
|
|
41
|
+
export function isPyLockFile(lockFilePath) {
|
|
42
|
+
if (!lockFilePath) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return PYLOCK_FILE_REGEX.test(basename(lockFilePath));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Check whether a parsed toml object follows pylock format.
|
|
50
|
+
*
|
|
51
|
+
* @param {object} lockTomlObj parsed toml object
|
|
52
|
+
* @returns {boolean} true if object appears to be pylock data
|
|
53
|
+
*/
|
|
54
|
+
export function isPyLockObject(lockTomlObj) {
|
|
55
|
+
return !!(
|
|
56
|
+
lockTomlObj?.["lock-version"] && Array.isArray(lockTomlObj.packages)
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get package entries from py lock data in a format-agnostic way.
|
|
62
|
+
*
|
|
63
|
+
* @param {object} lockTomlObj parsed toml object
|
|
64
|
+
* @returns {Array<object>} package entries
|
|
65
|
+
*/
|
|
66
|
+
export function getPyLockPackages(lockTomlObj) {
|
|
67
|
+
if (Array.isArray(lockTomlObj?.package)) {
|
|
68
|
+
return lockTomlObj.package;
|
|
69
|
+
}
|
|
70
|
+
if (Array.isArray(lockTomlObj?.packages)) {
|
|
71
|
+
return lockTomlObj.packages;
|
|
72
|
+
}
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Convert top-level pylock keys to custom cdx properties.
|
|
78
|
+
*
|
|
79
|
+
* @param {object} lockTomlObj parsed toml object
|
|
80
|
+
* @returns {Array<object>} custom properties
|
|
81
|
+
*/
|
|
82
|
+
export function collectPyLockTopLevelProperties(lockTomlObj) {
|
|
83
|
+
const properties = [];
|
|
84
|
+
for (const akey of PYLOCK_TOP_LEVEL_KEYS) {
|
|
85
|
+
if (lockTomlObj?.[akey] !== undefined) {
|
|
86
|
+
properties.push({
|
|
87
|
+
name: `cdx:pylock:${akey.replaceAll("-", "_")}`,
|
|
88
|
+
value: toPropertyValue(lockTomlObj[akey]),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return properties;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Convert package-level pylock keys to custom cdx properties.
|
|
97
|
+
*
|
|
98
|
+
* @param {object} pkg pylock package entry
|
|
99
|
+
* @returns {Array<object>} custom properties
|
|
100
|
+
*/
|
|
101
|
+
export function collectPyLockPackageProperties(pkg) {
|
|
102
|
+
const properties = [];
|
|
103
|
+
for (const akey of PYLOCK_PACKAGE_CUSTOM_KEYS) {
|
|
104
|
+
if (pkg?.[akey] !== undefined) {
|
|
105
|
+
properties.push({
|
|
106
|
+
name: `cdx:pylock:${akey.replaceAll("-", "_")}`,
|
|
107
|
+
value: toPropertyValue(pkg[akey]),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return properties;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Build file components from pylock source entries.
|
|
116
|
+
*
|
|
117
|
+
* @param {object} pkg pylock package entry
|
|
118
|
+
* @param {string} lockFile lock file path
|
|
119
|
+
* @returns {Array<object>} file components
|
|
120
|
+
*/
|
|
121
|
+
export function collectPyLockFileComponents(pkg, lockFile) {
|
|
122
|
+
const fileComponents = [];
|
|
123
|
+
if (pkg?.archive) {
|
|
124
|
+
const archiveComp = createArtifactComponent(
|
|
125
|
+
pkg.archive,
|
|
126
|
+
"archive",
|
|
127
|
+
lockFile,
|
|
128
|
+
pkg.name,
|
|
129
|
+
);
|
|
130
|
+
if (archiveComp) {
|
|
131
|
+
fileComponents.push(archiveComp);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (pkg?.sdist) {
|
|
135
|
+
const sdistComp = createArtifactComponent(
|
|
136
|
+
pkg.sdist,
|
|
137
|
+
"sdist",
|
|
138
|
+
lockFile,
|
|
139
|
+
pkg.name,
|
|
140
|
+
);
|
|
141
|
+
if (sdistComp) {
|
|
142
|
+
fileComponents.push(sdistComp);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (Array.isArray(pkg?.wheels)) {
|
|
146
|
+
for (const awheel of pkg.wheels) {
|
|
147
|
+
const wheelComp = createArtifactComponent(
|
|
148
|
+
awheel,
|
|
149
|
+
"wheel",
|
|
150
|
+
lockFile,
|
|
151
|
+
pkg.name,
|
|
152
|
+
);
|
|
153
|
+
if (wheelComp) {
|
|
154
|
+
fileComponents.push(wheelComp);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return fileComponents;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Check whether index points to the default pypi registry.
|
|
163
|
+
*
|
|
164
|
+
* @param {string} indexUrl index URL from pylock
|
|
165
|
+
* @returns {boolean} true for default pypi
|
|
166
|
+
*/
|
|
167
|
+
export function isDefaultPypiRegistry(indexUrl) {
|
|
168
|
+
if (!indexUrl) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
return DEFAULT_PYPI_REGISTRIES.has(indexUrl);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function createArtifactComponent(artifact, sourceType, lockFile, packageName) {
|
|
175
|
+
if (!artifact) {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
const properties = [{ name: "SrcFile", value: lockFile }];
|
|
179
|
+
properties.push({
|
|
180
|
+
name: "cdx:pylock:file:source_type",
|
|
181
|
+
value: sourceType,
|
|
182
|
+
});
|
|
183
|
+
if (artifact.url) {
|
|
184
|
+
properties.push({
|
|
185
|
+
name: "cdx:pylock:file:url",
|
|
186
|
+
value: artifact.url,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
if (artifact.path) {
|
|
190
|
+
properties.push({
|
|
191
|
+
name: "cdx:pylock:file:path",
|
|
192
|
+
value: artifact.path,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
if (artifact.size !== undefined) {
|
|
196
|
+
properties.push({
|
|
197
|
+
name: "cdx:pylock:file:size",
|
|
198
|
+
value: `${artifact.size}`,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
if (artifact["upload-time"]) {
|
|
202
|
+
properties.push({
|
|
203
|
+
name: "cdx:pylock:file:upload_time",
|
|
204
|
+
value: toPropertyValue(artifact["upload-time"]),
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
if (artifact.subdirectory) {
|
|
208
|
+
properties.push({
|
|
209
|
+
name: "cdx:pylock:file:subdirectory",
|
|
210
|
+
value: artifact.subdirectory,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
type: "file",
|
|
215
|
+
name: resolveArtifactName(artifact, packageName, sourceType),
|
|
216
|
+
hashes: toHashes(artifact.hashes),
|
|
217
|
+
properties,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function toHashes(hashesObj) {
|
|
222
|
+
if (!hashesObj || typeof hashesObj !== "object") {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
const hashes = [];
|
|
226
|
+
for (const [alg, content] of Object.entries(hashesObj)) {
|
|
227
|
+
if (!content) {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
const normalizedAlg = normalizeHashAlgorithm(alg);
|
|
231
|
+
hashes.push({ alg: normalizedAlg, content: `${content}` });
|
|
232
|
+
}
|
|
233
|
+
return hashes.length ? hashes : undefined;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function resolveArtifactName(artifact, packageName, sourceType) {
|
|
237
|
+
if (artifact.name) {
|
|
238
|
+
return artifact.name;
|
|
239
|
+
}
|
|
240
|
+
if (artifact.path) {
|
|
241
|
+
return basename(artifact.path);
|
|
242
|
+
}
|
|
243
|
+
if (artifact.url) {
|
|
244
|
+
try {
|
|
245
|
+
return basename(new URL(artifact.url).pathname);
|
|
246
|
+
} catch (_err) {
|
|
247
|
+
return `${packageName || "package"}-${sourceType}-invalid-url`;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return `${packageName || "package"}-${sourceType}`;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function normalizeHashAlgorithm(algorithm) {
|
|
254
|
+
const normalized = `${algorithm}`.toLowerCase();
|
|
255
|
+
if (normalized.startsWith("sha3")) {
|
|
256
|
+
return `SHA3-${normalized.slice(4).replace(/^[-_]/, "")}`;
|
|
257
|
+
}
|
|
258
|
+
if (normalized.startsWith("sha")) {
|
|
259
|
+
return `SHA-${normalized.slice(3).replace(/^[-_]/, "").toUpperCase()}`;
|
|
260
|
+
}
|
|
261
|
+
return normalized.toUpperCase();
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function toPropertyValue(value) {
|
|
265
|
+
if (value === null) {
|
|
266
|
+
return "null";
|
|
267
|
+
}
|
|
268
|
+
if (value === undefined) {
|
|
269
|
+
return "";
|
|
270
|
+
}
|
|
271
|
+
if (typeof value === "string") {
|
|
272
|
+
return value;
|
|
273
|
+
}
|
|
274
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
275
|
+
return `${value}`;
|
|
276
|
+
}
|
|
277
|
+
if (value instanceof Date) {
|
|
278
|
+
return value.toISOString();
|
|
279
|
+
}
|
|
280
|
+
return JSON.stringify(value);
|
|
281
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { assert, describe, it } from "poku";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
collectPyLockTopLevelProperties,
|
|
5
|
+
getPyLockPackages,
|
|
6
|
+
isPyLockFile,
|
|
7
|
+
isPyLockObject,
|
|
8
|
+
} from "./pylockutils.js";
|
|
9
|
+
|
|
10
|
+
describe("pylockutils", () => {
|
|
11
|
+
it("detects valid pylock file names", () => {
|
|
12
|
+
assert.ok(isPyLockFile("/tmp/pylock.toml"));
|
|
13
|
+
assert.ok(isPyLockFile("/tmp/pylock.api.toml"));
|
|
14
|
+
assert.ok(!isPyLockFile("/tmp/poetry.lock"));
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("detects pylock object shape and packages", () => {
|
|
18
|
+
const pylockData = {
|
|
19
|
+
"lock-version": "1.0",
|
|
20
|
+
packages: [{ name: "attrs", version: "1.0.0" }],
|
|
21
|
+
};
|
|
22
|
+
assert.ok(isPyLockObject(pylockData));
|
|
23
|
+
assert.deepStrictEqual(getPyLockPackages(pylockData).length, 1);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("collects pylock top-level custom properties", () => {
|
|
27
|
+
const properties = collectPyLockTopLevelProperties({
|
|
28
|
+
"lock-version": "1.0",
|
|
29
|
+
"requires-python": ">=3.11",
|
|
30
|
+
"created-by": "uv",
|
|
31
|
+
});
|
|
32
|
+
assert.ok(
|
|
33
|
+
properties.some(
|
|
34
|
+
(p) => p.name === "cdx:pylock:lock_version" && p.value === "1.0",
|
|
35
|
+
),
|
|
36
|
+
);
|
|
37
|
+
assert.ok(
|
|
38
|
+
properties.some(
|
|
39
|
+
(p) => p.name === "cdx:pylock:requires_python" && p.value === ">=3.11",
|
|
40
|
+
),
|
|
41
|
+
);
|
|
42
|
+
assert.ok(
|
|
43
|
+
properties.some(
|
|
44
|
+
(p) => p.name === "cdx:pylock:created_by" && p.value === "uv",
|
|
45
|
+
),
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
});
|