@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,238 @@
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
+
5
+ /**
6
+ * Configuration options for HTTP call strategies
7
+ */
8
+ export interface IHttpCallStrategyOptions {
9
+ /**
10
+ * List of header names that should be forwarded from the original request context.
11
+ * Only headers matching these names will be included in outgoing requests.
12
+ * @example ['authorization', 'x-tenant-id', 'content-type']
13
+ */
14
+ headersWhitelist?: string[];
15
+ /**
16
+ * Optional function to determine if JSON parsing should be skipped for a response body.
17
+ * Useful for handling non-JSON responses or streaming data.
18
+ * @param body - The raw response body as a string
19
+ * @returns `true` to skip parsing and return the raw body, `false` to parse as JSON
20
+ * @example (body) => body.startsWith('<html>')
21
+ */
22
+ shouldSkipJsonParse?: (body: string) => boolean;
23
+ }
24
+
25
+ /**
26
+ * HTTP request options compliant with all HTTP-based call strategies.
27
+ * This interface provides a unified way to configure HTTP requests across different transport mechanisms.
28
+ * @template TData - The type of data being sent in the request body (e.g., object, string, Buffer, stream)
29
+ * @template TParams - The shape of URL query parameters as a key-value record
30
+ * @example
31
+ * ```typescript
32
+ * // For a POST request with JSON body
33
+ * const options: HttpOptions<{ userId: number }, { includeDetails: string }> = {
34
+ * method: 'POST',
35
+ * data: { userId: 123 },
36
+ * parameters: { includeDetails: 'true' }
37
+ * };
38
+ * ```
39
+ */
40
+ export interface HttpOptions<
41
+ TData = string | object | Buffer | NodeJS.ReadableStream,
42
+ TParams extends Record<string, any> = Record<string, any>,
43
+ > {
44
+ /** HTTP headers to include in the request */
45
+ headers?: IncomingHttpHeaders | Record<string, string>;
46
+ /** HTTP method (GET, POST, PUT, DELETE, etc.) */
47
+ method?: HTTPMethods;
48
+ /** AbortSignal for cancelling the request */
49
+ signal?: AbortSignal;
50
+ /** Additional request configuration (implementation-specific) */
51
+ Request?: object;
52
+ /** Request payload/body data */
53
+ data?: TData;
54
+ /** URL query parameters as key-value pairs */
55
+ parameters?: TParams;
56
+ }
57
+
58
+ /**
59
+ * Standard HTTP response structure returned by all HTTP call strategies.
60
+ * @template T - The type of the parsed response data
61
+ * @example
62
+ * ```typescript
63
+ * // For an API returning user data
64
+ * const response: IHttpCallStrategyResponse<{ id: number; name: string }> = await strategy.get('/users/1');
65
+ * console.log(response.data.name); // TypeScript knows data has 'name' property
66
+ * ```
67
+ */
68
+ export interface IHttpCallStrategyResponse<T = any> {
69
+ /** The parsed response body */
70
+ data: T;
71
+ /** HTTP status code (e.g., 200, 404, 500) */
72
+ status: number;
73
+ /** HTTP status text (e.g., "OK", "Not Found") */
74
+ statusText: string;
75
+ /** Response headers from the server */
76
+ headers: OutgoingHttpHeaders;
77
+ /** Raw request object (implementation-specific) */
78
+ request?: any;
79
+ }
80
+
81
+ /**
82
+ * Interface defining the contract for HTTP-based API call strategies.
83
+ * Implementations must provide methods for making HTTP requests with type-safe request/response handling.
84
+ */
85
+ export interface IHttpCallStrategy extends IApiCallStrategy {
86
+ /**
87
+ * Execute an HTTP request with full control over method, data, and parameters.
88
+ * @template TOptData - The type of request body data (default: string | object | Buffer | stream)
89
+ * @template TParams - The shape of URL query parameters (default: Record<string, any>)
90
+ * @template TResData - The expected type of the response body after parsing
91
+ * @param path - The URL path or full URL to request
92
+ * @param options - HTTP request configuration including method, headers, data, and parameters
93
+ * @returns Promise resolving to the HTTP response with typed data
94
+ * @example
95
+ * ```typescript
96
+ * // POST request with typed request/response
97
+ * interface CreateUserDto { name: string; email: string; }
98
+ * interface UserResponse { id: number; name: string; email: string; }
99
+ *
100
+ * const response = await strategy.call<CreateUserDto, {}, UserResponse>('/users', {
101
+ * method: 'POST',
102
+ * data: { name: 'John', email: 'john@example.com' }
103
+ * });
104
+ * console.log(response.data.id); // TypeScript knows this is a number
105
+ * ```
106
+ */
107
+ call<TOptData, TParams extends Record<string, any>, TResData>(
108
+ path: string,
109
+ options?: HttpOptions<TOptData, TParams> | { method?: string },
110
+ ): Promise<IHttpCallStrategyResponse<TResData>>;
111
+ /**
112
+ * Execute an HTTP GET request.
113
+ * @template TOptData - The type of request body data (typically unused for GET)
114
+ * @template TParams - The shape of URL query parameters
115
+ * @template TResData - The expected type of the response body
116
+ * @param path - The URL path or full URL to request
117
+ * @param options - HTTP request configuration (excluding method, which is fixed to GET)
118
+ * @returns Promise resolving to the HTTP response with typed data
119
+ * @example
120
+ * ```typescript
121
+ * // GET request with query parameters
122
+ * interface UserListResponse { users: Array<{ id: number; name: string }>; total: number; }
123
+ *
124
+ * const response = await strategy.get<never, { page: string; limit: string }, UserListResponse>(
125
+ * '/users',
126
+ * { parameters: { page: '1', limit: '10' } }
127
+ * );
128
+ * console.log(response.data.total);
129
+ * ```
130
+ */
131
+ get<TOptData, TParams extends Record<string, any>, TResData>(
132
+ path: string,
133
+ options?: HttpOptions<TOptData, TParams> | { method?: string },
134
+ ): Promise<IHttpCallStrategyResponse<TResData>>;
135
+ /**
136
+ * Execute an HTTP POST request.
137
+ * @template TOptData - The type of request body data to send
138
+ * @template TParams - The shape of URL query parameters
139
+ * @template TResData - The expected type of the response body
140
+ * @param path - The URL path or full URL to request
141
+ * @param options - HTTP request configuration (excluding method, which is fixed to POST)
142
+ * @returns Promise resolving to the HTTP response with typed data
143
+ * @example
144
+ * ```typescript
145
+ * // POST request with body and query parameters
146
+ * interface CreateOrderDto { productId: number; quantity: number; }
147
+ * interface OrderResponse { orderId: string; total: number; }
148
+ *
149
+ * const response = await strategy.post<CreateOrderDto, { notify: string }, OrderResponse>(
150
+ * '/orders',
151
+ * {
152
+ * data: { productId: 42, quantity: 2 },
153
+ * parameters: { notify: 'true' }
154
+ * }
155
+ * );
156
+ * console.log(response.data.orderId);
157
+ * ```
158
+ */
159
+ post<TOptData, TParams extends Record<string, any>, TResData>(
160
+ path: string,
161
+ options?: HttpOptions<TOptData, TParams> | { method?: string },
162
+ ): Promise<IHttpCallStrategyResponse<TResData>>;
163
+ }
164
+
165
+ /**
166
+ * Abstract base class for HTTP-based API call strategies.
167
+ * Provides convenience methods (get, post) that delegate to the abstract `call` method.
168
+ * Concrete implementations must implement the `call` method for their specific transport mechanism
169
+ * (e.g., Axios, Fastify inject, native fetch).
170
+ * @example
171
+ * ```typescript
172
+ * class MyHttpStrategy extends HttpAbstractStrategy {
173
+ * async call<TOptData, TParams extends Record<string, any>, TResData>(
174
+ * path: string,
175
+ * options?: HttpOptions<TOptData, TParams>
176
+ * ): Promise<IHttpCallStrategyResponse<TResData>> {
177
+ * // Implementation using your HTTP client
178
+ * const response = await myHttpClient.request({ url: path, ...options });
179
+ * return { data: response.body, status: response.statusCode, ... };
180
+ * }
181
+ * }
182
+ * ```
183
+ */
184
+ export abstract class HttpAbstractStrategy implements IHttpCallStrategy {
185
+ /**
186
+ * Abstract method to execute an HTTP request. Must be implemented by concrete strategy classes.
187
+ * @template TOptData - The type of request body data being sent
188
+ * @template TParams - The shape of URL query parameters
189
+ * @template TResData - The expected type of the response body
190
+ * @param path - The URL path or full URL to request
191
+ * @param options - HTTP request configuration including method, headers, data, and parameters
192
+ * @returns Promise resolving to the HTTP response with typed data
193
+ */
194
+ abstract call<TOptData, TParams extends Record<string, any>, TResData>(
195
+ path: string,
196
+ options?: HttpOptions<TOptData, TParams> | { method?: string },
197
+ ): Promise<IHttpCallStrategyResponse<TResData>>;
198
+
199
+ /**
200
+ * Convenience method to execute an HTTP GET request.
201
+ * Delegates to `call()` with method set to 'GET'.
202
+ * @template TOptData - The type of request body data (typically unused for GET)
203
+ * @template TParams - The shape of URL query parameters
204
+ * @template TResData - The expected type of the response body
205
+ * @param path - The URL path or full URL to request
206
+ * @param options - HTTP request configuration (method will be overridden to GET)
207
+ * @returns Promise resolving to the HTTP response with typed data
208
+ */
209
+ get<TOptData, TParams extends Record<string, any>, TResData>(
210
+ path: string,
211
+ options?: HttpOptions<TOptData, TParams> | { method?: string },
212
+ ): Promise<IHttpCallStrategyResponse<TResData>> {
213
+ return this.call<TOptData, TParams, TResData>(path, {
214
+ ...options,
215
+ method: 'GET',
216
+ });
217
+ }
218
+
219
+ /**
220
+ * Convenience method to execute an HTTP POST request.
221
+ * Delegates to `call()` with method set to 'POST'.
222
+ * @template TOptData - The type of request body data to send
223
+ * @template TParams - The shape of URL query parameters
224
+ * @template TResData - The expected type of the response body
225
+ * @param path - The URL path or full URL to request
226
+ * @param options - HTTP request configuration (method will be overridden to POST)
227
+ * @returns Promise resolving to the HTTP response with typed data
228
+ */
229
+ post<TOptData, TParams extends Record<string, any>, TResData>(
230
+ path: string,
231
+ options?: HttpOptions<TOptData, TParams> | { method?: string },
232
+ ): Promise<IHttpCallStrategyResponse<TResData>> {
233
+ return this.call<TOptData, TParams, TResData>(path, {
234
+ ...options,
235
+ method: 'POST',
236
+ });
237
+ }
238
+ }
@@ -0,0 +1,30 @@
1
+ import { ClassType } from '@nest-yalc-2/types/globals.d.js';
2
+ import { HttpService } from '@nestjs/axios';
3
+ import { HttpAbstractStrategy, IHttpCallStrategyResponse, HttpOptions, IHttpCallStrategyOptions } from './http-abstract-call.strategy.js';
4
+ import { YalcGlobalClsService } from '@nest-yalc-2/app/cls.module.js';
5
+ export type NestHttpCallStrategyOptions = IHttpCallStrategyOptions & {
6
+ internalRequestHeader?: string;
7
+ internalRequestToken?: string;
8
+ };
9
+ export declare class NestHttpCallStrategy extends HttpAbstractStrategy {
10
+ protected readonly httpService: HttpService;
11
+ protected readonly clsService: YalcGlobalClsService;
12
+ private baseUrl;
13
+ protected readonly options: NestHttpCallStrategyOptions;
14
+ private readonly internalHeader;
15
+ private readonly internalToken?;
16
+ constructor(httpService: HttpService, clsService: YalcGlobalClsService, baseUrl?: string, options?: NestHttpCallStrategyOptions);
17
+ call<TOptData, TParams extends Record<string, any>, TResData>(path: string, options?: HttpOptions<TOptData, TParams>): Promise<IHttpCallStrategyResponse<TResData>>;
18
+ }
19
+ export interface NestHttpCallStrategyProviderOptions {
20
+ baseUrl?: string;
21
+ NestHttpStrategy?: ClassType<NestHttpCallStrategy>;
22
+ headersWhitelist?: string[];
23
+ internalRequestHeader?: string;
24
+ internalRequestToken?: string;
25
+ }
26
+ export declare const NestHttpCallStrategyProvider: (provide: string, options?: NestHttpCallStrategyProviderOptions) => {
27
+ provide: string;
28
+ useFactory: (httpAdapter: HttpService, clsService: YalcGlobalClsService) => NestHttpCallStrategy;
29
+ inject: (typeof YalcGlobalClsService | typeof HttpService)[];
30
+ };
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NestHttpCallStrategyProvider = exports.NestHttpCallStrategy = void 0;
4
+ const axios_1 = require("@nestjs/axios");
5
+ const http_abstract_call_strategy_js_1 = require("./http-abstract-call.strategy.js");
6
+ const cls_module_js_1 = require("@nest-yalc-2/app/cls.module.js");
7
+ const header_whitelist_helper_js_1 = require("../header-whitelist.helper.js");
8
+ class NestHttpCallStrategy extends http_abstract_call_strategy_js_1.HttpAbstractStrategy {
9
+ constructor(httpService, clsService, baseUrl = '', options = {}) {
10
+ super();
11
+ this.httpService = httpService;
12
+ this.clsService = clsService;
13
+ this.baseUrl = baseUrl;
14
+ this.options = options;
15
+ this.internalHeader =
16
+ options.internalRequestHeader ?? 'x-internal-request-token';
17
+ this.internalToken = options.internalRequestToken;
18
+ }
19
+ async call(path, options) {
20
+ const clsHeaders = (0, header_whitelist_helper_js_1.filterHeaders)(this.clsService.get('headers'), this.options.headersWhitelist);
21
+ const headers = {
22
+ ...clsHeaders,
23
+ ...(options?.headers ?? {}),
24
+ };
25
+ if (this.internalHeader &&
26
+ this.internalToken &&
27
+ !headers[this.internalHeader]) {
28
+ headers[this.internalHeader] = this.internalToken;
29
+ }
30
+ const _options = {
31
+ headers,
32
+ method: options?.method,
33
+ signal: options?.signal,
34
+ data: options?.data,
35
+ };
36
+ if (options?.parameters) {
37
+ _options.params = new URLSearchParams(options.parameters);
38
+ }
39
+ const { data, ...res } = await this.httpService.axiosRef.request({
40
+ headers: _options?.headers,
41
+ method: _options?.method,
42
+ signal: _options?.signal,
43
+ data: _options?.data,
44
+ params: _options?.params,
45
+ url: `${this.baseUrl}${path}`,
46
+ });
47
+ return {
48
+ ...res,
49
+ headers: res.headers,
50
+ data,
51
+ };
52
+ }
53
+ }
54
+ exports.NestHttpCallStrategy = NestHttpCallStrategy;
55
+ const NestHttpCallStrategyProvider = (provide, options = {}) => ({
56
+ provide,
57
+ useFactory: (httpAdapter, clsService) => {
58
+ const _options = {
59
+ baseUrl: '',
60
+ NestHttpStrategy: NestHttpCallStrategy,
61
+ ...options,
62
+ };
63
+ return new _options.NestHttpStrategy(httpAdapter, clsService, _options.baseUrl, _options);
64
+ },
65
+ inject: [axios_1.HttpService, cls_module_js_1.YalcGlobalClsService],
66
+ });
67
+ exports.NestHttpCallStrategyProvider = NestHttpCallStrategyProvider;
68
+ //# sourceMappingURL=nest-http-call.strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nest-http-call.strategy.js","sourceRoot":"","sources":["nest-http-call.strategy.ts"],"names":[],"mappings":";;;AACA,yCAA4C;AAC5C,qFAK0C;AAE1C,kEAAsE;AACtE,8EAA8D;AAQ9D,MAAa,oBAAqB,SAAQ,qDAAoB;IAI5D,YACqB,WAAwB,EACxB,UAAgC,EAC3C,UAAU,EAAE,EACD,UAAuC,EAAE;QAE5D,KAAK,EAAE,CAAC;QALW,gBAAW,GAAX,WAAW,CAAa;QACxB,eAAU,GAAV,UAAU,CAAsB;QAC3C,YAAO,GAAP,OAAO,CAAK;QACD,YAAO,GAAP,OAAO,CAAkC;QAG5D,IAAI,CAAC,cAAc;YACjB,OAAO,CAAC,qBAAqB,IAAI,0BAA0B,CAAC;QAC9D,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,oBAAoB,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,IAAI,CACR,IAAY,EACZ,OAAwC;QAExC,MAAM,UAAU,GAAG,IAAA,0CAAa,EAC9B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAC9B,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAC9B,CAAC;QACF,MAAM,OAAO,GAAwB;YACnC,GAAG,UAAU;YACb,GAAG,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;SAC5B,CAAC;QACF,IACE,IAAI,CAAC,cAAc;YACnB,IAAI,CAAC,aAAa;YAClB,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,EAC7B,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC;QACpD,CAAC;QAKD,MAAM,QAAQ,GAIW;YACvB,OAAO;YACP,MAAM,EAAE,OAAO,EAAE,MAAM;YACvB,MAAM,EAAE,OAAO,EAAE,MAAM;YACvB,IAAI,EAAE,OAAO,EAAE,IAAI;SACpB,CAAC;QAEF,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;YACxB,QAAQ,CAAC,MAAM,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC5D,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC/D,OAAO,EAAE,QAAQ,EAAE,OAAc;YACjC,MAAM,EAAE,QAAQ,EAAE,MAAM;YACxB,MAAM,EAAE,QAAQ,EAAE,MAAM;YACxB,IAAI,EAAE,QAAQ,EAAE,IAAI;YACpB,MAAM,EAAE,QAAQ,EAAE,MAAM;YACxB,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE;SAC9B,CAAC,CAAC;QAEH,OAAO;YACL,GAAG,GAAG;YACN,OAAO,EAAE,GAAG,CAAC,OAA8B;YAC3C,IAAI;SACL,CAAC;IACJ,CAAC;CACF;AArED,oDAqEC;AAaM,MAAM,4BAA4B,GAAG,CAC1C,OAAe,EACf,UAA+C,EAAE,EACjD,EAAE,CAAC,CAAC;IACJ,OAAO;IACP,UAAU,EAAE,CAAC,WAAwB,EAAE,UAAgC,EAAE,EAAE;QACzE,MAAM,QAAQ,GAAG;YACf,OAAO,EAAE,EAAE;YACX,gBAAgB,EAAE,oBAAoB;YACtC,GAAG,OAAO;SACX,CAAC;QAEF,OAAO,IAAI,QAAQ,CAAC,gBAAgB,CAClC,WAAW,EACX,UAAU,EACV,QAAQ,CAAC,OAAO,EAChB,QAAQ,CACT,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,CAAC,mBAAW,EAAE,oCAAoB,CAAC;CAC5C,CAAC,CAAC;AApBU,QAAA,4BAA4B,gCAoBtC"}
@@ -0,0 +1,121 @@
1
+ import { ClassType } from '@nest-yalc-2/types/globals.d.js';
2
+ import { HttpService } from '@nestjs/axios';
3
+ import {
4
+ HttpAbstractStrategy,
5
+ IHttpCallStrategyResponse,
6
+ HttpOptions,
7
+ IHttpCallStrategyOptions,
8
+ } from './http-abstract-call.strategy.js';
9
+ import { AxiosRequestConfig } from 'axios';
10
+ import { YalcGlobalClsService } from '@nest-yalc-2/app/cls.module.js';
11
+ import { filterHeaders } from '../header-whitelist.helper.js';
12
+ import type { OutgoingHttpHeaders } from 'node:http2';
13
+
14
+ export type NestHttpCallStrategyOptions = IHttpCallStrategyOptions & {
15
+ internalRequestHeader?: string;
16
+ internalRequestToken?: string;
17
+ };
18
+
19
+ export class NestHttpCallStrategy extends HttpAbstractStrategy {
20
+ private readonly internalHeader: string;
21
+ private readonly internalToken?: string;
22
+
23
+ constructor(
24
+ protected readonly httpService: HttpService,
25
+ protected readonly clsService: YalcGlobalClsService,
26
+ private baseUrl = '',
27
+ protected readonly options: NestHttpCallStrategyOptions = {},
28
+ ) {
29
+ super();
30
+ this.internalHeader =
31
+ options.internalRequestHeader ?? 'x-internal-request-token';
32
+ this.internalToken = options.internalRequestToken;
33
+ }
34
+
35
+ async call<TOptData, TParams extends Record<string, any>, TResData>(
36
+ path: string,
37
+ options?: HttpOptions<TOptData, TParams>,
38
+ ): Promise<IHttpCallStrategyResponse<TResData>> {
39
+ const clsHeaders = filterHeaders(
40
+ this.clsService.get('headers'),
41
+ this.options.headersWhitelist,
42
+ );
43
+ const headers: Record<string, any> = {
44
+ ...clsHeaders,
45
+ ...(options?.headers ?? {}),
46
+ };
47
+ if (
48
+ this.internalHeader &&
49
+ this.internalToken &&
50
+ !headers[this.internalHeader]
51
+ ) {
52
+ headers[this.internalHeader] = this.internalToken;
53
+ }
54
+ /**
55
+ * We need this to do a type check on the options and
56
+ * implement the mapping from HttpOptions to AxiosRequestConfig
57
+ */
58
+ const _options:
59
+ | {
60
+ [k: string | number | symbol]: never;
61
+ }
62
+ | AxiosRequestConfig = {
63
+ headers,
64
+ method: options?.method,
65
+ signal: options?.signal,
66
+ data: options?.data,
67
+ };
68
+
69
+ if (options?.parameters) {
70
+ _options.params = new URLSearchParams(options.parameters);
71
+ }
72
+
73
+ const { data, ...res } = await this.httpService.axiosRef.request({
74
+ headers: _options?.headers as any,
75
+ method: _options?.method,
76
+ signal: _options?.signal,
77
+ data: _options?.data,
78
+ params: _options?.params,
79
+ url: `${this.baseUrl}${path}`,
80
+ });
81
+
82
+ return {
83
+ ...res,
84
+ headers: res.headers as OutgoingHttpHeaders,
85
+ data,
86
+ };
87
+ }
88
+ }
89
+
90
+ export interface NestHttpCallStrategyProviderOptions {
91
+ baseUrl?: string;
92
+ NestHttpStrategy?: ClassType<NestHttpCallStrategy>;
93
+ headersWhitelist?: string[];
94
+ internalRequestHeader?: string;
95
+ internalRequestToken?: string;
96
+ }
97
+
98
+ /**
99
+ * Just a convenient provider to inject the NestLocalCallStrategy
100
+ */
101
+ export const NestHttpCallStrategyProvider = (
102
+ provide: string,
103
+ options: NestHttpCallStrategyProviderOptions = {},
104
+ ) => ({
105
+ provide,
106
+ useFactory: (httpAdapter: HttpService, clsService: YalcGlobalClsService) => {
107
+ const _options = {
108
+ baseUrl: '',
109
+ NestHttpStrategy: NestHttpCallStrategy,
110
+ ...options,
111
+ };
112
+
113
+ return new _options.NestHttpStrategy(
114
+ httpAdapter,
115
+ clsService,
116
+ _options.baseUrl,
117
+ _options,
118
+ );
119
+ },
120
+ inject: [HttpService, YalcGlobalClsService],
121
+ });
@@ -0,0 +1,32 @@
1
+ import { HttpAdapterHost } from '@nestjs/core';
2
+ import { HttpAbstractStrategy, HttpOptions, IHttpCallStrategyOptions, IHttpCallStrategyResponse } from './http-abstract-call.strategy.js';
3
+ import { ClassType } from '@nest-yalc-2/types/globals.d.js';
4
+ import { YalcGlobalClsService } from '@nest-yalc-2/app/cls.module.js';
5
+ import { AppConfigService } from '@nest-yalc-2/app/app-config.service.js';
6
+ export type NestLocalCallStrategyOptions = IHttpCallStrategyOptions & {
7
+ internalRequestHeader?: string;
8
+ internalRequestToken?: string;
9
+ };
10
+ export declare class NestLocalCallStrategy extends HttpAbstractStrategy {
11
+ protected readonly adapterHost: HttpAdapterHost;
12
+ protected readonly clsService: YalcGlobalClsService;
13
+ protected readonly configService: AppConfigService;
14
+ private baseUrl;
15
+ protected readonly options: NestLocalCallStrategyOptions;
16
+ private readonly internalHeader;
17
+ private readonly internalToken?;
18
+ constructor(adapterHost: HttpAdapterHost, clsService: YalcGlobalClsService, configService: AppConfigService, baseUrl?: string, options?: NestLocalCallStrategyOptions);
19
+ call<TOptData extends string | object | Buffer | NodeJS.ReadableStream, TParams extends Record<string, any>, TResData>(path: string, options?: HttpOptions<TOptData, TParams>): Promise<IHttpCallStrategyResponse<TResData>>;
20
+ }
21
+ export interface NestLocalCallStrategyProviderOptions {
22
+ baseUrl?: string;
23
+ NestLocalStrategy?: ClassType<NestLocalCallStrategy>;
24
+ headersWhitelist?: string[];
25
+ internalRequestHeader?: string;
26
+ internalRequestToken?: string;
27
+ }
28
+ export declare const NestLocalCallStrategyProvider: (provide: string, options?: NestLocalCallStrategyProviderOptions) => {
29
+ provide: string;
30
+ useFactory: (httpAdapter: HttpAdapterHost, clsService: YalcGlobalClsService, configService: AppConfigService) => NestLocalCallStrategy;
31
+ inject: (string | typeof YalcGlobalClsService | typeof HttpAdapterHost)[];
32
+ };
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NestLocalCallStrategyProvider = exports.NestLocalCallStrategy = void 0;
4
+ const core_1 = require("@nestjs/core");
5
+ const http_abstract_call_strategy_js_1 = require("./http-abstract-call.strategy.js");
6
+ const cls_module_js_1 = require("@nest-yalc-2/app/cls.module.js");
7
+ const header_whitelist_helper_js_1 = require("../header-whitelist.helper.js");
8
+ const def_const_js_1 = require("@nest-yalc-2/app/def.const.js");
9
+ class NestLocalCallStrategy extends http_abstract_call_strategy_js_1.HttpAbstractStrategy {
10
+ constructor(adapterHost, clsService, configService, baseUrl = '', options = {}) {
11
+ super();
12
+ this.adapterHost = adapterHost;
13
+ this.clsService = clsService;
14
+ this.configService = configService;
15
+ this.baseUrl = baseUrl;
16
+ this.options = options;
17
+ this.internalHeader =
18
+ options.internalRequestHeader ?? 'x-internal-request-token';
19
+ this.internalToken =
20
+ options.internalRequestToken ??
21
+ configService?.values?.internalRequestToken;
22
+ }
23
+ async call(path, options) {
24
+ const instance = this.adapterHost.httpAdapter.getInstance();
25
+ const clsHeaders = (0, header_whitelist_helper_js_1.filterHeaders)(this.clsService.get('headers'), this.options.headersWhitelist);
26
+ const headers = {
27
+ ...clsHeaders,
28
+ ...(options?.headers ?? {}),
29
+ };
30
+ if (this.internalHeader &&
31
+ this.internalToken &&
32
+ !headers[this.internalHeader]) {
33
+ headers[this.internalHeader] = this.internalToken;
34
+ }
35
+ const _options = {
36
+ headers,
37
+ method: options?.method,
38
+ payload: options?.data,
39
+ };
40
+ const args = {
41
+ ..._options,
42
+ url: `${this.baseUrl}${path}`,
43
+ };
44
+ if (options?.parameters) {
45
+ args.query = Object.fromEntries(new URLSearchParams(options.parameters));
46
+ }
47
+ const result = await instance.inject(args);
48
+ let data;
49
+ try {
50
+ if (this.options.shouldSkipJsonParse &&
51
+ this.options.shouldSkipJsonParse(result.body)) {
52
+ data = result.body;
53
+ }
54
+ else {
55
+ data = result.json();
56
+ }
57
+ }
58
+ catch (_e) {
59
+ data = result.body;
60
+ }
61
+ return {
62
+ data,
63
+ headers: result.headers,
64
+ status: result.statusCode,
65
+ statusText: result.statusMessage,
66
+ request: result.payload,
67
+ };
68
+ }
69
+ }
70
+ exports.NestLocalCallStrategy = NestLocalCallStrategy;
71
+ const NestLocalCallStrategyProvider = (provide, options = {}) => ({
72
+ provide,
73
+ useFactory: (httpAdapter, clsService, configService) => {
74
+ const _options = {
75
+ baseUrl: '',
76
+ NestLocalStrategy: NestLocalCallStrategy,
77
+ ...options,
78
+ };
79
+ return new _options.NestLocalStrategy(httpAdapter, clsService, configService, _options.baseUrl, _options);
80
+ },
81
+ inject: [core_1.HttpAdapterHost, cls_module_js_1.YalcGlobalClsService, def_const_js_1.MAIN_APP_CONFIG_SERVICE],
82
+ });
83
+ exports.NestLocalCallStrategyProvider = NestLocalCallStrategyProvider;
84
+ //# sourceMappingURL=nest-local-call.strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nest-local-call.strategy.js","sourceRoot":"","sources":["nest-local-call.strategy.ts"],"names":[],"mappings":"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"}