gutterpress 0.11.10-alpha.2 → 0.11.10-alpha.6

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 (59) hide show
  1. package/README.md +24 -46
  2. package/dist/api/index.d.ts +1 -1
  3. package/dist/api/index.js +10 -6
  4. package/dist/{build-dfpvvhys.js → build-npxq1tvm.js} +7 -6
  5. package/dist/cdp-jg95s674.js +15 -0
  6. package/dist/cdp-smdx6mr3.js +16 -0
  7. package/dist/{cli-d8rdk1y7.js → cli-30j93gzt.js} +11 -335
  8. package/dist/{cli-pfczdbyd.js → cli-5qr3z0qa.js} +10 -404
  9. package/dist/{cli-c41yr7he.js → cli-7fkhgtfn.js} +3 -1
  10. package/dist/{cli-k2hwrp7s.js → cli-97bdz5k0.js} +1 -4
  11. package/dist/cli-kkzka31p.js +261 -0
  12. package/dist/{cli-p679pvce.js → cli-vbzkkcbv.js} +2 -2
  13. package/dist/{cli-4xksazfr.js → cli-z8ye91f0.js} +283 -1142
  14. package/dist/cli.js +12 -14
  15. package/dist/{doctor-hheax5yc.js → doctor-ykr6gtpv.js} +3 -3
  16. package/dist/engine/shared/cdp.d.ts +23 -19
  17. package/dist/engine-3gwctsty.js +24 -0
  18. package/dist/engine-mwshptgf.js +25 -0
  19. package/dist/{ext-q5024j6v.js → ext-bna9nr3v.js} +7 -6
  20. package/dist/{index-1a4rx87v.js → index-322fxk25.js} +344 -1130
  21. package/dist/{index-kqftehgy.js → index-dzp0hc2c.js} +4 -2
  22. package/dist/{index-fnhak0nh.js → index-qf7y4d85.js} +10 -404
  23. package/dist/index-r4wvy5v3.js +267 -0
  24. package/dist/{index-t43k5rq1.js → index-rzm1phg0.js} +23 -356
  25. package/dist/index.d.ts +0 -1
  26. package/dist/index.js +12 -87
  27. package/dist/lib/build-error.d.ts +4 -5
  28. package/dist/lib/build-preflight.d.ts +1 -35
  29. package/dist/lib/build-runner.d.ts +27 -44
  30. package/dist/lib/chromium.d.ts +5 -1
  31. package/dist/lib/engine.d.ts +3 -18
  32. package/dist/lib/extension-manager.d.ts +2 -2
  33. package/dist/lib/extension-manifest.d.ts +1 -1
  34. package/dist/lib/markdown/assemble.d.ts +2 -9
  35. package/dist/lib/markdown/index.d.ts +2 -4
  36. package/dist/lib/markdown/plugins.d.ts +0 -3
  37. package/dist/lib/npm-plugin-installer.d.ts +6 -1
  38. package/dist/lib/plugin-vendor.d.ts +10 -78
  39. package/dist/lib/source-provider.d.ts +1 -1
  40. package/dist/lib/validation-exec.d.ts +5 -6
  41. package/dist/{new-6xm4tdxb.js → new-0hv3nwqj.js} +9 -8
  42. package/dist/{preflight-ezt8rvg3.js → preflight-pk0k25fm.js} +7 -6
  43. package/dist/preview/file-watcher.d.ts +4 -43
  44. package/dist/preview/http-server.d.ts +1 -3
  45. package/dist/{preview-hehs46dd.js → preview-8b1fn59h.js} +7 -6
  46. package/dist/{preview-shell-gqnc5xxe.js → preview-shell-tqndvhbx.js} +5 -7
  47. package/dist/{publish-ha505ejq.js → publish-ba5h76tz.js} +7 -6
  48. package/dist/render.d.ts +1 -1
  49. package/dist/render.js +1 -9
  50. package/dist/{source-provider-ta09wegv.js → source-provider-pzmz0br9.js} +1 -1
  51. package/dist/{source-provider-7c2ww3bz.js → source-provider-qbthnmqw.js} +1 -1
  52. package/dist/{validate-je56vdbj.js → validate-4rq2r5b3.js} +7 -6
  53. package/package.json +1 -4
  54. package/dist/audit-v9594a72.js +0 -69
  55. package/dist/engine-qtfrfbpk.js +0 -41
  56. package/dist/engine-trte2tg2.js +0 -40
  57. package/dist/lib/browser-pool.d.ts +0 -35
  58. package/dist/lib/lint-runner.d.ts +0 -29
  59. package/dist/lint-tbywt66a.js +0 -68
