@keynv/cli 0.1.0-rc.6 → 0.1.0-rc.8

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/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'module';
3
3
  import 'crypto';
4
- import { readFileSync, existsSync, mkdirSync, writeFileSync, rmSync } from 'fs';
4
+ import { readFileSync, existsSync, statSync, writeFileSync, unlinkSync, mkdirSync, rmSync, readdirSync } from 'fs';
5
5
  import { homedir } from 'os';
6
- import { join, dirname } from 'path';
6
+ import { isAbsolute, resolve, join, dirname, basename } from 'path';
7
7
  import { Entry } from '@napi-rs/keyring';
8
8
  import { styleText } from 'util';
9
9
  import j2, { stdin, stdout } from 'process';
@@ -1056,7 +1056,7 @@ var require_lib = __commonJS({
1056
1056
  var VERSION, AGENT;
1057
1057
  var init_version = __esm({
1058
1058
  "src/version.ts"() {
1059
- VERSION = "0.1.0-rc.6" ;
1059
+ VERSION = "0.1.0-rc.8" ;
1060
1060
  AGENT = `keynv-cli/${VERSION}`;
1061
1061
  }
1062
1062
  });
@@ -5716,6 +5716,137 @@ var init_format = __esm({
5716
5716
  "src/ui/format.ts"() {
5717
5717
  }
5718
5718
  });
5719
+ function parseEnvFile(content, filename) {
5720
+ const normalized = content.charCodeAt(0) === 65279 ? content.slice(1) : content;
5721
+ const lines = normalized.split(/\r?\n/);
5722
+ const entries = [];
5723
+ for (let i = 0; i < lines.length; i++) {
5724
+ const raw = lines[i] ?? "";
5725
+ const lineNo = i + 1;
5726
+ const trimmed = raw.trim();
5727
+ if (trimmed.length === 0) continue;
5728
+ if (trimmed.startsWith("#")) continue;
5729
+ let body = trimmed;
5730
+ if (body.startsWith("export ")) {
5731
+ body = body.slice("export ".length).trimStart();
5732
+ }
5733
+ const eq = body.indexOf("=");
5734
+ if (eq <= 0) {
5735
+ throw new EnvFileParseError(filename, lineNo, "expected 'KEY=value'");
5736
+ }
5737
+ const name = body.slice(0, eq).trim();
5738
+ if (!KEY_RE2.test(name)) {
5739
+ throw new EnvFileParseError(
5740
+ filename,
5741
+ lineNo,
5742
+ `invalid key '${name}' (must match /^[A-Za-z_][A-Za-z0-9_]*$/)`
5743
+ );
5744
+ }
5745
+ let valueRaw = body.slice(eq + 1);
5746
+ let value;
5747
+ const valueLeading = valueRaw.replace(/^\s+/, "");
5748
+ const firstCh = valueLeading.charAt(0);
5749
+ if (firstCh === '"' || firstCh === "'") {
5750
+ const close = valueLeading.lastIndexOf(firstCh);
5751
+ if (close === 0) {
5752
+ throw new EnvFileParseError(filename, lineNo, `unclosed ${firstCh} quote`);
5753
+ }
5754
+ const after = valueLeading.slice(close + 1).trim();
5755
+ if (after.length > 0) {
5756
+ throw new EnvFileParseError(
5757
+ filename,
5758
+ lineNo,
5759
+ `unexpected content after closing ${firstCh}`
5760
+ );
5761
+ }
5762
+ value = valueLeading.slice(1, close);
5763
+ } else {
5764
+ value = valueRaw.replace(/\s+$/, "");
5765
+ value = value.replace(/^\s+/, "");
5766
+ }
5767
+ entries.push({
5768
+ name,
5769
+ value,
5770
+ isAlias: parseAlias(value) !== null,
5771
+ line: lineNo
5772
+ });
5773
+ }
5774
+ return entries;
5775
+ }
5776
+ function findEnvFile(startDir) {
5777
+ let dir = resolve(startDir);
5778
+ for (let i = 0; i < 64; i++) {
5779
+ const candidate = join(dir, ENV_FILE_BASENAME);
5780
+ if (existsSync(candidate)) {
5781
+ try {
5782
+ if (statSync(candidate).isFile()) return candidate;
5783
+ } catch {
5784
+ }
5785
+ }
5786
+ const parent = dirname(dir);
5787
+ if (parent === dir) return null;
5788
+ dir = parent;
5789
+ }
5790
+ return null;
5791
+ }
5792
+ function loadEnvFile(opts) {
5793
+ if (opts.disabled) return null;
5794
+ const pickExplicit = opts.explicitPath ?? opts.envVarOverride;
5795
+ let path = null;
5796
+ if (pickExplicit !== void 0) {
5797
+ path = isAbsolute(pickExplicit) ? pickExplicit : resolve(opts.cwd, pickExplicit);
5798
+ if (!existsSync(path)) throw new EnvFileNotFoundError(path);
5799
+ } else {
5800
+ path = findEnvFile(opts.cwd);
5801
+ }
5802
+ if (path === null) return null;
5803
+ const stat = statSync(path);
5804
+ if (stat.size > MAX_FILE_BYTES) {
5805
+ throw new EnvFileTooLargeError(path, stat.size);
5806
+ }
5807
+ const content = readFileSync(path, "utf8");
5808
+ const entries = parseEnvFile(content, path);
5809
+ return { path, entries };
5810
+ }
5811
+ var MAX_FILE_BYTES, KEY_RE2, ENV_FILE_BASENAME, EnvFileParseError, EnvFileNotFoundError, EnvFileTooLargeError;
5812
+ var init_envFile = __esm({
5813
+ "src/exec/envFile.ts"() {
5814
+ init_dist();
5815
+ MAX_FILE_BYTES = 1e6;
5816
+ KEY_RE2 = /^[A-Za-z_][A-Za-z0-9_]*$/;
5817
+ ENV_FILE_BASENAME = ".keynv.env";
5818
+ EnvFileParseError = class extends Error {
5819
+ constructor(file, line, reason) {
5820
+ super(`${file}:${line}: ${reason}`);
5821
+ this.file = file;
5822
+ this.line = line;
5823
+ this.reason = reason;
5824
+ this.name = "EnvFileParseError";
5825
+ }
5826
+ file;
5827
+ line;
5828
+ reason;
5829
+ };
5830
+ EnvFileNotFoundError = class extends Error {
5831
+ constructor(path) {
5832
+ super(`env file not found: ${path}`);
5833
+ this.path = path;
5834
+ this.name = "EnvFileNotFoundError";
5835
+ }
5836
+ path;
5837
+ };
5838
+ EnvFileTooLargeError = class extends Error {
5839
+ constructor(path, bytes) {
5840
+ super(`env file ${path} is ${bytes} bytes (max ${MAX_FILE_BYTES})`);
5841
+ this.path = path;
5842
+ this.bytes = bytes;
5843
+ this.name = "EnvFileTooLargeError";
5844
+ }
5845
+ path;
5846
+ bytes;
5847
+ };
5848
+ }
5849
+ });
5719
5850
 
5720
5851
  // src/ui/helpers/tty.ts
5721
5852
  var tty_exports = {};
@@ -6095,7 +6226,7 @@ var require_src = __commonJS({
6095
6226
  var ESC2 = "\x1B";
6096
6227
  var CSI2 = `${ESC2}[`;
6097
6228
  var beep = "\x07";
6098
- var cursor2 = {
6229
+ var cursor = {
6099
6230
  to(x, y) {
6100
6231
  if (!y) return `${CSI2}${x + 1}G`;
6101
6232
  return `${CSI2}${y + 1};${x + 1}H`;
@@ -6134,13 +6265,13 @@ var require_src = __commonJS({
6134
6265
  lines(count) {
6135
6266
  let clear = "";
6136
6267
  for (let i = 0; i < count; i++)
6137
- clear += this.line + (i < count - 1 ? cursor2.up() : "");
6268
+ clear += this.line + (i < count - 1 ? cursor.up() : "");
6138
6269
  if (count)
6139
- clear += cursor2.left;
6270
+ clear += cursor.left;
6140
6271
  return clear;
6141
6272
  }
6142
6273
  };
6143
- module.exports = { cursor: cursor2, scroll, erase, beep };
6274
+ module.exports = { cursor, scroll, erase, beep };
6144
6275
  }
6145
6276
  });
6146
6277
  function d(r, t, s) {
@@ -6884,6 +7015,413 @@ ${c2}
6884
7015
  } }).prompt();
6885
7016
  }
6886
7017
  });
