@lenne.tech/cli 1.50.1 → 1.50.2

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.
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const path_1 = require("path");
13
+ const reinit_command_1 = require("../../lib/reinit-command");
13
14
  /**
14
15
  * Reinitialize npm packages
15
16
  */
@@ -83,8 +84,11 @@ const NewCommand = {
83
84
  if (system.which('rimraf')) {
84
85
  yield system.run(pm.globalInstall('rimraf'));
85
86
  }
86
- const lockfile = pm.getLockfileName(detectedPm);
87
- yield system.run(`cd ${(0, path_1.dirname)(path)} && rimraf ${lockfile} && rimraf node_modules && ${pm.cacheClean(detectedPm)} && ${pm.install(detectedPm)}`);
87
+ yield system.run((0, reinit_command_1.buildReinitCommand)({
88
+ dir: (0, path_1.dirname)(path),
89
+ install: pm.install(detectedPm),
90
+ lockfile: pm.getLockfileName(detectedPm),
91
+ }));
88
92
  reinitSpin.succeed();
89
93
  if (data.scripts && data.scripts['test:e2e']) {
90
94
  const testE2eSpin = spin('Run tests');
@@ -1,4 +1,4 @@
1
1
  {
2
- "$comment": "Upstream @lenne.tech/nest-server DEVDEPENDENCIES that must land in a vendored project's `dependencies`. Vendoring copies upstream `dependencies` verbatim and does not read `peerDependencies` at all, so a package the framework imports at runtime while keeping it in devDependencies would never reach the production runtime. Entries here are matched against upstream `devDependencies` only — see `isVendorRuntimeDep`, consulted in the `upstreamDevDeps` loop in `extensions/server.ts` — and promoted into `dependencies`, preferring the upstream peer RANGE over the exact devDep pin where one exists, so a generated project still receives patch-level security fixes. A package that appears ONLY in upstream `peerDependencies` cannot be promoted by this list: listing it here is a silent no-op. Two live cases: `find-file-up` (imported by the config loader, devDependency only), and the better-auth trio (declared as peerDependencies AND mirrored into devDependencies upstream; the mirror is what makes the promotion fire, so this list is the fallback if the starter ever stops declaring them itself).",
3
- "runtimeHelpers": ["@better-auth/core", "@better-auth/passkey", "better-auth", "find-file-up"]
2
+ "$comment": "Upstream @lenne.tech/nest-server DEVDEPENDENCIES that must land in a vendored project's `dependencies`. Vendoring copies upstream `dependencies` verbatim and does not read `peerDependencies` at all, so a package the framework imports at runtime while keeping it in devDependencies would never reach the production runtime. Entries here are matched against upstream `devDependencies` only — see `isVendorRuntimeDep`, consulted in the `upstreamDevDeps` loop in `extensions/server.ts` — and promoted into `dependencies`, preferring the upstream peer RANGE over the exact devDep pin where one exists, so a generated project still receives patch-level security fixes. A package that appears ONLY in upstream `peerDependencies` cannot be promoted by this list: listing it here is a silent no-op. One live case: the better-auth trio (declared as peerDependencies AND mirrored into devDependencies upstream; the mirror is what makes the promotion fire, so this list is the fallback if the starter ever stops declaring them itself). `find-file-up` was listed here until 2026-10-03 and never needed: no nest-server release from 8.x to 11.x imports it from src/ (only the dev script extras/sync-version.ts did), and 11.41.8 dropped the package altogether.",
3
+ "runtimeHelpers": ["@better-auth/core", "@better-auth/passkey", "better-auth"]
4
4
  }
@@ -43,21 +43,6 @@ class PackageManager {
43
43
  const manager = pm || this.detect();
44
44
  return manager;
45
45
  }
46
- /**
47
- * Get the cache clean command
48
- * @param pm - Override detected package manager
49
- */
50
- cacheClean(pm) {
51
- const manager = pm || this.detect();
52
- switch (manager) {
53
- case 'pnpm':
54
- return 'pnpm store prune';
55
- case 'yarn':
56
- return 'yarn cache clean';
57
- default:
58
- return 'npm cache clean --force';
59
- }
60
- }
61
46
  /**
62
47
  * Detect the package manager for the given directory
63
48
  * Uses caching per directory for performance
@@ -1919,8 +1919,8 @@ class Server {
1919
1919
  * dep in disguise that needs to live in `dependencies` after vendoring?
1920
1920
  *
1921
1921
  * `@lenne.tech/nest-server` keeps a few packages in devDependencies that
1922
- * the framework code imports at runtime (e.g. `find-file-up` in its
1923
- * config loader). When we vendor the framework source into a consumer
1922
+ * the framework code imports at runtime (e.g. the better-auth trio, which
1923
+ * it mirrors from peerDependencies). When we vendor the framework source into a consumer
1924
1924
  * project, those must end up in `dependencies` so the compiled/dist
1925
1925
  * runtime has them available.
1926
1926
  *
@@ -37,14 +37,23 @@ function describeLog(d) {
37
37
  }
38
38
  return [`Last lines of ${d.file}:`, ...d.tail.map((l) => ` ${l}`)];
39
39
  }
40
- /** Read `file` and keep its last `lines` non-empty lines. */
41
- function diagnoseLog(file, lines = 20) {
40
+ /**
41
+ * How much of a log's end is read. A dev log reached 1 GB (Vue warnings carry
42
+ * serialized vnode traces of several MB each), and reading all of it to show 20
43
+ * lines threw "Cannot create a string longer than 0x1fffffe8 characters".
44
+ */
45
+ const TAIL_BYTES = 64 * 1024;
46
+ /** Longest line shown: one of those traces would otherwise flood the terminal. */
47
+ const MAX_LINE_LENGTH = 500;
48
+ /** Read the end of `file` and keep its last `lines` non-empty lines. */
49
+ function diagnoseLog(file, lines = 20, maxBytes = TAIL_BYTES) {
42
50
  if (!(0, fs_1.existsSync)(file))
43
51
  return { file, size: -1, state: 'missing', tail: [] };
44
52
  const size = (0, fs_1.statSync)(file).size;
45
53
  if (size === 0)
46
54
  return { file, size, state: 'empty', tail: [] };
47
- return { file, size, state: 'ok', tail: tailLines((0, fs_1.readFileSync)(file, 'utf8'), lines) };
55
+ const tail = tailLines(readEnd(file, size, maxBytes), lines).map((l) => l.length > MAX_LINE_LENGTH ? `${l.slice(0, MAX_LINE_LENGTH)}…` : l);
56
+ return { file, size, state: 'ok', tail };
48
57
  }
49
58
  /**
50
59
  * Components whose pid is gone within `budgetMs` of their start.
@@ -89,3 +98,24 @@ function tailLines(content, n) {
89
98
  .filter((l) => l.trim().length > 0)
90
99
  .slice(-n);
91
100
  }
101
+ /**
102
+ * The last `maxBytes` of `file`. The first line of a cut window is partial and
103
+ * dropped, unless the window lies inside one line: then the fragment is kept,
104
+ * marked with a leading `…`.
105
+ */
106
+ function readEnd(file, size, maxBytes) {
107
+ const length = Math.min(size, maxBytes);
108
+ const buffer = Buffer.alloc(length);
109
+ const fd = (0, fs_1.openSync)(file, 'r');
110
+ try {
111
+ (0, fs_1.readSync)(fd, buffer, 0, length, size - length);
112
+ }
113
+ finally {
114
+ (0, fs_1.closeSync)(fd);
115
+ }
116
+ const text = buffer.toString('utf8');
117
+ if (length === size)
118
+ return text;
119
+ const rest = text.slice(text.indexOf('\n') + 1);
120
+ return text.includes('\n') && rest.trim() ? rest : `…${text}`;
121
+ }
@@ -180,7 +180,18 @@ function patchClaudeMd(file, options) {
180
180
  if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
181
181
  const before = content.slice(0, startIdx);
182
182
  const after = content.slice(endIdx + endMarker.length);
183
- next = before + block + after;
183
+ // Anything between the markers that is NOT this generated block is somebody's own writing,
184
+ // and it is kept — moved out in front of the block rather than overwritten.
185
+ //
186
+ // Replacing the span wholesale was silent data loss, observed in `offers`: a 29-line section
187
+ // of project documentation sat between the markers and one `lt dev up` deleted it, reporting
188
+ // only "updated CLAUDE.md URL block in 1 file(s)". Nothing about the markers suggests the
189
+ // span is owned — they are HTML comments, so they are invisible in every rendered view of the
190
+ // file, and a section appended after the preceding one lands inside them without anyone
191
+ // seeing it. The only reason it was noticed at all is that the file happened to be under
192
+ // review in the same minute.
193
+ const rescued = rescueForeignContent(content.slice(startIdx + startMarker.length, endIdx));
194
+ next = before + (rescued ? `${rescued}\n\n` : '') + block + after;
184
195
  }
185
196
  else {
186
197
  const sep = content.endsWith('\n\n') ? '' : content.endsWith('\n') ? '\n' : '\n\n';
@@ -427,3 +438,26 @@ function normaliseBridgeBlock(s) {
427
438
  .replace(/\s+/g, ' ')
428
439
  .trim();
429
440
  }
441
+ /**
442
+ * Pull out the sections between the lt-dev markers that this tool did not write.
443
+ *
444
+ * The generated block is one section, `## Local Development (lt dev)`. Every other `##` section
445
+ * found inside the markers was written by somebody else and is returned so the caller can place
446
+ * it outside the block. Whitespace-only remainders are dropped — that is the generated block's
447
+ * own padding, not content.
448
+ *
449
+ * Deliberately conservative about what counts as ours: a section is discarded only when its
450
+ * heading matches exactly. A renamed or hand-edited heading is treated as foreign and kept, which
451
+ * leaves a duplicate for a human to resolve. A duplicate is visible; a deletion is not.
452
+ */
453
+ function rescueForeignContent(span) {
454
+ const own = '## Local Development (lt dev)';
455
+ const sections = span.split(/\n(?=## )/);
456
+ // Compare the whole heading line, not a prefix: `## Local Development (lt dev) — notes` is a
457
+ // section somebody wrote next to ours, and a prefix match would delete it.
458
+ const foreign = sections
459
+ .filter((section) => section.trimStart().split(/\r?\n/, 1)[0].trim() !== own)
460
+ .map((section) => section.trim())
461
+ .filter(Boolean);
462
+ return foreign.join('\n\n');
463
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildReinitCommand = buildReinitCommand;
4
+ /**
5
+ * Shell command for `lt npm reinit` in a project without its own `reinit` script:
6
+ * remove the lockfile and node_modules, then install fresh.
7
+ *
8
+ * Deliberately no cache step. `pnpm store prune` empties the machine-wide store on APFS
9
+ * (clone imports leave every store file with link count 1, which is exactly what prune
10
+ * deletes), and `npm cache clean --force` / `yarn cache clean` wipe the shared caches the
11
+ * same way — every other project then downloads again, and a parallel install loses the
12
+ * files it is linking. A fresh resolution needs neither: deleting the lockfile is what
13
+ * makes the package manager ask the registry again, and pnpm verifies store integrity
14
+ * on every install.
15
+ */
16
+ function buildReinitCommand(opts) {
17
+ const { dir, install, lockfile } = opts;
18
+ return `cd ${dir} && rimraf ${lockfile} && rimraf node_modules && ${install}`;
19
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/cli",
3
- "version": "1.50.1",
3
+ "version": "1.50.2",
4
4
  "description": "lenne.Tech CLI: lt",
5
5
  "keywords": [
6
6
  "lenne.Tech",
@@ -41,7 +41,7 @@
41
41
  "lint:fix": "eslint \"./src/**/*.{ts,js,vue}\" --fix",
42
42
  "prepublishOnly": "npm run build",
43
43
  "preversion": "npm run lint",
44
- "reinit": "npx rimraf package-lock.json && npx rimraf node_modules && npm cache clean --force && npm i && npm run build",
44
+ "reinit": "npx rimraf package-lock.json && npx rimraf node_modules && npm i && npm run build",
45
45
  "snapupdate": "jest --updateSnapshot",
46
46
  "start": "node bin/lt",
47
47
  "start:build": "npm run build && node bin/lt --compiled-build",
@@ -58,12 +58,13 @@
58
58
  "bin"
59
59
  ],
60
60
  "dependencies": {
61
- "@aws-sdk/client-s3": "3.1100.0",
61
+ "@aws-sdk/client-s3": "3.1146.0",
62
62
  "@lenne.tech/cli-plugin-helper": "0.0.14",
63
- "axios": "1.19.0",
63
+ "axios": "1.20.0",
64
64
  "bcrypt": "6.0.0",
65
65
  "cross-spawn": "7.0.6",
66
- "defuddle": "0.19.2",
66
+ "defuddle": "0.19.4",
67
+ "ejs": "6.0.1",
67
68
  "glob": "13.0.6",
68
69
  "gluegun": "5.2.2",
69
70
  "js-sha256": "1.0.0",
@@ -71,8 +72,8 @@
71
72
  "jsdom": "29.1.1",
72
73
  "jsonc-parser": "3.3.1",
73
74
  "lodash": "4.18.1",
74
- "open": "11.0.0",
75
- "playwright-core": "1.62.1",
75
+ "open": "11.0.4",
76
+ "playwright-core": "1.63.0",
76
77
  "ts-morph": "28.0.0",
77
78
  "ts-node": "10.9.2",
78
79
  "turndown": "7.2.4",
@@ -84,8 +85,8 @@
84
85
  "@emnapi/runtime": "Same as @emnapi/core."
85
86
  },
86
87
  "devDependencies": {
87
- "@emnapi/core": "^1.11.3",
88
- "@emnapi/runtime": "^1.11.3",
88
+ "@emnapi/core": "1.11.3",
89
+ "@emnapi/runtime": "1.11.3",
89
90
  "@lenne.tech/eslint-config-ts": "2.3.0",
90
91
  "@lenne.tech/npm-package-helper": "0.0.12",
91
92
  "@types/cross-spawn": "6.0.6",
@@ -93,33 +94,32 @@
93
94
  "@types/jest": "30.0.0",
94
95
  "@types/js-yaml": "4.0.9",
95
96
  "@types/jsdom": "28.0.1",
96
- "@types/lodash": "4.17.24",
97
- "@types/node": "26.1.2",
97
+ "@types/lodash": "4.17.25",
98
+ "@types/node": "26.6.4",
98
99
  "@types/turndown": "5.0.6",
99
- "ejs": "6.0.1",
100
- "eslint": "10.8.0",
100
+ "eslint": "10.12.0",
101
101
  "husky": "9.1.7",
102
- "jest": "30.4.2",
102
+ "jest": "30.5.2",
103
103
  "minimatch": "10.2.6",
104
- "prettier": "3.8.3",
104
+ "prettier": "3.9.9",
105
105
  "rimraf": "6.1.3",
106
- "ts-jest": "29.4.12"
106
+ "ts-jest": "29.4.14"
107
107
  },
108
108
  "//overrides": {
109
109
  "semver@*": "Force latest semver 7.x across all sub-deps; gluegun@5.2.2 pins semver@7.7.0 which is stale - remove once gluegun updates its dep.",
110
- "brace-expansion@<1.1.18": "Two DoS advisories: exponential-time expansion of consecutive non-expanding {} groups (GHSA-3jxr-9vmj-r5cp, high) and unbounded expansion length causing an OOM crash (GHSA-mh99-v99m-4gvg, high). Transitive via dotgitignore/eslint/fs-jetpack/glob/test-exclude/ts-morph > minimatch. One bounded key per affected major so each can only raise a vulnerable version, never cap a patched one - remove once minimatch requests the patched ranges.",
111
- "brace-expansion@>=2.0.0 <2.1.4": "Same advisories, 2.x line.",
112
- "brace-expansion@>=5.0.0 <5.0.9": "Same advisories, 5.x line. Floored at >=5.0.0 so a future 3.x/4.x dependency is not silently forced across two majors.",
113
- "//minimatch-note": "brace-expansion 1.x and 2.x are END OF LINE for GHSA-mh99-v99m-4gvg: the advisory range is <=5.0.7 across ALL majors and upstream patched ONLY 5.0.8+. 1.1.18 and 2.1.4 are the newest releases of their majors and remain vulnerable. Forcing brace-expansion 5.x globally is NOT an option: 5.x is ESM/tshy and exports an object ({ expand, ... }) while 1.x/2.x export the function itself, so minimatch 3.x/5.x would die on `expand is not a function`. The only real fix is to raise each CONSUMER off minimatch 3.x/5.x, which is what the scoped entries below do. Each was verified against the consumer's actual call site before being added. The eslint / @eslint/eslintrc / @eslint/config-array entries were REMOVED in 1.42.0: eslint 10 requests minimatch ^10.2.5 itself, config-array ^10.2.4, and eslintrc is no longer in the tree at all.",
114
- "minimatch@>=4 <10": "Bounded raise of every minimatch 4.x-9.x install to 10.2.6, whose brace-expansion ^5.0.8 is patched. Covers filelist (gluegun > ejs > jake > filelist, PRODUCTION-reachable, minimatch ^5.0.1), @typescript-eslint/typescript-estree (^9.0.4) and jest-config/jest-runtime/@jest/reporters (^9). Verified safe per consumer: filelist calls only the static helper `minimatch.match(files, pat, opts)`; typescript-estree calls the named `minimatch(filePath, pattern, { dot: true })`; the three jest packages declare minimatch but never require it. Floored at >=4 so the 3.x line is NOT swept in: minimatch 3.x is callable while 9.x/10.x export an object with __esModule but no `default` key, so sweeping it would break any consumer that calls the default export. Drop once these consumers request minimatch >=10 themselves.",
115
- "babel-plugin-istanbul > test-exclude@<8": "test-exclude 6.0.0 pins minimatch ^3.0.4 and glob ^7. test-exclude 8.0.0 uses minimatch ^10.2.2 + glob ^13 (the glob major this project already ships) and is still CJS with the same `module.exports = TestExclude` class shape, so babel-plugin-istanbul's _interopRequireDefault + `new TestExclude(opts)` keeps working. Drop once babel-plugin-istanbul widens its ^6.0.0 range.",
110
+ "brace-expansion@<1.1.21": "Five DoS advisories, all patched in the 1.x line by 1.1.21: exponential-time expansion of consecutive non-expanding {} groups (GHSA-3jxr-9vmj-r5cp, high, fixed 1.1.16), unbounded expansion length causing an OOM crash (GHSA-mh99-v99m-4gvg, high, fixed 1.1.17), uncontrolled recursion in parseCommaParts (GHSA-6j4f-fj2g-mc7p, high, fixed 1.1.19), uncontrolled recursion on nested brace groups (GHSA-qhr7-859c-m2p7, high, fixed 1.1.20) and quadratic-time `{a},b}` rewrite (GHSA-q2hr-2g5m-vwhr, medium, fixed 1.1.21). Raised from 1.1.18 on 2026-10-03: 1.1.18 was still open to the last three. Transitive via dotgitignore/eslint/fs-jetpack/glob/test-exclude/ts-morph > minimatch. Latent today: the minimatch raises below leave no 1.x install in the tree (only brace-expansion 5.0.12), so this key catches a future minimatch 3.x consumer. One bounded key per affected major so each can only raise a vulnerable version, never cap a patched one - remove once minimatch requests the patched ranges.",
111
+ "brace-expansion@>=2.0.0 <2.1.7": "Same five advisories, 2.x line (fixed 2.1.2 / 2.1.3 / 2.1.5 / 2.1.6 / 2.1.7). Raised from 2.1.4 on 2026-10-03. Latent today, like the 1.x key.",
112
+ "brace-expansion@>=5.0.0 <5.0.12": "Same advisories, 5.x line, plus three newer DoS advisories fixed only in 5.0.10-5.0.12 (GHSA-6j4f-fj2g-mc7p, GHSA-qhr7-859c-m2p7, GHSA-q2hr-2g5m-vwhr; all high). Reaches production via gluegun > fs-jetpack > minimatch. Floored at >=5.0.0 so a future 3.x/4.x dependency is not silently forced across two majors.",
113
+ "//minimatch-note": "Why the minimatch raises exist: when they were added, brace-expansion 1.x and 2.x were END OF LINE for GHSA-mh99-v99m-4gvg (advisory range <=5.0.7 across ALL majors, patched only 5.0.8+), so the only fix was to raise each CONSUMER off minimatch 3.x/5.x/9.x. That premise no longer holds: upstream has since backported every fix (GHSA-mh99 now reads <1.1.17 / >=2.0.0 <2.1.3, and 1.1.21 / 2.1.7 patch all five current advisories). Verified 2026-10-03 with fresh lockfile resolves: without `minimatch@>=4 <10` and `fs-jetpack > minimatch@<10` npm audit is still clean, the tree only gains minimatch 3.1.5 + 5.1.9 and brace-expansion 1.1.21 + 2.1.7 (7 packages). So both are now a DEDUPE measure (one minimatch 10.2.6, one brace-expansion 5.0.12), not a security fix - dropping them is a judgment call, it reopens no advisory. Forcing brace-expansion 5.x globally is still NOT an option: 5.x is ESM/tshy and exports an object ({ expand, ... }) while 1.x/2.x export the function itself, so minimatch 3.x/5.x would die on `expand is not a function`. Each scoped entry was verified against the consumer's actual call site before being added. The eslint / @eslint/eslintrc / @eslint/config-array entries were REMOVED in 1.42.0: eslint 10 requests minimatch ^10.2.5 itself, config-array ^10.2.4, and eslintrc is no longer in the tree at all.",
114
+ "minimatch@>=4 <10": "Bounded raise of every minimatch 4.x-9.x install to 10.2.6, whose brace-expansion ^5.0.8 is patched. As of 2026-10-03 the only consumer it still raises is filelist (gluegun > ejs 3.1.10 > jake > filelist, PRODUCTION-reachable, minimatch ^5.0.1): @typescript-eslint/typescript-estree 8.65 requests ^10.2.2 itself and the jest 30.5 packages no longer depend on minimatch. Verified safe: filelist calls only the static helper `minimatch.match(files, pat, opts)`. Floored at >=4 so the 3.x line is NOT swept in: minimatch 3.x is callable while 9.x/10.x export an object with __esModule but no `default` key, so sweeping it would break any consumer that calls the default export. Dedupe, not security (see //minimatch-note). Drop once filelist requests minimatch >=10.",
115
+ "babel-plugin-istanbul > test-exclude@<8": "Dedupe override, no longer a security fix. Added when babel-plugin-istanbul requested test-exclude ^6.0.0, whose 6.0.0 pins minimatch ^3.0.4 and glob ^7. Since jest 30.5 (babel-plugin-istanbul 8.0.0) the request is ^7.0.1, and test-exclude 7.0.2 already uses minimatch ^10.2.2: a fresh resolve without this entry audits clean (2026-10-03) but adds 23 packages (glob 10.5.0 and its subtree). 8.0.0 uses glob ^13, the major this project already ships, and is still CJS with the same `module.exports = TestExclude` class shape, so babel-plugin-istanbul 8's _interopRequireDefault + `new _testExclude.default(opts)` keeps working. Drop once babel-plugin-istanbul requests test-exclude ^8.",
116
116
  "fs-jetpack > minimatch@<10": "Same chain, PRODUCTION-reachable (gluegun > fs-jetpack). Safe: lib/utils/matcher.js does `require('minimatch').Minimatch` and uses only `new Minimatch(pattern, { matchBase, nocomment, nocase, dot })`, `.negate` and `.match()` - all verified against 10.x. Not fixable by upgrading fs-jetpack: gluegun@5.2.2 is the latest release and fs-jetpack@5.1.0 still requests minimatch ^5.1.0 (brace-expansion ^2.0.1, also unpatched)."
117
117
  },
118
118
  "overrides": {
119
119
  "semver@*": "7.8.5",
120
- "brace-expansion@<1.1.18": "1.1.18",
121
- "brace-expansion@>=2.0.0 <2.1.4": "2.1.4",
122
- "brace-expansion@>=5.0.0 <5.0.9": "5.0.9",
120
+ "brace-expansion@<1.1.21": "1.1.21",
121
+ "brace-expansion@>=2.0.0 <2.1.7": "2.1.7",
122
+ "brace-expansion@>=5.0.0 <5.0.12": "5.0.12",
123
123
  "fs-jetpack": {
124
124
  "minimatch@<10": "10.2.6"
125
125
  },