knarr 0.0.1 → 0.0.3

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 (84) hide show
  1. package/LICENSE +20 -20
  2. package/dist/{add-ODK52RZI.mjs → add-LZ6CZTHG.mjs} +1 -1
  3. package/dist/bell-YD6IWNXO.mjs +0 -0
  4. package/dist/check-YVEJEI2G.mjs +0 -0
  5. package/dist/chokidar-LVDD2IK4.mjs +0 -0
  6. package/dist/chunk-2GDRDQA5.mjs +0 -0
  7. package/dist/chunk-2VCW5RWI.mjs +0 -0
  8. package/dist/chunk-37AAX47E.mjs +19 -0
  9. package/dist/chunk-3KNUBUPH.mjs +0 -0
  10. package/dist/{chunk-7DZPDPP6.mjs → chunk-5BZD55UB.mjs} +1 -1
  11. package/dist/chunk-7HVPEBK5.mjs +0 -0
  12. package/dist/chunk-7JG555TZ.mjs +0 -0
  13. package/dist/chunk-7SDPRKFT.mjs +13 -0
  14. package/dist/chunk-B3DZ5HVQ.mjs +0 -0
  15. package/dist/chunk-BS4VKVYH.mjs +0 -0
  16. package/dist/chunk-CTJF2EWO.mjs +3 -0
  17. package/dist/{chunk-HQ7NKBQW.mjs → chunk-EE2UYGFD.mjs} +2 -2
  18. package/dist/chunk-GO6F6AGH.mjs +3 -0
  19. package/dist/chunk-GQYG5FCW.mjs +5 -0
  20. package/dist/chunk-HEDVIVEO.mjs +14 -0
  21. package/dist/chunk-KOHUNKHP.mjs +3 -0
  22. package/dist/{chunk-U5ZZAYNU.mjs → chunk-LXGALE74.mjs} +2 -2
  23. package/dist/chunk-MBKCCWSD.mjs +0 -0
  24. package/dist/chunk-NBSJGM2X.mjs +0 -0
  25. package/dist/chunk-OPLSUHCD.mjs +4 -0
  26. package/dist/chunk-QGLOGD5G.mjs +3 -0
  27. package/dist/chunk-SFLWVTJC.mjs +0 -0
  28. package/dist/{chunk-XQVMCMO7.mjs → chunk-SN4TOUQW.mjs} +3 -3
  29. package/dist/chunk-SYADAYF4.mjs +0 -0
  30. package/dist/chunk-TEFMLGCB.mjs +0 -0
  31. package/dist/{chunk-2EZDTBUU.mjs → chunk-UBGMLVMB.mjs} +2 -2
  32. package/dist/{chunk-FU7FCNTW.mjs → chunk-XKO24LUM.mjs} +2 -2
  33. package/dist/chunk-XQPVRRTN.mjs +0 -0
  34. package/dist/{chunk-FUINO5RD.mjs → chunk-ZJEEAMB3.mjs} +2 -2
  35. package/dist/clean-ZD5GPGXQ.mjs +3 -0
  36. package/dist/cli.mjs +1 -1
  37. package/dist/{dev-7L35BV6M.mjs → dev-TMWMIT7W.mjs} +2 -2
  38. package/dist/doctor-AXP7GVBM.mjs +4 -0
  39. package/dist/fs-2NITBGIO.mjs +2 -0
  40. package/dist/{history-XUZSDCNE.mjs → history-SKKGT225.mjs} +1 -1
  41. package/dist/index.d.ts +1 -1
  42. package/dist/index.mjs +239 -140
  43. package/dist/{init-OBJFQ6OB.mjs → init-XK4B7XYG.mjs} +4 -4
  44. package/dist/{list-AQKUBZ2I.mjs → list-GLSA6I67.mjs} +2 -2
  45. package/dist/migrate-MW4BVLL2.mjs +8 -0
  46. package/dist/preflight-TVJFHRI2.mjs +0 -0
  47. package/dist/publish-TAWTHPSD.mjs +3 -0
  48. package/dist/{push-NHCPN6MO.mjs → push-65ZZFZJY.mjs} +2 -2
  49. package/dist/remove-LOBXHBMC.mjs +2 -0
  50. package/dist/reset-EAN5NVGM.mjs +3 -0
  51. package/dist/{restore-YGPO42W4.mjs → restore-YHZYT54B.mjs} +3 -3
  52. package/dist/rollback-U3LQTWH5.mjs +3 -0
  53. package/dist/{status-3VUPPR5D.mjs → status-FA6UEHEF.mjs} +3 -3
  54. package/dist/tailwind-source-RIWWXW2Y.mjs +5 -0
  55. package/dist/topo-sort-WEIVPJKN.mjs +0 -0
  56. package/dist/{tracker-R4ZZIDJV.mjs → tracker-JJEYXX45.mjs} +1 -1
  57. package/dist/update-VOUKMOLK.mjs +3 -0
  58. package/dist/{use-NKLXGPIZ.mjs → use-BXAZ5OP3.mjs} +1 -1
  59. package/dist/{vite-config-URP2SYRQ.mjs → vite-config-UWCLPTOZ.mjs} +1 -1
  60. package/dist/watch-orchestrator-I2623SMT.mjs +3 -0
  61. package/dist/watcher-PTPUN2HE.mjs +0 -0
  62. package/dist/{workspace-L5CGPK7U.mjs → workspace-S3TAUSS3.mjs} +1 -1
  63. package/dist/xxhash-wasm-DTW44IIQ.mjs +0 -0
  64. package/package.json +7 -4
  65. package/dist/chunk-23HXXAGG.mjs +0 -5
  66. package/dist/chunk-2QPLXLJW.mjs +0 -3
  67. package/dist/chunk-IM555H3S.mjs +0 -4
  68. package/dist/chunk-KXLQGVT2.mjs +0 -13
  69. package/dist/chunk-OLUZ7T7G.mjs +0 -3
  70. package/dist/chunk-OXI2KGCW.mjs +0 -14
  71. package/dist/chunk-V2ED74ZQ.mjs +0 -3
  72. package/dist/chunk-YZCBBQCH.mjs +0 -19
  73. package/dist/chunk-Z22BYXWQ.mjs +0 -3
  74. package/dist/clean-XMLDIZDZ.mjs +0 -3
  75. package/dist/doctor-4TTAYNGW.mjs +0 -4
  76. package/dist/fs-35635IS7.mjs +0 -2
  77. package/dist/migrate-7B7ACQHY.mjs +0 -8
  78. package/dist/publish-Q4JYQPQP.mjs +0 -3
  79. package/dist/remove-PDERBH66.mjs +0 -2
  80. package/dist/reset-3FXWAAPQ.mjs +0 -3
  81. package/dist/rollback-FKNGLGFC.mjs +0 -3
  82. package/dist/tailwind-source-ND5FE6PQ.mjs +0 -5
  83. package/dist/update-QPBWYDSG.mjs +0 -3
  84. package/dist/watch-orchestrator-F6S5WQQX.mjs +0 -3
