@penvhq/cli 0.9.2 → 0.9.4

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/bin.cjs CHANGED
@@ -47720,8 +47720,8 @@ var META_FORMATS = ["json", "toml", "yml"];
47720
47720
  function assertNever2(value2, context) {
47721
47721
  throw new Error(`Unhandled ${context}: ${JSON.stringify(value2)}`);
47722
47722
  }
47723
- function own(record2, key) {
47724
- return record2 !== void 0 && Object.hasOwn(record2, key) ? record2[key] : void 0;
47723
+ function own(record3, key) {
47724
+ return record3 !== void 0 && Object.hasOwn(record3, key) ? record3[key] : void 0;
47725
47725
  }
47726
47726
  function retainsPrevious(provider) {
47727
47727
  return typeof provider.readPrevious === "function";
@@ -50275,15 +50275,15 @@ function caseInsensitiveNames() {
50275
50275
  return process.platform === "win32";
50276
50276
  }
50277
50277
  function childRecord(host) {
50278
- const record2 = { ...host };
50278
+ const record3 = { ...host };
50279
50279
  if (!caseInsensitiveNames()) {
50280
- return record2;
50280
+ return record3;
50281
50281
  }
50282
50282
  const spelling = (name) => {
50283
50283
  const upper = name.toUpperCase();
50284
- return Object.keys(record2).find((key) => key.toUpperCase() === upper);
50284
+ return Object.keys(record3).find((key) => key.toUpperCase() === upper);
50285
50285
  };
50286
- return new Proxy(record2, {
50286
+ return new Proxy(record3, {
50287
50287
  get: (target, property) => typeof property === "string" ? target[spelling(property) ?? property] : Reflect.get(target, property),
50288
50288
  set(target, property, value2) {
50289
50289
  if (typeof property !== "string") {
@@ -50437,7 +50437,7 @@ var startChild = (invocation) => {
50437
50437
  const ended = new Promise((resolve12, reject) => {
50438
50438
  child.on("error", (cause) => {
50439
50439
  release();
50440
- reject(cannotStart(executable, cause));
50440
+ reject(cannotStart(executable, cause, invocation.purpose));
50441
50441
  });
50442
50442
  child.on("exit", (code, signal) => {
50443
50443
  release();
@@ -50458,8 +50458,15 @@ function noCommand() {
50458
50458
  "Put the command after `--`, e.g. `penv run -- pnpm dev`."
50459
50459
  );
50460
50460
  }
50461
- function cannotStart(executable, cause) {
50461
+ function cannotStart(executable, cause, purpose) {
50462
50462
  const detail = cause instanceof Error ? cause.message : String(cause);
50463
+ if (purpose !== void 0) {
50464
+ return new PenvError(
50465
+ "PENV_COMMAND_NOT_STARTED",
50466
+ `penv could not start \`${executable}\` to ${purpose}: ${detail}`,
50467
+ `Check that \`${executable}\` runs on its own \u2014 penv starts it the way your shell does, so it has to be on PATH. Nothing was changed.`
50468
+ );
50469
+ }
50463
50470
  return new PenvError(
50464
50471
  "RUN_COMMAND_NOT_STARTED",
50465
50472
  `\`${executable}\` could not be started: ${detail}`,
@@ -50488,12 +50495,15 @@ function cmdCommandLine(resolved, args) {
50488
50495
  " "
50489
50496
  );
50490
50497
  }
50491
- function extensions(env) {
50498
+ function extensions(env, platform) {
50499
+ if (platform !== "win32") {
50500
+ return [""];
50501
+ }
50492
50502
  const declared = env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD";
50493
- return ["", ...declared.split(";").filter((extension) => extension.length > 0)];
50503
+ return [...declared.split(";").filter((extension) => extension.length > 0), ""];
50494
50504
  }
50495
- function findExecutable(executable, env) {
50496
- const candidates = extensions(env);
50505
+ function findExecutable(executable, env, platform = process.platform) {
50506
+ const candidates = extensions(env, platform);
50497
50507
  const isFile = (path2) => (0, import_node_fs.existsSync)(path2) && (0, import_node_fs.statSync)(path2).isFile();
50498
50508
  if (executable.includes("/") || executable.includes("\\") || (0, import_node_path.isAbsolute)(executable)) {
50499
50509
  return candidates.map((extension) => executable + extension).find(isFile);
@@ -50519,6 +50529,7 @@ function escapeArgument(argument, doubleEscape) {
50519
50529
 
50520
50530
  // src/install.ts
50521
50531
  var RUNTIME_PACKAGE = "@penvhq/penv";
50532
+ var SCHEMA_PACKAGE = "zod";
50522
50533
  var LOCKFILES = [
50523
50534
  ["pnpm", "pnpm-lock.yaml"],
50524
50535
  ["yarn", "yarn.lock"],
@@ -50533,13 +50544,9 @@ var ADD = {
50533
50544
  bun: ["bun", "add", "--exact"]
50534
50545
  };
50535
50546
  function engineVersion() {
50536
- const manifest = new URL("../package.json", importMetaUrl);
50537
- try {
50538
- const version2 = JSON.parse((0, import_node_fs2.readFileSync)(manifest, "utf8")).version;
50539
- if (typeof version2 === "string" && version2.length > 0) {
50540
- return version2;
50541
- }
50542
- } catch {
50547
+ const version2 = ownManifest()?.version;
50548
+ if (typeof version2 === "string" && version2.length > 0) {
50549
+ return version2;
50543
50550
  }
50544
50551
  throw new PenvError(
50545
50552
  "ENGINE_VERSION_UNREADABLE",
@@ -50547,6 +50554,29 @@ function engineVersion() {
50547
50554
  `Reinstall penv, then run \`penv init\` again.`
50548
50555
  );
50549
50556
  }
50557
+ function schemaPackageVersion() {
50558
+ const peers = ownManifest()?.peerDependencies;
50559
+ const declared = peers !== null && typeof peers === "object" && !Array.isArray(peers) ? peers[SCHEMA_PACKAGE] : void 0;
50560
+ const floor = typeof declared === "string" ? declared.replace(/^[\^~>=\s]+/, "").trim() : "";
50561
+ if (floor.length > 0) {
50562
+ return floor;
50563
+ }
50564
+ throw new PenvError(
50565
+ "ENGINE_PEER_UNREADABLE",
50566
+ `penv could not read its own \`${SCHEMA_PACKAGE}\` peer range, so it cannot say which ${SCHEMA_PACKAGE} this project needs`,
50567
+ `Reinstall penv, then run \`penv init\` again.`
50568
+ );
50569
+ }
50570
+ function ownManifest() {
50571
+ try {
50572
+ const parsed = JSON.parse(
50573
+ (0, import_node_fs2.readFileSync)(new URL("../package.json", importMetaUrl), "utf8")
50574
+ );
50575
+ return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
50576
+ } catch {
50577
+ return void 0;
50578
+ }
50579
+ }
50550
50580
  function detectPackageManager(root) {
50551
50581
  for (const [manager, lockfile] of LOCKFILES) {
50552
50582
  if ((0, import_node_fs2.existsSync)((0, import_node_path2.join)(root, lockfile))) {
@@ -50575,12 +50605,12 @@ function manifestOf(root) {
50575
50605
  return void 0;
50576
50606
  }
50577
50607
  }
50578
- function declaredVersion(root) {
50608
+ function declaredVersion(root, name) {
50579
50609
  const manifest = manifestOf(root);
50580
50610
  for (const field of ["dependencies", "devDependencies"]) {
50581
50611
  const block = manifest?.[field];
50582
50612
  if (block !== null && typeof block === "object" && !Array.isArray(block)) {
50583
- const version2 = block[RUNTIME_PACKAGE];
50613
+ const version2 = block[name];
50584
50614
  if (typeof version2 === "string") {
50585
50615
  return version2;
50586
50616
  }
@@ -50593,27 +50623,61 @@ function planInstall(root, version2 = engineVersion()) {
50593
50623
  const lockfile = LOCKFILES.find(
50594
50624
  ([name, file2]) => name === manager && (0, import_node_fs2.existsSync)((0, import_node_path2.join)(root, file2))
50595
50625
  )?.[1];
50596
- const declared = declaredVersion(root);
50626
+ const runtimeDeclared = declaredVersion(root, RUNTIME_PACKAGE);
50627
+ const zodDeclared = declaredVersion(root, SCHEMA_PACKAGE);
50628
+ const packages = [
50629
+ {
50630
+ name: RUNTIME_PACKAGE,
50631
+ version: version2,
50632
+ ...runtimeDeclared === void 0 ? {} : { declared: runtimeDeclared },
50633
+ satisfied: runtimeDeclared === version2
50634
+ },
50635
+ {
50636
+ name: SCHEMA_PACKAGE,
50637
+ version: schemaPackageVersion(),
50638
+ ...zodDeclared === void 0 ? {} : { declared: zodDeclared },
50639
+ // Any declared zod counts: which zod a project uses is the project's
50640
+ // decision, and penv is here to make sure there is one, not to move it.
50641
+ satisfied: zodDeclared !== void 0
50642
+ }
50643
+ ];
50644
+ const pending = packages.filter((entry) => !entry.satisfied);
50645
+ const specs = (pending.length === 0 ? packages : pending).map(
50646
+ (entry) => `${entry.name}@${entry.version}`
50647
+ );
50597
50648
  return {
50598
50649
  root,
50599
50650
  manager,
50600
- package: RUNTIME_PACKAGE,
50601
- version: version2,
50602
- command: [...ADD[manager], `${RUNTIME_PACKAGE}@${version2}`],
50651
+ packages,
50652
+ command: [...ADD[manager], ...specs],
50603
50653
  ...lockfile === void 0 ? {} : { lockfile },
50604
- ...declared === void 0 ? {} : { declared },
50605
- satisfied: declared === version2
50654
+ satisfied: pending.length === 0
50606
50655
  };
50607
50656
  }
50657
+ function describe4(entry) {
50658
+ return `${entry.name} ${entry.version}`;
50659
+ }
50608
50660
  function renderInstallPlan(plan2) {
50609
50661
  if (plan2.satisfied) {
50610
- return [`package.json already pins ${plan2.package} ${plan2.version} \u2014 nothing to install.`];
50662
+ return [
50663
+ `package.json already has ${plan2.packages.map(describe4).join(" and ")} \u2014 nothing to install.`
50664
+ ];
50611
50665
  }
50612
- const line = `"${plan2.package}": "${plan2.version}"`;
50666
+ const pending = plan2.packages.filter((entry) => !entry.satisfied);
50667
+ const added = pending.filter((entry) => entry.declared === void 0);
50668
+ const replaced = pending.filter((entry) => entry.declared !== void 0);
50613
50669
  return [
50614
50670
  "package.json",
50615
- ...plan2.declared === void 0 ? [' + "dependencies": {', ` + ${line}`, " + }"] : [` - "${plan2.package}": "${plan2.declared}"`, ` + ${line}`],
50616
- ...plan2.lockfile === void 0 ? [] : [plan2.lockfile, ` + ${plan2.package}@${plan2.version}`],
50671
+ ...added.length === 0 ? [] : [
50672
+ ' + "dependencies": {',
50673
+ ...added.map((entry) => ` + "${entry.name}": "${entry.version}"`),
50674
+ " + }"
50675
+ ],
50676
+ ...replaced.flatMap((entry) => [
50677
+ ` - "${entry.name}": "${entry.declared}"`,
50678
+ ` + "${entry.name}": "${entry.version}"`
50679
+ ]),
50680
+ ...plan2.lockfile === void 0 ? [] : [plan2.lockfile, ...pending.map((entry) => ` + ${entry.name}@${entry.version}`)],
50617
50681
  "",
50618
50682
  `Run with: ${plan2.command.join(" ")}`
50619
50683
  ];
@@ -50622,7 +50686,8 @@ var installWithPackageManager = async (plan2) => {
50622
50686
  const child = startChild({
50623
50687
  command: plan2.command,
50624
50688
  env: process.env,
50625
- cwd: plan2.root
50689
+ cwd: plan2.root,
50690
+ purpose: `install ${plan2.packages.map(describe4).join(" and ")}`
50626
50691
  });
50627
50692
  const ended = await child.ended;
50628
50693
  if (ended.exitCode !== 0 || ended.signal !== null) {
@@ -52572,20 +52637,20 @@ function readCutover(root) {
52572
52637
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
52573
52638
  throw unreadable("it is not an object");
52574
52639
  }
52575
- const record2 = parsed;
52576
- if (record2.format !== CUTOVER_FORMAT) {
52640
+ const record3 = parsed;
52641
+ if (record3.format !== CUTOVER_FORMAT) {
52577
52642
  throw unreadable(
52578
- `it is format ${JSON.stringify(record2.format)}, and penv reads format ${CUTOVER_FORMAT}`
52643
+ `it is format ${JSON.stringify(record3.format)}, and penv reads format ${CUTOVER_FORMAT}`
52579
52644
  );
52580
52645
  }
52581
- const files = record2.files;
52646
+ const files = record3.files;
52582
52647
  if (!Array.isArray(files) || files.some((name) => typeof name !== "string")) {
52583
52648
  throw unreadable("it lists no filenames");
52584
52649
  }
52585
- const environments = Array.isArray(record2.environments) ? record2.environments.filter((name) => typeof name === "string") : [];
52650
+ const environments = Array.isArray(record3.environments) ? record3.environments.filter((name) => typeof name === "string") : [];
52586
52651
  return {
52587
52652
  format: CUTOVER_FORMAT,
52588
- movedAt: typeof record2.movedAt === "string" ? record2.movedAt : "",
52653
+ movedAt: typeof record3.movedAt === "string" ? record3.movedAt : "",
52589
52654
  files,
52590
52655
  environments
52591
52656
  };
@@ -54579,8 +54644,8 @@ var getCommand = defineCommand({
54579
54644
 
54580
54645
  // src/commands/import.ts
54581
54646
  init_cjs_shims();
54582
- var import_node_fs12 = require("fs");
54583
- var import_node_path13 = require("path");
54647
+ var import_node_fs13 = require("fs");
54648
+ var import_node_path14 = require("path");
54584
54649
 
54585
54650
  // src/adopt.ts
54586
54651
  init_cjs_shims();
@@ -54814,9 +54879,92 @@ function draftFieldsAcross(sources, environments) {
54814
54879
 
54815
54880
  // src/commands/init.ts
54816
54881
  init_cjs_shims();
54882
+ var import_node_fs12 = require("fs");
54883
+ var import_node_path13 = require("path");
54884
+ var import_promises = require("readline/promises");
54885
+
54886
+ // src/scaffold-undo.ts
54887
+ init_cjs_shims();
54817
54888
  var import_node_fs11 = require("fs");
54818
54889
  var import_node_path12 = require("path");
54819
- var import_promises = require("readline/promises");
54890
+ function record2(path, files, dirs) {
54891
+ let stats;
54892
+ try {
54893
+ stats = (0, import_node_fs11.statSync)(path);
54894
+ } catch {
54895
+ return;
54896
+ }
54897
+ if (stats.isDirectory()) {
54898
+ dirs.add(path);
54899
+ for (const entry of (0, import_node_fs11.readdirSync)(path)) {
54900
+ record2((0, import_node_path12.join)(path, entry), files, dirs);
54901
+ }
54902
+ return;
54903
+ }
54904
+ if (stats.isFile()) {
54905
+ files.set(path, (0, import_node_fs11.readFileSync)(path));
54906
+ }
54907
+ }
54908
+ function captureScaffold(root, paths) {
54909
+ const files = /* @__PURE__ */ new Map();
54910
+ const dirs = /* @__PURE__ */ new Set();
54911
+ for (const path of paths) {
54912
+ for (let dir = (0, import_node_path12.dirname)(path); dir.startsWith(root) && dir !== root; dir = (0, import_node_path12.dirname)(dir)) {
54913
+ if ((0, import_node_fs11.existsSync)(dir)) {
54914
+ dirs.add(dir);
54915
+ }
54916
+ }
54917
+ record2(path, files, dirs);
54918
+ }
54919
+ return { root, paths: [...paths], files, dirs };
54920
+ }
54921
+ function restoreScaffold(undo) {
54922
+ for (const path of undo.paths) {
54923
+ removeAdded(path, undo);
54924
+ }
54925
+ for (const path of undo.paths) {
54926
+ pruneAncestors(path, undo);
54927
+ }
54928
+ for (const [file2, contents] of undo.files) {
54929
+ (0, import_node_fs11.mkdirSync)((0, import_node_path12.dirname)(file2), { recursive: true });
54930
+ (0, import_node_fs11.writeFileSync)(file2, contents);
54931
+ }
54932
+ }
54933
+ function removeAdded(path, undo) {
54934
+ let stats;
54935
+ try {
54936
+ stats = (0, import_node_fs11.statSync)(path);
54937
+ } catch {
54938
+ return;
54939
+ }
54940
+ if (stats.isFile()) {
54941
+ if (!undo.files.has(path)) {
54942
+ (0, import_node_fs11.unlinkSync)(path);
54943
+ }
54944
+ return;
54945
+ }
54946
+ if (!stats.isDirectory()) {
54947
+ return;
54948
+ }
54949
+ for (const entry of (0, import_node_fs11.readdirSync)(path)) {
54950
+ removeAdded((0, import_node_path12.join)(path, entry), undo);
54951
+ }
54952
+ if (!undo.dirs.has(path) && (0, import_node_fs11.readdirSync)(path).length === 0) {
54953
+ (0, import_node_fs11.rmdirSync)(path);
54954
+ }
54955
+ }
54956
+ function pruneAncestors(path, undo) {
54957
+ for (let dir = (0, import_node_path12.dirname)(path); dir.startsWith(undo.root) && dir !== undo.root; dir = (0, import_node_path12.dirname)(dir)) {
54958
+ if (undo.dirs.has(dir)) {
54959
+ return;
54960
+ }
54961
+ try {
54962
+ (0, import_node_fs11.rmdirSync)(dir);
54963
+ } catch {
54964
+ return;
54965
+ }
54966
+ }
54967
+ }
54820
54968
 
54821
54969
  // src/seams.ts
54822
54970
  init_cjs_shims();
@@ -54974,7 +55122,7 @@ var NOT_ENVIRONMENTS2 = [...RESERVED_TOKENS, "example", "sample", "template"];
54974
55122
  function suggestEnvironments(root) {
54975
55123
  let entries;
54976
55124
  try {
54977
- entries = (0, import_node_fs11.readdirSync)(root);
55125
+ entries = (0, import_node_fs12.readdirSync)(root);
54978
55126
  } catch {
54979
55127
  return [];
54980
55128
  }
@@ -55018,8 +55166,8 @@ function configOf(decisions) {
55018
55166
  return { environments: decisions.environments, providers: {}, schemaFile: decisions.schemaFile };
55019
55167
  }
55020
55168
  function declaredIn(root) {
55021
- const file2 = (0, import_node_path12.join)(root, CONFIG_FILE);
55022
- if (!(0, import_node_fs11.existsSync)(file2)) {
55169
+ const file2 = (0, import_node_path13.join)(root, CONFIG_FILE);
55170
+ if (!(0, import_node_fs12.existsSync)(file2)) {
55023
55171
  return void 0;
55024
55172
  }
55025
55173
  return loadConfigFrom(file2);
@@ -55461,16 +55609,16 @@ function renderTsconfig(target, alias) {
55461
55609
  `;
55462
55610
  }
55463
55611
  function ensurePenvDir(root) {
55464
- const dir = (0, import_node_path12.resolve)(root, PENV_DIR);
55465
- if ((0, import_node_fs11.existsSync)(dir)) {
55612
+ const dir = (0, import_node_path13.resolve)(root, PENV_DIR);
55613
+ if ((0, import_node_fs12.existsSync)(dir)) {
55466
55614
  return { target: "penv-dir", action: "kept", text: `Found ${PENV_DIR}/` };
55467
55615
  }
55468
- (0, import_node_fs11.mkdirSync)(dir, { recursive: true });
55616
+ (0, import_node_fs12.mkdirSync)(dir, { recursive: true });
55469
55617
  return { target: "penv-dir", action: "created", text: `Created ${PENV_DIR}/` };
55470
55618
  }
55471
55619
  function writeSchemaShapeFile(root, fields, draft, decisions = DEFAULT_DECISIONS) {
55472
- const file2 = (0, import_node_path12.join)(root, SCHEMA_SHAPE_FILE);
55473
- if ((0, import_node_fs11.existsSync)(file2)) {
55620
+ const file2 = (0, import_node_path13.join)(root, SCHEMA_SHAPE_FILE);
55621
+ if ((0, import_node_fs12.existsSync)(file2)) {
55474
55622
  return {
55475
55623
  target: "schema",
55476
55624
  action: "kept",
@@ -55487,7 +55635,7 @@ function writeSchemaShapeFile(root, fields, draft, decisions = DEFAULT_DECISIONS
55487
55635
  note: `(the shape lives there, from before the ${SCHEMA_SHAPE_FILE} split \u2014 penv did not add a second one. To adopt the split: move the \`z.object\` (and any \`declare module\` block) into ${SCHEMA_SHAPE_FILE}, leaving ${oldLayout} importing \`schema\` from it and calling \`load\`.)`
55488
55636
  };
55489
55637
  }
55490
- (0, import_node_fs11.writeFileSync)(file2, renderSchemaShapeModule(fields, draft), "utf8");
55638
+ (0, import_node_fs12.writeFileSync)(file2, renderSchemaShapeModule(fields, draft), "utf8");
55491
55639
  return {
55492
55640
  target: "schema",
55493
55641
  action: "created",
@@ -55496,8 +55644,8 @@ function writeSchemaShapeFile(root, fields, draft, decisions = DEFAULT_DECISIONS
55496
55644
  };
55497
55645
  }
55498
55646
  function writeEnvFile(root, decisions = DEFAULT_DECISIONS) {
55499
- const file2 = (0, import_node_path12.join)(root, ...decisions.schemaFile.split("/"));
55500
- if ((0, import_node_fs11.existsSync)(file2)) {
55647
+ const file2 = (0, import_node_path13.join)(root, ...decisions.schemaFile.split("/"));
55648
+ if ((0, import_node_fs12.existsSync)(file2)) {
55501
55649
  return {
55502
55650
  target: "env",
55503
55651
  action: "kept",
@@ -55505,8 +55653,8 @@ function writeEnvFile(root, decisions = DEFAULT_DECISIONS) {
55505
55653
  note: "(yours \u2014 penv never regenerates it)"
55506
55654
  };
55507
55655
  }
55508
- (0, import_node_fs11.mkdirSync)((0, import_node_path12.dirname)(file2), { recursive: true });
55509
- (0, import_node_fs11.writeFileSync)(file2, renderEnvModule(decisions.schemaFile, decisions.inject), "utf8");
55656
+ (0, import_node_fs12.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55657
+ (0, import_node_fs12.writeFileSync)(file2, renderEnvModule(decisions.schemaFile, decisions.inject), "utf8");
55510
55658
  return {
55511
55659
  target: "env",
55512
55660
  action: "created",
@@ -55515,19 +55663,19 @@ function writeEnvFile(root, decisions = DEFAULT_DECISIONS) {
55515
55663
  };
55516
55664
  }
55517
55665
  function writeConfigFile(root, decisions = DEFAULT_DECISIONS) {
55518
- const file2 = (0, import_node_path12.join)(root, CONFIG_FILE);
55519
- if ((0, import_node_fs11.existsSync)(file2)) {
55666
+ const file2 = (0, import_node_path13.join)(root, CONFIG_FILE);
55667
+ if ((0, import_node_fs12.existsSync)(file2)) {
55520
55668
  return { target: "config", action: "kept", text: `Kept ${CONFIG_FILE}` };
55521
55669
  }
55522
- (0, import_node_fs11.writeFileSync)(file2, renderConfigModule(decisions), "utf8");
55670
+ (0, import_node_fs12.writeFileSync)(file2, renderConfigModule(decisions), "utf8");
55523
55671
  return { target: "config", action: "created", text: `Generated ${CONFIG_FILE}` };
55524
55672
  }
55525
55673
  function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
55526
55674
  const alias = decisions.alias;
55527
55675
  const imports = alias.startsWith(IMPORTS_PREFIX);
55528
- const file2 = (0, import_node_path12.join)(root, imports ? PACKAGE_FILE : TSCONFIG_FILE);
55676
+ const file2 = (0, import_node_path13.join)(root, imports ? PACKAGE_FILE : TSCONFIG_FILE);
55529
55677
  const where = imports ? PACKAGE_FILE : TSCONFIG_FILE;
55530
- if (!(0, import_node_fs11.existsSync)(file2)) {
55678
+ if (!(0, import_node_fs12.existsSync)(file2)) {
55531
55679
  if (imports) {
55532
55680
  return {
55533
55681
  target: "tsconfig",
@@ -55536,14 +55684,14 @@ function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
55536
55684
  note: `(run \`npm init\` first, or use \`--alias @env\` to alias through ${TSCONFIG_FILE})`
55537
55685
  };
55538
55686
  }
55539
- (0, import_node_fs11.writeFileSync)(file2, renderTsconfig(decisions.schemaFile, alias), "utf8");
55687
+ (0, import_node_fs12.writeFileSync)(file2, renderTsconfig(decisions.schemaFile, alias), "utf8");
55540
55688
  return {
55541
55689
  target: "tsconfig",
55542
55690
  action: "created",
55543
55691
  text: `Created ${TSCONFIG_FILE} with the ${alias} path alias`
55544
55692
  };
55545
55693
  }
55546
- const source = (0, import_node_fs11.readFileSync)(file2, "utf8");
55694
+ const source = (0, import_node_fs12.readFileSync)(file2, "utf8");
55547
55695
  const edit = imports ? insertImportsAlias(source, decisions.schemaFile, alias) : insertEnvAlias(source, decisions.schemaFile, alias);
55548
55696
  if (edit.conflict !== void 0) {
55549
55697
  return {
@@ -55560,7 +55708,7 @@ function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
55560
55708
  text: `Kept the ${alias} alias in ${where}`
55561
55709
  };
55562
55710
  }
55563
- (0, import_node_fs11.writeFileSync)(file2, edit.source, "utf8");
55711
+ (0, import_node_fs12.writeFileSync)(file2, edit.source, "utf8");
55564
55712
  return {
55565
55713
  target: "tsconfig",
55566
55714
  action: "updated",
@@ -55568,14 +55716,14 @@ function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
55568
55716
  };
55569
55717
  }
55570
55718
  function writeGitignore(root, decisions = DEFAULT_DECISIONS) {
55571
- const file2 = (0, import_node_path12.join)(root, ...STATE_GITIGNORE_PATH.split("/"));
55719
+ const file2 = (0, import_node_path13.join)(root, ...STATE_GITIGNORE_PATH.split("/"));
55572
55720
  const wanted = renderStateGitignore(configOf(decisions));
55573
- const existing = (0, import_node_fs11.existsSync)(file2) ? (0, import_node_fs11.readFileSync)(file2, "utf8") : void 0;
55721
+ const existing = (0, import_node_fs12.existsSync)(file2) ? (0, import_node_fs12.readFileSync)(file2, "utf8") : void 0;
55574
55722
  if (existing === wanted) {
55575
55723
  return { target: "gitignore", action: "kept", text: `Kept ${STATE_GITIGNORE_PATH}` };
55576
55724
  }
55577
- (0, import_node_fs11.mkdirSync)((0, import_node_path12.dirname)(file2), { recursive: true });
55578
- (0, import_node_fs11.writeFileSync)(file2, wanted, "utf8");
55725
+ (0, import_node_fs12.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55726
+ (0, import_node_fs12.writeFileSync)(file2, wanted, "utf8");
55579
55727
  return {
55580
55728
  target: "gitignore",
55581
55729
  action: existing === void 0 ? "created" : "updated",
@@ -55591,12 +55739,12 @@ function outdatedRuntimeWarning(root) {
55591
55739
  return `Injection needs @penvhq/penv ${INJECT_MIN_VERSION}+ \u2014 this project has ${version2}, whose \`load\` ignores \`{ inject: true }\`. Upgrade, or process.env stays empty.`;
55592
55740
  }
55593
55741
  function installedPenvVersion(root) {
55594
- const file2 = (0, import_node_path12.join)(root, "node_modules", "@penvhq", "penv", "package.json");
55595
- if (!(0, import_node_fs11.existsSync)(file2)) {
55742
+ const file2 = (0, import_node_path13.join)(root, "node_modules", "@penvhq", "penv", "package.json");
55743
+ if (!(0, import_node_fs12.existsSync)(file2)) {
55596
55744
  return void 0;
55597
55745
  }
55598
55746
  try {
55599
- const version2 = JSON.parse((0, import_node_fs11.readFileSync)(file2, "utf8")).version;
55747
+ const version2 = JSON.parse((0, import_node_fs12.readFileSync)(file2, "utf8")).version;
55600
55748
  return typeof version2 === "string" ? version2 : void 0;
55601
55749
  } catch {
55602
55750
  return void 0;
@@ -55636,11 +55784,11 @@ function writeSeam(root, decisions = DEFAULT_DECISIONS, framework = detectFramew
55636
55784
  };
55637
55785
  }
55638
55786
  const alsoNote = writeAlso(root, seam.also);
55639
- const file2 = (0, import_node_path12.join)(root, ...seam.file.split("/"));
55787
+ const file2 = (0, import_node_path13.join)(root, ...seam.file.split("/"));
55640
55788
  const baseNotes = [...seam.notes, ...alsoNote === void 0 ? [] : [alsoNote]];
55641
55789
  const notes = baseNotes.length === 0 ? "" : `
55642
55790
  ${baseNotes.map((n) => ` ${n}`).join("\n")}`;
55643
- if ((0, import_node_fs11.existsSync)(file2)) {
55791
+ if ((0, import_node_fs12.existsSync)(file2)) {
55644
55792
  return {
55645
55793
  target: "seam",
55646
55794
  action: "info",
@@ -55648,8 +55796,8 @@ ${baseNotes.map((n) => ` ${n}`).join("\n")}`;
55648
55796
  note: withWarning(`${seam.ifPresent}${notes}`, outdated)
55649
55797
  };
55650
55798
  }
55651
- (0, import_node_fs11.mkdirSync)((0, import_node_path12.dirname)(file2), { recursive: true });
55652
- (0, import_node_fs11.writeFileSync)(file2, seam.content, "utf8");
55799
+ (0, import_node_fs12.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55800
+ (0, import_node_fs12.writeFileSync)(file2, seam.content, "utf8");
55653
55801
  return {
55654
55802
  target: "seam",
55655
55803
  action: outdated === void 0 ? "created" : "info",
@@ -55661,12 +55809,12 @@ function writeAlso(root, also) {
55661
55809
  if (also === void 0) {
55662
55810
  return void 0;
55663
55811
  }
55664
- const file2 = (0, import_node_path12.join)(root, ...also.file.split("/"));
55665
- if ((0, import_node_fs11.existsSync)(file2)) {
55812
+ const file2 = (0, import_node_path13.join)(root, ...also.file.split("/"));
55813
+ if ((0, import_node_fs12.existsSync)(file2)) {
55666
55814
  return also.ifPresent;
55667
55815
  }
55668
- (0, import_node_fs11.mkdirSync)((0, import_node_path12.dirname)(file2), { recursive: true });
55669
- (0, import_node_fs11.writeFileSync)(file2, also.content, "utf8");
55816
+ (0, import_node_fs12.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55817
+ (0, import_node_fs12.writeFileSync)(file2, also.content, "utf8");
55670
55818
  return `Wrote ${also.file} to register it.`;
55671
55819
  }
55672
55820
  function withWarning(note, warning) {
@@ -55691,6 +55839,23 @@ function scaffold(root, fields, draft, decisions = DEFAULT_DECISIONS, framework
55691
55839
  const seam = writeSeam(root, decisions, framework);
55692
55840
  return seam === void 0 ? steps : [...steps, seam];
55693
55841
  }
55842
+ function scaffoldPaths(root, decisions = DEFAULT_DECISIONS, framework = detectFramework(root)?.name) {
55843
+ const fileAt = (relative5) => (0, import_node_path13.join)(root, ...relative5.split("/"));
55844
+ const seam = decisions.inject ? seamFor(framework, {
55845
+ alias: decisions.alias,
55846
+ srcDir: srcPrefix(root),
55847
+ schemaFile: decisions.schemaFile
55848
+ }) : void 0;
55849
+ return [
55850
+ fileAt(PENV_DIR),
55851
+ fileAt(SCHEMA_SHAPE_FILE),
55852
+ fileAt(decisions.schemaFile),
55853
+ fileAt(CONFIG_FILE),
55854
+ fileAt(TSCONFIG_FILE),
55855
+ fileAt(PACKAGE_FILE),
55856
+ ...seam?.kind === "scaffold" ? [fileAt(seam.file), ...seam.also === void 0 ? [] : [fileAt(seam.also.file)]] : []
55857
+ ];
55858
+ }
55694
55859
  var DEVELOPMENT = "development";
55695
55860
  var LOCAL_PROVIDER = "@penvhq/provider-filesystem";
55696
55861
  function planAdoption(root) {
@@ -55753,7 +55918,7 @@ function planCutover(input) {
55753
55918
  const diagnostics = [];
55754
55919
  let variables = 0;
55755
55920
  for (const file2 of selected) {
55756
- const parsed = parseDotenv((0, import_node_fs11.readFileSync)((0, import_node_path12.join)(root, file2.name), "utf8"));
55921
+ const parsed = parseDotenv((0, import_node_fs12.readFileSync)((0, import_node_path13.join)(root, file2.name), "utf8"));
55757
55922
  const fileRefs = refsForEntries(parsed.entries, file2.name, config2);
55758
55923
  adopted.push({ file: file2, entries: parsed.entries, refs: fileRefs, scope: scopeOf(file2) });
55759
55924
  refs.push(...fileRefs);
@@ -55864,17 +56029,27 @@ async function applyCutover(plan2, options = {}) {
55864
56029
  if (!plan2.install.satisfied) {
55865
56030
  await (options.install ?? installWithPackageManager)(plan2.install);
55866
56031
  }
55867
- const steps = scaffold(plan2.root, plan2.fields, true, plan2.decisions, plan2.framework);
55868
- const project = openProject(plan2.root);
55869
- const tree = localTree(project);
55870
- for (const adopted of plan2.adopted) {
55871
- writeEntries(tree, adopted.entries, adopted.refs, adopted.scope);
55872
- }
55873
- for (const environment of plan2.adopting) {
55874
- const check2 = await checkEnvironment(project, environment);
55875
- if (!check2.result.ok) {
55876
- throw invalidAfterImport(check2.result);
56032
+ const undo = captureScaffold(plan2.root, scaffoldPaths(plan2.root, plan2.decisions, plan2.framework));
56033
+ let steps;
56034
+ try {
56035
+ steps = scaffold(plan2.root, plan2.fields, true, plan2.decisions, plan2.framework);
56036
+ const project = openProject(plan2.root);
56037
+ const tree = localTree(project);
56038
+ for (const adopted of plan2.adopted) {
56039
+ writeEntries(tree, adopted.entries, adopted.refs, adopted.scope);
56040
+ }
56041
+ for (const environment of plan2.adopting) {
56042
+ const check2 = await checkEnvironment(project, environment);
56043
+ if (check2.schema === void 0) {
56044
+ throw draftNotLoaded(check2.result);
56045
+ }
56046
+ if (!check2.result.ok) {
56047
+ throw invalidAfterImport(check2.result);
56048
+ }
55877
56049
  }
56050
+ } catch (error51) {
56051
+ restoreScaffold(undo);
56052
+ throw error51;
55878
56053
  }
55879
56054
  const cutover = bundleDotenvFiles(
55880
56055
  plan2.root,
@@ -55883,13 +56058,24 @@ async function applyCutover(plan2, options = {}) {
55883
56058
  );
55884
56059
  return { plan: plan2, steps, moved: cutover.files, validated: plan2.adopting };
55885
56060
  }
56061
+ function issueLines(result2) {
56062
+ return result2.issues.map((issue2) => ` ${issue2.subject}: ${issue2.message}`).join("\n");
56063
+ }
56064
+ var SCAFFOLD_ROLLED_BACK = "penv put the project back as it found it \u2014 your dotenv files and everything else are exactly where they were.";
55886
56065
  function invalidAfterImport(result2) {
55887
- const lines = result2.issues.map((issue2) => ` ${issue2.subject}: ${issue2.message}`).join("\n");
55888
56066
  return new PenvError(
55889
56067
  "INIT_CUTOVER_INVALID",
55890
- `The imported values do not satisfy the draft schema for ${result2.environment}, so your dotenv files were left where they are:
55891
- ${lines}`,
55892
- `Correct ${SCHEMA_SHAPE_FILE} or the values above, then run \`penv init\` again.`
56068
+ `The imported values do not satisfy the draft schema for ${result2.environment}:
56069
+ ${issueLines(result2)}`,
56070
+ `Correct the values above, then run \`penv init\` again. ${SCAFFOLD_ROLLED_BACK}`
56071
+ );
56072
+ }
56073
+ function draftNotLoaded(result2) {
56074
+ return new PenvError(
56075
+ "INIT_DRAFT_NOT_LOADED",
56076
+ `penv could not load the schema it drafted for ${result2.environment}, so nothing was checked against it:
56077
+ ${issueLines(result2)}`,
56078
+ `Fix the error above, then run \`penv init\` again. ${SCAFFOLD_ROLLED_BACK}`
55893
56079
  );
55894
56080
  }
55895
56081
  function renderSelection(plan2, selected = plan2.preselected) {
@@ -55952,7 +56138,7 @@ function renderCutover(result2) {
55952
56138
  const glyph = step.action === "conflicted" ? WARN : step.action === "info" ? "\u2192" : CHECK;
55953
56139
  return step.note === void 0 ? { glyph, text: step.text } : { glyph, text: step.text, note: step.note };
55954
56140
  }),
55955
- ...plan2.install.satisfied ? [] : [{ glyph: CHECK, text: `Installed ${plan2.install.package}`, note: plan2.install.version }],
56141
+ ...plan2.install.packages.filter((entry) => !entry.satisfied).map((entry) => ({ glyph: CHECK, text: `Installed ${entry.name}`, note: entry.version })),
55956
56142
  {
55957
56143
  glyph: CHECK,
55958
56144
  text: `Imported ${plan2.fields.length} parameters`,
@@ -55976,12 +56162,12 @@ function dailyCommand(root) {
55976
56162
  return `penv run -- ${detectPackageManager(root)} ${devScript(root)}`;
55977
56163
  }
55978
56164
  function devScript(root) {
55979
- const file2 = (0, import_node_path12.join)(root, PACKAGE_FILE);
55980
- if (!(0, import_node_fs11.existsSync)(file2)) {
56165
+ const file2 = (0, import_node_path13.join)(root, PACKAGE_FILE);
56166
+ if (!(0, import_node_fs12.existsSync)(file2)) {
55981
56167
  return "dev";
55982
56168
  }
55983
56169
  try {
55984
- const scripts = JSON.parse((0, import_node_fs11.readFileSync)(file2, "utf8")).scripts;
56170
+ const scripts = JSON.parse((0, import_node_fs12.readFileSync)(file2, "utf8")).scripts;
55985
56171
  if (scripts !== null && typeof scripts === "object" && !Array.isArray(scripts)) {
55986
56172
  const named = Object.keys(scripts);
55987
56173
  return ["dev", "start"].find((script) => named.includes(script)) ?? named[0] ?? "dev";
@@ -55991,7 +56177,7 @@ function devScript(root) {
55991
56177
  return "dev";
55992
56178
  }
55993
56179
  function runInit(options) {
55994
- const root = (0, import_node_path12.resolve)(options.cwd);
56180
+ const root = (0, import_node_path13.resolve)(options.cwd);
55995
56181
  const decisions = options.decisions ?? planInit(root).decisions;
55996
56182
  return { root, decisions, steps: scaffold(root, [], false, decisions, options.framework) };
55997
56183
  }
@@ -56154,7 +56340,7 @@ var initCommand = defineCommand({
56154
56340
  },
56155
56341
  run({ args }) {
56156
56342
  return guard(async () => {
56157
- const root = (0, import_node_path12.resolve)(process.cwd());
56343
+ const root = (0, import_node_path13.resolve)(process.cwd());
56158
56344
  if (args.action !== void 0) {
56159
56345
  runUndoAction(root, String(args.action));
56160
56346
  return;
@@ -56230,7 +56416,7 @@ function assertDeclared(segment, config2) {
56230
56416
  throw new UnknownEnvironmentError(segment, config2.environments);
56231
56417
  }
56232
56418
  function scopeFromFilename(file2, config2) {
56233
- const name = (0, import_node_path13.basename)(file2);
56419
+ const name = (0, import_node_path14.basename)(file2);
56234
56420
  const segments = name.split(".");
56235
56421
  const start = segments.indexOf(DOTENV_SEGMENT);
56236
56422
  if (start === -1) {
@@ -56314,7 +56500,7 @@ function environmentNamed(file2, explicit) {
56314
56500
  if (explicit !== void 0 && explicit.trim().length > 0) {
56315
56501
  return explicit.trim();
56316
56502
  }
56317
- const segments = (0, import_node_path13.basename)(file2).split(".");
56503
+ const segments = (0, import_node_path14.basename)(file2).split(".");
56318
56504
  const start = segments.indexOf(DOTENV_SEGMENT);
56319
56505
  if (start === -1) {
56320
56506
  return void 0;
@@ -56348,16 +56534,16 @@ function configInEffect(cwd, environment) {
56348
56534
  return { config: openProject(cwd).config, decisions };
56349
56535
  }
56350
56536
  function importDotenv(options) {
56351
- const cwd = (0, import_node_path13.resolve)(options.cwd);
56352
- const file2 = (0, import_node_path13.isAbsolute)(options.file) ? options.file : (0, import_node_path13.resolve)(cwd, options.file);
56353
- if (!(0, import_node_fs12.existsSync)(file2)) {
56537
+ const cwd = (0, import_node_path14.resolve)(options.cwd);
56538
+ const file2 = (0, import_node_path14.isAbsolute)(options.file) ? options.file : (0, import_node_path14.resolve)(cwd, options.file);
56539
+ if (!(0, import_node_fs13.existsSync)(file2)) {
56354
56540
  throw new PenvError(
56355
56541
  "IMPORT_FILE_MISSING",
56356
56542
  `There is no file at ${file2} to import`,
56357
56543
  "Point `penv import` at an existing dotenv file, e.g. `penv import .env`."
56358
56544
  );
56359
56545
  }
56360
- const parsed = parseDotenv((0, import_node_fs12.readFileSync)(file2, "utf8"));
56546
+ const parsed = parseDotenv((0, import_node_fs13.readFileSync)(file2, "utf8"));
56361
56547
  const { config: config2, decisions } = configInEffect(cwd, environmentNamed(file2, options.environment));
56362
56548
  const source = displayPath3(cwd, file2);
56363
56549
  const named = scopeFromFilename(file2, config2);
@@ -56373,7 +56559,7 @@ function importDotenv(options) {
56373
56559
  const tree = localTree(project);
56374
56560
  writeEntries(tree, parsed.entries, refs, scope);
56375
56561
  const backup = `${file2}${BACKUP_SUFFIX}`;
56376
- (0, import_node_fs12.copyFileSync)(file2, backup);
56562
+ (0, import_node_fs13.copyFileSync)(file2, backup);
56377
56563
  return {
56378
56564
  root: project.root,
56379
56565
  file: file2,
@@ -56387,7 +56573,7 @@ function importDotenv(options) {
56387
56573
  };
56388
56574
  }
56389
56575
  function displayPath3(root, file2) {
56390
- const rel = (0, import_node_path13.relative)(root, file2);
56576
+ const rel = (0, import_node_path14.relative)(root, file2);
56391
56577
  return rel === "" || rel.startsWith("..") ? file2 : rel.split("\\").join("/");
56392
56578
  }
56393
56579
  function keptSchemaStep(step, variables) {
@@ -56706,28 +56892,28 @@ var listCommand = defineCommand({
56706
56892
 
56707
56893
  // src/commands/migrate.ts
56708
56894
  init_cjs_shims();
56709
- var import_node_fs13 = require("fs");
56710
- var import_node_path14 = require("path");
56895
+ var import_node_fs14 = require("fs");
56896
+ var import_node_path15 = require("path");
56711
56897
  var import_promises2 = require("readline/promises");
56712
56898
  var OLD_GITIGNORE = `${PENV_DIR}/.gitignore`;
56713
56899
  function planMigrate(cwd) {
56714
56900
  const { config: config2, file: file2 } = loadConfig(cwd);
56715
- const root = (0, import_node_path14.dirname)(file2);
56901
+ const root = (0, import_node_path15.dirname)(file2);
56716
56902
  const entries = oldLayoutEntries(root, config2);
56717
56903
  const tree = recordsDir(root);
56718
56904
  const collisions = collidingEntries(entries, tree);
56719
56905
  if (collisions.length > 0) {
56720
56906
  throw new PenvError(
56721
56907
  "HALF_MIGRATED",
56722
- `${describe4(collisions)} in both \`${PENV_DIR}/\` and \`${RECORDS_PATH2}/\`, and penv cannot tell which copy is current`,
56908
+ `${describe5(collisions)} in both \`${PENV_DIR}/\` and \`${RECORDS_PATH2}/\`, and penv cannot tell which copy is current`,
56723
56909
  `Move what is left under \`${PENV_DIR}/\` into \`${RECORDS_PATH2}/\` yourself, keeping the copy you want, then run \`penv validate\`.`
56724
56910
  );
56725
56911
  }
56726
56912
  const creates = [];
56727
- if (entries.length > 0 && !(0, import_node_fs13.existsSync)(tree)) {
56913
+ if (entries.length > 0 && !(0, import_node_fs14.existsSync)(tree)) {
56728
56914
  creates.push(`${RECORDS_PATH2}/`);
56729
56915
  }
56730
- if (readIfPresent((0, import_node_path14.join)(root, ...STATE_GITIGNORE_PATH.split("/"))) !== renderStateGitignore(config2)) {
56916
+ if (readIfPresent((0, import_node_path15.join)(root, ...STATE_GITIGNORE_PATH.split("/"))) !== renderStateGitignore(config2)) {
56731
56917
  creates.push(STATE_GITIGNORE_PATH);
56732
56918
  }
56733
56919
  return {
@@ -56737,23 +56923,23 @@ function planMigrate(cwd) {
56737
56923
  to: `${RECORDS_PATH2}/${entry}`
56738
56924
  })),
56739
56925
  creates,
56740
- removes: (0, import_node_fs13.existsSync)((0, import_node_path14.join)(root, ...OLD_GITIGNORE.split("/"))) ? [OLD_GITIGNORE] : []
56926
+ removes: (0, import_node_fs14.existsSync)((0, import_node_path15.join)(root, ...OLD_GITIGNORE.split("/"))) ? [OLD_GITIGNORE] : []
56741
56927
  };
56742
56928
  }
56743
56929
  function readIfPresent(file2) {
56744
- return (0, import_node_fs13.existsSync)(file2) ? (0, import_node_fs13.readFileSync)(file2, "utf8") : void 0;
56930
+ return (0, import_node_fs14.existsSync)(file2) ? (0, import_node_fs14.readFileSync)(file2, "utf8") : void 0;
56745
56931
  }
56746
56932
  function collidingEntries(entries, tree) {
56747
56933
  let held;
56748
56934
  try {
56749
- held = (0, import_node_fs13.readdirSync)(tree);
56935
+ held = (0, import_node_fs14.readdirSync)(tree);
56750
56936
  } catch {
56751
56937
  return [];
56752
56938
  }
56753
56939
  const taken = new Set(held.map((name) => name.toLowerCase()));
56754
56940
  return entries.filter((entry) => taken.has(entry.toLowerCase())).sort();
56755
56941
  }
56756
- function describe4(names) {
56942
+ function describe5(names) {
56757
56943
  return names.length === 1 ? `\`${names[0]}\` is` : `${names.map((name) => `\`${name}\``).join(", ")} are`;
56758
56944
  }
56759
56945
  function isNoop(plan2) {
@@ -56765,18 +56951,18 @@ function applyMigrate(plan2) {
56765
56951
  }
56766
56952
  const { config: config2 } = loadConfig(plan2.root);
56767
56953
  if (plan2.moves.length > 0) {
56768
- (0, import_node_fs13.mkdirSync)(recordsDir(plan2.root), { recursive: true });
56954
+ (0, import_node_fs14.mkdirSync)(recordsDir(plan2.root), { recursive: true });
56769
56955
  for (const move of plan2.moves) {
56770
- (0, import_node_fs13.renameSync)((0, import_node_path14.join)(plan2.root, ...move.from.split("/")), (0, import_node_path14.join)(plan2.root, ...move.to.split("/")));
56956
+ (0, import_node_fs14.renameSync)((0, import_node_path15.join)(plan2.root, ...move.from.split("/")), (0, import_node_path15.join)(plan2.root, ...move.to.split("/")));
56771
56957
  }
56772
56958
  }
56773
56959
  if (plan2.creates.includes(STATE_GITIGNORE_PATH)) {
56774
- const ignore = (0, import_node_path14.join)(plan2.root, ...STATE_GITIGNORE_PATH.split("/"));
56775
- (0, import_node_fs13.mkdirSync)((0, import_node_path14.dirname)(ignore), { recursive: true });
56776
- (0, import_node_fs13.writeFileSync)(ignore, renderStateGitignore(config2), "utf8");
56960
+ const ignore = (0, import_node_path15.join)(plan2.root, ...STATE_GITIGNORE_PATH.split("/"));
56961
+ (0, import_node_fs14.mkdirSync)((0, import_node_path15.dirname)(ignore), { recursive: true });
56962
+ (0, import_node_fs14.writeFileSync)(ignore, renderStateGitignore(config2), "utf8");
56777
56963
  }
56778
56964
  for (const removed of plan2.removes) {
56779
- (0, import_node_fs13.rmSync)((0, import_node_path14.join)(plan2.root, ...removed.split("/")), { force: true });
56965
+ (0, import_node_fs14.rmSync)((0, import_node_path15.join)(plan2.root, ...removed.split("/")), { force: true });
56780
56966
  }
56781
56967
  return { ...plan2, status: "migrated" };
56782
56968
  }
@@ -57253,12 +57439,12 @@ var rotateCommand = defineCommand({
57253
57439
 
57254
57440
  // src/commands/watch.ts
57255
57441
  init_cjs_shims();
57256
- var import_node_fs14 = require("fs");
57257
- var import_node_path15 = require("path");
57442
+ var import_node_fs15 = require("fs");
57443
+ var import_node_path16 = require("path");
57258
57444
  var DEBOUNCE_MS2 = 100;
57259
57445
  function runWatch(options) {
57260
57446
  const project = openProject(options.cwd);
57261
- const configFile = (0, import_node_path15.basename)(project.configFile);
57447
+ const configFile = (0, import_node_path16.basename)(project.configFile);
57262
57448
  const debounceMs = options.debounceMs ?? DEBOUNCE_MS2;
57263
57449
  const watchers = /* @__PURE__ */ new Set();
57264
57450
  let timer;
@@ -57311,22 +57497,22 @@ function runWatch(options) {
57311
57497
  watcher.close();
57312
57498
  }
57313
57499
  function armRecovery(target, recursive, only) {
57314
- const parent = (0, import_node_path15.dirname)(target);
57315
- const name = (0, import_node_path15.basename)(target);
57500
+ const parent = (0, import_node_path16.dirname)(target);
57501
+ const name = (0, import_node_path16.basename)(target);
57316
57502
  let recovery;
57317
57503
  try {
57318
- recovery = (0, import_node_fs14.watch)(parent, { recursive: false }, (_event, filename) => {
57504
+ recovery = (0, import_node_fs15.watch)(parent, { recursive: false }, (_event, filename) => {
57319
57505
  if (closed || recovery === void 0) {
57320
57506
  return;
57321
57507
  }
57322
- if (!(0, import_node_fs14.existsSync)(parent)) {
57508
+ if (!(0, import_node_fs15.existsSync)(parent)) {
57323
57509
  stop2(recovery);
57324
57510
  return;
57325
57511
  }
57326
- if (filename !== null && (0, import_node_path15.basename)(filename) !== name) {
57512
+ if (filename !== null && (0, import_node_path16.basename)(filename) !== name) {
57327
57513
  return;
57328
57514
  }
57329
- if (!(0, import_node_fs14.existsSync)(target)) {
57515
+ if (!(0, import_node_fs15.existsSync)(target)) {
57330
57516
  return;
57331
57517
  }
57332
57518
  stop2(recovery);
@@ -57346,11 +57532,11 @@ function runWatch(options) {
57346
57532
  }
57347
57533
  function addWatcher(target, recursive, only) {
57348
57534
  let watcher;
57349
- const listen = (useRecursive) => (0, import_node_fs14.watch)(target, { recursive: useRecursive }, (_event, filename) => {
57535
+ const listen = (useRecursive) => (0, import_node_fs15.watch)(target, { recursive: useRecursive }, (_event, filename) => {
57350
57536
  if (closed) {
57351
57537
  return;
57352
57538
  }
57353
- if (!(0, import_node_fs14.existsSync)(target)) {
57539
+ if (!(0, import_node_fs15.existsSync)(target)) {
57354
57540
  if (watcher !== void 0) {
57355
57541
  stop2(watcher);
57356
57542
  }
@@ -57358,7 +57544,7 @@ function runWatch(options) {
57358
57544
  schedule();
57359
57545
  return;
57360
57546
  }
57361
- if (only !== void 0 && (filename === null || (0, import_node_path15.basename)(filename) !== only)) {
57547
+ if (only !== void 0 && (filename === null || (0, import_node_path16.basename)(filename) !== only)) {
57362
57548
  return;
57363
57549
  }
57364
57550
  schedule();
@@ -57385,11 +57571,11 @@ function runWatch(options) {
57385
57571
  watchers.add(watcher);
57386
57572
  }
57387
57573
  addWatcher(project.recordsDir, true);
57388
- addWatcher((0, import_node_path15.dirname)(project.configFile), false, configFile);
57574
+ addWatcher((0, import_node_path16.dirname)(project.configFile), false, configFile);
57389
57575
  addWatcher(project.root, false, SCHEMA_SHAPE_FILE);
57390
57576
  if (schemaInsideTree(project.config) === void 0) {
57391
- const schemaFile = (0, import_node_path15.resolve)(project.root, schemaFileOf(project.config));
57392
- addWatcher((0, import_node_path15.dirname)(schemaFile), false, (0, import_node_path15.basename)(schemaFile));
57577
+ const schemaFile = (0, import_node_path16.resolve)(project.root, schemaFileOf(project.config));
57578
+ addWatcher((0, import_node_path16.dirname)(schemaFile), false, (0, import_node_path16.basename)(schemaFile));
57393
57579
  }
57394
57580
  void validate();
57395
57581
  return {