@visulima/vis 1.0.0-alpha.11 → 1.0.0-alpha.13

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 (116) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/LICENSE.md +559 -186
  3. package/README.md +18 -0
  4. package/dist/bin.js +1 -9
  5. package/dist/config/index.d.ts +477 -556
  6. package/dist/config/index.js +1 -2
  7. package/dist/generate/index.js +1 -3
  8. package/dist/packem_chunks/applyDefaults.js +2 -336
  9. package/dist/packem_chunks/bin.js +234 -9552
  10. package/dist/packem_chunks/doctor-probe.js +2 -112
  11. package/dist/packem_chunks/fix.js +11 -234
  12. package/dist/packem_chunks/handler.js +1 -99
  13. package/dist/packem_chunks/handler10.js +2 -53
  14. package/dist/packem_chunks/handler11.js +1 -32
  15. package/dist/packem_chunks/handler12.js +5 -100
  16. package/dist/packem_chunks/handler13.js +1 -25
  17. package/dist/packem_chunks/handler14.js +18 -916
  18. package/dist/packem_chunks/handler15.js +15 -201
  19. package/dist/packem_chunks/handler16.js +1 -124
  20. package/dist/packem_chunks/handler17.js +1 -13
  21. package/dist/packem_chunks/handler18.js +1 -106
  22. package/dist/packem_chunks/handler19.js +1 -19
  23. package/dist/packem_chunks/handler2.js +2 -75
  24. package/dist/packem_chunks/handler20.js +5 -29
  25. package/dist/packem_chunks/handler21.js +1 -222
  26. package/dist/packem_chunks/handler22.js +1 -237
  27. package/dist/packem_chunks/handler23.js +5 -101
  28. package/dist/packem_chunks/handler24.js +1 -110
  29. package/dist/packem_chunks/handler25.js +3 -402
  30. package/dist/packem_chunks/handler26.js +1 -13
  31. package/dist/packem_chunks/handler27.js +1 -63
  32. package/dist/packem_chunks/handler28.js +7 -34
  33. package/dist/packem_chunks/handler29.js +21 -456
  34. package/dist/packem_chunks/handler3.js +4 -95
  35. package/dist/packem_chunks/handler30.js +3 -170
  36. package/dist/packem_chunks/handler31.js +1 -530
  37. package/dist/packem_chunks/handler32.js +2 -214
  38. package/dist/packem_chunks/handler33.js +25 -119
  39. package/dist/packem_chunks/handler34.js +2 -630
  40. package/dist/packem_chunks/handler35.js +3 -283
  41. package/dist/packem_chunks/handler36.js +22 -542
  42. package/dist/packem_chunks/handler37.js +410 -744
  43. package/dist/packem_chunks/handler38.js +22 -989
  44. package/dist/packem_chunks/handler39.js +22 -574
  45. package/dist/packem_chunks/handler4.js +2 -90
  46. package/dist/packem_chunks/handler40.js +22 -1685
  47. package/dist/packem_chunks/handler41.js +6 -1088
  48. package/dist/packem_chunks/handler42.js +5 -797
  49. package/dist/packem_chunks/handler43.js +10 -2658
  50. package/dist/packem_chunks/handler44.js +51 -3784
  51. package/dist/packem_chunks/handler45.js +25 -2574
  52. package/dist/packem_chunks/handler46.js +3 -3769
  53. package/dist/packem_chunks/handler47.js +21 -1485
  54. package/dist/packem_chunks/handler48.js +42 -0
  55. package/dist/packem_chunks/handler5.js +8 -174
  56. package/dist/packem_chunks/handler6.js +1 -95
  57. package/dist/packem_chunks/handler7.js +1 -115
  58. package/dist/packem_chunks/handler8.js +1 -12
  59. package/dist/packem_chunks/handler9.js +1 -29
  60. package/dist/packem_chunks/heal-accept.js +10 -522
  61. package/dist/packem_chunks/heal.js +14 -673
  62. package/dist/packem_chunks/index.js +7 -873
  63. package/dist/packem_chunks/loader.js +1 -23
  64. package/dist/packem_chunks/tar.js +3 -0
  65. package/dist/packem_shared/ai-analysis-hm8d2W7z.js +67 -0
  66. package/dist/packem_shared/ai-cache-DoiF80AR.js +1 -0
  67. package/dist/packem_shared/ai-fix-nn4zOE95.js +43 -0
  68. package/dist/packem_shared/cache-directory-CwHlJhgx.js +1 -0
  69. package/dist/packem_shared/dependency-scan-COr5n63B.js +2 -0
  70. package/dist/packem_shared/docker-D6OGr5_S.js +2 -0
  71. package/dist/packem_shared/failure-log-iUVLf6ts.js +2 -0
  72. package/dist/packem_shared/flakiness-D9wf0t56.js +1 -0
  73. package/dist/packem_shared/giget-CcEy_Elm.js +2 -0
  74. package/dist/packem_shared/index-DH-5hsrC.js +1 -0
  75. package/dist/packem_shared/otel-DxDUPJJH.js +6 -0
  76. package/dist/packem_shared/otelPlugin-CQq6poq8.js +1 -0
  77. package/dist/packem_shared/registry-CkubDdiY.js +2 -0
  78. package/dist/packem_shared/run-summary-utils-BfBvjzhY.js +1 -0
  79. package/dist/packem_shared/runtime-check-BXZ43CBW.js +1 -0
  80. package/dist/packem_shared/selectors-BylODRiM.js +3 -0
  81. package/dist/packem_shared/symbols-CQmER5MT.js +1 -0
  82. package/dist/packem_shared/toolchain-BgBOUHII.js +5 -0
  83. package/dist/packem_shared/typosquats-CcZl99B1.js +1 -0
  84. package/dist/packem_shared/use-measured-height-DjYgUOKk.js +1 -0
  85. package/dist/packem_shared/utils-DrNg0XTR.js +1 -0
  86. package/dist/packem_shared/verify-Baj5mFJ7.js +1 -0
  87. package/dist/packem_shared/vis-update-app-D1jl0UZZ.js +1 -0
  88. package/dist/packem_shared/xxh3-DrAUNq4n.js +1 -0
  89. package/index.js +556 -727
  90. package/package.json +19 -29
  91. package/schemas/project.schema.json +739 -297
  92. package/schemas/vis-config.schema.json +3365 -384
  93. package/templates/buildkite-ci/template.yml +20 -20
  94. package/dist/packem_shared/VisUpdateApp-D-Yz_wvg.js +0 -1316
  95. package/dist/packem_shared/_commonjsHelpers-BqLXS_qQ.js +0 -5
  96. package/dist/packem_shared/ai-analysis-CHeB1joD.js +0 -367
  97. package/dist/packem_shared/ai-cache-Be_jexe4.js +0 -142
  98. package/dist/packem_shared/ai-fix-B9iQVcD2.js +0 -379
  99. package/dist/packem_shared/cache-directory-2qvs4goY.js +0 -98
  100. package/dist/packem_shared/catalog-BJTtyi-O.js +0 -1371
  101. package/dist/packem_shared/dependency-scan-A0KSklpG.js +0 -188
  102. package/dist/packem_shared/docker-2iZzc280.js +0 -181
  103. package/dist/packem_shared/failure-log-Cz3Z4SKL.js +0 -100
  104. package/dist/packem_shared/flakiness-goTxXuCX.js +0 -180
  105. package/dist/packem_shared/otel-DCvqCTz_.js +0 -158
  106. package/dist/packem_shared/otelPlugin-DFaLDvJf.js +0 -3
  107. package/dist/packem_shared/registry-CbqXI0rc.js +0 -272
  108. package/dist/packem_shared/run-summary-utils-PVMl4aIh.js +0 -130
  109. package/dist/packem_shared/runtime-check-Cobi3p6l.js +0 -127
  110. package/dist/packem_shared/selectors-SM69TfqC.js +0 -194
  111. package/dist/packem_shared/symbols-Ta7g2nU-.js +0 -14
  112. package/dist/packem_shared/toolchain-BdZd9eBi.js +0 -975
  113. package/dist/packem_shared/typosquats-C-bCh3PX.js +0 -1210
  114. package/dist/packem_shared/use-measured-height-CNP0vT4M.js +0 -20
  115. package/dist/packem_shared/utils-CthVdBPS.js +0 -40
  116. package/dist/packem_shared/xxh3-Ck8mXNg1.js +0 -239
