@hoox-sh/hoox-cli 0.11.8 → 0.12.0
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 +2 -2
- package/dist/index.js +487 -148
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -201,10 +201,10 @@ Validates bun ≥1.2, git ≥2.40, wrangler, Docker, Cloudflare auth, and reposi
|
|
|
201
201
|
hoox secrets list trade-worker
|
|
202
202
|
|
|
203
203
|
# Set a secret
|
|
204
|
-
hoox secrets set trade-worker
|
|
204
|
+
hoox secrets set trade-worker EXCHANGE_KEY_BINDING
|
|
205
205
|
|
|
206
206
|
# Delete a secret
|
|
207
|
-
hoox secrets delete trade-worker
|
|
207
|
+
hoox secrets delete trade-worker EXCHANGE_KEY_BINDING
|
|
208
208
|
|
|
209
209
|
# Sync system/mesh secrets only (recommended after key rotation)
|
|
210
210
|
hoox secrets sync --system
|
package/dist/index.js
CHANGED
|
@@ -14843,8 +14843,10 @@ function toError(err, fallback = "Unknown error") {
|
|
|
14843
14843
|
return err.message;
|
|
14844
14844
|
if (typeof err === "string")
|
|
14845
14845
|
return err;
|
|
14846
|
-
if (err && typeof err === "object" && "message" in err
|
|
14847
|
-
|
|
14846
|
+
if (err && typeof err === "object" && "message" in err) {
|
|
14847
|
+
const message = err.message;
|
|
14848
|
+
if (typeof message === "string")
|
|
14849
|
+
return message;
|
|
14848
14850
|
}
|
|
14849
14851
|
if (err === null || err === undefined)
|
|
14850
14852
|
return fallback;
|
|
@@ -15105,6 +15107,24 @@ async function logKvTimestamp(env, prefix = "timestamp") {
|
|
|
15105
15107
|
console.error(`Failed to log timestamp to KV: ${toError(error51, "Unknown error")}`);
|
|
15106
15108
|
}
|
|
15107
15109
|
}
|
|
15110
|
+
async function kvGetMany(kv, keys) {
|
|
15111
|
+
if (keys.length === 0)
|
|
15112
|
+
return [];
|
|
15113
|
+
return Promise.all(keys.map((key) => kv.get(key)));
|
|
15114
|
+
}
|
|
15115
|
+
async function kvGetManyAsRecord(kv, keys) {
|
|
15116
|
+
const values = await kvGetMany(kv, keys);
|
|
15117
|
+
const out = {};
|
|
15118
|
+
for (let i = 0;i < keys.length; i++) {
|
|
15119
|
+
out[keys[i]] = values[i] ?? null;
|
|
15120
|
+
}
|
|
15121
|
+
return out;
|
|
15122
|
+
}
|
|
15123
|
+
async function kvPutMany(kv, entries) {
|
|
15124
|
+
if (entries.length === 0)
|
|
15125
|
+
return;
|
|
15126
|
+
await Promise.all(entries.map((entry) => kv.put(entry.key, entry.value, entry.options)));
|
|
15127
|
+
}
|
|
15108
15128
|
function headersToObject(headers) {
|
|
15109
15129
|
const result = {};
|
|
15110
15130
|
if (!headers)
|
|
@@ -15180,7 +15200,7 @@ function createQueueHandler(options) {
|
|
|
15180
15200
|
} catch (error51) {
|
|
15181
15201
|
const errorMsg = error51 instanceof Error ? error51.message : String(error51);
|
|
15182
15202
|
if (attemptNumber < maxRetries) {
|
|
15183
|
-
const delaySeconds = backoffDelays[attemptNumber] ?? backoffDelays[backoffDelays.length - 1];
|
|
15203
|
+
const delaySeconds = backoffDelays[attemptNumber] ?? backoffDelays[backoffDelays.length - 1] ?? 0;
|
|
15184
15204
|
logger?.info(`${logId} Retrying in ${delaySeconds}s (attempt ${attemptNumber + 2}/${maxRetries + 1})`);
|
|
15185
15205
|
await onRetry?.(msg.body, attemptNumber, errorMsg, delaySeconds);
|
|
15186
15206
|
msg.retry({ delaySeconds });
|
|
@@ -17078,7 +17098,7 @@ var init_presets = __esm(() => {
|
|
|
17078
17098
|
"analytics-worker",
|
|
17079
17099
|
"telegram-worker"
|
|
17080
17100
|
],
|
|
17081
|
-
integrations: ["
|
|
17101
|
+
integrations: ["exchange", "telegram"]
|
|
17082
17102
|
},
|
|
17083
17103
|
{
|
|
17084
17104
|
name: "full",
|
|
@@ -17095,15 +17115,7 @@ var init_presets = __esm(() => {
|
|
|
17095
17115
|
"web3-wallet-worker",
|
|
17096
17116
|
"pyne-worker"
|
|
17097
17117
|
],
|
|
17098
|
-
integrations: [
|
|
17099
|
-
"binance",
|
|
17100
|
-
"bybit",
|
|
17101
|
-
"mexc",
|
|
17102
|
-
"telegram",
|
|
17103
|
-
"openai",
|
|
17104
|
-
"wallet",
|
|
17105
|
-
"pyne"
|
|
17106
|
-
]
|
|
17118
|
+
integrations: ["exchange", "telegram", "openai", "wallet", "pyne"]
|
|
17107
17119
|
}
|
|
17108
17120
|
];
|
|
17109
17121
|
WORKER_DEPENDENCIES = {
|
|
@@ -17116,30 +17128,12 @@ var init_presets = __esm(() => {
|
|
|
17116
17128
|
};
|
|
17117
17129
|
INTEGRATIONS = [
|
|
17118
17130
|
{
|
|
17119
|
-
key: "
|
|
17120
|
-
label: "Binance
|
|
17131
|
+
key: "exchange",
|
|
17132
|
+
label: "Exchange API (Binance / Bybit / MEXC)",
|
|
17121
17133
|
workerName: "trade-worker",
|
|
17122
17134
|
secrets: {
|
|
17123
|
-
|
|
17124
|
-
|
|
17125
|
-
}
|
|
17126
|
-
},
|
|
17127
|
-
{
|
|
17128
|
-
key: "mexc",
|
|
17129
|
-
label: "MEXC Exchange",
|
|
17130
|
-
workerName: "trade-worker",
|
|
17131
|
-
secrets: {
|
|
17132
|
-
MEXC_KEY_BINDING: "MEXC API Key",
|
|
17133
|
-
MEXC_SECRET_BINDING: "MEXC API Secret"
|
|
17134
|
-
}
|
|
17135
|
-
},
|
|
17136
|
-
{
|
|
17137
|
-
key: "bybit",
|
|
17138
|
-
label: "Bybit Exchange",
|
|
17139
|
-
workerName: "trade-worker",
|
|
17140
|
-
secrets: {
|
|
17141
|
-
BYBIT_KEY_BINDING: "Bybit API Key",
|
|
17142
|
-
BYBIT_SECRET_BINDING: "Bybit API Secret"
|
|
17135
|
+
EXCHANGE_KEY_BINDING: "Exchange API Key",
|
|
17136
|
+
EXCHANGE_SECRET_BINDING: "Exchange API Secret"
|
|
17143
17137
|
}
|
|
17144
17138
|
},
|
|
17145
17139
|
{
|
|
@@ -17311,7 +17305,11 @@ class WizardEngine {
|
|
|
17311
17305
|
return { ...this.state };
|
|
17312
17306
|
}
|
|
17313
17307
|
getCurrentStep() {
|
|
17314
|
-
|
|
17308
|
+
const step = STEPS.find((s) => s.id === this.state.step) ?? STEPS[0];
|
|
17309
|
+
if (!step) {
|
|
17310
|
+
throw new Error("Wizard has no steps defined");
|
|
17311
|
+
}
|
|
17312
|
+
return step;
|
|
17315
17313
|
}
|
|
17316
17314
|
getCompletedSteps() {
|
|
17317
17315
|
return [...this.state.completedSteps];
|
|
@@ -17334,8 +17332,11 @@ class WizardEngine {
|
|
|
17334
17332
|
this.state.completedSteps.push(this.state.step);
|
|
17335
17333
|
}
|
|
17336
17334
|
const currentIdx = STEP_ORDER.indexOf(this.state.step);
|
|
17337
|
-
if (currentIdx < STEP_ORDER.length - 1) {
|
|
17338
|
-
|
|
17335
|
+
if (currentIdx >= 0 && currentIdx < STEP_ORDER.length - 1) {
|
|
17336
|
+
const nextStep = STEP_ORDER[currentIdx + 1];
|
|
17337
|
+
if (nextStep !== undefined) {
|
|
17338
|
+
this.state.step = nextStep;
|
|
17339
|
+
}
|
|
17339
17340
|
}
|
|
17340
17341
|
this.state.updatedAt = Date.now();
|
|
17341
17342
|
return [];
|
|
@@ -17346,6 +17347,8 @@ class WizardEngine {
|
|
|
17346
17347
|
const currentIdx = STEP_ORDER.indexOf(this.state.step);
|
|
17347
17348
|
if (currentIdx > 0) {
|
|
17348
17349
|
const previousStep = STEP_ORDER[currentIdx - 1];
|
|
17350
|
+
if (previousStep === undefined)
|
|
17351
|
+
return;
|
|
17349
17352
|
this.state.step = previousStep;
|
|
17350
17353
|
this.state.completedSteps = this.state.completedSteps.filter((s) => s !== this.state.step || STEP_ORDER.indexOf(s) <= STEP_ORDER.indexOf(previousStep));
|
|
17351
17354
|
}
|
|
@@ -17573,9 +17576,12 @@ function deriveCalledBy(manifests) {
|
|
|
17573
17576
|
if (!calledBy[workerName])
|
|
17574
17577
|
calledBy[workerName] = new Set;
|
|
17575
17578
|
for (const svc of manifest.services) {
|
|
17576
|
-
|
|
17577
|
-
|
|
17578
|
-
|
|
17579
|
+
let callers = calledBy[svc.service];
|
|
17580
|
+
if (!callers) {
|
|
17581
|
+
callers = new Set;
|
|
17582
|
+
calledBy[svc.service] = callers;
|
|
17583
|
+
}
|
|
17584
|
+
callers.add(workerName);
|
|
17579
17585
|
}
|
|
17580
17586
|
}
|
|
17581
17587
|
const result = {};
|
|
@@ -17584,12 +17590,16 @@ function deriveCalledBy(manifests) {
|
|
|
17584
17590
|
}
|
|
17585
17591
|
return result;
|
|
17586
17592
|
}
|
|
17587
|
-
|
|
17593
|
+
function getWorkerDefaultEnabled(name) {
|
|
17594
|
+
return manifests[name]?.defaultEnabled;
|
|
17595
|
+
}
|
|
17596
|
+
var manifests, CALLED_BY, WORKER_MANIFESTS, WORKER_NAMES, WORKER_CATALOG;
|
|
17588
17597
|
var init_registry = __esm(() => {
|
|
17589
17598
|
manifests = {
|
|
17590
17599
|
hoox: {
|
|
17591
17600
|
name: "hoox",
|
|
17592
17601
|
path: "workers/hoox-worker",
|
|
17602
|
+
defaultEnabled: true,
|
|
17593
17603
|
vars: {
|
|
17594
17604
|
WEBHOOK_API_KEY_BINDING: {
|
|
17595
17605
|
type: "secret",
|
|
@@ -17640,6 +17650,7 @@ var init_registry = __esm(() => {
|
|
|
17640
17650
|
"trade-worker": {
|
|
17641
17651
|
name: "trade-worker",
|
|
17642
17652
|
path: "workers/trade-worker",
|
|
17653
|
+
defaultEnabled: true,
|
|
17643
17654
|
vars: {
|
|
17644
17655
|
INTERNAL_KEY_BINDING: {
|
|
17645
17656
|
type: "secret",
|
|
@@ -17649,15 +17660,22 @@ var init_registry = __esm(() => {
|
|
|
17649
17660
|
type: "secret",
|
|
17650
17661
|
description: "Telegram outbound auth"
|
|
17651
17662
|
},
|
|
17652
|
-
|
|
17653
|
-
|
|
17663
|
+
EXCHANGE_KEY_BINDING: {
|
|
17664
|
+
type: "secret",
|
|
17665
|
+
description: "Unified exchange API key (Binance / Bybit / MEXC)"
|
|
17666
|
+
},
|
|
17667
|
+
EXCHANGE_SECRET_BINDING: {
|
|
17654
17668
|
type: "secret",
|
|
17655
|
-
description: "
|
|
17669
|
+
description: "Unified exchange API secret"
|
|
17656
17670
|
},
|
|
17657
|
-
|
|
17658
|
-
|
|
17659
|
-
|
|
17660
|
-
|
|
17671
|
+
EXCHANGE_TESTNET_KEY_BINDING: {
|
|
17672
|
+
type: "secret",
|
|
17673
|
+
description: "Optional unified testnet API key"
|
|
17674
|
+
},
|
|
17675
|
+
EXCHANGE_TESTNET_SECRET_BINDING: {
|
|
17676
|
+
type: "secret",
|
|
17677
|
+
description: "Optional unified testnet API secret"
|
|
17678
|
+
}
|
|
17661
17679
|
},
|
|
17662
17680
|
services: [
|
|
17663
17681
|
{
|
|
@@ -17699,6 +17717,7 @@ var init_registry = __esm(() => {
|
|
|
17699
17717
|
"telegram-worker": {
|
|
17700
17718
|
name: "telegram-worker",
|
|
17701
17719
|
path: "workers/telegram-worker",
|
|
17720
|
+
defaultEnabled: true,
|
|
17702
17721
|
vars: {
|
|
17703
17722
|
INTERNAL_KEY_BINDING: {
|
|
17704
17723
|
type: "secret",
|
|
@@ -17732,6 +17751,7 @@ var init_registry = __esm(() => {
|
|
|
17732
17751
|
"d1-worker": {
|
|
17733
17752
|
name: "d1-worker",
|
|
17734
17753
|
path: "workers/d1-worker",
|
|
17754
|
+
defaultEnabled: true,
|
|
17735
17755
|
vars: {
|
|
17736
17756
|
INTERNAL_KEY_BINDING: {
|
|
17737
17757
|
type: "secret",
|
|
@@ -17754,6 +17774,7 @@ var init_registry = __esm(() => {
|
|
|
17754
17774
|
"web3-wallet-worker": {
|
|
17755
17775
|
name: "web3-wallet-worker",
|
|
17756
17776
|
path: "workers/web3-wallet-worker",
|
|
17777
|
+
defaultEnabled: false,
|
|
17757
17778
|
vars: {
|
|
17758
17779
|
WALLET_PK_SECRET: { type: "secret", description: "Wallet private key" },
|
|
17759
17780
|
WALLET_MNEMONIC_SECRET: {
|
|
@@ -17774,6 +17795,7 @@ var init_registry = __esm(() => {
|
|
|
17774
17795
|
"agent-worker": {
|
|
17775
17796
|
name: "agent-worker",
|
|
17776
17797
|
path: "workers/agent-worker",
|
|
17798
|
+
defaultEnabled: true,
|
|
17777
17799
|
vars: {
|
|
17778
17800
|
AGENT_INTERNAL_KEY: { type: "secret", description: "Agent worker auth" },
|
|
17779
17801
|
INTERNAL_KEY_BINDING: {
|
|
@@ -17810,6 +17832,7 @@ var init_registry = __esm(() => {
|
|
|
17810
17832
|
"email-worker": {
|
|
17811
17833
|
name: "email-worker",
|
|
17812
17834
|
path: "workers/email-worker",
|
|
17835
|
+
defaultEnabled: false,
|
|
17813
17836
|
vars: {
|
|
17814
17837
|
INTERNAL_KEY_BINDING: {
|
|
17815
17838
|
type: "secret",
|
|
@@ -17847,6 +17870,7 @@ var init_registry = __esm(() => {
|
|
|
17847
17870
|
"analytics-worker": {
|
|
17848
17871
|
name: "analytics-worker",
|
|
17849
17872
|
path: "workers/analytics-worker",
|
|
17873
|
+
defaultEnabled: true,
|
|
17850
17874
|
vars: {
|
|
17851
17875
|
CLOUDFLARE_API_TOKEN: {
|
|
17852
17876
|
type: "secret",
|
|
@@ -17866,6 +17890,7 @@ var init_registry = __esm(() => {
|
|
|
17866
17890
|
"report-worker": {
|
|
17867
17891
|
name: "report-worker",
|
|
17868
17892
|
path: "workers/report-worker",
|
|
17893
|
+
defaultEnabled: false,
|
|
17869
17894
|
vars: {
|
|
17870
17895
|
CF_API_TOKEN_BINDING: {
|
|
17871
17896
|
type: "secret",
|
|
@@ -17900,6 +17925,7 @@ var init_registry = __esm(() => {
|
|
|
17900
17925
|
"pyne-worker": {
|
|
17901
17926
|
name: "pyne-worker",
|
|
17902
17927
|
path: "workers/pyne-worker",
|
|
17928
|
+
defaultEnabled: true,
|
|
17903
17929
|
vars: {
|
|
17904
17930
|
API_KEY: {
|
|
17905
17931
|
type: "secret",
|
|
@@ -17937,6 +17963,7 @@ var init_registry = __esm(() => {
|
|
|
17937
17963
|
dashboard: {
|
|
17938
17964
|
name: "dashboard",
|
|
17939
17965
|
path: "workers/dashboard",
|
|
17966
|
+
defaultEnabled: true,
|
|
17940
17967
|
vars: {
|
|
17941
17968
|
DASHBOARD_USER: {
|
|
17942
17969
|
type: "secret",
|
|
@@ -17979,6 +18006,14 @@ var init_registry = __esm(() => {
|
|
|
17979
18006
|
CALLED_BY = deriveCalledBy(manifests);
|
|
17980
18007
|
WORKER_MANIFESTS = manifests;
|
|
17981
18008
|
WORKER_NAMES = Object.keys(manifests).sort();
|
|
18009
|
+
WORKER_CATALOG = WORKER_NAMES.map((name) => {
|
|
18010
|
+
const m = manifests[name];
|
|
18011
|
+
return {
|
|
18012
|
+
name: m.name,
|
|
18013
|
+
path: m.path,
|
|
18014
|
+
defaultEnabled: m.defaultEnabled
|
|
18015
|
+
};
|
|
18016
|
+
});
|
|
17982
18017
|
});
|
|
17983
18018
|
|
|
17984
18019
|
// ../../node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
|
|
@@ -19735,6 +19770,8 @@ function generateWranglerJsonc(manifest) {
|
|
|
19735
19770
|
parts.push(` "vars": {`);
|
|
19736
19771
|
for (const [i, name] of varKeys.entries()) {
|
|
19737
19772
|
const def = manifest.vars[name];
|
|
19773
|
+
if (!def)
|
|
19774
|
+
continue;
|
|
19738
19775
|
const comma = i < varKeys.length - 1 ? "," : "";
|
|
19739
19776
|
const val = def.type === "secret" ? "__SECRET__" : JSON.stringify(def.default ?? "");
|
|
19740
19777
|
parts.push(` "${name}": ${val}${comma}`);
|
|
@@ -21561,7 +21598,7 @@ function getBackoffDelay(retryCount) {
|
|
|
21561
21598
|
if (retryCount <= 0)
|
|
21562
21599
|
return 0;
|
|
21563
21600
|
const index = Math.min(retryCount - 1, BACKOFF_SEQUENCE.length - 1);
|
|
21564
|
-
return BACKOFF_SEQUENCE[index];
|
|
21601
|
+
return BACKOFF_SEQUENCE[index] ?? 0;
|
|
21565
21602
|
}
|
|
21566
21603
|
var BACKOFF_SEQUENCE, MAX_RETRIES2 = 5, tradeStreamAbort = null, logStreamAbort = null, fetchWorkersGeneration = 0, reconnectTimer = null, scheduledReconnectTick = async () => {}, MAX_TRADES = 500, MAX_ALERTS = 100, MAX_LOGS = 1000, initialState2, useServiceStore;
|
|
21567
21604
|
var init_service_store = __esm(() => {
|
|
@@ -22218,7 +22255,10 @@ __export(exports_src, {
|
|
|
22218
22255
|
logKvTimestamp: () => logKvTimestamp,
|
|
22219
22256
|
loadDashboardManifestsFromRoot: () => loadDashboardManifestsFromRoot,
|
|
22220
22257
|
loadDashboardKvManifestFromRoot: () => loadDashboardKvManifestFromRoot,
|
|
22258
|
+
kvPutMany: () => kvPutMany,
|
|
22221
22259
|
kvManifestFromDashboardManifests: () => kvManifestFromDashboardManifests,
|
|
22260
|
+
kvGetManyAsRecord: () => kvGetManyAsRecord,
|
|
22261
|
+
kvGetMany: () => kvGetMany,
|
|
22222
22262
|
isWithinHooxHome: () => isWithinHooxHome,
|
|
22223
22263
|
isUnixModeGroupOrWorldAccessible: () => isUnixModeGroupOrWorldAccessible,
|
|
22224
22264
|
isTruthyKillSwitchFlag: () => isTruthyKillSwitchFlag,
|
|
@@ -22233,6 +22273,7 @@ __export(exports_src, {
|
|
|
22233
22273
|
healthCheck: () => healthCheck,
|
|
22234
22274
|
headersToObject: () => headersToObject,
|
|
22235
22275
|
hasOperatorClientCredentials: () => hasOperatorClientCredentials,
|
|
22276
|
+
getWorkerDefaultEnabled: () => getWorkerDefaultEnabled,
|
|
22236
22277
|
getTuiEntryCandidates: () => getTuiEntryCandidates,
|
|
22237
22278
|
getRememberedMonorepoRoot: () => getRememberedMonorepoRoot,
|
|
22238
22279
|
getRememberedMonorepoPath: () => getRememberedMonorepoPath,
|
|
@@ -22295,6 +22336,7 @@ __export(exports_src, {
|
|
|
22295
22336
|
WORKER_NAMES: () => WORKER_NAMES,
|
|
22296
22337
|
WORKER_MANIFESTS: () => WORKER_MANIFESTS,
|
|
22297
22338
|
WORKER_DEPENDENCIES: () => WORKER_DEPENDENCIES,
|
|
22339
|
+
WORKER_CATALOG: () => WORKER_CATALOG,
|
|
22298
22340
|
WIZARD_STATE_PATH: () => WIZARD_STATE_PATH,
|
|
22299
22341
|
WALLET_EXECUTE_AUTH_KEY_FIELDS: () => WALLET_EXECUTE_AUTH_KEY_FIELDS,
|
|
22300
22342
|
TradeSignalSchema: () => TradeSignalSchema,
|
|
@@ -25257,6 +25299,76 @@ ${e.errors.map((m3) => ` - ${m3}`).join(`
|
|
|
25257
25299
|
const config2 = this.ensureLoaded();
|
|
25258
25300
|
return Object.entries(config2.workers).filter(([, w]) => w.enabled).map(([name]) => name);
|
|
25259
25301
|
}
|
|
25302
|
+
listWorkerStatuses() {
|
|
25303
|
+
const config2 = this.ensureLoaded();
|
|
25304
|
+
const names = new Set([
|
|
25305
|
+
...WORKER_CATALOG.map((w) => w.name),
|
|
25306
|
+
...Object.keys(config2.workers ?? {})
|
|
25307
|
+
]);
|
|
25308
|
+
return [...names].sort().map((name) => {
|
|
25309
|
+
const catalog = WORKER_MANIFESTS[name];
|
|
25310
|
+
const cfg = config2.workers?.[name];
|
|
25311
|
+
return {
|
|
25312
|
+
name,
|
|
25313
|
+
path: cfg?.path ?? catalog?.path ?? `workers/${name}`,
|
|
25314
|
+
enabled: cfg?.enabled ?? catalog?.defaultEnabled ?? false,
|
|
25315
|
+
defaultEnabled: catalog?.defaultEnabled,
|
|
25316
|
+
inConfig: Boolean(cfg),
|
|
25317
|
+
inCatalog: Boolean(catalog)
|
|
25318
|
+
};
|
|
25319
|
+
});
|
|
25320
|
+
}
|
|
25321
|
+
async setWorkersEnabled(names, enabled) {
|
|
25322
|
+
this.ensureLoaded();
|
|
25323
|
+
const filePath = this.configPath;
|
|
25324
|
+
const file2 = Bun.file(filePath);
|
|
25325
|
+
if (!await file2.exists()) {
|
|
25326
|
+
throw new Error(`Config file not found: ${filePath}`);
|
|
25327
|
+
}
|
|
25328
|
+
let raw = await file2.text();
|
|
25329
|
+
const results = [];
|
|
25330
|
+
const unique = [...new Set(names.map((n3) => n3.trim()).filter(Boolean))];
|
|
25331
|
+
for (const name of unique) {
|
|
25332
|
+
const existing = this.config.workers?.[name];
|
|
25333
|
+
const catalog = WORKER_MANIFESTS[name];
|
|
25334
|
+
if (!existing && !catalog) {
|
|
25335
|
+
throw new Error(`Unknown worker "${name}". Known workers: ${WORKER_CATALOG.map((w) => w.name).join(", ")}`);
|
|
25336
|
+
}
|
|
25337
|
+
let seeded = false;
|
|
25338
|
+
if (!existing) {
|
|
25339
|
+
const entry = {
|
|
25340
|
+
enabled,
|
|
25341
|
+
path: catalog.path,
|
|
25342
|
+
vars: {},
|
|
25343
|
+
secrets: []
|
|
25344
|
+
};
|
|
25345
|
+
const seedEdits = modify(raw, ["workers", name], entry, {
|
|
25346
|
+
formattingOptions: JSONC_FORMAT,
|
|
25347
|
+
isArrayInsertion: false
|
|
25348
|
+
});
|
|
25349
|
+
raw = applyEdits(raw, seedEdits);
|
|
25350
|
+
seeded = true;
|
|
25351
|
+
} else {
|
|
25352
|
+
const edits = modify(raw, ["workers", name, "enabled"], enabled, {
|
|
25353
|
+
formattingOptions: JSONC_FORMAT
|
|
25354
|
+
});
|
|
25355
|
+
raw = applyEdits(raw, edits);
|
|
25356
|
+
}
|
|
25357
|
+
results.push({ name, enabled, seeded });
|
|
25358
|
+
}
|
|
25359
|
+
await Bun.write(filePath, raw);
|
|
25360
|
+
await this.load(filePath);
|
|
25361
|
+
return results;
|
|
25362
|
+
}
|
|
25363
|
+
async enableWorker(name) {
|
|
25364
|
+
await this.setWorkersEnabled([name], true);
|
|
25365
|
+
}
|
|
25366
|
+
async disableWorker(name) {
|
|
25367
|
+
await this.setWorkersEnabled([name], false);
|
|
25368
|
+
}
|
|
25369
|
+
getWorkerDefaultEnabled(name) {
|
|
25370
|
+
return getWorkerDefaultEnabled(name);
|
|
25371
|
+
}
|
|
25260
25372
|
validate() {
|
|
25261
25373
|
const errors4 = [];
|
|
25262
25374
|
if (!this.config) {
|
|
@@ -25309,9 +25421,16 @@ ${e.errors.map((m3) => ` - ${m3}`).join(`
|
|
|
25309
25421
|
return this.config;
|
|
25310
25422
|
}
|
|
25311
25423
|
}
|
|
25424
|
+
var JSONC_FORMAT;
|
|
25312
25425
|
var init_config_service = __esm(() => {
|
|
25313
25426
|
init_main();
|
|
25314
25427
|
init_src();
|
|
25428
|
+
JSONC_FORMAT = {
|
|
25429
|
+
tabSize: 2,
|
|
25430
|
+
insertSpaces: true,
|
|
25431
|
+
eol: `
|
|
25432
|
+
`
|
|
25433
|
+
};
|
|
25315
25434
|
});
|
|
25316
25435
|
|
|
25317
25436
|
// src/services/config/index.ts
|
|
@@ -25758,6 +25877,9 @@ class PrerequisitesService {
|
|
|
25758
25877
|
return { outdated: false };
|
|
25759
25878
|
}
|
|
25760
25879
|
const current2 = match[1];
|
|
25880
|
+
if (!current2) {
|
|
25881
|
+
return { outdated: false };
|
|
25882
|
+
}
|
|
25761
25883
|
const meetsMin = this.satisfies(current2, this.MINIMUM_WRANGLER);
|
|
25762
25884
|
return {
|
|
25763
25885
|
outdated: !meetsMin,
|
|
@@ -25814,7 +25936,7 @@ class PrerequisitesService {
|
|
|
25814
25936
|
});
|
|
25815
25937
|
const stdout2 = await new Response(proc.stdout).text();
|
|
25816
25938
|
const match = stdout2.match(/(\d+\.\d+)/);
|
|
25817
|
-
const version2 = match
|
|
25939
|
+
const version2 = match?.[1] ?? "unknown";
|
|
25818
25940
|
const [major, minor] = version2.split(".").map(Number);
|
|
25819
25941
|
const passed = (major ?? 0) >= 2 && (minor ?? 0) >= 40;
|
|
25820
25942
|
return {
|
|
@@ -26334,7 +26456,7 @@ var exports_schema_service = {};
|
|
|
26334
26456
|
__export(exports_schema_service, {
|
|
26335
26457
|
SchemaService: () => SchemaService
|
|
26336
26458
|
});
|
|
26337
|
-
import { readFileSync as
|
|
26459
|
+
import { readFileSync as readFileSync8, existsSync as existsSync11 } from "fs";
|
|
26338
26460
|
import { resolve as resolve4 } from "path";
|
|
26339
26461
|
|
|
26340
26462
|
class SchemaService {
|
|
@@ -26370,7 +26492,7 @@ class SchemaService {
|
|
|
26370
26492
|
const errors4 = [];
|
|
26371
26493
|
const isHooxProject = existsSync11(resolve4(this.projectRoot, "wrangler.jsonc")) || existsSync11(resolve4(this.projectRoot, "workers"));
|
|
26372
26494
|
try {
|
|
26373
|
-
const wranglerContent =
|
|
26495
|
+
const wranglerContent = readFileSync8(workerWranglerPath, "utf-8");
|
|
26374
26496
|
errors4.push(...validateWranglerJsonc(name, manifest, wranglerContent));
|
|
26375
26497
|
} catch (e) {
|
|
26376
26498
|
const isErrnoException = e instanceof Error && "code" in e;
|
|
@@ -26384,7 +26506,7 @@ class SchemaService {
|
|
|
26384
26506
|
});
|
|
26385
26507
|
}
|
|
26386
26508
|
try {
|
|
26387
|
-
const rootContent =
|
|
26509
|
+
const rootContent = readFileSync8(rootWranglerPath, "utf-8");
|
|
26388
26510
|
errors4.push(...validateRootSecrets(name, manifest, rootContent));
|
|
26389
26511
|
} catch (e) {
|
|
26390
26512
|
const errMessage = e instanceof Error ? e.message : String(e);
|
|
@@ -26395,7 +26517,7 @@ class SchemaService {
|
|
|
26395
26517
|
});
|
|
26396
26518
|
}
|
|
26397
26519
|
try {
|
|
26398
|
-
const devVarsContent =
|
|
26520
|
+
const devVarsContent = readFileSync8(devVarsPath, "utf-8");
|
|
26399
26521
|
errors4.push(...validateDevVars(name, manifest, devVarsContent));
|
|
26400
26522
|
} catch (e) {
|
|
26401
26523
|
const errMessage = e instanceof Error ? e.message : String(e);
|
|
@@ -26654,7 +26776,7 @@ var init_trace_service = __esm(() => {
|
|
|
26654
26776
|
});
|
|
26655
26777
|
|
|
26656
26778
|
// src/index.ts
|
|
26657
|
-
import { readFileSync as
|
|
26779
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
26658
26780
|
|
|
26659
26781
|
// ../../node_modules/.bun/commander@15.0.0/node_modules/commander/lib/error.js
|
|
26660
26782
|
class CommanderError extends Error {
|
|
@@ -28857,7 +28979,13 @@ function formatTable(rows, opts = {}) {
|
|
|
28857
28979
|
const alignNumbers = opts.alignNumbers !== false;
|
|
28858
28980
|
const colorizeStatus = opts.colorizeStatus !== false;
|
|
28859
28981
|
const compact = opts.compact === true;
|
|
28860
|
-
const
|
|
28982
|
+
const firstRow = rows[0];
|
|
28983
|
+
if (!firstRow) {
|
|
28984
|
+
process.stdout.write(`${theme.dim("(empty)")}
|
|
28985
|
+
`);
|
|
28986
|
+
return;
|
|
28987
|
+
}
|
|
28988
|
+
const keys = Object.keys(firstRow);
|
|
28861
28989
|
const processed = rows.map((row) => {
|
|
28862
28990
|
const out = {};
|
|
28863
28991
|
for (const k of keys) {
|
|
@@ -28894,17 +29022,18 @@ function formatTable(rows, opts = {}) {
|
|
|
28894
29022
|
widths[key] = Math.max(widths[key], stripped);
|
|
28895
29023
|
}
|
|
28896
29024
|
}
|
|
28897
|
-
const topParts = keys.map((k) => "\u2500".repeat(widths[k] + 2));
|
|
29025
|
+
const topParts = keys.map((k) => "\u2500".repeat((widths[k] ?? 0) + 2));
|
|
28898
29026
|
const topBorder = `\u250C${topParts.join("\u252C")}\u2510`;
|
|
28899
29027
|
const sepBorder = `\u251C${topParts.join("\u253C")}\u2524`;
|
|
28900
29028
|
const botBorder = `\u2514${topParts.join("\u2534")}\u2518`;
|
|
28901
|
-
const headerCells = keys.map((k) => theme.bold(k.padEnd(widths[k])).toString());
|
|
29029
|
+
const headerCells = keys.map((k) => theme.bold(k.padEnd(widths[k] ?? 0)).toString());
|
|
28902
29030
|
const headerRow = `\u2502 ${headerCells.join(" \u2502 ")} \u2502`;
|
|
28903
29031
|
const dataRows = processed.map((row, rowIdx) => {
|
|
28904
29032
|
const isAlt = zebra && rowIdx % 2 === 0;
|
|
28905
29033
|
const cells = keys.map((k) => {
|
|
28906
29034
|
const value = row[k] ?? "";
|
|
28907
|
-
const
|
|
29035
|
+
const width = widths[k] ?? 0;
|
|
29036
|
+
const padded = numericColumns.has(k) ? value.padStart(width) : value.padEnd(width);
|
|
28908
29037
|
if (isAlt && !value.includes("\x1B")) {
|
|
28909
29038
|
return theme.textMuted(padded);
|
|
28910
29039
|
}
|
|
@@ -29027,11 +29156,11 @@ function levenshtein(a2, b) {
|
|
|
29027
29156
|
curr[0] = j;
|
|
29028
29157
|
for (let i = 1;i <= m; i++) {
|
|
29029
29158
|
const cost = s.charCodeAt(i - 1) === t.charCodeAt(j - 1) ? 0 : 1;
|
|
29030
|
-
curr[i] = Math.min(curr[i - 1] + 1, prev[i] + 1, prev[i - 1] + cost);
|
|
29159
|
+
curr[i] = Math.min((curr[i - 1] ?? 0) + 1, (prev[i] ?? 0) + 1, (prev[i - 1] ?? 0) + cost);
|
|
29031
29160
|
}
|
|
29032
29161
|
[prev, curr] = [curr, prev];
|
|
29033
29162
|
}
|
|
29034
|
-
return prev[m];
|
|
29163
|
+
return prev[m] ?? 0;
|
|
29035
29164
|
}
|
|
29036
29165
|
|
|
29037
29166
|
// src/utils/error-handler.ts
|
|
@@ -30480,6 +30609,8 @@ class SetupService {
|
|
|
30480
30609
|
if (!varsMatch)
|
|
30481
30610
|
continue;
|
|
30482
30611
|
const varsBlock = varsMatch[1];
|
|
30612
|
+
if (varsBlock === undefined)
|
|
30613
|
+
continue;
|
|
30483
30614
|
const nullEntries = varsBlock.match(/"\w+"\s*:\s*null/g);
|
|
30484
30615
|
if (!nullEntries)
|
|
30485
30616
|
continue;
|
|
@@ -31614,46 +31745,32 @@ class EnvService {
|
|
|
31614
31745
|
hint: "Telegram webhook secret token"
|
|
31615
31746
|
},
|
|
31616
31747
|
{
|
|
31617
|
-
name: "
|
|
31748
|
+
name: "EXCHANGE_KEY_BINDING",
|
|
31618
31749
|
required: false,
|
|
31619
31750
|
secret: true,
|
|
31620
31751
|
section: "Exchanges",
|
|
31621
|
-
hint: "
|
|
31752
|
+
hint: "Unified exchange API key (Binance / Bybit / MEXC \u2014 venue via routing)"
|
|
31622
31753
|
},
|
|
31623
31754
|
{
|
|
31624
|
-
name: "
|
|
31755
|
+
name: "EXCHANGE_SECRET_BINDING",
|
|
31625
31756
|
required: false,
|
|
31626
31757
|
secret: true,
|
|
31627
31758
|
section: "Exchanges",
|
|
31628
|
-
hint: "
|
|
31759
|
+
hint: "Unified exchange API secret"
|
|
31629
31760
|
},
|
|
31630
31761
|
{
|
|
31631
|
-
name: "
|
|
31762
|
+
name: "EXCHANGE_TESTNET_KEY_BINDING",
|
|
31632
31763
|
required: false,
|
|
31633
31764
|
secret: true,
|
|
31634
31765
|
section: "Exchanges",
|
|
31635
|
-
hint: "
|
|
31766
|
+
hint: "Optional testnet API key (when signals use test: true)"
|
|
31636
31767
|
},
|
|
31637
31768
|
{
|
|
31638
|
-
name: "
|
|
31769
|
+
name: "EXCHANGE_TESTNET_SECRET_BINDING",
|
|
31639
31770
|
required: false,
|
|
31640
31771
|
secret: true,
|
|
31641
31772
|
section: "Exchanges",
|
|
31642
|
-
hint: "
|
|
31643
|
-
},
|
|
31644
|
-
{
|
|
31645
|
-
name: "BYBIT_KEY_BINDING",
|
|
31646
|
-
required: false,
|
|
31647
|
-
secret: true,
|
|
31648
|
-
section: "Exchanges",
|
|
31649
|
-
hint: "Bybit API key"
|
|
31650
|
-
},
|
|
31651
|
-
{
|
|
31652
|
-
name: "BYBIT_SECRET_BINDING",
|
|
31653
|
-
required: false,
|
|
31654
|
-
secret: true,
|
|
31655
|
-
section: "Exchanges",
|
|
31656
|
-
hint: "Bybit API secret"
|
|
31773
|
+
hint: "Optional testnet API secret"
|
|
31657
31774
|
},
|
|
31658
31775
|
{
|
|
31659
31776
|
name: "EMAIL_HOST_BINDING",
|
|
@@ -31824,12 +31941,8 @@ class EnvService {
|
|
|
31824
31941
|
"workers/trade-worker": [
|
|
31825
31942
|
"API_SERVICE_KEY_BINDING",
|
|
31826
31943
|
"INTERNAL_KEY_BINDING",
|
|
31827
|
-
"
|
|
31828
|
-
"
|
|
31829
|
-
"MEXC_KEY_BINDING",
|
|
31830
|
-
"MEXC_SECRET_BINDING",
|
|
31831
|
-
"BYBIT_KEY_BINDING",
|
|
31832
|
-
"BYBIT_SECRET_BINDING"
|
|
31944
|
+
"EXCHANGE_KEY_BINDING",
|
|
31945
|
+
"EXCHANGE_SECRET_BINDING"
|
|
31833
31946
|
],
|
|
31834
31947
|
"workers/agent-worker": ["AGENT_INTERNAL_KEY"],
|
|
31835
31948
|
"workers/d1-worker": ["INTERNAL_KEY_BINDING"],
|
|
@@ -33724,6 +33837,27 @@ var SYSTEM_SECRET_NAMES = [
|
|
|
33724
33837
|
"API_SERVICE_KEY_BINDING"
|
|
33725
33838
|
];
|
|
33726
33839
|
var SYSTEM_SECRET_SET = new Set(SYSTEM_SECRET_NAMES);
|
|
33840
|
+
var WORKER_SYSTEM_SECRETS = {
|
|
33841
|
+
"d1-worker": ["INTERNAL_KEY_BINDING"],
|
|
33842
|
+
"analytics-worker": ["INTERNAL_KEY_BINDING"],
|
|
33843
|
+
"trade-worker": [
|
|
33844
|
+
"INTERNAL_KEY_BINDING",
|
|
33845
|
+
"TELEGRAM_INTERNAL_KEY_BINDING",
|
|
33846
|
+
"API_SERVICE_KEY_BINDING"
|
|
33847
|
+
],
|
|
33848
|
+
"report-worker": ["INTERNAL_KEY_BINDING"],
|
|
33849
|
+
"email-worker": ["INTERNAL_KEY_BINDING"],
|
|
33850
|
+
"agent-worker": ["INTERNAL_KEY_BINDING", "AGENT_INTERNAL_KEY"],
|
|
33851
|
+
hoox: ["INTERNAL_KEY_BINDING", "WEBHOOK_API_KEY_BINDING"],
|
|
33852
|
+
"web3-wallet-worker": ["INTERNAL_KEY_BINDING"],
|
|
33853
|
+
"telegram-worker": ["INTERNAL_KEY_BINDING"],
|
|
33854
|
+
dashboard: [
|
|
33855
|
+
"AGENT_INTERNAL_KEY",
|
|
33856
|
+
"SESSION_SECRET",
|
|
33857
|
+
"TRADE_INTERNAL_KEY",
|
|
33858
|
+
"API_SERVICE_KEY_BINDING"
|
|
33859
|
+
]
|
|
33860
|
+
};
|
|
33727
33861
|
function isSystemSecret(name) {
|
|
33728
33862
|
return SYSTEM_SECRET_SET.has(name);
|
|
33729
33863
|
}
|
|
@@ -33844,11 +33978,19 @@ class SecretsService {
|
|
|
33844
33978
|
const content = await devVarsFile.text();
|
|
33845
33979
|
existingValues = this.parseDotEnv(content);
|
|
33846
33980
|
}
|
|
33981
|
+
let keysFallback = new Map;
|
|
33982
|
+
if (options.systemOnly) {
|
|
33983
|
+
const keysFile = Bun.file(".keys/setup.env");
|
|
33984
|
+
if (await keysFile.exists()) {
|
|
33985
|
+
keysFallback = this.parseDotEnv(await keysFile.text());
|
|
33986
|
+
}
|
|
33987
|
+
}
|
|
33847
33988
|
let secrets;
|
|
33848
33989
|
if (options.systemOnly) {
|
|
33849
33990
|
const fromDeclared = declared.filter((s) => isSystemSecret(s));
|
|
33850
33991
|
const fromDevVars = [...SYSTEM_SECRET_NAMES].filter((s) => existingValues.has(s));
|
|
33851
|
-
|
|
33992
|
+
const fromMap = [...WORKER_SYSTEM_SECRETS[workerName] ?? []];
|
|
33993
|
+
secrets = [...new Set([...fromDeclared, ...fromDevVars, ...fromMap])];
|
|
33852
33994
|
} else {
|
|
33853
33995
|
secrets = declared;
|
|
33854
33996
|
}
|
|
@@ -33858,7 +34000,7 @@ class SecretsService {
|
|
|
33858
34000
|
const items = [];
|
|
33859
34001
|
for (const secret of secrets) {
|
|
33860
34002
|
try {
|
|
33861
|
-
const value = existingValues.get(secret);
|
|
34003
|
+
const value = existingValues.get(secret) ?? keysFallback.get(secret);
|
|
33862
34004
|
if (value !== undefined && !this.isPlaceholder(value)) {
|
|
33863
34005
|
await this.execWranglerSecretPut(worker.path, secret, value, workerName);
|
|
33864
34006
|
synced.push(secret);
|
|
@@ -34138,8 +34280,8 @@ The command will prompt for the secret value (hidden input).
|
|
|
34138
34280
|
It writes to the worker's .dev.vars file and syncs to Cloudflare.
|
|
34139
34281
|
|
|
34140
34282
|
EXAMPLES:
|
|
34141
|
-
hoox secrets set trade-worker
|
|
34142
|
-
hoox config secrets set trade-worker
|
|
34283
|
+
hoox secrets set trade-worker EXCHANGE_KEY_BINDING
|
|
34284
|
+
hoox config secrets set trade-worker EXCHANGE_KEY_BINDING`).action(withErrorHandling(async (workerName, secretName, _2, cmd) => {
|
|
34143
34285
|
const opts = getFormatOptions(cmd);
|
|
34144
34286
|
const svc = await SecretsService.create();
|
|
34145
34287
|
const declared = svc.listSecrets(workerName);
|
|
@@ -34184,8 +34326,8 @@ ARGUMENTS:
|
|
|
34184
34326
|
This removes the secret from Cloudflare and from the worker's .dev.vars file.
|
|
34185
34327
|
|
|
34186
34328
|
EXAMPLES:
|
|
34187
|
-
hoox secrets delete trade-worker
|
|
34188
|
-
hoox config secrets delete trade-worker
|
|
34329
|
+
hoox secrets delete trade-worker EXCHANGE_KEY_BINDING
|
|
34330
|
+
hoox config secrets delete trade-worker EXCHANGE_KEY_BINDING`).action(withErrorHandling(async (workerName, secretName, _2, cmd) => {
|
|
34189
34331
|
const opts = getFormatOptions(cmd);
|
|
34190
34332
|
const svc = await SecretsService.create();
|
|
34191
34333
|
const declared = svc.listSecrets(workerName);
|
|
@@ -34327,7 +34469,7 @@ EXAMPLES:
|
|
|
34327
34469
|
}
|
|
34328
34470
|
|
|
34329
34471
|
// src/commands/config/keys-subcommands.ts
|
|
34330
|
-
import { existsSync as existsSync9 } from "fs";
|
|
34472
|
+
import { chmodSync as chmodSync6, existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
|
|
34331
34473
|
init_fs_secure();
|
|
34332
34474
|
init_theme();
|
|
34333
34475
|
function generateKey(bytes = 32) {
|
|
@@ -34335,6 +34477,82 @@ function generateKey(bytes = 32) {
|
|
|
34335
34477
|
crypto.getRandomValues(buf);
|
|
34336
34478
|
return Array.from(buf, (b3) => b3.toString(16).padStart(2, "0")).join("");
|
|
34337
34479
|
}
|
|
34480
|
+
var DEV_VARS_WORKER_KEYS2 = {
|
|
34481
|
+
"d1-worker": ["INTERNAL_KEY_BINDING"],
|
|
34482
|
+
"analytics-worker": ["INTERNAL_KEY_BINDING"],
|
|
34483
|
+
"trade-worker": [
|
|
34484
|
+
"INTERNAL_KEY_BINDING",
|
|
34485
|
+
"TELEGRAM_INTERNAL_KEY_BINDING",
|
|
34486
|
+
"API_SERVICE_KEY_BINDING"
|
|
34487
|
+
],
|
|
34488
|
+
"report-worker": ["INTERNAL_KEY_BINDING"],
|
|
34489
|
+
"email-worker": ["INTERNAL_KEY_BINDING"],
|
|
34490
|
+
"agent-worker": ["INTERNAL_KEY_BINDING", "AGENT_INTERNAL_KEY"],
|
|
34491
|
+
hoox: ["INTERNAL_KEY_BINDING", "WEBHOOK_API_KEY_BINDING"],
|
|
34492
|
+
"web3-wallet-worker": ["INTERNAL_KEY_BINDING"],
|
|
34493
|
+
"telegram-worker": ["INTERNAL_KEY_BINDING"],
|
|
34494
|
+
dashboard: [
|
|
34495
|
+
"AGENT_INTERNAL_KEY",
|
|
34496
|
+
"SESSION_SECRET",
|
|
34497
|
+
"TRADE_INTERNAL_KEY",
|
|
34498
|
+
"API_SERVICE_KEY_BINDING"
|
|
34499
|
+
]
|
|
34500
|
+
};
|
|
34501
|
+
var WORKER_FS_DIR2 = {
|
|
34502
|
+
hoox: "hoox-worker"
|
|
34503
|
+
};
|
|
34504
|
+
function workerFsDir2(worker) {
|
|
34505
|
+
return WORKER_FS_DIR2[worker] ?? worker;
|
|
34506
|
+
}
|
|
34507
|
+
function parseEnvFile2(text2) {
|
|
34508
|
+
const map2 = new Map;
|
|
34509
|
+
for (const line of text2.split(`
|
|
34510
|
+
`)) {
|
|
34511
|
+
const trimmed = line.trim();
|
|
34512
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
34513
|
+
continue;
|
|
34514
|
+
const eq = trimmed.indexOf("=");
|
|
34515
|
+
if (eq <= 0)
|
|
34516
|
+
continue;
|
|
34517
|
+
map2.set(trimmed.slice(0, eq), trimmed.slice(eq + 1));
|
|
34518
|
+
}
|
|
34519
|
+
return map2;
|
|
34520
|
+
}
|
|
34521
|
+
async function writeDevVarsFromKeys(keys) {
|
|
34522
|
+
let count = 0;
|
|
34523
|
+
for (const [worker, secretNames] of Object.entries(DEV_VARS_WORKER_KEYS2)) {
|
|
34524
|
+
const path5 = `workers/${workerFsDir2(worker)}/.dev.vars`;
|
|
34525
|
+
const meshSet = new Set(secretNames);
|
|
34526
|
+
const existing = existsSync9(path5) ? parseEnvFile2(readFileSync7(path5, "utf-8")) : new Map;
|
|
34527
|
+
for (const secretName of secretNames) {
|
|
34528
|
+
const value = keys[secretName];
|
|
34529
|
+
if (value)
|
|
34530
|
+
existing.set(secretName, value);
|
|
34531
|
+
}
|
|
34532
|
+
let content = `# .dev.vars \u2014 local secrets for ${worker}
|
|
34533
|
+
`;
|
|
34534
|
+
content += `# Generated by \`hoox keys generate\`. NEVER commit this file.
|
|
34535
|
+
|
|
34536
|
+
`;
|
|
34537
|
+
for (const secretName of secretNames) {
|
|
34538
|
+
const value = existing.get(secretName);
|
|
34539
|
+
if (value !== undefined)
|
|
34540
|
+
content += `${secretName}=${value}
|
|
34541
|
+
`;
|
|
34542
|
+
}
|
|
34543
|
+
for (const [k, v] of existing) {
|
|
34544
|
+
if (!meshSet.has(k))
|
|
34545
|
+
content += `${k}=${v}
|
|
34546
|
+
`;
|
|
34547
|
+
}
|
|
34548
|
+
await Bun.write(path5, content);
|
|
34549
|
+
try {
|
|
34550
|
+
chmodSync6(path5, 384);
|
|
34551
|
+
} catch {}
|
|
34552
|
+
count++;
|
|
34553
|
+
}
|
|
34554
|
+
return count;
|
|
34555
|
+
}
|
|
34338
34556
|
function registerKeysSubcommands(keysCmd, service = "config") {
|
|
34339
34557
|
keysCmd.command("generate").summary("Generate new internal auth keys").description(`Generate new internal auth keys and save to .keys/ directory.
|
|
34340
34558
|
|
|
@@ -34376,9 +34594,12 @@ EXAMPLES:
|
|
|
34376
34594
|
`) + `
|
|
34377
34595
|
`);
|
|
34378
34596
|
secureSecretFile(`${keysDir}/setup.env`);
|
|
34379
|
-
|
|
34597
|
+
const devVarsCount = await writeDevVarsFromKeys(keys);
|
|
34598
|
+
formatSuccess(`Generated ${Object.keys(keys).length} keys in ${keysDir}/ + ${devVarsCount} .dev.vars`, opts);
|
|
34380
34599
|
if (!opts.quiet && !opts.json) {
|
|
34381
34600
|
process.stdout.write(`${theme.warning("!")} Keep these keys secret. Add ${keysDir}/ to .gitignore.
|
|
34601
|
+
`);
|
|
34602
|
+
process.stdout.write(`${theme.dim("\u2192")} Next: hoox secrets sync --system
|
|
34382
34603
|
`);
|
|
34383
34604
|
formatKeyValue(keys, opts);
|
|
34384
34605
|
}
|
|
@@ -34476,7 +34697,7 @@ EXAMPLES:
|
|
|
34476
34697
|
hoox config show Display current configuration
|
|
34477
34698
|
hoox config set workers.agent-worker.enabled false
|
|
34478
34699
|
hoox config secrets list List secrets for a worker
|
|
34479
|
-
hoox config secrets set trade-worker
|
|
34700
|
+
hoox config secrets set trade-worker EXCHANGE_KEY_BINDING
|
|
34480
34701
|
hoox config keys generate Generate new internal keys`);
|
|
34481
34702
|
configCmd.command("show").summary("Display current wrangler.jsonc configuration").description(`Display the current wrangler.jsonc configuration in a formatted table.
|
|
34482
34703
|
|
|
@@ -34671,7 +34892,7 @@ COMMANDS:
|
|
|
34671
34892
|
|
|
34672
34893
|
EXAMPLES:
|
|
34673
34894
|
hoox secrets list trade-worker
|
|
34674
|
-
hoox secrets set trade-worker
|
|
34895
|
+
hoox secrets set trade-worker EXCHANGE_KEY_BINDING
|
|
34675
34896
|
hoox secrets sync --system
|
|
34676
34897
|
hoox secrets sync`);
|
|
34677
34898
|
registerSecretsSubcommands(cmd, "secrets");
|
|
@@ -36223,11 +36444,19 @@ async function resolveZone(cf) {
|
|
|
36223
36444
|
if (lines.length === 0) {
|
|
36224
36445
|
throw new CLIError("No zones found. Set CLOUDFLARE_ZONE_ID environment variable.", 1 /* ERROR */);
|
|
36225
36446
|
}
|
|
36226
|
-
const
|
|
36447
|
+
const firstLine = lines[0];
|
|
36448
|
+
if (!firstLine) {
|
|
36449
|
+
throw new CLIError("No zones found. Set CLOUDFLARE_ZONE_ID environment variable.", 1 /* ERROR */);
|
|
36450
|
+
}
|
|
36451
|
+
const match = firstLine.match(/^(.+?)\s+\((.+?)\)\s*$/);
|
|
36227
36452
|
if (match) {
|
|
36228
|
-
|
|
36453
|
+
const name = match[1];
|
|
36454
|
+
const id = match[2];
|
|
36455
|
+
if (name && id) {
|
|
36456
|
+
return { name, id };
|
|
36457
|
+
}
|
|
36229
36458
|
}
|
|
36230
|
-
return { name:
|
|
36459
|
+
return { name: firstLine, id: firstLine };
|
|
36231
36460
|
}
|
|
36232
36461
|
async function handleStatus(opts) {
|
|
36233
36462
|
const cf = new CloudflareService;
|
|
@@ -36545,6 +36774,8 @@ EXAMPLES:
|
|
|
36545
36774
|
const results = [];
|
|
36546
36775
|
for (let i2 = 0;i2 < workers.length; i2++) {
|
|
36547
36776
|
const name2 = workers[i2];
|
|
36777
|
+
if (!name2)
|
|
36778
|
+
continue;
|
|
36548
36779
|
const workerConfig = configService.getWorker(name2);
|
|
36549
36780
|
if (!workerConfig)
|
|
36550
36781
|
continue;
|
|
@@ -36822,7 +37053,11 @@ class DbService {
|
|
|
36822
37053
|
if (!match) {
|
|
36823
37054
|
throw new Error(`Migration script "${path6}" was found but no \`d1 execute \u2026 --command="\u2026"\` line could be extracted. ` + `Refusing to fall back to a no-op migration \u2014 please check the script format.`);
|
|
36824
37055
|
}
|
|
36825
|
-
|
|
37056
|
+
const command = match[1];
|
|
37057
|
+
if (!command) {
|
|
37058
|
+
throw new Error(`Migration script "${path6}" was found but no \`d1 execute \u2026 --command="\u2026"\` line could be extracted. ` + `Refusing to fall back to a no-op migration \u2014 please check the script format.`);
|
|
37059
|
+
}
|
|
37060
|
+
return command;
|
|
36826
37061
|
}
|
|
36827
37062
|
}
|
|
36828
37063
|
// src/commands/db/db-command.ts
|
|
@@ -37129,15 +37364,19 @@ function parseWranglerQueuesTable(raw) {
|
|
|
37129
37364
|
const cells = line.split("\u2502").map((c3) => c3.trim()).filter((c3) => c3.length > 0);
|
|
37130
37365
|
if (cells.length < 2)
|
|
37131
37366
|
continue;
|
|
37132
|
-
|
|
37367
|
+
const queueId = cells[0];
|
|
37368
|
+
const queueName = cells[1];
|
|
37369
|
+
if (!queueId || !queueName)
|
|
37133
37370
|
continue;
|
|
37134
|
-
if (
|
|
37371
|
+
if (queueId === "id" || queueId === "name")
|
|
37372
|
+
continue;
|
|
37373
|
+
if (!/^[0-9a-f-]{16,}$/i.test(queueId))
|
|
37135
37374
|
continue;
|
|
37136
37375
|
const producers = cells[4] !== undefined && cells[4] !== "" ? Number(cells[4]) : undefined;
|
|
37137
37376
|
const consumers = cells[5] !== undefined && cells[5] !== "" ? Number(cells[5]) : undefined;
|
|
37138
37377
|
queues.push({
|
|
37139
|
-
queue_id:
|
|
37140
|
-
queue_name:
|
|
37378
|
+
queue_id: queueId,
|
|
37379
|
+
queue_name: queueName,
|
|
37141
37380
|
created_on: cells[2],
|
|
37142
37381
|
modified_on: cells[3],
|
|
37143
37382
|
producers_total_count: Number.isFinite(producers) ? producers : undefined,
|
|
@@ -37322,57 +37561,151 @@ SUBCOMMANDS:
|
|
|
37322
37561
|
}, { service: "monitor" }));
|
|
37323
37562
|
}
|
|
37324
37563
|
// src/commands/workers/workers-command.ts
|
|
37564
|
+
init_src();
|
|
37325
37565
|
init_config2();
|
|
37566
|
+
init_errors4();
|
|
37326
37567
|
async function doListWorkers(fmt) {
|
|
37327
37568
|
const configService = new ConfigService;
|
|
37328
37569
|
await configService.load();
|
|
37329
|
-
const
|
|
37330
|
-
const rows =
|
|
37331
|
-
|
|
37332
|
-
|
|
37333
|
-
|
|
37334
|
-
|
|
37335
|
-
|
|
37336
|
-
|
|
37337
|
-
|
|
37338
|
-
});
|
|
37570
|
+
const statuses = configService.listWorkerStatuses();
|
|
37571
|
+
const rows = statuses.map((w) => ({
|
|
37572
|
+
Worker: w.name,
|
|
37573
|
+
Status: w.enabled ? "enabled" : "disabled",
|
|
37574
|
+
Default: w.defaultEnabled === undefined ? "-" : w.defaultEnabled ? "enabled" : "disabled",
|
|
37575
|
+
Path: w.path,
|
|
37576
|
+
Config: w.inConfig ? "yes" : "no",
|
|
37577
|
+
Catalog: w.inCatalog ? "yes" : "no"
|
|
37578
|
+
}));
|
|
37339
37579
|
if (fmt.json) {
|
|
37340
|
-
formatJson(
|
|
37580
|
+
formatJson(statuses.map((w) => ({
|
|
37581
|
+
name: w.name,
|
|
37582
|
+
enabled: w.enabled,
|
|
37583
|
+
defaultEnabled: w.defaultEnabled ?? null,
|
|
37584
|
+
path: w.path,
|
|
37585
|
+
inConfig: w.inConfig,
|
|
37586
|
+
inCatalog: w.inCatalog
|
|
37587
|
+
})), fmt);
|
|
37341
37588
|
return;
|
|
37342
37589
|
}
|
|
37343
37590
|
formatTable(rows, fmt);
|
|
37344
37591
|
}
|
|
37592
|
+
function doCatalog(fmt) {
|
|
37593
|
+
const rows = WORKER_CATALOG.map((w) => ({
|
|
37594
|
+
Worker: w.name,
|
|
37595
|
+
Default: w.defaultEnabled ? "enabled" : "disabled",
|
|
37596
|
+
Path: w.path
|
|
37597
|
+
}));
|
|
37598
|
+
if (fmt.json) {
|
|
37599
|
+
formatJson(WORKER_CATALOG.map((w) => ({
|
|
37600
|
+
name: w.name,
|
|
37601
|
+
defaultEnabled: w.defaultEnabled,
|
|
37602
|
+
path: w.path
|
|
37603
|
+
})), fmt);
|
|
37604
|
+
return;
|
|
37605
|
+
}
|
|
37606
|
+
formatTable(rows, fmt);
|
|
37607
|
+
}
|
|
37608
|
+
async function doSetEnabled(names, enabled, fmt) {
|
|
37609
|
+
if (names.length === 0) {
|
|
37610
|
+
throw new CLIError(`Specify at least one worker name (e.g. hoox workers ${enabled ? "enable" : "disable"} trade-worker)`, 2 /* INVALID_USAGE */, undefined, true, `Run \`hoox workers catalog\` to see known workers.`);
|
|
37611
|
+
}
|
|
37612
|
+
const configService = new ConfigService;
|
|
37613
|
+
await configService.load();
|
|
37614
|
+
let results;
|
|
37615
|
+
try {
|
|
37616
|
+
results = await configService.setWorkersEnabled(names, enabled);
|
|
37617
|
+
} catch (e) {
|
|
37618
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
37619
|
+
throw new CLIError(msg, 2 /* INVALID_USAGE */, undefined, true);
|
|
37620
|
+
}
|
|
37621
|
+
if (fmt.json) {
|
|
37622
|
+
formatJson({ action: enabled ? "enable" : "disable", results }, fmt);
|
|
37623
|
+
return;
|
|
37624
|
+
}
|
|
37625
|
+
for (const r2 of results) {
|
|
37626
|
+
const seedNote = r2.seeded ? " (seeded from catalog)" : "";
|
|
37627
|
+
formatSuccess(`${r2.name} \u2192 ${r2.enabled ? "enabled" : "disabled"}${seedNote}`, fmt);
|
|
37628
|
+
}
|
|
37629
|
+
}
|
|
37345
37630
|
function registerWorkersCommand(program2) {
|
|
37346
|
-
const workersCmd = program2.command("workers").summary("Manage Cloudflare Workers (list, dev, logs)").description(`Manage your Hoox Cloudflare Workers.
|
|
37631
|
+
const workersCmd = program2.command("workers").summary("Manage Cloudflare Workers (list, enable, disable, dev, logs)").description(`Manage your Hoox Cloudflare Workers.
|
|
37347
37632
|
|
|
37348
37633
|
SUBCOMMANDS:
|
|
37349
|
-
list List all workers
|
|
37634
|
+
list List all workers (catalog + config) with status
|
|
37635
|
+
catalog Show the canonical worker catalog and defaults
|
|
37636
|
+
enable <name...> Enable workers in wrangler.jsonc
|
|
37637
|
+
disable <name...> Disable workers in wrangler.jsonc
|
|
37350
37638
|
dev <name> Start a worker for local development (delegates to dev worker)
|
|
37351
37639
|
logs <name> Tail logs for a specific worker (delegates to logs worker)
|
|
37352
37640
|
|
|
37641
|
+
The worker catalog (shared package) is the source of all known workers and
|
|
37642
|
+
their default enabled flags. Enable/disable updates workers.<name>.enabled
|
|
37643
|
+
in the root wrangler.jsonc. Missing catalog workers are seeded on enable.
|
|
37644
|
+
|
|
37353
37645
|
For health checks, use 'hoox check health'.
|
|
37354
37646
|
For deployments, use 'hoox deploy workers' or 'hoox deploy worker <name>'.
|
|
37355
37647
|
|
|
37356
37648
|
EXAMPLES:
|
|
37357
|
-
hoox workers list
|
|
37358
|
-
hoox workers
|
|
37359
|
-
hoox workers
|
|
37360
|
-
hoox workers
|
|
37361
|
-
|
|
37362
|
-
|
|
37363
|
-
|
|
37364
|
-
|
|
37365
|
-
|
|
37366
|
-
-
|
|
37367
|
-
-
|
|
37649
|
+
hoox workers list
|
|
37650
|
+
hoox workers catalog
|
|
37651
|
+
hoox workers enable trade-worker agent-worker
|
|
37652
|
+
hoox workers disable web3-wallet-worker email-worker
|
|
37653
|
+
hoox workers dev trade-worker
|
|
37654
|
+
hoox workers logs hoox`);
|
|
37655
|
+
workersCmd.command("list").summary("List workers with enabled status (catalog + config)").description(`List all workers from the shared catalog merged with wrangler.jsonc.
|
|
37656
|
+
|
|
37657
|
+
Columns:
|
|
37658
|
+
- Worker name
|
|
37659
|
+
- Status (effective enabled/disabled)
|
|
37660
|
+
- Default (catalog default)
|
|
37661
|
+
- Path
|
|
37662
|
+
- Config / Catalog membership
|
|
37368
37663
|
|
|
37369
37664
|
EXAMPLES:
|
|
37370
|
-
hoox workers list
|
|
37371
|
-
hoox workers list --json
|
|
37372
|
-
hoox workers list --quiet Minimal output`).action(withErrorHandling(async (_opts, cmd) => {
|
|
37665
|
+
hoox workers list
|
|
37666
|
+
hoox workers list --json`).action(withErrorHandling(async (_opts, cmd) => {
|
|
37373
37667
|
const fmt = getFormatOptions(cmd);
|
|
37374
37668
|
await doListWorkers(fmt);
|
|
37375
37669
|
}, { service: "workers" }));
|
|
37670
|
+
workersCmd.command("catalog").summary("Show the canonical worker catalog with defaults").description(`Print the shared worker catalog \u2014 every known worker and its default
|
|
37671
|
+
enabled flag. This is the source of truth used when seeding missing workers
|
|
37672
|
+
on enable.
|
|
37673
|
+
|
|
37674
|
+
EXAMPLES:
|
|
37675
|
+
hoox workers catalog
|
|
37676
|
+
hoox workers catalog --json`).action(withErrorHandling(async (_opts, cmd) => {
|
|
37677
|
+
const fmt = getFormatOptions(cmd);
|
|
37678
|
+
doCatalog(fmt);
|
|
37679
|
+
}, { service: "workers" }));
|
|
37680
|
+
workersCmd.command("enable").argument("<names...>", "Worker name(s) to enable").summary("Enable one or more workers in wrangler.jsonc").description(`Set workers.<name>.enabled = true in the root wrangler.jsonc.
|
|
37681
|
+
|
|
37682
|
+
If a worker exists in the catalog but not in config, it is seeded with
|
|
37683
|
+
path/secrets from the catalog and enabled.
|
|
37684
|
+
|
|
37685
|
+
ARGUMENTS:
|
|
37686
|
+
names One or more worker names (e.g. trade-worker email-worker)
|
|
37687
|
+
|
|
37688
|
+
EXAMPLES:
|
|
37689
|
+
hoox workers enable trade-worker
|
|
37690
|
+
hoox workers enable report-worker web3-wallet-worker
|
|
37691
|
+
hoox workers enable dashboard --json`).action(withErrorHandling(async (names, _opts, cmd) => {
|
|
37692
|
+
const fmt = getFormatOptions(cmd);
|
|
37693
|
+
await doSetEnabled(names, true, fmt);
|
|
37694
|
+
}, { service: "workers" }));
|
|
37695
|
+
workersCmd.command("disable").argument("<names...>", "Worker name(s) to disable").summary("Disable one or more workers in wrangler.jsonc").description(`Set workers.<name>.enabled = false in the root wrangler.jsonc.
|
|
37696
|
+
|
|
37697
|
+
Disabled workers are skipped by deploy/logs/all flows that use
|
|
37698
|
+
ConfigService.listEnabledWorkers().
|
|
37699
|
+
|
|
37700
|
+
ARGUMENTS:
|
|
37701
|
+
names One or more worker names
|
|
37702
|
+
|
|
37703
|
+
EXAMPLES:
|
|
37704
|
+
hoox workers disable email-worker
|
|
37705
|
+
hoox workers disable web3-wallet-worker report-worker`).action(withErrorHandling(async (names, _opts, cmd) => {
|
|
37706
|
+
const fmt = getFormatOptions(cmd);
|
|
37707
|
+
await doSetEnabled(names, false, fmt);
|
|
37708
|
+
}, { service: "workers" }));
|
|
37376
37709
|
workersCmd.command("dev <name>").summary("Start a single worker for local development").description(`Start a specific worker for local development by running \`hoox dev worker <name>\` in-process.
|
|
37377
37710
|
|
|
37378
37711
|
ARGUMENTS:
|
|
@@ -37918,10 +38251,10 @@ import { existsSync as existsSync12, realpathSync } from "fs";
|
|
|
37918
38251
|
import { homedir as homedir4 } from "os";
|
|
37919
38252
|
|
|
37920
38253
|
// src/services/perf/endpoint-resolver.ts
|
|
37921
|
-
import { readFileSync as
|
|
38254
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
37922
38255
|
function readSubdomainPrefix() {
|
|
37923
38256
|
try {
|
|
37924
|
-
const raw =
|
|
38257
|
+
const raw = readFileSync9("wrangler.jsonc", "utf8");
|
|
37925
38258
|
const stripped = raw.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "");
|
|
37926
38259
|
const parsed = JSON.parse(stripped);
|
|
37927
38260
|
const prefix = parsed.global?.subdomain_prefix;
|
|
@@ -38965,7 +39298,7 @@ function registerDisclaimerCommand(program2) {
|
|
|
38965
39298
|
}));
|
|
38966
39299
|
}
|
|
38967
39300
|
// src/commands/agent/agent-command.ts
|
|
38968
|
-
import { readFileSync as
|
|
39301
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
38969
39302
|
init_errors4();
|
|
38970
39303
|
var PROVIDERS = [
|
|
38971
39304
|
{
|
|
@@ -38999,7 +39332,7 @@ function checkDevVars() {
|
|
|
38999
39332
|
const candidates = ["workers/agent-worker/.dev.vars", ".dev.vars"];
|
|
39000
39333
|
for (const filePath of candidates) {
|
|
39001
39334
|
try {
|
|
39002
|
-
const content =
|
|
39335
|
+
const content = readFileSync10(filePath, "utf-8");
|
|
39003
39336
|
for (const line of content.split(`
|
|
39004
39337
|
`)) {
|
|
39005
39338
|
const trimmed = line.trim();
|
|
@@ -39530,7 +39863,7 @@ EXAMPLES:
|
|
|
39530
39863
|
}
|
|
39531
39864
|
// src/commands/pyne/pyne-command.ts
|
|
39532
39865
|
init_config2();
|
|
39533
|
-
import { existsSync as existsSync14, readFileSync as
|
|
39866
|
+
import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
|
|
39534
39867
|
import { resolve as resolve8 } from "path";
|
|
39535
39868
|
init_errors4();
|
|
39536
39869
|
var DEFAULT_TIMEOUT_MS = 30000;
|
|
@@ -39556,7 +39889,7 @@ function loadDevVars(workerDir) {
|
|
|
39556
39889
|
try {
|
|
39557
39890
|
if (!existsSync14(filePath))
|
|
39558
39891
|
continue;
|
|
39559
|
-
const content =
|
|
39892
|
+
const content = readFileSync11(filePath, "utf-8");
|
|
39560
39893
|
for (const line of content.split(`
|
|
39561
39894
|
`)) {
|
|
39562
39895
|
const trimmed = line.trim();
|
|
@@ -39775,7 +40108,7 @@ EXAMPLES:
|
|
|
39775
40108
|
if (!existsSync14(abs)) {
|
|
39776
40109
|
throw new CLIError(`Script not found: ${abs}`, 1 /* ERROR */);
|
|
39777
40110
|
}
|
|
39778
|
-
body.script =
|
|
40111
|
+
body.script = readFileSync11(abs, "utf-8");
|
|
39779
40112
|
}
|
|
39780
40113
|
const res = await pyneFetch(baseUrl, "/run", {
|
|
39781
40114
|
method: "POST",
|
|
@@ -39826,7 +40159,7 @@ EXAMPLES:
|
|
|
39826
40159
|
if (!existsSync14(abs)) {
|
|
39827
40160
|
throw new CLIError(`Script not found: ${abs}`, 1 /* ERROR */);
|
|
39828
40161
|
}
|
|
39829
|
-
const script =
|
|
40162
|
+
const script = readFileSync11(abs, "utf-8");
|
|
39830
40163
|
const baseName = abs.split(/[/\\]/).pop() ?? "script.pine";
|
|
39831
40164
|
const scriptId = opts.id ?? baseName.replace(/\.pine$/i, "").replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
39832
40165
|
const res = await pyneFetch(baseUrl, "/scripts", {
|
|
@@ -40189,15 +40522,21 @@ function parseTime(input) {
|
|
|
40189
40522
|
return;
|
|
40190
40523
|
const relativeMatch = input.match(/^(\d+)([smhd])$/);
|
|
40191
40524
|
if (relativeMatch) {
|
|
40192
|
-
const
|
|
40525
|
+
const rawValue = relativeMatch[1];
|
|
40193
40526
|
const unit = relativeMatch[2];
|
|
40527
|
+
if (!rawValue || !unit)
|
|
40528
|
+
return;
|
|
40529
|
+
const value = parseInt(rawValue, 10);
|
|
40194
40530
|
const multipliers = {
|
|
40195
40531
|
s: 1000,
|
|
40196
40532
|
m: 60 * 1000,
|
|
40197
40533
|
h: 60 * 60 * 1000,
|
|
40198
40534
|
d: 24 * 60 * 60 * 1000
|
|
40199
40535
|
};
|
|
40200
|
-
|
|
40536
|
+
const mult = multipliers[unit];
|
|
40537
|
+
if (mult === undefined)
|
|
40538
|
+
return;
|
|
40539
|
+
return Date.now() - value * mult;
|
|
40201
40540
|
}
|
|
40202
40541
|
const ms = new Date(input).getTime();
|
|
40203
40542
|
return Number.isFinite(ms) ? ms : undefined;
|
|
@@ -41489,7 +41828,7 @@ function registerCompletionCommand(program2) {
|
|
|
41489
41828
|
// src/ui/banner.ts
|
|
41490
41829
|
init_ansis();
|
|
41491
41830
|
init_theme();
|
|
41492
|
-
import { existsSync as existsSync15, readFileSync as
|
|
41831
|
+
import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
|
|
41493
41832
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
41494
41833
|
import { dirname as dirname4, join as join13 } from "path";
|
|
41495
41834
|
var ORANGE = ansis_default.hex("#ff7f2a");
|
|
@@ -41507,7 +41846,7 @@ function findCliVersion() {
|
|
|
41507
41846
|
const pkgPath = join13(dir, "package.json");
|
|
41508
41847
|
if (existsSync15(pkgPath)) {
|
|
41509
41848
|
try {
|
|
41510
|
-
const pkg = JSON.parse(
|
|
41849
|
+
const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
|
|
41511
41850
|
if (pkg.name === PKG_NAME)
|
|
41512
41851
|
return pkg.version;
|
|
41513
41852
|
} catch {}
|
|
@@ -42142,7 +42481,7 @@ if (typeof Bun === "undefined") {
|
|
|
42142
42481
|
`);
|
|
42143
42482
|
process.exit(1);
|
|
42144
42483
|
}
|
|
42145
|
-
var pkgVersion = JSON.parse(
|
|
42484
|
+
var pkgVersion = JSON.parse(readFileSync13(new URL("../package.json", import.meta.url), "utf-8")).version;
|
|
42146
42485
|
var program2 = new Command;
|
|
42147
42486
|
program2.name("hoox").description("Hoox CLI \u2014 manage Cloudflare Workers, infrastructure, secrets, and deployments").version(`${pkgVersion}
|
|
42148
42487
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hoox-sh/hoox-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Hoox CLI — manage Cloudflare Workers, infrastructure, secrets, and deployments (@hoox-sh/hoox-cli)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@hoox-sh/hoox-tui": "workspace:*"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@hoox-sh/hoox-shared": "^1.
|
|
29
|
+
"@hoox-sh/hoox-shared": "^1.4.0",
|
|
30
30
|
"@types/node": "^26.1.1",
|
|
31
31
|
"bun-types": "^1.3.14",
|
|
32
32
|
"typescript": "^6.0.3"
|