@tradejs/infra 2.0.19 → 2.0.21
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/ai.js +36 -20
- package/dist/ai.mjs +36 -20
- package/dist/coreResearch.d.mts +20 -0
- package/dist/coreResearch.d.ts +20 -0
- package/dist/coreResearch.js +89 -0
- package/dist/coreResearch.mjs +48 -0
- package/dist/ml.mjs +3 -3
- package/dist/strategyReleaseEvidence.d.mts +17 -0
- package/dist/strategyReleaseEvidence.d.ts +17 -0
- package/dist/strategyReleaseEvidence.js +140 -0
- package/dist/strategyReleaseEvidence.mjs +109 -0
- package/dist/timescale.mjs +10 -10
- package/package.json +12 -2
package/dist/ai.js
CHANGED
|
@@ -134,21 +134,32 @@ var getRunIdFromAiChunkFileName = (strategyName, fileName) => {
|
|
|
134
134
|
var appendAiDatasetRow = async (params) => {
|
|
135
135
|
const { strategyName, chunkId, row, outDir = DEFAULT_DIR } = params;
|
|
136
136
|
const filePath = getAiChunkFilePath(strategyName, chunkId, outDir);
|
|
137
|
-
let
|
|
138
|
-
if (!
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
137
|
+
let statePromise = writerByPath.get(filePath);
|
|
138
|
+
if (!statePromise) {
|
|
139
|
+
statePromise = (async () => {
|
|
140
|
+
await import_promises2.default.mkdir(outDir, { recursive: true });
|
|
141
|
+
const stream = (0, import_fs2.createWriteStream)(filePath, {
|
|
142
|
+
encoding: "utf8",
|
|
143
|
+
flags: "a"
|
|
144
|
+
});
|
|
145
|
+
return {
|
|
146
|
+
filePath,
|
|
147
|
+
stream,
|
|
148
|
+
buffer: [],
|
|
149
|
+
writeQueue: Promise.resolve(),
|
|
150
|
+
closed: false
|
|
151
|
+
};
|
|
152
|
+
})();
|
|
153
|
+
writerByPath.set(filePath, statePromise);
|
|
154
|
+
}
|
|
155
|
+
let state;
|
|
156
|
+
try {
|
|
157
|
+
state = await statePromise;
|
|
158
|
+
} catch (error) {
|
|
159
|
+
if (writerByPath.get(filePath) === statePromise) {
|
|
160
|
+
writerByPath.delete(filePath);
|
|
161
|
+
}
|
|
162
|
+
throw error;
|
|
152
163
|
}
|
|
153
164
|
if (state.closed) {
|
|
154
165
|
throw new Error(`AI dataset writer is closed: ${filePath}`);
|
|
@@ -171,10 +182,12 @@ var flushState = async (state) => {
|
|
|
171
182
|
}
|
|
172
183
|
};
|
|
173
184
|
var flushAiDatasetWriter = async (filePath) => {
|
|
174
|
-
const
|
|
175
|
-
if (!
|
|
185
|
+
const statePromise = writerByPath.get(filePath);
|
|
186
|
+
if (!statePromise) {
|
|
176
187
|
return;
|
|
177
188
|
}
|
|
189
|
+
const state = await statePromise;
|
|
190
|
+
if (state.closed) return;
|
|
178
191
|
state.writeQueue = state.writeQueue.then(() => flushState(state));
|
|
179
192
|
await state.writeQueue;
|
|
180
193
|
};
|
|
@@ -191,13 +204,16 @@ var closeState = async (state) => {
|
|
|
191
204
|
]);
|
|
192
205
|
};
|
|
193
206
|
var closeAiDatasetWriter = async (filePath) => {
|
|
194
|
-
const
|
|
195
|
-
if (!
|
|
207
|
+
const statePromise = writerByPath.get(filePath);
|
|
208
|
+
if (!statePromise) {
|
|
196
209
|
return;
|
|
197
210
|
}
|
|
211
|
+
const state = await statePromise;
|
|
198
212
|
state.writeQueue = state.writeQueue.then(() => closeState(state));
|
|
199
213
|
await state.writeQueue;
|
|
200
|
-
writerByPath.
|
|
214
|
+
if (writerByPath.get(filePath) === statePromise) {
|
|
215
|
+
writerByPath.delete(filePath);
|
|
216
|
+
}
|
|
201
217
|
};
|
|
202
218
|
var closeAllAiDatasetWriters = async () => {
|
|
203
219
|
const filePaths = [...writerByPath.keys()];
|
package/dist/ai.mjs
CHANGED
|
@@ -35,21 +35,32 @@ var getRunIdFromAiChunkFileName = (strategyName, fileName) => {
|
|
|
35
35
|
var appendAiDatasetRow = async (params) => {
|
|
36
36
|
const { strategyName, chunkId, row, outDir = DEFAULT_DIR } = params;
|
|
37
37
|
const filePath = getAiChunkFilePath(strategyName, chunkId, outDir);
|
|
38
|
-
let
|
|
39
|
-
if (!
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
38
|
+
let statePromise = writerByPath.get(filePath);
|
|
39
|
+
if (!statePromise) {
|
|
40
|
+
statePromise = (async () => {
|
|
41
|
+
await fs.mkdir(outDir, { recursive: true });
|
|
42
|
+
const stream = createWriteStream(filePath, {
|
|
43
|
+
encoding: "utf8",
|
|
44
|
+
flags: "a"
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
filePath,
|
|
48
|
+
stream,
|
|
49
|
+
buffer: [],
|
|
50
|
+
writeQueue: Promise.resolve(),
|
|
51
|
+
closed: false
|
|
52
|
+
};
|
|
53
|
+
})();
|
|
54
|
+
writerByPath.set(filePath, statePromise);
|
|
55
|
+
}
|
|
56
|
+
let state;
|
|
57
|
+
try {
|
|
58
|
+
state = await statePromise;
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (writerByPath.get(filePath) === statePromise) {
|
|
61
|
+
writerByPath.delete(filePath);
|
|
62
|
+
}
|
|
63
|
+
throw error;
|
|
53
64
|
}
|
|
54
65
|
if (state.closed) {
|
|
55
66
|
throw new Error(`AI dataset writer is closed: ${filePath}`);
|
|
@@ -72,10 +83,12 @@ var flushState = async (state) => {
|
|
|
72
83
|
}
|
|
73
84
|
};
|
|
74
85
|
var flushAiDatasetWriter = async (filePath) => {
|
|
75
|
-
const
|
|
76
|
-
if (!
|
|
86
|
+
const statePromise = writerByPath.get(filePath);
|
|
87
|
+
if (!statePromise) {
|
|
77
88
|
return;
|
|
78
89
|
}
|
|
90
|
+
const state = await statePromise;
|
|
91
|
+
if (state.closed) return;
|
|
79
92
|
state.writeQueue = state.writeQueue.then(() => flushState(state));
|
|
80
93
|
await state.writeQueue;
|
|
81
94
|
};
|
|
@@ -92,13 +105,16 @@ var closeState = async (state) => {
|
|
|
92
105
|
]);
|
|
93
106
|
};
|
|
94
107
|
var closeAiDatasetWriter = async (filePath) => {
|
|
95
|
-
const
|
|
96
|
-
if (!
|
|
108
|
+
const statePromise = writerByPath.get(filePath);
|
|
109
|
+
if (!statePromise) {
|
|
97
110
|
return;
|
|
98
111
|
}
|
|
112
|
+
const state = await statePromise;
|
|
99
113
|
state.writeQueue = state.writeQueue.then(() => closeState(state));
|
|
100
114
|
await state.writeQueue;
|
|
101
|
-
writerByPath.
|
|
115
|
+
if (writerByPath.get(filePath) === statePromise) {
|
|
116
|
+
writerByPath.delete(filePath);
|
|
117
|
+
}
|
|
102
118
|
};
|
|
103
119
|
var closeAllAiDatasetWriters = async () => {
|
|
104
120
|
const filePaths = [...writerByPath.keys()];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CoreResearchTraceEvent } from '@tradejs/types';
|
|
2
|
+
|
|
3
|
+
declare const getCoreResearchTraceFilePath: (params: {
|
|
4
|
+
strategyName: string;
|
|
5
|
+
chunkId: string;
|
|
6
|
+
outDir?: string;
|
|
7
|
+
}) => string;
|
|
8
|
+
declare const listCoreResearchTraceFiles: (params: {
|
|
9
|
+
strategyName: string;
|
|
10
|
+
runId: string;
|
|
11
|
+
outDir?: string;
|
|
12
|
+
}) => Promise<string[]>;
|
|
13
|
+
declare const appendCoreResearchTraceEvent: (params: {
|
|
14
|
+
strategyName: string;
|
|
15
|
+
chunkId: string;
|
|
16
|
+
event: CoreResearchTraceEvent;
|
|
17
|
+
outDir?: string;
|
|
18
|
+
}) => Promise<string>;
|
|
19
|
+
|
|
20
|
+
export { appendCoreResearchTraceEvent, getCoreResearchTraceFilePath, listCoreResearchTraceFiles };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CoreResearchTraceEvent } from '@tradejs/types';
|
|
2
|
+
|
|
3
|
+
declare const getCoreResearchTraceFilePath: (params: {
|
|
4
|
+
strategyName: string;
|
|
5
|
+
chunkId: string;
|
|
6
|
+
outDir?: string;
|
|
7
|
+
}) => string;
|
|
8
|
+
declare const listCoreResearchTraceFiles: (params: {
|
|
9
|
+
strategyName: string;
|
|
10
|
+
runId: string;
|
|
11
|
+
outDir?: string;
|
|
12
|
+
}) => Promise<string[]>;
|
|
13
|
+
declare const appendCoreResearchTraceEvent: (params: {
|
|
14
|
+
strategyName: string;
|
|
15
|
+
chunkId: string;
|
|
16
|
+
event: CoreResearchTraceEvent;
|
|
17
|
+
outDir?: string;
|
|
18
|
+
}) => Promise<string>;
|
|
19
|
+
|
|
20
|
+
export { appendCoreResearchTraceEvent, getCoreResearchTraceFilePath, listCoreResearchTraceFiles };
|
|
@@ -0,0 +1,89 @@
|
|
|
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/coreResearch.ts
|
|
31
|
+
var coreResearch_exports = {};
|
|
32
|
+
__export(coreResearch_exports, {
|
|
33
|
+
appendCoreResearchTraceEvent: () => appendCoreResearchTraceEvent,
|
|
34
|
+
getCoreResearchTraceFilePath: () => getCoreResearchTraceFilePath,
|
|
35
|
+
listCoreResearchTraceFiles: () => listCoreResearchTraceFiles
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(coreResearch_exports);
|
|
38
|
+
|
|
39
|
+
// src/coreResearchTraceFile.ts
|
|
40
|
+
var import_promises = __toESM(require("fs/promises"));
|
|
41
|
+
var import_node_path = __toESM(require("path"));
|
|
42
|
+
|
|
43
|
+
// src/mlDatasetFile.ts
|
|
44
|
+
var import_node_readline = __toESM(require("readline"));
|
|
45
|
+
var toFileToken = (value) => value.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "_").replace(/^_+|_+$/g, "") || "any";
|
|
46
|
+
|
|
47
|
+
// src/coreResearchTraceFile.ts
|
|
48
|
+
var DEFAULT_DIR = "data/research/core/trace";
|
|
49
|
+
var queueByPath = /* @__PURE__ */ new Map();
|
|
50
|
+
var getCoreResearchTraceFilePath = (params) => import_node_path.default.join(
|
|
51
|
+
params.outDir ?? DEFAULT_DIR,
|
|
52
|
+
`core-research-trace-${toFileToken(params.strategyName)}-chunk-${toFileToken(params.chunkId)}.jsonl`
|
|
53
|
+
);
|
|
54
|
+
var listCoreResearchTraceFiles = async (params) => {
|
|
55
|
+
const outDir = import_node_path.default.resolve(params.outDir ?? DEFAULT_DIR);
|
|
56
|
+
let names = [];
|
|
57
|
+
try {
|
|
58
|
+
names = await import_promises.default.readdir(outDir);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (error.code === "ENOENT") return [];
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
const prefix = `core-research-trace-${toFileToken(params.strategyName)}-chunk-`;
|
|
64
|
+
return names.filter(
|
|
65
|
+
(name) => name.startsWith(prefix) && name.includes(toFileToken(params.runId)) && name.endsWith(".jsonl")
|
|
66
|
+
).sort((left, right) => left < right ? -1 : left > right ? 1 : 0).map((name) => import_node_path.default.join(outDir, name));
|
|
67
|
+
};
|
|
68
|
+
var appendCoreResearchTraceEvent = async (params) => {
|
|
69
|
+
const filePath = getCoreResearchTraceFilePath(params);
|
|
70
|
+
const previous = queueByPath.get(filePath) ?? Promise.resolve();
|
|
71
|
+
const next = previous.then(async () => {
|
|
72
|
+
await import_promises.default.mkdir(import_node_path.default.dirname(filePath), { recursive: true });
|
|
73
|
+
await import_promises.default.appendFile(filePath, `${JSON.stringify(params.event)}
|
|
74
|
+
`, "utf8");
|
|
75
|
+
});
|
|
76
|
+
queueByPath.set(filePath, next);
|
|
77
|
+
try {
|
|
78
|
+
await next;
|
|
79
|
+
} finally {
|
|
80
|
+
if (queueByPath.get(filePath) === next) queueByPath.delete(filePath);
|
|
81
|
+
}
|
|
82
|
+
return filePath;
|
|
83
|
+
};
|
|
84
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
85
|
+
0 && (module.exports = {
|
|
86
|
+
appendCoreResearchTraceEvent,
|
|
87
|
+
getCoreResearchTraceFilePath,
|
|
88
|
+
listCoreResearchTraceFiles
|
|
89
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
toFileToken
|
|
3
|
+
} from "./chunk-RQP5VSTH.mjs";
|
|
4
|
+
|
|
5
|
+
// src/coreResearchTraceFile.ts
|
|
6
|
+
import fs from "fs/promises";
|
|
7
|
+
import path from "path";
|
|
8
|
+
var DEFAULT_DIR = "data/research/core/trace";
|
|
9
|
+
var queueByPath = /* @__PURE__ */ new Map();
|
|
10
|
+
var getCoreResearchTraceFilePath = (params) => path.join(
|
|
11
|
+
params.outDir ?? DEFAULT_DIR,
|
|
12
|
+
`core-research-trace-${toFileToken(params.strategyName)}-chunk-${toFileToken(params.chunkId)}.jsonl`
|
|
13
|
+
);
|
|
14
|
+
var listCoreResearchTraceFiles = async (params) => {
|
|
15
|
+
const outDir = path.resolve(params.outDir ?? DEFAULT_DIR);
|
|
16
|
+
let names = [];
|
|
17
|
+
try {
|
|
18
|
+
names = await fs.readdir(outDir);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
if (error.code === "ENOENT") return [];
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
const prefix = `core-research-trace-${toFileToken(params.strategyName)}-chunk-`;
|
|
24
|
+
return names.filter(
|
|
25
|
+
(name) => name.startsWith(prefix) && name.includes(toFileToken(params.runId)) && name.endsWith(".jsonl")
|
|
26
|
+
).sort((left, right) => left < right ? -1 : left > right ? 1 : 0).map((name) => path.join(outDir, name));
|
|
27
|
+
};
|
|
28
|
+
var appendCoreResearchTraceEvent = async (params) => {
|
|
29
|
+
const filePath = getCoreResearchTraceFilePath(params);
|
|
30
|
+
const previous = queueByPath.get(filePath) ?? Promise.resolve();
|
|
31
|
+
const next = previous.then(async () => {
|
|
32
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
33
|
+
await fs.appendFile(filePath, `${JSON.stringify(params.event)}
|
|
34
|
+
`, "utf8");
|
|
35
|
+
});
|
|
36
|
+
queueByPath.set(filePath, next);
|
|
37
|
+
try {
|
|
38
|
+
await next;
|
|
39
|
+
} finally {
|
|
40
|
+
if (queueByPath.get(filePath) === next) queueByPath.delete(filePath);
|
|
41
|
+
}
|
|
42
|
+
return filePath;
|
|
43
|
+
};
|
|
44
|
+
export {
|
|
45
|
+
appendCoreResearchTraceEvent,
|
|
46
|
+
getCoreResearchTraceFilePath,
|
|
47
|
+
listCoreResearchTraceFiles
|
|
48
|
+
};
|
package/dist/ml.mjs
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
logger
|
|
3
|
+
} from "./chunk-LNFUOXDW.mjs";
|
|
1
4
|
import {
|
|
2
5
|
appendMlDatasetRow,
|
|
3
6
|
closeAllMlDatasetWriters,
|
|
@@ -10,9 +13,6 @@ import {
|
|
|
10
13
|
mergeJsonlFiles,
|
|
11
14
|
toFileToken
|
|
12
15
|
} from "./chunk-RQP5VSTH.mjs";
|
|
13
|
-
import {
|
|
14
|
-
logger
|
|
15
|
-
} from "./chunk-LNFUOXDW.mjs";
|
|
16
16
|
|
|
17
17
|
// src/mlGrpc.ts
|
|
18
18
|
import path from "path";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StrategyEvidenceMarkerPayload, StrategyEvidenceMarkerEnvelope } from '@tradejs/types';
|
|
2
|
+
|
|
3
|
+
declare const canonicalStrategyEvidenceJson: (value: unknown) => string;
|
|
4
|
+
declare const strategyEvidenceSha256: (value: unknown) => string;
|
|
5
|
+
declare const strategyEvidenceFingerprint: (value: unknown) => string;
|
|
6
|
+
/**
|
|
7
|
+
* Fingerprints strategy decision semantics without local/runtime bindings,
|
|
8
|
+
* credentials, config identity, or position-risk scale.
|
|
9
|
+
*/
|
|
10
|
+
declare const strategyLogicConfigFingerprint: (value: unknown) => string;
|
|
11
|
+
declare const strategyEvidenceFileSha256: (filePath: string) => Promise<string>;
|
|
12
|
+
declare const safeStrategyEvidenceSegment: (value: string, fallback?: string) => string;
|
|
13
|
+
declare const compactStrategyEvidenceTimestamp: (timestamp: number) => string;
|
|
14
|
+
declare const createStrategyEvidenceMarkerEnvelope: (payload: StrategyEvidenceMarkerPayload) => StrategyEvidenceMarkerEnvelope;
|
|
15
|
+
declare const verifyStrategyEvidenceMarkerEnvelope: (value: unknown) => StrategyEvidenceMarkerEnvelope;
|
|
16
|
+
|
|
17
|
+
export { canonicalStrategyEvidenceJson, compactStrategyEvidenceTimestamp, createStrategyEvidenceMarkerEnvelope, safeStrategyEvidenceSegment, strategyEvidenceFileSha256, strategyEvidenceFingerprint, strategyEvidenceSha256, strategyLogicConfigFingerprint, verifyStrategyEvidenceMarkerEnvelope };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StrategyEvidenceMarkerPayload, StrategyEvidenceMarkerEnvelope } from '@tradejs/types';
|
|
2
|
+
|
|
3
|
+
declare const canonicalStrategyEvidenceJson: (value: unknown) => string;
|
|
4
|
+
declare const strategyEvidenceSha256: (value: unknown) => string;
|
|
5
|
+
declare const strategyEvidenceFingerprint: (value: unknown) => string;
|
|
6
|
+
/**
|
|
7
|
+
* Fingerprints strategy decision semantics without local/runtime bindings,
|
|
8
|
+
* credentials, config identity, or position-risk scale.
|
|
9
|
+
*/
|
|
10
|
+
declare const strategyLogicConfigFingerprint: (value: unknown) => string;
|
|
11
|
+
declare const strategyEvidenceFileSha256: (filePath: string) => Promise<string>;
|
|
12
|
+
declare const safeStrategyEvidenceSegment: (value: string, fallback?: string) => string;
|
|
13
|
+
declare const compactStrategyEvidenceTimestamp: (timestamp: number) => string;
|
|
14
|
+
declare const createStrategyEvidenceMarkerEnvelope: (payload: StrategyEvidenceMarkerPayload) => StrategyEvidenceMarkerEnvelope;
|
|
15
|
+
declare const verifyStrategyEvidenceMarkerEnvelope: (value: unknown) => StrategyEvidenceMarkerEnvelope;
|
|
16
|
+
|
|
17
|
+
export { canonicalStrategyEvidenceJson, compactStrategyEvidenceTimestamp, createStrategyEvidenceMarkerEnvelope, safeStrategyEvidenceSegment, strategyEvidenceFileSha256, strategyEvidenceFingerprint, strategyEvidenceSha256, strategyLogicConfigFingerprint, verifyStrategyEvidenceMarkerEnvelope };
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/strategyReleaseEvidence.ts
|
|
21
|
+
var strategyReleaseEvidence_exports = {};
|
|
22
|
+
__export(strategyReleaseEvidence_exports, {
|
|
23
|
+
canonicalStrategyEvidenceJson: () => canonicalStrategyEvidenceJson,
|
|
24
|
+
compactStrategyEvidenceTimestamp: () => compactStrategyEvidenceTimestamp,
|
|
25
|
+
createStrategyEvidenceMarkerEnvelope: () => createStrategyEvidenceMarkerEnvelope,
|
|
26
|
+
safeStrategyEvidenceSegment: () => safeStrategyEvidenceSegment,
|
|
27
|
+
strategyEvidenceFileSha256: () => strategyEvidenceFileSha256,
|
|
28
|
+
strategyEvidenceFingerprint: () => strategyEvidenceFingerprint,
|
|
29
|
+
strategyEvidenceSha256: () => strategyEvidenceSha256,
|
|
30
|
+
strategyLogicConfigFingerprint: () => strategyLogicConfigFingerprint,
|
|
31
|
+
verifyStrategyEvidenceMarkerEnvelope: () => verifyStrategyEvidenceMarkerEnvelope
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(strategyReleaseEvidence_exports);
|
|
34
|
+
var import_node_crypto = require("crypto");
|
|
35
|
+
var import_node_fs = require("fs");
|
|
36
|
+
var import_types = require("@tradejs/types");
|
|
37
|
+
var SHA256_RE = /^[a-f0-9]{64}$/;
|
|
38
|
+
var LINEAGE_FINGERPRINT_RE = /^[a-f0-9]{16}$/;
|
|
39
|
+
var MARKER_TYPES = /* @__PURE__ */ new Set([
|
|
40
|
+
"G",
|
|
41
|
+
"L",
|
|
42
|
+
"E",
|
|
43
|
+
"D",
|
|
44
|
+
"P",
|
|
45
|
+
"R"
|
|
46
|
+
]);
|
|
47
|
+
var STRATEGY_LOGIC_BINDING_KEYS = /* @__PURE__ */ new Set([
|
|
48
|
+
"ACCOUNT_ID",
|
|
49
|
+
"DEPLOYMENT_ID",
|
|
50
|
+
"MAX_LOSS_VALUE",
|
|
51
|
+
"configId"
|
|
52
|
+
]);
|
|
53
|
+
var SECRET_CONFIG_KEY_RE = /(?:^|_)(?:API_KEY|API_SECRET|TOKEN|PASSWORD|PRIVATE_KEY)$/i;
|
|
54
|
+
var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
55
|
+
var isString = (value) => typeof value === "string" && value.trim().length > 0;
|
|
56
|
+
var isNumber = (value) => typeof value === "number" && Number.isFinite(value);
|
|
57
|
+
var canonicalStrategyEvidenceJson = (value) => {
|
|
58
|
+
const normalize = (current) => {
|
|
59
|
+
if (Array.isArray(current)) return current.map(normalize);
|
|
60
|
+
const record = asRecord(current);
|
|
61
|
+
if (!record) return current;
|
|
62
|
+
return Object.fromEntries(
|
|
63
|
+
Object.entries(record).filter(([, entry]) => entry !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, normalize(entry)])
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
return JSON.stringify(normalize(value));
|
|
67
|
+
};
|
|
68
|
+
var strategyEvidenceSha256 = (value) => (0, import_node_crypto.createHash)("sha256").update(canonicalStrategyEvidenceJson(value)).digest("hex");
|
|
69
|
+
var strategyEvidenceFingerprint = (value) => strategyEvidenceSha256(value).slice(0, 16);
|
|
70
|
+
var normalizeStrategyLogicConfig = (value) => {
|
|
71
|
+
if (Array.isArray(value)) return value.map(normalizeStrategyLogicConfig);
|
|
72
|
+
const record = asRecord(value);
|
|
73
|
+
if (!record) return value;
|
|
74
|
+
return Object.fromEntries(
|
|
75
|
+
Object.entries(record).filter(
|
|
76
|
+
([key]) => !STRATEGY_LOGIC_BINDING_KEYS.has(key) && !SECRET_CONFIG_KEY_RE.test(key)
|
|
77
|
+
).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, normalizeStrategyLogicConfig(entry)])
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
var strategyLogicConfigFingerprint = (value) => strategyEvidenceFingerprint(normalizeStrategyLogicConfig(value));
|
|
81
|
+
var strategyEvidenceFileSha256 = async (filePath) => {
|
|
82
|
+
const hash = (0, import_node_crypto.createHash)("sha256");
|
|
83
|
+
for await (const chunk of (0, import_node_fs.createReadStream)(filePath)) hash.update(chunk);
|
|
84
|
+
return hash.digest("hex");
|
|
85
|
+
};
|
|
86
|
+
var safeStrategyEvidenceSegment = (value, fallback = "strategy") => {
|
|
87
|
+
const safe = value.trim().replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
88
|
+
return safe && safe !== "." && safe !== ".." ? safe : fallback;
|
|
89
|
+
};
|
|
90
|
+
var compactStrategyEvidenceTimestamp = (timestamp) => new Date(timestamp).toISOString().replace(/[-:]/g, "").replace(/\.000Z$/, "Z");
|
|
91
|
+
var createStrategyEvidenceMarkerEnvelope = (payload) => {
|
|
92
|
+
const payloadSha256 = strategyEvidenceSha256(payload);
|
|
93
|
+
return {
|
|
94
|
+
schema: import_types.STRATEGY_EVIDENCE_MARKERS_SCHEMA,
|
|
95
|
+
artifactId: `${safeStrategyEvidenceSegment(payload.strategy)}_${compactStrategyEvidenceTimestamp(payload.createdAt)}_${payloadSha256.slice(0, 16)}`,
|
|
96
|
+
payloadSha256,
|
|
97
|
+
payload
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
var verifyStrategyEvidenceMarkerEnvelope = (value) => {
|
|
101
|
+
const envelope = asRecord(value);
|
|
102
|
+
const payload = asRecord(envelope?.payload);
|
|
103
|
+
if (envelope?.schema !== import_types.STRATEGY_EVIDENCE_MARKERS_SCHEMA || !isString(envelope.artifactId) || !isString(envelope.payloadSha256) || !SHA256_RE.test(envelope.payloadSha256) || !payload || !isString(payload.strategy) || !isNumber(payload.createdAt) || !Array.isArray(payload.markers) || !Array.isArray(payload.sourceArtifacts)) {
|
|
104
|
+
throw new Error("Invalid strategy evidence marker envelope");
|
|
105
|
+
}
|
|
106
|
+
for (const value2 of payload.markers) {
|
|
107
|
+
const marker = asRecord(value2);
|
|
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.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
|
+
throw new Error("Invalid strategy evidence marker");
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
for (const value2 of payload.sourceArtifacts) {
|
|
114
|
+
const artifact = asRecord(value2);
|
|
115
|
+
if (!artifact || !isString(artifact.artifactId) || !isString(artifact.sha256) || !SHA256_RE.test(artifact.sha256) || artifact.path !== void 0 && typeof artifact.path !== "string") {
|
|
116
|
+
throw new Error("Invalid strategy evidence source artifact");
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const payloadSha256 = strategyEvidenceSha256(payload);
|
|
120
|
+
if (payloadSha256 !== envelope.payloadSha256) {
|
|
121
|
+
throw new Error("Strategy evidence marker checksum mismatch");
|
|
122
|
+
}
|
|
123
|
+
const expectedId = `${safeStrategyEvidenceSegment(payload.strategy)}_${compactStrategyEvidenceTimestamp(payload.createdAt)}_${payloadSha256.slice(0, 16)}`;
|
|
124
|
+
if (expectedId !== envelope.artifactId) {
|
|
125
|
+
throw new Error("Strategy evidence marker artifact identity mismatch");
|
|
126
|
+
}
|
|
127
|
+
return value;
|
|
128
|
+
};
|
|
129
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
130
|
+
0 && (module.exports = {
|
|
131
|
+
canonicalStrategyEvidenceJson,
|
|
132
|
+
compactStrategyEvidenceTimestamp,
|
|
133
|
+
createStrategyEvidenceMarkerEnvelope,
|
|
134
|
+
safeStrategyEvidenceSegment,
|
|
135
|
+
strategyEvidenceFileSha256,
|
|
136
|
+
strategyEvidenceFingerprint,
|
|
137
|
+
strategyEvidenceSha256,
|
|
138
|
+
strategyLogicConfigFingerprint,
|
|
139
|
+
verifyStrategyEvidenceMarkerEnvelope
|
|
140
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// src/strategyReleaseEvidence.ts
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
import { createReadStream } from "fs";
|
|
4
|
+
import {
|
|
5
|
+
STRATEGY_EVIDENCE_MARKERS_SCHEMA
|
|
6
|
+
} from "@tradejs/types";
|
|
7
|
+
var SHA256_RE = /^[a-f0-9]{64}$/;
|
|
8
|
+
var LINEAGE_FINGERPRINT_RE = /^[a-f0-9]{16}$/;
|
|
9
|
+
var MARKER_TYPES = /* @__PURE__ */ new Set([
|
|
10
|
+
"G",
|
|
11
|
+
"L",
|
|
12
|
+
"E",
|
|
13
|
+
"D",
|
|
14
|
+
"P",
|
|
15
|
+
"R"
|
|
16
|
+
]);
|
|
17
|
+
var STRATEGY_LOGIC_BINDING_KEYS = /* @__PURE__ */ new Set([
|
|
18
|
+
"ACCOUNT_ID",
|
|
19
|
+
"DEPLOYMENT_ID",
|
|
20
|
+
"MAX_LOSS_VALUE",
|
|
21
|
+
"configId"
|
|
22
|
+
]);
|
|
23
|
+
var SECRET_CONFIG_KEY_RE = /(?:^|_)(?:API_KEY|API_SECRET|TOKEN|PASSWORD|PRIVATE_KEY)$/i;
|
|
24
|
+
var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
25
|
+
var isString = (value) => typeof value === "string" && value.trim().length > 0;
|
|
26
|
+
var isNumber = (value) => typeof value === "number" && Number.isFinite(value);
|
|
27
|
+
var canonicalStrategyEvidenceJson = (value) => {
|
|
28
|
+
const normalize = (current) => {
|
|
29
|
+
if (Array.isArray(current)) return current.map(normalize);
|
|
30
|
+
const record = asRecord(current);
|
|
31
|
+
if (!record) return current;
|
|
32
|
+
return Object.fromEntries(
|
|
33
|
+
Object.entries(record).filter(([, entry]) => entry !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, normalize(entry)])
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
return JSON.stringify(normalize(value));
|
|
37
|
+
};
|
|
38
|
+
var strategyEvidenceSha256 = (value) => createHash("sha256").update(canonicalStrategyEvidenceJson(value)).digest("hex");
|
|
39
|
+
var strategyEvidenceFingerprint = (value) => strategyEvidenceSha256(value).slice(0, 16);
|
|
40
|
+
var normalizeStrategyLogicConfig = (value) => {
|
|
41
|
+
if (Array.isArray(value)) return value.map(normalizeStrategyLogicConfig);
|
|
42
|
+
const record = asRecord(value);
|
|
43
|
+
if (!record) return value;
|
|
44
|
+
return Object.fromEntries(
|
|
45
|
+
Object.entries(record).filter(
|
|
46
|
+
([key]) => !STRATEGY_LOGIC_BINDING_KEYS.has(key) && !SECRET_CONFIG_KEY_RE.test(key)
|
|
47
|
+
).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, normalizeStrategyLogicConfig(entry)])
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
var strategyLogicConfigFingerprint = (value) => strategyEvidenceFingerprint(normalizeStrategyLogicConfig(value));
|
|
51
|
+
var strategyEvidenceFileSha256 = async (filePath) => {
|
|
52
|
+
const hash = createHash("sha256");
|
|
53
|
+
for await (const chunk of createReadStream(filePath)) hash.update(chunk);
|
|
54
|
+
return hash.digest("hex");
|
|
55
|
+
};
|
|
56
|
+
var safeStrategyEvidenceSegment = (value, fallback = "strategy") => {
|
|
57
|
+
const safe = value.trim().replace(/[^a-zA-Z0-9._-]+/g, "-");
|
|
58
|
+
return safe && safe !== "." && safe !== ".." ? safe : fallback;
|
|
59
|
+
};
|
|
60
|
+
var compactStrategyEvidenceTimestamp = (timestamp) => new Date(timestamp).toISOString().replace(/[-:]/g, "").replace(/\.000Z$/, "Z");
|
|
61
|
+
var createStrategyEvidenceMarkerEnvelope = (payload) => {
|
|
62
|
+
const payloadSha256 = strategyEvidenceSha256(payload);
|
|
63
|
+
return {
|
|
64
|
+
schema: STRATEGY_EVIDENCE_MARKERS_SCHEMA,
|
|
65
|
+
artifactId: `${safeStrategyEvidenceSegment(payload.strategy)}_${compactStrategyEvidenceTimestamp(payload.createdAt)}_${payloadSha256.slice(0, 16)}`,
|
|
66
|
+
payloadSha256,
|
|
67
|
+
payload
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
var verifyStrategyEvidenceMarkerEnvelope = (value) => {
|
|
71
|
+
const envelope = asRecord(value);
|
|
72
|
+
const payload = asRecord(envelope?.payload);
|
|
73
|
+
if (envelope?.schema !== STRATEGY_EVIDENCE_MARKERS_SCHEMA || !isString(envelope.artifactId) || !isString(envelope.payloadSha256) || !SHA256_RE.test(envelope.payloadSha256) || !payload || !isString(payload.strategy) || !isNumber(payload.createdAt) || !Array.isArray(payload.markers) || !Array.isArray(payload.sourceArtifacts)) {
|
|
74
|
+
throw new Error("Invalid strategy evidence marker envelope");
|
|
75
|
+
}
|
|
76
|
+
for (const value2 of payload.markers) {
|
|
77
|
+
const marker = asRecord(value2);
|
|
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.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
|
+
throw new Error("Invalid strategy evidence marker");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
for (const value2 of payload.sourceArtifacts) {
|
|
84
|
+
const artifact = asRecord(value2);
|
|
85
|
+
if (!artifact || !isString(artifact.artifactId) || !isString(artifact.sha256) || !SHA256_RE.test(artifact.sha256) || artifact.path !== void 0 && typeof artifact.path !== "string") {
|
|
86
|
+
throw new Error("Invalid strategy evidence source artifact");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const payloadSha256 = strategyEvidenceSha256(payload);
|
|
90
|
+
if (payloadSha256 !== envelope.payloadSha256) {
|
|
91
|
+
throw new Error("Strategy evidence marker checksum mismatch");
|
|
92
|
+
}
|
|
93
|
+
const expectedId = `${safeStrategyEvidenceSegment(payload.strategy)}_${compactStrategyEvidenceTimestamp(payload.createdAt)}_${payloadSha256.slice(0, 16)}`;
|
|
94
|
+
if (expectedId !== envelope.artifactId) {
|
|
95
|
+
throw new Error("Strategy evidence marker artifact identity mismatch");
|
|
96
|
+
}
|
|
97
|
+
return value;
|
|
98
|
+
};
|
|
99
|
+
export {
|
|
100
|
+
canonicalStrategyEvidenceJson,
|
|
101
|
+
compactStrategyEvidenceTimestamp,
|
|
102
|
+
createStrategyEvidenceMarkerEnvelope,
|
|
103
|
+
safeStrategyEvidenceSegment,
|
|
104
|
+
strategyEvidenceFileSha256,
|
|
105
|
+
strategyEvidenceFingerprint,
|
|
106
|
+
strategyEvidenceSha256,
|
|
107
|
+
strategyLogicConfigFingerprint,
|
|
108
|
+
verifyStrategyEvidenceMarkerEnvelope
|
|
109
|
+
};
|
package/dist/timescale.mjs
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
deleteCandles,
|
|
3
|
+
findContinuityGap,
|
|
4
|
+
getCandlesRange,
|
|
5
|
+
getDataEdges,
|
|
6
|
+
getDataEdgesForSymbols,
|
|
7
|
+
toRows,
|
|
8
|
+
upsertCandles,
|
|
9
|
+
waitForDbReady
|
|
10
|
+
} from "./chunk-YVIHTUV5.mjs";
|
|
1
11
|
import {
|
|
2
12
|
applyDerivativesMetricCoverage,
|
|
3
13
|
getDerivativesBackfillCoverage,
|
|
@@ -53,16 +63,6 @@ import {
|
|
|
53
63
|
getSpreadSummary,
|
|
54
64
|
upsertSpreadRows
|
|
55
65
|
} from "./chunk-2CZREG43.mjs";
|
|
56
|
-
import {
|
|
57
|
-
deleteCandles,
|
|
58
|
-
findContinuityGap,
|
|
59
|
-
getCandlesRange,
|
|
60
|
-
getDataEdges,
|
|
61
|
-
getDataEdgesForSymbols,
|
|
62
|
-
toRows,
|
|
63
|
-
upsertCandles,
|
|
64
|
-
waitForDbReady
|
|
65
|
-
} from "./chunk-YVIHTUV5.mjs";
|
|
66
66
|
import {
|
|
67
67
|
closeTimescalePool,
|
|
68
68
|
configureTimescaleMarketContextSchemaMode,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/infra",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.21",
|
|
4
4
|
"description": "MIT-licensed server infrastructure adapters for TradeJS: Redis, Timescale, ML, logging, and IO.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
@@ -49,6 +49,11 @@
|
|
|
49
49
|
"import": "./dist/backtestArtifacts.mjs",
|
|
50
50
|
"require": "./dist/backtestArtifacts.js"
|
|
51
51
|
},
|
|
52
|
+
"./coreResearch": {
|
|
53
|
+
"types": "./dist/coreResearch.d.ts",
|
|
54
|
+
"import": "./dist/coreResearch.mjs",
|
|
55
|
+
"require": "./dist/coreResearch.js"
|
|
56
|
+
},
|
|
52
57
|
"./files": {
|
|
53
58
|
"types": "./dist/files.d.ts",
|
|
54
59
|
"import": "./dist/files.mjs",
|
|
@@ -84,6 +89,11 @@
|
|
|
84
89
|
"import": "./dist/runtimeDeployments.mjs",
|
|
85
90
|
"require": "./dist/runtimeDeployments.js"
|
|
86
91
|
},
|
|
92
|
+
"./strategyReleaseEvidence": {
|
|
93
|
+
"types": "./dist/strategyReleaseEvidence.d.ts",
|
|
94
|
+
"import": "./dist/strategyReleaseEvidence.mjs",
|
|
95
|
+
"require": "./dist/strategyReleaseEvidence.js"
|
|
96
|
+
},
|
|
87
97
|
"./userSettings": {
|
|
88
98
|
"types": "./dist/userSettings.d.ts",
|
|
89
99
|
"import": "./dist/userSettings.mjs",
|
|
@@ -133,7 +143,7 @@
|
|
|
133
143
|
"dependencies": {
|
|
134
144
|
"@grpc/grpc-js": "^1.14.4",
|
|
135
145
|
"@grpc/proto-loader": "^0.8.1",
|
|
136
|
-
"@tradejs/types": "^2.0.
|
|
146
|
+
"@tradejs/types": "^2.0.21",
|
|
137
147
|
"chalk": "4.1.2",
|
|
138
148
|
"date-fns": "^3.6.0",
|
|
139
149
|
"ioredis": "5.11.1",
|