flatlock 1.1.0 → 1.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 +95 -1
- package/bin/flatcover.js +398 -0
- package/bin/flatlock-cmp.js +71 -45
- package/bin/flatlock.js +158 -0
- package/package.json +21 -8
- package/src/compare.js +385 -28
- package/src/detect.js +3 -4
- package/src/index.js +9 -2
- package/src/parsers/index.js +24 -4
- package/src/parsers/npm.js +144 -14
- package/src/parsers/pnpm/detect.js +198 -0
- package/src/parsers/pnpm/index.js +359 -0
- package/src/parsers/pnpm/internal.js +41 -0
- package/src/parsers/pnpm/shrinkwrap.js +241 -0
- package/src/parsers/pnpm/v5.js +225 -0
- package/src/parsers/pnpm/v6plus.js +290 -0
- package/src/parsers/pnpm.js +11 -89
- package/src/parsers/types.js +10 -0
- package/src/parsers/yarn-berry.js +271 -36
- package/src/parsers/yarn-classic.js +81 -21
- package/src/set.js +1307 -0
- package/dist/compare.d.ts +0 -63
- package/dist/compare.d.ts.map +0 -1
- package/dist/detect.d.ts +0 -33
- package/dist/detect.d.ts.map +0 -1
- package/dist/index.d.ts +0 -70
- package/dist/index.d.ts.map +0 -1
- package/dist/parsers/index.d.ts +0 -5
- package/dist/parsers/index.d.ts.map +0 -1
- package/dist/parsers/npm.d.ts +0 -82
- package/dist/parsers/npm.d.ts.map +0 -1
- package/dist/parsers/pnpm.d.ts +0 -60
- package/dist/parsers/pnpm.d.ts.map +0 -1
- package/dist/parsers/yarn-berry.d.ts +0 -65
- package/dist/parsers/yarn-berry.d.ts.map +0 -1
- package/dist/parsers/yarn-classic.d.ts +0 -64
- package/dist/parsers/yarn-classic.d.ts.map +0 -1
- package/dist/result.d.ts +0 -12
- package/dist/result.d.ts.map +0 -1
package/bin/flatlock-cmp.js
CHANGED
|
@@ -5,18 +5,6 @@ import { join } from 'node:path';
|
|
|
5
5
|
import { parseArgs } from 'node:util';
|
|
6
6
|
import * as flatlock from '../src/index.js';
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
* Get comparison parser name for type
|
|
10
|
-
*/
|
|
11
|
-
function getComparisonName(type) {
|
|
12
|
-
switch (type) {
|
|
13
|
-
case 'npm': return '@npmcli/arborist';
|
|
14
|
-
case 'yarn-classic': return '@yarnpkg/lockfile';
|
|
15
|
-
case 'yarn-berry': return '@yarnpkg/parsers';
|
|
16
|
-
case 'pnpm': return 'js-yaml';
|
|
17
|
-
default: return 'unknown';
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
8
|
|
|
21
9
|
/**
|
|
22
10
|
* Convert glob pattern to regex
|
|
@@ -59,18 +47,17 @@ async function processFile(filepath, baseDir) {
|
|
|
59
47
|
try {
|
|
60
48
|
const result = await flatlock.compare(filepath);
|
|
61
49
|
const rel = baseDir ? filepath.replace(baseDir + '/', '') : filepath;
|
|
62
|
-
const comparisonName = getComparisonName(result.type);
|
|
63
50
|
|
|
64
|
-
if (result.
|
|
51
|
+
if (result.equinumerous === null) {
|
|
65
52
|
// Unsupported type or no comparison available
|
|
66
53
|
return {
|
|
67
54
|
type: result.type,
|
|
68
55
|
path: rel,
|
|
69
|
-
|
|
56
|
+
source: result.source || 'unknown',
|
|
70
57
|
flatlockCount: result.flatlockCount,
|
|
71
58
|
comparisonCount: null,
|
|
72
59
|
workspaceCount: 0,
|
|
73
|
-
|
|
60
|
+
equinumerous: null,
|
|
74
61
|
onlyInFlatlock: null,
|
|
75
62
|
onlyInComparison: null
|
|
76
63
|
};
|
|
@@ -79,11 +66,11 @@ async function processFile(filepath, baseDir) {
|
|
|
79
66
|
return {
|
|
80
67
|
type: result.type,
|
|
81
68
|
path: rel,
|
|
82
|
-
|
|
69
|
+
source: result.source,
|
|
83
70
|
flatlockCount: result.flatlockCount,
|
|
84
71
|
comparisonCount: result.comparisonCount,
|
|
85
72
|
workspaceCount: result.workspaceCount,
|
|
86
|
-
|
|
73
|
+
equinumerous: result.equinumerous,
|
|
87
74
|
onlyInFlatlock: result.onlyInFlatlock,
|
|
88
75
|
onlyInComparison: result.onlyInComparison
|
|
89
76
|
};
|
|
@@ -118,10 +105,21 @@ Options:
|
|
|
118
105
|
-h, --help Show this help
|
|
119
106
|
|
|
120
107
|
Comparison parsers (workspace/link entries excluded from all):
|
|
121
|
-
npm: @npmcli/arborist (
|
|
108
|
+
npm: @npmcli/arborist (preferred) or @cyclonedx/cyclonedx-npm
|
|
122
109
|
yarn-classic: @yarnpkg/lockfile
|
|
123
110
|
yarn-berry: @yarnpkg/parsers
|
|
124
|
-
pnpm: js-yaml
|
|
111
|
+
pnpm: @pnpm/lockfile.fs (preferred) or js-yaml
|
|
112
|
+
|
|
113
|
+
Result types:
|
|
114
|
+
✓ equinumerous Same packages in both (exact match)
|
|
115
|
+
⊃ SUPERSET flatlock found MORE packages (expected for pnpm)
|
|
116
|
+
❌ MISMATCH Unexpected difference (comparison found packages flatlock missed)
|
|
117
|
+
|
|
118
|
+
Note on pnpm supersets:
|
|
119
|
+
flatlock performs full reachability analysis on lockfiles, finding all
|
|
120
|
+
transitive dependencies. pnpm's official tools don't enumerate all reachable
|
|
121
|
+
packages - they omit some transitive deps from their API output. When flatlock
|
|
122
|
+
finds MORE packages than pnpm, this is expected and correct behavior.
|
|
125
123
|
|
|
126
124
|
Examples:
|
|
127
125
|
flatlock-cmp package-lock.json
|
|
@@ -153,6 +151,7 @@ Examples:
|
|
|
153
151
|
let fileCount = 0;
|
|
154
152
|
let errorCount = 0;
|
|
155
153
|
let matchCount = 0;
|
|
154
|
+
let supersetCount = 0; // flatlock found more (expected for pnpm reachability)
|
|
156
155
|
let mismatchCount = 0;
|
|
157
156
|
|
|
158
157
|
for (const file of files) {
|
|
@@ -175,44 +174,61 @@ Examples:
|
|
|
175
174
|
if (!values.quiet) {
|
|
176
175
|
console.log(`\n⚠️ ${result.path}`);
|
|
177
176
|
console.log(` flatlock: ${result.flatlockCount} packages`);
|
|
178
|
-
console.log(` ${result.
|
|
177
|
+
console.log(` ${result.source}: unavailable`);
|
|
179
178
|
}
|
|
180
179
|
continue;
|
|
181
180
|
}
|
|
182
181
|
|
|
183
182
|
totalComparison += result.comparisonCount;
|
|
184
183
|
|
|
185
|
-
if (result.
|
|
184
|
+
if (result.equinumerous) {
|
|
186
185
|
matchCount++;
|
|
187
186
|
if (!values.quiet) {
|
|
188
187
|
const wsNote = result.workspaceCount > 0 ? ` (${result.workspaceCount} workspaces excluded)` : '';
|
|
189
188
|
console.log(`✓ ${result.path}${wsNote}`);
|
|
190
|
-
console.log(` count: flatlock=${result.flatlockCount} ${result.
|
|
191
|
-
console.log(` sets:
|
|
189
|
+
console.log(` count: flatlock=${result.flatlockCount} ${result.source}=${result.comparisonCount}`);
|
|
190
|
+
console.log(` sets: equinumerous`);
|
|
192
191
|
}
|
|
193
192
|
} else {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if (
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
console.log(`
|
|
193
|
+
// Determine if this is a "superset" (flatlock found more, expected for pnpm)
|
|
194
|
+
// or a true "mismatch" (comparison found packages flatlock missed)
|
|
195
|
+
const isPnpm = result.type === 'pnpm' || result.path.includes('pnpm-lock');
|
|
196
|
+
const isSuperset = result.onlyInFlatlock.length > 0 && result.onlyInComparison.length === 0;
|
|
197
|
+
|
|
198
|
+
if (isPnpm && isSuperset) {
|
|
199
|
+
// Expected behavior: flatlock's reachability analysis found more packages
|
|
200
|
+
supersetCount++;
|
|
201
|
+
if (!values.quiet) {
|
|
202
|
+
const wsNote = result.workspaceCount > 0 ? ` (${result.workspaceCount} workspaces excluded)` : '';
|
|
203
|
+
console.log(`⊃ ${result.path}${wsNote}`);
|
|
204
|
+
console.log(` count: flatlock=${result.flatlockCount} ${result.source}=${result.comparisonCount}`);
|
|
205
|
+
console.log(` sets: SUPERSET (+${result.onlyInFlatlock.length} reachable deps)`);
|
|
206
|
+
console.log(` note: flatlock's reachability analysis found transitive deps pnpm omits`);
|
|
206
207
|
}
|
|
207
|
-
}
|
|
208
|
+
} else {
|
|
209
|
+
mismatchCount++;
|
|
210
|
+
console.log(`\n❌ ${result.path}`);
|
|
211
|
+
console.log(` count: flatlock=${result.flatlockCount} ${result.source}=${result.comparisonCount}`);
|
|
212
|
+
console.log(` sets: MISMATCH`);
|
|
208
213
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
214
|
+
if (result.onlyInFlatlock.length > 0) {
|
|
215
|
+
console.log(` only in flatlock (${result.onlyInFlatlock.length}):`);
|
|
216
|
+
for (const pkg of result.onlyInFlatlock.slice(0, 10)) {
|
|
217
|
+
console.log(` + ${pkg}`);
|
|
218
|
+
}
|
|
219
|
+
if (result.onlyInFlatlock.length > 10) {
|
|
220
|
+
console.log(` ... and ${result.onlyInFlatlock.length - 10} more`);
|
|
221
|
+
}
|
|
213
222
|
}
|
|
214
|
-
|
|
215
|
-
|
|
223
|
+
|
|
224
|
+
if (result.onlyInComparison.length > 0) {
|
|
225
|
+
console.log(` only in ${result.source} (${result.onlyInComparison.length}):`);
|
|
226
|
+
for (const pkg of result.onlyInComparison.slice(0, 10)) {
|
|
227
|
+
console.log(` - ${pkg}`);
|
|
228
|
+
}
|
|
229
|
+
if (result.onlyInComparison.length > 10) {
|
|
230
|
+
console.log(` ... and ${result.onlyInComparison.length - 10} more`);
|
|
231
|
+
}
|
|
216
232
|
}
|
|
217
233
|
}
|
|
218
234
|
}
|
|
@@ -220,7 +236,13 @@ Examples:
|
|
|
220
236
|
|
|
221
237
|
// Summary
|
|
222
238
|
console.log('\n' + '='.repeat(70));
|
|
223
|
-
|
|
239
|
+
const summaryParts = [`${fileCount} files`, `${matchCount} equinumerous`];
|
|
240
|
+
if (supersetCount > 0) {
|
|
241
|
+
summaryParts.push(`${supersetCount} supersets`);
|
|
242
|
+
}
|
|
243
|
+
summaryParts.push(`${mismatchCount} mismatches`, `${errorCount} errors`);
|
|
244
|
+
console.log(`SUMMARY: ${summaryParts.join(', ')}`);
|
|
245
|
+
|
|
224
246
|
console.log(` flatlock total: ${totalFlatlock.toString().padStart(8)} packages`);
|
|
225
247
|
if (totalComparison > 0) {
|
|
226
248
|
console.log(` comparison total: ${totalComparison.toString().padStart(8)} packages`);
|
|
@@ -228,8 +250,12 @@ Examples:
|
|
|
228
250
|
if (totalWorkspaces > 0) {
|
|
229
251
|
console.log(` workspaces: ${totalWorkspaces.toString().padStart(8)} excluded (local/workspace refs)`);
|
|
230
252
|
}
|
|
253
|
+
if (supersetCount > 0) {
|
|
254
|
+
console.log(` supersets: ${supersetCount.toString().padStart(8)} (flatlock found more via reachability)`);
|
|
255
|
+
}
|
|
231
256
|
|
|
232
|
-
// Exit with error
|
|
257
|
+
// Exit with error only for true mismatches (not supersets)
|
|
258
|
+
// Supersets are expected: flatlock's reachability analysis is more thorough
|
|
233
259
|
if (mismatchCount > 0) {
|
|
234
260
|
process.exit(1);
|
|
235
261
|
}
|
package/bin/flatlock.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* flatlock - Get dependencies from a lockfile
|
|
4
|
+
*
|
|
5
|
+
* For monorepo workspaces, outputs the production dependencies of a workspace.
|
|
6
|
+
* For standalone packages, outputs all production dependencies.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* flatlock <lockfile> # all deps (names only)
|
|
10
|
+
* flatlock <lockfile> --specs # name@version
|
|
11
|
+
* flatlock <lockfile> --json # JSON array
|
|
12
|
+
* flatlock <lockfile> --specs --json # JSON with versions
|
|
13
|
+
* flatlock <lockfile> --specs --ndjson # streaming NDJSON
|
|
14
|
+
* flatlock <lockfile> --full --ndjson # full metadata streaming
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { parseArgs } from 'node:util';
|
|
18
|
+
import { readFileSync } from 'node:fs';
|
|
19
|
+
import { dirname, join } from 'node:path';
|
|
20
|
+
import { FlatlockSet } from '../src/set.js';
|
|
21
|
+
|
|
22
|
+
const { values, positionals } = parseArgs({
|
|
23
|
+
options: {
|
|
24
|
+
workspace: { type: 'string', short: 'w' },
|
|
25
|
+
dev: { type: 'boolean', default: false },
|
|
26
|
+
peer: { type: 'boolean', default: true },
|
|
27
|
+
specs: { type: 'boolean', short: 's', default: false },
|
|
28
|
+
json: { type: 'boolean', default: false },
|
|
29
|
+
ndjson: { type: 'boolean', default: false },
|
|
30
|
+
full: { type: 'boolean', default: false },
|
|
31
|
+
help: { type: 'boolean', short: 'h' }
|
|
32
|
+
},
|
|
33
|
+
allowPositionals: true
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
if (values.help || positionals.length === 0) {
|
|
37
|
+
console.log(`flatlock - Get dependencies from a lockfile
|
|
38
|
+
|
|
39
|
+
Usage:
|
|
40
|
+
flatlock <lockfile>
|
|
41
|
+
flatlock <lockfile> --workspace <path>
|
|
42
|
+
|
|
43
|
+
Options:
|
|
44
|
+
-w, --workspace <path> Workspace path within monorepo
|
|
45
|
+
-s, --specs Include version (name@version or {name,version})
|
|
46
|
+
--json Output as JSON array
|
|
47
|
+
--ndjson Output as newline-delimited JSON (streaming)
|
|
48
|
+
--full Include all metadata (integrity, resolved)
|
|
49
|
+
--dev Include dev dependencies (default: false)
|
|
50
|
+
--peer Include peer dependencies (default: true)
|
|
51
|
+
-h, --help Show this help
|
|
52
|
+
|
|
53
|
+
Output formats:
|
|
54
|
+
(default) package names, one per line
|
|
55
|
+
--specs package@version, one per line
|
|
56
|
+
--json ["package", ...]
|
|
57
|
+
--specs --json [{"name":"...","version":"..."}, ...]
|
|
58
|
+
--full --json [{"name":"...","version":"...","integrity":"...","resolved":"..."}, ...]
|
|
59
|
+
--ndjson "package" per line
|
|
60
|
+
--specs --ndjson {"name":"...","version":"..."} per line
|
|
61
|
+
--full --ndjson {"name":"...","version":"...","integrity":"...","resolved":"..."} per line
|
|
62
|
+
|
|
63
|
+
Examples:
|
|
64
|
+
flatlock package-lock.json
|
|
65
|
+
flatlock package-lock.json --specs
|
|
66
|
+
flatlock package-lock.json --specs --json
|
|
67
|
+
flatlock package-lock.json --full --ndjson | jq -c 'select(.name | startswith("@babel"))'
|
|
68
|
+
flatlock pnpm-lock.yaml -w packages/core -s --ndjson`);
|
|
69
|
+
process.exit(values.help ? 0 : 1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (values.json && values.ndjson) {
|
|
73
|
+
console.error('Error: --json and --ndjson are mutually exclusive');
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// --full implies --specs
|
|
78
|
+
if (values.full) {
|
|
79
|
+
values.specs = true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const lockfilePath = positionals[0];
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Format a single dependency based on output options
|
|
86
|
+
* @param {{ name: string, version: string, integrity?: string, resolved?: string }} dep
|
|
87
|
+
* @param {{ specs: boolean, full: boolean }} options
|
|
88
|
+
* @returns {string | object}
|
|
89
|
+
*/
|
|
90
|
+
function formatDep(dep, { specs, full }) {
|
|
91
|
+
if (full) {
|
|
92
|
+
const obj = { name: dep.name, version: dep.version };
|
|
93
|
+
if (dep.integrity) obj.integrity = dep.integrity;
|
|
94
|
+
if (dep.resolved) obj.resolved = dep.resolved;
|
|
95
|
+
return obj;
|
|
96
|
+
}
|
|
97
|
+
if (specs) {
|
|
98
|
+
return { name: dep.name, version: dep.version };
|
|
99
|
+
}
|
|
100
|
+
return dep.name;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Output dependencies in the requested format
|
|
105
|
+
* @param {Iterable<{ name: string, version: string, integrity?: string, resolved?: string }>} deps
|
|
106
|
+
* @param {{ specs: boolean, json: boolean, ndjson: boolean, full: boolean }} options
|
|
107
|
+
*/
|
|
108
|
+
function outputDeps(deps, { specs, json, ndjson, full }) {
|
|
109
|
+
const sorted = [...deps].sort((a, b) => a.name.localeCompare(b.name));
|
|
110
|
+
|
|
111
|
+
if (json) {
|
|
112
|
+
const data = sorted.map(d => formatDep(d, { specs, full }));
|
|
113
|
+
console.log(JSON.stringify(data, null, 2));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (ndjson) {
|
|
118
|
+
for (const d of sorted) {
|
|
119
|
+
console.log(JSON.stringify(formatDep(d, { specs, full })));
|
|
120
|
+
}
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Plain text
|
|
125
|
+
for (const d of sorted) {
|
|
126
|
+
console.log(specs ? `${d.name}@${d.version}` : d.name);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
const lockfile = await FlatlockSet.fromPath(lockfilePath);
|
|
132
|
+
let deps;
|
|
133
|
+
|
|
134
|
+
if (values.workspace) {
|
|
135
|
+
const repoDir = dirname(lockfilePath);
|
|
136
|
+
const workspacePkgPath = join(repoDir, values.workspace, 'package.json');
|
|
137
|
+
const workspacePkg = JSON.parse(readFileSync(workspacePkgPath, 'utf8'));
|
|
138
|
+
|
|
139
|
+
deps = await lockfile.dependenciesOf(workspacePkg, {
|
|
140
|
+
workspacePath: values.workspace,
|
|
141
|
+
repoDir,
|
|
142
|
+
dev: values.dev,
|
|
143
|
+
peer: values.peer
|
|
144
|
+
});
|
|
145
|
+
} else {
|
|
146
|
+
deps = lockfile;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
outputDeps(deps, {
|
|
150
|
+
specs: values.specs,
|
|
151
|
+
json: values.json,
|
|
152
|
+
ndjson: values.ndjson,
|
|
153
|
+
full: values.full
|
|
154
|
+
});
|
|
155
|
+
} catch (err) {
|
|
156
|
+
console.error(`Error: ${err.message}`);
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flatlock",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "The Matlock of lockfile parsers - extracts packages without building dependency graphs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lockfile",
|
|
@@ -35,15 +35,19 @@
|
|
|
35
35
|
},
|
|
36
36
|
"main": "src/index.js",
|
|
37
37
|
"bin": {
|
|
38
|
-
"flatlock
|
|
38
|
+
"flatlock": "./bin/flatlock.js",
|
|
39
|
+
"flatlock-cmp": "./bin/flatlock-cmp.js",
|
|
40
|
+
"flatcover": "./bin/flatcover.js"
|
|
39
41
|
},
|
|
40
42
|
"files": [
|
|
41
43
|
"src",
|
|
42
44
|
"dist",
|
|
43
|
-
"bin"
|
|
45
|
+
"bin/flatlock.js",
|
|
46
|
+
"bin/flatlock-cmp.js",
|
|
47
|
+
"bin/flatcover.js"
|
|
44
48
|
],
|
|
45
49
|
"scripts": {
|
|
46
|
-
"test": "node --test ./test/*.test.js",
|
|
50
|
+
"test": "node --test ./test/*.test.js ./test/**/*.test.js",
|
|
47
51
|
"test:coverage": "c8 node --test ./test/*.test.js",
|
|
48
52
|
"build:types": "tsc",
|
|
49
53
|
"lint": "biome lint src test",
|
|
@@ -53,29 +57,38 @@
|
|
|
53
57
|
"format:check": "biome format src test",
|
|
54
58
|
"check": "biome check src test && pnpm run build:types",
|
|
55
59
|
"check:fix": "biome check --write src test",
|
|
60
|
+
"build:ncc": "./bin/ncc.sh",
|
|
56
61
|
"prepublishOnly": "pnpm run build:types"
|
|
57
62
|
},
|
|
58
63
|
"dependencies": {
|
|
59
64
|
"@yarnpkg/lockfile": "^1.1.0",
|
|
60
65
|
"@yarnpkg/parsers": "^3.0.3",
|
|
61
|
-
"js-yaml": "^4.1.1"
|
|
66
|
+
"js-yaml": "^4.1.1",
|
|
67
|
+
"undici": "^7.0.0"
|
|
62
68
|
},
|
|
63
69
|
"devDependencies": {
|
|
64
70
|
"@biomejs/biome": "^2.3.8",
|
|
65
|
-
"@
|
|
71
|
+
"@vercel/ncc": "^0.38.4",
|
|
66
72
|
"@types/js-yaml": "^4.0.9",
|
|
67
73
|
"@types/node": "^22.10.2",
|
|
68
74
|
"c8": "^10.1.3",
|
|
75
|
+
"chalk": "^5.6.2",
|
|
76
|
+
"fast-glob": "^3.3.3",
|
|
77
|
+
"jackspeak": "^4.1.1",
|
|
69
78
|
"markdownlint-cli2": "^0.17.2",
|
|
70
79
|
"snyk-nodejs-lockfile-parser": "^1.55.0",
|
|
80
|
+
"tinyexec": "^1.0.2",
|
|
71
81
|
"typescript": "^5.7.2"
|
|
72
82
|
},
|
|
73
83
|
"optionalDependencies": {
|
|
74
|
-
"@
|
|
84
|
+
"@cyclonedx/cdxgen": "^11.3.3",
|
|
85
|
+
"@npmcli/arborist": "^9.1.9",
|
|
86
|
+
"@pnpm/lockfile.fs": "^1001.0.0",
|
|
87
|
+
"@yarnpkg/core": "^4.5.0"
|
|
75
88
|
},
|
|
76
89
|
"packageManager": "pnpm@10.25.0",
|
|
77
90
|
"engines": {
|
|
78
|
-
"node": ">=
|
|
91
|
+
"node": ">=22"
|
|
79
92
|
},
|
|
80
93
|
"c8": {
|
|
81
94
|
"all": true,
|