@quantform/core 0.7.0-beta.21 → 0.7.0-beta.23

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.
@@ -1,5 +1,5 @@
1
1
  /// <reference types="jest" />
2
- import { Observable } from 'rxjs';
2
+ import { Observable, Subject } from 'rxjs';
3
3
  import { Dependency } from './module';
4
4
  export declare function makeTestModule(dependencies: Dependency[]): Promise<{
5
5
  act: <T>(func: () => T) => T;
@@ -9,5 +9,6 @@ type MockableFunction = (...args: any[]) => any;
9
9
  export declare const mockedFunc: <Func extends MockableFunction>(mockedFunc: Func) => jest.MockedFunction<Func>;
10
10
  export declare function toArray<T>(observable: Observable<T>): (Error | T)[];
11
11
  export type InferObservableType<T> = T extends Observable<infer U> ? U : never;
12
+ export declare function mockSubject<T extends jest.FunctionProperties<Required<T>>, M extends keyof jest.FunctionProperties<Required<T>>>(object: T, method: M): Subject<InferObservableType<ReturnType<jest.FunctionProperties<Required<T>>[M]>>>;
12
13
  export {};
13
14
  //# sourceMappingURL=make-test-module.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"make-test-module.d.ts","sourceRoot":"","sources":["../src/make-test-module.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAGlC,OAAO,EAAE,UAAU,EAAU,MAAM,aAAa,CAAC;AAEjD,wBAAsB,cAAc,CAAC,YAAY,EAAE,UAAU,EAAE;;;GAS9D;AAED,KAAK,gBAAgB,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;AAEhD,eAAO,MAAM,UAAU,gFAC+B,CAAC;AAEvD,wBAAgB,OAAO,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,iBAyBnD;AAED,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAAI,CAAC,SAAS,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC"}
1
+ {"version":3,"file":"make-test-module.d.ts","sourceRoot":"","sources":["../src/make-test-module.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAG3C,OAAO,EAAE,UAAU,EAAU,MAAM,aAAa,CAAC;AAEjD,wBAAsB,cAAc,CAAC,YAAY,EAAE,UAAU,EAAE;;;GAS9D;AAED,KAAK,gBAAgB,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;AAEhD,eAAO,MAAM,UAAU,gFAC+B,CAAC;AAEvD,wBAAgB,OAAO,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,iBAyBnD;AAED,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAAI,CAAC,SAAS,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAE/E,wBAAgB,WAAW,CACzB,CAAC,SAAS,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAC9C,CAAC,SAAS,MAAM,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EACpD,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,qFAYrB"}
@@ -9,7 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.toArray = exports.mockedFunc = exports.makeTestModule = void 0;
12
+ exports.mockSubject = exports.toArray = exports.mockedFunc = exports.makeTestModule = void 0;
13
+ const rxjs_1 = require("rxjs");
13
14
  const core_1 = require("./core");
14
15
  const module_1 = require("./module");
15
16
  function makeTestModule(dependencies) {
@@ -46,3 +47,11 @@ function toArray(observable) {
46
47
  return array;
47
48
  }
48
49
  exports.toArray = toArray;
50
+ function mockSubject(object, method) {
51
+ const subject = new rxjs_1.Subject();
52
+ jest
53
+ .spyOn(object, method)
54
+ .mockReturnValue(subject.asObservable());
55
+ return subject;
56
+ }
57
+ exports.mockSubject = mockSubject;
@@ -18,7 +18,7 @@ function whenSocket(url, options = { pingInterval: 5000 }) {
18
18
  stream.error(it);
19
19
  };
20
20
  socket.onclose = () => {
21
- debug('errored', url);
21
+ debug('closed', url);
22
22
  clearInterval(interval);
23
23
  stream.error();
24
24
  };
@@ -1,16 +1,17 @@
1
+ import { Observable } from 'rxjs';
1
2
  export type RequestMethod = 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE' | 'PATCH';
2
3
  export declare class RequestNetworkError extends Error {
3
4
  readonly statusCode: number;
4
5
  readonly json: () => Promise<string>;
5
6
  constructor(statusCode: number, json: () => Promise<string>);
6
7
  }
7
- export declare function withRequest(args: {
8
+ export declare function withRequest({ method, url, headers, body }: {
8
9
  method: RequestMethod;
9
10
  url: string;
10
11
  headers?: Record<string, any>;
11
12
  body?: string;
12
- }): import("rxjs").Observable<{
13
+ }): Observable<{
13
14
  timestamp: number;
14
- payload: any;
15
+ payload: unknown;
15
16
  }>;
16
17
  //# sourceMappingURL=with-request.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"with-request.d.ts","sourceRoot":"","sources":["../src/with-request.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,aAAa,GACrB,KAAK,GACL,MAAM,GACN,MAAM,GACN,KAAK,GACL,QAAQ,GACR,SAAS,GACT,SAAS,GACT,OAAO,GACP,OAAO,CAAC;AAEZ,qBAAa,mBAAoB,SAAQ,KAAK;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC;gBAAxD,UAAU,EAAE,MAAM,EAAW,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC;CAG9E;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,MAAM,EAAE,aAAa,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;;;GAsBA"}
1
+ {"version":3,"file":"with-request.d.ts","sourceRoot":"","sources":["../src/with-request.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAMlC,MAAM,MAAM,aAAa,GACrB,KAAK,GACL,MAAM,GACN,MAAM,GACN,KAAK,GACL,QAAQ,GACR,SAAS,GACT,SAAS,GACT,OAAO,GACP,OAAO,CAAC;AAEZ,qBAAa,mBAAoB,SAAQ,KAAK;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC;gBAAxD,UAAU,EAAE,MAAM,EAAW,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC;CAG9E;AAED,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,GAAG,EACH,OAAO,EACP,IAAI,EACL,EAAE;IACD,MAAM,EAAE,aAAa,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;eAGoC,MAAM;aAAW,OAAO;GA6C5D"}
@@ -1,6 +1,16 @@
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
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  exports.withRequest = exports.RequestNetworkError = void 0;
13
+ const node_crypto_1 = require("node:crypto");
4
14
  const rxjs_1 = require("rxjs");
5
15
  const undici_1 = require("undici");
6
16
  const use_logger_1 = require("./use-logger");
@@ -13,14 +23,47 @@ class RequestNetworkError extends Error {
13
23
  }
14
24
  }
15
25
  exports.RequestNetworkError = RequestNetworkError;
16
- function withRequest(args) {
17
- const { error } = (0, use_logger_1.useLogger)(withRequest.name);
18
- return (0, rxjs_1.defer)(() => (0, rxjs_1.from)((0, undici_1.request)(args.url, args)).pipe((0, rxjs_1.switchMap)(it => {
19
- if (it.statusCode !== 200) {
20
- error(`errored`, Object.assign(Object.assign({}, args), { statusCode: it.statusCode }));
21
- return (0, rxjs_1.throwError)(() => new RequestNetworkError(it.statusCode, () => it.body.json()));
22
- }
23
- return (0, rxjs_1.from)(it.body.json());
24
- }), (0, rxjs_1.map)(payload => ({ timestamp: (0, use_timestamp_1.useTimestamp)(), payload }))));
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
+ });
25
68
  }
26
69
  exports.withRequest = withRequest;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantform/core",
3
- "version": "0.7.0-beta.21",
3
+ "version": "0.7.0-beta.23",
4
4
  "license": "MIT",
5
5
  "author": "Mateusz Majchrzak",
6
6
  "description": "Node.js library for building systematic trading strategies in reactive way.",
@@ -1,4 +1,4 @@
1
- import { Observable } from 'rxjs';
1
+ import { Observable, Subject } from 'rxjs';
2
2
 
3
3
  import { core } from '@lib/core';
4
4
  import { Dependency, Module } from '@lib/module';
@@ -47,3 +47,20 @@ export function toArray<T>(observable: Observable<T>) {
47
47
  }
48
48
 
49
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
+ }
@@ -23,7 +23,7 @@ export function whenSocket(
23
23
  stream.error(it);
24
24
  };
25
25
  socket.onclose = () => {
26
- debug('errored', url);
26
+ debug('closed', url);
27
27
  clearInterval(interval);
28
28
  stream.error();
29
29
  };
@@ -1,4 +1,5 @@
1
- import { defer, from, map, switchMap, throwError } from 'rxjs';
1
+ import { randomUUID } from 'node:crypto';
2
+ import { Observable } from 'rxjs';
2
3
  import { request } from 'undici';
3
4
 
4
5
  import { useLogger } from './use-logger';
@@ -21,31 +22,62 @@ export class RequestNetworkError extends Error {
21
22
  }
22
23
  }
