@nest-yalc-2/api-strategy 1.3.3

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/LICENSE +661 -0
  2. package/README.md +40 -0
  3. package/package.json +33 -0
  4. package/src/__tests__/call-strategy-wrappers.spec.ts +217 -0
  5. package/src/__tests__/context-call.service.spec.ts +52 -0
  6. package/src/__tests__/context-event.service.spec.ts +52 -0
  7. package/src/__tests__/event-strategy-composition.spec.ts +185 -0
  8. package/src/__tests__/header-whitelist.helper.spec.ts +30 -0
  9. package/src/__tests__/http-abstract-call.strategy.spec.ts +17 -0
  10. package/src/__tests__/nest-http-call.strategy.spec.ts +164 -0
  11. package/src/__tests__/nest-local-call.strategy.spec.ts +263 -0
  12. package/src/__tests__/nest-local-event.strategy.spec.ts +55 -0
  13. package/src/__tests__/rabbitmq-event.strategy.spec.ts +220 -0
  14. package/src/__tests__/strategy-selector.provider.spec.ts +182 -0
  15. package/src/context-call.interface.d.ts +12 -0
  16. package/src/context-call.interface.js +3 -0
  17. package/src/context-call.interface.js.map +1 -0
  18. package/src/context-call.interface.ts +49 -0
  19. package/src/context-call.service.d.ts +7 -0
  20. package/src/context-call.service.js +32 -0
  21. package/src/context-call.service.js.map +1 -0
  22. package/src/context-call.service.ts +31 -0
  23. package/src/context-event.interface.d.ts +4 -0
  24. package/src/context-event.interface.js +3 -0
  25. package/src/context-event.interface.js.map +1 -0
  26. package/src/context-event.interface.ts +4 -0
  27. package/src/context-event.service.d.ts +7 -0
  28. package/src/context-event.service.js +32 -0
  29. package/src/context-event.service.js.map +1 -0
  30. package/src/context-event.service.ts +31 -0
  31. package/src/header-whitelist.helper.d.ts +2 -0
  32. package/src/header-whitelist.helper.js +13 -0
  33. package/src/header-whitelist.helper.js.map +1 -0
  34. package/src/header-whitelist.helper.ts +12 -0
  35. package/src/index.d.ts +15 -0
  36. package/src/index.js +32 -0
  37. package/src/index.js.map +1 -0
  38. package/src/index.ts +17 -0
  39. package/src/strategies/composite-event.strategy.d.ts +14 -0
  40. package/src/strategies/composite-event.strategy.js +52 -0
  41. package/src/strategies/composite-event.strategy.js.map +1 -0
  42. package/src/strategies/composite-event.strategy.ts +76 -0
  43. package/src/strategies/conditional-call.strategy.d.ts +17 -0
  44. package/src/strategies/conditional-call.strategy.js +41 -0
  45. package/src/strategies/conditional-call.strategy.js.map +1 -0
  46. package/src/strategies/conditional-call.strategy.ts +70 -0
  47. package/src/strategies/conditional-event.strategy.d.ts +16 -0
  48. package/src/strategies/conditional-event.strategy.js +38 -0
  49. package/src/strategies/conditional-event.strategy.js.map +1 -0
  50. package/src/strategies/conditional-event.strategy.ts +54 -0
  51. package/src/strategies/fallback-call.strategy.d.ts +14 -0
  52. package/src/strategies/fallback-call.strategy.js +41 -0
  53. package/src/strategies/fallback-call.strategy.js.map +1 -0
  54. package/src/strategies/fallback-call.strategy.ts +67 -0
  55. package/src/strategies/http-abstract-call.strategy.d.ts +44 -0
  56. package/src/strategies/http-abstract-call.strategy.js +19 -0
  57. package/src/strategies/http-abstract-call.strategy.js.map +1 -0
  58. package/src/strategies/http-abstract-call.strategy.ts +238 -0
  59. package/src/strategies/nest-http-call.strategy.d.ts +30 -0
  60. package/src/strategies/nest-http-call.strategy.js +68 -0
  61. package/src/strategies/nest-http-call.strategy.js.map +1 -0
  62. package/src/strategies/nest-http-call.strategy.ts +121 -0
  63. package/src/strategies/nest-local-call.strategy.d.ts +32 -0
  64. package/src/strategies/nest-local-call.strategy.js +84 -0
  65. package/src/strategies/nest-local-call.strategy.js.map +1 -0
  66. package/src/strategies/nest-local-call.strategy.ts +153 -0
  67. package/src/strategies/nest-local-event.strategy.d.ts +17 -0
  68. package/src/strategies/nest-local-event.strategy.js +30 -0
  69. package/src/strategies/nest-local-event.strategy.js.map +1 -0
  70. package/src/strategies/nest-local-event.strategy.ts +42 -0
  71. package/src/strategies/rabbitmq-event.strategy.d.ts +34 -0
  72. package/src/strategies/rabbitmq-event.strategy.js +97 -0
  73. package/src/strategies/rabbitmq-event.strategy.js.map +1 -0
  74. package/src/strategies/rabbitmq-event.strategy.ts +154 -0
  75. package/src/strategies/shadow-call.strategy.d.ts +17 -0
  76. package/src/strategies/shadow-call.strategy.js +42 -0
  77. package/src/strategies/shadow-call.strategy.js.map +1 -0
  78. package/src/strategies/shadow-call.strategy.ts +87 -0
  79. package/src/strategy-selector.provider.d.ts +19 -0
  80. package/src/strategy-selector.provider.js +52 -0
  81. package/src/strategy-selector.provider.js.map +1 -0
  82. package/src/strategy-selector.provider.ts +103 -0