package/dist/index.mjs CHANGED
@@ -97,12 +97,12 @@ function pLimit(concurrency) {
97
97
  head = 0;
98
98
  }
99
99
  };
100
- return (fn) => new Promise((resolve7, reject) => {
100
+ return (fn) => new Promise((resolve8, reject) => {
101
101
  const run = () => {
102
102
  fn().then(
103
103
  (val) => {
104
104
  active--;
105
- resolve7(val);
105
+ resolve8(val);
106
106
  next();
107
107
  },
108
108
  (err) => {
@@ -126,19 +126,86 @@ var init_concurrency = __esm({
126
126
  }
127
127
  });
128
128
 
129
+ // src/utils/validators.ts
130
+ import { readFile } from "fs/promises";
131
+ import { join } from "path";
132
+ function validatePackageName(name) {
133
+ if (!name || name.length > 214 || CONTROL_CHARS_RE.test(name) || name.includes("\\") || name.includes("//") || name.split("/").some((part) => part === "." || part === "..") || !PACKAGE_NAME_RE.test(name)) {
134
+ throw new Error(`Invalid package name "${name}"`);
135
+ }
136
+ }
137
+ function validatePackageVersion(version) {
138
+ if (!version || CONTROL_CHARS_RE.test(version) || version.includes("/") || version.includes("\\") || version.includes("..") || !SEMVER_RE.test(version)) {
139
+ throw new Error(`Invalid package version "${version}"`);
140
+ }
141
+ }
142
+ function validatePackageIdentity(name, version) {
143
+ validatePackageName(name);
144
+ validatePackageVersion(version);
145
+ }
146
+ function isKnarrMeta(value) {
147
+ if (typeof value !== "object" || value === null) return false;
148
+ const v = value;
149
+ return typeof v.contentHash === "string" && typeof v.publishedAt === "string" && typeof v.sourcePath === "string" && (v.buildId === void 0 || typeof v.buildId === "string") && (v.schemaVersion === void 0 || typeof v.schemaVersion === "number");
150
+ }
151
+ function isLinkEntry(value) {
152
+ if (typeof value !== "object" || value === null) return false;
153
+ const v = value;
154
+ return typeof v.version === "string" && typeof v.contentHash === "string" && typeof v.linkedAt === "string" && typeof v.sourcePath === "string" && typeof v.backupExists === "boolean" && typeof v.packageManager === "string" && ["npm", "pnpm", "yarn", "bun"].includes(v.packageManager) && (v.buildId === void 0 || typeof v.buildId === "string");
155
+ }
156
+ function isConsumerState(value) {
157
+ if (typeof value !== "object" || value === null) return false;
158
+ const v = value;
159
+ if (v.version !== "1") return false;
160
+ if (typeof v.links !== "object" || v.links === null) return false;
161
+ const links = v.links;
162
+ for (const entry of Object.values(links)) {
163
+ if (!isLinkEntry(entry)) return false;
164
+ }
165
+ return true;
166
+ }
167
+ function isConsumersRegistry(value) {
168
+ if (typeof value !== "object" || value === null) return false;
169
+ const v = value;
170
+ for (const val of Object.values(v)) {
171
+ if (!Array.isArray(val)) return false;
172
+ for (const item of val) {
173
+ if (typeof item !== "string") return false;
174
+ }
175
+ }
176
+ return true;
177
+ }
178
+ var PACKAGE_NAME_RE, SEMVER_RE, CONTROL_CHARS_RE;
179
+ var init_validators = __esm({
180
+ "src/utils/validators.ts"() {
181
+ "use strict";
182
+ PACKAGE_NAME_RE = /^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/;
183
+ SEMVER_RE = /^(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-]+)*)?$/;
184
+ CONTROL_CHARS_RE = /[\x00-\x1F\x7F]/;
185
+ }
186
+ });
187
+
129
188
  // src/utils/paths.ts
130
189
  import { homedir } from "os";
131
- import { join } from "path";
190
+ import { isAbsolute, join as join2, relative, resolve } from "path";
191
+ function assertInside(root, target, label) {
192
+ const resolvedRoot = resolve(root);
193
+ const resolvedTarget = resolve(target);
194
+ const rel = relative(resolvedRoot, resolvedTarget);
195
+ if (rel === "" || !rel.startsWith("..") && !isAbsolute(rel)) return;
196
+ throw new Error(`${label} escapes expected directory: ${target}`);
197
+ }
132
198
  function getKnarrHome() {
133
- return process.env.KNARR_HOME || join(homedir(), ".knarr");
199
+ return process.env.KNARR_HOME || join2(homedir(), ".knarr");
134
200
  }
135
201
  function getStorePath() {
136
- return join(getKnarrHome(), "store");
202
+ return join2(getKnarrHome(), "store");
137
203
  }
138
204
  function getConsumersPath() {
139
- return join(getKnarrHome(), "consumers.json");
205
+ return join2(getKnarrHome(), "consumers.json");
140
206
  }
141
207
  function encodePackageName(name) {
208
+ validatePackageName(name);
142
209
  return name.replace(/\//g, "+");
143
210
  }
144
211
  function decodePackageName(encoded) {
@@ -151,38 +218,54 @@ function decodePackageName(encoded) {
151
218
  return encoded;
152
219
  }
153
220
  function getStoreEntryPath(name, version) {
154
- return join(getStorePath(), `${encodePackageName(name)}@${version}`);
221
+ validatePackageIdentity(name, version);
222
+ const root = getStorePath();
223
+ const target = join2(root, `${encodePackageName(name)}@${version}`);
224
+ assertInside(root, target, "Store entry path");
225
+ return target;
155
226
  }
156
227
  function getStorePackagePath(name, version) {
157
- return join(getStoreEntryPath(name, version), "package");
228
+ return join2(getStoreEntryPath(name, version), "package");
158
229
  }
159
230
  function getStoreMetaPath(name, version) {
160
- return join(getStoreEntryPath(name, version), ".knarr-meta.json");
231
+ return join2(getStoreEntryPath(name, version), ".knarr-meta.json");
161
232
  }
162
233
  function getStoreHistoryPath(name, version) {
163
- return join(getStoreEntryPath(name, version), "history");
234
+ return join2(getStoreEntryPath(name, version), "history");
164
235
  }
165
236
  function getHistoryEntryPath(name, version, buildId) {
166
- return join(getStoreHistoryPath(name, version), buildId);
237
+ if (!/^[a-f0-9]{8,64}$/i.test(buildId)) {
238
+ throw new Error(`Invalid build id "${buildId}"`);
239
+ }
240
+ return join2(getStoreHistoryPath(name, version), buildId);
167
241
  }
168
242
  function getConsumerKnarrDir(consumerPath) {
169
- return join(consumerPath, ".knarr");
243
+ return join2(consumerPath, ".knarr");
170
244
  }
171
245
  function getConsumerStatePath(consumerPath) {
172
- return join(consumerPath, ".knarr", "state.json");
246
+ return join2(consumerPath, ".knarr", "state.json");
173
247
  }
174
248
  function getConsumerBackupPath(consumerPath, packageName) {
175
- return join(consumerPath, ".knarr", "backups", encodePackageName(packageName));
249
+ validatePackageName(packageName);
250
+ const root = join2(consumerPath, ".knarr", "backups");
251
+ const target = join2(root, encodePackageName(packageName));
252
+ assertInside(root, target, "Backup path");
253
+ return target;
176
254
  }
177
255
  function normalizePath(p) {
178
256
  return p.replace(/\\/g, "/");
179
257
  }
180
258
  function getNodeModulesPackagePath(consumerPath, packageName) {
181
- return join(consumerPath, "node_modules", packageName);
259
+ validatePackageName(packageName);
260
+ const root = join2(consumerPath, "node_modules");
261
+ const target = join2(root, packageName);
262
+ assertInside(root, target, "node_modules package path");
263
+ return target;
182
264
  }
183
265
  var init_paths = __esm({
184
266
  "src/utils/paths.ts"() {
185
267
  "use strict";
268
+ init_validators();
186
269
  }
187
270
  });
188
271
 
@@ -209,8 +292,8 @@ var init_logger = __esm({
209
292
 
210
293
  // src/utils/hash.ts
211
294
  import { createHash } from "crypto";
212
- import { readFile, stat } from "fs/promises";
213
- import { relative } from "path";
295
+ import { readFile as readFile2, stat } from "fs/promises";
296
+ import { relative as relative2 } from "path";
214
297
  import { availableParallelism } from "os";
215
298
  function getXXHash() {
216
299
  if (!_xxhash) {
@@ -223,8 +306,8 @@ function getXXHash() {
223
306
  }
224
307
  async function computeContentHash(files, baseDir) {
225
308
  const sorted = [...files].sort((a, b) => {
226
- const relA = normalizePath(relative(baseDir, a));
227
- const relB = normalizePath(relative(baseDir, b));
309
+ const relA = normalizePath(relative2(baseDir, a));
310
+ const relB = normalizePath(relative2(baseDir, b));
228
311
  return relA.localeCompare(relB);
229
312
  });
230
313
  const currentFiles = new Set(sorted);
@@ -232,14 +315,14 @@ async function computeContentHash(files, baseDir) {
232
315
  const contents = await Promise.all(
233
316
  sorted.map(
234
317
  (file) => limit(async () => {
235
- const rel = normalizePath(relative(baseDir, file));
318
+ const rel = normalizePath(relative2(baseDir, file));
236
319
  const s = await stat(file);
237
320
  const cached = _contentCache.get(file);
238
321
  if (cached && cached.mtimeMs === s.mtimeMs && cached.size === s.size) {
239
322
  cacheHits++;
240
323
  return { rel, content: cached.content };
241
324
  }
242
- const content = await readFile(file);
325
+ const content = await readFile2(file);
243
326
  _contentCache.set(file, { mtimeMs: s.mtimeMs, size: s.size, content });
244
327
  return { rel, content };
245
328
  })
@@ -268,16 +351,16 @@ async function hashFile(filePath, knownSize) {
268
351
  if (size > STREAM_THRESHOLD) {
269
352
  return hashFileStream(filePath, xx);
270
353
  }
271
- const content = await readFile(filePath);
354
+ const content = await readFile2(filePath);
272
355
  return xx.h64Raw(content).toString(16);
273
356
  }
274
357
  async function hashFileStream(filePath, xx) {
275
358
  const { createReadStream } = await import("fs");
276
359
  const hasher = xx.create64();
277
- return new Promise((resolve7, reject) => {
360
+ return new Promise((resolve8, reject) => {
278
361
  const stream = createReadStream(filePath);
279
362
  stream.on("data", (chunk) => hasher.update(chunk));
280
- stream.on("end", () => resolve7(hasher.digest().toString(16)));
363
+ stream.on("end", () => resolve8(hasher.digest().toString(16)));
281
364
  stream.on("error", reject);
282
365
  });
283
366
  }
@@ -330,7 +413,8 @@ function printDryRunReport() {
330
413
  "bin-unlink": "Remove bin link",
331
414
  "cache-invalidate": "Invalidate cache",
332
415
  "lock-skip": "Skip lock",
333
- "lifecycle-skip": "Skip lifecycle hook"
416
+ "lifecycle-skip": "Skip lifecycle hook",
417
+ "command-skip": "Skip command"
334
418
  };
335
419
  for (const [type, items] of grouped) {
336
420
  consola.info(` ${labels[type]} (${items.length}):`);
@@ -385,7 +469,7 @@ import {
385
469
  writeFile,
386
470
  constants
387
471
  } from "fs/promises";
388
- import { join as join2, dirname, relative as relative2, parse as parsePath } from "path";
472
+ import { join as join3, dirname, relative as relative3, parse as parsePath } from "path";
389
473
  import { availableParallelism as availableParallelism2 } from "os";
390
474
  function isNodeError(err) {
391
475
  return err instanceof Error && "code" in err;
@@ -424,7 +508,7 @@ async function copyWithCoW(src, dest, options) {
424
508
  }
425
509
  async function collectFiles(dir) {
426
510
  const entries = await readdir(dir, { recursive: true, withFileTypes: true });
427
- return entries.filter((e) => e.isFile()).map((e) => join2(e.parentPath, e.name));
511
+ return entries.filter((e) => e.isFile()).map((e) => join3(e.parentPath, e.name));
428
512
  }
429
513
  async function incrementalCopy(srcDir, destDir, options = {}) {
430
514
  const srcFilesPromise = collectFiles(srcDir);
@@ -439,8 +523,8 @@ async function incrementalCopy(srcDir, destDir, options = {}) {
439
523
  const results = await Promise.all(
440
524
  srcFiles.map(
441
525
  (srcFile) => ioLimit(async () => {
442
- const rel = relative2(srcDir, srcFile);
443
- const destFile = join2(destDir, rel);
526
+ const rel = relative3(srcDir, srcFile);
527
+ const destFile = join3(destDir, rel);
444
528
  let needsCopy = true;
445
529
  let srcTimes = null;
446
530
  if (options.force) {
@@ -494,14 +578,14 @@ async function incrementalCopy(srcDir, destDir, options = {}) {
494
578
  if (r === "copied") copied++;
495
579
  else skipped++;
496
580
  }
497
- const srcRelPaths = new Set(srcFiles.map((f) => relative2(srcDir, f)));
581
+ const srcRelPaths = new Set(srcFiles.map((f) => relative3(srcDir, f)));
498
582
  const filesToRemove = destFiles.filter(
499
- (f) => !srcRelPaths.has(relative2(destDir, f))
583
+ (f) => !srcRelPaths.has(relative3(destDir, f))
500
584
  );
501
585
  await Promise.all(
502
586
  filesToRemove.map(
503
587
  (destFile) => ioLimit(async () => {
504
- verbose(`[remove] ${relative2(destDir, destFile)} (no longer in source)`);
588
+ verbose(`[remove] ${relative3(destDir, destFile)} (no longer in source)`);
505
589
  if (isDryRun()) {
506
590
  recordMutation({ type: "remove", path: destFile });
507
591
  } else {
@@ -584,6 +668,11 @@ async function dirSize(dir) {
584
668
  }
585
669
  }
586
670
  async function copyDir(src, dest) {
671
+ if (isDryRun()) {
672
+ verbose(`[dry-run] would copy directory ${src} \u2192 ${dest}`);
673
+ recordMutation({ type: "copy", path: src, dest });
674
+ return;
675
+ }
587
676
  await cp(src, dest, { recursive: true });
588
677
  }
589
678
  var ioLimit, reflinkSupported;
@@ -601,19 +690,19 @@ var init_fs = __esm({
601
690
  });
602
691
 
603
692
  // src/utils/pack-list.ts
604
- import { readFile as readFile2, readdir as readdir2, stat as stat3 } from "fs/promises";
605
- import { join as join3, relative as relative3, resolve, sep } from "path";
693
+ import { readFile as readFile3, readdir as readdir2, stat as stat3 } from "fs/promises";
694
+ import { join as join4, relative as relative4, resolve as resolve2, sep } from "path";
606
695
  import picomatch from "picomatch";
607
696
  async function resolvePackFiles(packageDir, pkg) {
608
697
  const files = [];
609
- const absDir = resolve(packageDir);
610
- files.push(join3(absDir, "package.json"));
698
+ const absDir = resolve2(packageDir);
699
+ files.push(join4(absDir, "package.json"));
611
700
  const allFiles = await collectAllFiles(absDir, absDir);
612
- const allRelPaths = allFiles.map((f) => normalizePath(relative3(absDir, f)));
701
+ const allRelPaths = allFiles.map((f) => normalizePath(relative4(absDir, f)));
613
702
  if (pkg.files && pkg.files.length > 0) {
614
703
  for (const pattern of pkg.files) {
615
- const target = join3(absDir, pattern);
616
- const resolved = resolve(target);
704
+ const target = join4(absDir, pattern);
705
+ const resolved = resolve2(target);
617
706
  if (!resolved.startsWith(absDir + sep) && resolved !== absDir) {
618
707
  consola.warn(`files pattern "${pattern}" escapes package directory, skipping`);
619
708
  continue;
@@ -622,7 +711,7 @@ async function resolvePackFiles(packageDir, pkg) {
622
711
  try {
623
712
  const s = await stat3(target);
624
713
  if (s.isDirectory()) {
625
- const prefix = normalizePath(relative3(absDir, target)) + "/";
714
+ const prefix = normalizePath(relative4(absDir, target)) + "/";
626
715
  for (let i = 0; i < allRelPaths.length; i++) {
627
716
  if (allRelPaths[i].startsWith(prefix)) {
628
717
  files.push(allFiles[i]);
@@ -643,7 +732,7 @@ async function resolvePackFiles(packageDir, pkg) {
643
732
  let globMatched = 0;
644
733
  for (let i = 0; i < allRelPaths.length; i++) {
645
734
  if (isMatch(allRelPaths[i])) {
646
- const absFile = resolve(allFiles[i]);
735
+ const absFile = resolve2(allFiles[i]);
647
736
  if (!absFile.startsWith(absDir + sep) && absFile !== absDir) continue;
648
737
  files.push(allFiles[i]);
649
738
  globMatched++;
@@ -665,7 +754,7 @@ async function resolvePackFiles(packageDir, pkg) {
665
754
  const fileSet = new Set(files);
666
755
  const allFileSet = new Set(allFiles);
667
756
  for (const name of ["README.md", "README", "LICENSE", "LICENCE", "CHANGELOG.md"]) {
668
- const p = join3(absDir, name);
757
+ const p = join4(absDir, name);
669
758
  if (fileSet.has(p)) continue;
670
759
  if (!allFileSet.has(p)) continue;
671
760
  files.push(p);
@@ -691,7 +780,7 @@ function shouldIgnore(relPath, matchers) {
691
780
  async function loadNpmIgnore(dir) {
692
781
  const matchers = { literals: /* @__PURE__ */ new Set(), patterns: [], negations: [] };
693
782
  try {
694
- const content = await readFile2(join3(dir, ".npmignore"), "utf-8");
783
+ const content = await readFile3(join4(dir, ".npmignore"), "utf-8");
695
784
  for (const line of content.split("\n")) {
696
785
  const trimmed = line.trim();
697
786
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -723,7 +812,7 @@ async function collectAllFiles(dir, rootDir) {
723
812
  try {
724
813
  const entries = await readdir2(dir, { withFileTypes: true });
725
814
  for (const entry of entries) {
726
- const full = join3(dir, entry.name);
815
+ const full = join4(dir, entry.name);
727
816
  if (entry.isDirectory()) {
728
817
  if (entry.name === ".git") continue;
729
818
  if (dir === rootDir && entry.name === "node_modules") continue;
@@ -779,47 +868,6 @@ var init_pack_list = __esm({
779
868
  }
780
869
  });
781
870
 
782
- // src/utils/validators.ts
783
- import { readFile as readFile3 } from "fs/promises";
784
- import { join as join4 } from "path";
785
- function isKnarrMeta(value) {
786
- if (typeof value !== "object" || value === null) return false;
787
- const v = value;
788
- return typeof v.contentHash === "string" && typeof v.publishedAt === "string" && typeof v.sourcePath === "string" && (v.buildId === void 0 || typeof v.buildId === "string") && (v.schemaVersion === void 0 || typeof v.schemaVersion === "number");
789
- }
790
- function isLinkEntry(value) {
791
- if (typeof value !== "object" || value === null) return false;
792
- const v = value;
793
- return typeof v.version === "string" && typeof v.contentHash === "string" && typeof v.linkedAt === "string" && typeof v.sourcePath === "string" && typeof v.backupExists === "boolean" && typeof v.packageManager === "string" && ["npm", "pnpm", "yarn", "bun"].includes(v.packageManager) && (v.buildId === void 0 || typeof v.buildId === "string");
794
- }
795
- function isConsumerState(value) {
796
- if (typeof value !== "object" || value === null) return false;
797
- const v = value;
798
- if (v.version !== "1") return false;
799
- if (typeof v.links !== "object" || v.links === null) return false;
800
- const links = v.links;
801
- for (const entry of Object.values(links)) {
802
- if (!isLinkEntry(entry)) return false;
803
- }
804
- return true;
805
- }
806
- function isConsumersRegistry(value) {
807
- if (typeof value !== "object" || value === null) return false;
808
- const v = value;
809
- for (const val of Object.values(v)) {
810
- if (!Array.isArray(val)) return false;
811
- for (const item of val) {
812
- if (typeof item !== "string") return false;
813
- }
814
- }
815
- return true;
816
- }
817
- var init_validators = __esm({
818
- "src/utils/validators.ts"() {
819
- "use strict";
820
- }
821
- });
822
-
823
871
  // src/core/store.ts
824
872
  import { readFile as readFile4, readdir as readdir3 } from "fs/promises";
825
873
  import "path";
@@ -991,7 +1039,7 @@ __export(history_exports, {
991
1039
  resolveHistoryLimit: () => resolveHistoryLimit,
992
1040
  restoreHistoryEntry: () => restoreHistoryEntry
993
1041
  });
994
- import { readdir as readdir4, readFile as readFile5, rename as rename2, writeFile as writeFile2 } from "fs/promises";
1042
+ import { readdir as readdir4, readFile as readFile5 } from "fs/promises";
995
1043
  import { join as join6 } from "path";
996
1044
  async function captureHistory(name, version, oldEntryDir, historyLimit) {
997
1045
  const metaPath = join6(oldEntryDir, ".knarr-meta.json");
@@ -1021,11 +1069,11 @@ async function captureHistory(name, version, oldEntryDir, historyLimit) {
1021
1069
  if (await exists(oldPkgDir)) {
1022
1070
  await moveDir(oldPkgDir, join6(tmpHistoryEntry, "package"));
1023
1071
  }
1024
- await writeFile2(
1072
+ await atomicWriteFile(
1025
1073
  join6(tmpHistoryEntry, ".knarr-meta.json"),
1026
1074
  JSON.stringify(meta, null, 2)
1027
1075
  );
1028
- await rename2(tmpHistoryEntry, entryDir);
1076
+ await moveDir(tmpHistoryEntry, entryDir);
1029
1077
  verbose(`[history] Captured build ${buildId} to history`);
1030
1078
  } catch (err) {
1031
1079
  verbose(`[history] Failed to capture history: ${err instanceof Error ? err.message : String(err)}`);
@@ -1086,17 +1134,54 @@ async function restoreHistoryEntry(name, version, buildId, historyLimit) {
1086
1134
  const historyPkg = join6(historyEntryDir, "package");
1087
1135
  const historyMeta = join6(historyEntryDir, ".knarr-meta.json");
1088
1136
  const metaContent = await readFile5(historyMeta, "utf-8");
1089
- if (await exists(storeEntryDir)) {
1090
- await captureHistory(name, version, storeEntryDir, historyLimit);
1091
- }
1092
1137
  const storePkg = join6(storeEntryDir, "package");
1093
1138
  const storeMeta = join6(storeEntryDir, ".knarr-meta.json");
1094
- if (await exists(storePkg)) await removeDir(storePkg);
1095
- if (await exists(historyPkg)) {
1139
+ if (!await exists(historyPkg)) {
1140
+ throw new Error(`History entry ${buildId} is missing its package directory`);
1141
+ }
1142
+ const currentMetaContent = await readFile5(storeMeta, "utf-8").catch(() => null);
1143
+ const oldEntryDir = storeEntryDir + `.restore-old-${process.pid}-${Date.now()}`;
1144
+ const oldPkg = join6(oldEntryDir, "package");
1145
+ let stagedOld = false;
1146
+ let historyMovedToStore = false;
1147
+ try {
1148
+ if (await exists(storePkg) || currentMetaContent) {
1149
+ await ensureDir(oldEntryDir);
1150
+ if (await exists(storePkg)) {
1151
+ await moveDir(storePkg, oldPkg);
1152
+ }
1153
+ if (currentMetaContent) {
1154
+ await atomicWriteFile(join6(oldEntryDir, ".knarr-meta.json"), currentMetaContent);
1155
+ }
1156
+ stagedOld = true;
1157
+ }
1096
1158
  await moveDir(historyPkg, storePkg);
1159
+ historyMovedToStore = true;
1160
+ await atomicWriteFile(storeMeta, metaContent);
1161
+ await removeDir(historyEntryDir);
1162
+ if (stagedOld) {
1163
+ try {
1164
+ await captureHistory(name, version, oldEntryDir, historyLimit);
1165
+ } finally {
1166
+ await removeDir(oldEntryDir);
1167
+ }
1168
+ }
1169
+ } catch (err) {
1170
+ if (historyMovedToStore && await exists(storePkg)) {
1171
+ await ensureDir(historyEntryDir);
1172
+ await moveDir(storePkg, historyPkg);
1173
+ } else if (stagedOld && await exists(storePkg)) {
1174
+ await removeDir(storePkg);
1175
+ }
1176
+ if (stagedOld && await exists(oldPkg)) {
1177
+ await moveDir(oldPkg, storePkg);
1178
+ }
1179
+ if (currentMetaContent) {
1180
+ await atomicWriteFile(storeMeta, currentMetaContent);
1181
+ }
1182
+ await removeDir(oldEntryDir);
1183
+ throw err;
1097
1184
  }
1098
- await writeFile2(storeMeta, metaContent);
1099
- await removeDir(historyEntryDir);
1100
1185
  verbose(`[history] Restored build ${buildId} as current`);
1101
1186
  return entry;
1102
1187
  }
@@ -1147,7 +1232,7 @@ __export(workspace_exports, {
1147
1232
  parseCatalogs: () => parseCatalogs
1148
1233
  });
1149
1234
  import { readFile as readFile6, readdir as readdir5 } from "fs/promises";
1150
- import { join as join7, dirname as dirname3, resolve as resolve2, relative as relative4 } from "path";
1235
+ import { join as join7, dirname as dirname3, resolve as resolve3, relative as relative5 } from "path";
1151
1236
  import picomatch2 from "picomatch";
1152
1237
  async function findWorkspaceRoot(startDir) {
1153
1238
  let dir = startDir;
@@ -1317,14 +1402,14 @@ async function resolveWorkspaceGlobs(rootDir, patterns, negations = []) {
1317
1402
  const isMatch = picomatch2(pattern);
1318
1403
  const candidates = await collectDirs(rootDir, 8);
1319
1404
  for (const candidate of candidates) {
1320
- const rel = normalizePath(relative4(rootDir, candidate));
1405
+ const rel = normalizePath(relative5(rootDir, candidate));
1321
1406
  if (isMatch(rel) && await exists(join7(candidate, "package.json"))) {
1322
1407
  results.push(candidate);
1323
1408
  }
1324
1409
  }
1325
1410
  }
1326
1411
  } else {
1327
- const pkgDir = resolve2(rootDir, pattern);
1412
+ const pkgDir = resolve3(rootDir, pattern);
1328
1413
  if (await exists(join7(pkgDir, "package.json"))) {
1329
1414
  results.push(pkgDir);
1330
1415
  }
@@ -1334,7 +1419,7 @@ async function resolveWorkspaceGlobs(rootDir, patterns, negations = []) {
1334
1419
  if (negations.length === 0) return unique;
1335
1420
  const isExcluded = picomatch2(negations);
1336
1421
  return unique.filter((dir) => {
1337
- const rel = normalizePath(relative4(rootDir, dir));
1422
+ const rel = normalizePath(relative5(rootDir, dir));
1338
1423
  return !isExcluded(rel);
1339
1424
  });
1340
1425
  }
@@ -1420,8 +1505,8 @@ var init_workspace = __esm({
1420
1505
  });
1421
1506
 
1422
1507
  // src/core/publisher.ts
1423
- import { readFile as readFile7, writeFile as writeFile3, rename as rename3, stat as stat5 } from "fs/promises";
1424
- import { join as join8, relative as relative5, dirname as dirname4, resolve as resolve3 } from "path";
1508
+ import { readFile as readFile7, stat as stat5 } from "fs/promises";
1509
+ import { join as join8, relative as relative6, dirname as dirname4, resolve as resolve4 } from "path";
1425
1510
  import { spawn } from "child_process";
1426
1511
  import { platform } from "os";
1427
1512
  import { availableParallelism as availableParallelism3 } from "os";
@@ -1436,6 +1521,7 @@ async function publish(packageDir, options = {}) {
1436
1521
  const pkg = JSON.parse(pkgContent);
1437
1522
  if (!pkg.name) throw new Error("package.json missing 'name' field");
1438
1523
  if (!pkg.version) throw new Error("package.json missing 'version' field");
1524
+ validatePackageIdentity(pkg.name, pkg.version);
1439
1525
  if (pkg.private && !options.allowPrivate) {
1440
1526
  throw new Error(
1441
1527
  `Package "${pkg.name}" is private. Use --private flag to publish private packages.`
@@ -1447,7 +1533,7 @@ async function publish(packageDir, options = {}) {
1447
1533
  }
1448
1534
  let publishDir = packageDir;
1449
1535
  if (pkg.publishConfig?.directory) {
1450
- publishDir = resolve3(packageDir, pkg.publishConfig.directory);
1536
+ publishDir = resolve4(packageDir, pkg.publishConfig.directory);
1451
1537
  try {
1452
1538
  const s = await stat5(publishDir);
1453
1539
  if (!s.isDirectory()) {
@@ -1511,16 +1597,16 @@ async function publish(packageDir, options = {}) {
1511
1597
  processedPkg = applyPublishConfig(processedPkg);
1512
1598
  verbose(`[publish] Copying files to temp store...`);
1513
1599
  const uniqueDirs = new Set(
1514
- files.map((file) => dirname4(join8(tmpPackageDir, relative5(publishDir, file))))
1600
+ files.map((file) => dirname4(join8(tmpPackageDir, relative6(publishDir, file))))
1515
1601
  );
1516
1602
  await Promise.all([...uniqueDirs].map((d) => ensureDir(d)));
1517
1603
  await Promise.all(
1518
1604
  files.map(
1519
1605
  (file) => copyLimit(async () => {
1520
- const rel = relative5(publishDir, file);
1606
+ const rel = relative6(publishDir, file);
1521
1607
  const dest = join8(tmpPackageDir, rel);
1522
1608
  if (rel === "package.json" && processedPkg !== pkg) {
1523
- await writeFile3(dest, JSON.stringify(processedPkg, null, 2));
1609
+ await atomicWriteFile(dest, JSON.stringify(processedPkg, null, 2));
1524
1610
  } else {
1525
1611
  await copyWithCoW(file, dest, { ensureParent: false });
1526
1612
  }
@@ -1528,7 +1614,7 @@ async function publish(packageDir, options = {}) {
1528
1614
  )
1529
1615
  );
1530
1616
  if (publishDir !== packageDir) {
1531
- await writeFile3(
1617
+ await atomicWriteFile(
1532
1618
  join8(tmpPackageDir, "package.json"),
1533
1619
  JSON.stringify(processedPkg, null, 2)
1534
1620
  );
@@ -1540,15 +1626,29 @@ async function publish(packageDir, options = {}) {
1540
1626
  sourcePath: packageDir,
1541
1627
  buildId
1542
1628
  };
1543
- await writeFile3(
1629
+ await atomicWriteFile(
1544
1630
  join8(tmpDir, ".knarr-meta.json"),
1545
1631
  JSON.stringify(meta, null, 2)
1546
1632
  );
1547
1633
  const hadOld = await exists(storeEntryDir);
1548
1634
  const oldDir = storeEntryDir + ".old-" + Date.now();
1549
- if (hadOld) await rename3(storeEntryDir, oldDir);
1550
- await moveDir(tmpDir, storeEntryDir);
1551
- if (hadOld) {
1635
+ let oldMoved = false;
1636
+ try {
1637
+ if (hadOld) {
1638
+ await moveDir(storeEntryDir, oldDir);
1639
+ oldMoved = !isDryRun();
1640
+ }
1641
+ await moveDir(tmpDir, storeEntryDir);
1642
+ } catch (err) {
1643
+ if (oldMoved && await exists(oldDir)) {
1644
+ if (await exists(storeEntryDir)) {
1645
+ await removeDir(storeEntryDir);
1646
+ }
1647
+ await moveDir(oldDir, storeEntryDir);
1648
+ }
1649
+ throw err;
1650
+ }
1651
+ if (hadOld && !isDryRun()) {
1552
1652
  try {
1553
1653
  const { captureHistory: captureHistory2 } = await Promise.resolve().then(() => (init_history(), history_exports));
1554
1654
  await captureHistory2(pkg.name, pkg.version, oldDir, options.historyLimit);
@@ -1595,7 +1695,7 @@ async function runLifecycleHook(packageDir, pkg, hookName) {
1595
1695
  return;
1596
1696
  }
1597
1697
  verbose(`[lifecycle] Running ${hookName}: ${script}`);
1598
- return new Promise((resolve7, reject) => {
1698
+ return new Promise((resolve8, reject) => {
1599
1699
  const isWin = platform() === "win32";
1600
1700
  const shell = isWin ? "cmd" : "sh";
1601
1701
  const shellFlag = isWin ? "/c" : "-c";
@@ -1610,7 +1710,7 @@ async function runLifecycleHook(packageDir, pkg, hookName) {
1610
1710
  child.on("close", (code) => {
1611
1711
  clearTimeout(timer);
1612
1712
  if (code === 0) {
1613
- resolve7();
1713
+ resolve8();
1614
1714
  } else {
1615
1715
  reject(new Error(`${hookName} script failed with exit code ${code}`));
1616
1716
  }
@@ -1769,6 +1869,7 @@ var init_publisher = __esm({
1769
1869
  init_lockfile();
1770
1870
  init_logger();
1771
1871
  init_dry_run();
1872
+ init_validators();
1772
1873
  copyLimit = pLimit(Math.max(availableParallelism3(), 8));
1773
1874
  HOOK_TIMEOUT = parseInt(process.env.KNARR_HOOK_TIMEOUT ?? "30000", 10);
1774
1875
  PUBLISH_CONFIG_OVERRIDES = [
@@ -1787,8 +1888,8 @@ var init_publisher = __esm({
1787
1888
  });
1788
1889
 
1789
1890
  // src/utils/bin-linker.ts
1790
- import { mkdir as mkdir3, symlink, writeFile as writeFile4, chmod, rm as rm3 } from "fs/promises";
1791
- import { join as join9, relative as relative6, resolve as resolve4, sep as sep2 } from "path";
1891
+ import { mkdir as mkdir3, symlink, writeFile as writeFile2, chmod, rm as rm3 } from "fs/promises";
1892
+ import { join as join9, relative as relative7, resolve as resolve5, sep as sep2 } from "path";
1792
1893
  import { platform as platform2 } from "os";
1793
1894
  function resolveBinEntries(pkg) {
1794
1895
  if (!pkg.bin) return {};
@@ -1815,12 +1916,12 @@ async function createBinLinks(consumerPath, packageName, pkg) {
1815
1916
  for (const [binName, binPath] of Object.entries(entries)) {
1816
1917
  const packageRoot = join9(consumerPath, "node_modules", packageName);
1817
1918
  const targetAbsolute = join9(packageRoot, binPath);
1818
- const resolvedTarget = resolve4(targetAbsolute);
1819
- if (!resolvedTarget.startsWith(resolve4(packageRoot) + sep2) && resolvedTarget !== resolve4(packageRoot)) {
1919
+ const resolvedTarget = resolve5(targetAbsolute);
1920
+ if (!resolvedTarget.startsWith(resolve5(packageRoot) + sep2) && resolvedTarget !== resolve5(packageRoot)) {
1820
1921
  consola.warn(`bin "${binName}" points outside package directory, skipping`);
1821
1922
  continue;
1822
1923
  }
1823
- const targetRelative = normalizePath(relative6(binDir, targetAbsolute));
1924
+ const targetRelative = normalizePath(relative7(binDir, targetAbsolute));
1824
1925
  if (isWindows) {
1825
1926
  const cmdPath = join9(binDir, `${binName}.cmd`);
1826
1927
  const targetWindows = targetRelative.replace(/\//g, "\\");
@@ -1831,21 +1932,21 @@ SET dp0=%~dp0\r
1831
1932
  EXIT /b\r
1832
1933
  :start\r
1833
1934
  CALL :find_dp0\r
1834
- "%dp0%\\${targetWindows}" %*\r
1935
+ node "%dp0%\\${targetWindows}" %*\r
1835
1936
  `;
1836
- await writeFile4(cmdPath, cmdContent);
1937
+ await writeFile2(cmdPath, cmdContent);
1837
1938
  const ps1Path = join9(binDir, `${binName}.ps1`);
1838
1939
  const ps1Content = `#!/usr/bin/env pwsh
1839
1940
  $basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
1840
1941
  & node "$basedir/${targetRelative}" $args
1841
1942
  exit $LASTEXITCODE
1842
1943
  `;
1843
- await writeFile4(ps1Path, ps1Content);
1944
+ await writeFile2(ps1Path, ps1Content);
1844
1945
  const shPath = join9(binDir, binName);
1845
1946
  const shContent = `#!/bin/sh
1846
1947
  exec node "${targetRelative}" "$@"
1847
1948
  `;
1848
- await writeFile4(shPath, shContent);
1949
+ await writeFile2(shPath, shContent);
1849
1950
  } else {
1850
1951
  const linkPath = join9(binDir, binName);
1851
1952
  try {
@@ -1861,7 +1962,7 @@ exec node "${targetRelative}" "$@"
1861
1962
  const shContent = `#!/bin/sh
1862
1963
  exec node "${targetRelative}" "$@"
1863
1964
  `;
1864
- await writeFile4(linkPath, shContent);
1965
+ await writeFile2(linkPath, shContent);
1865
1966
  await chmod(linkPath, 493);
1866
1967
  } else {
1867
1968
  throw err;
@@ -2066,7 +2167,7 @@ var init_bundler_cache = __esm({
2066
2167
 
2067
2168
  // src/core/injector.ts
2068
2169
  import { readFile as readFile9, readdir as readdir6, realpath, stat as stat7 } from "fs/promises";
2069
- import { join as join13, resolve as resolve5 } from "path";
2170
+ import { join as join13, resolve as resolve6 } from "path";
2070
2171
  async function inject(storeEntry, consumerPath, pm, options = {}) {
2071
2172
  const targetDir = await resolveTargetDir(
2072
2173
  consumerPath,
@@ -2146,7 +2247,7 @@ async function resolveTargetDir(consumerPath, packageName, pm, version) {
2146
2247
  }
2147
2248
  try {
2148
2249
  const realPath = await resolveRealPath(directPath);
2149
- if (realPath !== resolve5(directPath)) {
2250
+ if (realPath !== resolve6(directPath)) {
2150
2251
  verbose(`[inject] pnpm: resolved symlink \u2192 ${realPath}`);
2151
2252
  return realPath;
2152
2253
  }
@@ -2194,7 +2295,7 @@ async function resolveRealPath(linkPath) {
2194
2295
  return await realpath(linkPath);
2195
2296
  } catch (err) {
2196
2297
  if (isNodeError(err) && err.code === "ENOENT") {
2197
- return resolve5(linkPath);
2298
+ return resolve6(linkPath);
2198
2299
  }
2199
2300
  throw err;
2200
2301
  }
@@ -3008,7 +3109,7 @@ async function startWatcher(watchDir, options, onChange) {
3008
3109
  return watcherHandle;
3009
3110
  }
3010
3111
  function runBuildCommand(cmd, cwd) {
3011
- return new Promise((resolve7) => {
3112
+ return new Promise((resolve8) => {
3012
3113
  const isWin = platform3() === "win32";
3013
3114
  const shell = isWin ? "cmd" : "sh";
3014
3115
  const shellFlag = isWin ? "/c" : "-c";
@@ -3022,16 +3123,16 @@ function runBuildCommand(cmd, cwd) {
3022
3123
  activeChild = null;
3023
3124
  if (code === 0) {
3024
3125
  consola.success("Build succeeded");
3025
- resolve7(true);
3126
+ resolve8(true);
3026
3127
  } else {
3027
3128
  consola.error(`Build failed with code ${code}`);
3028
- resolve7(false);
3129
+ resolve8(false);
3029
3130
  }
3030
3131
  });
3031
3132
  child.on("error", (err) => {
3032
3133
  activeChild = null;
3033
3134
  consola.error(`Build error: ${err.message}`);
3034
- resolve7(false);
3135
+ resolve8(false);
3035
3136
  });
3036
3137
  });
3037
3138
  }
@@ -3117,14 +3218,14 @@ var init_watch_orchestrator = __esm({
3117
3218
  },
3118
3219
  wrappedOnChange
3119
3220
  );
3120
- this.packages.set(name, { dir, state: "idle", watcher });
3221
+ this.packages.set(name, { dir, buildCmd, state: "idle", watcher });
3121
3222
  }
3122
3223
  consola.info(`Watching ${this.packages.size} workspace packages`);
3123
- await new Promise((resolve7) => {
3224
+ await new Promise((resolve8) => {
3124
3225
  const cleanup = async () => {
3125
3226
  consola.info("Stopping watchers...");
3126
3227
  await this.close();
3127
- resolve7();
3228
+ resolve8();
3128
3229
  };
3129
3230
  process.once("SIGINT", cleanup);
3130
3231
  process.once("SIGTERM", cleanup);
@@ -3155,11 +3256,9 @@ var init_watch_orchestrator = __esm({
3155
3256
  entry.state = "building";
3156
3257
  verbose(`[cascade] Rebuilding ${name}`);
3157
3258
  try {
3158
- const config = await loadKnarrConfig(entry.dir);
3159
- const buildCmd = config.buildCmd;
3160
- if (buildCmd) {
3259
+ if (entry.buildCmd) {
3161
3260
  const { runBuildCommand: runBuildCommand2 } = await Promise.resolve().then(() => (init_watcher(), watcher_exports));
3162
- const success = await runBuildCommand2(buildCmd, entry.dir);
3261
+ const success = await runBuildCommand2(entry.buildCmd, entry.dir);
3163
3262
  if (!success) {
3164
3263
  consola.warn(`[cascade] Build failed for ${name}, skipping dependents`);
3165
3264
  entry.state = "idle";
@@ -3256,7 +3355,7 @@ init_workspace();
3256
3355
  // src/utils/preflight.ts
3257
3356
  init_logger();
3258
3357
  import { readFile as readFile14, stat as stat9 } from "fs/promises";
3259
- import { join as join18, resolve as resolve6 } from "path";
3358
+ import { join as join18, resolve as resolve7 } from "path";
3260
3359
  async function runPreflightChecks(packageDir) {
3261
3360
  const issues = [];
3262
3361
  let pkgContent;
@@ -3326,7 +3425,7 @@ async function fileExists(filePath) {
3326
3425
  }
3327
3426
  }
3328
3427
  async function checkPath(packageDir, filePath, field, issues) {
3329
- const resolved = resolve6(packageDir, filePath);
3428
+ const resolved = resolve7(packageDir, filePath);
3330
3429
  if (!await fileExists(resolved)) {
3331
3430
  issues.push({
3332
3431
  code: "MISSING_PATH",
@@ -3339,7 +3438,7 @@ async function checkExports(packageDir, exports, issues) {
3339
3438
  for (const [key, value] of Object.entries(exports)) {
3340
3439
  if (typeof value === "string") {
3341
3440
  if (value.startsWith(".")) {
3342
- const resolved = resolve6(packageDir, value);
3441
+ const resolved = resolve7(packageDir, value);
3343
3442
  if (!await fileExists(resolved)) {
3344
3443
  issues.push({
3345
3444
  code: "EXPORTS_PATH_MISSING",
@@ -3380,7 +3479,7 @@ async function checkExportsConditions(packageDir, exportKey, conditions, issues)
3380
3479
  }
3381
3480
  for (const [condition, value] of Object.entries(conditions)) {
3382
3481
  if (typeof value === "string" && value.startsWith(".")) {
3383
- const resolved = resolve6(packageDir, value);
3482
+ const resolved = resolve7(packageDir, value);
3384
3483
  if (!await fileExists(resolved)) {
3385
3484
  issues.push({
3386
3485
  code: "EXPORTS_PATH_MISSING",