@jango-blockchained/hoox-shared 1.0.8 → 1.1.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 +17 -0
- package/dist/analytics.d.ts +23 -2
- package/dist/analytics.d.ts.map +1 -1
- package/dist/analytics.js +14 -3
- package/dist/api-client.d.ts +12 -2
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +74 -7
- package/dist/colors.d.ts +63 -25
- package/dist/colors.d.ts.map +1 -1
- package/dist/colors.js +60 -20
- package/dist/config.d.ts +34 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +61 -6
- package/dist/cron-handler.d.ts +34 -0
- package/dist/cron-handler.d.ts.map +1 -0
- package/dist/cron-handler.js +48 -0
- package/dist/d1/index.js +50 -6
- package/dist/d1/repository.d.ts +5 -0
- package/dist/d1/repository.d.ts.map +1 -1
- package/dist/d1/repository.js +297 -0
- package/dist/d1/schemas.js +81 -0
- package/dist/errors.d.ts +1 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +48 -5
- package/dist/exchanges/base-exchange-client.d.ts +68 -0
- package/dist/exchanges/base-exchange-client.d.ts.map +1 -0
- package/dist/exchanges/base-exchange-client.js +120 -0
- package/dist/exchanges/index.d.ts +3 -0
- package/dist/exchanges/index.d.ts.map +1 -0
- package/dist/exchanges/index.js +120 -0
- package/dist/exchanges/types.d.ts +19 -0
- package/dist/exchanges/types.d.ts.map +1 -0
- package/dist/exchanges/types.js +1 -0
- package/dist/health.js +48 -5
- package/dist/index.d.ts +30 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1058 -73
- package/dist/kvUtils.js +48 -5
- package/dist/middleware/auth.d.ts +46 -7
- package/dist/middleware/auth.d.ts.map +1 -1
- package/dist/middleware/auth.js +151 -0
- package/dist/middleware/cors.d.ts +28 -2
- package/dist/middleware/cors.d.ts.map +1 -1
- package/dist/middleware/cors.js +77 -0
- package/dist/middleware/index.d.ts +2 -2
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +361 -101
- package/dist/middleware/logger.d.ts +2 -1
- package/dist/middleware/logger.d.ts.map +1 -1
- package/dist/middleware/logger.js +202 -0
- package/dist/middleware/rate-limit.d.ts +3 -1
- package/dist/middleware/rate-limit.d.ts.map +1 -1
- package/dist/middleware/rate-limit.js +181 -0
- package/dist/middleware/security-headers.js +58 -0
- package/dist/middleware/validate.js +56 -0
- package/dist/operator-transport.d.ts +61 -0
- package/dist/operator-transport.d.ts.map +1 -0
- package/dist/operator-transport.js +87 -0
- package/dist/path-utils.d.ts +205 -0
- package/dist/path-utils.d.ts.map +1 -0
- package/dist/path-utils.js +188 -0
- package/dist/queue-handler.d.ts +43 -0
- package/dist/queue-handler.d.ts.map +1 -0
- package/dist/queue-handler.js +46 -0
- package/dist/router.d.ts +2 -2
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +15 -8
- package/dist/schemas/index.js +7 -4
- package/dist/schemas/registry.js +387 -0
- package/dist/schemas/types.js +1 -0
- package/dist/schemas/validators.d.ts.map +1 -1
- package/dist/schemas/validators.js +290 -0
- package/dist/service-bindings.d.ts +68 -26
- package/dist/service-bindings.d.ts.map +1 -1
- package/dist/service-bindings.js +219 -2
- package/dist/session.d.ts +9 -5
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +179 -4
- package/dist/sse.d.ts +12 -3
- package/dist/sse.d.ts.map +1 -1
- package/dist/sse.js +70 -7
- package/dist/stores/config-store.d.ts.map +1 -1
- package/dist/stores/config-store.js +129 -6
- package/dist/stores/service-store.d.ts +50 -1
- package/dist/stores/service-store.d.ts.map +1 -1
- package/dist/stores/service-store.js +162 -27
- package/dist/test-utils.d.ts +132 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +128 -0
- package/dist/types/router.d.ts +18 -8
- package/dist/types/router.d.ts.map +1 -1
- package/dist/types.d.ts +124 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +11 -0
- package/dist/wizard/engine.d.ts.map +1 -1
- package/dist/wizard/engine.js +501 -0
- package/dist/wizard/index.js +2 -1
- package/dist/wizard/persistence.js +31 -0
- package/dist/wizard/presets.js +199 -0
- package/dist/wizard/provisioner.js +1 -0
- package/dist/wizard/types.js +1 -0
- package/package.json +46 -12
package/dist/sse.js
CHANGED
|
@@ -15,22 +15,86 @@ var __export = (target, all) => {
|
|
|
15
15
|
};
|
|
16
16
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
17
|
|
|
18
|
+
// src/operator-transport.ts
|
|
19
|
+
function stripTrailingSlashes(url) {
|
|
20
|
+
return url.replace(/\/+$/, "");
|
|
21
|
+
}
|
|
22
|
+
function parseTransport(raw) {
|
|
23
|
+
if (!raw)
|
|
24
|
+
return null;
|
|
25
|
+
const v = raw.trim().toLowerCase();
|
|
26
|
+
if (VALID_TRANSPORTS.has(v)) {
|
|
27
|
+
return v;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
function resolveOperatorTransportProfile(env = process.env, options = {}) {
|
|
32
|
+
const accessClientId = env.CF_ACCESS_CLIENT_ID?.trim() ?? "";
|
|
33
|
+
const accessClientSecret = env.CF_ACCESS_CLIENT_SECRET?.trim() ?? "";
|
|
34
|
+
const hasAccess = Boolean(accessClientId && accessClientSecret);
|
|
35
|
+
const explicit = parseTransport(env.HOOX_TRANSPORT) ?? parseTransport(options.configTransport);
|
|
36
|
+
const transport = explicit ?? (hasAccess ? "access" : "public");
|
|
37
|
+
const apiFromEnv = env.HOOX_API_URL?.trim();
|
|
38
|
+
const apiFromConfig = options.configApiUrl?.trim();
|
|
39
|
+
const tokenFromEnv = env.HOOX_API_TOKEN?.trim();
|
|
40
|
+
const tokenFromConfig = options.configApiToken?.trim();
|
|
41
|
+
return {
|
|
42
|
+
transport,
|
|
43
|
+
apiBase: stripTrailingSlashes(apiFromEnv || apiFromConfig || DEFAULT_API_BASE),
|
|
44
|
+
bearerToken: tokenFromEnv || tokenFromConfig || "",
|
|
45
|
+
accessClientId,
|
|
46
|
+
accessClientSecret
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function buildOperatorAuthHeaders(profile) {
|
|
50
|
+
const headers = {};
|
|
51
|
+
if (profile.bearerToken) {
|
|
52
|
+
headers.Authorization = `Bearer ${profile.bearerToken}`;
|
|
53
|
+
}
|
|
54
|
+
const useAccessHeaders = profile.transport === "access" || Boolean(profile.accessClientId) && Boolean(profile.accessClientSecret);
|
|
55
|
+
if (useAccessHeaders && profile.accessClientId && profile.accessClientSecret) {
|
|
56
|
+
headers["CF-Access-Client-Id"] = profile.accessClientId;
|
|
57
|
+
headers["CF-Access-Client-Secret"] = profile.accessClientSecret;
|
|
58
|
+
}
|
|
59
|
+
return headers;
|
|
60
|
+
}
|
|
61
|
+
function hasOperatorClientCredentials(profile) {
|
|
62
|
+
if (profile.bearerToken)
|
|
63
|
+
return true;
|
|
64
|
+
return Boolean(profile.accessClientId && profile.accessClientSecret);
|
|
65
|
+
}
|
|
66
|
+
function operatorUrl(profile, path) {
|
|
67
|
+
const base = profile.apiBase.replace(/\/+$/, "");
|
|
68
|
+
const p = path.startsWith("/") ? path : `/${path}`;
|
|
69
|
+
return `${base}${p}`;
|
|
70
|
+
}
|
|
71
|
+
var DEFAULT_API_BASE = "http://localhost:8787", VALID_TRANSPORTS;
|
|
72
|
+
var init_operator_transport = __esm(() => {
|
|
73
|
+
VALID_TRANSPORTS = new Set([
|
|
74
|
+
"public",
|
|
75
|
+
"access",
|
|
76
|
+
"mtls",
|
|
77
|
+
"tunnel"
|
|
78
|
+
]);
|
|
79
|
+
});
|
|
80
|
+
|
|
18
81
|
// src/sse.ts
|
|
19
82
|
var exports_sse = {};
|
|
20
83
|
__export(exports_sse, {
|
|
21
84
|
subscribeSSE: () => subscribeSSE
|
|
22
85
|
});
|
|
23
|
-
function subscribeSSE(path, callback, onStatus) {
|
|
86
|
+
function subscribeSSE(path, callback, onStatus, options) {
|
|
24
87
|
let aborted = false;
|
|
88
|
+
const profile = options?.transport ?? (options?.transportEnv ? resolveOperatorTransportProfile(options.transportEnv) : resolveOperatorTransportProfile());
|
|
25
89
|
const run = async () => {
|
|
26
90
|
let attempt = 0;
|
|
27
91
|
while (!aborted && attempt < MAX_RECONNECT_ATTEMPTS) {
|
|
28
92
|
try {
|
|
29
|
-
const url =
|
|
93
|
+
const url = operatorUrl(profile, path);
|
|
30
94
|
const response = await fetch(url, {
|
|
31
95
|
headers: {
|
|
32
96
|
Accept: "text/event-stream",
|
|
33
|
-
...
|
|
97
|
+
...buildOperatorAuthHeaders(profile)
|
|
34
98
|
}
|
|
35
99
|
});
|
|
36
100
|
if (!response.ok || !response.body) {
|
|
@@ -59,7 +123,7 @@ function subscribeSSE(path, callback, onStatus) {
|
|
|
59
123
|
}
|
|
60
124
|
}
|
|
61
125
|
}
|
|
62
|
-
} catch
|
|
126
|
+
} catch {
|
|
63
127
|
if (aborted)
|
|
64
128
|
break;
|
|
65
129
|
onStatus?.("reconnecting");
|
|
@@ -79,10 +143,9 @@ function subscribeSSE(path, callback, onStatus) {
|
|
|
79
143
|
}
|
|
80
144
|
};
|
|
81
145
|
}
|
|
82
|
-
var
|
|
146
|
+
var RECONNECT_BASE_MS = 1000, RECONNECT_MAX_MS = 16000, MAX_RECONNECT_ATTEMPTS = 10;
|
|
83
147
|
var init_sse = __esm(() => {
|
|
84
|
-
|
|
85
|
-
API_TOKEN = process.env.HOOX_API_TOKEN || "";
|
|
148
|
+
init_operator_transport();
|
|
86
149
|
});
|
|
87
150
|
init_sse();
|
|
88
151
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../../src/stores/config-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config-store.d.ts","sourceRoot":"","sources":["../../src/stores/config-store.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAoF3E,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,UAAU,EAAE,SAAS,CAAC;IACtB,aAAa,EAAE,uBAAuB,CAAC;IACvC,YAAY,EAAE,OAAO,CAAC;CACvB;AAID,UAAU,aAAa;IACrB,+DAA+D;IAC/D,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACtD,8CAA8C;IAC9C,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,yCAAyC;IACzC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,8CAA8C;IAC9C,kBAAkB,EAAE,CAAC,OAAO,EAAE,MAAM,uBAAuB,KAAK,IAAI,CAAC;CACtE;AAiBD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;eAtClB,MAAM,GAAG,OAAO;2BACJ,MAAM;qBACZ,MAAM;;;;;;;;;;;;;;;;sBAKL,OAAO;sBAOP,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI;uBAEtC,MAAM,IAAI;qBAEZ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI;4BAE9B,CAAC,OAAO,EAAE,MAAM,uBAAuB,KAAK,IAAI;;;eApB7D,MAAM,GAAG,OAAO;2BACJ,MAAM;qBACZ,MAAM;;;;;;;;;;;;;;;;sBAKL,OAAO;sBAOP,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI;uBAEtC,MAAM,IAAI;qBAEZ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI;4BAE9B,CAAC,OAAO,EAAE,MAAM,uBAAuB,KAAK,IAAI;;EA+ErE,CAAC"}
|
|
@@ -15,16 +15,133 @@ var __export = (target, all) => {
|
|
|
15
15
|
};
|
|
16
16
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
17
|
|
|
18
|
+
// src/config.ts
|
|
19
|
+
import {
|
|
20
|
+
readFileSync,
|
|
21
|
+
writeFileSync,
|
|
22
|
+
existsSync,
|
|
23
|
+
mkdirSync,
|
|
24
|
+
chmodSync,
|
|
25
|
+
statSync
|
|
26
|
+
} from "fs";
|
|
27
|
+
import { join } from "path";
|
|
28
|
+
import { homedir } from "os";
|
|
29
|
+
var HOX_DIR = join(homedir(), ".hoox");
|
|
30
|
+
var CONFIG_PATH = join(HOX_DIR, "config.json");
|
|
31
|
+
var HOOX_DIR_MODE = 448;
|
|
32
|
+
var HOOX_CONFIG_FILE_MODE = 384;
|
|
33
|
+
var DEFAULT_CONFIG = {
|
|
34
|
+
apiUrl: "http://localhost:8787",
|
|
35
|
+
apiToken: "",
|
|
36
|
+
transport: "public",
|
|
37
|
+
refreshIntervalMs: 500,
|
|
38
|
+
theme: "dark",
|
|
39
|
+
activeExchanges: ["binance", "bybit", "mexc"],
|
|
40
|
+
notifications: {
|
|
41
|
+
alerts: true,
|
|
42
|
+
trades: true,
|
|
43
|
+
debug: false,
|
|
44
|
+
system: true
|
|
45
|
+
},
|
|
46
|
+
soundEnabled: true,
|
|
47
|
+
defaultView: "dashboard"
|
|
48
|
+
};
|
|
49
|
+
function readConfigSync() {
|
|
50
|
+
const envConfig = {
|
|
51
|
+
apiUrl: process.env.HOOX_API_URL,
|
|
52
|
+
apiToken: process.env.HOOX_API_TOKEN
|
|
53
|
+
};
|
|
54
|
+
let fileConfig = {};
|
|
55
|
+
try {
|
|
56
|
+
if (existsSync(CONFIG_PATH)) {
|
|
57
|
+
fileConfig = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
58
|
+
}
|
|
59
|
+
} catch {}
|
|
60
|
+
return {
|
|
61
|
+
...DEFAULT_CONFIG,
|
|
62
|
+
...fileConfig,
|
|
63
|
+
...Object.fromEntries(Object.entries(envConfig).filter(([_, v]) => v !== undefined))
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
async function readConfig() {
|
|
67
|
+
return readConfigSync();
|
|
68
|
+
}
|
|
69
|
+
function ensureHooxDirSecure(dir = HOX_DIR) {
|
|
70
|
+
if (!existsSync(dir)) {
|
|
71
|
+
mkdirSync(dir, { recursive: true, mode: HOOX_DIR_MODE });
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
chmodSync(dir, HOOX_DIR_MODE);
|
|
75
|
+
} catch {}
|
|
76
|
+
}
|
|
77
|
+
function writeSecureFileSync(filePath, contents, mode = HOOX_CONFIG_FILE_MODE) {
|
|
78
|
+
writeFileSync(filePath, contents, { encoding: "utf-8", mode });
|
|
79
|
+
try {
|
|
80
|
+
chmodSync(filePath, mode);
|
|
81
|
+
} catch {}
|
|
82
|
+
}
|
|
83
|
+
function isUnixModeGroupOrWorldAccessible(mode) {
|
|
84
|
+
return (mode & 63) !== 0;
|
|
85
|
+
}
|
|
86
|
+
function isConfigWorldOrGroupReadable(filePath = CONFIG_PATH) {
|
|
87
|
+
try {
|
|
88
|
+
if (!existsSync(filePath))
|
|
89
|
+
return false;
|
|
90
|
+
return isUnixModeGroupOrWorldAccessible(statSync(filePath).mode & 511);
|
|
91
|
+
} catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function formatConfigPermissionWarning(filePath = CONFIG_PATH) {
|
|
96
|
+
if (!isConfigWorldOrGroupReadable(filePath))
|
|
97
|
+
return null;
|
|
98
|
+
return `Warning: ${filePath} is group/world-accessible. ` + `Run: chmod 600 ${filePath} (and chmod 700 on the parent dir). ` + `This file may contain apiToken / operator secrets.`;
|
|
99
|
+
}
|
|
100
|
+
function writeConfigSync(config) {
|
|
101
|
+
try {
|
|
102
|
+
ensureHooxDirSecure(HOX_DIR);
|
|
103
|
+
writeSecureFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), HOOX_CONFIG_FILE_MODE);
|
|
104
|
+
} catch (err) {
|
|
105
|
+
console.error("Failed to write config:", err);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async function writeConfig(config) {
|
|
109
|
+
writeConfigSync(config);
|
|
110
|
+
}
|
|
111
|
+
var VALID_TRANSPORTS = new Set([
|
|
112
|
+
"public",
|
|
113
|
+
"access",
|
|
114
|
+
"mtls",
|
|
115
|
+
"tunnel"
|
|
116
|
+
]);
|
|
117
|
+
function validateConfig(config) {
|
|
118
|
+
const errors = [];
|
|
119
|
+
if (config.apiUrl && !config.apiUrl.startsWith("http")) {
|
|
120
|
+
errors.push("apiUrl must start with http:// or https://");
|
|
121
|
+
}
|
|
122
|
+
if (config.refreshIntervalMs !== undefined && config.refreshIntervalMs < 100) {
|
|
123
|
+
errors.push("refreshIntervalMs must be >= 100ms");
|
|
124
|
+
}
|
|
125
|
+
if (config.theme && !["dark", "light"].includes(config.theme)) {
|
|
126
|
+
errors.push('theme must be "dark" or "light"');
|
|
127
|
+
}
|
|
128
|
+
if (config.transport !== undefined && !VALID_TRANSPORTS.has(config.transport)) {
|
|
129
|
+
errors.push('transport must be "public" | "access" | "mtls" | "tunnel"');
|
|
130
|
+
}
|
|
131
|
+
return errors;
|
|
132
|
+
}
|
|
133
|
+
|
|
18
134
|
// src/stores/config-store.ts
|
|
19
135
|
import { create } from "zustand";
|
|
20
136
|
import { immer } from "zustand/middleware/immer";
|
|
21
137
|
import { persist, createJSONStorage } from "zustand/middleware";
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
138
|
+
import { chmodSync as chmodSync2, mkdirSync as mkdirSync2, existsSync as existsSync2 } from "fs";
|
|
139
|
+
import { homedir as homedir2 } from "os";
|
|
140
|
+
import { join as join2 } from "path";
|
|
24
141
|
var bunConfigStorage = {
|
|
25
142
|
getItem: async (_name) => {
|
|
26
143
|
try {
|
|
27
|
-
const file = Bun.file(
|
|
144
|
+
const file = Bun.file(join2(homedir2(), ".hoox", "config.json"));
|
|
28
145
|
const exists = await file.exists();
|
|
29
146
|
if (!exists)
|
|
30
147
|
return null;
|
|
@@ -34,12 +151,18 @@ var bunConfigStorage = {
|
|
|
34
151
|
}
|
|
35
152
|
},
|
|
36
153
|
setItem: async (_name, value) => {
|
|
37
|
-
const dir =
|
|
154
|
+
const dir = join2(homedir2(), ".hoox");
|
|
155
|
+
if (!existsSync2(dir)) {
|
|
156
|
+
mkdirSync2(dir, { recursive: true, mode: HOOX_DIR_MODE });
|
|
157
|
+
}
|
|
38
158
|
try {
|
|
39
|
-
|
|
159
|
+
chmodSync2(dir, HOOX_DIR_MODE);
|
|
40
160
|
} catch {}
|
|
41
|
-
const filePath =
|
|
161
|
+
const filePath = join2(dir, "config.json");
|
|
42
162
|
await Bun.write(filePath, value);
|
|
163
|
+
try {
|
|
164
|
+
chmodSync2(filePath, HOOX_CONFIG_FILE_MODE);
|
|
165
|
+
} catch {}
|
|
43
166
|
},
|
|
44
167
|
removeItem: async (_name) => {}
|
|
45
168
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { WorkerInfo, Trade, Alert, LogEntry, SystemMetrics, ConnectionStatus } from "../types";
|
|
1
|
+
import type { WorkerInfo, Trade, Alert, LogEntry, SystemMetrics, ConnectionStatus, CliErrorDetails } from "../types";
|
|
2
2
|
export interface ServiceState {
|
|
3
3
|
workers: WorkerInfo[];
|
|
4
4
|
tradeStream: Trade[];
|
|
@@ -12,6 +12,13 @@ export interface ServiceState {
|
|
|
12
12
|
retryCount: number;
|
|
13
13
|
/** Last connection error message (for display) */
|
|
14
14
|
lastError: string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Structured CLI bridge error details. Populated when a `hoox` command
|
|
17
|
+
* fails so the status bar can render the full diagnostic context
|
|
18
|
+
* (command, exit code, stderr, error type) — not just a one-line summary.
|
|
19
|
+
* Cleared together with `lastError` on success or retry reset.
|
|
20
|
+
*/
|
|
21
|
+
lastErrorDetails: CliErrorDetails | null;
|
|
15
22
|
/** Timestamp (ms) of the last successful API fetch */
|
|
16
23
|
lastSuccessfulFetch: number;
|
|
17
24
|
/** Current backoff delay in ms (0 when not reconnecting) */
|
|
@@ -39,6 +46,24 @@ interface ServiceActions {
|
|
|
39
46
|
resetRetries: () => void;
|
|
40
47
|
/** Force a connection retry from offline state */
|
|
41
48
|
forceRetry: () => void;
|
|
49
|
+
/**
|
|
50
|
+
* Record a structured CLI bridge failure. Stores both the short
|
|
51
|
+
* `lastError` string (for the one-line summary) and the full
|
|
52
|
+
* `lastErrorDetails` (for click-to-expand). Pass `null` to clear.
|
|
53
|
+
*/
|
|
54
|
+
setLastErrorDetails: (details: CliErrorDetails | null) => void;
|
|
55
|
+
/**
|
|
56
|
+
* Clear the last error and last error details. Convenience alias for
|
|
57
|
+
* `setLastErrorDetails(null)` — clearer at call sites where the
|
|
58
|
+
* intent is to acknowledge an error rather than record a new one.
|
|
59
|
+
*/
|
|
60
|
+
clearError: () => void;
|
|
61
|
+
/**
|
|
62
|
+
* Record a CLI bridge failure **and** add a matching high-severity
|
|
63
|
+
* alert to the alerts ring buffer. Use this when a failure should
|
|
64
|
+
* also be visible in the alerts panel (not just the status bar).
|
|
65
|
+
*/
|
|
66
|
+
addCliErrorAlert: (details: CliErrorDetails) => void;
|
|
42
67
|
}
|
|
43
68
|
export declare const useServiceStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<ServiceState & ServiceActions>, "setState"> & {
|
|
44
69
|
setState(nextStateOrUpdater: (ServiceState & ServiceActions) | Partial<ServiceState & ServiceActions> | ((state: {
|
|
@@ -102,6 +127,15 @@ export declare const useServiceStore: import("zustand").UseBoundStore<Omit<impor
|
|
|
102
127
|
selectedWorkerId: string | null;
|
|
103
128
|
retryCount: number;
|
|
104
129
|
lastError: string | null;
|
|
130
|
+
lastErrorDetails: {
|
|
131
|
+
command: string;
|
|
132
|
+
exitCode: number;
|
|
133
|
+
stderr: string;
|
|
134
|
+
stdout: string;
|
|
135
|
+
errorType: import("..").CliErrorType;
|
|
136
|
+
timestamp: number;
|
|
137
|
+
duration: number;
|
|
138
|
+
} | null;
|
|
105
139
|
lastSuccessfulFetch: number;
|
|
106
140
|
reconnectDelay: number;
|
|
107
141
|
disconnectedAt: number | null;
|
|
@@ -120,6 +154,9 @@ export declare const useServiceStore: import("zustand").UseBoundStore<Omit<impor
|
|
|
120
154
|
handleConnectionFailure: (errorMessage: string) => void;
|
|
121
155
|
resetRetries: () => void;
|
|
122
156
|
forceRetry: () => void;
|
|
157
|
+
setLastErrorDetails: (details: CliErrorDetails | null) => void;
|
|
158
|
+
clearError: () => void;
|
|
159
|
+
addCliErrorAlert: (details: CliErrorDetails) => void;
|
|
123
160
|
}) => void), shouldReplace?: false): void;
|
|
124
161
|
setState(nextStateOrUpdater: (ServiceState & ServiceActions) | ((state: {
|
|
125
162
|
workers: {
|
|
@@ -182,6 +219,15 @@ export declare const useServiceStore: import("zustand").UseBoundStore<Omit<impor
|
|
|
182
219
|
selectedWorkerId: string | null;
|
|
183
220
|
retryCount: number;
|
|
184
221
|
lastError: string | null;
|
|
222
|
+
lastErrorDetails: {
|
|
223
|
+
command: string;
|
|
224
|
+
exitCode: number;
|
|
225
|
+
stderr: string;
|
|
226
|
+
stdout: string;
|
|
227
|
+
errorType: import("..").CliErrorType;
|
|
228
|
+
timestamp: number;
|
|
229
|
+
duration: number;
|
|
230
|
+
} | null;
|
|
185
231
|
lastSuccessfulFetch: number;
|
|
186
232
|
reconnectDelay: number;
|
|
187
233
|
disconnectedAt: number | null;
|
|
@@ -200,6 +246,9 @@ export declare const useServiceStore: import("zustand").UseBoundStore<Omit<impor
|
|
|
200
246
|
handleConnectionFailure: (errorMessage: string) => void;
|
|
201
247
|
resetRetries: () => void;
|
|
202
248
|
forceRetry: () => void;
|
|
249
|
+
setLastErrorDetails: (details: CliErrorDetails | null) => void;
|
|
250
|
+
clearError: () => void;
|
|
251
|
+
addCliErrorAlert: (details: CliErrorDetails) => void;
|
|
203
252
|
}) => void), shouldReplace: true): void;
|
|
204
253
|
}>;
|
|
205
254
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service-store.d.ts","sourceRoot":"","sources":["../../src/stores/service-store.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EACV,UAAU,EACV,KAAK,EACL,KAAK,EACL,QAAQ,EACR,aAAa,EACb,gBAAgB,
|
|
1
|
+
{"version":3,"file":"service-store.d.ts","sourceRoot":"","sources":["../../src/stores/service-store.ts"],"names":[],"mappings":"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"}
|