@quantform/core 0.7.0-beta.33 → 0.7.0-beta.34

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.
Files changed (82) hide show
  1. package/dist/cli/replay.d.ts.map +1 -1
  2. package/dist/cli/replay.js +3 -35
  3. package/dist/cli/run.d.ts.map +1 -1
  4. package/dist/cli/run.js +3 -37
  5. package/dist/index.d.ts +1 -4
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -4
  8. package/dist/replay/index.d.ts +6 -4
  9. package/dist/replay/index.d.ts.map +1 -1
  10. package/dist/replay/index.js +6 -4
  11. package/dist/replay/replay-guard.d.ts +10 -0
  12. package/dist/replay/replay-guard.d.ts.map +1 -0
  13. package/dist/replay/replay-guard.js +8 -0
  14. package/dist/replay/replay.d.ts +10 -0
  15. package/dist/replay/replay.d.ts.map +1 -0
  16. package/dist/replay/replay.js +9 -0
  17. package/dist/replay/use-replay-breakpoint.d.ts +3 -0
  18. package/dist/replay/use-replay-breakpoint.d.ts.map +1 -0
  19. package/dist/replay/use-replay-breakpoint.js +22 -0
  20. package/dist/replay/use-replay-manager.d.ts +12 -0
  21. package/dist/replay/use-replay-manager.d.ts.map +1 -0
  22. package/dist/replay/use-replay-manager.js +88 -0
  23. package/dist/replay/use-replay-storage-buffer.d.ts +15 -0
  24. package/dist/replay/use-replay-storage-buffer.d.ts.map +1 -0
  25. package/dist/replay/use-replay-storage-buffer.js +50 -0
  26. package/dist/replay/use-replay-storage.d.ts +11 -8
  27. package/dist/replay/use-replay-storage.d.ts.map +1 -1
  28. package/dist/replay/use-replay-storage.js +34 -5
  29. package/dist/replay/use-replay-storage.spec.d.ts +2 -0
  30. package/dist/replay/use-replay-storage.spec.d.ts.map +1 -0
  31. package/dist/replay/use-replay-storage.spec.js +74 -0
  32. package/dist/replay/use-replay.d.ts +2 -2
  33. package/dist/replay/use-replay.d.ts.map +1 -1
  34. package/dist/replay/use-replay.js +8 -20
  35. package/dist/replay/use-replay.spec.js +125 -101
  36. package/dist/storage/index.d.ts +1 -0
  37. package/dist/storage/index.d.ts.map +1 -1
  38. package/dist/storage/index.js +1 -0
  39. package/dist/use-execution-mode.d.ts +1 -1
  40. package/dist/use-execution-mode.js +7 -7
  41. package/dist/use-timestamp.js +2 -2
  42. package/package.json +1 -1
  43. package/src/cli/replay.ts +4 -16
  44. package/src/cli/run.ts +4 -18
  45. package/src/index.ts +1 -4
  46. package/src/replay/index.ts +6 -4
  47. package/src/replay/replay-guard.ts +11 -0
  48. package/src/replay/replay.ts +13 -0
  49. package/src/replay/use-replay-breakpoint.ts +29 -0
  50. package/src/replay/use-replay-manager.ts +106 -0
  51. package/src/replay/use-replay-storage-buffer.ts +43 -0
  52. package/src/replay/use-replay-storage.spec.ts +85 -0
  53. package/src/replay/use-replay-storage.ts +26 -5
  54. package/src/replay/use-replay.spec.ts +10 -3
  55. package/src/replay/use-replay.ts +11 -17
  56. package/src/storage/index.ts +1 -0
  57. package/src/use-execution-mode.ts +8 -8
  58. package/src/use-timestamp.ts +2 -2
  59. package/dist/replay/use-replay-coordinator.d.ts +0 -10
  60. package/dist/replay/use-replay-coordinator.d.ts.map +0 -1
  61. package/dist/replay/use-replay-coordinator.js +0 -119
  62. package/dist/replay/use-replay-reader.d.ts +0 -7
  63. package/dist/replay/use-replay-reader.d.ts.map +0 -1
  64. package/dist/replay/use-replay-reader.js +0 -32
  65. package/dist/replay/use-replay-reader.spec.d.ts +0 -2
  66. package/dist/replay/use-replay-reader.spec.d.ts.map +0 -1
  67. package/dist/replay/use-replay-reader.spec.js +0 -58
  68. package/dist/replay/use-replay-writer.d.ts +0 -6
  69. package/dist/replay/use-replay-writer.d.ts.map +0 -1
  70. package/dist/replay/use-replay-writer.js +0 -14
  71. package/dist/replay/use-replay-writer.spec.d.ts +0 -2
  72. package/dist/replay/use-replay-writer.spec.d.ts.map +0 -1
  73. package/dist/replay/use-replay-writer.spec.js +0 -53
  74. package/dist/replay/with-replay.d.ts +0 -4
  75. package/dist/replay/with-replay.d.ts.map +0 -1
  76. package/dist/replay/with-replay.js +0 -8
  77. package/src/replay/use-replay-coordinator.ts +0 -142
  78. package/src/replay/use-replay-reader.spec.ts +0 -64
  79. package/src/replay/use-replay-reader.ts +0 -23
  80. package/src/replay/use-replay-writer.spec.ts +0 -56
  81. package/src/replay/use-replay-writer.ts +0 -17
  82. package/src/replay/with-replay.ts +0 -10