7018
+ function findProjectRoot(startDir) {
7019
+ let dir = resolve(startDir);
7020
+ for (let i = 0; i < 64; i++) {
7021
+ for (const marker of PROJECT_MARKERS) {
7022
+ const candidate = join(dir, marker);
7023
+ if (existsSync(candidate)) {
7024
+ return buildRoot(dir, marker);
7025
+ }
7026
+ }
7027
+ if (existsSync(join(dir, GIT_MARKER))) {
7028
+ return buildRoot(dir, GIT_MARKER);
7029
+ }
7030
+ const parent = dirname(dir);
7031
+ if (parent === dir) return null;
7032
+ dir = parent;
7033
+ }
7034
+ return null;
7035
+ }
7036
+ function buildRoot(dir, marker) {
7037
+ let suggestedName = basename(dir);
7038
+ let scripts = null;
7039
+ let invalid = false;
7040
+ if (marker === "package.json" || existsSync(join(dir, "package.json"))) {
7041
+ try {
7042
+ const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
7043
+ if (typeof pkg.name === "string" && pkg.name.length > 0) {
7044
+ suggestedName = pkg.name.replace(/^@[^/]+\//, "");
7045
+ }
7046
+ if (pkg.scripts && typeof pkg.scripts === "object") {
7047
+ scripts = Object.fromEntries(
7048
+ Object.entries(pkg.scripts).filter(
7049
+ ([, v2]) => typeof v2 === "string"
7050
+ )
7051
+ );
7052
+ }
7053
+ } catch {
7054
+ invalid = true;
7055
+ }
7056
+ }
7057
+ return { path: dir, suggestedName, marker, packageJsonScripts: scripts, packageJsonInvalid: invalid };
7058
+ }
7059
+ function findEnvFiles(rootDir) {
7060
+ let entries;
7061
+ try {
7062
+ entries = readdirSync(rootDir);
7063
+ } catch {
7064
+ return [];
7065
+ }
7066
+ const hits = [];
7067
+ for (const name of entries) {
7068
+ if (!ENV_GLOB.test(name)) continue;
7069
+ if (ENV_EXAMPLE.test(name)) continue;
7070
+ if (name === KEYNV_ENV_BASENAME) continue;
7071
+ const full = join(rootDir, name);
7072
+ try {
7073
+ if (!statSync(full).isFile()) continue;
7074
+ } catch {
7075
+ continue;
7076
+ }
7077
+ const suffixMatch = name.match(/^\.env\.(.+)$/);
7078
+ const suffix = suffixMatch ? suffixMatch[1] : null;
7079
+ hits.push({ path: full, name, suffix, suggestedEnv: suggestedEnvForSuffix(suffix) });
7080
+ }
7081
+ hits.sort((a, b2) => {
7082
+ if (a.suffix === null) return -1;
7083
+ if (b2.suffix === null) return 1;
7084
+ return a.name.localeCompare(b2.name);
7085
+ });
7086
+ return hits;
7087
+ }
7088
+ function suggestedEnvForSuffix(suffix) {
7089
+ if (suffix === null) return "dev";
7090
+ switch (suffix) {
7091
+ case "local":
7092
+ case "development":
7093
+ case "dev":
7094
+ return "dev";
7095
+ case "production":
7096
+ case "prod":
7097
+ return "prod";
7098
+ case "staging":
7099
+ case "stage":
7100
+ return "staging";
7101
+ case "test":
7102
+ return "test";
7103
+ case "preview":
7104
+ return "preview";
7105
+ default:
7106
+ return suffix;
7107
+ }
7108
+ }
7109
+ function hasExistingKeynvEnv(rootDir) {
7110
+ return existsSync(join(rootDir, KEYNV_ENV_BASENAME));
7111
+ }
7112
+ var PROJECT_MARKERS, GIT_MARKER, ENV_GLOB, ENV_EXAMPLE, KEYNV_ENV_BASENAME;
7113
+ var init_detect = __esm({
7114
+ "src/init/detect.ts"() {
7115
+ PROJECT_MARKERS = [
7116
+ "package.json",
7117
+ "pyproject.toml",
7118
+ "Cargo.toml",
7119
+ "go.mod",
7120
+ "pnpm-workspace.yaml",
7121
+ "deno.json",
7122
+ "deno.jsonc",
7123
+ "requirements.txt"
7124
+ ];
7125
+ GIT_MARKER = ".git";
7126
+ ENV_GLOB = /^\.env(\.[A-Za-z0-9_-]+)?$/;
7127
+ ENV_EXAMPLE = /^\.env\.(example|sample|template)$/;
7128
+ KEYNV_ENV_BASENAME = ".keynv.env";
7129
+ }
7130
+ });
7131
+
7132
+ // src/init/heuristics.ts
7133
+ function shannonEntropyBits(s) {
7134
+ if (s.length === 0) return 0;
7135
+ const counts = /* @__PURE__ */ new Map();
7136
+ for (const ch of s) counts.set(ch, (counts.get(ch) ?? 0) + 1);
7137
+ let h2 = 0;
7138
+ for (const c2 of counts.values()) {
7139
+ const p2 = c2 / s.length;
7140
+ h2 -= p2 * Math.log2(p2);
7141
+ }
7142
+ return h2;
7143
+ }
7144
+ function nameMatchesLiteralPrefix(name) {
7145
+ const upper = name.toUpperCase();
7146
+ return NAME_LITERAL_PREFIX.some((p2) => upper.startsWith(p2));
7147
+ }
7148
+ function nameMatchesSecretSuffix(name) {
7149
+ const upper = name.toUpperCase();
7150
+ for (const { suffix, hint } of NAME_SECRET_SUFFIXES) {
7151
+ if (upper.endsWith(suffix) || upper.endsWith(`_${suffix}`)) {
7152
+ return { matched: true, hint };
7153
+ }
7154
+ }
7155
+ return { matched: false, hint: "" };
7156
+ }
7157
+ function classifyEntry(name, value) {
7158
+ const upper = name.toUpperCase();
7159
+ if (NAME_LITERAL_EXACT.has(upper)) {
7160
+ return { verdict: "literal", hint: "common config var" };
7161
+ }
7162
+ if (nameMatchesLiteralPrefix(name)) {
7163
+ return { verdict: "literal", hint: "public env (build-time bundled)" };
7164
+ }
7165
+ if (value.length === 0) {
7166
+ return { verdict: "literal", hint: "empty" };
7167
+ }
7168
+ for (const { re, hint } of VALUE_PATTERNS) {
7169
+ if (re.test(value)) return { verdict: "secret", hint };
7170
+ }
7171
+ const suffix = nameMatchesSecretSuffix(name);
7172
+ if (suffix.matched) {
7173
+ return { verdict: "secret", hint: suffix.hint };
7174
+ }
7175
+ if (NAME_DB_URL.test(name)) {
7176
+ return { verdict: "secret", hint: "database URL" };
7177
+ }
7178
+ if (value.length >= 32) {
7179
+ const bits = shannonEntropyBits(value);
7180
+ if (bits >= 3.5) {
7181
+ return { verdict: "secret", hint: `${value.length}-char random-looking string` };
7182
+ }
7183
+ }
7184
+ return { verdict: "ambiguous", hint: "" };
7185
+ }
7186
+ function previewValue(value, max = 40) {
7187
+ if (value.length === 0) return "(empty)";
7188
+ if (value.length <= max) return value;
7189
+ return `${value.slice(0, max - 1)}\u2026`;
7190
+ }
7191
+ var NAME_LITERAL_EXACT, NAME_LITERAL_PREFIX, NAME_SECRET_SUFFIXES, NAME_DB_URL, VALUE_PATTERNS;
7192
+ var init_heuristics = __esm({
7193
+ "src/init/heuristics.ts"() {
7194
+ NAME_LITERAL_EXACT = /* @__PURE__ */ new Set([
7195
+ "NODE_ENV",
7196
+ "PORT",
7197
+ "HOST",
7198
+ "HOSTNAME",
7199
+ "DEBUG",
7200
+ "LOG_LEVEL",
7201
+ "LOGLEVEL",
7202
+ "TZ",
7203
+ "LANG",
7204
+ "LC_ALL",
7205
+ "PATH",
7206
+ "HOME",
7207
+ "USER",
7208
+ "SHELL",
7209
+ "PWD",
7210
+ "CI",
7211
+ "NODE_OPTIONS",
7212
+ "NPM_CONFIG_LOGLEVEL",
7213
+ "TS_NODE_PROJECT"
7214
+ ]);
7215
+ NAME_LITERAL_PREFIX = ["NEXT_PUBLIC_", "VITE_", "REACT_APP_", "PUBLIC_", "EXPO_PUBLIC_"];
7216
+ NAME_SECRET_SUFFIXES = [
7217
+ { suffix: "PRIVATE_KEY", hint: "private key" },
7218
+ { suffix: "API_KEY", hint: "API key" },
7219
+ { suffix: "ACCESS_KEY", hint: "access key" },
7220
+ { suffix: "SECRET_KEY", hint: "secret key" },
7221
+ { suffix: "SECRET", hint: "secret" },
7222
+ { suffix: "PASSWORD", hint: "password" },
7223
+ { suffix: "PASSPHRASE", hint: "passphrase" },
7224
+ { suffix: "TOKEN", hint: "token" },
7225
+ { suffix: "KEY", hint: "key" },
7226
+ { suffix: "CREDENTIALS", hint: "credentials" },
7227
+ { suffix: "AUTH", hint: "auth" },
7228
+ { suffix: "DSN", hint: "connection string" }
7229
+ ];
7230
+ NAME_DB_URL = /^(DATABASE|DB|POSTGRES|MYSQL|MONGO|REDIS)_URL$/i;
7231
+ VALUE_PATTERNS = [
7232
+ { re: /^sk-proj-/, hint: "OpenAI project key" },
7233
+ { re: /^sk-[A-Za-z0-9]{20,}/, hint: "OpenAI key" },
7234
+ { re: /^sk_live_/, hint: "Stripe live key" },
7235
+ { re: /^sk_test_/, hint: "Stripe test key" },
7236
+ { re: /^pk_live_/, hint: "Stripe publishable (often public, double-check)" },
7237
+ { re: /^xoxb-/, hint: "Slack bot token" },
7238
+ { re: /^xoxp-/, hint: "Slack user token" },
7239
+ { re: /^ghp_[A-Za-z0-9]{30,}/, hint: "GitHub personal access token" },
7240
+ { re: /^github_pat_/, hint: "GitHub fine-grained PAT" },
7241
+ { re: /^gho_/, hint: "GitHub OAuth token" },
7242
+ { re: /^AKIA[0-9A-Z]{16}$/, hint: "AWS access key id" },
7243
+ { re: /^ASIA[0-9A-Z]{16}$/, hint: "AWS temporary key id" },
7244
+ { re: /^AIza[0-9A-Za-z_-]{35}$/, hint: "Google API key" },
7245
+ { re: /^ya29\./, hint: "Google OAuth access token" },
7246
+ { re: /^eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/, hint: "JWT" },
7247
+ { re: /^-----BEGIN [A-Z ]+PRIVATE KEY-----/, hint: "PEM private key" },
7248
+ { re: /^([a-z]+):\/\/[^@]+:[^@]+@/i, hint: "connection string with credentials" }
7249
+ ];
7250
+ }
7251
+ });
7252
+
7253
+ // src/init/scriptWrap.ts
7254
+ function analyzeScript(name, command) {
7255
+ const trimmed = command.trim();
7256
+ if (trimmed.startsWith("keynv ") || trimmed.startsWith("keynv ")) {
7257
+ return {
7258
+ name,
7259
+ original: command,
7260
+ wrapped: command,
7261
+ verdict: "skip-already-wrapped",
7262
+ hint: "already wrapped"
7263
+ };
7264
+ }
7265
+ const firstWord = extractFirstCommandWord(trimmed);
7266
+ if (firstWord === null) {
7267
+ return {
7268
+ name,
7269
+ original: command,
7270
+ wrapped: `${KEYNV_PREFIX} ${command}`,
7271
+ verdict: "skip-unknown",
7272
+ hint: "cannot parse"
7273
+ };
7274
+ }
7275
+ const wrapped = `${KEYNV_PREFIX} ${command}`;
7276
+ if (ENV_AWARE_TOOLS.has(firstWord)) {
7277
+ return { name, original: command, wrapped, verdict: "wrap", hint: `${firstWord} reads env` };
7278
+ }
7279
+ if (NON_ENV_TOOLS.has(firstWord)) {
7280
+ return {
7281
+ name,
7282
+ original: command,
7283
+ wrapped,
7284
+ verdict: "skip-no-env-tool",
7285
+ hint: `${firstWord} doesn't need env`
7286
+ };
7287
+ }
7288
+ return {
7289
+ name,
7290
+ original: command,
7291
+ wrapped,
7292
+ verdict: "skip-unknown",
7293
+ hint: `unrecognized: ${firstWord}`
7294
+ };
7295
+ }
7296
+ function extractFirstCommandWord(s) {
7297
+ const tokens = s.split(/\s+/).filter((t) => t.length > 0);
7298
+ let i = 0;
7299
+ while (i < tokens.length) {
7300
+ const t = tokens[i];
7301
+ if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(t)) {
7302
+ i++;
7303
+ continue;
7304
+ }
7305
+ if (t === "cross-env") {
7306
+ i++;
7307
+ while (i < tokens.length && /^[A-Za-z_][A-Za-z0-9_]*=/.test(tokens[i])) i++;
7308
+ continue;
7309
+ }
7310
+ if (t === "dotenv") {
7311
+ const dashDash = tokens.indexOf("--", i + 1);
7312
+ if (dashDash >= 0) {
7313
+ i = dashDash + 1;
7314
+ continue;
7315
+ }
7316
+ i++;
7317
+ while (i < tokens.length && tokens[i].startsWith("-")) i++;
7318
+ continue;
7319
+ }
7320
+ if (t === "sh" || t === "bash" || t === "zsh") {
7321
+ return null;
7322
+ }
7323
+ return t.replace(/^.*\//, "");
7324
+ }
7325
+ return null;
7326
+ }
7327
+ function planScriptWrap(scripts) {
7328
+ const recommended = [];
7329
+ const skipped = [];
7330
+ const unknown = [];
7331
+ for (const [name, command] of Object.entries(scripts)) {
7332
+ const analysis = analyzeScript(name, command);
7333
+ switch (analysis.verdict) {
7334
+ case "wrap":
7335
+ recommended.push(analysis);
7336
+ break;
7337
+ case "skip-unknown":
7338
+ unknown.push(analysis);
7339
+ break;
7340
+ default:
7341
+ skipped.push(analysis);
7342
+ }
7343
+ }
7344
+ return { recommended, skipped, unknown };
7345
+ }
7346
+ function applyWraps(original, selectedScriptNames) {
7347
+ const out = { ...original };
7348
+ const selection = new Set(selectedScriptNames);
7349
+ for (const [name, command] of Object.entries(original)) {
7350
+ if (!selection.has(name)) continue;
7351
+ const trimmed = command.trim();
7352
+ if (trimmed.startsWith("keynv ") || trimmed.startsWith("keynv ")) continue;
7353
+ out[name] = `${KEYNV_PREFIX} ${command}`;
7354
+ }
7355
+ return out;
7356
+ }
7357
+ var KEYNV_PREFIX, ENV_AWARE_TOOLS, NON_ENV_TOOLS;
7358
+ var init_scriptWrap = __esm({
7359
+ "src/init/scriptWrap.ts"() {
7360
+ KEYNV_PREFIX = "keynv exec --";
7361
+ ENV_AWARE_TOOLS = /* @__PURE__ */ new Set([
7362
+ "node",
7363
+ "tsx",
7364
+ "ts-node",
7365
+ "bun",
7366
+ "deno",
7367
+ "next",
7368
+ "nuxt",
7369
+ "vite",
7370
+ "remix",
7371
+ "astro",
7372
+ "gatsby",
7373
+ "nest",
7374
+ "webpack",
7375
+ "rollup",
7376
+ "parcel",
7377
+ "vitest",
7378
+ "jest",
7379
+ "mocha",
7380
+ "cypress",
7381
+ "playwright",
7382
+ "storybook",
7383
+ "tsc-watch",
7384
+ "pm2",
7385
+ "forever",
7386
+ "nodemon",
7387
+ "concurrently",
7388
+ "pytest",
7389
+ "python",
7390
+ "python3",
7391
+ "gunicorn",
7392
+ "uvicorn",
7393
+ "celery",
7394
+ "flask",
7395
+ "django-admin",
7396
+ "manage.py",
7397
+ "rails",
7398
+ "rake",
7399
+ "go",
7400
+ "cargo",
7401
+ "air"
7402
+ ]);
7403
+ NON_ENV_TOOLS = /* @__PURE__ */ new Set([
7404
+ "eslint",
7405
+ "biome",
7406
+ "prettier",
7407
+ "tsc",
7408
+ "tslint",
7409
+ "stylelint",
7410
+ "rm",
7411
+ "cp",
7412
+ "mv",
7413
+ "mkdir",
7414
+ "echo",
7415
+ "cat",
7416
+ "find",
7417
+ "grep",
7418
+ "sort",
7419
+ "uniq",
7420
+ "sed",
7421
+ "awk"
7422
+ ]);
7423
+ }
7424
+ });
6887
7425
 
6888
7426
  // src/ui/helpers/cancel.ts
6889
7427
  function unwrap(value) {
@@ -6925,6 +7463,419 @@ var init_pickProject = __esm({
6925
7463
  }
6926
7464
  });
6927
7465
 
7466
+ // src/ui/flows/init.ts
7467
+ var init_exports = {};
7468
+ __export(init_exports, {
7469
+ UserCancelled: () => UserCancelled,
7470
+ runInitFlow: () => runInitFlow
7471
+ });
7472
+ async function runInitFlow(client, opts) {
7473
+ ge("keynv init");
7474
+ const root = findProjectRoot(opts.cwd);
7475
+ if (root === null) {
7476
+ me(
7477
+ "Couldn't find a project root (no package.json, pyproject.toml, Cargo.toml, go.mod, or .git anywhere up the tree). Run `keynv init` inside a project directory."
7478
+ );
7479
+ return { exitCode: 1 };
7480
+ }
7481
+ if (root.packageJsonInvalid) {
7482
+ R2.warn(`package.json at ${root.path} is not valid JSON \u2014 script wrapping will be skipped.`);
7483
+ }
7484
+ const envFiles = findEnvFiles(root.path);
7485
+ if (envFiles.length === 0 && !hasExistingKeynvEnv(root.path)) {
7486
+ R2.info(
7487
+ `No .env files found in ${root.path}. There's nothing to migrate yet \u2014 create a .keynv.env by hand or run \`keynv exec\` once you have one.`
7488
+ );
7489
+ ye("Nothing to do.");
7490
+ return { exitCode: 0 };
7491
+ }
7492
+ const intoExisting = hasExistingKeynvEnv(root.path);
7493
+ Se(
7494
+ [
7495
+ `Project root: ${root.path}`,
7496
+ `Marker: ${root.marker}`,
7497
+ envFiles.length > 0 ? `Found env files: ${envFiles.map((f) => f.name).join(", ")}` : "Found env files: (none)",
7498
+ intoExisting ? "Existing .keynv.env detected \u2014 will merge new entries in." : ""
7499
+ ].filter(Boolean).join("\n"),
7500
+ "Detected"
7501
+ );
7502
+ const merged = mergeEnvFiles(envFiles);
7503
+ if (merged.length === 0) {
7504
+ R2.info("All env files were empty (only comments/blanks). Nothing to upload.");
7505
+ ye("Done.");
7506
+ return { exitCode: 0 };
7507
+ }
7508
+ const projectChoice = await pickOrCreateProject(client, root.suggestedName);
7509
+ if (projectChoice === null) {
7510
+ me("No project selected.");
7511
+ return { exitCode: 130 };
7512
+ }
7513
+ const envName = await pickEnvForUpload(client, projectChoice, envFiles);
7514
+ if (envName === null) {
7515
+ me("No environment selected.");
7516
+ return { exitCode: 130 };
7517
+ }
7518
+ const choices = merged.map((e2) => {
7519
+ const verdict = classifyEntry(e2.name, e2.value);
7520
+ const hint = verdict.hint || (e2.isAlias ? "looks like an alias literal" : "no signal");
7521
+ const preview2 = e2.isAlias ? e2.value : previewValue(e2.value, 32);
7522
+ return {
7523
+ name: e2.name,
7524
+ value: e2.value,
7525
+ isAlias: e2.isAlias,
7526
+ verdict: verdict.verdict,
7527
+ label: `${e2.name} ${preview2}`,
7528
+ hint,
7529
+ sourceLine: e2.sourceLine,
7530
+ source: e2.source
7531
+ };
7532
+ });
7533
+ const initialSecretSelection = choices.filter((c2) => c2.verdict === "secret" && !c2.isAlias).map((c2) => c2.name);
7534
+ const selectedSecretNames = unwrap(
7535
+ await ve({
7536
+ message: "Mark which keys are secrets (vault-uploaded). Unchecked keys stay as literals.",
7537
+ options: choices.map((c2) => ({
7538
+ value: c2.name,
7539
+ label: c2.label,
7540
+ hint: c2.isAlias ? `${c2.hint} \u2014 already aliased; will pass through` : c2.hint
7541
+ })),
7542
+ initialValues: initialSecretSelection,
7543
+ required: false
7544
+ })
7545
+ );
7546
+ const selected = new Set(selectedSecretNames);
7547
+ let scriptWrapSelection = [];
7548
+ let scriptPlan = root.packageJsonScripts ? planScriptWrap(root.packageJsonScripts) : null;
7549
+ if (!opts.noScripts && scriptPlan && scriptPlan.recommended.length > 0) {
7550
+ const wrapAnswer = unwrap(
7551
+ await ve({
7552
+ message: "Wrap package.json scripts with `keynv exec`? (recommended)",
7553
+ options: [
7554
+ ...scriptPlan.recommended.map((a) => ({
7555
+ value: a.name,
7556
+ label: `${a.name} \u2192 ${a.wrapped}`,
7557
+ hint: a.hint
7558
+ })),
7559
+ ...scriptPlan.unknown.map((a) => ({
7560
+ value: a.name,
7561
+ label: `${a.name} \u2192 ${a.wrapped}`,
7562
+ hint: `unknown tool \u2014 opt in if you know it reads env`
7563
+ }))
7564
+ ],
7565
+ initialValues: scriptPlan.recommended.map((a) => a.name),
7566
+ required: false
7567
+ })
7568
+ );
7569
+ scriptWrapSelection = wrapAnswer;
7570
+ } else if (opts.noScripts) {
7571
+ scriptPlan = null;
7572
+ }
7573
+ const envFileFateRaw = unwrap(
7574
+ await Ee({
7575
+ message: "After upload, what about the original .env files?",
7576
+ options: [
7577
+ { value: "delete", label: "Delete (recommended \u2014 eliminates the leak vector)" },
7578
+ { value: "gitignore", label: "Keep but make sure .gitignore covers them" }
7579
+ ],
7580
+ initialValue: "delete"
7581
+ })
7582
+ );
7583
+ const planSummary = [
7584
+ `Project: ${projectChoice.name}${projectChoice.created ? " (will be created)" : ""}`,
7585
+ `Environment: ${envName}`,
7586
+ `Secrets to vault: ${selected.size}`,
7587
+ `Literals in file: ${merged.length - selected.size}`,
7588
+ `Script wraps: ${scriptWrapSelection.length}`,
7589
+ `Original .env: ${envFileFateRaw === "delete" ? "delete" : "keep + gitignore"}`,
7590
+ opts.dryRun ? "Dry-run: no changes will be made." : ""
7591
+ ].filter(Boolean).join("\n");
7592
+ Se(planSummary, "About to apply");
7593
+ const proceed = unwrap(await ue({ message: "Proceed?", initialValue: true }));
7594
+ if (!proceed) {
7595
+ me("Aborted.");
7596
+ return { exitCode: 130 };
7597
+ }
7598
+ if (opts.dryRun) {
7599
+ ye("Dry-run complete \u2014 no changes were made.");
7600
+ return { exitCode: 0 };
7601
+ }
7602
+ let projectId2;
7603
+ if (projectChoice.created) {
7604
+ const s = ft();
7605
+ s.start(`Creating project "${projectChoice.name}"`);
7606
+ try {
7607
+ const created = await client.request("/v1/projects", {
7608
+ method: "POST",
7609
+ body: {
7610
+ name: projectChoice.name,
7611
+ environments: [{ name: envName, tier: "non-production", require_approval: false }]
7612
+ }
7613
+ });
7614
+ projectId2 = created.id;
7615
+ s.stop(`Created project ${created.name}`);
7616
+ } catch (err) {
7617
+ s.error(`Failed to create project: ${err instanceof Error ? err.message : String(err)}`);
7618
+ return { exitCode: 1 };
7619
+ }
7620
+ } else {
7621
+ projectId2 = projectChoice.id;
7622
+ }
7623
+ const uploaded = [];
7624
+ const failed = [];
7625
+ if (selected.size > 0) {
7626
+ const s = ft();
7627
+ s.start(`Uploading ${selected.size} secrets`);
7628
+ let i = 0;
7629
+ for (const entry2 of merged) {
7630
+ if (!selected.has(entry2.name)) continue;
7631
+ i++;
7632
+ s.message(`Uploading (${i}/${selected.size}) ${entry2.name}`);
7633
+ const aliasKey = entry2.name.toLowerCase().replace(/_/g, "-");
7634
+ try {
7635
+ await client.request(`/v1/projects/${projectId2}/secrets`, {
7636
+ method: "POST",
7637
+ body: { env: envName, key: aliasKey, value: entry2.value }
7638
+ });
7639
+ const alias2 = buildAlias({ project: projectChoice.name, environment: envName, key: aliasKey });
7640
+ if (alias2 === null) {
7641
+ failed.push({
7642
+ name: entry2.name,
7643
+ reason: `produced an invalid alias for project=${projectChoice.name} env=${envName} key=${aliasKey}`
7644
+ });
7645
+ } else {
7646
+ uploaded.push({ name: entry2.name, aliasLiteral: alias2.literal });
7647
+ }
7648
+ } catch (err) {
7649
+ failed.push({ name: entry2.name, reason: err instanceof Error ? err.message : String(err) });
7650
+ }
7651
+ }
7652
+ if (failed.length === 0) {
7653
+ s.stop(`Uploaded ${uploaded.length} secrets`);
7654
+ } else {
7655
+ s.error(`${uploaded.length}/${selected.size} uploaded; ${failed.length} failed`);
7656
+ for (const f of failed) R2.warn(` ${f.name}: ${f.reason}`);
7657
+ }
7658
+ }
7659
+ const literals = merged.filter((e2) => !selected.has(e2.name));
7660
+ const successUploads = new Map(uploaded.map((u) => [u.name, u.aliasLiteral]));
7661
+ const keynvEnvPath = join(root.path, ".keynv.env");
7662
+ let writtenLines;
7663
+ try {
7664
+ writtenLines = composeKeynvEnv({
7665
+ uploadedAliases: successUploads,
7666
+ literals,
7667
+ mergeWithExisting: intoExisting ? readFileSync(keynvEnvPath, "utf8") : null
7668
+ });
7669
+ writeFileSync(keynvEnvPath, `${writtenLines.join("\n")}
7670
+ `);
7671
+ R2.success(
7672
+ `${intoExisting ? "Updated" : "Wrote"} ${keynvEnvPath} (${successUploads.size + literals.length} entries)`
7673
+ );
7674
+ } catch (err) {
7675
+ R2.error(`Failed to write .keynv.env: ${err instanceof Error ? err.message : String(err)}`);
7676
+ return { exitCode: 1 };
7677
+ }
7678
+ if (scriptWrapSelection.length > 0 && root.packageJsonScripts) {
7679
+ try {
7680
+ updatePackageJsonScripts(
7681
+ join(root.path, "package.json"),
7682
+ root.packageJsonScripts,
7683
+ scriptWrapSelection
7684
+ );
7685
+ R2.success(`Wrapped ${scriptWrapSelection.length} script(s) in package.json`);
7686
+ } catch (err) {
7687
+ R2.warn(
7688
+ `Could not update package.json scripts: ${err instanceof Error ? err.message : String(err)}`
7689
+ );
7690
+ }
7691
+ }
7692
+ if (envFileFateRaw === "delete") {
7693
+ for (const f of envFiles) {
7694
+ try {
7695
+ unlinkSync(f.path);
7696
+ R2.success(`Removed ${f.name}`);
7697
+ } catch (err) {
7698
+ R2.warn(`Could not remove ${f.name}: ${err instanceof Error ? err.message : String(err)}`);
7699
+ }
7700
+ }
7701
+ } else {
7702
+ const gitignorePath = join(root.path, ".gitignore");
7703
+ try {
7704
+ ensureGitignoreEntries(gitignorePath, envFiles.map((f) => f.name));
7705
+ R2.success(`Updated .gitignore (${envFiles.length} entries ensured)`);
7706
+ } catch (err) {
7707
+ R2.warn(`Could not update .gitignore: ${err instanceof Error ? err.message : String(err)}`);
7708
+ }
7709
+ }
7710
+ ye(
7711
+ failed.length > 0 ? `Done with ${failed.length} failure(s) \u2014 see warnings above.` : `Done. Try: ${scriptWrapSelection.includes("dev") ? "npm run dev" : "keynv exec -- <your command>"}`
7712
+ );
7713
+ return { exitCode: failed.length > 0 ? 1 : 0 };
7714
+ }
7715
+ function mergeEnvFiles(files) {
7716
+ const map = /* @__PURE__ */ new Map();
7717
+ for (const f of files) {
7718
+ let entries;
7719
+ try {
7720
+ entries = parseEnvFile(readFileSync(f.path, "utf8"), f.path);
7721
+ } catch (err) {
7722
+ R2.warn(`${f.name}: ${err instanceof Error ? err.message : String(err)} \u2014 skipping file`);
7723
+ continue;
7724
+ }
7725
+ for (const e2 of entries) {
7726
+ const existing = map.get(e2.name);
7727
+ if (existing) {
7728
+ existing.shadowedBy.push(f.name);
7729
+ existing.value = e2.value;
7730
+ existing.isAlias = e2.isAlias;
7731
+ } else {
7732
+ map.set(e2.name, {
7733
+ name: e2.name,
7734
+ value: e2.value,
7735
+ isAlias: e2.isAlias,
7736
+ source: f.name,
7737
+ sourceLine: e2.line,
7738
+ shadowedBy: []
7739
+ });
7740
+ }
7741
+ }
7742
+ }
7743
+ return [...map.values()];
7744
+ }
7745
+ async function pickOrCreateProject(client, suggestedName) {
7746
+ const projects = await listProjects(client);
7747
+ const value = unwrap(
7748
+ await Ee({
7749
+ message: "Use which keynv project?",
7750
+ options: [
7751
+ { value: "__new", label: `+ Create new: "${suggestedName}"` },
7752
+ ...projects.map((p2) => ({ value: p2.id, label: p2.name, hint: p2.id }))
7753
+ ]
7754
+ })
7755
+ );
7756
+ if (value === "__new") {
7757
+ const name = unwrap(
7758
+ await Re({
7759
+ message: "Project name",
7760
+ initialValue: suggestedName,
7761
+ validate: (v2) => v2 && /^[a-z0-9][a-z0-9-]{0,47}$/.test(v2) ? void 0 : "lowercase letters, digits, dashes; up to 48 chars"
7762
+ })
7763
+ );
7764
+ return { id: "", name, created: true };
7765
+ }
7766
+ const match = projects.find((p2) => p2.id === value);
7767
+ if (!match) return null;
7768
+ return { id: match.id, name: match.name, created: false };
7769
+ }
7770
+ async function pickEnvForUpload(client, project, envFiles) {
7771
+ const firstSuffix = envFiles[0]?.suffix ?? null;
7772
+ const suggested = suggestedEnvForSuffix(firstSuffix);
7773
+ if (project.created) {
7774
+ const value2 = unwrap(
7775
+ await Re({
7776
+ message: "Environment to create",
7777
+ initialValue: suggested,
7778
+ validate: (v2) => v2 && /^[a-z0-9][a-z0-9-]{0,23}$/.test(v2) ? void 0 : "lowercase letters, digits, dashes; up to 24 chars"
7779
+ })
7780
+ );
7781
+ return value2;
7782
+ }
7783
+ const detail = await client.request(`/v1/projects/${project.id}`);
7784
+ if (detail.environments.length === 0) {
7785
+ me(
7786
+ `Project "${project.name}" has no environments yet, and we can't add one from init in this version. Create one with \`keynv project create\` (or pick a different project).`
7787
+ );
7788
+ return null;
7789
+ }
7790
+ if (detail.environments.length === 1) {
7791
+ return detail.environments[0]?.name ?? null;
7792
+ }
7793
+ const value = unwrap(
7794
+ await Ee({
7795
+ message: "Upload to which environment?",
7796
+ options: detail.environments.map((e2) => ({
7797
+ value: e2.name,
7798
+ label: e2.name,
7799
+ hint: e2.tier
7800
+ })),
7801
+ initialValue: detail.environments.find((e2) => e2.name === suggested)?.name
7802
+ })
7803
+ );
7804
+ return value;
7805
+ }
7806
+ function composeKeynvEnv(opts) {
7807
+ const { uploadedAliases, literals, mergeWithExisting } = opts;
7808
+ const lines = [];
7809
+ if (mergeWithExisting !== null) {
7810
+ const trimmed = mergeWithExisting.replace(/\n+$/, "");
7811
+ if (trimmed.length > 0) {
7812
+ lines.push(...trimmed.split("\n"));
7813
+ lines.push("");
7814
+ }
7815
+ lines.push(`# >>> keynv init ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)} >>>`);
7816
+ } else {
7817
+ lines.push("# .keynv.env \u2014 alias references to vault secrets.");
7818
+ lines.push("# Safe to commit: this file contains references, not values.");
7819
+ lines.push("# Auto-loaded by `keynv exec`. See https://keynv.dev/docs/keynv-env");
7820
+ lines.push("");
7821
+ }
7822
+ if (uploadedAliases.size > 0) {
7823
+ lines.push("# Vault-resolved (real values live on the keynv server)");
7824
+ for (const [name, alias2] of uploadedAliases) {
7825
+ lines.push(`${name}=${alias2}`);
7826
+ }
7827
+ }
7828
+ if (literals.length > 0) {
7829
+ if (uploadedAliases.size > 0) lines.push("");
7830
+ lines.push("# Plain literals (passed through unchanged)");
7831
+ for (const e2 of literals) {
7832
+ const value = needsQuoting(e2.value) ? `"${e2.value.replace(/"/g, '\\"')}"` : e2.value;
7833
+ lines.push(`${e2.name}=${value}`);
7834
+ }
7835
+ }
7836
+ if (mergeWithExisting !== null) {
7837
+ lines.push(`# <<< keynv init <<<`);
7838
+ }
7839
+ return lines;
7840
+ }
7841
+ function needsQuoting(value) {
7842
+ return /\s/.test(value) || value.includes("#") || value.length === 0;
7843
+ }
7844
+ function updatePackageJsonScripts(path, originalScripts, selectedNames) {
7845
+ const raw = readFileSync(path, "utf8");
7846
+ const indentMatch = raw.match(/^([ \t]+)"/m);
7847
+ const indent = indentMatch ? indentMatch[1] : " ";
7848
+ const trailingNewline = raw.endsWith("\n");
7849
+ const pkg = JSON.parse(raw);
7850
+ const updated = applyWraps(originalScripts, selectedNames);
7851
+ pkg.scripts = updated;
7852
+ const out = JSON.stringify(pkg, null, indent);
7853
+ writeFileSync(path, trailingNewline ? `${out}
7854
+ ` : out);
7855
+ }
7856
+ function ensureGitignoreEntries(path, basenames) {
7857
+ let existing = "";
7858
+ if (existsSync(path)) existing = readFileSync(path, "utf8");
7859
+ const existingLines = new Set(existing.split("\n").map((l) => l.trim()));
7860
+ const toAdd = basenames.filter((n) => !existingLines.has(n));
7861
+ if (toAdd.length === 0) return;
7862
+ const sep = existing.length === 0 || existing.endsWith("\n") ? "" : "\n";
7863
+ const block = ["", "# added by keynv init", ...toAdd, ""].join("\n");
7864
+ writeFileSync(path, `${existing}${sep}${block}`);
7865
+ }
7866
+ var init_init = __esm({
7867
+ "src/ui/flows/init.ts"() {
7868
+ init_dist();
7869
+ init_dist5();
7870
+ init_envFile();
7871
+ init_detect();
7872
+ init_heuristics();
7873
+ init_scriptWrap();
7874
+ init_cancel();
7875
+ init_pickProject();
7876
+ }
7877
+ });
7878
+
6928
7879
  // src/ui/helpers/pickSecret.ts
6929
7880
  async function listSecrets(client, projectId2) {
6930
7881
  const data = await client.request(
@@ -7060,14 +8011,14 @@ async function runSecretMenu(client, project, alias2) {
7060
8011
  async function copyToClipboard(value) {
7061
8012
  const platform = process.platform;
7062
8013
  const cmd = platform === "darwin" ? ["pbcopy", []] : platform === "win32" ? ["clip", []] : ["xclip", ["-selection", "clipboard"]];
7063
- return new Promise((resolve) => {
8014
+ return new Promise((resolve3) => {
7064
8015
  try {
7065
8016
  const child = spawn(cmd[0], cmd[1], { stdio: ["pipe", "ignore", "ignore"] });
7066
- child.on("error", () => resolve(false));
7067
- child.on("exit", (code) => resolve(code === 0));
8017
+ child.on("error", () => resolve3(false));
8018
+ child.on("exit", (code) => resolve3(code === 0));
7068
8019
  child.stdin.end(value);
7069
8020
  } catch {
7070
- resolve(false);
8021
+ resolve3(false);
7071
8022
  }
7072
8023
  });
7073
8024
  }
@@ -7187,24 +8138,24 @@ var require_lib2 = __commonJS({
7187
8138
  const currentChar = sql.charCodeAt(position);
7188
8139
  const nextChar = sql.charCodeAt(position + 1);
7189
8140
  if (currentChar === charCode.singleQuote) {
7190
- for (let cursor2 = position + 1; cursor2 < sql.length; cursor2++) {
7191
- if (sql.charCodeAt(cursor2) === charCode.backslash)
7192
- cursor2++;
7193
- else if (sql.charCodeAt(cursor2) === charCode.singleQuote)
7194
- return cursor2 + 1;
8141
+ for (let cursor = position + 1; cursor < sql.length; cursor++) {
8142
+ if (sql.charCodeAt(cursor) === charCode.backslash)
8143
+ cursor++;
8144
+ else if (sql.charCodeAt(cursor) === charCode.singleQuote)
8145
+ return cursor + 1;
7195
8146
  }
7196
8147
  return sql.length;
7197
8148
  }
7198
8149
  if (currentChar === charCode.backtick) {
7199
8150
  const length = sql.length;
7200
- for (let cursor2 = position + 1; cursor2 < length; cursor2++) {
7201
- if (sql.charCodeAt(cursor2) !== charCode.backtick)
8151
+ for (let cursor = position + 1; cursor < length; cursor++) {
8152
+ if (sql.charCodeAt(cursor) !== charCode.backtick)
7202
8153
  continue;
7203
- if (sql.charCodeAt(cursor2 + 1) === charCode.backtick) {
7204
- cursor2++;
8154
+ if (sql.charCodeAt(cursor + 1) === charCode.backtick) {
8155
+ cursor++;
7205
8156
  continue;
7206
8157
  }
7207
- return cursor2 + 1;
8158
+ return cursor + 1;
7208
8159
  }
7209
8160
  return length;
7210
8161
  }
@@ -7247,11 +8198,11 @@ var require_lib2 = __commonJS({
7247
8198
  if (lower === 115 && matchesWord(sql, position, "set", length))
7248
8199
  return position + 3;
7249
8200
  if (lower === 107 && matchesWord(sql, position, "key", length)) {
7250
- let cursor2 = position + 3;
7251
- while (cursor2 < length && isWhitespace(sql.charCodeAt(cursor2)))
7252
- cursor2++;
7253
- if (matchesWord(sql, cursor2, "update", length))
7254
- return cursor2 + 6;
8201
+ let cursor = position + 3;
8202
+ while (cursor < length && isWhitespace(sql.charCodeAt(cursor)))
8203
+ cursor++;
8204
+ if (matchesWord(sql, cursor, "update", length))
8205
+ return cursor + 6;
7255
8206
  }
7256
8207
  }
7257
8208
  return -1;
@@ -23813,7 +24764,7 @@ var require_named_placeholders = __commonJS({
23813
24764
  }
23814
24765
  return s;
23815
24766
  }
23816
- function join7(tree) {
24767
+ function join5(tree) {
23817
24768
  if (tree.length === 1) {
23818
24769
  return tree;
23819
24770
  }
@@ -23839,7 +24790,7 @@ var require_named_placeholders = __commonJS({
23839
24790
  if (cache2 && (tree = cache2.get(query))) {
23840
24791
  return toArrayParams(tree, paramsObj);
23841
24792
  }
23842
- tree = join7(parse(query));
24793
+ tree = join5(parse(query));
23843
24794
  if (cache2) {
23844
24795
  cache2.set(query, tree);
23845
24796
  }
@@ -23995,11 +24946,11 @@ var require_connection = __commonJS({
23995
24946
  const config = this.config;
23996
24947
  tracePromise(
23997
24948
  connectChannel,
23998
- () => new Promise((resolve, reject) => {
24949
+ () => new Promise((resolve3, reject) => {
23999
24950
  let onConnect, onError;
24000
24951
  onConnect = (param) => {
24001
24952
  this.removeListener("error", onError);
24002
- resolve(param);
24953
+ resolve3(param);
24003
24954
  };
24004
24955
  onError = (err) => {
24005
24956
  this.removeListener("connect", onConnect);
@@ -24424,9 +25375,9 @@ var require_connection = __commonJS({
24424
25375
  } else if (shouldTrace(queryChannel)) {
24425
25376
  tracePromise(
24426
25377
  queryChannel,
24427
- () => new Promise((resolve, reject) => {
25378
+ () => new Promise((resolve3, reject) => {
24428
25379
  cmdQuery.once("error", reject);
24429
- cmdQuery.once("end", () => resolve());
25380
+ cmdQuery.once("end", () => resolve3());
24430
25381
  this.addCommand(cmdQuery);
24431
25382
  }),
24432
25383
  () => {
@@ -24573,12 +25524,12 @@ var require_connection = __commonJS({
24573
25524
  } else if (shouldTrace(executeChannel)) {
24574
25525
  tracePromise(
24575
25526
  executeChannel,
24576
- () => new Promise((resolve, reject) => {
25527
+ () => new Promise((resolve3, reject) => {
24577
25528
  prepareAndExecute((err) => {
24578
25529
  executeCommand.emit("error", err);
24579
25530
  });
24580
25531
  executeCommand.once("error", reject);
24581
- executeCommand.once("end", () => resolve());
25532
+ executeCommand.once("end", () => resolve3());
24582
25533
  }),
24583
25534
  () => {
24584
25535
  const server = getServerContext(this.config);
@@ -24843,13 +25794,13 @@ var require_capture_local_err = __commonJS({
24843
25794
  var require_make_done_cb = __commonJS({
24844
25795
  "../../node_modules/.pnpm/mysql2@3.22.3_@types+node@24.12.3/node_modules/mysql2/lib/promise/make_done_cb.js"(exports, module) {
24845
25796
  var { applyCapturedStack } = require_capture_local_err();
24846
- function makeDoneCb(resolve, reject, stackHolder) {
25797
+ function makeDoneCb(resolve3, reject, stackHolder) {
24847
25798
  return function(err, rows, fields) {
24848
25799
  if (err) {
24849
25800
  applyCapturedStack(err, stackHolder);
24850
25801
  reject(err);
24851
25802
  } else {
24852
- resolve([rows, fields]);
25803
+ resolve3([rows, fields]);
24853
25804
  }
24854
25805
  };
24855
25806
  }
@@ -24872,8 +25823,8 @@ var require_prepared_statement_info = __commonJS({
24872
25823
  const stackHolder = captureStackHolder(
24873
25824
  _PromisePreparedStatementInfo.prototype.execute
24874
25825
  );
24875
- return new this.Promise((resolve, reject) => {
24876
- const done = makeDoneCb(resolve, reject, stackHolder);
25826
+ return new this.Promise((resolve3, reject) => {
25827
+ const done = makeDoneCb(resolve3, reject, stackHolder);
24877
25828
  if (parameters) {
24878
25829
  s.execute(parameters, done);
24879
25830
  } else {
@@ -24882,9 +25833,9 @@ var require_prepared_statement_info = __commonJS({
24882
25833
  });
24883
25834
  }
24884
25835
  close() {
24885
- return new this.Promise((resolve) => {
25836
+ return new this.Promise((resolve3) => {
24886
25837
  this.statement.close();
24887
- resolve();
25838
+ resolve3();
24888
25839
  });
24889
25840
  }
24890
25841
  };
@@ -24955,8 +25906,8 @@ var require_connection2 = __commonJS({
24955
25906
  "Callback function is not available with promise clients."
24956
25907
  );
24957
25908
  }
24958
- return new this.Promise((resolve, reject) => {
24959
- const done = makeDoneCb(resolve, reject, stackHolder);
25909
+ return new this.Promise((resolve3, reject) => {
25910
+ const done = makeDoneCb(resolve3, reject, stackHolder);
24960
25911
  if (params !== void 0) {
24961
25912
  c2.query(query, params, done);
24962
25913
  } else {
@@ -24972,8 +25923,8 @@ var require_connection2 = __commonJS({
24972
25923
  "Callback function is not available with promise clients."
24973
25924
  );
24974
25925
  }
24975
- return new this.Promise((resolve, reject) => {
24976
- const done = makeDoneCb(resolve, reject, stackHolder);
25926
+ return new this.Promise((resolve3, reject) => {
25927
+ const done = makeDoneCb(resolve3, reject, stackHolder);
24977
25928
  if (params !== void 0) {
24978
25929
  c2.execute(query, params, done);
24979
25930
  } else {
@@ -24982,8 +25933,8 @@ var require_connection2 = __commonJS({
24982
25933
  });
24983
25934
  }
24984
25935
  end() {
24985
- return new this.Promise((resolve) => {
24986
- this.connection.end(resolve);
25936
+ return new this.Promise((resolve3) => {
25937
+ this.connection.end(resolve3);
24987
25938
  });
24988
25939
  }
24989
25940
  async [Symbol.asyncDispose]() {
@@ -24996,16 +25947,16 @@ var require_connection2 = __commonJS({
24996
25947
  const stackHolder = captureStackHolder(
24997
25948
  _PromiseConnection.prototype.beginTransaction
24998
25949
  );
24999
- return new this.Promise((resolve, reject) => {
25000
- const done = makeDoneCb(resolve, reject, stackHolder);
25950
+ return new this.Promise((resolve3, reject) => {
25951
+ const done = makeDoneCb(resolve3, reject, stackHolder);
25001
25952
  c2.beginTransaction(done);
25002
25953
  });
25003
25954
  }
25004
25955
  commit() {
25005
25956
  const c2 = this.connection;
25006
25957
  const stackHolder = captureStackHolder(_PromiseConnection.prototype.commit);
25007
- return new this.Promise((resolve, reject) => {
25008
- const done = makeDoneCb(resolve, reject, stackHolder);
25958
+ return new this.Promise((resolve3, reject) => {
25959
+ const done = makeDoneCb(resolve3, reject, stackHolder);
25009
25960
  c2.commit(done);
25010
25961
  });
25011
25962
  }
@@ -25014,21 +25965,21 @@ var require_connection2 = __commonJS({
25014
25965
  const stackHolder = captureStackHolder(
25015
25966
  _PromiseConnection.prototype.rollback
25016
25967
  );
25017
- return new this.Promise((resolve, reject) => {
25018
- const done = makeDoneCb(resolve, reject, stackHolder);
25968
+ return new this.Promise((resolve3, reject) => {
25969
+ const done = makeDoneCb(resolve3, reject, stackHolder);
25019
25970
  c2.rollback(done);
25020
25971
  });
25021
25972
  }
25022
25973
  ping() {
25023
25974
  const c2 = this.connection;
25024
25975
  const stackHolder = captureStackHolder(_PromiseConnection.prototype.ping);
25025
- return new this.Promise((resolve, reject) => {
25976
+ return new this.Promise((resolve3, reject) => {
25026
25977
  c2.ping((err) => {
25027
25978
  if (err) {
25028
25979
  applyCapturedStack(err, stackHolder);
25029
25980
  reject(err);
25030
25981
  } else {
25031
- resolve(true);
25982
+ resolve3(true);
25032
25983
  }
25033
25984
  });
25034
25985
  });
@@ -25036,13 +25987,13 @@ var require_connection2 = __commonJS({
25036
25987
  reset() {
25037
25988
  const c2 = this.connection;
25038
25989
  const stackHolder = captureStackHolder(_PromiseConnection.prototype.reset);
25039
- return new this.Promise((resolve, reject) => {
25990
+ return new this.Promise((resolve3, reject) => {
25040
25991
  c2.reset((err) => {
25041
25992
  if (err) {
25042
25993
  applyCapturedStack(err, stackHolder);
25043
25994
  reject(err);
25044
25995
  } else {
25045
- resolve();
25996
+ resolve3();
25046
25997
  }
25047
25998
  });
25048
25999
  });
@@ -25050,13 +26001,13 @@ var require_connection2 = __commonJS({
25050
26001
  connect() {
25051
26002
  const c2 = this.connection;
25052
26003
  const stackHolder = captureStackHolder(_PromiseConnection.prototype.connect);
25053
- return new this.Promise((resolve, reject) => {
26004
+ return new this.Promise((resolve3, reject) => {
25054
26005
  c2.connect((err, param) => {
25055
26006
  if (err) {
25056
26007
  applyCapturedStack(err, stackHolder);
25057
26008
  reject(err);
25058
26009
  } else {
25059
- resolve(param);
26010
+ resolve3(param);
25060
26011
  }
25061
26012
  });
25062
26013
  });
@@ -25065,7 +26016,7 @@ var require_connection2 = __commonJS({
25065
26016
  const c2 = this.connection;
25066
26017
  const promiseImpl = this.Promise;
25067
26018
  const stackHolder = captureStackHolder(_PromiseConnection.prototype.prepare);
25068
- return new this.Promise((resolve, reject) => {
26019
+ return new this.Promise((resolve3, reject) => {
25069
26020
  c2.prepare(options, (err, statement) => {
25070
26021
  if (err) {
25071
26022
  applyCapturedStack(err, stackHolder);
@@ -25075,7 +26026,7 @@ var require_connection2 = __commonJS({
25075
26026
  statement,
25076
26027
  promiseImpl
25077
26028
  );
25078
- resolve(wrappedStatement);
26029
+ resolve3(wrappedStatement);
25079
26030
  }
25080
26031
  });
25081
26032
  });
@@ -25085,13 +26036,13 @@ var require_connection2 = __commonJS({
25085
26036
  const stackHolder = captureStackHolder(
25086
26037
  _PromiseConnection.prototype.changeUser
25087
26038
  );
25088
- return new this.Promise((resolve, reject) => {
26039
+ return new this.Promise((resolve3, reject) => {
25089
26040
  c2.changeUser(options, (err) => {
25090
26041
  if (err) {
25091
26042
  applyCapturedStack(err, stackHolder);
25092
26043
  reject(err);
25093
26044
  } else {
25094
- resolve();
26045
+ resolve3();
25095
26046
  }
25096
26047
  });
25097
26048
  });
@@ -25553,12 +26504,12 @@ var require_pool2 = __commonJS({
25553
26504
  }
25554
26505
  getConnection() {
25555
26506
  const corePool = this.pool;
25556
- return new this.Promise((resolve, reject) => {
26507
+ return new this.Promise((resolve3, reject) => {
25557
26508
  corePool.getConnection((err, coreConnection) => {
25558
26509
  if (err) {
25559
26510
  reject(err);
25560
26511
  } else {
25561
- resolve(new PromisePoolConnection(coreConnection, this.Promise));
26512
+ resolve3(new PromisePoolConnection(coreConnection, this.Promise));
25562
26513
  }
25563
26514
  });
25564
26515
  });
@@ -25574,8 +26525,8 @@ var require_pool2 = __commonJS({
25574
26525
  "Callback function is not available with promise clients."
25575
26526
  );
25576
26527
  }
25577
- return new this.Promise((resolve, reject) => {
25578
- const done = makeDoneCb(resolve, reject, stackHolder);
26528
+ return new this.Promise((resolve3, reject) => {
26529
+ const done = makeDoneCb(resolve3, reject, stackHolder);
25579
26530
  if (args !== void 0) {
25580
26531
  corePool.query(sql, args, done);
25581
26532
  } else {
@@ -25591,8 +26542,8 @@ var require_pool2 = __commonJS({
25591
26542
  "Callback function is not available with promise clients."
25592
26543
  );
25593
26544
  }
25594
- return new this.Promise((resolve, reject) => {
25595
- const done = makeDoneCb(resolve, reject, stackHolder);
26545
+ return new this.Promise((resolve3, reject) => {
26546
+ const done = makeDoneCb(resolve3, reject, stackHolder);
25596
26547
  if (args) {
25597
26548
  corePool.execute(sql, args, done);
25598
26549
  } else {
@@ -25603,13 +26554,13 @@ var require_pool2 = __commonJS({
25603
26554
  end() {
25604
26555
  const corePool = this.pool;
25605
26556
  const stackHolder = captureStackHolder(_PromisePool.prototype.end);
25606
- return new this.Promise((resolve, reject) => {
26557
+ return new this.Promise((resolve3, reject) => {
25607
26558
  corePool.end((err) => {
25608
26559
  if (err) {
25609
26560
  applyCapturedStack(err, stackHolder);
25610
26561
  reject(err);
25611
26562
  } else {
25612
- resolve();
26563
+ resolve3();
25613
26564
  }
25614
26565
  });
25615
26566
  });
@@ -26034,12 +26985,12 @@ var require_pool_cluster2 = __commonJS({
26034
26985
  }
26035
26986
  getConnection() {
26036
26987
  const corePoolNamespace = this.poolNamespace;
26037
- return new this.Promise((resolve, reject) => {
26988
+ return new this.Promise((resolve3, reject) => {
26038
26989
  corePoolNamespace.getConnection((err, coreConnection) => {
26039
26990
  if (err) {
26040
26991
  reject(err);
26041
26992
  } else {
26042
- resolve(new PromisePoolConnection(coreConnection, this.Promise));
26993
+ resolve3(new PromisePoolConnection(coreConnection, this.Promise));
26043
26994
  }
26044
26995
  });
26045
26996
  });
@@ -26054,8 +27005,8 @@ var require_pool_cluster2 = __commonJS({
26054
27005
  "Callback function is not available with promise clients."
26055
27006
  );
26056
27007
  }
26057
- return new this.Promise((resolve, reject) => {
26058
- const done = makeDoneCb(resolve, reject, stackHolder);
27008
+ return new this.Promise((resolve3, reject) => {
27009
+ const done = makeDoneCb(resolve3, reject, stackHolder);
26059
27010
  corePoolNamespace.query(sql, values, done);
26060
27011
  });
26061
27012
  }
@@ -26069,8 +27020,8 @@ var require_pool_cluster2 = __commonJS({
26069
27020
  "Callback function is not available with promise clients."
26070
27021
  );
26071
27022
  }
26072
- return new this.Promise((resolve, reject) => {
26073
- const done = makeDoneCb(resolve, reject, stackHolder);
27023
+ return new this.Promise((resolve3, reject) => {
27024
+ const done = makeDoneCb(resolve3, reject, stackHolder);
26074
27025
  corePoolNamespace.execute(sql, values, done);
26075
27026
  });
26076
27027
  }
@@ -26108,9 +27059,9 @@ var require_promise = __commonJS({
26108
27059
  "no Promise implementation available.Use promise-enabled node version or pass userland Promise implementation as parameter, for example: { Promise: require('bluebird') }"
26109
27060
  );
26110
27061
  }
26111
- return new thePromise((resolve, reject) => {
27062
+ return new thePromise((resolve3, reject) => {
26112
27063
  coreConnection.once("connect", () => {
26113
- resolve(new PromiseConnection(coreConnection, thePromise));
27064
+ resolve3(new PromiseConnection(coreConnection, thePromise));
26114
27065
  });
26115
27066
  coreConnection.once("error", (err) => {
26116
27067
  applyCapturedStack(err, stackHolder);
@@ -26137,7 +27088,7 @@ var require_promise = __commonJS({
26137
27088
  }
26138
27089
  getConnection(pattern, selector) {
26139
27090
  const corePoolCluster = this.poolCluster;
26140
- return new this.Promise((resolve, reject) => {
27091
+ return new this.Promise((resolve3, reject) => {
26141
27092
  corePoolCluster.getConnection(
26142
27093
  pattern,
26143
27094
  selector,
@@ -26145,7 +27096,7 @@ var require_promise = __commonJS({
26145
27096
  if (err) {
26146
27097
  reject(err);
26147
27098
  } else {
26148
- resolve(new PromisePoolConnection(coreConnection, this.Promise));
27099
+ resolve3(new PromisePoolConnection(coreConnection, this.Promise));
26149
27100
  }
26150
27101
  }
26151
27102
  );
@@ -26159,8 +27110,8 @@ var require_promise = __commonJS({
26159
27110
  "Callback function is not available with promise clients."
26160
27111
  );
26161
27112
  }
26162
- return new this.Promise((resolve, reject) => {
26163
- const done = makeDoneCb(resolve, reject, stackHolder);
27113
+ return new this.Promise((resolve3, reject) => {
27114
+ const done = makeDoneCb(resolve3, reject, stackHolder);
26164
27115
  corePoolCluster.query(sql, args, done);
26165
27116
  });
26166
27117
  }
@@ -26174,8 +27125,8 @@ var require_promise = __commonJS({
26174
27125
  "Callback function is not available with promise clients."
26175
27126
  );
26176
27127
  }
26177
- return new this.Promise((resolve, reject) => {
26178
- const done = makeDoneCb(resolve, reject, stackHolder);
27128
+ return new this.Promise((resolve3, reject) => {
27129
+ const done = makeDoneCb(resolve3, reject, stackHolder);
26179
27130
  corePoolCluster.execute(sql, args, done);
26180
27131
  });
26181
27132
  }
@@ -26188,13 +27139,13 @@ var require_promise = __commonJS({
26188
27139
  end() {
26189
27140
  const corePoolCluster = this.poolCluster;
26190
27141
  const stackHolder = captureStackHolder(_PromisePoolCluster.prototype.end);
26191
- return new this.Promise((resolve, reject) => {
27142
+ return new this.Promise((resolve3, reject) => {
26192
27143
  corePoolCluster.end((err) => {
26193
27144
  if (err) {
26194
27145
  applyCapturedStack(err, stackHolder);
26195
27146
  reject(err);
26196
27147
  } else {
26197
- resolve();
27148
+ resolve3();
26198
27149
  }
26199
27150
  });
26200
27151
  });
@@ -29269,7 +30220,7 @@ var require_dist = __commonJS({
29269
30220
  function parse(stream, callback) {
29270
30221
  const parser = new parser_1.Parser();
29271
30222
  stream.on("data", (buffer) => parser.parse(buffer, callback));
29272
- return new Promise((resolve) => stream.on("end", () => resolve()));
30223
+ return new Promise((resolve3) => stream.on("end", () => resolve3()));
29273
30224
  }
29274
30225
  exports.parse = parse;
29275
30226
  }
@@ -29994,12 +30945,12 @@ var require_client2 = __commonJS({
29994
30945
  this._connect(callback);
29995
30946
  return;
29996
30947
  }
29997
- return new this._Promise((resolve, reject) => {
30948
+ return new this._Promise((resolve3, reject) => {
29998
30949
  this._connect((error) => {
29999
30950
  if (error) {
30000
30951
  reject(error);
30001
30952
  } else {
30002
- resolve(this);
30953
+ resolve3(this);
30003
30954
  }
30004
30955
  });
30005
30956
  });
@@ -30345,8 +31296,8 @@ var require_client2 = __commonJS({
30345
31296
  readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
30346
31297
  query = new Query2(config, values, callback);
30347
31298
  if (!query.callback) {
30348
- result = new this._Promise((resolve, reject) => {
30349
- query.callback = (err, res) => err ? reject(err) : resolve(res);
31299
+ result = new this._Promise((resolve3, reject) => {
31300
+ query.callback = (err, res) => err ? reject(err) : resolve3(res);
30350
31301
  }).catch((err) => {
30351
31302
  Error.captureStackTrace(err);
30352
31303
  throw err;
@@ -30423,8 +31374,8 @@ var require_client2 = __commonJS({
30423
31374
  if (cb) {
30424
31375
  this.connection.once("end", cb);
30425
31376
  } else {
30426
- return new this._Promise((resolve) => {
30427
- this.connection.once("end", resolve);
31377
+ return new this._Promise((resolve3) => {
31378
+ this.connection.once("end", resolve3);
30428
31379
  });
30429
31380
  }
30430
31381
  }
@@ -30472,8 +31423,8 @@ var require_pg_pool = __commonJS({
30472
31423
  const cb = function(err, client) {
30473
31424
  err ? rej(err) : res(client);
30474
31425
  };
30475
- const result = new Promise2(function(resolve, reject) {
30476
- res = resolve;
31426
+ const result = new Promise2(function(resolve3, reject) {
31427
+ res = resolve3;
30477
31428
  rej = reject;
30478
31429
  }).catch((err) => {
30479
31430
  Error.captureStackTrace(err);
@@ -30534,7 +31485,7 @@ var require_pg_pool = __commonJS({
30534
31485
  if (typeof Promise2.try === "function") {
30535
31486
  return Promise2.try(f);
30536
31487
  }
30537
- return new Promise2((resolve) => resolve(f()));
31488
+ return new Promise2((resolve3) => resolve3(f()));
30538
31489
  }
30539
31490
  _isFull() {
30540
31491
  return this._clients.length >= this.options.max;
@@ -30926,8 +31877,8 @@ var require_query4 = __commonJS({
30926
31877
  NativeQuery.prototype._getPromise = function() {
30927
31878
  if (this._promise) return this._promise;
30928
31879
  this._promise = new Promise(
30929
- function(resolve, reject) {
30930
- this._once("end", resolve);
31880
+ function(resolve3, reject) {
31881
+ this._once("end", resolve3);
30931
31882
  this._once("error", reject);
30932
31883
  }.bind(this)
30933
31884
  );
@@ -31104,12 +32055,12 @@ var require_client3 = __commonJS({
31104
32055
  this._connect(callback);
31105
32056
  return;
31106
32057
  }
31107
- return new this._Promise((resolve, reject) => {
32058
+ return new this._Promise((resolve3, reject) => {
31108
32059
  this._connect((error) => {
31109
32060
  if (error) {
31110
32061
  reject(error);
31111
32062
  } else {
31112
- resolve(this);
32063
+ resolve3(this);
31113
32064
  }
31114
32065
  });
31115
32066
  });
@@ -31133,8 +32084,8 @@ var require_client3 = __commonJS({
31133
32084
  query = new NativeQuery(config, values, callback);
31134
32085
  if (!query.callback) {
31135
32086
  let resolveOut, rejectOut;
31136
- result = new this._Promise((resolve, reject) => {
31137
- resolveOut = resolve;
32087
+ result = new this._Promise((resolve3, reject) => {
32088
+ resolveOut = resolve3;
31138
32089
  rejectOut = reject;
31139
32090
  }).catch((err) => {
31140
32091
  Error.captureStackTrace(err);
@@ -31194,8 +32145,8 @@ var require_client3 = __commonJS({
31194
32145
  }
31195
32146
  let result;
31196
32147
  if (!cb) {
31197
- result = new this._Promise(function(resolve, reject) {
31198
- cb = (err) => err ? reject(err) : resolve();
32148
+ result = new this._Promise(function(resolve3, reject) {
32149
+ cb = (err) => err ? reject(err) : resolve3();
31199
32150
  });
31200
32151
  }
31201
32152
  this.native.end(function() {
@@ -36302,7 +37253,7 @@ var require_Command = __commonJS({
36302
37253
  }
36303
37254
  }
36304
37255
  initPromise() {
36305
- const promise = new Promise((resolve, reject) => {
37256
+ const promise = new Promise((resolve3, reject) => {
36306
37257
  if (!this.transformed) {
36307
37258
  this.transformed = true;
36308
37259
  const transformer = _Command._transformer.argument[this.name];
@@ -36311,7 +37262,7 @@ var require_Command = __commonJS({
36311
37262
  }
36312
37263
  this.stringifyArguments();
36313
37264
  }
36314
- this.resolve = this._convertValue(resolve);
37265
+ this.resolve = this._convertValue(resolve3);
36315
37266
  this.reject = (err) => {
36316
37267
  this._clearTimers();
36317
37268
  if (this.errorStack) {
@@ -36344,11 +37295,11 @@ var require_Command = __commonJS({
36344
37295
  /**
36345
37296
  * Convert the value from buffer to the target encoding.
36346
37297
  */
36347
- _convertValue(resolve) {
37298
+ _convertValue(resolve3) {
36348
37299
  return (value) => {
36349
37300
  try {
36350
37301
  this._clearTimers();
36351
- resolve(this.transformReply(value));
37302
+ resolve3(this.transformReply(value));
36352
37303
  this.isResolved = true;
36353
37304
  } catch (err) {
36354
37305
  this.reject(err);
@@ -36626,13 +37577,13 @@ var require_autoPipelining = __commonJS({
36626
37577
  if (client.isCluster && !client.slots.length) {
36627
37578
  if (client.status === "wait")
36628
37579
  client.connect().catch(lodash_1.noop);
36629
- return (0, standard_as_callback_1.default)(new Promise(function(resolve, reject) {
37580
+ return (0, standard_as_callback_1.default)(new Promise(function(resolve3, reject) {
36630
37581
  client.delayUntilReady((err) => {
36631
37582
  if (err) {
36632
37583
  reject(err);
36633
37584
  return;
36634
37585
  }
36635
- executeWithAutoPipelining(client, functionName, commandName, args, null).then(resolve, reject);
37586
+ executeWithAutoPipelining(client, functionName, commandName, args, null).then(resolve3, reject);
36636
37587
  });
36637
37588
  }), callback);
36638
37589
  }
@@ -36653,13 +37604,13 @@ var require_autoPipelining = __commonJS({
36653
37604
  pipeline[exports.kExec] = true;
36654
37605
  setImmediate(executeAutoPipeline, client, slotKey);
36655
37606
  }
36656
- const autoPipelinePromise = new Promise(function(resolve, reject) {
37607
+ const autoPipelinePromise = new Promise(function(resolve3, reject) {
36657
37608
  pipeline[exports.kCallbacks].push(function(err, value) {
36658
37609
  if (err) {
36659
37610
  reject(err);
36660
37611
  return;
36661
37612
  }
36662
- resolve(value);
37613
+ resolve3(value);
36663
37614
  });
36664
37615
  if (functionName === "call") {
36665
37616
  args.unshift(commandName);
@@ -36894,8 +37845,8 @@ var require_Pipeline = __commonJS({
36894
37845
  this[name] = redis[name];
36895
37846
  this[name + "Buffer"] = redis[name + "Buffer"];
36896
37847
  });
36897
- this.promise = new Promise((resolve, reject) => {
36898
- this.resolve = resolve;
37848
+ this.promise = new Promise((resolve3, reject) => {
37849
+ this.resolve = resolve3;
36899
37850
  this.reject = reject;
36900
37851
  });
36901
37852
  const _this = this;
@@ -37195,13 +38146,13 @@ var require_transaction = __commonJS({
37195
38146
  if (this.isCluster && !this.redis.slots.length) {
37196
38147
  if (this.redis.status === "wait")
37197
38148
  this.redis.connect().catch(utils_1.noop);
37198
- return (0, standard_as_callback_1.default)(new Promise((resolve, reject) => {
38149
+ return (0, standard_as_callback_1.default)(new Promise((resolve3, reject) => {
37199
38150
  this.redis.delayUntilReady((err) => {
37200
38151
  if (err) {
37201
38152
  reject(err);
37202
38153
  return;
37203
38154
  }
37204
- this.exec(pipeline).then(resolve, reject);
38155
+ this.exec(pipeline).then(resolve3, reject);
37205
38156
  });
37206
38157
  }), callback);
37207
38158
  }
@@ -38330,7 +39281,7 @@ var require_cluster = __commonJS({
38330
39281
  * Connect to a cluster
38331
39282
  */
38332
39283
  connect() {
38333
- return new Promise((resolve, reject) => {
39284
+ return new Promise((resolve3, reject) => {
38334
39285
  if (this.status === "connecting" || this.status === "connect" || this.status === "ready") {
38335
39286
  reject(new Error("Redis is already connecting/connected"));
38336
39287
  return;
@@ -38359,7 +39310,7 @@ var require_cluster = __commonJS({
38359
39310
  this.retryAttempts = 0;
38360
39311
  this.executeOfflineCommands();
38361
39312
  this.resetNodesRefreshInterval();
38362
- resolve();
39313
+ resolve3();
38363
39314
  };
38364
39315
  let closeListener = void 0;
38365
39316
  const refreshListener = () => {
@@ -38969,7 +39920,7 @@ var require_cluster = __commonJS({
38969
39920
  });
38970
39921
  }
38971
39922
  resolveSrv(hostname) {
38972
- return new Promise((resolve, reject) => {
39923
+ return new Promise((resolve3, reject) => {
38973
39924
  this.options.resolveSrv(hostname, (err, records) => {
38974
39925
  if (err) {
38975
39926
  return reject(err);
@@ -38983,7 +39934,7 @@ var require_cluster = __commonJS({
38983
39934
  if (!group.records.length) {
38984
39935
  sortedKeys.shift();
38985
39936
  }
38986
- self2.dnsLookup(record.name).then((host) => resolve({
39937
+ self2.dnsLookup(record.name).then((host) => resolve3({
38987
39938
  host,
38988
39939
  port: record.port
38989
39940
  }), tryFirstOne);
@@ -38993,14 +39944,14 @@ var require_cluster = __commonJS({
38993
39944
  });
38994
39945
  }
38995
39946
  dnsLookup(hostname) {
38996
- return new Promise((resolve, reject) => {
39947
+ return new Promise((resolve3, reject) => {
38997
39948
  this.options.dnsLookup(hostname, (err, address) => {
38998
39949
  if (err) {
38999
39950
  debug2("failed to resolve hostname %s to IP: %s", hostname, err.message);
39000
39951
  reject(err);
39001
39952
  } else {
39002
39953
  debug2("resolved hostname %s to IP %s", hostname, address);
39003
- resolve(address);
39954
+ resolve3(address);
39004
39955
  }
39005
39956
  });
39006
39957
  });
@@ -39155,7 +40106,7 @@ var require_StandaloneConnector = __commonJS({
39155
40106
  if (options.tls) {
39156
40107
  Object.assign(connectionOptions, options.tls);
39157
40108
  }
39158
- return new Promise((resolve, reject) => {
40109
+ return new Promise((resolve3, reject) => {
39159
40110
  process.nextTick(() => {
39160
40111
  if (!this.connecting) {
39161
40112
  reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG));
@@ -39174,7 +40125,7 @@ var require_StandaloneConnector = __commonJS({
39174
40125
  this.stream.once("error", (err) => {
39175
40126
  this.firstError = err;
39176
40127
  });
39177
- resolve(this.stream);
40128
+ resolve3(this.stream);
39178
40129
  });
39179
40130
  });
39180
40131
  }
@@ -39330,7 +40281,7 @@ var require_SentinelConnector = __commonJS({
39330
40281
  const error = new Error(errorMsg);
39331
40282
  if (typeof retryDelay === "number") {
39332
40283
  eventEmitter("error", error);
39333
- await new Promise((resolve) => setTimeout(resolve, retryDelay));
40284
+ await new Promise((resolve3) => setTimeout(resolve3, retryDelay));
39334
40285
  return connectToNext();
39335
40286
  } else {
39336
40287
  throw error;
@@ -40647,7 +41598,7 @@ var require_Redis = __commonJS({
40647
41598
  * if the connection fails, times out, or if Redis is already connecting/connected.
40648
41599
  */
40649
41600
  connect(callback) {
40650
- const promise = new Promise((resolve, reject) => {
41601
+ const promise = new Promise((resolve3, reject) => {
40651
41602
  if (this.status === "connecting" || this.status === "connect" || this.status === "ready") {
40652
41603
  reject(new Error("Redis is already connecting/connected"));
40653
41604
  return;
@@ -40726,7 +41677,7 @@ var require_Redis = __commonJS({
40726
41677
  }
40727
41678
  const connectionReadyHandler = function() {
40728
41679
  _this.removeListener("close", connectionCloseHandler);
40729
- resolve();
41680
+ resolve3();
40730
41681
  };
40731
41682
  var connectionCloseHandler = function() {
40732
41683
  _this.removeListener("ready", connectionReadyHandler);
@@ -40820,10 +41771,10 @@ var require_Redis = __commonJS({
40820
41771
  monitor: true,
40821
41772
  lazyConnect: false
40822
41773
  });
40823
- return (0, standard_as_callback_1.default)(new Promise(function(resolve, reject) {
41774
+ return (0, standard_as_callback_1.default)(new Promise(function(resolve3, reject) {
40824
41775
  monitorInstance.once("error", reject);
40825
41776
  monitorInstance.once("monitoring", function() {
40826
- resolve(monitorInstance);
41777
+ resolve3(monitorInstance);
40827
41778
  });
40828
41779
  }), callback);
40829
41780
  }
@@ -41645,6 +42596,7 @@ async function runMenu() {
41645
42596
  const value = await Ee({
41646
42597
  message: "What now?",
41647
42598
  options: [
42599
+ { value: "init", label: "Initialize this project (migrate .env)", hint: "keynv init" },
41648
42600
  { value: "projects", label: "Projects" },
41649
42601
  { value: "secrets", label: "Secrets" },
41650
42602
  { value: "members", label: "Members" },
@@ -41683,7 +42635,10 @@ async function runMenu() {
41683
42635
  ye("Logged out.");
41684
42636
  return 0;
41685
42637
  }
41686
- if (choice === "projects") await runProjectsFlow(client);
42638
+ if (choice === "init") {
42639
+ const { runInitFlow: runInitFlow2 } = await Promise.resolve().then(() => (init_init(), init_exports));
42640
+ await runInitFlow2(client, { cwd: process.cwd(), dryRun: false, noScripts: false });
42641
+ } else if (choice === "projects") await runProjectsFlow(client);
41687
42642
  else if (choice === "secrets") await runSecretsFlow(client);
41688
42643
  else if (choice === "members") await runMembersFlow(client);
41689
42644
  else if (choice === "audit") await runAuditFlow(client);
@@ -43496,6 +44451,7 @@ var AuditVerifyCommand = class extends Command {
43496
44451
 
43497
44452
  // src/commands/exec.ts
43498
44453
  init_http();
44454
+ init_envFile();
43499
44455
 
43500
44456
  // src/exec/resolve.ts
43501
44457
  init_dist();
@@ -43856,14 +44812,14 @@ function spawnPrivileged(opts) {
43856
44812
  }, opts.timeoutS * 1e3);
43857
44813
  timer.unref();
43858
44814
  }
43859
- return new Promise((resolve, reject) => {
44815
+ return new Promise((resolve3, reject) => {
43860
44816
  child.on("error", (err) => {
43861
44817
  if (timer) clearTimeout(timer);
43862
44818
  reject(err);
43863
44819
  });
43864
44820
  child.on("close", (code, signal) => {
43865
44821
  if (timer) clearTimeout(timer);
43866
- resolve({
44822
+ resolve3({
43867
44823
  exitCode: code ?? 0,
43868
44824
  signal,
43869
44825
  durationMs: Date.now() - startedAt
@@ -43886,11 +44842,23 @@ the redactor before being copied to the calling process's stdout/stderr.
43886
44842
 
43887
44843
  The subprocess does NOT inherit the caller's full environment; only
43888
44844
  PATH/HOME/USER/SHELL/TERM/LANG/etc. plus anything passed through
43889
- --via-env. The intent is to keep accidental secrets in the caller's
43890
- shell from being seen by the subprocess (and by extension, the AI
43891
- agent that wraps it).
44845
+ --via-env or via an auto-loaded ${ENV_FILE_BASENAME} file.
44846
+
44847
+ If a ${ENV_FILE_BASENAME} file is found in the current directory or any
44848
+ parent (walked git-style), every NAME=@alias entry is resolved and
44849
+ injected into the subprocess env. Plain NAME=value lines are passed
44850
+ through unchanged. The file is safe to commit because it carries
44851
+ references, not values. Use \`--no-env-file\` to opt out, \`--from PATH\`
44852
+ to load a specific file, or set KEYNV_ENV_FILE in the environment.
44853
+
44854
+ (Note: Node.js itself reserves \`--env-file\`, so the keynv flag is
44855
+ spelled \`--from\` to avoid the collision.)
43892
44856
  `,
43893
44857
  examples: [
44858
+ [
44859
+ "Auto-load .keynv.env from cwd or parents",
44860
+ "$0 exec -- next dev"
44861
+ ],
43894
44862
  [
43895
44863
  "Run mysql with the alias substituted at fork-exec time",
43896
44864
  "$0 exec -- mysql -p@billing.dev.db_pass -h db.example.com"
@@ -43898,7 +44866,8 @@ agent that wraps it).
43898
44866
  [
43899
44867
  "Inject env vars without showing them in argv",
43900
44868
  "$0 exec --via-env DB_PASS=@billing.dev.db_pass -- node ./scripts/migrate.js"
43901
- ]
44869
+ ],
44870
+ ["Skip auto-discovery", "$0 exec --no-env-file -- npm test"]
43902
44871
  ]
43903
44872
  });
43904
44873
  viaEnv = options_exports.Array("--via-env", {
@@ -43908,7 +44877,15 @@ agent that wraps it).
43908
44877
  description: "Disable the stdout/stderr redactor. Audit-flagged."
43909
44878
  });
43910
44879
  timeout = options_exports.String("--timeout", { description: "Kill subprocess after N seconds." });
43911
- // Everything after `--` is the command + its args.
44880
+ envFile = options_exports.String("--from", {
44881
+ description: `Load env mappings from this file instead of auto-discovering ${ENV_FILE_BASENAME}. Errors if missing. (Node intercepts \`--env-file\` for itself, so we use \`--from\`.)`
44882
+ });
44883
+ noEnvFile = options_exports.Boolean("--no-env-file", false, {
44884
+ description: `Skip auto-loading ${ENV_FILE_BASENAME} (and ignore KEYNV_ENV_FILE).`
44885
+ });
44886
+ quiet = options_exports.Boolean("--quiet", false, {
44887
+ description: `Suppress the "loaded N vars from ${ENV_FILE_BASENAME}" status line.`
44888
+ });
43912
44889
  rest = options_exports.Rest();
43913
44890
  async execute() {
43914
44891
  if (!this.rest || this.rest.length === 0) {
@@ -43928,6 +44905,25 @@ agent that wraps it).
43928
44905
  this.context.stderr.write("keynv: not logged in. Run `keynv login` first.\n");
43929
44906
  return 1;
43930
44907
  }
44908
+ let envFileLoaded = null;
44909
+ try {
44910
+ const loaded = loadEnvFile({
44911
+ cwd: process.cwd(),
44912
+ disabled: this.noEnvFile,
44913
+ ...this.envFile !== void 0 ? { explicitPath: this.envFile } : {},
44914
+ ...process.env.KEYNV_ENV_FILE !== void 0 ? { envVarOverride: process.env.KEYNV_ENV_FILE } : {}
44915
+ });
44916
+ if (loaded) {
44917
+ envFileLoaded = loaded;
44918
+ }
44919
+ } catch (err) {
44920
+ if (err instanceof EnvFileNotFoundError || err instanceof EnvFileParseError || err instanceof EnvFileTooLargeError) {
44921
+ this.context.stderr.write(`keynv: ${err.message}
44922
+ `);
44923
+ return 2;
44924
+ }
44925
+ throw err;
44926
+ }
43931
44927
  const viaEnvSpecs = [];
43932
44928
  for (const spec of this.viaEnv ?? []) {
43933
44929
  const eq = spec.indexOf("=");
@@ -43941,13 +44937,16 @@ agent that wraps it).
43941
44937
  aliasLiteral: spec.slice(eq + 1)
43942
44938
  });
43943
44939
  }
44940
+ const extraAliasStrings = [];
44941
+ if (envFileLoaded) {
44942
+ for (const e2 of envFileLoaded.entries) {
44943
+ if (e2.isAlias) extraAliasStrings.push(e2.value);
44944
+ }
44945
+ }
44946
+ for (const s of viaEnvSpecs) extraAliasStrings.push(s.aliasLiteral);
43944
44947
  let resolved;
43945
44948
  try {
43946
- resolved = await resolveAllAliases(
43947
- client,
43948
- [command, ...args],
43949
- viaEnvSpecs.map((s) => s.aliasLiteral)
43950
- );
44949
+ resolved = await resolveAllAliases(client, [command, ...args], extraAliasStrings);
43951
44950
  } catch (err) {
43952
44951
  const message = err instanceof Error ? err.message : String(err);
43953
44952
  this.context.stderr.write(`keynv: ${message}
@@ -43957,6 +44956,25 @@ agent that wraps it).
43957
44956
  const substArgs = args.map((a) => substitute(a, resolved));
43958
44957
  const substCommand = substitute(command, resolved);
43959
44958
  const injectedEnv = {};
44959
+ const fromEnvFile = /* @__PURE__ */ new Map();
44960
+ if (envFileLoaded) {
44961
+ for (const e2 of envFileLoaded.entries) {
44962
+ if (e2.isAlias) {
44963
+ const subst = substitute(e2.value, resolved);
44964
+ if (subst === e2.value) {
44965
+ this.context.stderr.write(
44966
+ `keynv: ${envFileLoaded.path}:${e2.line}: alias ${e2.value} did not resolve
44967
+ `
44968
+ );
44969
+ return 1;
44970
+ }
44971
+ injectedEnv[e2.name] = subst;
44972
+ } else {
44973
+ injectedEnv[e2.name] = e2.value;
44974
+ }
44975
+ fromEnvFile.set(e2.name, e2.line);
44976
+ }
44977
+ }
43960
44978
  for (const spec of viaEnvSpecs) {
43961
44979
  const value = substitute(spec.aliasLiteral, resolved);
43962
44980
  if (value === spec.aliasLiteral) {
@@ -43966,8 +44984,23 @@ agent that wraps it).
43966
44984
  );
43967
44985
  return 1;
43968
44986
  }
44987
+ const overriddenLine = fromEnvFile.get(spec.name);
44988
+ if (overriddenLine !== void 0 && envFileLoaded && !this.quiet) {
44989
+ this.context.stderr.write(
44990
+ `keynv: --via-env ${spec.name} overrides ${envFileLoaded.path}:${overriddenLine}
44991
+ `
44992
+ );
44993
+ }
43969
44994
  injectedEnv[spec.name] = value;
43970
44995
  }
44996
+ if (envFileLoaded && !this.quiet) {
44997
+ const total = envFileLoaded.entries.length;
44998
+ const aliasCount = envFileLoaded.entries.filter((e2) => e2.isAlias).length;
44999
+ this.context.stderr.write(
45000
+ `keynv: loaded ${total} var${total === 1 ? "" : "s"} from ${envFileLoaded.path} (${aliasCount} resolved from vault)
45001
+ `
45002
+ );
45003
+ }
43971
45004
  const timeoutS = this.timeout ? Number.parseInt(this.timeout, 10) : void 0;
43972
45005
  if (this.timeout && (timeoutS === void 0 || Number.isNaN(timeoutS))) {
43973
45006
  this.context.stderr.write("keynv: invalid --timeout (expected integer seconds)\n");
@@ -44004,527 +45037,67 @@ function signalNumber(sig) {
44004
45037
  return map[sig] ?? null;
44005
45038
  }
44006
45039
 
44007
- // ../../packages/integrations/dist/file-deny-list.js
44008
- var KEYNV_FILE_DENY_PATTERNS = [
44009
- // dotenv variants
44010
- ".env",
44011
- ".env.*",
44012
- "*.env",
44013
- "**/.env",
44014
- "**/.env.*",
44015
- "**/*.env",
44016
- // raw key material
44017
- "*.pem",
44018
- "*.key",
44019
- "*.p12",
44020
- "*.pfx",
44021
- "**/*.pem",
44022
- "**/*.key",
44023
- "**/*.p12",
44024
- "**/*.pfx",
44025
- // SSH private keys
44026
- "id_rsa",
44027
- "id_rsa.*",
44028
- "id_ed25519",
44029
- "id_ed25519.*",
44030
- "id_ecdsa",
44031
- "id_ecdsa.*",
44032
- "**/id_rsa",
44033
- "**/id_rsa.*",
44034
- "**/id_ed25519",
44035
- "**/id_ed25519.*",
44036
- "**/id_ecdsa",
44037
- "**/id_ecdsa.*",
44038
- // Generic credential containers
44039
- "*credentials*",
44040
- "*.kdbx",
44041
- "**/*credentials*",
44042
- "**/*.kdbx",
44043
- // Cloud provider credential paths (typically under ~/, but also
44044
- // appear at project roots in dev setups)
44045
- ".aws/credentials",
44046
- "**/.aws/credentials",
44047
- ".aws/config",
44048
- "**/.aws/config",
44049
- ".gcp/**/key.json",
44050
- "**/.gcp/**/key.json",
44051
- "**/google-services.json",
44052
- "**/service-account*.json",
44053
- ".azure/**",
44054
- "**/.azure/**",
44055
- ".kube/config",
44056
- "**/.kube/config",
44057
- ".docker/config.json",
44058
- "**/.docker/config.json"
44059
- ];
44060
- var KEYNV_BEGIN = "# >>> keynv >>>";
44061
- var KEYNV_END = "# <<< keynv <<<";
44062
- function readJsonOrEmpty(path) {
44063
- if (!existsSync(path))
44064
- return {};
44065
- try {
44066
- return JSON.parse(readFileSync(path, "utf8"));
44067
- } catch {
44068
- return {};
44069
- }
44070
- }
44071
- function ensureDir(path) {
44072
- const dir = dirname(path);
44073
- if (!existsSync(dir))
44074
- mkdirSync(dir, { recursive: true });
44075
- }
44076
- function writeJson(path, value) {
44077
- ensureDir(path);
44078
- writeFileSync(path, `${JSON.stringify(value, null, 2)}
44079
- `, { mode: 420 });
44080
- }
44081
- function ensureKeynvBlock(path, lines) {
44082
- const existing = existsSync(path) ? readFileSync(path, "utf8") : "";
44083
- const marked = existing.split("\n");
44084
- const beginIdx = marked.findIndex((l) => l.trim() === KEYNV_BEGIN);
44085
- const endIdx = marked.findIndex((l) => l.trim() === KEYNV_END);
44086
- const block = [KEYNV_BEGIN, ...lines, KEYNV_END];
44087
- let next;
44088
- if (beginIdx >= 0 && endIdx > beginIdx) {
44089
- next = [...marked.slice(0, beginIdx), ...block, ...marked.slice(endIdx + 1)];
44090
- } else {
44091
- next = existing.length > 0 && !existing.endsWith("\n") ? [...marked, "", ...block] : [...marked[marked.length - 1] === "" ? marked.slice(0, -1) : marked, ...block, ""];
44092
- }
44093
- const out = next.join("\n");
44094
- if (out === existing)
44095
- return false;
44096
- ensureDir(path);
44097
- writeFileSync(path, out, { mode: 420 });
44098
- return true;
44099
- }
44100
- function removeKeynvBlock(path) {
44101
- if (!existsSync(path))
44102
- return false;
44103
- const lines = readFileSync(path, "utf8").split("\n");
44104
- const beginIdx = lines.findIndex((l) => l.trim() === KEYNV_BEGIN);
44105
- const endIdx = lines.findIndex((l) => l.trim() === KEYNV_END);
44106
- if (beginIdx < 0 || endIdx <= beginIdx)
44107
- return false;
44108
- const next = [...lines.slice(0, beginIdx), ...lines.slice(endIdx + 1)];
44109
- while (next.length > 0 && next[next.length - 1] === "")
44110
- next.pop();
44111
- writeFileSync(path, `${next.join("\n")}${next.length ? "\n" : ""}`, { mode: 420 });
44112
- return true;
44113
- }
44114
-
44115
- // ../../packages/integrations/dist/aider.js
44116
- var AIDER_IGNORE_REL = ".aiderignore";
44117
- var aider = {
44118
- name: "aider",
44119
- displayName: "Aider",
44120
- async detect(opts = {}) {
44121
- const cwd = opts.cwd ?? process.cwd();
44122
- return existsSync(join(cwd, AIDER_IGNORE_REL)) || existsSync(join(cwd, ".aider.conf.yml")) || existsSync(join(homedir(), ".aider.conf.yml"));
44123
- },
44124
- async install(opts = {}) {
44125
- const cwd = opts.cwd ?? process.cwd();
44126
- const path = join(cwd, AIDER_IGNORE_REL);
44127
- if (opts.dryRun) {
44128
- return {
44129
- agent: "aider",
44130
- applied: false,
44131
- changes: [{ path, action: "update" }],
44132
- summary: `[dry-run] would write ${path}`
44133
- };
44134
- }
44135
- const changed = ensureKeynvBlock(path, [...KEYNV_FILE_DENY_PATTERNS]);
44136
- return {
44137
- agent: "aider",
44138
- applied: true,
44139
- changes: [{ path, action: changed ? "update" : "skip" }],
44140
- summary: changed ? `wrote ${KEYNV_FILE_DENY_PATTERNS.length} patterns to ${AIDER_IGNORE_REL}` : "unchanged"
44141
- };
44142
- },
44143
- async uninstall(opts = {}) {
44144
- const cwd = opts.cwd ?? process.cwd();
44145
- const path = join(cwd, AIDER_IGNORE_REL);
44146
- if (opts.dryRun) {
44147
- return {
44148
- agent: "aider",
44149
- applied: false,
44150
- changes: [{ path, action: "update" }],
44151
- summary: `[dry-run] would remove keynv block from ${AIDER_IGNORE_REL}`
44152
- };
44153
- }
44154
- const changed = removeKeynvBlock(path);
44155
- return {
44156
- agent: "aider",
44157
- applied: true,
44158
- changes: [{ path, action: changed ? "update" : "skip" }],
44159
- summary: changed ? "removed keynv block" : "no keynv block found"
44160
- };
44161
- }
44162
- };
44163
- var SETTINGS_PATH_REL = ".claude/settings.local.json";
44164
- var KEYNV_DENY_TAG = "__keynv_managed__";
44165
- function denyEntriesForReadTool() {
44166
- return KEYNV_FILE_DENY_PATTERNS.map((p2) => `Read(${p2})`);
44167
- }
44168
- var claudeCode = {
44169
- name: "claude-code",
44170
- displayName: "Claude Code",
44171
- async detect(opts = {}) {
44172
- const cwd = opts.cwd ?? process.cwd();
44173
- return existsSync(join(cwd, ".claude"));
44174
- },
44175
- async install(opts = {}) {
44176
- const cwd = opts.cwd ?? process.cwd();
44177
- const path = join(cwd, SETTINGS_PATH_REL);
44178
- const settings = readJsonOrEmpty(path);
44179
- const denyToAdd = denyEntriesForReadTool();
44180
- const existingDeny = new Set(settings.permissions?.deny ?? []);
44181
- const newlyAdded = [];
44182
- for (const entry2 of denyToAdd) {
44183
- if (!existingDeny.has(entry2)) {
44184
- existingDeny.add(entry2);
44185
- newlyAdded.push(entry2);
44186
- }
44187
- }
44188
- settings.permissions = {
44189
- ...settings.permissions,
44190
- deny: [...existingDeny].sort((a, b2) => a.localeCompare(b2))
44191
- };
44192
- settings.hooks = settings.hooks ?? {};
44193
- const post = settings.hooks["PostToolUse"] ?? [];
44194
- const alreadyHooked = post.some((entry2) => (entry2.hooks ?? []).some((h2) => h2.command?.includes("keynv redact-stream")));
44195
- if (!alreadyHooked) {
44196
- post.push({
44197
- matcher: "Bash",
44198
- hooks: [{ type: "command", command: "keynv redact-stream" }]
44199
- });
44200
- settings.hooks["PostToolUse"] = post;
44201
- }
44202
- settings[KEYNV_DENY_TAG] = {
44203
- deny_added: denyToAdd,
44204
- hook_added: true
44205
- };
44206
- const changes = [];
44207
- if (opts.dryRun) {
44208
- changes.push({
44209
- path,
44210
- action: existsSync(path) ? "update" : "create",
44211
- note: `would add ${newlyAdded.length} deny entries${alreadyHooked ? "" : " + PostToolUse(Bash) \u2192 keynv redact-stream"}`
44212
- });
44213
- } else {
44214
- writeJson(path, settings);
44215
- changes.push({
44216
- path,
44217
- action: existsSync(path) ? "update" : "create",
44218
- note: `${newlyAdded.length} new deny entries${alreadyHooked ? "" : " + redact hook"}`
44219
- });
44220
- }
44221
- return {
44222
- agent: "claude-code",
44223
- applied: !opts.dryRun,
44224
- changes,
44225
- summary: opts.dryRun ? `[dry-run] ${path}: would add ${newlyAdded.length} permission denies + redact hook` : `installed: ${newlyAdded.length} new denies; redact hook ${alreadyHooked ? "kept" : "added"}.`
44226
- };
44227
- },
44228
- async uninstall(opts = {}) {
44229
- const cwd = opts.cwd ?? process.cwd();
44230
- const path = join(cwd, SETTINGS_PATH_REL);
44231
- if (!existsSync(path)) {
44232
- return {
44233
- agent: "claude-code",
44234
- applied: false,
44235
- changes: [{ path, action: "skip", note: "no settings file" }],
44236
- summary: "nothing to uninstall"
44237
- };
44238
- }
44239
- const settings = readJsonOrEmpty(path);
44240
- const tracker = settings[KEYNV_DENY_TAG];
44241
- const removedDeny = [];
44242
- const permissions = settings.permissions;
44243
- if (tracker?.deny_added && permissions && Array.isArray(permissions.deny)) {
44244
- const remove = new Set(tracker.deny_added);
44245
- const before = permissions.deny;
44246
- permissions.deny = before.filter((entry2) => {
44247
- if (remove.has(entry2)) {
44248
- removedDeny.push(entry2);
44249
- return false;
44250
- }
44251
- return true;
44252
- });
44253
- if (permissions.deny.length === 0)
44254
- delete permissions.deny;
44255
- }
44256
- const hooks = settings.hooks;
44257
- if (tracker?.hook_added && hooks && Array.isArray(hooks.PostToolUse)) {
44258
- const filtered = hooks.PostToolUse.filter((entry2) => !(entry2.hooks ?? []).some((h2) => h2.command?.includes("keynv redact-stream")));
44259
- hooks.PostToolUse = filtered;
44260
- if (filtered.length === 0)
44261
- delete hooks.PostToolUse;
44262
- }
44263
- delete settings[KEYNV_DENY_TAG];
44264
- if (opts.dryRun) {
44265
- return {
44266
- agent: "claude-code",
44267
- applied: false,
44268
- changes: [
44269
- { path, action: "update", note: `would remove ${removedDeny.length} denies + hook` }
44270
- ],
44271
- summary: `[dry-run] would remove ${removedDeny.length} denies`
44272
- };
44273
- }
44274
- writeJson(path, settings);
44275
- return {
44276
- agent: "claude-code",
44277
- applied: true,
44278
- changes: [{ path, action: "update" }],
44279
- summary: `removed ${removedDeny.length} denies + hook`
44280
- };
44281
- }
44282
- };
44283
- var CODEX_IGNORE_REL = ".codex/.deny";
44284
- var codexCli = {
44285
- name: "codex",
44286
- displayName: "Codex CLI",
44287
- async detect(opts = {}) {
44288
- const cwd = opts.cwd ?? process.cwd();
44289
- return existsSync(join(cwd, ".codex")) || existsSync(join(homedir(), ".codex"));
44290
- },
44291
- async install(opts = {}) {
44292
- const cwd = opts.cwd ?? process.cwd();
44293
- const path = join(cwd, CODEX_IGNORE_REL);
44294
- if (opts.dryRun) {
44295
- return {
44296
- agent: "codex",
44297
- applied: false,
44298
- changes: [{ path, action: "update" }],
44299
- summary: `[dry-run] would write ${CODEX_IGNORE_REL}`
44300
- };
44301
- }
44302
- const changed = ensureKeynvBlock(path, [...KEYNV_FILE_DENY_PATTERNS]);
44303
- return {
44304
- agent: "codex",
44305
- applied: true,
44306
- changes: [{ path, action: changed ? "update" : "skip" }],
44307
- summary: changed ? `wrote ${CODEX_IGNORE_REL}; consider adding 'alias codex="keynv exec -- codex"' to your shell rc` : "unchanged"
44308
- };
44309
- },
44310
- async uninstall(opts = {}) {
44311
- const cwd = opts.cwd ?? process.cwd();
44312
- const path = join(cwd, CODEX_IGNORE_REL);
44313
- if (opts.dryRun) {
44314
- return {
44315
- agent: "codex",
44316
- applied: false,
44317
- changes: [{ path, action: "update" }],
44318
- summary: `[dry-run] would remove keynv block from ${CODEX_IGNORE_REL}`
44319
- };
44320
- }
44321
- const changed = removeKeynvBlock(path);
44322
- return {
44323
- agent: "codex",
44324
- applied: true,
44325
- changes: [{ path, action: changed ? "update" : "skip" }],
44326
- summary: changed ? "removed keynv block" : "no keynv block found"
44327
- };
44328
- }
44329
- };
44330
- var CURSOR_IGNORE_REL = ".cursorignore";
44331
- var cursor = {
44332
- name: "cursor",
44333
- displayName: "Cursor",
44334
- async detect(opts = {}) {
44335
- const cwd = opts.cwd ?? process.cwd();
44336
- return existsSync(join(cwd, ".cursor")) || existsSync(join(cwd, ".cursorrules"));
44337
- },
44338
- async install(opts = {}) {
44339
- const cwd = opts.cwd ?? process.cwd();
44340
- const path = join(cwd, CURSOR_IGNORE_REL);
44341
- if (opts.dryRun) {
44342
- return {
44343
- agent: "cursor",
44344
- applied: false,
44345
- changes: [
44346
- {
44347
- path,
44348
- action: "update",
44349
- note: `would add ${KEYNV_FILE_DENY_PATTERNS.length} ignore patterns`
44350
- }
44351
- ],
44352
- summary: `[dry-run] would write ${path}`
44353
- };
44354
- }
44355
- const changed = ensureKeynvBlock(path, [...KEYNV_FILE_DENY_PATTERNS]);
44356
- return {
44357
- agent: "cursor",
44358
- applied: true,
44359
- changes: [{ path, action: changed ? "update" : "skip" }],
44360
- summary: changed ? `wrote ${KEYNV_FILE_DENY_PATTERNS.length} patterns to ${CURSOR_IGNORE_REL}` : "unchanged"
44361
- };
44362
- },
44363
- async uninstall(opts = {}) {
44364
- const cwd = opts.cwd ?? process.cwd();
44365
- const path = join(cwd, CURSOR_IGNORE_REL);
44366
- if (opts.dryRun) {
44367
- return {
44368
- agent: "cursor",
44369
- applied: false,
44370
- changes: [{ path, action: "update" }],
44371
- summary: `[dry-run] would remove keynv block from ${CURSOR_IGNORE_REL}`
44372
- };
44373
- }
44374
- const changed = removeKeynvBlock(path);
44375
- return {
44376
- agent: "cursor",
44377
- applied: true,
44378
- changes: [{ path, action: changed ? "update" : "skip" }],
44379
- summary: changed ? "removed keynv block" : "no keynv block found"
44380
- };
44381
- }
44382
- };
44383
- var OPENCODE_IGNORE_REL = ".opencode/.keynv-deny";
44384
- var opencode = {
44385
- name: "opencode",
44386
- displayName: "OpenCode",
44387
- async detect(opts = {}) {
44388
- const cwd = opts.cwd ?? process.cwd();
44389
- return existsSync(join(cwd, ".opencode")) || existsSync(join(homedir(), ".opencode"));
44390
- },
44391
- async install(opts = {}) {
44392
- const cwd = opts.cwd ?? process.cwd();
44393
- const path = join(cwd, OPENCODE_IGNORE_REL);
44394
- if (opts.dryRun) {
44395
- return {
44396
- agent: "opencode",
44397
- applied: false,
44398
- changes: [{ path, action: "update" }],
44399
- summary: `[dry-run] would write ${OPENCODE_IGNORE_REL}`
44400
- };
44401
- }
44402
- const changed = ensureKeynvBlock(path, [...KEYNV_FILE_DENY_PATTERNS]);
44403
- return {
44404
- agent: "opencode",
44405
- applied: true,
44406
- changes: [{ path, action: changed ? "update" : "skip" }],
44407
- summary: changed ? `wrote ${OPENCODE_IGNORE_REL}; full hook/MCP integration TBD` : "unchanged"
44408
- };
44409
- },
44410
- async uninstall(opts = {}) {
44411
- const cwd = opts.cwd ?? process.cwd();
44412
- const path = join(cwd, OPENCODE_IGNORE_REL);
44413
- if (opts.dryRun) {
44414
- return {
44415
- agent: "opencode",
44416
- applied: false,
44417
- changes: [{ path, action: "update" }],
44418
- summary: `[dry-run] would remove keynv block from ${OPENCODE_IGNORE_REL}`
44419
- };
44420
- }
44421
- const changed = removeKeynvBlock(path);
44422
- return {
44423
- agent: "opencode",
44424
- applied: true,
44425
- changes: [{ path, action: changed ? "update" : "skip" }],
44426
- summary: changed ? "removed keynv block" : "no keynv block found"
44427
- };
44428
- }
44429
- };
44430
-
44431
- // ../../packages/integrations/dist/index.js
44432
- var REGISTRY = [claudeCode, cursor, opencode, codexCli, aider];
44433
- function findIntegration(name) {
44434
- return REGISTRY.find((i) => i.name === name) ?? null;
44435
- }
44436
-
44437
- // src/commands/install.ts
44438
- function printReport(stdout, report) {
44439
- stdout.write(`[${report.agent}] ${report.summary}
44440
- `);
44441
- for (const change of report.changes) {
44442
- const note = change.note ? `: ${change.note}` : "";
44443
- stdout.write(` ${change.action.padEnd(7)} ${change.path}${note}
44444
- `);
44445
- }
44446
- }
44447
- var InstallCommand = class extends Command {
44448
- static paths = [["install"]];
45040
+ // src/commands/init.ts
45041
+ init_http();
45042
+ init_tty();
45043
+ init_init();
45044
+ init_cancel();
45045
+ var InitCommand = class extends Command {
45046
+ static paths = [["init"]];
44449
45047
  static usage = Command.Usage({
44450
- description: "Install per-agent file deny lists, hooks, and config templates.",
45048
+ description: "Migrate an existing project from .env to keynv.",
44451
45049
  details: `
44452
- Each integration writes a small, idempotent set of files. Re-running
44453
- yields the same state. Use --dry-run to preview changes before they
44454
- land.
45050
+ Walks the current directory's .env files, prompts you to mark which
45051
+ keys are real secrets, uploads those to the keynv vault, writes a
45052
+ .keynv.env file with alias references, and (optionally) wraps your
45053
+ package.json scripts with \`keynv exec\`.
45054
+
45055
+ Safe to re-run: existing .keynv.env entries are preserved; new
45056
+ entries are appended below a marker.
45057
+
45058
+ Requires an interactive terminal (clack TUI). For scripted
45059
+ migration, use the lower-level \`keynv project\` and \`keynv secret\`
45060
+ commands directly.
44455
45061
  `,
44456
45062
  examples: [
44457
- ["Install Claude Code", "$0 install claude-code"],
44458
- ["Preview the change", "$0 install claude-code --dry-run"],
44459
- ["Install all detected", "$0 install --all"],
44460
- ["List supported integrations", "$0 install list"]
45063
+ ["Walk the current project", "$0 init"],
45064
+ ["Preview without writing or uploading", "$0 init --dry-run"],
45065
+ ["Skip the package.json script-wrapping step", "$0 init --no-scripts"]
44461
45066
  ]
44462
45067
  });
44463
- agent = options_exports.String({ required: false });
44464
- dryRun = options_exports.Boolean("--dry-run", false);
44465
- all = options_exports.Boolean("--all", false);
45068
+ dryRun = options_exports.Boolean("--dry-run", false, {
45069
+ description: "Show what would be done without writing files or uploading secrets."
45070
+ });
45071
+ noScripts = options_exports.Boolean("--no-scripts", false, {
45072
+ description: "Skip the package.json script-wrapping step."
45073
+ });
44466
45074
  async execute() {
44467
- if (this.agent === "list") {
44468
- this.context.stdout.write("Supported integrations:\n");
44469
- for (const i of REGISTRY) {
44470
- this.context.stdout.write(` ${i.name.padEnd(14)} ${i.displayName}
44471
- `);
44472
- }
44473
- return 0;
44474
- }
44475
- if (this.all) {
44476
- const cwd = process.cwd();
44477
- let any = false;
44478
- for (const integration2 of REGISTRY) {
44479
- const detected = await integration2.detect({ cwd });
44480
- if (!detected) continue;
44481
- any = true;
44482
- const report2 = await integration2.install({ cwd, dryRun: this.dryRun });
44483
- printReport(this.context.stdout, report2);
44484
- }
44485
- if (!any) {
44486
- this.context.stdout.write("no integrations detected in this directory\n");
44487
- }
44488
- return 0;
44489
- }
44490
- if (!this.agent) {
45075
+ if (!isInteractive()) {
44491
45076
  this.context.stderr.write(
44492
- "keynv: usage: keynv install <agent> | keynv install --all | keynv install list\n"
45077
+ "keynv init requires an interactive terminal. Use the lower-level commands (`keynv project`, `keynv secret`) for scripted setup.\n"
44493
45078
  );
44494
- return 2;
45079
+ return 1;
44495
45080
  }
44496
- const integration = findIntegration(this.agent);
44497
- if (!integration) {
44498
- this.context.stderr.write(
44499
- `keynv: unknown integration '${this.agent}'. Try \`keynv install list\`.
44500
- `
44501
- );
45081
+ const client = new ApiClient();
45082
+ await client.ensureHydrated();
45083
+ if (!client.isLoggedIn) {
45084
+ this.context.stderr.write("keynv: not logged in. Run `keynv login` first.\n");
44502
45085
  return 1;
44503
45086
  }
44504
- const report = await integration.install({ cwd: process.cwd(), dryRun: this.dryRun });
44505
- printReport(this.context.stdout, report);
44506
- return 0;
44507
- }
44508
- };
44509
- var UninstallCommand = class extends Command {
44510
- static paths = [["uninstall"]];
44511
- static usage = Command.Usage({
44512
- description: "Remove keynv-managed entries written by an earlier `keynv install`."
44513
- });
44514
- agent = options_exports.String();
44515
- dryRun = options_exports.Boolean("--dry-run", false);
44516
- async execute() {
44517
- const integration = findIntegration(this.agent);
44518
- if (!integration) {
44519
- this.context.stderr.write(
44520
- `keynv: unknown integration '${this.agent}'. Try \`keynv install list\`.
44521
- `
44522
- );
45087
+ try {
45088
+ const outcome = await runInitFlow(client, {
45089
+ cwd: process.cwd(),
45090
+ dryRun: this.dryRun,
45091
+ noScripts: this.noScripts
45092
+ });
45093
+ return outcome.exitCode;
45094
+ } catch (err) {
45095
+ if (err instanceof UserCancelled) return 130;
45096
+ const e2 = err;
45097
+ this.context.stderr.write(`keynv: ${e2.message}
45098
+ `);
44523
45099
  return 1;
44524
45100
  }
44525
- const report = await integration.uninstall({ cwd: process.cwd(), dryRun: this.dryRun });
44526
- printReport(this.context.stdout, report);
44527
- return 0;
44528
45101
  }
44529
45102
  };
44530
45103
 
@@ -44540,7 +45113,7 @@ async function promptHidden(prompt) {
44540
45113
  process.stdin.setRawMode(true);
44541
45114
  process.stdin.resume();
44542
45115
  process.stdin.setEncoding("utf8");
44543
- return new Promise((resolve) => {
45116
+ return new Promise((resolve3) => {
44544
45117
  let buf = "";
44545
45118
  const onData = (chunk) => {
44546
45119
  for (const ch of chunk) {
@@ -44549,7 +45122,7 @@ async function promptHidden(prompt) {
44549
45122
  process.stdin.pause();
44550
45123
  process.stdin.removeListener("data", onData);
44551
45124
  process.stdout.write("\n");
44552
- resolve(buf);
45125
+ resolve3(buf);
44553
45126
  return;
44554
45127
  }
44555
45128
  if (ch === "") {
@@ -44567,10 +45140,10 @@ async function promptHidden(prompt) {
44567
45140
  }
44568
45141
  async function promptLine(prompt) {
44569
45142
  const rl = createInterface({ input: process.stdin, output: process.stdout });
44570
- return new Promise((resolve) => {
45143
+ return new Promise((resolve3) => {
44571
45144
  rl.question(prompt, (answer) => {
44572
45145
  rl.close();
44573
- resolve(answer.trim());
45146
+ resolve3(answer.trim());
44574
45147
  });
44575
45148
  });
44576
45149
  }
@@ -44961,9 +45534,9 @@ streaming-mode limitation in @keynv/redactor).
44961
45534
  `
44962
45535
  });
44963
45536
  async execute() {
44964
- return new Promise((resolve, reject) => {
45537
+ return new Promise((resolve3, reject) => {
44965
45538
  const transform = createRedactStream();
44966
- this.context.stdin.pipe(transform).pipe(this.context.stdout).on("error", reject).on("finish", () => resolve(0));
45539
+ this.context.stdin.pipe(transform).pipe(this.context.stdout).on("error", reject).on("finish", () => resolve3(0));
44967
45540
  this.context.stdin.on("error", reject);
44968
45541
  });
44969
45542
  }
@@ -45453,7 +46026,7 @@ var sshTester = {
45453
46026
  async test(secret, target) {
45454
46027
  const start = Date.now();
45455
46028
  const { Client: Client2 } = await import('ssh2');
45456
- return new Promise((resolve) => {
46029
+ return new Promise((resolve3) => {
45457
46030
  const client = new Client2();
45458
46031
  let settled = false;
45459
46032
  const settle = (result) => {
@@ -45464,7 +46037,7 @@ var sshTester = {
45464
46037
  client.end();
45465
46038
  } catch {
45466
46039
  }
45467
- resolve(result);
46040
+ resolve3(result);
45468
46041
  };
45469
46042
  client.once("ready", () => {
45470
46043
  client.exec("true", (err, stream) => {
@@ -45530,12 +46103,12 @@ function sanitizeResult(result, secret) {
45530
46103
 
45531
46104
  // ../../packages/testers/dist/run.js
45532
46105
  function withTimeout(promise, ms) {
45533
- return new Promise((resolve, reject) => {
46106
+ return new Promise((resolve3, reject) => {
45534
46107
  const t = setTimeout(() => reject(new Error(`tester timed out after ${ms}ms`)), ms);
45535
46108
  t.unref();
45536
46109
  promise.then((v2) => {
45537
46110
  clearTimeout(t);
45538
- resolve(v2);
46111
+ resolve3(v2);
45539
46112
  }, (err) => {
45540
46113
  clearTimeout(t);
45541
46114
  reject(err);
@@ -45769,10 +46342,9 @@ cli.register(MemberListCommand);
45769
46342
  cli.register(AuditListCommand);
45770
46343
  cli.register(AuditVerifyCommand);
45771
46344
  cli.register(ExecCommand);
46345
+ cli.register(InitCommand);
45772
46346
  cli.register(RedactCommand);
45773
46347
  cli.register(RedactStreamCommand);
45774
- cli.register(InstallCommand);
45775
- cli.register(UninstallCommand);
45776
46348
  cli.register(TestCommand);
45777
46349
  cli.register(UICommand);
45778
46350
  var argv = process.argv.slice(2);