@tradejs/cli 3.1.0 → 3.1.2

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.
@@ -0,0 +1,395 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/scripts/runtimeConfig.ts
31
+ var runtimeConfig_exports = {};
32
+ __export(runtimeConfig_exports, {
33
+ buildBootstrapRuntimeDeployment: () => buildBootstrapRuntimeDeployment,
34
+ main: () => main,
35
+ runtimeConfig: () => runtimeConfig
36
+ });
37
+ module.exports = __toCommonJS(runtimeConfig_exports);
38
+ var import_config = require("dotenv/config");
39
+ var import_promises = require("fs/promises");
40
+ var import_node_path = __toESM(require("path"));
41
+ var import_runtimeDeployments = require("@tradejs/infra/runtimeDeployments");
42
+ var import_runtimeStrategyConfigs = require("@tradejs/infra/runtimeStrategyConfigs");
43
+ var import_runtimeStrategyReleases = require("@tradejs/infra/runtimeStrategyReleases");
44
+ var import_runtimeStrategies = require("@tradejs/node/runtimeStrategies");
45
+ var import_strategies = require("@tradejs/node/strategies");
46
+ var argv = process.argv.slice(2);
47
+ var action = argv[0] ?? "inspect";
48
+ var option = (name) => {
49
+ const index = argv.indexOf(`--${name}`);
50
+ return index >= 0 ? argv[index + 1] : void 0;
51
+ };
52
+ var hasFlag = (name) => argv.includes(`--${name}`);
53
+ var required = (name) => {
54
+ const value = String(option(name) ?? "").trim();
55
+ if (!value) throw new Error(`--${name} is required`);
56
+ return value;
57
+ };
58
+ var projectRoot = String(process.env.PROJECT_CWD || process.cwd()).trim() || process.cwd();
59
+ var userName = String(option("user") ?? process.env.USER_NAME ?? "root");
60
+ var OPERATIONAL_CONFIG_KEYS = [
61
+ "ACCOUNT_ID",
62
+ "AI_REPLAY_ANALYSES",
63
+ "DEPLOYMENT_ID",
64
+ "ENABLE",
65
+ "ENV",
66
+ "MAKE_ORDERS",
67
+ "RECORD_RUNTIME_TRADES",
68
+ "configId"
69
+ ];
70
+ var toReleaseConfig = async (strategyName, sourceConfig) => {
71
+ const defaults = await (0, import_strategies.getStrategyDefaults)(strategyName, projectRoot) ?? {};
72
+ const config = { ...defaults, ...sourceConfig };
73
+ for (const key of OPERATIONAL_CONFIG_KEYS) delete config[key];
74
+ return config;
75
+ };
76
+ var writeMigrationBackup = async (payload) => {
77
+ const directory = import_node_path.default.join(projectRoot, "data", "runtime-config-backups");
78
+ await (0, import_promises.mkdir)(directory, { recursive: true });
79
+ const backupPath = import_node_path.default.join(
80
+ directory,
81
+ `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.json`
82
+ );
83
+ await (0, import_promises.writeFile)(backupPath, `${JSON.stringify(payload, null, 2)}
84
+ `, {
85
+ flag: "wx"
86
+ });
87
+ return backupPath;
88
+ };
89
+ var publish = async ({
90
+ strategyName,
91
+ sourceConfig
92
+ }) => {
93
+ const config = await toReleaseConfig(strategyName, sourceConfig);
94
+ const metadata = await (0, import_runtimeStrategies.getRuntimeStrategyPackageMetadata)({
95
+ strategyName,
96
+ projectRoot
97
+ });
98
+ return (0, import_runtimeStrategyReleases.publishRuntimeStrategyRelease)({
99
+ userName,
100
+ strategyName,
101
+ config,
102
+ ...metadata,
103
+ createdBy: `cli:${userName}`
104
+ });
105
+ };
106
+ var buildBootstrapRuntimeDeployment = ({
107
+ deploymentId,
108
+ label,
109
+ connectorName,
110
+ provider,
111
+ accountId,
112
+ strategyName,
113
+ releaseVersion,
114
+ config
115
+ }) => ({
116
+ id: deploymentId,
117
+ label,
118
+ connectorName,
119
+ provider,
120
+ accountId,
121
+ universe: config.UNIVERSE,
122
+ interval: String(config.INTERVAL),
123
+ enabled: true,
124
+ strategies: [
125
+ {
126
+ strategyName,
127
+ releaseVersion,
128
+ controlState: "entries_paused"
129
+ }
130
+ ]
131
+ });
132
+ var bootstrap = async () => {
133
+ const strategyName = required("strategy");
134
+ const deploymentId = required("deployment");
135
+ const accountId = required("account");
136
+ const connectorName = option("connector") ?? "bybit";
137
+ const provider = option("provider") ?? connectorName;
138
+ const label = option("label") ?? deploymentId;
139
+ const configFile = import_node_path.default.resolve(projectRoot, required("file"));
140
+ const sourceConfig = JSON.parse(
141
+ await (0, import_promises.readFile)(configFile, "utf8")
142
+ );
143
+ const existingDeployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(userName, deploymentId);
144
+ if (existingDeployment) {
145
+ throw new Error(
146
+ `Deployment already exists: ${deploymentId}; publish a release and switch its pointer instead`
147
+ );
148
+ }
149
+ const releaseConfig = await toReleaseConfig(strategyName, sourceConfig);
150
+ const previewDeployment = buildBootstrapRuntimeDeployment({
151
+ deploymentId,
152
+ label,
153
+ connectorName,
154
+ provider,
155
+ accountId,
156
+ strategyName,
157
+ releaseVersion: 1,
158
+ config: releaseConfig
159
+ });
160
+ if (!hasFlag("write")) {
161
+ console.log(
162
+ JSON.stringify(
163
+ {
164
+ dryRun: true,
165
+ releaseConfig,
166
+ deployment: {
167
+ ...previewDeployment,
168
+ strategies: previewDeployment.strategies.map((strategy) => ({
169
+ ...strategy,
170
+ releaseVersion: "<allocated on write>"
171
+ }))
172
+ }
173
+ },
174
+ null,
175
+ 2
176
+ )
177
+ );
178
+ return;
179
+ }
180
+ const backupPath = await writeMigrationBackup({
181
+ userName,
182
+ capturedAt: Date.now(),
183
+ reason: "bootstrap",
184
+ sourceConfig
185
+ });
186
+ const release = await publish({ strategyName, sourceConfig });
187
+ const deployment = await (0, import_runtimeDeployments.saveRuntimeDeployment)(
188
+ userName,
189
+ buildBootstrapRuntimeDeployment({
190
+ deploymentId,
191
+ label,
192
+ connectorName,
193
+ provider,
194
+ accountId,
195
+ strategyName,
196
+ releaseVersion: release.releaseVersion,
197
+ config: release.config
198
+ })
199
+ );
200
+ console.log(
201
+ JSON.stringify(
202
+ { bootstrapped: true, backupPath, release, deployment },
203
+ null,
204
+ 2
205
+ )
206
+ );
207
+ };
208
+ var migrate = async () => {
209
+ const strategyName = required("strategy");
210
+ const configId = option("config") ?? "config";
211
+ const deploymentId = required("deployment");
212
+ const [sourceConfig, deployment] = await Promise.all([
213
+ (0, import_runtimeStrategyConfigs.getRuntimeStrategyConfig)(userName, strategyName, configId),
214
+ (0, import_runtimeDeployments.getRuntimeDeployment)(userName, deploymentId)
215
+ ]);
216
+ if (!sourceConfig) {
217
+ throw new Error(`Legacy config not found: ${strategyName}:${configId}`);
218
+ }
219
+ if (!deployment) throw new Error(`Deployment not found: ${deploymentId}`);
220
+ const reference = deployment.strategies.find(
221
+ (strategy) => strategy.strategyName === strategyName
222
+ );
223
+ if (!reference) {
224
+ throw new Error(`${strategyName} is not bound to ${deploymentId}`);
225
+ }
226
+ const preview = {
227
+ source: { configId, config: sourceConfig },
228
+ releaseConfig: await toReleaseConfig(strategyName, sourceConfig),
229
+ deployment: {
230
+ id: deployment.id,
231
+ accountId: deployment.accountId,
232
+ strategy: {
233
+ strategyName,
234
+ releaseVersion: "<allocated on write>",
235
+ controlState: "entries_paused"
236
+ }
237
+ }
238
+ };
239
+ if (!hasFlag("write")) {
240
+ console.log(JSON.stringify({ dryRun: true, ...preview }, null, 2));
241
+ return;
242
+ }
243
+ const backupPath = await writeMigrationBackup({
244
+ userName,
245
+ capturedAt: Date.now(),
246
+ deployment,
247
+ legacyConfig: sourceConfig
248
+ });
249
+ const release = await publish({ strategyName, sourceConfig });
250
+ const updatedDeployment = {
251
+ ...deployment,
252
+ strategies: deployment.strategies.map(
253
+ (strategy) => strategy.strategyName === strategyName ? {
254
+ strategyName,
255
+ releaseVersion: release.releaseVersion,
256
+ controlState: "entries_paused"
257
+ } : strategy
258
+ )
259
+ };
260
+ await (0, import_runtimeDeployments.saveRuntimeDeployment)(userName, updatedDeployment);
261
+ console.log(
262
+ JSON.stringify(
263
+ { migrated: true, backupPath, release, deployment: updatedDeployment },
264
+ null,
265
+ 2
266
+ )
267
+ );
268
+ };
269
+ var publishDraft = async () => {
270
+ const strategyName = required("strategy");
271
+ const draft = await (0, import_runtimeStrategyReleases.getRuntimeStrategyDraft)(userName, strategyName);
272
+ if (!draft) throw new Error(`Draft not found: ${strategyName}`);
273
+ const release = await publish({ strategyName, sourceConfig: draft.config });
274
+ console.log(JSON.stringify({ release }, null, 2));
275
+ };
276
+ var updateControlState = async (nextState) => {
277
+ const strategyName = required("strategy");
278
+ const deploymentId = required("deployment");
279
+ const deployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(userName, deploymentId);
280
+ if (!deployment) throw new Error(`Deployment not found: ${deploymentId}`);
281
+ const reference = deployment.strategies.find(
282
+ (strategy) => strategy.strategyName === strategyName
283
+ );
284
+ if (!reference?.releaseVersion) {
285
+ throw new Error(`${strategyName} is not a versioned deployment reference`);
286
+ }
287
+ const previousState = reference.controlState ?? "active";
288
+ const updated = await (0, import_runtimeDeployments.saveRuntimeDeployment)(userName, {
289
+ ...deployment,
290
+ strategies: deployment.strategies.map(
291
+ (strategy) => strategy.strategyName === strategyName ? { ...strategy, controlState: nextState } : strategy
292
+ )
293
+ });
294
+ const event = previousState === nextState ? null : await (0, import_runtimeStrategyReleases.recordRuntimeStrategyControlEvent)({
295
+ userName,
296
+ deploymentId,
297
+ strategyName,
298
+ releaseVersion: reference.releaseVersion,
299
+ previousState,
300
+ nextState,
301
+ createdBy: `cli:${userName}`
302
+ });
303
+ console.log(JSON.stringify({ deployment: updated, event }, null, 2));
304
+ };
305
+ var rollback = async () => {
306
+ const strategyName = required("strategy");
307
+ const deploymentId = required("deployment");
308
+ const releaseVersion = Number(required("release"));
309
+ if (!Number.isSafeInteger(releaseVersion) || releaseVersion <= 0) {
310
+ throw new Error("--release must be a positive integer");
311
+ }
312
+ const deployment = await (0, import_runtimeDeployments.getRuntimeDeployment)(userName, deploymentId);
313
+ if (!deployment) throw new Error(`Deployment not found: ${deploymentId}`);
314
+ const release = (await (0, import_runtimeStrategyReleases.listRuntimeStrategyReleases)(userName, strategyName)).find((candidate) => candidate.releaseVersion === releaseVersion);
315
+ if (!release)
316
+ throw new Error(`Release not found: ${strategyName} v${releaseVersion}`);
317
+ const backupPath = await writeMigrationBackup({
318
+ userName,
319
+ capturedAt: Date.now(),
320
+ deployment,
321
+ reason: "rollback"
322
+ });
323
+ const updated = await (0, import_runtimeDeployments.saveRuntimeDeployment)(userName, {
324
+ ...deployment,
325
+ strategies: deployment.strategies.map(
326
+ (strategy) => strategy.strategyName === strategyName ? {
327
+ strategyName,
328
+ releaseVersion,
329
+ controlState: "entries_paused"
330
+ } : strategy
331
+ )
332
+ });
333
+ console.log(JSON.stringify({ backupPath, deployment: updated }, null, 2));
334
+ };
335
+ var verify = async () => {
336
+ const deployments = await (0, import_runtimeDeployments.listRuntimeDeployments)(userName);
337
+ const selected = option("deployment") ? deployments.filter((deployment) => deployment.id === option("deployment")) : deployments;
338
+ const results = [];
339
+ for (const deployment of selected) {
340
+ try {
341
+ const strategies = await (0, import_runtimeStrategies.loadResolvedRuntimeStrategies)({
342
+ userName,
343
+ projectRoot,
344
+ deployment,
345
+ connectorName: deployment.connectorName
346
+ });
347
+ results.push({
348
+ deploymentId: deployment.id,
349
+ ok: true,
350
+ strategies: strategies.map((strategy) => ({
351
+ strategyName: strategy.strategyName,
352
+ releaseVersion: strategy.releaseVersion,
353
+ controlState: strategy.controlState,
354
+ interval: strategy.interval,
355
+ universe: strategy.universe,
356
+ accountId: strategy.accountId
357
+ }))
358
+ });
359
+ } catch (error) {
360
+ results.push({
361
+ deploymentId: deployment.id,
362
+ ok: false,
363
+ error: error instanceof Error ? error.message : String(error)
364
+ });
365
+ }
366
+ }
367
+ console.log(JSON.stringify({ userName, results }, null, 2));
368
+ if (results.some((result) => !result.ok)) process.exitCode = 1;
369
+ };
370
+ var inspect = async () => {
371
+ const strategyName = option("strategy");
372
+ const deployments = await (0, import_runtimeDeployments.listRuntimeDeployments)(userName);
373
+ const releases = strategyName ? await (0, import_runtimeStrategyReleases.listRuntimeStrategyReleases)(userName, strategyName) : void 0;
374
+ console.log(JSON.stringify({ userName, deployments, releases }, null, 2));
375
+ };
376
+ var runtimeConfig = async () => {
377
+ if (action === "bootstrap") return bootstrap();
378
+ if (action === "migrate") return migrate();
379
+ if (action === "publish-draft") return publishDraft();
380
+ if (action === "verify") return verify();
381
+ if (action === "pause") return updateControlState("entries_paused");
382
+ if (action === "resume") return updateControlState("active");
383
+ if (action === "rollback") return rollback();
384
+ if (action === "inspect") return inspect();
385
+ throw new Error(
386
+ "Usage: tradejs runtime-config inspect|verify|bootstrap|migrate|publish-draft|pause|resume|rollback"
387
+ );
388
+ };
389
+ var main = runtimeConfig;
390
+ // Annotate the CommonJS export names for ESM import in node:
391
+ 0 && (module.exports = {
392
+ buildBootstrapRuntimeDeployment,
393
+ main,
394
+ runtimeConfig
395
+ });
@@ -573,7 +573,7 @@ var import_promises2 = __toESM(require("fs/promises"));
573
573
  var import_node_path2 = __toESM(require("path"));
574
574
 
575
575
  // src/lib/runtimeLineage.ts
576
- var runtimeLineageKey = (lineage) => [
576
+ var runtimeLineageKey = (lineage) => lineage.schemaVersion === 2 ? ["v2", lineage.releaseVersion].join(":") : [
577
577
  lineage.schemaVersion,
578
578
  lineage.compositionId ?? "unbound-composition",
579
579
  lineage.gitSha ?? "unknown",
@@ -4808,7 +4808,7 @@ var buildRuntimeModeStrategyConfig = ({
4808
4808
  ...strategyConfig,
4809
4809
  ENV: env,
4810
4810
  MAKE_ORDERS: makeOrders,
4811
- INTERVAL: interval2,
4811
+ INTERVAL: strategyConfig.INTERVAL ?? interval2,
4812
4812
  ...typeof recordRuntimeTrades === "boolean" ? { RECORD_RUNTIME_TRADES: recordRuntimeTrades } : {},
4813
4813
  ...aiReplayAnalyses?.length ? { AI_REPLAY_ANALYSES: aiReplayAnalyses } : {}
4814
4814
  });