@hoox-sh/hoox-cli 0.11.3 → 0.11.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +259 -108
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -25548,6 +25548,33 @@ var init_cloudflare_service = __esm(() => {
|
|
|
25548
25548
|
init_wrangler_output();
|
|
25549
25549
|
});
|
|
25550
25550
|
|
|
25551
|
+
// src/utils/fs-secure.ts
|
|
25552
|
+
var exports_fs_secure = {};
|
|
25553
|
+
__export(exports_fs_secure, {
|
|
25554
|
+
secureSecretFile: () => secureSecretFile,
|
|
25555
|
+
secureChmod: () => secureChmod,
|
|
25556
|
+
ensureSecretDir: () => ensureSecretDir,
|
|
25557
|
+
SECRET_FILE_MODE: () => SECRET_FILE_MODE,
|
|
25558
|
+
SECRET_DIR_MODE: () => SECRET_DIR_MODE
|
|
25559
|
+
});
|
|
25560
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync3 } from "fs";
|
|
25561
|
+
function secureChmod(path4, mode) {
|
|
25562
|
+
try {
|
|
25563
|
+
chmodSync3(path4, mode);
|
|
25564
|
+
} catch {}
|
|
25565
|
+
}
|
|
25566
|
+
function ensureSecretDir(dir) {
|
|
25567
|
+
try {
|
|
25568
|
+
mkdirSync3(dir, { recursive: true, mode: SECRET_DIR_MODE });
|
|
25569
|
+
} catch {}
|
|
25570
|
+
secureChmod(dir, SECRET_DIR_MODE);
|
|
25571
|
+
}
|
|
25572
|
+
function secureSecretFile(path4) {
|
|
25573
|
+
secureChmod(path4, SECRET_FILE_MODE);
|
|
25574
|
+
}
|
|
25575
|
+
var SECRET_FILE_MODE = 384, SECRET_DIR_MODE = 448;
|
|
25576
|
+
var init_fs_secure = () => {};
|
|
25577
|
+
|
|
25551
25578
|
// src/services/prerequisites/prerequisites-service.ts
|
|
25552
25579
|
class PrerequisitesService {
|
|
25553
25580
|
MINIMUM_WRANGLER = "3.88.0";
|
|
@@ -28583,6 +28610,10 @@ function formatSuccess(message, opts) {
|
|
|
28583
28610
|
function formatError2(error51, opts = {}) {
|
|
28584
28611
|
const message = typeof error51 === "string" ? error51 : error51.message;
|
|
28585
28612
|
const cliError = error51 instanceof CLIError ? error51 : null;
|
|
28613
|
+
const write = (s) => {
|
|
28614
|
+
process.stderr.write(s);
|
|
28615
|
+
process.stdout.write(s);
|
|
28616
|
+
};
|
|
28586
28617
|
if (opts.json) {
|
|
28587
28618
|
const output = {
|
|
28588
28619
|
success: false,
|
|
@@ -28596,12 +28627,12 @@ function formatError2(error51, opts = {}) {
|
|
|
28596
28627
|
if (opts.suggestions && opts.suggestions.length > 0) {
|
|
28597
28628
|
output.suggestions = opts.suggestions;
|
|
28598
28629
|
}
|
|
28599
|
-
|
|
28630
|
+
write(JSON.stringify(output) + `
|
|
28600
28631
|
`);
|
|
28601
28632
|
return;
|
|
28602
28633
|
}
|
|
28603
28634
|
if (opts.quiet) {
|
|
28604
|
-
|
|
28635
|
+
write(`${message}
|
|
28605
28636
|
`);
|
|
28606
28637
|
return;
|
|
28607
28638
|
}
|
|
@@ -28611,13 +28642,13 @@ function formatError2(error51, opts = {}) {
|
|
|
28611
28642
|
titleParts.push(theme.textSubtle(`[${cliError.code}]`));
|
|
28612
28643
|
}
|
|
28613
28644
|
titleParts.push(theme.text(message));
|
|
28614
|
-
|
|
28645
|
+
write(`${titleParts.join(" ")}
|
|
28615
28646
|
`);
|
|
28616
28647
|
if (cliError?.details) {
|
|
28617
28648
|
const detailLines = cliError.details.split(`
|
|
28618
28649
|
`).filter((l) => l.length > 0);
|
|
28619
28650
|
for (const line of detailLines) {
|
|
28620
|
-
|
|
28651
|
+
write(` ${theme.textMuted(line)}
|
|
28621
28652
|
`);
|
|
28622
28653
|
}
|
|
28623
28654
|
}
|
|
@@ -28625,24 +28656,24 @@ function formatError2(error51, opts = {}) {
|
|
|
28625
28656
|
const hasSuggestions = !!opts.suggestions && opts.suggestions.length > 0;
|
|
28626
28657
|
if (hasHint || hasSuggestions) {
|
|
28627
28658
|
if (inCard) {
|
|
28628
|
-
|
|
28659
|
+
write(` ${theme.border(icons.pipe)}
|
|
28629
28660
|
`);
|
|
28630
28661
|
}
|
|
28631
28662
|
if (hasHint) {
|
|
28632
|
-
|
|
28663
|
+
write(` ${inCard ? theme.border(icons.pipe) : " "} ${theme.dim("\u21B3 hint:")} ${theme.value(cliError.hint)}
|
|
28633
28664
|
`);
|
|
28634
28665
|
}
|
|
28635
28666
|
if (hasSuggestions) {
|
|
28636
28667
|
const sugText = opts.suggestions.map((s) => `'${s}'`).join(", ");
|
|
28637
|
-
|
|
28668
|
+
write(` ${inCard ? theme.border(icons.pipe) : " "} ${theme.dim("did you mean:")} ${theme.accent(sugText)} ${theme.dim("?")}
|
|
28638
28669
|
`);
|
|
28639
28670
|
}
|
|
28640
28671
|
if (inCard) {
|
|
28641
|
-
|
|
28672
|
+
write(` ${theme.border(icons.pipe)}
|
|
28642
28673
|
`);
|
|
28643
28674
|
}
|
|
28644
28675
|
} else if (inCard && !cliError?.details) {
|
|
28645
|
-
|
|
28676
|
+
write(` ${theme.border(icons.pipe)}
|
|
28646
28677
|
`);
|
|
28647
28678
|
}
|
|
28648
28679
|
}
|
|
@@ -29189,6 +29220,8 @@ async function createDevVars(config2, secrets, opts) {
|
|
|
29189
29220
|
const dir = `${worker.path}`;
|
|
29190
29221
|
try {
|
|
29191
29222
|
await Bun.write(filePath, content);
|
|
29223
|
+
const { secureSecretFile: secureSecretFile2 } = await Promise.resolve().then(() => (init_fs_secure(), exports_fs_secure));
|
|
29224
|
+
secureSecretFile2(filePath);
|
|
29192
29225
|
if (!opts?.quiet) {
|
|
29193
29226
|
formatSuccess(`Created ${filePath}`, opts);
|
|
29194
29227
|
}
|
|
@@ -29196,6 +29229,8 @@ async function createDevVars(config2, secrets, opts) {
|
|
|
29196
29229
|
const { mkdir } = await import("fs/promises");
|
|
29197
29230
|
await mkdir(dir, { recursive: true });
|
|
29198
29231
|
await Bun.write(filePath, content);
|
|
29232
|
+
const { secureSecretFile: secureSecretFile2 } = await Promise.resolve().then(() => (init_fs_secure(), exports_fs_secure));
|
|
29233
|
+
secureSecretFile2(filePath);
|
|
29199
29234
|
if (!opts?.quiet) {
|
|
29200
29235
|
formatSuccess(`Created ${filePath}`, opts);
|
|
29201
29236
|
}
|
|
@@ -29586,9 +29621,10 @@ async function runInitCommand(options, globalOpts, isNonInteractive) {
|
|
|
29586
29621
|
}
|
|
29587
29622
|
// src/services/setup/setup-service.ts
|
|
29588
29623
|
import {
|
|
29589
|
-
chmodSync as
|
|
29624
|
+
chmodSync as chmodSync4,
|
|
29590
29625
|
existsSync as existsSync7,
|
|
29591
|
-
mkdirSync as
|
|
29626
|
+
mkdirSync as mkdirSync4,
|
|
29627
|
+
readdirSync as readdirSync3,
|
|
29592
29628
|
readFileSync as readFileSync3,
|
|
29593
29629
|
statSync as statSync2,
|
|
29594
29630
|
writeFileSync as writeFileSync2
|
|
@@ -29663,9 +29699,38 @@ function parseEnvFile(text2) {
|
|
|
29663
29699
|
}
|
|
29664
29700
|
function safeChmod(path4, mode) {
|
|
29665
29701
|
try {
|
|
29666
|
-
|
|
29702
|
+
chmodSync4(path4, mode);
|
|
29667
29703
|
} catch {}
|
|
29668
29704
|
}
|
|
29705
|
+
function loadExistingKeysFromDisk() {
|
|
29706
|
+
const setupEnv = join7(KEYS_DIR, "setup.env");
|
|
29707
|
+
if (!existsSync7(setupEnv))
|
|
29708
|
+
return null;
|
|
29709
|
+
let text2;
|
|
29710
|
+
try {
|
|
29711
|
+
text2 = readFileSync3(setupEnv, "utf-8");
|
|
29712
|
+
} catch {
|
|
29713
|
+
return null;
|
|
29714
|
+
}
|
|
29715
|
+
const map2 = parseEnvFile(text2);
|
|
29716
|
+
const required2 = [
|
|
29717
|
+
"INTERNAL_KEY_BINDING",
|
|
29718
|
+
"AGENT_INTERNAL_KEY",
|
|
29719
|
+
"SESSION_SECRET",
|
|
29720
|
+
"WEBHOOK_API_KEY_BINDING",
|
|
29721
|
+
"TELEGRAM_INTERNAL_KEY_BINDING",
|
|
29722
|
+
"TRADE_INTERNAL_KEY",
|
|
29723
|
+
"API_SERVICE_KEY_BINDING"
|
|
29724
|
+
];
|
|
29725
|
+
const keys = {};
|
|
29726
|
+
for (const name of required2) {
|
|
29727
|
+
const v = map2.get(name);
|
|
29728
|
+
if (!v)
|
|
29729
|
+
return null;
|
|
29730
|
+
keys[name] = v;
|
|
29731
|
+
}
|
|
29732
|
+
return keys;
|
|
29733
|
+
}
|
|
29669
29734
|
|
|
29670
29735
|
class SetupService {
|
|
29671
29736
|
onProgress;
|
|
@@ -29676,7 +29741,20 @@ class SetupService {
|
|
|
29676
29741
|
}
|
|
29677
29742
|
async generateKeys(skip = false) {
|
|
29678
29743
|
if (skip) {
|
|
29679
|
-
|
|
29744
|
+
const existing = loadExistingKeysFromDisk();
|
|
29745
|
+
if (existing) {
|
|
29746
|
+
this.onProgress({
|
|
29747
|
+
type: "info",
|
|
29748
|
+
step: "keys",
|
|
29749
|
+
message: "Using existing keys from .keys/setup.env (--skip-keys)"
|
|
29750
|
+
});
|
|
29751
|
+
return existing;
|
|
29752
|
+
}
|
|
29753
|
+
this.onProgress({
|
|
29754
|
+
type: "info",
|
|
29755
|
+
step: "keys",
|
|
29756
|
+
message: "Skipped (no existing .keys/setup.env)"
|
|
29757
|
+
});
|
|
29680
29758
|
return null;
|
|
29681
29759
|
}
|
|
29682
29760
|
this.onProgress({
|
|
@@ -29695,9 +29773,9 @@ class SetupService {
|
|
|
29695
29773
|
API_SERVICE_KEY_BINDING: internalKey
|
|
29696
29774
|
};
|
|
29697
29775
|
if (!existsSync7(KEYS_DIR)) {
|
|
29698
|
-
|
|
29776
|
+
mkdirSync4(KEYS_DIR, { recursive: true });
|
|
29699
29777
|
} else if (!statSync2(KEYS_DIR).isDirectory()) {
|
|
29700
|
-
|
|
29778
|
+
mkdirSync4(KEYS_DIR, { recursive: true });
|
|
29701
29779
|
}
|
|
29702
29780
|
safeChmod(KEYS_DIR, 448);
|
|
29703
29781
|
const setupEnvPath = join7(KEYS_DIR, "setup.env");
|
|
@@ -30071,36 +30149,38 @@ class SetupService {
|
|
|
30071
30149
|
];
|
|
30072
30150
|
return markers.some((p3) => existsSync7(p3));
|
|
30073
30151
|
}
|
|
30074
|
-
|
|
30075
|
-
this.onProgress({
|
|
30076
|
-
type: "step-start",
|
|
30077
|
-
step: "workers",
|
|
30078
|
-
message: "Checking worker submodules..."
|
|
30079
|
-
});
|
|
30152
|
+
listMissingWorkers() {
|
|
30080
30153
|
const workerDirs = [
|
|
30081
30154
|
...ALL_WORKERS,
|
|
30082
30155
|
...TOOLING_WORKERS,
|
|
30083
30156
|
"dashboard"
|
|
30084
30157
|
];
|
|
30085
30158
|
const missing = [];
|
|
30086
|
-
const gitmodulesPath = ".gitmodules";
|
|
30087
30159
|
for (const name of workerDirs) {
|
|
30088
30160
|
const dir = `workers/${workerFsDir(name)}`;
|
|
30089
30161
|
try {
|
|
30090
30162
|
const gitEntry = readFileSync3(join7(dir, ".git"), "utf-8").trim();
|
|
30091
30163
|
if (gitEntry.startsWith("gitdir:") || gitEntry.length > 0) {
|
|
30092
|
-
if (!this.isWorkerTreePopulated(dir, name))
|
|
30164
|
+
if (!this.isWorkerTreePopulated(dir, name))
|
|
30093
30165
|
missing.push(name);
|
|
30094
|
-
}
|
|
30095
30166
|
} else if (!this.isWorkerTreePopulated(dir, name)) {
|
|
30096
30167
|
missing.push(name);
|
|
30097
30168
|
}
|
|
30098
30169
|
} catch {
|
|
30099
|
-
if (!this.isWorkerTreePopulated(dir, name))
|
|
30170
|
+
if (!this.isWorkerTreePopulated(dir, name))
|
|
30100
30171
|
missing.push(name);
|
|
30101
|
-
}
|
|
30102
30172
|
}
|
|
30103
30173
|
}
|
|
30174
|
+
return missing;
|
|
30175
|
+
}
|
|
30176
|
+
async ensureWorkers() {
|
|
30177
|
+
this.onProgress({
|
|
30178
|
+
type: "step-start",
|
|
30179
|
+
step: "workers",
|
|
30180
|
+
message: "Checking worker submodules..."
|
|
30181
|
+
});
|
|
30182
|
+
const missing = this.listMissingWorkers();
|
|
30183
|
+
const gitmodulesPath = ".gitmodules";
|
|
30104
30184
|
if (missing.length === 0) {
|
|
30105
30185
|
this.onProgress({
|
|
30106
30186
|
type: "step-complete",
|
|
@@ -30155,14 +30235,17 @@ class SetupService {
|
|
|
30155
30235
|
];
|
|
30156
30236
|
const toBuild = [];
|
|
30157
30237
|
for (const pkg of packages) {
|
|
30238
|
+
let built = false;
|
|
30158
30239
|
try {
|
|
30159
|
-
|
|
30160
|
-
|
|
30161
|
-
|
|
30240
|
+
if (existsSync7(pkg.dist) && statSync2(pkg.dist).isDirectory()) {
|
|
30241
|
+
const entries = readdirSync3(pkg.dist);
|
|
30242
|
+
built = entries.some((e) => e.endsWith(".js"));
|
|
30162
30243
|
}
|
|
30163
30244
|
} catch {
|
|
30164
|
-
|
|
30245
|
+
built = false;
|
|
30165
30246
|
}
|
|
30247
|
+
if (!built)
|
|
30248
|
+
toBuild.push(pkg.name);
|
|
30166
30249
|
}
|
|
30167
30250
|
if (toBuild.length === 0) {
|
|
30168
30251
|
this.onProgress({
|
|
@@ -30479,13 +30562,21 @@ class SetupService {
|
|
|
30479
30562
|
results.success = false;
|
|
30480
30563
|
return results;
|
|
30481
30564
|
}
|
|
30482
|
-
const
|
|
30483
|
-
|
|
30565
|
+
const missingAfterClone = await this.ensureWorkers();
|
|
30566
|
+
const stillMissing = this.listMissingWorkers();
|
|
30567
|
+
if (stillMissing.length > 0) {
|
|
30568
|
+
steps.push({
|
|
30569
|
+
step: "workers",
|
|
30570
|
+
success: false,
|
|
30571
|
+
message: `Missing worker trees: ${stillMissing.join(", ")}. Run: git submodule update --init --recursive`
|
|
30572
|
+
});
|
|
30484
30573
|
this.onProgress({
|
|
30485
|
-
type: "
|
|
30574
|
+
type: "step-error",
|
|
30486
30575
|
step: "workers",
|
|
30487
|
-
message: "
|
|
30576
|
+
message: missingAfterClone.length > 0 ? "Workers still missing after clone attempt \u2014 aborting setup." : "Workers missing \u2014 aborting setup."
|
|
30488
30577
|
});
|
|
30578
|
+
results.success = false;
|
|
30579
|
+
return results;
|
|
30489
30580
|
}
|
|
30490
30581
|
const built = await this.ensurePackages();
|
|
30491
30582
|
if (!built) {
|
|
@@ -30494,6 +30585,8 @@ class SetupService {
|
|
|
30494
30585
|
success: false,
|
|
30495
30586
|
message: "Package build failed \u2014 check dependencies"
|
|
30496
30587
|
});
|
|
30588
|
+
results.success = false;
|
|
30589
|
+
return results;
|
|
30497
30590
|
}
|
|
30498
30591
|
this.fixWranglerConfigs();
|
|
30499
30592
|
const keys = await this.generateKeys(options.skipKeys);
|
|
@@ -30644,6 +30737,14 @@ async function runOnboard(options, fmt) {
|
|
|
30644
30737
|
if (process.exitCode && process.exitCode !== 0) {
|
|
30645
30738
|
return;
|
|
30646
30739
|
}
|
|
30740
|
+
const configReady = await Bun.file("wrangler.jsonc").exists();
|
|
30741
|
+
if (!configReady) {
|
|
30742
|
+
if (!quiet) {
|
|
30743
|
+
formatError2(new CLIError("Onboard stopped: workspace config was not written (init cancelled or incomplete).", 1 /* ERROR */, undefined, false, "Re-run `hoox onboard` or `hoox init` to finish configuration, then `hoox setup`."), fmt);
|
|
30744
|
+
}
|
|
30745
|
+
process.exitCode = 1 /* ERROR */;
|
|
30746
|
+
return;
|
|
30747
|
+
}
|
|
30647
30748
|
if (options.token) {
|
|
30648
30749
|
process.env.CLOUDFLARE_API_TOKEN = options.token;
|
|
30649
30750
|
}
|
|
@@ -33130,6 +33231,8 @@ async function handleInit(opts) {
|
|
|
33130
33231
|
await Bun.write(tmpPath, envContent);
|
|
33131
33232
|
await Bun.write(".env.local", envContent);
|
|
33132
33233
|
await Bun.file(tmpPath).delete().catch(() => {});
|
|
33234
|
+
const { secureSecretFile: secureSecretFile2 } = await Promise.resolve().then(() => (init_fs_secure(), exports_fs_secure));
|
|
33235
|
+
secureSecretFile2(".env.local");
|
|
33133
33236
|
if (!opts.quiet)
|
|
33134
33237
|
formatSuccess(".env.local written", opts);
|
|
33135
33238
|
log.step("Writing .dev.vars files...");
|
|
@@ -33144,6 +33247,8 @@ async function handleInit(opts) {
|
|
|
33144
33247
|
].join(`
|
|
33145
33248
|
`);
|
|
33146
33249
|
await Bun.write(`${workerPath}/.dev.vars`, content);
|
|
33250
|
+
const { secureSecretFile: chmodDev } = await Promise.resolve().then(() => (init_fs_secure(), exports_fs_secure));
|
|
33251
|
+
chmodDev(`${workerPath}/.dev.vars`);
|
|
33147
33252
|
if (!opts.quiet)
|
|
33148
33253
|
formatSuccess(`Created ${workerPath}/.dev.vars`, opts);
|
|
33149
33254
|
}
|
|
@@ -33220,6 +33325,8 @@ async function handleGenerateDevVars(opts) {
|
|
|
33220
33325
|
].join(`
|
|
33221
33326
|
`);
|
|
33222
33327
|
await Bun.write(`${workerPath}/.dev.vars`, content);
|
|
33328
|
+
const { secureSecretFile: secureSecretFile2 } = await Promise.resolve().then(() => (init_fs_secure(), exports_fs_secure));
|
|
33329
|
+
secureSecretFile2(`${workerPath}/.dev.vars`);
|
|
33223
33330
|
count++;
|
|
33224
33331
|
}
|
|
33225
33332
|
formatSuccess(`Generated .dev.vars for ${count} worker(s)`, opts);
|
|
@@ -33467,7 +33574,7 @@ class SecretsService {
|
|
|
33467
33574
|
const path5 = configPath ?? "wrangler.jsonc";
|
|
33468
33575
|
const file2 = Bun.file(path5);
|
|
33469
33576
|
if (!await file2.exists()) {
|
|
33470
|
-
throw new Error(`Config file not found: ${path5}
|
|
33577
|
+
throw new Error(`Config file not found: ${path5}. Run 'hoox onboard' (or 'hoox init') to create one.`);
|
|
33471
33578
|
}
|
|
33472
33579
|
const text2 = await file2.text();
|
|
33473
33580
|
const config2 = parse6(text2);
|
|
@@ -33550,6 +33657,8 @@ class SecretsService {
|
|
|
33550
33657
|
const devVarsPath = `${worker.path}/.dev.vars`;
|
|
33551
33658
|
try {
|
|
33552
33659
|
await Bun.write(devVarsPath, content);
|
|
33660
|
+
const { secureSecretFile: secureSecretFile2 } = await Promise.resolve().then(() => (init_fs_secure(), exports_fs_secure));
|
|
33661
|
+
secureSecretFile2(devVarsPath);
|
|
33553
33662
|
return { ok: true, value: devVarsPath };
|
|
33554
33663
|
} catch (err) {
|
|
33555
33664
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -33797,6 +33906,8 @@ async function updateDevVars(filePath, key, value) {
|
|
|
33797
33906
|
await Bun.write(filePath, `${key}=${value}
|
|
33798
33907
|
`);
|
|
33799
33908
|
}
|
|
33909
|
+
const { secureSecretFile: secureSecretFile2 } = await Promise.resolve().then(() => (init_fs_secure(), exports_fs_secure));
|
|
33910
|
+
secureSecretFile2(filePath);
|
|
33800
33911
|
}
|
|
33801
33912
|
function registerSecretsSubcommands(secretsCmd, service = "config") {
|
|
33802
33913
|
secretsCmd.command("list [worker]").summary("List secrets for all workers or a specific worker").description(`List the secrets declared in wrangler.jsonc for workers.
|
|
@@ -33870,7 +33981,7 @@ EXAMPLES:
|
|
|
33870
33981
|
const svc = await SecretsService.create();
|
|
33871
33982
|
const declared = svc.listSecrets(workerName);
|
|
33872
33983
|
if (!declared.includes(secretName) && declared.length > 0) {
|
|
33873
|
-
throw new CLIError(`Secret "${secretName}" is not declared for worker "${workerName}".
|
|
33984
|
+
throw new CLIError(`Secret "${secretName}" is not declared for worker "${workerName}". Declared secrets: ${declared.join(", ")}`, 2 /* INVALID_USAGE */);
|
|
33874
33985
|
}
|
|
33875
33986
|
const value = await promptSecret(`Enter value for "${secretName}"`);
|
|
33876
33987
|
if (!value) {
|
|
@@ -34053,7 +34164,8 @@ EXAMPLES:
|
|
|
34053
34164
|
}
|
|
34054
34165
|
|
|
34055
34166
|
// src/commands/config/keys-subcommands.ts
|
|
34056
|
-
import { existsSync as existsSync9
|
|
34167
|
+
import { existsSync as existsSync9 } from "fs";
|
|
34168
|
+
init_fs_secure();
|
|
34057
34169
|
init_theme();
|
|
34058
34170
|
function generateKey(bytes = 32) {
|
|
34059
34171
|
const buf = new Uint8Array(bytes);
|
|
@@ -34079,9 +34191,7 @@ EXAMPLES:
|
|
|
34079
34191
|
hoox config keys generate`).action(withErrorHandling(async (_2, cmd) => {
|
|
34080
34192
|
const opts = getFormatOptions(cmd);
|
|
34081
34193
|
const keysDir = ".keys";
|
|
34082
|
-
|
|
34083
|
-
mkdirSync4(keysDir, { recursive: true });
|
|
34084
|
-
}
|
|
34194
|
+
ensureSecretDir(keysDir);
|
|
34085
34195
|
const meshKey = generateKey();
|
|
34086
34196
|
const keys = {
|
|
34087
34197
|
INTERNAL_KEY_BINDING: meshKey,
|
|
@@ -34096,7 +34206,13 @@ EXAMPLES:
|
|
|
34096
34206
|
const filePath = `${keysDir}/${name.toLowerCase()}.env`;
|
|
34097
34207
|
await Bun.write(filePath, `${name}=${value}
|
|
34098
34208
|
`);
|
|
34209
|
+
secureSecretFile(filePath);
|
|
34099
34210
|
}
|
|
34211
|
+
await Bun.write(`${keysDir}/setup.env`, `# Generated by hoox keys generate
|
|
34212
|
+
` + Object.entries(keys).map(([k, v]) => `${k}=${v}`).join(`
|
|
34213
|
+
`) + `
|
|
34214
|
+
`);
|
|
34215
|
+
secureSecretFile(`${keysDir}/setup.env`);
|
|
34100
34216
|
formatSuccess(`Generated ${Object.keys(keys).length} keys in ${keysDir}/`, opts);
|
|
34101
34217
|
if (!opts.quiet && !opts.json) {
|
|
34102
34218
|
process.stdout.write(`${theme.warning("!")} Keep these keys secret. Add ${keysDir}/ to .gitignore.
|
|
@@ -34708,6 +34824,22 @@ async function runInfraChecks(cf) {
|
|
|
34708
34824
|
});
|
|
34709
34825
|
return { name: "Infrastructure", checks: checks3 };
|
|
34710
34826
|
}
|
|
34827
|
+
function parseRemoteSecretNames(raw) {
|
|
34828
|
+
try {
|
|
34829
|
+
const parsed = JSON.parse(raw);
|
|
34830
|
+
if (!Array.isArray(parsed))
|
|
34831
|
+
return null;
|
|
34832
|
+
const names = new Set;
|
|
34833
|
+
for (const item of parsed) {
|
|
34834
|
+
if (item && typeof item === "object" && typeof item.name === "string") {
|
|
34835
|
+
names.add(item.name);
|
|
34836
|
+
}
|
|
34837
|
+
}
|
|
34838
|
+
return names;
|
|
34839
|
+
} catch {
|
|
34840
|
+
return null;
|
|
34841
|
+
}
|
|
34842
|
+
}
|
|
34711
34843
|
async function runSecretsChecks(secretsService, configService, cf) {
|
|
34712
34844
|
const checks3 = [];
|
|
34713
34845
|
const enabledWorkers = configService.listEnabledWorkers();
|
|
@@ -34716,11 +34848,11 @@ async function runSecretsChecks(secretsService, configService, cf) {
|
|
|
34716
34848
|
for (const workerName of enabledWorkers) {
|
|
34717
34849
|
const result = await secretsService.checkLocalSecrets(workerName);
|
|
34718
34850
|
if (result.missing.length > 0) {
|
|
34719
|
-
errors4.push(`Worker "${workerName}" missing secrets: ${result.missing.join(", ")}`);
|
|
34851
|
+
errors4.push(`Worker "${workerName}" missing secrets: ${result.missing.join(", ")}. ` + `Fix: hoox setup --skip-db --skip-dashboard (mesh keys) or ` + `hoox secrets set ${workerName} <NAME>`);
|
|
34720
34852
|
}
|
|
34721
34853
|
for (const secret of result.secrets) {
|
|
34722
|
-
if (secret.set && secret.source) {
|
|
34723
|
-
warnings.push(`Worker "${workerName}": ${secret.name} is
|
|
34854
|
+
if (!secret.set && secret.source) {
|
|
34855
|
+
warnings.push(`Worker "${workerName}": ${secret.name} is present in ${secret.source} but empty/placeholder`);
|
|
34724
34856
|
}
|
|
34725
34857
|
}
|
|
34726
34858
|
}
|
|
@@ -34733,14 +34865,22 @@ async function runSecretsChecks(secretsService, configService, cf) {
|
|
|
34733
34865
|
const remoteErrors = [];
|
|
34734
34866
|
const remoteWarnings = [];
|
|
34735
34867
|
for (const workerName of enabledWorkers) {
|
|
34736
|
-
const
|
|
34737
|
-
if (
|
|
34868
|
+
const expected = secretsService.listSecrets(workerName);
|
|
34869
|
+
if (expected.length === 0)
|
|
34738
34870
|
continue;
|
|
34739
34871
|
const result = await cf.secretList(workerName);
|
|
34740
34872
|
if (!result.ok) {
|
|
34741
34873
|
remoteErrors.push(`Worker "${workerName}": ${result.error}`);
|
|
34742
|
-
|
|
34743
|
-
|
|
34874
|
+
continue;
|
|
34875
|
+
}
|
|
34876
|
+
const remoteNames = parseRemoteSecretNames(result.value);
|
|
34877
|
+
if (!remoteNames) {
|
|
34878
|
+
remoteWarnings.push(`Worker "${workerName}": could not parse remote secret list (raw length ${result.value.length})`);
|
|
34879
|
+
continue;
|
|
34880
|
+
}
|
|
34881
|
+
const missingRemote = expected.filter((n3) => !remoteNames.has(n3));
|
|
34882
|
+
if (missingRemote.length > 0) {
|
|
34883
|
+
remoteErrors.push(`Worker "${workerName}" missing on Cloudflare: ${missingRemote.join(", ")}. ` + `Fix: hoox secrets sync ${workerName}`);
|
|
34744
34884
|
}
|
|
34745
34885
|
}
|
|
34746
34886
|
checks3.push({
|
|
@@ -41157,68 +41297,78 @@ function findCliVersion() {
|
|
|
41157
41297
|
}
|
|
41158
41298
|
var VERSION = findCliVersion();
|
|
41159
41299
|
var DISCLAIMER2 = "DISCLAIMER: Trading cryptocurrencies involves substantial risk of loss. Use at your own risk.";
|
|
41160
|
-
var
|
|
41161
|
-
|
|
41162
|
-
"| | | |/ _ \\ / _ \\ \\/ / ",
|
|
41163
|
-
"| |_| | (_) | (_) > < ",
|
|
41164
|
-
" \\___/ \\___/ \\___/_/\\_\\ "
|
|
41165
|
-
];
|
|
41166
|
-
var WORD_W = WORDMARK[0].length;
|
|
41167
|
-
function colorWordmark(phase, mode) {
|
|
41168
|
-
return WORDMARK.map((line, row) => {
|
|
41169
|
-
if (mode === "assemble") {
|
|
41170
|
-
const local = Math.max(0, Math.min(1, phase));
|
|
41171
|
-
const cut = Math.floor(local * line.length);
|
|
41172
|
-
let out = "";
|
|
41173
|
-
for (let col = 0;col < line.length; col++) {
|
|
41174
|
-
const ch = line[col];
|
|
41175
|
-
if (ch === " ") {
|
|
41176
|
-
out += " ";
|
|
41177
|
-
continue;
|
|
41178
|
-
}
|
|
41179
|
-
if (col > cut)
|
|
41180
|
-
out += ZINC_FAINT("\xB7");
|
|
41181
|
-
else if (local < 0.85)
|
|
41182
|
-
out += ZINC(ch);
|
|
41183
|
-
else
|
|
41184
|
-
out += theme.heading(ch);
|
|
41185
|
-
}
|
|
41186
|
-
return out;
|
|
41187
|
-
}
|
|
41188
|
-
if (mode === "pulse") {
|
|
41189
|
-
let out = "";
|
|
41190
|
-
for (let col = 0;col < line.length; col++) {
|
|
41191
|
-
const ch = line[col];
|
|
41192
|
-
if (ch === " ") {
|
|
41193
|
-
out += " ";
|
|
41194
|
-
continue;
|
|
41195
|
-
}
|
|
41196
|
-
const t2 = (phase * 1.5 + col * 0.05 + row * 0.06) % 1;
|
|
41197
|
-
if (t2 < 0.12)
|
|
41198
|
-
out += AMBER(ch);
|
|
41199
|
-
else if (t2 < 0.25)
|
|
41200
|
-
out += ORANGE(ch);
|
|
41201
|
-
else if (t2 < 0.4)
|
|
41202
|
-
out += INDIGO_SOFT(ch);
|
|
41203
|
-
else
|
|
41204
|
-
out += INDIGO.bold(ch);
|
|
41205
|
-
}
|
|
41206
|
-
return out;
|
|
41207
|
-
}
|
|
41208
|
-
return theme.heading(line);
|
|
41209
|
-
});
|
|
41210
|
-
}
|
|
41300
|
+
var LETTERS = ["H", "O", "O", "X"];
|
|
41301
|
+
var RULE_W = 38;
|
|
41211
41302
|
var PAD = " ";
|
|
41303
|
+
function colorDiamond(phase, mode) {
|
|
41304
|
+
if (mode === "assemble") {
|
|
41305
|
+
if (phase < 0.05)
|
|
41306
|
+
return " ";
|
|
41307
|
+
if (phase < 0.2)
|
|
41308
|
+
return ZINC_FAINT("\u25C6");
|
|
41309
|
+
return AMBER("\u25C6");
|
|
41310
|
+
}
|
|
41311
|
+
if (mode === "pulse") {
|
|
41312
|
+
const t2 = phase * 2 % 1;
|
|
41313
|
+
return t2 < 0.5 ? AMBER("\u25C6") : ORANGE("\u25C6");
|
|
41314
|
+
}
|
|
41315
|
+
return AMBER("\u25C6");
|
|
41316
|
+
}
|
|
41317
|
+
function colorLetter(letter, index, phase, mode) {
|
|
41318
|
+
if (mode === "assemble") {
|
|
41319
|
+
const start = 0.12;
|
|
41320
|
+
const span = 0.88;
|
|
41321
|
+
const letterPhase = (phase - start) / span;
|
|
41322
|
+
const revealAt = index / LETTERS.length;
|
|
41323
|
+
if (letterPhase < revealAt)
|
|
41324
|
+
return " ";
|
|
41325
|
+
if (letterPhase < revealAt + 0.12)
|
|
41326
|
+
return ZINC(letter);
|
|
41327
|
+
return INDIGO.bold(letter);
|
|
41328
|
+
}
|
|
41329
|
+
if (mode === "pulse") {
|
|
41330
|
+
const t2 = (phase * 1.4 + index * 0.18) % 1;
|
|
41331
|
+
if (t2 < 0.15)
|
|
41332
|
+
return INDIGO_SOFT(letter);
|
|
41333
|
+
if (t2 < 0.3)
|
|
41334
|
+
return AMBER(letter);
|
|
41335
|
+
return INDIGO.bold(letter);
|
|
41336
|
+
}
|
|
41337
|
+
return INDIGO.bold(letter);
|
|
41338
|
+
}
|
|
41339
|
+
function colorDot(afterLetterIndex, phase, mode) {
|
|
41340
|
+
if (mode === "assemble") {
|
|
41341
|
+
const start = 0.12;
|
|
41342
|
+
const span = 0.88;
|
|
41343
|
+
const letterPhase = (phase - start) / span;
|
|
41344
|
+
const revealAt = (afterLetterIndex + 1) / LETTERS.length;
|
|
41345
|
+
if (letterPhase < revealAt - 0.02)
|
|
41346
|
+
return " ";
|
|
41347
|
+
return ZINC_FAINT("\xB7");
|
|
41348
|
+
}
|
|
41349
|
+
return ZINC_FAINT("\xB7");
|
|
41350
|
+
}
|
|
41351
|
+
function composeTitleLine(phase, mode) {
|
|
41352
|
+
const diamond = colorDiamond(phase, mode);
|
|
41353
|
+
const parts = [diamond, " "];
|
|
41354
|
+
for (let i2 = 0;i2 < LETTERS.length; i2++) {
|
|
41355
|
+
parts.push(colorLetter(LETTERS[i2], i2, phase, mode));
|
|
41356
|
+
if (i2 < LETTERS.length - 1) {
|
|
41357
|
+
parts.push(" ");
|
|
41358
|
+
parts.push(colorDot(i2, phase, mode));
|
|
41359
|
+
parts.push(" ");
|
|
41360
|
+
}
|
|
41361
|
+
}
|
|
41362
|
+
return PAD + parts.join("");
|
|
41363
|
+
}
|
|
41364
|
+
function composeMetaLine() {
|
|
41365
|
+
return PAD + ZINC_SOFT(TAGLINE) + " " + ZINC_FAINT("\xB7") + " " + INDIGO_SOFT(`v${VERSION}`);
|
|
41366
|
+
}
|
|
41212
41367
|
function composeFrame(phase, mode) {
|
|
41213
|
-
const
|
|
41214
|
-
const
|
|
41215
|
-
const
|
|
41216
|
-
|
|
41217
|
-
const metaInner = ZINC_SOFT(TAGLINE) + " " + ZINC_FAINT("\xB7") + " " + INDIGO_SOFT(`v${VERSION}`);
|
|
41218
|
-
const metaVis = stripAnsi(metaInner).length;
|
|
41219
|
-
const metaPad = Math.max(0, Math.floor((contentW - metaVis) / 2));
|
|
41220
|
-
const meta3 = PAD + " ".repeat(metaPad) + metaInner;
|
|
41221
|
-
return [rule, ...body, rule, meta3].join(`
|
|
41368
|
+
const title = composeTitleLine(phase, mode);
|
|
41369
|
+
const rule = PAD + ZINC_SOFT("\xB7") + " " + ZINC_FAINT("\u2500".repeat(RULE_W - 2));
|
|
41370
|
+
const meta3 = composeMetaLine();
|
|
41371
|
+
return [title, rule, meta3].join(`
|
|
41222
41372
|
`);
|
|
41223
41373
|
}
|
|
41224
41374
|
function canAnimate() {
|
|
@@ -41850,7 +42000,8 @@ program2.exitOverride((err) => {
|
|
|
41850
42000
|
const match = err.message.match(/'([^']+)'/);
|
|
41851
42001
|
const badArg = match?.[1] ?? "";
|
|
41852
42002
|
const suggestion = suggestForCommand(program2, badArg);
|
|
41853
|
-
|
|
42003
|
+
const cleanMsg = err.message.replace(/\n?\(Did you mean[^)]*\)\s*/gi, "").trim();
|
|
42004
|
+
formatError2(new CLIError(cleanMsg, 2 /* INVALID_USAGE */, undefined, false), suggestion ? { ...errFmtOpts, suggestions: [suggestion] } : errFmtOpts);
|
|
41854
42005
|
process.exitCode = 2 /* INVALID_USAGE */;
|
|
41855
42006
|
throw err;
|
|
41856
42007
|
}
|