@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.
@@ -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/runtimeDeployments.ts
31
- var runtimeDeployments_exports = {};
32
- __export(runtimeDeployments_exports, {
33
- deleteRuntimeDeployment: () => deleteRuntimeDeployment,
34
- getRuntimeDeployment: () => getRuntimeDeployment,
30
+ // src/runtimeHeartbeats.ts
31
+ var runtimeHeartbeats_exports = {};
32
+ __export(runtimeHeartbeats_exports, {
35
33
  getRuntimeDeploymentHeartbeat: () => getRuntimeDeploymentHeartbeat,
36
- listRuntimeDeployments: () => listRuntimeDeployments,
37
- saveRuntimeDeployment: () => saveRuntimeDeployment,
38
- saveRuntimeDeploymentHeartbeat: () => saveRuntimeDeploymentHeartbeat,
39
- verifyRuntimeDeployment: () => verifyRuntimeDeployment
34
+ saveRuntimeDeploymentHeartbeat: () => saveRuntimeDeploymentHeartbeat
40
35
  });
41
- module.exports = __toCommonJS(runtimeDeployments_exports);
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/runtimeDeployments.ts
381
- var normalizeId = (value, label) => {
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(`${label} is required`);
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
- normalizeId(deploymentId, "Deployment id")
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
- normalizeId(heartbeat.deploymentId, "Deployment id")
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
- listRuntimeDeployments,
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`,
@@ -3,7 +3,7 @@ import {
3
3
  getKeys,
4
4
  redisKeys,
5
5
  setData
6
- } from "./chunk-JLVCBKE3.mjs";
6
+ } from "./chunk-NN4CAPDW.mjs";
7
7
 
8
8
  // src/runtimeStrategyConfigs.ts
9
9
  var RESERVED_STRATEGY_NAMES = /* @__PURE__ */ new Set(["charts"]);
@@ -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.releaseVersion !== void 0 && (!Number.isSafeInteger(marker.releaseVersion) || Number(marker.releaseVersion) <= 0) || 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)) {
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.releaseVersion !== void 0 && (!Number.isSafeInteger(marker.releaseVersion) || Number(marker.releaseVersion) <= 0) || 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)) {
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
  }
@@ -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`,
@@ -4,7 +4,7 @@ import {
4
4
  getKeys,
5
5
  redisKeys,
6
6
  setData
7
- } from "./chunk-JLVCBKE3.mjs";
7
+ } from "./chunk-NN4CAPDW.mjs";
8
8
 
9
9
  // src/tradingAccounts.ts
10
10
  var normalizeId = (value, label) => {
@@ -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`,
@@ -2,7 +2,7 @@ import {
2
2
  getData,
3
3
  redisKeys,
4
4
  setData
5
- } from "./chunk-JLVCBKE3.mjs";
5
+ } from "./chunk-NN4CAPDW.mjs";
6
6
 
7
7
  // src/userSettings.ts
8
8
  var readString = (value) => typeof value === "string" ? value.trim() : "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tradejs/infra",
3
- "version": "3.1.8-beta.207",
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
- "./runtimeStrategyReleases": {
71
- "types": "./dist/runtimeStrategyReleases.d.ts",
72
- "import": "./dist/runtimeStrategyReleases.mjs",
73
- "require": "./dist/runtimeStrategyReleases.js"
70
+ "./runtimeHeartbeats": {
71
+ "types": "./dist/runtimeHeartbeats.d.ts",
72
+ "import": "./dist/runtimeHeartbeats.mjs",
73
+ "require": "./dist/runtimeHeartbeats.js"
74
74
  },
75
- "./runtimeDeployments": {
76
- "types": "./dist/runtimeDeployments.d.ts",
77
- "import": "./dist/runtimeDeployments.mjs",
78
- "require": "./dist/runtimeDeployments.js"
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.207",
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 };