@tradejs/infra 3.0.1 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/{chunk-6ZKAUA4Q.mjs → chunk-RZTVC4ZL.mjs} +49 -0
- package/dist/redis.d.mts +10 -1
- package/dist/redis.d.ts +10 -1
- package/dist/redis.js +51 -0
- package/dist/redis.mjs +5 -1
- package/dist/runtimeDeployments.js +29 -1
- package/dist/runtimeDeployments.mjs +24 -2
- package/dist/runtimeStrategyConfigs.js +7 -1
- package/dist/runtimeStrategyConfigs.mjs +2 -2
- package/dist/runtimeStrategyReleases.d.mts +34 -0
- package/dist/runtimeStrategyReleases.d.ts +34 -0
- package/dist/runtimeStrategyReleases.js +598 -0
- package/dist/runtimeStrategyReleases.mjs +220 -0
- package/dist/strategyReleaseEvidence.js +1 -1
- package/dist/strategyReleaseEvidence.mjs +1 -1
- package/dist/tradingAccounts.js +6 -0
- package/dist/tradingAccounts.mjs +1 -1
- package/dist/userSettings.js +6 -0
- package/dist/userSettings.mjs +1 -1
- package/package.json +11 -8
- package/dist/http.d.mts +0 -8
- package/dist/http.d.ts +0 -8
- package/dist/http.js +0 -79
- package/dist/http.mjs +0 -54
package/README.md
CHANGED
|
@@ -35,7 +35,6 @@ npm i @tradejs/infra @tradejs/types
|
|
|
35
35
|
Import only explicit subpaths:
|
|
36
36
|
|
|
37
37
|
- `@tradejs/infra/files`
|
|
38
|
-
- `@tradejs/infra/http`
|
|
39
38
|
- `@tradejs/infra/logger`
|
|
40
39
|
- `@tradejs/infra/ml`
|
|
41
40
|
- `@tradejs/infra/redis`
|
|
@@ -55,3 +54,5 @@ import { logger } from '@tradejs/infra/logger';
|
|
|
55
54
|
- `@tradejs/infra` is server-only. Do not import it into browser/client code.
|
|
56
55
|
- Environment loading should happen in your app/runtime entrypoint, not inside shared library code.
|
|
57
56
|
- If you are following the standard external quickstart, start with `@tradejs/app`, `@tradejs/core`, `@tradejs/node`, `@tradejs/base`, and `@tradejs/cli` instead of adding `@tradejs/infra` manually.
|
|
57
|
+
|
|
58
|
+
Keywords: ai, claude, codex.
|
|
@@ -301,6 +301,47 @@ var setData = async (key, data, options = {}) => {
|
|
|
301
301
|
}
|
|
302
302
|
}
|
|
303
303
|
};
|
|
304
|
+
var setDataIfAbsent = async (key, data) => {
|
|
305
|
+
if (redisUnavailable) return false;
|
|
306
|
+
const redis = await getReadyRedis();
|
|
307
|
+
if (!redis) return false;
|
|
308
|
+
try {
|
|
309
|
+
return await redis.call("JSON.SET", key, "$", toJson(data), "NX") === "OK";
|
|
310
|
+
} catch (error) {
|
|
311
|
+
if (error instanceof Error && isRedisConnectivityError(error)) {
|
|
312
|
+
markRedisUnavailable(error);
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
logger.log(
|
|
316
|
+
"warn",
|
|
317
|
+
"failed JSON.SET NX %s: %s (fallback to SET NX)",
|
|
318
|
+
key,
|
|
319
|
+
String(error)
|
|
320
|
+
);
|
|
321
|
+
try {
|
|
322
|
+
return await redis.set(key, toJson(data), "NX") === "OK";
|
|
323
|
+
} catch (fallbackError) {
|
|
324
|
+
if (fallbackError instanceof Error && isRedisConnectivityError(fallbackError)) {
|
|
325
|
+
markRedisUnavailable(fallbackError);
|
|
326
|
+
}
|
|
327
|
+
logger.log("error", "failed SET NX %s: %s", key, String(fallbackError));
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
var incrementKey = async (key) => {
|
|
333
|
+
if (redisUnavailable) throw new Error("Redis is unavailable");
|
|
334
|
+
const redis = await getReadyRedis();
|
|
335
|
+
if (!redis) throw new Error("Redis is unavailable");
|
|
336
|
+
try {
|
|
337
|
+
return await redis.incr(key);
|
|
338
|
+
} catch (error) {
|
|
339
|
+
if (error instanceof Error && isRedisConnectivityError(error)) {
|
|
340
|
+
markRedisUnavailable(error);
|
|
341
|
+
}
|
|
342
|
+
throw error;
|
|
343
|
+
}
|
|
344
|
+
};
|
|
304
345
|
var setHashJsonField = async (key, field, data, options = {}) => {
|
|
305
346
|
if (redisUnavailable) return;
|
|
306
347
|
const { expire } = { ...DEFAULT_OPTIONS, ...options };
|
|
@@ -476,6 +517,12 @@ var redisKeys = {
|
|
|
476
517
|
backtestConfig: (userName, config) => `users:${userName}:backtests:configs:${config}`,
|
|
477
518
|
strategies: (userName) => `users:${userName}:strategies`,
|
|
478
519
|
strategyConfig: (userName, strategyName, configId = "config") => `users:${userName}:strategies:${strategyName}:${configId}`,
|
|
520
|
+
runtimeStrategyDraft: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:draft`,
|
|
521
|
+
runtimeStrategyReleases: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:releases:`,
|
|
522
|
+
runtimeStrategyRelease: (userName, strategyName, releaseVersion) => `users:${userName}:strategies:${strategyName}:releases:${releaseVersion}`,
|
|
523
|
+
runtimeStrategyReleaseSequence: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:release-seq`,
|
|
524
|
+
runtimeStrategyControlEvents: (userName) => `users:${userName}:runtime:strategy-control-events:`,
|
|
525
|
+
runtimeStrategyControlEvent: (userName, eventId) => `users:${userName}:runtime:strategy-control-events:${eventId}`,
|
|
479
526
|
strategyResults: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:results`,
|
|
480
527
|
strategyCharts: (userName, mode) => `users:${userName}:strategies:charts:${mode}`,
|
|
481
528
|
strategyChartCards: (userName, mode) => `users:${userName}:strategies:charts:${mode}:cards:`,
|
|
@@ -541,6 +588,8 @@ export {
|
|
|
541
588
|
RedisWriteBlockedError,
|
|
542
589
|
delKeyWithOptions,
|
|
543
590
|
setData,
|
|
591
|
+
setDataIfAbsent,
|
|
592
|
+
incrementKey,
|
|
544
593
|
setHashJsonField,
|
|
545
594
|
setHashJsonFields,
|
|
546
595
|
getHashJsonField,
|
package/dist/redis.d.mts
CHANGED
|
@@ -19,6 +19,9 @@ declare class RedisWriteBlockedError extends Error {
|
|
|
19
19
|
}
|
|
20
20
|
declare const delKeyWithOptions: (key: string, options?: DelKeyOptions) => Promise<boolean>;
|
|
21
21
|
declare const setData: <T>(key: string, data: T, options?: Options) => Promise<void>;
|
|
22
|
+
/** Writes a JSON value only when the key does not exist. */
|
|
23
|
+
declare const setDataIfAbsent: <T>(key: string, data: T) => Promise<boolean>;
|
|
24
|
+
declare const incrementKey: (key: string) => Promise<number>;
|
|
22
25
|
declare const setHashJsonField: <T>(key: string, field: string, data: T, options?: Options) => Promise<void>;
|
|
23
26
|
declare const setHashJsonFields: <T>(key: string, entries: ReadonlyArray<{
|
|
24
27
|
field: string;
|
|
@@ -44,6 +47,12 @@ declare const redisKeys: {
|
|
|
44
47
|
backtestConfig: (userName: string, config: string) => string;
|
|
45
48
|
strategies: (userName: string) => string;
|
|
46
49
|
strategyConfig: (userName: string, strategyName: string, configId?: string) => string;
|
|
50
|
+
runtimeStrategyDraft: (userName: string, strategyName: string) => string;
|
|
51
|
+
runtimeStrategyReleases: (userName: string, strategyName: string) => string;
|
|
52
|
+
runtimeStrategyRelease: (userName: string, strategyName: string, releaseVersion: number) => string;
|
|
53
|
+
runtimeStrategyReleaseSequence: (userName: string, strategyName: string) => string;
|
|
54
|
+
runtimeStrategyControlEvents: (userName: string) => string;
|
|
55
|
+
runtimeStrategyControlEvent: (userName: string, eventId: string) => string;
|
|
47
56
|
strategyResults: (userName: string, strategyName: string) => string;
|
|
48
57
|
strategyCharts: (userName: string, mode: string) => string;
|
|
49
58
|
strategyChartCards: (userName: string, mode: string) => string;
|
|
@@ -100,4 +109,4 @@ declare const redisKeys: {
|
|
|
100
109
|
mlResult: (strategyName: string, signalId: string) => string;
|
|
101
110
|
};
|
|
102
111
|
|
|
103
|
-
export { RedisWriteBlockedError, closeRedisConnection, consumeScreenshotSessionToken, createScreenshotSessionToken, delKey, delKeyWithOptions, getData, getHashData, getHashJsonField, getHashJsonValues, getKeys, incrHashFields, publishData, redisKeys, setData, setHashJsonField, setHashJsonFields };
|
|
112
|
+
export { RedisWriteBlockedError, closeRedisConnection, consumeScreenshotSessionToken, createScreenshotSessionToken, delKey, delKeyWithOptions, getData, getHashData, getHashJsonField, getHashJsonValues, getKeys, incrHashFields, incrementKey, publishData, redisKeys, setData, setDataIfAbsent, setHashJsonField, setHashJsonFields };
|
package/dist/redis.d.ts
CHANGED
|
@@ -19,6 +19,9 @@ declare class RedisWriteBlockedError extends Error {
|
|
|
19
19
|
}
|
|
20
20
|
declare const delKeyWithOptions: (key: string, options?: DelKeyOptions) => Promise<boolean>;
|
|
21
21
|
declare const setData: <T>(key: string, data: T, options?: Options) => Promise<void>;
|
|
22
|
+
/** Writes a JSON value only when the key does not exist. */
|
|
23
|
+
declare const setDataIfAbsent: <T>(key: string, data: T) => Promise<boolean>;
|
|
24
|
+
declare const incrementKey: (key: string) => Promise<number>;
|
|
22
25
|
declare const setHashJsonField: <T>(key: string, field: string, data: T, options?: Options) => Promise<void>;
|
|
23
26
|
declare const setHashJsonFields: <T>(key: string, entries: ReadonlyArray<{
|
|
24
27
|
field: string;
|
|
@@ -44,6 +47,12 @@ declare const redisKeys: {
|
|
|
44
47
|
backtestConfig: (userName: string, config: string) => string;
|
|
45
48
|
strategies: (userName: string) => string;
|
|
46
49
|
strategyConfig: (userName: string, strategyName: string, configId?: string) => string;
|
|
50
|
+
runtimeStrategyDraft: (userName: string, strategyName: string) => string;
|
|
51
|
+
runtimeStrategyReleases: (userName: string, strategyName: string) => string;
|
|
52
|
+
runtimeStrategyRelease: (userName: string, strategyName: string, releaseVersion: number) => string;
|
|
53
|
+
runtimeStrategyReleaseSequence: (userName: string, strategyName: string) => string;
|
|
54
|
+
runtimeStrategyControlEvents: (userName: string) => string;
|
|
55
|
+
runtimeStrategyControlEvent: (userName: string, eventId: string) => string;
|
|
47
56
|
strategyResults: (userName: string, strategyName: string) => string;
|
|
48
57
|
strategyCharts: (userName: string, mode: string) => string;
|
|
49
58
|
strategyChartCards: (userName: string, mode: string) => string;
|
|
@@ -100,4 +109,4 @@ declare const redisKeys: {
|
|
|
100
109
|
mlResult: (strategyName: string, signalId: string) => string;
|
|
101
110
|
};
|
|
102
111
|
|
|
103
|
-
export { RedisWriteBlockedError, closeRedisConnection, consumeScreenshotSessionToken, createScreenshotSessionToken, delKey, delKeyWithOptions, getData, getHashData, getHashJsonField, getHashJsonValues, getKeys, incrHashFields, publishData, redisKeys, setData, setHashJsonField, setHashJsonFields };
|
|
112
|
+
export { RedisWriteBlockedError, closeRedisConnection, consumeScreenshotSessionToken, createScreenshotSessionToken, delKey, delKeyWithOptions, getData, getHashData, getHashJsonField, getHashJsonValues, getKeys, incrHashFields, incrementKey, publishData, redisKeys, setData, setDataIfAbsent, setHashJsonField, setHashJsonFields };
|
package/dist/redis.js
CHANGED
|
@@ -42,9 +42,11 @@ __export(redis_exports, {
|
|
|
42
42
|
getHashJsonValues: () => getHashJsonValues,
|
|
43
43
|
getKeys: () => getKeys,
|
|
44
44
|
incrHashFields: () => incrHashFields,
|
|
45
|
+
incrementKey: () => incrementKey,
|
|
45
46
|
publishData: () => publishData,
|
|
46
47
|
redisKeys: () => redisKeys,
|
|
47
48
|
setData: () => setData,
|
|
49
|
+
setDataIfAbsent: () => setDataIfAbsent,
|
|
48
50
|
setHashJsonField: () => setHashJsonField,
|
|
49
51
|
setHashJsonFields: () => setHashJsonFields
|
|
50
52
|
});
|
|
@@ -351,6 +353,47 @@ var setData = async (key, data, options = {}) => {
|
|
|
351
353
|
}
|
|
352
354
|
}
|
|
353
355
|
};
|
|
356
|
+
var setDataIfAbsent = async (key, data) => {
|
|
357
|
+
if (redisUnavailable) return false;
|
|
358
|
+
const redis = await getReadyRedis();
|
|
359
|
+
if (!redis) return false;
|
|
360
|
+
try {
|
|
361
|
+
return await redis.call("JSON.SET", key, "$", toJson(data), "NX") === "OK";
|
|
362
|
+
} catch (error) {
|
|
363
|
+
if (error instanceof Error && isRedisConnectivityError(error)) {
|
|
364
|
+
markRedisUnavailable(error);
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
logger.log(
|
|
368
|
+
"warn",
|
|
369
|
+
"failed JSON.SET NX %s: %s (fallback to SET NX)",
|
|
370
|
+
key,
|
|
371
|
+
String(error)
|
|
372
|
+
);
|
|
373
|
+
try {
|
|
374
|
+
return await redis.set(key, toJson(data), "NX") === "OK";
|
|
375
|
+
} catch (fallbackError) {
|
|
376
|
+
if (fallbackError instanceof Error && isRedisConnectivityError(fallbackError)) {
|
|
377
|
+
markRedisUnavailable(fallbackError);
|
|
378
|
+
}
|
|
379
|
+
logger.log("error", "failed SET NX %s: %s", key, String(fallbackError));
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
var incrementKey = async (key) => {
|
|
385
|
+
if (redisUnavailable) throw new Error("Redis is unavailable");
|
|
386
|
+
const redis = await getReadyRedis();
|
|
387
|
+
if (!redis) throw new Error("Redis is unavailable");
|
|
388
|
+
try {
|
|
389
|
+
return await redis.incr(key);
|
|
390
|
+
} catch (error) {
|
|
391
|
+
if (error instanceof Error && isRedisConnectivityError(error)) {
|
|
392
|
+
markRedisUnavailable(error);
|
|
393
|
+
}
|
|
394
|
+
throw error;
|
|
395
|
+
}
|
|
396
|
+
};
|
|
354
397
|
var setHashJsonField = async (key, field, data, options = {}) => {
|
|
355
398
|
if (redisUnavailable) return;
|
|
356
399
|
const { expire } = { ...DEFAULT_OPTIONS, ...options };
|
|
@@ -526,6 +569,12 @@ var redisKeys = {
|
|
|
526
569
|
backtestConfig: (userName, config) => `users:${userName}:backtests:configs:${config}`,
|
|
527
570
|
strategies: (userName) => `users:${userName}:strategies`,
|
|
528
571
|
strategyConfig: (userName, strategyName, configId = "config") => `users:${userName}:strategies:${strategyName}:${configId}`,
|
|
572
|
+
runtimeStrategyDraft: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:draft`,
|
|
573
|
+
runtimeStrategyReleases: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:releases:`,
|
|
574
|
+
runtimeStrategyRelease: (userName, strategyName, releaseVersion) => `users:${userName}:strategies:${strategyName}:releases:${releaseVersion}`,
|
|
575
|
+
runtimeStrategyReleaseSequence: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:release-seq`,
|
|
576
|
+
runtimeStrategyControlEvents: (userName) => `users:${userName}:runtime:strategy-control-events:`,
|
|
577
|
+
runtimeStrategyControlEvent: (userName, eventId) => `users:${userName}:runtime:strategy-control-events:${eventId}`,
|
|
529
578
|
strategyResults: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:results`,
|
|
530
579
|
strategyCharts: (userName, mode) => `users:${userName}:strategies:charts:${mode}`,
|
|
531
580
|
strategyChartCards: (userName, mode) => `users:${userName}:strategies:charts:${mode}:cards:`,
|
|
@@ -595,9 +644,11 @@ var redisKeys = {
|
|
|
595
644
|
getHashJsonValues,
|
|
596
645
|
getKeys,
|
|
597
646
|
incrHashFields,
|
|
647
|
+
incrementKey,
|
|
598
648
|
publishData,
|
|
599
649
|
redisKeys,
|
|
600
650
|
setData,
|
|
651
|
+
setDataIfAbsent,
|
|
601
652
|
setHashJsonField,
|
|
602
653
|
setHashJsonFields
|
|
603
654
|
});
|
package/dist/redis.mjs
CHANGED
|
@@ -11,12 +11,14 @@ import {
|
|
|
11
11
|
getHashJsonValues,
|
|
12
12
|
getKeys,
|
|
13
13
|
incrHashFields,
|
|
14
|
+
incrementKey,
|
|
14
15
|
publishData,
|
|
15
16
|
redisKeys,
|
|
16
17
|
setData,
|
|
18
|
+
setDataIfAbsent,
|
|
17
19
|
setHashJsonField,
|
|
18
20
|
setHashJsonFields
|
|
19
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-RZTVC4ZL.mjs";
|
|
20
22
|
export {
|
|
21
23
|
RedisWriteBlockedError,
|
|
22
24
|
closeRedisConnection,
|
|
@@ -30,9 +32,11 @@ export {
|
|
|
30
32
|
getHashJsonValues,
|
|
31
33
|
getKeys,
|
|
32
34
|
incrHashFields,
|
|
35
|
+
incrementKey,
|
|
33
36
|
publishData,
|
|
34
37
|
redisKeys,
|
|
35
38
|
setData,
|
|
39
|
+
setDataIfAbsent,
|
|
36
40
|
setHashJsonField,
|
|
37
41
|
setHashJsonFields
|
|
38
42
|
};
|
|
@@ -315,6 +315,12 @@ var redisKeys = {
|
|
|
315
315
|
backtestConfig: (userName, config) => `users:${userName}:backtests:configs:${config}`,
|
|
316
316
|
strategies: (userName) => `users:${userName}:strategies`,
|
|
317
317
|
strategyConfig: (userName, strategyName, configId = "config") => `users:${userName}:strategies:${strategyName}:${configId}`,
|
|
318
|
+
runtimeStrategyDraft: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:draft`,
|
|
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
|
+
runtimeStrategyControlEvents: (userName) => `users:${userName}:runtime:strategy-control-events:`,
|
|
323
|
+
runtimeStrategyControlEvent: (userName, eventId) => `users:${userName}:runtime:strategy-control-events:${eventId}`,
|
|
318
324
|
strategyResults: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:results`,
|
|
319
325
|
strategyCharts: (userName, mode) => `users:${userName}:strategies:charts:${mode}`,
|
|
320
326
|
strategyChartCards: (userName, mode) => `users:${userName}:strategies:charts:${mode}:cards:`,
|
|
@@ -394,12 +400,34 @@ var getRuntimeDeployment = async (userName, deploymentId) => {
|
|
|
394
400
|
return isRuntimeDeployment(value) ? value : null;
|
|
395
401
|
};
|
|
396
402
|
var saveRuntimeDeployment = async (userName, deployment) => {
|
|
403
|
+
const hasVersionedStrategies = deployment.strategies.some(
|
|
404
|
+
(strategy) => strategy.releaseVersion != null
|
|
405
|
+
);
|
|
406
|
+
if (hasVersionedStrategies && deployment.strategies.some((strategy) => strategy.releaseVersion == null)) {
|
|
407
|
+
throw new Error("A deployment cannot mix legacy configs and releases");
|
|
408
|
+
}
|
|
409
|
+
const strategies = deployment.strategies.map(
|
|
410
|
+
(strategy) => {
|
|
411
|
+
if (!hasVersionedStrategies) return strategy;
|
|
412
|
+
if (!Number.isSafeInteger(strategy.releaseVersion) || !strategy.releaseVersion || strategy.config && Object.keys(strategy.config).length) {
|
|
413
|
+
throw new Error(
|
|
414
|
+
`Invalid versioned strategy reference: ${strategy.strategyName}`
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
return {
|
|
418
|
+
strategyName: strategy.strategyName,
|
|
419
|
+
releaseVersion: strategy.releaseVersion,
|
|
420
|
+
controlState: strategy.controlState === "entries_paused" ? "entries_paused" : "active"
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
);
|
|
397
424
|
const normalized = {
|
|
398
425
|
...deployment,
|
|
399
426
|
id: normalizeId(deployment.id, "Deployment id"),
|
|
400
427
|
label: deployment.label.trim(),
|
|
401
428
|
provider: deployment.provider.trim().toLowerCase(),
|
|
402
|
-
accountId: normalizeId(deployment.accountId, "Account id")
|
|
429
|
+
accountId: normalizeId(deployment.accountId, "Account id"),
|
|
430
|
+
strategies
|
|
403
431
|
};
|
|
404
432
|
await setData(
|
|
405
433
|
redisKeys.runtimeDeployment(userName, normalized.id),
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getKeys,
|
|
5
5
|
redisKeys,
|
|
6
6
|
setData
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-RZTVC4ZL.mjs";
|
|
8
8
|
|
|
9
9
|
// src/runtimeDeployments.ts
|
|
10
10
|
var normalizeId = (value, label) => {
|
|
@@ -29,12 +29,34 @@ var getRuntimeDeployment = async (userName, deploymentId) => {
|
|
|
29
29
|
return isRuntimeDeployment(value) ? value : null;
|
|
30
30
|
};
|
|
31
31
|
var saveRuntimeDeployment = async (userName, deployment) => {
|
|
32
|
+
const hasVersionedStrategies = deployment.strategies.some(
|
|
33
|
+
(strategy) => strategy.releaseVersion != null
|
|
34
|
+
);
|
|
35
|
+
if (hasVersionedStrategies && deployment.strategies.some((strategy) => strategy.releaseVersion == null)) {
|
|
36
|
+
throw new Error("A deployment cannot mix legacy configs and releases");
|
|
37
|
+
}
|
|
38
|
+
const strategies = deployment.strategies.map(
|
|
39
|
+
(strategy) => {
|
|
40
|
+
if (!hasVersionedStrategies) return strategy;
|
|
41
|
+
if (!Number.isSafeInteger(strategy.releaseVersion) || !strategy.releaseVersion || strategy.config && Object.keys(strategy.config).length) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
`Invalid versioned strategy reference: ${strategy.strategyName}`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
strategyName: strategy.strategyName,
|
|
48
|
+
releaseVersion: strategy.releaseVersion,
|
|
49
|
+
controlState: strategy.controlState === "entries_paused" ? "entries_paused" : "active"
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
);
|
|
32
53
|
const normalized = {
|
|
33
54
|
...deployment,
|
|
34
55
|
id: normalizeId(deployment.id, "Deployment id"),
|
|
35
56
|
label: deployment.label.trim(),
|
|
36
57
|
provider: deployment.provider.trim().toLowerCase(),
|
|
37
|
-
accountId: normalizeId(deployment.accountId, "Account id")
|
|
58
|
+
accountId: normalizeId(deployment.accountId, "Account id"),
|
|
59
|
+
strategies
|
|
38
60
|
};
|
|
39
61
|
await setData(
|
|
40
62
|
redisKeys.runtimeDeployment(userName, normalized.id),
|
|
@@ -284,6 +284,12 @@ var redisKeys = {
|
|
|
284
284
|
backtestConfig: (userName, config) => `users:${userName}:backtests:configs:${config}`,
|
|
285
285
|
strategies: (userName) => `users:${userName}:strategies`,
|
|
286
286
|
strategyConfig: (userName, strategyName, configId = "config") => `users:${userName}:strategies:${strategyName}:${configId}`,
|
|
287
|
+
runtimeStrategyDraft: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:draft`,
|
|
288
|
+
runtimeStrategyReleases: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:releases:`,
|
|
289
|
+
runtimeStrategyRelease: (userName, strategyName, releaseVersion) => `users:${userName}:strategies:${strategyName}:releases:${releaseVersion}`,
|
|
290
|
+
runtimeStrategyReleaseSequence: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:release-seq`,
|
|
291
|
+
runtimeStrategyControlEvents: (userName) => `users:${userName}:runtime:strategy-control-events:`,
|
|
292
|
+
runtimeStrategyControlEvent: (userName, eventId) => `users:${userName}:runtime:strategy-control-events:${eventId}`,
|
|
287
293
|
strategyResults: (userName, strategyName) => `users:${userName}:strategies:${strategyName}:results`,
|
|
288
294
|
strategyCharts: (userName, mode) => `users:${userName}:strategies:charts:${mode}`,
|
|
289
295
|
strategyChartCards: (userName, mode) => `users:${userName}:strategies:charts:${mode}:cards:`,
|
|
@@ -342,7 +348,7 @@ var redisKeys = {
|
|
|
342
348
|
|
|
343
349
|
// src/runtimeStrategyConfigs.ts
|
|
344
350
|
var RESERVED_STRATEGY_NAMES = /* @__PURE__ */ new Set(["charts"]);
|
|
345
|
-
var RESERVED_CONFIG_IDS = /* @__PURE__ */ new Set(["results"]);
|
|
351
|
+
var RESERVED_CONFIG_IDS = /* @__PURE__ */ new Set(["results", "draft", "release-seq"]);
|
|
346
352
|
var isStrategyConfig = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
347
353
|
var resolveStrategyConfigIdentityByKey = (userName, key) => {
|
|
348
354
|
const parts = key.split(":");
|
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
getKeys,
|
|
4
4
|
redisKeys,
|
|
5
5
|
setData
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-RZTVC4ZL.mjs";
|
|
7
7
|
|
|
8
8
|
// src/runtimeStrategyConfigs.ts
|
|
9
9
|
var RESERVED_STRATEGY_NAMES = /* @__PURE__ */ new Set(["charts"]);
|
|
10
|
-
var RESERVED_CONFIG_IDS = /* @__PURE__ */ new Set(["results"]);
|
|
10
|
+
var RESERVED_CONFIG_IDS = /* @__PURE__ */ new Set(["results", "draft", "release-seq"]);
|
|
11
11
|
var isStrategyConfig = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
12
12
|
var resolveStrategyConfigIdentityByKey = (userName, key) => {
|
|
13
13
|
const parts = key.split(":");
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { StrategyConfig, RuntimeStrategyDraft, RuntimeStrategyRelease, RuntimeStrategyControlState, RuntimeStrategyControlEvent } from '@tradejs/types';
|
|
2
|
+
|
|
3
|
+
declare const assertRuntimeStrategyReleaseConfig: (config: StrategyConfig) => void;
|
|
4
|
+
declare const verifyRuntimeStrategyRelease: (value: unknown) => RuntimeStrategyRelease;
|
|
5
|
+
declare const getRuntimeStrategyDraft: (userName: string, strategyName: string) => Promise<RuntimeStrategyDraft | null>;
|
|
6
|
+
declare const saveRuntimeStrategyDraft: ({ userName, strategyName, config, baseReleaseVersion, updatedBy, }: {
|
|
7
|
+
userName: string;
|
|
8
|
+
strategyName: string;
|
|
9
|
+
config: StrategyConfig;
|
|
10
|
+
baseReleaseVersion?: number | null;
|
|
11
|
+
updatedBy: string;
|
|
12
|
+
}) => Promise<RuntimeStrategyDraft>;
|
|
13
|
+
declare const getRuntimeStrategyRelease: (userName: string, strategyName: string, releaseVersion: number) => Promise<RuntimeStrategyRelease | null>;
|
|
14
|
+
declare const listRuntimeStrategyReleases: (userName: string, strategyName: string) => Promise<RuntimeStrategyRelease[]>;
|
|
15
|
+
declare const publishRuntimeStrategyRelease: ({ userName, strategyName, config, strategyPackage, strategyPackageVersion, runtimePackageVersion, createdBy, }: {
|
|
16
|
+
userName: string;
|
|
17
|
+
strategyName: string;
|
|
18
|
+
config: StrategyConfig;
|
|
19
|
+
strategyPackage?: string | null;
|
|
20
|
+
strategyPackageVersion?: string | null;
|
|
21
|
+
runtimePackageVersion?: string | null;
|
|
22
|
+
createdBy: string;
|
|
23
|
+
}) => Promise<RuntimeStrategyRelease>;
|
|
24
|
+
declare const recordRuntimeStrategyControlEvent: ({ userName, deploymentId, strategyName, releaseVersion, previousState, nextState, createdBy, }: {
|
|
25
|
+
userName: string;
|
|
26
|
+
deploymentId: string;
|
|
27
|
+
strategyName: string;
|
|
28
|
+
releaseVersion: number;
|
|
29
|
+
previousState: RuntimeStrategyControlState;
|
|
30
|
+
nextState: RuntimeStrategyControlState;
|
|
31
|
+
createdBy: string;
|
|
32
|
+
}) => Promise<RuntimeStrategyControlEvent>;
|
|
33
|
+
|
|
34
|
+
export { assertRuntimeStrategyReleaseConfig, getRuntimeStrategyDraft, getRuntimeStrategyRelease, listRuntimeStrategyReleases, publishRuntimeStrategyRelease, recordRuntimeStrategyControlEvent, saveRuntimeStrategyDraft, verifyRuntimeStrategyRelease };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { StrategyConfig, RuntimeStrategyDraft, RuntimeStrategyRelease, RuntimeStrategyControlState, RuntimeStrategyControlEvent } from '@tradejs/types';
|
|
2
|
+
|
|
3
|
+
declare const assertRuntimeStrategyReleaseConfig: (config: StrategyConfig) => void;
|
|
4
|
+
declare const verifyRuntimeStrategyRelease: (value: unknown) => RuntimeStrategyRelease;
|
|
5
|
+
declare const getRuntimeStrategyDraft: (userName: string, strategyName: string) => Promise<RuntimeStrategyDraft | null>;
|
|
6
|
+
declare const saveRuntimeStrategyDraft: ({ userName, strategyName, config, baseReleaseVersion, updatedBy, }: {
|
|
7
|
+
userName: string;
|
|
8
|
+
strategyName: string;
|
|
9
|
+
config: StrategyConfig;
|
|
10
|
+
baseReleaseVersion?: number | null;
|
|
11
|
+
updatedBy: string;
|
|
12
|
+
}) => Promise<RuntimeStrategyDraft>;
|
|
13
|
+
declare const getRuntimeStrategyRelease: (userName: string, strategyName: string, releaseVersion: number) => Promise<RuntimeStrategyRelease | null>;
|
|
14
|
+
declare const listRuntimeStrategyReleases: (userName: string, strategyName: string) => Promise<RuntimeStrategyRelease[]>;
|
|
15
|
+
declare const publishRuntimeStrategyRelease: ({ userName, strategyName, config, strategyPackage, strategyPackageVersion, runtimePackageVersion, createdBy, }: {
|
|
16
|
+
userName: string;
|
|
17
|
+
strategyName: string;
|
|
18
|
+
config: StrategyConfig;
|
|
19
|
+
strategyPackage?: string | null;
|
|
20
|
+
strategyPackageVersion?: string | null;
|
|
21
|
+
runtimePackageVersion?: string | null;
|
|
22
|
+
createdBy: string;
|
|
23
|
+
}) => Promise<RuntimeStrategyRelease>;
|
|
24
|
+
declare const recordRuntimeStrategyControlEvent: ({ userName, deploymentId, strategyName, releaseVersion, previousState, nextState, createdBy, }: {
|
|
25
|
+
userName: string;
|
|
26
|
+
deploymentId: string;
|
|
27
|
+
strategyName: string;
|
|
28
|
+
releaseVersion: number;
|
|
29
|
+
previousState: RuntimeStrategyControlState;
|
|
30
|
+
nextState: RuntimeStrategyControlState;
|
|
31
|
+
createdBy: string;
|
|
32
|
+
}) => Promise<RuntimeStrategyControlEvent>;
|
|
33
|
+
|
|
34
|
+
export { assertRuntimeStrategyReleaseConfig, getRuntimeStrategyDraft, getRuntimeStrategyRelease, listRuntimeStrategyReleases, publishRuntimeStrategyRelease, recordRuntimeStrategyControlEvent, saveRuntimeStrategyDraft, verifyRuntimeStrategyRelease };
|