@keynv/cli 0.1.0-rc.7 → 0.1.0-rc.9
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 +1244 -804
- package/dist/index.js.map +1 -1
- package/package.json +1 -2
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, statSync,
|
|
4
|
+
import { readFileSync, existsSync, statSync, writeFileSync, unlinkSync, mkdirSync, rmSync, readdirSync } from 'fs';
|
|
5
5
|
import { homedir } from 'os';
|
|
6
|
-
import { isAbsolute, resolve, 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.
|
|
1059
|
+
VERSION = "0.1.0-rc.9" ;
|
|
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
|
|
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 ?
|
|
6268
|
+
clear += this.line + (i < count - 1 ? cursor.up() : "");
|
|
6138
6269
|
if (count)
|
|
6139
|
-
clear +=
|
|
6270
|
+
clear += cursor.left;
|
|
6140
6271
|
return clear;
|
|
6141
6272
|
}
|
|
6142
6273
|
};
|
|
6143
|
-
module.exports = { cursor
|
|
6274
|
+
module.exports = { cursor, scroll, erase, beep };
|
|
6144
6275
|
}
|
|
6145
6276
|
});
|
|
6146
6277
|
function d(r, t, s) {
|
|
@@ -6884,6 +7015,502 @@ ${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
|
+
function aiContextBody() {
|
|
7132
|
+
return `## keynv (secrets)
|
|
7133
|
+
|
|
7134
|
+
This project uses [keynv](https://keynv.dev) for secrets. There is a \`.keynv.env\` file at the project root containing **alias references** like \`OPENAI_API_KEY=@projectname.dev.openai-key\` \u2014 these are NOT real values, they are references to secrets stored in the keynv vault.
|
|
7135
|
+
|
|
7136
|
+
### Mental model
|
|
7137
|
+
|
|
7138
|
+
- **\`.keynv.env\`** \u2014 checked into git, contains aliases. Safe to read, edit, commit.
|
|
7139
|
+
- **Vault** \u2014 holds the real values. The \`keynv\` CLI reads it on demand.
|
|
7140
|
+
- **\`keynv exec -- <command>\`** \u2014 forks the command in a subprocess where the real values are injected into env vars. The parent process (where you, the AI agent, run) NEVER sees the real values.
|
|
7141
|
+
- **Redactor** \u2014 pipes subprocess stdout/stderr through a masker before they reach this terminal. Even if a script accidentally echoes a secret, you see \`<REDACTED:...>\` here.
|
|
7142
|
+
|
|
7143
|
+
### What you should do
|
|
7144
|
+
|
|
7145
|
+
When the user asks about secrets or env vars, follow this decision tree:
|
|
7146
|
+
|
|
7147
|
+
| User intent | Run / suggest |
|
|
7148
|
+
|---|---|
|
|
7149
|
+
| "Add a new API key" / "set up a secret" | \`keynv secret create\` (interactive prompt picks project + env + key) |
|
|
7150
|
+
| "I have a \`.env\`, migrate it" | \`keynv init\` (you're seeing this file because that already happened) |
|
|
7151
|
+
| "Run the app / dev server / tests" | \`keynv exec -- <their existing command>\` (auto-loads \`.keynv.env\`) |
|
|
7152
|
+
| "Show me the value of X" | \`keynv secret get @alias\` \u2014 but copy to clipboard, do NOT print the value into chat / terminal |
|
|
7153
|
+
| "Rotate this key" | \`keynv secret rotate @alias\` |
|
|
7154
|
+
| "Add a new env var to the project" | Edit \`.keynv.env\` and add \`NAME=@project.env.key\` (after creating the secret with \`keynv secret create\`) |
|
|
7155
|
+
| "Who has access?" | \`keynv member list <project>\` |
|
|
7156
|
+
|
|
7157
|
+
### Hard rules \u2014 do not violate
|
|
7158
|
+
|
|
7159
|
+
1. **Never print resolved secret values** to the chat, terminal, log, or any file. The user's editor / scrollback / chat history is an attack surface.
|
|
7160
|
+
2. **Never write a \`.env\` file** (or any file) containing real secret values. The whole point of keynv is that those don't exist on disk.
|
|
7161
|
+
3. **Never edit \`.keynv.env\` to substitute resolved values for aliases.** The file should only ever contain \`@project.env.key\` references and plain non-secret literals.
|
|
7162
|
+
4. **Use \`keynv exec --\` to run commands that need env vars.** Don't try to load \`.keynv.env\` yourself by parsing it manually; the wrapper handles resolution + redaction + subprocess isolation.
|
|
7163
|
+
5. **If a tool fails with "blocked by keynv-guard" or similar**, do NOT try to work around it. Tell the user \u2014 that's a sign of a misconfiguration, not an obstacle to bypass.
|
|
7164
|
+
6. **Treat the alias literal (\`@project.env.key\`) as the canonical reference**, never the resolved value. When you write code, configs, or commands that need a secret, write the alias.
|
|
7165
|
+
|
|
7166
|
+
### Quick reference
|
|
7167
|
+
|
|
7168
|
+
\`\`\`bash
|
|
7169
|
+
keynv # interactive TUI menu (pick projects, secrets, members)
|
|
7170
|
+
keynv exec -- <cmd> # run cmd with .keynv.env loaded
|
|
7171
|
+
keynv secret create # walk through creating a new secret
|
|
7172
|
+
keynv secret list <project> # list aliases (no values)
|
|
7173
|
+
keynv whoami # who am I logged in as
|
|
7174
|
+
keynv --help # full command list
|
|
7175
|
+
\`\`\`
|
|
7176
|
+
|
|
7177
|
+
If \`.keynv.env\` is missing or empty, the user probably hasn't run \`keynv init\` yet \u2014 suggest they do so before they paste a secret into a \`.env\`.`;
|
|
7178
|
+
}
|
|
7179
|
+
function renderKeynvBlock() {
|
|
7180
|
+
return `${KEYNV_BLOCK_START}
|
|
7181
|
+
${aiContextBody()}
|
|
7182
|
+
${KEYNV_BLOCK_END}`;
|
|
7183
|
+
}
|
|
7184
|
+
function writeAiContext(rootPath) {
|
|
7185
|
+
const path = join(rootPath, AGENTS_FILE_BASENAME);
|
|
7186
|
+
const block = renderKeynvBlock();
|
|
7187
|
+
if (!existsSync(path)) {
|
|
7188
|
+
const initial = `# Agent guidance for this project
|
|
7189
|
+
|
|
7190
|
+
${block}
|
|
7191
|
+
`;
|
|
7192
|
+
writeFileSync(path, initial);
|
|
7193
|
+
return "created";
|
|
7194
|
+
}
|
|
7195
|
+
const existing = readFileSync(path, "utf8");
|
|
7196
|
+
const startIdx = existing.indexOf(KEYNV_BLOCK_START);
|
|
7197
|
+
const endIdx = existing.indexOf(KEYNV_BLOCK_END);
|
|
7198
|
+
if (startIdx >= 0 && endIdx > startIdx) {
|
|
7199
|
+
const before = existing.slice(0, startIdx);
|
|
7200
|
+
const after = existing.slice(endIdx + KEYNV_BLOCK_END.length);
|
|
7201
|
+
const next = `${before}${block}${after}`;
|
|
7202
|
+
if (next === existing) return "unchanged";
|
|
7203
|
+
writeFileSync(path, next);
|
|
7204
|
+
return "updated";
|
|
7205
|
+
}
|
|
7206
|
+
const sep = existing.length === 0 ? "" : existing.endsWith("\n\n") ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
|
|
7207
|
+
const trailingNewline = existing.endsWith("\n") ? "" : "\n";
|
|
7208
|
+
writeFileSync(path, `${existing}${trailingNewline}${sep}${block}
|
|
7209
|
+
`);
|
|
7210
|
+
return "appended";
|
|
7211
|
+
}
|
|
7212
|
+
var AGENTS_FILE_BASENAME, KEYNV_BLOCK_START, KEYNV_BLOCK_END;
|
|
7213
|
+
var init_aiContext = __esm({
|
|
7214
|
+
"src/init/aiContext.ts"() {
|
|
7215
|
+
AGENTS_FILE_BASENAME = "AGENTS.md";
|
|
7216
|
+
KEYNV_BLOCK_START = "<!-- keynv:start -- generated by `keynv init`; safe to leave intact, will be refreshed on re-run -->";
|
|
7217
|
+
KEYNV_BLOCK_END = "<!-- keynv:end -->";
|
|
7218
|
+
}
|
|
7219
|
+
});
|
|
7220
|
+
|
|
7221
|
+
// src/init/heuristics.ts
|
|
7222
|
+
function shannonEntropyBits(s) {
|
|
7223
|
+
if (s.length === 0) return 0;
|
|
7224
|
+
const counts = /* @__PURE__ */ new Map();
|
|
7225
|
+
for (const ch of s) counts.set(ch, (counts.get(ch) ?? 0) + 1);
|
|
7226
|
+
let h2 = 0;
|
|
7227
|
+
for (const c2 of counts.values()) {
|
|
7228
|
+
const p2 = c2 / s.length;
|
|
7229
|
+
h2 -= p2 * Math.log2(p2);
|
|
7230
|
+
}
|
|
7231
|
+
return h2;
|
|
7232
|
+
}
|
|
7233
|
+
function nameMatchesLiteralPrefix(name) {
|
|
7234
|
+
const upper = name.toUpperCase();
|
|
7235
|
+
return NAME_LITERAL_PREFIX.some((p2) => upper.startsWith(p2));
|
|
7236
|
+
}
|
|
7237
|
+
function nameMatchesSecretSuffix(name) {
|
|
7238
|
+
const upper = name.toUpperCase();
|
|
7239
|
+
for (const { suffix, hint } of NAME_SECRET_SUFFIXES) {
|
|
7240
|
+
if (upper.endsWith(suffix) || upper.endsWith(`_${suffix}`)) {
|
|
7241
|
+
return { matched: true, hint };
|
|
7242
|
+
}
|
|
7243
|
+
}
|
|
7244
|
+
return { matched: false, hint: "" };
|
|
7245
|
+
}
|
|
7246
|
+
function classifyEntry(name, value) {
|
|
7247
|
+
const upper = name.toUpperCase();
|
|
7248
|
+
if (NAME_LITERAL_EXACT.has(upper)) {
|
|
7249
|
+
return { verdict: "literal", hint: "common config var" };
|
|
7250
|
+
}
|
|
7251
|
+
if (nameMatchesLiteralPrefix(name)) {
|
|
7252
|
+
return { verdict: "literal", hint: "public env (build-time bundled)" };
|
|
7253
|
+
}
|
|
7254
|
+
if (value.length === 0) {
|
|
7255
|
+
return { verdict: "literal", hint: "empty" };
|
|
7256
|
+
}
|
|
7257
|
+
for (const { re, hint } of VALUE_PATTERNS) {
|
|
7258
|
+
if (re.test(value)) return { verdict: "secret", hint };
|
|
7259
|
+
}
|
|
7260
|
+
const suffix = nameMatchesSecretSuffix(name);
|
|
7261
|
+
if (suffix.matched) {
|
|
7262
|
+
return { verdict: "secret", hint: suffix.hint };
|
|
7263
|
+
}
|
|
7264
|
+
if (NAME_DB_URL.test(name)) {
|
|
7265
|
+
return { verdict: "secret", hint: "database URL" };
|
|
7266
|
+
}
|
|
7267
|
+
if (value.length >= 32) {
|
|
7268
|
+
const bits = shannonEntropyBits(value);
|
|
7269
|
+
if (bits >= 3.5) {
|
|
7270
|
+
return { verdict: "secret", hint: `${value.length}-char random-looking string` };
|
|
7271
|
+
}
|
|
7272
|
+
}
|
|
7273
|
+
return { verdict: "ambiguous", hint: "" };
|
|
7274
|
+
}
|
|
7275
|
+
function previewValue(value, max = 40) {
|
|
7276
|
+
if (value.length === 0) return "(empty)";
|
|
7277
|
+
if (value.length <= max) return value;
|
|
7278
|
+
return `${value.slice(0, max - 1)}\u2026`;
|
|
7279
|
+
}
|
|
7280
|
+
var NAME_LITERAL_EXACT, NAME_LITERAL_PREFIX, NAME_SECRET_SUFFIXES, NAME_DB_URL, VALUE_PATTERNS;
|
|
7281
|
+
var init_heuristics = __esm({
|
|
7282
|
+
"src/init/heuristics.ts"() {
|
|
7283
|
+
NAME_LITERAL_EXACT = /* @__PURE__ */ new Set([
|
|
7284
|
+
"NODE_ENV",
|
|
7285
|
+
"PORT",
|
|
7286
|
+
"HOST",
|
|
7287
|
+
"HOSTNAME",
|
|
7288
|
+
"DEBUG",
|
|
7289
|
+
"LOG_LEVEL",
|
|
7290
|
+
"LOGLEVEL",
|
|
7291
|
+
"TZ",
|
|
7292
|
+
"LANG",
|
|
7293
|
+
"LC_ALL",
|
|
7294
|
+
"PATH",
|
|
7295
|
+
"HOME",
|
|
7296
|
+
"USER",
|
|
7297
|
+
"SHELL",
|
|
7298
|
+
"PWD",
|
|
7299
|
+
"CI",
|
|
7300
|
+
"NODE_OPTIONS",
|
|
7301
|
+
"NPM_CONFIG_LOGLEVEL",
|
|
7302
|
+
"TS_NODE_PROJECT"
|
|
7303
|
+
]);
|
|
7304
|
+
NAME_LITERAL_PREFIX = ["NEXT_PUBLIC_", "VITE_", "REACT_APP_", "PUBLIC_", "EXPO_PUBLIC_"];
|
|
7305
|
+
NAME_SECRET_SUFFIXES = [
|
|
7306
|
+
{ suffix: "PRIVATE_KEY", hint: "private key" },
|
|
7307
|
+
{ suffix: "API_KEY", hint: "API key" },
|
|
7308
|
+
{ suffix: "ACCESS_KEY", hint: "access key" },
|
|
7309
|
+
{ suffix: "SECRET_KEY", hint: "secret key" },
|
|
7310
|
+
{ suffix: "SECRET", hint: "secret" },
|
|
7311
|
+
{ suffix: "PASSWORD", hint: "password" },
|
|
7312
|
+
{ suffix: "PASSPHRASE", hint: "passphrase" },
|
|
7313
|
+
{ suffix: "TOKEN", hint: "token" },
|
|
7314
|
+
{ suffix: "KEY", hint: "key" },
|
|
7315
|
+
{ suffix: "CREDENTIALS", hint: "credentials" },
|
|
7316
|
+
{ suffix: "AUTH", hint: "auth" },
|
|
7317
|
+
{ suffix: "DSN", hint: "connection string" }
|
|
7318
|
+
];
|
|
7319
|
+
NAME_DB_URL = /^(DATABASE|DB|POSTGRES|MYSQL|MONGO|REDIS)_URL$/i;
|
|
7320
|
+
VALUE_PATTERNS = [
|
|
7321
|
+
{ re: /^sk-proj-/, hint: "OpenAI project key" },
|
|
7322
|
+
{ re: /^sk-[A-Za-z0-9]{20,}/, hint: "OpenAI key" },
|
|
7323
|
+
{ re: /^sk_live_/, hint: "Stripe live key" },
|
|
7324
|
+
{ re: /^sk_test_/, hint: "Stripe test key" },
|
|
7325
|
+
{ re: /^pk_live_/, hint: "Stripe publishable (often public, double-check)" },
|
|
7326
|
+
{ re: /^xoxb-/, hint: "Slack bot token" },
|
|
7327
|
+
{ re: /^xoxp-/, hint: "Slack user token" },
|
|
7328
|
+
{ re: /^ghp_[A-Za-z0-9]{30,}/, hint: "GitHub personal access token" },
|
|
7329
|
+
{ re: /^github_pat_/, hint: "GitHub fine-grained PAT" },
|
|
7330
|
+
{ re: /^gho_/, hint: "GitHub OAuth token" },
|
|
7331
|
+
{ re: /^AKIA[0-9A-Z]{16}$/, hint: "AWS access key id" },
|
|
7332
|
+
{ re: /^ASIA[0-9A-Z]{16}$/, hint: "AWS temporary key id" },
|
|
7333
|
+
{ re: /^AIza[0-9A-Za-z_-]{35}$/, hint: "Google API key" },
|
|
7334
|
+
{ re: /^ya29\./, hint: "Google OAuth access token" },
|
|
7335
|
+
{ re: /^eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/, hint: "JWT" },
|
|
7336
|
+
{ re: /^-----BEGIN [A-Z ]+PRIVATE KEY-----/, hint: "PEM private key" },
|
|
7337
|
+
{ re: /^([a-z]+):\/\/[^@]+:[^@]+@/i, hint: "connection string with credentials" }
|
|
7338
|
+
];
|
|
7339
|
+
}
|
|
7340
|
+
});
|
|
7341
|
+
|
|
7342
|
+
// src/init/scriptWrap.ts
|
|
7343
|
+
function analyzeScript(name, command) {
|
|
7344
|
+
const trimmed = command.trim();
|
|
7345
|
+
if (trimmed.startsWith("keynv ") || trimmed.startsWith("keynv ")) {
|
|
7346
|
+
return {
|
|
7347
|
+
name,
|
|
7348
|
+
original: command,
|
|
7349
|
+
wrapped: command,
|
|
7350
|
+
verdict: "skip-already-wrapped",
|
|
7351
|
+
hint: "already wrapped"
|
|
7352
|
+
};
|
|
7353
|
+
}
|
|
7354
|
+
const firstWord = extractFirstCommandWord(trimmed);
|
|
7355
|
+
if (firstWord === null) {
|
|
7356
|
+
return {
|
|
7357
|
+
name,
|
|
7358
|
+
original: command,
|
|
7359
|
+
wrapped: `${KEYNV_PREFIX} ${command}`,
|
|
7360
|
+
verdict: "skip-unknown",
|
|
7361
|
+
hint: "cannot parse"
|
|
7362
|
+
};
|
|
7363
|
+
}
|
|
7364
|
+
const wrapped = `${KEYNV_PREFIX} ${command}`;
|
|
7365
|
+
if (ENV_AWARE_TOOLS.has(firstWord)) {
|
|
7366
|
+
return { name, original: command, wrapped, verdict: "wrap", hint: `${firstWord} reads env` };
|
|
7367
|
+
}
|
|
7368
|
+
if (NON_ENV_TOOLS.has(firstWord)) {
|
|
7369
|
+
return {
|
|
7370
|
+
name,
|
|
7371
|
+
original: command,
|
|
7372
|
+
wrapped,
|
|
7373
|
+
verdict: "skip-no-env-tool",
|
|
7374
|
+
hint: `${firstWord} doesn't need env`
|
|
7375
|
+
};
|
|
7376
|
+
}
|
|
7377
|
+
return {
|
|
7378
|
+
name,
|
|
7379
|
+
original: command,
|
|
7380
|
+
wrapped,
|
|
7381
|
+
verdict: "skip-unknown",
|
|
7382
|
+
hint: `unrecognized: ${firstWord}`
|
|
7383
|
+
};
|
|
7384
|
+
}
|
|
7385
|
+
function extractFirstCommandWord(s) {
|
|
7386
|
+
const tokens = s.split(/\s+/).filter((t) => t.length > 0);
|
|
7387
|
+
let i = 0;
|
|
7388
|
+
while (i < tokens.length) {
|
|
7389
|
+
const t = tokens[i];
|
|
7390
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(t)) {
|
|
7391
|
+
i++;
|
|
7392
|
+
continue;
|
|
7393
|
+
}
|
|
7394
|
+
if (t === "cross-env") {
|
|
7395
|
+
i++;
|
|
7396
|
+
while (i < tokens.length && /^[A-Za-z_][A-Za-z0-9_]*=/.test(tokens[i])) i++;
|
|
7397
|
+
continue;
|
|
7398
|
+
}
|
|
7399
|
+
if (t === "dotenv") {
|
|
7400
|
+
const dashDash = tokens.indexOf("--", i + 1);
|
|
7401
|
+
if (dashDash >= 0) {
|
|
7402
|
+
i = dashDash + 1;
|
|
7403
|
+
continue;
|
|
7404
|
+
}
|
|
7405
|
+
i++;
|
|
7406
|
+
while (i < tokens.length && tokens[i].startsWith("-")) i++;
|
|
7407
|
+
continue;
|
|
7408
|
+
}
|
|
7409
|
+
if (t === "sh" || t === "bash" || t === "zsh") {
|
|
7410
|
+
return null;
|
|
7411
|
+
}
|
|
7412
|
+
return t.replace(/^.*\//, "");
|
|
7413
|
+
}
|
|
7414
|
+
return null;
|
|
7415
|
+
}
|
|
7416
|
+
function planScriptWrap(scripts) {
|
|
7417
|
+
const recommended = [];
|
|
7418
|
+
const skipped = [];
|
|
7419
|
+
const unknown = [];
|
|
7420
|
+
for (const [name, command] of Object.entries(scripts)) {
|
|
7421
|
+
const analysis = analyzeScript(name, command);
|
|
7422
|
+
switch (analysis.verdict) {
|
|
7423
|
+
case "wrap":
|
|
7424
|
+
recommended.push(analysis);
|
|
7425
|
+
break;
|
|
7426
|
+
case "skip-unknown":
|
|
7427
|
+
unknown.push(analysis);
|
|
7428
|
+
break;
|
|
7429
|
+
default:
|
|
7430
|
+
skipped.push(analysis);
|
|
7431
|
+
}
|
|
7432
|
+
}
|
|
7433
|
+
return { recommended, skipped, unknown };
|
|
7434
|
+
}
|
|
7435
|
+
function applyWraps(original, selectedScriptNames) {
|
|
7436
|
+
const out = { ...original };
|
|
7437
|
+
const selection = new Set(selectedScriptNames);
|
|
7438
|
+
for (const [name, command] of Object.entries(original)) {
|
|
7439
|
+
if (!selection.has(name)) continue;
|
|
7440
|
+
const trimmed = command.trim();
|
|
7441
|
+
if (trimmed.startsWith("keynv ") || trimmed.startsWith("keynv ")) continue;
|
|
7442
|
+
out[name] = `${KEYNV_PREFIX} ${command}`;
|
|
7443
|
+
}
|
|
7444
|
+
return out;
|
|
7445
|
+
}
|
|
7446
|
+
var KEYNV_PREFIX, ENV_AWARE_TOOLS, NON_ENV_TOOLS;
|
|
7447
|
+
var init_scriptWrap = __esm({
|
|
7448
|
+
"src/init/scriptWrap.ts"() {
|
|
7449
|
+
KEYNV_PREFIX = "keynv exec --";
|
|
7450
|
+
ENV_AWARE_TOOLS = /* @__PURE__ */ new Set([
|
|
7451
|
+
"node",
|
|
7452
|
+
"tsx",
|
|
7453
|
+
"ts-node",
|
|
7454
|
+
"bun",
|
|
7455
|
+
"deno",
|
|
7456
|
+
"next",
|
|
7457
|
+
"nuxt",
|
|
7458
|
+
"vite",
|
|
7459
|
+
"remix",
|
|
7460
|
+
"astro",
|
|
7461
|
+
"gatsby",
|
|
7462
|
+
"nest",
|
|
7463
|
+
"webpack",
|
|
7464
|
+
"rollup",
|
|
7465
|
+
"parcel",
|
|
7466
|
+
"vitest",
|
|
7467
|
+
"jest",
|
|
7468
|
+
"mocha",
|
|
7469
|
+
"cypress",
|
|
7470
|
+
"playwright",
|
|
7471
|
+
"storybook",
|
|
7472
|
+
"tsc-watch",
|
|
7473
|
+
"pm2",
|
|
7474
|
+
"forever",
|
|
7475
|
+
"nodemon",
|
|
7476
|
+
"concurrently",
|
|
7477
|
+
"pytest",
|
|
7478
|
+
"python",
|
|
7479
|
+
"python3",
|
|
7480
|
+
"gunicorn",
|
|
7481
|
+
"uvicorn",
|
|
7482
|
+
"celery",
|
|
7483
|
+
"flask",
|
|
7484
|
+
"django-admin",
|
|
7485
|
+
"manage.py",
|
|
7486
|
+
"rails",
|
|
7487
|
+
"rake",
|
|
7488
|
+
"go",
|
|
7489
|
+
"cargo",
|
|
7490
|
+
"air"
|
|
7491
|
+
]);
|
|
7492
|
+
NON_ENV_TOOLS = /* @__PURE__ */ new Set([
|
|
7493
|
+
"eslint",
|
|
7494
|
+
"biome",
|
|
7495
|
+
"prettier",
|
|
7496
|
+
"tsc",
|
|
7497
|
+
"tslint",
|
|
7498
|
+
"stylelint",
|
|
7499
|
+
"rm",
|
|
7500
|
+
"cp",
|
|
7501
|
+
"mv",
|
|
7502
|
+
"mkdir",
|
|
7503
|
+
"echo",
|
|
7504
|
+
"cat",
|
|
7505
|
+
"find",
|
|
7506
|
+
"grep",
|
|
7507
|
+
"sort",
|
|
7508
|
+
"uniq",
|
|
7509
|
+
"sed",
|
|
7510
|
+
"awk"
|
|
7511
|
+
]);
|
|
7512
|
+
}
|
|
7513
|
+
});
|
|
6887
7514
|
|
|
6888
7515
|
// src/ui/helpers/cancel.ts
|
|
6889
7516
|
function unwrap(value) {
|
|
@@ -6925,6 +7552,428 @@ var init_pickProject = __esm({
|
|
|
6925
7552
|
}
|
|
6926
7553
|
});
|
|
6927
7554
|
|
|
7555
|
+
// src/ui/flows/init.ts
|
|
7556
|
+
var init_exports = {};
|
|
7557
|
+
__export(init_exports, {
|
|
7558
|
+
UserCancelled: () => UserCancelled,
|
|
7559
|
+
runInitFlow: () => runInitFlow
|
|
7560
|
+
});
|
|
7561
|
+
async function runInitFlow(client, opts) {
|
|
7562
|
+
ge("keynv init");
|
|
7563
|
+
const root = findProjectRoot(opts.cwd);
|
|
7564
|
+
if (root === null) {
|
|
7565
|
+
me(
|
|
7566
|
+
"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."
|
|
7567
|
+
);
|
|
7568
|
+
return { exitCode: 1 };
|
|
7569
|
+
}
|
|
7570
|
+
if (root.packageJsonInvalid) {
|
|
7571
|
+
R2.warn(`package.json at ${root.path} is not valid JSON \u2014 script wrapping will be skipped.`);
|
|
7572
|
+
}
|
|
7573
|
+
const envFiles = findEnvFiles(root.path);
|
|
7574
|
+
if (envFiles.length === 0 && !hasExistingKeynvEnv(root.path)) {
|
|
7575
|
+
R2.info(
|
|
7576
|
+
`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.`
|
|
7577
|
+
);
|
|
7578
|
+
ye("Nothing to do.");
|
|
7579
|
+
return { exitCode: 0 };
|
|
7580
|
+
}
|
|
7581
|
+
const intoExisting = hasExistingKeynvEnv(root.path);
|
|
7582
|
+
Se(
|
|
7583
|
+
[
|
|
7584
|
+
`Project root: ${root.path}`,
|
|
7585
|
+
`Marker: ${root.marker}`,
|
|
7586
|
+
envFiles.length > 0 ? `Found env files: ${envFiles.map((f) => f.name).join(", ")}` : "Found env files: (none)",
|
|
7587
|
+
intoExisting ? "Existing .keynv.env detected \u2014 will merge new entries in." : ""
|
|
7588
|
+
].filter(Boolean).join("\n"),
|
|
7589
|
+
"Detected"
|
|
7590
|
+
);
|
|
7591
|
+
const merged = mergeEnvFiles(envFiles);
|
|
7592
|
+
if (merged.length === 0) {
|
|
7593
|
+
R2.info("All env files were empty (only comments/blanks). Nothing to upload.");
|
|
7594
|
+
ye("Done.");
|
|
7595
|
+
return { exitCode: 0 };
|
|
7596
|
+
}
|
|
7597
|
+
const projectChoice = await pickOrCreateProject(client, root.suggestedName);
|
|
7598
|
+
if (projectChoice === null) {
|
|
7599
|
+
me("No project selected.");
|
|
7600
|
+
return { exitCode: 130 };
|
|
7601
|
+
}
|
|
7602
|
+
const envName = await pickEnvForUpload(client, projectChoice, envFiles);
|
|
7603
|
+
if (envName === null) {
|
|
7604
|
+
me("No environment selected.");
|
|
7605
|
+
return { exitCode: 130 };
|
|
7606
|
+
}
|
|
7607
|
+
const choices = merged.map((e2) => {
|
|
7608
|
+
const verdict = classifyEntry(e2.name, e2.value);
|
|
7609
|
+
const hint = verdict.hint || (e2.isAlias ? "looks like an alias literal" : "no signal");
|
|
7610
|
+
const preview2 = e2.isAlias ? e2.value : previewValue(e2.value, 32);
|
|
7611
|
+
return {
|
|
7612
|
+
name: e2.name,
|
|
7613
|
+
value: e2.value,
|
|
7614
|
+
isAlias: e2.isAlias,
|
|
7615
|
+
verdict: verdict.verdict,
|
|
7616
|
+
label: `${e2.name} ${preview2}`,
|
|
7617
|
+
hint,
|
|
7618
|
+
sourceLine: e2.sourceLine,
|
|
7619
|
+
source: e2.source
|
|
7620
|
+
};
|
|
7621
|
+
});
|
|
7622
|
+
const initialSecretSelection = choices.filter((c2) => c2.verdict === "secret" && !c2.isAlias).map((c2) => c2.name);
|
|
7623
|
+
const selectedSecretNames = unwrap(
|
|
7624
|
+
await ve({
|
|
7625
|
+
message: "Mark which keys are secrets (vault-uploaded). Unchecked keys stay as literals.",
|
|
7626
|
+
options: choices.map((c2) => ({
|
|
7627
|
+
value: c2.name,
|
|
7628
|
+
label: c2.label,
|
|
7629
|
+
hint: c2.isAlias ? `${c2.hint} \u2014 already aliased; will pass through` : c2.hint
|
|
7630
|
+
})),
|
|
7631
|
+
initialValues: initialSecretSelection,
|
|
7632
|
+
required: false
|
|
7633
|
+
})
|
|
7634
|
+
);
|
|
7635
|
+
const selected = new Set(selectedSecretNames);
|
|
7636
|
+
let scriptWrapSelection = [];
|
|
7637
|
+
let scriptPlan = root.packageJsonScripts ? planScriptWrap(root.packageJsonScripts) : null;
|
|
7638
|
+
if (!opts.noScripts && scriptPlan && scriptPlan.recommended.length > 0) {
|
|
7639
|
+
const wrapAnswer = unwrap(
|
|
7640
|
+
await ve({
|
|
7641
|
+
message: "Wrap package.json scripts with `keynv exec`? (recommended)",
|
|
7642
|
+
options: [
|
|
7643
|
+
...scriptPlan.recommended.map((a) => ({
|
|
7644
|
+
value: a.name,
|
|
7645
|
+
label: `${a.name} \u2192 ${a.wrapped}`,
|
|
7646
|
+
hint: a.hint
|
|
7647
|
+
})),
|
|
7648
|
+
...scriptPlan.unknown.map((a) => ({
|
|
7649
|
+
value: a.name,
|
|
7650
|
+
label: `${a.name} \u2192 ${a.wrapped}`,
|
|
7651
|
+
hint: `unknown tool \u2014 opt in if you know it reads env`
|
|
7652
|
+
}))
|
|
7653
|
+
],
|
|
7654
|
+
initialValues: scriptPlan.recommended.map((a) => a.name),
|
|
7655
|
+
required: false
|
|
7656
|
+
})
|
|
7657
|
+
);
|
|
7658
|
+
scriptWrapSelection = wrapAnswer;
|
|
7659
|
+
} else if (opts.noScripts) {
|
|
7660
|
+
scriptPlan = null;
|
|
7661
|
+
}
|
|
7662
|
+
const envFileFateRaw = unwrap(
|
|
7663
|
+
await Ee({
|
|
7664
|
+
message: "After upload, what about the original .env files?",
|
|
7665
|
+
options: [
|
|
7666
|
+
{ value: "delete", label: "Delete (recommended \u2014 eliminates the leak vector)" },
|
|
7667
|
+
{ value: "gitignore", label: "Keep but make sure .gitignore covers them" }
|
|
7668
|
+
],
|
|
7669
|
+
initialValue: "delete"
|
|
7670
|
+
})
|
|
7671
|
+
);
|
|
7672
|
+
const planSummary = [
|
|
7673
|
+
`Project: ${projectChoice.name}${projectChoice.created ? " (will be created)" : ""}`,
|
|
7674
|
+
`Environment: ${envName}`,
|
|
7675
|
+
`Secrets to vault: ${selected.size}`,
|
|
7676
|
+
`Literals in file: ${merged.length - selected.size}`,
|
|
7677
|
+
`Script wraps: ${scriptWrapSelection.length}`,
|
|
7678
|
+
`Original .env: ${envFileFateRaw === "delete" ? "delete" : "keep + gitignore"}`,
|
|
7679
|
+
opts.dryRun ? "Dry-run: no changes will be made." : ""
|
|
7680
|
+
].filter(Boolean).join("\n");
|
|
7681
|
+
Se(planSummary, "About to apply");
|
|
7682
|
+
const proceed = unwrap(await ue({ message: "Proceed?", initialValue: true }));
|
|
7683
|
+
if (!proceed) {
|
|
7684
|
+
me("Aborted.");
|
|
7685
|
+
return { exitCode: 130 };
|
|
7686
|
+
}
|
|
7687
|
+
if (opts.dryRun) {
|
|
7688
|
+
ye("Dry-run complete \u2014 no changes were made.");
|
|
7689
|
+
return { exitCode: 0 };
|
|
7690
|
+
}
|
|
7691
|
+
let projectId2;
|
|
7692
|
+
if (projectChoice.created) {
|
|
7693
|
+
const s = ft();
|
|
7694
|
+
s.start(`Creating project "${projectChoice.name}"`);
|
|
7695
|
+
try {
|
|
7696
|
+
const created = await client.request("/v1/projects", {
|
|
7697
|
+
method: "POST",
|
|
7698
|
+
body: {
|
|
7699
|
+
name: projectChoice.name,
|
|
7700
|
+
environments: [{ name: envName, tier: "non-production", require_approval: false }]
|
|
7701
|
+
}
|
|
7702
|
+
});
|
|
7703
|
+
projectId2 = created.id;
|
|
7704
|
+
s.stop(`Created project ${created.name}`);
|
|
7705
|
+
} catch (err) {
|
|
7706
|
+
s.error(`Failed to create project: ${err instanceof Error ? err.message : String(err)}`);
|
|
7707
|
+
return { exitCode: 1 };
|
|
7708
|
+
}
|
|
7709
|
+
} else {
|
|
7710
|
+
projectId2 = projectChoice.id;
|
|
7711
|
+
}
|
|
7712
|
+
const uploaded = [];
|
|
7713
|
+
const failed = [];
|
|
7714
|
+
if (selected.size > 0) {
|
|
7715
|
+
const s = ft();
|
|
7716
|
+
s.start(`Uploading ${selected.size} secrets`);
|
|
7717
|
+
let i = 0;
|
|
7718
|
+
for (const entry2 of merged) {
|
|
7719
|
+
if (!selected.has(entry2.name)) continue;
|
|
7720
|
+
i++;
|
|
7721
|
+
s.message(`Uploading (${i}/${selected.size}) ${entry2.name}`);
|
|
7722
|
+
const aliasKey = entry2.name.toLowerCase().replace(/_/g, "-");
|
|
7723
|
+
try {
|
|
7724
|
+
await client.request(`/v1/projects/${projectId2}/secrets`, {
|
|
7725
|
+
method: "POST",
|
|
7726
|
+
body: { env: envName, key: aliasKey, value: entry2.value }
|
|
7727
|
+
});
|
|
7728
|
+
const alias2 = buildAlias({ project: projectChoice.name, environment: envName, key: aliasKey });
|
|
7729
|
+
if (alias2 === null) {
|
|
7730
|
+
failed.push({
|
|
7731
|
+
name: entry2.name,
|
|
7732
|
+
reason: `produced an invalid alias for project=${projectChoice.name} env=${envName} key=${aliasKey}`
|
|
7733
|
+
});
|
|
7734
|
+
} else {
|
|
7735
|
+
uploaded.push({ name: entry2.name, aliasLiteral: alias2.literal });
|
|
7736
|
+
}
|
|
7737
|
+
} catch (err) {
|
|
7738
|
+
failed.push({ name: entry2.name, reason: err instanceof Error ? err.message : String(err) });
|
|
7739
|
+
}
|
|
7740
|
+
}
|
|
7741
|
+
if (failed.length === 0) {
|
|
7742
|
+
s.stop(`Uploaded ${uploaded.length} secrets`);
|
|
7743
|
+
} else {
|
|
7744
|
+
s.error(`${uploaded.length}/${selected.size} uploaded; ${failed.length} failed`);
|
|
7745
|
+
for (const f of failed) R2.warn(` ${f.name}: ${f.reason}`);
|
|
7746
|
+
}
|
|
7747
|
+
}
|
|
7748
|
+
const literals = merged.filter((e2) => !selected.has(e2.name));
|
|
7749
|
+
const successUploads = new Map(uploaded.map((u) => [u.name, u.aliasLiteral]));
|
|
7750
|
+
const keynvEnvPath = join(root.path, ".keynv.env");
|
|
7751
|
+
let writtenLines;
|
|
7752
|
+
try {
|
|
7753
|
+
writtenLines = composeKeynvEnv({
|
|
7754
|
+
uploadedAliases: successUploads,
|
|
7755
|
+
literals,
|
|
7756
|
+
mergeWithExisting: intoExisting ? readFileSync(keynvEnvPath, "utf8") : null
|
|
7757
|
+
});
|
|
7758
|
+
writeFileSync(keynvEnvPath, `${writtenLines.join("\n")}
|
|
7759
|
+
`);
|
|
7760
|
+
R2.success(
|
|
7761
|
+
`${intoExisting ? "Updated" : "Wrote"} ${keynvEnvPath} (${successUploads.size + literals.length} entries)`
|
|
7762
|
+
);
|
|
7763
|
+
} catch (err) {
|
|
7764
|
+
R2.error(`Failed to write .keynv.env: ${err instanceof Error ? err.message : String(err)}`);
|
|
7765
|
+
return { exitCode: 1 };
|
|
7766
|
+
}
|
|
7767
|
+
try {
|
|
7768
|
+
const outcome = writeAiContext(root.path);
|
|
7769
|
+
if (outcome === "created") R2.success("Wrote AGENTS.md (so AI agents understand keynv)");
|
|
7770
|
+
else if (outcome === "updated") R2.success("Refreshed keynv section in AGENTS.md");
|
|
7771
|
+
else if (outcome === "appended") R2.success("Appended keynv section to AGENTS.md");
|
|
7772
|
+
} catch (err) {
|
|
7773
|
+
R2.warn(`Could not write AGENTS.md: ${err instanceof Error ? err.message : String(err)}`);
|
|
7774
|
+
}
|
|
7775
|
+
if (scriptWrapSelection.length > 0 && root.packageJsonScripts) {
|
|
7776
|
+
try {
|
|
7777
|
+
updatePackageJsonScripts(
|
|
7778
|
+
join(root.path, "package.json"),
|
|
7779
|
+
root.packageJsonScripts,
|
|
7780
|
+
scriptWrapSelection
|
|
7781
|
+
);
|
|
7782
|
+
R2.success(`Wrapped ${scriptWrapSelection.length} script(s) in package.json`);
|
|
7783
|
+
} catch (err) {
|
|
7784
|
+
R2.warn(
|
|
7785
|
+
`Could not update package.json scripts: ${err instanceof Error ? err.message : String(err)}`
|
|
7786
|
+
);
|
|
7787
|
+
}
|
|
7788
|
+
}
|
|
7789
|
+
if (envFileFateRaw === "delete") {
|
|
7790
|
+
for (const f of envFiles) {
|
|
7791
|
+
try {
|
|
7792
|
+
unlinkSync(f.path);
|
|
7793
|
+
R2.success(`Removed ${f.name}`);
|
|
7794
|
+
} catch (err) {
|
|
7795
|
+
R2.warn(`Could not remove ${f.name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
7796
|
+
}
|
|
7797
|
+
}
|
|
7798
|
+
} else {
|
|
7799
|
+
const gitignorePath = join(root.path, ".gitignore");
|
|
7800
|
+
try {
|
|
7801
|
+
ensureGitignoreEntries(gitignorePath, envFiles.map((f) => f.name));
|
|
7802
|
+
R2.success(`Updated .gitignore (${envFiles.length} entries ensured)`);
|
|
7803
|
+
} catch (err) {
|
|
7804
|
+
R2.warn(`Could not update .gitignore: ${err instanceof Error ? err.message : String(err)}`);
|
|
7805
|
+
}
|
|
7806
|
+
}
|
|
7807
|
+
ye(
|
|
7808
|
+
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>"}`
|
|
7809
|
+
);
|
|
7810
|
+
return { exitCode: failed.length > 0 ? 1 : 0 };
|
|
7811
|
+
}
|
|
7812
|
+
function mergeEnvFiles(files) {
|
|
7813
|
+
const map = /* @__PURE__ */ new Map();
|
|
7814
|
+
for (const f of files) {
|
|
7815
|
+
let entries;
|
|
7816
|
+
try {
|
|
7817
|
+
entries = parseEnvFile(readFileSync(f.path, "utf8"), f.path);
|
|
7818
|
+
} catch (err) {
|
|
7819
|
+
R2.warn(`${f.name}: ${err instanceof Error ? err.message : String(err)} \u2014 skipping file`);
|
|
7820
|
+
continue;
|
|
7821
|
+
}
|
|
7822
|
+
for (const e2 of entries) {
|
|
7823
|
+
const existing = map.get(e2.name);
|
|
7824
|
+
if (existing) {
|
|
7825
|
+
existing.shadowedBy.push(f.name);
|
|
7826
|
+
existing.value = e2.value;
|
|
7827
|
+
existing.isAlias = e2.isAlias;
|
|
7828
|
+
} else {
|
|
7829
|
+
map.set(e2.name, {
|
|
7830
|
+
name: e2.name,
|
|
7831
|
+
value: e2.value,
|
|
7832
|
+
isAlias: e2.isAlias,
|
|
7833
|
+
source: f.name,
|
|
7834
|
+
sourceLine: e2.line,
|
|
7835
|
+
shadowedBy: []
|
|
7836
|
+
});
|
|
7837
|
+
}
|
|
7838
|
+
}
|
|
7839
|
+
}
|
|
7840
|
+
return [...map.values()];
|
|
7841
|
+
}
|
|
7842
|
+
async function pickOrCreateProject(client, suggestedName) {
|
|
7843
|
+
const projects = await listProjects(client);
|
|
7844
|
+
const value = unwrap(
|
|
7845
|
+
await Ee({
|
|
7846
|
+
message: "Use which keynv project?",
|
|
7847
|
+
options: [
|
|
7848
|
+
{ value: "__new", label: `+ Create new: "${suggestedName}"` },
|
|
7849
|
+
...projects.map((p2) => ({ value: p2.id, label: p2.name, hint: p2.id }))
|
|
7850
|
+
]
|
|
7851
|
+
})
|
|
7852
|
+
);
|
|
7853
|
+
if (value === "__new") {
|
|
7854
|
+
const name = unwrap(
|
|
7855
|
+
await Re({
|
|
7856
|
+
message: "Project name",
|
|
7857
|
+
initialValue: suggestedName,
|
|
7858
|
+
validate: (v2) => v2 && /^[a-z0-9][a-z0-9-]{0,47}$/.test(v2) ? void 0 : "lowercase letters, digits, dashes; up to 48 chars"
|
|
7859
|
+
})
|
|
7860
|
+
);
|
|
7861
|
+
return { id: "", name, created: true };
|
|
7862
|
+
}
|
|
7863
|
+
const match = projects.find((p2) => p2.id === value);
|
|
7864
|
+
if (!match) return null;
|
|
7865
|
+
return { id: match.id, name: match.name, created: false };
|
|
7866
|
+
}
|
|
7867
|
+
async function pickEnvForUpload(client, project, envFiles) {
|
|
7868
|
+
const firstSuffix = envFiles[0]?.suffix ?? null;
|
|
7869
|
+
const suggested = suggestedEnvForSuffix(firstSuffix);
|
|
7870
|
+
if (project.created) {
|
|
7871
|
+
const value2 = unwrap(
|
|
7872
|
+
await Re({
|
|
7873
|
+
message: "Environment to create",
|
|
7874
|
+
initialValue: suggested,
|
|
7875
|
+
validate: (v2) => v2 && /^[a-z0-9][a-z0-9-]{0,23}$/.test(v2) ? void 0 : "lowercase letters, digits, dashes; up to 24 chars"
|
|
7876
|
+
})
|
|
7877
|
+
);
|
|
7878
|
+
return value2;
|
|
7879
|
+
}
|
|
7880
|
+
const detail = await client.request(`/v1/projects/${project.id}`);
|
|
7881
|
+
if (detail.environments.length === 0) {
|
|
7882
|
+
me(
|
|
7883
|
+
`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).`
|
|
7884
|
+
);
|
|
7885
|
+
return null;
|
|
7886
|
+
}
|
|
7887
|
+
if (detail.environments.length === 1) {
|
|
7888
|
+
return detail.environments[0]?.name ?? null;
|
|
7889
|
+
}
|
|
7890
|
+
const value = unwrap(
|
|
7891
|
+
await Ee({
|
|
7892
|
+
message: "Upload to which environment?",
|
|
7893
|
+
options: detail.environments.map((e2) => ({
|
|
7894
|
+
value: e2.name,
|
|
7895
|
+
label: e2.name,
|
|
7896
|
+
hint: e2.tier
|
|
7897
|
+
})),
|
|
7898
|
+
initialValue: detail.environments.find((e2) => e2.name === suggested)?.name
|
|
7899
|
+
})
|
|
7900
|
+
);
|
|
7901
|
+
return value;
|
|
7902
|
+
}
|
|
7903
|
+
function composeKeynvEnv(opts) {
|
|
7904
|
+
const { uploadedAliases, literals, mergeWithExisting } = opts;
|
|
7905
|
+
const lines = [];
|
|
7906
|
+
if (mergeWithExisting !== null) {
|
|
7907
|
+
const trimmed = mergeWithExisting.replace(/\n+$/, "");
|
|
7908
|
+
if (trimmed.length > 0) {
|
|
7909
|
+
lines.push(...trimmed.split("\n"));
|
|
7910
|
+
lines.push("");
|
|
7911
|
+
}
|
|
7912
|
+
lines.push(`# >>> keynv init ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)} >>>`);
|
|
7913
|
+
} else {
|
|
7914
|
+
lines.push("# .keynv.env \u2014 alias references to vault secrets.");
|
|
7915
|
+
lines.push("# Safe to commit: this file contains references, not values.");
|
|
7916
|
+
lines.push("# Auto-loaded by `keynv exec`. See https://keynv.dev/docs/keynv-env");
|
|
7917
|
+
lines.push("");
|
|
7918
|
+
}
|
|
7919
|
+
if (uploadedAliases.size > 0) {
|
|
7920
|
+
lines.push("# Vault-resolved (real values live on the keynv server)");
|
|
7921
|
+
for (const [name, alias2] of uploadedAliases) {
|
|
7922
|
+
lines.push(`${name}=${alias2}`);
|
|
7923
|
+
}
|
|
7924
|
+
}
|
|
7925
|
+
if (literals.length > 0) {
|
|
7926
|
+
if (uploadedAliases.size > 0) lines.push("");
|
|
7927
|
+
lines.push("# Plain literals (passed through unchanged)");
|
|
7928
|
+
for (const e2 of literals) {
|
|
7929
|
+
const value = needsQuoting(e2.value) ? `"${e2.value.replace(/"/g, '\\"')}"` : e2.value;
|
|
7930
|
+
lines.push(`${e2.name}=${value}`);
|
|
7931
|
+
}
|
|
7932
|
+
}
|
|
7933
|
+
if (mergeWithExisting !== null) {
|
|
7934
|
+
lines.push(`# <<< keynv init <<<`);
|
|
7935
|
+
}
|
|
7936
|
+
return lines;
|
|
7937
|
+
}
|
|
7938
|
+
function needsQuoting(value) {
|
|
7939
|
+
return /\s/.test(value) || value.includes("#") || value.length === 0;
|
|
7940
|
+
}
|
|
7941
|
+
function updatePackageJsonScripts(path, originalScripts, selectedNames) {
|
|
7942
|
+
const raw = readFileSync(path, "utf8");
|
|
7943
|
+
const indentMatch = raw.match(/^([ \t]+)"/m);
|
|
7944
|
+
const indent = indentMatch ? indentMatch[1] : " ";
|
|
7945
|
+
const trailingNewline = raw.endsWith("\n");
|
|
7946
|
+
const pkg = JSON.parse(raw);
|
|
7947
|
+
const updated = applyWraps(originalScripts, selectedNames);
|
|
7948
|
+
pkg.scripts = updated;
|
|
7949
|
+
const out = JSON.stringify(pkg, null, indent);
|
|
7950
|
+
writeFileSync(path, trailingNewline ? `${out}
|
|
7951
|
+
` : out);
|
|
7952
|
+
}
|
|
7953
|
+
function ensureGitignoreEntries(path, basenames) {
|
|
7954
|
+
let existing = "";
|
|
7955
|
+
if (existsSync(path)) existing = readFileSync(path, "utf8");
|
|
7956
|
+
const existingLines = new Set(existing.split("\n").map((l) => l.trim()));
|
|
7957
|
+
const toAdd = basenames.filter((n) => !existingLines.has(n));
|
|
7958
|
+
if (toAdd.length === 0) return;
|
|
7959
|
+
const sep = existing.length === 0 || existing.endsWith("\n") ? "" : "\n";
|
|
7960
|
+
const block = ["", "# added by keynv init", ...toAdd, ""].join("\n");
|
|
7961
|
+
writeFileSync(path, `${existing}${sep}${block}`);
|
|
7962
|
+
}
|
|
7963
|
+
var init_init = __esm({
|
|
7964
|
+
"src/ui/flows/init.ts"() {
|
|
7965
|
+
init_dist();
|
|
7966
|
+
init_dist5();
|
|
7967
|
+
init_envFile();
|
|
7968
|
+
init_detect();
|
|
7969
|
+
init_aiContext();
|
|
7970
|
+
init_heuristics();
|
|
7971
|
+
init_scriptWrap();
|
|
7972
|
+
init_cancel();
|
|
7973
|
+
init_pickProject();
|
|
7974
|
+
}
|
|
7975
|
+
});
|
|
7976
|
+
|
|
6928
7977
|
// src/ui/helpers/pickSecret.ts
|
|
6929
7978
|
async function listSecrets(client, projectId2) {
|
|
6930
7979
|
const data = await client.request(
|
|
@@ -7060,14 +8109,14 @@ async function runSecretMenu(client, project, alias2) {
|
|
|
7060
8109
|
async function copyToClipboard(value) {
|
|
7061
8110
|
const platform = process.platform;
|
|
7062
8111
|
const cmd = platform === "darwin" ? ["pbcopy", []] : platform === "win32" ? ["clip", []] : ["xclip", ["-selection", "clipboard"]];
|
|
7063
|
-
return new Promise((
|
|
8112
|
+
return new Promise((resolve3) => {
|
|
7064
8113
|
try {
|
|
7065
8114
|
const child = spawn(cmd[0], cmd[1], { stdio: ["pipe", "ignore", "ignore"] });
|
|
7066
|
-
child.on("error", () =>
|
|
7067
|
-
child.on("exit", (code) =>
|
|
8115
|
+
child.on("error", () => resolve3(false));
|
|
8116
|
+
child.on("exit", (code) => resolve3(code === 0));
|
|
7068
8117
|
child.stdin.end(value);
|
|
7069
8118
|
} catch {
|
|
7070
|
-
|
|
8119
|
+
resolve3(false);
|
|
7071
8120
|
}
|
|
7072
8121
|
});
|
|
7073
8122
|
}
|
|
@@ -7187,24 +8236,24 @@ var require_lib2 = __commonJS({
|
|
|
7187
8236
|
const currentChar = sql.charCodeAt(position);
|
|
7188
8237
|
const nextChar = sql.charCodeAt(position + 1);
|
|
7189
8238
|
if (currentChar === charCode.singleQuote) {
|
|
7190
|
-
for (let
|
|
7191
|
-
if (sql.charCodeAt(
|
|
7192
|
-
|
|
7193
|
-
else if (sql.charCodeAt(
|
|
7194
|
-
return
|
|
8239
|
+
for (let cursor = position + 1; cursor < sql.length; cursor++) {
|
|
8240
|
+
if (sql.charCodeAt(cursor) === charCode.backslash)
|
|
8241
|
+
cursor++;
|
|
8242
|
+
else if (sql.charCodeAt(cursor) === charCode.singleQuote)
|
|
8243
|
+
return cursor + 1;
|
|
7195
8244
|
}
|
|
7196
8245
|
return sql.length;
|
|
7197
8246
|
}
|
|
7198
8247
|
if (currentChar === charCode.backtick) {
|
|
7199
8248
|
const length = sql.length;
|
|
7200
|
-
for (let
|
|
7201
|
-
if (sql.charCodeAt(
|
|
8249
|
+
for (let cursor = position + 1; cursor < length; cursor++) {
|
|
8250
|
+
if (sql.charCodeAt(cursor) !== charCode.backtick)
|
|
7202
8251
|
continue;
|
|
7203
|
-
if (sql.charCodeAt(
|
|
7204
|
-
|
|
8252
|
+
if (sql.charCodeAt(cursor + 1) === charCode.backtick) {
|
|
8253
|
+
cursor++;
|
|
7205
8254
|
continue;
|
|
7206
8255
|
}
|
|
7207
|
-
return
|
|
8256
|
+
return cursor + 1;
|
|
7208
8257
|
}
|
|
7209
8258
|
return length;
|
|
7210
8259
|
}
|
|
@@ -7247,11 +8296,11 @@ var require_lib2 = __commonJS({
|
|
|
7247
8296
|
if (lower === 115 && matchesWord(sql, position, "set", length))
|
|
7248
8297
|
return position + 3;
|
|
7249
8298
|
if (lower === 107 && matchesWord(sql, position, "key", length)) {
|
|
7250
|
-
let
|
|
7251
|
-
while (
|
|
7252
|
-
|
|
7253
|
-
if (matchesWord(sql,
|
|
7254
|
-
return
|
|
8299
|
+
let cursor = position + 3;
|
|
8300
|
+
while (cursor < length && isWhitespace(sql.charCodeAt(cursor)))
|
|
8301
|
+
cursor++;
|
|
8302
|
+
if (matchesWord(sql, cursor, "update", length))
|
|
8303
|
+
return cursor + 6;
|
|
7255
8304
|
}
|
|
7256
8305
|
}
|
|
7257
8306
|
return -1;
|
|
@@ -23813,7 +24862,7 @@ var require_named_placeholders = __commonJS({
|
|
|
23813
24862
|
}
|
|
23814
24863
|
return s;
|
|
23815
24864
|
}
|
|
23816
|
-
function
|
|
24865
|
+
function join6(tree) {
|
|
23817
24866
|
if (tree.length === 1) {
|
|
23818
24867
|
return tree;
|
|
23819
24868
|
}
|
|
@@ -23839,7 +24888,7 @@ var require_named_placeholders = __commonJS({
|
|
|
23839
24888
|
if (cache2 && (tree = cache2.get(query))) {
|
|
23840
24889
|
return toArrayParams(tree, paramsObj);
|
|
23841
24890
|
}
|
|
23842
|
-
tree =
|
|
24891
|
+
tree = join6(parse(query));
|
|
23843
24892
|
if (cache2) {
|
|
23844
24893
|
cache2.set(query, tree);
|
|
23845
24894
|
}
|
|
@@ -23995,11 +25044,11 @@ var require_connection = __commonJS({
|
|
|
23995
25044
|
const config = this.config;
|
|
23996
25045
|
tracePromise(
|
|
23997
25046
|
connectChannel,
|
|
23998
|
-
() => new Promise((
|
|
25047
|
+
() => new Promise((resolve3, reject) => {
|
|
23999
25048
|
let onConnect, onError;
|
|
24000
25049
|
onConnect = (param) => {
|
|
24001
25050
|
this.removeListener("error", onError);
|
|
24002
|
-
|
|
25051
|
+
resolve3(param);
|
|
24003
25052
|
};
|
|
24004
25053
|
onError = (err) => {
|
|
24005
25054
|
this.removeListener("connect", onConnect);
|
|
@@ -24424,9 +25473,9 @@ var require_connection = __commonJS({
|
|
|
24424
25473
|
} else if (shouldTrace(queryChannel)) {
|
|
24425
25474
|
tracePromise(
|
|
24426
25475
|
queryChannel,
|
|
24427
|
-
() => new Promise((
|
|
25476
|
+
() => new Promise((resolve3, reject) => {
|
|
24428
25477
|
cmdQuery.once("error", reject);
|
|
24429
|
-
cmdQuery.once("end", () =>
|
|
25478
|
+
cmdQuery.once("end", () => resolve3());
|
|
24430
25479
|
this.addCommand(cmdQuery);
|
|
24431
25480
|
}),
|
|
24432
25481
|
() => {
|
|
@@ -24573,12 +25622,12 @@ var require_connection = __commonJS({
|
|
|
24573
25622
|
} else if (shouldTrace(executeChannel)) {
|
|
24574
25623
|
tracePromise(
|
|
24575
25624
|
executeChannel,
|
|
24576
|
-
() => new Promise((
|
|
25625
|
+
() => new Promise((resolve3, reject) => {
|
|
24577
25626
|
prepareAndExecute((err) => {
|
|
24578
25627
|
executeCommand.emit("error", err);
|
|
24579
25628
|
});
|
|
24580
25629
|
executeCommand.once("error", reject);
|
|
24581
|
-
executeCommand.once("end", () =>
|
|
25630
|
+
executeCommand.once("end", () => resolve3());
|
|
24582
25631
|
}),
|
|
24583
25632
|
() => {
|
|
24584
25633
|
const server = getServerContext(this.config);
|
|
@@ -24843,13 +25892,13 @@ var require_capture_local_err = __commonJS({
|
|
|
24843
25892
|
var require_make_done_cb = __commonJS({
|
|
24844
25893
|
"../../node_modules/.pnpm/mysql2@3.22.3_@types+node@24.12.3/node_modules/mysql2/lib/promise/make_done_cb.js"(exports, module) {
|
|
24845
25894
|
var { applyCapturedStack } = require_capture_local_err();
|
|
24846
|
-
function makeDoneCb(
|
|
25895
|
+
function makeDoneCb(resolve3, reject, stackHolder) {
|
|
24847
25896
|
return function(err, rows, fields) {
|
|
24848
25897
|
if (err) {
|
|
24849
25898
|
applyCapturedStack(err, stackHolder);
|
|
24850
25899
|
reject(err);
|
|
24851
25900
|
} else {
|
|
24852
|
-
|
|
25901
|
+
resolve3([rows, fields]);
|
|
24853
25902
|
}
|
|
24854
25903
|
};
|
|
24855
25904
|
}
|
|
@@ -24872,8 +25921,8 @@ var require_prepared_statement_info = __commonJS({
|
|
|
24872
25921
|
const stackHolder = captureStackHolder(
|
|
24873
25922
|
_PromisePreparedStatementInfo.prototype.execute
|
|
24874
25923
|
);
|
|
24875
|
-
return new this.Promise((
|
|
24876
|
-
const done = makeDoneCb(
|
|
25924
|
+
return new this.Promise((resolve3, reject) => {
|
|
25925
|
+
const done = makeDoneCb(resolve3, reject, stackHolder);
|
|
24877
25926
|
if (parameters) {
|
|
24878
25927
|
s.execute(parameters, done);
|
|
24879
25928
|
} else {
|
|
@@ -24882,9 +25931,9 @@ var require_prepared_statement_info = __commonJS({
|
|
|
24882
25931
|
});
|
|
24883
25932
|
}
|
|
24884
25933
|
close() {
|
|
24885
|
-
return new this.Promise((
|
|
25934
|
+
return new this.Promise((resolve3) => {
|
|
24886
25935
|
this.statement.close();
|
|
24887
|
-
|
|
25936
|
+
resolve3();
|
|
24888
25937
|
});
|
|
24889
25938
|
}
|
|
24890
25939
|
};
|
|
@@ -24955,8 +26004,8 @@ var require_connection2 = __commonJS({
|
|
|
24955
26004
|
"Callback function is not available with promise clients."
|
|
24956
26005
|
);
|
|
24957
26006
|
}
|
|
24958
|
-
return new this.Promise((
|
|
24959
|
-
const done = makeDoneCb(
|
|
26007
|
+
return new this.Promise((resolve3, reject) => {
|
|
26008
|
+
const done = makeDoneCb(resolve3, reject, stackHolder);
|
|
24960
26009
|
if (params !== void 0) {
|
|
24961
26010
|
c2.query(query, params, done);
|
|
24962
26011
|
} else {
|
|
@@ -24972,8 +26021,8 @@ var require_connection2 = __commonJS({
|
|
|
24972
26021
|
"Callback function is not available with promise clients."
|
|
24973
26022
|
);
|
|
24974
26023
|
}
|
|
24975
|
-
return new this.Promise((
|
|
24976
|
-
const done = makeDoneCb(
|
|
26024
|
+
return new this.Promise((resolve3, reject) => {
|
|
26025
|
+
const done = makeDoneCb(resolve3, reject, stackHolder);
|
|
24977
26026
|
if (params !== void 0) {
|
|
24978
26027
|
c2.execute(query, params, done);
|
|
24979
26028
|
} else {
|
|
@@ -24982,8 +26031,8 @@ var require_connection2 = __commonJS({
|
|
|
24982
26031
|
});
|
|
24983
26032
|
}
|
|
24984
26033
|
end() {
|
|
24985
|
-
return new this.Promise((
|
|
24986
|
-
this.connection.end(
|
|
26034
|
+
return new this.Promise((resolve3) => {
|
|
26035
|
+
this.connection.end(resolve3);
|
|
24987
26036
|
});
|
|
24988
26037
|
}
|
|
24989
26038
|
async [Symbol.asyncDispose]() {
|
|
@@ -24996,16 +26045,16 @@ var require_connection2 = __commonJS({
|
|
|
24996
26045
|
const stackHolder = captureStackHolder(
|
|
24997
26046
|
_PromiseConnection.prototype.beginTransaction
|
|
24998
26047
|
);
|
|
24999
|
-
return new this.Promise((
|
|
25000
|
-
const done = makeDoneCb(
|
|
26048
|
+
return new this.Promise((resolve3, reject) => {
|
|
26049
|
+
const done = makeDoneCb(resolve3, reject, stackHolder);
|
|
25001
26050
|
c2.beginTransaction(done);
|
|
25002
26051
|
});
|
|
25003
26052
|
}
|
|
25004
26053
|
commit() {
|
|
25005
26054
|
const c2 = this.connection;
|
|
25006
26055
|
const stackHolder = captureStackHolder(_PromiseConnection.prototype.commit);
|
|
25007
|
-
return new this.Promise((
|
|
25008
|
-
const done = makeDoneCb(
|
|
26056
|
+
return new this.Promise((resolve3, reject) => {
|
|
26057
|
+
const done = makeDoneCb(resolve3, reject, stackHolder);
|
|
25009
26058
|
c2.commit(done);
|
|
25010
26059
|
});
|
|
25011
26060
|
}
|
|
@@ -25014,21 +26063,21 @@ var require_connection2 = __commonJS({
|
|
|
25014
26063
|
const stackHolder = captureStackHolder(
|
|
25015
26064
|
_PromiseConnection.prototype.rollback
|
|
25016
26065
|
);
|
|
25017
|
-
return new this.Promise((
|
|
25018
|
-
const done = makeDoneCb(
|
|
26066
|
+
return new this.Promise((resolve3, reject) => {
|
|
26067
|
+
const done = makeDoneCb(resolve3, reject, stackHolder);
|
|
25019
26068
|
c2.rollback(done);
|
|
25020
26069
|
});
|
|
25021
26070
|
}
|
|
25022
26071
|
ping() {
|
|
25023
26072
|
const c2 = this.connection;
|
|
25024
26073
|
const stackHolder = captureStackHolder(_PromiseConnection.prototype.ping);
|
|
25025
|
-
return new this.Promise((
|
|
26074
|
+
return new this.Promise((resolve3, reject) => {
|
|
25026
26075
|
c2.ping((err) => {
|
|
25027
26076
|
if (err) {
|
|
25028
26077
|
applyCapturedStack(err, stackHolder);
|
|
25029
26078
|
reject(err);
|
|
25030
26079
|
} else {
|
|
25031
|
-
|
|
26080
|
+
resolve3(true);
|
|
25032
26081
|
}
|
|
25033
26082
|
});
|
|
25034
26083
|
});
|
|
@@ -25036,13 +26085,13 @@ var require_connection2 = __commonJS({
|
|
|
25036
26085
|
reset() {
|
|
25037
26086
|
const c2 = this.connection;
|
|
25038
26087
|
const stackHolder = captureStackHolder(_PromiseConnection.prototype.reset);
|
|
25039
|
-
return new this.Promise((
|
|
26088
|
+
return new this.Promise((resolve3, reject) => {
|
|
25040
26089
|
c2.reset((err) => {
|
|
25041
26090
|
if (err) {
|
|
25042
26091
|
applyCapturedStack(err, stackHolder);
|
|
25043
26092
|
reject(err);
|
|
25044
26093
|
} else {
|
|
25045
|
-
|
|
26094
|
+
resolve3();
|
|
25046
26095
|
}
|
|
25047
26096
|
});
|
|
25048
26097
|
});
|
|
@@ -25050,13 +26099,13 @@ var require_connection2 = __commonJS({
|
|
|
25050
26099
|
connect() {
|
|
25051
26100
|
const c2 = this.connection;
|
|
25052
26101
|
const stackHolder = captureStackHolder(_PromiseConnection.prototype.connect);
|
|
25053
|
-
return new this.Promise((
|
|
26102
|
+
return new this.Promise((resolve3, reject) => {
|
|
25054
26103
|
c2.connect((err, param) => {
|
|
25055
26104
|
if (err) {
|
|
25056
26105
|
applyCapturedStack(err, stackHolder);
|
|
25057
26106
|
reject(err);
|
|
25058
26107
|
} else {
|
|
25059
|
-
|
|
26108
|
+
resolve3(param);
|
|
25060
26109
|
}
|
|
25061
26110
|
});
|
|
25062
26111
|
});
|
|
@@ -25065,7 +26114,7 @@ var require_connection2 = __commonJS({
|
|
|
25065
26114
|
const c2 = this.connection;
|
|
25066
26115
|
const promiseImpl = this.Promise;
|
|
25067
26116
|
const stackHolder = captureStackHolder(_PromiseConnection.prototype.prepare);
|
|
25068
|
-
return new this.Promise((
|
|
26117
|
+
return new this.Promise((resolve3, reject) => {
|
|
25069
26118
|
c2.prepare(options, (err, statement) => {
|
|
25070
26119
|
if (err) {
|
|
25071
26120
|
applyCapturedStack(err, stackHolder);
|
|
@@ -25075,7 +26124,7 @@ var require_connection2 = __commonJS({
|
|
|
25075
26124
|
statement,
|
|
25076
26125
|
promiseImpl
|
|
25077
26126
|
);
|
|
25078
|
-
|
|
26127
|
+
resolve3(wrappedStatement);
|
|
25079
26128
|
}
|
|
25080
26129
|
});
|
|
25081
26130
|
});
|
|
@@ -25085,13 +26134,13 @@ var require_connection2 = __commonJS({
|
|
|
25085
26134
|
const stackHolder = captureStackHolder(
|
|
25086
26135
|
_PromiseConnection.prototype.changeUser
|
|
25087
26136
|
);
|
|
25088
|
-
return new this.Promise((
|
|
26137
|
+
return new this.Promise((resolve3, reject) => {
|
|
25089
26138
|
c2.changeUser(options, (err) => {
|
|
25090
26139
|
if (err) {
|
|
25091
26140
|
applyCapturedStack(err, stackHolder);
|
|
25092
26141
|
reject(err);
|
|
25093
26142
|
} else {
|
|
25094
|
-
|
|
26143
|
+
resolve3();
|
|
25095
26144
|
}
|
|
25096
26145
|
});
|
|
25097
26146
|
});
|
|
@@ -25553,12 +26602,12 @@ var require_pool2 = __commonJS({
|
|
|
25553
26602
|
}
|
|
25554
26603
|
getConnection() {
|
|
25555
26604
|
const corePool = this.pool;
|
|
25556
|
-
return new this.Promise((
|
|
26605
|
+
return new this.Promise((resolve3, reject) => {
|
|
25557
26606
|
corePool.getConnection((err, coreConnection) => {
|
|
25558
26607
|
if (err) {
|
|
25559
26608
|
reject(err);
|
|
25560
26609
|
} else {
|
|
25561
|
-
|
|
26610
|
+
resolve3(new PromisePoolConnection(coreConnection, this.Promise));
|
|
25562
26611
|
}
|
|
25563
26612
|
});
|
|
25564
26613
|
});
|
|
@@ -25574,8 +26623,8 @@ var require_pool2 = __commonJS({
|
|
|
25574
26623
|
"Callback function is not available with promise clients."
|
|
25575
26624
|
);
|
|
25576
26625
|
}
|
|
25577
|
-
return new this.Promise((
|
|
25578
|
-
const done = makeDoneCb(
|
|
26626
|
+
return new this.Promise((resolve3, reject) => {
|
|
26627
|
+
const done = makeDoneCb(resolve3, reject, stackHolder);
|
|
25579
26628
|
if (args !== void 0) {
|
|
25580
26629
|
corePool.query(sql, args, done);
|
|
25581
26630
|
} else {
|
|
@@ -25591,8 +26640,8 @@ var require_pool2 = __commonJS({
|
|
|
25591
26640
|
"Callback function is not available with promise clients."
|
|
25592
26641
|
);
|
|
25593
26642
|
}
|
|
25594
|
-
return new this.Promise((
|
|
25595
|
-
const done = makeDoneCb(
|
|
26643
|
+
return new this.Promise((resolve3, reject) => {
|
|
26644
|
+
const done = makeDoneCb(resolve3, reject, stackHolder);
|
|
25596
26645
|
if (args) {
|
|
25597
26646
|
corePool.execute(sql, args, done);
|
|
25598
26647
|
} else {
|
|
@@ -25603,13 +26652,13 @@ var require_pool2 = __commonJS({
|
|
|
25603
26652
|
end() {
|
|
25604
26653
|
const corePool = this.pool;
|
|
25605
26654
|
const stackHolder = captureStackHolder(_PromisePool.prototype.end);
|
|
25606
|
-
return new this.Promise((
|
|
26655
|
+
return new this.Promise((resolve3, reject) => {
|
|
25607
26656
|
corePool.end((err) => {
|
|
25608
26657
|
if (err) {
|
|
25609
26658
|
applyCapturedStack(err, stackHolder);
|
|
25610
26659
|
reject(err);
|
|
25611
26660
|
} else {
|
|
25612
|
-
|
|
26661
|
+
resolve3();
|
|
25613
26662
|
}
|
|
25614
26663
|
});
|
|
25615
26664
|
});
|
|
@@ -26034,12 +27083,12 @@ var require_pool_cluster2 = __commonJS({
|
|
|
26034
27083
|
}
|
|
26035
27084
|
getConnection() {
|
|
26036
27085
|
const corePoolNamespace = this.poolNamespace;
|
|
26037
|
-
return new this.Promise((
|
|
27086
|
+
return new this.Promise((resolve3, reject) => {
|
|
26038
27087
|
corePoolNamespace.getConnection((err, coreConnection) => {
|
|
26039
27088
|
if (err) {
|
|
26040
27089
|
reject(err);
|
|
26041
27090
|
} else {
|
|
26042
|
-
|
|
27091
|
+
resolve3(new PromisePoolConnection(coreConnection, this.Promise));
|
|
26043
27092
|
}
|
|
26044
27093
|
});
|
|
26045
27094
|
});
|
|
@@ -26054,8 +27103,8 @@ var require_pool_cluster2 = __commonJS({
|
|
|
26054
27103
|
"Callback function is not available with promise clients."
|
|
26055
27104
|
);
|
|
26056
27105
|
}
|
|
26057
|
-
return new this.Promise((
|
|
26058
|
-
const done = makeDoneCb(
|
|
27106
|
+
return new this.Promise((resolve3, reject) => {
|
|
27107
|
+
const done = makeDoneCb(resolve3, reject, stackHolder);
|
|
26059
27108
|
corePoolNamespace.query(sql, values, done);
|
|
26060
27109
|
});
|
|
26061
27110
|
}
|
|
@@ -26069,8 +27118,8 @@ var require_pool_cluster2 = __commonJS({
|
|
|
26069
27118
|
"Callback function is not available with promise clients."
|
|
26070
27119
|
);
|
|
26071
27120
|
}
|
|
26072
|
-
return new this.Promise((
|
|
26073
|
-
const done = makeDoneCb(
|
|
27121
|
+
return new this.Promise((resolve3, reject) => {
|
|
27122
|
+
const done = makeDoneCb(resolve3, reject, stackHolder);
|
|
26074
27123
|
corePoolNamespace.execute(sql, values, done);
|
|
26075
27124
|
});
|
|
26076
27125
|
}
|
|
@@ -26108,9 +27157,9 @@ var require_promise = __commonJS({
|
|
|
26108
27157
|
"no Promise implementation available.Use promise-enabled node version or pass userland Promise implementation as parameter, for example: { Promise: require('bluebird') }"
|
|
26109
27158
|
);
|
|
26110
27159
|
}
|
|
26111
|
-
return new thePromise((
|
|
27160
|
+
return new thePromise((resolve3, reject) => {
|
|
26112
27161
|
coreConnection.once("connect", () => {
|
|
26113
|
-
|
|
27162
|
+
resolve3(new PromiseConnection(coreConnection, thePromise));
|
|
26114
27163
|
});
|
|
26115
27164
|
coreConnection.once("error", (err) => {
|
|
26116
27165
|
applyCapturedStack(err, stackHolder);
|
|
@@ -26137,7 +27186,7 @@ var require_promise = __commonJS({
|
|
|
26137
27186
|
}
|
|
26138
27187
|
getConnection(pattern, selector) {
|
|
26139
27188
|
const corePoolCluster = this.poolCluster;
|
|
26140
|
-
return new this.Promise((
|
|
27189
|
+
return new this.Promise((resolve3, reject) => {
|
|
26141
27190
|
corePoolCluster.getConnection(
|
|
26142
27191
|
pattern,
|
|
26143
27192
|
selector,
|
|
@@ -26145,7 +27194,7 @@ var require_promise = __commonJS({
|
|
|
26145
27194
|
if (err) {
|
|
26146
27195
|
reject(err);
|
|
26147
27196
|
} else {
|
|
26148
|
-
|
|
27197
|
+
resolve3(new PromisePoolConnection(coreConnection, this.Promise));
|
|
26149
27198
|
}
|
|
26150
27199
|
}
|
|
26151
27200
|
);
|
|
@@ -26159,8 +27208,8 @@ var require_promise = __commonJS({
|
|
|
26159
27208
|
"Callback function is not available with promise clients."
|
|
26160
27209
|
);
|
|
26161
27210
|
}
|
|
26162
|
-
return new this.Promise((
|
|
26163
|
-
const done = makeDoneCb(
|
|
27211
|
+
return new this.Promise((resolve3, reject) => {
|
|
27212
|
+
const done = makeDoneCb(resolve3, reject, stackHolder);
|
|
26164
27213
|
corePoolCluster.query(sql, args, done);
|
|
26165
27214
|
});
|
|
26166
27215
|
}
|
|
@@ -26174,8 +27223,8 @@ var require_promise = __commonJS({
|
|
|
26174
27223
|
"Callback function is not available with promise clients."
|
|
26175
27224
|
);
|
|
26176
27225
|
}
|
|
26177
|
-
return new this.Promise((
|
|
26178
|
-
const done = makeDoneCb(
|
|
27226
|
+
return new this.Promise((resolve3, reject) => {
|
|
27227
|
+
const done = makeDoneCb(resolve3, reject, stackHolder);
|
|
26179
27228
|
corePoolCluster.execute(sql, args, done);
|
|
26180
27229
|
});
|
|
26181
27230
|
}
|
|
@@ -26188,13 +27237,13 @@ var require_promise = __commonJS({
|
|
|
26188
27237
|
end() {
|
|
26189
27238
|
const corePoolCluster = this.poolCluster;
|
|
26190
27239
|
const stackHolder = captureStackHolder(_PromisePoolCluster.prototype.end);
|
|
26191
|
-
return new this.Promise((
|
|
27240
|
+
return new this.Promise((resolve3, reject) => {
|
|
26192
27241
|
corePoolCluster.end((err) => {
|
|
26193
27242
|
if (err) {
|
|
26194
27243
|
applyCapturedStack(err, stackHolder);
|
|
26195
27244
|
reject(err);
|
|
26196
27245
|
} else {
|
|
26197
|
-
|
|
27246
|
+
resolve3();
|
|
26198
27247
|
}
|
|
26199
27248
|
});
|
|
26200
27249
|
});
|
|
@@ -29269,7 +30318,7 @@ var require_dist = __commonJS({
|
|
|
29269
30318
|
function parse(stream, callback) {
|
|
29270
30319
|
const parser = new parser_1.Parser();
|
|
29271
30320
|
stream.on("data", (buffer) => parser.parse(buffer, callback));
|
|
29272
|
-
return new Promise((
|
|
30321
|
+
return new Promise((resolve3) => stream.on("end", () => resolve3()));
|
|
29273
30322
|
}
|
|
29274
30323
|
exports.parse = parse;
|
|
29275
30324
|
}
|
|
@@ -29994,12 +31043,12 @@ var require_client2 = __commonJS({
|
|
|
29994
31043
|
this._connect(callback);
|
|
29995
31044
|
return;
|
|
29996
31045
|
}
|
|
29997
|
-
return new this._Promise((
|
|
31046
|
+
return new this._Promise((resolve3, reject) => {
|
|
29998
31047
|
this._connect((error) => {
|
|
29999
31048
|
if (error) {
|
|
30000
31049
|
reject(error);
|
|
30001
31050
|
} else {
|
|
30002
|
-
|
|
31051
|
+
resolve3(this);
|
|
30003
31052
|
}
|
|
30004
31053
|
});
|
|
30005
31054
|
});
|
|
@@ -30345,8 +31394,8 @@ var require_client2 = __commonJS({
|
|
|
30345
31394
|
readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
|
|
30346
31395
|
query = new Query2(config, values, callback);
|
|
30347
31396
|
if (!query.callback) {
|
|
30348
|
-
result = new this._Promise((
|
|
30349
|
-
query.callback = (err, res) => err ? reject(err) :
|
|
31397
|
+
result = new this._Promise((resolve3, reject) => {
|
|
31398
|
+
query.callback = (err, res) => err ? reject(err) : resolve3(res);
|
|
30350
31399
|
}).catch((err) => {
|
|
30351
31400
|
Error.captureStackTrace(err);
|
|
30352
31401
|
throw err;
|
|
@@ -30423,8 +31472,8 @@ var require_client2 = __commonJS({
|
|
|
30423
31472
|
if (cb) {
|
|
30424
31473
|
this.connection.once("end", cb);
|
|
30425
31474
|
} else {
|
|
30426
|
-
return new this._Promise((
|
|
30427
|
-
this.connection.once("end",
|
|
31475
|
+
return new this._Promise((resolve3) => {
|
|
31476
|
+
this.connection.once("end", resolve3);
|
|
30428
31477
|
});
|
|
30429
31478
|
}
|
|
30430
31479
|
}
|
|
@@ -30472,8 +31521,8 @@ var require_pg_pool = __commonJS({
|
|
|
30472
31521
|
const cb = function(err, client) {
|
|
30473
31522
|
err ? rej(err) : res(client);
|
|
30474
31523
|
};
|
|
30475
|
-
const result = new Promise2(function(
|
|
30476
|
-
res =
|
|
31524
|
+
const result = new Promise2(function(resolve3, reject) {
|
|
31525
|
+
res = resolve3;
|
|
30477
31526
|
rej = reject;
|
|
30478
31527
|
}).catch((err) => {
|
|
30479
31528
|
Error.captureStackTrace(err);
|
|
@@ -30534,7 +31583,7 @@ var require_pg_pool = __commonJS({
|
|
|
30534
31583
|
if (typeof Promise2.try === "function") {
|
|
30535
31584
|
return Promise2.try(f);
|
|
30536
31585
|
}
|
|
30537
|
-
return new Promise2((
|
|
31586
|
+
return new Promise2((resolve3) => resolve3(f()));
|
|
30538
31587
|
}
|
|
30539
31588
|
_isFull() {
|
|
30540
31589
|
return this._clients.length >= this.options.max;
|
|
@@ -30926,8 +31975,8 @@ var require_query4 = __commonJS({
|
|
|
30926
31975
|
NativeQuery.prototype._getPromise = function() {
|
|
30927
31976
|
if (this._promise) return this._promise;
|
|
30928
31977
|
this._promise = new Promise(
|
|
30929
|
-
function(
|
|
30930
|
-
this._once("end",
|
|
31978
|
+
function(resolve3, reject) {
|
|
31979
|
+
this._once("end", resolve3);
|
|
30931
31980
|
this._once("error", reject);
|
|
30932
31981
|
}.bind(this)
|
|
30933
31982
|
);
|
|
@@ -31104,12 +32153,12 @@ var require_client3 = __commonJS({
|
|
|
31104
32153
|
this._connect(callback);
|
|
31105
32154
|
return;
|
|
31106
32155
|
}
|
|
31107
|
-
return new this._Promise((
|
|
32156
|
+
return new this._Promise((resolve3, reject) => {
|
|
31108
32157
|
this._connect((error) => {
|
|
31109
32158
|
if (error) {
|
|
31110
32159
|
reject(error);
|
|
31111
32160
|
} else {
|
|
31112
|
-
|
|
32161
|
+
resolve3(this);
|
|
31113
32162
|
}
|
|
31114
32163
|
});
|
|
31115
32164
|
});
|
|
@@ -31133,8 +32182,8 @@ var require_client3 = __commonJS({
|
|
|
31133
32182
|
query = new NativeQuery(config, values, callback);
|
|
31134
32183
|
if (!query.callback) {
|
|
31135
32184
|
let resolveOut, rejectOut;
|
|
31136
|
-
result = new this._Promise((
|
|
31137
|
-
resolveOut =
|
|
32185
|
+
result = new this._Promise((resolve3, reject) => {
|
|
32186
|
+
resolveOut = resolve3;
|
|
31138
32187
|
rejectOut = reject;
|
|
31139
32188
|
}).catch((err) => {
|
|
31140
32189
|
Error.captureStackTrace(err);
|
|
@@ -31194,8 +32243,8 @@ var require_client3 = __commonJS({
|
|
|
31194
32243
|
}
|
|
31195
32244
|
let result;
|
|
31196
32245
|
if (!cb) {
|
|
31197
|
-
result = new this._Promise(function(
|
|
31198
|
-
cb = (err) => err ? reject(err) :
|
|
32246
|
+
result = new this._Promise(function(resolve3, reject) {
|
|
32247
|
+
cb = (err) => err ? reject(err) : resolve3();
|
|
31199
32248
|
});
|
|
31200
32249
|
}
|
|
31201
32250
|
this.native.end(function() {
|
|
@@ -36302,7 +37351,7 @@ var require_Command = __commonJS({
|
|
|
36302
37351
|
}
|
|
36303
37352
|
}
|
|
36304
37353
|
initPromise() {
|
|
36305
|
-
const promise = new Promise((
|
|
37354
|
+
const promise = new Promise((resolve3, reject) => {
|
|
36306
37355
|
if (!this.transformed) {
|
|
36307
37356
|
this.transformed = true;
|
|
36308
37357
|
const transformer = _Command._transformer.argument[this.name];
|
|
@@ -36311,7 +37360,7 @@ var require_Command = __commonJS({
|
|
|
36311
37360
|
}
|
|
36312
37361
|
this.stringifyArguments();
|
|
36313
37362
|
}
|
|
36314
|
-
this.resolve = this._convertValue(
|
|
37363
|
+
this.resolve = this._convertValue(resolve3);
|
|
36315
37364
|
this.reject = (err) => {
|
|
36316
37365
|
this._clearTimers();
|
|
36317
37366
|
if (this.errorStack) {
|
|
@@ -36344,11 +37393,11 @@ var require_Command = __commonJS({
|
|
|
36344
37393
|
/**
|
|
36345
37394
|
* Convert the value from buffer to the target encoding.
|
|
36346
37395
|
*/
|
|
36347
|
-
_convertValue(
|
|
37396
|
+
_convertValue(resolve3) {
|
|
36348
37397
|
return (value) => {
|
|
36349
37398
|
try {
|
|
36350
37399
|
this._clearTimers();
|
|
36351
|
-
|
|
37400
|
+
resolve3(this.transformReply(value));
|
|
36352
37401
|
this.isResolved = true;
|
|
36353
37402
|
} catch (err) {
|
|
36354
37403
|
this.reject(err);
|
|
@@ -36626,13 +37675,13 @@ var require_autoPipelining = __commonJS({
|
|
|
36626
37675
|
if (client.isCluster && !client.slots.length) {
|
|
36627
37676
|
if (client.status === "wait")
|
|
36628
37677
|
client.connect().catch(lodash_1.noop);
|
|
36629
|
-
return (0, standard_as_callback_1.default)(new Promise(function(
|
|
37678
|
+
return (0, standard_as_callback_1.default)(new Promise(function(resolve3, reject) {
|
|
36630
37679
|
client.delayUntilReady((err) => {
|
|
36631
37680
|
if (err) {
|
|
36632
37681
|
reject(err);
|
|
36633
37682
|
return;
|
|
36634
37683
|
}
|
|
36635
|
-
executeWithAutoPipelining(client, functionName, commandName, args, null).then(
|
|
37684
|
+
executeWithAutoPipelining(client, functionName, commandName, args, null).then(resolve3, reject);
|
|
36636
37685
|
});
|
|
36637
37686
|
}), callback);
|
|
36638
37687
|
}
|
|
@@ -36653,13 +37702,13 @@ var require_autoPipelining = __commonJS({
|
|
|
36653
37702
|
pipeline[exports.kExec] = true;
|
|
36654
37703
|
setImmediate(executeAutoPipeline, client, slotKey);
|
|
36655
37704
|
}
|
|
36656
|
-
const autoPipelinePromise = new Promise(function(
|
|
37705
|
+
const autoPipelinePromise = new Promise(function(resolve3, reject) {
|
|
36657
37706
|
pipeline[exports.kCallbacks].push(function(err, value) {
|
|
36658
37707
|
if (err) {
|
|
36659
37708
|
reject(err);
|
|
36660
37709
|
return;
|
|
36661
37710
|
}
|
|
36662
|
-
|
|
37711
|
+
resolve3(value);
|
|
36663
37712
|
});
|
|
36664
37713
|
if (functionName === "call") {
|
|
36665
37714
|
args.unshift(commandName);
|
|
@@ -36894,8 +37943,8 @@ var require_Pipeline = __commonJS({
|
|
|
36894
37943
|
this[name] = redis[name];
|
|
36895
37944
|
this[name + "Buffer"] = redis[name + "Buffer"];
|
|
36896
37945
|
});
|
|
36897
|
-
this.promise = new Promise((
|
|
36898
|
-
this.resolve =
|
|
37946
|
+
this.promise = new Promise((resolve3, reject) => {
|
|
37947
|
+
this.resolve = resolve3;
|
|
36899
37948
|
this.reject = reject;
|
|
36900
37949
|
});
|
|
36901
37950
|
const _this = this;
|
|
@@ -37195,13 +38244,13 @@ var require_transaction = __commonJS({
|
|
|
37195
38244
|
if (this.isCluster && !this.redis.slots.length) {
|
|
37196
38245
|
if (this.redis.status === "wait")
|
|
37197
38246
|
this.redis.connect().catch(utils_1.noop);
|
|
37198
|
-
return (0, standard_as_callback_1.default)(new Promise((
|
|
38247
|
+
return (0, standard_as_callback_1.default)(new Promise((resolve3, reject) => {
|
|
37199
38248
|
this.redis.delayUntilReady((err) => {
|
|
37200
38249
|
if (err) {
|
|
37201
38250
|
reject(err);
|
|
37202
38251
|
return;
|
|
37203
38252
|
}
|
|
37204
|
-
this.exec(pipeline).then(
|
|
38253
|
+
this.exec(pipeline).then(resolve3, reject);
|
|
37205
38254
|
});
|
|
37206
38255
|
}), callback);
|
|
37207
38256
|
}
|
|
@@ -38330,7 +39379,7 @@ var require_cluster = __commonJS({
|
|
|
38330
39379
|
* Connect to a cluster
|
|
38331
39380
|
*/
|
|
38332
39381
|
connect() {
|
|
38333
|
-
return new Promise((
|
|
39382
|
+
return new Promise((resolve3, reject) => {
|
|
38334
39383
|
if (this.status === "connecting" || this.status === "connect" || this.status === "ready") {
|
|
38335
39384
|
reject(new Error("Redis is already connecting/connected"));
|
|
38336
39385
|
return;
|
|
@@ -38359,7 +39408,7 @@ var require_cluster = __commonJS({
|
|
|
38359
39408
|
this.retryAttempts = 0;
|
|
38360
39409
|
this.executeOfflineCommands();
|
|
38361
39410
|
this.resetNodesRefreshInterval();
|
|
38362
|
-
|
|
39411
|
+
resolve3();
|
|
38363
39412
|
};
|
|
38364
39413
|
let closeListener = void 0;
|
|
38365
39414
|
const refreshListener = () => {
|
|
@@ -38969,7 +40018,7 @@ var require_cluster = __commonJS({
|
|
|
38969
40018
|
});
|
|
38970
40019
|
}
|
|
38971
40020
|
resolveSrv(hostname) {
|
|
38972
|
-
return new Promise((
|
|
40021
|
+
return new Promise((resolve3, reject) => {
|
|
38973
40022
|
this.options.resolveSrv(hostname, (err, records) => {
|
|
38974
40023
|
if (err) {
|
|
38975
40024
|
return reject(err);
|
|
@@ -38983,7 +40032,7 @@ var require_cluster = __commonJS({
|
|
|
38983
40032
|
if (!group.records.length) {
|
|
38984
40033
|
sortedKeys.shift();
|
|
38985
40034
|
}
|
|
38986
|
-
self2.dnsLookup(record.name).then((host) =>
|
|
40035
|
+
self2.dnsLookup(record.name).then((host) => resolve3({
|
|
38987
40036
|
host,
|
|
38988
40037
|
port: record.port
|
|
38989
40038
|
}), tryFirstOne);
|
|
@@ -38993,14 +40042,14 @@ var require_cluster = __commonJS({
|
|
|
38993
40042
|
});
|
|
38994
40043
|
}
|
|
38995
40044
|
dnsLookup(hostname) {
|
|
38996
|
-
return new Promise((
|
|
40045
|
+
return new Promise((resolve3, reject) => {
|
|
38997
40046
|
this.options.dnsLookup(hostname, (err, address) => {
|
|
38998
40047
|
if (err) {
|
|
38999
40048
|
debug2("failed to resolve hostname %s to IP: %s", hostname, err.message);
|
|
39000
40049
|
reject(err);
|
|
39001
40050
|
} else {
|
|
39002
40051
|
debug2("resolved hostname %s to IP %s", hostname, address);
|
|
39003
|
-
|
|
40052
|
+
resolve3(address);
|
|
39004
40053
|
}
|
|
39005
40054
|
});
|
|
39006
40055
|
});
|
|
@@ -39155,7 +40204,7 @@ var require_StandaloneConnector = __commonJS({
|
|
|
39155
40204
|
if (options.tls) {
|
|
39156
40205
|
Object.assign(connectionOptions, options.tls);
|
|
39157
40206
|
}
|
|
39158
|
-
return new Promise((
|
|
40207
|
+
return new Promise((resolve3, reject) => {
|
|
39159
40208
|
process.nextTick(() => {
|
|
39160
40209
|
if (!this.connecting) {
|
|
39161
40210
|
reject(new Error(utils_1.CONNECTION_CLOSED_ERROR_MSG));
|
|
@@ -39174,7 +40223,7 @@ var require_StandaloneConnector = __commonJS({
|
|
|
39174
40223
|
this.stream.once("error", (err) => {
|
|
39175
40224
|
this.firstError = err;
|
|
39176
40225
|
});
|
|
39177
|
-
|
|
40226
|
+
resolve3(this.stream);
|
|
39178
40227
|
});
|
|
39179
40228
|
});
|
|
39180
40229
|
}
|
|
@@ -39330,7 +40379,7 @@ var require_SentinelConnector = __commonJS({
|
|
|
39330
40379
|
const error = new Error(errorMsg);
|
|
39331
40380
|
if (typeof retryDelay === "number") {
|
|
39332
40381
|
eventEmitter("error", error);
|
|
39333
|
-
await new Promise((
|
|
40382
|
+
await new Promise((resolve3) => setTimeout(resolve3, retryDelay));
|
|
39334
40383
|
return connectToNext();
|
|
39335
40384
|
} else {
|
|
39336
40385
|
throw error;
|
|
@@ -40647,7 +41696,7 @@ var require_Redis = __commonJS({
|
|
|
40647
41696
|
* if the connection fails, times out, or if Redis is already connecting/connected.
|
|
40648
41697
|
*/
|
|
40649
41698
|
connect(callback) {
|
|
40650
|
-
const promise = new Promise((
|
|
41699
|
+
const promise = new Promise((resolve3, reject) => {
|
|
40651
41700
|
if (this.status === "connecting" || this.status === "connect" || this.status === "ready") {
|
|
40652
41701
|
reject(new Error("Redis is already connecting/connected"));
|
|
40653
41702
|
return;
|
|
@@ -40726,7 +41775,7 @@ var require_Redis = __commonJS({
|
|
|
40726
41775
|
}
|
|
40727
41776
|
const connectionReadyHandler = function() {
|
|
40728
41777
|
_this.removeListener("close", connectionCloseHandler);
|
|
40729
|
-
|
|
41778
|
+
resolve3();
|
|
40730
41779
|
};
|
|
40731
41780
|
var connectionCloseHandler = function() {
|
|
40732
41781
|
_this.removeListener("ready", connectionReadyHandler);
|
|
@@ -40820,10 +41869,10 @@ var require_Redis = __commonJS({
|
|
|
40820
41869
|
monitor: true,
|
|
40821
41870
|
lazyConnect: false
|
|
40822
41871
|
});
|
|
40823
|
-
return (0, standard_as_callback_1.default)(new Promise(function(
|
|
41872
|
+
return (0, standard_as_callback_1.default)(new Promise(function(resolve3, reject) {
|
|
40824
41873
|
monitorInstance.once("error", reject);
|
|
40825
41874
|
monitorInstance.once("monitoring", function() {
|
|
40826
|
-
|
|
41875
|
+
resolve3(monitorInstance);
|
|
40827
41876
|
});
|
|
40828
41877
|
}), callback);
|
|
40829
41878
|
}
|
|
@@ -41645,6 +42694,7 @@ async function runMenu() {
|
|
|
41645
42694
|
const value = await Ee({
|
|
41646
42695
|
message: "What now?",
|
|
41647
42696
|
options: [
|
|
42697
|
+
{ value: "init", label: "Initialize this project (migrate .env)", hint: "keynv init" },
|
|
41648
42698
|
{ value: "projects", label: "Projects" },
|
|
41649
42699
|
{ value: "secrets", label: "Secrets" },
|
|
41650
42700
|
{ value: "members", label: "Members" },
|
|
@@ -41683,7 +42733,10 @@ async function runMenu() {
|
|
|
41683
42733
|
ye("Logged out.");
|
|
41684
42734
|
return 0;
|
|
41685
42735
|
}
|
|
41686
|
-
if (choice === "
|
|
42736
|
+
if (choice === "init") {
|
|
42737
|
+
const { runInitFlow: runInitFlow2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
42738
|
+
await runInitFlow2(client, { cwd: process.cwd(), dryRun: false, noScripts: false });
|
|
42739
|
+
} else if (choice === "projects") await runProjectsFlow(client);
|
|
41687
42740
|
else if (choice === "secrets") await runSecretsFlow(client);
|
|
41688
42741
|
else if (choice === "members") await runMembersFlow(client);
|
|
41689
42742
|
else if (choice === "audit") await runAuditFlow(client);
|
|
@@ -43496,134 +44549,7 @@ var AuditVerifyCommand = class extends Command {
|
|
|
43496
44549
|
|
|
43497
44550
|
// src/commands/exec.ts
|
|
43498
44551
|
init_http();
|
|
43499
|
-
|
|
43500
|
-
// src/exec/envFile.ts
|
|
43501
|
-
init_dist();
|
|
43502
|
-
var MAX_FILE_BYTES = 1e6;
|
|
43503
|
-
var KEY_RE2 = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
43504
|
-
var ENV_FILE_BASENAME = ".keynv.env";
|
|
43505
|
-
var EnvFileParseError = class extends Error {
|
|
43506
|
-
constructor(file, line, reason) {
|
|
43507
|
-
super(`${file}:${line}: ${reason}`);
|
|
43508
|
-
this.file = file;
|
|
43509
|
-
this.line = line;
|
|
43510
|
-
this.reason = reason;
|
|
43511
|
-
this.name = "EnvFileParseError";
|
|
43512
|
-
}
|
|
43513
|
-
file;
|
|
43514
|
-
line;
|
|
43515
|
-
reason;
|
|
43516
|
-
};
|
|
43517
|
-
var EnvFileNotFoundError = class extends Error {
|
|
43518
|
-
constructor(path) {
|
|
43519
|
-
super(`env file not found: ${path}`);
|
|
43520
|
-
this.path = path;
|
|
43521
|
-
this.name = "EnvFileNotFoundError";
|
|
43522
|
-
}
|
|
43523
|
-
path;
|
|
43524
|
-
};
|
|
43525
|
-
var EnvFileTooLargeError = class extends Error {
|
|
43526
|
-
constructor(path, bytes) {
|
|
43527
|
-
super(`env file ${path} is ${bytes} bytes (max ${MAX_FILE_BYTES})`);
|
|
43528
|
-
this.path = path;
|
|
43529
|
-
this.bytes = bytes;
|
|
43530
|
-
this.name = "EnvFileTooLargeError";
|
|
43531
|
-
}
|
|
43532
|
-
path;
|
|
43533
|
-
bytes;
|
|
43534
|
-
};
|
|
43535
|
-
function parseEnvFile(content, filename) {
|
|
43536
|
-
const normalized = content.charCodeAt(0) === 65279 ? content.slice(1) : content;
|
|
43537
|
-
const lines = normalized.split(/\r?\n/);
|
|
43538
|
-
const entries = [];
|
|
43539
|
-
for (let i = 0; i < lines.length; i++) {
|
|
43540
|
-
const raw = lines[i] ?? "";
|
|
43541
|
-
const lineNo = i + 1;
|
|
43542
|
-
const trimmed = raw.trim();
|
|
43543
|
-
if (trimmed.length === 0) continue;
|
|
43544
|
-
if (trimmed.startsWith("#")) continue;
|
|
43545
|
-
let body = trimmed;
|
|
43546
|
-
if (body.startsWith("export ")) {
|
|
43547
|
-
body = body.slice("export ".length).trimStart();
|
|
43548
|
-
}
|
|
43549
|
-
const eq = body.indexOf("=");
|
|
43550
|
-
if (eq <= 0) {
|
|
43551
|
-
throw new EnvFileParseError(filename, lineNo, "expected 'KEY=value'");
|
|
43552
|
-
}
|
|
43553
|
-
const name = body.slice(0, eq).trim();
|
|
43554
|
-
if (!KEY_RE2.test(name)) {
|
|
43555
|
-
throw new EnvFileParseError(
|
|
43556
|
-
filename,
|
|
43557
|
-
lineNo,
|
|
43558
|
-
`invalid key '${name}' (must match /^[A-Za-z_][A-Za-z0-9_]*$/)`
|
|
43559
|
-
);
|
|
43560
|
-
}
|
|
43561
|
-
let valueRaw = body.slice(eq + 1);
|
|
43562
|
-
let value;
|
|
43563
|
-
const valueLeading = valueRaw.replace(/^\s+/, "");
|
|
43564
|
-
const firstCh = valueLeading.charAt(0);
|
|
43565
|
-
if (firstCh === '"' || firstCh === "'") {
|
|
43566
|
-
const close = valueLeading.lastIndexOf(firstCh);
|
|
43567
|
-
if (close === 0) {
|
|
43568
|
-
throw new EnvFileParseError(filename, lineNo, `unclosed ${firstCh} quote`);
|
|
43569
|
-
}
|
|
43570
|
-
const after = valueLeading.slice(close + 1).trim();
|
|
43571
|
-
if (after.length > 0) {
|
|
43572
|
-
throw new EnvFileParseError(
|
|
43573
|
-
filename,
|
|
43574
|
-
lineNo,
|
|
43575
|
-
`unexpected content after closing ${firstCh}`
|
|
43576
|
-
);
|
|
43577
|
-
}
|
|
43578
|
-
value = valueLeading.slice(1, close);
|
|
43579
|
-
} else {
|
|
43580
|
-
value = valueRaw.replace(/\s+$/, "");
|
|
43581
|
-
value = value.replace(/^\s+/, "");
|
|
43582
|
-
}
|
|
43583
|
-
entries.push({
|
|
43584
|
-
name,
|
|
43585
|
-
value,
|
|
43586
|
-
isAlias: parseAlias(value) !== null,
|
|
43587
|
-
line: lineNo
|
|
43588
|
-
});
|
|
43589
|
-
}
|
|
43590
|
-
return entries;
|
|
43591
|
-
}
|
|
43592
|
-
function findEnvFile(startDir) {
|
|
43593
|
-
let dir = resolve(startDir);
|
|
43594
|
-
for (let i = 0; i < 64; i++) {
|
|
43595
|
-
const candidate = join(dir, ENV_FILE_BASENAME);
|
|
43596
|
-
if (existsSync(candidate)) {
|
|
43597
|
-
try {
|
|
43598
|
-
if (statSync(candidate).isFile()) return candidate;
|
|
43599
|
-
} catch {
|
|
43600
|
-
}
|
|
43601
|
-
}
|
|
43602
|
-
const parent = dirname(dir);
|
|
43603
|
-
if (parent === dir) return null;
|
|
43604
|
-
dir = parent;
|
|
43605
|
-
}
|
|
43606
|
-
return null;
|
|
43607
|
-
}
|
|
43608
|
-
function loadEnvFile(opts) {
|
|
43609
|
-
if (opts.disabled) return null;
|
|
43610
|
-
const pickExplicit = opts.explicitPath ?? opts.envVarOverride;
|
|
43611
|
-
let path = null;
|
|
43612
|
-
if (pickExplicit !== void 0) {
|
|
43613
|
-
path = isAbsolute(pickExplicit) ? pickExplicit : resolve(opts.cwd, pickExplicit);
|
|
43614
|
-
if (!existsSync(path)) throw new EnvFileNotFoundError(path);
|
|
43615
|
-
} else {
|
|
43616
|
-
path = findEnvFile(opts.cwd);
|
|
43617
|
-
}
|
|
43618
|
-
if (path === null) return null;
|
|
43619
|
-
const stat = statSync(path);
|
|
43620
|
-
if (stat.size > MAX_FILE_BYTES) {
|
|
43621
|
-
throw new EnvFileTooLargeError(path, stat.size);
|
|
43622
|
-
}
|
|
43623
|
-
const content = readFileSync(path, "utf8");
|
|
43624
|
-
const entries = parseEnvFile(content, path);
|
|
43625
|
-
return { path, entries };
|
|
43626
|
-
}
|
|
44552
|
+
init_envFile();
|
|
43627
44553
|
|
|
43628
44554
|
// src/exec/resolve.ts
|
|
43629
44555
|
init_dist();
|
|
@@ -43984,14 +44910,14 @@ function spawnPrivileged(opts) {
|
|
|
43984
44910
|
}, opts.timeoutS * 1e3);
|
|
43985
44911
|
timer.unref();
|
|
43986
44912
|
}
|
|
43987
|
-
return new Promise((
|
|
44913
|
+
return new Promise((resolve3, reject) => {
|
|
43988
44914
|
child.on("error", (err) => {
|
|
43989
44915
|
if (timer) clearTimeout(timer);
|
|
43990
44916
|
reject(err);
|
|
43991
44917
|
});
|
|
43992
44918
|
child.on("close", (code, signal) => {
|
|
43993
44919
|
if (timer) clearTimeout(timer);
|
|
43994
|
-
|
|
44920
|
+
resolve3({
|
|
43995
44921
|
exitCode: code ?? 0,
|
|
43996
44922
|
signal,
|
|
43997
44923
|
durationMs: Date.now() - startedAt
|
|
@@ -44209,552 +45135,67 @@ function signalNumber(sig) {
|
|
|
44209
45135
|
return map[sig] ?? null;
|
|
44210
45136
|
}
|
|
44211
45137
|
|
|
44212
|
-
//
|
|
44213
|
-
|
|
44214
|
-
|
|
44215
|
-
|
|
44216
|
-
|
|
44217
|
-
|
|
44218
|
-
"
|
|
44219
|
-
"**/.env.*",
|
|
44220
|
-
"**/*.env",
|
|
44221
|
-
// raw key material
|
|
44222
|
-
"*.pem",
|
|
44223
|
-
"*.key",
|
|
44224
|
-
"*.p12",
|
|
44225
|
-
"*.pfx",
|
|
44226
|
-
"**/*.pem",
|
|
44227
|
-
"**/*.key",
|
|
44228
|
-
"**/*.p12",
|
|
44229
|
-
"**/*.pfx",
|
|
44230
|
-
// SSH private keys
|
|
44231
|
-
"id_rsa",
|
|
44232
|
-
"id_rsa.*",
|
|
44233
|
-
"id_ed25519",
|
|
44234
|
-
"id_ed25519.*",
|
|
44235
|
-
"id_ecdsa",
|
|
44236
|
-
"id_ecdsa.*",
|
|
44237
|
-
"**/id_rsa",
|
|
44238
|
-
"**/id_rsa.*",
|
|
44239
|
-
"**/id_ed25519",
|
|
44240
|
-
"**/id_ed25519.*",
|
|
44241
|
-
"**/id_ecdsa",
|
|
44242
|
-
"**/id_ecdsa.*",
|
|
44243
|
-
// Generic credential containers
|
|
44244
|
-
"*credentials*",
|
|
44245
|
-
"*.kdbx",
|
|
44246
|
-
"**/*credentials*",
|
|
44247
|
-
"**/*.kdbx",
|
|
44248
|
-
// Cloud provider credential paths (typically under ~/, but also
|
|
44249
|
-
// appear at project roots in dev setups)
|
|
44250
|
-
".aws/credentials",
|
|
44251
|
-
"**/.aws/credentials",
|
|
44252
|
-
".aws/config",
|
|
44253
|
-
"**/.aws/config",
|
|
44254
|
-
".gcp/**/key.json",
|
|
44255
|
-
"**/.gcp/**/key.json",
|
|
44256
|
-
"**/google-services.json",
|
|
44257
|
-
"**/service-account*.json",
|
|
44258
|
-
".azure/**",
|
|
44259
|
-
"**/.azure/**",
|
|
44260
|
-
".kube/config",
|
|
44261
|
-
"**/.kube/config",
|
|
44262
|
-
".docker/config.json",
|
|
44263
|
-
"**/.docker/config.json"
|
|
44264
|
-
];
|
|
44265
|
-
var KEYNV_FILE_ALLOW_PATTERNS = [
|
|
44266
|
-
".keynv.env",
|
|
44267
|
-
"**/.keynv.env"
|
|
44268
|
-
];
|
|
44269
|
-
function gitignoreBlock() {
|
|
44270
|
-
return [...KEYNV_FILE_DENY_PATTERNS, ...KEYNV_FILE_ALLOW_PATTERNS.map((p2) => `!${p2}`)];
|
|
44271
|
-
}
|
|
44272
|
-
var KEYNV_BEGIN = "# >>> keynv >>>";
|
|
44273
|
-
var KEYNV_END = "# <<< keynv <<<";
|
|
44274
|
-
function readJsonOrEmpty(path) {
|
|
44275
|
-
if (!existsSync(path))
|
|
44276
|
-
return {};
|
|
44277
|
-
try {
|
|
44278
|
-
return JSON.parse(readFileSync(path, "utf8"));
|
|
44279
|
-
} catch {
|
|
44280
|
-
return {};
|
|
44281
|
-
}
|
|
44282
|
-
}
|
|
44283
|
-
function ensureDir(path) {
|
|
44284
|
-
const dir = dirname(path);
|
|
44285
|
-
if (!existsSync(dir))
|
|
44286
|
-
mkdirSync(dir, { recursive: true });
|
|
44287
|
-
}
|
|
44288
|
-
function writeJson(path, value) {
|
|
44289
|
-
ensureDir(path);
|
|
44290
|
-
writeFileSync(path, `${JSON.stringify(value, null, 2)}
|
|
44291
|
-
`, { mode: 420 });
|
|
44292
|
-
}
|
|
44293
|
-
function ensureKeynvBlock(path, lines) {
|
|
44294
|
-
const existing = existsSync(path) ? readFileSync(path, "utf8") : "";
|
|
44295
|
-
const marked = existing.split("\n");
|
|
44296
|
-
const beginIdx = marked.findIndex((l) => l.trim() === KEYNV_BEGIN);
|
|
44297
|
-
const endIdx = marked.findIndex((l) => l.trim() === KEYNV_END);
|
|
44298
|
-
const block = [KEYNV_BEGIN, ...lines, KEYNV_END];
|
|
44299
|
-
let next;
|
|
44300
|
-
if (beginIdx >= 0 && endIdx > beginIdx) {
|
|
44301
|
-
next = [...marked.slice(0, beginIdx), ...block, ...marked.slice(endIdx + 1)];
|
|
44302
|
-
} else {
|
|
44303
|
-
next = existing.length > 0 && !existing.endsWith("\n") ? [...marked, "", ...block] : [...marked[marked.length - 1] === "" ? marked.slice(0, -1) : marked, ...block, ""];
|
|
44304
|
-
}
|
|
44305
|
-
const out = next.join("\n");
|
|
44306
|
-
if (out === existing)
|
|
44307
|
-
return false;
|
|
44308
|
-
ensureDir(path);
|
|
44309
|
-
writeFileSync(path, out, { mode: 420 });
|
|
44310
|
-
return true;
|
|
44311
|
-
}
|
|
44312
|
-
function removeKeynvBlock(path) {
|
|
44313
|
-
if (!existsSync(path))
|
|
44314
|
-
return false;
|
|
44315
|
-
const lines = readFileSync(path, "utf8").split("\n");
|
|
44316
|
-
const beginIdx = lines.findIndex((l) => l.trim() === KEYNV_BEGIN);
|
|
44317
|
-
const endIdx = lines.findIndex((l) => l.trim() === KEYNV_END);
|
|
44318
|
-
if (beginIdx < 0 || endIdx <= beginIdx)
|
|
44319
|
-
return false;
|
|
44320
|
-
const next = [...lines.slice(0, beginIdx), ...lines.slice(endIdx + 1)];
|
|
44321
|
-
while (next.length > 0 && next[next.length - 1] === "")
|
|
44322
|
-
next.pop();
|
|
44323
|
-
writeFileSync(path, `${next.join("\n")}${next.length ? "\n" : ""}`, { mode: 420 });
|
|
44324
|
-
return true;
|
|
44325
|
-
}
|
|
44326
|
-
|
|
44327
|
-
// ../../packages/integrations/dist/aider.js
|
|
44328
|
-
var AIDER_IGNORE_REL = ".aiderignore";
|
|
44329
|
-
var aider = {
|
|
44330
|
-
name: "aider",
|
|
44331
|
-
displayName: "Aider",
|
|
44332
|
-
async detect(opts = {}) {
|
|
44333
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44334
|
-
return existsSync(join(cwd, AIDER_IGNORE_REL)) || existsSync(join(cwd, ".aider.conf.yml")) || existsSync(join(homedir(), ".aider.conf.yml"));
|
|
44335
|
-
},
|
|
44336
|
-
async install(opts = {}) {
|
|
44337
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44338
|
-
const path = join(cwd, AIDER_IGNORE_REL);
|
|
44339
|
-
if (opts.dryRun) {
|
|
44340
|
-
return {
|
|
44341
|
-
agent: "aider",
|
|
44342
|
-
applied: false,
|
|
44343
|
-
changes: [{ path, action: "update" }],
|
|
44344
|
-
summary: `[dry-run] would write ${path}`
|
|
44345
|
-
};
|
|
44346
|
-
}
|
|
44347
|
-
const changed = ensureKeynvBlock(path, gitignoreBlock());
|
|
44348
|
-
return {
|
|
44349
|
-
agent: "aider",
|
|
44350
|
-
applied: true,
|
|
44351
|
-
changes: [{ path, action: changed ? "update" : "skip" }],
|
|
44352
|
-
summary: changed ? `wrote ${KEYNV_FILE_DENY_PATTERNS.length} patterns to ${AIDER_IGNORE_REL}` : "unchanged"
|
|
44353
|
-
};
|
|
44354
|
-
},
|
|
44355
|
-
async uninstall(opts = {}) {
|
|
44356
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44357
|
-
const path = join(cwd, AIDER_IGNORE_REL);
|
|
44358
|
-
if (opts.dryRun) {
|
|
44359
|
-
return {
|
|
44360
|
-
agent: "aider",
|
|
44361
|
-
applied: false,
|
|
44362
|
-
changes: [{ path, action: "update" }],
|
|
44363
|
-
summary: `[dry-run] would remove keynv block from ${AIDER_IGNORE_REL}`
|
|
44364
|
-
};
|
|
44365
|
-
}
|
|
44366
|
-
const changed = removeKeynvBlock(path);
|
|
44367
|
-
return {
|
|
44368
|
-
agent: "aider",
|
|
44369
|
-
applied: true,
|
|
44370
|
-
changes: [{ path, action: changed ? "update" : "skip" }],
|
|
44371
|
-
summary: changed ? "removed keynv block" : "no keynv block found"
|
|
44372
|
-
};
|
|
44373
|
-
}
|
|
44374
|
-
};
|
|
44375
|
-
var SETTINGS_PATH_REL = ".claude/settings.local.json";
|
|
44376
|
-
var KEYNV_DENY_TAG = "__keynv_managed__";
|
|
44377
|
-
function denyEntriesForReadTool() {
|
|
44378
|
-
return KEYNV_FILE_DENY_PATTERNS.map((p2) => `Read(${p2})`);
|
|
44379
|
-
}
|
|
44380
|
-
function allowEntriesForReadTool() {
|
|
44381
|
-
return KEYNV_FILE_ALLOW_PATTERNS.map((p2) => `Read(${p2})`);
|
|
44382
|
-
}
|
|
44383
|
-
var claudeCode = {
|
|
44384
|
-
name: "claude-code",
|
|
44385
|
-
displayName: "Claude Code",
|
|
44386
|
-
async detect(opts = {}) {
|
|
44387
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44388
|
-
return existsSync(join(cwd, ".claude"));
|
|
44389
|
-
},
|
|
44390
|
-
async install(opts = {}) {
|
|
44391
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44392
|
-
const path = join(cwd, SETTINGS_PATH_REL);
|
|
44393
|
-
const settings = readJsonOrEmpty(path);
|
|
44394
|
-
const denyToAdd = denyEntriesForReadTool();
|
|
44395
|
-
const allowToAdd = allowEntriesForReadTool();
|
|
44396
|
-
const existingDeny = new Set(settings.permissions?.deny ?? []);
|
|
44397
|
-
const existingAllow = new Set(settings.permissions?.allow ?? []);
|
|
44398
|
-
const newlyAdded = [];
|
|
44399
|
-
for (const entry2 of denyToAdd) {
|
|
44400
|
-
if (!existingDeny.has(entry2)) {
|
|
44401
|
-
existingDeny.add(entry2);
|
|
44402
|
-
newlyAdded.push(entry2);
|
|
44403
|
-
}
|
|
44404
|
-
}
|
|
44405
|
-
for (const entry2 of allowToAdd) {
|
|
44406
|
-
if (!existingAllow.has(entry2)) {
|
|
44407
|
-
existingAllow.add(entry2);
|
|
44408
|
-
}
|
|
44409
|
-
}
|
|
44410
|
-
settings.permissions = {
|
|
44411
|
-
...settings.permissions,
|
|
44412
|
-
allow: [...existingAllow].sort((a, b2) => a.localeCompare(b2)),
|
|
44413
|
-
deny: [...existingDeny].sort((a, b2) => a.localeCompare(b2))
|
|
44414
|
-
};
|
|
44415
|
-
settings.hooks = settings.hooks ?? {};
|
|
44416
|
-
const post = settings.hooks["PostToolUse"] ?? [];
|
|
44417
|
-
const alreadyHooked = post.some((entry2) => (entry2.hooks ?? []).some((h2) => h2.command?.includes("keynv redact-stream")));
|
|
44418
|
-
if (!alreadyHooked) {
|
|
44419
|
-
post.push({
|
|
44420
|
-
matcher: "Bash",
|
|
44421
|
-
hooks: [{ type: "command", command: "keynv redact-stream" }]
|
|
44422
|
-
});
|
|
44423
|
-
settings.hooks["PostToolUse"] = post;
|
|
44424
|
-
}
|
|
44425
|
-
settings[KEYNV_DENY_TAG] = {
|
|
44426
|
-
deny_added: denyToAdd,
|
|
44427
|
-
allow_added: allowToAdd,
|
|
44428
|
-
hook_added: true
|
|
44429
|
-
};
|
|
44430
|
-
const changes = [];
|
|
44431
|
-
if (opts.dryRun) {
|
|
44432
|
-
changes.push({
|
|
44433
|
-
path,
|
|
44434
|
-
action: existsSync(path) ? "update" : "create",
|
|
44435
|
-
note: `would add ${newlyAdded.length} deny entries${alreadyHooked ? "" : " + PostToolUse(Bash) \u2192 keynv redact-stream"}`
|
|
44436
|
-
});
|
|
44437
|
-
} else {
|
|
44438
|
-
writeJson(path, settings);
|
|
44439
|
-
changes.push({
|
|
44440
|
-
path,
|
|
44441
|
-
action: existsSync(path) ? "update" : "create",
|
|
44442
|
-
note: `${newlyAdded.length} new deny entries${alreadyHooked ? "" : " + redact hook"}`
|
|
44443
|
-
});
|
|
44444
|
-
}
|
|
44445
|
-
return {
|
|
44446
|
-
agent: "claude-code",
|
|
44447
|
-
applied: !opts.dryRun,
|
|
44448
|
-
changes,
|
|
44449
|
-
summary: opts.dryRun ? `[dry-run] ${path}: would add ${newlyAdded.length} permission denies + redact hook` : `installed: ${newlyAdded.length} new denies; redact hook ${alreadyHooked ? "kept" : "added"}.`
|
|
44450
|
-
};
|
|
44451
|
-
},
|
|
44452
|
-
async uninstall(opts = {}) {
|
|
44453
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44454
|
-
const path = join(cwd, SETTINGS_PATH_REL);
|
|
44455
|
-
if (!existsSync(path)) {
|
|
44456
|
-
return {
|
|
44457
|
-
agent: "claude-code",
|
|
44458
|
-
applied: false,
|
|
44459
|
-
changes: [{ path, action: "skip", note: "no settings file" }],
|
|
44460
|
-
summary: "nothing to uninstall"
|
|
44461
|
-
};
|
|
44462
|
-
}
|
|
44463
|
-
const settings = readJsonOrEmpty(path);
|
|
44464
|
-
const tracker = settings[KEYNV_DENY_TAG];
|
|
44465
|
-
const removedDeny = [];
|
|
44466
|
-
const permissions = settings.permissions;
|
|
44467
|
-
if (tracker?.deny_added && permissions && Array.isArray(permissions.deny)) {
|
|
44468
|
-
const remove = new Set(tracker.deny_added);
|
|
44469
|
-
const before = permissions.deny;
|
|
44470
|
-
permissions.deny = before.filter((entry2) => {
|
|
44471
|
-
if (remove.has(entry2)) {
|
|
44472
|
-
removedDeny.push(entry2);
|
|
44473
|
-
return false;
|
|
44474
|
-
}
|
|
44475
|
-
return true;
|
|
44476
|
-
});
|
|
44477
|
-
if (permissions.deny.length === 0)
|
|
44478
|
-
delete permissions.deny;
|
|
44479
|
-
}
|
|
44480
|
-
if (tracker?.allow_added && permissions && Array.isArray(permissions.allow)) {
|
|
44481
|
-
const remove = new Set(tracker.allow_added);
|
|
44482
|
-
permissions.allow = permissions.allow.filter((entry2) => !remove.has(entry2));
|
|
44483
|
-
if (permissions.allow.length === 0)
|
|
44484
|
-
delete permissions.allow;
|
|
44485
|
-
}
|
|
44486
|
-
const hooks = settings.hooks;
|
|
44487
|
-
if (tracker?.hook_added && hooks && Array.isArray(hooks.PostToolUse)) {
|
|
44488
|
-
const filtered = hooks.PostToolUse.filter((entry2) => !(entry2.hooks ?? []).some((h2) => h2.command?.includes("keynv redact-stream")));
|
|
44489
|
-
hooks.PostToolUse = filtered;
|
|
44490
|
-
if (filtered.length === 0)
|
|
44491
|
-
delete hooks.PostToolUse;
|
|
44492
|
-
}
|
|
44493
|
-
delete settings[KEYNV_DENY_TAG];
|
|
44494
|
-
if (opts.dryRun) {
|
|
44495
|
-
return {
|
|
44496
|
-
agent: "claude-code",
|
|
44497
|
-
applied: false,
|
|
44498
|
-
changes: [
|
|
44499
|
-
{ path, action: "update", note: `would remove ${removedDeny.length} denies + hook` }
|
|
44500
|
-
],
|
|
44501
|
-
summary: `[dry-run] would remove ${removedDeny.length} denies`
|
|
44502
|
-
};
|
|
44503
|
-
}
|
|
44504
|
-
writeJson(path, settings);
|
|
44505
|
-
return {
|
|
44506
|
-
agent: "claude-code",
|
|
44507
|
-
applied: true,
|
|
44508
|
-
changes: [{ path, action: "update" }],
|
|
44509
|
-
summary: `removed ${removedDeny.length} denies + hook`
|
|
44510
|
-
};
|
|
44511
|
-
}
|
|
44512
|
-
};
|
|
44513
|
-
var CODEX_IGNORE_REL = ".codex/.deny";
|
|
44514
|
-
var codexCli = {
|
|
44515
|
-
name: "codex",
|
|
44516
|
-
displayName: "Codex CLI",
|
|
44517
|
-
async detect(opts = {}) {
|
|
44518
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44519
|
-
return existsSync(join(cwd, ".codex")) || existsSync(join(homedir(), ".codex"));
|
|
44520
|
-
},
|
|
44521
|
-
async install(opts = {}) {
|
|
44522
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44523
|
-
const path = join(cwd, CODEX_IGNORE_REL);
|
|
44524
|
-
if (opts.dryRun) {
|
|
44525
|
-
return {
|
|
44526
|
-
agent: "codex",
|
|
44527
|
-
applied: false,
|
|
44528
|
-
changes: [{ path, action: "update" }],
|
|
44529
|
-
summary: `[dry-run] would write ${CODEX_IGNORE_REL}`
|
|
44530
|
-
};
|
|
44531
|
-
}
|
|
44532
|
-
const changed = ensureKeynvBlock(path, gitignoreBlock());
|
|
44533
|
-
return {
|
|
44534
|
-
agent: "codex",
|
|
44535
|
-
applied: true,
|
|
44536
|
-
changes: [{ path, action: changed ? "update" : "skip" }],
|
|
44537
|
-
summary: changed ? `wrote ${CODEX_IGNORE_REL}; consider adding 'alias codex="keynv exec -- codex"' to your shell rc` : "unchanged"
|
|
44538
|
-
};
|
|
44539
|
-
},
|
|
44540
|
-
async uninstall(opts = {}) {
|
|
44541
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44542
|
-
const path = join(cwd, CODEX_IGNORE_REL);
|
|
44543
|
-
if (opts.dryRun) {
|
|
44544
|
-
return {
|
|
44545
|
-
agent: "codex",
|
|
44546
|
-
applied: false,
|
|
44547
|
-
changes: [{ path, action: "update" }],
|
|
44548
|
-
summary: `[dry-run] would remove keynv block from ${CODEX_IGNORE_REL}`
|
|
44549
|
-
};
|
|
44550
|
-
}
|
|
44551
|
-
const changed = removeKeynvBlock(path);
|
|
44552
|
-
return {
|
|
44553
|
-
agent: "codex",
|
|
44554
|
-
applied: true,
|
|
44555
|
-
changes: [{ path, action: changed ? "update" : "skip" }],
|
|
44556
|
-
summary: changed ? "removed keynv block" : "no keynv block found"
|
|
44557
|
-
};
|
|
44558
|
-
}
|
|
44559
|
-
};
|
|
44560
|
-
var CURSOR_IGNORE_REL = ".cursorignore";
|
|
44561
|
-
var cursor = {
|
|
44562
|
-
name: "cursor",
|
|
44563
|
-
displayName: "Cursor",
|
|
44564
|
-
async detect(opts = {}) {
|
|
44565
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44566
|
-
return existsSync(join(cwd, ".cursor")) || existsSync(join(cwd, ".cursorrules"));
|
|
44567
|
-
},
|
|
44568
|
-
async install(opts = {}) {
|
|
44569
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44570
|
-
const path = join(cwd, CURSOR_IGNORE_REL);
|
|
44571
|
-
if (opts.dryRun) {
|
|
44572
|
-
return {
|
|
44573
|
-
agent: "cursor",
|
|
44574
|
-
applied: false,
|
|
44575
|
-
changes: [
|
|
44576
|
-
{
|
|
44577
|
-
path,
|
|
44578
|
-
action: "update",
|
|
44579
|
-
note: `would add ${KEYNV_FILE_DENY_PATTERNS.length} ignore patterns`
|
|
44580
|
-
}
|
|
44581
|
-
],
|
|
44582
|
-
summary: `[dry-run] would write ${path}`
|
|
44583
|
-
};
|
|
44584
|
-
}
|
|
44585
|
-
const changed = ensureKeynvBlock(path, gitignoreBlock());
|
|
44586
|
-
return {
|
|
44587
|
-
agent: "cursor",
|
|
44588
|
-
applied: true,
|
|
44589
|
-
changes: [{ path, action: changed ? "update" : "skip" }],
|
|
44590
|
-
summary: changed ? `wrote ${KEYNV_FILE_DENY_PATTERNS.length} patterns to ${CURSOR_IGNORE_REL}` : "unchanged"
|
|
44591
|
-
};
|
|
44592
|
-
},
|
|
44593
|
-
async uninstall(opts = {}) {
|
|
44594
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44595
|
-
const path = join(cwd, CURSOR_IGNORE_REL);
|
|
44596
|
-
if (opts.dryRun) {
|
|
44597
|
-
return {
|
|
44598
|
-
agent: "cursor",
|
|
44599
|
-
applied: false,
|
|
44600
|
-
changes: [{ path, action: "update" }],
|
|
44601
|
-
summary: `[dry-run] would remove keynv block from ${CURSOR_IGNORE_REL}`
|
|
44602
|
-
};
|
|
44603
|
-
}
|
|
44604
|
-
const changed = removeKeynvBlock(path);
|
|
44605
|
-
return {
|
|
44606
|
-
agent: "cursor",
|
|
44607
|
-
applied: true,
|
|
44608
|
-
changes: [{ path, action: changed ? "update" : "skip" }],
|
|
44609
|
-
summary: changed ? "removed keynv block" : "no keynv block found"
|
|
44610
|
-
};
|
|
44611
|
-
}
|
|
44612
|
-
};
|
|
44613
|
-
var OPENCODE_IGNORE_REL = ".opencode/.keynv-deny";
|
|
44614
|
-
var opencode = {
|
|
44615
|
-
name: "opencode",
|
|
44616
|
-
displayName: "OpenCode",
|
|
44617
|
-
async detect(opts = {}) {
|
|
44618
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44619
|
-
return existsSync(join(cwd, ".opencode")) || existsSync(join(homedir(), ".opencode"));
|
|
44620
|
-
},
|
|
44621
|
-
async install(opts = {}) {
|
|
44622
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44623
|
-
const path = join(cwd, OPENCODE_IGNORE_REL);
|
|
44624
|
-
if (opts.dryRun) {
|
|
44625
|
-
return {
|
|
44626
|
-
agent: "opencode",
|
|
44627
|
-
applied: false,
|
|
44628
|
-
changes: [{ path, action: "update" }],
|
|
44629
|
-
summary: `[dry-run] would write ${OPENCODE_IGNORE_REL}`
|
|
44630
|
-
};
|
|
44631
|
-
}
|
|
44632
|
-
const changed = ensureKeynvBlock(path, gitignoreBlock());
|
|
44633
|
-
return {
|
|
44634
|
-
agent: "opencode",
|
|
44635
|
-
applied: true,
|
|
44636
|
-
changes: [{ path, action: changed ? "update" : "skip" }],
|
|
44637
|
-
summary: changed ? `wrote ${OPENCODE_IGNORE_REL}; full hook/MCP integration TBD` : "unchanged"
|
|
44638
|
-
};
|
|
44639
|
-
},
|
|
44640
|
-
async uninstall(opts = {}) {
|
|
44641
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
44642
|
-
const path = join(cwd, OPENCODE_IGNORE_REL);
|
|
44643
|
-
if (opts.dryRun) {
|
|
44644
|
-
return {
|
|
44645
|
-
agent: "opencode",
|
|
44646
|
-
applied: false,
|
|
44647
|
-
changes: [{ path, action: "update" }],
|
|
44648
|
-
summary: `[dry-run] would remove keynv block from ${OPENCODE_IGNORE_REL}`
|
|
44649
|
-
};
|
|
44650
|
-
}
|
|
44651
|
-
const changed = removeKeynvBlock(path);
|
|
44652
|
-
return {
|
|
44653
|
-
agent: "opencode",
|
|
44654
|
-
applied: true,
|
|
44655
|
-
changes: [{ path, action: changed ? "update" : "skip" }],
|
|
44656
|
-
summary: changed ? "removed keynv block" : "no keynv block found"
|
|
44657
|
-
};
|
|
44658
|
-
}
|
|
44659
|
-
};
|
|
44660
|
-
|
|
44661
|
-
// ../../packages/integrations/dist/index.js
|
|
44662
|
-
var REGISTRY = [claudeCode, cursor, opencode, codexCli, aider];
|
|
44663
|
-
function findIntegration(name) {
|
|
44664
|
-
return REGISTRY.find((i) => i.name === name) ?? null;
|
|
44665
|
-
}
|
|
44666
|
-
|
|
44667
|
-
// src/commands/install.ts
|
|
44668
|
-
function printReport(stdout, report) {
|
|
44669
|
-
stdout.write(`[${report.agent}] ${report.summary}
|
|
44670
|
-
`);
|
|
44671
|
-
for (const change of report.changes) {
|
|
44672
|
-
const note = change.note ? `: ${change.note}` : "";
|
|
44673
|
-
stdout.write(` ${change.action.padEnd(7)} ${change.path}${note}
|
|
44674
|
-
`);
|
|
44675
|
-
}
|
|
44676
|
-
}
|
|
44677
|
-
var InstallCommand = class extends Command {
|
|
44678
|
-
static paths = [["install"]];
|
|
45138
|
+
// src/commands/init.ts
|
|
45139
|
+
init_http();
|
|
45140
|
+
init_tty();
|
|
45141
|
+
init_init();
|
|
45142
|
+
init_cancel();
|
|
45143
|
+
var InitCommand = class extends Command {
|
|
45144
|
+
static paths = [["init"]];
|
|
44679
45145
|
static usage = Command.Usage({
|
|
44680
|
-
description: "
|
|
45146
|
+
description: "Migrate an existing project from .env to keynv.",
|
|
44681
45147
|
details: `
|
|
44682
|
-
|
|
44683
|
-
|
|
44684
|
-
|
|
45148
|
+
Walks the current directory's .env files, prompts you to mark which
|
|
45149
|
+
keys are real secrets, uploads those to the keynv vault, writes a
|
|
45150
|
+
.keynv.env file with alias references, and (optionally) wraps your
|
|
45151
|
+
package.json scripts with \`keynv exec\`.
|
|
45152
|
+
|
|
45153
|
+
Safe to re-run: existing .keynv.env entries are preserved; new
|
|
45154
|
+
entries are appended below a marker.
|
|
45155
|
+
|
|
45156
|
+
Requires an interactive terminal (clack TUI). For scripted
|
|
45157
|
+
migration, use the lower-level \`keynv project\` and \`keynv secret\`
|
|
45158
|
+
commands directly.
|
|
44685
45159
|
`,
|
|
44686
45160
|
examples: [
|
|
44687
|
-
["
|
|
44688
|
-
["Preview
|
|
44689
|
-
["
|
|
44690
|
-
["List supported integrations", "$0 install list"]
|
|
45161
|
+
["Walk the current project", "$0 init"],
|
|
45162
|
+
["Preview without writing or uploading", "$0 init --dry-run"],
|
|
45163
|
+
["Skip the package.json script-wrapping step", "$0 init --no-scripts"]
|
|
44691
45164
|
]
|
|
44692
45165
|
});
|
|
44693
|
-
|
|
44694
|
-
|
|
44695
|
-
|
|
45166
|
+
dryRun = options_exports.Boolean("--dry-run", false, {
|
|
45167
|
+
description: "Show what would be done without writing files or uploading secrets."
|
|
45168
|
+
});
|
|
45169
|
+
noScripts = options_exports.Boolean("--no-scripts", false, {
|
|
45170
|
+
description: "Skip the package.json script-wrapping step."
|
|
45171
|
+
});
|
|
44696
45172
|
async execute() {
|
|
44697
|
-
if (
|
|
44698
|
-
this.context.stdout.write("Supported integrations:\n");
|
|
44699
|
-
for (const i of REGISTRY) {
|
|
44700
|
-
this.context.stdout.write(` ${i.name.padEnd(14)} ${i.displayName}
|
|
44701
|
-
`);
|
|
44702
|
-
}
|
|
44703
|
-
return 0;
|
|
44704
|
-
}
|
|
44705
|
-
if (this.all) {
|
|
44706
|
-
const cwd = process.cwd();
|
|
44707
|
-
let any = false;
|
|
44708
|
-
for (const integration2 of REGISTRY) {
|
|
44709
|
-
const detected = await integration2.detect({ cwd });
|
|
44710
|
-
if (!detected) continue;
|
|
44711
|
-
any = true;
|
|
44712
|
-
const report2 = await integration2.install({ cwd, dryRun: this.dryRun });
|
|
44713
|
-
printReport(this.context.stdout, report2);
|
|
44714
|
-
}
|
|
44715
|
-
if (!any) {
|
|
44716
|
-
this.context.stdout.write("no integrations detected in this directory\n");
|
|
44717
|
-
}
|
|
44718
|
-
return 0;
|
|
44719
|
-
}
|
|
44720
|
-
if (!this.agent) {
|
|
45173
|
+
if (!isInteractive()) {
|
|
44721
45174
|
this.context.stderr.write(
|
|
44722
|
-
"keynv
|
|
45175
|
+
"keynv init requires an interactive terminal. Use the lower-level commands (`keynv project`, `keynv secret`) for scripted setup.\n"
|
|
44723
45176
|
);
|
|
44724
|
-
return
|
|
45177
|
+
return 1;
|
|
44725
45178
|
}
|
|
44726
|
-
const
|
|
44727
|
-
|
|
44728
|
-
|
|
44729
|
-
|
|
44730
|
-
`
|
|
44731
|
-
);
|
|
45179
|
+
const client = new ApiClient();
|
|
45180
|
+
await client.ensureHydrated();
|
|
45181
|
+
if (!client.isLoggedIn) {
|
|
45182
|
+
this.context.stderr.write("keynv: not logged in. Run `keynv login` first.\n");
|
|
44732
45183
|
return 1;
|
|
44733
45184
|
}
|
|
44734
|
-
|
|
44735
|
-
|
|
44736
|
-
|
|
44737
|
-
|
|
44738
|
-
|
|
44739
|
-
|
|
44740
|
-
|
|
44741
|
-
|
|
44742
|
-
|
|
44743
|
-
|
|
44744
|
-
|
|
44745
|
-
|
|
44746
|
-
async execute() {
|
|
44747
|
-
const integration = findIntegration(this.agent);
|
|
44748
|
-
if (!integration) {
|
|
44749
|
-
this.context.stderr.write(
|
|
44750
|
-
`keynv: unknown integration '${this.agent}'. Try \`keynv install list\`.
|
|
44751
|
-
`
|
|
44752
|
-
);
|
|
45185
|
+
try {
|
|
45186
|
+
const outcome = await runInitFlow(client, {
|
|
45187
|
+
cwd: process.cwd(),
|
|
45188
|
+
dryRun: this.dryRun,
|
|
45189
|
+
noScripts: this.noScripts
|
|
45190
|
+
});
|
|
45191
|
+
return outcome.exitCode;
|
|
45192
|
+
} catch (err) {
|
|
45193
|
+
if (err instanceof UserCancelled) return 130;
|
|
45194
|
+
const e2 = err;
|
|
45195
|
+
this.context.stderr.write(`keynv: ${e2.message}
|
|
45196
|
+
`);
|
|
44753
45197
|
return 1;
|
|
44754
45198
|
}
|
|
44755
|
-
const report = await integration.uninstall({ cwd: process.cwd(), dryRun: this.dryRun });
|
|
44756
|
-
printReport(this.context.stdout, report);
|
|
44757
|
-
return 0;
|
|
44758
45199
|
}
|
|
44759
45200
|
};
|
|
44760
45201
|
|
|
@@ -44770,7 +45211,7 @@ async function promptHidden(prompt) {
|
|
|
44770
45211
|
process.stdin.setRawMode(true);
|
|
44771
45212
|
process.stdin.resume();
|
|
44772
45213
|
process.stdin.setEncoding("utf8");
|
|
44773
|
-
return new Promise((
|
|
45214
|
+
return new Promise((resolve3) => {
|
|
44774
45215
|
let buf = "";
|
|
44775
45216
|
const onData = (chunk) => {
|
|
44776
45217
|
for (const ch of chunk) {
|
|
@@ -44779,7 +45220,7 @@ async function promptHidden(prompt) {
|
|
|
44779
45220
|
process.stdin.pause();
|
|
44780
45221
|
process.stdin.removeListener("data", onData);
|
|
44781
45222
|
process.stdout.write("\n");
|
|
44782
|
-
|
|
45223
|
+
resolve3(buf);
|
|
44783
45224
|
return;
|
|
44784
45225
|
}
|
|
44785
45226
|
if (ch === "") {
|
|
@@ -44797,10 +45238,10 @@ async function promptHidden(prompt) {
|
|
|
44797
45238
|
}
|
|
44798
45239
|
async function promptLine(prompt) {
|
|
44799
45240
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
44800
|
-
return new Promise((
|
|
45241
|
+
return new Promise((resolve3) => {
|
|
44801
45242
|
rl.question(prompt, (answer) => {
|
|
44802
45243
|
rl.close();
|
|
44803
|
-
|
|
45244
|
+
resolve3(answer.trim());
|
|
44804
45245
|
});
|
|
44805
45246
|
});
|
|
44806
45247
|
}
|
|
@@ -45191,9 +45632,9 @@ streaming-mode limitation in @keynv/redactor).
|
|
|
45191
45632
|
`
|
|
45192
45633
|
});
|
|
45193
45634
|
async execute() {
|
|
45194
|
-
return new Promise((
|
|
45635
|
+
return new Promise((resolve3, reject) => {
|
|
45195
45636
|
const transform = createRedactStream();
|
|
45196
|
-
this.context.stdin.pipe(transform).pipe(this.context.stdout).on("error", reject).on("finish", () =>
|
|
45637
|
+
this.context.stdin.pipe(transform).pipe(this.context.stdout).on("error", reject).on("finish", () => resolve3(0));
|
|
45197
45638
|
this.context.stdin.on("error", reject);
|
|
45198
45639
|
});
|
|
45199
45640
|
}
|
|
@@ -45683,7 +46124,7 @@ var sshTester = {
|
|
|
45683
46124
|
async test(secret, target) {
|
|
45684
46125
|
const start = Date.now();
|
|
45685
46126
|
const { Client: Client2 } = await import('ssh2');
|
|
45686
|
-
return new Promise((
|
|
46127
|
+
return new Promise((resolve3) => {
|
|
45687
46128
|
const client = new Client2();
|
|
45688
46129
|
let settled = false;
|
|
45689
46130
|
const settle = (result) => {
|
|
@@ -45694,7 +46135,7 @@ var sshTester = {
|
|
|
45694
46135
|
client.end();
|
|
45695
46136
|
} catch {
|
|
45696
46137
|
}
|
|
45697
|
-
|
|
46138
|
+
resolve3(result);
|
|
45698
46139
|
};
|
|
45699
46140
|
client.once("ready", () => {
|
|
45700
46141
|
client.exec("true", (err, stream) => {
|
|
@@ -45760,12 +46201,12 @@ function sanitizeResult(result, secret) {
|
|
|
45760
46201
|
|
|
45761
46202
|
// ../../packages/testers/dist/run.js
|
|
45762
46203
|
function withTimeout(promise, ms) {
|
|
45763
|
-
return new Promise((
|
|
46204
|
+
return new Promise((resolve3, reject) => {
|
|
45764
46205
|
const t = setTimeout(() => reject(new Error(`tester timed out after ${ms}ms`)), ms);
|
|
45765
46206
|
t.unref();
|
|
45766
46207
|
promise.then((v2) => {
|
|
45767
46208
|
clearTimeout(t);
|
|
45768
|
-
|
|
46209
|
+
resolve3(v2);
|
|
45769
46210
|
}, (err) => {
|
|
45770
46211
|
clearTimeout(t);
|
|
45771
46212
|
reject(err);
|
|
@@ -45999,10 +46440,9 @@ cli.register(MemberListCommand);
|
|
|
45999
46440
|
cli.register(AuditListCommand);
|
|
46000
46441
|
cli.register(AuditVerifyCommand);
|
|
46001
46442
|
cli.register(ExecCommand);
|
|
46443
|
+
cli.register(InitCommand);
|
|
46002
46444
|
cli.register(RedactCommand);
|
|
46003
46445
|
cli.register(RedactStreamCommand);
|
|
46004
|
-
cli.register(InstallCommand);
|
|
46005
|
-
cli.register(UninstallCommand);
|
|
46006
46446
|
cli.register(TestCommand);
|
|
46007
46447
|
cli.register(UICommand);
|
|
46008
46448
|
var argv = process.argv.slice(2);
|