@@ -1,32 +1,20 @@
1
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
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.useReplay = void 0;
13
4
  const rxjs_1 = require("rxjs");
14
- const use_replay_coordinator_1 = require("../replay/use-replay-coordinator");
15
5
  const use_execution_mode_1 = require("../use-execution-mode");
16
- const use_replay_writer_1 = require("./use-replay-writer");
17
- const useReplay = (input, dependencies) => {
6
+ const use_replay_manager_1 = require("./use-replay-manager");
7
+ const use_replay_storage_1 = require("./use-replay-storage");
8
+ function useReplay(input, dependencies) {
18
9
  const { isReplay, recording } = (0, use_execution_mode_1.useExecutionMode)();
19
10
  if (isReplay) {
20
- const { subscribe } = (0, use_replay_coordinator_1.useReplayCoordinator)();
21
- return subscribe(dependencies).pipe((0, rxjs_1.map)(it => it));
11
+ const { when } = (0, use_replay_manager_1.useReplayManager)();
12
+ return when(dependencies);
22
13
  }
23
14
  if (recording) {
24
- const writer = (0, use_replay_writer_1.useReplayWriter)(dependencies);
25
- return input.pipe((0, rxjs_1.concatMap)((it) => __awaiter(void 0, void 0, void 0, function* () {
26
- yield writer([it]);
27
- return it;
28
- })));
15
+ const { save } = (0, use_replay_storage_1.useReplayStorage)(dependencies);
16
+ return input.pipe((0, rxjs_1.tap)(it => save([it])));
29
17
  }
30
18
  return input;
31
- };
19
+ }
32
20
  exports.useReplay = useReplay;
@@ -1,106 +1,130 @@
1
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
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
- const rxjs_1 = require("rxjs");
13
- const make_test_module_1 = require("../make-test-module");
14
- const use_replay_coordinator_1 = require("../replay/use-replay-coordinator");
15
- const use_execution_mode_1 = require("../use-execution-mode");
16
- const __1 = require("..");
17
3
  const use_replay_1 = require("./use-replay");
