@penvhq/cli 0.9.4 → 0.9.5

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
@@ -47374,17 +47374,55 @@ var import_url = require("url");
47374
47374
  var import_crypto2 = require("crypto");
47375
47375
  var import_fs2 = require("fs");
47376
47376
  var import_path2 = require("path");
47377
+ var REMEDY_ARROW = "\u2192";
47378
+ function framesOf(stack) {
47379
+ return (stack ?? "").split("\n").filter((line) => /^\s+at\s/.test(line));
47380
+ }
47381
+ function renderRefusal(error51) {
47382
+ const captured = error51.stack;
47383
+ Object.defineProperty(error51, "stack", {
47384
+ configurable: true,
47385
+ get: () => [error51.toString(), ...framesOf(captured)].join("\n"),
47386
+ set(value2) {
47387
+ Object.defineProperty(error51, "stack", { value: value2, writable: true, configurable: true });
47388
+ }
47389
+ });
47390
+ }
47377
47391
  var PenvError = class extends Error {
47378
47392
  name = "PenvError";
47379
47393
  /** A stable, machine-readable discriminator. */
47380
47394
  code;
47381
47395
  /** What the user should do about it. */
47382
47396
  remedy;
47397
+ /** The message alone, without the remedy the constructor folds into it. */
47398
+ summary;
47383
47399
  constructor(code, message, remedy) {
47384
47400
  super(remedy ? `${message}
47385
47401
  ${remedy}` : message);
47386
47402
  this.code = code;
47387
47403
  this.remedy = remedy;
47404
+ this.summary = message;
47405
+ renderRefusal(this);
47406
+ }
47407
+ /**
47408
+ * Drops every frame from `below` upward, so the stack shows where the
47409
+ * application called in rather than the path penv took inside itself. The
47410
+ * caller names its own entry point; nothing here guesses which files are
47411
+ * penv's.
47412
+ */
47413
+ hideFramesAbove(below) {
47414
+ const capture = Error.captureStackTrace;
47415
+ if (capture !== void 0) {
47416
+ capture(this, below);
47417
+ renderRefusal(this);
47418
+ }
47419
+ return this;
47420
+ }
47421
+ /** The refusal as every penv command prints it: the message, then the remedy. */
47422
+ toString() {
47423
+ const head = `${this.name}: ${this.summary}`;
47424
+ return this.remedy === void 0 ? head : `${head}
47425
+ ${REMEDY_ARROW} ${this.remedy}`;
47388
47426
  }
47389
47427
  };