23
24
 
24
- export function withRequest(args: {
25
+ export function withRequest({
26
+ method,
27
+ url,
28
+ headers,
29
+ body
30
+ }: {
25
31
  method: RequestMethod;
26
32
  url: string;
27
33
  headers?: Record<string, any>;
28
34
  body?: string;
29
35
  }) {
30
- const { error } = useLogger(withRequest.name);
36
+ const { error, debug } = useLogger(withRequest.name);
31
37
 
32
- return defer(() =>
33
- from(request(args.url, args)).pipe(
34
- switchMap(it => {
35
- if (it.statusCode !== 200) {
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) {
36
57
  error(`errored`, {
37
- ...args,
38
- statusCode: it.statusCode
58
+ method,
59
+ url,
60
+ headers,
61
+ body,
62
+ statusCode
39
63
  });
40
64
 
41
- return throwError(
42
- () => new RequestNetworkError(it.statusCode, () => it.body.json())
43
- );
65
+ subscriber.error(new RequestNetworkError(statusCode, () => json));
66
+ } else {
67
+ subscriber.next({ timestamp: useTimestamp(), payload: json });
44
68
  }
69
+ })
70
+ .catch((e: Error) => {
71
+ error(`errored`, {
72
+ method,
73
+ url,
74
+ headers,
75
+ body,
76
+ error: e
77
+ });
45
78
 
46
- return from(it.body.json());
47
- }),
48
- map(payload => ({ timestamp: useTimestamp(), payload }))
49
- )
50
- );
79
+ subscriber.error(error);
80
+ })
81
+ .finally(() => subscriber.complete());
82
+ });
51
83
  }