@penvhq/cli 0.9.4 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.cjs CHANGED
@@ -3023,7 +3023,7 @@ var require_jiti = __commonJS({
3023
3023
  }
3024
3024
  const isAbsolute6 = function(e3) {
3025
3025
  return ze.test(e3);
3026
- }, extname = function(e3) {
3026
+ }, extname2 = function(e3) {
3027
3027
  if (".." === e3) return "";
3028
3028
  const t3 = Ye.exec(pathe_M_eThtNZ_normalizeWindowsPath(e3));
3029
3029
  return t3 && t3[1] || "";
@@ -3725,7 +3725,7 @@ Default "index" lookups for the main are deprecated for ES modules.`, "Deprecati
3725
3725
  }
3726
3726
  const a2 = jitiResolve(e3, t3, i2);
3727
3727
  if (!a2 && i2.try) return;
3728
- const c2 = extname(a2);
3728
+ const c2 = extname2(a2);
3729
3729
  if (".json" === c2) {
3730
3730
  debug(e3, "[json]", a2);
3731
3731
  const t4 = e3.nativeRequire(a2);
@@ -3797,7 +3797,7 @@ Default "index" lookups for the main are deprecated for ES modules.`, "Deprecati
3797
3797
  return i2.startsWith("#!") && (i2 = "// " + i2), i2;
3798
3798
  }
3799
3799
  function eval_evalModule(t3, i2, n2 = {}) {
3800
- const a2 = n2.id || (n2.filename ? basename4(n2.filename) : `_jitiEval.${n2.ext || (n2.async ? "mjs" : "js")}`), c2 = n2.filename || jitiResolve(t3, a2, { async: n2.async }), l2 = n2.ext || extname(c2), y2 = n2.cache || t3.parentCache || {}, E2 = /\.[cm]?tsx?$/.test(l2), w2 = ".mjs" === l2 || ".js" === l2 && "module" === (function(e3) {
3800
+ const a2 = n2.id || (n2.filename ? basename4(n2.filename) : `_jitiEval.${n2.ext || (n2.async ? "mjs" : "js")}`), c2 = n2.filename || jitiResolve(t3, a2, { async: n2.async }), l2 = n2.ext || extname2(c2), y2 = n2.cache || t3.parentCache || {}, E2 = /\.[cm]?tsx?$/.test(l2), w2 = ".mjs" === l2 || ".js" === l2 && "module" === (function(e3) {
3801
3801
  for (; e3 && "." !== e3 && "/" !== e3; ) {
3802
3802
  e3 = pathe_M_eThtNZ_join(e3, "..");
3803
3803
  try {
@@ -3845,7 +3845,7 @@ Default "index" lookups for the main are deprecated for ES modules.`, "Deprecati
3845
3845
  (0, $e.mkdirSync)(n4, { recursive: true });
3846
3846
  } catch {
3847
3847
  }
3848
- const a4 = pathe_M_eThtNZ_join(n4, `${basename4(i6, extname(i6))}-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`);
3848
+ const a4 = pathe_M_eThtNZ_join(n4, `${basename4(i6, extname2(i6))}-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`);
3849
3849
  return (0, $e.writeFileSync)(a4, t5), a4;
3850
3850
  })(l3, n3), debug(t4, "[esm]", "[tempfile]", c4), a3(pathToFileURL3(c4))), E3 = y3 ? a3(y3).catch((e3) => {
3851
3851
  if ("ENAMETOOLONG" !== e3?.code) throw e3;
@@ -4222,7 +4222,7 @@ Did you specify these with the most recent transformation maps first?`);
4222
4222
  for (let e5 = 1; e5 < s; e5++) a += "/" + n[e5];
4223
4223
  (!a || o && !a.endsWith("/..")) && (a += "/"), e4.path = a;
4224
4224
  }
4225
- function resolve12(e4, t3) {
4225
+ function resolve13(e4, t3) {
4226
4226
  if (!e4 && !t3) return "";
4227
4227
  const r3 = parseUrl(e4);
4228
4228
  let n = r3.type;
@@ -4259,7 +4259,7 @@ Did you specify these with the most recent transformation maps first?`);
4259
4259
  return r3.scheme + "//" + r3.user + r3.host + r3.port + r3.path + s;
4260
4260
  }
4261
4261
  }
4262
- return resolve12;
4262
+ return resolve13;
4263
4263
  })();
4264
4264
  }, "./node_modules/.pnpm/@jridgewell+sourcemap-codec@1.5.5/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.umd.js"(e2, t2, r2) {
4265
4265
  var n;
@@ -47374,17 +47374,58 @@ 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 import_fs3 = require("fs");
47378
+ var import_os = require("os");
47379
+ var import_path3 = require("path");
47380
+ var REMEDY_ARROW = "\u2192";
47381
+ function framesOf(stack) {
47382
+ return (stack ?? "").split("\n").filter((line) => /^\s+at\s/.test(line));
47383
+ }
47384
+ function renderRefusal(error51) {
47385
+ const captured = error51.stack;
47386
+ Object.defineProperty(error51, "stack", {
47387
+ configurable: true,
47388
+ get: () => [error51.toString(), ...framesOf(captured)].join("\n"),
47389
+ set(value2) {
47390
+ Object.defineProperty(error51, "stack", { value: value2, writable: true, configurable: true });
47391
+ }
47392
+ });
47393
+ }
47377
47394
  var PenvError = class extends Error {
47378
47395
  name = "PenvError";
47379
47396
  /** A stable, machine-readable discriminator. */
47380
47397
  code;
47381
47398
  /** What the user should do about it. */
47382
47399
  remedy;
47400
+ /** The message alone, without the remedy the constructor folds into it. */
47401
+ summary;
47383
47402
  constructor(code, message, remedy) {
47384
47403
  super(remedy ? `${message}
47385
47404
  ${remedy}` : message);
47386
47405
  this.code = code;
47387
47406
  this.remedy = remedy;
47407
+ this.summary = message;
47408
+ renderRefusal(this);
47409
+ }
47410
+ /**
47411
+ * Drops every frame from `below` upward, so the stack shows where the
47412
+ * application called in rather than the path penv took inside itself. The
47413
+ * caller names its own entry point; nothing here guesses which files are
47414
+ * penv's.
47415
+ */
47416
+ hideFramesAbove(below) {
47417
+ const capture = Error.captureStackTrace;
47418
+ if (capture !== void 0) {
47419
+ capture(this, below);
47420
+ renderRefusal(this);
47421
+ }
47422
+ return this;
47423
+ }
47424
+ /** The refusal as every penv command prints it: the message, then the remedy. */
47425
+ toString() {
47426
+ const head = `${this.name}: ${this.summary}`;
47427
+ return this.remedy === void 0 ? head : `${head}
47428
+ ${REMEDY_ARROW} ${this.remedy}`;
47388
47429
  }
47389
47430
  };
47390
47431
  var FilenameGrammarError = class extends PenvError {
@@ -47398,10 +47439,10 @@ var FilenameGrammarError = class extends PenvError {
47398
47439
  var ReservedTokenError = class extends PenvError {
47399
47440
  name = "ReservedTokenError";
47400
47441
  token;
47401
- constructor(subject, token, where) {
47442
+ constructor(subject, token, where2) {
47402
47443
  super(
47403
47444
  "RESERVED_TOKEN",
47404
- `The ${subject} name \`${token}\` in ${where} is a reserved token`,
47445
+ `The ${subject} name \`${token}\` in ${where2} is a reserved token`,
47405
47446
  `Filenames are split on \`.\`, so \`${token}\` cannot be a ${subject} name. Rename it.`
47406
47447
  );
47407
47448
  this.token = token;
@@ -48912,6 +48953,7 @@ var RECORDS_PATH2 = `${STATE_PATH}/records`;
48912
48953
  var STATE_GITIGNORE_PATH = `${STATE_PATH}/.gitignore`;
48913
48954
  var MANIFEST_PATH = `${STATE_PATH}/manifest.json`;
48914
48955
  var EXTENSIONS_PATH = `${STATE_PATH}/extensions`;
48956
+ var LOCAL_EXTENSIONS_PATH = `${STATE_PATH}/local-extensions.json`;
48915
48957
  var CUTOVER_FILE = "cutover.json";
48916
48958
  var ROLLBACK_DIR = "rollback";
48917
48959
  var CUTOVER_PATH = `${STATE_PATH}/${CUTOVER_FILE}`;
@@ -48920,6 +48962,9 @@ var ROLLBACK_DOTENV_PATH = `${ROLLBACK_PATH}/dotenv`;
48920
48962
  function penvDir(projectRoot) {
48921
48963
  return (0, import_path2.resolve)(projectRoot, PENV_DIR);
48922
48964
  }
48965
+ function localExtensionsFile(projectRoot) {
48966
+ return (0, import_path2.resolve)(projectRoot, ...LOCAL_EXTENSIONS_PATH.split("/"));
48967
+ }
48923
48968
  function recordsDir(projectRoot) {
48924
48969
  return (0, import_path2.resolve)(projectRoot, ...RECORDS_PATH2.split("/"));
48925
48970
  }
@@ -48964,10 +49009,60 @@ ${inside === void 0 ? "" : `!${inside}
48964
49009
  ${ROLLBACK_DIR}/
48965
49010
  `;
48966
49011
  }
49012
+ function invalid(problem) {
49013
+ return new PenvError(
49014
+ "LOCAL_EXTENSIONS_INVALID",
49015
+ `${LOCAL_EXTENSIONS_PATH} does not hold the list penv writes: ${problem}`,
49016
+ "It is a JSON array of package names. Delete it and run `penv add --local <package>` for each extension this project develops."
49017
+ );
49018
+ }
49019
+ function parseLocalExtensions(text) {
49020
+ let parsed;
49021
+ try {
49022
+ parsed = JSON.parse(text);
49023
+ } catch {
49024
+ throw invalid("it is not valid JSON");
49025
+ }
49026
+ if (!Array.isArray(parsed)) {
49027
+ throw invalid("its root is not an array");
49028
+ }
49029
+ for (const name of parsed) {
49030
+ if (typeof name !== "string" || name.trim() === "") {
49031
+ throw invalid("it holds something that is not a package name");
49032
+ }
49033
+ }
49034
+ return normalize(parsed);
49035
+ }
49036
+ function normalize(names) {
49037
+ return [...new Set(names.map((name) => name.trim()))].sort();
49038
+ }
49039
+ var MANIFEST_PATH2 = ".penv/state/manifest.json";
48967
49040
  var MANIFEST_FORMAT = 1;
48968
49041
  var ENGINE_PACKAGE = "@penvhq/cli";
48969
49042
  var OFFICIAL_SCOPE = "@penvhq/";
48970
49043
  var DEFAULT_REGISTRY_HOSTS = ["registry.npmjs.org", "registry.npmjs.com", "npmjs.org"];
49044
+ var ManifestError = class extends PenvError {
49045
+ name = "ManifestError";
49046
+ };
49047
+ var UnsupportedManifestFormatError = class _UnsupportedManifestFormatError extends PenvError {
49048
+ name = "UnsupportedManifestFormatError";
49049
+ /** The format the file declares. */
49050
+ found;
49051
+ /** The format this engine implements. */
49052
+ supported = MANIFEST_FORMAT;
49053
+ constructor(found, update) {
49054
+ super(
49055
+ "MANIFEST_FORMAT_UNSUPPORTED",
49056
+ `${MANIFEST_PATH2} is format ${found}, and this penv understands format ${MANIFEST_FORMAT}`,
49057
+ update === void 0 ? "Update penv, then run the command again." : `Run \`${update.updateCommand}\`, then \`${update.invokedCommand}\` again.`
49058
+ );
49059
+ this.found = found;
49060
+ }
49061
+ /** The same refusal, with the launcher's own update command and the user's command. */
49062
+ withLauncherUpdate(update) {
49063
+ return new _UnsupportedManifestFormatError(this.found, update);
49064
+ }
49065
+ };
48971
49066
  var EXACT_VERSION = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
48972
49067
  var INTEGRITY = /^sha512-[A-Za-z0-9+/]{86}==$/;
48973
49068
  var PACKAGE_NAME2 = /^(?:@[a-z0-9~-][a-z0-9._~-]*\/)?[a-z0-9~-][a-z0-9._~-]*$/;
@@ -49107,6 +49202,224 @@ var MANIFEST = external_exports.strictObject({
49107
49202
  }),
49108
49203
  extensions: EXTENSIONS2
49109
49204
  });
49205
+ var FORBIDDEN = [
49206
+ {
49207
+ pattern: /(?:^|[\s"'=(])(?:\/(?:[A-Za-z0-9._-]+\/)+|~\/|[A-Za-z]:[\\/]|\\\\[A-Za-z0-9._-]+\\)/,
49208
+ code: "MANIFEST_ABSOLUTE_PATH",
49209
+ problem: "holds an absolute path",
49210
+ remedy: "Remove it. The manifest is committed and read on every machine that clones the repo, so it names packages and versions only \u2014 never a location on one of them."
49211
+ },
49212
+ {
49213
+ pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----|\b(?:gh[pousr]_[A-Za-z0-9]{16,}|github_pat_[A-Za-z0-9_]{20,}|xox[abopsr]-[A-Za-z0-9-]{10,}|AKIA[0-9A-Z]{16}|hv[sb]\.[A-Za-z0-9._-]{10,}|sk-[A-Za-z0-9]{16,}|sk_live_[A-Za-z0-9]{10,}|eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,})\b|:\/\/[^/\s:@]+:[^/\s@]+@/,
49214
+ code: "MANIFEST_CREDENTIAL",
49215
+ problem: "holds something shaped like a credential",
49216
+ remedy: "Remove it and rotate that credential. Anything committed here is readable by everyone with the repository, and by everyone who ever had it."
49217
+ },
49218
+ {
49219
+ pattern: /\b[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+\s*=|\b(?:postgres|postgresql|mysql|mongodb|redis|amqps?|s3)(?:\+[a-z]+)?:\/\//,
49220
+ code: "MANIFEST_PROVIDER_CONFIG",
49221
+ problem: "holds provider configuration or a value",
49222
+ remedy: "Move it to penv.config.ts. The manifest records which extension is pinned and why it is trusted, never how it is configured or what it holds."
49223
+ }
49224
+ ];
49225
+ var UNSCANNED_KEY = "integrity";
49226
+ function pathText(path) {
49227
+ return path.map((segment, index) => {
49228
+ if (typeof segment === "number") return `[${segment}]`;
49229
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(segment)) return `[${JSON.stringify(segment)}]`;
49230
+ return index === 0 ? segment : `.${segment}`;
49231
+ }).join("");
49232
+ }
49233
+ function fieldName(path) {
49234
+ return path.length === 0 ? "root" : `\`${pathText(path)}\``;
49235
+ }
49236
+ function isPlainObject22(value2) {
49237
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
49238
+ }
49239
+ function valueAt(root, path) {
49240
+ let current = root;
49241
+ for (const segment of path) {
49242
+ if (Array.isArray(current) && typeof segment === "number") {
49243
+ current = current[segment];
49244
+ continue;
49245
+ }
49246
+ if (!isPlainObject22(current)) return void 0;
49247
+ current = current[String(segment)];
49248
+ }
49249
+ return current;
49250
+ }
49251
+ function scanForbidden(value2, path) {
49252
+ if (typeof value2 === "string") {
49253
+ for (const rule of FORBIDDEN) {
49254
+ if (rule.pattern.test(value2)) {
49255
+ return new ManifestError(
49256
+ rule.code,
49257
+ `${fieldName(path)} in ${MANIFEST_PATH2} ${rule.problem}: \`${value2}\``,
49258
+ rule.remedy
49259
+ );
49260
+ }
49261
+ }
49262
+ return void 0;
49263
+ }
49264
+ if (Array.isArray(value2)) {
49265
+ for (const [index, item] of value2.entries()) {
49266
+ const found = scanForbidden(item, [...path, index]);
49267
+ if (found) return found;
49268
+ }
49269
+ return void 0;
49270
+ }
49271
+ if (isPlainObject22(value2)) {
49272
+ for (const [key, item] of Object.entries(value2)) {
49273
+ if (key === UNSCANNED_KEY) continue;
49274
+ const found = scanForbidden(item, [...path, key]);
49275
+ if (found) return found;
49276
+ }
49277
+ }
49278
+ return void 0;
49279
+ }
49280
+ function sectionRemedy(path) {
49281
+ const [section, name] = path;
49282
+ if (section === "engine") {
49283
+ return `Restore it with \`git checkout ${MANIFEST_PATH2}\`, or write the exact version and the \`integrity\` npm published for that ${ENGINE_PACKAGE} release. penv runs the bytes this pin names, so it will not guess one.`;
49284
+ }
49285
+ if (section === "extensions" && typeof name === "string") {
49286
+ return `Run \`penv add ${name}\` to rewrite that entry.`;
49287
+ }
49288
+ return `Restore it \u2014 format ${MANIFEST_FORMAT} requires it.`;
49289
+ }
49290
+ function describeType2(value2) {
49291
+ if (value2 === null) return "null";
49292
+ if (Array.isArray(value2)) return "an array";
49293
+ return `a ${typeof value2}`;
49294
+ }
49295
+ function customParams(issue2) {
49296
+ if (issue2.code !== "custom") return void 0;
49297
+ const params = issue2.params;
49298
+ if (!isPlainObject22(params)) return void 0;
49299
+ const code = params.code;
49300
+ const remedy = params.remedy;
49301
+ if (typeof code !== "string" || typeof remedy !== "string") return void 0;
49302
+ return { code, remedy };
49303
+ }
49304
+ function toManifestError(issue2, raw) {
49305
+ const path = issue2.path;
49306
+ const custom2 = customParams(issue2);
49307
+ if (custom2) {
49308
+ return new ManifestError(
49309
+ custom2.code,
49310
+ `${fieldName(path)} in ${MANIFEST_PATH2} ${issue2.message}`,
49311
+ custom2.remedy
49312
+ );
49313
+ }
49314
+ switch (issue2.code) {
49315
+ case "unrecognized_keys": {
49316
+ const key = issue2.keys[0] ?? "";
49317
+ const where2 = path.length === 0 ? "at its root" : `in ${fieldName(path)}`;
49318
+ return new ManifestError(
49319
+ "MANIFEST_UNKNOWN_KEY",
49320
+ `${MANIFEST_PATH2} has an unknown key \`${key}\` ${where2}`,
49321
+ `Remove it. Format ${MANIFEST_FORMAT} is a closed shape, so a key penv does not know is either a typo or a file a newer penv wrote.`
49322
+ );
49323
+ }
49324
+ case "invalid_key":
49325
+ return new ManifestError(
49326
+ "MANIFEST_PACKAGE_NAME",
49327
+ `\`${String(path[path.length - 1] ?? "")}\` in ${MANIFEST_PATH2} is not an npm package name`,
49328
+ "Name the package exactly as npm does, e.g. `@acme/provider-consul`."
49329
+ );
49330
+ case "invalid_union":
49331
+ return new ManifestError(
49332
+ "MANIFEST_TRUST_TIER",
49333
+ `${fieldName(path)} in ${MANIFEST_PATH2} is \`${String(valueAt(raw, path))}\`, which is not a trust tier`,
49334
+ "Use `third-party` for a package published outside your organisation, or `private` for one your own team publishes."
49335
+ );
49336
+ case "invalid_value":
49337
+ return new ManifestError(
49338
+ "MANIFEST_FIELD_VALUE",
49339
+ `${fieldName(path)} in ${MANIFEST_PATH2} is \`${String(valueAt(raw, path))}\`, and format ${MANIFEST_FORMAT} requires \`${String(issue2.values[0])}\``,
49340
+ sectionRemedy(path)
49341
+ );
49342
+ case "invalid_format": {
49343
+ if (issue2.format !== "datetime") break;
49344
+ return new ManifestError(
49345
+ "MANIFEST_TIMESTAMP",
49346
+ `${fieldName(path)} in ${MANIFEST_PATH2} is \`${String(valueAt(raw, path))}\`, which is not a UTC timestamp`,
49347
+ "Write it as ISO 8601 in UTC, e.g. `2026-08-17T00:00:00Z`."
49348
+ );
49349
+ }
49350
+ default:
49351
+ break;
49352
+ }
49353
+ const actual = valueAt(raw, path);
49354
+ if (actual === void 0) {
49355
+ return new ManifestError(
49356
+ "MANIFEST_FIELD_MISSING",
49357
+ `${MANIFEST_PATH2} is missing ${fieldName(path)}`,
49358
+ sectionRemedy(path)
49359
+ );
49360
+ }
49361
+ return new ManifestError(
49362
+ "MANIFEST_FIELD_TYPE",
49363
+ `${fieldName(path)} in ${MANIFEST_PATH2} is ${describeType2(actual)}, not what format ${MANIFEST_FORMAT} declares`,
49364
+ sectionRemedy(path)
49365
+ );
49366
+ }
49367
+ function assertFormat(root) {
49368
+ const format = root.format;
49369
+ if (typeof format === "number" && Number.isInteger(format) && format > 0) {
49370
+ if (format !== MANIFEST_FORMAT) {
49371
+ throw new UnsupportedManifestFormatError(format);
49372
+ }
49373
+ return;
49374
+ }
49375
+ const declared = format === void 0 ? "no format" : `\`${String(format)}\` as its format`;
49376
+ throw new ManifestError(
49377
+ "MANIFEST_FORMAT_INVALID",
49378
+ `${MANIFEST_PATH2} declares ${declared}, so penv cannot tell how to read it`,
49379
+ `Restore the key as \`"format": ${MANIFEST_FORMAT}\` \u2014 every manifest says its format first.`
49380
+ );
49381
+ }
49382
+ function validateManifest(value2) {
49383
+ if (!isPlainObject22(value2)) {
49384
+ throw new ManifestError(
49385
+ "MANIFEST_ROOT",
49386
+ `${MANIFEST_PATH2} holds ${describeType2(value2)} at its root, not a manifest object`,
49387
+ `Restore it with \`git checkout ${MANIFEST_PATH2}\` \u2014 penv writes this file, and every manifest is a JSON object.`
49388
+ );
49389
+ }
49390
+ assertFormat(value2);
49391
+ const forbidden = scanForbidden(value2, []);
49392
+ if (forbidden) {
49393
+ throw forbidden;
49394
+ }
49395
+ const result2 = MANIFEST.safeParse(value2);
49396
+ if (!result2.success) {
49397
+ const issue2 = result2.error.issues[0];
49398
+ if (issue2 === void 0) {
49399
+ throw new ManifestError(
49400
+ "MANIFEST_INVALID",
49401
+ `${MANIFEST_PATH2} is not a format ${MANIFEST_FORMAT} manifest`,
49402
+ `Restore it with \`git checkout ${MANIFEST_PATH2}\` \u2014 penv writes this file, and it is committed.`
49403
+ );
49404
+ }
49405
+ throw toManifestError(issue2, value2);
49406
+ }
49407
+ return result2.data;
49408
+ }
49409
+ function parseManifest(text) {
49410
+ let parsed;
49411
+ try {
49412
+ parsed = JSON.parse(text);
49413
+ } catch (cause) {
49414
+ const detail = cause instanceof Error ? cause.message : String(cause);
49415
+ throw new ManifestError(
49416
+ "MANIFEST_PARSE",
49417
+ `${MANIFEST_PATH2} is not valid JSON: ${detail}`,
49418
+ `Restore it with \`git checkout ${MANIFEST_PATH2}\` \u2014 penv writes this file, so a syntax error in it is an edit that went wrong.`
49419
+ );
49420
+ }
49421
+ return validateManifest(parsed);
49422
+ }
49110
49423
  var ENVIRONMENTS_KEY = "environments";
49111
49424
  var PRIORITY_KEYS = ["description", "owner"];
49112
49425
  function isPlainObject3(value2) {
@@ -49489,6 +49802,80 @@ function completeRotation(meta3, environment, nowIso) {
49489
49802
  };
49490
49803
  return { ...base, environments };
49491
49804
  }
49805
+ var PENV_HOME_VAR = "PENV_HOME";
49806
+ function penvHome(env) {
49807
+ const declared = env[PENV_HOME_VAR];
49808
+ if (declared !== void 0 && declared.trim() !== "") {
49809
+ return (0, import_path3.resolve)(declared);
49810
+ }
49811
+ return (0, import_path3.join)((0, import_os.homedir)(), ".penv");
49812
+ }
49813
+ function packageDir(home, kind, name, version2) {
49814
+ const bucket = (0, import_path3.resolve)(home, kind);
49815
+ const dir = (0, import_path3.resolve)(bucket, ...name.split("/"), version2);
49816
+ if (!dir.startsWith(bucket + import_path3.sep)) {
49817
+ throw new PenvError(
49818
+ "PENV_HOME_ESCAPE",
49819
+ `\`${name}\` at \`${version2}\` resolves to ${dir}, which is outside ${bucket}`,
49820
+ "Name the package exactly as npm does, e.g. `@penvhq/provider-vault`."
49821
+ );
49822
+ }
49823
+ return dir;
49824
+ }
49825
+ var IMPORTABLE = /* @__PURE__ */ new Set([".js", ".mjs", ".cjs", ".node"]);
49826
+ function isImportableEntry(file2) {
49827
+ return IMPORTABLE.has((0, import_path3.extname)(file2).toLowerCase());
49828
+ }
49829
+ var IMPORT_CONDITIONS = ["node", "import", "default"];
49830
+ function isPlainObject4(value2) {
49831
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
49832
+ }
49833
+ function pickCondition(value2) {
49834
+ if (typeof value2 === "string") {
49835
+ return value2;
49836
+ }
49837
+ if (!isPlainObject4(value2)) {
49838
+ return void 0;
49839
+ }
49840
+ for (const condition of IMPORT_CONDITIONS) {
49841
+ const picked = pickCondition(value2[condition]);
49842
+ if (picked !== void 0) {
49843
+ return picked;
49844
+ }
49845
+ }
49846
+ return void 0;
49847
+ }
49848
+ function mainExport(exports2) {
49849
+ if (typeof exports2 === "string") {
49850
+ return exports2;
49851
+ }
49852
+ if (!isPlainObject4(exports2)) {
49853
+ return void 0;
49854
+ }
49855
+ return Object.keys(exports2).some((key) => key.startsWith(".")) ? pickCondition(exports2["."]) : pickCondition(exports2);
49856
+ }
49857
+ function stringField(source, key) {
49858
+ if (!isPlainObject4(source)) {
49859
+ return void 0;
49860
+ }
49861
+ const value2 = source[key];
49862
+ return typeof value2 === "string" && value2.trim() !== "" ? value2.trim() : void 0;
49863
+ }
49864
+ function packageEntry(dir) {
49865
+ let parsed;
49866
+ try {
49867
+ parsed = JSON.parse((0, import_fs3.readFileSync)((0, import_path3.join)(dir, "package.json"), "utf8"));
49868
+ } catch {
49869
+ return void 0;
49870
+ }
49871
+ const declared = mainExport(isPlainObject4(parsed) ? parsed.exports : void 0) ?? stringField(parsed, "main") ?? "index.js";
49872
+ const root = (0, import_path3.resolve)(dir);
49873
+ const file2 = (0, import_path3.resolve)(root, ...declared.split("/"));
49874
+ if (!file2.startsWith(root + import_path3.sep)) {
49875
+ return void 0;
49876
+ }
49877
+ return { file: file2, importable: isImportableEntry(file2) && (0, import_fs3.existsSync)(file2) };
49878
+ }
49492
49879
 
49493
49880
  // src/bin.ts
49494
49881
  var import_jiti = __toESM(require_jiti2(), 1);
@@ -49969,7 +50356,7 @@ function _getBuiltinFlags(long, short, userNames, userAliases) {
49969
50356
 
49970
50357
  // src/commands/artifact.ts
49971
50358
  init_cjs_shims();
49972
- var import_node_fs6 = require("fs");
50359
+ var import_node_fs7 = require("fs");
49973
50360
  var import_node_path7 = require("path");
49974
50361
 
49975
50362
  // ../runtime/dist/index.js
@@ -49980,8 +50367,8 @@ init_cjs_shims();
49980
50367
 
49981
50368
  // ../providers/filesystem/dist/index.js
49982
50369
  init_cjs_shims();
49983
- var import_fs3 = require("fs");
49984
- var import_path3 = require("path");
50370
+ var import_fs4 = require("fs");
50371
+ var import_path4 = require("path");
49985
50372
  var META_FORMAT = "json";
49986
50373
  function isErrnoCode(error51, code) {
49987
50374
  return error51 instanceof Error && error51.code === code;
@@ -49991,7 +50378,7 @@ var FilesystemProvider = class {
49991
50378
  #root;
49992
50379
  #config;
49993
50380
  constructor(options) {
49994
- this.#root = (0, import_path3.resolve)(options.root);
50381
+ this.#root = (0, import_path4.resolve)(options.root);
49995
50382
  this.#config = options.config;
49996
50383
  }
49997
50384
  /** The records directory this provider is rooted at, absolute. */
@@ -50061,19 +50448,19 @@ var FilesystemProvider = class {
50061
50448
  /** Deletes a file that may not be there, and tidies the namespace it emptied. */
50062
50449
  #unlink(path) {
50063
50450
  try {
50064
- (0, import_fs3.unlinkSync)(path);
50451
+ (0, import_fs4.unlinkSync)(path);
50065
50452
  } catch (error51) {
50066
50453
  if (!isErrnoCode(error51, "ENOENT")) throw error51;
50067
50454
  return;
50068
50455
  }
50069
- this.#pruneEmpty((0, import_path3.dirname)(path));
50456
+ this.#pruneEmpty((0, import_path4.dirname)(path));
50070
50457
  }
50071
50458
  #pathOf(relativePosix) {
50072
- return (0, import_path3.join)(this.#root, ...relativePosix.split("/"));
50459
+ return (0, import_path4.join)(this.#root, ...relativePosix.split("/"));
50073
50460
  }
50074
50461
  #readFile(path) {
50075
50462
  try {
50076
- return (0, import_fs3.readFileSync)(path, "utf8");
50463
+ return (0, import_fs4.readFileSync)(path, "utf8");
50077
50464
  } catch (error51) {
50078
50465
  if (isErrnoCode(error51, "ENOENT") || isErrnoCode(error51, "EISDIR")) return void 0;
50079
50466
  throw error51;
@@ -50081,32 +50468,32 @@ var FilesystemProvider = class {
50081
50468
  }
50082
50469
  #writeFile(relativePosix, contents) {
50083
50470
  const path = this.#pathOf(relativePosix);
50084
- (0, import_fs3.mkdirSync)((0, import_path3.dirname)(path), { recursive: true });
50085
- (0, import_fs3.writeFileSync)(path, contents, "utf8");
50471
+ (0, import_fs4.mkdirSync)((0, import_path4.dirname)(path), { recursive: true });
50472
+ (0, import_fs4.writeFileSync)(path, contents, "utf8");
50086
50473
  }
50087
50474
  /** Namespaces are folders, so a namespace with no parameters left is no namespace. */
50088
50475
  #pruneEmpty(directory) {
50089
50476
  let current = directory;
50090
- while (current !== this.#root && current.startsWith(this.#root + import_path3.sep)) {
50477
+ while (current !== this.#root && current.startsWith(this.#root + import_path4.sep)) {
50091
50478
  try {
50092
- (0, import_fs3.rmdirSync)(current);
50479
+ (0, import_fs4.rmdirSync)(current);
50093
50480
  } catch {
50094
50481
  return;
50095
50482
  }
50096
- current = (0, import_path3.dirname)(current);
50483
+ current = (0, import_path4.dirname)(current);
50097
50484
  }
50098
50485
  }
50099
50486
  #walk(directory, namespace, out2) {
50100
50487
  let entries;
50101
50488
  try {
50102
- entries = (0, import_fs3.readdirSync)(directory, { withFileTypes: true });
50489
+ entries = (0, import_fs4.readdirSync)(directory, { withFileTypes: true });
50103
50490
  } catch (error51) {
50104
50491
  if (isErrnoCode(error51, "ENOENT")) return;
50105
50492
  throw error51;
50106
50493
  }
50107
50494
  for (const entry of [...entries].sort((a, b) => a.name < b.name ? -1 : 1)) {
50108
50495
  if (entry.isDirectory()) {
50109
- this.#walk((0, import_path3.join)(directory, entry.name), [...namespace, entry.name], out2);
50496
+ this.#walk((0, import_path4.join)(directory, entry.name), [...namespace, entry.name], out2);
50110
50497
  continue;
50111
50498
  }
50112
50499
  const relativePath = [...namespace, entry.name].join("/");
@@ -50139,11 +50526,13 @@ var RUN_MARKER = "PENV_RUN";
50139
50526
  var ENVIRONMENT_VARIABLE = "PENV_ENV";
50140
50527
  var DELIVERY_VARIABLE = "PENV_DELIVERY";
50141
50528
  var SNAPSHOT_VARIABLE = "PENV_SNAPSHOT";
50529
+ var LAUNCHER_HOME = "PENV_HOME";
50142
50530
  var CONTROL_VARIABLES = [
50143
50531
  RUN_MARKER,
50144
50532
  DELIVERY_VARIABLE,
50145
50533
  SCHEMA_HARVEST_ENV,
50146
- SNAPSHOT_VARIABLE
50534
+ SNAPSHOT_VARIABLE,
50535
+ LAUNCHER_HOME
50147
50536
  ];
50148
50537
  var RESERVED_VARIABLES = [...CONTROL_VARIABLES, ENVIRONMENT_VARIABLE];
50149
50538
  function assertDeliverableNames(refs, config2) {
@@ -50217,7 +50606,7 @@ function inject(input) {
50217
50606
  written += 1;
50218
50607
  continue;
50219
50608
  }
50220
- const defaulted = validated === void 0 ? void 0 : valueAt(validated, accessPath(ref));
50609
+ const defaulted = validated === void 0 ? void 0 : valueAt2(validated, accessPath(ref));
50221
50610
  if (defaulted !== void 0) {
50222
50611
  target[variable] = toEnvString(defaulted);
50223
50612
  written += 1;
@@ -50233,7 +50622,7 @@ function inject(input) {
50233
50622
  function slashId(ref) {
50234
50623
  return [...ref.namespace, ref.name].join("/");
50235
50624
  }
50236
- function valueAt(root, path) {
50625
+ function valueAt2(root, path) {
50237
50626
  let node2 = root;
50238
50627
  for (const key of path) {
50239
50628
  if (typeof node2 !== "object" || node2 === null) {
@@ -50434,14 +50823,14 @@ var startChild = (invocation) => {
50434
50823
  process.off(signal, handler);
50435
50824
  }
50436
50825
  };
50437
- const ended = new Promise((resolve12, reject) => {
50826
+ const ended = new Promise((resolve13, reject) => {
50438
50827
  child.on("error", (cause) => {
50439
50828
  release();
50440
50829
  reject(cannotStart(executable, cause, invocation.purpose));
50441
50830
  });
50442
50831
  child.on("exit", (code, signal) => {
50443
50832
  release();
50444
- resolve12({ exitCode: code ?? 1, signal });
50833
+ resolve13({ exitCode: code ?? 1, signal });
50445
50834
  });
50446
50835
  });
50447
50836
  return {
@@ -50704,7 +51093,7 @@ function installFailed(plan2) {
50704
51093
 
50705
51094
  // src/project.ts
50706
51095
  init_cjs_shims();
50707
- var import_node_fs3 = require("fs");
51096
+ var import_node_fs4 = require("fs");
50708
51097
  var import_node_path4 = require("path");
50709
51098
 
50710
51099
  // src/env-flags.ts
@@ -50767,14 +51156,15 @@ function environmentFromShorthand(config2, candidates, explicit) {
50767
51156
 
50768
51157
  // src/registry.ts
50769
51158
  init_cjs_shims();
51159
+ var import_node_fs3 = require("fs");
50770
51160
  var import_node_module = require("module");
50771
51161
  var import_node_path3 = require("path");
50772
51162
  var import_node_url = require("url");
50773
51163
 
50774
51164
  // ../providers/mock/dist/index.js
50775
51165
  init_cjs_shims();
50776
- var import_fs4 = require("fs");
50777
- var import_path4 = require("path");
51166
+ var import_fs5 = require("fs");
51167
+ var import_path5 = require("path");
50778
51168
  function scopeKey(scope) {
50779
51169
  switch (scope.kind) {
50780
51170
  case "unscoped":
@@ -50867,7 +51257,7 @@ var MockProvider = class {
50867
51257
  #load() {
50868
51258
  let contents;
50869
51259
  try {
50870
- contents = (0, import_fs4.readFileSync)(this.#storePath, "utf8");
51260
+ contents = (0, import_fs5.readFileSync)(this.#storePath, "utf8");
50871
51261
  } catch (error51) {
50872
51262
  if (error51.code === "ENOENT") return emptyStore();
50873
51263
  throw error51;
@@ -50879,8 +51269,8 @@ var MockProvider = class {
50879
51269
  };
50880
51270
  }
50881
51271
  #save(store) {
50882
- (0, import_fs4.mkdirSync)((0, import_path4.dirname)(this.#storePath), { recursive: true });
50883
- (0, import_fs4.writeFileSync)(this.#storePath, JSON.stringify(store, null, 2), "utf8");
51272
+ (0, import_fs5.mkdirSync)((0, import_path5.dirname)(this.#storePath), { recursive: true });
51273
+ (0, import_fs5.writeFileSync)(this.#storePath, JSON.stringify(store, null, 2), "utf8");
50884
51274
  }
50885
51275
  };
50886
51276
  function createMockProvider(options) {
@@ -50928,19 +51318,12 @@ async function createSourceProvider(type, context) {
50928
51318
  return loadPluginProvider(type, context);
50929
51319
  }
50930
51320
  async function loadPluginProvider(type, context) {
50931
- const resolved = resolvePlugin(type, context.root);
50932
- if (resolved === void 0) {
50933
- throw unknownProvider(type, context.environment);
50934
- }
51321
+ const path = resolveExtension(type, context.root, context.environment);
50935
51322
  let mod;
50936
51323
  try {
50937
- mod = await importPlugin(resolved);
50938
- } catch {
50939
- throw new PenvError(
50940
- "PROVIDER_PLUGIN_LOAD",
50941
- `The provider package \`${type}\` failed to load`,
50942
- "It resolved but threw while importing. Check it builds and its dependencies are installed."
50943
- );
51324
+ mod = await importPlugin(path);
51325
+ } catch (cause) {
51326
+ throw providerLoadFailed(type, path, cause);
50944
51327
  }
50945
51328
  const factory = mod[PLUGIN_FACTORY_EXPORT];
50946
51329
  if (typeof factory !== "function") {
@@ -50954,16 +51337,72 @@ async function loadPluginProvider(type, context) {
50954
51337
  assertSatisfiesContract(provider, type);
50955
51338
  return provider;
50956
51339
  }
50957
- function assertProvidersRegistered(config2, projectRoot) {
51340
+ function assertProvidersRegistered(config2, projectRoot, options) {
51341
+ const local = localExtensions(projectRoot);
51342
+ const ci = options?.ci ?? isCi(process.env.CI);
50958
51343
  for (const [environment, provider] of Object.entries(config2.providers)) {
50959
51344
  if (isProviderRegistered(provider.type)) {
50960
51345
  continue;
50961
51346
  }
50962
- if (resolvePlugin(provider.type, projectRoot) === void 0) {
50963
- throw unknownProvider(provider.type, environment);
51347
+ if (ci && local.includes(provider.type)) {
51348
+ throw localExtensionInCi(provider.type, environment);
50964
51349
  }
51350
+ resolveExtension(provider.type, projectRoot, environment, local);
50965
51351
  }
50966
51352
  }
51353
+ function resolveExtension(type, projectRoot, environment, local = localExtensions(projectRoot)) {
51354
+ const fromProject = resolvePlugin(type, projectRoot);
51355
+ if (local.includes(type)) {
51356
+ if (fromProject === void 0) {
51357
+ throw localExtensionUnresolved(type, projectRoot, environment);
51358
+ }
51359
+ return fromProject;
51360
+ }
51361
+ if (fromProject !== void 0) {
51362
+ return fromProject;
51363
+ }
51364
+ const version2 = pinnedVersion(type, projectRoot);
51365
+ if (version2 === void 0) {
51366
+ throw unknownProvider(type, environment);
51367
+ }
51368
+ const stored = storedExtension(type, version2);
51369
+ if (stored === void 0) {
51370
+ throw extensionNotInstalled(type, version2, environment);
51371
+ }
51372
+ return stored;
51373
+ }
51374
+ function pinnedVersion(type, projectRoot) {
51375
+ let manifest;
51376
+ try {
51377
+ manifest = parseManifest((0, import_node_fs3.readFileSync)((0, import_node_path3.join)(projectRoot, ...MANIFEST_PATH.split("/")), "utf8"));
51378
+ } catch {
51379
+ return void 0;
51380
+ }
51381
+ return manifest.extensions[type]?.version;
51382
+ }
51383
+ function storedExtension(type, version2) {
51384
+ const entry = packageEntry(packageDir(penvHome(process.env), "extensions", type, version2));
51385
+ return entry?.file;
51386
+ }
51387
+ function localExtensions(projectRoot) {
51388
+ let text;
51389
+ try {
51390
+ text = (0, import_node_fs3.readFileSync)(localExtensionsFile(projectRoot), "utf8");
51391
+ } catch {
51392
+ return [];
51393
+ }
51394
+ return parseLocalExtensions(text);
51395
+ }
51396
+ function isCi(value2) {
51397
+ return value2 !== void 0 && value2 !== "" && value2 !== "0" && value2.toLowerCase() !== "false";
51398
+ }
51399
+ function localExtensionInCi(type, environment) {
51400
+ return new PenvError(
51401
+ "LOCAL_EXTENSION_IN_CI",
51402
+ `The provider \`${type}\` for environment ${environment} is a local extension, and this is CI`,
51403
+ `${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.`
51404
+ );
51405
+ }
50967
51406
  function resolvePlugin(specifier, fromDir) {
50968
51407
  try {
50969
51408
  const require2 = (0, import_node_module.createRequire)((0, import_node_path3.resolve)(fromDir, "noop.js"));
@@ -50995,13 +51434,37 @@ function assertSatisfiesContract(provider, specifier) {
50995
51434
  }
50996
51435
  }
50997
51436
  }
51437
+ function where(environment) {
51438
+ return environment === void 0 ? "" : ` for environment ${environment}`;
51439
+ }
50998
51440
  function unknownProvider(type, environment) {
50999
51441
  const preinstalled = [...REGISTRY.keys()].map((name) => `\`${name}\``).join(", ");
51000
- const where = environment === void 0 ? "" : ` for environment ${environment}`;
51001
51442
  return new PenvError(
51002
51443
  "UNKNOWN_PROVIDER",
51003
- `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.`
51444
+ `The provider \`${type}\`${where(environment)} in penv.config.ts is nowhere penv looks for it`,
51445
+ `Run \`penv add ${type}\` to pin a release, or \`penv add --local ${type}\` if this repository is the one that builds it. penv looks in ${LOCAL_EXTENSIONS_PATH}, this project's node_modules, and then $PENV_HOME at the version ${MANIFEST_PATH} pins. The CLI ships ${preinstalled} pre-installed.`
51446
+ );
51447
+ }
51448
+ function extensionNotInstalled(type, version2, environment) {
51449
+ return new PenvError(
51450
+ "EXTENSION_NOT_INSTALLED",
51451
+ `${MANIFEST_PATH} pins \`${type}\` ${version2}${where(environment)}, and it is not installed in ${penvHome(process.env)}`,
51452
+ "Run `penv install` \u2014 it downloads and verifies every version the manifest pins, extensions included."
51453
+ );
51454
+ }
51455
+ function localExtensionUnresolved(type, projectRoot, environment) {
51456
+ return new PenvError(
51457
+ "LOCAL_EXTENSION_UNRESOLVED",
51458
+ `${LOCAL_EXTENSIONS_PATH} records \`${type}\`${where(environment)} as a package this project develops, and it does not resolve from ${projectRoot}`,
51459
+ `Add it as a dependency of the root (a workspace link is one) and run \`pnpm install\`, or drop the name from ${LOCAL_EXTENSIONS_PATH} if this project no longer builds it.`
51460
+ );
51461
+ }
51462
+ function providerLoadFailed(type, path, cause) {
51463
+ const detail = cause instanceof Error ? cause.message : String(cause);
51464
+ return new PenvError(
51465
+ "PROVIDER_PLUGIN_LOAD",
51466
+ `The provider package \`${type}\` failed to load from ${path}: ${detail}`,
51467
+ "penv imports that file exactly as it stands, with no transform, so it has to be built JavaScript with its dependencies installed."
51005
51468
  );
51006
51469
  }
51007
51470
 
@@ -51031,10 +51494,10 @@ function localTree(project) {
51031
51494
  }
51032
51495
  function selfContainedSchemaModule(root, schemaFile) {
51033
51496
  const file2 = (0, import_node_path4.join)(root, ...schemaFile.split("/"));
51034
- if (!(0, import_node_fs3.existsSync)(file2)) {
51497
+ if (!(0, import_node_fs4.existsSync)(file2)) {
51035
51498
  return void 0;
51036
51499
  }
51037
- const source = (0, import_node_fs3.readFileSync)(file2, "utf8");
51500
+ const source = (0, import_node_fs4.readFileSync)(file2, "utf8");
51038
51501
  return source.includes("PenvSchemaShape") || source.includes("z.object") ? schemaFile : void 0;
51039
51502
  }
51040
51503
  function schemaShapeFileOf(project) {
@@ -51271,10 +51734,7 @@ function writeError(lines) {
51271
51734
  }
51272
51735
  function reportError(error51) {
51273
51736
  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}
51737
+ process.stderr.write(`${err.red(CROSS)} ${error51.summary}
51278
51738
  `);
51279
51739
  if (error51.remedy !== void 0) {
51280
51740
  process.stderr.write(` ${err.cyan("\u2192")} ${error51.remedy}
@@ -51305,13 +51765,13 @@ async function guard(run) {
51305
51765
 
51306
51766
  // src/commands/run.ts
51307
51767
  init_cjs_shims();
51308
- var import_node_fs5 = require("fs");
51768
+ var import_node_fs6 = require("fs");
51309
51769
  var import_node_module2 = require("module");
51310
51770
  var import_node_path6 = require("path");
51311
51771
 
51312
51772
  // src/dotenv-files.ts
51313
51773
  init_cjs_shims();
51314
- var import_node_fs4 = require("fs");
51774
+ var import_node_fs5 = require("fs");
51315
51775
  var SHARED = ".env";
51316
51776
  var LOCAL2 = "local";
51317
51777
  var NOT_ENVIRONMENTS = [
@@ -51370,7 +51830,7 @@ function order(file2) {
51370
51830
  function discoverDotenvFiles(root) {
51371
51831
  let entries;
51372
51832
  try {
51373
- entries = (0, import_node_fs4.readdirSync)(root, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name);
51833
+ entries = (0, import_node_fs5.readdirSync)(root, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name);
51374
51834
  } catch {
51375
51835
  return [];
51376
51836
  }
@@ -52093,7 +52553,7 @@ function assertNoActiveDotenv(project) {
52093
52553
  );
52094
52554
  }
52095
52555
  var VARIABLE2 = /^[A-Za-z_][A-Za-z0-9_]*$/;
52096
- function isPlainObject4(value2) {
52556
+ function isPlainObject5(value2) {
52097
52557
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
52098
52558
  }
52099
52559
  function packageManifest(specifier, root) {
@@ -52105,10 +52565,10 @@ function packageManifest(specifier, root) {
52105
52565
  }
52106
52566
  for (; ; ) {
52107
52567
  const file2 = (0, import_node_path6.join)(directory, "package.json");
52108
- if ((0, import_node_fs5.existsSync)(file2)) {
52568
+ if ((0, import_node_fs6.existsSync)(file2)) {
52109
52569
  try {
52110
- const parsed = JSON.parse((0, import_node_fs5.readFileSync)(file2, "utf8"));
52111
- if (isPlainObject4(parsed) && parsed.name === specifier) {
52570
+ const parsed = JSON.parse((0, import_node_fs6.readFileSync)(file2, "utf8"));
52571
+ if (isPlainObject5(parsed) && parsed.name === specifier) {
52112
52572
  return parsed;
52113
52573
  }
52114
52574
  } catch {
@@ -52129,7 +52589,7 @@ function declaredCredentials(config2, root) {
52129
52589
  continue;
52130
52590
  }
52131
52591
  const penv = packageManifest(provider.type, root)?.penv;
52132
- const credentials = isPlainObject4(penv) ? penv.credentials : void 0;
52592
+ const credentials = isPlainObject5(penv) ? penv.credentials : void 0;
52133
52593
  if (credentials === void 0) {
52134
52594
  continue;
52135
52595
  }
@@ -52180,7 +52640,7 @@ function snapshotPath(host) {
52180
52640
  }
52181
52641
  function readSnapshot(path) {
52182
52642
  try {
52183
- return (0, import_node_fs5.readFileSync)(path, "utf8");
52643
+ return (0, import_node_fs6.readFileSync)(path, "utf8");
52184
52644
  } catch {
52185
52645
  throw new PenvError(
52186
52646
  "RUN_SNAPSHOT_MISSING",
@@ -52259,11 +52719,11 @@ function watchProject(project, onChange) {
52259
52719
  timer = setTimeout(onChange, DEBOUNCE_MS);
52260
52720
  };
52261
52721
  const add = (target, recursive, only) => {
52262
- if (!(0, import_node_fs5.existsSync)(target)) {
52722
+ if (!(0, import_node_fs6.existsSync)(target)) {
52263
52723
  return;
52264
52724
  }
52265
52725
  try {
52266
- const watcher = (0, import_node_fs5.watch)(target, { recursive }, (_event, filename) => {
52726
+ const watcher = (0, import_node_fs6.watch)(target, { recursive }, (_event, filename) => {
52267
52727
  if (only !== void 0 && (filename === null || (0, import_node_path6.basename)(filename) !== only)) {
52268
52728
  return;
52269
52729
  }
@@ -52526,8 +52986,8 @@ ${lines}`,
52526
52986
  keySource: keySourceIdentifier(project.config, environment),
52527
52987
  values
52528
52988
  };
52529
- (0, import_node_fs6.mkdirSync)((0, import_node_path7.dirname)(file2), { recursive: true });
52530
- (0, import_node_fs6.writeFileSync)(file2, serializeArtifact(artifact), "utf8");
52989
+ (0, import_node_fs7.mkdirSync)((0, import_node_path7.dirname)(file2), { recursive: true });
52990
+ (0, import_node_fs7.writeFileSync)(file2, serializeArtifact(artifact), "utf8");
52531
52991
  const inside = (0, import_node_path7.relative)(project.root, file2);
52532
52992
  return {
52533
52993
  file: file2,
@@ -52597,7 +53057,7 @@ init_cjs_shims();
52597
53057
 
52598
53058
  // src/cutover.ts
52599
53059
  init_cjs_shims();
52600
- var import_node_fs7 = require("fs");
53060
+ var import_node_fs8 = require("fs");
52601
53061
  var import_node_path8 = require("path");
52602
53062
  var CUTOVER_FORMAT = 1;
52603
53063
  function fileFor(root, relativePosix) {
@@ -52615,7 +53075,7 @@ function cutoverRoot(cwd) {
52615
53075
  }
52616
53076
  function bundledFiles(root) {
52617
53077
  try {
52618
- return (0, import_node_fs7.readdirSync)(bundleDir(root)).sort();
53078
+ return (0, import_node_fs8.readdirSync)(bundleDir(root)).sort();
52619
53079
  } catch {
52620
53080
  return [];
52621
53081
  }
@@ -52625,12 +53085,12 @@ function bundleUnresolved(root) {
52625
53085
  }
52626
53086
  function readCutover(root) {
52627
53087
  const file2 = cutoverFile(root);
52628
- if (!(0, import_node_fs7.existsSync)(file2)) {
53088
+ if (!(0, import_node_fs8.existsSync)(file2)) {
52629
53089
  return void 0;
52630
53090
  }
52631
53091
  let parsed;
52632
53092
  try {
52633
- parsed = JSON.parse((0, import_node_fs7.readFileSync)(file2, "utf8"));
53093
+ parsed = JSON.parse((0, import_node_fs8.readFileSync)(file2, "utf8"));
52634
53094
  } catch {
52635
53095
  throw unreadable("it is not JSON");
52636
53096
  }
@@ -52683,12 +53143,12 @@ function bundleDotenvFiles(root, files, environments, now = /* @__PURE__ */ new
52683
53143
  environments: [...environments]
52684
53144
  };
52685
53145
  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");
53146
+ (0, import_node_fs8.mkdirSync)((0, import_node_path8.dirname)(file2), { recursive: true });
53147
+ (0, import_node_fs8.writeFileSync)(file2, serializeCutover(cutover), "utf8");
52688
53148
  const bundle = bundleDir(root);
52689
- (0, import_node_fs7.mkdirSync)(bundle, { recursive: true });
53149
+ (0, import_node_fs8.mkdirSync)(bundle, { recursive: true });
52690
53150
  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));
53151
+ (0, import_node_fs8.renameSync)((0, import_node_path8.join)(root, name), (0, import_node_path8.join)(bundle, name));
52692
53152
  }
52693
53153
  return cutover;
52694
53154
  }
@@ -52707,7 +53167,7 @@ function runUndo(options) {
52707
53167
  const names = [...recorded, ...bundled.filter((name) => !recorded.includes(name))];
52708
53168
  const bundle = bundleDir(root);
52709
53169
  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)));
53170
+ const occupied2 = names.filter((name) => held.has(name) && (0, import_node_fs8.existsSync)((0, import_node_path8.join)(root, name)));
52711
53171
  if (occupied2.length > 0) {
52712
53172
  const listed = occupied2.join(", ");
52713
53173
  const many = occupied2.length > 1;
@@ -52722,9 +53182,9 @@ function runUndo(options) {
52722
53182
  const missing = [];
52723
53183
  for (const name of names) {
52724
53184
  if (held.has(name)) {
52725
- (0, import_node_fs7.renameSync)((0, import_node_path8.join)(bundle, name), (0, import_node_path8.join)(root, name));
53185
+ (0, import_node_fs8.renameSync)((0, import_node_path8.join)(bundle, name), (0, import_node_path8.join)(root, name));
52726
53186
  restored.push(name);
52727
- } else if ((0, import_node_fs7.existsSync)((0, import_node_path8.join)(root, name))) {
53187
+ } else if ((0, import_node_fs8.existsSync)((0, import_node_path8.join)(root, name))) {
52728
53188
  alreadyBack.push(name);
52729
53189
  } else {
52730
53190
  missing.push(name);
@@ -52736,13 +53196,13 @@ function runUndo(options) {
52736
53196
  function runCleanup(options) {
52737
53197
  const root = cutoverRoot(options.cwd);
52738
53198
  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));
53199
+ const cleaned = held.length > 0 || (0, import_node_fs8.existsSync)(cutoverFile(root)) || (0, import_node_fs8.existsSync)(fileFor(root, ROLLBACK_PATH));
52740
53200
  removeBundle(root);
52741
53201
  return { root, removed: held, cleaned };
52742
53202
  }
52743
53203
  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 });
53204
+ (0, import_node_fs8.rmSync)(fileFor(root, ROLLBACK_PATH), { recursive: true, force: true });
53205
+ (0, import_node_fs8.rmSync)(cutoverFile(root), { force: true });
52746
53206
  }
52747
53207
 
52748
53208
  // src/commands/cleanup.ts
@@ -52778,7 +53238,7 @@ var cleanupCommand = defineCommand({
52778
53238
 
52779
53239
  // src/commands/doctor.ts
52780
53240
  init_cjs_shims();
52781
- var import_node_fs8 = require("fs");
53241
+ var import_node_fs9 = require("fs");
52782
53242
  var import_node_path9 = require("path");
52783
53243
 
52784
53244
  // src/commands/push.ts
@@ -52817,8 +53277,8 @@ function lineReader(input = process.stdin, output = process.stdout) {
52817
53277
  }
52818
53278
  rl.setPrompt(question);
52819
53279
  rl.prompt();
52820
- return new Promise((resolve12) => {
52821
- waiting.push(resolve12);
53280
+ return new Promise((resolve13) => {
53281
+ waiting.push(resolve13);
52822
53282
  });
52823
53283
  },
52824
53284
  close() {
@@ -53222,6 +53682,7 @@ async function runDoctor(options) {
53222
53682
  findings.push(...unusedFindings(drift));
53223
53683
  }
53224
53684
  findings.push(...fallbackFindings(subjects, environment));
53685
+ findings.push(...secrecyFindings(subjects, environment));
53225
53686
  findings.push(...plaintextSecretFindings(subjects, environment));
53226
53687
  findings.push(...publicSecretFindings(subjects, environment, project.config));
53227
53688
  findings.push(...encryptionFindings(subjects, environment));
@@ -53234,6 +53695,7 @@ async function runDoctor(options) {
53234
53695
  }
53235
53696
  findings.push(...await providerDriftFindings(project, environment, options.source));
53236
53697
  findings.push(...await projectionFindings(project, environment, options.projection));
53698
+ findings.push(...localExtensionFindings(project));
53237
53699
  findings.push(...artifactFindings(project));
53238
53700
  findings.push({
53239
53701
  check: "provider",
@@ -53371,6 +53833,31 @@ function fallbackFindings(subjects, environment) {
53371
53833
  }
53372
53834
  ];
53373
53835
  }
53836
+ function secrecyFindings(subjects, environment) {
53837
+ const undeclared = subjects.filter(
53838
+ ({ meta: meta3 }) => effectiveMeta(meta3, environment).secret === void 0
53839
+ );
53840
+ if (undeclared.length === 0) {
53841
+ return [
53842
+ {
53843
+ check: "secrecy-undeclared",
53844
+ severity: "pass",
53845
+ label: "Secrecy policy",
53846
+ subject: subjects.length === 0 ? `no parameter resolves for ${environment}` : `every parameter declares whether it is secret for ${environment}`
53847
+ }
53848
+ ];
53849
+ }
53850
+ return [
53851
+ {
53852
+ check: "secrecy-undeclared",
53853
+ severity: "unknown",
53854
+ label: "Secrecy policy",
53855
+ subject: `${undeclared.length} of ${subjects.length} declare neither way for ${environment}`,
53856
+ detail: "penv was never told which of these values must be encrypted",
53857
+ remedy: `declare \`"secret": true\` or \`"secret": false\` in a parameter's meta file, ${RECORDS_PATH2}/<name>.json`
53858
+ }
53859
+ ];
53860
+ }
53374
53861
  function plaintextSecretFindings(subjects, environment) {
53375
53862
  const secrets = subjects.filter(({ meta: meta3 }) => isSecret(meta3, environment));
53376
53863
  const findings = [];
@@ -53674,7 +54161,7 @@ function looksLikeArtifact(text) {
53674
54161
  function scannableFiles(directory, out2) {
53675
54162
  let entries;
53676
54163
  try {
53677
- entries = (0, import_node_fs8.readdirSync)(directory, { withFileTypes: true });
54164
+ entries = (0, import_node_fs9.readdirSync)(directory, { withFileTypes: true });
53678
54165
  } catch {
53679
54166
  return;
53680
54167
  }
@@ -53691,6 +54178,29 @@ function scannableFiles(directory, out2) {
53691
54178
  }
53692
54179
  }
53693
54180
  }
54181
+ function localExtensionFindings(project) {
54182
+ const names = localExtensions(project.root);
54183
+ if (names.length === 0) {
54184
+ return [
54185
+ {
54186
+ check: "local-extension",
54187
+ severity: "pass",
54188
+ label: "Extensions",
54189
+ subject: "every extension this project names is pinned"
54190
+ }
54191
+ ];
54192
+ }
54193
+ return [
54194
+ {
54195
+ check: "local-extension",
54196
+ severity: "unknown",
54197
+ label: "Extensions",
54198
+ subject: names.join(", "),
54199
+ detail: "resolved from this project's node_modules \u2014 no release, no pinned bytes",
54200
+ remedy: `publish it and run \`penv add ${names[0]}\` when this stops being a development path`
54201
+ }
54202
+ ];
54203
+ }
53694
54204
  function artifactFindings(project) {
53695
54205
  const files = [];
53696
54206
  scannableFiles(project.root, files);
@@ -53698,10 +54208,10 @@ function artifactFindings(project) {
53698
54208
  for (const file2 of files) {
53699
54209
  let text;
53700
54210
  try {
53701
- if ((0, import_node_fs8.statSync)(file2).size > ARTIFACT_SCAN_LIMIT) {
54211
+ if ((0, import_node_fs9.statSync)(file2).size > ARTIFACT_SCAN_LIMIT) {
53702
54212
  continue;
53703
54213
  }
53704
- text = (0, import_node_fs8.readFileSync)(file2, "utf8");
54214
+ text = (0, import_node_fs9.readFileSync)(file2, "utf8");
53705
54215
  } catch {
53706
54216
  continue;
53707
54217
  }
@@ -54459,7 +54969,7 @@ var fillCommand = defineCommand({
54459
54969
 
54460
54970
  // src/commands/generate.ts
54461
54971
  init_cjs_shims();
54462
- var import_node_fs9 = require("fs");
54972
+ var import_node_fs10 = require("fs");
54463
54973
  var import_node_path10 = require("path");
54464
54974
  var DEFAULT_OUTPUT = ".env";
54465
54975
  function entriesFor(project, environment, allowDecrypt) {
@@ -54506,7 +55016,7 @@ function runGenerate(options) {
54506
55016
  const environment = targetEnvironment(project, options.environment, options.envFlags);
54507
55017
  const { entries, decrypted } = entriesFor(project, environment, options.allowDecrypt === true);
54508
55018
  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");
55019
+ (0, import_node_fs10.writeFileSync)(file2, serializeDotenv(entries), "utf8");
54510
55020
  return { file: file2, environment, entries: entries.length, decrypted };
54511
55021
  }
54512
55022
  function displayPath2(cwd, file2) {
@@ -54644,7 +55154,7 @@ var getCommand = defineCommand({
54644
55154
 
54645
55155
  // src/commands/import.ts
54646
55156
  init_cjs_shims();
54647
- var import_node_fs13 = require("fs");
55157
+ var import_node_fs14 = require("fs");
54648
55158
  var import_node_path14 = require("path");
54649
55159
 
54650
55160
  // src/adopt.ts
@@ -54659,9 +55169,9 @@ function assertImportable(ref, variable) {
54659
55169
  `Filenames are split on \`.\`. Rename ${variable} in the source file, then import it again.`
54660
55170
  );
54661
55171
  }
54662
- function assertNotReserved(ref, variable, where, config2) {
55172
+ function assertNotReserved(ref, variable, where2, config2) {
54663
55173
  if (isReservedToken(ref.name, config2)) {
54664
- throw new ReservedTokenError("parameter", variable, where);
55174
+ throw new ReservedTokenError("parameter", variable, where2);
54665
55175
  }
54666
55176
  }
54667
55177
  function assertRoundTrips(ref, variable, config2) {
@@ -54678,12 +55188,12 @@ function assertRoundTrips(ref, variable, config2) {
54678
55188
  `\`penv generate\` would write ${generated}, so anything reading \`process.env["${variable}"]\` would read \`undefined\`. Declare the name you want in the \`override\` block of penv.config.ts \u2014 \`override: { "${ref.name}": "${variable}" }\` \u2014 then import it again. Nothing was imported.`
54679
55189
  );
54680
55190
  }
54681
- function refsForEntries(entries, where, config2) {
55191
+ function refsForEntries(entries, where2, config2) {
54682
55192
  const refs = [];
54683
55193
  for (const entry of entries) {
54684
55194
  const ref = refFromVariable(entry.key);
54685
55195
  assertImportable(ref, entry.key);
54686
- assertNotReserved(ref, entry.key, where, config2);
55196
+ assertNotReserved(ref, entry.key, where2, config2);
54687
55197
  assertRoundTrips(ref, entry.key, config2);
54688
55198
  refs.push(ref);
54689
55199
  }
@@ -54714,7 +55224,7 @@ function writeEntries(tree, entries, refs, scope) {
54714
55224
 
54715
55225
  // src/detect.ts
54716
55226
  init_cjs_shims();
54717
- var import_node_fs10 = require("fs");
55227
+ var import_node_fs11 = require("fs");
54718
55228
  var import_node_path11 = require("path");
54719
55229
  var SIGNATURES = [
54720
55230
  { name: "Next.js", packages: ["next"], publicPrefixes: ["NEXT_PUBLIC_"] },
@@ -54731,7 +55241,7 @@ var SIGNATURES = [
54731
55241
  function exportsSchema(file2) {
54732
55242
  let source;
54733
55243
  try {
54734
- source = (0, import_node_fs10.readFileSync)(file2, "utf8");
55244
+ source = (0, import_node_fs11.readFileSync)(file2, "utf8");
54735
55245
  } catch {
54736
55246
  return false;
54737
55247
  }
@@ -54743,7 +55253,7 @@ function exportsSchema(file2) {
54743
55253
  }
54744
55254
  function occupied(cwd, relative5) {
54745
55255
  const file2 = (0, import_node_path11.join)(cwd, ...relative5.split("/"));
54746
- return (0, import_node_fs10.existsSync)(file2) && !exportsSchema(file2);
55256
+ return (0, import_node_fs11.existsSync)(file2) && !exportsSchema(file2);
54747
55257
  }
54748
55258
  function schemaFileFor(cwd) {
54749
55259
  const dir = srcPrefix(cwd);
@@ -54758,7 +55268,7 @@ function schemaFileFor(cwd) {
54758
55268
  return { file: DEFAULT_SCHEMA_FILE, displaced: preferred };
54759
55269
  }
54760
55270
  function srcPrefix(cwd) {
54761
- return (0, import_node_fs10.existsSync)((0, import_node_path11.join)(cwd, "src")) ? "src/" : "";
55271
+ return (0, import_node_fs11.existsSync)((0, import_node_path11.join)(cwd, "src")) ? "src/" : "";
54762
55272
  }
54763
55273
  function dependenciesOf(cwd) {
54764
55274
  const manifest = manifestOf2(cwd);
@@ -54778,12 +55288,12 @@ function dependenciesOf(cwd) {
54778
55288
  }
54779
55289
  function manifestOf2(cwd) {
54780
55290
  const file2 = (0, import_node_path11.join)(cwd, "package.json");
54781
- if (!(0, import_node_fs10.existsSync)(file2)) {
55291
+ if (!(0, import_node_fs11.existsSync)(file2)) {
54782
55292
  return void 0;
54783
55293
  }
54784
55294
  let manifest;
54785
55295
  try {
54786
- manifest = JSON.parse((0, import_node_fs10.readFileSync)(file2, "utf8"));
55296
+ manifest = JSON.parse((0, import_node_fs11.readFileSync)(file2, "utf8"));
54787
55297
  } catch {
54788
55298
  return void 0;
54789
55299
  }
@@ -54799,7 +55309,7 @@ function detectFramework(cwd) {
54799
55309
  return detectedFrom(cwd, signature.name, signature.publicPrefixes);
54800
55310
  }
54801
55311
  }
54802
- if ((0, import_node_fs10.existsSync)((0, import_node_path11.join)(cwd, "bunfig.toml")) || dependencies.has("bun-types")) {
55312
+ if ((0, import_node_fs11.existsSync)((0, import_node_path11.join)(cwd, "bunfig.toml")) || dependencies.has("bun-types")) {
54803
55313
  return detectedFrom(cwd, "Bun", []);
54804
55314
  }
54805
55315
  return void 0;
@@ -54879,30 +55389,30 @@ function draftFieldsAcross(sources, environments) {
54879
55389
 
54880
55390
  // src/commands/init.ts
54881
55391
  init_cjs_shims();
54882
- var import_node_fs12 = require("fs");
55392
+ var import_node_fs13 = require("fs");
54883
55393
  var import_node_path13 = require("path");
54884
55394
  var import_promises = require("readline/promises");
54885
55395
 
54886
55396
  // src/scaffold-undo.ts
54887
55397
  init_cjs_shims();
54888
- var import_node_fs11 = require("fs");
55398
+ var import_node_fs12 = require("fs");
54889
55399
  var import_node_path12 = require("path");
54890
55400
  function record2(path, files, dirs) {
54891
55401
  let stats;
54892
55402
  try {
54893
- stats = (0, import_node_fs11.statSync)(path);
55403
+ stats = (0, import_node_fs12.statSync)(path);
54894
55404
  } catch {
54895
55405
  return;
54896
55406
  }
54897
55407
  if (stats.isDirectory()) {
54898
55408
  dirs.add(path);
54899
- for (const entry of (0, import_node_fs11.readdirSync)(path)) {
55409
+ for (const entry of (0, import_node_fs12.readdirSync)(path)) {
54900
55410
  record2((0, import_node_path12.join)(path, entry), files, dirs);
54901
55411
  }
54902
55412
  return;
54903
55413
  }
54904
55414
  if (stats.isFile()) {
54905
- files.set(path, (0, import_node_fs11.readFileSync)(path));
55415
+ files.set(path, (0, import_node_fs12.readFileSync)(path));
54906
55416
  }
54907
55417
  }
54908
55418
  function captureScaffold(root, paths) {
@@ -54910,7 +55420,7 @@ function captureScaffold(root, paths) {
54910
55420
  const dirs = /* @__PURE__ */ new Set();
54911
55421
  for (const path of paths) {
54912
55422
  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)) {
55423
+ if ((0, import_node_fs12.existsSync)(dir)) {
54914
55424
  dirs.add(dir);
54915
55425
  }
54916
55426
  }
@@ -54926,31 +55436,31 @@ function restoreScaffold(undo) {
54926
55436
  pruneAncestors(path, undo);
54927
55437
  }
54928
55438
  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);
55439
+ (0, import_node_fs12.mkdirSync)((0, import_node_path12.dirname)(file2), { recursive: true });
55440
+ (0, import_node_fs12.writeFileSync)(file2, contents);
54931
55441
  }
54932
55442
  }
54933
55443
  function removeAdded(path, undo) {
54934
55444
  let stats;
54935
55445
  try {
54936
- stats = (0, import_node_fs11.statSync)(path);
55446
+ stats = (0, import_node_fs12.statSync)(path);
54937
55447
  } catch {
54938
55448
  return;
54939
55449
  }
54940
55450
  if (stats.isFile()) {
54941
55451
  if (!undo.files.has(path)) {
54942
- (0, import_node_fs11.unlinkSync)(path);
55452
+ (0, import_node_fs12.unlinkSync)(path);
54943
55453
  }
54944
55454
  return;
54945
55455
  }
54946
55456
  if (!stats.isDirectory()) {
54947
55457
  return;
54948
55458
  }
54949
- for (const entry of (0, import_node_fs11.readdirSync)(path)) {
55459
+ for (const entry of (0, import_node_fs12.readdirSync)(path)) {
54950
55460
  removeAdded((0, import_node_path12.join)(path, entry), undo);
54951
55461
  }
54952
- if (!undo.dirs.has(path) && (0, import_node_fs11.readdirSync)(path).length === 0) {
54953
- (0, import_node_fs11.rmdirSync)(path);
55462
+ if (!undo.dirs.has(path) && (0, import_node_fs12.readdirSync)(path).length === 0) {
55463
+ (0, import_node_fs12.rmdirSync)(path);
54954
55464
  }
54955
55465
  }
54956
55466
  function pruneAncestors(path, undo) {
@@ -54959,7 +55469,7 @@ function pruneAncestors(path, undo) {
54959
55469
  return;
54960
55470
  }
54961
55471
  try {
54962
- (0, import_node_fs11.rmdirSync)(dir);
55472
+ (0, import_node_fs12.rmdirSync)(dir);
54963
55473
  } catch {
54964
55474
  return;
54965
55475
  }
@@ -55122,7 +55632,7 @@ var NOT_ENVIRONMENTS2 = [...RESERVED_TOKENS, "example", "sample", "template"];
55122
55632
  function suggestEnvironments(root) {
55123
55633
  let entries;
55124
55634
  try {
55125
- entries = (0, import_node_fs12.readdirSync)(root);
55635
+ entries = (0, import_node_fs13.readdirSync)(root);
55126
55636
  } catch {
55127
55637
  return [];
55128
55638
  }
@@ -55167,7 +55677,7 @@ function configOf(decisions) {
55167
55677
  }
55168
55678
  function declaredIn(root) {
55169
55679
  const file2 = (0, import_node_path13.join)(root, CONFIG_FILE);
55170
- if (!(0, import_node_fs12.existsSync)(file2)) {
55680
+ if (!(0, import_node_fs13.existsSync)(file2)) {
55171
55681
  return void 0;
55172
55682
  }
55173
55683
  return loadConfigFrom(file2);
@@ -55610,15 +56120,15 @@ function renderTsconfig(target, alias) {
55610
56120
  }
55611
56121
  function ensurePenvDir(root) {
55612
56122
  const dir = (0, import_node_path13.resolve)(root, PENV_DIR);
55613
- if ((0, import_node_fs12.existsSync)(dir)) {
56123
+ if ((0, import_node_fs13.existsSync)(dir)) {
55614
56124
  return { target: "penv-dir", action: "kept", text: `Found ${PENV_DIR}/` };
55615
56125
  }
55616
- (0, import_node_fs12.mkdirSync)(dir, { recursive: true });
56126
+ (0, import_node_fs13.mkdirSync)(dir, { recursive: true });
55617
56127
  return { target: "penv-dir", action: "created", text: `Created ${PENV_DIR}/` };
55618
56128
  }
55619
56129
  function writeSchemaShapeFile(root, fields, draft, decisions = DEFAULT_DECISIONS) {
55620
56130
  const file2 = (0, import_node_path13.join)(root, SCHEMA_SHAPE_FILE);
55621
- if ((0, import_node_fs12.existsSync)(file2)) {
56131
+ if ((0, import_node_fs13.existsSync)(file2)) {
55622
56132
  return {
55623
56133
  target: "schema",
55624
56134
  action: "kept",
@@ -55635,7 +56145,7 @@ function writeSchemaShapeFile(root, fields, draft, decisions = DEFAULT_DECISIONS
55635
56145
  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
56146
  };
55637
56147
  }
55638
- (0, import_node_fs12.writeFileSync)(file2, renderSchemaShapeModule(fields, draft), "utf8");
56148
+ (0, import_node_fs13.writeFileSync)(file2, renderSchemaShapeModule(fields, draft), "utf8");
55639
56149
  return {
55640
56150
  target: "schema",
55641
56151
  action: "created",
@@ -55645,7 +56155,7 @@ function writeSchemaShapeFile(root, fields, draft, decisions = DEFAULT_DECISIONS
55645
56155
  }
55646
56156
  function writeEnvFile(root, decisions = DEFAULT_DECISIONS) {
55647
56157
  const file2 = (0, import_node_path13.join)(root, ...decisions.schemaFile.split("/"));
55648
- if ((0, import_node_fs12.existsSync)(file2)) {
56158
+ if ((0, import_node_fs13.existsSync)(file2)) {
55649
56159
  return {
55650
56160
  target: "env",
55651
56161
  action: "kept",
@@ -55653,8 +56163,8 @@ function writeEnvFile(root, decisions = DEFAULT_DECISIONS) {
55653
56163
  note: "(yours \u2014 penv never regenerates it)"
55654
56164
  };
55655
56165
  }
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");
56166
+ (0, import_node_fs13.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
56167
+ (0, import_node_fs13.writeFileSync)(file2, renderEnvModule(decisions.schemaFile, decisions.inject), "utf8");
55658
56168
  return {
55659
56169
  target: "env",
55660
56170
  action: "created",
@@ -55664,18 +56174,18 @@ function writeEnvFile(root, decisions = DEFAULT_DECISIONS) {
55664
56174
  }
55665
56175
  function writeConfigFile(root, decisions = DEFAULT_DECISIONS) {
55666
56176
  const file2 = (0, import_node_path13.join)(root, CONFIG_FILE);
55667
- if ((0, import_node_fs12.existsSync)(file2)) {
56177
+ if ((0, import_node_fs13.existsSync)(file2)) {
55668
56178
  return { target: "config", action: "kept", text: `Kept ${CONFIG_FILE}` };
55669
56179
  }
55670
- (0, import_node_fs12.writeFileSync)(file2, renderConfigModule(decisions), "utf8");
56180
+ (0, import_node_fs13.writeFileSync)(file2, renderConfigModule(decisions), "utf8");
55671
56181
  return { target: "config", action: "created", text: `Generated ${CONFIG_FILE}` };
55672
56182
  }
55673
56183
  function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
55674
56184
  const alias = decisions.alias;
55675
56185
  const imports = alias.startsWith(IMPORTS_PREFIX);
55676
56186
  const file2 = (0, import_node_path13.join)(root, imports ? PACKAGE_FILE : TSCONFIG_FILE);
55677
- const where = imports ? PACKAGE_FILE : TSCONFIG_FILE;
55678
- if (!(0, import_node_fs12.existsSync)(file2)) {
56187
+ const where2 = imports ? PACKAGE_FILE : TSCONFIG_FILE;
56188
+ if (!(0, import_node_fs13.existsSync)(file2)) {
55679
56189
  if (imports) {
55680
56190
  return {
55681
56191
  target: "tsconfig",
@@ -55684,20 +56194,20 @@ function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
55684
56194
  note: `(run \`npm init\` first, or use \`--alias @env\` to alias through ${TSCONFIG_FILE})`
55685
56195
  };
55686
56196
  }
55687
- (0, import_node_fs12.writeFileSync)(file2, renderTsconfig(decisions.schemaFile, alias), "utf8");
56197
+ (0, import_node_fs13.writeFileSync)(file2, renderTsconfig(decisions.schemaFile, alias), "utf8");
55688
56198
  return {
55689
56199
  target: "tsconfig",
55690
56200
  action: "created",
55691
56201
  text: `Created ${TSCONFIG_FILE} with the ${alias} path alias`
55692
56202
  };
55693
56203
  }
55694
- const source = (0, import_node_fs12.readFileSync)(file2, "utf8");
56204
+ const source = (0, import_node_fs13.readFileSync)(file2, "utf8");
55695
56205
  const edit = imports ? insertImportsAlias(source, decisions.schemaFile, alias) : insertEnvAlias(source, decisions.schemaFile, alias);
55696
56206
  if (edit.conflict !== void 0) {
55697
56207
  return {
55698
56208
  target: "tsconfig",
55699
56209
  action: "conflicted",
55700
- text: `${where} already maps ${alias} to ${edit.conflict}`,
56210
+ text: `${where2} already maps ${alias} to ${edit.conflict}`,
55701
56211
  note: `(left alone \u2014 \`import { env } from "${alias}"\` will not reach ${decisions.schemaFile})`
55702
56212
  };
55703
56213
  }
@@ -55705,25 +56215,25 @@ function writeTsconfigAlias(root, decisions = DEFAULT_DECISIONS) {
55705
56215
  return {
55706
56216
  target: "tsconfig",
55707
56217
  action: "kept",
55708
- text: `Kept the ${alias} alias in ${where}`
56218
+ text: `Kept the ${alias} alias in ${where2}`
55709
56219
  };
55710
56220
  }
55711
- (0, import_node_fs12.writeFileSync)(file2, edit.source, "utf8");
56221
+ (0, import_node_fs13.writeFileSync)(file2, edit.source, "utf8");
55712
56222
  return {
55713
56223
  target: "tsconfig",
55714
56224
  action: "updated",
55715
- text: `Added ${alias} alias to ${where}`
56225
+ text: `Added ${alias} alias to ${where2}`
55716
56226
  };
55717
56227
  }
55718
56228
  function writeGitignore(root, decisions = DEFAULT_DECISIONS) {
55719
56229
  const file2 = (0, import_node_path13.join)(root, ...STATE_GITIGNORE_PATH.split("/"));
55720
56230
  const wanted = renderStateGitignore(configOf(decisions));
55721
- const existing = (0, import_node_fs12.existsSync)(file2) ? (0, import_node_fs12.readFileSync)(file2, "utf8") : void 0;
56231
+ const existing = (0, import_node_fs13.existsSync)(file2) ? (0, import_node_fs13.readFileSync)(file2, "utf8") : void 0;
55722
56232
  if (existing === wanted) {
55723
56233
  return { target: "gitignore", action: "kept", text: `Kept ${STATE_GITIGNORE_PATH}` };
55724
56234
  }
55725
- (0, import_node_fs12.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55726
- (0, import_node_fs12.writeFileSync)(file2, wanted, "utf8");
56235
+ (0, import_node_fs13.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
56236
+ (0, import_node_fs13.writeFileSync)(file2, wanted, "utf8");
55727
56237
  return {
55728
56238
  target: "gitignore",
55729
56239
  action: existing === void 0 ? "created" : "updated",
@@ -55740,11 +56250,11 @@ function outdatedRuntimeWarning(root) {
55740
56250
  }
55741
56251
  function installedPenvVersion(root) {
55742
56252
  const file2 = (0, import_node_path13.join)(root, "node_modules", "@penvhq", "penv", "package.json");
55743
- if (!(0, import_node_fs12.existsSync)(file2)) {
56253
+ if (!(0, import_node_fs13.existsSync)(file2)) {
55744
56254
  return void 0;
55745
56255
  }
55746
56256
  try {
55747
- const version2 = JSON.parse((0, import_node_fs12.readFileSync)(file2, "utf8")).version;
56257
+ const version2 = JSON.parse((0, import_node_fs13.readFileSync)(file2, "utf8")).version;
55748
56258
  return typeof version2 === "string" ? version2 : void 0;
55749
56259
  } catch {
55750
56260
  return void 0;
@@ -55788,7 +56298,7 @@ function writeSeam(root, decisions = DEFAULT_DECISIONS, framework = detectFramew
55788
56298
  const baseNotes = [...seam.notes, ...alsoNote === void 0 ? [] : [alsoNote]];
55789
56299
  const notes = baseNotes.length === 0 ? "" : `
55790
56300
  ${baseNotes.map((n) => ` ${n}`).join("\n")}`;
55791
- if ((0, import_node_fs12.existsSync)(file2)) {
56301
+ if ((0, import_node_fs13.existsSync)(file2)) {
55792
56302
  return {
55793
56303
  target: "seam",
55794
56304
  action: "info",
@@ -55796,8 +56306,8 @@ ${baseNotes.map((n) => ` ${n}`).join("\n")}`;
55796
56306
  note: withWarning(`${seam.ifPresent}${notes}`, outdated)
55797
56307
  };
55798
56308
  }
55799
- (0, import_node_fs12.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55800
- (0, import_node_fs12.writeFileSync)(file2, seam.content, "utf8");
56309
+ (0, import_node_fs13.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
56310
+ (0, import_node_fs13.writeFileSync)(file2, seam.content, "utf8");
55801
56311
  return {
55802
56312
  target: "seam",
55803
56313
  action: outdated === void 0 ? "created" : "info",
@@ -55810,11 +56320,11 @@ function writeAlso(root, also) {
55810
56320
  return void 0;
55811
56321
  }
55812
56322
  const file2 = (0, import_node_path13.join)(root, ...also.file.split("/"));
55813
- if ((0, import_node_fs12.existsSync)(file2)) {
56323
+ if ((0, import_node_fs13.existsSync)(file2)) {
55814
56324
  return also.ifPresent;
55815
56325
  }
55816
- (0, import_node_fs12.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
55817
- (0, import_node_fs12.writeFileSync)(file2, also.content, "utf8");
56326
+ (0, import_node_fs13.mkdirSync)((0, import_node_path13.dirname)(file2), { recursive: true });
56327
+ (0, import_node_fs13.writeFileSync)(file2, also.content, "utf8");
55818
56328
  return `Wrote ${also.file} to register it.`;
55819
56329
  }
55820
56330
  function withWarning(note, warning) {
@@ -55918,7 +56428,7 @@ function planCutover(input) {
55918
56428
  const diagnostics = [];
55919
56429
  let variables = 0;
55920
56430
  for (const file2 of selected) {
55921
- const parsed = parseDotenv((0, import_node_fs12.readFileSync)((0, import_node_path13.join)(root, file2.name), "utf8"));
56431
+ const parsed = parseDotenv((0, import_node_fs13.readFileSync)((0, import_node_path13.join)(root, file2.name), "utf8"));
55922
56432
  const fileRefs = refsForEntries(parsed.entries, file2.name, config2);
55923
56433
  adopted.push({ file: file2, entries: parsed.entries, refs: fileRefs, scope: scopeOf(file2) });
55924
56434
  refs.push(...fileRefs);
@@ -56163,11 +56673,11 @@ function dailyCommand(root) {
56163
56673
  }
56164
56674
  function devScript(root) {
56165
56675
  const file2 = (0, import_node_path13.join)(root, PACKAGE_FILE);
56166
- if (!(0, import_node_fs12.existsSync)(file2)) {
56676
+ if (!(0, import_node_fs13.existsSync)(file2)) {
56167
56677
  return "dev";
56168
56678
  }
56169
56679
  try {
56170
- const scripts = JSON.parse((0, import_node_fs12.readFileSync)(file2, "utf8")).scripts;
56680
+ const scripts = JSON.parse((0, import_node_fs13.readFileSync)(file2, "utf8")).scripts;
56171
56681
  if (scripts !== null && typeof scripts === "object" && !Array.isArray(scripts)) {
56172
56682
  const named = Object.keys(scripts);
56173
56683
  return ["dev", "start"].find((script) => named.includes(script)) ?? named[0] ?? "dev";
@@ -56536,14 +57046,14 @@ function configInEffect(cwd, environment) {
56536
57046
  function importDotenv(options) {
56537
57047
  const cwd = (0, import_node_path14.resolve)(options.cwd);
56538
57048
  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)) {
57049
+ if (!(0, import_node_fs14.existsSync)(file2)) {
56540
57050
  throw new PenvError(
56541
57051
  "IMPORT_FILE_MISSING",
56542
57052
  `There is no file at ${file2} to import`,
56543
57053
  "Point `penv import` at an existing dotenv file, e.g. `penv import .env`."
56544
57054
  );
56545
57055
  }
56546
- const parsed = parseDotenv((0, import_node_fs13.readFileSync)(file2, "utf8"));
57056
+ const parsed = parseDotenv((0, import_node_fs14.readFileSync)(file2, "utf8"));
56547
57057
  const { config: config2, decisions } = configInEffect(cwd, environmentNamed(file2, options.environment));
56548
57058
  const source = displayPath3(cwd, file2);
56549
57059
  const named = scopeFromFilename(file2, config2);
@@ -56559,7 +57069,7 @@ function importDotenv(options) {
56559
57069
  const tree = localTree(project);
56560
57070
  writeEntries(tree, parsed.entries, refs, scope);
56561
57071
  const backup = `${file2}${BACKUP_SUFFIX}`;
56562
- (0, import_node_fs13.copyFileSync)(file2, backup);
57072
+ (0, import_node_fs14.copyFileSync)(file2, backup);
56563
57073
  return {
56564
57074
  root: project.root,
56565
57075
  file: file2,
@@ -56892,7 +57402,7 @@ var listCommand = defineCommand({
56892
57402
 
56893
57403
  // src/commands/migrate.ts
56894
57404
  init_cjs_shims();
56895
- var import_node_fs14 = require("fs");
57405
+ var import_node_fs15 = require("fs");
56896
57406
  var import_node_path15 = require("path");
56897
57407
  var import_promises2 = require("readline/promises");
56898
57408
  var OLD_GITIGNORE = `${PENV_DIR}/.gitignore`;
@@ -56910,7 +57420,7 @@ function planMigrate(cwd) {
56910
57420
  );
56911
57421
  }
56912
57422
  const creates = [];
56913
- if (entries.length > 0 && !(0, import_node_fs14.existsSync)(tree)) {
57423
+ if (entries.length > 0 && !(0, import_node_fs15.existsSync)(tree)) {
56914
57424
  creates.push(`${RECORDS_PATH2}/`);
56915
57425
  }
56916
57426
  if (readIfPresent((0, import_node_path15.join)(root, ...STATE_GITIGNORE_PATH.split("/"))) !== renderStateGitignore(config2)) {
@@ -56923,16 +57433,16 @@ function planMigrate(cwd) {
56923
57433
  to: `${RECORDS_PATH2}/${entry}`
56924
57434
  })),
56925
57435
  creates,
56926
- removes: (0, import_node_fs14.existsSync)((0, import_node_path15.join)(root, ...OLD_GITIGNORE.split("/"))) ? [OLD_GITIGNORE] : []
57436
+ removes: (0, import_node_fs15.existsSync)((0, import_node_path15.join)(root, ...OLD_GITIGNORE.split("/"))) ? [OLD_GITIGNORE] : []
56927
57437
  };
56928
57438
  }
56929
57439
  function readIfPresent(file2) {
56930
- return (0, import_node_fs14.existsSync)(file2) ? (0, import_node_fs14.readFileSync)(file2, "utf8") : void 0;
57440
+ return (0, import_node_fs15.existsSync)(file2) ? (0, import_node_fs15.readFileSync)(file2, "utf8") : void 0;
56931
57441
  }
56932
57442
  function collidingEntries(entries, tree) {
56933
57443
  let held;
56934
57444
  try {
56935
- held = (0, import_node_fs14.readdirSync)(tree);
57445
+ held = (0, import_node_fs15.readdirSync)(tree);
56936
57446
  } catch {
56937
57447
  return [];
56938
57448
  }
@@ -56951,18 +57461,18 @@ function applyMigrate(plan2) {
56951
57461
  }
56952
57462
  const { config: config2 } = loadConfig(plan2.root);
56953
57463
  if (plan2.moves.length > 0) {
56954
- (0, import_node_fs14.mkdirSync)(recordsDir(plan2.root), { recursive: true });
57464
+ (0, import_node_fs15.mkdirSync)(recordsDir(plan2.root), { recursive: true });
56955
57465
  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("/")));
57466
+ (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
57467
  }
56958
57468
  }
56959
57469
  if (plan2.creates.includes(STATE_GITIGNORE_PATH)) {
56960
57470
  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");
57471
+ (0, import_node_fs15.mkdirSync)((0, import_node_path15.dirname)(ignore), { recursive: true });
57472
+ (0, import_node_fs15.writeFileSync)(ignore, renderStateGitignore(config2), "utf8");
56963
57473
  }
56964
57474
  for (const removed of plan2.removes) {
56965
- (0, import_node_fs14.rmSync)((0, import_node_path15.join)(plan2.root, ...removed.split("/")), { force: true });
57475
+ (0, import_node_fs15.rmSync)((0, import_node_path15.join)(plan2.root, ...removed.split("/")), { force: true });
56966
57476
  }
56967
57477
  return { ...plan2, status: "migrated" };
56968
57478
  }
@@ -57439,7 +57949,7 @@ var rotateCommand = defineCommand({
57439
57949
 
57440
57950
  // src/commands/watch.ts
57441
57951
  init_cjs_shims();
57442
- var import_node_fs15 = require("fs");
57952
+ var import_node_fs16 = require("fs");
57443
57953
  var import_node_path16 = require("path");
57444
57954
  var DEBOUNCE_MS2 = 100;
57445
57955
  function runWatch(options) {
@@ -57501,18 +58011,18 @@ function runWatch(options) {
57501
58011
  const name = (0, import_node_path16.basename)(target);
57502
58012
  let recovery;
57503
58013
  try {
57504
- recovery = (0, import_node_fs15.watch)(parent, { recursive: false }, (_event, filename) => {
58014
+ recovery = (0, import_node_fs16.watch)(parent, { recursive: false }, (_event, filename) => {
57505
58015
  if (closed || recovery === void 0) {
57506
58016
  return;
57507
58017
  }
57508
- if (!(0, import_node_fs15.existsSync)(parent)) {
58018
+ if (!(0, import_node_fs16.existsSync)(parent)) {
57509
58019
  stop2(recovery);
57510
58020
  return;
57511
58021
  }
57512
58022
  if (filename !== null && (0, import_node_path16.basename)(filename) !== name) {
57513
58023
  return;
57514
58024
  }
57515
- if (!(0, import_node_fs15.existsSync)(target)) {
58025
+ if (!(0, import_node_fs16.existsSync)(target)) {
57516
58026
  return;
57517
58027
  }
57518
58028
  stop2(recovery);
@@ -57532,11 +58042,11 @@ function runWatch(options) {
57532
58042
  }
57533
58043
  function addWatcher(target, recursive, only) {
57534
58044
  let watcher;
57535
- const listen = (useRecursive) => (0, import_node_fs15.watch)(target, { recursive: useRecursive }, (_event, filename) => {
58045
+ const listen = (useRecursive) => (0, import_node_fs16.watch)(target, { recursive: useRecursive }, (_event, filename) => {
57536
58046
  if (closed) {
57537
58047
  return;
57538
58048
  }
57539
- if (!(0, import_node_fs15.existsSync)(target)) {
58049
+ if (!(0, import_node_fs16.existsSync)(target)) {
57540
58050
  if (watcher !== void 0) {
57541
58051
  stop2(watcher);
57542
58052
  }
@@ -57646,10 +58156,10 @@ var watchCommand = defineCommand({
57646
58156
  }
57647
58157
  });
57648
58158
  write([`Watching .penv/ and penv.config.ts. ${out.dim("Ctrl-C to stop.")}`]);
57649
- await new Promise((resolve12) => {
58159
+ await new Promise((resolve13) => {
57650
58160
  process.once("SIGINT", () => {
57651
58161
  handle.close();
57652
- resolve12();
58162
+ resolve13();
57653
58163
  });
57654
58164
  });
57655
58165
  });