47390
47428
  var FilenameGrammarError = class extends PenvError {
@@ -48912,6 +48950,7 @@ var RECORDS_PATH2 = `${STATE_PATH}/records`;
48912
48950
  var STATE_GITIGNORE_PATH = `${STATE_PATH}/.gitignore`;
48913
48951
  var MANIFEST_PATH = `${STATE_PATH}/manifest.json`;
48914
48952
  var EXTENSIONS_PATH = `${STATE_PATH}/extensions`;
48953
+ var LOCAL_EXTENSIONS_PATH = `${STATE_PATH}/local-extensions.json`;
48915
48954
  var CUTOVER_FILE = "cutover.json";
48916
48955
  var ROLLBACK_DIR = "rollback";
48917
48956
  var CUTOVER_PATH = `${STATE_PATH}/${CUTOVER_FILE}`;
@@ -48920,6 +48959,9 @@ var ROLLBACK_DOTENV_PATH = `${ROLLBACK_PATH}/dotenv`;
48920
48959
  function penvDir(projectRoot) {
48921
48960
  return (0, import_path2.resolve)(projectRoot, PENV_DIR);
48922
48961
  }
48962
+ function localExtensionsFile(projectRoot) {
48963
+ return (0, import_path2.resolve)(projectRoot, ...LOCAL_EXTENSIONS_PATH.split("/"));
48964
+ }
48923
48965
  function recordsDir(projectRoot) {
48924
48966
  return (0, import_path2.resolve)(projectRoot, ...RECORDS_PATH2.split("/"));
48925
48967
  }
@@ -48964,6 +49006,33 @@ ${inside === void 0 ? "" : `!${inside}
48964
49006
  ${ROLLBACK_DIR}/
48965
49007
  `;
48966
49008
  }
49009
+ function invalid(problem) {
49010
+ return new PenvError(
49011
+ "LOCAL_EXTENSIONS_INVALID",
49012
+ `${LOCAL_EXTENSIONS_PATH} does not hold the list penv writes: ${problem}`,
49013
+ "It is a JSON array of package names. Delete it and run `penv add --local <package>` for each extension this project develops."
49014
+ );
49015
+ }
49016
+ function parseLocalExtensions(text) {
49017
+ let parsed;
49018
+ try {
49019
+ parsed = JSON.parse(text);
49020
+ } catch {
49021
+ throw invalid("it is not valid JSON");
49022
+ }
49023
+ if (!Array.isArray(parsed)) {
49024
+ throw invalid("its root is not an array");
49025
+ }
49026
+ for (const name of parsed) {
49027
+ if (typeof name !== "string" || name.trim() === "") {
49028
+ throw invalid("it holds something that is not a package name");
49029
+ }
49030
+ }
49031
+ return normalize(parsed);
49032
+ }
49033
+ function normalize(names) {
49034
+ return [...new Set(names.map((name) => name.trim()))].sort();
49035
+ }
48967
49036
  var MANIFEST_FORMAT = 1;
48968
49037
  var ENGINE_PACKAGE = "@penvhq/cli";
48969
49038
  var OFFICIAL_SCOPE = "@penvhq/";
@@ -49969,7 +50038,7 @@ function _getBuiltinFlags(long, short, userNames, userAliases) {
49969
50038
 
49970
50039
  // src/commands/artifact.ts
49971
50040
  init_cjs_shims();
49972
- var import_node_fs6 = require("fs");
50041
+ var import_node_fs7 = require("fs");
49973
50042
  var import_node_path7 = require("path");
49974
50043
 
49975
50044
  // ../runtime/dist/index.js
@@ -50139,11 +50208,13 @@ var RUN_MARKER = "PENV_RUN";
50139
50208
  var ENVIRONMENT_VARIABLE = "PENV_ENV";
50140
50209
  var DELIVERY_VARIABLE = "PENV_DELIVERY";
50141
50210
  var SNAPSHOT_VARIABLE = "PENV_SNAPSHOT";
50211
+ var LAUNCHER_HOME = "PENV_HOME";
50142
50212
  var CONTROL_VARIABLES = [
50143
50213
  RUN_MARKER,
50144
50214
  DELIVERY_VARIABLE,
50145
50215
  SCHEMA_HARVEST_ENV,
50146
- SNAPSHOT_VARIABLE
50216
+ SNAPSHOT_VARIABLE,
50217
+ LAUNCHER_HOME
50147
50218
  ];
50148
50219
  var RESERVED_VARIABLES = [...CONTROL_VARIABLES, ENVIRONMENT_VARIABLE];
50149
50220
  function assertDeliverableNames(refs, config2) {
@@ -50704,7 +50775,7 @@ function installFailed(plan2) {
50704
50775
 
50705
50776
  // src/project.ts
50706
50777
  init_cjs_shims();
50707
- var import_node_fs3 = require("fs");
50778
+ var import_node_fs4 = require("fs");
50708
50779
  var import_node_path4 = require("path");
50709
50780
 
50710
50781
  // src/env-flags.ts
@@ -50767,6 +50838,7 @@ function environmentFromShorthand(config2, candidates, explicit) {
50767
50838
 
50768
50839
  // src/registry.ts
50769
50840
  init_cjs_shims();
50841
+ var import_node_fs3 = require("fs");
50770
50842
  var import_node_module = require("module");
50771
50843
  var import_node_path3 = require("path");
50772
50844
  var import_node_url = require("url");
@@ -50954,16 +51026,40 @@ async function loadPluginProvider(type, context) {
50954
51026
  assertSatisfiesContract(provider, type);
50955
51027
  return provider;
50956
51028
  }
50957
- function assertProvidersRegistered(config2, projectRoot) {
51029
+ function assertProvidersRegistered(config2, projectRoot, options) {
51030
+ const local = localExtensions(projectRoot);
51031
+ const ci = options?.ci ?? isCi(process.env.CI);
50958
51032
  for (const [environment, provider] of Object.entries(config2.providers)) {
50959
51033
  if (isProviderRegistered(provider.type)) {
50960
51034
  continue;
50961
51035
  }
51036
+ if (ci && local.includes(provider.type)) {
51037
+ throw localExtensionInCi(provider.type, environment);
51038
+ }
50962
51039
  if (resolvePlugin(provider.type, projectRoot) === void 0) {
50963
51040
  throw unknownProvider(provider.type, environment);
50964
51041
  }
50965
51042
  }
50966
51043
  }
51044
+ function localExtensions(projectRoot) {
51045
+ let text;
51046
+ try {
51047
+ text = (0, import_node_fs3.readFileSync)(localExtensionsFile(projectRoot), "utf8");
51048
+ } catch {
51049
+ return [];
51050
+ }
51051
+ return parseLocalExtensions(text);
51052
+ }
51053
+ function isCi(value2) {
51054
+ return value2 !== void 0 && value2 !== "" && value2 !== "0" && value2.toLowerCase() !== "false";
51055
+ }
51056
+ function localExtensionInCi(type, environment) {
51057
+ return new PenvError(
51058
+ "LOCAL_EXTENSION_IN_CI",
51059
+ `The provider \`${type}\` for environment ${environment} is a local extension, and this is CI`,
51060
+ `${LOCAL_EXTENSIONS_PATH} records it as a package this project develops, so nothing pins the bytes CI would run. Publish it and run \`penv add ${type}\` to pin a release.`
51061
+ );
51062
+ }
50967
51063
  function resolvePlugin(specifier, fromDir) {
50968
51064
  try {
50969
51065
  const require2 = (0, import_node_module.createRequire)((0, import_node_path3.resolve)(fromDir, "noop.js"));
@@ -51001,7 +51097,7 @@ function unknownProvider(type, environment) {
51001
51097
  return new PenvError(
51002
51098
  "UNKNOWN_PROVIDER",
51003
51099
  `The provider \`${type}\`${where} in penv.config.ts is not installed in this project`,
51004
- `Install it with \`npm i ${type}\` \u2014 a provider's \`type\` is the package penv imports. The CLI ships ${preinstalled} pre-installed.`
51100
+ `A provider's \`type\` is the package penv imports, so it has to resolve from this project: install it with \`npm i ${type}\`, or \u2014 if this repository is the one that builds it \u2014 run \`penv add --local ${type}\` once it is a dependency of the root. The CLI ships ${preinstalled} pre-installed.`
51005
51101
  );
51006
51102
  }
51007
51103
 
@@ -51031,10 +51127,10 @@ function localTree(project) {
51031
51127
  }
51032
51128
  function selfContainedSchemaModule(root, schemaFile) {
51033
51129
  const file2 = (0, import_node_path4.join)(root, ...schemaFile.split("/"));
51034
- if (!(0, import_node_fs3.existsSync)(file2)) {
51130
+ if (!(0, import_node_fs4.existsSync)(file2)) {
51035
51131
  return void 0;
51036
51132
  }
51037
- const source = (0, import_node_fs3.readFileSync)(file2, "utf8");
51133
+ const source = (0, import_node_fs4.readFileSync)(file2, "utf8");
51038
51134
  return source.includes("PenvSchemaShape") || source.includes("z.object") ? schemaFile : void 0;
51039
51135
  }
51040
51136
  function schemaShapeFileOf(project) {
@@ -51271,10 +51367,7 @@ function writeError(lines) {
51271
51367
  }
51272
51368
  function reportError(error51) {
51273
51369
  if (error51 instanceof PenvError) {
51274
- const suffix = error51.remedy === void 0 ? void 0 : `
51275
- ${error51.remedy}`;
51276
- const message = suffix !== void 0 && error51.message.endsWith(suffix) ? error51.message.slice(0, -suffix.length) : error51.message;
51277
- process.stderr.write(`${err.red(CROSS)} ${message}
51370
+ process.stderr.write(`${err.red(CROSS)} ${error51.summary}
51278
51371
  `);
51279
51372
  if (error51.remedy !== void 0) {
51280
51373
  process.stderr.write(` ${err.cyan("\u2192")} ${error51.remedy}
@@ -51305,13 +51398,13 @@ async function guard(run) {
51305
51398
 
51306
51399
  // src/commands/run.ts
51307
51400
  init_cjs_shims();
51308
- var import_node_fs5 = require("fs");
51401
+ var import_node_fs6 = require("fs");
51309
51402
  var import_node_module2 = require("module");
51310
51403
  var import_node_path6 = require("path");
51311
51404
 
51312
51405
  // src/dotenv-files.ts
51313
51406
  init_cjs_shims();
51314
- var import_node_fs4 = require("fs");
51407
+ var import_node_fs5 = require("fs");
51315
51408
  var SHARED = ".env";
51316
51409
  var LOCAL2 = "local";
51317
51410
  var NOT_ENVIRONMENTS = [
@@ -51370,7 +51463,7 @@ function order(file2) {
51370
51463
  function discoverDotenvFiles(root) {
51371
51464
  let entries;
51372
51465
  try {
51373
- entries = (0, import_node_fs4.readdirSync)(root, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name);
51466
+ entries = (0, import_node_fs5.readdirSync)(root, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name);
51374
51467
  } catch {
51375
51468
  return [];
51376
51469
  }
@@ -52105,9 +52198,9 @@ function packageManifest(specifier, root) {
52105
52198
  }
52106
52199
  for (; ; ) {
52107
52200
  const file2 = (0, import_node_path6.join)(directory, "package.json");
52108
- if ((0, import_node_fs5.existsSync)(file2)) {
52201
+ if ((0, import_node_fs6.existsSync)(file2)) {
52109
52202
  try {
52110
- const parsed = JSON.parse((0, import_node_fs5.readFileSync)(file2, "utf8"));
52203
+ const parsed = JSON.parse((0, import_node_fs6.readFileSync)(file2, "utf8"));
52111
52204
  if (isPlainObject4(parsed) && parsed.name === specifier) {
52112
52205
  return parsed;
52113
52206
  }
@@ -52180,7 +52273,7 @@ function snapshotPath(host) {
52180
52273
  }
52181
52274
  function readSnapshot(path) {
52182
52275
  try {
52183
- return (0, import_node_fs5.readFileSync)(path, "utf8");
52276
+ return (0, import_node_fs6.readFileSync)(path, "utf8");
52184
52277
  } catch {
52185
52278
  throw new PenvError(
52186
52279
  "RUN_SNAPSHOT_MISSING",
@@ -52259,11 +52352,11 @@ function watchProject(project, onChange) {
52259
52352
  timer = setTimeout(onChange, DEBOUNCE_MS);
52260
52353
  };
52261
52354
  const add = (target, recursive, only) => {
52262
- if (!(0, import_node_fs5.existsSync)(target)) {
52355
+ if (!(0, import_node_fs6.existsSync)(target)) {
52263
52356
  return;
52264
52357
  }
52265
52358
  try {
52266
- const watcher = (0, import_node_fs5.watch)(target, { recursive }, (_event, filename) => {
52359
+ const watcher = (0, import_node_fs6.watch)(target, { recursive }, (_event, filename) => {
52267
52360
  if (only !== void 0 && (filename === null || (0, import_node_path6.basename)(filename) !== only)) {
52268
52361
  return;
52269
52362
  }
@@ -52526,8 +52619,8 @@ ${lines}`,
52526
52619
  keySource: keySourceIdentifier(project.config, environment),
52527
52620
  values
52528
52621
  };
52529
- (0, import_node_fs6.mkdirSync)((0, import_node_path7.dirname)(file2), { recursive: true });
52530
- (0, import_node_fs6.writeFileSync)(file2, serializeArtifact(artifact), "utf8");
52622
+ (0, import_node_fs7.mkdirSync)((0, import_node_path7.dirname)(file2), { recursive: true });
52623
+ (0, import_node_fs7.writeFileSync)(file2, serializeArtifact(artifact), "utf8");
52531
52624
  const inside = (0, import_node_path7.relative)(project.root, file2);
52532
52625
  return {
52533
52626
  file: file2,
@@ -52597,7 +52690,7 @@ init_cjs_shims();
52597
52690
 
52598
52691
  // src/cutover.ts
52599
52692
  init_cjs_shims();
52600
- var import_node_fs7 = require("fs");
52693
+ var import_node_fs8 = require("fs");
52601
52694
  var import_node_path8 = require("path");
52602
52695
  var CUTOVER_FORMAT = 1;
52603
52696
  function fileFor(root, relativePosix) {
@@ -52615,7 +52708,7 @@ function cutoverRoot(cwd) {
52615
52708
  }
52616
52709
  function bundledFiles(root) {
52617
52710
  try {
52618
- return (0, import_node_fs7.readdirSync)(bundleDir(root)).sort();
52711
+ return (0, import_node_fs8.readdirSync)(bundleDir(root)).sort();
52619
52712
  } catch {
52620
52713
  return [];
52621
52714
  }
@@ -52625,12 +52718,12 @@ function bundleUnresolved(root) {
52625
52718
  }
52626
52719
  function readCutover(root) {
52627
52720
  const file2 = cutoverFile(root);
52628
- if (!(0, import_node_fs7.existsSync)(file2)) {
52721
+ if (!(0, import_node_fs8.existsSync)(file2)) {
52629
52722
  return void 0;
52630
52723
  }
52631
52724
  let parsed;
52632
52725
  try {
52633
- parsed = JSON.parse((0, import_node_fs7.readFileSync)(file2, "utf8"));
52726
+ parsed = JSON.parse((0, import_node_fs8.readFileSync)(file2, "utf8"));
52634
52727
  } catch {
52635
52728
  throw unreadable("it is not JSON");
52636
52729
  }
@@ -52683,12 +52776,12 @@ function bundleDotenvFiles(root, files, environments, now = /* @__PURE__ */ new
52683
52776
  environments: [...environments]
52684
52777
  };
52685
52778
  const file2 = cutoverFile(root);
52686
- (0, import_node_fs7.mkdirSync)((0, import_node_path8.dirname)(file2), { recursive: true });
52687
- (0, import_node_fs7.writeFileSync)(file2, serializeCutover(cutover), "utf8");
52779
+ (0, import_node_fs8.mkdirSync)((0, import_node_path8.dirname)(file2), { recursive: true });
52780
+ (0, import_node_fs8.writeFileSync)(file2, serializeCutover(cutover), "utf8");
52688
52781
  const bundle = bundleDir(root);
52689
- (0, import_node_fs7.mkdirSync)(bundle, { recursive: true });
52782
+ (0, import_node_fs8.mkdirSync)(bundle, { recursive: true });
52690
52783
  for (const name of files) {
52691
- (0, import_node_fs7.renameSync)((0, import_node_path8.join)(root, name), (0, import_node_path8.join)(bundle, name));
52784
+ (0, import_node_fs8.renameSync)((0, import_node_path8.join)(root, name), (0, import_node_path8.join)(bundle, name));
52692
52785
  }
52693
52786
  return cutover;
52694
52787
  }
@@ -52707,7 +52800,7 @@ function runUndo(options) {
52707
52800
  const names = [...recorded, ...bundled.filter((name) => !recorded.includes(name))];
52708
52801
  const bundle = bundleDir(root);
52709
52802
  const held = new Set(bundled);
52710
- const occupied2 = names.filter((name) => held.has(name) && (0, import_node_fs7.existsSync)((0, import_node_path8.join)(root, name)));
52803
+ const occupied2 = names.filter((name) => held.has(name) && (0, import_node_fs8.existsSync)((0, import_node_path8.join)(root, name)));
52711
52804
  if (occupied2.length > 0) {
52712
52805
  const listed = occupied2.join(", ");
52713
52806
  const many = occupied2.length > 1;
@@ -52722,9 +52815,9 @@ function runUndo(options) {
52722
52815
  const missing = [];
52723
52816
  for (const name of names) {
52724
52817
  if (held.has(name)) {
52725
- (0, import_node_fs7.renameSync)((0, import_node_path8.join)(bundle, name), (0, import_node_path8.join)(root, name));
52818
+ (0, import_node_fs8.renameSync)((0, import_node_path8.join)(bundle, name), (0, import_node_path8.join)(root, name));
52726
52819
  restored.push(name);
52727
- } else if ((0, import_node_fs7.existsSync)((0, import_node_path8.join)(root, name))) {
52820
+ } else if ((0, import_node_fs8.existsSync)((0, import_node_path8.join)(root, name))) {
52728
52821
  alreadyBack.push(name);
52729
52822
  } else {
52730
52823
  missing.push(name);
@@ -52736,13 +52829,13 @@ function runUndo(options) {
52736
52829
  function runCleanup(options) {
52737
52830
  const root = cutoverRoot(options.cwd);
52738
52831
  const held = bundledFiles(root);
52739
- const cleaned = held.length > 0 || (0, import_node_fs7.existsSync)(cutoverFile(root)) || (0, import_node_fs7.existsSync)(fileFor(root, ROLLBACK_PATH));
52832
+ const cleaned = held.length > 0 || (0, import_node_fs8.existsSync)(cutoverFile(root)) || (0, import_node_fs8.existsSync)(fileFor(root, ROLLBACK_PATH));
52740
52833
  removeBundle(root);
52741
52834
  return { root, removed: held, cleaned };
52742
52835
  }
52743
52836
  function removeBundle(root) {
52744
- (0, import_node_fs7.rmSync)(fileFor(root, ROLLBACK_PATH), { recursive: true, force: true });
52745
- (0, import_node_fs7.rmSync)(cutoverFile(root), { force: true });
52837
+ (0, import_node_fs8.rmSync)(fileFor(root, ROLLBACK_PATH), { recursive: true, force: true });
52838
+ (0, import_node_fs8.rmSync)(cutoverFile(root), { force: true });
52746
52839
  }
52747
52840
 
52748
52841
  // src/commands/cleanup.ts
@@ -52778,7 +52871,7 @@ var cleanupCommand = defineCommand({
52778
52871
 
52779
52872
  // src/commands/doctor.ts
52780
52873
  init_cjs_shims();
52781
- var import_node_fs8 = require("fs");
52874
+ var import_node_fs9 = require("fs");
52782
52875
  var import_node_path9 = require("path");
52783
52876
 
52784
52877
  // src/commands/push.ts
@@ -53222,6 +53315,7 @@ async function runDoctor(options) {
53222
53315
  findings.push(...unusedFindings(drift));
53223
53316
  }
53224
53317
  findings.push(...fallbackFindings(subjects, environment));
53318
+ findings.push(...secrecyFindings(subjects, environment));
53225
53319
  findings.push(...plaintextSecretFindings(subjects, environment));
53226
53320
  findings.push(...publicSecretFindings(subjects, environment, project.config));
53227
53321
  findings.push(...encryptionFindings(subjects, environment));
@@ -53234,6 +53328,7 @@ async function runDoctor(options) {
53234
53328
  }
53235
53329
  findings.push(...await providerDriftFindings(project, environment, options.source));
53236
53330
  findings.push(...await projectionFindings(project, environment, options.projection));
53331
+ findings.push(...localExtensionFindings(project));
53237
53332
  findings.push(...artifactFindings(project));
53238
53333
  findings.push({
53239
53334
  check: "provider",
@@ -53371,6 +53466,31 @@ function fallbackFindings(subjects, environment) {
53371
53466
  }
53372
53467
  ];
53373
53468
  }
53469
+ function secrecyFindings(subjects, environment) {
53470
+ const undeclared = subjects.filter(
53471
+ ({ meta: meta3 }) => effectiveMeta(meta3, environment).secret === void 0
53472
+ );
53473
+ if (undeclared.length === 0) {
53474
+ return [
53475
+ {
53476
+ check: "secrecy-undeclared",
53477
+ severity: "pass",
53478
+ label: "Secrecy policy",
53479
+ subject: subjects.length === 0 ? `no parameter resolves for ${environment}` : `every parameter declares whether it is secret for ${environment}`
53480
+ }
53481
+ ];
53482
+ }
53483
+ return [
53484
+ {
53485
+ check: "secrecy-undeclared",
53486
+ severity: "unknown",
53487
+ label: "Secrecy policy",
53488
+ subject: `${undeclared.length} of ${subjects.length} declare neither way for ${environment}`,
53489
+ detail: "penv was never told which of these values must be encrypted",
53490
+ remedy: `declare \`"secret": true\` or \`"secret": false\` in a parameter's meta file, ${RECORDS_PATH2}/<name>.json`
53491
+ }
53492
+ ];
53493
+ }
53374
53494
  function plaintextSecretFindings(subjects, environment) {
53375
53495
  const secrets = subjects.filter(({ meta: meta3 }) => isSecret(meta3, environment));
53376
53496
  const findings = [];
@@ -53674,7 +53794,7 @@ function looksLikeArtifact(text) {
53674
53794
  function scannableFiles(directory, out2) {
53675
53795
  let entries;
53676
53796
  try {
53677
- entries = (0, import_node_fs8.readdirSync)(directory, { withFileTypes: true });
53797
+ entries = (0, import_node_fs9.readdirSync)(directory, { withFileTypes: true });
53678
53798
  } catch {
53679
53799
  return;
53680
53800
  }
@@ -53691,6 +53811,29 @@ function scannableFiles(directory, out2) {
53691
53811
  }
53692
53812
  }
53693
53813
  }
53814
+ function localExtensionFindings(project) {
53815
+ const names = localExtensions(project.root);
53816
+ if (names.length === 0) {
53817
+ return [
53818
+ {
53819
+ check: "local-extension",
53820
+ severity: "pass",
53821
+ label: "Extensions",
53822
+ subject: "every extension this project names is pinned"
53823
+ }
53824
+ ];
53825
+ }
53826
+ return [
53827
+ {
53828
+ check: "local-extension",
53829
+ severity: "unknown",
53830
+ label: "Extensions",
53831
+ subject: names.join(", "),
53832
+ detail: "resolved from this project's node_modules \u2014 no release, no pinned bytes",
53833
+ remedy: `publish it and run \`penv add ${names[0]}\` when this stops being a development path`
53834
+ }
53835
+ ];
53836
+ }
53694
53837
  function artifactFindings(project) {
53695
53838
  const files = [];
53696
53839
  scannableFiles(project.root, files);
@@ -53698,10 +53841,10 @@ function artifactFindings(project) {
53698
53841
  for (const file2 of files) {
53699
53842
  let text;
53700
53843
  try {
53701
- if ((0, import_node_fs8.statSync)(file2).size > ARTIFACT_SCAN_LIMIT) {
53844
+ if ((0, import_node_fs9.statSync)(file2).size > ARTIFACT_SCAN_LIMIT) {
53702
53845
  continue;
53703
53846
  }
53704
- text = (0, import_node_fs8.readFileSync)(file2, "utf8");
53847
+ text = (0, import_node_fs9.readFileSync)(file2, "utf8");
53705
53848
  } catch {
53706
53849
  continue;
53707
53850
  }
@@ -54459,7 +54602,7 @@ var fillCommand = defineCommand({
54459
54602
 
54460
54603
  // src/commands/generate.ts
54461
54604
  init_cjs_shims();
54462
- var import_node_fs9 = require("fs");
54605
+ var import_node_fs10 = require("fs");
54463
54606
  var import_node_path10 = require("path");
54464
54607
  var DEFAULT_OUTPUT = ".env";
54465
54608
  function entriesFor(project, environment, allowDecrypt) {
@@ -54506,7 +54649,7 @@ function runGenerate(options) {
54506
54649
  const environment = targetEnvironment(project, options.environment, options.envFlags);
54507
54650
  const { entries, decrypted } = entriesFor(project, environment, options.allowDecrypt === true);
54508
54651
  const file2 = options.out === void 0 ? (0, import_node_path10.resolve)(project.root, DEFAULT_OUTPUT) : (0, import_node_path10.isAbsolute)(options.out) ? options.out : (0, import_node_path10.resolve)(options.cwd, options.out);
54509
- (0, import_node_fs9.writeFileSync)(file2, serializeDotenv(entries), "utf8");
54652
+ (0, import_node_fs10.writeFileSync)(file2, serializeDotenv(entries), "utf8");
54510
54653
  return { file: file2, environment, entries: entries.length, decrypted };
54511
54654
  }
54512
54655
  function displayPath2(cwd, file2) {
@@ -54644,7 +54787,7 @@ var getCommand = defineCommand({
54644
54787
 
54645
54788
  // src/commands/import.ts
54646
54789
  init_cjs_shims();
54647
- var import_node_fs13 = require("fs");
54790
+ var import_node_fs14 = require("fs");
54648
54791
  var import_node_path14 = require("path");
54649
54792
 
54650
54793
  // src/adopt.ts
@@ -54714,7 +54857,7 @@ function writeEntries(tree, entries, refs, scope) {
54714
54857
 
54715
54858
  // src/detect.ts
54716
54859
  init_cjs_shims();
54717
- var import_node_fs10 = require("fs");
54860
+ var import_node_fs11 = require("fs");
54718
54861
  var import_node_path11 = require("path");
54719
54862
  var SIGNATURES = [
54720
54863
  { name: "Next.js", packages: ["next"], publicPrefixes: ["NEXT_PUBLIC_"] },
@@ -54731,7 +54874,7 @@ var SIGNATURES = [
54731
54874
  function exportsSchema(file2) {
54732
54875
  let source;
54733
54876
  try {
54734
- source = (0, import_node_fs10.readFileSync)(file2, "utf8");
54877
+ source = (0, import_node_fs11.readFileSync)(file2, "utf8");
54735
54878
  } catch {
54736
54879
  return false;
54737
54880
  }
@@ -54743,7 +54886,7 @@ function exportsSchema(file2) {
54743
54886
  }
54744
54887
  function occupied(cwd, relative5) {
54745
54888
  const file2 = (0, import_node_path11.join)(cwd, ...relative5.split("/"));
54746
- return (0, import_node_fs10.existsSync)(file2) && !exportsSchema(file2);
54889
+ return (0, import_node_fs11.existsSync)(file2) && !exportsSchema(file2);
54747
54890
  }
54748
54891
  function schemaFileFor(cwd) {
54749
54892
  const dir = srcPrefix(cwd);
@@ -54758,7 +54901,7 @@ function schemaFileFor(cwd) {
54758
54901
  return { file: DEFAULT_SCHEMA_FILE, displaced: preferred };
54759
54902
  }
54760
54903
  function srcPrefix(cwd) {
54761
- return (0, import_node_fs10.existsSync)((0, import_node_path11.join)(cwd, "src")) ? "src/" : "";
54904
+ return (0, import_node_fs11.existsSync)((0, import_node_path11.join)(cwd, "src")) ? "src/" : "";
54762
54905
  }
54763
54906
  function dependenciesOf(cwd) {
54764
54907
  const manifest = manifestOf2(cwd);
@@ -54778,12 +54921,12 @@ function dependenciesOf(cwd) {
54778
54921
  }
54779
54922
  function manifestOf2(cwd) {
54780
54923
  const file2 = (0, import_node_path11.join)(cwd, "package.json");
54781
- if (!(0, import_node_fs10.existsSync)(file2)) {
54924
+ if (!(0, import_node_fs11.existsSync)(file2)) {
54782
54925
  return void 0;
54783
54926
  }
54784
54927
  let manifest;
54785
54928
  try {
54786
- manifest = JSON.parse((0, import_node_fs10.readFileSync)(file2, "utf8"));
54929
+ manifest = JSON.parse((0, import_node_fs11.readFileSync)(file2, "utf8"));
54787
54930
  } catch {
54788
54931
  return void 0;
54789
54932
  }
@@ -54799,7 +54942,7 @@ function detectFramework(cwd) {
54799
54942
  return detectedFrom(cwd, signature.name, signature.publicPrefixes);
54800
54943
  }
54801
54944
  }
54802
- if ((0, import_node_fs10.existsSync)((0, import_node_path11.join)(cwd, "bunfig.toml")) || dependencies.has("bun-types")) {
54945
+ if ((0, import_node_fs11.existsSync)((0, import_node_path11.join)(cwd, "bunfig.toml")) || dependencies.has("bun-types")) {
54803
54946
  return detectedFrom(cwd, "Bun", []);
54804
54947
  }
54805
54948
  return void 0;
@@ -54879,30 +55022,30 @@ function draftFieldsAcross(sources, environments) {
54879
55022
 
54880
55023
  // src/commands/init.ts
54881
55024
  init_cjs_shims();
54882
- var import_node_fs12 = require("fs");
55025
+ var import_node_fs13 = require("fs");
54883
55026
  var import_node_path13 = require("path");
54884
55027
  var import_promises = require("readline/promises");
54885
55028
 
54886
55029
  // src/scaffold-undo.ts
54887
55030
  init_cjs_shims();
54888
- var import_node_fs11 = require("fs");
55031
+ var import_node_fs12 = require("fs");
54889
55032
  var import_node_path12 = require("path");
54890
55033
  function record2(path, files, dirs) {
54891
55034
  let stats;
54892
55035
  try {
54893
- stats = (0, import_node_fs11.statSync)(path);
55036
+ stats = (0, import_node_fs12.statSync)(path);
54894
55037
  } catch {
54895
55038
  return;
54896
55039
  }
54897
55040
  if (stats.isDirectory()) {
54898
55041
  dirs.add(path);
54899
- for (const entry of (0, import_node_fs11.readdirSync)(path)) {
55042
+ for (const entry of (0, import_node_fs12.readdirSync)(path)) {
54900
55043
  record2((0, import_node_path12.join)(path, entry), files, dirs);
54901
55044
  }
54902
55045
  return;
54903
55046
  }
54904
55047
  if (stats.isFile()) {
54905
- files.set(path, (0, import_node_fs11.readFileSync)(path));
55048
+ files.set(path, (0, import_node_fs12.readFileSync)(path));
54906
55049
  }
54907
55050
  }
54908
55051
  function captureScaffold(root, paths) {
@@ -54910,7 +55053,7 @@ function captureScaffold(root, paths) {
54910
55053
  const dirs = /* @__PURE__ */ new Set();
54911
55054
  for (const path of paths) {
54912
55055
  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)) {
55056
+ if ((0, import_node_fs12.existsSync)(dir)) {
54914
55057
  dirs.add(dir);
54915
55058
  }
54916
55059
  }
@@ -54926,31 +55069,31 @@ function restoreScaffold(undo) {
54926
55069
  pruneAncestors(path, undo);
54927
55070
  }
54928
55071
  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);
55072
+ (0, import_node_fs12.mkdirSync)((0, import_node_path12.dirname)(file2), { recursive: true });
55073
+ (0, import_node_fs12.writeFileSync)(file2, contents);
54931
55074
  }
54932
55075
  }
54933
55076
  function removeAdded(path, undo) {
54934
55077
  let stats;
54935
55078
  try {
54936
- stats = (0, import_node_fs11.statSync)(path);
55079
+ stats = (0, import_node_fs12.statSync)(path);
54937
55080
  } catch {
54938
55081
  return;
54939
55082
  }
54940
55083
  if (stats.isFile()) {
54941
55084
  if (!undo.files.has(path)) {
54942
- (0, import_node_fs11.unlinkSync)(path);
55085
+ (0, import_node_fs12.unlinkSync)(path);
54943
55086
  }
54944
55087
  return;
54945
55088
  }
54946
55089
  if (!stats.isDirectory()) {
54947
55090
  return;
54948
55091
  }
54949
- for (const entry of (0, import_node_fs11.readdirSync)(path)) {
55092
+ for (const entry of (0, import_node_fs12.readdirSync)(path)) {
54950
55093
  removeAdded((0, import_node_path12.join)(path, entry), undo);
54951
55094
  }
54952
- if (!undo.dirs.has(path) && (0, import_node_fs11.readdirSync)(path).length === 0) {
54953
- (0, import_node_fs11.rmdirSync)(path);
55095
+ if (!undo.dirs.has(path) && (0, import_node_fs12.readdirSync)(path).length === 0) {
55096
+ (0, import_node_fs12.rmdirSync)(path);
54954
55097
  }
54955
55098
  }
54956
55099
  function pruneAncestors(path, undo) {
@@ -54959,7 +55102,7 @@ function pruneAncestors(path, undo) {
54959
55102
  return;
54960
55103
  }
54961
55104
  try {
54962
- (0, import_node_fs11.rmdirSync)(dir);
55105
+ (0, import_node_fs12.rmdirSync)(dir);
54963
55106
  } catch {
54964
55107
  return;
54965
55108
  }
@@ -55122,7 +55265,7 @@ var NOT_ENVIRONMENTS2 = [...RESERVED_TOKENS, "example", "sample", "template"];
55122
55265
  function suggestEnvironments(root) {
55123
55266
  let entries;
55124
55267
  try {
55125
- entries = (0, import_node_fs12.readdirSync)(root);
55268
+ entries = (0, import_node_fs13.readdirSync)(root);
55126
55269
  } catch {
55127
55270
  return [];
55128
55271
  }
@@ -55167,7 +55310,7 @@ function configOf(decisions) {
55167
55310
  }
55168
55311
  function declaredIn(root) {
55169
55312
  const file2 = (0, import_node_path13.join)(root, CONFIG_FILE);
55170
- if (!(0, import_node_fs12.existsSync)(file2)) {
55313
+ if (!(0, import_node_fs13.existsSync)(file2)) {
55171
55314
  return void 0;
55172
55315
  }
55173
55316
  return loadConfigFrom(file2);
@@ -55610,15 +55753,15 @@ function renderTsconfig(target, alias) {
55610
55753
  }
55611
55754
  function ensurePenvDir(root) {
55612
55755
  const dir = (0, import_node_path13.resolve)(root, PENV_DIR);
55613
- if ((0, import_node_fs12.existsSync)(dir)) {
55756
+ if ((0, import_node_fs13.existsSync)(dir)) {
55614
55757
  return { target: "penv-dir", action: "kept", text: `Found ${PENV_DIR}/` };
55615
55758
  }
55616
- (0, import_node_fs12.mkdirSync)(dir, { recursive: true });
55759
+ (0, import_node_fs13.mkdirSync)(dir, { recursive: true });
55617
55760
  return { target: "penv-dir", action: "created", text: `Created ${PENV_DIR}/` };
55618
55761
  }
55619
55762
  function writeSchemaShapeFile(root, fields, draft, decisions = DEFAULT_DECISIONS) {
55620
55763
  const file2 = (0, import_node_path13.join)(root, SCHEMA_SHAPE_FILE);
55621
- if ((0, import_node_fs12.existsSync)(file2)) {
55764
+ if ((0, import_node_fs13.existsSync)(file2)) {
55622
55765
  return {
55623
55766
  target: "schema",
55624
55767
  action: "kept",
@@ -55635,7 +55778,7 @@ function writeSchemaShapeFile(root, fields, draft, decisions = DEFAULT_DECISIONS
55635
55778
  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\`.)`
55636
55779
  };
55637
55780
  }
55638
- (0, import_node_fs12.writeFileSync)(file2, renderSchemaShapeModule(fields, draft), "utf8");
55781
+ (0, import_node_fs13.writeFileSync)(file2, renderSchemaShapeModule(fields, draft), "utf8");
55639
55782
  return {
55640
55783
  target: "schema",
55641
55784
  action: "created",
@@ -55645,7 +55788,7 @@ function writeSchemaShapeFile(root, fields, draft, decisions = DEFAULT_DECISIONS
55645
55788
  }
55646
55789
  function writeEnvFile(root, decisions = DEFAULT_DECISIONS) {
55647
55790
  const file2 = (0, import_node_path13.join)(root, ...decisions.schemaFile.split("/"));
55648
- if ((0, import_node_fs12.existsSync)(file2)) {
55791
+ if ((0, import_node_fs13.existsSync)(file2)) {
55649
55792
  return {
55650
55793
  target: "env",
55651
55794
  action: "kept",
@@ -55653,8 +55796,8 @@ function writeEnvFile(root, decisions = DEFAULT_DECISIONS) {
55653
55796
  note: "(yours \u2014 penv never regenerates it)"
55654
55797
  };
55655
55798
  }
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");
55799
+ (0, import_node_fs13.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55800
+ (0, import_node_fs13.writeFileSync)(file2, renderEnvModule(decisions.schemaFile, decisions.inject), "utf8");
55658
55801
  return {
55659
55802
  target: "env",
55660
55803
  action: "created",
@@ -55664,10 +55807,10 @@ function writeEnvFile(root, decisions = DEFAULT_DECISIONS) {
55664
55807
  }
55665
55808
  function writeConfigFile(root, decisions = DEFAULT_DECISIONS) {
55666
55809
  const file2 = (0, import_node_path13.join)(root, CONFIG_FILE);
55667
- if ((0, import_node_fs12.existsSync)(file2)) {
55810
+ if ((0, import_node_fs13.existsSync)(file2)) {
55668
55811
  return { target: "config", action: "kept", text: `Kept ${CONFIG_FILE}` };
55669
55812
  }
55670
- (0, import_node_fs12.writeFileSync)(file2, renderConfigModule(decisions), "utf8");
55813
+ (0, import_node_fs13.writeFileSync)(file2, renderConfigModule(decisions), "utf8");
55671
55814
  return { target: "config", action: "created", text: `Generated ${CONFIG_FILE}` };
55672
55815
  }
55673
55816
  function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
@@ -55675,7 +55818,7 @@ function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
55675
55818
  const imports = alias.startsWith(IMPORTS_PREFIX);
55676
55819
  const file2 = (0, import_node_path13.join)(root, imports ? PACKAGE_FILE : TSCONFIG_FILE);
55677
55820
  const where = imports ? PACKAGE_FILE : TSCONFIG_FILE;
55678
- if (!(0, import_node_fs12.existsSync)(file2)) {
55821
+ if (!(0, import_node_fs13.existsSync)(file2)) {
55679
55822
  if (imports) {
55680
55823
  return {
55681
55824
  target: "tsconfig",
@@ -55684,14 +55827,14 @@ function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
55684
55827
  note: `(run \`npm init\` first, or use \`--alias @env\` to alias through ${TSCONFIG_FILE})`
55685
55828
  };
55686
55829
  }
55687
- (0, import_node_fs12.writeFileSync)(file2, renderTsconfig(decisions.schemaFile, alias), "utf8");
55830
+ (0, import_node_fs13.writeFileSync)(file2, renderTsconfig(decisions.schemaFile, alias), "utf8");
55688
55831
  return {
55689
55832
  target: "tsconfig",
55690
55833
  action: "created",
55691
55834
  text: `Created ${TSCONFIG_FILE} with the ${alias} path alias`
55692
55835
  };
55693
55836
  }
55694
- const source = (0, import_node_fs12.readFileSync)(file2, "utf8");
55837
+ const source = (0, import_node_fs13.readFileSync)(file2, "utf8");
55695
55838
  const edit = imports ? insertImportsAlias(source, decisions.schemaFile, alias) : insertEnvAlias(source, decisions.schemaFile, alias);
55696
55839
  if (edit.conflict !== void 0) {
55697
55840
  return {
@@ -55708,7 +55851,7 @@ function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
55708
55851
  text: `Kept the ${alias} alias in ${where}`
55709
55852
  };
55710
55853
  }
55711
- (0, import_node_fs12.writeFileSync)(file2, edit.source, "utf8");
55854
+ (0, import_node_fs13.writeFileSync)(file2, edit.source, "utf8");
55712
55855
  return {
55713
55856
  target: "tsconfig",
55714
55857
  action: "updated",
@@ -55718,12 +55861,12 @@ function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
55718
55861
  function writeGitignore(root, decisions = DEFAULT_DECISIONS) {
55719
55862
  const file2 = (0, import_node_path13.join)(root, ...STATE_GITIGNORE_PATH.split("/"));
55720
55863
  const wanted = renderStateGitignore(configOf(decisions));
55721
- const existing = (0, import_node_fs12.existsSync)(file2) ? (0, import_node_fs12.readFileSync)(file2, "utf8") : void 0;
55864
+ const existing = (0, import_node_fs13.existsSync)(file2) ? (0, import_node_fs13.readFileSync)(file2, "utf8") : void 0;
55722
55865
  if (existing === wanted) {
55723
55866
  return { target: "gitignore", action: "kept", text: `Kept ${STATE_GITIGNORE_PATH}` };
55724
55867
  }
55725
- (0, import_node_fs12.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55726
- (0, import_node_fs12.writeFileSync)(file2, wanted, "utf8");
55868
+ (0, import_node_fs13.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55869
+ (0, import_node_fs13.writeFileSync)(file2, wanted, "utf8");
55727
55870
  return {
55728
55871
  target: "gitignore",
55729
55872
  action: existing === void 0 ? "created" : "updated",
@@ -55740,11 +55883,11 @@ function outdatedRuntimeWarning(root) {
55740
55883
  }
55741
55884
  function installedPenvVersion(root) {
55742
55885
  const file2 = (0, import_node_path13.join)(root, "node_modules", "@penvhq", "penv", "package.json");
55743
- if (!(0, import_node_fs12.existsSync)(file2)) {
55886
+ if (!(0, import_node_fs13.existsSync)(file2)) {
55744
55887
  return void 0;
55745
55888
  }
55746
55889
  try {
55747
- const version2 = JSON.parse((0, import_node_fs12.readFileSync)(file2, "utf8")).version;
55890
+ const version2 = JSON.parse((0, import_node_fs13.readFileSync)(file2, "utf8")).version;
55748
55891
  return typeof version2 === "string" ? version2 : void 0;
55749
55892
  } catch {
55750
55893
  return void 0;
@@ -55788,7 +55931,7 @@ function writeSeam(root, decisions = DEFAULT_DECISIONS, framework = detectFramew
55788
55931
  const baseNotes = [...seam.notes, ...alsoNote === void 0 ? [] : [alsoNote]];
55789
55932
  const notes = baseNotes.length === 0 ? "" : `
55790
55933
  ${baseNotes.map((n) => ` ${n}`).join("\n")}`;
55791
- if ((0, import_node_fs12.existsSync)(file2)) {
55934
+ if ((0, import_node_fs13.existsSync)(file2)) {
55792
55935
  return {
55793
55936
  target: "seam",
55794
55937
  action: "info",
@@ -55796,8 +55939,8 @@ ${baseNotes.map((n) => ` ${n}`).join("\n")}`;
55796
55939
  note: withWarning(`${seam.ifPresent}${notes}`, outdated)
55797
55940
  };
55798
55941
  }
55799
- (0, import_node_fs12.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55800
- (0, import_node_fs12.writeFileSync)(file2, seam.content, "utf8");
55942
+ (0, import_node_fs13.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55943
+ (0, import_node_fs13.writeFileSync)(file2, seam.content, "utf8");
55801
55944
  return {
55802
55945
  target: "seam",
55803
55946
  action: outdated === void 0 ? "created" : "info",
@@ -55810,11 +55953,11 @@ function writeAlso(root, also) {
55810
55953
  return void 0;
55811
55954
  }
55812
55955
  const file2 = (0, import_node_path13.join)(root, ...also.file.split("/"));
55813
- if ((0, import_node_fs12.existsSync)(file2)) {
55956
+ if ((0, import_node_fs13.existsSync)(file2)) {
55814
55957
  return also.ifPresent;
55815
55958
  }
55816
- (0, import_node_fs12.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55817
- (0, import_node_fs12.writeFileSync)(file2, also.content, "utf8");
55959
+ (0, import_node_fs13.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55960
+ (0, import_node_fs13.writeFileSync)(file2, also.content, "utf8");
55818
55961
  return `Wrote ${also.file} to register it.`;
55819
55962
  }
55820
55963
  function withWarning(note, warning) {
@@ -55918,7 +56061,7 @@ function planCutover(input) {
55918
56061
  const diagnostics = [];
55919
56062
  let variables = 0;
55920
56063
  for (const file2 of selected) {
55921
- const parsed = parseDotenv((0, import_node_fs12.readFileSync)((0, import_node_path13.join)(root, file2.name), "utf8"));
56064
+ const parsed = parseDotenv((0, import_node_fs13.readFileSync)((0, import_node_path13.join)(root, file2.name), "utf8"));
55922
56065
  const fileRefs = refsForEntries(parsed.entries, file2.name, config2);
55923
56066
  adopted.push({ file: file2, entries: parsed.entries, refs: fileRefs, scope: scopeOf(file2) });
55924
56067
  refs.push(...fileRefs);
@@ -56163,11 +56306,11 @@ function dailyCommand(root) {
56163
56306
  }
56164
56307
  function devScript(root) {
56165
56308
  const file2 = (0, import_node_path13.join)(root, PACKAGE_FILE);
56166
- if (!(0, import_node_fs12.existsSync)(file2)) {
56309
+ if (!(0, import_node_fs13.existsSync)(file2)) {
56167
56310
  return "dev";
56168
56311
  }
56169
56312
  try {
56170
- const scripts = JSON.parse((0, import_node_fs12.readFileSync)(file2, "utf8")).scripts;
56313
+ const scripts = JSON.parse((0, import_node_fs13.readFileSync)(file2, "utf8")).scripts;
56171
56314
  if (scripts !== null && typeof scripts === "object" && !Array.isArray(scripts)) {
56172
56315
  const named = Object.keys(scripts);
56173
56316
  return ["dev", "start"].find((script) => named.includes(script)) ?? named[0] ?? "dev";
@@ -56536,14 +56679,14 @@ function configInEffect(cwd, environment) {
56536
56679
  function importDotenv(options) {
56537
56680
  const cwd = (0, import_node_path14.resolve)(options.cwd);
56538
56681
  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)) {
56682
+ if (!(0, import_node_fs14.existsSync)(file2)) {
56540
56683
  throw new PenvError(
56541
56684
  "IMPORT_FILE_MISSING",
56542
56685
  `There is no file at ${file2} to import`,
56543
56686
  "Point `penv import` at an existing dotenv file, e.g. `penv import .env`."
56544
56687
  );
56545
56688
  }
56546
- const parsed = parseDotenv((0, import_node_fs13.readFileSync)(file2, "utf8"));
56689
+ const parsed = parseDotenv((0, import_node_fs14.readFileSync)(file2, "utf8"));
56547
56690
  const { config: config2, decisions } = configInEffect(cwd, environmentNamed(file2, options.environment));
56548
56691
  const source = displayPath3(cwd, file2);
56549
56692
  const named = scopeFromFilename(file2, config2);
@@ -56559,7 +56702,7 @@ function importDotenv(options) {
56559
56702
  const tree = localTree(project);
56560
56703
  writeEntries(tree, parsed.entries, refs, scope);
56561
56704
  const backup = `${file2}${BACKUP_SUFFIX}`;
56562
- (0, import_node_fs13.copyFileSync)(file2, backup);
56705
+ (0, import_node_fs14.copyFileSync)(file2, backup);
56563
56706
  return {
56564
56707
  root: project.root,
56565
56708
  file: file2,
@@ -56892,7 +57035,7 @@ var listCommand = defineCommand({
56892
57035
 
56893
57036
  // src/commands/migrate.ts
56894
57037
  init_cjs_shims();
56895
- var import_node_fs14 = require("fs");
57038
+ var import_node_fs15 = require("fs");
56896
57039
  var import_node_path15 = require("path");
56897
57040
  var import_promises2 = require("readline/promises");
56898
57041
  var OLD_GITIGNORE = `${PENV_DIR}/.gitignore`;
@@ -56910,7 +57053,7 @@ function planMigrate(cwd) {
56910
57053
  );
56911
57054
  }
56912
57055
  const creates = [];
56913
- if (entries.length > 0 && !(0, import_node_fs14.existsSync)(tree)) {
57056
+ if (entries.length > 0 && !(0, import_node_fs15.existsSync)(tree)) {
56914
57057
  creates.push(`${RECORDS_PATH2}/`);
56915
57058
  }
56916
57059
  if (readIfPresent((0, import_node_path15.join)(root, ...STATE_GITIGNORE_PATH.split("/"))) !== renderStateGitignore(config2)) {
@@ -56923,16 +57066,16 @@ function planMigrate(cwd) {
56923
57066
  to: `${RECORDS_PATH2}/${entry}`
56924
57067
  })),
56925
57068
  creates,
56926
- removes: (0, import_node_fs14.existsSync)((0, import_node_path15.join)(root, ...OLD_GITIGNORE.split("/"))) ? [OLD_GITIGNORE] : []
57069
+ removes: (0, import_node_fs15.existsSync)((0, import_node_path15.join)(root, ...OLD_GITIGNORE.split("/"))) ? [OLD_GITIGNORE] : []
56927
57070
  };
56928
57071
  }
56929
57072
  function readIfPresent(file2) {
56930
- return (0, import_node_fs14.existsSync)(file2) ? (0, import_node_fs14.readFileSync)(file2, "utf8") : void 0;
57073
+ return (0, import_node_fs15.existsSync)(file2) ? (0, import_node_fs15.readFileSync)(file2, "utf8") : void 0;
56931
57074
  }
56932
57075
  function collidingEntries(entries, tree) {
56933
57076
  let held;
56934
57077
  try {
56935
- held = (0, import_node_fs14.readdirSync)(tree);
57078
+ held = (0, import_node_fs15.readdirSync)(tree);
56936
57079
  } catch {
56937
57080
  return [];
56938
57081
  }
@@ -56951,18 +57094,18 @@ function applyMigrate(plan2) {
56951
57094
  }
56952
57095
  const { config: config2 } = loadConfig(plan2.root);
56953
57096
  if (plan2.moves.length > 0) {
56954
- (0, import_node_fs14.mkdirSync)(recordsDir(plan2.root), { recursive: true });
57097
+ (0, import_node_fs15.mkdirSync)(recordsDir(plan2.root), { recursive: true });
56955
57098
  for (const move of plan2.moves) {
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("/")));
57099
+ (0, import_node_fs15.renameSync)((0, import_node_path15.join)(plan2.root, ...move.from.split("/")), (0, import_node_path15.join)(plan2.root, ...move.to.split("/")));
56957
57100
  }
56958
57101
  }
56959
57102
  if (plan2.creates.includes(STATE_GITIGNORE_PATH)) {
56960
57103
  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");
57104
+ (0, import_node_fs15.mkdirSync)((0, import_node_path15.dirname)(ignore), { recursive: true });
57105
+ (0, import_node_fs15.writeFileSync)(ignore, renderStateGitignore(config2), "utf8");
56963
57106
  }
56964
57107
  for (const removed of plan2.removes) {
56965
- (0, import_node_fs14.rmSync)((0, import_node_path15.join)(plan2.root, ...removed.split("/")), { force: true });
57108
+ (0, import_node_fs15.rmSync)((0, import_node_path15.join)(plan2.root, ...removed.split("/")), { force: true });
56966
57109
  }
56967
57110
  return { ...plan2, status: "migrated" };
56968
57111
  }
@@ -57439,7 +57582,7 @@ var rotateCommand = defineCommand({
57439
57582
 
57440
57583
  // src/commands/watch.ts
57441
57584
  init_cjs_shims();
57442
- var import_node_fs15 = require("fs");
57585
+ var import_node_fs16 = require("fs");
57443
57586
  var import_node_path16 = require("path");
57444
57587
  var DEBOUNCE_MS2 = 100;
57445
57588
  function runWatch(options) {
@@ -57501,18 +57644,18 @@ function runWatch(options) {
57501
57644
  const name = (0, import_node_path16.basename)(target);
57502
57645
  let recovery;
57503
57646
  try {
57504
- recovery = (0, import_node_fs15.watch)(parent, { recursive: false }, (_event, filename) => {
57647
+ recovery = (0, import_node_fs16.watch)(parent, { recursive: false }, (_event, filename) => {
57505
57648
  if (closed || recovery === void 0) {
57506
57649
  return;
57507
57650
  }
57508
- if (!(0, import_node_fs15.existsSync)(parent)) {
57651
+ if (!(0, import_node_fs16.existsSync)(parent)) {
57509
57652
  stop2(recovery);
57510
57653
  return;
57511
57654
  }
57512
57655
  if (filename !== null && (0, import_node_path16.basename)(filename) !== name) {
57513
57656
  return;
57514
57657
  }
57515
- if (!(0, import_node_fs15.existsSync)(target)) {
57658
+ if (!(0, import_node_fs16.existsSync)(target)) {
57516
57659
  return;
57517
57660
  }
57518
57661
  stop2(recovery);
@@ -57532,11 +57675,11 @@ function runWatch(options) {
57532
57675
  }
57533
57676
  function addWatcher(target, recursive, only) {
57534
57677
  let watcher;
57535
- const listen = (useRecursive) => (0, import_node_fs15.watch)(target, { recursive: useRecursive }, (_event, filename) => {
57678
+ const listen = (useRecursive) => (0, import_node_fs16.watch)(target, { recursive: useRecursive }, (_event, filename) => {
57536
57679
  if (closed) {
57537
57680
  return;
57538
57681
  }
57539
- if (!(0, import_node_fs15.existsSync)(target)) {
57682
+ if (!(0, import_node_fs16.existsSync)(target)) {
57540
57683
  if (watcher !== void 0) {
57541
57684
  stop2(watcher);
57542
57685
  }