@tradejs/infra 3.1.8-beta.207 → 3.1.8-beta.210
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-JLVCBKE3.mjs → chunk-NN4CAPDW.mjs} +97 -5
- package/dist/redis.d.mts +10 -6
- package/dist/redis.d.ts +10 -6
- package/dist/redis.js +100 -5
- package/dist/redis.mjs +7 -1
- package/dist/runtimeControls.d.mts +28 -0
- package/dist/runtimeControls.d.ts +28 -0
- package/dist/{runtimeStrategyReleases.js → runtimeControls.js} +141 -266
- package/dist/runtimeControls.mjs +133 -0
- package/dist/runtimeHeartbeats.d.mts +6 -0
- package/dist/runtimeHeartbeats.d.ts +6 -0
- package/dist/{runtimeDeployments.js → runtimeHeartbeats.js} +12 -181
- package/dist/runtimeHeartbeats.mjs +37 -0
- package/dist/runtimeStrategyConfigs.js +1 -5
- package/dist/runtimeStrategyConfigs.mjs +1 -1
- package/dist/strategyReleaseEvidence.js +1 -1
- package/dist/strategyReleaseEvidence.mjs +1 -1
- package/dist/tradingAccounts.js +1 -5
- package/dist/tradingAccounts.mjs +1 -1
- package/dist/userSettings.js +1 -5
- package/dist/userSettings.mjs +1 -1
- package/package.json +10 -10
- package/dist/runtimeDeployments.d.mts +0 -11
- package/dist/runtimeDeployments.d.ts +0 -11
- package/dist/runtimeDeployments.mjs +0 -134
- package/dist/runtimeStrategyReleases.d.mts +0 -26
- package/dist/runtimeStrategyReleases.d.ts +0 -26
- package/dist/runtimeStrategyReleases.mjs +0 -196
|
@@ -27,18 +27,13 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
27
|
));
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
29
|
|
|
30
|
-
// src/
|
|
31
|
-
var
|
|
32
|
-
__export(
|
|
33
|
-
deleteRuntimeDeployment: () => deleteRuntimeDeployment,
|
|
34
|
-
getRuntimeDeployment: () => getRuntimeDeployment,
|
|
30
|
+
// src/runtimeHeartbeats.ts
|
|
31
|
+
var runtimeHeartbeats_exports = {};
|
|
32
|
+
__export(runtimeHeartbeats_exports, {
|
|
35
33
|
getRuntimeDeploymentHeartbeat: () => getRuntimeDeploymentHeartbeat,
|
|
36
|
-
|
|
37
|
-
saveRuntimeDeployment: () => saveRuntimeDeployment,
|
|
38
|
-
saveRuntimeDeploymentHeartbeat: () => saveRuntimeDeploymentHeartbeat,
|
|
39
|
-
verifyRuntimeDeployment: () => verifyRuntimeDeployment
|
|
34
|
+
saveRuntimeDeploymentHeartbeat: () => saveRuntimeDeploymentHeartbeat
|
|
40
35
|
});
|
|
41
|
-
module.exports = __toCommonJS(
|
|
36
|
+
module.exports = __toCommonJS(runtimeHeartbeats_exports);
|
|
42
37
|
|
|
43
38
|
// src/redis.ts
|
|
44
39
|
var import_ioredis = __toESM(require("ioredis"));
|
|
@@ -166,38 +161,6 @@ var parseJsonOrDeleteKey = async (redis, key, raw, fallback) => {
|
|
|
166
161
|
return fallback;
|
|
167
162
|
}
|
|
168
163
|
};
|
|
169
|
-
var getKeys = async (prefix) => {
|
|
170
|
-
if (redisUnavailable) return [];
|
|
171
|
-
const redis = await getReadyRedis();
|
|
172
|
-
if (!redis) return [];
|
|
173
|
-
const keys = [];
|
|
174
|
-
try {
|
|
175
|
-
let cursor = "0";
|
|
176
|
-
do {
|
|
177
|
-
const [nextCursor, batch] = await redis.scan(
|
|
178
|
-
cursor,
|
|
179
|
-
"MATCH",
|
|
180
|
-
`${prefix}*`,
|
|
181
|
-
"COUNT",
|
|
182
|
-
"200"
|
|
183
|
-
);
|
|
184
|
-
cursor = nextCursor;
|
|
185
|
-
for (const key of batch) {
|
|
186
|
-
if (key.startsWith(prefix)) {
|
|
187
|
-
keys.push(key);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
} while (cursor !== "0");
|
|
191
|
-
} catch (e) {
|
|
192
|
-
if (e instanceof Error && isRedisConnectivityError(e)) {
|
|
193
|
-
markRedisUnavailable(e);
|
|
194
|
-
return [];
|
|
195
|
-
}
|
|
196
|
-
logger.log("warn", "failed SCAN for %s: %s", prefix, String(e));
|
|
197
|
-
return [];
|
|
198
|
-
}
|
|
199
|
-
return keys;
|
|
200
|
-
};
|
|
201
164
|
var getData = async (key, fallback = []) => {
|
|
202
165
|
if (redisUnavailable) return fallback;
|
|
203
166
|
const redis = await getReadyRedis();
|
|
@@ -232,39 +195,6 @@ var getData = async (key, fallback = []) => {
|
|
|
232
195
|
return fallback;
|
|
233
196
|
}
|
|
234
197
|
};
|
|
235
|
-
var delKey = async (key) => {
|
|
236
|
-
return delKeyWithOptions(key);
|
|
237
|
-
};
|
|
238
|
-
var RedisWriteBlockedError = class extends Error {
|
|
239
|
-
constructor(message) {
|
|
240
|
-
super(message);
|
|
241
|
-
this.name = "RedisWriteBlockedError";
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
var delKeyWithOptions = async (key, options = {}) => {
|
|
245
|
-
if (redisUnavailable) return false;
|
|
246
|
-
const { raiseOnMisconf = false } = options;
|
|
247
|
-
const redis = await getReadyRedis();
|
|
248
|
-
if (!redis) return false;
|
|
249
|
-
try {
|
|
250
|
-
const result = await redis.del(key);
|
|
251
|
-
if (result === 1) {
|
|
252
|
-
return true;
|
|
253
|
-
}
|
|
254
|
-
return false;
|
|
255
|
-
} catch (e) {
|
|
256
|
-
if (e instanceof Error && isRedisConnectivityError(e)) {
|
|
257
|
-
markRedisUnavailable(e);
|
|
258
|
-
return false;
|
|
259
|
-
}
|
|
260
|
-
const msg = String(e);
|
|
261
|
-
if (raiseOnMisconf && msg.includes("MISCONF")) {
|
|
262
|
-
throw new RedisWriteBlockedError(msg);
|
|
263
|
-
}
|
|
264
|
-
logger.log("error", "failed DEL %s: %s", key, String(e));
|
|
265
|
-
return false;
|
|
266
|
-
}
|
|
267
|
-
};
|
|
268
198
|
var setData = async (key, data, options = {}) => {
|
|
269
199
|
if (redisUnavailable) return;
|
|
270
200
|
const { expire } = { ...DEFAULT_OPTIONS, ...options };
|
|
@@ -307,18 +237,14 @@ var redisKeys = {
|
|
|
307
237
|
user: (userName) => `users:index:${userName}`,
|
|
308
238
|
tradingAccounts: (userName) => `users:${userName}:trading-accounts:`,
|
|
309
239
|
tradingAccount: (userName, accountId) => `users:${userName}:trading-accounts:${accountId}`,
|
|
310
|
-
runtimeDeployments: (userName) => `users:${userName}:runtime:deployments:`,
|
|
311
|
-
runtimeDeployment: (userName, deploymentId) => `users:${userName}:runtime:deployments:${deploymentId}`,
|
|
312
240
|
runtimeDeploymentHeartbeat: (userName, deploymentId) => `users:${userName}:runtime:deployments:${deploymentId}:heartbeat`,
|
|
241
|
+
runtimeControls: (userName) => `users:${userName}:runtime:controls`,
|
|
313
242
|
bots: (userName) => `users:${userName}:bots`,
|
|
314
243
|
botsPrefix: () => "users:",
|
|
315
244
|
bot: (userName, botId) => `users:${userName}:bots:${botId}`,
|
|
316
245
|
backtestConfig: (userName, config) => `users:${userName}:backtests:configs:${config}`,
|
|
317
246
|
strategies: (userName) => `users:${userName}:strategies`,
|
|
318
247
|
strategyConfig: (userName, strategyName, configId = "config") => `users:${userName}:strategies:${strategyName}:${configId}`,
|
|
319
|
-
runtimeStrategyReleases: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:releases:`,
|
|
320
|
-
runtimeStrategyRelease: (userName, strategyName, releaseVersion) => `users:${userName}:strategies:${strategyName}:releases:${releaseVersion}`,
|
|
321
|
-
runtimeStrategyReleaseSequence: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:release-seq`,
|
|
322
248
|
runtimeStrategyControlEvents: (userName) => `users:${userName}:runtime:strategy-control-events:`,
|
|
323
249
|
runtimeStrategyControlEvent: (userName, eventId) => `users:${userName}:runtime:strategy-control-events:${eventId}`,
|
|
324
250
|
strategyResults: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:results`,
|
|
@@ -377,107 +303,17 @@ var redisKeys = {
|
|
|
377
303
|
mlResult: (strategyName, signalId) => `ml:${strategyName}:results:${signalId}`
|
|
378
304
|
};
|
|
379
305
|
|
|
380
|
-
// src/
|
|
381
|
-
var
|
|
306
|
+
// src/runtimeHeartbeats.ts
|
|
307
|
+
var normalizeDeploymentId = (value) => {
|
|
382
308
|
const normalized = value.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "-");
|
|
383
|
-
if (!normalized) throw new Error(
|
|
384
|
-
return normalized;
|
|
385
|
-
};
|
|
386
|
-
var DEPLOYMENT_KEYS = /* @__PURE__ */ new Set([
|
|
387
|
-
"id",
|
|
388
|
-
"label",
|
|
389
|
-
"connectorName",
|
|
390
|
-
"provider",
|
|
391
|
-
"accountId",
|
|
392
|
-
"enabled",
|
|
393
|
-
"strategies",
|
|
394
|
-
"assetClasses",
|
|
395
|
-
"tickers"
|
|
396
|
-
]);
|
|
397
|
-
var REFERENCE_KEYS = /* @__PURE__ */ new Set([
|
|
398
|
-
"strategyName",
|
|
399
|
-
"releaseVersion",
|
|
400
|
-
"controlState"
|
|
401
|
-
]);
|
|
402
|
-
var verifyRuntimeDeployment = (value) => {
|
|
403
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
404
|
-
throw new Error("Invalid runtime deployment");
|
|
405
|
-
}
|
|
406
|
-
const deployment = value;
|
|
407
|
-
const strategies = deployment.strategies;
|
|
408
|
-
if (Object.keys(deployment).some((key) => !DEPLOYMENT_KEYS.has(key)) || typeof deployment.id !== "string" || typeof deployment.label !== "string" || typeof deployment.connectorName !== "string" || typeof deployment.provider !== "string" || typeof deployment.accountId !== "string" || typeof deployment.enabled !== "boolean" || !Array.isArray(strategies) || !strategies.length || strategies.some((value2) => {
|
|
409
|
-
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) {
|
|
410
|
-
return true;
|
|
411
|
-
}
|
|
412
|
-
const reference = value2;
|
|
413
|
-
return Object.keys(reference).some((key) => !REFERENCE_KEYS.has(key)) || typeof reference.strategyName !== "string" || !reference.strategyName.trim() || !Number.isSafeInteger(reference.releaseVersion) || Number(reference.releaseVersion) <= 0 || reference.controlState !== "active" && reference.controlState !== "entries_paused";
|
|
414
|
-
})) {
|
|
415
|
-
throw new Error("Invalid runtime deployment");
|
|
416
|
-
}
|
|
417
|
-
return value;
|
|
418
|
-
};
|
|
419
|
-
var listRuntimeDeployments = async (userName) => {
|
|
420
|
-
const keys = await getKeys(redisKeys.runtimeDeployments(userName));
|
|
421
|
-
const deploymentKeys = keys.filter((key) => !key.endsWith(":heartbeat"));
|
|
422
|
-
const values = await Promise.all(
|
|
423
|
-
deploymentKeys.map((key) => getData(key, null))
|
|
424
|
-
);
|
|
425
|
-
return values.filter((value) => value != null).map(verifyRuntimeDeployment).sort((left, right) => left.label.localeCompare(right.label));
|
|
426
|
-
};
|
|
427
|
-
var getRuntimeDeployment = async (userName, deploymentId) => {
|
|
428
|
-
const normalizedId = normalizeId(deploymentId, "Deployment id");
|
|
429
|
-
const value = await getData(
|
|
430
|
-
redisKeys.runtimeDeployment(userName, normalizedId),
|
|
431
|
-
null
|
|
432
|
-
);
|
|
433
|
-
return value == null ? null : verifyRuntimeDeployment(value);
|
|
434
|
-
};
|
|
435
|
-
var saveRuntimeDeployment = async (userName, deployment) => {
|
|
436
|
-
const strategies = deployment.strategies.map(
|
|
437
|
-
(strategy) => {
|
|
438
|
-
if (!Number.isSafeInteger(strategy.releaseVersion) || !strategy.releaseVersion || strategy.controlState !== "active" && strategy.controlState !== "entries_paused") {
|
|
439
|
-
throw new Error(
|
|
440
|
-
`Invalid runtime strategy reference: ${strategy.strategyName}`
|
|
441
|
-
);
|
|
442
|
-
}
|
|
443
|
-
return {
|
|
444
|
-
strategyName: strategy.strategyName,
|
|
445
|
-
releaseVersion: strategy.releaseVersion,
|
|
446
|
-
controlState: strategy.controlState
|
|
447
|
-
};
|
|
448
|
-
}
|
|
449
|
-
);
|
|
450
|
-
const normalized = {
|
|
451
|
-
id: normalizeId(deployment.id, "Deployment id"),
|
|
452
|
-
label: deployment.label.trim(),
|
|
453
|
-
connectorName: deployment.connectorName.trim(),
|
|
454
|
-
provider: deployment.provider.trim().toLowerCase(),
|
|
455
|
-
accountId: normalizeId(deployment.accountId, "Account id"),
|
|
456
|
-
enabled: deployment.enabled,
|
|
457
|
-
strategies,
|
|
458
|
-
assetClasses: deployment.assetClasses,
|
|
459
|
-
tickers: deployment.tickers
|
|
460
|
-
};
|
|
461
|
-
verifyRuntimeDeployment(normalized);
|
|
462
|
-
await setData(
|
|
463
|
-
redisKeys.runtimeDeployment(userName, normalized.id),
|
|
464
|
-
normalized,
|
|
465
|
-
{ expire: 0 }
|
|
466
|
-
);
|
|
309
|
+
if (!normalized) throw new Error("Deployment id is required");
|
|
467
310
|
return normalized;
|
|
468
311
|
};
|
|
469
|
-
var deleteRuntimeDeployment = async (userName, deploymentId) => {
|
|
470
|
-
const normalizedId = normalizeId(deploymentId, "Deployment id");
|
|
471
|
-
await Promise.all([
|
|
472
|
-
delKey(redisKeys.runtimeDeployment(userName, normalizedId)),
|
|
473
|
-
delKey(redisKeys.runtimeDeploymentHeartbeat(userName, normalizedId))
|
|
474
|
-
]);
|
|
475
|
-
};
|
|
476
312
|
var getRuntimeDeploymentHeartbeat = async (userName, deploymentId) => {
|
|
477
313
|
const value = await getData(
|
|
478
314
|
redisKeys.runtimeDeploymentHeartbeat(
|
|
479
315
|
userName,
|
|
480
|
-
|
|
316
|
+
normalizeDeploymentId(deploymentId)
|
|
481
317
|
),
|
|
482
318
|
null
|
|
483
319
|
);
|
|
@@ -487,7 +323,7 @@ var saveRuntimeDeploymentHeartbeat = async (userName, heartbeat) => {
|
|
|
487
323
|
await setData(
|
|
488
324
|
redisKeys.runtimeDeploymentHeartbeat(
|
|
489
325
|
userName,
|
|
490
|
-
|
|
326
|
+
normalizeDeploymentId(heartbeat.deploymentId)
|
|
491
327
|
),
|
|
492
328
|
heartbeat,
|
|
493
329
|
{ expire: 0 }
|
|
@@ -496,11 +332,6 @@ var saveRuntimeDeploymentHeartbeat = async (userName, heartbeat) => {
|
|
|
496
332
|
};
|
|
497
333
|
// Annotate the CommonJS export names for ESM import in node:
|
|
498
334
|
0 && (module.exports = {
|
|
499
|
-
deleteRuntimeDeployment,
|
|
500
|
-
getRuntimeDeployment,
|
|
501
335
|
getRuntimeDeploymentHeartbeat,
|
|
502
|
-
|
|
503
|
-
saveRuntimeDeployment,
|
|
504
|
-
saveRuntimeDeploymentHeartbeat,
|
|
505
|
-
verifyRuntimeDeployment
|
|
336
|
+
saveRuntimeDeploymentHeartbeat
|
|
506
337
|
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getData,
|
|
3
|
+
redisKeys,
|
|
4
|
+
setData
|
|
5
|
+
} from "./chunk-NN4CAPDW.mjs";
|
|
6
|
+
|
|
7
|
+
// src/runtimeHeartbeats.ts
|
|
8
|
+
var normalizeDeploymentId = (value) => {
|
|
9
|
+
const normalized = value.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "-");
|
|
10
|
+
if (!normalized) throw new Error("Deployment id is required");
|
|
11
|
+
return normalized;
|
|
12
|
+
};
|
|
13
|
+
var getRuntimeDeploymentHeartbeat = async (userName, deploymentId) => {
|
|
14
|
+
const value = await getData(
|
|
15
|
+
redisKeys.runtimeDeploymentHeartbeat(
|
|
16
|
+
userName,
|
|
17
|
+
normalizeDeploymentId(deploymentId)
|
|
18
|
+
),
|
|
19
|
+
null
|
|
20
|
+
);
|
|
21
|
+
return value && typeof value === "object" ? value : null;
|
|
22
|
+
};
|
|
23
|
+
var saveRuntimeDeploymentHeartbeat = async (userName, heartbeat) => {
|
|
24
|
+
await setData(
|
|
25
|
+
redisKeys.runtimeDeploymentHeartbeat(
|
|
26
|
+
userName,
|
|
27
|
+
normalizeDeploymentId(heartbeat.deploymentId)
|
|
28
|
+
),
|
|
29
|
+
heartbeat,
|
|
30
|
+
{ expire: 0 }
|
|
31
|
+
);
|
|
32
|
+
return heartbeat;
|
|
33
|
+
};
|
|
34
|
+
export {
|
|
35
|
+
getRuntimeDeploymentHeartbeat,
|
|
36
|
+
saveRuntimeDeploymentHeartbeat
|
|
37
|
+
};
|
|
@@ -275,18 +275,14 @@ var redisKeys = {
|
|
|
275
275
|
user: (userName) => `users:index:${userName}`,
|
|
276
276
|
tradingAccounts: (userName) => `users:${userName}:trading-accounts:`,
|
|
277
277
|
tradingAccount: (userName, accountId) => `users:${userName}:trading-accounts:${accountId}`,
|
|
278
|
-
runtimeDeployments: (userName) => `users:${userName}:runtime:deployments:`,
|
|
279
|
-
runtimeDeployment: (userName, deploymentId) => `users:${userName}:runtime:deployments:${deploymentId}`,
|
|
280
278
|
runtimeDeploymentHeartbeat: (userName, deploymentId) => `users:${userName}:runtime:deployments:${deploymentId}:heartbeat`,
|
|
279
|
+
runtimeControls: (userName) => `users:${userName}:runtime:controls`,
|
|
281
280
|
bots: (userName) => `users:${userName}:bots`,
|
|
282
281
|
botsPrefix: () => "users:",
|
|
283
282
|
bot: (userName, botId) => `users:${userName}:bots:${botId}`,
|
|
284
283
|
backtestConfig: (userName, config) => `users:${userName}:backtests:configs:${config}`,
|
|
285
284
|
strategies: (userName) => `users:${userName}:strategies`,
|
|
286
285
|
strategyConfig: (userName, strategyName, configId = "config") => `users:${userName}:strategies:${strategyName}:${configId}`,
|
|
287
|
-
runtimeStrategyReleases: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:releases:`,
|
|
288
|
-
runtimeStrategyRelease: (userName, strategyName, releaseVersion) => `users:${userName}:strategies:${strategyName}:releases:${releaseVersion}`,
|
|
289
|
-
runtimeStrategyReleaseSequence: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:release-seq`,
|
|
290
286
|
runtimeStrategyControlEvents: (userName) => `users:${userName}:runtime:strategy-control-events:`,
|
|
291
287
|
runtimeStrategyControlEvent: (userName, eventId) => `users:${userName}:runtime:strategy-control-events:${eventId}`,
|
|
292
288
|
strategyResults: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:results`,
|
|
@@ -106,7 +106,7 @@ var verifyStrategyEvidenceMarkerEnvelope = (value) => {
|
|
|
106
106
|
for (const value2 of payload.markers) {
|
|
107
107
|
const marker = asRecord(value2);
|
|
108
108
|
const coverage = asRecord(marker?.coverage);
|
|
109
|
-
if (!marker || !isString(marker.id) || !isString(marker.type) || !MARKER_TYPES.has(marker.type) || !isNumber(marker.timestamp) || !isString(marker.label) || !isString(marker.summary) || !isString(marker.artifactId) || !isString(marker.artifactSha256) || !SHA256_RE.test(marker.artifactSha256) || marker.
|
|
109
|
+
if (!marker || !isString(marker.id) || !isString(marker.type) || !MARKER_TYPES.has(marker.type) || !isNumber(marker.timestamp) || !isString(marker.label) || !isString(marker.summary) || !isString(marker.artifactId) || !isString(marker.artifactSha256) || !SHA256_RE.test(marker.artifactSha256) || marker.gitSha !== void 0 && !isString(marker.gitSha) || marker.gateFingerprint !== void 0 && (!isString(marker.gateFingerprint) || !LINEAGE_FINGERPRINT_RE.test(marker.gateFingerprint)) || marker.configFingerprint !== void 0 && (!isString(marker.configFingerprint) || !LINEAGE_FINGERPRINT_RE.test(marker.configFingerprint)) || marker.contextFingerprint !== void 0 && (!isString(marker.contextFingerprint) || !LINEAGE_FINGERPRINT_RE.test(marker.contextFingerprint)) || marker.maxLossValue !== void 0 && !isNumber(marker.maxLossValue) || marker.coverage !== void 0 && (!coverage || !isNumber(coverage.startTime) || !isNumber(coverage.endTime) || coverage.startTime > coverage.endTime)) {
|
|
110
110
|
throw new Error("Invalid strategy evidence marker");
|
|
111
111
|
}
|
|
112
112
|
}
|
|
@@ -76,7 +76,7 @@ var verifyStrategyEvidenceMarkerEnvelope = (value) => {
|
|
|
76
76
|
for (const value2 of payload.markers) {
|
|
77
77
|
const marker = asRecord(value2);
|
|
78
78
|
const coverage = asRecord(marker?.coverage);
|
|
79
|
-
if (!marker || !isString(marker.id) || !isString(marker.type) || !MARKER_TYPES.has(marker.type) || !isNumber(marker.timestamp) || !isString(marker.label) || !isString(marker.summary) || !isString(marker.artifactId) || !isString(marker.artifactSha256) || !SHA256_RE.test(marker.artifactSha256) || marker.
|
|
79
|
+
if (!marker || !isString(marker.id) || !isString(marker.type) || !MARKER_TYPES.has(marker.type) || !isNumber(marker.timestamp) || !isString(marker.label) || !isString(marker.summary) || !isString(marker.artifactId) || !isString(marker.artifactSha256) || !SHA256_RE.test(marker.artifactSha256) || marker.gitSha !== void 0 && !isString(marker.gitSha) || marker.gateFingerprint !== void 0 && (!isString(marker.gateFingerprint) || !LINEAGE_FINGERPRINT_RE.test(marker.gateFingerprint)) || marker.configFingerprint !== void 0 && (!isString(marker.configFingerprint) || !LINEAGE_FINGERPRINT_RE.test(marker.configFingerprint)) || marker.contextFingerprint !== void 0 && (!isString(marker.contextFingerprint) || !LINEAGE_FINGERPRINT_RE.test(marker.contextFingerprint)) || marker.maxLossValue !== void 0 && !isNumber(marker.maxLossValue) || marker.coverage !== void 0 && (!coverage || !isNumber(coverage.startTime) || !isNumber(coverage.endTime) || coverage.startTime > coverage.endTime)) {
|
|
80
80
|
throw new Error("Invalid strategy evidence marker");
|
|
81
81
|
}
|
|
82
82
|
}
|
package/dist/tradingAccounts.js
CHANGED
|
@@ -305,18 +305,14 @@ var redisKeys = {
|
|
|
305
305
|
user: (userName) => `users:index:${userName}`,
|
|
306
306
|
tradingAccounts: (userName) => `users:${userName}:trading-accounts:`,
|
|
307
307
|
tradingAccount: (userName, accountId) => `users:${userName}:trading-accounts:${accountId}`,
|
|
308
|
-
runtimeDeployments: (userName) => `users:${userName}:runtime:deployments:`,
|
|
309
|
-
runtimeDeployment: (userName, deploymentId) => `users:${userName}:runtime:deployments:${deploymentId}`,
|
|
310
308
|
runtimeDeploymentHeartbeat: (userName, deploymentId) => `users:${userName}:runtime:deployments:${deploymentId}:heartbeat`,
|
|
309
|
+
runtimeControls: (userName) => `users:${userName}:runtime:controls`,
|
|
311
310
|
bots: (userName) => `users:${userName}:bots`,
|
|
312
311
|
botsPrefix: () => "users:",
|
|
313
312
|
bot: (userName, botId) => `users:${userName}:bots:${botId}`,
|
|
314
313
|
backtestConfig: (userName, config) => `users:${userName}:backtests:configs:${config}`,
|
|
315
314
|
strategies: (userName) => `users:${userName}:strategies`,
|
|
316
315
|
strategyConfig: (userName, strategyName, configId = "config") => `users:${userName}:strategies:${strategyName}:${configId}`,
|
|
317
|
-
runtimeStrategyReleases: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:releases:`,
|
|
318
|
-
runtimeStrategyRelease: (userName, strategyName, releaseVersion) => `users:${userName}:strategies:${strategyName}:releases:${releaseVersion}`,
|
|
319
|
-
runtimeStrategyReleaseSequence: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:release-seq`,
|
|
320
316
|
runtimeStrategyControlEvents: (userName) => `users:${userName}:runtime:strategy-control-events:`,
|
|
321
317
|
runtimeStrategyControlEvent: (userName, eventId) => `users:${userName}:runtime:strategy-control-events:${eventId}`,
|
|
322
318
|
strategyResults: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:results`,
|
package/dist/tradingAccounts.mjs
CHANGED
package/dist/userSettings.js
CHANGED
|
@@ -238,18 +238,14 @@ var redisKeys = {
|
|
|
238
238
|
user: (userName) => `users:index:${userName}`,
|
|
239
239
|
tradingAccounts: (userName) => `users:${userName}:trading-accounts:`,
|
|
240
240
|
tradingAccount: (userName, accountId) => `users:${userName}:trading-accounts:${accountId}`,
|
|
241
|
-
runtimeDeployments: (userName) => `users:${userName}:runtime:deployments:`,
|
|
242
|
-
runtimeDeployment: (userName, deploymentId) => `users:${userName}:runtime:deployments:${deploymentId}`,
|
|
243
241
|
runtimeDeploymentHeartbeat: (userName, deploymentId) => `users:${userName}:runtime:deployments:${deploymentId}:heartbeat`,
|
|
242
|
+
runtimeControls: (userName) => `users:${userName}:runtime:controls`,
|
|
244
243
|
bots: (userName) => `users:${userName}:bots`,
|
|
245
244
|
botsPrefix: () => "users:",
|
|
246
245
|
bot: (userName, botId) => `users:${userName}:bots:${botId}`,
|
|
247
246
|
backtestConfig: (userName, config) => `users:${userName}:backtests:configs:${config}`,
|
|
248
247
|
strategies: (userName) => `users:${userName}:strategies`,
|
|
249
248
|
strategyConfig: (userName, strategyName, configId = "config") => `users:${userName}:strategies:${strategyName}:${configId}`,
|
|
250
|
-
runtimeStrategyReleases: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:releases:`,
|
|
251
|
-
runtimeStrategyRelease: (userName, strategyName, releaseVersion) => `users:${userName}:strategies:${strategyName}:releases:${releaseVersion}`,
|
|
252
|
-
runtimeStrategyReleaseSequence: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:release-seq`,
|
|
253
249
|
runtimeStrategyControlEvents: (userName) => `users:${userName}:runtime:strategy-control-events:`,
|
|
254
250
|
runtimeStrategyControlEvent: (userName, eventId) => `users:${userName}:runtime:strategy-control-events:${eventId}`,
|
|
255
251
|
strategyResults: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:results`,
|
package/dist/userSettings.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/infra",
|
|
3
|
-
"version": "3.1.8-beta.
|
|
3
|
+
"version": "3.1.8-beta.210",
|
|
4
4
|
"description": "MIT-licensed server infrastructure adapters for TradeJS: Redis, Timescale, ML, logging, and IO.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
@@ -67,15 +67,15 @@
|
|
|
67
67
|
"import": "./dist/runtimeStrategyConfigs.mjs",
|
|
68
68
|
"require": "./dist/runtimeStrategyConfigs.js"
|
|
69
69
|
},
|
|
70
|
-
"./
|
|
71
|
-
"types": "./dist/
|
|
72
|
-
"import": "./dist/
|
|
73
|
-
"require": "./dist/
|
|
70
|
+
"./runtimeHeartbeats": {
|
|
71
|
+
"types": "./dist/runtimeHeartbeats.d.ts",
|
|
72
|
+
"import": "./dist/runtimeHeartbeats.mjs",
|
|
73
|
+
"require": "./dist/runtimeHeartbeats.js"
|
|
74
74
|
},
|
|
75
|
-
"./
|
|
76
|
-
"types": "./dist/
|
|
77
|
-
"import": "./dist/
|
|
78
|
-
"require": "./dist/
|
|
75
|
+
"./runtimeControls": {
|
|
76
|
+
"types": "./dist/runtimeControls.d.ts",
|
|
77
|
+
"import": "./dist/runtimeControls.mjs",
|
|
78
|
+
"require": "./dist/runtimeControls.js"
|
|
79
79
|
},
|
|
80
80
|
"./strategyReleaseEvidence": {
|
|
81
81
|
"types": "./dist/strategyReleaseEvidence.d.ts",
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
"dependencies": {
|
|
127
127
|
"@grpc/grpc-js": "^1.14.4",
|
|
128
128
|
"@grpc/proto-loader": "^0.8.1",
|
|
129
|
-
"@tradejs/types": "^3.1.8-beta.
|
|
129
|
+
"@tradejs/types": "^3.1.8-beta.210",
|
|
130
130
|
"chalk": "4.1.2",
|
|
131
131
|
"date-fns": "^3.6.0",
|
|
132
132
|
"ioredis": "5.11.1",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { RuntimeDeployment, RuntimeDeploymentHeartbeat } from '@tradejs/types';
|
|
2
|
-
|
|
3
|
-
declare const verifyRuntimeDeployment: (value: unknown) => RuntimeDeployment;
|
|
4
|
-
declare const listRuntimeDeployments: (userName: string) => Promise<RuntimeDeployment[]>;
|
|
5
|
-
declare const getRuntimeDeployment: (userName: string, deploymentId: string) => Promise<RuntimeDeployment | null>;
|
|
6
|
-
declare const saveRuntimeDeployment: (userName: string, deployment: RuntimeDeployment) => Promise<RuntimeDeployment>;
|
|
7
|
-
declare const deleteRuntimeDeployment: (userName: string, deploymentId: string) => Promise<void>;
|
|
8
|
-
declare const getRuntimeDeploymentHeartbeat: (userName: string, deploymentId: string) => Promise<RuntimeDeploymentHeartbeat | null>;
|
|
9
|
-
declare const saveRuntimeDeploymentHeartbeat: (userName: string, heartbeat: RuntimeDeploymentHeartbeat) => Promise<RuntimeDeploymentHeartbeat>;
|
|
10
|
-
|
|
11
|
-
export { deleteRuntimeDeployment, getRuntimeDeployment, getRuntimeDeploymentHeartbeat, listRuntimeDeployments, saveRuntimeDeployment, saveRuntimeDeploymentHeartbeat, verifyRuntimeDeployment };
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { RuntimeDeployment, RuntimeDeploymentHeartbeat } from '@tradejs/types';
|
|
2
|
-
|
|
3
|
-
declare const verifyRuntimeDeployment: (value: unknown) => RuntimeDeployment;
|
|
4
|
-
declare const listRuntimeDeployments: (userName: string) => Promise<RuntimeDeployment[]>;
|
|
5
|
-
declare const getRuntimeDeployment: (userName: string, deploymentId: string) => Promise<RuntimeDeployment | null>;
|
|
6
|
-
declare const saveRuntimeDeployment: (userName: string, deployment: RuntimeDeployment) => Promise<RuntimeDeployment>;
|
|
7
|
-
declare const deleteRuntimeDeployment: (userName: string, deploymentId: string) => Promise<void>;
|
|
8
|
-
declare const getRuntimeDeploymentHeartbeat: (userName: string, deploymentId: string) => Promise<RuntimeDeploymentHeartbeat | null>;
|
|
9
|
-
declare const saveRuntimeDeploymentHeartbeat: (userName: string, heartbeat: RuntimeDeploymentHeartbeat) => Promise<RuntimeDeploymentHeartbeat>;
|
|
10
|
-
|
|
11
|
-
export { deleteRuntimeDeployment, getRuntimeDeployment, getRuntimeDeploymentHeartbeat, listRuntimeDeployments, saveRuntimeDeployment, saveRuntimeDeploymentHeartbeat, verifyRuntimeDeployment };
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
delKey,
|
|
3
|
-
getData,
|
|
4
|
-
getKeys,
|
|
5
|
-
redisKeys,
|
|
6
|
-
setData
|
|
7
|
-
} from "./chunk-JLVCBKE3.mjs";
|
|
8
|
-
|
|
9
|
-
// src/runtimeDeployments.ts
|
|
10
|
-
var normalizeId = (value, label) => {
|
|
11
|
-
const normalized = value.trim().toLowerCase().replace(/[^a-z0-9_-]/g, "-");
|
|
12
|
-
if (!normalized) throw new Error(`${label} is required`);
|
|
13
|
-
return normalized;
|
|
14
|
-
};
|
|
15
|
-
var DEPLOYMENT_KEYS = /* @__PURE__ */ new Set([
|
|
16
|
-
"id",
|
|
17
|
-
"label",
|
|
18
|
-
"connectorName",
|
|
19
|
-
"provider",
|
|
20
|
-
"accountId",
|
|
21
|
-
"enabled",
|
|
22
|
-
"strategies",
|
|
23
|
-
"assetClasses",
|
|
24
|
-
"tickers"
|
|
25
|
-
]);
|
|
26
|
-
var REFERENCE_KEYS = /* @__PURE__ */ new Set([
|
|
27
|
-
"strategyName",
|
|
28
|
-
"releaseVersion",
|
|
29
|
-
"controlState"
|
|
30
|
-
]);
|
|
31
|
-
var verifyRuntimeDeployment = (value) => {
|
|
32
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
33
|
-
throw new Error("Invalid runtime deployment");
|
|
34
|
-
}
|
|
35
|
-
const deployment = value;
|
|
36
|
-
const strategies = deployment.strategies;
|
|
37
|
-
if (Object.keys(deployment).some((key) => !DEPLOYMENT_KEYS.has(key)) || typeof deployment.id !== "string" || typeof deployment.label !== "string" || typeof deployment.connectorName !== "string" || typeof deployment.provider !== "string" || typeof deployment.accountId !== "string" || typeof deployment.enabled !== "boolean" || !Array.isArray(strategies) || !strategies.length || strategies.some((value2) => {
|
|
38
|
-
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) {
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
const reference = value2;
|
|
42
|
-
return Object.keys(reference).some((key) => !REFERENCE_KEYS.has(key)) || typeof reference.strategyName !== "string" || !reference.strategyName.trim() || !Number.isSafeInteger(reference.releaseVersion) || Number(reference.releaseVersion) <= 0 || reference.controlState !== "active" && reference.controlState !== "entries_paused";
|
|
43
|
-
})) {
|
|
44
|
-
throw new Error("Invalid runtime deployment");
|
|
45
|
-
}
|
|
46
|
-
return value;
|
|
47
|
-
};
|
|
48
|
-
var listRuntimeDeployments = async (userName) => {
|
|
49
|
-
const keys = await getKeys(redisKeys.runtimeDeployments(userName));
|
|
50
|
-
const deploymentKeys = keys.filter((key) => !key.endsWith(":heartbeat"));
|
|
51
|
-
const values = await Promise.all(
|
|
52
|
-
deploymentKeys.map((key) => getData(key, null))
|
|
53
|
-
);
|
|
54
|
-
return values.filter((value) => value != null).map(verifyRuntimeDeployment).sort((left, right) => left.label.localeCompare(right.label));
|
|
55
|
-
};
|
|
56
|
-
var getRuntimeDeployment = async (userName, deploymentId) => {
|
|
57
|
-
const normalizedId = normalizeId(deploymentId, "Deployment id");
|
|
58
|
-
const value = await getData(
|
|
59
|
-
redisKeys.runtimeDeployment(userName, normalizedId),
|
|
60
|
-
null
|
|
61
|
-
);
|
|
62
|
-
return value == null ? null : verifyRuntimeDeployment(value);
|
|
63
|
-
};
|
|
64
|
-
var saveRuntimeDeployment = async (userName, deployment) => {
|
|
65
|
-
const strategies = deployment.strategies.map(
|
|
66
|
-
(strategy) => {
|
|
67
|
-
if (!Number.isSafeInteger(strategy.releaseVersion) || !strategy.releaseVersion || strategy.controlState !== "active" && strategy.controlState !== "entries_paused") {
|
|
68
|
-
throw new Error(
|
|
69
|
-
`Invalid runtime strategy reference: ${strategy.strategyName}`
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
return {
|
|
73
|
-
strategyName: strategy.strategyName,
|
|
74
|
-
releaseVersion: strategy.releaseVersion,
|
|
75
|
-
controlState: strategy.controlState
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
);
|
|
79
|
-
const normalized = {
|
|
80
|
-
id: normalizeId(deployment.id, "Deployment id"),
|
|
81
|
-
label: deployment.label.trim(),
|
|
82
|
-
connectorName: deployment.connectorName.trim(),
|
|
83
|
-
provider: deployment.provider.trim().toLowerCase(),
|
|
84
|
-
accountId: normalizeId(deployment.accountId, "Account id"),
|
|
85
|
-
enabled: deployment.enabled,
|
|
86
|
-
strategies,
|
|
87
|
-
assetClasses: deployment.assetClasses,
|
|
88
|
-
tickers: deployment.tickers
|
|
89
|
-
};
|
|
90
|
-
verifyRuntimeDeployment(normalized);
|
|
91
|
-
await setData(
|
|
92
|
-
redisKeys.runtimeDeployment(userName, normalized.id),
|
|
93
|
-
normalized,
|
|
94
|
-
{ expire: 0 }
|
|
95
|
-
);
|
|
96
|
-
return normalized;
|
|
97
|
-
};
|
|
98
|
-
var deleteRuntimeDeployment = async (userName, deploymentId) => {
|
|
99
|
-
const normalizedId = normalizeId(deploymentId, "Deployment id");
|
|
100
|
-
await Promise.all([
|
|
101
|
-
delKey(redisKeys.runtimeDeployment(userName, normalizedId)),
|
|
102
|
-
delKey(redisKeys.runtimeDeploymentHeartbeat(userName, normalizedId))
|
|
103
|
-
]);
|
|
104
|
-
};
|
|
105
|
-
var getRuntimeDeploymentHeartbeat = async (userName, deploymentId) => {
|
|
106
|
-
const value = await getData(
|
|
107
|
-
redisKeys.runtimeDeploymentHeartbeat(
|
|
108
|
-
userName,
|
|
109
|
-
normalizeId(deploymentId, "Deployment id")
|
|
110
|
-
),
|
|
111
|
-
null
|
|
112
|
-
);
|
|
113
|
-
return value && typeof value === "object" ? value : null;
|
|
114
|
-
};
|
|
115
|
-
var saveRuntimeDeploymentHeartbeat = async (userName, heartbeat) => {
|
|
116
|
-
await setData(
|
|
117
|
-
redisKeys.runtimeDeploymentHeartbeat(
|
|
118
|
-
userName,
|
|
119
|
-
normalizeId(heartbeat.deploymentId, "Deployment id")
|
|
120
|
-
),
|
|
121
|
-
heartbeat,
|
|
122
|
-
{ expire: 0 }
|
|
123
|
-
);
|
|
124
|
-
return heartbeat;
|
|
125
|
-
};
|
|
126
|
-
export {
|
|
127
|
-
deleteRuntimeDeployment,
|
|
128
|
-
getRuntimeDeployment,
|
|
129
|
-
getRuntimeDeploymentHeartbeat,
|
|
130
|
-
listRuntimeDeployments,
|
|
131
|
-
saveRuntimeDeployment,
|
|
132
|
-
saveRuntimeDeploymentHeartbeat,
|
|
133
|
-
verifyRuntimeDeployment
|
|
134
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { StrategyConfig, RuntimeStrategyRelease, RuntimeStrategyControlState, RuntimeStrategyControlEvent } from '@tradejs/types';
|
|
2
|
-
|
|
3
|
-
declare const assertRuntimeStrategyReleaseConfig: (config: StrategyConfig) => void;
|
|
4
|
-
declare const verifyRuntimeStrategyRelease: (value: unknown) => RuntimeStrategyRelease;
|
|
5
|
-
declare const getRuntimeStrategyRelease: (userName: string, strategyName: string, releaseVersion: number) => Promise<RuntimeStrategyRelease | null>;
|
|
6
|
-
declare const listRuntimeStrategyReleases: (userName: string, strategyName: string) => Promise<RuntimeStrategyRelease[]>;
|
|
7
|
-
declare const publishRuntimeStrategyRelease: ({ userName, strategyName, config, strategyPackage, strategyPackageVersion, runtimePackageVersion, createdBy, }: {
|
|
8
|
-
userName: string;
|
|
9
|
-
strategyName: string;
|
|
10
|
-
config: StrategyConfig;
|
|
11
|
-
strategyPackage: string;
|
|
12
|
-
strategyPackageVersion: string;
|
|
13
|
-
runtimePackageVersion: string;
|
|
14
|
-
createdBy: string;
|
|
15
|
-
}) => Promise<RuntimeStrategyRelease>;
|
|
16
|
-
declare const recordRuntimeStrategyControlEvent: ({ userName, deploymentId, strategyName, releaseVersion, previousState, nextState, createdBy, }: {
|
|
17
|
-
userName: string;
|
|
18
|
-
deploymentId: string;
|
|
19
|
-
strategyName: string;
|
|
20
|
-
releaseVersion: number;
|
|
21
|
-
previousState: RuntimeStrategyControlState;
|
|
22
|
-
nextState: RuntimeStrategyControlState;
|
|
23
|
-
createdBy: string;
|
|
24
|
-
}) => Promise<RuntimeStrategyControlEvent>;
|
|
25
|
-
|
|
26
|
-
export { assertRuntimeStrategyReleaseConfig, getRuntimeStrategyRelease, listRuntimeStrategyReleases, publishRuntimeStrategyRelease, recordRuntimeStrategyControlEvent, verifyRuntimeStrategyRelease };
|