18
- const use_replay_options_1 = require("./use-replay-options");
19
- const use_replay_reader_1 = require("./use-replay-reader");
20
- const use_replay_writer_1 = require("./use-replay-writer");
21
- describe.skip(use_replay_coordinator_1.useReplayCoordinator.name, () => {
22
- let fixtures;
23
- beforeEach(() => __awaiter(void 0, void 0, void 0, function* () {
24
- fixtures = yield getFixtures();
25
- }));
26
- test('return single data stream for single data source', () => __awaiter(void 0, void 0, void 0, function* () {
27
- fixtures.givenRecordingEnabled(false);
28
- yield fixtures.givenSampleStored(fixtures.sample1, ['sample1']);
29
- const sample1 = fixtures.whenUseReplayCalled(fixtures.sample1, ['sample']);
30
- yield fixtures.whenUseSampleStreamerStarted();
31
- expect(yield sample1).toEqual(fixtures.sample1);
32
- }));
33
- test('return combined data stream for multiple data sources', () => __awaiter(void 0, void 0, void 0, function* () {
34
- fixtures.givenRecordingEnabled(false);
35
- yield fixtures.givenSampleStored(fixtures.sample1, ['sample1']);
36
- yield fixtures.givenSampleStored(fixtures.sample2, ['sample2']);
37
- const sample1 = fixtures.whenUseReplayCalled(fixtures.sample1, ['sample1']);
38
- const sample2 = fixtures.whenUseReplayCalled(fixtures.sample2, ['sample2']);
39
- yield fixtures.whenUseSampleStreamerStarted();
40
- expect(yield sample1).toEqual(fixtures.sample1);
41
- expect(yield sample2).toEqual(fixtures.sample2);
42
- }));
43
- test('record and write data stream into storage', () => __awaiter(void 0, void 0, void 0, function* () {
44
- fixtures.givenRecordingEnabled(true);
45
- const sample1 = yield fixtures.whenUseReplayCalled(fixtures.sample1, ['sample1x']);
46
- const sample2 = yield fixtures.whenUseReplayCalled(fixtures.sample2, ['sample2x']);
47
- fixtures.thenReplaySampleStored(sample1, ['sample1x']);
48
- fixtures.thenReplaySampleStored(sample2, ['sample2x']);
49
- }));
50
- });
51
- function getFixtures() {
52
- return __awaiter(this, void 0, void 0, function* () {
53
- const executionMode = (0, use_execution_mode_1.replayExecutionMode)();
54
- const { act } = yield (0, make_test_module_1.makeTestModule)([
55
- executionMode,
56
- (0, use_replay_options_1.replayOptions)({ from: 0, to: Number.MAX_VALUE })
57
- ]);
58
- return {
59
- sample1: [
60
- { timestamp: 1, payload: { o: 111, h: 112, l: 113, c: 114 } },
61
- { timestamp: 2, payload: { o: 121, h: 122, l: 123, c: 124 } },
62
- { timestamp: 3, payload: { o: 131, h: 132, l: 133, c: 134 } }
63
- ],
64
- sample2: [
65
- { timestamp: 1, payload: { o: 211, h: 212, l: 213, c: 214 } },
66
- { timestamp: 2, payload: { o: 221, h: 222, l: 223, c: 224 } },
67
- { timestamp: 3, payload: { o: 231, h: 232, l: 233, c: 234 } }
68
- ],
69
- givenRecordingEnabled(recording) {
70
- executionMode.useValue.recording = recording;
71
- },
72
- givenSampleStored(sample, dependencies) {
73
- return act(() => {
74
- const writer = (0, use_replay_writer_1.useReplayWriter)(dependencies);
75
- return writer(sample);
76
- });
77
- },
78
- whenUseReplayCalled(input, dependencies) {
79
- return __awaiter(this, void 0, void 0, function* () {
80
- const sample = Array.of();
81
- yield act(() => (0, rxjs_1.lastValueFrom)((0, use_replay_1.useReplay)((0, rxjs_1.from)(input), dependencies).pipe((0, rxjs_1.tap)(it => sample.push(it)))));
82
- return sample;
83
- });
84
- },
85
- whenUseSampleStreamerStarted() {
86
- act(() => {
87
- const { tryContinue } = (0, use_replay_coordinator_1.useReplayCoordinator)();
88
- tryContinue();
89
- });
90
- },
91
- thenReplaySampleStored(sample, dependencies) {
92
- return __awaiter(this, void 0, void 0, function* () {
93
- const stored = yield act(() => {
94
- const reader = (0, use_replay_reader_1.useReplayReader)(dependencies);
95
- return reader({
96
- where: {
97
- timestamp: (0, __1.between)(sample[0].timestamp, sample[sample.length - 1].timestamp + 1)
98
- }
99
- });
100
- });
101
- expect(stored).toEqual(sample);
102
- });
103
- }
104
- };
4
+ describe(use_replay_1.useReplay.name, () => {
5
+ test('happy path', () => {
6
+ expect(true).toBe(true);
105
7
  });
8
+ });
9
+ /*
10
+
11
+ describe.skip(useReplayCoordinator.name, () => {
12
+ let fixtures: Awaited<ReturnType<typeof getFixtures>>;
13
+
14
+ beforeEach(async () => {
15
+ fixtures = await getFixtures();
16
+ });
17
+
18
+ test('return single data stream for single data source', async () => {
19
+ fixtures.givenRecordingEnabled(false);
20
+ await fixtures.givenSampleStored(fixtures.sample1, ['sample1']);
21
+
22
+ const sample1 = fixtures.whenUseReplayCalled(fixtures.sample1, ['sample']);
23
+ await fixtures.whenUseSampleStreamerStarted();
24
+
25
+ expect(await sample1).toEqual(fixtures.sample1);
26
+ });
27
+
28
+ test('return combined data stream for multiple data sources', async () => {
29
+ fixtures.givenRecordingEnabled(false);
30
+ await fixtures.givenSampleStored(fixtures.sample1, ['sample1']);
31
+ await fixtures.givenSampleStored(fixtures.sample2, ['sample2']);
32
+
33
+ const sample1 = fixtures.whenUseReplayCalled(fixtures.sample1, ['sample1']);
34
+ const sample2 = fixtures.whenUseReplayCalled(fixtures.sample2, ['sample2']);
35
+ await fixtures.whenUseSampleStreamerStarted();
36
+
37
+ expect(await sample1).toEqual(fixtures.sample1);
38
+ expect(await sample2).toEqual(fixtures.sample2);
39
+ });
40
+
41
+ test('record and write data stream into storage', async () => {
42
+ fixtures.givenRecordingEnabled(true);
43
+ const sample1 = await fixtures.whenUseReplayCalled(fixtures.sample1, ['sample1x']);
44
+ const sample2 = await fixtures.whenUseReplayCalled(fixtures.sample2, ['sample2x']);
45
+
46
+ fixtures.thenReplaySampleStored(sample1, ['sample1x']);
47
+ fixtures.thenReplaySampleStored(sample2, ['sample2x']);
48
+ });
49
+ });
50
+
51
+ async function getFixtures() {
52
+ const executionMode = replayExecutionMode();
53
+
54
+ const { act } = await makeTestModule([
55
+ executionMode,
56
+ replayOptions({ from: 0, to: Number.MAX_VALUE })
57
+ ]);
58
+
59
+ return {
60
+ sample1: [
61
+ { timestamp: 1, payload: { o: 111, h: 112, l: 113, c: 114 } },
62
+ { timestamp: 2, payload: { o: 121, h: 122, l: 123, c: 124 } },
63
+ { timestamp: 3, payload: { o: 131, h: 132, l: 133, c: 134 } }
64
+ ],
65
+ sample2: [
66
+ { timestamp: 1, payload: { o: 211, h: 212, l: 213, c: 214 } },
67
+ { timestamp: 2, payload: { o: 221, h: 222, l: 223, c: 224 } },
68
+ { timestamp: 3, payload: { o: 231, h: 232, l: 233, c: 234 } }
69
+ ],
70
+
71
+ givenRecordingEnabled(recording: boolean) {
72
+ executionMode.useValue.recording = recording;
73
+ },
74
+
75
+ givenSampleStored<T>(
76
+ sample: { timestamp: number; payload: T }[],
77
+ dependencies: dependency[]
78
+ ) {
79
+ return act(() => {
80
+ const writer = useReplayWriter(dependencies);
81
+
82
+ return writer(sample);
83
+ });
84
+ },
85
+
86
+ async whenUseReplayCalled<T>(
87
+ input: { timestamp: number; payload: T }[],
88
+ dependencies: dependency[]
89
+ ) {
90
+ const sample = Array.of<{ timestamp: number; payload: T }>();
91
+
92
+ await act(() =>
93
+ lastValueFrom(
94
+ useReplay<T>(from(input), dependencies).pipe(tap(it => sample.push(it)))
95
+ )
96
+ );
97
+
98
+ return sample;
99
+ },
100
+
101
+ whenUseSampleStreamerStarted() {
102
+ act(() => {
103
+ const { tryContinue } = useReplayCoordinator();
104
+
105
+ tryContinue();
106
+ });
107
+ },
108
+
109
+ async thenReplaySampleStored<T extends { timestamp: number }>(
110
+ sample: T[],
111
+ dependencies: dependency[]
112
+ ) {
113
+ const stored = await act(() => {
114
+ const reader = useReplayReader(dependencies);
115
+
116
+ return reader({
117
+ where: {
118
+ timestamp: between(
119
+ sample[0].timestamp,
120
+ sample[sample.length - 1].timestamp + 1
121
+ )
122
+ }
123
+ });
124
+ });
125
+
126
+ expect(stored).toEqual(sample);
127
+ }
128
+ };
106
129
  }
130
+ */
@@ -1,4 +1,5 @@
1
1
  export * from './storage';
2
+ export * from './use-cache';
2
3
  export * from './use-storage';
3
4
  export * from './use-storage-factory';
4
5
  export * from './in-memory';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC"}
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./storage"), exports);
18
+ __exportStar(require("./use-cache"), exports);
18
19
  __exportStar(require("./use-storage"), exports);
19
20
  __exportStar(require("./use-storage-factory"), exports);
20
21
  __exportStar(require("./in-memory"), exports);
@@ -1,5 +1,5 @@
1
1
  type ExecutionMode = {
2
- mode: 'REPLAY' | 'PAPER' | 'LIVE';
2
+ mode: 'replay' | 'paper' | 'live';
3
3
  recording: boolean;
4
4
  };
5
5
  export declare function replayExecutionMode(): {
@@ -6,31 +6,31 @@ const injectionToken = Symbol('execution-mode');
6
6
  function replayExecutionMode() {
7
7
  return {
8
8
  provide: injectionToken,
9
- useValue: { mode: 'REPLAY', recording: false }
9
+ useValue: { mode: 'replay', recording: false }
10
10
  };
11
11
  }
12
12
  exports.replayExecutionMode = replayExecutionMode;
13
13
  function paperExecutionMode(options) {
14
14
  return {
15
15
  provide: injectionToken,
16
- useValue: Object.assign({ mode: 'PAPER' }, options)
16
+ useValue: Object.assign({ mode: 'paper' }, options)
17
17
  };
18
18
  }
19
19
  exports.paperExecutionMode = paperExecutionMode;
20
20
  function liveExecutionMode(options) {
21
21
  return {
22
22
  provide: injectionToken,
23
- useValue: Object.assign({ mode: 'LIVE' }, options)
23
+ useValue: Object.assign({ mode: 'live' }, options)
24
24
  };
25
25
  }
26
26
  exports.liveExecutionMode = liveExecutionMode;
27
27
  const useExecutionMode = () => {
28
28
  const mode = (0, module_1.useContext)(injectionToken);
29
29
  return {
30
- isReplay: mode.mode === 'REPLAY',
31
- isPaper: mode.mode === 'PAPER',
32
- isLive: mode.mode === 'LIVE',
33
- isSimulation: mode.mode !== 'LIVE',
30
+ isReplay: mode.mode === 'replay',
31
+ isPaper: mode.mode === 'paper',
32
+ isLive: mode.mode === 'live',
33
+ isSimulation: mode.mode !== 'live',
34
34
  recording: mode.recording
35
35
  };
36
36
  };
@@ -1,12 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useTimestamp = void 0;
4
- const use_replay_coordinator_1 = require("./replay/use-replay-coordinator");
4
+ const replay_1 = require("./replay");
5
5
  const use_execution_mode_1 = require("./use-execution-mode");
6
6
  function useTimestamp() {
7
7
  const { isReplay } = (0, use_execution_mode_1.useExecutionMode)();
8
8
  if (isReplay) {
9
- return (0, use_replay_coordinator_1.useReplayCoordinator)().timestamp();
9
+ return (0, replay_1.useReplayManager)().timestamp();
10
10
  }
11
11
  return Date.now();
12
12
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantform/core",
3
- "version": "0.7.0-beta.33",
3
+ "version": "0.7.0-beta.34",
4
4
  "license": "MIT",
5
5
  "author": "Mateusz Majchrzak",
6
6
  "description": "Node.js library for building systematic trading strategies in reactive way.",
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 = await import(join(buildDirectory(), name));
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 = await import(join(buildDirectory(), name));
16
- const dependencies = script.module2 as Dependency[];
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,13 +7,10 @@ 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/replay/use-replay-coordinator';
11
10
  export * from '@lib/use-execution-mode';
12
- export * from '@lib/storage/use-storage';
13
- export * from '@lib/storage/use-cache';
11
+ export * from '@lib/storage';
14
12
  export * from '@lib/use-logger';
15
13
  export * from '@lib/replay';
16
- export * from '@lib/replay/use-replay-coordinator';
17
14
  export * from '@lib/when-socket';
18
15
  export * from '@lib/with-request';
19
16
  export * from '@lib/with-memo';
@@ -1,6 +1,8 @@
1
1
  export * from './use-replay';
2
- export * from './use-replay-coordinator';
2
+ export * from './use-replay-breakpoint';
3
3
  export * from './use-replay-options';
4
- export * from './use-replay-reader';
5
- export * from './use-replay-writer';
6
- export * from './with-replay';
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
+ });