@jango-blockchained/hoox-cli 0.5.1 → 0.5.2
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/package.json +1 -1
- package/src/commands/check/check-command.ts +8 -65
- package/src/commands/check/prerequisites-command.ts +7 -6
- package/src/commands/clone/clone-command.test.ts +8 -10
- package/src/commands/config/config-command.test.ts +4 -4
- package/src/commands/config/config-command.ts +10 -11
- package/src/commands/config/env-command.test.ts +2 -2
- package/src/commands/config/env-command.ts +40 -43
- package/src/commands/config/kv-command.ts +60 -60
- package/src/commands/dashboard/dashboard-command.ts +32 -30
- package/src/commands/db/db-command.ts +79 -80
- package/src/commands/deploy/deploy-command.test.ts +54 -34
- package/src/commands/deploy/deploy-command.ts +3 -84
- package/src/commands/dev/dev-command.test.ts +84 -62
- package/src/commands/disclaimer/disclaimer-command.ts +21 -0
- package/src/commands/disclaimer/index.ts +1 -0
- package/src/commands/init/init-command.test.ts +69 -91
- package/src/commands/init/init-command.ts +19 -15
- package/src/commands/logs/logs-command.test.ts +0 -1
- package/src/commands/monitor/monitor-command.test.ts +37 -29
- package/src/commands/repair/repair-command.test.ts +60 -41
- package/src/commands/repair/repair-service.ts +26 -0
- package/src/commands/schema/index.ts +1 -0
- package/src/commands/schema/schema-command.ts +137 -0
- package/src/commands/test/test-command.test.ts +2 -3
- package/src/commands/update/update-command.ts +6 -65
- package/src/commands/waf/waf-command.ts +56 -59
- package/src/index.ts +5 -13
- package/src/services/config/config-service.ts +1 -6
- package/src/services/db/db-service.test.ts +13 -1
- package/src/services/env/env-service.test.ts +41 -18
- package/src/services/env/env-service.ts +45 -59
- package/src/services/kv/kv-sync-service.ts +14 -5
- package/src/services/schema/index.ts +1 -0
- package/src/services/schema/schema-service.ts +99 -0
- package/src/services/secrets/secrets-service.test.ts +42 -35
- package/src/services/secrets/types.ts +1 -1
- package/src/ui/menu.ts +1 -1
- package/src/utils/error-handler.ts +62 -0
- package/src/utils/errors.ts +1 -0
- package/src/utils/git.ts +134 -0
- package/src/utils/theme.ts +0 -2
package/package.json
CHANGED
|
@@ -21,8 +21,10 @@ import {
|
|
|
21
21
|
formatSuccess,
|
|
22
22
|
formatError,
|
|
23
23
|
formatTable,
|
|
24
|
+
getFormatOptions,
|
|
24
25
|
} from "../../utils/formatters.js";
|
|
25
|
-
import {
|
|
26
|
+
import { ExitCode } from "../../utils/errors.js";
|
|
27
|
+
import { isGitTracked, gitUntrackFile } from "../../utils/git.js";
|
|
26
28
|
import type { FormatOptions } from "../../utils/formatters.js";
|
|
27
29
|
import type {
|
|
28
30
|
CheckResult,
|
|
@@ -104,13 +106,6 @@ function buildReport(categories: CheckCategory[]): CheckReport {
|
|
|
104
106
|
};
|
|
105
107
|
}
|
|
106
108
|
|
|
107
|
-
/**
|
|
108
|
-
* Return a single-character icon for a check result.
|
|
109
|
-
*/
|
|
110
|
-
function checkIcon(success: boolean): string {
|
|
111
|
-
return success ? icons.success : icons.error;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
109
|
// ---------------------------------------------------------------------------
|
|
115
110
|
// Submodule Gitignore Helpers
|
|
116
111
|
// ---------------------------------------------------------------------------
|
|
@@ -136,42 +131,6 @@ async function getWorkerDirs(): Promise<string[]> {
|
|
|
136
131
|
}
|
|
137
132
|
}
|
|
138
133
|
|
|
139
|
-
/**
|
|
140
|
-
* Check if a file or directory is tracked by git in a given directory.
|
|
141
|
-
*/
|
|
142
|
-
async function isGitTracked(dir: string, filename: string): Promise<boolean> {
|
|
143
|
-
try {
|
|
144
|
-
const proc = Bun.spawn(["git", "ls-files", "--error-unmatch", filename], {
|
|
145
|
-
cwd: dir,
|
|
146
|
-
stdout: "pipe",
|
|
147
|
-
stderr: "pipe",
|
|
148
|
-
});
|
|
149
|
-
const exitCode = await proc.exited;
|
|
150
|
-
return exitCode === 0;
|
|
151
|
-
} catch {
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Run git rm --cached to untrack a file while keeping it locally.
|
|
158
|
-
*/
|
|
159
|
-
async function gitUntrackFile(dir: string, filename: string): Promise<void> {
|
|
160
|
-
await new Promise<void>((resolve, reject) => {
|
|
161
|
-
const proc = Bun.spawn(["git", "rm", "--cached", filename], {
|
|
162
|
-
cwd: dir,
|
|
163
|
-
stdout: "pipe",
|
|
164
|
-
stderr: "pipe",
|
|
165
|
-
});
|
|
166
|
-
proc.exited
|
|
167
|
-
.then((code) => {
|
|
168
|
-
if (code === 0) resolve();
|
|
169
|
-
else reject(new Error(`git rm --cached failed with code ${code}`));
|
|
170
|
-
})
|
|
171
|
-
.catch(reject);
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
|
|
175
134
|
// ---------------------------------------------------------------------------
|
|
176
135
|
// Category 1: Config checks
|
|
177
136
|
// ---------------------------------------------------------------------------
|
|
@@ -871,7 +830,7 @@ interface SubmoduleGitignoreResult {
|
|
|
871
830
|
* - Untracks wrangler.jsonc if it's mistakenly tracked by git
|
|
872
831
|
*/
|
|
873
832
|
async function checkSubmoduleGitignore(
|
|
874
|
-
|
|
833
|
+
_opts: FormatOptions
|
|
875
834
|
): Promise<SubmoduleGitignoreResult> {
|
|
876
835
|
const workerDirs = await getWorkerDirs();
|
|
877
836
|
const issues: string[] = [];
|
|
@@ -1039,11 +998,7 @@ EXAMPLES:
|
|
|
1039
998
|
hoox check setup --json`
|
|
1040
999
|
)
|
|
1041
1000
|
.action(async (_, cmd: Command) => {
|
|
1042
|
-
const
|
|
1043
|
-
const opts: FormatOptions = {
|
|
1044
|
-
json: Boolean(rootCmd?.optsWithGlobals()?.json),
|
|
1045
|
-
quiet: Boolean(rootCmd?.optsWithGlobals()?.quiet),
|
|
1046
|
-
};
|
|
1001
|
+
const opts = getFormatOptions(cmd);
|
|
1047
1002
|
await handleSetup(opts);
|
|
1048
1003
|
});
|
|
1049
1004
|
|
|
@@ -1072,11 +1027,7 @@ EXAMPLES:
|
|
|
1072
1027
|
)
|
|
1073
1028
|
.option("--fix", "Attempt automatic repair for detected issues")
|
|
1074
1029
|
.action(async (options: { fix?: boolean }, cmd: Command) => {
|
|
1075
|
-
const
|
|
1076
|
-
const opts: FormatOptions = {
|
|
1077
|
-
json: Boolean(rootCmd?.optsWithGlobals()?.json),
|
|
1078
|
-
quiet: Boolean(rootCmd?.optsWithGlobals()?.quiet),
|
|
1079
|
-
};
|
|
1030
|
+
const opts = getFormatOptions(cmd);
|
|
1080
1031
|
await handleHealth(opts, Boolean(options.fix));
|
|
1081
1032
|
});
|
|
1082
1033
|
|
|
@@ -1101,11 +1052,7 @@ EXAMPLES:
|
|
|
1101
1052
|
)
|
|
1102
1053
|
.option("--dry-run", "Preview changes without applying them")
|
|
1103
1054
|
.action(async (options: { dryRun?: boolean }, cmd: Command) => {
|
|
1104
|
-
const
|
|
1105
|
-
const opts: FormatOptions = {
|
|
1106
|
-
json: Boolean(rootCmd?.optsWithGlobals()?.json),
|
|
1107
|
-
quiet: Boolean(rootCmd?.optsWithGlobals()?.quiet),
|
|
1108
|
-
};
|
|
1055
|
+
const opts = getFormatOptions(cmd);
|
|
1109
1056
|
await handleFix(opts, Boolean(options.dryRun));
|
|
1110
1057
|
});
|
|
1111
1058
|
|
|
@@ -1134,11 +1081,7 @@ EXAMPLES:
|
|
|
1134
1081
|
hoox check sg # alias`
|
|
1135
1082
|
)
|
|
1136
1083
|
.action(async (_, cmd: Command) => {
|
|
1137
|
-
const
|
|
1138
|
-
const opts: FormatOptions = {
|
|
1139
|
-
json: Boolean(rootCmd?.optsWithGlobals()?.json),
|
|
1140
|
-
quiet: Boolean(rootCmd?.optsWithGlobals()?.quiet),
|
|
1141
|
-
};
|
|
1084
|
+
const opts = getFormatOptions(cmd);
|
|
1142
1085
|
await handleSubmoduleGitignore(opts);
|
|
1143
1086
|
});
|
|
1144
1087
|
}
|
|
@@ -2,7 +2,11 @@ import { Command } from "commander";
|
|
|
2
2
|
import { PrerequisitesService } from "../../services/prerequisites/index.js";
|
|
3
3
|
import type { PrerequisitesReport } from "../../services/prerequisites/prerequisites-service.js";
|
|
4
4
|
import { theme, icons } from "../../utils/theme.js";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
getFormatOptions,
|
|
7
|
+
formatError,
|
|
8
|
+
formatJson,
|
|
9
|
+
} from "../../utils/formatters.js";
|
|
6
10
|
import { CLIError, ExitCode } from "../../utils/errors.js";
|
|
7
11
|
import type { FormatOptions } from "../../utils/formatters.js";
|
|
8
12
|
|
|
@@ -46,6 +50,7 @@ async function handlePrerequisites(
|
|
|
46
50
|
if (opts.json) {
|
|
47
51
|
formatJson(report, opts);
|
|
48
52
|
} else if (opts.quiet) {
|
|
53
|
+
// quiet mode — no output
|
|
49
54
|
} else {
|
|
50
55
|
renderReport(report);
|
|
51
56
|
}
|
|
@@ -86,11 +91,7 @@ EXAMPLES:
|
|
|
86
91
|
)
|
|
87
92
|
.option("--tool <name>", "Only check a specific tool")
|
|
88
93
|
.action(async (options: { tool?: string }, cmd: Command) => {
|
|
89
|
-
const
|
|
90
|
-
const opts: FormatOptions = {
|
|
91
|
-
json: Boolean(rootCmd?.optsWithGlobals()?.json),
|
|
92
|
-
quiet: Boolean(rootCmd?.optsWithGlobals()?.quiet),
|
|
93
|
-
};
|
|
94
|
+
const opts = getFormatOptions(cmd);
|
|
94
95
|
await handlePrerequisites(opts, options.tool);
|
|
95
96
|
});
|
|
96
97
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
/**
|
|
3
2
|
* Unit tests for the clone command.
|
|
4
3
|
*
|
|
@@ -27,7 +26,6 @@ type MockSpawnResult = {
|
|
|
27
26
|
|
|
28
27
|
const realSpawn = Bun.spawn;
|
|
29
28
|
let origCwd: string;
|
|
30
|
-
let lastSpawnCmd: string[] = [];
|
|
31
29
|
|
|
32
30
|
function successSpawn(stdout = ""): MockSpawnResult {
|
|
33
31
|
return {
|
|
@@ -57,9 +55,7 @@ function enqueueSpawn(result: MockSpawnResult): void {
|
|
|
57
55
|
}
|
|
58
56
|
|
|
59
57
|
function installSpawnMock(): void {
|
|
60
|
-
|
|
61
|
-
const spawnMock = mock((cmd: string[], _opts?: { cwd?: string }) => {
|
|
62
|
-
lastSpawnCmd = [...cmd];
|
|
58
|
+
const spawnMock = mock((_cmd: string[], _opts?: { cwd?: string }) => {
|
|
63
59
|
return spawnQueue.shift() ?? errorSpawn("unexpected spawn call", 127);
|
|
64
60
|
});
|
|
65
61
|
(Bun as Record<string, unknown>).spawn = spawnMock;
|
|
@@ -115,10 +111,12 @@ async function captureStdout(
|
|
|
115
111
|
|
|
116
112
|
let output = "";
|
|
117
113
|
const orig = process.stdout.write.bind(process.stdout);
|
|
118
|
-
(process.stdout as Record<string, unknown>).write = mock(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
114
|
+
(process.stdout as unknown as Record<string, unknown>).write = mock(
|
|
115
|
+
(chunk: string) => {
|
|
116
|
+
output += chunk;
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
);
|
|
122
120
|
|
|
123
121
|
try {
|
|
124
122
|
await program.parseAsync([...args], { from: "user" });
|
|
@@ -126,7 +124,7 @@ async function captureStdout(
|
|
|
126
124
|
// exitOverride throws CommanderError — swallow
|
|
127
125
|
}
|
|
128
126
|
|
|
129
|
-
(process.stdout as Record<string, unknown>).write = orig;
|
|
127
|
+
(process.stdout as unknown as Record<string, unknown>).write = orig;
|
|
130
128
|
process.chdir(origCwd);
|
|
131
129
|
return output;
|
|
132
130
|
}
|
|
@@ -508,10 +508,10 @@ describe("config keys", () => {
|
|
|
508
508
|
expect(text).toContain(".keys/");
|
|
509
509
|
|
|
510
510
|
// Verify files were created
|
|
511
|
-
const internalKeyFile = Bun.file(".keys/
|
|
511
|
+
const internalKeyFile = Bun.file(".keys/internal_key_binding.env");
|
|
512
512
|
expect(await internalKeyFile.exists()).toBe(true);
|
|
513
513
|
const content = await internalKeyFile.text();
|
|
514
|
-
expect(content).toMatch(/^
|
|
514
|
+
expect(content).toMatch(/^INTERNAL_KEY_BINDING=[a-f0-9]{64}\n$/);
|
|
515
515
|
});
|
|
516
516
|
|
|
517
517
|
it("lists generated key files", async () => {
|
|
@@ -572,10 +572,10 @@ describe("config keys", () => {
|
|
|
572
572
|
const capture = await runCommand(program, ["config", "keys", "generate"]);
|
|
573
573
|
capture.restore();
|
|
574
574
|
|
|
575
|
-
const file = Bun.file(".keys/
|
|
575
|
+
const file = Bun.file(".keys/webhook_api_key_binding.env");
|
|
576
576
|
expect(await file.exists()).toBe(true);
|
|
577
577
|
const content = await file.text();
|
|
578
|
-
const match = content.match(/^
|
|
578
|
+
const match = content.match(/^WEBHOOK_API_KEY_BINDING=([a-f0-9]+)\n$/);
|
|
579
579
|
expect(match).not.toBeNull();
|
|
580
580
|
// Service keys are 32 bytes = 64 hex chars
|
|
581
581
|
expect(match![1].length).toBe(64);
|
|
@@ -204,7 +204,7 @@ EXAMPLES:
|
|
|
204
204
|
hoox config show Display current configuration
|
|
205
205
|
hoox config set workers.agent-worker.enabled false
|
|
206
206
|
hoox config secrets list List secrets for a worker
|
|
207
|
-
hoox config secrets set trade-worker
|
|
207
|
+
hoox config secrets set trade-worker BINANCE_KEY_BINDING
|
|
208
208
|
hoox config keys generate Generate new internal keys`
|
|
209
209
|
);
|
|
210
210
|
|
|
@@ -454,7 +454,7 @@ The command will prompt for the secret value (hidden input).
|
|
|
454
454
|
It writes to the worker's .dev.vars file and syncs to Cloudflare.
|
|
455
455
|
|
|
456
456
|
EXAMPLES:
|
|
457
|
-
hoox config secrets set trade-worker
|
|
457
|
+
hoox config secrets set trade-worker BINANCE_KEY_BINDING
|
|
458
458
|
hoox config secrets set agent-worker OPENAI_KEY`
|
|
459
459
|
)
|
|
460
460
|
.action(async (workerName: string, secretName: string) => {
|
|
@@ -529,7 +529,7 @@ ARGUMENTS:
|
|
|
529
529
|
This removes the secret from Cloudflare and from the worker's .dev.vars file.
|
|
530
530
|
|
|
531
531
|
EXAMPLES:
|
|
532
|
-
hoox config secrets delete trade-worker
|
|
532
|
+
hoox config secrets delete trade-worker BINANCE_KEY_BINDING`
|
|
533
533
|
)
|
|
534
534
|
.action(async (workerName: string, secretName: string) => {
|
|
535
535
|
const opts = formatOpts(program);
|
|
@@ -718,11 +718,11 @@ EXAMPLES:
|
|
|
718
718
|
`Generate new internal auth keys and save to .keys/ directory.
|
|
719
719
|
|
|
720
720
|
Creates the following keys:
|
|
721
|
-
-
|
|
722
|
-
-
|
|
721
|
+
- INTERNAL_KEY_BINDING (32 char)
|
|
722
|
+
- WEBHOOK_API_KEY_BINDING (32 char)
|
|
723
723
|
- AGENT_INTERNAL_KEY (32 char)
|
|
724
|
-
-
|
|
725
|
-
-
|
|
724
|
+
- TG_BOT_TOKEN_BINDING (16 char)
|
|
725
|
+
- INTERNAL_KEY_BINDING (32 char)
|
|
726
726
|
|
|
727
727
|
WARNING: Add .keys/ to your .gitignore to avoid committing secrets!
|
|
728
728
|
|
|
@@ -739,11 +739,10 @@ EXAMPLES:
|
|
|
739
739
|
}
|
|
740
740
|
|
|
741
741
|
const keys: Record<string, string> = {
|
|
742
|
-
|
|
743
|
-
|
|
742
|
+
INTERNAL_KEY_BINDING: generateKey(),
|
|
743
|
+
WEBHOOK_API_KEY_BINDING: generateKey(),
|
|
744
744
|
AGENT_INTERNAL_KEY: generateKey(),
|
|
745
|
-
|
|
746
|
-
INTERNAL_KEY: generateKey(),
|
|
745
|
+
TG_BOT_TOKEN_BINDING: generateKey(16),
|
|
747
746
|
};
|
|
748
747
|
|
|
749
748
|
for (const [name, value] of Object.entries(keys)) {
|
|
@@ -14,12 +14,12 @@ describe("env command", () => {
|
|
|
14
14
|
CLOUDFLARE_API_TOKEN: "cfut_xxx",
|
|
15
15
|
CLOUDFLARE_ACCOUNT_ID: "abc123",
|
|
16
16
|
SUBDOMAIN_PREFIX: "myapp",
|
|
17
|
-
D1_INTERNAL_KEY: "d1-key",
|
|
18
17
|
TRADE_INTERNAL_KEY: "trade-key",
|
|
19
18
|
AGENT_INTERNAL_KEY: "agent-key",
|
|
20
19
|
WEBHOOK_API_KEY_BINDING: "webhook-key",
|
|
21
20
|
INTERNAL_KEY_BINDING: "inter-key",
|
|
22
|
-
|
|
21
|
+
API_SERVICE_KEY_BINDING: "api-key",
|
|
22
|
+
TELEGRAM_INTERNAL_KEY: "tg-key",
|
|
23
23
|
DASHBOARD_USER: "admin",
|
|
24
24
|
DASHBOARD_PASS: "pass123",
|
|
25
25
|
SESSION_SECRET: "a".repeat(32),
|
|
@@ -13,11 +13,8 @@ import * as p from "@clack/prompts";
|
|
|
13
13
|
|
|
14
14
|
import { EnvService } from "../../services/env/index.js";
|
|
15
15
|
import { CLIError, ExitCode } from "../../utils/errors.js";
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
formatError,
|
|
19
|
-
formatJson,
|
|
20
|
-
} from "../../utils/formatters.js";
|
|
16
|
+
import { formatSuccess, formatJson } from "../../utils/formatters.js";
|
|
17
|
+
import { withErrorHandling } from "../../utils/error-handler.js";
|
|
21
18
|
import type { FormatOptions } from "../../utils/formatters.js";
|
|
22
19
|
|
|
23
20
|
// ---------------------------------------------------------------------------
|
|
@@ -50,7 +47,7 @@ async function handleInit(opts: FormatOptions): Promise<void> {
|
|
|
50
47
|
});
|
|
51
48
|
if (p.isCancel(overwrite)) {
|
|
52
49
|
p.cancel("Setup cancelled.");
|
|
53
|
-
process.
|
|
50
|
+
process.exitCode = 0;
|
|
54
51
|
}
|
|
55
52
|
if (!overwrite) {
|
|
56
53
|
p.outro("Setup cancelled. Existing .env.local preserved.");
|
|
@@ -89,7 +86,7 @@ async function handleInit(opts: FormatOptions): Promise<void> {
|
|
|
89
86
|
}
|
|
90
87
|
if (p.isCancel(value)) {
|
|
91
88
|
p.cancel("Setup cancelled.");
|
|
92
|
-
process.
|
|
89
|
+
process.exitCode = 0;
|
|
93
90
|
}
|
|
94
91
|
collected[def.name] = typeof value === "string" ? value : "";
|
|
95
92
|
}
|
|
@@ -244,52 +241,52 @@ EXAMPLES:
|
|
|
244
241
|
envCmd
|
|
245
242
|
.command("init")
|
|
246
243
|
.description("Interactive wizard to generate .env.local and .dev.vars")
|
|
247
|
-
.action(
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
244
|
+
.action(
|
|
245
|
+
withErrorHandling(
|
|
246
|
+
async (_, cmd: Command) => {
|
|
247
|
+
const opts = formatOpts(cmd);
|
|
248
|
+
await handleInit(opts);
|
|
249
|
+
},
|
|
250
|
+
{ service: "env" }
|
|
251
|
+
)
|
|
252
|
+
);
|
|
256
253
|
|
|
257
254
|
envCmd
|
|
258
255
|
.command("show")
|
|
259
256
|
.description("Display current .env.local (secrets redacted)")
|
|
260
|
-
.action(
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
257
|
+
.action(
|
|
258
|
+
withErrorHandling(
|
|
259
|
+
async (_, cmd: Command) => {
|
|
260
|
+
const opts = formatOpts(cmd);
|
|
261
|
+
await handleShow(opts);
|
|
262
|
+
},
|
|
263
|
+
{ service: "env" }
|
|
264
|
+
)
|
|
265
|
+
);
|
|
269
266
|
|
|
270
267
|
envCmd
|
|
271
268
|
.command("validate")
|
|
272
269
|
.description("Check required environment variables")
|
|
273
|
-
.action(
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
270
|
+
.action(
|
|
271
|
+
withErrorHandling(
|
|
272
|
+
async (_, cmd: Command) => {
|
|
273
|
+
const opts = formatOpts(cmd);
|
|
274
|
+
await handleValidate(opts);
|
|
275
|
+
},
|
|
276
|
+
{ service: "env" }
|
|
277
|
+
)
|
|
278
|
+
);
|
|
282
279
|
|
|
283
280
|
envCmd
|
|
284
281
|
.command("generate-dev-vars")
|
|
285
282
|
.description("Create per-worker .dev.vars from .env.local")
|
|
286
|
-
.action(
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
283
|
+
.action(
|
|
284
|
+
withErrorHandling(
|
|
285
|
+
async (_, cmd: Command) => {
|
|
286
|
+
const opts = formatOpts(cmd);
|
|
287
|
+
await handleGenerateDevVars(opts);
|
|
288
|
+
},
|
|
289
|
+
{ service: "env" }
|
|
290
|
+
)
|
|
291
|
+
);
|
|
295
292
|
}
|
|
@@ -14,11 +14,11 @@ import { Command } from "commander";
|
|
|
14
14
|
import { KvSyncService } from "../../services/kv/index.js";
|
|
15
15
|
import {
|
|
16
16
|
formatSuccess,
|
|
17
|
-
formatError,
|
|
18
17
|
formatTable,
|
|
19
18
|
formatJson,
|
|
20
19
|
} from "../../utils/formatters.js";
|
|
21
20
|
import { CLIError, ExitCode } from "../../utils/errors.js";
|
|
21
|
+
import { withErrorHandling } from "../../utils/error-handler.js";
|
|
22
22
|
import { theme } from "../../utils/theme.js";
|
|
23
23
|
import type { FormatOptions } from "../../utils/formatters.js";
|
|
24
24
|
|
|
@@ -203,88 +203,88 @@ EXAMPLES:
|
|
|
203
203
|
kvCmd
|
|
204
204
|
.command("list")
|
|
205
205
|
.description("List all keys in the KV namespace")
|
|
206
|
-
.action(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
206
|
+
.action(
|
|
207
|
+
withErrorHandling(
|
|
208
|
+
async (_, cmd: Command) => {
|
|
209
|
+
const opts = formatOpts(cmd);
|
|
210
|
+
const nsId = await resolveNs(cmd);
|
|
211
|
+
await handleList(opts, nsId);
|
|
212
|
+
},
|
|
213
|
+
{ service: "kv" }
|
|
214
|
+
)
|
|
215
|
+
);
|
|
216
216
|
|
|
217
217
|
// -- get
|
|
218
218
|
kvCmd
|
|
219
219
|
.command("get <key>")
|
|
220
220
|
.description("Get a key's value from the KV namespace")
|
|
221
|
-
.action(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
221
|
+
.action(
|
|
222
|
+
withErrorHandling(
|
|
223
|
+
async (key: string, _, cmd: Command) => {
|
|
224
|
+
const opts = formatOpts(cmd);
|
|
225
|
+
const nsId = await resolveNs(cmd);
|
|
226
|
+
await handleGet(opts, nsId, key);
|
|
227
|
+
},
|
|
228
|
+
{ service: "kv" }
|
|
229
|
+
)
|
|
230
|
+
);
|
|
231
231
|
|
|
232
232
|
// -- set
|
|
233
233
|
kvCmd
|
|
234
234
|
.command("set <key> <value>")
|
|
235
235
|
.description("Set a key's value in the KV namespace")
|
|
236
|
-
.action(
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
236
|
+
.action(
|
|
237
|
+
withErrorHandling(
|
|
238
|
+
async (key: string, value: string, _, cmd: Command) => {
|
|
239
|
+
const opts = formatOpts(cmd);
|
|
240
|
+
const nsId = await resolveNs(cmd);
|
|
241
|
+
await handleSet(opts, nsId, key, value);
|
|
242
|
+
},
|
|
243
|
+
{ service: "kv" }
|
|
244
|
+
)
|
|
245
|
+
);
|
|
246
246
|
|
|
247
247
|
// -- delete
|
|
248
248
|
kvCmd
|
|
249
249
|
.command("delete <key>")
|
|
250
250
|
.description("Delete a key from the KV namespace")
|
|
251
|
-
.action(
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
251
|
+
.action(
|
|
252
|
+
withErrorHandling(
|
|
253
|
+
async (key: string, _, cmd: Command) => {
|
|
254
|
+
const opts = formatOpts(cmd);
|
|
255
|
+
const nsId = await resolveNs(cmd);
|
|
256
|
+
await handleDelete(opts, nsId, key);
|
|
257
|
+
},
|
|
258
|
+
{ service: "kv" }
|
|
259
|
+
)
|
|
260
|
+
);
|
|
261
261
|
|
|
262
262
|
// -- apply-manifest
|
|
263
263
|
kvCmd
|
|
264
264
|
.command("apply-manifest")
|
|
265
265
|
.description("Apply manifest key defaults to the KV namespace")
|
|
266
|
-
.action(
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
266
|
+
.action(
|
|
267
|
+
withErrorHandling(
|
|
268
|
+
async (_, cmd: Command) => {
|
|
269
|
+
const opts = formatOpts(cmd);
|
|
270
|
+
const nsId = await resolveNs(cmd);
|
|
271
|
+
await handleApplyManifest(opts, nsId);
|
|
272
|
+
},
|
|
273
|
+
{ service: "kv" }
|
|
274
|
+
)
|
|
275
|
+
);
|
|
276
276
|
|
|
277
277
|
// -- manifest
|
|
278
278
|
kvCmd
|
|
279
279
|
.command("manifest")
|
|
280
280
|
.description("Show expected KV keys from manifest")
|
|
281
|
-
.action(
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
281
|
+
.action(
|
|
282
|
+
withErrorHandling(
|
|
283
|
+
async (_, cmd: Command) => {
|
|
284
|
+
const opts = formatOpts(cmd);
|
|
285
|
+
await handleManifest(opts);
|
|
286
|
+
},
|
|
287
|
+
{ service: "kv" }
|
|
288
|
+
)
|
|
289
|
+
);
|
|
290
290
|
}
|