@jango-blockchained/hoox-cli 0.9.4 → 0.9.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/README.md +29 -30
- package/dist/index.js +1585 -1563
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -24114,798 +24114,1186 @@ var init_config2 = __esm(() => {
|
|
|
24114
24114
|
init_config_service();
|
|
24115
24115
|
});
|
|
24116
24116
|
|
|
24117
|
-
// src/services/
|
|
24118
|
-
|
|
24119
|
-
__export(exports_kv_sync_service, {
|
|
24120
|
-
KvSyncService: () => KvSyncService
|
|
24121
|
-
});
|
|
24117
|
+
// src/services/cloudflare/cloudflare-service.ts
|
|
24118
|
+
import path3 from "path";
|
|
24122
24119
|
|
|
24123
|
-
class
|
|
24124
|
-
|
|
24125
|
-
|
|
24126
|
-
|
|
24120
|
+
class CloudflareService {
|
|
24121
|
+
cwd;
|
|
24122
|
+
homeDir;
|
|
24123
|
+
configService;
|
|
24124
|
+
constructor(cwd, homeDir, configService) {
|
|
24125
|
+
this.cwd = cwd ?? process.cwd();
|
|
24126
|
+
this.homeDir = homeDir;
|
|
24127
|
+
this.configService = configService ?? (this.homeDir ? new ConfigService(undefined, this.homeDir) : undefined);
|
|
24128
|
+
}
|
|
24129
|
+
resolveWorkerPath(workerPath) {
|
|
24130
|
+
if (this.configService) {
|
|
24131
|
+
const workerName = path3.basename(workerPath);
|
|
24132
|
+
return this.configService.getWorkerPath(workerName);
|
|
24133
|
+
}
|
|
24134
|
+
if (this.homeDir) {
|
|
24135
|
+
const workerName = path3.basename(workerPath);
|
|
24136
|
+
return path3.join(this.homeDir, ".hoox", "workers", workerName);
|
|
24137
|
+
}
|
|
24138
|
+
return path3.resolve(this.cwd, workerPath);
|
|
24139
|
+
}
|
|
24140
|
+
async runWrangler(args, cwd) {
|
|
24127
24141
|
try {
|
|
24128
|
-
const proc = Bun.spawn(["wrangler",
|
|
24142
|
+
const proc = Bun.spawn(["wrangler", ...args], {
|
|
24143
|
+
cwd: cwd ?? this.cwd,
|
|
24129
24144
|
stdout: "pipe",
|
|
24130
24145
|
stderr: "pipe"
|
|
24131
24146
|
});
|
|
24132
24147
|
const stdout2 = await new Response(proc.stdout).text();
|
|
24148
|
+
const stderr = await new Response(proc.stderr).text();
|
|
24133
24149
|
const exitCode = await proc.exited;
|
|
24134
24150
|
if (exitCode === 0) {
|
|
24135
|
-
|
|
24136
|
-
const namespaces = JSON.parse(stdout2);
|
|
24137
|
-
const configKv = namespaces.find((n3) => n3.title === "CONFIG_KV");
|
|
24138
|
-
if (configKv)
|
|
24139
|
-
return configKv.id;
|
|
24140
|
-
} catch {}
|
|
24151
|
+
return { ok: true, value: stdout2.trim() };
|
|
24141
24152
|
}
|
|
24142
|
-
|
|
24143
|
-
|
|
24153
|
+
return {
|
|
24154
|
+
ok: false,
|
|
24155
|
+
error: stderr.trim() || `wrangler exited with code ${exitCode}`
|
|
24156
|
+
};
|
|
24157
|
+
} catch (err) {
|
|
24158
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
24159
|
+
const hint = /ENOENT|not found/i.test(message) ? "Install wrangler with `bun add -g wrangler` (or `npm i -g wrangler`), then run `wrangler login`." : undefined;
|
|
24160
|
+
return {
|
|
24161
|
+
ok: false,
|
|
24162
|
+
error: hint ? `Failed to spawn wrangler: ${message}
|
|
24163
|
+
\u21B3 hint: ${hint}` : `Failed to spawn wrangler: ${message}`
|
|
24164
|
+
};
|
|
24165
|
+
}
|
|
24144
24166
|
}
|
|
24145
|
-
async
|
|
24146
|
-
|
|
24147
|
-
|
|
24148
|
-
|
|
24149
|
-
|
|
24150
|
-
|
|
24167
|
+
async whoami() {
|
|
24168
|
+
return this.runWrangler(["whoami"]);
|
|
24169
|
+
}
|
|
24170
|
+
async deploy(workerPath, env) {
|
|
24171
|
+
const resolvedPath = this.resolveWorkerPath(workerPath);
|
|
24172
|
+
const args = ["deploy"];
|
|
24173
|
+
if (env) {
|
|
24174
|
+
args.push("--env", env);
|
|
24151
24175
|
}
|
|
24152
|
-
|
|
24153
|
-
|
|
24154
|
-
return
|
|
24155
|
-
}
|
|
24156
|
-
|
|
24157
|
-
|
|
24176
|
+
const result = await this.runWrangler(args, resolvedPath);
|
|
24177
|
+
if (!result.ok) {
|
|
24178
|
+
return result;
|
|
24179
|
+
}
|
|
24180
|
+
const url2 = this.extractUrl(result.value);
|
|
24181
|
+
const output = result.value;
|
|
24182
|
+
const deployResult = { url: url2, rawOutput: output };
|
|
24183
|
+
const pathParts = workerPath.split("/");
|
|
24184
|
+
deployResult.name = pathParts[pathParts.length - 1];
|
|
24185
|
+
const sizeMatch = output.match(/Total Upload:\s*([\d.]+)\s*([KMGT]?i?B)/i);
|
|
24186
|
+
if (sizeMatch) {
|
|
24187
|
+
deployResult.size = `${sizeMatch[1]} ${sizeMatch[2]}`;
|
|
24188
|
+
}
|
|
24189
|
+
const startupMatch = output.match(/Worker Startup Time:\s*(\d+)\s*ms/i);
|
|
24190
|
+
if (startupMatch) {
|
|
24191
|
+
deployResult.startupTime = `${startupMatch[1]} ms`;
|
|
24192
|
+
}
|
|
24193
|
+
const versionMatch = output.match(/Current Version ID:\s*([a-f0-9-]{36,})/i);
|
|
24194
|
+
if (versionMatch) {
|
|
24195
|
+
deployResult.versionId = versionMatch[1];
|
|
24158
24196
|
}
|
|
24197
|
+
return { ok: true, value: deployResult };
|
|
24159
24198
|
}
|
|
24160
|
-
async
|
|
24161
|
-
const
|
|
24162
|
-
|
|
24163
|
-
|
|
24164
|
-
|
|
24165
|
-
|
|
24166
|
-
|
|
24167
|
-
|
|
24168
|
-
|
|
24199
|
+
async versionsList(workerName) {
|
|
24200
|
+
const result = await this.runWrangler([
|
|
24201
|
+
"versions",
|
|
24202
|
+
"list",
|
|
24203
|
+
"--name",
|
|
24204
|
+
workerName,
|
|
24205
|
+
"--json"
|
|
24206
|
+
]);
|
|
24207
|
+
if (!result.ok) {
|
|
24208
|
+
return result;
|
|
24209
|
+
}
|
|
24210
|
+
try {
|
|
24211
|
+
const parsed = JSON.parse(result.value);
|
|
24212
|
+
if (!Array.isArray(parsed)) {
|
|
24213
|
+
return {
|
|
24214
|
+
ok: false,
|
|
24215
|
+
error: `Expected array from wrangler versions list, got ${typeof parsed}`
|
|
24216
|
+
};
|
|
24217
|
+
}
|
|
24218
|
+
const versions2 = parsed.map((v) => ({
|
|
24219
|
+
id: String(v.id ?? ""),
|
|
24220
|
+
number: typeof v.number === "number" ? v.number : undefined,
|
|
24221
|
+
created_on: typeof v.metadata === "object" && v.metadata !== null ? String(v.metadata.created_on ?? "") : undefined,
|
|
24222
|
+
author: typeof v.metadata === "object" && v.metadata !== null ? String(v.metadata.author ?? "") : undefined,
|
|
24223
|
+
message: typeof v.metadata === "object" && v.metadata !== null ? String(v.metadata.message ?? "") : undefined,
|
|
24224
|
+
source: typeof v.metadata === "object" && v.metadata !== null ? String(v.metadata.source ?? "") : undefined
|
|
24225
|
+
}));
|
|
24226
|
+
return { ok: true, value: versions2 };
|
|
24227
|
+
} catch (err) {
|
|
24228
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
24229
|
+
return {
|
|
24230
|
+
ok: false,
|
|
24231
|
+
error: `Failed to parse versions list: ${message}`
|
|
24232
|
+
};
|
|
24169
24233
|
}
|
|
24170
|
-
return stdout2.trim() || null;
|
|
24171
24234
|
}
|
|
24172
|
-
async
|
|
24173
|
-
|
|
24174
|
-
|
|
24175
|
-
|
|
24176
|
-
|
|
24177
|
-
|
|
24178
|
-
|
|
24179
|
-
|
|
24235
|
+
async versionsRollback(workerName, versionId) {
|
|
24236
|
+
return this.runWrangler([
|
|
24237
|
+
"versions",
|
|
24238
|
+
"rollback",
|
|
24239
|
+
"--name",
|
|
24240
|
+
workerName,
|
|
24241
|
+
"--version-id",
|
|
24242
|
+
versionId
|
|
24180
24243
|
]);
|
|
24181
|
-
|
|
24182
|
-
|
|
24183
|
-
|
|
24244
|
+
}
|
|
24245
|
+
async dev(workerPath, port) {
|
|
24246
|
+
const devPort = port ?? 8787;
|
|
24247
|
+
const resolvedPath = this.resolveWorkerPath(workerPath);
|
|
24248
|
+
try {
|
|
24249
|
+
Bun.spawn(["wrangler", "dev", "--port", String(devPort)], {
|
|
24250
|
+
cwd: resolvedPath,
|
|
24251
|
+
stdout: "pipe",
|
|
24252
|
+
stderr: "pipe"
|
|
24253
|
+
});
|
|
24254
|
+
return { ok: true, value: { port: devPort } };
|
|
24255
|
+
} catch (err) {
|
|
24256
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
24257
|
+
return { ok: false, error: `Failed to start dev server: ${message}` };
|
|
24184
24258
|
}
|
|
24185
24259
|
}
|
|
24186
|
-
async
|
|
24187
|
-
|
|
24188
|
-
|
|
24189
|
-
|
|
24190
|
-
|
|
24191
|
-
|
|
24260
|
+
async tail(workerName) {
|
|
24261
|
+
return this.runWrangler(["tail", workerName]);
|
|
24262
|
+
}
|
|
24263
|
+
async d1List() {
|
|
24264
|
+
return this.runWrangler(["d1", "list", "--json"]);
|
|
24265
|
+
}
|
|
24266
|
+
async d1Create(name) {
|
|
24267
|
+
return this.runWrangler(["d1", "create", name]);
|
|
24268
|
+
}
|
|
24269
|
+
async d1Delete(name) {
|
|
24270
|
+
return this.runWrangler(["d1", "delete", name]);
|
|
24271
|
+
}
|
|
24272
|
+
async d1Execute(name, sql, remote = true) {
|
|
24273
|
+
const args = ["d1", "execute", name, "--command", sql];
|
|
24274
|
+
if (remote)
|
|
24275
|
+
args.push("--remote");
|
|
24276
|
+
const result = await this.runWrangler(args);
|
|
24277
|
+
if (!result.ok)
|
|
24278
|
+
return result;
|
|
24279
|
+
const extracted = extractJsonArray(result.value);
|
|
24280
|
+
if (extracted === null) {
|
|
24281
|
+
return {
|
|
24282
|
+
ok: false,
|
|
24283
|
+
error: `wrangler d1 execute returned non-JSON output: ${result.value.slice(0, 200)}`
|
|
24284
|
+
};
|
|
24192
24285
|
}
|
|
24286
|
+
return { ok: true, value: extracted };
|
|
24193
24287
|
}
|
|
24194
|
-
|
|
24195
|
-
return
|
|
24196
|
-
namespace: "CONFIG_KV",
|
|
24197
|
-
keys: [
|
|
24198
|
-
{
|
|
24199
|
-
key: "webhook:tradingview:ip_check_enabled",
|
|
24200
|
-
type: "boolean",
|
|
24201
|
-
default: "false",
|
|
24202
|
-
description: "Enable TradingView IP allowlist check"
|
|
24203
|
-
},
|
|
24204
|
-
{
|
|
24205
|
-
key: "webhook:allowed_ips",
|
|
24206
|
-
type: "string",
|
|
24207
|
-
default: "",
|
|
24208
|
-
description: "Comma-separated allowed IPs for webhook"
|
|
24209
|
-
},
|
|
24210
|
-
{
|
|
24211
|
-
key: "routing:dynamic:enabled",
|
|
24212
|
-
type: "boolean",
|
|
24213
|
-
default: "false",
|
|
24214
|
-
description: "Enable dynamic routing"
|
|
24215
|
-
},
|
|
24216
|
-
{
|
|
24217
|
-
key: "trade:max_daily_drawdown_percent",
|
|
24218
|
-
type: "number",
|
|
24219
|
-
default: "10",
|
|
24220
|
-
description: "Max daily loss percentage before halt"
|
|
24221
|
-
},
|
|
24222
|
-
{
|
|
24223
|
-
key: "trade:kill_switch",
|
|
24224
|
-
type: "boolean",
|
|
24225
|
-
default: "false",
|
|
24226
|
-
description: "Emergency stop all trading"
|
|
24227
|
-
},
|
|
24228
|
-
{
|
|
24229
|
-
key: "trade:watermark:{exchange}:{symbol}:{side}",
|
|
24230
|
-
type: "number",
|
|
24231
|
-
default: "",
|
|
24232
|
-
description: "Per-market watermark (template key)",
|
|
24233
|
-
secret: true
|
|
24234
|
-
},
|
|
24235
|
-
{
|
|
24236
|
-
key: "agent:openai_key",
|
|
24237
|
-
type: "string",
|
|
24238
|
-
default: "",
|
|
24239
|
-
description: "OpenAI API key for AI agent",
|
|
24240
|
-
secret: true
|
|
24241
|
-
},
|
|
24242
|
-
{
|
|
24243
|
-
key: "agent:anthropic_key",
|
|
24244
|
-
type: "string",
|
|
24245
|
-
default: "",
|
|
24246
|
-
description: "Anthropic API key for AI agent",
|
|
24247
|
-
secret: true
|
|
24248
|
-
},
|
|
24249
|
-
{
|
|
24250
|
-
key: "agent:google_key",
|
|
24251
|
-
type: "string",
|
|
24252
|
-
default: "",
|
|
24253
|
-
description: "Google AI API key for agent",
|
|
24254
|
-
secret: true
|
|
24255
|
-
},
|
|
24256
|
-
{
|
|
24257
|
-
key: "agent:azure_api_key",
|
|
24258
|
-
type: "string",
|
|
24259
|
-
default: "",
|
|
24260
|
-
description: "Azure OpenAI API key",
|
|
24261
|
-
secret: true
|
|
24262
|
-
},
|
|
24263
|
-
{
|
|
24264
|
-
key: "agent:azure_endpoint",
|
|
24265
|
-
type: "string",
|
|
24266
|
-
default: "",
|
|
24267
|
-
description: "Azure OpenAI endpoint",
|
|
24268
|
-
secret: true
|
|
24269
|
-
},
|
|
24270
|
-
{
|
|
24271
|
-
key: "email:scan_subject",
|
|
24272
|
-
type: "string",
|
|
24273
|
-
default: "",
|
|
24274
|
-
description: "Email subject filter for signal scanning"
|
|
24275
|
-
},
|
|
24276
|
-
{
|
|
24277
|
-
key: "email:coin_pattern",
|
|
24278
|
-
type: "string",
|
|
24279
|
-
default: "",
|
|
24280
|
-
description: "Regex pattern to extract coin from email"
|
|
24281
|
-
},
|
|
24282
|
-
{
|
|
24283
|
-
key: "email:action_pattern",
|
|
24284
|
-
type: "string",
|
|
24285
|
-
default: "",
|
|
24286
|
-
description: "Regex pattern to extract action from email"
|
|
24287
|
-
},
|
|
24288
|
-
{
|
|
24289
|
-
key: "email:quantity_multiplier",
|
|
24290
|
-
type: "number",
|
|
24291
|
-
default: "1",
|
|
24292
|
-
description: "Multiplier for email signal quantity"
|
|
24293
|
-
},
|
|
24294
|
-
{
|
|
24295
|
-
key: "email:use_imap",
|
|
24296
|
-
type: "boolean",
|
|
24297
|
-
default: "false",
|
|
24298
|
-
description: "Use IMAP for email scanning"
|
|
24299
|
-
}
|
|
24300
|
-
]
|
|
24301
|
-
};
|
|
24288
|
+
async kvList() {
|
|
24289
|
+
return this.runWrangler(["kv", "namespace", "list"]);
|
|
24302
24290
|
}
|
|
24303
|
-
|
|
24304
|
-
return
|
|
24291
|
+
async kvCreate(name) {
|
|
24292
|
+
return this.runWrangler(["kv", "namespace", "create", name]);
|
|
24305
24293
|
}
|
|
24306
|
-
|
|
24307
|
-
|
|
24308
|
-
|
|
24309
|
-
|
|
24310
|
-
|
|
24311
|
-
|
|
24312
|
-
|
|
24313
|
-
|
|
24314
|
-
import { resolve as resolve4 } from "path";
|
|
24315
|
-
|
|
24316
|
-
class SchemaService {
|
|
24317
|
-
projectRoot;
|
|
24318
|
-
constructor(projectRoot = process.cwd()) {
|
|
24319
|
-
this.projectRoot = projectRoot;
|
|
24294
|
+
async kvDelete(id) {
|
|
24295
|
+
return this.runWrangler([
|
|
24296
|
+
"kv",
|
|
24297
|
+
"namespace",
|
|
24298
|
+
"delete",
|
|
24299
|
+
"--namespace-id",
|
|
24300
|
+
id
|
|
24301
|
+
]);
|
|
24320
24302
|
}
|
|
24321
|
-
|
|
24322
|
-
return
|
|
24303
|
+
async r2List() {
|
|
24304
|
+
return this.runWrangler(["r2", "bucket", "list"]);
|
|
24323
24305
|
}
|
|
24324
|
-
|
|
24325
|
-
return
|
|
24306
|
+
async r2Create(name) {
|
|
24307
|
+
return this.runWrangler(["r2", "bucket", "create", name]);
|
|
24326
24308
|
}
|
|
24327
|
-
|
|
24328
|
-
|
|
24329
|
-
|
|
24309
|
+
async r2Delete(name) {
|
|
24310
|
+
return this.runWrangler(["r2", "bucket", "delete", name]);
|
|
24311
|
+
}
|
|
24312
|
+
async queueList() {
|
|
24313
|
+
return this.runWrangler(["queues", "list"]);
|
|
24314
|
+
}
|
|
24315
|
+
async queueCreate(name) {
|
|
24316
|
+
return this.runWrangler(["queues", "create", name]);
|
|
24317
|
+
}
|
|
24318
|
+
async queueDelete(name) {
|
|
24319
|
+
return this.runWrangler(["queues", "delete", name]);
|
|
24320
|
+
}
|
|
24321
|
+
async vectorizeList() {
|
|
24322
|
+
return this.runWrangler(["vectorize", "list", "--json"]);
|
|
24323
|
+
}
|
|
24324
|
+
async vectorizeCreate(name, dimensions = 768, metric = "cosine") {
|
|
24325
|
+
return this.runWrangler([
|
|
24326
|
+
"vectorize",
|
|
24327
|
+
"create",
|
|
24328
|
+
name,
|
|
24329
|
+
"--dimensions",
|
|
24330
|
+
String(dimensions),
|
|
24331
|
+
"--metric",
|
|
24332
|
+
metric
|
|
24333
|
+
]);
|
|
24334
|
+
}
|
|
24335
|
+
async vectorizeDelete(name) {
|
|
24336
|
+
return this.runWrangler(["vectorize", "delete", name]);
|
|
24337
|
+
}
|
|
24338
|
+
async analyticsList() {
|
|
24339
|
+
return this.runWrangler(["analytics", "dataset", "list"]);
|
|
24340
|
+
}
|
|
24341
|
+
async analyticsCreate(_name) {
|
|
24342
|
+
return {
|
|
24343
|
+
ok: false,
|
|
24344
|
+
error: `Analytics datasets cannot be created via wrangler. ` + `Please use the Cloudflare Dashboard: ` + `https://dash.cloudflare.com/?to=/:account/analytics`
|
|
24345
|
+
};
|
|
24346
|
+
}
|
|
24347
|
+
async secretList(workerName) {
|
|
24348
|
+
const result = await this.runWrangler([
|
|
24349
|
+
"secret",
|
|
24350
|
+
"list",
|
|
24351
|
+
"--name",
|
|
24352
|
+
workerName
|
|
24353
|
+
]);
|
|
24354
|
+
if (!result.ok)
|
|
24355
|
+
return result;
|
|
24356
|
+
const extracted = extractJsonArray(result.value);
|
|
24357
|
+
if (extracted === null) {
|
|
24330
24358
|
return {
|
|
24331
|
-
|
|
24332
|
-
|
|
24333
|
-
errors: [
|
|
24334
|
-
{
|
|
24335
|
-
worker: name,
|
|
24336
|
-
severity: "error",
|
|
24337
|
-
message: `Unknown worker "${name}"`
|
|
24338
|
-
}
|
|
24339
|
-
]
|
|
24359
|
+
ok: false,
|
|
24360
|
+
error: `wrangler secret list returned non-JSON output: ${result.value.slice(0, 200)}`
|
|
24340
24361
|
};
|
|
24341
24362
|
}
|
|
24342
|
-
|
|
24343
|
-
|
|
24344
|
-
|
|
24345
|
-
const devVarsPath = resolve4(workersDir, name, ".dev.vars");
|
|
24346
|
-
const errors4 = [];
|
|
24347
|
-
const isHooxProject = existsSync6(resolve4(this.projectRoot, "wrangler.jsonc")) || existsSync6(resolve4(this.projectRoot, "workers"));
|
|
24363
|
+
return { ok: true, value: extracted };
|
|
24364
|
+
}
|
|
24365
|
+
async secretPut(workerName, secretName, value) {
|
|
24348
24366
|
try {
|
|
24349
|
-
const
|
|
24350
|
-
|
|
24351
|
-
|
|
24352
|
-
|
|
24353
|
-
|
|
24354
|
-
const errMessage = e instanceof Error ? e.message : String(e);
|
|
24355
|
-
const message = isEnoent && !isHooxProject ? `Cannot read ${workerWranglerPath}: File not found. Are you in the Hoox project root directory?` : `Cannot read ${workerWranglerPath}: ${errMessage}`;
|
|
24356
|
-
errors4.push({
|
|
24357
|
-
worker: name,
|
|
24358
|
-
severity: "error",
|
|
24359
|
-
message
|
|
24367
|
+
const proc = Bun.spawn(["wrangler", "secret", "put", secretName, "--name", workerName], {
|
|
24368
|
+
cwd: this.cwd,
|
|
24369
|
+
stdout: "pipe",
|
|
24370
|
+
stderr: "pipe",
|
|
24371
|
+
stdin: "pipe"
|
|
24360
24372
|
});
|
|
24373
|
+
proc.stdin.write(value + `
|
|
24374
|
+
`);
|
|
24375
|
+
proc.stdin.end();
|
|
24376
|
+
const stdout2 = await new Response(proc.stdout).text();
|
|
24377
|
+
const stderr = await new Response(proc.stderr).text();
|
|
24378
|
+
const exitCode = await proc.exited;
|
|
24379
|
+
if (exitCode === 0) {
|
|
24380
|
+
return { ok: true, value: stdout2.trim() };
|
|
24381
|
+
}
|
|
24382
|
+
return {
|
|
24383
|
+
ok: false,
|
|
24384
|
+
error: stderr.trim() || `wrangler exited with code ${exitCode}`
|
|
24385
|
+
};
|
|
24386
|
+
} catch (err) {
|
|
24387
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
24388
|
+
return { ok: false, error: `Failed to set secret: ${message}` };
|
|
24361
24389
|
}
|
|
24362
|
-
|
|
24363
|
-
|
|
24364
|
-
|
|
24365
|
-
|
|
24366
|
-
|
|
24367
|
-
|
|
24368
|
-
|
|
24369
|
-
|
|
24370
|
-
|
|
24371
|
-
|
|
24390
|
+
}
|
|
24391
|
+
async secretDelete(workerName, secretName) {
|
|
24392
|
+
return this.runWrangler([
|
|
24393
|
+
"secret",
|
|
24394
|
+
"delete",
|
|
24395
|
+
secretName,
|
|
24396
|
+
"--name",
|
|
24397
|
+
workerName
|
|
24398
|
+
]);
|
|
24399
|
+
}
|
|
24400
|
+
async zonesList() {
|
|
24401
|
+
const token = process.env.CLOUDFLARE_API_TOKEN;
|
|
24402
|
+
if (!token) {
|
|
24403
|
+
return {
|
|
24404
|
+
ok: false,
|
|
24405
|
+
error: "CLOUDFLARE_API_TOKEN environment variable is not set. Set it or run `wrangler login`."
|
|
24406
|
+
};
|
|
24372
24407
|
}
|
|
24373
24408
|
try {
|
|
24374
|
-
const
|
|
24375
|
-
|
|
24376
|
-
|
|
24377
|
-
|
|
24378
|
-
|
|
24379
|
-
worker: name,
|
|
24380
|
-
severity: "warning",
|
|
24381
|
-
message: `Cannot read ${devVarsPath}: ${errMessage}`
|
|
24409
|
+
const response = await fetch("https://api.cloudflare.com/client/v4/zones?per_page=50", {
|
|
24410
|
+
headers: {
|
|
24411
|
+
Authorization: `Bearer ${token}`,
|
|
24412
|
+
"Content-Type": "application/json"
|
|
24413
|
+
}
|
|
24382
24414
|
});
|
|
24415
|
+
const json2 = await response.json();
|
|
24416
|
+
if (!response.ok || !json2.success) {
|
|
24417
|
+
const errorMsg = json2.errors?.map((e) => e.message).join("; ") || `HTTP ${response.status}`;
|
|
24418
|
+
return { ok: false, error: `Failed to list zones: ${errorMsg}` };
|
|
24419
|
+
}
|
|
24420
|
+
const lines = json2.result.map((z2) => `${z2.name} (${z2.id})`);
|
|
24421
|
+
return { ok: true, value: lines.join(`
|
|
24422
|
+
`) };
|
|
24423
|
+
} catch (err) {
|
|
24424
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
24425
|
+
return { ok: false, error: `Cloudflare API request failed: ${message}` };
|
|
24383
24426
|
}
|
|
24384
|
-
return {
|
|
24385
|
-
worker: name,
|
|
24386
|
-
passed: errors4.filter((e) => e.severity === "error").length === 0,
|
|
24387
|
-
errors: errors4
|
|
24388
|
-
};
|
|
24389
24427
|
}
|
|
24390
|
-
|
|
24391
|
-
|
|
24392
|
-
|
|
24393
|
-
|
|
24394
|
-
|
|
24395
|
-
|
|
24396
|
-
|
|
24397
|
-
|
|
24398
|
-
|
|
24399
|
-
var exports_trace_service = {};
|
|
24400
|
-
__export(exports_trace_service, {
|
|
24401
|
-
TraceService: () => TraceService
|
|
24402
|
-
});
|
|
24403
|
-
function getCredentials2() {
|
|
24404
|
-
const token = process.env.CLOUDFLARE_API_TOKEN;
|
|
24405
|
-
const accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
24406
|
-
if (!token) {
|
|
24407
|
-
throw new CLIError("CLOUDFLARE_API_TOKEN environment variable is not set. Set it or run `wrangler login`.", 1 /* ERROR */);
|
|
24408
|
-
}
|
|
24409
|
-
if (!accountId) {
|
|
24410
|
-
throw new CLIError("CLOUDFLARE_ACCOUNT_ID environment variable is not set.", 1 /* ERROR */);
|
|
24428
|
+
extractUrl(stdout2) {
|
|
24429
|
+
for (const line of stdout2.split(`
|
|
24430
|
+
`)) {
|
|
24431
|
+
const trimmed = line.trim();
|
|
24432
|
+
const match = trimmed.match(/(https?:\/\/[^\s]+(?:workers\.dev|cloudflareworkers\.com)[^\s]*)/);
|
|
24433
|
+
if (match)
|
|
24434
|
+
return match[1];
|
|
24435
|
+
}
|
|
24436
|
+
return;
|
|
24411
24437
|
}
|
|
24412
|
-
return { token, accountId };
|
|
24413
24438
|
}
|
|
24414
|
-
|
|
24415
|
-
const
|
|
24416
|
-
|
|
24417
|
-
|
|
24418
|
-
|
|
24419
|
-
|
|
24420
|
-
|
|
24421
|
-
|
|
24439
|
+
function extractJsonArray(raw) {
|
|
24440
|
+
const first = raw.indexOf("[");
|
|
24441
|
+
if (first === -1)
|
|
24442
|
+
return null;
|
|
24443
|
+
let depth = 0;
|
|
24444
|
+
let inString = false;
|
|
24445
|
+
let escape = false;
|
|
24446
|
+
for (let i2 = first;i2 < raw.length; i2++) {
|
|
24447
|
+
const ch = raw[i2];
|
|
24448
|
+
if (escape) {
|
|
24449
|
+
escape = false;
|
|
24450
|
+
continue;
|
|
24422
24451
|
}
|
|
24423
|
-
|
|
24424
|
-
|
|
24425
|
-
|
|
24426
|
-
|
|
24427
|
-
|
|
24428
|
-
|
|
24429
|
-
|
|
24430
|
-
|
|
24431
|
-
|
|
24432
|
-
|
|
24433
|
-
|
|
24434
|
-
|
|
24435
|
-
|
|
24436
|
-
|
|
24437
|
-
|
|
24438
|
-
|
|
24439
|
-
|
|
24452
|
+
if (inString) {
|
|
24453
|
+
if (ch === "\\")
|
|
24454
|
+
escape = true;
|
|
24455
|
+
else if (ch === '"')
|
|
24456
|
+
inString = false;
|
|
24457
|
+
continue;
|
|
24458
|
+
}
|
|
24459
|
+
if (ch === '"') {
|
|
24460
|
+
inString = true;
|
|
24461
|
+
continue;
|
|
24462
|
+
}
|
|
24463
|
+
if (ch === "[")
|
|
24464
|
+
depth++;
|
|
24465
|
+
else if (ch === "]") {
|
|
24466
|
+
depth--;
|
|
24467
|
+
if (depth === 0)
|
|
24468
|
+
return raw.slice(first, i2 + 1);
|
|
24440
24469
|
}
|
|
24441
|
-
return json2.result;
|
|
24442
|
-
} catch (err) {
|
|
24443
|
-
if (err instanceof CLIError)
|
|
24444
|
-
throw err;
|
|
24445
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
24446
|
-
throw new CLIError(`Cloudflare API request failed: ${message}`, 1 /* ERROR */);
|
|
24447
24470
|
}
|
|
24471
|
+
return null;
|
|
24448
24472
|
}
|
|
24473
|
+
var init_cloudflare_service = __esm(() => {
|
|
24474
|
+
init_config2();
|
|
24475
|
+
});
|
|
24449
24476
|
|
|
24450
|
-
|
|
24451
|
-
|
|
24452
|
-
|
|
24453
|
-
|
|
24454
|
-
|
|
24477
|
+
// src/services/kv/kv-sync-service.ts
|
|
24478
|
+
var exports_kv_sync_service = {};
|
|
24479
|
+
__export(exports_kv_sync_service, {
|
|
24480
|
+
stripWranglerStdoutNoise: () => stripWranglerStdoutNoise,
|
|
24481
|
+
KvSyncService: () => KvSyncService
|
|
24482
|
+
});
|
|
24483
|
+
function stripWranglerStdoutNoise(raw) {
|
|
24484
|
+
const lines = raw.split(`
|
|
24485
|
+
`);
|
|
24486
|
+
const cleaned = lines.filter((line) => {
|
|
24487
|
+
const t2 = line.trim();
|
|
24488
|
+
if (!t2)
|
|
24489
|
+
return false;
|
|
24490
|
+
if (t2.startsWith("There is a newer version of Wrangler"))
|
|
24491
|
+
return false;
|
|
24492
|
+
if (t2.includes("update available"))
|
|
24493
|
+
return false;
|
|
24494
|
+
if (t2.startsWith("\u26C5"))
|
|
24495
|
+
return false;
|
|
24496
|
+
if (/^[\u2500\-\u2550]{3,}$/.test(t2))
|
|
24497
|
+
return false;
|
|
24498
|
+
if (t2.startsWith("\u25B2 [WARNING]") || t2.startsWith("\u2718 [ERROR]"))
|
|
24499
|
+
return false;
|
|
24500
|
+
return true;
|
|
24501
|
+
});
|
|
24502
|
+
return cleaned.join(`
|
|
24503
|
+
`).trim();
|
|
24504
|
+
}
|
|
24505
|
+
|
|
24506
|
+
class KvSyncService {
|
|
24507
|
+
async resolveNamespaceId(namespaceId) {
|
|
24508
|
+
if (namespaceId)
|
|
24509
|
+
return namespaceId;
|
|
24510
|
+
try {
|
|
24511
|
+
const proc = Bun.spawn(["wrangler", "kv", "namespace", "list"], {
|
|
24512
|
+
stdout: "pipe",
|
|
24513
|
+
stderr: "pipe"
|
|
24514
|
+
});
|
|
24515
|
+
const stdout2 = await new Response(proc.stdout).text();
|
|
24516
|
+
const exitCode = await proc.exited;
|
|
24517
|
+
if (exitCode === 0) {
|
|
24518
|
+
try {
|
|
24519
|
+
const jsonText = extractJsonArray(stdout2) ?? stripWranglerStdoutNoise(stdout2);
|
|
24520
|
+
const namespaces = JSON.parse(jsonText);
|
|
24521
|
+
const configKv = namespaces.find((n3) => n3.title === "CONFIG_KV");
|
|
24522
|
+
if (configKv)
|
|
24523
|
+
return configKv.id;
|
|
24524
|
+
} catch {}
|
|
24525
|
+
}
|
|
24526
|
+
} catch {}
|
|
24527
|
+
throw new Error("Could not resolve CONFIG_KV namespace ID. Provide --namespace-id flag.");
|
|
24455
24528
|
}
|
|
24456
|
-
async
|
|
24457
|
-
const
|
|
24458
|
-
const
|
|
24459
|
-
|
|
24460
|
-
|
|
24461
|
-
|
|
24529
|
+
async list(namespaceId) {
|
|
24530
|
+
const proc = Bun.spawn(["wrangler", "kv", "key", "list", "--namespace-id", namespaceId], { stdout: "pipe", stderr: "pipe" });
|
|
24531
|
+
const stdout2 = await new Response(proc.stdout).text();
|
|
24532
|
+
const exitCode = await proc.exited;
|
|
24533
|
+
if (exitCode !== 0) {
|
|
24534
|
+
throw new Error(`Failed to list KV keys: ${stdout2.trim() || `exit ${exitCode}`}`);
|
|
24462
24535
|
}
|
|
24463
|
-
|
|
24464
|
-
const
|
|
24465
|
-
|
|
24466
|
-
|
|
24467
|
-
|
|
24468
|
-
|
|
24469
|
-
groupBy: c3.groupBy
|
|
24470
|
-
}));
|
|
24471
|
-
return { success: true, metrics };
|
|
24536
|
+
try {
|
|
24537
|
+
const parsed = JSON.parse(stdout2);
|
|
24538
|
+
return parsed;
|
|
24539
|
+
} catch {
|
|
24540
|
+
return stdout2.split(`
|
|
24541
|
+
`).filter(Boolean).map((name) => ({ name: name.trim() }));
|
|
24472
24542
|
}
|
|
24473
|
-
return { success: true };
|
|
24474
24543
|
}
|
|
24475
|
-
async
|
|
24476
|
-
const
|
|
24477
|
-
|
|
24478
|
-
|
|
24479
|
-
|
|
24480
|
-
|
|
24481
|
-
|
|
24482
|
-
|
|
24483
|
-
});
|
|
24484
|
-
}
|
|
24485
|
-
if (options.trigger) {
|
|
24486
|
-
filters.push({
|
|
24487
|
-
key: "$metadata.trigger",
|
|
24488
|
-
operation: "includes",
|
|
24489
|
-
type: "string",
|
|
24490
|
-
value: options.trigger
|
|
24491
|
-
});
|
|
24492
|
-
}
|
|
24493
|
-
if (options.level) {
|
|
24494
|
-
filters.push({
|
|
24495
|
-
key: "$metadata.level",
|
|
24496
|
-
operation: "eq",
|
|
24497
|
-
type: "string",
|
|
24498
|
-
value: options.level
|
|
24499
|
-
});
|
|
24544
|
+
async get(namespaceId, key) {
|
|
24545
|
+
const proc = Bun.spawn(["wrangler", "kv", "key", "get", "--namespace-id", namespaceId, key], { stdout: "pipe", stderr: "pipe" });
|
|
24546
|
+
const stdout2 = await new Response(proc.stdout).text();
|
|
24547
|
+
const stderr = await new Response(proc.stderr).text();
|
|
24548
|
+
const exitCode = await proc.exited;
|
|
24549
|
+
if (exitCode !== 0) {
|
|
24550
|
+
if (stderr.includes("not found"))
|
|
24551
|
+
return null;
|
|
24552
|
+
throw new Error(`Failed to get key "${key}": ${stderr.trim() || `exit ${exitCode}`}`);
|
|
24500
24553
|
}
|
|
24501
|
-
const
|
|
24502
|
-
|
|
24503
|
-
const request = {
|
|
24504
|
-
view: "events",
|
|
24505
|
-
queryId: "trace-events",
|
|
24506
|
-
limit: options.limit ?? 50,
|
|
24507
|
-
parameters: {
|
|
24508
|
-
filters
|
|
24509
|
-
},
|
|
24510
|
-
timeframe: {
|
|
24511
|
-
from: options.from ?? oneHourAgo,
|
|
24512
|
-
to: options.to ?? now
|
|
24513
|
-
}
|
|
24514
|
-
};
|
|
24515
|
-
return this.query(request);
|
|
24554
|
+
const cleaned = stripWranglerStdoutNoise(stdout2);
|
|
24555
|
+
return cleaned.length > 0 ? cleaned : null;
|
|
24516
24556
|
}
|
|
24517
|
-
async
|
|
24518
|
-
const
|
|
24519
|
-
|
|
24520
|
-
|
|
24521
|
-
|
|
24522
|
-
|
|
24523
|
-
|
|
24524
|
-
|
|
24525
|
-
|
|
24557
|
+
async set(namespaceId, key, value) {
|
|
24558
|
+
const proc = Bun.spawn(["wrangler", "kv", "key", "put", "--namespace-id", namespaceId, key], { stdout: "pipe", stderr: "pipe", stdin: "pipe" });
|
|
24559
|
+
proc.stdin.write(value + `
|
|
24560
|
+
`);
|
|
24561
|
+
proc.stdin.end();
|
|
24562
|
+
const [, stderr] = await Promise.all([
|
|
24563
|
+
new Response(proc.stdout).text(),
|
|
24564
|
+
new Response(proc.stderr).text()
|
|
24565
|
+
]);
|
|
24566
|
+
const exitCode = await proc.exited;
|
|
24567
|
+
if (exitCode !== 0) {
|
|
24568
|
+
throw new Error(`Failed to set key "${key}": ${stderr.trim() || `exit ${exitCode}`}`);
|
|
24526
24569
|
}
|
|
24527
|
-
const calculations = (options.calculations ?? [{ operator: "count" }]).map((c3) => ({
|
|
24528
|
-
operator: c3.operator,
|
|
24529
|
-
key: c3.key,
|
|
24530
|
-
keyType: c3.key ? "number" : undefined,
|
|
24531
|
-
alias: c3.alias ?? c3.operator
|
|
24532
|
-
}));
|
|
24533
|
-
const groupBys = options.groupBy ? [{ type: "string", value: options.groupBy }] : [];
|
|
24534
|
-
const now = Date.now();
|
|
24535
|
-
const oneHourAgo = now - 60 * 60 * 1000;
|
|
24536
|
-
const request = {
|
|
24537
|
-
view: "calculations",
|
|
24538
|
-
queryId: "trace-metrics",
|
|
24539
|
-
parameters: {
|
|
24540
|
-
filters,
|
|
24541
|
-
calculations,
|
|
24542
|
-
groupBys
|
|
24543
|
-
},
|
|
24544
|
-
timeframe: {
|
|
24545
|
-
from: options.from ?? oneHourAgo,
|
|
24546
|
-
to: options.to ?? now
|
|
24547
|
-
}
|
|
24548
|
-
};
|
|
24549
|
-
return this.query(request);
|
|
24550
24570
|
}
|
|
24551
|
-
async
|
|
24552
|
-
const
|
|
24553
|
-
const
|
|
24554
|
-
|
|
24555
|
-
|
|
24556
|
-
|
|
24557
|
-
const raw = await cfApi2("POST", path6, body);
|
|
24558
|
-
return { keys: raw };
|
|
24559
|
-
}
|
|
24560
|
-
async listValues(options) {
|
|
24561
|
-
const path6 = `/accounts/${this.accountId}/workers/observability/telemetry/values`;
|
|
24562
|
-
const now = Date.now();
|
|
24563
|
-
const oneHourAgo = now - 60 * 60 * 1000;
|
|
24564
|
-
const body = {
|
|
24565
|
-
key: options.key,
|
|
24566
|
-
type: options.type ?? "string",
|
|
24567
|
-
datasets: [],
|
|
24568
|
-
limit: options.limit ?? 50,
|
|
24569
|
-
timeframe: {
|
|
24570
|
-
from: options.from ?? oneHourAgo,
|
|
24571
|
-
to: options.to ?? now
|
|
24572
|
-
}
|
|
24573
|
-
};
|
|
24574
|
-
const raw = await cfApi2("POST", path6, body);
|
|
24575
|
-
return { values: raw.map((v) => v.value) };
|
|
24576
|
-
}
|
|
24577
|
-
async listDestinations() {
|
|
24578
|
-
const path6 = `/accounts/${this.accountId}/workers/observability/destinations`;
|
|
24579
|
-
return cfApi2("GET", path6);
|
|
24580
|
-
}
|
|
24581
|
-
async createDestination(input) {
|
|
24582
|
-
const path6 = `/accounts/${this.accountId}/workers/observability/destinations`;
|
|
24583
|
-
return cfApi2("POST", path6, input);
|
|
24584
|
-
}
|
|
24585
|
-
async deleteDestination(slug) {
|
|
24586
|
-
const path6 = `/accounts/${this.accountId}/workers/observability/destinations/${slug}`;
|
|
24587
|
-
await cfApi2("DELETE", path6);
|
|
24588
|
-
}
|
|
24589
|
-
async getUsage(options) {
|
|
24590
|
-
const path6 = `/accounts/${this.accountId}/workers/observability/usage`;
|
|
24591
|
-
const now = Date.now();
|
|
24592
|
-
const sevenDaysAgo = now - 7 * 24 * 60 * 60 * 1000;
|
|
24593
|
-
const raw = await cfApi2("GET", path6, undefined, {
|
|
24594
|
-
from: options?.from ?? sevenDaysAgo,
|
|
24595
|
-
to: options?.to ?? now
|
|
24596
|
-
});
|
|
24597
|
-
const byWorker = {};
|
|
24598
|
-
for (const row of raw.breakdown ?? []) {
|
|
24599
|
-
byWorker[row.service] = (byWorker[row.service] ?? 0) + row.count;
|
|
24571
|
+
async delete(namespaceId, key) {
|
|
24572
|
+
const proc = Bun.spawn(["wrangler", "kv", "key", "delete", "--namespace-id", namespaceId, key], { stdout: "pipe", stderr: "pipe" });
|
|
24573
|
+
const exitCode = await proc.exited;
|
|
24574
|
+
const stderr = await new Response(proc.stderr).text();
|
|
24575
|
+
if (exitCode !== 0) {
|
|
24576
|
+
throw new Error(`Failed to delete key "${key}": ${stderr.trim() || `exit ${exitCode}`}`);
|
|
24600
24577
|
}
|
|
24601
|
-
return {
|
|
24602
|
-
eventCount: raw.events,
|
|
24603
|
-
from: new Date(options?.from ?? sevenDaysAgo).toISOString(),
|
|
24604
|
-
to: new Date(options?.to ?? now).toISOString(),
|
|
24605
|
-
byWorker
|
|
24606
|
-
};
|
|
24607
24578
|
}
|
|
24608
|
-
|
|
24609
|
-
|
|
24610
|
-
|
|
24611
|
-
|
|
24579
|
+
static getManifest() {
|
|
24580
|
+
return {
|
|
24581
|
+
namespace: "CONFIG_KV",
|
|
24582
|
+
keys: [
|
|
24612
24583
|
{
|
|
24613
|
-
key: "
|
|
24614
|
-
|
|
24584
|
+
key: "webhook:tradingview:ip_check_enabled",
|
|
24585
|
+
type: "boolean",
|
|
24586
|
+
default: "false",
|
|
24587
|
+
description: "Enable TradingView IP allowlist check"
|
|
24588
|
+
},
|
|
24589
|
+
{
|
|
24590
|
+
key: "webhook:allowed_ips",
|
|
24615
24591
|
type: "string",
|
|
24616
|
-
|
|
24592
|
+
default: "",
|
|
24593
|
+
description: "Comma-separated allowed IPs for webhook"
|
|
24594
|
+
},
|
|
24595
|
+
{
|
|
24596
|
+
key: "routing:dynamic:enabled",
|
|
24597
|
+
type: "boolean",
|
|
24598
|
+
default: "false",
|
|
24599
|
+
description: "Enable dynamic routing"
|
|
24600
|
+
},
|
|
24601
|
+
{
|
|
24602
|
+
key: "trade:max_daily_drawdown_percent",
|
|
24603
|
+
type: "number",
|
|
24604
|
+
default: "10",
|
|
24605
|
+
description: "Max daily loss percentage before halt"
|
|
24606
|
+
},
|
|
24607
|
+
{
|
|
24608
|
+
key: "trade:kill_switch",
|
|
24609
|
+
type: "boolean",
|
|
24610
|
+
default: "false",
|
|
24611
|
+
description: "Emergency stop all trading"
|
|
24612
|
+
},
|
|
24613
|
+
{
|
|
24614
|
+
key: "trade:watermark:{exchange}:{symbol}:{side}",
|
|
24615
|
+
type: "number",
|
|
24616
|
+
default: "",
|
|
24617
|
+
description: "Per-market watermark (template key)",
|
|
24618
|
+
secret: true
|
|
24619
|
+
},
|
|
24620
|
+
{
|
|
24621
|
+
key: "agent:openai_key",
|
|
24622
|
+
type: "string",
|
|
24623
|
+
default: "",
|
|
24624
|
+
description: "OpenAI API key for AI agent",
|
|
24625
|
+
secret: true
|
|
24626
|
+
},
|
|
24627
|
+
{
|
|
24628
|
+
key: "agent:anthropic_key",
|
|
24629
|
+
type: "string",
|
|
24630
|
+
default: "",
|
|
24631
|
+
description: "Anthropic API key for AI agent",
|
|
24632
|
+
secret: true
|
|
24633
|
+
},
|
|
24634
|
+
{
|
|
24635
|
+
key: "agent:google_key",
|
|
24636
|
+
type: "string",
|
|
24637
|
+
default: "",
|
|
24638
|
+
description: "Google AI API key for agent",
|
|
24639
|
+
secret: true
|
|
24640
|
+
},
|
|
24641
|
+
{
|
|
24642
|
+
key: "agent:azure_api_key",
|
|
24643
|
+
type: "string",
|
|
24644
|
+
default: "",
|
|
24645
|
+
description: "Azure OpenAI API key",
|
|
24646
|
+
secret: true
|
|
24647
|
+
},
|
|
24648
|
+
{
|
|
24649
|
+
key: "agent:azure_endpoint",
|
|
24650
|
+
type: "string",
|
|
24651
|
+
default: "",
|
|
24652
|
+
description: "Azure OpenAI endpoint",
|
|
24653
|
+
secret: true
|
|
24654
|
+
},
|
|
24655
|
+
{
|
|
24656
|
+
key: "email:scan_subject",
|
|
24657
|
+
type: "string",
|
|
24658
|
+
default: "",
|
|
24659
|
+
description: "Email subject filter for signal scanning"
|
|
24660
|
+
},
|
|
24661
|
+
{
|
|
24662
|
+
key: "email:coin_pattern",
|
|
24663
|
+
type: "string",
|
|
24664
|
+
default: "",
|
|
24665
|
+
description: "Regex pattern to extract coin from email"
|
|
24666
|
+
},
|
|
24667
|
+
{
|
|
24668
|
+
key: "email:action_pattern",
|
|
24669
|
+
type: "string",
|
|
24670
|
+
default: "",
|
|
24671
|
+
description: "Regex pattern to extract action from email"
|
|
24672
|
+
},
|
|
24673
|
+
{
|
|
24674
|
+
key: "email:quantity_multiplier",
|
|
24675
|
+
type: "number",
|
|
24676
|
+
default: "1",
|
|
24677
|
+
description: "Multiplier for email signal quantity"
|
|
24678
|
+
},
|
|
24679
|
+
{
|
|
24680
|
+
key: "email:use_imap",
|
|
24681
|
+
type: "boolean",
|
|
24682
|
+
default: "false",
|
|
24683
|
+
description: "Use IMAP for email scanning"
|
|
24617
24684
|
}
|
|
24618
|
-
]
|
|
24685
|
+
]
|
|
24619
24686
|
};
|
|
24620
|
-
return cfApi2("POST", path6, body);
|
|
24621
24687
|
}
|
|
24622
|
-
|
|
24623
|
-
|
|
24624
|
-
await cfApi2("POST", path6, { sessionId });
|
|
24688
|
+
static getManifestKeys() {
|
|
24689
|
+
return KvSyncService.getManifest().keys;
|
|
24625
24690
|
}
|
|
24626
24691
|
}
|
|
24627
|
-
var
|
|
24628
|
-
|
|
24629
|
-
init_errors4();
|
|
24692
|
+
var init_kv_sync_service = __esm(() => {
|
|
24693
|
+
init_cloudflare_service();
|
|
24630
24694
|
});
|
|
24631
24695
|
|
|
24632
|
-
// src/
|
|
24633
|
-
|
|
24634
|
-
|
|
24635
|
-
|
|
24636
|
-
|
|
24637
|
-
|
|
24638
|
-
|
|
24639
|
-
Error.captureStackTrace(this, this.constructor);
|
|
24640
|
-
this.name = this.constructor.name;
|
|
24641
|
-
this.code = code;
|
|
24642
|
-
this.exitCode = exitCode;
|
|
24643
|
-
this.nestedError = undefined;
|
|
24644
|
-
}
|
|
24645
|
-
}
|
|
24646
|
-
|
|
24647
|
-
class InvalidArgumentError extends CommanderError {
|
|
24648
|
-
constructor(message) {
|
|
24649
|
-
super(1, "commander.invalidArgument", message);
|
|
24650
|
-
Error.captureStackTrace(this, this.constructor);
|
|
24651
|
-
this.name = this.constructor.name;
|
|
24652
|
-
}
|
|
24653
|
-
}
|
|
24696
|
+
// src/services/schema/schema-service.ts
|
|
24697
|
+
var exports_schema_service = {};
|
|
24698
|
+
__export(exports_schema_service, {
|
|
24699
|
+
SchemaService: () => SchemaService
|
|
24700
|
+
});
|
|
24701
|
+
import { readFileSync as readFileSync4, existsSync as existsSync7 } from "fs";
|
|
24702
|
+
import { resolve as resolve4 } from "path";
|
|
24654
24703
|
|
|
24655
|
-
|
|
24656
|
-
|
|
24657
|
-
constructor(
|
|
24658
|
-
this.
|
|
24659
|
-
this.variadic = false;
|
|
24660
|
-
this.parseArg = undefined;
|
|
24661
|
-
this.defaultValue = undefined;
|
|
24662
|
-
this.defaultValueDescription = undefined;
|
|
24663
|
-
this.argChoices = undefined;
|
|
24664
|
-
switch (name[0]) {
|
|
24665
|
-
case "<":
|
|
24666
|
-
this.required = true;
|
|
24667
|
-
this._name = name.slice(1, -1);
|
|
24668
|
-
break;
|
|
24669
|
-
case "[":
|
|
24670
|
-
this.required = false;
|
|
24671
|
-
this._name = name.slice(1, -1);
|
|
24672
|
-
break;
|
|
24673
|
-
default:
|
|
24674
|
-
this.required = true;
|
|
24675
|
-
this._name = name;
|
|
24676
|
-
break;
|
|
24677
|
-
}
|
|
24678
|
-
if (this._name.endsWith("...")) {
|
|
24679
|
-
this.variadic = true;
|
|
24680
|
-
this._name = this._name.slice(0, -3);
|
|
24681
|
-
}
|
|
24682
|
-
}
|
|
24683
|
-
name() {
|
|
24684
|
-
return this._name;
|
|
24704
|
+
class SchemaService {
|
|
24705
|
+
projectRoot;
|
|
24706
|
+
constructor(projectRoot = process.cwd()) {
|
|
24707
|
+
this.projectRoot = projectRoot;
|
|
24685
24708
|
}
|
|
24686
|
-
|
|
24687
|
-
|
|
24688
|
-
return [value];
|
|
24689
|
-
}
|
|
24690
|
-
previous.push(value);
|
|
24691
|
-
return previous;
|
|
24709
|
+
getWorkerNames() {
|
|
24710
|
+
return WORKER_NAMES;
|
|
24692
24711
|
}
|
|
24693
|
-
|
|
24694
|
-
|
|
24695
|
-
this.defaultValueDescription = description;
|
|
24696
|
-
return this;
|
|
24712
|
+
getManifest(name) {
|
|
24713
|
+
return WORKER_MANIFESTS[name];
|
|
24697
24714
|
}
|
|
24698
|
-
|
|
24699
|
-
|
|
24700
|
-
|
|
24701
|
-
|
|
24702
|
-
|
|
24703
|
-
|
|
24704
|
-
|
|
24705
|
-
|
|
24706
|
-
|
|
24707
|
-
|
|
24708
|
-
|
|
24709
|
-
|
|
24710
|
-
|
|
24711
|
-
|
|
24715
|
+
validateWorker(name) {
|
|
24716
|
+
const manifest = WORKER_MANIFESTS[name];
|
|
24717
|
+
if (!manifest) {
|
|
24718
|
+
return {
|
|
24719
|
+
worker: name,
|
|
24720
|
+
passed: false,
|
|
24721
|
+
errors: [
|
|
24722
|
+
{
|
|
24723
|
+
worker: name,
|
|
24724
|
+
severity: "error",
|
|
24725
|
+
message: `Unknown worker "${name}"`
|
|
24726
|
+
}
|
|
24727
|
+
]
|
|
24728
|
+
};
|
|
24729
|
+
}
|
|
24730
|
+
const workersDir = resolve4(this.projectRoot, "workers");
|
|
24731
|
+
const rootWranglerPath = resolve4(this.projectRoot, "wrangler.jsonc");
|
|
24732
|
+
const workerWranglerPath = resolve4(workersDir, name, "wrangler.jsonc");
|
|
24733
|
+
const devVarsPath = resolve4(workersDir, name, ".dev.vars");
|
|
24734
|
+
const errors4 = [];
|
|
24735
|
+
const isHooxProject = existsSync7(resolve4(this.projectRoot, "wrangler.jsonc")) || existsSync7(resolve4(this.projectRoot, "workers"));
|
|
24736
|
+
try {
|
|
24737
|
+
const wranglerContent = readFileSync4(workerWranglerPath, "utf-8");
|
|
24738
|
+
errors4.push(...validateWranglerJsonc(name, manifest, wranglerContent));
|
|
24739
|
+
} catch (e) {
|
|
24740
|
+
const isErrnoException = e instanceof Error && "code" in e;
|
|
24741
|
+
const isEnoent = isErrnoException && e.code === "ENOENT";
|
|
24742
|
+
const errMessage = e instanceof Error ? e.message : String(e);
|
|
24743
|
+
const message = isEnoent && !isHooxProject ? `Cannot read ${workerWranglerPath}: File not found. Are you in the Hoox project root directory?` : `Cannot read ${workerWranglerPath}: ${errMessage}`;
|
|
24744
|
+
errors4.push({
|
|
24745
|
+
worker: name,
|
|
24746
|
+
severity: "error",
|
|
24747
|
+
message
|
|
24748
|
+
});
|
|
24749
|
+
}
|
|
24750
|
+
try {
|
|
24751
|
+
const rootContent = readFileSync4(rootWranglerPath, "utf-8");
|
|
24752
|
+
errors4.push(...validateRootSecrets(name, manifest, rootContent));
|
|
24753
|
+
} catch (e) {
|
|
24754
|
+
const errMessage = e instanceof Error ? e.message : String(e);
|
|
24755
|
+
errors4.push({
|
|
24756
|
+
worker: name,
|
|
24757
|
+
severity: "warning",
|
|
24758
|
+
message: `Cannot read root wrangler.jsonc: ${errMessage}`
|
|
24759
|
+
});
|
|
24760
|
+
}
|
|
24761
|
+
try {
|
|
24762
|
+
const devVarsContent = readFileSync4(devVarsPath, "utf-8");
|
|
24763
|
+
errors4.push(...validateDevVars(name, manifest, devVarsContent));
|
|
24764
|
+
} catch (e) {
|
|
24765
|
+
const errMessage = e instanceof Error ? e.message : String(e);
|
|
24766
|
+
errors4.push({
|
|
24767
|
+
worker: name,
|
|
24768
|
+
severity: "warning",
|
|
24769
|
+
message: `Cannot read ${devVarsPath}: ${errMessage}`
|
|
24770
|
+
});
|
|
24771
|
+
}
|
|
24772
|
+
return {
|
|
24773
|
+
worker: name,
|
|
24774
|
+
passed: errors4.filter((e) => e.severity === "error").length === 0,
|
|
24775
|
+
errors: errors4
|
|
24712
24776
|
};
|
|
24713
|
-
return this;
|
|
24714
24777
|
}
|
|
24715
|
-
|
|
24716
|
-
|
|
24717
|
-
return this;
|
|
24718
|
-
}
|
|
24719
|
-
argOptional() {
|
|
24720
|
-
this.required = false;
|
|
24721
|
-
return this;
|
|
24778
|
+
validateAll() {
|
|
24779
|
+
return WORKER_NAMES.map((name) => this.validateWorker(name));
|
|
24722
24780
|
}
|
|
24723
24781
|
}
|
|
24724
|
-
|
|
24725
|
-
|
|
24726
|
-
|
|
24727
|
-
}
|
|
24728
|
-
|
|
24729
|
-
// ../../node_modules/.bun/commander@15.0.0/node_modules/commander/lib/command.js
|
|
24730
|
-
import { EventEmitter } from "events";
|
|
24731
|
-
import childProcess from "child_process";
|
|
24732
|
-
import path from "path";
|
|
24733
|
-
import fs from "fs";
|
|
24734
|
-
import process2 from "process";
|
|
24735
|
-
import { stripVTControlCharacters as stripVTControlCharacters2 } from "util";
|
|
24736
|
-
|
|
24737
|
-
// ../../node_modules/.bun/commander@15.0.0/node_modules/commander/lib/help.js
|
|
24738
|
-
import { stripVTControlCharacters } from "util";
|
|
24782
|
+
var init_schema_service = __esm(() => {
|
|
24783
|
+
init_src();
|
|
24784
|
+
});
|
|
24739
24785
|
|
|
24740
|
-
|
|
24741
|
-
|
|
24742
|
-
|
|
24743
|
-
|
|
24744
|
-
|
|
24745
|
-
|
|
24746
|
-
|
|
24786
|
+
// src/commands/trace/trace-service.ts
|
|
24787
|
+
var exports_trace_service = {};
|
|
24788
|
+
__export(exports_trace_service, {
|
|
24789
|
+
TraceService: () => TraceService
|
|
24790
|
+
});
|
|
24791
|
+
function getCredentials2() {
|
|
24792
|
+
const token = process.env.CLOUDFLARE_API_TOKEN;
|
|
24793
|
+
const accountId = process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
24794
|
+
if (!token) {
|
|
24795
|
+
throw new CLIError("CLOUDFLARE_API_TOKEN environment variable is not set. Set it or run `wrangler login`.", 1 /* ERROR */);
|
|
24747
24796
|
}
|
|
24748
|
-
|
|
24749
|
-
|
|
24797
|
+
if (!accountId) {
|
|
24798
|
+
throw new CLIError("CLOUDFLARE_ACCOUNT_ID environment variable is not set.", 1 /* ERROR */);
|
|
24750
24799
|
}
|
|
24751
|
-
|
|
24752
|
-
|
|
24753
|
-
|
|
24754
|
-
|
|
24755
|
-
|
|
24800
|
+
return { token, accountId };
|
|
24801
|
+
}
|
|
24802
|
+
async function cfApi2(method, path6, body, query) {
|
|
24803
|
+
const { token } = getCredentials2();
|
|
24804
|
+
let url2 = `${CF_API_BASE2}${path6}`;
|
|
24805
|
+
if (query) {
|
|
24806
|
+
const params = new URLSearchParams;
|
|
24807
|
+
for (const [k, v] of Object.entries(query)) {
|
|
24808
|
+
if (v !== undefined)
|
|
24809
|
+
params.set(k, String(v));
|
|
24756
24810
|
}
|
|
24757
|
-
|
|
24758
|
-
|
|
24759
|
-
|
|
24760
|
-
|
|
24811
|
+
const qs = params.toString();
|
|
24812
|
+
if (qs)
|
|
24813
|
+
url2 += `?${qs}`;
|
|
24814
|
+
}
|
|
24815
|
+
try {
|
|
24816
|
+
const response = await fetch(url2, {
|
|
24817
|
+
method,
|
|
24818
|
+
headers: {
|
|
24819
|
+
Authorization: `Bearer ${token}`,
|
|
24820
|
+
"Content-Type": "application/json"
|
|
24821
|
+
},
|
|
24822
|
+
body: body !== undefined ? JSON.stringify(body) : undefined
|
|
24823
|
+
});
|
|
24824
|
+
const json2 = await response.json();
|
|
24825
|
+
if (!response.ok || !json2.success) {
|
|
24826
|
+
const errorMsg = json2.errors?.map((e) => e.message).join("; ") || `HTTP ${response.status}`;
|
|
24827
|
+
throw new CLIError(`Cloudflare API error: ${errorMsg}`, 1 /* ERROR */);
|
|
24761
24828
|
}
|
|
24762
|
-
return
|
|
24829
|
+
return json2.result;
|
|
24830
|
+
} catch (err) {
|
|
24831
|
+
if (err instanceof CLIError)
|
|
24832
|
+
throw err;
|
|
24833
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
24834
|
+
throw new CLIError(`Cloudflare API request failed: ${message}`, 1 /* ERROR */);
|
|
24763
24835
|
}
|
|
24764
|
-
|
|
24765
|
-
|
|
24766
|
-
|
|
24767
|
-
|
|
24768
|
-
|
|
24836
|
+
}
|
|
24837
|
+
|
|
24838
|
+
class TraceService {
|
|
24839
|
+
accountId;
|
|
24840
|
+
constructor() {
|
|
24841
|
+
const { accountId } = getCredentials2();
|
|
24842
|
+
this.accountId = accountId;
|
|
24769
24843
|
}
|
|
24770
|
-
|
|
24771
|
-
const
|
|
24772
|
-
const
|
|
24773
|
-
if (
|
|
24774
|
-
const
|
|
24775
|
-
|
|
24776
|
-
if (!removeShort && !removeLong) {
|
|
24777
|
-
visibleOptions.push(helpOption);
|
|
24778
|
-
} else if (helpOption.long && !removeLong) {
|
|
24779
|
-
visibleOptions.push(cmd.createOption(helpOption.long, helpOption.description));
|
|
24780
|
-
} else if (helpOption.short && !removeShort) {
|
|
24781
|
-
visibleOptions.push(cmd.createOption(helpOption.short, helpOption.description));
|
|
24782
|
-
}
|
|
24844
|
+
async query(request) {
|
|
24845
|
+
const path6 = `/accounts/${this.accountId}/workers/observability/telemetry/query`;
|
|
24846
|
+
const result = await cfApi2("POST", path6, request);
|
|
24847
|
+
if (request.view === "events") {
|
|
24848
|
+
const events = result.events?.events ?? [];
|
|
24849
|
+
return { success: true, events };
|
|
24783
24850
|
}
|
|
24784
|
-
if (
|
|
24785
|
-
|
|
24851
|
+
if (request.view === "calculations") {
|
|
24852
|
+
const metrics = (result.calculations ?? []).map((c3) => ({
|
|
24853
|
+
calculations: (c3.aggregates ?? []).map((a3) => ({
|
|
24854
|
+
alias: c3.calculation,
|
|
24855
|
+
value: typeof a3.value === "number" ? a3.value : Number(a3.value ?? 0)
|
|
24856
|
+
})),
|
|
24857
|
+
groupBy: c3.groupBy
|
|
24858
|
+
}));
|
|
24859
|
+
return { success: true, metrics };
|
|
24786
24860
|
}
|
|
24787
|
-
return
|
|
24861
|
+
return { success: true };
|
|
24788
24862
|
}
|
|
24789
|
-
|
|
24790
|
-
|
|
24791
|
-
|
|
24792
|
-
|
|
24793
|
-
|
|
24794
|
-
|
|
24795
|
-
|
|
24796
|
-
|
|
24797
|
-
|
|
24798
|
-
globalOptions.sort(this.compareOptions);
|
|
24863
|
+
async queryEvents(options) {
|
|
24864
|
+
const filters = [];
|
|
24865
|
+
if (options.service) {
|
|
24866
|
+
filters.push({
|
|
24867
|
+
key: "$metadata.service",
|
|
24868
|
+
operation: "eq",
|
|
24869
|
+
type: "string",
|
|
24870
|
+
value: options.service
|
|
24871
|
+
});
|
|
24799
24872
|
}
|
|
24800
|
-
|
|
24801
|
-
|
|
24802
|
-
|
|
24803
|
-
|
|
24804
|
-
|
|
24805
|
-
|
|
24873
|
+
if (options.trigger) {
|
|
24874
|
+
filters.push({
|
|
24875
|
+
key: "$metadata.trigger",
|
|
24876
|
+
operation: "includes",
|
|
24877
|
+
type: "string",
|
|
24878
|
+
value: options.trigger
|
|
24806
24879
|
});
|
|
24807
24880
|
}
|
|
24808
|
-
if (
|
|
24809
|
-
|
|
24881
|
+
if (options.level) {
|
|
24882
|
+
filters.push({
|
|
24883
|
+
key: "$metadata.level",
|
|
24884
|
+
operation: "eq",
|
|
24885
|
+
type: "string",
|
|
24886
|
+
value: options.level
|
|
24887
|
+
});
|
|
24810
24888
|
}
|
|
24811
|
-
|
|
24812
|
-
|
|
24813
|
-
|
|
24814
|
-
|
|
24815
|
-
|
|
24816
|
-
|
|
24817
|
-
|
|
24818
|
-
|
|
24819
|
-
|
|
24820
|
-
|
|
24821
|
-
|
|
24889
|
+
const now = Date.now();
|
|
24890
|
+
const oneHourAgo = now - 60 * 60 * 1000;
|
|
24891
|
+
const request = {
|
|
24892
|
+
view: "events",
|
|
24893
|
+
queryId: "trace-events",
|
|
24894
|
+
limit: options.limit ?? 50,
|
|
24895
|
+
parameters: {
|
|
24896
|
+
filters
|
|
24897
|
+
},
|
|
24898
|
+
timeframe: {
|
|
24899
|
+
from: options.from ?? oneHourAgo,
|
|
24900
|
+
to: options.to ?? now
|
|
24901
|
+
}
|
|
24902
|
+
};
|
|
24903
|
+
return this.query(request);
|
|
24822
24904
|
}
|
|
24823
|
-
|
|
24824
|
-
|
|
24825
|
-
|
|
24826
|
-
|
|
24905
|
+
async queryMetrics(options) {
|
|
24906
|
+
const filters = [];
|
|
24907
|
+
if (options.service) {
|
|
24908
|
+
filters.push({
|
|
24909
|
+
key: "$metadata.service",
|
|
24910
|
+
operation: "eq",
|
|
24911
|
+
type: "string",
|
|
24912
|
+
value: options.service
|
|
24913
|
+
});
|
|
24914
|
+
}
|
|
24915
|
+
const calculations = (options.calculations ?? [{ operator: "count" }]).map((c3) => ({
|
|
24916
|
+
operator: c3.operator,
|
|
24917
|
+
key: c3.key,
|
|
24918
|
+
keyType: c3.key ? "number" : undefined,
|
|
24919
|
+
alias: c3.alias ?? c3.operator
|
|
24920
|
+
}));
|
|
24921
|
+
const groupBys = options.groupBy ? [{ type: "string", value: options.groupBy }] : [];
|
|
24922
|
+
const now = Date.now();
|
|
24923
|
+
const oneHourAgo = now - 60 * 60 * 1000;
|
|
24924
|
+
const request = {
|
|
24925
|
+
view: "calculations",
|
|
24926
|
+
queryId: "trace-metrics",
|
|
24927
|
+
parameters: {
|
|
24928
|
+
filters,
|
|
24929
|
+
calculations,
|
|
24930
|
+
groupBys
|
|
24931
|
+
},
|
|
24932
|
+
timeframe: {
|
|
24933
|
+
from: options.from ?? oneHourAgo,
|
|
24934
|
+
to: options.to ?? now
|
|
24935
|
+
}
|
|
24936
|
+
};
|
|
24937
|
+
return this.query(request);
|
|
24827
24938
|
}
|
|
24828
|
-
|
|
24829
|
-
|
|
24830
|
-
|
|
24831
|
-
|
|
24939
|
+
async listKeys(options) {
|
|
24940
|
+
const path6 = `/accounts/${this.accountId}/workers/observability/telemetry/keys`;
|
|
24941
|
+
const body = {
|
|
24942
|
+
needle: options?.needle ? { value: options.needle, isRegex: false, matchCase: false } : undefined,
|
|
24943
|
+
limit: options?.limit ?? 100
|
|
24944
|
+
};
|
|
24945
|
+
const raw = await cfApi2("POST", path6, body);
|
|
24946
|
+
return { keys: raw };
|
|
24832
24947
|
}
|
|
24833
|
-
|
|
24834
|
-
|
|
24835
|
-
|
|
24836
|
-
|
|
24948
|
+
async listValues(options) {
|
|
24949
|
+
const path6 = `/accounts/${this.accountId}/workers/observability/telemetry/values`;
|
|
24950
|
+
const now = Date.now();
|
|
24951
|
+
const oneHourAgo = now - 60 * 60 * 1000;
|
|
24952
|
+
const body = {
|
|
24953
|
+
key: options.key,
|
|
24954
|
+
type: options.type ?? "string",
|
|
24955
|
+
datasets: [],
|
|
24956
|
+
limit: options.limit ?? 50,
|
|
24957
|
+
timeframe: {
|
|
24958
|
+
from: options.from ?? oneHourAgo,
|
|
24959
|
+
to: options.to ?? now
|
|
24960
|
+
}
|
|
24961
|
+
};
|
|
24962
|
+
const raw = await cfApi2("POST", path6, body);
|
|
24963
|
+
return { values: raw.map((v) => v.value) };
|
|
24837
24964
|
}
|
|
24838
|
-
|
|
24839
|
-
|
|
24840
|
-
|
|
24841
|
-
}, 0);
|
|
24965
|
+
async listDestinations() {
|
|
24966
|
+
const path6 = `/accounts/${this.accountId}/workers/observability/destinations`;
|
|
24967
|
+
return cfApi2("GET", path6);
|
|
24842
24968
|
}
|
|
24843
|
-
|
|
24844
|
-
|
|
24845
|
-
|
|
24846
|
-
|
|
24847
|
-
|
|
24848
|
-
|
|
24849
|
-
|
|
24850
|
-
|
|
24969
|
+
async createDestination(input) {
|
|
24970
|
+
const path6 = `/accounts/${this.accountId}/workers/observability/destinations`;
|
|
24971
|
+
return cfApi2("POST", path6, input);
|
|
24972
|
+
}
|
|
24973
|
+
async deleteDestination(slug) {
|
|
24974
|
+
const path6 = `/accounts/${this.accountId}/workers/observability/destinations/${slug}`;
|
|
24975
|
+
await cfApi2("DELETE", path6);
|
|
24976
|
+
}
|
|
24977
|
+
async getUsage(options) {
|
|
24978
|
+
const path6 = `/accounts/${this.accountId}/workers/observability/usage`;
|
|
24979
|
+
const now = Date.now();
|
|
24980
|
+
const sevenDaysAgo = now - 7 * 24 * 60 * 60 * 1000;
|
|
24981
|
+
const raw = await cfApi2("GET", path6, undefined, {
|
|
24982
|
+
from: options?.from ?? sevenDaysAgo,
|
|
24983
|
+
to: options?.to ?? now
|
|
24984
|
+
});
|
|
24985
|
+
const byWorker = {};
|
|
24986
|
+
for (const row of raw.breakdown ?? []) {
|
|
24987
|
+
byWorker[row.service] = (byWorker[row.service] ?? 0) + row.count;
|
|
24851
24988
|
}
|
|
24852
|
-
return
|
|
24989
|
+
return {
|
|
24990
|
+
eventCount: raw.events,
|
|
24991
|
+
from: new Date(options?.from ?? sevenDaysAgo).toISOString(),
|
|
24992
|
+
to: new Date(options?.to ?? now).toISOString(),
|
|
24993
|
+
byWorker
|
|
24994
|
+
};
|
|
24853
24995
|
}
|
|
24854
|
-
|
|
24855
|
-
|
|
24996
|
+
async prepareLiveTail(options) {
|
|
24997
|
+
const path6 = `/accounts/${this.accountId}/workers/observability/telemetry/live-tail`;
|
|
24998
|
+
const body = {
|
|
24999
|
+
filters: options?.service ? [
|
|
25000
|
+
{
|
|
25001
|
+
key: "$metadata.service",
|
|
25002
|
+
operation: "eq",
|
|
25003
|
+
type: "string",
|
|
25004
|
+
value: options.service
|
|
25005
|
+
}
|
|
25006
|
+
] : []
|
|
25007
|
+
};
|
|
25008
|
+
return cfApi2("POST", path6, body);
|
|
24856
25009
|
}
|
|
24857
|
-
|
|
24858
|
-
|
|
25010
|
+
async liveTailHeartbeat(sessionId) {
|
|
25011
|
+
const path6 = `/accounts/${this.accountId}/workers/observability/telemetry/live-tail/heartbeat`;
|
|
25012
|
+
await cfApi2("POST", path6, { sessionId });
|
|
24859
25013
|
}
|
|
24860
|
-
|
|
24861
|
-
|
|
24862
|
-
|
|
24863
|
-
|
|
24864
|
-
|
|
24865
|
-
|
|
24866
|
-
|
|
24867
|
-
|
|
24868
|
-
|
|
24869
|
-
|
|
24870
|
-
|
|
24871
|
-
|
|
24872
|
-
|
|
24873
|
-
|
|
24874
|
-
|
|
24875
|
-
|
|
24876
|
-
|
|
24877
|
-
|
|
24878
|
-
const extraDescription = `(${extraInfo.join(", ")})`;
|
|
24879
|
-
if (option.description) {
|
|
24880
|
-
return `${option.description} ${extraDescription}`;
|
|
24881
|
-
}
|
|
24882
|
-
return extraDescription;
|
|
24883
|
-
}
|
|
24884
|
-
return option.description;
|
|
25014
|
+
}
|
|
25015
|
+
var CF_API_BASE2 = "https://api.cloudflare.com/client/v4";
|
|
25016
|
+
var init_trace_service = __esm(() => {
|
|
25017
|
+
init_errors4();
|
|
25018
|
+
});
|
|
25019
|
+
|
|
25020
|
+
// src/index.ts
|
|
25021
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
25022
|
+
|
|
25023
|
+
// ../../node_modules/.bun/commander@15.0.0/node_modules/commander/lib/error.js
|
|
25024
|
+
class CommanderError extends Error {
|
|
25025
|
+
constructor(exitCode, code, message) {
|
|
25026
|
+
super(message);
|
|
25027
|
+
Error.captureStackTrace(this, this.constructor);
|
|
25028
|
+
this.name = this.constructor.name;
|
|
25029
|
+
this.code = code;
|
|
25030
|
+
this.exitCode = exitCode;
|
|
25031
|
+
this.nestedError = undefined;
|
|
24885
25032
|
}
|
|
24886
|
-
|
|
24887
|
-
|
|
24888
|
-
|
|
24889
|
-
|
|
25033
|
+
}
|
|
25034
|
+
|
|
25035
|
+
class InvalidArgumentError extends CommanderError {
|
|
25036
|
+
constructor(message) {
|
|
25037
|
+
super(1, "commander.invalidArgument", message);
|
|
25038
|
+
Error.captureStackTrace(this, this.constructor);
|
|
25039
|
+
this.name = this.constructor.name;
|
|
25040
|
+
}
|
|
25041
|
+
}
|
|
25042
|
+
|
|
25043
|
+
// ../../node_modules/.bun/commander@15.0.0/node_modules/commander/lib/argument.js
|
|
25044
|
+
class Argument {
|
|
25045
|
+
constructor(name, description) {
|
|
25046
|
+
this.description = description || "";
|
|
25047
|
+
this.variadic = false;
|
|
25048
|
+
this.parseArg = undefined;
|
|
25049
|
+
this.defaultValue = undefined;
|
|
25050
|
+
this.defaultValueDescription = undefined;
|
|
25051
|
+
this.argChoices = undefined;
|
|
25052
|
+
switch (name[0]) {
|
|
25053
|
+
case "<":
|
|
25054
|
+
this.required = true;
|
|
25055
|
+
this._name = name.slice(1, -1);
|
|
25056
|
+
break;
|
|
25057
|
+
case "[":
|
|
25058
|
+
this.required = false;
|
|
25059
|
+
this._name = name.slice(1, -1);
|
|
25060
|
+
break;
|
|
25061
|
+
default:
|
|
25062
|
+
this.required = true;
|
|
25063
|
+
this._name = name;
|
|
25064
|
+
break;
|
|
24890
25065
|
}
|
|
24891
|
-
if (
|
|
24892
|
-
|
|
25066
|
+
if (this._name.endsWith("...")) {
|
|
25067
|
+
this.variadic = true;
|
|
25068
|
+
this._name = this._name.slice(0, -3);
|
|
24893
25069
|
}
|
|
24894
|
-
|
|
24895
|
-
|
|
24896
|
-
|
|
24897
|
-
|
|
24898
|
-
|
|
24899
|
-
|
|
25070
|
+
}
|
|
25071
|
+
name() {
|
|
25072
|
+
return this._name;
|
|
25073
|
+
}
|
|
25074
|
+
_collectValue(value, previous) {
|
|
25075
|
+
if (previous === this.defaultValue || !Array.isArray(previous)) {
|
|
25076
|
+
return [value];
|
|
24900
25077
|
}
|
|
24901
|
-
|
|
25078
|
+
previous.push(value);
|
|
25079
|
+
return previous;
|
|
24902
25080
|
}
|
|
24903
|
-
|
|
24904
|
-
|
|
24905
|
-
|
|
24906
|
-
return
|
|
25081
|
+
default(value, description) {
|
|
25082
|
+
this.defaultValue = value;
|
|
25083
|
+
this.defaultValueDescription = description;
|
|
25084
|
+
return this;
|
|
24907
25085
|
}
|
|
24908
|
-
|
|
25086
|
+
argParser(fn) {
|
|
25087
|
+
this.parseArg = fn;
|
|
25088
|
+
return this;
|
|
25089
|
+
}
|
|
25090
|
+
choices(values) {
|
|
25091
|
+
this.argChoices = values.slice();
|
|
25092
|
+
this.parseArg = (arg, previous) => {
|
|
25093
|
+
if (!this.argChoices.includes(arg)) {
|
|
25094
|
+
throw new InvalidArgumentError(`Allowed choices are ${this.argChoices.join(", ")}.`);
|
|
25095
|
+
}
|
|
25096
|
+
if (this.variadic) {
|
|
25097
|
+
return this._collectValue(arg, previous);
|
|
25098
|
+
}
|
|
25099
|
+
return arg;
|
|
25100
|
+
};
|
|
25101
|
+
return this;
|
|
25102
|
+
}
|
|
25103
|
+
argRequired() {
|
|
25104
|
+
this.required = true;
|
|
25105
|
+
return this;
|
|
25106
|
+
}
|
|
25107
|
+
argOptional() {
|
|
25108
|
+
this.required = false;
|
|
25109
|
+
return this;
|
|
25110
|
+
}
|
|
25111
|
+
}
|
|
25112
|
+
function humanReadableArgName(arg) {
|
|
25113
|
+
const nameOutput = arg.name() + (arg.variadic === true ? "..." : "");
|
|
25114
|
+
return arg.required ? "<" + nameOutput + ">" : "[" + nameOutput + "]";
|
|
25115
|
+
}
|
|
25116
|
+
|
|
25117
|
+
// ../../node_modules/.bun/commander@15.0.0/node_modules/commander/lib/command.js
|
|
25118
|
+
import { EventEmitter } from "events";
|
|
25119
|
+
import childProcess from "child_process";
|
|
25120
|
+
import path from "path";
|
|
25121
|
+
import fs from "fs";
|
|
25122
|
+
import process2 from "process";
|
|
25123
|
+
import { stripVTControlCharacters as stripVTControlCharacters2 } from "util";
|
|
25124
|
+
|
|
25125
|
+
// ../../node_modules/.bun/commander@15.0.0/node_modules/commander/lib/help.js
|
|
25126
|
+
import { stripVTControlCharacters } from "util";
|
|
25127
|
+
|
|
25128
|
+
class Help {
|
|
25129
|
+
constructor() {
|
|
25130
|
+
this.helpWidth = undefined;
|
|
25131
|
+
this.minWidthToWrap = 40;
|
|
25132
|
+
this.sortSubcommands = false;
|
|
25133
|
+
this.sortOptions = false;
|
|
25134
|
+
this.showGlobalOptions = false;
|
|
25135
|
+
}
|
|
25136
|
+
prepareContext(contextOptions) {
|
|
25137
|
+
this.helpWidth = this.helpWidth ?? contextOptions.helpWidth ?? 80;
|
|
25138
|
+
}
|
|
25139
|
+
visibleCommands(cmd) {
|
|
25140
|
+
const visibleCommands = cmd.commands.filter((cmd2) => !cmd2._hidden);
|
|
25141
|
+
const helpCommand = cmd._getHelpCommand();
|
|
25142
|
+
if (helpCommand && !helpCommand._hidden) {
|
|
25143
|
+
visibleCommands.push(helpCommand);
|
|
25144
|
+
}
|
|
25145
|
+
if (this.sortSubcommands) {
|
|
25146
|
+
visibleCommands.sort((a, b) => {
|
|
25147
|
+
return a.name().localeCompare(b.name());
|
|
25148
|
+
});
|
|
25149
|
+
}
|
|
25150
|
+
return visibleCommands;
|
|
25151
|
+
}
|
|
25152
|
+
compareOptions(a, b) {
|
|
25153
|
+
const getSortKey = (option) => {
|
|
25154
|
+
return option.short ? option.short.replace(/^-/, "") : option.long.replace(/^--/, "");
|
|
25155
|
+
};
|
|
25156
|
+
return getSortKey(a).localeCompare(getSortKey(b));
|
|
25157
|
+
}
|
|
25158
|
+
visibleOptions(cmd) {
|
|
25159
|
+
const visibleOptions = cmd.options.filter((option) => !option.hidden);
|
|
25160
|
+
const helpOption = cmd._getHelpOption();
|
|
25161
|
+
if (helpOption && !helpOption.hidden) {
|
|
25162
|
+
const removeShort = helpOption.short && cmd._findOption(helpOption.short);
|
|
25163
|
+
const removeLong = helpOption.long && cmd._findOption(helpOption.long);
|
|
25164
|
+
if (!removeShort && !removeLong) {
|
|
25165
|
+
visibleOptions.push(helpOption);
|
|
25166
|
+
} else if (helpOption.long && !removeLong) {
|
|
25167
|
+
visibleOptions.push(cmd.createOption(helpOption.long, helpOption.description));
|
|
25168
|
+
} else if (helpOption.short && !removeShort) {
|
|
25169
|
+
visibleOptions.push(cmd.createOption(helpOption.short, helpOption.description));
|
|
25170
|
+
}
|
|
25171
|
+
}
|
|
25172
|
+
if (this.sortOptions) {
|
|
25173
|
+
visibleOptions.sort(this.compareOptions);
|
|
25174
|
+
}
|
|
25175
|
+
return visibleOptions;
|
|
25176
|
+
}
|
|
25177
|
+
visibleGlobalOptions(cmd) {
|
|
25178
|
+
if (!this.showGlobalOptions)
|
|
25179
|
+
return [];
|
|
25180
|
+
const globalOptions = [];
|
|
25181
|
+
for (let ancestorCmd = cmd.parent;ancestorCmd; ancestorCmd = ancestorCmd.parent) {
|
|
25182
|
+
const visibleOptions = ancestorCmd.options.filter((option) => !option.hidden);
|
|
25183
|
+
globalOptions.push(...visibleOptions);
|
|
25184
|
+
}
|
|
25185
|
+
if (this.sortOptions) {
|
|
25186
|
+
globalOptions.sort(this.compareOptions);
|
|
25187
|
+
}
|
|
25188
|
+
return globalOptions;
|
|
25189
|
+
}
|
|
25190
|
+
visibleArguments(cmd) {
|
|
25191
|
+
if (cmd._argsDescription) {
|
|
25192
|
+
cmd.registeredArguments.forEach((argument) => {
|
|
25193
|
+
argument.description = argument.description || cmd._argsDescription[argument.name()] || "";
|
|
25194
|
+
});
|
|
25195
|
+
}
|
|
25196
|
+
if (cmd.registeredArguments.find((argument) => argument.description)) {
|
|
25197
|
+
return cmd.registeredArguments;
|
|
25198
|
+
}
|
|
25199
|
+
return [];
|
|
25200
|
+
}
|
|
25201
|
+
subcommandTerm(cmd) {
|
|
25202
|
+
const args = cmd.registeredArguments.map((arg) => humanReadableArgName(arg)).join(" ");
|
|
25203
|
+
return cmd._name + (cmd._aliases[0] ? "|" + cmd._aliases[0] : "") + (cmd.options.length ? " [options]" : "") + (args ? " " + args : "");
|
|
25204
|
+
}
|
|
25205
|
+
optionTerm(option) {
|
|
25206
|
+
return option.flags;
|
|
25207
|
+
}
|
|
25208
|
+
argumentTerm(argument) {
|
|
25209
|
+
return argument.name();
|
|
25210
|
+
}
|
|
25211
|
+
longestSubcommandTermLength(cmd, helper) {
|
|
25212
|
+
return helper.visibleCommands(cmd).reduce((max, command) => {
|
|
25213
|
+
return Math.max(max, this.displayWidth(helper.styleSubcommandTerm(helper.subcommandTerm(command))));
|
|
25214
|
+
}, 0);
|
|
25215
|
+
}
|
|
25216
|
+
longestOptionTermLength(cmd, helper) {
|
|
25217
|
+
return helper.visibleOptions(cmd).reduce((max, option) => {
|
|
25218
|
+
return Math.max(max, this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))));
|
|
25219
|
+
}, 0);
|
|
25220
|
+
}
|
|
25221
|
+
longestGlobalOptionTermLength(cmd, helper) {
|
|
25222
|
+
return helper.visibleGlobalOptions(cmd).reduce((max, option) => {
|
|
25223
|
+
return Math.max(max, this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option))));
|
|
25224
|
+
}, 0);
|
|
25225
|
+
}
|
|
25226
|
+
longestArgumentTermLength(cmd, helper) {
|
|
25227
|
+
return helper.visibleArguments(cmd).reduce((max, argument) => {
|
|
25228
|
+
return Math.max(max, this.displayWidth(helper.styleArgumentTerm(helper.argumentTerm(argument))));
|
|
25229
|
+
}, 0);
|
|
25230
|
+
}
|
|
25231
|
+
commandUsage(cmd) {
|
|
25232
|
+
let cmdName = cmd._name;
|
|
25233
|
+
if (cmd._aliases[0]) {
|
|
25234
|
+
cmdName = cmdName + "|" + cmd._aliases[0];
|
|
25235
|
+
}
|
|
25236
|
+
let ancestorCmdNames = "";
|
|
25237
|
+
for (let ancestorCmd = cmd.parent;ancestorCmd; ancestorCmd = ancestorCmd.parent) {
|
|
25238
|
+
ancestorCmdNames = ancestorCmd.name() + " " + ancestorCmdNames;
|
|
25239
|
+
}
|
|
25240
|
+
return ancestorCmdNames + cmdName + " " + cmd.usage();
|
|
25241
|
+
}
|
|
25242
|
+
commandDescription(cmd) {
|
|
25243
|
+
return cmd.description();
|
|
25244
|
+
}
|
|
25245
|
+
subcommandDescription(cmd) {
|
|
25246
|
+
return cmd.summary() || cmd.description();
|
|
25247
|
+
}
|
|
25248
|
+
optionDescription(option) {
|
|
25249
|
+
const extraInfo = [];
|
|
25250
|
+
if (option.argChoices) {
|
|
25251
|
+
extraInfo.push(`choices: ${option.argChoices.map((choice) => JSON.stringify(choice)).join(", ")}`);
|
|
25252
|
+
}
|
|
25253
|
+
if (option.defaultValue !== undefined) {
|
|
25254
|
+
const showDefault = option.required || option.optional || option.isBoolean() && typeof option.defaultValue === "boolean";
|
|
25255
|
+
if (showDefault) {
|
|
25256
|
+
extraInfo.push(`default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`);
|
|
25257
|
+
}
|
|
25258
|
+
}
|
|
25259
|
+
if (option.presetArg !== undefined && option.optional) {
|
|
25260
|
+
extraInfo.push(`preset: ${JSON.stringify(option.presetArg)}`);
|
|
25261
|
+
}
|
|
25262
|
+
if (option.envVar !== undefined) {
|
|
25263
|
+
extraInfo.push(`env: ${option.envVar}`);
|
|
25264
|
+
}
|
|
25265
|
+
if (extraInfo.length > 0) {
|
|
25266
|
+
const extraDescription = `(${extraInfo.join(", ")})`;
|
|
25267
|
+
if (option.description) {
|
|
25268
|
+
return `${option.description} ${extraDescription}`;
|
|
25269
|
+
}
|
|
25270
|
+
return extraDescription;
|
|
25271
|
+
}
|
|
25272
|
+
return option.description;
|
|
25273
|
+
}
|
|
25274
|
+
argumentDescription(argument) {
|
|
25275
|
+
const extraInfo = [];
|
|
25276
|
+
if (argument.argChoices) {
|
|
25277
|
+
extraInfo.push(`choices: ${argument.argChoices.map((choice) => JSON.stringify(choice)).join(", ")}`);
|
|
25278
|
+
}
|
|
25279
|
+
if (argument.defaultValue !== undefined) {
|
|
25280
|
+
extraInfo.push(`default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`);
|
|
25281
|
+
}
|
|
25282
|
+
if (extraInfo.length > 0) {
|
|
25283
|
+
const extraDescription = `(${extraInfo.join(", ")})`;
|
|
25284
|
+
if (argument.description) {
|
|
25285
|
+
return `${argument.description} ${extraDescription}`;
|
|
25286
|
+
}
|
|
25287
|
+
return extraDescription;
|
|
25288
|
+
}
|
|
25289
|
+
return argument.description;
|
|
25290
|
+
}
|
|
25291
|
+
formatItemList(heading, items, helper) {
|
|
25292
|
+
if (items.length === 0)
|
|
25293
|
+
return [];
|
|
25294
|
+
return [helper.styleTitle(heading), ...items, ""];
|
|
25295
|
+
}
|
|
25296
|
+
groupItems(unsortedItems, visibleItems, getGroup) {
|
|
24909
25297
|
const result = new Map;
|
|
24910
25298
|
unsortedItems.forEach((item) => {
|
|
24911
25299
|
const group = getGroup(item);
|
|
@@ -26983,608 +27371,254 @@ function colorizeCell(value, colorizeStatus) {
|
|
|
26983
27371
|
].includes(lower)) {
|
|
26984
27372
|
return `${theme.success(icons.success)} ${theme.text(v)}`;
|
|
26985
27373
|
}
|
|
26986
|
-
if (["warn", "warning", "degraded", "partial", "pending"].includes(lower)) {
|
|
26987
|
-
return `${theme.warning(icons.warning)} ${theme.text(v)}`;
|
|
26988
|
-
}
|
|
26989
|
-
if ([
|
|
26990
|
-
"err",
|
|
26991
|
-
"error",
|
|
26992
|
-
"fail",
|
|
26993
|
-
"failed",
|
|
26994
|
-
"down",
|
|
26995
|
-
"unreachable",
|
|
26996
|
-
"disabled"
|
|
26997
|
-
].includes(lower)) {
|
|
26998
|
-
return `${theme.error(icons.error)} ${theme.text(v)}`;
|
|
26999
|
-
}
|
|
27000
|
-
return value;
|
|
27001
|
-
}
|
|
27002
|
-
function formatJson(data, opts) {
|
|
27003
|
-
const json2 = opts?.quiet ? JSON.stringify(data) : JSON.stringify(data, null, 2);
|
|
27004
|
-
process.stdout.write(`${json2}
|
|
27005
|
-
`);
|
|
27006
|
-
}
|
|
27007
|
-
function formatKeyValue(pairs, opts = {}) {
|
|
27008
|
-
if (opts.quiet)
|
|
27009
|
-
return;
|
|
27010
|
-
if (opts.json) {
|
|
27011
|
-
process.stdout.write(JSON.stringify(pairs, null, 2) + `
|
|
27012
|
-
`);
|
|
27013
|
-
return;
|
|
27014
|
-
}
|
|
27015
|
-
const maxKeyLen = Math.max(...Object.keys(pairs).map((k) => stripAnsi(k).length), 0);
|
|
27016
|
-
for (const [key, value] of Object.entries(pairs)) {
|
|
27017
|
-
const paddedKey = key.padEnd(maxKeyLen);
|
|
27018
|
-
process.stdout.write(` ${theme.key(paddedKey)} ${theme.textMuted(":")} ${value}
|
|
27019
|
-
`);
|
|
27020
|
-
}
|
|
27021
|
-
}
|
|
27022
|
-
function getFormatOptions(cmd) {
|
|
27023
|
-
const opts = cmd.optsWithGlobals();
|
|
27024
|
-
return {
|
|
27025
|
-
json: Boolean(opts.json),
|
|
27026
|
-
quiet: Boolean(opts.quiet),
|
|
27027
|
-
noColor: Boolean(opts.color === false)
|
|
27028
|
-
};
|
|
27029
|
-
}
|
|
27030
|
-
function formatCompletion(message, opts = {}) {
|
|
27031
|
-
if (opts.json || opts.quiet)
|
|
27032
|
-
return;
|
|
27033
|
-
if (process.exitCode && process.exitCode !== 0)
|
|
27034
|
-
return;
|
|
27035
|
-
if (!isRichMode(opts))
|
|
27036
|
-
return;
|
|
27037
|
-
const parts = [theme.success(icons.success), theme.text(message)];
|
|
27038
|
-
if (opts.durationMs !== undefined) {
|
|
27039
|
-
parts.push(theme.textMuted(formatDuration3(opts.durationMs)));
|
|
27040
|
-
}
|
|
27041
|
-
process.stdout.write(`${parts.join(" ")}
|
|
27042
|
-
`);
|
|
27043
|
-
if (opts.suggestion) {
|
|
27044
|
-
const reason = opts.suggestion.reason ? ` ${theme.textMuted(`(${opts.suggestion.reason})`)}` : "";
|
|
27045
|
-
process.stdout.write(` ${theme.textMuted("\u2192")} ${theme.textMuted("next:")} ${theme.accent(opts.suggestion.command)}${reason}
|
|
27046
|
-
`);
|
|
27047
|
-
}
|
|
27048
|
-
}
|
|
27049
|
-
|
|
27050
|
-
// src/utils/error-handler.ts
|
|
27051
|
-
init_errors4();
|
|
27052
|
-
|
|
27053
|
-
// src/utils/string.ts
|
|
27054
|
-
function levenshtein(a2, b) {
|
|
27055
|
-
if (a2 === b)
|
|
27056
|
-
return 0;
|
|
27057
|
-
if (a2.length === 0)
|
|
27058
|
-
return b.length;
|
|
27059
|
-
if (b.length === 0)
|
|
27060
|
-
return a2.length;
|
|
27061
|
-
const [s, t] = a2.length <= b.length ? [a2, b] : [b, a2];
|
|
27062
|
-
const m = s.length;
|
|
27063
|
-
const n = t.length;
|
|
27064
|
-
let prev = new Array(m + 1);
|
|
27065
|
-
for (let i = 0;i <= m; i++)
|
|
27066
|
-
prev[i] = i;
|
|
27067
|
-
let curr = new Array(m + 1);
|
|
27068
|
-
for (let j = 1;j <= n; j++) {
|
|
27069
|
-
curr[0] = j;
|
|
27070
|
-
for (let i = 1;i <= m; i++) {
|
|
27071
|
-
const cost = s.charCodeAt(i - 1) === t.charCodeAt(j - 1) ? 0 : 1;
|
|
27072
|
-
curr[i] = Math.min(curr[i - 1] + 1, prev[i] + 1, prev[i - 1] + cost);
|
|
27073
|
-
}
|
|
27074
|
-
[prev, curr] = [curr, prev];
|
|
27075
|
-
}
|
|
27076
|
-
return prev[m];
|
|
27077
|
-
}
|
|
27078
|
-
|
|
27079
|
-
// src/utils/error-handler.ts
|
|
27080
|
-
var SUGGESTION_THRESHOLD = 2;
|
|
27081
|
-
function collectCommandNames(cmd, acc = new Set) {
|
|
27082
|
-
for (const sub of cmd.commands) {
|
|
27083
|
-
if (sub.name() && !sub.hidden) {
|
|
27084
|
-
acc.add(sub.name());
|
|
27085
|
-
collectCommandNames(sub, acc);
|
|
27086
|
-
}
|
|
27087
|
-
}
|
|
27088
|
-
return acc;
|
|
27089
|
-
}
|
|
27090
|
-
function suggestForCommand(program2, unknown2) {
|
|
27091
|
-
if (unknown2.length < 2)
|
|
27092
|
-
return;
|
|
27093
|
-
const normalized = unknown2.replace(/s$/, "");
|
|
27094
|
-
const candidates = collectCommandNames(program2);
|
|
27095
|
-
let best;
|
|
27096
|
-
for (const candidate of candidates) {
|
|
27097
|
-
const d = Math.min(levenshtein(unknown2, candidate), levenshtein(normalized, candidate));
|
|
27098
|
-
if (d > SUGGESTION_THRESHOLD)
|
|
27099
|
-
continue;
|
|
27100
|
-
if (!best || d < best.dist) {
|
|
27101
|
-
best = { name: candidate, dist: d };
|
|
27102
|
-
}
|
|
27103
|
-
}
|
|
27104
|
-
return best?.name;
|
|
27105
|
-
}
|
|
27106
|
-
function withErrorHandling(handler, options) {
|
|
27107
|
-
return async (...args) => {
|
|
27108
|
-
try {
|
|
27109
|
-
await handler(...args);
|
|
27110
|
-
} catch (error51) {
|
|
27111
|
-
const service = options?.service ?? "cli";
|
|
27112
|
-
if (error51 instanceof CLIError) {
|
|
27113
|
-
formatError2(error51, options?.opts);
|
|
27114
|
-
process.exitCode = error51.code;
|
|
27115
|
-
return;
|
|
27116
|
-
} else if (error51 instanceof Error) {
|
|
27117
|
-
formatError2(`[${service}] ${error51.message}`, options?.opts);
|
|
27118
|
-
process.exitCode = 1 /* ERROR */;
|
|
27119
|
-
return;
|
|
27120
|
-
} else {
|
|
27121
|
-
formatError2(`[${service}] Unknown error: ${String(error51)}`, options?.opts);
|
|
27122
|
-
process.exitCode = 4 /* CommandFailed */;
|
|
27123
|
-
return;
|
|
27124
|
-
}
|
|
27125
|
-
}
|
|
27126
|
-
};
|
|
27127
|
-
}
|
|
27128
|
-
|
|
27129
|
-
// src/utils/help-formatter.ts
|
|
27130
|
-
function renderHelp(cmd, helper) {
|
|
27131
|
-
const subcommands = cmd.commands.filter((c) => !c._hidden).map((c) => ({ name: c.name(), desc: c.description() ?? "" }));
|
|
27132
|
-
const blocks = [];
|
|
27133
|
-
const argNames = cmd.registeredArguments.map((a2) => a2.name()).join(" ");
|
|
27134
|
-
const titleName = argNames ? `${cmd.name()} ${argNames}` : cmd.name();
|
|
27135
|
-
blocks.push(theme.heading(` ${titleName}`));
|
|
27136
|
-
if (cmd.description()) {
|
|
27137
|
-
blocks.push(` ${theme.textMuted(cmd.description())}`);
|
|
27138
|
-
}
|
|
27139
|
-
blocks.push(theme.textFaint("\u2500".repeat(60)));
|
|
27140
|
-
const usageLine = buildUsage(cmd);
|
|
27141
|
-
blocks.push(headerLine("Usage"));
|
|
27142
|
-
blocks.push(` ${theme.accent(usageLine)}`);
|
|
27143
|
-
const options = cmd.options.filter((o) => !o.hidden);
|
|
27144
|
-
if (options.length > 0) {
|
|
27145
|
-
blocks.push("");
|
|
27146
|
-
blocks.push(headerLine("Options"));
|
|
27147
|
-
const flagWidth = Math.max(...options.map((o) => o.flags.length));
|
|
27148
|
-
for (const o of options) {
|
|
27149
|
-
const padded = o.flags.padEnd(flagWidth);
|
|
27150
|
-
const desc = o.description ? theme.textMuted(o.description) : "";
|
|
27151
|
-
blocks.push(` ${theme.text(padded)} ${desc}`);
|
|
27152
|
-
}
|
|
27153
|
-
}
|
|
27154
|
-
if (subcommands.length > 0) {
|
|
27155
|
-
blocks.push("");
|
|
27156
|
-
blocks.push(headerLine("Commands"));
|
|
27157
|
-
const nameWidth = Math.max(...subcommands.map((s) => s.name.length));
|
|
27158
|
-
for (const s of subcommands) {
|
|
27159
|
-
const padded = s.name.padEnd(nameWidth);
|
|
27160
|
-
blocks.push(` ${theme.text(padded)} ${theme.textMuted(s.desc)}`);
|
|
27161
|
-
}
|
|
27162
|
-
}
|
|
27163
|
-
const afterText = captureHelpEvent(cmd, "afterHelp");
|
|
27164
|
-
if (afterText.trim()) {
|
|
27165
|
-
blocks.push("");
|
|
27166
|
-
blocks.push(headerLine("Examples"));
|
|
27167
|
-
blocks.push(` ${theme.textMuted(afterText.trim())}`);
|
|
27168
|
-
}
|
|
27169
|
-
const out = blocks.join(`
|
|
27170
|
-
`) + `
|
|
27171
|
-
`;
|
|
27172
|
-
return isRichMode() ? out : stripAnsi(out);
|
|
27173
|
-
}
|
|
27174
|
-
function headerLine(text) {
|
|
27175
|
-
return ` ${theme.textSubtle(text)}`;
|
|
27176
|
-
}
|
|
27177
|
-
function buildUsage(cmd) {
|
|
27178
|
-
const parts = [];
|
|
27179
|
-
let c = cmd;
|
|
27180
|
-
while (c && c.name()) {
|
|
27181
|
-
parts.unshift(c.name());
|
|
27182
|
-
c = c.parent;
|
|
27183
|
-
}
|
|
27184
|
-
for (const arg of cmd.registeredArguments) {
|
|
27185
|
-
parts.push(arg.name());
|
|
27186
|
-
}
|
|
27187
|
-
return `${parts.join(" ")} [options]`;
|
|
27188
|
-
}
|
|
27189
|
-
function captureHelpEvent(cmd, eventName) {
|
|
27190
|
-
const parts = [];
|
|
27191
|
-
const context = {
|
|
27192
|
-
error: false,
|
|
27193
|
-
command: cmd,
|
|
27194
|
-
write: (str) => {
|
|
27195
|
-
parts.push(str);
|
|
27196
|
-
}
|
|
27197
|
-
};
|
|
27198
|
-
const emitter = cmd;
|
|
27199
|
-
emitter.emit(eventName, context);
|
|
27200
|
-
return parts.join("");
|
|
27201
|
-
}
|
|
27202
|
-
|
|
27203
|
-
// src/utils/completion.ts
|
|
27204
|
-
var SUGGEST_NEXT = {
|
|
27205
|
-
init: { command: "hoox setup", reason: "provision infrastructure" },
|
|
27206
|
-
setup: { command: "hoox deploy all", reason: "ship to Cloudflare" },
|
|
27207
|
-
"deploy all": { command: "hoox check health", reason: "verify the deploy" },
|
|
27208
|
-
"check health": { command: "hoox monitor status", reason: "keep watching" },
|
|
27209
|
-
"monitor kill-switch off": {
|
|
27210
|
-
command: "hoox check health",
|
|
27211
|
-
reason: "re-enable trading"
|
|
27212
|
-
}
|
|
27213
|
-
};
|
|
27214
|
-
function suggestNextCommand(commandPath) {
|
|
27215
|
-
return SUGGEST_NEXT[commandPath];
|
|
27216
|
-
}
|
|
27217
|
-
function getCmdPath(cmd) {
|
|
27218
|
-
const parts = [];
|
|
27219
|
-
let current2 = cmd;
|
|
27220
|
-
while (current2 && current2.name() && current2.parent) {
|
|
27221
|
-
parts.unshift(current2.name());
|
|
27222
|
-
current2 = current2.parent;
|
|
27223
|
-
}
|
|
27224
|
-
return parts.join(" ");
|
|
27225
|
-
}
|
|
27226
|
-
|
|
27227
|
-
// src/commands/init/init-command.ts
|
|
27228
|
-
init_dist4();
|
|
27229
|
-
init_src();
|
|
27230
|
-
|
|
27231
|
-
// src/services/cloudflare/cloudflare-service.ts
|
|
27232
|
-
init_config2();
|
|
27233
|
-
import path3 from "path";
|
|
27234
|
-
|
|
27235
|
-
class CloudflareService {
|
|
27236
|
-
cwd;
|
|
27237
|
-
homeDir;
|
|
27238
|
-
configService;
|
|
27239
|
-
constructor(cwd, homeDir, configService) {
|
|
27240
|
-
this.cwd = cwd ?? process.cwd();
|
|
27241
|
-
this.homeDir = homeDir;
|
|
27242
|
-
this.configService = configService ?? (this.homeDir ? new ConfigService(undefined, this.homeDir) : undefined);
|
|
27243
|
-
}
|
|
27244
|
-
resolveWorkerPath(workerPath) {
|
|
27245
|
-
if (this.configService) {
|
|
27246
|
-
const workerName = path3.basename(workerPath);
|
|
27247
|
-
return this.configService.getWorkerPath(workerName);
|
|
27248
|
-
}
|
|
27249
|
-
if (this.homeDir) {
|
|
27250
|
-
const workerName = path3.basename(workerPath);
|
|
27251
|
-
return path3.join(this.homeDir, ".hoox", "workers", workerName);
|
|
27252
|
-
}
|
|
27253
|
-
return path3.resolve(this.cwd, workerPath);
|
|
27254
|
-
}
|
|
27255
|
-
async runWrangler(args, cwd) {
|
|
27256
|
-
try {
|
|
27257
|
-
const proc = Bun.spawn(["wrangler", ...args], {
|
|
27258
|
-
cwd: cwd ?? this.cwd,
|
|
27259
|
-
stdout: "pipe",
|
|
27260
|
-
stderr: "pipe"
|
|
27261
|
-
});
|
|
27262
|
-
const stdout2 = await new Response(proc.stdout).text();
|
|
27263
|
-
const stderr = await new Response(proc.stderr).text();
|
|
27264
|
-
const exitCode = await proc.exited;
|
|
27265
|
-
if (exitCode === 0) {
|
|
27266
|
-
return { ok: true, value: stdout2.trim() };
|
|
27267
|
-
}
|
|
27268
|
-
return {
|
|
27269
|
-
ok: false,
|
|
27270
|
-
error: stderr.trim() || `wrangler exited with code ${exitCode}`
|
|
27271
|
-
};
|
|
27272
|
-
} catch (err) {
|
|
27273
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
27274
|
-
const hint = /ENOENT|not found/i.test(message) ? "Install wrangler with `bun add -g wrangler` (or `npm i -g wrangler`), then run `wrangler login`." : undefined;
|
|
27275
|
-
return {
|
|
27276
|
-
ok: false,
|
|
27277
|
-
error: hint ? `Failed to spawn wrangler: ${message}
|
|
27278
|
-
\u21B3 hint: ${hint}` : `Failed to spawn wrangler: ${message}`
|
|
27279
|
-
};
|
|
27280
|
-
}
|
|
27281
|
-
}
|
|
27282
|
-
async whoami() {
|
|
27283
|
-
return this.runWrangler(["whoami"]);
|
|
27284
|
-
}
|
|
27285
|
-
async deploy(workerPath, env) {
|
|
27286
|
-
const resolvedPath = this.resolveWorkerPath(workerPath);
|
|
27287
|
-
const args = ["deploy"];
|
|
27288
|
-
if (env) {
|
|
27289
|
-
args.push("--env", env);
|
|
27290
|
-
}
|
|
27291
|
-
const result = await this.runWrangler(args, resolvedPath);
|
|
27292
|
-
if (!result.ok) {
|
|
27293
|
-
return result;
|
|
27294
|
-
}
|
|
27295
|
-
const url2 = this.extractUrl(result.value);
|
|
27296
|
-
const output = result.value;
|
|
27297
|
-
const deployResult = { url: url2, rawOutput: output };
|
|
27298
|
-
const pathParts = workerPath.split("/");
|
|
27299
|
-
deployResult.name = pathParts[pathParts.length - 1];
|
|
27300
|
-
const sizeMatch = output.match(/Total Upload:\s*([\d.]+)\s*([KMGT]?i?B)/i);
|
|
27301
|
-
if (sizeMatch) {
|
|
27302
|
-
deployResult.size = `${sizeMatch[1]} ${sizeMatch[2]}`;
|
|
27303
|
-
}
|
|
27304
|
-
const startupMatch = output.match(/Worker Startup Time:\s*(\d+)\s*ms/i);
|
|
27305
|
-
if (startupMatch) {
|
|
27306
|
-
deployResult.startupTime = `${startupMatch[1]} ms`;
|
|
27307
|
-
}
|
|
27308
|
-
const versionMatch = output.match(/Current Version ID:\s*([a-f0-9-]{36,})/i);
|
|
27309
|
-
if (versionMatch) {
|
|
27310
|
-
deployResult.versionId = versionMatch[1];
|
|
27311
|
-
}
|
|
27312
|
-
return { ok: true, value: deployResult };
|
|
27313
|
-
}
|
|
27314
|
-
async versionsList(workerName) {
|
|
27315
|
-
const result = await this.runWrangler([
|
|
27316
|
-
"versions",
|
|
27317
|
-
"list",
|
|
27318
|
-
"--name",
|
|
27319
|
-
workerName,
|
|
27320
|
-
"--json"
|
|
27321
|
-
]);
|
|
27322
|
-
if (!result.ok) {
|
|
27323
|
-
return result;
|
|
27324
|
-
}
|
|
27325
|
-
try {
|
|
27326
|
-
const parsed = JSON.parse(result.value);
|
|
27327
|
-
if (!Array.isArray(parsed)) {
|
|
27328
|
-
return {
|
|
27329
|
-
ok: false,
|
|
27330
|
-
error: `Expected array from wrangler versions list, got ${typeof parsed}`
|
|
27331
|
-
};
|
|
27332
|
-
}
|
|
27333
|
-
const versions2 = parsed.map((v) => ({
|
|
27334
|
-
id: String(v.id ?? ""),
|
|
27335
|
-
number: typeof v.number === "number" ? v.number : undefined,
|
|
27336
|
-
created_on: typeof v.metadata === "object" && v.metadata !== null ? String(v.metadata.created_on ?? "") : undefined,
|
|
27337
|
-
author: typeof v.metadata === "object" && v.metadata !== null ? String(v.metadata.author ?? "") : undefined,
|
|
27338
|
-
message: typeof v.metadata === "object" && v.metadata !== null ? String(v.metadata.message ?? "") : undefined,
|
|
27339
|
-
source: typeof v.metadata === "object" && v.metadata !== null ? String(v.metadata.source ?? "") : undefined
|
|
27340
|
-
}));
|
|
27341
|
-
return { ok: true, value: versions2 };
|
|
27342
|
-
} catch (err) {
|
|
27343
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
27344
|
-
return {
|
|
27345
|
-
ok: false,
|
|
27346
|
-
error: `Failed to parse versions list: ${message}`
|
|
27347
|
-
};
|
|
27348
|
-
}
|
|
27349
|
-
}
|
|
27350
|
-
async versionsRollback(workerName, versionId) {
|
|
27351
|
-
return this.runWrangler([
|
|
27352
|
-
"versions",
|
|
27353
|
-
"rollback",
|
|
27354
|
-
"--name",
|
|
27355
|
-
workerName,
|
|
27356
|
-
"--version-id",
|
|
27357
|
-
versionId
|
|
27358
|
-
]);
|
|
27359
|
-
}
|
|
27360
|
-
async dev(workerPath, port) {
|
|
27361
|
-
const devPort = port ?? 8787;
|
|
27362
|
-
const resolvedPath = this.resolveWorkerPath(workerPath);
|
|
27363
|
-
try {
|
|
27364
|
-
Bun.spawn(["wrangler", "dev", "--port", String(devPort)], {
|
|
27365
|
-
cwd: resolvedPath,
|
|
27366
|
-
stdout: "pipe",
|
|
27367
|
-
stderr: "pipe"
|
|
27368
|
-
});
|
|
27369
|
-
return { ok: true, value: { port: devPort } };
|
|
27370
|
-
} catch (err) {
|
|
27371
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
27372
|
-
return { ok: false, error: `Failed to start dev server: ${message}` };
|
|
27373
|
-
}
|
|
27374
|
-
}
|
|
27375
|
-
async tail(workerName) {
|
|
27376
|
-
return this.runWrangler(["tail", workerName]);
|
|
27377
|
-
}
|
|
27378
|
-
async d1List() {
|
|
27379
|
-
return this.runWrangler(["d1", "list", "--json"]);
|
|
27380
|
-
}
|
|
27381
|
-
async d1Create(name) {
|
|
27382
|
-
return this.runWrangler(["d1", "create", name]);
|
|
27383
|
-
}
|
|
27384
|
-
async d1Delete(name) {
|
|
27385
|
-
return this.runWrangler(["d1", "delete", name]);
|
|
27386
|
-
}
|
|
27387
|
-
async d1Execute(name, sql, remote = true) {
|
|
27388
|
-
const args = ["d1", "execute", name, "--command", sql];
|
|
27389
|
-
if (remote)
|
|
27390
|
-
args.push("--remote");
|
|
27391
|
-
const result = await this.runWrangler(args);
|
|
27392
|
-
if (!result.ok)
|
|
27393
|
-
return result;
|
|
27394
|
-
const extracted = extractJsonArray(result.value);
|
|
27395
|
-
if (extracted === null) {
|
|
27396
|
-
return {
|
|
27397
|
-
ok: false,
|
|
27398
|
-
error: `wrangler d1 execute returned non-JSON output: ${result.value.slice(0, 200)}`
|
|
27399
|
-
};
|
|
27400
|
-
}
|
|
27401
|
-
return { ok: true, value: extracted };
|
|
27402
|
-
}
|
|
27403
|
-
async kvList() {
|
|
27404
|
-
return this.runWrangler(["kv", "namespace", "list"]);
|
|
27405
|
-
}
|
|
27406
|
-
async kvCreate(name) {
|
|
27407
|
-
return this.runWrangler(["kv", "namespace", "create", name]);
|
|
27408
|
-
}
|
|
27409
|
-
async kvDelete(id) {
|
|
27410
|
-
return this.runWrangler([
|
|
27411
|
-
"kv",
|
|
27412
|
-
"namespace",
|
|
27413
|
-
"delete",
|
|
27414
|
-
"--namespace-id",
|
|
27415
|
-
id
|
|
27416
|
-
]);
|
|
27417
|
-
}
|
|
27418
|
-
async r2List() {
|
|
27419
|
-
return this.runWrangler(["r2", "bucket", "list"]);
|
|
27420
|
-
}
|
|
27421
|
-
async r2Create(name) {
|
|
27422
|
-
return this.runWrangler(["r2", "bucket", "create", name]);
|
|
27423
|
-
}
|
|
27424
|
-
async r2Delete(name) {
|
|
27425
|
-
return this.runWrangler(["r2", "bucket", "delete", name]);
|
|
27426
|
-
}
|
|
27427
|
-
async queueList() {
|
|
27428
|
-
return this.runWrangler(["queues", "list"]);
|
|
27374
|
+
if (["warn", "warning", "degraded", "partial", "pending"].includes(lower)) {
|
|
27375
|
+
return `${theme.warning(icons.warning)} ${theme.text(v)}`;
|
|
27429
27376
|
}
|
|
27430
|
-
|
|
27431
|
-
|
|
27377
|
+
if ([
|
|
27378
|
+
"err",
|
|
27379
|
+
"error",
|
|
27380
|
+
"fail",
|
|
27381
|
+
"failed",
|
|
27382
|
+
"down",
|
|
27383
|
+
"unreachable",
|
|
27384
|
+
"disabled"
|
|
27385
|
+
].includes(lower)) {
|
|
27386
|
+
return `${theme.error(icons.error)} ${theme.text(v)}`;
|
|
27432
27387
|
}
|
|
27433
|
-
|
|
27434
|
-
|
|
27388
|
+
return value;
|
|
27389
|
+
}
|
|
27390
|
+
function formatJson(data, opts) {
|
|
27391
|
+
const json2 = opts?.quiet ? JSON.stringify(data) : JSON.stringify(data, null, 2);
|
|
27392
|
+
process.stdout.write(`${json2}
|
|
27393
|
+
`);
|
|
27394
|
+
}
|
|
27395
|
+
function formatKeyValue(pairs, opts = {}) {
|
|
27396
|
+
if (opts.quiet)
|
|
27397
|
+
return;
|
|
27398
|
+
if (opts.json) {
|
|
27399
|
+
process.stdout.write(JSON.stringify(pairs, null, 2) + `
|
|
27400
|
+
`);
|
|
27401
|
+
return;
|
|
27435
27402
|
}
|
|
27436
|
-
|
|
27437
|
-
|
|
27403
|
+
const maxKeyLen = Math.max(...Object.keys(pairs).map((k) => stripAnsi(k).length), 0);
|
|
27404
|
+
for (const [key, value] of Object.entries(pairs)) {
|
|
27405
|
+
const paddedKey = key.padEnd(maxKeyLen);
|
|
27406
|
+
process.stdout.write(` ${theme.key(paddedKey)} ${theme.textMuted(":")} ${value}
|
|
27407
|
+
`);
|
|
27438
27408
|
}
|
|
27439
|
-
|
|
27440
|
-
|
|
27441
|
-
|
|
27442
|
-
|
|
27443
|
-
|
|
27444
|
-
|
|
27445
|
-
|
|
27446
|
-
|
|
27447
|
-
|
|
27448
|
-
|
|
27409
|
+
}
|
|
27410
|
+
function getFormatOptions(cmd) {
|
|
27411
|
+
const opts = cmd.optsWithGlobals();
|
|
27412
|
+
return {
|
|
27413
|
+
json: Boolean(opts.json),
|
|
27414
|
+
quiet: Boolean(opts.quiet),
|
|
27415
|
+
noColor: Boolean(opts.color === false)
|
|
27416
|
+
};
|
|
27417
|
+
}
|
|
27418
|
+
function formatCompletion(message, opts = {}) {
|
|
27419
|
+
if (opts.json || opts.quiet)
|
|
27420
|
+
return;
|
|
27421
|
+
if (process.exitCode && process.exitCode !== 0)
|
|
27422
|
+
return;
|
|
27423
|
+
if (!isRichMode(opts))
|
|
27424
|
+
return;
|
|
27425
|
+
const parts = [theme.success(icons.success), theme.text(message)];
|
|
27426
|
+
if (opts.durationMs !== undefined) {
|
|
27427
|
+
parts.push(theme.textMuted(formatDuration3(opts.durationMs)));
|
|
27449
27428
|
}
|
|
27450
|
-
|
|
27451
|
-
|
|
27429
|
+
process.stdout.write(`${parts.join(" ")}
|
|
27430
|
+
`);
|
|
27431
|
+
if (opts.suggestion) {
|
|
27432
|
+
const reason = opts.suggestion.reason ? ` ${theme.textMuted(`(${opts.suggestion.reason})`)}` : "";
|
|
27433
|
+
process.stdout.write(` ${theme.textMuted("\u2192")} ${theme.textMuted("next:")} ${theme.accent(opts.suggestion.command)}${reason}
|
|
27434
|
+
`);
|
|
27452
27435
|
}
|
|
27453
|
-
|
|
27454
|
-
|
|
27436
|
+
}
|
|
27437
|
+
|
|
27438
|
+
// src/utils/error-handler.ts
|
|
27439
|
+
init_errors4();
|
|
27440
|
+
|
|
27441
|
+
// src/utils/string.ts
|
|
27442
|
+
function levenshtein(a2, b) {
|
|
27443
|
+
if (a2 === b)
|
|
27444
|
+
return 0;
|
|
27445
|
+
if (a2.length === 0)
|
|
27446
|
+
return b.length;
|
|
27447
|
+
if (b.length === 0)
|
|
27448
|
+
return a2.length;
|
|
27449
|
+
const [s, t] = a2.length <= b.length ? [a2, b] : [b, a2];
|
|
27450
|
+
const m = s.length;
|
|
27451
|
+
const n = t.length;
|
|
27452
|
+
let prev = new Array(m + 1);
|
|
27453
|
+
for (let i = 0;i <= m; i++)
|
|
27454
|
+
prev[i] = i;
|
|
27455
|
+
let curr = new Array(m + 1);
|
|
27456
|
+
for (let j = 1;j <= n; j++) {
|
|
27457
|
+
curr[0] = j;
|
|
27458
|
+
for (let i = 1;i <= m; i++) {
|
|
27459
|
+
const cost = s.charCodeAt(i - 1) === t.charCodeAt(j - 1) ? 0 : 1;
|
|
27460
|
+
curr[i] = Math.min(curr[i - 1] + 1, prev[i] + 1, prev[i - 1] + cost);
|
|
27461
|
+
}
|
|
27462
|
+
[prev, curr] = [curr, prev];
|
|
27455
27463
|
}
|
|
27456
|
-
|
|
27457
|
-
|
|
27458
|
-
|
|
27459
|
-
|
|
27460
|
-
|
|
27464
|
+
return prev[m];
|
|
27465
|
+
}
|
|
27466
|
+
|
|
27467
|
+
// src/utils/error-handler.ts
|
|
27468
|
+
var SUGGESTION_THRESHOLD = 2;
|
|
27469
|
+
function collectCommandNames(cmd, acc = new Set) {
|
|
27470
|
+
for (const sub of cmd.commands) {
|
|
27471
|
+
if (sub.name() && !sub.hidden) {
|
|
27472
|
+
acc.add(sub.name());
|
|
27473
|
+
collectCommandNames(sub, acc);
|
|
27474
|
+
}
|
|
27461
27475
|
}
|
|
27462
|
-
|
|
27463
|
-
|
|
27464
|
-
|
|
27465
|
-
|
|
27466
|
-
|
|
27467
|
-
|
|
27468
|
-
|
|
27469
|
-
|
|
27470
|
-
|
|
27471
|
-
const
|
|
27472
|
-
if (
|
|
27473
|
-
|
|
27474
|
-
|
|
27475
|
-
|
|
27476
|
-
};
|
|
27476
|
+
return acc;
|
|
27477
|
+
}
|
|
27478
|
+
function suggestForCommand(program2, unknown2) {
|
|
27479
|
+
if (unknown2.length < 2)
|
|
27480
|
+
return;
|
|
27481
|
+
const normalized = unknown2.replace(/s$/, "");
|
|
27482
|
+
const candidates = collectCommandNames(program2);
|
|
27483
|
+
let best;
|
|
27484
|
+
for (const candidate of candidates) {
|
|
27485
|
+
const d = Math.min(levenshtein(unknown2, candidate), levenshtein(normalized, candidate));
|
|
27486
|
+
if (d > SUGGESTION_THRESHOLD)
|
|
27487
|
+
continue;
|
|
27488
|
+
if (!best || d < best.dist) {
|
|
27489
|
+
best = { name: candidate, dist: d };
|
|
27477
27490
|
}
|
|
27478
|
-
return { ok: true, value: extracted };
|
|
27479
27491
|
}
|
|
27480
|
-
|
|
27492
|
+
return best?.name;
|
|
27493
|
+
}
|
|
27494
|
+
function withErrorHandling(handler, options) {
|
|
27495
|
+
return async (...args) => {
|
|
27481
27496
|
try {
|
|
27482
|
-
|
|
27483
|
-
|
|
27484
|
-
|
|
27485
|
-
|
|
27486
|
-
|
|
27487
|
-
|
|
27488
|
-
|
|
27489
|
-
|
|
27490
|
-
|
|
27491
|
-
|
|
27492
|
-
|
|
27493
|
-
|
|
27494
|
-
|
|
27495
|
-
|
|
27497
|
+
await handler(...args);
|
|
27498
|
+
} catch (error51) {
|
|
27499
|
+
const service = options?.service ?? "cli";
|
|
27500
|
+
if (error51 instanceof CLIError) {
|
|
27501
|
+
formatError2(error51, options?.opts);
|
|
27502
|
+
process.exitCode = error51.code;
|
|
27503
|
+
return;
|
|
27504
|
+
} else if (error51 instanceof Error) {
|
|
27505
|
+
formatError2(`[${service}] ${error51.message}`, options?.opts);
|
|
27506
|
+
process.exitCode = 1 /* ERROR */;
|
|
27507
|
+
return;
|
|
27508
|
+
} else {
|
|
27509
|
+
formatError2(`[${service}] Unknown error: ${String(error51)}`, options?.opts);
|
|
27510
|
+
process.exitCode = 4 /* CommandFailed */;
|
|
27511
|
+
return;
|
|
27496
27512
|
}
|
|
27497
|
-
return {
|
|
27498
|
-
ok: false,
|
|
27499
|
-
error: stderr.trim() || `wrangler exited with code ${exitCode}`
|
|
27500
|
-
};
|
|
27501
|
-
} catch (err) {
|
|
27502
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
27503
|
-
return { ok: false, error: `Failed to set secret: ${message}` };
|
|
27504
27513
|
}
|
|
27514
|
+
};
|
|
27515
|
+
}
|
|
27516
|
+
|
|
27517
|
+
// src/utils/help-formatter.ts
|
|
27518
|
+
function renderHelp(cmd, helper) {
|
|
27519
|
+
const subcommands = cmd.commands.filter((c) => !c._hidden).map((c) => ({ name: c.name(), desc: c.description() ?? "" }));
|
|
27520
|
+
const blocks = [];
|
|
27521
|
+
const argNames = cmd.registeredArguments.map((a2) => a2.name()).join(" ");
|
|
27522
|
+
const titleName = argNames ? `${cmd.name()} ${argNames}` : cmd.name();
|
|
27523
|
+
blocks.push(theme.heading(` ${titleName}`));
|
|
27524
|
+
if (cmd.description()) {
|
|
27525
|
+
blocks.push(` ${theme.textMuted(cmd.description())}`);
|
|
27505
27526
|
}
|
|
27506
|
-
|
|
27507
|
-
|
|
27508
|
-
|
|
27509
|
-
|
|
27510
|
-
|
|
27511
|
-
|
|
27512
|
-
|
|
27513
|
-
|
|
27514
|
-
|
|
27515
|
-
|
|
27516
|
-
|
|
27517
|
-
|
|
27518
|
-
|
|
27519
|
-
ok: false,
|
|
27520
|
-
error: "CLOUDFLARE_API_TOKEN environment variable is not set. Set it or run `wrangler login`."
|
|
27521
|
-
};
|
|
27527
|
+
blocks.push(theme.textFaint("\u2500".repeat(60)));
|
|
27528
|
+
const usageLine = buildUsage(cmd);
|
|
27529
|
+
blocks.push(headerLine("Usage"));
|
|
27530
|
+
blocks.push(` ${theme.accent(usageLine)}`);
|
|
27531
|
+
const options = cmd.options.filter((o) => !o.hidden);
|
|
27532
|
+
if (options.length > 0) {
|
|
27533
|
+
blocks.push("");
|
|
27534
|
+
blocks.push(headerLine("Options"));
|
|
27535
|
+
const flagWidth = Math.max(...options.map((o) => o.flags.length));
|
|
27536
|
+
for (const o of options) {
|
|
27537
|
+
const padded = o.flags.padEnd(flagWidth);
|
|
27538
|
+
const desc = o.description ? theme.textMuted(o.description) : "";
|
|
27539
|
+
blocks.push(` ${theme.text(padded)} ${desc}`);
|
|
27522
27540
|
}
|
|
27523
|
-
|
|
27524
|
-
|
|
27525
|
-
|
|
27526
|
-
|
|
27527
|
-
|
|
27528
|
-
|
|
27529
|
-
|
|
27530
|
-
|
|
27531
|
-
if (!response.ok || !json2.success) {
|
|
27532
|
-
const errorMsg = json2.errors?.map((e) => e.message).join("; ") || `HTTP ${response.status}`;
|
|
27533
|
-
return { ok: false, error: `Failed to list zones: ${errorMsg}` };
|
|
27534
|
-
}
|
|
27535
|
-
const lines = json2.result.map((z2) => `${z2.name} (${z2.id})`);
|
|
27536
|
-
return { ok: true, value: lines.join(`
|
|
27537
|
-
`) };
|
|
27538
|
-
} catch (err) {
|
|
27539
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
27540
|
-
return { ok: false, error: `Cloudflare API request failed: ${message}` };
|
|
27541
|
+
}
|
|
27542
|
+
if (subcommands.length > 0) {
|
|
27543
|
+
blocks.push("");
|
|
27544
|
+
blocks.push(headerLine("Commands"));
|
|
27545
|
+
const nameWidth = Math.max(...subcommands.map((s) => s.name.length));
|
|
27546
|
+
for (const s of subcommands) {
|
|
27547
|
+
const padded = s.name.padEnd(nameWidth);
|
|
27548
|
+
blocks.push(` ${theme.text(padded)} ${theme.textMuted(s.desc)}`);
|
|
27541
27549
|
}
|
|
27542
27550
|
}
|
|
27543
|
-
|
|
27544
|
-
|
|
27545
|
-
|
|
27546
|
-
|
|
27547
|
-
|
|
27548
|
-
if (match)
|
|
27549
|
-
return match[1];
|
|
27550
|
-
}
|
|
27551
|
-
return;
|
|
27551
|
+
const afterText = captureHelpEvent(cmd, "afterHelp");
|
|
27552
|
+
if (afterText.trim()) {
|
|
27553
|
+
blocks.push("");
|
|
27554
|
+
blocks.push(headerLine("Examples"));
|
|
27555
|
+
blocks.push(` ${theme.textMuted(afterText.trim())}`);
|
|
27552
27556
|
}
|
|
27557
|
+
const out = blocks.join(`
|
|
27558
|
+
`) + `
|
|
27559
|
+
`;
|
|
27560
|
+
return isRichMode() ? out : stripAnsi(out);
|
|
27553
27561
|
}
|
|
27554
|
-
function
|
|
27555
|
-
|
|
27556
|
-
|
|
27557
|
-
|
|
27558
|
-
|
|
27559
|
-
let
|
|
27560
|
-
|
|
27561
|
-
|
|
27562
|
-
|
|
27563
|
-
|
|
27564
|
-
|
|
27565
|
-
|
|
27566
|
-
|
|
27567
|
-
|
|
27568
|
-
|
|
27569
|
-
|
|
27570
|
-
|
|
27571
|
-
|
|
27572
|
-
|
|
27573
|
-
|
|
27574
|
-
|
|
27575
|
-
|
|
27576
|
-
continue;
|
|
27577
|
-
}
|
|
27578
|
-
if (ch === "[")
|
|
27579
|
-
depth++;
|
|
27580
|
-
else if (ch === "]") {
|
|
27581
|
-
depth--;
|
|
27582
|
-
if (depth === 0)
|
|
27583
|
-
return raw.slice(first, i2 + 1);
|
|
27562
|
+
function headerLine(text) {
|
|
27563
|
+
return ` ${theme.textSubtle(text)}`;
|
|
27564
|
+
}
|
|
27565
|
+
function buildUsage(cmd) {
|
|
27566
|
+
const parts = [];
|
|
27567
|
+
let c = cmd;
|
|
27568
|
+
while (c && c.name()) {
|
|
27569
|
+
parts.unshift(c.name());
|
|
27570
|
+
c = c.parent;
|
|
27571
|
+
}
|
|
27572
|
+
for (const arg of cmd.registeredArguments) {
|
|
27573
|
+
parts.push(arg.name());
|
|
27574
|
+
}
|
|
27575
|
+
return `${parts.join(" ")} [options]`;
|
|
27576
|
+
}
|
|
27577
|
+
function captureHelpEvent(cmd, eventName) {
|
|
27578
|
+
const parts = [];
|
|
27579
|
+
const context = {
|
|
27580
|
+
error: false,
|
|
27581
|
+
command: cmd,
|
|
27582
|
+
write: (str) => {
|
|
27583
|
+
parts.push(str);
|
|
27584
27584
|
}
|
|
27585
|
+
};
|
|
27586
|
+
const emitter = cmd;
|
|
27587
|
+
emitter.emit(eventName, context);
|
|
27588
|
+
return parts.join("");
|
|
27589
|
+
}
|
|
27590
|
+
|
|
27591
|
+
// src/utils/completion.ts
|
|
27592
|
+
var SUGGEST_NEXT = {
|
|
27593
|
+
init: { command: "hoox setup", reason: "provision infrastructure" },
|
|
27594
|
+
setup: { command: "hoox deploy all", reason: "ship to Cloudflare" },
|
|
27595
|
+
"deploy all": { command: "hoox check health", reason: "verify the deploy" },
|
|
27596
|
+
"check health": { command: "hoox monitor status", reason: "keep watching" },
|
|
27597
|
+
"monitor kill-switch off": {
|
|
27598
|
+
command: "hoox check health",
|
|
27599
|
+
reason: "re-enable trading"
|
|
27585
27600
|
}
|
|
27586
|
-
|
|
27601
|
+
};
|
|
27602
|
+
function suggestNextCommand(commandPath) {
|
|
27603
|
+
return SUGGEST_NEXT[commandPath];
|
|
27604
|
+
}
|
|
27605
|
+
function getCmdPath(cmd) {
|
|
27606
|
+
const parts = [];
|
|
27607
|
+
let current2 = cmd;
|
|
27608
|
+
while (current2 && current2.name() && current2.parent) {
|
|
27609
|
+
parts.unshift(current2.name());
|
|
27610
|
+
current2 = current2.parent;
|
|
27611
|
+
}
|
|
27612
|
+
return parts.join(" ");
|
|
27587
27613
|
}
|
|
27614
|
+
|
|
27615
|
+
// src/commands/init/init-command.ts
|
|
27616
|
+
init_dist4();
|
|
27617
|
+
init_src();
|
|
27618
|
+
|
|
27619
|
+
// src/services/cloudflare/index.ts
|
|
27620
|
+
init_cloudflare_service();
|
|
27621
|
+
|
|
27588
27622
|
// src/commands/init/init-command.ts
|
|
27589
27623
|
init_errors4();
|
|
27590
27624
|
|
|
@@ -30832,7 +30866,7 @@ async function doUpdateInternalUrls(fmt) {
|
|
|
30832
30866
|
}
|
|
30833
30867
|
async function doKvConfig(fmt) {
|
|
30834
30868
|
try {
|
|
30835
|
-
const { KvSyncService: KvSyncService2 } = await Promise.resolve().then(() => exports_kv_sync_service);
|
|
30869
|
+
const { KvSyncService: KvSyncService2 } = await Promise.resolve().then(() => (init_kv_sync_service(), exports_kv_sync_service));
|
|
30836
30870
|
const kvSync = new KvSyncService2;
|
|
30837
30871
|
process.stdout.write(`${theme.info("Resolving CONFIG_KV namespace...")}
|
|
30838
30872
|
`);
|
|
@@ -32054,6 +32088,10 @@ EXAMPLES:
|
|
|
32054
32088
|
await handleGenerateDevVars(opts);
|
|
32055
32089
|
}, { service: "env" }));
|
|
32056
32090
|
}
|
|
32091
|
+
|
|
32092
|
+
// src/services/kv/index.ts
|
|
32093
|
+
init_kv_sync_service();
|
|
32094
|
+
|
|
32057
32095
|
// src/commands/config/kv-command.ts
|
|
32058
32096
|
init_errors4();
|
|
32059
32097
|
async function resolveNs(cmd) {
|
|
@@ -33419,12 +33457,75 @@ async function handleSetup(opts) {
|
|
|
33419
33457
|
process.exitCode = 1 /* ERROR */;
|
|
33420
33458
|
}
|
|
33421
33459
|
}
|
|
33460
|
+
var HEALTH_PROBE_TIMEOUT_MS = 8000;
|
|
33461
|
+
function resolveWorkerBaseUrl(workerName, global) {
|
|
33462
|
+
if (workerName === "hoox") {
|
|
33463
|
+
const envUrl = process.env.HOOX_GATEWAY_URL;
|
|
33464
|
+
if (envUrl && envUrl.length > 0) {
|
|
33465
|
+
return envUrl.replace(/\/+$/, "");
|
|
33466
|
+
}
|
|
33467
|
+
}
|
|
33468
|
+
const prefix = global.subdomain_prefix;
|
|
33469
|
+
if (prefix && prefix.length > 0) {
|
|
33470
|
+
return `https://${workerName}.${prefix}.workers.dev`;
|
|
33471
|
+
}
|
|
33472
|
+
const accountId = global.cloudflare_account_id || process.env.CLOUDFLARE_ACCOUNT_ID;
|
|
33473
|
+
if (accountId && accountId.length > 0) {
|
|
33474
|
+
return `https://${workerName}.${accountId}.workers.dev`;
|
|
33475
|
+
}
|
|
33476
|
+
throw new Error(`Cannot resolve URL for worker "${workerName}". Set global.subdomain_prefix or cloudflare_account_id in wrangler.jsonc (or HOOX_GATEWAY_URL for the gateway).`);
|
|
33477
|
+
}
|
|
33478
|
+
async function probeWorkerHealth(workerName, baseUrl, timeoutMs = HEALTH_PROBE_TIMEOUT_MS) {
|
|
33479
|
+
const url2 = `${baseUrl.replace(/\/+$/, "")}/health`;
|
|
33480
|
+
const started = Date.now();
|
|
33481
|
+
const controller = new AbortController;
|
|
33482
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
33483
|
+
try {
|
|
33484
|
+
const res = await fetch(url2, {
|
|
33485
|
+
method: "GET",
|
|
33486
|
+
signal: controller.signal,
|
|
33487
|
+
headers: { Accept: "application/json" }
|
|
33488
|
+
});
|
|
33489
|
+
const responseTime = Date.now() - started;
|
|
33490
|
+
if (res.ok) {
|
|
33491
|
+
return {
|
|
33492
|
+
worker: workerName,
|
|
33493
|
+
status: "healthy",
|
|
33494
|
+
connectivity: true,
|
|
33495
|
+
responseTime,
|
|
33496
|
+
url: url2
|
|
33497
|
+
};
|
|
33498
|
+
}
|
|
33499
|
+
return {
|
|
33500
|
+
worker: workerName,
|
|
33501
|
+
status: res.status >= 500 ? "down" : "degraded",
|
|
33502
|
+
connectivity: true,
|
|
33503
|
+
responseTime,
|
|
33504
|
+
url: url2,
|
|
33505
|
+
error: `HTTP ${res.status}`
|
|
33506
|
+
};
|
|
33507
|
+
} catch (err) {
|
|
33508
|
+
const responseTime = Date.now() - started;
|
|
33509
|
+
const aborted2 = err instanceof Error && err.name === "AbortError" || typeof err === "object" && err !== null && "name" in err && err.name === "AbortError";
|
|
33510
|
+
const message = aborted2 ? `Timeout after ${timeoutMs}ms` : err instanceof Error ? err.message : String(err);
|
|
33511
|
+
return {
|
|
33512
|
+
worker: workerName,
|
|
33513
|
+
status: "down",
|
|
33514
|
+
connectivity: false,
|
|
33515
|
+
responseTime,
|
|
33516
|
+
url: url2,
|
|
33517
|
+
error: message
|
|
33518
|
+
};
|
|
33519
|
+
} finally {
|
|
33520
|
+
clearTimeout(timer);
|
|
33521
|
+
}
|
|
33522
|
+
}
|
|
33422
33523
|
async function handleHealth(opts, autoFix) {
|
|
33423
33524
|
const results = [];
|
|
33424
33525
|
try {
|
|
33425
33526
|
const configService = new ConfigService;
|
|
33426
33527
|
await configService.load();
|
|
33427
|
-
const
|
|
33528
|
+
const global = configService.getGlobal();
|
|
33428
33529
|
const enabledWorkers = configService.listEnabledWorkers();
|
|
33429
33530
|
if (enabledWorkers.length === 0) {
|
|
33430
33531
|
formatSuccess("No enabled workers to check", opts);
|
|
@@ -33434,14 +33535,8 @@ async function handleHealth(opts, autoFix) {
|
|
|
33434
33535
|
title: `Probe ${workerName}`,
|
|
33435
33536
|
run: async () => {
|
|
33436
33537
|
try {
|
|
33437
|
-
const
|
|
33438
|
-
|
|
33439
|
-
return {
|
|
33440
|
-
worker: workerName,
|
|
33441
|
-
status: healthy ? "healthy" : "degraded",
|
|
33442
|
-
connectivity: healthy,
|
|
33443
|
-
error: tailResult.ok ? undefined : tailResult.error ?? "Unknown error"
|
|
33444
|
-
};
|
|
33538
|
+
const baseUrl = resolveWorkerBaseUrl(workerName, global);
|
|
33539
|
+
return await probeWorkerHealth(workerName, baseUrl);
|
|
33445
33540
|
} catch (err) {
|
|
33446
33541
|
const message = err instanceof Error ? err.message : String(err);
|
|
33447
33542
|
return {
|
|
@@ -33468,6 +33563,7 @@ async function handleHealth(opts, autoFix) {
|
|
|
33468
33563
|
const rows = results.map((r2) => ({
|
|
33469
33564
|
Worker: r2.worker,
|
|
33470
33565
|
Status: r2.status,
|
|
33566
|
+
Latency: r2.responseTime != null ? `${r2.responseTime}ms` : "-",
|
|
33471
33567
|
Connectivity: r2.connectivity ? "connected" : "failed",
|
|
33472
33568
|
Error: r2.error ?? "-"
|
|
33473
33569
|
}));
|
|
@@ -33796,10 +33892,11 @@ EXAMPLES:
|
|
|
33796
33892
|
}, { service: "check" }));
|
|
33797
33893
|
checkCmd.command("health").summary("Check worker connectivity and responsiveness").description(`Run health checks on all enabled workers to verify they are running and responsive.
|
|
33798
33894
|
|
|
33799
|
-
Each worker is probed to
|
|
33800
|
-
- Worker
|
|
33801
|
-
-
|
|
33802
|
-
-
|
|
33895
|
+
Each worker is probed with a short HTTP GET to /health (default timeout 8s):
|
|
33896
|
+
- Worker URL from global.subdomain_prefix (or account id)
|
|
33897
|
+
- healthy \u2192 HTTP 2xx from /health
|
|
33898
|
+
- degraded \u2192 reachable but non-2xx (e.g. 4xx)
|
|
33899
|
+
- down \u2192 timeout, DNS, or network error
|
|
33803
33900
|
|
|
33804
33901
|
OPTIONS:
|
|
33805
33902
|
--fix Attempt automatic repair for detected issues (informational)
|
|
@@ -34285,6 +34382,7 @@ function registerTestCommand(program2) {
|
|
|
34285
34382
|
}, { service: "test" }));
|
|
34286
34383
|
}
|
|
34287
34384
|
// src/commands/waf/waf-command.ts
|
|
34385
|
+
init_cloudflare_service();
|
|
34288
34386
|
init_errors4();
|
|
34289
34387
|
var CF_API_BASE = "https://api.cloudflare.com/client/v4";
|
|
34290
34388
|
function getCredentials() {
|
|
@@ -34818,14 +34916,22 @@ init_dist4();
|
|
|
34818
34916
|
|
|
34819
34917
|
// src/services/db/db-service.ts
|
|
34820
34918
|
init_config2();
|
|
34919
|
+
init_cloudflare_service();
|
|
34920
|
+
import { existsSync as existsSync6 } from "fs";
|
|
34821
34921
|
import { join as join7 } from "path";
|
|
34922
|
+
var D1_WRANGLER_CONFIG_CANDIDATES = [
|
|
34923
|
+
"workers/d1-worker/wrangler.jsonc",
|
|
34924
|
+
"workers/trade-worker/wrangler.jsonc"
|
|
34925
|
+
];
|
|
34822
34926
|
|
|
34823
34927
|
class DbService {
|
|
34824
34928
|
configService;
|
|
34825
34929
|
homeDir;
|
|
34826
|
-
|
|
34930
|
+
wranglerConfigPath;
|
|
34931
|
+
constructor(configService, homeDir, wranglerConfigPath) {
|
|
34827
34932
|
this.configService = configService ?? new ConfigService;
|
|
34828
34933
|
this.homeDir = homeDir;
|
|
34934
|
+
this.wranglerConfigPath = wranglerConfigPath ?? process.env.HOOX_WRANGLER_CONFIG;
|
|
34829
34935
|
}
|
|
34830
34936
|
resolveDefaultSchemaPath() {
|
|
34831
34937
|
if (this.homeDir) {
|
|
@@ -34897,7 +35003,8 @@ class DbService {
|
|
|
34897
35003
|
}
|
|
34898
35004
|
static parseTableNames(output) {
|
|
34899
35005
|
try {
|
|
34900
|
-
const
|
|
35006
|
+
const jsonText = extractJsonArray(output) ?? output;
|
|
35007
|
+
const parsed = JSON.parse(jsonText);
|
|
34901
35008
|
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
34902
35009
|
const first = parsed[0];
|
|
34903
35010
|
if (first.results && Array.isArray(first.results)) {
|
|
@@ -34908,8 +35015,19 @@ class DbService {
|
|
|
34908
35015
|
return output.split(`
|
|
34909
35016
|
`).map((l2) => l2.trim()).filter(Boolean);
|
|
34910
35017
|
}
|
|
35018
|
+
resolveWranglerConfigPath() {
|
|
35019
|
+
if (this.wranglerConfigPath)
|
|
35020
|
+
return this.wranglerConfigPath;
|
|
35021
|
+
for (const candidate of D1_WRANGLER_CONFIG_CANDIDATES) {
|
|
35022
|
+
if (existsSync6(candidate))
|
|
35023
|
+
return candidate;
|
|
35024
|
+
}
|
|
35025
|
+
return;
|
|
35026
|
+
}
|
|
34911
35027
|
async runWrangler(args) {
|
|
34912
|
-
const
|
|
35028
|
+
const configPath = this.resolveWranglerConfigPath();
|
|
35029
|
+
const fullArgs = configPath && !args.includes("-c") && !args.includes("--config") ? [...args, "-c", configPath] : args;
|
|
35030
|
+
const proc = Bun.spawn(["wrangler", ...fullArgs], {
|
|
34913
35031
|
stdout: "pipe",
|
|
34914
35032
|
stderr: "pipe"
|
|
34915
35033
|
});
|
|
@@ -34917,7 +35035,8 @@ class DbService {
|
|
|
34917
35035
|
const stderr = await new Response(proc.stderr).text();
|
|
34918
35036
|
const exitCode = await proc.exited;
|
|
34919
35037
|
if (exitCode !== 0) {
|
|
34920
|
-
|
|
35038
|
+
const detail = stderr.trim() || stdout2.trim() || `wrangler exited with code ${exitCode}`;
|
|
35039
|
+
throw new Error(detail);
|
|
34921
35040
|
}
|
|
34922
35041
|
return stdout2.trim();
|
|
34923
35042
|
}
|
|
@@ -35151,6 +35270,7 @@ EXAMPLES:
|
|
|
35151
35270
|
}, { service: "db" }));
|
|
35152
35271
|
}
|
|
35153
35272
|
// src/commands/monitor/monitor-command.ts
|
|
35273
|
+
init_kv_sync_service();
|
|
35154
35274
|
init_errors4();
|
|
35155
35275
|
function assertSafeInteger(value, name, max) {
|
|
35156
35276
|
if (!Number.isInteger(value) || value < 0 || value > max || !Number.isSafeInteger(value)) {
|
|
@@ -35219,7 +35339,11 @@ function parseWranglerQueuesJson(raw) {
|
|
|
35219
35339
|
const cleaned = raw.trim();
|
|
35220
35340
|
if (!cleaned)
|
|
35221
35341
|
return [];
|
|
35222
|
-
const
|
|
35342
|
+
const firstBracket = cleaned.indexOf("[");
|
|
35343
|
+
const firstBrace = cleaned.indexOf("{");
|
|
35344
|
+
const start = firstBracket === -1 ? firstBrace : firstBrace === -1 ? firstBracket : Math.min(firstBracket, firstBrace);
|
|
35345
|
+
const payload = start >= 0 ? cleaned.slice(start) : cleaned;
|
|
35346
|
+
const parsed = JSON.parse(payload);
|
|
35223
35347
|
if (Array.isArray(parsed)) {
|
|
35224
35348
|
return parsed;
|
|
35225
35349
|
}
|
|
@@ -35228,9 +35352,37 @@ function parseWranglerQueuesJson(raw) {
|
|
|
35228
35352
|
}
|
|
35229
35353
|
return [];
|
|
35230
35354
|
}
|
|
35355
|
+
function parseWranglerQueuesTable(raw) {
|
|
35356
|
+
const queues = [];
|
|
35357
|
+
for (const line of raw.split(`
|
|
35358
|
+
`)) {
|
|
35359
|
+
if (!line.includes("\u2502"))
|
|
35360
|
+
continue;
|
|
35361
|
+
if (/[\u250C\u2514\u251C\u2500\u252C\u2534\u253C]/.test(line))
|
|
35362
|
+
continue;
|
|
35363
|
+
const cells = line.split("\u2502").map((c3) => c3.trim()).filter((c3) => c3.length > 0);
|
|
35364
|
+
if (cells.length < 2)
|
|
35365
|
+
continue;
|
|
35366
|
+
if (cells[0] === "id" || cells[0] === "name")
|
|
35367
|
+
continue;
|
|
35368
|
+
if (!/^[0-9a-f-]{16,}$/i.test(cells[0]))
|
|
35369
|
+
continue;
|
|
35370
|
+
const producers = cells[4] !== undefined && cells[4] !== "" ? Number(cells[4]) : undefined;
|
|
35371
|
+
const consumers = cells[5] !== undefined && cells[5] !== "" ? Number(cells[5]) : undefined;
|
|
35372
|
+
queues.push({
|
|
35373
|
+
queue_id: cells[0],
|
|
35374
|
+
queue_name: cells[1],
|
|
35375
|
+
created_on: cells[2],
|
|
35376
|
+
modified_on: cells[3],
|
|
35377
|
+
producers_total_count: Number.isFinite(producers) ? producers : undefined,
|
|
35378
|
+
consumers_total_count: Number.isFinite(consumers) ? consumers : undefined
|
|
35379
|
+
});
|
|
35380
|
+
}
|
|
35381
|
+
return queues;
|
|
35382
|
+
}
|
|
35231
35383
|
async function doMonitorQueueDepth(fmt) {
|
|
35232
35384
|
try {
|
|
35233
|
-
const proc = Bun.spawn(["wrangler", "queues", "list"
|
|
35385
|
+
const proc = Bun.spawn(["wrangler", "queues", "list"], {
|
|
35234
35386
|
stdout: "pipe",
|
|
35235
35387
|
stderr: "pipe"
|
|
35236
35388
|
});
|
|
@@ -35241,22 +35393,20 @@ async function doMonitorQueueDepth(fmt) {
|
|
|
35241
35393
|
throw new Error(stderr.trim() || `wrangler exited with code ${exitCode}`);
|
|
35242
35394
|
}
|
|
35243
35395
|
if (fmt.json) {
|
|
35244
|
-
|
|
35396
|
+
let queues;
|
|
35397
|
+
try {
|
|
35398
|
+
queues = parseWranglerQueuesJson(stdout2);
|
|
35399
|
+
if (queues.length === 0) {
|
|
35400
|
+
queues = parseWranglerQueuesTable(stdout2);
|
|
35401
|
+
}
|
|
35402
|
+
} catch {
|
|
35403
|
+
queues = parseWranglerQueuesTable(stdout2);
|
|
35404
|
+
}
|
|
35245
35405
|
process.stdout.write(JSON.stringify({ queues }, null, 2) + `
|
|
35246
35406
|
`);
|
|
35247
35407
|
return;
|
|
35248
35408
|
}
|
|
35249
|
-
|
|
35250
|
-
stdout: "pipe",
|
|
35251
|
-
stderr: "pipe"
|
|
35252
|
-
});
|
|
35253
|
-
const stdoutHuman = await new Response(procHuman.stdout).text();
|
|
35254
|
-
const stderrHuman = await new Response(procHuman.stderr).text();
|
|
35255
|
-
const exitHuman = await procHuman.exited;
|
|
35256
|
-
if (exitHuman !== 0) {
|
|
35257
|
-
throw new Error(stderrHuman.trim() || `wrangler exited with code ${exitHuman}`);
|
|
35258
|
-
}
|
|
35259
|
-
process.stdout.write(stdoutHuman + `
|
|
35409
|
+
process.stdout.write(stdout2 + `
|
|
35260
35410
|
`);
|
|
35261
35411
|
} catch (err) {
|
|
35262
35412
|
formatError2(err instanceof Error ? err.message : String(err), fmt);
|
|
@@ -35640,7 +35790,9 @@ class RepairService {
|
|
|
35640
35790
|
}
|
|
35641
35791
|
}
|
|
35642
35792
|
}
|
|
35793
|
+
|
|
35643
35794
|
// src/commands/repair/repair-command.ts
|
|
35795
|
+
init_kv_sync_service();
|
|
35644
35796
|
init_errors4();
|
|
35645
35797
|
async function handleCheck(fmt, options = {}) {
|
|
35646
35798
|
try {
|
|
@@ -35649,10 +35801,23 @@ async function handleCheck(fmt, options = {}) {
|
|
|
35649
35801
|
installDeps: Boolean(options.installDeps),
|
|
35650
35802
|
typecheck: options.typecheck !== false
|
|
35651
35803
|
});
|
|
35652
|
-
if (
|
|
35653
|
-
|
|
35804
|
+
if (fmt.json) {
|
|
35805
|
+
process.stdout.write(JSON.stringify(result, null, 2) + `
|
|
35806
|
+
`);
|
|
35654
35807
|
} else {
|
|
35655
|
-
|
|
35808
|
+
const rows = result.steps.map((s) => ({
|
|
35809
|
+
Step: s.step,
|
|
35810
|
+
Status: s.success ? "ok" : "fail",
|
|
35811
|
+
Detail: s.message ?? s.error ?? "-"
|
|
35812
|
+
}));
|
|
35813
|
+
formatTable(rows, fmt);
|
|
35814
|
+
if (result.allPassed) {
|
|
35815
|
+
formatSuccess(`All ${result.passedCount} check(s) passed`, fmt);
|
|
35816
|
+
} else {
|
|
35817
|
+
formatError2(new CLIError(`${result.failedCount} of ${result.steps.length} check(s) failed`, 1 /* ERROR */), fmt);
|
|
35818
|
+
}
|
|
35819
|
+
}
|
|
35820
|
+
if (!result.allPassed) {
|
|
35656
35821
|
process.exitCode = 1 /* ERROR */;
|
|
35657
35822
|
}
|
|
35658
35823
|
} catch (err) {
|
|
@@ -35930,22 +36095,56 @@ function registerSchemaCommand(program2) {
|
|
|
35930
36095
|
}
|
|
35931
36096
|
// src/commands/tui/tui-command.ts
|
|
35932
36097
|
import { spawn } from "child_process";
|
|
35933
|
-
import {
|
|
36098
|
+
import { createRequire } from "module";
|
|
36099
|
+
import { resolve as resolve6, dirname as dirname2, join as join8 } from "path";
|
|
35934
36100
|
import { fileURLToPath } from "url";
|
|
35935
|
-
import { existsSync as
|
|
36101
|
+
import { existsSync as existsSync8 } from "fs";
|
|
35936
36102
|
init_errors4();
|
|
35937
36103
|
var __dirname2 = dirname2(fileURLToPath(import.meta.url));
|
|
35938
|
-
|
|
36104
|
+
var require2 = createRequire(import.meta.url);
|
|
36105
|
+
var TUI_PKG = "@jango-blockchained/hoox-tui";
|
|
36106
|
+
function collectTuiCandidates() {
|
|
35939
36107
|
const candidates = [
|
|
35940
36108
|
resolve6(__dirname2, "../../../../tui/src/main.tsx"),
|
|
36109
|
+
resolve6(__dirname2, "../../../../tui/dist/main.js"),
|
|
36110
|
+
resolve6(__dirname2, "../../../tui/src/main.tsx"),
|
|
36111
|
+
resolve6(__dirname2, "../../../tui/dist/main.js"),
|
|
35941
36112
|
resolve6(process.cwd(), "packages/tui/src/main.tsx"),
|
|
35942
|
-
resolve6(process.cwd(), "
|
|
36113
|
+
resolve6(process.cwd(), "packages/tui/dist/main.js"),
|
|
36114
|
+
resolve6(process.cwd(), "../tui/src/main.tsx"),
|
|
36115
|
+
resolve6(process.cwd(), "../tui/dist/main.js")
|
|
35943
36116
|
];
|
|
36117
|
+
pushPackageEntries(candidates, require2);
|
|
36118
|
+
try {
|
|
36119
|
+
const cwdRequire = createRequire(join8(process.cwd(), "package.json"));
|
|
36120
|
+
pushPackageEntries(candidates, cwdRequire);
|
|
36121
|
+
} catch {}
|
|
36122
|
+
return candidates;
|
|
36123
|
+
}
|
|
36124
|
+
function pushPackageEntries(candidates, req) {
|
|
36125
|
+
try {
|
|
36126
|
+
const pkgJsonPath = req.resolve(`${TUI_PKG}/package.json`);
|
|
36127
|
+
const root = dirname2(pkgJsonPath);
|
|
36128
|
+
candidates.push(join8(root, "src/main.tsx"), join8(root, "dist/main.js"), join8(root, "src/main.ts"));
|
|
36129
|
+
} catch {}
|
|
36130
|
+
}
|
|
36131
|
+
function resolveTUIEntry() {
|
|
36132
|
+
const candidates = collectTuiCandidates();
|
|
35944
36133
|
for (const path6 of candidates) {
|
|
35945
|
-
if (
|
|
36134
|
+
if (existsSync8(path6))
|
|
35946
36135
|
return path6;
|
|
35947
36136
|
}
|
|
35948
|
-
throw new CLIError(
|
|
36137
|
+
throw new CLIError([
|
|
36138
|
+
"Could not find the Hoox TUI entry point.",
|
|
36139
|
+
"",
|
|
36140
|
+
"Fix options:",
|
|
36141
|
+
" \u2022 From the monorepo: ensure packages/tui/src/main.tsx exists",
|
|
36142
|
+
` \u2022 Or install the package: bun add -g ${TUI_PKG}`,
|
|
36143
|
+
" \u2022 Or from a project: bun add -d " + TUI_PKG,
|
|
36144
|
+
"",
|
|
36145
|
+
"Then re-run: hoox tui"
|
|
36146
|
+
].join(`
|
|
36147
|
+
`), 1 /* ERROR */);
|
|
35949
36148
|
}
|
|
35950
36149
|
function registerTUICommand(program2) {
|
|
35951
36150
|
program2.command("tui").description("Launch the OpenTUI terminal operations center").option("--fps <number>", "Target frames per second", "30").option("--no-mouse", "Disable mouse support").action(withErrorHandling(async (options) => {
|
|
@@ -36812,7 +37011,20 @@ EXAMPLES:
|
|
|
36812
37011
|
to: options.to
|
|
36813
37012
|
}, fmt);
|
|
36814
37013
|
}, { service: "trace" }));
|
|
36815
|
-
const destinationsCmd = traceCmd.command("destinations").summary("Manage OTLP export destinations")
|
|
37014
|
+
const destinationsCmd = traceCmd.command("destinations").summary("Manage OTLP export destinations").description(`List and manage OTLP export destinations.
|
|
37015
|
+
|
|
37016
|
+
SUBCOMMANDS:
|
|
37017
|
+
list List destinations (default when no subcommand given)
|
|
37018
|
+
add <name> <url> Add a destination
|
|
37019
|
+
remove <slug> Remove a destination
|
|
37020
|
+
|
|
37021
|
+
EXAMPLES:
|
|
37022
|
+
hoox trace destinations List (default)
|
|
37023
|
+
hoox trace destinations list
|
|
37024
|
+
hoox trace destinations add honeycomb https://api.honeycomb.io/1/traces`).action(withErrorHandling(async (_options, cmd) => {
|
|
37025
|
+
const fmt = getFormatOptions(cmd);
|
|
37026
|
+
await handleDestinationsList(fmt);
|
|
37027
|
+
}, { service: "trace" }));
|
|
36816
37028
|
destinationsCmd.command("list").summary("List OTLP export destinations").description(`List all configured OTLP export destinations.
|
|
36817
37029
|
|
|
36818
37030
|
Destinations allow exporting traces (and logs) to third-party observability
|
|
@@ -37534,137 +37746,24 @@ function registerCompletionCommand(program2) {
|
|
|
37534
37746
|
}
|
|
37535
37747
|
}));
|
|
37536
37748
|
}
|
|
37537
|
-
// src/commands/pine/pine-command.ts
|
|
37538
|
-
import { resolve as resolve7 } from "path";
|
|
37539
|
-
var PINE_WORKER_DIR = resolve7(process.cwd(), "workers/pine-worker");
|
|
37540
|
-
async function spawnPineScript(script, args = []) {
|
|
37541
|
-
const proc = Bun.spawn(["bun", "run", script, ...args], {
|
|
37542
|
-
cwd: PINE_WORKER_DIR,
|
|
37543
|
-
stdio: ["inherit", "inherit", "inherit"]
|
|
37544
|
-
});
|
|
37545
|
-
return await proc.exited;
|
|
37546
|
-
}
|
|
37547
|
-
function registerPineCommand(program2) {
|
|
37548
|
-
const pineCmd = program2.command("pine").summary("Pine Script strategy tooling (backtest, data, export)").description(`Manage Pine Script strategies, data, and chart exports.
|
|
37549
|
-
|
|
37550
|
-
SUBCOMMANDS:
|
|
37551
|
-
download Download OHLCV historical data from Binance
|
|
37552
|
-
backtest <file> Run a Pine Script against local historical data
|
|
37553
|
-
export <file> Export per-bar chart data as CSV or JSON
|
|
37554
|
-
bundle Bundle built-in Pine libraries for deployment
|
|
37555
|
-
|
|
37556
|
-
Data is stored under workers/pine-worker/data/ and consumed by the
|
|
37557
|
-
pine-worker at runtime.
|
|
37558
|
-
|
|
37559
|
-
EXAMPLES:
|
|
37560
|
-
hoox pine download Default: BTCUSDT 1d 365d
|
|
37561
|
-
hoox pine download --all All default symbols
|
|
37562
|
-
hoox pine download -s ETHUSDT --tf 1h -d 30 Custom download
|
|
37563
|
-
hoox pine backtest ../grid.pine -s BTCUSDT Run a strategy
|
|
37564
|
-
hoox pine export ../grid.pine --csv Export chart data as CSV
|
|
37565
|
-
hoox pine bundle Bundle libraries for deploy`);
|
|
37566
|
-
pineCmd.command("download").summary("Download OHLCV historical data from Binance").description(`Fetch historical klines from Binance and store as compressed JSON Lines
|
|
37567
|
-
under workers/pine-worker/data/{SYMBOL}/{TIMEFRAME}/{YYYY}.jsonl.gz.
|
|
37568
|
-
|
|
37569
|
-
OPTIONS:
|
|
37570
|
-
-s, --symbol Symbol to download (default: BTCUSDT)
|
|
37571
|
-
--tf Timeframe: 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h,
|
|
37572
|
-
8h, 12h, 1d, 3d, 1w, 1M (default: 1d)
|
|
37573
|
-
-d, --days Days of history to fetch (default: 365)
|
|
37574
|
-
-a, --all Download all default symbols (BTC, ETH, SOL, BNB,
|
|
37575
|
-
XRP, ADA, DOGE, AVAX)
|
|
37576
|
-
|
|
37577
|
-
EXAMPLES:
|
|
37578
|
-
hoox pine download
|
|
37579
|
-
hoox pine download --all
|
|
37580
|
-
hoox pine download -s ETHUSDT --tf 1h -d 30`).option("-s, --symbol <symbol>", "Symbol to download", "BTCUSDT").option("--tf <timeframe>", "Timeframe interval", "1d").option("-d, --days <days>", "Days of history to fetch", "365").option("-a, --all", "Download all default symbols").action(withErrorHandling(async (opts) => {
|
|
37581
|
-
const args = [];
|
|
37582
|
-
if (opts.all) {
|
|
37583
|
-
args.push("--all");
|
|
37584
|
-
} else {
|
|
37585
|
-
args.push("--symbol", opts.symbol);
|
|
37586
|
-
args.push("--tf", opts.tf);
|
|
37587
|
-
if (opts.days !== "365")
|
|
37588
|
-
args.push("--days", opts.days);
|
|
37589
|
-
}
|
|
37590
|
-
process.exitCode = await spawnPineScript("scripts/download-data.ts", args);
|
|
37591
|
-
}, { service: "pine" }));
|
|
37592
|
-
pineCmd.command("backtest <script-path>").summary("Run a Pine Script against local historical data").description(`Execute a Pine Script strategy against historical OHLCV data and
|
|
37593
|
-
print trade events (entries, exits, orders) to stdout.
|
|
37594
|
-
|
|
37595
|
-
ARGUMENTS:
|
|
37596
|
-
script-path Path to the .pine script file
|
|
37597
|
-
|
|
37598
|
-
OPTIONS:
|
|
37599
|
-
-s, --symbol Trading symbol (default: BTCUSDT)
|
|
37600
|
-
--tf Timeframe (default: 5m)
|
|
37601
|
-
-b, --bars Number of bars to evaluate (default: 864)
|
|
37602
|
-
|
|
37603
|
-
EXAMPLES:
|
|
37604
|
-
hoox pine backtest ../grid.pine
|
|
37605
|
-
hoox pine backtest ../grid.pine -s ETHUSDT --tf 15m -b 500`).option("-s, --symbol <symbol>", "Trading symbol", "BTCUSDT").option("--tf <timeframe>", "Timeframe", "5m").option("-b, --bars <bars>", "Number of bars to evaluate", "864").action(withErrorHandling(async (scriptPath, opts) => {
|
|
37606
|
-
process.exitCode = await spawnPineScript("scripts/run-backtest.ts", [
|
|
37607
|
-
scriptPath,
|
|
37608
|
-
opts.symbol,
|
|
37609
|
-
opts.tf,
|
|
37610
|
-
opts.bars
|
|
37611
|
-
]);
|
|
37612
|
-
}, { service: "pine" }));
|
|
37613
|
-
pineCmd.command("export <script-path>").summary("Export per-bar chart data (TradingView-style)").description(`Run a Pine Script and export per-bar OHLCV + plot values as
|
|
37614
|
-
CSV or JSON \u2014 matching TradingView's "Export chart data" layout.
|
|
37615
|
-
|
|
37616
|
-
ARGUMENTS:
|
|
37617
|
-
script-path Path to the .pine script file
|
|
37618
|
-
|
|
37619
|
-
OPTIONS:
|
|
37620
|
-
-s, --symbol Trading symbol (default: BTCUSDT)
|
|
37621
|
-
--tf Timeframe (default: 1d)
|
|
37622
|
-
-b, --bars Number of bars to evaluate (default: 500)
|
|
37623
|
-
--csv Export as CSV (default: JSON)
|
|
37624
|
-
|
|
37625
|
-
Output files are written to the current directory:
|
|
37626
|
-
{SYMBOL}_{TIMEFRAME}_chart.csv or {SYMBOL}_{TIMEFRAME}_chart.json
|
|
37627
|
-
|
|
37628
|
-
EXAMPLES:
|
|
37629
|
-
hoox pine export ../grid.pine
|
|
37630
|
-
hoox pine export ../grid.pine -s ETHUSDT --csv
|
|
37631
|
-
hoox pine export ../grid.pine --tf 1h -b 200`).option("-s, --symbol <symbol>", "Trading symbol", "BTCUSDT").option("--tf <timeframe>", "Timeframe", "1d").option("-b, --bars <bars>", "Number of bars to evaluate", "500").option("--csv", "Export as CSV (default: JSON)").action(withErrorHandling(async (scriptPath, opts) => {
|
|
37632
|
-
const args = [scriptPath, opts.symbol, opts.tf, opts.bars];
|
|
37633
|
-
if (opts.csv)
|
|
37634
|
-
args.push("--csv");
|
|
37635
|
-
process.exitCode = await spawnPineScript("scripts/export-chart.ts", args);
|
|
37636
|
-
}, { service: "pine" }));
|
|
37637
|
-
pineCmd.command("bundle").summary("Bundle built-in Pine libraries for deployment").description(`Embed libraries/*.pine files into src/module/bundled-libraries.ts
|
|
37638
|
-
so library imports work in the Cloudflare Worker runtime.
|
|
37639
|
-
|
|
37640
|
-
This runs automatically as a prebuild step before deploy, but can
|
|
37641
|
-
also be run manually after updating library files.
|
|
37642
|
-
|
|
37643
|
-
EXAMPLES:
|
|
37644
|
-
hoox pine bundle`).action(withErrorHandling(async () => {
|
|
37645
|
-
process.exitCode = await spawnPineScript("scripts/bundle-libraries.ts");
|
|
37646
|
-
}, { service: "pine" }));
|
|
37647
|
-
pineCmd.action(() => {
|
|
37648
|
-
pineCmd.help();
|
|
37649
|
-
});
|
|
37650
|
-
}
|
|
37651
37749
|
// src/ui/banner.ts
|
|
37652
|
-
import { existsSync as
|
|
37750
|
+
import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
37653
37751
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
37654
|
-
import { dirname as dirname3, join as
|
|
37655
|
-
var TAGLINE = "Cloudflare Workers Platform";
|
|
37752
|
+
import { dirname as dirname3, join as join9 } from "path";
|
|
37656
37753
|
var ORANGE = ansis_default.hex("#ff7f2a");
|
|
37657
37754
|
var AMBER = ansis_default.hex("#ffb722");
|
|
37658
37755
|
var INDIGO = ansis_default.hex("#818cf8");
|
|
37659
37756
|
var INDIGO_SOFT = ansis_default.hex("#a5b4fc");
|
|
37660
37757
|
var ZINC = ansis_default.hex("#a1a1aa");
|
|
37661
37758
|
var ZINC_FAINT = ansis_default.hex("#52525b");
|
|
37759
|
+
var ZINC_SOFT = ansis_default.hex("#71717a");
|
|
37760
|
+
var TAGLINE = "Cloudflare Workers Platform";
|
|
37662
37761
|
function findCliVersion() {
|
|
37663
37762
|
const PKG_NAME = "@jango-blockchained/hoox-cli";
|
|
37664
37763
|
let dir = dirname3(fileURLToPath2(import.meta.url));
|
|
37665
37764
|
for (let i2 = 0;i2 < 5; i2++) {
|
|
37666
|
-
const pkgPath =
|
|
37667
|
-
if (
|
|
37765
|
+
const pkgPath = join9(dir, "package.json");
|
|
37766
|
+
if (existsSync9(pkgPath)) {
|
|
37668
37767
|
try {
|
|
37669
37768
|
const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
|
|
37670
37769
|
if (pkg.name === PKG_NAME)
|
|
@@ -37680,107 +37779,35 @@ function findCliVersion() {
|
|
|
37680
37779
|
}
|
|
37681
37780
|
var VERSION = findCliVersion();
|
|
37682
37781
|
var DISCLAIMER2 = "DISCLAIMER: Trading cryptocurrencies involves substantial risk of loss. Use at your own risk.";
|
|
37683
|
-
var LOGO_GRID = [
|
|
37684
|
-
" /\\ ",
|
|
37685
|
-
" /##\\ ",
|
|
37686
|
-
" /####\\ ",
|
|
37687
|
-
" // ## \\\\ ",
|
|
37688
|
-
" // #### \\\\ ",
|
|
37689
|
-
" // \\\\ ",
|
|
37690
|
-
" //- #### -\\\\ ",
|
|
37691
|
-
" \\\\- #### -// ",
|
|
37692
|
-
" \\\\ // ",
|
|
37693
|
-
" \\\\ #### // ",
|
|
37694
|
-
" \\\\ ## // ",
|
|
37695
|
-
" \\####/ ",
|
|
37696
|
-
" \\##/ ",
|
|
37697
|
-
" \\/ "
|
|
37698
|
-
];
|
|
37699
|
-
var LOGO_W = LOGO_GRID[0].length;
|
|
37700
|
-
function cellRole(ch) {
|
|
37701
|
-
if (ch === "#" || ch === "\u2588")
|
|
37702
|
-
return "solid";
|
|
37703
|
-
if (ch === " " || ch === "")
|
|
37704
|
-
return "empty";
|
|
37705
|
-
return "outline";
|
|
37706
|
-
}
|
|
37707
|
-
function displayChar(ch) {
|
|
37708
|
-
if (ch === "#")
|
|
37709
|
-
return "\u2588";
|
|
37710
|
-
if (ch === "/")
|
|
37711
|
-
return "\u2571";
|
|
37712
|
-
if (ch === "\\")
|
|
37713
|
-
return "\u2572";
|
|
37714
|
-
if (ch === "-" || ch === "_")
|
|
37715
|
-
return "\u2500";
|
|
37716
|
-
return ch;
|
|
37717
|
-
}
|
|
37718
|
-
function colorLogoLine(raw, row, phase, mode) {
|
|
37719
|
-
let out = "";
|
|
37720
|
-
for (let col = 0;col < raw.length; col++) {
|
|
37721
|
-
const enc = raw[col];
|
|
37722
|
-
const role = cellRole(enc);
|
|
37723
|
-
if (role === "empty") {
|
|
37724
|
-
out += " ";
|
|
37725
|
-
continue;
|
|
37726
|
-
}
|
|
37727
|
-
const ch = displayChar(enc);
|
|
37728
|
-
if (mode === "assemble") {
|
|
37729
|
-
const solidReady = phase >= 0.15;
|
|
37730
|
-
const outlineReady = phase >= 0.5;
|
|
37731
|
-
if (role === "solid" && !solidReady) {
|
|
37732
|
-
out += ZINC_FAINT("\xB7");
|
|
37733
|
-
continue;
|
|
37734
|
-
}
|
|
37735
|
-
if (role === "outline" && !outlineReady) {
|
|
37736
|
-
out += " ";
|
|
37737
|
-
continue;
|
|
37738
|
-
}
|
|
37739
|
-
if (role === "solid" && phase < 0.45) {
|
|
37740
|
-
out += ZINC(ch);
|
|
37741
|
-
continue;
|
|
37742
|
-
}
|
|
37743
|
-
if (role === "outline" && phase < 0.75) {
|
|
37744
|
-
out += ZINC_FAINT(ch);
|
|
37745
|
-
continue;
|
|
37746
|
-
}
|
|
37747
|
-
}
|
|
37748
|
-
if (mode === "shimmer") {
|
|
37749
|
-
const t2 = (phase * 1.5 + (col + row) * 0.07) % 1;
|
|
37750
|
-
if (t2 < 0.12) {
|
|
37751
|
-
out += (role === "solid" ? AMBER : INDIGO_SOFT)(ch);
|
|
37752
|
-
} else if (t2 < 0.3) {
|
|
37753
|
-
out += (role === "solid" ? ORANGE : INDIGO)(ch);
|
|
37754
|
-
} else {
|
|
37755
|
-
out += role === "solid" ? ansis_default.hex("#e4e4e7")(ch) : INDIGO.dim(ch);
|
|
37756
|
-
}
|
|
37757
|
-
continue;
|
|
37758
|
-
}
|
|
37759
|
-
out += role === "solid" ? ansis_default.hex("#fafafa")(ch) : ansis_default.hex("#a1a1aa")(ch);
|
|
37760
|
-
}
|
|
37761
|
-
return out;
|
|
37762
|
-
}
|
|
37763
|
-
function renderLogoBlock(phase, mode) {
|
|
37764
|
-
return LOGO_GRID.map((line, row) => colorLogoLine(line, row, phase, mode));
|
|
37765
|
-
}
|
|
37766
37782
|
var WORDMARK = [
|
|
37767
|
-
"
|
|
37768
|
-
"
|
|
37769
|
-
"
|
|
37770
|
-
"
|
|
37771
|
-
"\u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2554\u255D \u2588\u2588\u2557",
|
|
37772
|
-
"\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D"
|
|
37783
|
+
" _ _ ___ _____ _ ",
|
|
37784
|
+
"| | | |/ _ \\ / _ \\ \\/ / ",
|
|
37785
|
+
"| |_| | (_) | (_) > < ",
|
|
37786
|
+
" \\___/ \\___/ \\___/_/\\_\\ "
|
|
37773
37787
|
];
|
|
37788
|
+
var WORD_W = WORDMARK[0].length;
|
|
37774
37789
|
function colorWordmark(phase, mode) {
|
|
37775
37790
|
return WORDMARK.map((line, row) => {
|
|
37776
|
-
if (mode === "assemble"
|
|
37777
|
-
const
|
|
37778
|
-
|
|
37779
|
-
|
|
37780
|
-
|
|
37781
|
-
|
|
37782
|
-
|
|
37783
|
-
|
|
37791
|
+
if (mode === "assemble") {
|
|
37792
|
+
const local = Math.max(0, Math.min(1, phase));
|
|
37793
|
+
const cut = Math.floor(local * line.length);
|
|
37794
|
+
let out = "";
|
|
37795
|
+
for (let col = 0;col < line.length; col++) {
|
|
37796
|
+
const ch = line[col];
|
|
37797
|
+
if (ch === " ") {
|
|
37798
|
+
out += " ";
|
|
37799
|
+
continue;
|
|
37800
|
+
}
|
|
37801
|
+
if (col > cut)
|
|
37802
|
+
out += ZINC_FAINT("\xB7");
|
|
37803
|
+
else if (local < 0.85)
|
|
37804
|
+
out += ZINC(ch);
|
|
37805
|
+
else
|
|
37806
|
+
out += theme.heading(ch);
|
|
37807
|
+
}
|
|
37808
|
+
return out;
|
|
37809
|
+
}
|
|
37810
|
+
if (mode === "pulse") {
|
|
37784
37811
|
let out = "";
|
|
37785
37812
|
for (let col = 0;col < line.length; col++) {
|
|
37786
37813
|
const ch = line[col];
|
|
@@ -37788,36 +37815,32 @@ function colorWordmark(phase, mode) {
|
|
|
37788
37815
|
out += " ";
|
|
37789
37816
|
continue;
|
|
37790
37817
|
}
|
|
37791
|
-
const t2 = (phase * 1.
|
|
37792
|
-
|
|
37818
|
+
const t2 = (phase * 1.5 + col * 0.05 + row * 0.06) % 1;
|
|
37819
|
+
if (t2 < 0.12)
|
|
37820
|
+
out += AMBER(ch);
|
|
37821
|
+
else if (t2 < 0.25)
|
|
37822
|
+
out += ORANGE(ch);
|
|
37823
|
+
else if (t2 < 0.4)
|
|
37824
|
+
out += INDIGO_SOFT(ch);
|
|
37825
|
+
else
|
|
37826
|
+
out += INDIGO.bold(ch);
|
|
37793
37827
|
}
|
|
37794
37828
|
return out;
|
|
37795
37829
|
}
|
|
37796
37830
|
return theme.heading(line);
|
|
37797
37831
|
});
|
|
37798
37832
|
}
|
|
37799
|
-
var
|
|
37833
|
+
var PAD = " ";
|
|
37800
37834
|
function composeFrame(phase, mode) {
|
|
37801
|
-
const logo = renderLogoBlock(phase, mode);
|
|
37802
37835
|
const word = colorWordmark(phase, mode);
|
|
37803
|
-
const
|
|
37804
|
-
const
|
|
37805
|
-
const
|
|
37806
|
-
const
|
|
37807
|
-
const
|
|
37808
|
-
const
|
|
37809
|
-
|
|
37810
|
-
|
|
37811
|
-
const wi = i2 - topPad;
|
|
37812
|
-
const right = wi >= 0 && wi < wordH ? word[wi] : " ".repeat(WORDMARK[0].length);
|
|
37813
|
-
lines.push(BANNER_PAD + left + gap + right);
|
|
37814
|
-
}
|
|
37815
|
-
const rule = ZINC_FAINT("\u2500".repeat(contentW + 2));
|
|
37816
|
-
const meta3 = BANNER_PAD + ZINC(TAGLINE) + " " + ZINC_FAINT("\xB7") + " " + INDIGO_SOFT(`v${VERSION}`);
|
|
37817
|
-
const metaVis = stripAnsi(meta3).length;
|
|
37818
|
-
const metaPad = Math.max(0, Math.floor((contentW + 2 - metaVis) / 2));
|
|
37819
|
-
const metaLine = " ".repeat(metaPad) + meta3.trimStart();
|
|
37820
|
-
return [BANNER_PAD + rule, ...lines, BANNER_PAD + rule, metaLine].join(`
|
|
37836
|
+
const contentW = WORD_W;
|
|
37837
|
+
const body = word.map((line) => PAD + line);
|
|
37838
|
+
const rule = PAD + ZINC_FAINT("\u2500".repeat(contentW));
|
|
37839
|
+
const metaInner = ZINC_SOFT(TAGLINE) + " " + ZINC_FAINT("\xB7") + " " + INDIGO_SOFT(`v${VERSION}`);
|
|
37840
|
+
const metaVis = stripAnsi(metaInner).length;
|
|
37841
|
+
const metaPad = Math.max(0, Math.floor((contentW - metaVis) / 2));
|
|
37842
|
+
const meta3 = PAD + " ".repeat(metaPad) + metaInner;
|
|
37843
|
+
return [rule, ...body, rule, meta3].join(`
|
|
37821
37844
|
`);
|
|
37822
37845
|
}
|
|
37823
37846
|
function canAnimate() {
|
|
@@ -37844,12 +37867,12 @@ async function animateBanner(options) {
|
|
|
37844
37867
|
`);
|
|
37845
37868
|
return lineCount;
|
|
37846
37869
|
}
|
|
37847
|
-
const durationMs = options?.durationMs ??
|
|
37870
|
+
const durationMs = options?.durationMs ?? 800;
|
|
37848
37871
|
const assembleMs = Math.floor(durationMs * 0.55);
|
|
37849
|
-
const
|
|
37850
|
-
const fps =
|
|
37872
|
+
const pulseMs = durationMs - assembleMs;
|
|
37873
|
+
const fps = 28;
|
|
37851
37874
|
const assembleFrames = Math.max(6, Math.round(assembleMs / 1000 * fps));
|
|
37852
|
-
const
|
|
37875
|
+
const pulseFrames = Math.max(4, Math.round(pulseMs / 1000 * fps));
|
|
37853
37876
|
let wroteLines = 0;
|
|
37854
37877
|
const writeFrame = (frame) => {
|
|
37855
37878
|
const lines = frame.split(`
|
|
@@ -37873,14 +37896,14 @@ async function animateBanner(options) {
|
|
|
37873
37896
|
process.stdout.write("\x1B[?25l");
|
|
37874
37897
|
try {
|
|
37875
37898
|
for (let i2 = 0;i2 < assembleFrames; i2++) {
|
|
37876
|
-
const phase = i2 / (assembleFrames - 1);
|
|
37899
|
+
const phase = i2 / Math.max(1, assembleFrames - 1);
|
|
37877
37900
|
writeFrame(composeFrame(phase, "assemble"));
|
|
37878
37901
|
await sleep2(assembleMs / assembleFrames);
|
|
37879
37902
|
}
|
|
37880
|
-
for (let i2 = 0;i2 <
|
|
37881
|
-
const phase = i2 / Math.max(1,
|
|
37882
|
-
writeFrame(composeFrame(phase, "
|
|
37883
|
-
await sleep2(
|
|
37903
|
+
for (let i2 = 0;i2 < pulseFrames; i2++) {
|
|
37904
|
+
const phase = i2 / Math.max(1, pulseFrames - 1);
|
|
37905
|
+
writeFrame(composeFrame(phase, "pulse"));
|
|
37906
|
+
await sleep2(pulseMs / pulseFrames);
|
|
37884
37907
|
}
|
|
37885
37908
|
writeFrame(finalFrame);
|
|
37886
37909
|
} finally {
|
|
@@ -38358,7 +38381,6 @@ registerSetupCommand(program2);
|
|
|
38358
38381
|
registerTraceCommand(program2);
|
|
38359
38382
|
registerPerfCommand(program2);
|
|
38360
38383
|
registerCompletionCommand(program2);
|
|
38361
|
-
registerPineCommand(program2);
|
|
38362
38384
|
async function main() {
|
|
38363
38385
|
try {
|
|
38364
38386
|
const hasArgs = process.argv.slice(2).length > 0;
|