@@ -0,0 +1,76 @@
1
+ import { OnModuleDestroy } from '@nestjs/common';
2
+ import type { IEventStrategy } from '../context-event.interface.js';
3
+
4
+ export type CompositeEventStrategyErrorMode = 'throw' | 'ignore';
5
+
6
+ export interface CompositeEventStrategyOptions {
7
+ errorMode?: CompositeEventStrategyErrorMode;
8
+ }
9
+
10
+ export class CompositeEventStrategy<P = any, R = any, O = any>
11
+ implements IEventStrategy<P, R[], O>, OnModuleDestroy
12
+ {
13
+ private readonly errorMode: CompositeEventStrategyErrorMode;
14
+
15
+ constructor(
16
+ private readonly strategies: IEventStrategy<P, R, O>[],
17
+ options: CompositeEventStrategyOptions = {},
18
+ ) {
19
+ if (strategies.length === 0) {
20
+ throw new Error('CompositeEventStrategy requires at least one strategy.');
21
+ }
22
+
23
+ this.errorMode = options.errorMode ?? 'throw';
24
+ }
25
+
26
+ emit(path: string, payload: P, options?: O): R[] {
27
+ const results: R[] = [];
28
+
29
+ for (const strategy of this.strategies) {
30
+ try {
31
+ results.push(strategy.emit(path, payload, options));
32
+ } catch (error) {
33
+ if (this.errorMode === 'throw') {
34
+ throw error;
35
+ }
36
+ }
37
+ }
38
+
39
+ return results;
40
+ }
41
+
42
+ async emitAsync(path: string, payload: P, options?: O): Promise<R[]> {
43
+ const settled = await Promise.allSettled(
44
+ this.strategies.map((strategy) =>
45
+ strategy.emitAsync(path, payload, options),
46
+ ),
47
+ );
48
+ const results: R[] = [];
49
+
50
+ for (const result of settled) {
51
+ if (result.status === 'fulfilled') {
52
+ results.push(result.value);
53
+ } else if (this.errorMode === 'throw') {
54
+ throw result.reason;
55
+ }
56
+ }
57
+
58
+ return results;
59
+ }
60
+
61
+ async onModuleDestroy() {
62
+ await Promise.all(
63
+ this.strategies.map(async (strategy) => {
64
+ await maybeDestroyStrategy(strategy);
65
+ }),
66
+ );
67
+ }
68
+ }
69
+
70
+ async function maybeDestroyStrategy(strategy: unknown) {
71
+ const destroyable = strategy as Partial<OnModuleDestroy>;
72
+
73
+ if (typeof destroyable.onModuleDestroy === 'function') {
74
+ await destroyable.onModuleDestroy();
75
+ }
76
+ }
@@ -0,0 +1,17 @@
1
+ import { IApiCallStrategy, ICallOptions, IObjectWithData } from '../context-call.interface.js';
2
+ export interface ConditionalCallStrategyOptions {
3
+ enabled?: boolean | (() => boolean);
4
+ disabledResponse?: IObjectWithData<any>;
5
+ disabledError?: Error | (() => Error);
6
+ }
7
+ export declare class ConditionalCallStrategy implements IApiCallStrategy {
8
+ private readonly strategy;
9
+ private readonly options;
10
+ constructor(strategy: IApiCallStrategy, options?: ConditionalCallStrategyOptions);
11
+ call<TOptData, TParams extends Record<string, any>, TResData>(path: string, options?: ICallOptions<TOptData, TParams>): Promise<IObjectWithData<TResData>>;
12
+ get<TOptData, TParams extends Record<string, any>, TResData>(path: string, options?: ICallOptions<TOptData, TParams>): Promise<IObjectWithData<TResData>>;
13
+ post<TOptData, TParams extends Record<string, any>, TResData>(path: string, options?: ICallOptions<TOptData, TParams>): Promise<IObjectWithData<TResData>>;
14
+ private whenEnabled;
15
+ private isEnabled;
16
+ private resolveDisabledError;
17
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConditionalCallStrategy = void 0;
4
+ class ConditionalCallStrategy {
5
+ constructor(strategy, options = {}) {
6
+ this.strategy = strategy;
7
+ this.options = options;
8
+ }
9
+ call(path, options) {
10
+ return this.whenEnabled(() => this.strategy.call(path, options));
11
+ }
12
+ get(path, options) {
13
+ return this.whenEnabled(() => this.strategy.get(path, options));
14
+ }
15
+ post(path, options) {
16
+ return this.whenEnabled(() => this.strategy.post(path, options));
17
+ }
18
+ async whenEnabled(execute) {
19
+ if (this.isEnabled()) {
20
+ return execute();
21
+ }
22
+ if (this.options.disabledResponse) {
23
+ return this.options.disabledResponse;
24
+ }
25
+ throw this.resolveDisabledError();
26
+ }
27
+ isEnabled() {
28
+ return typeof this.options.enabled === 'function'
29
+ ? this.options.enabled()
30
+ : this.options.enabled !== false;
31
+ }
32
+ resolveDisabledError() {
33
+ if (typeof this.options.disabledError === 'function') {
34
+ return this.options.disabledError();
35
+ }
36
+ return (this.options.disabledError ??
37
+ new Error('ConditionalCallStrategy is disabled.'));
38
+ }
39
+ }
40
+ exports.ConditionalCallStrategy = ConditionalCallStrategy;
41
+ //# sourceMappingURL=conditional-call.strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditional-call.strategy.js","sourceRoot":"","sources":["conditional-call.strategy.ts"],"names":[],"mappings":";;;AAYA,MAAa,uBAAuB;IAClC,YACmB,QAA0B,EAC1B,UAA0C,EAAE;QAD5C,aAAQ,GAAR,QAAQ,CAAkB;QAC1B,YAAO,GAAP,OAAO,CAAqC;IAC5D,CAAC;IAEJ,IAAI,CACF,IAAY,EACZ,OAAyC;QAEzC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACnE,CAAC;IAED,GAAG,CACD,IAAY,EACZ,OAAyC;QAEzC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,IAAI,CACF,IAAY,EACZ,OAAyC;QAEzC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACnE,CAAC;IAEO,KAAK,CAAC,WAAW,CACvB,OAAiD;QAEjD,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACrB,OAAO,OAAO,EAAE,CAAC;QACnB,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC,OAAO,CAAC,gBAA6C,CAAC;QACpE,CAAC;QAED,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;IACpC,CAAC;IAEO,SAAS;QACf,OAAO,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,UAAU;YAC/C,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;YACxB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK,CAAC;IACrC,CAAC;IAEO,oBAAoB;QAC1B,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,KAAK,UAAU,EAAE,CAAC;YACrD,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QACtC,CAAC;QAED,OAAO,CACL,IAAI,CAAC,OAAO,CAAC,aAAa;YAC1B,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAClD,CAAC;IACJ,CAAC;CACF;AAzDD,0DAyDC"}
@@ -0,0 +1,70 @@
1
+ import {
2
+ IApiCallStrategy,
3
+ ICallOptions,
4
+ IObjectWithData,
5
+ } from '../context-call.interface.js';
6
+
7
+ export interface ConditionalCallStrategyOptions {
8
+ enabled?: boolean | (() => boolean);
9
+ disabledResponse?: IObjectWithData<any>;
10
+ disabledError?: Error | (() => Error);
11
+ }
12
+
13
+ export class ConditionalCallStrategy implements IApiCallStrategy {
14
+ constructor(
15
+ private readonly strategy: IApiCallStrategy,
16
+ private readonly options: ConditionalCallStrategyOptions = {},
17
+ ) {}
18
+
19
+ call<TOptData, TParams extends Record<string, any>, TResData>(
20
+ path: string,
21
+ options?: ICallOptions<TOptData, TParams>,
22
+ ): Promise<IObjectWithData<TResData>> {
23
+ return this.whenEnabled(() => this.strategy.call(path, options));
24
+ }
25
+
26
+ get<TOptData, TParams extends Record<string, any>, TResData>(
27
+ path: string,
28
+ options?: ICallOptions<TOptData, TParams>,
29
+ ): Promise<IObjectWithData<TResData>> {
30
+ return this.whenEnabled(() => this.strategy.get(path, options));
31
+ }
32
+
33
+ post<TOptData, TParams extends Record<string, any>, TResData>(
34
+ path: string,
35
+ options?: ICallOptions<TOptData, TParams>,
36
+ ): Promise<IObjectWithData<TResData>> {
37
+ return this.whenEnabled(() => this.strategy.post(path, options));
38
+ }
39
+
40
+ private async whenEnabled<TResData>(
41
+ execute: () => Promise<IObjectWithData<TResData>>,
42
+ ) {
43
+ if (this.isEnabled()) {
44
+ return execute();
45
+ }
46
+
47
+ if (this.options.disabledResponse) {
48
+ return this.options.disabledResponse as IObjectWithData<TResData>;
49
+ }
50
+
51
+ throw this.resolveDisabledError();
52
+ }
53
+
54
+ private isEnabled() {
55
+ return typeof this.options.enabled === 'function'
56
+ ? this.options.enabled()
57
+ : this.options.enabled !== false;
58
+ }
59
+
60
+ private resolveDisabledError() {
61
+ if (typeof this.options.disabledError === 'function') {
62
+ return this.options.disabledError();
63
+ }
64
+
65
+ return (
66
+ this.options.disabledError ??
67
+ new Error('ConditionalCallStrategy is disabled.')
68
+ );
69
+ }
70
+ }
@@ -0,0 +1,16 @@
1
+ import { OnModuleDestroy } from '@nestjs/common';
2
+ import type { IEventStrategy } from '../context-event.interface.js';
3
+ export interface ConditionalEventStrategyOptions<P = any, R = any, O = any> {
4
+ enabled?: boolean | (() => boolean);
5
+ shouldEmit?: (path: string, payload: P, options?: O) => boolean;
6
+ disabledResult?: R;
7
+ }
8
+ export declare class ConditionalEventStrategy<P = any, R = any, O = any> implements IEventStrategy<P, R, O>, OnModuleDestroy {
9
+ private readonly strategy;
10
+ private readonly options;
11
+ constructor(strategy: IEventStrategy<P, R, O>, options?: ConditionalEventStrategyOptions<P, R, O>);
12
+ emit(path: string, payload: P, options?: O): R;
13
+ emitAsync(path: string, payload: P, options?: O): Promise<R>;
14
+ onModuleDestroy(): Promise<void>;
15
+ private shouldRun;
16
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConditionalEventStrategy = void 0;
4
+ class ConditionalEventStrategy {
5
+ constructor(strategy, options = {}) {
6
+ this.strategy = strategy;
7
+ this.options = options;
8
+ }
9
+ emit(path, payload, options) {
10
+ if (!this.shouldRun(path, payload, options)) {
11
+ return this.options.disabledResult;
12
+ }
13
+ return this.strategy.emit(path, payload, options);
14
+ }
15
+ async emitAsync(path, payload, options) {
16
+ if (!this.shouldRun(path, payload, options)) {
17
+ return this.options.disabledResult;
18
+ }
19
+ return this.strategy.emitAsync(path, payload, options);
20
+ }
21
+ async onModuleDestroy() {
22
+ const destroyable = this.strategy;
23
+ if (typeof destroyable.onModuleDestroy === 'function') {
24
+ await destroyable.onModuleDestroy();
25
+ }
26
+ }
27
+ shouldRun(path, payload, options) {
28
+ const enabled = typeof this.options.enabled === 'function'
29
+ ? this.options.enabled()
30
+ : this.options.enabled;
31
+ if (enabled === false) {
32
+ return false;
33
+ }
34
+ return this.options.shouldEmit?.(path, payload, options) ?? true;
35
+ }
36
+ }
37
+ exports.ConditionalEventStrategy = ConditionalEventStrategy;
38
+ //# sourceMappingURL=conditional-event.strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditional-event.strategy.js","sourceRoot":"","sources":["conditional-event.strategy.ts"],"names":[],"mappings":";;;AASA,MAAa,wBAAwB;IAGnC,YACmB,QAAiC,EACjC,UAAoD,EAAE;QADtD,aAAQ,GAAR,QAAQ,CAAyB;QACjC,YAAO,GAAP,OAAO,CAA+C;IACtE,CAAC;IAEJ,IAAI,CAAC,IAAY,EAAE,OAAU,EAAE,OAAW;QACxC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,cAAmB,CAAC;QAC1C,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAY,EAAE,OAAU,EAAE,OAAW;QACnD,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,cAAmB,CAAC;QAC1C,CAAC;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,MAAM,WAAW,GAAG,IAAI,CAAC,QAAoC,CAAC;QAE9D,IAAI,OAAO,WAAW,CAAC,eAAe,KAAK,UAAU,EAAE,CAAC;YACtD,MAAM,WAAW,CAAC,eAAe,EAAE,CAAC;QACtC,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,IAAY,EAAE,OAAU,EAAE,OAAW;QACrD,MAAM,OAAO,GACX,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,UAAU;YACxC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;YACxB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;QAE3B,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;YACtB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC;IACnE,CAAC;CACF;AA5CD,4DA4CC"}
@@ -0,0 +1,54 @@
1
+ import { OnModuleDestroy } from '@nestjs/common';
2
+ import type { IEventStrategy } from '../context-event.interface.js';
3
+
4
+ export interface ConditionalEventStrategyOptions<P = any, R = any, O = any> {
5
+ enabled?: boolean | (() => boolean);
6
+ shouldEmit?: (path: string, payload: P, options?: O) => boolean;
7
+ disabledResult?: R;
8
+ }
9
+
10
+ export class ConditionalEventStrategy<P = any, R = any, O = any>
11
+ implements IEventStrategy<P, R, O>, OnModuleDestroy
12
+ {
13
+ constructor(
14
+ private readonly strategy: IEventStrategy<P, R, O>,
15
+ private readonly options: ConditionalEventStrategyOptions<P, R, O> = {},
16
+ ) {}
17
+
18
+ emit(path: string, payload: P, options?: O): R {
19
+ if (!this.shouldRun(path, payload, options)) {
20
+ return this.options.disabledResult as R;
21
+ }
22
+
23
+ return this.strategy.emit(path, payload, options);
24
+ }
25
+
26
+ async emitAsync(path: string, payload: P, options?: O): Promise<R> {
27
+ if (!this.shouldRun(path, payload, options)) {
28
+ return this.options.disabledResult as R;
29
+ }
30
+
31
+ return this.strategy.emitAsync(path, payload, options);
32
+ }
33
+
34
+ async onModuleDestroy() {
35
+ const destroyable = this.strategy as Partial<OnModuleDestroy>;
36
+
37
+ if (typeof destroyable.onModuleDestroy === 'function') {
38
+ await destroyable.onModuleDestroy();
39
+ }
40
+ }
41
+
42
+ private shouldRun(path: string, payload: P, options?: O) {
43
+ const enabled =
44
+ typeof this.options.enabled === 'function'
45
+ ? this.options.enabled()
46
+ : this.options.enabled;
47
+
48
+ if (enabled === false) {
49
+ return false;
50
+ }
51
+
52
+ return this.options.shouldEmit?.(path, payload, options) ?? true;
53
+ }
54
+ }
@@ -0,0 +1,14 @@
1
+ import { IApiCallStrategy, ICallOptions, IObjectWithData } from '../context-call.interface.js';
2
+ export interface FallbackCallStrategyOptions {
3
+ shouldFallback?: (error: unknown, strategyIndex: number) => boolean;
4
+ }
5
+ export declare class FallbackCallStrategy implements IApiCallStrategy {
6
+ private readonly strategies;
7
+ private readonly options;
8
+ constructor(strategies: IApiCallStrategy[], options?: FallbackCallStrategyOptions);
9
+ call<TOptData, TParams extends Record<string, any>, TResData>(path: string, options?: ICallOptions<TOptData, TParams>): Promise<IObjectWithData<TResData>>;
10
+ get<TOptData, TParams extends Record<string, any>, TResData>(path: string, options?: ICallOptions<TOptData, TParams>): Promise<IObjectWithData<TResData>>;
11
+ post<TOptData, TParams extends Record<string, any>, TResData>(path: string, options?: ICallOptions<TOptData, TParams>): Promise<IObjectWithData<TResData>>;
12
+ private execute;
13
+ private shouldFallback;
14
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FallbackCallStrategy = void 0;
4
+ class FallbackCallStrategy {
5
+ constructor(strategies, options = {}) {
6
+ this.strategies = strategies;
7
+ this.options = options;
8
+ if (strategies.length === 0) {
9
+ throw new Error('FallbackCallStrategy requires at least one strategy.');
10
+ }
11
+ }
12
+ call(path, options) {
13
+ return this.execute((strategy) => strategy.call(path, options));
14
+ }
15
+ get(path, options) {
16
+ return this.execute((strategy) => strategy.get(path, options));
17
+ }
18
+ post(path, options) {
19
+ return this.execute((strategy) => strategy.post(path, options));
20
+ }
21
+ async execute(callStrategy) {
22
+ let lastError;
23
+ for (const [index, strategy] of this.strategies.entries()) {
24
+ try {
25
+ return await callStrategy(strategy);
26
+ }
27
+ catch (error) {
28
+ lastError = error;
29
+ if (!this.shouldFallback(error, index)) {
30
+ throw error;
31
+ }
32
+ }
33
+ }
34
+ throw lastError;
35
+ }
36
+ shouldFallback(error, strategyIndex) {
37
+ return this.options.shouldFallback?.(error, strategyIndex) ?? true;
38
+ }
39
+ }
40
+ exports.FallbackCallStrategy = FallbackCallStrategy;
41
+ //# sourceMappingURL=fallback-call.strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback-call.strategy.js","sourceRoot":"","sources":["fallback-call.strategy.ts"],"names":[],"mappings":";;;AAUA,MAAa,oBAAoB;IAC/B,YACmB,UAA8B,EAC9B,UAAuC,EAAE;QADzC,eAAU,GAAV,UAAU,CAAoB;QAC9B,YAAO,GAAP,OAAO,CAAkC;QAE1D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IAED,IAAI,CACF,IAAY,EACZ,OAAyC;QAEzC,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,GAAG,CACD,IAAY,EACZ,OAAyC;QAEzC,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,CACF,IAAY,EACZ,OAAyC;QAEzC,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAClE,CAAC;IAEO,KAAK,CAAC,OAAO,CACnB,YAEuC;QAEvC,IAAI,SAAkB,CAAC;QAEvB,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC;YAC1D,IAAI,CAAC;gBACH,OAAO,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;YACtC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,SAAS,GAAG,KAAK,CAAC;gBAElB,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;oBACvC,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,SAAS,CAAC;IAClB,CAAC;IAEO,cAAc,CAAC,KAAc,EAAE,aAAqB;QAC1D,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,IAAI,CAAC;IACrE,CAAC;CACF;AAxDD,oDAwDC"}
@@ -0,0 +1,67 @@
1
+ import {
2
+ IApiCallStrategy,
3
+ ICallOptions,
4
+ IObjectWithData,
5
+ } from '../context-call.interface.js';
6
+
7
+ export interface FallbackCallStrategyOptions {
8
+ shouldFallback?: (error: unknown, strategyIndex: number) => boolean;
9
+ }
10
+
11
+ export class FallbackCallStrategy implements IApiCallStrategy {
12
+ constructor(
13
+ private readonly strategies: IApiCallStrategy[],
14
+ private readonly options: FallbackCallStrategyOptions = {},
15
+ ) {
16
+ if (strategies.length === 0) {
17
+ throw new Error('FallbackCallStrategy requires at least one strategy.');
18
+ }
19
+ }
20
+
21
+ call<TOptData, TParams extends Record<string, any>, TResData>(
22
+ path: string,
23
+ options?: ICallOptions<TOptData, TParams>,
24
+ ): Promise<IObjectWithData<TResData>> {
25
+ return this.execute((strategy) => strategy.call(path, options));
26
+ }
27
+
28
+ get<TOptData, TParams extends Record<string, any>, TResData>(
29
+ path: string,
30
+ options?: ICallOptions<TOptData, TParams>,
31
+ ): Promise<IObjectWithData<TResData>> {
32
+ return this.execute((strategy) => strategy.get(path, options));
33
+ }
34
+
35
+ post<TOptData, TParams extends Record<string, any>, TResData>(
36
+ path: string,
37
+ options?: ICallOptions<TOptData, TParams>,
38
+ ): Promise<IObjectWithData<TResData>> {
39
+ return this.execute((strategy) => strategy.post(path, options));
40
+ }
41
+
42
+ private async execute<TResData>(
43
+ callStrategy: (
44
+ strategy: IApiCallStrategy,
45
+ ) => Promise<IObjectWithData<TResData>>,
46
+ ) {
47
+ let lastError: unknown;
48
+
49
+ for (const [index, strategy] of this.strategies.entries()) {
50
+ try {
51
+ return await callStrategy(strategy);
52
+ } catch (error) {
53
+ lastError = error;
54
+
55
+ if (!this.shouldFallback(error, index)) {
56
+ throw error;
57
+ }
58
+ }
59
+ }
60
+
61
+ throw lastError;
62
+ }
63
+
64
+ private shouldFallback(error: unknown, strategyIndex: number) {
65
+ return this.options.shouldFallback?.(error, strategyIndex) ?? true;
66
+ }
67
+ }
@@ -0,0 +1,44 @@
1
+ import { HTTPMethods } from '@nest-yalc-2/types/globals.d.js';
2
+ import { OutgoingHttpHeaders, IncomingHttpHeaders } from 'node:http2';
3
+ import { IApiCallStrategy } from '../context-call.interface.js';
4
+ export interface IHttpCallStrategyOptions {
5
+ headersWhitelist?: string[];
6
+ shouldSkipJsonParse?: (body: string) => boolean;
7
+ }
8
+ export interface HttpOptions<TData = string | object | Buffer | NodeJS.ReadableStream, TParams extends Record<string, any> = Record<string, any>> {
9
+ headers?: IncomingHttpHeaders | Record<string, string>;
10
+ method?: HTTPMethods;
11
+ signal?: AbortSignal;
12
+ Request?: object;
13
+ data?: TData;
14
+ parameters?: TParams;
15
+ }
16
+ export interface IHttpCallStrategyResponse<T = any> {
17
+ data: T;
18
+ status: number;
19
+ statusText: string;
20
+ headers: OutgoingHttpHeaders;
21
+ request?: any;
22
+ }
23
+ export interface IHttpCallStrategy extends IApiCallStrategy {
24
+ call<TOptData, TParams extends Record<string, any>, TResData>(path: string, options?: HttpOptions<TOptData, TParams> | {
25
+ method?: string;
26
+ }): Promise<IHttpCallStrategyResponse<TResData>>;
27
+ get<TOptData, TParams extends Record<string, any>, TResData>(path: string, options?: HttpOptions<TOptData, TParams> | {
28
+ method?: string;
29
+ }): Promise<IHttpCallStrategyResponse<TResData>>;
30
+ post<TOptData, TParams extends Record<string, any>, TResData>(path: string, options?: HttpOptions<TOptData, TParams> | {
31
+ method?: string;
32
+ }): Promise<IHttpCallStrategyResponse<TResData>>;
33
+ }
34
+ export declare abstract class HttpAbstractStrategy implements IHttpCallStrategy {
35
+ abstract call<TOptData, TParams extends Record<string, any>, TResData>(path: string, options?: HttpOptions<TOptData, TParams> | {
36
+ method?: string;
37
+ }): Promise<IHttpCallStrategyResponse<TResData>>;
38
+ get<TOptData, TParams extends Record<string, any>, TResData>(path: string, options?: HttpOptions<TOptData, TParams> | {
39
+ method?: string;
40
+ }): Promise<IHttpCallStrategyResponse<TResData>>;
41
+ post<TOptData, TParams extends Record<string, any>, TResData>(path: string, options?: HttpOptions<TOptData, TParams> | {
42
+ method?: string;
43
+ }): Promise<IHttpCallStrategyResponse<TResData>>;
44
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpAbstractStrategy = void 0;
4
+ class HttpAbstractStrategy {
5
+ get(path, options) {
6
+ return this.call(path, {
7
+ ...options,
8
+ method: 'GET',
9
+ });
10
+ }
11
+ post(path, options) {
12
+ return this.call(path, {
13
+ ...options,
14
+ method: 'POST',
15
+ });
16
+ }
17
+ }
18
+ exports.HttpAbstractStrategy = HttpAbstractStrategy;
19
+ //# sourceMappingURL=http-abstract-call.strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-abstract-call.strategy.js","sourceRoot":"","sources":["http-abstract-call.strategy.ts"],"names":[],"mappings":";;;AAuLA,MAAsB,oBAAoB;IAyBxC,GAAG,CACD,IAAY,EACZ,OAA8D;QAE9D,OAAO,IAAI,CAAC,IAAI,CAA8B,IAAI,EAAE;YAClD,GAAG,OAAO;YACV,MAAM,EAAE,KAAK;SACd,CAAC,CAAC;IACL,CAAC;IAYD,IAAI,CACF,IAAY,EACZ,OAA8D;QAE9D,OAAO,IAAI,CAAC,IAAI,CAA8B,IAAI,EAAE;YAClD,GAAG,OAAO;YACV,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;IACL,CAAC;CACF;AAtDD,oDAsDC"}