@nimbus-sh/worker 0.9.0 → 0.10.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/dist/esbuild-wasm-bundle.generated.d.ts +24 -24
- package/dist/esbuild-wasm-bundle.generated.d.ts.map +1 -1
- package/dist/esbuild-wasm-bundle.generated.js +24 -24
- package/dist/facets/cirrus-real.js +3 -3
- package/dist/facets/compose.js +9 -2
- package/dist/facets/esbuild-bundle-pool.d.ts +1 -1
- package/dist/facets/esbuild-bundle-pool.js +3 -3
- package/dist/facets/esbuild-transform.d.ts +6 -2
- package/dist/facets/esbuild-transform.d.ts.map +1 -1
- package/dist/facets/esbuild-transform.js +8 -4
- package/dist/facets/manager.d.ts +28 -0
- package/dist/facets/manager.d.ts.map +1 -1
- package/dist/facets/manager.js +89 -37
- package/dist/facets/real-vite-hmr.d.ts +2 -0
- package/dist/facets/real-vite-hmr.d.ts.map +1 -1
- package/dist/facets/real-vite-hmr.js +3 -2
- package/dist/git/commands.d.ts +17 -1
- package/dist/git/commands.d.ts.map +1 -1
- package/dist/git/commands.js +73 -9
- package/dist/git/network-facet.d.ts +2 -0
- package/dist/git/network-facet.d.ts.map +1 -1
- package/dist/git/network-facet.js +10 -5
- package/dist/hosted/commands.d.ts.map +1 -1
- package/dist/hosted/commands.js +2 -2
- package/dist/hosted/runtime.d.ts +3 -2
- package/dist/hosted/runtime.d.ts.map +1 -1
- package/dist/hosted/runtime.js +1 -0
- package/dist/hosted/services.d.ts +8 -0
- package/dist/hosted/services.d.ts.map +1 -1
- package/dist/hosted/services.js +3 -0
- package/dist/loaders/generated-workers.d.ts +2 -2
- package/dist/loaders/generated-workers.d.ts.map +1 -1
- package/dist/loaders/generated-workers.js +4 -4
- package/dist/loaders/pre-bundle-preamble.d.ts +6 -3
- package/dist/loaders/pre-bundle-preamble.d.ts.map +1 -1
- package/dist/loaders/pre-bundle-preamble.js +13 -8
- package/dist/node-shims-artifact.generated.js +3 -3
- package/dist/npm/cache.d.ts +6 -1
- package/dist/npm/cache.d.ts.map +1 -1
- package/dist/npm/cache.js +8 -6
- package/dist/npm/install-batch-facet.d.ts +2 -0
- package/dist/npm/install-batch-facet.d.ts.map +1 -1
- package/dist/npm/install-batch-facet.js +29 -15
- package/dist/npm/installer.d.ts +8 -4
- package/dist/npm/installer.d.ts.map +1 -1
- package/dist/npm/installer.js +173 -113
- package/dist/npm/npx-install.d.ts +3 -1
- package/dist/npm/npx-install.d.ts.map +1 -1
- package/dist/npm/npx-install.js +4 -1
- package/dist/npm/placement.d.ts +16 -0
- package/dist/npm/placement.d.ts.map +1 -0
- package/dist/npm/placement.js +33 -0
- package/dist/npm/r2-cache.d.ts +10 -6
- package/dist/npm/r2-cache.d.ts.map +1 -1
- package/dist/npm/r2-cache.js +32 -16
- package/dist/npm/resolve-one-facet.d.ts +3 -0
- package/dist/npm/resolve-one-facet.d.ts.map +1 -1
- package/dist/npm/resolve-one-facet.js +1 -0
- package/dist/npm/resolver.d.ts +11 -6
- package/dist/npm/resolver.d.ts.map +1 -1
- package/dist/npm/resolver.js +12 -3
- package/dist/runtime/cpython-resident.d.ts.map +1 -1
- package/dist/runtime/cpython-resident.js +2 -10
- package/dist/runtime/esbuild-wasm-bytes.d.ts +25 -18
- package/dist/runtime/esbuild-wasm-bytes.d.ts.map +1 -1
- package/dist/runtime/esbuild-wasm-bytes.js +55 -30
- package/dist/runtime/facet-loader-host.d.ts.map +1 -1
- package/dist/runtime/facet-loader-host.js +0 -7
- package/dist/runtime/node-shims.d.ts.map +1 -1
- package/dist/runtime/node-shims.js +839 -180
- package/dist/runtime/python-repl.d.ts.map +1 -1
- package/dist/runtime/python-repl.js +2 -33
- package/dist/runtime/ruby-resident.d.ts.map +1 -1
- package/dist/runtime/ruby-resident.js +5 -16
- package/dist/runtime/wasi/preamble.d.ts +0 -22
- package/dist/runtime/wasi/preamble.d.ts.map +1 -1
- package/dist/runtime/wasi/preamble.js +98 -1401
- package/dist/session/hibernation.d.ts +45 -2
- package/dist/session/hibernation.d.ts.map +1 -1
- package/dist/session/hibernation.js +78 -1
- package/dist/session/nimbus-session.d.ts +10 -2
- package/dist/session/nimbus-session.d.ts.map +1 -1
- package/dist/session/nimbus-session.js +13 -1
- package/dist/session/npm-install-port.d.ts.map +1 -1
- package/dist/session/npm-install-port.js +1 -0
- package/dist/session/routes.d.ts.map +1 -1
- package/dist/session/routes.js +4 -2
- package/dist/session/rpc.d.ts +5 -2
- package/dist/session/rpc.d.ts.map +1 -1
- package/dist/session/rpc.js +10 -2
- package/dist/session/supervisor-rpc.d.ts +17 -9
- package/dist/session/supervisor-rpc.d.ts.map +1 -1
- package/dist/session/supervisor-rpc.js +15 -22
- package/dist/workspace-host.d.ts +1 -1
- package/dist/workspace-host.d.ts.map +1 -1
- package/dist/wrangler/nimbus-wrangler.d.ts.map +1 -1
- package/dist/wrangler/nimbus-wrangler.js +3 -0
- package/package.json +30 -4
- package/public/_assets/esbuild-0.24.2.js +2380 -0
- package/public/_assets/runtime/{node-shims-acaa037e6d26ec0d.js → node-shims-7b4dd7a76d95d21e.js} +838 -179
- package/scripts/bundle-esbuild-wasm.mjs +55 -39
- package/scripts/bundle-facet-workers.mjs +45 -7
package/dist/npm/installer.d.ts
CHANGED
|
@@ -91,6 +91,7 @@ export declare class NpmInstaller {
|
|
|
91
91
|
pid?: number;
|
|
92
92
|
npmLog?: NpmLogEmitter;
|
|
93
93
|
onProgress?: (msg: string) => void;
|
|
94
|
+
registry?: string;
|
|
94
95
|
}): Promise<NpmInstallResult>;
|
|
95
96
|
private _installInner;
|
|
96
97
|
/**
|
|
@@ -103,8 +104,13 @@ export declare class NpmInstaller {
|
|
|
103
104
|
* width < IN_DO_THRESHOLD (5) → in-DO fanout in-DO loader-pool
|
|
104
105
|
* width >= IN_DO_THRESHOLD → peer-DO fanout peer-DO (sibling NimbusSession DOs)
|
|
105
106
|
*
|
|
107
|
+
* Resolution is per edge, not per name: the first version of a name goes
|
|
108
|
+
* to root; a later edge the nearest visible placement does not satisfy
|
|
109
|
+
* nests a copy under its dependent, never higher (placement.ts; live case
|
|
110
|
+
* in tests/unit/npm-install-nested-conflict.mjs).
|
|
111
|
+
*
|
|
106
112
|
* The supervisor still owns:
|
|
107
|
-
* -
|
|
113
|
+
* - placement (`placed` / `pending` / `settled`, by placement path),
|
|
108
114
|
* - X.5-F top-level / required-peer policy,
|
|
109
115
|
* - X.5-G G1 optional-native silent-skip,
|
|
110
116
|
* - X.5-drizzle best-effort tagging on optional-peer subtrees,
|
|
@@ -170,9 +176,7 @@ export declare class NpmInstaller {
|
|
|
170
176
|
* Check if a lockfile is still valid against current package.json specs.
|
|
171
177
|
*/
|
|
172
178
|
private isLockfileValid;
|
|
173
|
-
/**
|
|
174
|
-
* Convert a lockfile back to resolved packages (for cache restore).
|
|
175
|
-
*/
|
|
179
|
+
/** Convert a lockfile back to resolved packages: root by name, nested by placement path. */
|
|
176
180
|
private lockfileToResolved;
|
|
177
181
|
/**
|
|
178
182
|
* Write lockfile to SQLite.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/npm/installer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EACV,SAAS,EAGV,MAAM,mCAAmC,CAAC;AAM3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAEjF,OAAO,EAAE,QAAQ,EAAsB,MAAM,YAAY,CAAC;AAC1D,OAAO,EAEiC,KAAK,OAAO,EACnD,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/npm/installer.ts"],"names":[],"mappings":"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"}
|
package/dist/npm/installer.js
CHANGED
|
@@ -22,8 +22,9 @@
|
|
|
22
22
|
import { CRED_KERNEL } from '@nimbus-sh/core/runtime/os-contracts.js';
|
|
23
23
|
import { BUNDLER_VERSION } from '@nimbus-sh/core/runtime/esbuild-service.js';
|
|
24
24
|
import { NpmCache } from './cache.js';
|
|
25
|
-
import { computeHoistPlan, } from './resolver.js';
|
|
26
|
-
import {
|
|
25
|
+
import { computeHoistPlan, hoistPlacements, } from './resolver.js';
|
|
26
|
+
import { nestedPlacement, visiblePlacements } from './placement.js';
|
|
27
|
+
import { npmRegistryOrigin, packumentUrl } from './r2-cache.js';
|
|
27
28
|
import { satisfiesRange, isSemverRange } from './semver.js';
|
|
28
29
|
import { npmAddedLine, npmHttpCacheLine, npmHttpFetchLine, npmTitleLine, } from '@nimbus-sh/core/substrate/lifo/commands/system/npm-log.js';
|
|
29
30
|
import { applySwaps, findRejects, lookupSwap, isOptionalNativeBinding, formatSwapNotice, emitRegistryEvent, } from '../facets/wasm-swap-registry.js';
|
|
@@ -115,6 +116,7 @@ export class NpmInstaller {
|
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
async _installInner(projDir, nmDir, opts, log, start) {
|
|
119
|
+
const registry = npmRegistryOrigin(opts?.registry);
|
|
118
120
|
const phases = {};
|
|
119
121
|
const installed = [];
|
|
120
122
|
const failed = [];
|
|
@@ -143,10 +145,11 @@ export class NpmInstaller {
|
|
|
143
145
|
}
|
|
144
146
|
const lockfile = this.cache.readLockfile(projDir);
|
|
145
147
|
let resolved;
|
|
148
|
+
let nested;
|
|
146
149
|
let usedLockfile = false;
|
|
147
150
|
if (lockfile && !opts?.packages && this.isLockfileValid(lockfile, specs)) {
|
|
148
151
|
log(`Lockfile valid (${lockfile.size} packages). Skipping resolution.`);
|
|
149
|
-
resolved = this.lockfileToResolved(lockfile);
|
|
152
|
+
({ resolved, nested } = this.lockfileToResolved(lockfile));
|
|
150
153
|
usedLockfile = true;
|
|
151
154
|
phases['lock-check'] = Date.now() - phaseStart;
|
|
152
155
|
}
|
|
@@ -166,8 +169,9 @@ export class NpmInstaller {
|
|
|
166
169
|
phaseStart = Date.now();
|
|
167
170
|
setInstallPhase('resolve');
|
|
168
171
|
log(`Resolving ${Object.keys(specs).length} dependencies (path: fanout, fetch: ${this.fetchFn ? 'facet-proxy' : 'global'})...`);
|
|
169
|
-
const tree = await this.resolveTreeViaFanout(specs, log, { optionalRoots, devOnly, advised });
|
|
172
|
+
const tree = await this.resolveTreeViaFanout(specs, log, { optionalRoots, devOnly, advised, registry });
|
|
170
173
|
resolved = tree.resolved;
|
|
174
|
+
nested = tree.nested;
|
|
171
175
|
phases['resolve'] = Date.now() - phaseStart;
|
|
172
176
|
// Transitive platform-gate refusals. Required ones join `failed`
|
|
173
177
|
// with their reason; optional-edge ones stay out of the outcome
|
|
@@ -197,13 +201,15 @@ export class NpmInstaller {
|
|
|
197
201
|
// ── Phase 2: Hoist ────────────────────────────────────────────────
|
|
198
202
|
phaseStart = Date.now();
|
|
199
203
|
setInstallPhase('hoist');
|
|
200
|
-
const hoistPlan = computeHoistPlan(resolved);
|
|
204
|
+
const hoistPlan = computeHoistPlan(resolved, nested);
|
|
201
205
|
phases['hoist'] = Date.now() - phaseStart;
|
|
202
206
|
// ── Phase 3: Diff (cache check) ─────────────────────────────────
|
|
207
|
+
// Per placement: a nested copy is checked at its own directory.
|
|
203
208
|
phaseStart = Date.now();
|
|
204
209
|
setInstallPhase('diff');
|
|
205
210
|
const toFetch = [];
|
|
206
|
-
for (const
|
|
211
|
+
for (const target of hoistPlacements(hoistPlan)) {
|
|
212
|
+
const { pkg } = target;
|
|
207
213
|
if (!pkg.tarballUrl) {
|
|
208
214
|
// Resolved metadata with no tarball cannot be installed. Silently
|
|
209
215
|
// dropping it here left the package absent from node_modules and
|
|
@@ -213,7 +219,7 @@ export class NpmInstaller {
|
|
|
213
219
|
continue;
|
|
214
220
|
}
|
|
215
221
|
// Check if already installed at the correct path
|
|
216
|
-
const pkgJsonPath = nmDir + '/' +
|
|
222
|
+
const pkgJsonPath = nmDir + '/' + target.placement + '/package.json';
|
|
217
223
|
if (this.vfs.exists(pkgJsonPath)) {
|
|
218
224
|
try {
|
|
219
225
|
const existing = JSON.parse(this.vfs.readFileString(pkgJsonPath));
|
|
@@ -229,7 +235,7 @@ export class NpmInstaller {
|
|
|
229
235
|
// Not present in the VFS at the right version — fetch it. The batch
|
|
230
236
|
// facet consults the shared L2 (caches.default) + L3 (R2) tarball
|
|
231
237
|
// tiers itself, so a cross-DO warm cache still lands here.
|
|
232
|
-
toFetch.push(
|
|
238
|
+
toFetch.push(target);
|
|
233
239
|
}
|
|
234
240
|
phases['diff'] = Date.now() - phaseStart;
|
|
235
241
|
log(`To fetch: ${toFetch.length}, already installed: ${cachedHits}`);
|
|
@@ -257,7 +263,7 @@ export class NpmInstaller {
|
|
|
257
263
|
const commitsBefore = this.storageCommitCount();
|
|
258
264
|
if (toFetch.length > 0) {
|
|
259
265
|
log(`Fetching ${toFetch.length} packages... (path: batch-facet)`);
|
|
260
|
-
const batchResult = await this.fetchViaBatchFacet(toFetch,
|
|
266
|
+
const batchResult = await this.fetchViaBatchFacet(toFetch, nmDir, opts?.pid);
|
|
261
267
|
totalFiles += batchResult.filesWritten;
|
|
262
268
|
for (const name of batchResult.installed)
|
|
263
269
|
installed.push(name);
|
|
@@ -273,7 +279,7 @@ export class NpmInstaller {
|
|
|
273
279
|
phases['link-bins'] = Date.now() - phaseStart;
|
|
274
280
|
// ── Write lockfile ──────────────────────────────────────────────
|
|
275
281
|
if (!usedLockfile || opts?.packages) {
|
|
276
|
-
this.writeLockfile(projDir,
|
|
282
|
+
this.writeLockfile(projDir, hoistPlan, nmDir);
|
|
277
283
|
}
|
|
278
284
|
// ── Update package.json if explicit packages were added ─────────
|
|
279
285
|
if (opts?.packages && opts.packages.length > 0) {
|
|
@@ -400,7 +406,8 @@ export class NpmInstaller {
|
|
|
400
406
|
`${failed.length} missing: ${failed.join(', ')}`);
|
|
401
407
|
}
|
|
402
408
|
else {
|
|
403
|
-
|
|
409
|
+
const nestedNote = hoistPlan.nested.size > 0 ? ` (${hoistPlan.nested.size} nested)` : '';
|
|
410
|
+
log(`Done! ${installed.length} packages${nestedNote}, ${totalFiles} files in ${(elapsed / 1000).toFixed(1)}s`);
|
|
404
411
|
// npm's own summary line, unstyled: the styled one the command site
|
|
405
412
|
// prints carries a colour prefix that no log parser matches. Carried
|
|
406
413
|
// at `http` — the level from which this stream is machine-readable —
|
|
@@ -442,8 +449,13 @@ export class NpmInstaller {
|
|
|
442
449
|
* width < IN_DO_THRESHOLD (5) → in-DO fanout in-DO loader-pool
|
|
443
450
|
* width >= IN_DO_THRESHOLD → peer-DO fanout peer-DO (sibling NimbusSession DOs)
|
|
444
451
|
*
|
|
452
|
+
* Resolution is per edge, not per name: the first version of a name goes
|
|
453
|
+
* to root; a later edge the nearest visible placement does not satisfy
|
|
454
|
+
* nests a copy under its dependent, never higher (placement.ts; live case
|
|
455
|
+
* in tests/unit/npm-install-nested-conflict.mjs).
|
|
456
|
+
*
|
|
445
457
|
* The supervisor still owns:
|
|
446
|
-
* -
|
|
458
|
+
* - placement (`placed` / `pending` / `settled`, by placement path),
|
|
447
459
|
* - X.5-F top-level / required-peer policy,
|
|
448
460
|
* - X.5-G G1 optional-native silent-skip,
|
|
449
461
|
* - X.5-drizzle best-effort tagging on optional-peer subtrees,
|
|
@@ -465,6 +477,7 @@ export class NpmInstaller {
|
|
|
465
477
|
*/
|
|
466
478
|
async resolveTreeViaFanout(specs, log, opts = {}) {
|
|
467
479
|
const t0 = Date.now();
|
|
480
|
+
const registry = npmRegistryOrigin(opts.registry);
|
|
468
481
|
const optionalRoots = opts.optionalRoots ?? new Set();
|
|
469
482
|
const devOnly = opts.devOnly ?? new Set();
|
|
470
483
|
// Policy advisories already announced — one `note:` line per name
|
|
@@ -479,21 +492,27 @@ export class NpmInstaller {
|
|
|
479
492
|
log(`[npm] note: ${ev.from} has no Workers-compatible build${marker}: ${ev.reason}${hint}`);
|
|
480
493
|
};
|
|
481
494
|
const __f2Diag = (globalThis.process?.env?.NIMBUS_DIAG_INSTALL_PIPELINE === '1');
|
|
482
|
-
// Per-walk state — supervisor side.
|
|
495
|
+
// Per-walk state — supervisor side. Root by name, nested by placement
|
|
496
|
+
// path, `placed` is both; `pending` is dispatched and unanswered,
|
|
497
|
+
// `settled` answered whatever the answer was.
|
|
483
498
|
const resolved = new Map();
|
|
499
|
+
const nested = new Map();
|
|
500
|
+
const placed = new Map();
|
|
501
|
+
const pending = new Set();
|
|
502
|
+
const settled = new Set();
|
|
484
503
|
// Dependencies the walk asked for and could not resolve, name → reason.
|
|
485
|
-
// A name lands here at most once: the frontier marks it `seen` before
|
|
486
|
-
// dispatch, so no later parent re-enqueues it.
|
|
487
504
|
const unresolved = new Map();
|
|
488
505
|
// EBADPLATFORM refusals (os/cpu/libc allowlists), in walk order.
|
|
489
506
|
// Announced as `[skip]` lines at record time; required-vs-optional is
|
|
490
507
|
// classified at end of walk, when every required edge has been seen.
|
|
491
508
|
const refusals = new Map();
|
|
492
|
-
const seen = new Set();
|
|
493
509
|
const topLevelNames = new Set(Object.keys(specs));
|
|
494
510
|
const optionalNames = new Set(); // X.5-G G1
|
|
495
511
|
const bestEffortNames = new Set(); // X.5-drizzle
|
|
496
|
-
|
|
512
|
+
// A cycle with mutually incompatible ranges has no finite layout; the
|
|
513
|
+
// edge is refused at this depth rather than nested without end.
|
|
514
|
+
const MAX_NEST_DEPTH = 16;
|
|
515
|
+
let queue = Object.entries(specs).map(([name, range]) => ({ name, range, from: '', kind: 'dep' }));
|
|
497
516
|
const cacheWritesPending = [];
|
|
498
517
|
let totalPackumentBytes = 0;
|
|
499
518
|
let totalPackumentsDecoded = 0;
|
|
@@ -544,21 +563,53 @@ export class NpmInstaller {
|
|
|
544
563
|
// Frontier loop. Each iteration = ONE BFS layer dispatched as ONE
|
|
545
564
|
// submitMany batch.
|
|
546
565
|
while (queue.length > 0) {
|
|
547
|
-
//
|
|
548
|
-
//
|
|
549
|
-
//
|
|
566
|
+
// Decide each edge against what Node's walk from its dependent sees.
|
|
567
|
+
// One whose nearest visible placement is in flight waits a layer.
|
|
568
|
+
// A copy nested under a package is decided here in the layer after
|
|
569
|
+
// that package resolves, before anything beneath it can resolve, so
|
|
570
|
+
// no descendant is ever decided against a copy it will later shadow.
|
|
550
571
|
const layer = [];
|
|
551
|
-
const
|
|
552
|
-
for (const
|
|
553
|
-
|
|
572
|
+
const deferred = [];
|
|
573
|
+
for (const edge of queue) {
|
|
574
|
+
const req = parseRegistryRequest(edge.name, edge.range);
|
|
575
|
+
let target = edge.name;
|
|
576
|
+
let decided = false;
|
|
577
|
+
for (const candidate of visiblePlacements(edge.from, edge.name)) {
|
|
578
|
+
if (pending.has(candidate)) {
|
|
579
|
+
deferred.push(edge);
|
|
580
|
+
decided = true;
|
|
581
|
+
break;
|
|
582
|
+
}
|
|
583
|
+
const pkg = placed.get(candidate);
|
|
584
|
+
if (!pkg)
|
|
585
|
+
continue; // never asked or failed: the walk goes on upward
|
|
586
|
+
if (!isSemverRange(req.range) || satisfiesRange(pkg.version, req.range)) {
|
|
587
|
+
decided = true; // reuse
|
|
588
|
+
}
|
|
589
|
+
else if (edge.kind === 'peer') {
|
|
590
|
+
decided = true; // reuse anyway, and say so the way npm does
|
|
591
|
+
log(` [warn] peer ${edge.name}@${edge.range} from ${edge.from} is met by ${pkg.name}@${pkg.version} (${candidate})`);
|
|
592
|
+
}
|
|
593
|
+
else {
|
|
594
|
+
target = nestedPlacement(edge.from, edge.name);
|
|
595
|
+
}
|
|
596
|
+
break;
|
|
597
|
+
}
|
|
598
|
+
if (decided)
|
|
599
|
+
continue;
|
|
600
|
+
if (settled.has(target))
|
|
601
|
+
continue; // failed once, on record under the name
|
|
602
|
+
if (target.split('/node_modules/').length - 1 > MAX_NEST_DEPTH) {
|
|
603
|
+
unresolved.set(edge.name, `${edge.name}@${edge.range} from ${edge.from} would nest deeper than ${MAX_NEST_DEPTH} levels (cycle with incompatible ranges)`);
|
|
604
|
+
settled.add(target);
|
|
554
605
|
continue;
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
layer.push(
|
|
606
|
+
}
|
|
607
|
+
pending.add(target);
|
|
608
|
+
layer.push({ edge, placement: target });
|
|
558
609
|
}
|
|
559
|
-
queue =
|
|
610
|
+
queue = deferred;
|
|
560
611
|
if (__f2Diag) {
|
|
561
|
-
log(`[f2-frontier] N=${layerN} width=${layer.length} resolved-so-far=${resolved.size}
|
|
612
|
+
log(`[f2-frontier] N=${layerN} width=${layer.length} resolved-so-far=${resolved.size} settled=${settled.size}`);
|
|
562
613
|
}
|
|
563
614
|
if (layer.length === 0)
|
|
564
615
|
break;
|
|
@@ -570,7 +621,7 @@ export class NpmInstaller {
|
|
|
570
621
|
// cache slice (only entries for THIS name) so the per-task RPC
|
|
571
622
|
// stays small. Bounded to 16 versions per name — enough to cover
|
|
572
623
|
// ~2 majors of typical packages, well under any RPC arg size cap.
|
|
573
|
-
const tasks = layer.map((
|
|
624
|
+
const tasks = layer.map(({ edge: { name, range }, placement }) => {
|
|
574
625
|
const cachedRows = this.cache.getRegistryVersions(name).slice(0, 16);
|
|
575
626
|
const cachedEntries = cachedRows.map((e) => ({
|
|
576
627
|
name: e.name,
|
|
@@ -594,8 +645,9 @@ export class NpmInstaller {
|
|
|
594
645
|
isOptional: optionalNames.has(name),
|
|
595
646
|
fetchTimeoutMs: 15_000,
|
|
596
647
|
retries: 3,
|
|
648
|
+
registry,
|
|
597
649
|
};
|
|
598
|
-
return { key:
|
|
650
|
+
return { key: placement, args: taskSpec };
|
|
599
651
|
});
|
|
600
652
|
// Dispatch the layer. Fanout routes:
|
|
601
653
|
// <5 → in-DO fanout in-DO (IsolatePool), concurrency = layer.length (capped at 4)
|
|
@@ -617,7 +669,10 @@ export class NpmInstaller {
|
|
|
617
669
|
// fanout failed to deliver is recorded instead of skipped.
|
|
618
670
|
for (let i = 0; i < layer.length; i++) {
|
|
619
671
|
const res = results[i];
|
|
620
|
-
const
|
|
672
|
+
const { edge, placement } = layer[i];
|
|
673
|
+
const taskName = edge.name;
|
|
674
|
+
pending.delete(placement);
|
|
675
|
+
settled.add(placement);
|
|
621
676
|
if (!res) {
|
|
622
677
|
unresolved.set(taskName, `resolver fanout returned no result at layer ${layerN}`);
|
|
623
678
|
continue;
|
|
@@ -643,10 +698,10 @@ export class NpmInstaller {
|
|
|
643
698
|
// One `npm http` line per packument, reporting the tier that actually
|
|
644
699
|
// served it. A skipped task issued no request, so it gets no line.
|
|
645
700
|
if (res.packumentSource === 'network') {
|
|
646
|
-
this.npmLog('http', npmHttpFetchLine(packumentUrl(taskName), res.packumentElapsedMs));
|
|
701
|
+
this.npmLog('http', npmHttpFetchLine(packumentUrl(taskName, registry), res.packumentElapsedMs));
|
|
647
702
|
}
|
|
648
703
|
else if (res.packumentSource !== 'skipped') {
|
|
649
|
-
this.npmLog('http', npmHttpCacheLine(packumentUrl(taskName)));
|
|
704
|
+
this.npmLog('http', npmHttpCacheLine(packumentUrl(taskName, registry)));
|
|
650
705
|
}
|
|
651
706
|
totalPackumentBytes += res.packumentBytesDecoded;
|
|
652
707
|
if (res.packumentSource === 'r2-cache')
|
|
@@ -716,37 +771,39 @@ export class NpmInstaller {
|
|
|
716
771
|
continue;
|
|
717
772
|
}
|
|
718
773
|
}
|
|
719
|
-
|
|
774
|
+
// A W6 swap answers with another name; place what came back.
|
|
775
|
+
const isRoot = placement === taskName;
|
|
776
|
+
const actual = isRoot ? pkg.name : nestedPlacement(edge.from, pkg.name);
|
|
777
|
+
if (placed.has(actual))
|
|
720
778
|
continue;
|
|
721
|
-
|
|
722
|
-
|
|
779
|
+
placed.set(actual, pkg);
|
|
780
|
+
settled.add(actual);
|
|
781
|
+
if (isRoot)
|
|
782
|
+
resolved.set(pkg.name, pkg);
|
|
783
|
+
else
|
|
784
|
+
nested.set(actual, pkg);
|
|
785
|
+
// Edge extraction, from this package's own placement.
|
|
723
786
|
const inheritBestEffort = bestEffortNames.has(pkg.name);
|
|
724
787
|
for (const [depName, depRange] of Object.entries(pkg.dependencies)) {
|
|
725
|
-
if (resolved.has(depName) || seen.has(depName))
|
|
726
|
-
continue;
|
|
727
788
|
if (inheritBestEffort)
|
|
728
789
|
bestEffortNames.add(depName);
|
|
729
|
-
queue.push(
|
|
790
|
+
queue.push({ name: depName, range: depRange, from: actual, kind: 'dep' });
|
|
730
791
|
}
|
|
731
792
|
const optDeps = pkg.optionalDependencies;
|
|
732
793
|
if (optDeps) {
|
|
733
794
|
for (const [depName, depRange] of Object.entries(optDeps)) {
|
|
734
|
-
if (resolved.has(depName) || seen.has(depName))
|
|
735
|
-
continue;
|
|
736
795
|
optionalNames.add(depName);
|
|
737
796
|
if (inheritBestEffort)
|
|
738
797
|
bestEffortNames.add(depName);
|
|
739
|
-
queue.push(
|
|
798
|
+
queue.push({ name: depName, range: depRange, from: actual, kind: 'dep' });
|
|
740
799
|
}
|
|
741
800
|
}
|
|
742
801
|
if (pkg.peerDependencies) {
|
|
743
802
|
for (const [peerName, peerRange] of Object.entries(pkg.peerDependencies)) {
|
|
744
|
-
if (resolved.has(peerName) || seen.has(peerName))
|
|
745
|
-
continue;
|
|
746
803
|
topLevelNames.add(peerName);
|
|
747
804
|
if (inheritBestEffort)
|
|
748
805
|
bestEffortNames.add(peerName);
|
|
749
|
-
queue.push(
|
|
806
|
+
queue.push({ name: peerName, range: peerRange, from: actual, kind: 'peer' });
|
|
750
807
|
}
|
|
751
808
|
}
|
|
752
809
|
// X.5-F R2.5 + X.5-J: optional peers when THIS pkg is the
|
|
@@ -757,11 +814,9 @@ export class NpmInstaller {
|
|
|
757
814
|
const allPeers = pkg.__allPeerDependencies;
|
|
758
815
|
if (allPeers) {
|
|
759
816
|
for (const [peerName, peerRange] of Object.entries(allPeers)) {
|
|
760
|
-
if (resolved.has(peerName) || seen.has(peerName))
|
|
761
|
-
continue;
|
|
762
817
|
topLevelNames.add(peerName);
|
|
763
818
|
bestEffortNames.add(peerName);
|
|
764
|
-
queue.push(
|
|
819
|
+
queue.push({ name: peerName, range: peerRange, from: actual, kind: 'peer' });
|
|
765
820
|
}
|
|
766
821
|
}
|
|
767
822
|
}
|
|
@@ -776,13 +831,18 @@ export class NpmInstaller {
|
|
|
776
831
|
// sees names in BFS order, so incremental propagation would freeze a
|
|
777
832
|
// dev/optional first sighting before a later required edge lands.
|
|
778
833
|
const requiredNames = new Set();
|
|
834
|
+
// Followed by name over every placement, root first.
|
|
835
|
+
const byName = new Map(resolved);
|
|
836
|
+
for (const pkg of nested.values())
|
|
837
|
+
if (!byName.has(pkg.name))
|
|
838
|
+
byName.set(pkg.name, pkg);
|
|
779
839
|
const pendingRequired = Object.keys(specs).filter((name) => !optionalRoots.has(name));
|
|
780
840
|
for (let i = 0; i < pendingRequired.length; i++) {
|
|
781
841
|
const name = pendingRequired[i];
|
|
782
842
|
if (requiredNames.has(name))
|
|
783
843
|
continue;
|
|
784
844
|
requiredNames.add(name);
|
|
785
|
-
const pkg =
|
|
845
|
+
const pkg = byName.get(name);
|
|
786
846
|
if (!pkg)
|
|
787
847
|
continue;
|
|
788
848
|
const optional = pkg.optionalDependencies ?? {};
|
|
@@ -829,7 +889,7 @@ export class NpmInstaller {
|
|
|
829
889
|
`, dispatch barriers=${dispatchBarriers}, ` +
|
|
830
890
|
`elapsed=${((Date.now() - t0) / 1000).toFixed(1)}s` +
|
|
831
891
|
(unresolved.size > 0 ? `, unresolved=${unresolved.size}` : ''));
|
|
832
|
-
return { resolved, unresolved, rejected };
|
|
892
|
+
return { resolved, nested, unresolved, rejected };
|
|
833
893
|
}
|
|
834
894
|
/**
|
|
835
895
|
* Batch install via two-tier fan-out (Fanout).
|
|
@@ -855,31 +915,26 @@ export class NpmInstaller {
|
|
|
855
915
|
* Two-tier topology re-expands the fan-out without re-introducing
|
|
856
916
|
* the V8 cap risk.
|
|
857
917
|
*/
|
|
858
|
-
async fetchViaBatchFacet(toFetch,
|
|
918
|
+
async fetchViaBatchFacet(toFetch, nmDir, pid) {
|
|
859
919
|
const log = (msg) => this.onProgress?.(msg);
|
|
860
920
|
const installed = [];
|
|
861
921
|
const failed = [];
|
|
862
922
|
let filesWritten = 0;
|
|
863
923
|
const mtime = Date.now();
|
|
864
924
|
// Every entry in `toFetch` has a tarball URL — the diff phase fails
|
|
865
|
-
// the ones that don't rather than dropping them.
|
|
925
|
+
// the ones that don't rather than dropping them. `pkgDir` is the
|
|
926
|
+
// spec's identity: one version may land at two placements.
|
|
866
927
|
const specs = toFetch
|
|
867
|
-
.map((p) => ({
|
|
928
|
+
.map(({ placement, pkg: p }) => ({
|
|
868
929
|
name: p.name,
|
|
869
930
|
version: p.version,
|
|
870
931
|
tarballUrl: p.tarballUrl,
|
|
871
932
|
integrity: p.integrity || '',
|
|
872
|
-
pkgDir: nmDir + '/' +
|
|
933
|
+
pkgDir: nmDir + '/' + placement,
|
|
873
934
|
installRoot: nmDir,
|
|
874
935
|
mtime,
|
|
875
936
|
chunkSize: CHUNK_SIZE,
|
|
876
937
|
}));
|
|
877
|
-
// hoistPlan is intentionally unused: the current installer maps
|
|
878
|
-
// every package to `${nmDir}/${name}` (flat hoisting). Accepting
|
|
879
|
-
// the plan as a parameter keeps the caller agnostic of the hoist
|
|
880
|
-
// strategy and lets a future nested-install variant slot in
|
|
881
|
-
// without changing the call site.
|
|
882
|
-
void hoistPlan;
|
|
883
938
|
if (specs.length === 0) {
|
|
884
939
|
return { installed, failed, filesWritten };
|
|
885
940
|
}
|
|
@@ -899,13 +954,22 @@ export class NpmInstaller {
|
|
|
899
954
|
// the two made the phase width control install parallelism, so widening it
|
|
900
955
|
// for latency widened the cold-start burst along with it.
|
|
901
956
|
const INSTALL_PEER_CAP = 8;
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
957
|
+
// A tarball's placements share a shard, which acquires it once.
|
|
958
|
+
const byTarball = new Map();
|
|
959
|
+
for (const spec of specs) {
|
|
960
|
+
const group = byTarball.get(spec.tarballUrl);
|
|
961
|
+
if (group)
|
|
962
|
+
group.push(spec);
|
|
963
|
+
else
|
|
964
|
+
byTarball.set(spec.tarballUrl, [spec]);
|
|
965
|
+
}
|
|
966
|
+
const shardCount = Math.min(byTarball.size, INSTALL_PEER_CAP);
|
|
967
|
+
// Round-robin assignment: tarball at idx → shard idx % shardCount.
|
|
968
|
+
// This produces ⌈tarballs / shardCount⌉ tarballs per shard at
|
|
905
969
|
// most, with the imbalance bounded to ±1.
|
|
906
970
|
const shards = Array.from({ length: shardCount }, () => []);
|
|
907
|
-
|
|
908
|
-
shards[idx % shardCount].push(
|
|
971
|
+
[...byTarball.values()].forEach((group, idx) => {
|
|
972
|
+
shards[idx % shardCount].push(...group);
|
|
909
973
|
});
|
|
910
974
|
const nonEmptyShards = shards.filter((s) => s.length > 0);
|
|
911
975
|
const topology = nonEmptyShards.length < IN_DO_THRESHOLD ? 'in-do (in-DO fanout)' : 'peer-do (peer-DO fanout)';
|
|
@@ -967,11 +1031,13 @@ export class NpmInstaller {
|
|
|
967
1031
|
let okCount = 0;
|
|
968
1032
|
let failCount = 0;
|
|
969
1033
|
const reported = new Set();
|
|
970
|
-
const
|
|
1034
|
+
const specByDir = new Map(specs.map((s) => [s.pkgDir, s]));
|
|
971
1035
|
for (const r of result.perPackage) {
|
|
972
|
-
|
|
1036
|
+
// A pre-placement shard reports no pkgDir; it only wrote root.
|
|
1037
|
+
const dir = r.pkgDir ?? `${nmDir}/${r.name}`;
|
|
1038
|
+
reported.add(dir);
|
|
973
1039
|
// One `npm http` line per tarball, reporting the tier that served it.
|
|
974
|
-
const spec =
|
|
1040
|
+
const spec = specByDir.get(dir);
|
|
975
1041
|
if (spec && r.tarballSource) {
|
|
976
1042
|
this.npmLog('http', r.tarballSource === 'registry'
|
|
977
1043
|
? npmHttpFetchLine(spec.tarballUrl, r.tarballElapsedMs ?? 0)
|
|
@@ -996,12 +1062,11 @@ export class NpmInstaller {
|
|
|
996
1062
|
// returns short would otherwise leave its packages in neither list,
|
|
997
1063
|
// which is the same silent partial one layer down.
|
|
998
1064
|
for (const s of specs) {
|
|
999
|
-
|
|
1000
|
-
if (reported.has(id))
|
|
1065
|
+
if (reported.has(s.pkgDir))
|
|
1001
1066
|
continue;
|
|
1002
|
-
failed.push(
|
|
1067
|
+
failed.push(`${s.name}@${s.version}`);
|
|
1003
1068
|
failCount++;
|
|
1004
|
-
log(` [warn] ${
|
|
1069
|
+
log(` [warn] ${s.name}@${s.version}: install shard returned no result for this package (${s.pkgDir})`);
|
|
1005
1070
|
}
|
|
1006
1071
|
// Fold facet counters into the supervisor's diagnostic state.
|
|
1007
1072
|
recordInstallFacetCounters(result.facetCounters);
|
|
@@ -1166,7 +1231,8 @@ export class NpmInstaller {
|
|
|
1166
1231
|
// info comes from the registry cache — if the cache miss happens
|
|
1167
1232
|
// too, we play it safe and invalidate (a fresh resolve repopulates
|
|
1168
1233
|
// it and is always correct).
|
|
1169
|
-
|
|
1234
|
+
// An edge is met by any placement Node's walk from the entry finds.
|
|
1235
|
+
for (const [placement, entry] of lockfile) {
|
|
1170
1236
|
const cached = this.cache.getRegistryEntry(entry.name, entry.resolvedVer);
|
|
1171
1237
|
if (!cached)
|
|
1172
1238
|
return false;
|
|
@@ -1175,67 +1241,61 @@ export class NpmInstaller {
|
|
|
1175
1241
|
for (const depName of Object.keys(deps)) {
|
|
1176
1242
|
if (Object.hasOwn(optional, depName))
|
|
1177
1243
|
continue;
|
|
1178
|
-
if (!lockfile.has(
|
|
1244
|
+
if (!visiblePlacements(placement, depName).some((p) => lockfile.has(p)))
|
|
1179
1245
|
return false;
|
|
1180
1246
|
}
|
|
1181
1247
|
const peers = safeJsonParse(cached.peerDepsJson || '{}', {});
|
|
1182
1248
|
for (const peerName of Object.keys(peers)) {
|
|
1183
|
-
if (!lockfile.has(
|
|
1249
|
+
if (!visiblePlacements(placement, peerName).some((p) => lockfile.has(p)))
|
|
1184
1250
|
return false;
|
|
1185
1251
|
}
|
|
1186
1252
|
}
|
|
1187
1253
|
return true;
|
|
1188
1254
|
}
|
|
1189
|
-
/**
|
|
1190
|
-
* Convert a lockfile back to resolved packages (for cache restore).
|
|
1191
|
-
*/
|
|
1255
|
+
/** Convert a lockfile back to resolved packages: root by name, nested by placement path. */
|
|
1192
1256
|
lockfileToResolved(lockfile) {
|
|
1193
1257
|
const resolved = new Map();
|
|
1194
|
-
|
|
1195
|
-
|
|
1258
|
+
const nested = new Map();
|
|
1259
|
+
for (const [placement, entry] of lockfile) {
|
|
1260
|
+
const name = entry.name;
|
|
1261
|
+
// Reconstruct from the registry cache; on a miss, a minimal entry.
|
|
1196
1262
|
const cached = this.cache.getRegistryEntry(name, entry.resolvedVer);
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
exports: null,
|
|
1219
|
-
main: '',
|
|
1220
|
-
module: '',
|
|
1221
|
-
bin: {},
|
|
1222
|
-
});
|
|
1223
|
-
}
|
|
1263
|
+
(placement === name ? resolved : nested).set(placement, cached ? {
|
|
1264
|
+
name: cached.name,
|
|
1265
|
+
version: cached.version,
|
|
1266
|
+
tarballUrl: cached.tarballUrl,
|
|
1267
|
+
integrity: cached.integrity,
|
|
1268
|
+
dependencies: safeJsonParse(cached.depsJson, {}),
|
|
1269
|
+
exports: safeJsonParse(cached.exportsJson, null),
|
|
1270
|
+
main: cached.main,
|
|
1271
|
+
module: cached.moduleField,
|
|
1272
|
+
bin: safeJsonParse(cached.binJson, {}),
|
|
1273
|
+
} : {
|
|
1274
|
+
name,
|
|
1275
|
+
version: entry.resolvedVer,
|
|
1276
|
+
tarballUrl: '',
|
|
1277
|
+
integrity: entry.integrity,
|
|
1278
|
+
dependencies: safeJsonParse(entry.depsJson, {}),
|
|
1279
|
+
exports: null,
|
|
1280
|
+
main: '',
|
|
1281
|
+
module: '',
|
|
1282
|
+
bin: {},
|
|
1283
|
+
});
|
|
1224
1284
|
}
|
|
1225
|
-
return resolved;
|
|
1285
|
+
return { resolved, nested };
|
|
1226
1286
|
}
|
|
1227
1287
|
/**
|
|
1228
1288
|
* Write lockfile to SQLite.
|
|
1229
1289
|
*/
|
|
1230
|
-
writeLockfile(projDir,
|
|
1290
|
+
writeLockfile(projDir, hoistPlan, nmDir) {
|
|
1231
1291
|
const entries = new Map();
|
|
1232
|
-
for (const
|
|
1233
|
-
entries.set(
|
|
1234
|
-
name,
|
|
1292
|
+
for (const { placement, pkg } of hoistPlacements(hoistPlan)) {
|
|
1293
|
+
entries.set(placement, {
|
|
1294
|
+
name: pkg.name,
|
|
1235
1295
|
resolvedVer: pkg.version,
|
|
1236
1296
|
integrity: pkg.integrity,
|
|
1237
1297
|
depsJson: JSON.stringify(pkg.dependencies),
|
|
1238
|
-
hoistedPath: nmDir + '/' +
|
|
1298
|
+
hoistedPath: nmDir + '/' + placement,
|
|
1239
1299
|
});
|
|
1240
1300
|
}
|
|
1241
1301
|
this.cache.writeLockfile(projDir, entries, this.ctx);
|
|
@@ -73,5 +73,7 @@ export interface NpxResolveResult {
|
|
|
73
73
|
* Callers can use describeNpxSelfInvocation()/formatNpxHelp() before calling
|
|
74
74
|
* this resolver.
|
|
75
75
|
*/
|
|
76
|
-
export declare function resolveNpxBinary(installer: NpmInstaller, vfs: CredentialedVfs, cwd: string, rawArgs: string[], log: (msg: string) => void, pid?: number
|
|
76
|
+
export declare function resolveNpxBinary(installer: NpmInstaller, vfs: CredentialedVfs, cwd: string, rawArgs: string[], log: (msg: string) => void, pid?: number,
|
|
77
|
+
/** The command's `NPM_REGISTRY`; the npx cache install reads from it too. */
|
|
78
|
+
registry?: string): Promise<NpxResolveResult>;
|
|
77
79
|
//# sourceMappingURL=npx-install.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"npx-install.d.ts","sourceRoot":"","sources":["../../src/npm/npx-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAE5G;gFACgF;AAChF,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAoC/C,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC;AA+BtE,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAE9E;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAElE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAG7D;AAED,wBAAgB,aAAa,IAAI,MAAM,CAWtC;AA6KD;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;0CACsC;IACtC,MAAM,CAAC,EAAE,YAAY,GAAG,WAAW,GAAG,eAAe,CAAC;CACvD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,YAAY,EACvB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EAAE,EACjB,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAC1B,GAAG,CAAC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"npx-install.d.ts","sourceRoot":"","sources":["../../src/npm/npx-install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAE5G;gFACgF;AAChF,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAoC/C,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC;AA+BtE,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAE9E;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAElE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAG7D;AAED,wBAAgB,aAAa,IAAI,MAAM,CAWtC;AA6KD;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;0CACsC;IACtC,MAAM,CAAC,EAAE,YAAY,GAAG,WAAW,GAAG,eAAe,CAAC;CACvD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,YAAY,EACvB,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EAAE,EACjB,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAC1B,GAAG,CAAC,EAAE,MAAM;AACZ,6EAA6E;AAC7E,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,gBAAgB,CAAC,CAoE3B"}
|