@quantform/core 0.7.0-beta.4 → 0.7.0-beta.40
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/asset/asset.d.ts +3 -0
- package/dist/asset/asset.d.ts.map +1 -1
- package/dist/asset/asset.js +7 -1
- package/dist/cli/dev.d.ts.map +1 -1
- package/dist/cli/dev.js +3 -36
- package/dist/cli/internal/script.d.ts +8 -0
- package/dist/cli/internal/script.d.ts.map +1 -0
- package/dist/cli/internal/script.js +58 -0
- package/dist/cli/pull.d.ts.map +1 -1
- package/dist/cli/pull.js +4 -83
- package/dist/cli/replay.d.ts.map +1 -1
- package/dist/cli/replay.js +3 -35
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +3 -37
- package/dist/index.d.ts +5 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -14
- package/dist/instrument/instrument.d.ts +3 -0
- package/dist/instrument/instrument.d.ts.map +1 -1
- package/dist/instrument/instrument.js +7 -1
- package/dist/make-test-module.d.ts +3 -2
- package/dist/make-test-module.d.ts.map +1 -1
- package/dist/make-test-module.js +13 -2
- package/dist/operators.d.ts +5 -0
- package/dist/operators.d.ts.map +1 -0
- package/dist/operators.js +16 -0
- package/dist/replay/index.d.ts +6 -4
- package/dist/replay/index.d.ts.map +1 -1
- package/dist/replay/index.js +6 -4
- package/dist/replay/replay-guard.d.ts +10 -0
- package/dist/replay/replay-guard.d.ts.map +1 -0
- package/dist/replay/replay-guard.js +8 -0
- package/dist/replay/replay.d.ts +10 -0
- package/dist/replay/replay.d.ts.map +1 -0
- package/dist/replay/replay.js +9 -0
- package/dist/replay/use-replay-breakpoint.d.ts +3 -0
- package/dist/replay/use-replay-breakpoint.d.ts.map +1 -0
- package/dist/replay/use-replay-breakpoint.js +22 -0
- package/dist/replay/use-replay-manager.d.ts +12 -0
- package/dist/replay/use-replay-manager.d.ts.map +1 -0
- package/dist/replay/use-replay-manager.js +88 -0
- package/dist/replay/use-replay-storage-buffer.d.ts +15 -0
- package/dist/replay/use-replay-storage-buffer.d.ts.map +1 -0
- package/dist/replay/use-replay-storage-buffer.js +50 -0
- package/dist/replay/use-replay-storage.d.ts +11 -8
- package/dist/replay/use-replay-storage.d.ts.map +1 -1
- package/dist/replay/use-replay-storage.js +34 -5
- package/dist/replay/use-replay-storage.spec.d.ts +2 -0
- package/dist/replay/use-replay-storage.spec.d.ts.map +1 -0
- package/dist/replay/use-replay-storage.spec.js +74 -0
- package/dist/replay/use-replay.d.ts +2 -2
- package/dist/replay/use-replay.d.ts.map +1 -1
- package/dist/replay/use-replay.js +8 -20
- package/dist/replay/use-replay.spec.js +125 -101
- package/dist/session/use-session-storage.js +2 -2
- package/dist/session/use-session.js +2 -2
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +1 -0
- package/dist/storage/use-storage.d.ts.map +1 -1
- package/dist/storage/use-storage.js +2 -2
- package/dist/use-execution-mode.d.ts +6 -1
- package/dist/use-execution-mode.d.ts.map +1 -1
- package/dist/use-execution-mode.js +16 -8
- package/dist/use-logger.js +4 -4
- package/dist/use-memo.d.ts +0 -10
- package/dist/use-memo.d.ts.map +1 -1
- package/dist/use-memo.js +0 -10
- package/dist/use-timestamp.js +2 -2
- package/dist/when-socket.d.ts +8 -0
- package/dist/when-socket.d.ts.map +1 -0
- package/dist/{use-socket.js → when-socket.js} +6 -5
- package/dist/with-memo.d.ts +5 -0
- package/dist/with-memo.d.ts.map +1 -0
- package/dist/{use.js → with-memo.js} +5 -5
- package/dist/with-memo.spec.d.ts +2 -0
- package/dist/with-memo.spec.d.ts.map +1 -0
- package/dist/{use.spec.js → with-memo.spec.js} +3 -3
- package/dist/{use-request.d.ts → with-request.d.ts} +5 -4
- package/dist/with-request.d.ts.map +1 -0
- package/dist/with-request.js +69 -0
- package/package.json +1 -1
- package/src/asset/asset.ts +6 -0
- package/src/cli/dev.ts +4 -20
- package/src/cli/internal/script.ts +49 -0
- package/src/cli/pull.ts +6 -66
- package/src/cli/replay.ts +4 -16
- package/src/cli/run.ts +4 -18
- package/src/index.ts +5 -14
- package/src/instrument/instrument.ts +6 -0
- package/src/make-test-module.ts +24 -4
- package/src/operators.ts +18 -0
- package/src/replay/index.ts +6 -4
- package/src/replay/replay-guard.ts +11 -0
- package/src/replay/replay.ts +13 -0
- package/src/replay/use-replay-breakpoint.ts +29 -0
- package/src/replay/use-replay-manager.ts +106 -0
- package/src/replay/use-replay-storage-buffer.ts +43 -0
- package/src/replay/use-replay-storage.spec.ts +85 -0
- package/src/replay/use-replay-storage.ts +26 -5
- package/src/replay/use-replay.spec.ts +10 -3
- package/src/replay/use-replay.ts +11 -17
- package/src/session/use-session-storage.ts +2 -2
- package/src/session/use-session.ts +2 -2
- package/src/storage/index.ts +1 -0
- package/src/storage/use-storage.ts +2 -2
- package/src/use-execution-mode.ts +16 -8
- package/src/use-logger.ts +4 -4
- package/src/use-memo.ts +0 -10
- package/src/use-timestamp.ts +2 -2
- package/src/{use-socket.ts → when-socket.ts} +6 -4
- package/src/{use.spec.ts → with-memo.spec.ts} +3 -3
- package/src/{use.ts → with-memo.ts} +4 -4
- package/src/with-request.ts +83 -0
- package/dist/as-readonly.d.ts +0 -3
- package/dist/as-readonly.d.ts.map +0 -1
- package/dist/as-readonly.js +0 -8
- package/dist/defined.d.ts +0 -3
- package/dist/defined.d.ts.map +0 -1
- package/dist/defined.js +0 -8
- package/dist/exclude.d.ts +0 -3
- package/dist/exclude.d.ts.map +0 -1
- package/dist/exclude.js +0 -8
- package/dist/not-found.d.ts +0 -2
- package/dist/not-found.d.ts.map +0 -1
- package/dist/not-found.js +0 -4
- package/dist/replay/use-replay-coordinator.d.ts +0 -10
- package/dist/replay/use-replay-coordinator.d.ts.map +0 -1
- package/dist/replay/use-replay-coordinator.js +0 -119
- package/dist/replay/use-replay-reader.d.ts +0 -7
- package/dist/replay/use-replay-reader.d.ts.map +0 -1
- package/dist/replay/use-replay-reader.js +0 -32
- package/dist/replay/use-replay-reader.spec.d.ts +0 -2
- package/dist/replay/use-replay-reader.spec.d.ts.map +0 -1
- package/dist/replay/use-replay-reader.spec.js +0 -58
- package/dist/replay/use-replay-writer.d.ts +0 -6
- package/dist/replay/use-replay-writer.d.ts.map +0 -1
- package/dist/replay/use-replay-writer.js +0 -14
- package/dist/replay/use-replay-writer.spec.d.ts +0 -2
- package/dist/replay/use-replay-writer.spec.d.ts.map +0 -1
- package/dist/replay/use-replay-writer.spec.js +0 -53
- package/dist/replay/with-replay.d.ts +0 -4
- package/dist/replay/with-replay.d.ts.map +0 -1
- package/dist/replay/with-replay.js +0 -8
- package/dist/strat.d.ts +0 -7
- package/dist/strat.d.ts.map +0 -1
- package/dist/strat.js +0 -7
- package/dist/use-lock.d.ts +0 -9
- package/dist/use-lock.d.ts.map +0 -1
- package/dist/use-lock.js +0 -40
- package/dist/use-request.d.ts.map +0 -1
- package/dist/use-request.js +0 -27
- package/dist/use-socket.d.ts +0 -6
- package/dist/use-socket.d.ts.map +0 -1
- package/dist/use-state.d.ts +0 -4
- package/dist/use-state.d.ts.map +0 -1
- package/dist/use-state.js +0 -24
- package/dist/use-state.spec.d.ts +0 -2
- package/dist/use-state.spec.d.ts.map +0 -1
- package/dist/use-state.spec.js +0 -36
- package/dist/use.d.ts +0 -5
- package/dist/use.d.ts.map +0 -1
- package/dist/use.spec.d.ts +0 -2
- package/dist/use.spec.d.ts.map +0 -1
- package/src/as-readonly.ts +0 -5
- package/src/defined.ts +0 -6
- package/src/exclude.ts +0 -9
- package/src/not-found.ts +0 -1
- package/src/replay/use-replay-coordinator.ts +0 -142
- package/src/replay/use-replay-reader.spec.ts +0 -64
- package/src/replay/use-replay-reader.ts +0 -23
- package/src/replay/use-replay-writer.spec.ts +0 -56
- package/src/replay/use-replay-writer.ts +0 -17
- package/src/replay/with-replay.ts +0 -10
- package/src/strat.ts +0 -7
- package/src/use-lock.ts +0 -52
- package/src/use-request.ts +0 -47
- package/src/use-state.spec.ts +0 -31
- package/src/use-state.ts +0 -30
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.withRequest = exports.RequestNetworkError = void 0;
|
|
13
|
+
const node_crypto_1 = require("node:crypto");
|
|
14
|
+
const rxjs_1 = require("rxjs");
|
|
15
|
+
const undici_1 = require("undici");
|
|
16
|
+
const use_logger_1 = require("./use-logger");
|
|
17
|
+
const use_timestamp_1 = require("./use-timestamp");
|
|
18
|
+
class RequestNetworkError extends Error {
|
|
19
|
+
constructor(statusCode, json) {
|
|
20
|
+
super(`Request network error, received status code: ${statusCode}`);
|
|
21
|
+
this.statusCode = statusCode;
|
|
22
|
+
this.json = json;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.RequestNetworkError = RequestNetworkError;
|
|
26
|
+
function withRequest({ method, url, headers, body }) {
|
|
27
|
+
const { error, debug } = (0, use_logger_1.useLogger)(withRequest.name);
|
|
28
|
+
return new rxjs_1.Observable(subscriber => {
|
|
29
|
+
const correlationId = (0, node_crypto_1.randomUUID)();
|
|
30
|
+
debug('requesting', { correlationId, method, url, headers, body });
|
|
31
|
+
(0, undici_1.request)(url, { method, headers, body })
|
|
32
|
+
.then(({ statusCode, body }) => __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
const json = yield body.json();
|
|
34
|
+
debug('received', {
|
|
35
|
+
correlationId,
|
|
36
|
+
method,
|
|
37
|
+
url,
|
|
38
|
+
headers,
|
|
39
|
+
body: json,
|
|
40
|
+
statusCode
|
|
41
|
+
});
|
|
42
|
+
if (statusCode !== 200) {
|
|
43
|
+
error(`errored`, {
|
|
44
|
+
method,
|
|
45
|
+
url,
|
|
46
|
+
headers,
|
|
47
|
+
body,
|
|
48
|
+
statusCode
|
|
49
|
+
});
|
|
50
|
+
subscriber.error(new RequestNetworkError(statusCode, () => json));
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
subscriber.next({ timestamp: (0, use_timestamp_1.useTimestamp)(), payload: json });
|
|
54
|
+
}
|
|
55
|
+
}))
|
|
56
|
+
.catch((e) => {
|
|
57
|
+
error(`errored`, {
|
|
58
|
+
method,
|
|
59
|
+
url,
|
|
60
|
+
headers,
|
|
61
|
+
body,
|
|
62
|
+
error: e
|
|
63
|
+
});
|
|
64
|
+
subscriber.error(error);
|
|
65
|
+
})
|
|
66
|
+
.finally(() => subscriber.complete());
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
exports.withRequest = withRequest;
|
package/package.json
CHANGED
package/src/asset/asset.ts
CHANGED
|
@@ -3,6 +3,12 @@ import { d, decimal } from '@lib/shared';
|
|
|
3
3
|
|
|
4
4
|
export const AssetSelectorSeparator = ':';
|
|
5
5
|
|
|
6
|
+
export class MissingAssetError extends Error {
|
|
7
|
+
constructor(asset: AssetSelector) {
|
|
8
|
+
super(`Missing asset: ${asset}`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
6
12
|
/**
|
|
7
13
|
* Supposed to query specific @see Asset based on string notation.
|
|
8
14
|
*/
|
package/src/cli/dev.ts
CHANGED
|
@@ -1,31 +1,15 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
2
|
-
import { lastValueFrom } from 'rxjs';
|
|
3
|
-
|
|
4
1
|
import build from '@lib/cli/build';
|
|
5
|
-
import { buildDirectory } from '@lib/cli/internal/workspace';
|
|
6
|
-
import { core } from '@lib/core';
|
|
7
|
-
import { Module } from '@lib/module';
|
|
8
|
-
import { strat } from '@lib/strat';
|
|
9
2
|
import { paperExecutionMode } from '@lib/use-execution-mode';
|
|
10
3
|
|
|
4
|
+
import { Script } from './internal/script';
|
|
5
|
+
|
|
11
6
|
export default async function (name: string, options: any) {
|
|
12
7
|
if (await build()) {
|
|
13
8
|
return;
|
|
14
9
|
}
|
|
15
10
|
|
|
16
|
-
const script =
|
|
17
|
-
|
|
18
|
-
>;
|
|
19
|
-
|
|
20
|
-
const module = new Module([
|
|
21
|
-
...core(),
|
|
22
|
-
...script.dependencies,
|
|
23
|
-
paperExecutionMode({ recording: false })
|
|
24
|
-
]);
|
|
25
|
-
|
|
26
|
-
const { act } = await module.awake();
|
|
27
|
-
|
|
28
|
-
const output = await act(() => lastValueFrom(script.fn()));
|
|
11
|
+
const script = new Script(name, [paperExecutionMode({ recording: false })]);
|
|
12
|
+
const output = await script.run();
|
|
29
13
|
|
|
30
14
|
console.log(output);
|
|
31
15
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import {
|
|
3
|
+
finalize,
|
|
4
|
+
firstValueFrom,
|
|
5
|
+
fromEvent,
|
|
6
|
+
last,
|
|
7
|
+
merge,
|
|
8
|
+
of,
|
|
9
|
+
switchMap,
|
|
10
|
+
take
|
|
11
|
+
} from 'rxjs';
|
|
12
|
+
|
|
13
|
+
import { core } from '@lib/core';
|
|
14
|
+
import { Dependency, Module } from '@lib/module';
|
|
15
|
+
|
|
16
|
+
import { buildDirectory } from './workspace';
|
|
17
|
+
|
|
18
|
+
export class Script {
|
|
19
|
+
constructor(
|
|
20
|
+
private readonly name: string,
|
|
21
|
+
private readonly dependencies: Dependency[]
|
|
22
|
+
) {}
|
|
23
|
+
|
|
24
|
+
async run() {
|
|
25
|
+
const script = await import(join(buildDirectory(), this.name));
|
|
26
|
+
const module = new Module([...core(), ...script.onInstall(), ...this.dependencies]);
|
|
27
|
+
|
|
28
|
+
const { act } = await module.awake();
|
|
29
|
+
|
|
30
|
+
return await act(() => {
|
|
31
|
+
process.stdin.resume();
|
|
32
|
+
|
|
33
|
+
return firstValueFrom(
|
|
34
|
+
merge(
|
|
35
|
+
script.onAwake().pipe(last()),
|
|
36
|
+
fromEvent(process, 'exit'),
|
|
37
|
+
fromEvent(process, 'SIGINT'),
|
|
38
|
+
fromEvent(process, 'SIGUSR1'),
|
|
39
|
+
fromEvent(process, 'SIGUSR2'),
|
|
40
|
+
fromEvent(process, 'uncaughtException')
|
|
41
|
+
).pipe(
|
|
42
|
+
take(1),
|
|
43
|
+
switchMap(it => script.onExit() ?? of(it)),
|
|
44
|
+
finalize(() => process.exit(0))
|
|
45
|
+
)
|
|
46
|
+
);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
package/src/cli/pull.ts
CHANGED
|
@@ -1,75 +1,15 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
2
|
-
|
|
3
1
|
import build from '@lib/cli/build';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
import { strat } from '@lib/strat';
|
|
8
|
-
import { paperExecutionMode } from '@lib/use-execution-mode';
|
|
9
|
-
import { token } from '@lib/use-memo';
|
|
2
|
+
import { idleExecutionMode } from '@lib/use-execution-mode';
|
|
3
|
+
|
|
4
|
+
import { Script } from './internal/script';
|
|
10
5
|
|
|
11
6
|
export default async function (name: string, instrument: string, options: any) {
|
|
12
7
|
if (await build()) {
|
|
13
8
|
return;
|
|
14
9
|
}
|
|
15
|
-
await import(join(buildDirectory(), 'index'));
|
|
16
|
-
|
|
17
|
-
const script = (await import(join(buildDirectory(), name))) as ReturnType<typeof strat>;
|
|
18
|
-
|
|
19
|
-
const module = new Module([
|
|
20
|
-
...core(),
|
|
21
|
-
...script.dependencies,
|
|
22
|
-
paperExecutionMode({ recording: false })
|
|
23
|
-
]);
|
|
24
|
-
|
|
25
|
-
const { act } = await module.awake();
|
|
26
|
-
|
|
27
|
-
const o = await act(() => script.fn());
|
|
28
|
-
console.log(module.get<any>(token));
|
|
29
|
-
|
|
30
|
-
/*const builder = new SessionBuilder().useSessionId(
|
|
31
|
-
options.id ? Number(options.id) : now()
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
await spawn(name, builder);
|
|
35
|
-
|
|
36
|
-
const session = builder.paper();
|
|
37
|
-
|
|
38
|
-
console.time('Pulling completed in');
|
|
39
|
-
|
|
40
|
-
await session.awake();
|
|
41
|
-
|
|
42
|
-
const bar = new SingleBar(
|
|
43
|
-
{
|
|
44
|
-
format: `Pulling ${instrument} [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}`
|
|
45
|
-
},
|
|
46
|
-
Presets.rect
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
const feed = new Feed(builder.storage('feed'));
|
|
50
|
-
const from = options.from ? Date.parse(options.from) : builder.period.from;
|
|
51
|
-
const to = options.to ? Date.parse(options.to) : builder.period.to;
|
|
52
|
-
|
|
53
|
-
bar.start(100, 0);
|
|
54
|
-
|
|
55
|
-
await session.aggregate.feed(
|
|
56
|
-
instrumentOf(instrument),
|
|
57
|
-
from,
|
|
58
|
-
to,
|
|
59
|
-
async (timestamp, events) => {
|
|
60
|
-
const duration = to - from;
|
|
61
|
-
const completed = timestamp - from;
|
|
62
|
-
|
|
63
|
-
await feed.save(events);
|
|
64
|
-
|
|
65
|
-
bar.update(Math.floor((completed / duration) * 100));
|
|
66
|
-
}
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
bar.update(100);
|
|
70
|
-
bar.stop();
|
|
71
10
|
|
|
72
|
-
|
|
11
|
+
const script = new Script(name, [idleExecutionMode()]);
|
|
12
|
+
//const output = await script.run();
|
|
73
13
|
|
|
74
|
-
console.
|
|
14
|
+
//console.log(output);
|
|
75
15
|
}
|
package/src/cli/replay.ts
CHANGED
|
@@ -1,31 +1,19 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
2
|
-
import { lastValueFrom } from 'rxjs';
|
|
3
|
-
|
|
4
1
|
import build from '@lib/cli/build';
|
|
5
|
-
import { buildDirectory } from '@lib/cli/internal/workspace';
|
|
6
|
-
import { core } from '@lib/core';
|
|
7
|
-
import { Dependency, Module } from '@lib/module';
|
|
8
2
|
import { replayOptions } from '@lib/replay';
|
|
9
3
|
import { replayExecutionMode } from '@lib/use-execution-mode';
|
|
10
4
|
|
|
5
|
+
import { Script } from './internal/script';
|
|
6
|
+
|
|
11
7
|
export default async function (name: string, options: any) {
|
|
12
8
|
if (await build()) {
|
|
13
9
|
return;
|
|
14
10
|
}
|
|
15
11
|
|
|
16
|
-
const script =
|
|
17
|
-
const dependencies = script.module2 as Dependency[];
|
|
18
|
-
|
|
19
|
-
const module = new Module([
|
|
20
|
-
...core(),
|
|
21
|
-
...dependencies,
|
|
12
|
+
const script = new Script(name, [
|
|
22
13
|
replayOptions({ from: 0, to: Number.MAX_VALUE }),
|
|
23
14
|
replayExecutionMode()
|
|
24
15
|
]);
|
|
25
|
-
|
|
26
|
-
const { act } = await module.awake();
|
|
27
|
-
|
|
28
|
-
const output = await act(() => lastValueFrom(script.default(options)));
|
|
16
|
+
const output = await script.run();
|
|
29
17
|
|
|
30
18
|
console.log(output);
|
|
31
19
|
}
|
package/src/cli/run.ts
CHANGED
|
@@ -1,29 +1,15 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
2
|
-
import { lastValueFrom } from 'rxjs';
|
|
3
|
-
|
|
4
1
|
import build from '@lib/cli/build';
|
|
5
|
-
import { buildDirectory } from '@lib/cli/internal/workspace';
|
|
6
|
-
import { core } from '@lib/core';
|
|
7
|
-
import { Dependency, Module } from '@lib/module';
|
|
8
2
|
import { liveExecutionMode } from '@lib/use-execution-mode';
|
|
9
3
|
|
|
4
|
+
import { Script } from './internal/script';
|
|
5
|
+
|
|
10
6
|
export default async function (name: string, options: any) {
|
|
11
7
|
if (await build()) {
|
|
12
8
|
return;
|
|
13
9
|
}
|
|
14
10
|
|
|
15
|
-
const script =
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
const module = new Module([
|
|
19
|
-
...core(),
|
|
20
|
-
...dependencies,
|
|
21
|
-
liveExecutionMode({ recording: true })
|
|
22
|
-
]);
|
|
23
|
-
|
|
24
|
-
const { act } = await module.awake();
|
|
25
|
-
|
|
26
|
-
const output = await act(() => lastValueFrom(script.default(options)));
|
|
11
|
+
const script = new Script(name, [liveExecutionMode({ recording: true })]);
|
|
12
|
+
const output = await script.run();
|
|
27
13
|
|
|
28
14
|
console.log(output);
|
|
29
15
|
}
|
package/src/index.ts
CHANGED
|
@@ -7,21 +7,12 @@ export * from '@lib/use-timestamp';
|
|
|
7
7
|
export * from '@lib/simulator';
|
|
8
8
|
export * from '@lib/make-test-module';
|
|
9
9
|
export * from '@lib/core';
|
|
10
|
-
export * from '@lib/use-state';
|
|
11
|
-
export * from '@lib/replay/use-replay-coordinator';
|
|
12
10
|
export * from '@lib/use-execution-mode';
|
|
13
|
-
export * from '@lib/storage
|
|
14
|
-
export * from '@lib/storage/use-cache';
|
|
11
|
+
export * from '@lib/storage';
|
|
15
12
|
export * from '@lib/use-logger';
|
|
16
13
|
export * from '@lib/replay';
|
|
17
|
-
export * from '@lib/
|
|
18
|
-
export * from '@lib/
|
|
19
|
-
export * from '@lib/
|
|
20
|
-
export * from '@lib/defined';
|
|
21
|
-
export * from '@lib/as-readonly';
|
|
22
|
-
export * from '@lib/use';
|
|
14
|
+
export * from '@lib/when-socket';
|
|
15
|
+
export * from '@lib/with-request';
|
|
16
|
+
export * from '@lib/with-memo';
|
|
23
17
|
export * from '@lib/session';
|
|
24
|
-
export * from '@lib/
|
|
25
|
-
export * from '@lib/use-lock';
|
|
26
|
-
export * from '@lib/strat';
|
|
27
|
-
export * from '@lib/not-found';
|
|
18
|
+
export * from '@lib/operators';
|
|
@@ -5,6 +5,12 @@ import { Commission } from './commission/commission';
|
|
|
5
5
|
|
|
6
6
|
export const InstrumentSelectorSeparator = '-';
|
|
7
7
|
|
|
8
|
+
export class MissingInstrumentError extends Error {
|
|
9
|
+
constructor(instrument: InstrumentSelector) {
|
|
10
|
+
super(`Missing instrument: ${instrument}`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
8
14
|
export class InstrumentSelector {
|
|
9
15
|
readonly id: string;
|
|
10
16
|
readonly base: AssetSelector;
|
package/src/make-test-module.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Observable,
|
|
1
|
+
import { Observable, Subject } from 'rxjs';
|
|
2
2
|
|
|
3
3
|
import { core } from '@lib/core';
|
|
4
4
|
import { Dependency, Module } from '@lib/module';
|
|
@@ -20,9 +20,9 @@ export const mockedFunc = <Func extends MockableFunction>(mockedFunc: Func) =>
|
|
|
20
20
|
mockedFunc as jest.MockedFunction<typeof mockedFunc>;
|
|
21
21
|
|
|
22
22
|
export function toArray<T>(observable: Observable<T>) {
|
|
23
|
-
const array = Array.of<T>();
|
|
23
|
+
const array = Array.of<T | Error>();
|
|
24
24
|
|
|
25
|
-
const clone = (it: T): T => {
|
|
25
|
+
const clone = (it: T | Error): T | Error => {
|
|
26
26
|
if (typeof it === 'symbol') {
|
|
27
27
|
return it;
|
|
28
28
|
}
|
|
@@ -38,9 +38,29 @@ export function toArray<T>(observable: Observable<T>) {
|
|
|
38
38
|
return it;
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
observable.
|
|
41
|
+
observable.subscribe({
|
|
42
|
+
next: it => array.push(clone(it)),
|
|
43
|
+
error: it => array.push(it)
|
|
44
|
+
});
|
|
42
45
|
|
|
43
46
|
return array;
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
export type InferObservableType<T> = T extends Observable<infer U> ? U : never;
|
|
50
|
+
|
|
51
|
+
export function mockSubject<
|
|
52
|
+
T extends jest.FunctionProperties<Required<T>>,
|
|
53
|
+
M extends keyof jest.FunctionProperties<Required<T>>
|
|
54
|
+
>(object: T, method: M) {
|
|
55
|
+
const subject = new Subject<
|
|
56
|
+
InferObservableType<ReturnType<jest.FunctionProperties<Required<T>>[M]>>
|
|
57
|
+
>();
|
|
58
|
+
|
|
59
|
+
jest
|
|
60
|
+
.spyOn<T, M>(object, method)
|
|
61
|
+
.mockReturnValue(
|
|
62
|
+
subject.asObservable() as ReturnType<jest.FunctionProperties<Required<T>>[M]>
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
return subject;
|
|
66
|
+
}
|
package/src/operators.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { filter, map, Observable } from 'rxjs';
|
|
2
|
+
|
|
3
|
+
export function asReadonly<T>() {
|
|
4
|
+
return (input: Observable<T>) => input.pipe(map(it => it as Readonly<T>));
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function defined<T>() {
|
|
8
|
+
return (observable: Observable<T | undefined | null>) =>
|
|
9
|
+
observable.pipe(filter(it => it !== undefined && it !== null));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function exclude<T, S extends symbol>(s: S) {
|
|
13
|
+
return (observable: Observable<T | S>) =>
|
|
14
|
+
observable.pipe(
|
|
15
|
+
filter(it => it !== s),
|
|
16
|
+
map(it => it as Exclude<T, typeof s>)
|
|
17
|
+
);
|
|
18
|
+
}
|
package/src/replay/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from './use-replay';
|
|
2
|
-
export * from './use-replay-
|
|
2
|
+
export * from './use-replay-breakpoint';
|
|
3
3
|
export * from './use-replay-options';
|
|
4
|
-
export * from './use-replay-
|
|
5
|
-
export * from './use-replay-
|
|
6
|
-
export * from './
|
|
4
|
+
export * from './use-replay-storage';
|
|
5
|
+
export * from './use-replay-storage-buffer';
|
|
6
|
+
export * from './use-replay-manager';
|
|
7
|
+
export * from './replay';
|
|
8
|
+
export * from './replay-guard';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
|
|
3
|
+
import { dependency } from '@lib/use-hash';
|
|
4
|
+
|
|
5
|
+
import { useReplayBreakpoint } from './use-replay-breakpoint';
|
|
6
|
+
|
|
7
|
+
export function replayGuard<T extends Array<dependency>, K>(
|
|
8
|
+
fn: (...args: T) => Observable<{ timestamp: number; payload: K }>
|
|
9
|
+
): (...args: T) => Observable<{ timestamp: number; payload: K }> {
|
|
10
|
+
return (...args: T) => useReplayBreakpoint(fn(...args));
|
|
11
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
|
|
3
|
+
import { dependency } from '@lib/use-hash';
|
|
4
|
+
import { withMemo } from '@lib/with-memo';
|
|
5
|
+
|
|
6
|
+
import { useReplay } from './use-replay';
|
|
7
|
+
|
|
8
|
+
export function replay<T extends Array<dependency>, K>(
|
|
9
|
+
fn: (...args: T) => Observable<{ timestamp: number; payload: K }>,
|
|
10
|
+
dependencies: dependency[]
|
|
11
|
+
): (...args: T) => Observable<{ timestamp: number; payload: K }> {
|
|
12
|
+
return withMemo((...args: T) => useReplay(fn(...args), [...dependencies, ...args]));
|
|
13
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { finalize, Observable } from 'rxjs';
|
|
2
|
+
|
|
3
|
+
import { useExecutionMode } from '@lib/use-execution-mode';
|
|
4
|
+
import { useLogger } from '@lib/use-logger';
|
|
5
|
+
|
|
6
|
+
import { useReplayManager } from './use-replay-manager';
|
|
7
|
+
|
|
8
|
+
export function useReplayBreakpoint<T>(input: Observable<T>): Observable<T> {
|
|
9
|
+
const { isReplay } = useExecutionMode();
|
|
10
|
+
|
|
11
|
+
if (!isReplay) {
|
|
12
|
+
return input;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const { info } = useLogger('useReplayBreakpoint');
|
|
16
|
+
const { stop, tryContinue } = useReplayManager();
|
|
17
|
+
|
|
18
|
+
info('locking resource...');
|
|
19
|
+
|
|
20
|
+
stop();
|
|
21
|
+
|
|
22
|
+
return input.pipe(
|
|
23
|
+
finalize(() => {
|
|
24
|
+
info('unlocking resource');
|
|
25
|
+
|
|
26
|
+
tryContinue();
|
|
27
|
+
})
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { defer, filter, map, Observable, Subject } from 'rxjs';
|
|
2
|
+
|
|
3
|
+
import { dependency, useHash } from '@lib/use-hash';
|
|
4
|
+
import { useLogger } from '@lib/use-logger';
|
|
5
|
+
import { withMemo } from '@lib/with-memo';
|
|
6
|
+
|
|
7
|
+
import { useReplayOptions } from './use-replay-options';
|
|
8
|
+
import { useReplayStorageBuffer } from './use-replay-storage-buffer';
|
|
9
|
+
|
|
10
|
+
export const useReplayManager = withMemo(() => {
|
|
11
|
+
const { from, to } = useReplayOptions();
|
|
12
|
+
const { info } = useLogger('useReplayManager');
|
|
13
|
+
|
|
14
|
+
let timestamp = from;
|
|
15
|
+
let stopAcquire = 1;
|
|
16
|
+
const subscriptions = Array.of<ReturnType<typeof useReplayStorageBuffer<any>>>();
|
|
17
|
+
|
|
18
|
+
const stream$ = new Subject<
|
|
19
|
+
[ReturnType<typeof useReplayStorageBuffer<any>>, { timestamp: number; payload: any }]
|
|
20
|
+
>();
|
|
21
|
+
|
|
22
|
+
const getNextStorage = async () => {
|
|
23
|
+
let next: ReturnType<typeof useReplayStorageBuffer<any>> | undefined;
|
|
24
|
+
|
|
25
|
+
for (const cursor of subscriptions) {
|
|
26
|
+
if (cursor.size() == 0 && !cursor.completed()) {
|
|
27
|
+
await cursor.fetchNextPage(timestamp, to + 1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (cursor.peek()) {
|
|
31
|
+
if (!next || next.peek().timestamp > cursor.peek().timestamp) {
|
|
32
|
+
next = cursor;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return next;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const processNext = async () => {
|
|
41
|
+
const cursor = await getNextStorage();
|
|
42
|
+
|
|
43
|
+
if (!cursor || !cursor.peek()) {
|
|
44
|
+
stream$.complete();
|
|
45
|
+
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const sample = cursor.dequeue();
|
|
50
|
+
|
|
51
|
+
timestamp = sample.timestamp;
|
|
52
|
+
|
|
53
|
+
stream$.next([cursor, sample]);
|
|
54
|
+
|
|
55
|
+
return true;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const next = async () => {
|
|
59
|
+
if (await processNext()) {
|
|
60
|
+
if (stopAcquire === 0) {
|
|
61
|
+
setImmediate(next);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const tryContinue = () => {
|
|
67
|
+
if (stopAcquire == 0) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
stopAcquire = Math.max(0, stopAcquire - 1);
|
|
72
|
+
|
|
73
|
+
if (stopAcquire != 0) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
next();
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
timestamp() {
|
|
82
|
+
return timestamp;
|
|
83
|
+
},
|
|
84
|
+
stop() {
|
|
85
|
+
stopAcquire++;
|
|
86
|
+
},
|
|
87
|
+
tryContinue,
|
|
88
|
+
when<T>(dependencies: dependency[]): Observable<{ timestamp: number; payload: T }> {
|
|
89
|
+
const storage = useReplayStorageBuffer<T>(dependencies);
|
|
90
|
+
|
|
91
|
+
if (!subscriptions.includes(storage)) {
|
|
92
|
+
info('subscribing to replay', useHash(dependencies));
|
|
93
|
+
subscriptions.push(storage);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return defer(() => {
|
|
97
|
+
tryContinue();
|
|
98
|
+
|
|
99
|
+
return stream$.pipe(
|
|
100
|
+
filter(([cur]) => cur === storage),
|
|
101
|
+
map(([, it]) => ({ timestamp: it.timestamp, payload: it.payload as T }))
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { between } from '@lib/storage';
|
|
2
|
+
import { dependency } from '@lib/use-hash';
|
|
3
|
+
import { withMemo } from '@lib/with-memo';
|
|
4
|
+
|
|
5
|
+
import { useReplayStorage } from './use-replay-storage';
|
|
6
|
+
|
|
7
|
+
export const useReplayStorageBuffer = withMemo(<T>(dependencies: dependency[]) => {
|
|
8
|
+
const { query } = useReplayStorage<T>(dependencies);
|
|
9
|
+
|
|
10
|
+
let page = new Array<{ timestamp: number; payload: T }>();
|
|
11
|
+
let index = 0;
|
|
12
|
+
let completed = false;
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
size() {
|
|
16
|
+
return page.length - index;
|
|
17
|
+
},
|
|
18
|
+
peek() {
|
|
19
|
+
return page[index];
|
|
20
|
+
},
|
|
21
|
+
dequeue() {
|
|
22
|
+
return page[index++];
|
|
23
|
+
},
|
|
24
|
+
completed() {
|
|
25
|
+
return completed;
|
|
26
|
+
},
|
|
27
|
+
async fetchNextPage(from: number, to: number) {
|
|
28
|
+
if (completed) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
index = 0;
|
|
33
|
+
|
|
34
|
+
page = await query({
|
|
35
|
+
where: {
|
|
36
|
+
timestamp: between(from, to)
|
|
37
|
+
},
|
|
38
|
+
limit: 10000
|
|
39
|
+
});
|
|
40
|
+
completed = page.length == 0;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
});
|