@@ -1,797 +1,5 @@
1
- import { createRequire as __cjs_createRequire } from "node:module";
2
-
3
- const __cjs_require = __cjs_createRequire(import.meta.url);
4
-
5
- const __cjs_getProcess = typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" ? globalThis.process : process;
6
-
7
- const __cjs_getBuiltinModule = (module) => {
8
- // Check if we're in Node.js and version supports getBuiltinModule
9
- if (typeof __cjs_getProcess !== "undefined" && __cjs_getProcess.versions && __cjs_getProcess.versions.node) {
10
- const [major, minor] = __cjs_getProcess.versions.node.split(".").map(Number);
11
- // Node.js 20.16.0+ and 22.3.0+
12
- if (major > 22 || (major === 22 && minor >= 3) || (major === 20 && minor >= 16)) {
13
- return __cjs_getProcess.getBuiltinModule(module);
14
- }
15
- }
16
- // Fallback to createRequire
17
- return __cjs_require(module);
18
- };
19
-
20
- const {
21
- readdirSync,
22
- writeFileSync
23
- } = __cjs_getBuiltinModule("node:fs");
24
- import { readJsonSync, readFileSync, ensureDirSync } from '@visulima/fs';
25
- import { join, resolve, dirname } from '@visulima/path';
26
- import { d as discoverWorkspace, b as buildProjectGraph, p as pail } from './bin.js';
27
- const {
28
- randomUUID
29
- } = __cjs_getBuiltinModule("node:crypto");
30
- import { toXML } from 'jstoxml';
31
- import { r as resolveFocusProjects } from '../packem_shared/docker-2iZzc280.js';
32
- import { parseLockFileContent } from '@visulima/package';
33
- import semver from 'semver';
34
-
35
- const readJsonSafe = (path) => {
36
- try {
37
- return readJsonSync(path);
38
- } catch {
39
- return void 0;
40
- }
41
- };
42
- const isSafePackageName = (name) => {
43
- if (name.length === 0 || name.includes("..") || name.startsWith(".") || name.includes("\0") || name.includes("\\")) {
44
- return false;
45
- }
46
- if (name.startsWith("@")) {
47
- const slashIndex = name.indexOf("/");
48
- return slashIndex > 1 && !name.includes("/", slashIndex + 1);
49
- }
50
- return !name.includes("/");
51
- };
52
- const isSafeVersion = (version) => version.length > 0 && !version.includes("/") && !version.includes("\\") && !version.includes("..") && !version.includes("\0");
53
- const readPnpmVirtualStore = (workspaceRoot, name, version) => {
54
- const encodedName = name.replaceAll("/", "+");
55
- const exactDir = `${encodedName}@${version}`;
56
- const pnpmRoot = join(workspaceRoot, "node_modules", ".pnpm");
57
- const exact = readJsonSafe(join(pnpmRoot, exactDir, "node_modules", name, "package.json"));
58
- if (exact) {
59
- return exact;
60
- }
61
- let directories;
62
- try {
63
- directories = readdirSync(pnpmRoot);
64
- } catch {
65
- return void 0;
66
- }
67
- const prefix = `${exactDir}_`;
68
- for (const directory of directories) {
69
- if (!directory.startsWith(prefix)) {
70
- continue;
71
- }
72
- const metadata = readJsonSafe(join(pnpmRoot, directory, "node_modules", name, "package.json"));
73
- if (metadata) {
74
- return metadata;
75
- }
76
- }
77
- return void 0;
78
- };
79
- const readHoistedCopy = (workspaceRoot, name, version) => {
80
- const metadata = readJsonSafe(join(workspaceRoot, "node_modules", name, "package.json"));
81
- return metadata?.version === version ? metadata : void 0;
82
- };
83
- const readInstalledPackageMetadata = (workspaceRoot, name, version) => {
84
- if (!isSafePackageName(name) || !isSafeVersion(version)) {
85
- return void 0;
86
- }
87
- return readPnpmVirtualStore(workspaceRoot, name, version) ?? readHoistedCopy(workspaceRoot, name, version);
88
- };
89
-
90
- const KNOWN_SPDX_IDS = /* @__PURE__ */ new Set([
91
- "0BSD",
92
- "AGPL-3.0",
93
- "AGPL-3.0-only",
94
- "AGPL-3.0-or-later",
95
- "Apache-1.1",
96
- "Apache-2.0",
97
- "Artistic-2.0",
98
- "BlueOak-1.0.0",
99
- "BSD-2-Clause",
100
- "BSD-3-Clause",
101
- "BSL-1.0",
102
- "CC0-1.0",
103
- "CC-BY-3.0",
104
- "CC-BY-4.0",
105
- "CDDL-1.0",
106
- "CDDL-1.1",
107
- "EPL-1.0",
108
- "EPL-2.0",
109
- "GPL-2.0",
110
- "GPL-2.0-only",
111
- "GPL-2.0-or-later",
112
- "GPL-3.0",
113
- "GPL-3.0-only",
114
- "GPL-3.0-or-later",
115
- "ISC",
116
- "LGPL-2.0",
117
- "LGPL-2.1",
118
- "LGPL-3.0",
119
- "MIT",
120
- "MIT-0",
121
- "MPL-1.1",
122
- "MPL-2.0",
123
- "Python-2.0",
124
- "Unlicense",
125
- "WTFPL",
126
- "Zlib"
127
- ]);
128
- const SPDX_ALIASES = {
129
- apache2: "Apache-2.0",
130
- "apache 2.0": "Apache-2.0",
131
- bsd: "BSD-3-Clause",
132
- "bsd-2": "BSD-2-Clause",
133
- "bsd-3": "BSD-3-Clause",
134
- mit: "MIT",
135
- public: "Unlicense",
136
- "public domain": "Unlicense"
137
- };
138
- const LOWERCASE_SPDX_LOOKUP = (() => {
139
- const map = /* @__PURE__ */ new Map();
140
- for (const id of KNOWN_SPDX_IDS) {
141
- map.set(id.toLowerCase(), id);
142
- }
143
- for (const [alias, canonical] of Object.entries(SPDX_ALIASES)) {
144
- map.set(alias, canonical);
145
- }
146
- return map;
147
- })();
148
- const normalizeSpdxId = (raw) => {
149
- const trimmed = raw.trim();
150
- if (trimmed.length === 0) {
151
- return void 0;
152
- }
153
- if (KNOWN_SPDX_IDS.has(trimmed)) {
154
- return trimmed;
155
- }
156
- return LOWERCASE_SPDX_LOOKUP.get(trimmed.toLowerCase());
157
- };
158
- const extractLicenseChoice = (input) => {
159
- let rawValue;
160
- if (typeof input.license === "string") {
161
- rawValue = input.license;
162
- } else if (input.license && typeof input.license === "object" && typeof input.license.type === "string") {
163
- rawValue = input.license.type;
164
- } else if (Array.isArray(input.licenses) && input.licenses.length > 0) {
165
- const first = input.licenses[0];
166
- if (first && typeof first.type === "string") {
167
- rawValue = first.type;
168
- }
169
- }
170
- if (!rawValue) {
171
- return void 0;
172
- }
173
- const trimmed = rawValue.trim();
174
- if (trimmed.length === 0) {
175
- return void 0;
176
- }
177
- if (/[()]|\b(and|or|with)\b/i.test(trimmed)) {
178
- return [{ expression: trimmed }];
179
- }
180
- const spdxId = normalizeSpdxId(trimmed);
181
- if (spdxId) {
182
- return [{ license: { id: spdxId } }];
183
- }
184
- return [{ license: { name: trimmed } }];
185
- };
186
-
187
- const SRI_TO_CYCLONEDX_ALG = {
188
- sha256: "SHA-256",
189
- sha384: "SHA-384",
190
- sha512: "SHA-512"
191
- };
192
- const SRI_HEX_LENGTH = {
193
- sha256: 64,
194
- sha384: 96,
195
- sha512: 128
196
- };
197
- const toResolvedPackage = (entry) => {
198
- const resolved = { name: entry.name, version: entry.version };
199
- const { integrity } = entry;
200
- if (integrity && integrity.hex.length === SRI_HEX_LENGTH[integrity.algorithm]) {
201
- resolved.hash = {
202
- alg: SRI_TO_CYCLONEDX_ALG[integrity.algorithm],
203
- content: integrity.hex
204
- };
205
- }
206
- if (entry.dependencies) {
207
- resolved.dependencies = entry.dependencies;
208
- }
209
- if (entry.peerDependencies) {
210
- resolved.peerDependencies = entry.peerDependencies;
211
- }
212
- if (entry.optionalDependencies) {
213
- resolved.optionalDependencies = entry.optionalDependencies;
214
- }
215
- return resolved;
216
- };
217
- const LOCKFILE_CANDIDATES = [
218
- { file: "pnpm-lock.yaml", type: "pnpm" },
219
- { file: "package-lock.json", type: "npm" },
220
- { file: "yarn.lock", type: "yarn" },
221
- { file: "bun.lock", type: "bun" }
222
- ];
223
- const readLockfilePackages = (workspaceRoot) => {
224
- for (const { file, type } of LOCKFILE_CANDIDATES) {
225
- let content;
226
- try {
227
- content = readFileSync(join(workspaceRoot, file));
228
- } catch {
229
- continue;
230
- }
231
- const packages = /* @__PURE__ */ new Map();
232
- for (const entry of parseLockFileContent(content, type)) {
233
- packages.set(`${entry.name}@${entry.version}`, toResolvedPackage(entry));
234
- }
235
- return { packages, type };
236
- }
237
- return void 0;
238
- };
239
-
240
- const encodeSegment = (input) => input.replaceAll(/[^\w.~-]/g, (char) => {
241
- const codePoint = char.codePointAt(0) ?? 0;
242
- return `%${codePoint.toString(16).toUpperCase().padStart(2, "0")}`;
243
- });
244
- const toNpmPurl = (packageName, version) => {
245
- const lowered = packageName.toLowerCase();
246
- if (lowered.startsWith("@")) {
247
- const slashIndex = lowered.indexOf("/");
248
- if (slashIndex > 0) {
249
- const namespace = lowered.slice(0, slashIndex);
250
- const name = lowered.slice(slashIndex + 1);
251
- return `pkg:npm/${encodeSegment(namespace)}/${encodeSegment(name)}@${encodeSegment(version)}`;
252
- }
253
- }
254
- return `pkg:npm/${encodeSegment(lowered)}@${encodeSegment(version)}`;
255
- };
256
-
257
- const stripProtocolPrefix = (specifier) => {
258
- const colonIndex = specifier.indexOf(":");
259
- if (colonIndex <= 0) {
260
- return specifier;
261
- }
262
- const prefix = specifier.slice(0, colonIndex);
263
- return prefix === "npm" ? specifier.slice(colonIndex + 1) : specifier;
264
- };
265
- const resolveSpecifier = (name, specifier, index) => {
266
- const versions = index.get(name);
267
- if (!versions || versions.size === 0) {
268
- return void 0;
269
- }
270
- if (versions.has(specifier)) {
271
- return specifier;
272
- }
273
- const stripped = stripProtocolPrefix(specifier);
274
- if (stripped !== specifier && versions.has(stripped)) {
275
- return stripped;
276
- }
277
- const list = [...versions];
278
- const best = semver.maxSatisfying(list, stripped, { includePrerelease: true });
279
- if (best) {
280
- return best;
281
- }
282
- return list[0];
283
- };
284
-
285
- const CYCLONEDX_SPEC_VERSION = "1.6";
286
- const CYCLONEDX_BOM_FORMAT = "CycloneDX";
287
- const CYCLONEDX_SCHEMA_URL = "http://cyclonedx.org/schema/bom-1.6.schema.json";
288
- const GENERATOR_NAME = "@visulima/vis";
289
- const readPackageJson = (path) => {
290
- try {
291
- return readJsonSync(path);
292
- } catch {
293
- return void 0;
294
- }
295
- };
296
- const toAuthorString = (author) => {
297
- if (!author) {
298
- return void 0;
299
- }
300
- if (typeof author === "string") {
301
- return author;
302
- }
303
- if (typeof author === "object" && author.name) {
304
- return author.email ? `${author.name} <${author.email}>` : author.name;
305
- }
306
- return void 0;
307
- };
308
- const toRepositoryUrl = (repository) => {
309
- if (!repository) {
310
- return void 0;
311
- }
312
- if (typeof repository === "string") {
313
- return repository;
314
- }
315
- return repository.url;
316
- };
317
- const toBugsUrl = (bugs) => {
318
- if (!bugs) {
319
- return void 0;
320
- }
321
- if (typeof bugs === "string") {
322
- return bugs;
323
- }
324
- return bugs.url;
325
- };
326
- const buildExternalReferences = (pkg) => {
327
- const references = [];
328
- if (pkg.homepage) {
329
- references.push({ type: "website", url: pkg.homepage });
330
- }
331
- const vcs = toRepositoryUrl(pkg.repository);
332
- if (vcs) {
333
- references.push({ type: "vcs", url: vcs });
334
- }
335
- const issues = toBugsUrl(pkg.bugs);
336
- if (issues) {
337
- references.push({ type: "issue-tracker", url: issues });
338
- }
339
- return references.length > 0 ? references : void 0;
340
- };
341
- const decoratePackageComponent = (component, pkg) => {
342
- if (!pkg) {
343
- return;
344
- }
345
- if (pkg.description) {
346
- component.description = pkg.description;
347
- }
348
- const author = toAuthorString(pkg.author);
349
- if (author) {
350
- component.author = author;
351
- }
352
- const license = extractLicenseChoice(pkg);
353
- if (license) {
354
- component.licenses = license;
355
- }
356
- const references = buildExternalReferences(pkg);
357
- if (references) {
358
- component.externalReferences = references;
359
- }
360
- };
361
- const buildCycloneDxBom = (options) => {
362
- const { focus, generatorVersion, includeDev = false, now = /* @__PURE__ */ new Date(), projectGraph, serialNumber, workspace, workspaceRoot } = options;
363
- const projectNames = focus && focus.length > 0 ? [...resolveFocusProjects(focus, projectGraph)].sort() : Object.keys(workspace.projects).sort();
364
- const inScope = new Set(projectNames);
365
- const projectPackages = /* @__PURE__ */ new Map();
366
- for (const name of projectNames) {
367
- const projectConfig = workspace.projects[name];
368
- if (projectConfig) {
369
- projectPackages.set(name, readPackageJson(join(workspaceRoot, projectConfig.root, "package.json")));
370
- }
371
- }
372
- const projectComponents = [];
373
- const projectBomRefs = /* @__PURE__ */ new Map();
374
- for (const name of projectNames) {
375
- const projectConfig = workspace.projects[name];
376
- if (!projectConfig) {
377
- continue;
378
- }
379
- const pkg = projectPackages.get(name);
380
- const version = pkg?.version ?? "0.0.0";
381
- const bomRef = toNpmPurl(name, version);
382
- projectBomRefs.set(name, bomRef);
383
- const component = {
384
- "bom-ref": bomRef,
385
- name,
386
- purl: bomRef,
387
- type: projectConfig.projectType === "application" ? "application" : "library",
388
- version
389
- };
390
- decoratePackageComponent(component, pkg);
391
- projectComponents.push(component);
392
- }
393
- const lockfile = readLockfilePackages(workspaceRoot);
394
- const lockfileByRef = /* @__PURE__ */ new Map();
395
- const versionIndex = /* @__PURE__ */ new Map();
396
- if (lockfile) {
397
- for (const pkg of lockfile.packages.values()) {
398
- lockfileByRef.set(`${pkg.name}@${pkg.version}`, pkg);
399
- let versions = versionIndex.get(pkg.name);
400
- if (!versions) {
401
- versions = /* @__PURE__ */ new Set();
402
- versionIndex.set(pkg.name, versions);
403
- }
404
- versions.add(pkg.version);
405
- }
406
- }
407
- const requiredSeed = [];
408
- const optionalSeed = [];
409
- const directDepEdges = /* @__PURE__ */ new Map();
410
- for (const name of projectNames) {
411
- const pkg = projectPackages.get(name);
412
- if (!pkg) {
413
- continue;
414
- }
415
- const requiredMaps = [pkg.dependencies, pkg.peerDependencies];
416
- if (includeDev) {
417
- requiredMaps.push(pkg.devDependencies);
418
- }
419
- const edges = /* @__PURE__ */ new Set();
420
- const seedRef = (target, depMap) => {
421
- if (!depMap) {
422
- return;
423
- }
424
- for (const [depName, specifier] of Object.entries(depMap)) {
425
- if (inScope.has(depName)) {
426
- const ref = projectBomRefs.get(depName);
427
- if (ref) {
428
- edges.add(ref);
429
- }
430
- continue;
431
- }
432
- const resolvedVersion = resolveSpecifier(depName, specifier, versionIndex);
433
- if (resolvedVersion) {
434
- edges.add(toNpmPurl(depName, resolvedVersion));
435
- target.push(`${depName}@${resolvedVersion}`);
436
- }
437
- }
438
- };
439
- for (const depMap of requiredMaps) {
440
- seedRef(requiredSeed, depMap);
441
- }
442
- seedRef(optionalSeed, pkg.optionalDependencies);
443
- directDepEdges.set(name, edges);
444
- }
445
- const reachableRegistryRefs = /* @__PURE__ */ new Map();
446
- const registryDepEdges = /* @__PURE__ */ new Map();
447
- const walk = (seeds, scope) => {
448
- const queue = [...seeds];
449
- while (queue.length > 0) {
450
- const ref = queue.pop();
451
- const existing = reachableRegistryRefs.get(ref);
452
- if (existing === "required" || existing === "optional" && scope === "optional") {
453
- continue;
454
- }
455
- reachableRegistryRefs.set(ref, scope);
456
- const entry = lockfileByRef.get(ref);
457
- if (!entry) {
458
- continue;
459
- }
460
- const outgoing = registryDepEdges.get(ref) ?? /* @__PURE__ */ new Set();
461
- const inheritedMaps = [entry.dependencies, entry.peerDependencies];
462
- for (const depMap of inheritedMaps) {
463
- if (!depMap) {
464
- continue;
465
- }
466
- for (const [depName, specifiers] of Object.entries(depMap)) {
467
- for (const specifier of specifiers) {
468
- const resolvedVersion = resolveSpecifier(depName, specifier, versionIndex);
469
- if (!resolvedVersion) {
470
- continue;
471
- }
472
- outgoing.add(toNpmPurl(depName, resolvedVersion));
473
- queue.push(`${depName}@${resolvedVersion}`);
474
- }
475
- }
476
- }
477
- if (entry.optionalDependencies) {
478
- for (const [depName, specifiers] of Object.entries(entry.optionalDependencies)) {
479
- for (const specifier of specifiers) {
480
- const resolvedVersion = resolveSpecifier(depName, specifier, versionIndex);
481
- if (!resolvedVersion) {
482
- continue;
483
- }
484
- outgoing.add(toNpmPurl(depName, resolvedVersion));
485
- optionalSeed.push(`${depName}@${resolvedVersion}`);
486
- }
487
- }
488
- }
489
- if (outgoing.size > 0) {
490
- registryDepEdges.set(ref, outgoing);
491
- }
492
- }
493
- };
494
- walk(requiredSeed, "required");
495
- walk(optionalSeed, "optional");
496
- const registryComponents = [];
497
- const sortedRefs = [...reachableRegistryRefs.keys()].sort();
498
- for (const ref of sortedRefs) {
499
- const pkg = lockfileByRef.get(ref);
500
- if (!pkg) {
501
- continue;
502
- }
503
- const purl = toNpmPurl(pkg.name, pkg.version);
504
- const component = {
505
- "bom-ref": purl,
506
- name: pkg.name,
507
- purl,
508
- scope: reachableRegistryRefs.get(ref) ?? "required",
509
- type: "library",
510
- version: pkg.version
511
- };
512
- if (pkg.hash) {
513
- component.hashes = [pkg.hash];
514
- }
515
- decoratePackageComponent(component, readInstalledPackageMetadata(workspaceRoot, pkg.name, pkg.version));
516
- registryComponents.push(component);
517
- }
518
- const dependencies = [];
519
- for (const [projectName, edges] of directDepEdges) {
520
- const ref = projectBomRefs.get(projectName);
521
- if (!ref) {
522
- continue;
523
- }
524
- const dependsOn = [...edges].sort();
525
- dependencies.push(dependsOn.length > 0 ? { dependsOn, ref } : { ref });
526
- }
527
- for (const ref of sortedRefs) {
528
- const pkg = lockfileByRef.get(ref);
529
- if (!pkg) {
530
- continue;
531
- }
532
- const purl = toNpmPurl(pkg.name, pkg.version);
533
- const outgoing = registryDepEdges.get(ref);
534
- const dependsOn = outgoing ? [...outgoing].sort() : [];
535
- dependencies.push(dependsOn.length > 0 ? { dependsOn, ref: purl } : { ref: purl });
536
- }
537
- dependencies.sort((a, b) => a.ref.localeCompare(b.ref));
538
- const rootPkg = readPackageJson(join(workspaceRoot, "package.json"));
539
- const metadataComponent = (() => {
540
- if (focus?.length === 1) {
541
- const match = projectComponents.find((component2) => component2.name === focus[0]);
542
- if (match) {
543
- return {
544
- "bom-ref": match["bom-ref"],
545
- name: match.name,
546
- purl: match.purl,
547
- type: match.type,
548
- version: match.version
549
- };
550
- }
551
- }
552
- const rootName = rootPkg?.name ?? "workspace";
553
- const rootVersion = rootPkg?.version ?? "0.0.0";
554
- const rootRef = toNpmPurl(rootName, rootVersion);
555
- const component = {
556
- "bom-ref": rootRef,
557
- name: rootName,
558
- purl: rootRef,
559
- type: "application",
560
- version: rootVersion
561
- };
562
- decoratePackageComponent(component, rootPkg);
563
- return component;
564
- })();
565
- const metadataRef = metadataComponent["bom-ref"];
566
- const filteredProjectComponents = metadataRef ? projectComponents.filter((component) => component["bom-ref"] !== metadataRef) : projectComponents;
567
- return {
568
- $schema: CYCLONEDX_SCHEMA_URL,
569
- bomFormat: CYCLONEDX_BOM_FORMAT,
570
- components: [...filteredProjectComponents, ...registryComponents],
571
- dependencies,
572
- metadata: {
573
- component: metadataComponent,
574
- lifecycles: [{ phase: "build" }],
575
- timestamp: now.toISOString(),
576
- tools: {
577
- components: [
578
- {
579
- name: GENERATOR_NAME,
580
- type: "application",
581
- ...generatorVersion ? { version: generatorVersion } : {}
582
- }
583
- ]
584
- }
585
- },
586
- serialNumber: serialNumber ?? `urn:uuid:${randomUUID()}`,
587
- specVersion: CYCLONEDX_SPEC_VERSION,
588
- version: 1
589
- };
590
- };
591
- const serializeBomToXml = (bom) => {
592
- const rootAttributes = {
593
- version: bom.version ?? 1,
594
- xmlns: "http://cyclonedx.org/schema/bom/1.6"
595
- };
596
- if (bom.serialNumber) {
597
- rootAttributes.serialNumber = bom.serialNumber;
598
- }
599
- const content = [];
600
- if (bom.metadata) {
601
- content.push(metadataToXmlElement(bom.metadata));
602
- }
603
- if (bom.components && bom.components.length > 0) {
604
- content.push({
605
- _content: bom.components.map(componentToXmlElement),
606
- _name: "components"
607
- });
608
- }
609
- if (bom.dependencies && bom.dependencies.length > 0) {
610
- content.push({
611
- _content: bom.dependencies.map(dependencyToXmlElement),
612
- _name: "dependencies"
613
- });
614
- }
615
- const xml = toXML(
616
- {
617
- _attrs: rootAttributes,
618
- _content: content,
619
- _name: "bom"
620
- },
621
- {
622
- header: true,
623
- indent: " ",
624
- selfCloseTags: true
625
- }
626
- );
627
- return `${xml}
628
- `;
629
- };
630
- const metadataToXmlElement = (metadata) => {
631
- const children = [];
632
- if (metadata.timestamp) {
633
- children.push({ timestamp: metadata.timestamp });
634
- }
635
- if (metadata.lifecycles && metadata.lifecycles.length > 0) {
636
- children.push({
637
- _content: metadata.lifecycles.map((lifecycle) => {
638
- const entries = [];
639
- if (lifecycle.phase) {
640
- entries.push({ phase: lifecycle.phase });
641
- }
642
- if (lifecycle.name) {
643
- entries.push({ name: lifecycle.name });
644
- }
645
- if (lifecycle.description) {
646
- entries.push({ description: lifecycle.description });
647
- }
648
- return { _content: entries, _name: "lifecycle" };
649
- }),
650
- _name: "lifecycles"
651
- });
652
- }
653
- if (metadata.tools?.components) {
654
- children.push({
655
- _content: [
656
- {
657
- _content: metadata.tools.components.map(componentToXmlElement),
658
- _name: "components"
659
- }
660
- ],
661
- _name: "tools"
662
- });
663
- }
664
- if (metadata.component) {
665
- children.push(componentToXmlElement(metadata.component));
666
- }
667
- return { _content: children, _name: "metadata" };
668
- };
669
- const componentToXmlElement = (component) => {
670
- const attributes = { type: component.type };
671
- if (component["bom-ref"]) {
672
- attributes["bom-ref"] = component["bom-ref"];
673
- }
674
- const children = [];
675
- if (component.group) {
676
- children.push({ group: component.group });
677
- }
678
- children.push({ name: component.name });
679
- if (component.version) {
680
- children.push({ version: component.version });
681
- }
682
- if (component.description) {
683
- children.push({ description: component.description });
684
- }
685
- if (component.author) {
686
- children.push({ author: component.author });
687
- }
688
- if (component.hashes && component.hashes.length > 0) {
689
- children.push({
690
- _content: component.hashes.map((hash) => {
691
- return {
692
- _attrs: { alg: hash.alg },
693
- _content: hash.content,
694
- _name: "hash"
695
- };
696
- }),
697
- _name: "hashes"
698
- });
699
- }
700
- const licenses = licensesToXmlElement(component.licenses);
701
- if (licenses) {
702
- children.push(licenses);
703
- }
704
- if (component.purl) {
705
- children.push({ purl: component.purl });
706
- }
707
- if (component.scope) {
708
- children.push({ scope: component.scope });
709
- }
710
- if (component.externalReferences && component.externalReferences.length > 0) {
711
- children.push({
712
- _content: component.externalReferences.map((reference) => {
713
- return {
714
- _attrs: { type: reference.type },
715
- _content: [{ url: reference.url }],
716
- _name: "reference"
717
- };
718
- }),
719
- _name: "externalReferences"
720
- });
721
- }
722
- return { _attrs: attributes, _content: children, _name: "component" };
723
- };
724
- const licensesToXmlElement = (licenses) => {
725
- if (!licenses || licenses.length === 0) {
726
- return void 0;
727
- }
728
- const entries = [];
729
- for (const entry of licenses) {
730
- if ("expression" in entry) {
731
- entries.push({ expression: entry.expression });
732
- continue;
733
- }
734
- const licenseChildren = [];
735
- if ("id" in entry.license && entry.license.id) {
736
- licenseChildren.push({ id: entry.license.id });
737
- } else if ("name" in entry.license && entry.license.name) {
738
- licenseChildren.push({ name: entry.license.name });
739
- }
740
- entries.push({ _content: licenseChildren, _name: "license" });
741
- }
742
- return { _content: entries, _name: "licenses" };
743
- };
744
- const dependencyToXmlElement = (dep) => {
745
- if (dep.dependsOn && dep.dependsOn.length > 0) {
746
- return {
747
- _attrs: { ref: dep.ref },
748
- _content: dep.dependsOn.map((child) => {
749
- return {
750
- _attrs: { ref: child },
751
- _name: "dependency"
752
- };
753
- }),
754
- _name: "dependency"
755
- };
756
- }
757
- return { _attrs: { ref: dep.ref }, _name: "dependency" };
758
- };
759
-
760
- const SBOM_FORMATS = ["json", "xml"];
761
- const isSbomFormat = (value) => SBOM_FORMATS.includes(value);
762
- const execute = async ({ options, visConfig, workspaceRoot: wsRoot }) => {
763
- if (!wsRoot) {
764
- throw new Error("Could not determine workspace root. Run inside a monorepo.");
765
- }
766
- const { packageJsons, workspace } = discoverWorkspace(wsRoot, visConfig);
767
- const projectGraph = buildProjectGraph(wsRoot, workspace, packageJsons);
768
- const focusRaw = options.focus;
769
- const focus = focusRaw ? focusRaw.split(",").map((name) => name.trim()).filter(Boolean) : void 0;
770
- const format = (options.format ?? "json").toLowerCase();
771
- if (!isSbomFormat(format)) {
772
- throw new Error(`Unknown --format: "${format}". Expected one of: ${SBOM_FORMATS.join(", ")}.`);
773
- }
774
- const bom = buildCycloneDxBom({
775
- focus,
776
- includeDev: Boolean(options.includeDev),
777
- projectGraph,
778
- workspace,
779
- workspaceRoot: wsRoot
780
- });
781
- const serialized = format === "xml" ? serializeBomToXml(bom) : `${JSON.stringify(bom, void 0, 2)}
782
- `;
783
- const output = options.output ?? (format === "xml" ? "sbom.cdx.xml" : "sbom.cdx.json");
784
- if (output === "-") {
785
- process.stdout.write(serialized);
786
- return;
787
- }
788
- const outPath = resolve(wsRoot, output);
789
- ensureDirSync(dirname(outPath));
790
- writeFileSync(outPath, serialized, "utf8");
791
- const componentCount = bom.components?.length ?? 0;
792
- const dependencyCount = bom.dependencies?.length ?? 0;
793
- pail.success(`SBOM written to ${outPath}`);
794
- pail.notice(`${componentCount} components, ${dependencyCount} dependency edges`);
795
- };
796
-
797
- export { execute as default };
1
+ var _e=Object.defineProperty;var C=(e,n)=>_e(e,"name",{value:n,configurable:!0});import{createRequire as ve}from"node:module";import{readJsonSync as pe,readFileSync as ke,ensureDirSync as je}from"@visulima/fs";import{join as F,resolve as Le,dirname as Ce}from"@visulima/path";import{aE as Pe,k as we,y as Ae,p as se}from"./bin.js";import{r as xe}from"../packem_shared/docker-D6OGr5_S.js";import{parseLockFileContent as De}from"@visulima/package";const $e=ve(import.meta.url),H=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,ie=C(e=>{if(typeof H<"u"&&H.versions&&H.versions.node){const[n,t]=H.versions.node.split(".").map(Number);if(n>22||n===22&&t>=3||n===20&&t>=16)return H.getBuiltinModule(e)}return $e(e)},"__cjs_getBuiltinModule"),{readdirSync:Oe,writeFileSync:Se}=ie("node:fs"),{randomUUID:Te}=ie("node:crypto");var Be=Object.defineProperty,k=C((e,n)=>Be(e,"name",{value:n,configurable:!0}),"a$1");const f={ARRAY:"array",BOOLEAN:"boolean",DATE:"date",FUNCTION:"function",JSTOXML_OBJECT:"jstoxml-object",NULL:"null",NUMBER:"number",OBJECT:"object",STRING:"string"},Ee=[f.STRING,f.NUMBER,f.BOOLEAN],Re='<?xml version="1.0" encoding="UTF-8"?>',re=["_selfCloseTag","_attrs"],Me=k((e="",n=0)=>e.repeat(n),"getIndentStr"),Z=k(e=>Array.isArray(e)&&f.ARRAY||typeof e===f.OBJECT&&e!==null&&e._name&&f.JSTOXML_OBJECT||e instanceof Date&&f.DATE||e===null&&f.NULL||typeof e,"getType"),le=k(e=>e.startsWith("<![CDATA["),"isCDATA"),ue=k((e="",n={},t)=>{let o=e;if(typeof e===f.STRING){if(le(e))return e;const s=new RegExp(`(${Object.keys(n).join("|")})(?!(\\w|#)*;)`,"g");o=String(e).replace(s,(p,d)=>n[d]||"")}return typeof t=="function"?t(o):o},"mapStr"),Ne=k((e={},n,t,o)=>(Array.isArray(e)?e:Object.entries(e).map(([s,p])=>({[s]:p}))).reduce((s,p)=>{const d=Object.keys(p)[0],b=p[d];if(typeof t===f.FUNCTION&&t(d,b))return s;const m=n?ue(b,n):b,h=!o&&m===!0?"":`="${m}"`;return s.push(`${d}${h}`),s},[]),"getAttributeKeyVals"),Ie=k((e={},n,t,o)=>{const s=Ne(e,n,t,o);return s.length===0?"":` ${s.join(" ")}`},"formatAttributes"),Ue=k((e={})=>Object.keys(e).map(n=>({_name:n,_content:e[n]})),"objToArray"),Fe=k(e=>Ee.includes(Z(e)),"isPrimitive"),Ge=k(e=>!e.match("<"),"isSimpleXML"),Je=k(({header:e,isOutputStart:n})=>e&&n?typeof e===f.BOOLEAN?Re:e:"","getHeaderString"),ce={"<":"&lt;",">":"&gt;","&":"&amp;",'"':"&quot;"},q=k((e={},n={})=>{const{depth:t=0,indent:o,_isFirstItem:s,_isOutputStart:p=!0,header:d,attributeReplacements:b={},attributeFilter:m,attributeExplicitTrue:h=!1,contentReplacements:B={},contentMap:P,selfCloseTags:j=!0}=n,M=typeof b=="boolean"&&!b?{}:{...ce,...b},G=typeof B=="boolean"&&!B?{}:{...ce,...B},w=typeof o=="string",A=Me(o,t),Y=Z(e),J=Je({header:d,indent:o,depth:t,isOutputStart:p}),N=p&&!J&&s&&t===0,I=w&&!N?`
2
+ `:"";let $="";switch(Y){case f.JSTOXML_OBJECT:{const{_name:y,_content:l}=e;if(l===null&&typeof P!="function"){$=`${I}${A}${y}`;break}if(Array.isArray(l)&&l.every(Fe))return l.map(L=>q({_name:y,_content:L},{...n,depth:t,_isOutputStart:!1})).join("");if(re.includes(y))break;const v=q(l,{...n,depth:t+1,_isOutputStart:N}),E=Z(v),O=Ge(v),S=le(v),R=`${I}${A}`;if(y==="_comment"){$+=`${R}<!-- ${l} -->`;break}const K=E==="undefined"||v==="",c=j,r=e._selfCloseTag,i=typeof r===f.BOOLEAN?K&&r:K&&c,a=i?"/":"",u=Ie(e._attrs,M,m,h),g=`<${y}${u}${a}>`,T=w&&!O&&!S?`
3
+ ${A}`:"",x=i?"":`${v}${T}</${y}>`;$+=`${R}${g}${x}`;break}case f.OBJECT:{const y=Object.keys(e);$=y.map((l,v)=>{const E={...n,_isFirstItem:v===0,_isLastItem:v+1===y.length,_isOutputStart:N},O={_name:l};if(Z(e[l])===f.OBJECT&&(re.forEach(S=>{const R=e[l][S];typeof R<"u"&&(O[S]=R,delete e[l][S])}),typeof e[l]._content<"u"&&Object.keys(e[l]).length>1)){const S=Object.assign({},e[l]);delete S._content,O._content=[...Ue(S),e[l]._content]}return typeof O._content>"u"&&(O._content=e[l]),q(O,E)},n).join("");break}case f.FUNCTION:{const y=e(n);$=q(y,n);break}case f.ARRAY:{$=e.map((y,l)=>{const v={...n,_isFirstItem:l===0,_isLastItem:l+1===e.length,_isOutputStart:N};return q(y,v)}).join("");break}default:{$=ue(e,G,P);break}}return`${J}${$}`},"toXML");var Xe=Object.defineProperty,z=C((e,n)=>Xe(e,"name",{value:n,configurable:!0}),"r$1");const te=z(e=>{try{return pe(e)}catch{return}},"readJsonSafe"),qe=z(e=>{if(e.length===0||e.includes("..")||e.startsWith(".")||e.includes("\0")||e.includes("\\"))return!1;if(e.startsWith("@")){const n=e.indexOf("/");return n>1&&!e.includes("/",n+1)}return!e.includes("/")},"isSafePackageName"),ze=z(e=>e.length>0&&!e.includes("/")&&!e.includes("\\")&&!e.includes("..")&&!e.includes("\0"),"isSafeVersion"),We=z((e,n,t)=>{const o=`${n.replaceAll("/","+")}@${t}`,s=F(e,"node_modules",".pnpm"),p=te(F(s,o,"node_modules",n,"package.json"));if(p)return p;let d;try{d=Oe(s)}catch{return}const b=`${o}_`;for(const m of d){if(!m.startsWith(b))continue;const h=te(F(s,m,"node_modules",n,"package.json"));if(h)return h}},"readPnpmVirtualStore"),He=z((e,n,t)=>{const o=te(F(e,"node_modules",n,"package.json"));return o?.version===t?o:void 0},"readHoistedCopy"),Ve=z((e,n,t)=>{if(!(!qe(n)||!ze(t)))return We(e,n,t)??He(e,n,t)},"readInstalledPackageMetadata");var Ye=Object.defineProperty,me=C((e,n)=>Ye(e,"name",{value:n,configurable:!0}),"i");const fe=new Set(["0BSD","AGPL-3.0","AGPL-3.0-only","AGPL-3.0-or-later","Apache-1.1","Apache-2.0","Artistic-2.0","BlueOak-1.0.0","BSD-2-Clause","BSD-3-Clause","BSL-1.0","CC0-1.0","CC-BY-3.0","CC-BY-4.0","CDDL-1.0","CDDL-1.1","EPL-1.0","EPL-2.0","GPL-2.0","GPL-2.0-only","GPL-2.0-or-later","GPL-3.0","GPL-3.0-only","GPL-3.0-or-later","ISC","LGPL-2.0","LGPL-2.1","LGPL-3.0","MIT","MIT-0","MPL-1.1","MPL-2.0","Python-2.0","Unlicense","WTFPL","Zlib"]),Ke={apache2:"Apache-2.0","apache 2.0":"Apache-2.0",bsd:"BSD-3-Clause","bsd-2":"BSD-2-Clause","bsd-3":"BSD-3-Clause",mit:"MIT",public:"Unlicense","public domain":"Unlicense"},Ze=(()=>{const e=new Map;for(const n of fe)e.set(n.toLowerCase(),n);for(const[n,t]of Object.entries(Ke))e.set(n,t);return e})(),Qe=me(e=>{const n=e.trim();if(n.length!==0)return fe.has(n)?n:Ze.get(n.toLowerCase())},"normalizeSpdxId"),en=me(e=>{let n;if(typeof e.license=="string")n=e.license;else if(e.license&&typeof e.license=="object"&&typeof e.license.type=="string")n=e.license.type;else if(Array.isArray(e.licenses)&&e.licenses.length>0){const s=e.licenses[0];s&&typeof s.type=="string"&&(n=s.type)}if(!n)return;const t=n.trim();if(t.length===0)return;if(/[()]|\b(?:and|or|with)\b/i.test(t))return[{expression:t}];const o=Qe(t);return o?[{license:{id:o}}]:[{license:{name:t}}]},"extractLicenseChoice");var nn=Object.defineProperty,de=C((e,n)=>nn(e,"name",{value:n,configurable:!0}),"t");const tn={sha256:"SHA-256",sha384:"SHA-384",sha512:"SHA-512"},on={sha256:64,sha384:96,sha512:128},sn=de(e=>{const n={name:e.name,version:e.version},{integrity:t}=e;return t&&t.hex.length===on[t.algorithm]&&(n.hash={alg:tn[t.algorithm],content:t.hex}),e.dependencies&&(n.dependencies=e.dependencies),e.peerDependencies&&(n.peerDependencies=e.peerDependencies),e.optionalDependencies&&(n.optionalDependencies=e.optionalDependencies),n},"toResolvedPackage"),rn=[{file:"pnpm-lock.yaml",type:"pnpm"},{file:"package-lock.json",type:"npm"},{file:"yarn.lock",type:"yarn"},{file:"bun.lock",type:"bun"}],cn=de(e=>{for(const{file:n,type:t}of rn){let o;try{o=ke(F(e,n))}catch{continue}const s=new Map;for(const p of De(o,t))s.set(`${p.name}@${p.version}`,sn(p));return{packages:s,type:t}}},"readLockfilePackages");var an=Object.defineProperty,he=C((e,n)=>an(e,"name",{value:n,configurable:!0}),"r");const V=he(e=>e.replaceAll(/[^\w.~-]/g,n=>`%${(n.codePointAt(0)??0).toString(16).toUpperCase().padStart(2,"0")}`),"encodeSegment"),U=he((e,n)=>{const t=e.toLowerCase();if(t.startsWith("@")){const o=t.indexOf("/");if(o>0){const s=t.slice(0,o),p=t.slice(o+1);return`pkg:npm/${V(s)}/${V(p)}@${V(n)}`}}return`pkg:npm/${V(t)}@${V(n)}`},"toNpmPurl");var pn=Object.defineProperty,ye=C((e,n)=>pn(e,"name",{value:n,configurable:!0}),"s");const ln=ye(e=>{const n=e.indexOf(":");return n<=0?e:e.slice(0,n)==="npm"?e.slice(n+1):e},"stripProtocolPrefix"),ee=ye((e,n,t)=>{const o=t.get(e);if(!o||o.size===0)return;if(o.has(n))return n;const s=ln(n);if(s!==n&&o.has(s))return s;const p=[...o];return Pe.maxSatisfying(p,s,{includePrerelease:!0})||p[0]},"resolveSpecifier");var un=Object.defineProperty,_=C((e,n)=>un(e,"name",{value:n,configurable:!0}),"p");const mn="1.6",fn="CycloneDX",dn="http://cyclonedx.org/schema/bom-1.6.schema.json",hn="@visulima/vis",ae=_(e=>{try{return pe(e)}catch{return}},"readPackageJson"),yn=_(e=>{if(e){if(typeof e=="string")return e;if(typeof e=="object"&&e.name)return e.email?`${e.name} <${e.email}>`:e.name}},"toAuthorString"),gn=_(e=>{if(e)return typeof e=="string"?e:e.url},"toRepositoryUrl"),bn=_(e=>{if(e)return typeof e=="string"?e:e.url},"toBugsUrl"),_n=_(e=>{const n=[];e.homepage&&n.push({type:"website",url:e.homepage});const t=gn(e.repository);t&&n.push({type:"vcs",url:t});const o=bn(e.bugs);return o&&n.push({type:"issue-tracker",url:o}),n.length>0?n:void 0},"buildExternalReferences"),ne=_((e,n)=>{if(!n)return;n.description&&(e.description=n.description);const t=yn(n.author);t&&(e.author=t);const o=en(n);o&&(e.licenses=o);const s=_n(n);s&&(e.externalReferences=s)},"decoratePackageComponent"),vn=_(e=>{const{focus:n,generatorVersion:t,includeDev:o=!1,now:s=new Date,projectGraph:p,serialNumber:d,workspace:b,workspaceRoot:m}=e,h=n&&n.length>0?[...xe(n,p)].sort():Object.keys(b.projects).sort(),B=new Set(h),P=new Map;for(const c of h){const r=b.projects[c];r&&P.set(c,ae(F(m,r.root,"package.json")))}const j=[],M=new Map;for(const c of h){const r=b.projects[c];if(!r)continue;const i=P.get(c),a=i?.version??"0.0.0",u=U(c,a);M.set(c,u);const g={"bom-ref":u,name:c,purl:u,type:r.projectType==="application"?"application":"library",version:a};ne(g,i),j.push(g)}const G=cn(m),w=new Map,A=new Map;if(G)for(const c of G.packages.values()){w.set(`${c.name}@${c.version}`,c);let r=A.get(c.name);r||(r=new Set,A.set(c.name,r)),r.add(c.version)}const Y=[],J=[],N=new Map;for(const c of h){const r=P.get(c);if(!r)continue;const i=[r.dependencies,r.peerDependencies];o&&i.push(r.devDependencies);const a=new Set,u=_((g,T)=>{if(T)for(const[x,L]of Object.entries(T)){if(B.has(x)){const X=M.get(x);X&&a.add(X);continue}const D=ee(x,L,A);D&&(a.add(U(x,D)),g.push(`${x}@${D}`))}},"seedRef");for(const g of i)u(Y,g);u(J,r.optionalDependencies),N.set(c,a)}const I=new Map,$=new Map,y=_((c,r)=>{const i=[...c];for(;i.length>0;){const a=i.pop(),u=I.get(a);if(u==="required"||u==="optional"&&r==="optional")continue;I.set(a,r);const g=w.get(a);if(!g)continue;const T=$.get(a)??new Set,x=[g.dependencies,g.peerDependencies];for(const L of x)if(L)for(const[D,X]of Object.entries(L))for(const W of X){const Q=ee(D,W,A);Q&&(T.add(U(D,Q)),i.push(`${D}@${Q}`))}if(g.optionalDependencies)for(const[L,D]of Object.entries(g.optionalDependencies))for(const X of D){const W=ee(L,X,A);W&&(T.add(U(L,W)),J.push(`${L}@${W}`))}T.size>0&&$.set(a,T)}},"walk");y(Y,"required"),y(J,"optional");const l=[],v=[...I.keys()].sort();for(const c of v){const r=w.get(c);if(!r)continue;const i=U(r.name,r.version),a={"bom-ref":i,name:r.name,purl:i,scope:I.get(c)??"required",type:"library",version:r.version};r.hash&&(a.hashes=[r.hash]),ne(a,Ve(m,r.name,r.version)),l.push(a)}const E=[];for(const[c,r]of N){const i=M.get(c);if(!i)continue;const a=[...r].sort();E.push(a.length>0?{dependsOn:a,ref:i}:{ref:i})}for(const c of v){const r=w.get(c);if(!r)continue;const i=U(r.name,r.version),a=$.get(c),u=a?[...a].sort():[];E.push(u.length>0?{dependsOn:u,ref:i}:{ref:i})}E.sort((c,r)=>c.ref.localeCompare(r.ref));const O=ae(F(m,"package.json")),S=(()=>{if(n?.length===1){const u=j.find(g=>g.name===n[0]);if(u)return{"bom-ref":u["bom-ref"],name:u.name,purl:u.purl,type:u.type,version:u.version}}const c=O?.name??"workspace",r=O?.version??"0.0.0",i=U(c,r),a={"bom-ref":i,name:c,purl:i,type:"application",version:r};return ne(a,O),a})(),R=S["bom-ref"],K=R?j.filter(c=>c["bom-ref"]!==R):j;return{$schema:dn,bomFormat:fn,components:[...K,...l],dependencies:E,metadata:{component:S,lifecycles:[{phase:"build"}],timestamp:s.toISOString(),tools:{components:[{name:hn,type:"application",...t?{version:t}:{}}]}},serialNumber:d??`urn:uuid:${Te()}`,specVersion:mn,version:1}},"buildCycloneDxBom"),$n=_(e=>{const n={version:e.version??1,xmlns:"http://cyclonedx.org/schema/bom/1.6"};e.serialNumber&&(n.serialNumber=e.serialNumber);const t=[];return e.metadata&&t.push(On(e.metadata)),e.components&&e.components.length>0&&t.push({_content:e.components.map(o=>oe(o)),_name:"components"}),e.dependencies&&e.dependencies.length>0&&t.push({_content:e.dependencies.map(o=>kn(o)),_name:"dependencies"}),`${q({_attrs:n,_content:t,_name:"bom"},{header:!0,indent:" ",selfCloseTags:!0})}
4
+ `},"serializeBomToXml"),On=_(e=>{const n=[];return e.timestamp&&n.push({timestamp:e.timestamp}),e.lifecycles&&e.lifecycles.length>0&&n.push({_content:e.lifecycles.map(t=>{const o=[];return t.phase&&o.push({phase:t.phase}),t.name&&o.push({name:t.name}),t.description&&o.push({description:t.description}),{_content:o,_name:"lifecycle"}}),_name:"lifecycles"}),e.tools?.components&&n.push({_content:[{_content:e.tools.components.map(t=>oe(t)),_name:"components"}],_name:"tools"}),e.component&&n.push(oe(e.component)),{_content:n,_name:"metadata"}},"metadataToXmlElement"),oe=_(e=>{const n={type:e.type};e["bom-ref"]&&(n["bom-ref"]=e["bom-ref"]);const t=[];e.group&&t.push({group:e.group}),t.push({name:e.name}),e.version&&t.push({version:e.version}),e.description&&t.push({description:e.description}),e.author&&t.push({author:e.author}),e.hashes&&e.hashes.length>0&&t.push({_content:e.hashes.map(s=>({_attrs:{alg:s.alg},_content:s.content,_name:"hash"})),_name:"hashes"});const o=Sn(e.licenses);return o&&t.push(o),e.purl&&t.push({purl:e.purl}),e.scope&&t.push({scope:e.scope}),e.externalReferences&&e.externalReferences.length>0&&t.push({_content:e.externalReferences.map(s=>({_attrs:{type:s.type},_content:[{url:s.url}],_name:"reference"})),_name:"externalReferences"}),{_attrs:n,_content:t,_name:"component"}},"componentToXmlElement"),Sn=_(e=>{if(!e||e.length===0)return;const n=[];for(const t of e){if("expression"in t){n.push({expression:t.expression});continue}const o=[];"id"in t.license&&t.license.id?o.push({id:t.license.id}):"name"in t.license&&t.license.name&&o.push({name:t.license.name}),n.push({_content:o,_name:"license"})}return{_content:n,_name:"licenses"}},"licensesToXmlElement"),kn=_(e=>e.dependsOn&&e.dependsOn.length>0?{_attrs:{ref:e.ref},_content:e.dependsOn.map(n=>({_attrs:{ref:n},_name:"dependency"})),_name:"dependency"}:{_attrs:{ref:e.ref},_name:"dependency"},"dependencyToXmlElement");var jn=Object.defineProperty,ge=C((e,n)=>jn(e,"name",{value:n,configurable:!0}),"m");const be=["json","xml"],Ln=ge(e=>be.includes(e),"isSbomFormat"),Bn=ge(async({options:e,visConfig:n,workspaceRoot:t})=>{if(!t)throw new Error("Could not determine workspace root. Run inside a monorepo.");const{packageJsons:o,workspace:s}=we(t,n),p=Ae(t,s,o),d=e.focus,b=d?d.split(",").map(w=>w.trim()).filter(Boolean):void 0,m=(e.format??"json").toLowerCase();if(!Ln(m))throw new Error(`Unknown --format: "${m}". Expected one of: ${be.join(", ")}.`);const h=vn({focus:b,includeDev:!!e.includeDev,projectGraph:p,workspace:s,workspaceRoot:t}),B=m==="xml"?$n(h):`${JSON.stringify(h,void 0,2)}
5
+ `,P=e.output??(m==="xml"?"sbom.cdx.xml":"sbom.cdx.json");if(P==="-"){process.stdout.write(B);return}const j=Le(t,P);je(Ce(j)),Se(j,B,"utf8");const M=h.components?.length??0,G=h.dependencies?.length??0;se.success(`SBOM written to ${j}`),se.notice(`${M} components, ${G} dependency edges`)},"execute");export{Bn as default};