@@ -1,10 +1,12 @@
1
1
  import {
2
2
  getAssetPath,
3
3
  isIgnoredMarginBoxProperty,
4
- launchChromium,
5
4
  marginBoxAlign,
6
5
  marginBoxRectPt
7
- } from "./index-t43k5rq1.js";
6
+ } from "./index-r4wvy5v3.js";
7
+ import {
8
+ launchChromium
9
+ } from "./index-rzm1phg0.js";
8
10
 
9
11
  // src/engine/compiler/build.ts
10
12
  import { readFile } from "node:fs/promises";
@@ -199,42 +199,14 @@ function formatData(data, clean) {
199
199
  }
200
200
 
201
201
  // src/lib/plugin-vendor.ts
202
- import { createHash } from "node:crypto";
203
- import { createReadStream } from "node:fs";
204
- import { lstat, readFile, readdir, realpath } from "node:fs/promises";
202
+ import { lstat, readFile, realpath } from "node:fs/promises";
205
203
  import path2 from "node:path";
206
204
  import { exports as resolveExports } from "resolve.exports";
207
- import { satisfies, validRange } from "semver";
208
-
209
- // src/lib/npm-registry.ts
210
- var DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org";
211
- var ENV_OVERRIDE = "GUTTERPRESS_NPM_REGISTRY";
212
- function npmRegistryUrl() {
213
- const configured = process.env[ENV_OVERRIDE]?.trim();
214
- if (!configured)
215
- return DEFAULT_NPM_REGISTRY;
216
- let scheme;
217
- try {
218
- scheme = new URL(configured).protocol;
219
- } catch {
220
- throw new Error(`Invalid ${ENV_OVERRIDE} URL "${configured}".`);
221
- }
222
- if (scheme !== "http:" && scheme !== "https:") {
223
- throw new Error(`${ENV_OVERRIDE} must be an http(s) URL — got "${scheme}".`);
224
- }
225
- return configured.replace(/\/+$/, "");
226
- }
227
-
228
- // src/lib/plugin-vendor.ts
229
205
  var PLUGINS_DIR = "plugins";
230
206
  var VENDORED_NPM_DIR = "npm";
231
- var VENDOR_RECEIPT_FILE = ".gutterpress-install.json";
232
- var VENDOR_RECEIPT_VERSION = 2;
233
207
  var NPM_SEGMENT = /^[a-z0-9][a-z0-9._~-]*$/;
234
208
  var EXACT_VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
235
209
  var WINDOWS_RESERVED = /^(con|prn|aux|nul|clock\$|conin\$|conout\$|com[1-9¹²³]|lpt[1-9¹²³])(?:\..*)?$/i;
