@quantform/core 0.7.0-beta.4 → 0.7.0-beta.41
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,85 @@
|
|
|
1
|
+
import { makeTestModule, mockedFunc } from '@lib/make-test-module';
|
|
2
|
+
import { Query, QueryObject, Storage } from '@lib/storage';
|
|
3
|
+
import { useStorage } from '@lib/storage';
|
|
4
|
+
|
|
5
|
+
import { useReplayStorage } from './use-replay-storage';
|
|
6
|
+
|
|
7
|
+
jest.mock('@lib/storage', () => ({
|
|
8
|
+
...jest.requireActual('@lib/storage'),
|
|
9
|
+
useStorage: jest.fn()
|
|
10
|
+
}));
|
|
11
|
+
|
|
12
|
+
describe(useReplayStorage.name, () => {
|
|
13
|
+
let fixtures: Awaited<ReturnType<typeof getFixtures>>;
|
|
14
|
+
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
fixtures = await getFixtures();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('query', () => {
|
|
20
|
+
test('happy path', async () => {
|
|
21
|
+
await fixtures.given.stored(fixtures.sample);
|
|
22
|
+
const sample = await fixtures.when.queried({});
|
|
23
|
+
|
|
24
|
+
expect(sample).toEqual(fixtures.sample);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe('save', () => {
|
|
29
|
+
test('happy path', async () => {
|
|
30
|
+
await fixtures.when.saved(fixtures.sample);
|
|
31
|
+
await fixtures.then.stored(fixtures.sample);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
async function getFixtures() {
|
|
37
|
+
const { act } = await makeTestModule([]);
|
|
38
|
+
|
|
39
|
+
const dependencies = ['binance:btc-usdt', 'candle', 'h1'];
|
|
40
|
+
const save: Storage['save'] = jest.fn();
|
|
41
|
+
const query: jest.MockedFunction<Storage['query']> = jest.fn();
|
|
42
|
+
|
|
43
|
+
mockedFunc(useStorage).mockReturnValue({ save, query } as any);
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
sample: [
|
|
47
|
+
{ timestamp: 1, payload: { o: 1.1, h: 1.1, l: 1.1, c: 1.1 } },
|
|
48
|
+
{ timestamp: 2, payload: { o: 1.1, h: 2.2, l: 1.1, c: 2.2 } },
|
|
49
|
+
{ timestamp: 3, payload: { o: 1.1, h: 3.3, l: 1.1, c: 3.3 } }
|
|
50
|
+
],
|
|
51
|
+
|
|
52
|
+
given: {
|
|
53
|
+
stored<T>(sample: { timestamp: number; payload: T }[]) {
|
|
54
|
+
return query.mockReturnValue(
|
|
55
|
+
Promise.resolve(
|
|
56
|
+
sample.map(it => ({
|
|
57
|
+
timestamp: it.timestamp,
|
|
58
|
+
payload: JSON.stringify(it.payload)
|
|
59
|
+
}))
|
|
60
|
+
)
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
when: {
|
|
65
|
+
saved<T>(sample: { timestamp: number; payload: T }[]) {
|
|
66
|
+
return act(() => useReplayStorage(dependencies).save(sample));
|
|
67
|
+
},
|
|
68
|
+
queried<T>(query: Query<QueryObject>) {
|
|
69
|
+
return act(() => useReplayStorage<T>(dependencies).query(query));
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
then: {
|
|
74
|
+
stored<T>(sample: { timestamp: number; payload: T }[]) {
|
|
75
|
+
expect(save).toHaveBeenCalledWith(
|
|
76
|
+
expect.anything(),
|
|
77
|
+
sample.map(it => ({
|
|
78
|
+
timestamp: it.timestamp,
|
|
79
|
+
payload: JSON.stringify(it.payload)
|
|
80
|
+
}))
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -1,8 +1,29 @@
|
|
|
1
|
-
import { Storage, useStorage } from '@lib/storage';
|
|
1
|
+
import { Query, QueryObject, Storage, useStorage } from '@lib/storage';
|
|
2
|
+
import { dependency, useHash } from '@lib/use-hash';
|
|
2
3
|
|
|
3
|
-
export
|
|
4
|
-
|
|
4
|
+
export function useReplayStorage<T>(dependencies: dependency[]) {
|
|
5
|
+
const storage = useStorage(['replay']);
|
|
6
|
+
const storageObjectKey = useHash(dependencies);
|
|
7
|
+
const storageObject = Storage.createObject(storageObjectKey, {
|
|
8
|
+
timestamp: 'number',
|
|
9
|
+
payload: 'string'
|
|
10
|
+
});
|
|
5
11
|
|
|
6
|
-
|
|
7
|
-
|
|
12
|
+
return {
|
|
13
|
+
async query(query: Query<QueryObject>) {
|
|
14
|
+
return (await storage.query(storageObject, query)).map(it => ({
|
|
15
|
+
timestamp: it.timestamp,
|
|
16
|
+
payload: JSON.parse(it.payload) as T
|
|
17
|
+
}));
|
|
18
|
+
},
|
|
19
|
+
save(objects: { timestamp: number; payload: T }[]) {
|
|
20
|
+
return storage.save(
|
|
21
|
+
storageObject,
|
|
22
|
+
objects.map(it => ({
|
|
23
|
+
timestamp: it.timestamp,
|
|
24
|
+
payload: JSON.stringify(it.payload)
|
|
25
|
+
}))
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
8
29
|
}
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
+
import exp from 'constants';
|
|
1
2
|
import { from, lastValueFrom, tap } from 'rxjs';
|
|
2
3
|
|
|
3
4
|
import { makeTestModule } from '@lib/make-test-module';
|
|
4
|
-
import { useReplayCoordinator } from '@lib/replay/use-replay-coordinator';
|
|
5
5
|
import { replayExecutionMode } from '@lib/use-execution-mode';
|
|
6
6
|
import { dependency } from '@lib/use-hash';
|
|
7
7
|
|
|
8
8
|
import { between } from '..';
|
|
9
9
|
import { useReplay } from './use-replay';
|
|
10
10
|
import { replayOptions } from './use-replay-options';
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
|
|
12
|
+
describe(useReplay.name, () => {
|
|
13
|
+
test('happy path', () => {
|
|
14
|
+
expect(true).toBe(true);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
/*
|
|
13
19
|
|
|
14
20
|
describe.skip(useReplayCoordinator.name, () => {
|
|
15
21
|
let fixtures: Awaited<ReturnType<typeof getFixtures>>;
|
|
@@ -130,3 +136,4 @@ async function getFixtures() {
|
|
|
130
136
|
}
|
|
131
137
|
};
|
|
132
138
|
}
|
|
139
|
+
*/
|
package/src/replay/use-replay.ts
CHANGED
|
@@ -1,34 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Observable, tap } from 'rxjs';
|
|
2
2
|
|
|
3
|
-
import { useReplayCoordinator } from '@lib/replay/use-replay-coordinator';
|
|
4
3
|
import { useExecutionMode } from '@lib/use-execution-mode';
|
|
5
4
|
import { dependency } from '@lib/use-hash';
|
|
6
5
|
|
|
7
|
-
import {
|
|
6
|
+
import { useReplayManager } from './use-replay-manager';
|
|
7
|
+
import { useReplayStorage } from './use-replay-storage';
|
|
8
8
|
|
|
9
|
-
export
|
|
9
|
+
export function useReplay<T>(
|
|
10
10
|
input: Observable<{ timestamp: number; payload: T }>,
|
|
11
11
|
dependencies: dependency[]
|
|
12
|
-
)
|
|
12
|
+
) {
|
|
13
13
|
const { isReplay, recording } = useExecutionMode();
|
|
14
14
|
|
|
15
15
|
if (isReplay) {
|
|
16
|
-
const {
|
|
16
|
+
const { when } = useReplayManager();
|
|
17
17
|
|
|
18
|
-
return
|
|
19
|
-
map(it => it as unknown as { timestamp: number; payload: T })
|
|
20
|
-
);
|
|
18
|
+
return when<T>(dependencies);
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
if (recording) {
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
await writer([it]);
|
|
28
|
-
return it;
|
|
29
|
-
})
|
|
30
|
-
);
|
|
22
|
+
const { save } = useReplayStorage<T>(dependencies);
|
|
23
|
+
|
|
24
|
+
return input.pipe(tap(it => save([it])));
|
|
31
25
|
}
|
|
32
26
|
|
|
33
27
|
return input;
|
|
34
|
-
}
|
|
28
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useSession } from '@lib/session';
|
|
2
2
|
import { useStorage } from '@lib/storage';
|
|
3
|
-
import {
|
|
3
|
+
import { withMemo } from '@lib/with-memo';
|
|
4
4
|
|
|
5
|
-
export const useSessionStorage =
|
|
5
|
+
export const useSessionStorage = withMemo(() => {
|
|
6
6
|
const { id } = useSession();
|
|
7
7
|
|
|
8
8
|
return useStorage(['session', id]);
|
package/src/storage/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { use } from '@lib/use';
|
|
2
1
|
import { dependency, useHash } from '@lib/use-hash';
|
|
2
|
+
import { withMemo } from '@lib/with-memo';
|
|
3
3
|
|
|
4
4
|
import { useStorageFactory } from './use-storage-factory';
|
|
5
5
|
|
|
6
|
-
export const useStorage =
|
|
6
|
+
export const useStorage = withMemo((dependencies: dependency[]) => {
|
|
7
7
|
const key = useHash(dependencies);
|
|
8
8
|
const factory = useStorageFactory();
|
|
9
9
|
|
|
@@ -3,28 +3,35 @@ import { useContext } from '@lib/module';
|
|
|
3
3
|
const injectionToken = Symbol('execution-mode');
|
|
4
4
|
|
|
5
5
|
type ExecutionMode = {
|
|
6
|
-
mode: '
|
|
6
|
+
mode: 'replay' | 'paper' | 'live' | 'idle';
|
|
7
7
|
recording: boolean;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
export function replayExecutionMode() {
|
|
11
11
|
return {
|
|
12
12
|
provide: injectionToken,
|
|
13
|
-
useValue: { mode: '
|
|
13
|
+
useValue: { mode: 'replay', recording: false } as ExecutionMode
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export function paperExecutionMode(options: { recording: boolean }) {
|
|
18
18
|
return {
|
|
19
19
|
provide: injectionToken,
|
|
20
|
-
useValue: { mode: '
|
|
20
|
+
useValue: { mode: 'paper', ...options } as ExecutionMode
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export function liveExecutionMode(options: { recording: boolean }) {
|
|
25
25
|
return {
|
|
26
26
|
provide: injectionToken,
|
|
27
|
-
useValue: { mode: '
|
|
27
|
+
useValue: { mode: 'live', ...options } as ExecutionMode
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function idleExecutionMode() {
|
|
32
|
+
return {
|
|
33
|
+
provide: injectionToken,
|
|
34
|
+
useValue: { mode: 'idle', recording: false } as ExecutionMode
|
|
28
35
|
};
|
|
29
36
|
}
|
|
30
37
|
|
|
@@ -32,10 +39,11 @@ export const useExecutionMode = () => {
|
|
|
32
39
|
const mode = useContext<ExecutionMode>(injectionToken);
|
|
33
40
|
|
|
34
41
|
return {
|
|
35
|
-
isReplay: mode.mode === '
|
|
36
|
-
isPaper: mode.mode === '
|
|
37
|
-
isLive: mode.mode === '
|
|
38
|
-
|
|
42
|
+
isReplay: mode.mode === 'replay',
|
|
43
|
+
isPaper: mode.mode === 'paper',
|
|
44
|
+
isLive: mode.mode === 'live',
|
|
45
|
+
isIdle: mode.mode === 'idle',
|
|
46
|
+
isSimulation: mode.mode !== 'live',
|
|
39
47
|
recording: mode.recording
|
|
40
48
|
};
|
|
41
49
|
};
|
package/src/use-logger.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
|
|
3
|
-
import { use } from './use';
|
|
4
3
|
import { useTimestamp } from './use-timestamp';
|
|
4
|
+
import { withMemo } from './with-memo';
|
|
5
5
|
|
|
6
6
|
const colorize = (content: string) => {
|
|
7
7
|
let hash = 0x811c9dc5;
|
|
@@ -17,7 +17,7 @@ const colorize = (content: string) => {
|
|
|
17
17
|
/**
|
|
18
18
|
*
|
|
19
19
|
*/
|
|
20
|
-
export const useLogger =
|
|
20
|
+
export const useLogger = withMemo((context: string, tint?: string) => {
|
|
21
21
|
const prefix = () =>
|
|
22
22
|
`${chalk.gray(new Date(useTimestamp()).toISOString())} ${chalk.hex(
|
|
23
23
|
tint ?? colorize(context)
|
|
@@ -41,7 +41,7 @@ export const useLogger = use((context: string, tint?: string) => {
|
|
|
41
41
|
|
|
42
42
|
error: (message: any, ...params: unknown[]) =>
|
|
43
43
|
params?.length
|
|
44
|
-
? console.error(`${prefix()}: ${message}`, params)
|
|
45
|
-
: console.error(`${prefix()}: ${message}`)
|
|
44
|
+
? console.error(`${prefix()}: ${chalk.red(message)}`, params)
|
|
45
|
+
: console.error(`${prefix()}: ${chalk.red(message)}`)
|
|
46
46
|
};
|
|
47
47
|
});
|
package/src/use-memo.ts
CHANGED
|
@@ -13,16 +13,6 @@ export function memo() {
|
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
/**
|
|
17
|
-
* @name useMemo
|
|
18
|
-
* @description
|
|
19
|
-
* A hook that caches the result of an expensive calculation, based on a set of dependencies.
|
|
20
|
-
*
|
|
21
|
-
* @template T The type of the value that is memoized.
|
|
22
|
-
* @param {() => T} calculateValue A function that returns the value to memoize.
|
|
23
|
-
* @param {dependency[]} dependencies An array of dependencies that determine when the value should be recalculated.
|
|
24
|
-
* @returns {T} The memoized value.
|
|
25
|
-
*/
|
|
26
16
|
export function useMemo<T>(calculateValue: () => T, dependencies: dependency[]) {
|
|
27
17
|
const memory = useContext<Record<string, any>>(token);
|
|
28
18
|
const hash = useHash(dependencies);
|
package/src/use-timestamp.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useReplayManager } from '@lib/replay';
|
|
2
2
|
import { useExecutionMode } from '@lib/use-execution-mode';
|
|
3
3
|
|
|
4
4
|
export function useTimestamp() {
|
|
5
5
|
const { isReplay } = useExecutionMode();
|
|
6
6
|
|
|
7
7
|
if (isReplay) {
|
|
8
|
-
return
|
|
8
|
+
return useReplayManager().timestamp();
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
return Date.now();
|
|
@@ -4,10 +4,11 @@ import { WebSocket } from 'ws';
|
|
|
4
4
|
import { useLogger } from './use-logger';
|
|
5
5
|
import { useTimestamp } from './use-timestamp';
|
|
6
6
|
|
|
7
|
-
export function
|
|
8
|
-
url: string
|
|
7
|
+
export function whenSocket(
|
|
8
|
+
url: string,
|
|
9
|
+
options: { pingInterval?: number } = { pingInterval: 5000 }
|
|
9
10
|
): [Observable<{ timestamp: number; payload: unknown }>, (message: unknown) => void] {
|
|
10
|
-
const { debug } = useLogger('
|
|
11
|
+
const { debug } = useLogger('whenSocket');
|
|
11
12
|
|
|
12
13
|
const message = new Observable<{ timestamp: number; payload: unknown }>(stream => {
|
|
13
14
|
const socket = new WebSocket(url);
|
|
@@ -18,6 +19,7 @@ export function useSocket(
|
|
|
18
19
|
stream.next({ timestamp: useTimestamp(), payload: JSON.parse(it.data as string) });
|
|
19
20
|
socket.onerror = it => {
|
|
20
21
|
clearInterval(interval);
|
|
22
|
+
debug('errored', url);
|
|
21
23
|
stream.error(it);
|
|
22
24
|
};
|
|
23
25
|
socket.onclose = () => {
|
|
@@ -37,7 +39,7 @@ export function useSocket(
|
|
|
37
39
|
socket.terminate();
|
|
38
40
|
clearInterval(interval);
|
|
39
41
|
}
|
|
40
|
-
},
|
|
42
|
+
}, options.pingInterval);
|
|
41
43
|
|
|
42
44
|
socket.on('pong', () => {
|
|
43
45
|
isAlive = true;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { makeTestModule } from '@lib/make-test-module';
|
|
2
2
|
|
|
3
3
|
import { instrumentOf, InstrumentSelector } from './instrument';
|
|
4
|
-
import {
|
|
4
|
+
import { withMemo } from './with-memo';
|
|
5
5
|
|
|
6
|
-
describe(
|
|
6
|
+
describe(withMemo.name, () => {
|
|
7
7
|
let fixtures: Awaited<ReturnType<typeof getFixtures>>;
|
|
8
8
|
|
|
9
9
|
beforeEach(async () => {
|
|
@@ -37,7 +37,7 @@ describe(use.name, () => {
|
|
|
37
37
|
async function getFixtures() {
|
|
38
38
|
const { act } = await makeTestModule([]);
|
|
39
39
|
|
|
40
|
-
const getValue =
|
|
40
|
+
const getValue = withMemo((instrument: InstrumentSelector) => instrument.id);
|
|
41
41
|
|
|
42
42
|
return {
|
|
43
43
|
act,
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { isObservable, Observable, shareReplay } from 'rxjs';
|
|
2
2
|
import { v4 } from 'uuid';
|
|
3
3
|
|
|
4
|
-
import { asReadonly } from './as-readonly';
|
|
5
4
|
import { throwWithContext } from './module';
|
|
5
|
+
import { asReadonly } from './operators';
|
|
6
6
|
import { dependency } from './use-hash';
|
|
7
7
|
import { useMemo } from './use-memo';
|
|
8
8
|
|
|
9
|
-
export function
|
|
9
|
+
export function withMemo<T extends Array<dependency>, U>(
|
|
10
10
|
fn: (...args: T) => U
|
|
11
11
|
): (...args: T) => U;
|
|
12
|
-
export function
|
|
12
|
+
export function withMemo<T extends Array<dependency>, U>(
|
|
13
13
|
fn: (...args: T) => Observable<U>
|
|
14
14
|
): (...args: T) => Observable<U>;
|
|
15
15
|
|
|
16
|
-
export function
|
|
16
|
+
export function withMemo<T extends Array<dependency>, U>(
|
|
17
17
|
fn: (...args: T) => U | Observable<U>
|
|
18
18
|
): (...args: T) => U | Observable<U> {
|
|
19
19
|
throwWithContext();
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { request } from 'undici';
|
|
4
|
+
|
|
5
|
+
import { useLogger } from './use-logger';
|
|
6
|
+
import { useTimestamp } from './use-timestamp';
|
|
7
|
+
|
|
8
|
+
export type RequestMethod =
|
|
9
|
+
| 'GET'
|
|
10
|
+
| 'HEAD'
|
|
11
|
+
| 'POST'
|
|
12
|
+
| 'PUT'
|
|
13
|
+
| 'DELETE'
|
|
14
|
+
| 'CONNECT'
|
|
15
|
+
| 'OPTIONS'
|
|
16
|
+
| 'TRACE'
|
|
17
|
+
| 'PATCH';
|
|
18
|
+
|
|
19
|
+
export class RequestNetworkError extends Error {
|
|
20
|
+
constructor(readonly statusCode: number, readonly json: () => Promise<string>) {
|
|
21
|
+
super(`Request network error, received status code: ${statusCode}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function withRequest({
|
|
26
|
+
method,
|
|
27
|
+
url,
|
|
28
|
+
headers,
|
|
29
|
+
body
|
|
30
|
+
}: {
|
|
31
|
+
method: RequestMethod;
|
|
32
|
+
url: string;
|
|
33
|
+
headers?: Record<string, any>;
|
|
34
|
+
body?: string;
|
|
35
|
+
}) {
|
|
36
|
+
const { error, debug } = useLogger(withRequest.name);
|
|
37
|
+
|
|
38
|
+
return new Observable<{ timestamp: number; payload: unknown }>(subscriber => {
|
|
39
|
+
const correlationId = randomUUID();
|
|
40
|
+
|
|
41
|
+
debug('requesting', { correlationId, method, url, headers, body });
|
|
42
|
+
|
|
43
|
+
request(url, { method, headers, body })
|
|
44
|
+
.then(async ({ statusCode, body }) => {
|
|
45
|
+
const json = await body.json();
|
|
46
|
+
|
|
47
|
+
debug('received', {
|
|
48
|
+
correlationId,
|
|
49
|
+
method,
|
|
50
|
+
url,
|
|
51
|
+
headers,
|
|
52
|
+
body: json,
|
|
53
|
+
statusCode
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (statusCode !== 200) {
|
|
57
|
+
error(`errored`, {
|
|
58
|
+
method,
|
|
59
|
+
url,
|
|
60
|
+
headers,
|
|
61
|
+
body,
|
|
62
|
+
statusCode
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
subscriber.error(new RequestNetworkError(statusCode, () => json));
|
|
66
|
+
} else {
|
|
67
|
+
subscriber.next({ timestamp: useTimestamp(), payload: json });
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
.catch((e: Error) => {
|
|
71
|
+
error(`errored`, {
|
|
72
|
+
method,
|
|
73
|
+
url,
|
|
74
|
+
headers,
|
|
75
|
+
body,
|
|
76
|
+
error: e
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
subscriber.error(error);
|
|
80
|
+
})
|
|
81
|
+
.finally(() => subscriber.complete());
|
|
82
|
+
});
|
|
83
|
+
}
|
package/dist/as-readonly.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"as-readonly.d.ts","sourceRoot":"","sources":["../src/as-readonly.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,UAAU,EAAE,MAAM,MAAM,CAAC;AAEvC,wBAAgB,UAAU,CAAC,CAAC,aACX,WAAW,CAAC,CAAC,6BAC7B"}
|
package/dist/as-readonly.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.asReadonly = void 0;
|
|
4
|
-
const rxjs_1 = require("rxjs");
|
|
5
|
-
function asReadonly() {
|
|
6
|
-
return (input) => input.pipe((0, rxjs_1.map)(it => it));
|
|
7
|
-
}
|
|
8
|
-
exports.asReadonly = asReadonly;
|
package/dist/defined.d.ts
DELETED
package/dist/defined.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"defined.d.ts","sourceRoot":"","sources":["../src/defined.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,UAAU,EAAE,MAAM,MAAM,CAAC;AAE1C,wBAAgB,OAAO,CAAC,CAAC,kBACH,WAAW,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC,sCAErD"}
|
package/dist/defined.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.defined = void 0;
|
|
4
|
-
const rxjs_1 = require("rxjs");
|
|
5
|
-
function defined() {
|
|
6
|
-
return (observable) => observable.pipe((0, rxjs_1.filter)(it => it !== undefined && it !== null));
|
|
7
|
-
}
|
|
8
|
-
exports.defined = defined;
|
package/dist/exclude.d.ts
DELETED
package/dist/exclude.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"exclude.d.ts","sourceRoot":"","sources":["../src/exclude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,UAAU,EAAE,MAAM,MAAM,CAAC;AAE/C,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,gBAC3B,WAAW,CAAC,GAAG,CAAC,CAAC,+BAKtC"}
|
package/dist/exclude.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.exclude = void 0;
|
|
4
|
-
const rxjs_1 = require("rxjs");
|
|
5
|
-
function exclude(s) {
|
|
6
|
-
return (observable) => observable.pipe((0, rxjs_1.filter)(it => it !== s), (0, rxjs_1.map)(it => it));
|
|
7
|
-
}
|
|
8
|
-
exports.exclude = exclude;
|
package/dist/not-found.d.ts
DELETED
package/dist/not-found.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"not-found.d.ts","sourceRoot":"","sources":["../src/not-found.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,eAA0B,CAAC"}
|
package/dist/not-found.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { dependency } from '../use-hash';
|
|
2
|
-
export declare function useReplayCoordinator(): {
|
|
3
|
-
timestamp: () => number;
|
|
4
|
-
stop: () => number;
|
|
5
|
-
tryContinue: () => void;
|
|
6
|
-
subscribe: (dependencies: dependency[]) => import("rxjs").Observable<{
|
|
7
|
-
timestamp: number;
|
|
8
|
-
}>;
|
|
9
|
-
};
|
|
10
|
-
//# sourceMappingURL=use-replay-coordinator.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"use-replay-coordinator.d.ts","sourceRoot":"","sources":["../../src/replay/use-replay-coordinator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAO3C,wBAAgB,oBAAoB;;;;8BAUC,UAAU,EAAE;mBAFW,MAAM;;EAsFjE"}
|