236
- var MAX_VERIFIED_FILES = 50000;
237
- var MAX_VERIFIED_BYTES = 512 * 1024 * 1024;
238
210
  function isValidNpmPackageName(name) {
239
211
  if (!name || name.length > 214 || name !== name.toLowerCase())
240
212
  return false;
@@ -287,10 +259,6 @@ function vendoredNpmPluginPackageDir(installRoot, name) {
287
259
  function toPosixPath(value) {
288
260
  return value.split(path2.sep).join("/");
289
261
  }
290
- function packageEntryFormat(manifest, relativeEntry) {
291
- const extension = path2.posix.extname(relativeEntry);
292
- return extension === ".cjs" || extension === ".json" || extension !== ".mjs" && manifest.type !== "module" ? "commonjs" : "module";
293
- }
294
262
  function assertWindowsSafeRelativePath(relative) {
295
263
  if (!relative || relative.includes("\\") || relative.startsWith("/") || /^[a-zA-Z]:/.test(relative)) {
296
264
  throw new Error(`Unsafe package path: ${relative || "(empty)"}`);
@@ -309,12 +277,6 @@ function assertWindowsSafeRelativePath(relative) {
309
277
  function windowsPathKey(relative) {
310
278
  return relative.normalize("NFKC").toLowerCase();
311
279
  }
312
- function safeReceiptPath(relative, label) {
313
- if (typeof relative !== "string")
314
- throw new Error(`${label} must be a string.`);
315
- assertWindowsSafeRelativePath(relative);
316
- return relative;
317
- }
318
280
  function isContained(root, candidate) {
319
281
  const relative = path2.relative(root, candidate);
320
282
  return relative === "" || !relative.startsWith("..") && !path2.isAbsolute(relative);
@@ -322,38 +284,6 @@ function isContained(root, candidate) {
322
284
  function object(value) {
323
285
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
324
286
  }
325
- function stringMap(value) {
326
- const map = object(value);
327
- if (!map)
328
- return {};
329
- const result = {};
330
- for (const [name, selector] of Object.entries(map)) {
331
- if (typeof selector === "string" && selector.trim())
332
- result[name] = selector.trim();
333
- }
334
- return result;
335
- }
336
- function dependencyDeclarations(manifest) {
337
- const required = stringMap(manifest.dependencies);
338
- const optional = stringMap(manifest.optionalDependencies);
339
- for (const name of Object.keys(optional))
340
- delete required[name];
341
- const peers = stringMap(manifest.peerDependencies);
342
- const peerMeta = object(manifest.peerDependenciesMeta) ?? {};
343
- const optionalPeers = {};
344
- for (const [name, selector] of Object.entries(peers)) {
345
- if (name in required || name in optional)
346
- continue;
347
- if (object(peerMeta[name])?.optional === true)
348
- optionalPeers[name] = selector;
349
- else
350
- required[name] = selector;
351
- }
352
- return { required, optional, optionalPeers };
353
- }
354
- function unsupportedRegistrySelector(selector) {
355
- return /^(?:file:|git\+|https?:|ssh:|github:|workspace:|link:|npm:)/i.test(selector);
356
- }
357
287
  async function readPackageJson(packageDir) {
358
288
  const packageJsonPath = path2.join(packageDir, "package.json");
359
289
  const info = await lstat(packageJsonPath);
@@ -365,26 +295,6 @@ async function readPackageJson(packageDir) {
365
295
  throw new Error(`Package metadata is not an object: ${packageJsonPath}`);
366
296
  return parsed;
367
297
  }
368
- async function verifyReceiptEntry(installRoot, packagePath, entry, label) {
369
- if (entry === undefined)
370
- return;
371
- const relative = safeReceiptPath(entry, label);
372
- if (!relative.startsWith(`${packagePath}/`)) {
373
- throw new Error(`${label} is outside its package.`);
374
- }
375
- const packageDir = path2.resolve(installRoot, ...packagePath.split("/"));
376
- const entryPath = path2.resolve(installRoot, ...relative.split("/"));
377
- const [realPackageDir, realEntry] = await Promise.all([
378
- realpath(packageDir),
379
- realpath(entryPath)
380
- ]);
381
- if (!isContained(realPackageDir, realEntry))
382
- throw new Error(`${label} escapes its package.`);
383
- const info = await lstat(realEntry);
384
- if (!info.isFile() || info.isSymbolicLink())
385
- throw new Error(`${label} is not a regular file.`);
386
- return realEntry;
387
- }
388
298
  function packageResolutionTargets(manifest, subpath, condition) {
389
299
  if (manifest.exports !== undefined) {
390
300
  try {
@@ -452,112 +362,16 @@ async function resolveEntryCandidate(packageDir, resolution) {
452
362
  }
453
363
  return null;
454
364
  }
455
- async function resolvePackageEntry(packageDir, packageJson, condition = "import") {
365
+ async function resolvePackageEntry(packageDir, packageJson) {
456
366
  const manifest = packageJson ?? await readPackageJson(packageDir);
457
- for (const target of packageResolutionTargets(manifest, "", condition)) {
458
- const resolved = await resolveEntryCandidate(packageDir, target);
459
- if (resolved)
460
- return resolved;
461
- }
462
- throw new Error("Package has no contained JavaScript entry point for ESM import.");
463
- }
464
- async function listTreeEntries(root) {
465
- const out = [];
466
- async function visit(dir) {
467
- const entries = await readdir(dir, { withFileTypes: true });
468
- entries.sort((a, b) => a.name.localeCompare(b.name));
469
- for (const entry of entries) {
470
- const absolute = path2.join(dir, entry.name);
471
- const relative = toPosixPath(path2.relative(root, absolute));
472
- if (relative === VENDOR_RECEIPT_FILE)
473
- continue;
474
- if (entry.isSymbolicLink())
475
- throw new Error(`Vendor tree contains a symbolic link: ${relative}`);
476
- if (entry.isDirectory()) {
477
- out.push({ relative, directory: true });
478
- await visit(absolute);
479
- } else if (entry.isFile())
480
- out.push({ relative, directory: false });
481
- else
482
- throw new Error(`Vendor tree contains an unsupported filesystem entry: ${relative}`);
367
+ for (const condition of ["import", "require"]) {
368
+ for (const target of packageResolutionTargets(manifest, "", condition)) {
369
+ const resolved = await resolveEntryCandidate(packageDir, target);
370
+ if (resolved)
371
+ return resolved;
483
372
  }
484
373
  }
485
- await visit(root);
486
- return out;
487
- }
488
- async function computeVendorTreeDigest(root) {
489
- const entries = await listTreeEntries(root);
490
- const files = entries.filter((entry) => !entry.directory);
491
- if (files.length > MAX_VERIFIED_FILES) {
492
- throw new Error(`Vendor tree contains more than ${MAX_VERIFIED_FILES} files.`);
493
- }
494
- const seen = new Set;
495
- const hash = createHash("sha256");
496
- let bytes = 0;
497
- for (const entry of entries) {
498
- const { relative } = entry;
499
- assertWindowsSafeRelativePath(relative);
500
- const key = windowsPathKey(relative);
501
- if (seen.has(key))
502
- throw new Error(`Vendor tree has a Windows-colliding path: ${relative}`);
503
- seen.add(key);
504
- if (entry.directory)
505
- continue;
506
- const absolute = path2.join(root, ...relative.split("/"));
507
- const info = await lstat(absolute);
508
- if (!info.isFile() || info.isSymbolicLink() || info.nlink !== 1) {
509
- throw new Error(`Vendor tree file is not an independent regular file: ${relative}`);
510
- }
511
- bytes += info.size;
512
- if (bytes > MAX_VERIFIED_BYTES) {
513
- throw new Error(`Vendor tree exceeds ${Math.round(MAX_VERIFIED_BYTES / 1024 / 1024)}MB.`);
514
- }
515
- hash.update(`${Buffer.byteLength(relative)}:${relative}:${info.size}\x00`);
516
- for await (const chunk of createReadStream(absolute))
517
- hash.update(chunk);
518
- }
519
- return { digest: hash.digest("hex"), files: files.length, bytes };
520
- }
521
- async function assertVendorPackageOwnership(root, packagePaths) {
522
- const packages = packagePaths.map((relative) => ({
523
- relative,
524
- key: windowsPathKey(relative),
525
- parts: relative.split("/").length
526
- })).sort((a, b) => b.key.length - a.key.length);
527
- for (const entry of await listTreeEntries(root)) {
528
- const actualParts = entry.relative.split("/");
529
- for (const part of actualParts) {
530
- if (part.normalize("NFKC").toLowerCase() === "node_modules" && part !== "node_modules") {
531
- throw new Error(`Vendor tree contains a non-canonical node_modules path: ${entry.relative}`);
532
- }
533
- }
534
- const key = windowsPathKey(entry.relative);
535
- const structural = packages.some((pkg) => pkg.key === key || pkg.key.startsWith(`${key}/`));
536
- if (entry.directory && structural)
537
- continue;
538
- const owner = packages.find((pkg) => key.startsWith(`${pkg.key}/`));
539
- if (!owner)
540
- throw new Error(`Vendor tree path is not owned by a receipt package: ${entry.relative}`);
541
- const packageRelative = actualParts.slice(owner.parts);
542
- const nodeModulesAt = packageRelative.findIndex((part) => part.normalize("NFKC").toLowerCase() === "node_modules");
543
- if (nodeModulesAt < 0)
544
- continue;
545
- const generatedEmptyDirectory = entry.directory && nodeModulesAt === 0 && (packageRelative.length === 1 || packageRelative.length === 2 && packageRelative[1].startsWith("@"));
546
- if (!generatedEmptyDirectory) {
547
- throw new Error(`Package contains bundled node_modules content: ${entry.relative}`);
548
- }
549
- }
550
- }
551
- async function recomputeReceiptEntry(packageDir, packagePath, manifest, condition) {
552
- try {
553
- const entry = await resolvePackageEntry(packageDir, manifest, condition);
554
- return `${packagePath}/${entry}`;
555
- } catch (error) {
556
- if (error instanceof Error && error.message.includes("no contained JavaScript entry point")) {
557
- return;
558
- }
559
- throw error;
560
- }
374
+ throw new Error("Package has no contained JavaScript entry point.");
561
375
  }
562
376
  async function resolveVendoredPluginInstallRoot(projectDir, expectedName, expectedVersion) {
563
377
  const requestedProjectRoot = path2.resolve(projectDir);
@@ -582,214 +396,6 @@ async function resolveVendoredPluginInstallRoot(projectDir, expectedName, expect
582
396
  }
583
397
  return installRoot;
584
398
  }
585
- function reconcileReceiptGraph(receipt, packages, manifests) {
586
- if (!Array.isArray(receipt.skipped))
587
- throw new Error("Vendor receipt skipped list is invalid.");
588
- const declarations = new Map;
589
- for (const [packagePath, manifest] of manifests) {
590
- declarations.set(packagePath, dependencyDeclarations(manifest));
591
- }
592
- const skippedByEdge = new Map;
593
- for (const skipped of receipt.skipped) {
594
- if (!packages.has(skipped.from) || !isValidNpmPackageName(skipped.name) || typeof skipped.selector !== "string" || !["optional", "optional-peer"].includes(skipped.kind) || typeof skipped.reason !== "string") {
595
- throw new Error("Vendor receipt contains an invalid skipped dependency.");
596
- }
597
- const declared = declarations.get(skipped.from);
598
- const expectedSelector = skipped.kind === "optional" ? declared.optional[skipped.name] : declared.optionalPeers[skipped.name];
599
- if (expectedSelector !== skipped.selector) {
600
- throw new Error(`Skipped dependency is not declared as ${skipped.kind}: ${skipped.name}`);
601
- }
602
- const key = `${skipped.from}\x00${skipped.name}`;
603
- if (skippedByEdge.has(key))
604
- throw new Error(`Duplicate skipped dependency: ${skipped.name}`);
605
- skippedByEdge.set(key, skipped);
606
- }
607
- for (const pkg of receipt.packages) {
608
- if (!object(pkg.dependencies))
609
- throw new Error(`Invalid dependency map for ${pkg.name}.`);
610
- const declared = declarations.get(pkg.path);
611
- for (const [dependency, target] of Object.entries(pkg.dependencies)) {
612
- const targetPackage = packages.get(target);
613
- if (!isValidNpmPackageName(dependency) || !targetPackage || targetPackage.name !== dependency) {
614
- throw new Error(`Broken dependency edge ${pkg.name} -> ${dependency}.`);
615
- }
616
- const selector = declared.required[dependency] ?? declared.optional[dependency];
617
- if (!selector)
618
- throw new Error(`Undeclared dependency edge ${pkg.name} -> ${dependency}.`);
619
- if (unsupportedRegistrySelector(selector)) {
620
- throw new Error(`Unsupported selector on dependency edge ${pkg.name} -> ${dependency}.`);
621
- }
622
- const range = validRange(selector);
623
- if (range && !satisfies(targetPackage.version, range)) {
624
- throw new Error(`Dependency edge ${pkg.name} -> ${dependency}@${targetPackage.version} does not satisfy ${selector}.`);
625
- }
626
- if (skippedByEdge.has(`${pkg.path}\x00${dependency}`)) {
627
- throw new Error(`Dependency is both installed and skipped: ${pkg.name} -> ${dependency}.`);
628
- }
629
- }
630
- for (const dependency of Object.keys(declared.required)) {
631
- if (!(dependency in pkg.dependencies)) {
632
- throw new Error(`Missing required dependency edge ${pkg.name} -> ${dependency}.`);
633
- }
634
- }
635
- for (const dependency of Object.keys(declared.optional)) {
636
- if (!(dependency in pkg.dependencies) && !skippedByEdge.has(`${pkg.path}\x00${dependency}`)) {
637
- throw new Error(`Optional dependency is neither installed nor skipped: ${pkg.name} -> ${dependency}.`);
638
- }
639
- }
640
- for (const dependency of Object.keys(declared.optionalPeers)) {
641
- if (!skippedByEdge.has(`${pkg.path}\x00${dependency}`)) {
642
- throw new Error(`Optional peer dependency is not recorded as skipped: ${pkg.name} -> ${dependency}.`);
643
- }
644
- }
645
- }
646
- }
647
- async function verifyVendoredPlugin(projectDir, expectedName, expectedVersion) {
648
- try {
649
- const installRoot = await resolveVendoredPluginInstallRoot(projectDir, expectedName, expectedVersion);
650
- if (!installRoot)
651
- return null;
652
- const receiptPath = path2.join(installRoot, VENDOR_RECEIPT_FILE);
653
- let raw;
654
- try {
655
- const info = await lstat(receiptPath);
656
- if (!info.isFile() || info.isSymbolicLink() || info.nlink !== 1 || info.size > 1024 * 1024) {
657
- throw new Error("Vendor receipt is not a small regular file.");
658
- }
659
- raw = await readFile(receiptPath, "utf8");
660
- } catch (error) {
661
- if (error.code === "ENOENT")
662
- return null;
663
- throw error;
664
- }
665
- const receipt = JSON.parse(raw);
666
- if (receipt.schemaVersion !== VENDOR_RECEIPT_VERSION) {
667
- throw new Error(`Unsupported vendor receipt schema ${String(receipt.schemaVersion)}.`);
668
- }
669
- if (receipt.root?.name !== expectedName || receipt.root?.version !== expectedVersion) {
670
- throw new Error("Vendor receipt identity does not match the manifest entry.");
671
- }
672
- if (!Array.isArray(receipt.packages) || receipt.packages.length === 0) {
673
- throw new Error("Vendor receipt has no package graph.");
674
- }
675
- const tree = await computeVendorTreeDigest(installRoot);
676
- if (receipt.tree?.algorithm !== "sha256" || receipt.tree.digest !== tree.digest || receipt.tree.files !== tree.files || receipt.tree.bytes !== tree.bytes) {
677
- throw new Error("Vendor tree hash does not match its receipt.");
678
- }
679
- const packages = new Map;
680
- const manifests = new Map;
681
- const verifiedPackages = [];
682
- const pathKeys = new Set;
683
- for (const pkg of receipt.packages) {
684
- const relative = safeReceiptPath(pkg.path, "Package receipt path");
685
- const key = windowsPathKey(relative);
686
- if (pathKeys.has(key))
687
- throw new Error(`Duplicate package receipt path: ${relative}`);
688
- pathKeys.add(key);
689
- if (!isValidNpmPackageName(pkg.name) || !isExactNpmVersion(pkg.version)) {
690
- throw new Error(`Invalid package identity in receipt: ${pkg.name}@${pkg.version}`);
691
- }
692
- const expectedSuffix = `node_modules/${pkg.name}`;
693
- if (relative !== expectedSuffix && !relative.endsWith(`/${expectedSuffix}`)) {
694
- throw new Error(`Package receipt path does not match ${pkg.name}: ${relative}`);
695
- }
696
- if (typeof pkg.integrity !== "string" || !/^(?:sha512|sha384|sha256|sha1)-(?:hex-)?[A-Za-z0-9+/=]+$/.test(pkg.integrity) || typeof pkg.legacySha1 !== "boolean" || pkg.legacySha1 !== pkg.integrity.startsWith("sha1-")) {
697
- throw new Error(`Package receipt is missing provenance: ${pkg.name}@${pkg.version}`);
698
- }
699
- const tarball = new URL(pkg.tarball);
700
- if (tarball.origin !== new URL(npmRegistryUrl()).origin || tarball.username || tarball.password) {
701
- throw new Error(`Package receipt has an invalid tarball URL: ${pkg.name}@${pkg.version}`);
702
- }
703
- const packageDir = path2.resolve(installRoot, ...relative.split("/"));
704
- if (!isContained(installRoot, packageDir))
705
- throw new Error(`Package escapes vendor root: ${relative}`);
706
- const realPackageDir2 = await realpath(packageDir);
707
- if (!isContained(installRoot, realPackageDir2)) {
708
- throw new Error(`Package resolves outside the vendor root: ${relative}`);
709
- }
710
- const manifest = await readPackageJson(packageDir);
711
- if (manifest.name !== pkg.name || manifest.version !== pkg.version) {
712
- throw new Error(`Installed package identity changed: ${pkg.name}@${pkg.version}`);
713
- }
714
- const [expectedEntry, expectedRequireEntry] = await Promise.all([
715
- recomputeReceiptEntry(packageDir, relative, manifest, "import"),
716
- recomputeReceiptEntry(packageDir, relative, manifest, "require")
717
- ]);
718
- if (pkg.entry !== expectedEntry || pkg.requireEntry !== expectedRequireEntry) {
719
- throw new Error(`Recorded package entries do not match package.json: ${pkg.name}@${pkg.version}`);
720
- }
721
- packages.set(relative, pkg);
722
- manifests.set(relative, manifest);
723
- verifiedPackages.push({
724
- path: relative,
725
- name: pkg.name,
726
- packageDir: realPackageDir2,
727
- manifest,
728
- entryPath: await verifyReceiptEntry(installRoot, relative, pkg.entry, "Package import entry"),
729
- requireEntryPath: await verifyReceiptEntry(installRoot, relative, pkg.requireEntry, "Package require entry"),
730
- dependencies: pkg.dependencies
731
- });
732
- }
733
- await assertVendorPackageOwnership(installRoot, receipt.packages.map((pkg) => pkg.path));
734
- reconcileReceiptGraph(receipt, packages, manifests);
735
- const rootPackagePath = safeReceiptPath(receipt.root.packagePath, "Root package path");
736
- const rootPackage = packages.get(rootPackagePath);
737
- if (!rootPackage || rootPackage.name !== expectedName || rootPackage.version !== expectedVersion) {
738
- throw new Error("Vendor receipt root package is missing.");
739
- }
740
- const reachablePackages = new Set([rootPackagePath]);
741
- const pendingPackages = [rootPackagePath];
742
- while (pendingPackages.length > 0) {
743
- const current = packages.get(pendingPackages.pop());
744
- for (const target of Object.values(current.dependencies)) {
745
- if (reachablePackages.has(target))
746
- continue;
747
- reachablePackages.add(target);
748
- pendingPackages.push(target);
749
- }
750
- }
751
- if (reachablePackages.size !== receipt.packages.length) {
752
- throw new Error("Vendor receipt contains a package that is not reachable from its root.");
753
- }
754
- const rootManifest = manifests.get(rootPackagePath);
755
- if (receipt.root.format !== "module" && receipt.root.format !== "commonjs") {
756
- throw new Error("Vendor receipt root format is invalid.");
757
- }
758
- const entryRelative = safeReceiptPath(receipt.root.entry, "Plugin entry path");
759
- if (!entryRelative.startsWith(`${rootPackagePath}/`)) {
760
- throw new Error("Plugin entry is outside its package.");
761
- }
762
- const expectedRootEntry = receipt.root.format === "commonjs" ? rootPackage.requireEntry ?? rootPackage.entry : rootPackage.entry;
763
- if (entryRelative !== expectedRootEntry) {
764
- throw new Error("Plugin entry does not match the package graph entry.");
765
- }
766
- if (packageEntryFormat(rootManifest, entryRelative) !== receipt.root.format) {
767
- throw new Error("Plugin entry format does not match its package metadata.");
768
- }
769
- const entryPath = path2.resolve(installRoot, ...entryRelative.split("/"));
770
- const rootPackageDir = path2.resolve(installRoot, ...rootPackagePath.split("/"));
771
- const [realPackageDir, realEntry] = await Promise.all([
772
- realpath(rootPackageDir),
773
- realpath(entryPath)
774
- ]);
775
- if (!isContained(installRoot, realEntry) || !isContained(realPackageDir, realEntry)) {
776
- throw new Error("Plugin entry resolves outside the verified vendor tree.");
777
- }
778
- const entryInfo = await lstat(realEntry);
779
- if (!entryInfo.isFile() || entryInfo.isSymbolicLink()) {
780
- throw new Error("Plugin entry is not a regular file.");
781
- }
782
- return {
783
- installRoot,
784
- entryPath: realEntry,
785
- format: receipt.root.format,
786
- packages: verifiedPackages,
787
- receipt
788
- };
789
- } catch (error) {
790
- throw new Error(`Vendored plugin "${expectedName}@${expectedVersion}" failed verification: ` + `${error instanceof Error ? error.message : String(error)} Reinstall it before building.`, { cause: error });
791
- }
792
- }
793
399
 
794
400
  // src/lib/source-provider.ts
795
401
  var noopLogger = {
@@ -1154,7 +760,7 @@ async function countUnversionedChanges(projectDir) {
1154
760
  const appWritten = `${bookPrefix}${PLUGINS_DIR}/${VENDORED_NPM_DIR}/`;
1155
761
  return withRepoLock(dir, async () => {
1156
762
  const { adds, removes } = await listWorkdirChanges(dir);
1157
- const mine = new Set([...adds, ...removes].filter((f) => f.startsWith(bookPrefix) && !f.startsWith(appWritten) && path3.posix.basename(f) !== VENDOR_RECEIPT_FILE));
763
+ const mine = new Set([...adds, ...removes].filter((f) => f.startsWith(bookPrefix) && !f.startsWith(appWritten)));
1158
764
  return { changedFiles: mine.size, stale: gitFs.existsSync(snapshotStagingMarkerPath(dir)) };
1159
765
  });
1160
766
  }
@@ -1330,4 +936,4 @@ async function switchBranch(options) {
1330
936
  });
1331
937
  }
1332
938
 
1333
- export { DEFAULT_NPM_REGISTRY, npmRegistryUrl, PLUGINS_DIR, VENDORED_NPM_DIR, VENDOR_RECEIPT_FILE, VENDOR_RECEIPT_VERSION, isValidNpmPackageName, parseNpmPluginSpec, isExactNpmVersion, vendoredNpmPluginRoot, vendoredNpmPluginPackageDir, toPosixPath, packageEntryFormat, assertWindowsSafeRelativePath, windowsPathKey, packageResolutionTargets, resolvePackageEntry, computeVendorTreeDigest, resolveVendoredPluginInstallRoot, verifyVendoredPlugin, gitFs, errorLogData, resolveLogger, gitScopeFor, HISTORY_PAGE_LIMIT, withRepoLock, whenGitIdle, __repoLockQueueSizeForTests, resolveGitAuthor, listWorkdirChanges, stageChanges, hasPendingChanges, hasUncommittedChanges, snapshotWorkingTreeUnlocked, isNoChangesError, countUnversionedChanges, providerFor, gitDirFor, snapshotStagingMarkerPath, RESTORE_BACKUP_MESSAGE, AUTO_SNAPSHOT_MESSAGE, restoreVersionWithBackup, SWITCH_BRANCH_SNAPSHOT_MESSAGE, listLocalBranches, switchBranch };
939
+ export { PLUGINS_DIR, VENDORED_NPM_DIR, isValidNpmPackageName, parseNpmPluginSpec, isExactNpmVersion, vendoredNpmPluginRoot, vendoredNpmPluginPackageDir, toPosixPath, assertWindowsSafeRelativePath, windowsPathKey, packageResolutionTargets, safePackageTarget, resolvePackageEntry, resolveVendoredPluginInstallRoot, gitFs, errorLogData, resolveLogger, gitScopeFor, HISTORY_PAGE_LIMIT, withRepoLock, whenGitIdle, __repoLockQueueSizeForTests, resolveGitAuthor, listWorkdirChanges, stageChanges, hasPendingChanges, hasUncommittedChanges, snapshotWorkingTreeUnlocked, isNoChangesError, countUnversionedChanges, providerFor, gitDirFor, snapshotStagingMarkerPath, RESTORE_BACKUP_MESSAGE, AUTO_SNAPSHOT_MESSAGE, restoreVersionWithBackup, SWITCH_BRANCH_SNAPSHOT_MESSAGE, listLocalBranches, switchBranch };