@congruent-stack/congruent-api 0.9.0-rc.0 → 0.10.0

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/index.cjs CHANGED
@@ -19,6 +19,11 @@ class HttpMethodEndpoint {
19
19
  }
20
20
  return this._cachedGenericPath;
21
21
  }
22
+ createPath(pathParams) {
23
+ return `/${this.pathSegments.map(
24
+ (segment) => segment.startsWith(":") ? pathParams[segment.slice(1)] ?? "?" : segment
25
+ ).join("/")}`;
26
+ }
22
27
  _method = null;
23
28
  get method() {
24
29
  return this._method;
@@ -112,6 +117,7 @@ var HttpStatusCode = /* @__PURE__ */ ((HttpStatusCode2) => {
112
117
  HttpStatusCode2[HttpStatusCode2["Forbidden_403"] = 403] = "Forbidden_403";
113
118
  HttpStatusCode2[HttpStatusCode2["NotFound_404"] = 404] = "NotFound_404";
114
119
  HttpStatusCode2[HttpStatusCode2["Conflict_409"] = 409] = "Conflict_409";
120
+ HttpStatusCode2[HttpStatusCode2["UnprocessableEntity_422"] = 422] = "UnprocessableEntity_422";
115
121
  HttpStatusCode2[HttpStatusCode2["InternalServerError_500"] = 500] = "InternalServerError_500";
116
122
  HttpStatusCode2[HttpStatusCode2["NotImplemented_501"] = 501] = "NotImplemented_501";
117
123
  HttpStatusCode2[HttpStatusCode2["BadGateway_502"] = 502] = "BadGateway_502";
@@ -140,6 +146,9 @@ class MethodEndpointHandlerRegistryEntry {
140
146
  this._methodEndpoint = methodEndpoint;
141
147
  this._dicontainer = dicontainer;
142
148
  }
149
+ get genericPath() {
150
+ return this._methodEndpoint.genericPath;
151
+ }
143
152
  _handler = null;
144
153
  get handler() {
145
154
  return this._handler;
@@ -149,6 +158,7 @@ class MethodEndpointHandlerRegistryEntry {
149
158
  if (this._onHandlerRegisteredCallback) {
150
159
  this._onHandlerRegisteredCallback(this);
151
160
  }
161
+ return this;
152
162
  }
153
163
  _onHandlerRegisteredCallback = null;
154
164
  _onHandlerRegistered(callback) {
@@ -166,7 +176,55 @@ class MethodEndpointHandlerRegistryEntry {
166
176
  this._injection = injection;
167
177
  return this;
168
178
  }
179
+ _decoratorFactories = [];
180
+ get decoratorFactories() {
181
+ return this._decoratorFactories;
182
+ }
183
+ /**
184
+ *
185
+ * @param decoratorFactory must be a function that takes exactly the DI scope type and returns an instance of a class that implements IEndpointHandlerDecorator
186
+ * @returns this
187
+ *
188
+ * Initially, the method was defined as:
189
+ * ```ts
190
+ * decorate<
191
+ * TDecoratorSchemas extends IDecoratorHandlerSchemas,
192
+ * TDecorator extends IEndpointHandlerDecorator<TDecoratorSchemas>
193
+ * > (
194
+ * decoratorFactory: IEndpointHandlerDecoratorFactory<TDecoratorSchemas, TDIContainer, TDecorator>
195
+ * ): this {
196
+ * this._decoratorFactories.push(decoratorFactory);
197
+ * return this;
198
+ * }
199
+ * ```
200
+ *
201
+ * and the type IEndpointHandlerDecoratorFactory was defined as:
202
+ * ```ts
203
+ * type IEndpointHandlerDecoratorFactory<
204
+ * TDecoratorSchemas extends IDecoratorHandlerSchemas,
205
+ * TDIContainer extends DIContainer,
206
+ * TDecorator extends IEndpointHandlerDecorator<TDecoratorSchemas>
207
+ * > = (diScope: ReturnType<TDIContainer['createScope']>) => TDecorator;
208
+ * ```
209
+ *
210
+ * However, TypeScript was incorrectly inferring the types when using the 'decorate' method.
211
+ * The end developer would have had to explicitly provide the generic types, which is not ideal.
212
+ *
213
+ * With the current definition, TypeScript can infer the types from the decoratorFactory parameter,
214
+ * making it easier to use.
215
+ */
216
+ decorate(decoratorFactory, decoratingArgs) {
217
+ this._decoratorFactories.push((scope) => decoratorFactory(scope, decoratingArgs));
218
+ return this;
219
+ }
220
+ decorateWith(decoratorStaticMethodFactory, decoratingArgs) {
221
+ this._decoratorFactories.push((scope) => decoratorStaticMethodFactory.create(scope, decoratingArgs));
222
+ return this;
223
+ }
169
224
  async trigger(diScope, requestObject) {
225
+ return this.triggerNoStaticTypeCheck(diScope, requestObject, { originalRequest: requestObject });
226
+ }
227
+ async exec(injected, requestObject) {
170
228
  if (!this._handler) {
171
229
  throw new Error("Handler not set for this endpoint");
172
230
  }
@@ -186,9 +244,7 @@ class MethodEndpointHandlerRegistryEntry {
186
244
  badRequestResponse = body;
187
245
  return badRequestResponse;
188
246
  }
189
- const path = `/${this._methodEndpoint.pathSegments.map(
190
- (segment) => segment.startsWith(":") ? requestObject.pathParams[segment.slice(1)] ?? "?" : segment
191
- ).join("/")}`;
247
+ const path = this._methodEndpoint.createPath(requestObject.pathParams);
192
248
  return await this._handler({
193
249
  method: this._methodEndpoint.method,
194
250
  path,
@@ -197,9 +253,41 @@ class MethodEndpointHandlerRegistryEntry {
197
253
  headers,
198
254
  pathParams: requestObject.pathParams,
199
255
  query,
200
- body,
201
- injected: this._injection(diScope)
202
- });
256
+ body
257
+ }, injected);
258
+ }
259
+ async triggerNoStaticTypeCheck(diScope, requestObject, context) {
260
+ if (!this._handler) {
261
+ throw new Error("Handler not set for this endpoint");
262
+ }
263
+ let badRequestResponse = null;
264
+ const headers = parseRequestDefinitionField(this._methodEndpoint.definition, "headers", requestObject);
265
+ if (isHttpResponseObject(headers)) {
266
+ badRequestResponse = headers;
267
+ return badRequestResponse;
268
+ }
269
+ const query = parseRequestDefinitionField(this._methodEndpoint.definition, "query", requestObject);
270
+ if (isHttpResponseObject(query)) {
271
+ badRequestResponse = query;
272
+ return badRequestResponse;
273
+ }
274
+ const body = parseRequestDefinitionField(this._methodEndpoint.definition, "body", requestObject);
275
+ if (isHttpResponseObject(body)) {
276
+ badRequestResponse = body;
277
+ return badRequestResponse;
278
+ }
279
+ const path = this._methodEndpoint.createPath(requestObject.pathParams);
280
+ Object.assign(context, this._injection(diScope));
281
+ return await this._handler({
282
+ method: this._methodEndpoint.method,
283
+ path,
284
+ genericPath: this._methodEndpoint.genericPath,
285
+ pathSegments: this._methodEndpoint.pathSegments,
286
+ headers,
287
+ pathParams: requestObject.pathParams,
288
+ query,
289
+ body
290
+ }, context);
203
291
  }
204
292
  }
205
293
  function parseRequestDefinitionField(definition, key, requestObject) {
@@ -255,7 +343,26 @@ class MiddlewareHandlersRegistryEntryInternal {
255
343
  get genericPath() {
256
344
  return this._middlewareGenericPath;
257
345
  }
258
- _splitMiddlewarePath() {
346
+ _middlewarePathSegments;
347
+ get pathSegments() {
348
+ return this._middlewarePathSegments;
349
+ }
350
+ _middlewareMethod;
351
+ get method() {
352
+ return this._middlewareMethod;
353
+ }
354
+ _middlewareSchemas;
355
+ get middlewareSchemas() {
356
+ return this._middlewareSchemas;
357
+ }
358
+ _handler;
359
+ constructor(diContainer, middlewarePath, middlewareSchemas, decoratorFactories, injection, handler) {
360
+ this._dicontainer = diContainer;
361
+ this._middlewareGenericPath = middlewarePath;
362
+ this._middlewareSchemas = middlewareSchemas;
363
+ this._decoratorFactories.push(...decoratorFactories);
364
+ this._injection = injection;
365
+ this._handler = handler;
259
366
  const splitResult = this._middlewareGenericPath.split(" ");
260
367
  let method = "";
261
368
  let pathSegments = [];
@@ -266,58 +373,57 @@ class MiddlewareHandlersRegistryEntryInternal {
266
373
  }
267
374
  pathSegments = splitResult[1].split("/").map((segment) => segment.trim()).filter((segment) => segment !== "");
268
375
  }
269
- return {
270
- method,
271
- pathSegments
272
- };
376
+ this._middlewareMethod = method;
377
+ this._middlewarePathSegments = pathSegments;
273
378
  }
274
- _inputSchemas;
275
- _handler;
276
- constructor(diContainer, middlewarePath, inputSchemas, injection, handler) {
277
- this._dicontainer = diContainer;
278
- this._middlewareGenericPath = middlewarePath;
279
- this._inputSchemas = inputSchemas;
280
- this._injection = injection;
281
- this._handler = handler;
379
+ _decoratorFactories = [];
380
+ get decoratorFactories() {
381
+ return this._decoratorFactories;
282
382
  }
283
383
  _injection = (_dicontainer) => ({});
284
- async trigger(diScope, requestObject, next) {
384
+ async trigger(diScope, requestObject, context) {
385
+ return this.triggerNoStaticTypeCheck(diScope, requestObject, context);
386
+ }
387
+ async triggerNoStaticTypeCheck(diScope, requestObject, context) {
285
388
  let badRequestResponse = null;
286
- const headers = middlewareParseRequestDefinitionField(this._inputSchemas, "headers", requestObject);
389
+ const headers = middlewareParseRequestDefinitionField(this._middlewareSchemas, "headers", requestObject);
287
390
  if (isHttpResponseObject(headers)) {
288
391
  badRequestResponse = headers;
289
392
  return badRequestResponse;
290
393
  }
291
- const query = middlewareParseRequestDefinitionField(this._inputSchemas, "query", requestObject);
394
+ const query = middlewareParseRequestDefinitionField(this._middlewareSchemas, "query", requestObject);
292
395
  if (isHttpResponseObject(query)) {
293
396
  badRequestResponse = query;
294
397
  return badRequestResponse;
295
398
  }
296
- const body = middlewareParseRequestDefinitionField(this._inputSchemas, "body", requestObject);
399
+ const body = middlewareParseRequestDefinitionField(this._middlewareSchemas, "body", requestObject);
297
400
  if (isHttpResponseObject(body)) {
298
401
  badRequestResponse = body;
299
402
  return badRequestResponse;
300
403
  }
301
- const { method, pathSegments } = this._splitMiddlewarePath();
302
- const path = `/${pathSegments.map(
303
- (segment) => segment.startsWith(":") ? requestObject.pathParams[segment.slice(1)] ?? "?" : segment
304
- ).join("/")}`;
404
+ const path = this.createPath(requestObject.pathParams);
405
+ Object.assign(context, this._injection(diScope));
305
406
  return await this._handler(
306
407
  {
307
- method,
308
- // TODO: might be empty, as middleware can be registered with path only, without method, possible fix: take it from express.request.method
408
+ method: this.method,
409
+ // TODO: might be empty, as middleware can be registered with path only, without method
309
410
  path,
310
411
  genericPath: this.genericPath,
311
- pathSegments,
412
+ pathSegments: this.pathSegments,
312
413
  headers,
313
414
  pathParams: requestObject.pathParams,
314
415
  query,
315
- body,
316
- injected: this._injection(diScope)
416
+ body
317
417
  },
318
- next
418
+ context
319
419
  );
320
420
  }
421
+ createPath(pathParams) {
422
+ const path = `/${this.pathSegments.map(
423
+ (segment) => segment.startsWith(":") ? pathParams[segment.slice(1)] ?? "?" : segment
424
+ ).join("/")}`;
425
+ return path;
426
+ }
321
427
  }
322
428
  class MiddlewareHandlersRegistryEntry {
323
429
  _registry;
@@ -334,16 +440,62 @@ class MiddlewareHandlersRegistryEntry {
334
440
  this._injection = injection;
335
441
  return this;
336
442
  }
337
- register(inputSchemas, handler) {
443
+ register(middlewareSchemas, handler) {
338
444
  const internalEntry = new MiddlewareHandlersRegistryEntryInternal(
339
445
  this._registry.dicontainer,
340
446
  this._path,
341
- inputSchemas,
447
+ middlewareSchemas,
448
+ this._decoratorFactories,
342
449
  this._injection,
343
450
  handler
344
451
  );
345
452
  this._registry.register(internalEntry);
346
453
  }
454
+ _decoratorFactories = [];
455
+ get decoratorFactories() {
456
+ return this._decoratorFactories;
457
+ }
458
+ /**
459
+ *
460
+ * @param decoratorFactory must be a function that takes exactly the DI scope type and returns an instance of a class that implements IEndpointHandlerDecorator
461
+ * @returns this
462
+ *
463
+ * Initially, the method was defined as:
464
+ * ```ts
465
+ * decorate<
466
+ * TDecoratorSchemas extends IDecoratorHandlerSchemas,
467
+ * TDecorator extends IEndpointHandlerDecorator<TDecoratorSchemas>
468
+ * > (
469
+ * decoratorFactory: IEndpointHandlerDecoratorFactory<TDecoratorSchemas, TDIContainer, TDecorator>
470
+ * ): this {
471
+ * this._decoratorFactories.push(decoratorFactory);
472
+ * return this;
473
+ * }
474
+ * ```
475
+ *
476
+ * and the type IEndpointHandlerDecoratorFactory was defined as:
477
+ * ```ts
478
+ * type IEndpointHandlerDecoratorFactory<
479
+ * TDecoratorSchemas extends IDecoratorHandlerSchemas,
480
+ * TDIContainer extends DIContainer,
481
+ * TDecorator extends IEndpointHandlerDecorator<TDecoratorSchemas>
482
+ * > = (diScope: ReturnType<TDIContainer['createScope']>) => TDecorator;
483
+ * ```
484
+ *
485
+ * However, TypeScript was incorrectly inferring the types when using the 'decorate' method.
486
+ * The end developer would have had to explicitly provide the generic types, which is not ideal.
487
+ *
488
+ * With the current definition, TypeScript can infer the types from the decoratorFactory parameter,
489
+ * making it easier to use.
490
+ */
491
+ decorate(decoratorFactory) {
492
+ this._decoratorFactories.push(decoratorFactory);
493
+ return this;
494
+ }
495
+ decorateWith(decoratorStaticMethodFactory) {
496
+ this._decoratorFactories.push(decoratorStaticMethodFactory.create);
497
+ return this;
498
+ }
347
499
  }
348
500
  class MiddlewareHandlersRegistry {
349
501
  dicontainer;
@@ -366,12 +518,12 @@ class MiddlewareHandlersRegistry {
366
518
  this._onHandlerRegisteredCallback = callback;
367
519
  }
368
520
  }
369
- function middlewareParseRequestDefinitionField(inputSchemas, key, requestObject) {
370
- if (inputSchemas[key]) {
521
+ function middlewareParseRequestDefinitionField(middlewareSchemas, key, requestObject) {
522
+ if (middlewareSchemas[key]) {
371
523
  if (!(key in requestObject) || requestObject[key] === null || requestObject[key] === void 0) {
372
- const result2 = inputSchemas[key].safeParse(requestObject[key]);
524
+ const result2 = middlewareSchemas[key].safeParse(requestObject[key]);
373
525
  if (!result2.success) {
374
- switch (inputSchemas[key].type) {
526
+ switch (middlewareSchemas[key].type) {
375
527
  case "optional":
376
528
  if (requestObject[key] === null) {
377
529
  return void 0;
@@ -390,7 +542,7 @@ function middlewareParseRequestDefinitionField(inputSchemas, key, requestObject)
390
542
  }
391
543
  return result2.data;
392
544
  }
393
- const result = inputSchemas[key].safeParse(requestObject[key]);
545
+ const result = middlewareSchemas[key].safeParse(requestObject[key]);
394
546
  if (!result.success) {
395
547
  return {
396
548
  code: HttpStatusCode.BadRequest_400,
@@ -521,6 +673,41 @@ function registerEntryHandler(endpointEntry, handler) {
521
673
  endpointEntry.register(handler);
522
674
  }
523
675
 
676
+ async function execHandlerChain(diScope, allHandlerEntries, input) {
677
+ const queue = [...allHandlerEntries];
678
+ let response = void 0;
679
+ const next = async () => {
680
+ if (response) {
681
+ return;
682
+ }
683
+ const current = queue.shift();
684
+ if (!current) {
685
+ return;
686
+ }
687
+ if (!input.genericPath.startsWith(current.genericPath)) {
688
+ await next();
689
+ return;
690
+ }
691
+ const currResponse = await current.triggerNoStaticTypeCheck(
692
+ diScope,
693
+ input,
694
+ {
695
+ next
696
+ }
697
+ );
698
+ if (response) {
699
+ return;
700
+ }
701
+ if (currResponse) {
702
+ response = currResponse;
703
+ return;
704
+ }
705
+ await next();
706
+ };
707
+ await next();
708
+ return response;
709
+ }
710
+
524
711
  function partialPathString(_apiReg, path) {
525
712
  return path;
526
713
  }
@@ -714,66 +901,175 @@ class DIContainerTestClone extends DIContainerBase {
714
901
  }
715
902
  }
716
903
 
717
- function execMiddleware(diScope, list, input) {
718
- const queue = [...list];
719
- const next = async () => {
720
- const current = queue.shift();
721
- if (!current) {
722
- return;
904
+ async function triggerEndpointDecoratorNoStaticTypeCheck(endpoint, decorator, requestObject, context) {
905
+ let badRequestResponse = null;
906
+ const headers = decoratorParseRequestDefinitionField(endpoint.definition, "headers", requestObject);
907
+ if (isHttpResponseObject(headers)) {
908
+ badRequestResponse = headers;
909
+ return badRequestResponse;
910
+ }
911
+ const query = decoratorParseRequestDefinitionField(endpoint.definition, "query", requestObject);
912
+ if (isHttpResponseObject(query)) {
913
+ badRequestResponse = query;
914
+ return badRequestResponse;
915
+ }
916
+ const body = decoratorParseRequestDefinitionField(endpoint.definition, "body", requestObject);
917
+ if (isHttpResponseObject(body)) {
918
+ badRequestResponse = body;
919
+ return badRequestResponse;
920
+ }
921
+ const path = endpoint.createPath(requestObject.pathParams);
922
+ return decorator.handle({
923
+ ...requestObject,
924
+ method: endpoint.method,
925
+ genericPath: endpoint.genericPath,
926
+ path,
927
+ pathSegments: endpoint.pathSegments
928
+ }, context);
929
+ }
930
+ async function triggerMiddlewareDecoratorNoStaticTypeCheck(middlewareEntry, decorator, requestObject, context) {
931
+ let badRequestResponse = null;
932
+ const headers = decoratorParseRequestDefinitionField(middlewareEntry.middlewareSchemas, "headers", requestObject);
933
+ if (isHttpResponseObject(headers)) {
934
+ badRequestResponse = headers;
935
+ return badRequestResponse;
936
+ }
937
+ const query = decoratorParseRequestDefinitionField(middlewareEntry.middlewareSchemas, "query", requestObject);
938
+ if (isHttpResponseObject(query)) {
939
+ badRequestResponse = query;
940
+ return badRequestResponse;
941
+ }
942
+ const body = decoratorParseRequestDefinitionField(middlewareEntry.middlewareSchemas, "body", requestObject);
943
+ if (isHttpResponseObject(body)) {
944
+ badRequestResponse = body;
945
+ return badRequestResponse;
946
+ }
947
+ const path = middlewareEntry.createPath(requestObject.pathParams);
948
+ return decorator.handle({
949
+ ...requestObject,
950
+ method: middlewareEntry.method,
951
+ // TODO: might be empty, as middleware can be registered with path only, without method
952
+ genericPath: middlewareEntry.genericPath,
953
+ path,
954
+ pathSegments: middlewareEntry.pathSegments
955
+ }, context);
956
+ }
957
+ function decoratorParseRequestDefinitionField(decoratorSchemas, key, requestObject) {
958
+ if (decoratorSchemas[key]) {
959
+ if (!(key in requestObject) || requestObject[key] === null || requestObject[key] === void 0) {
960
+ const result2 = decoratorSchemas[key].safeParse(requestObject[key]);
961
+ if (!result2.success) {
962
+ switch (decoratorSchemas[key].type) {
963
+ case "optional":
964
+ if (requestObject[key] === null) {
965
+ return void 0;
966
+ }
967
+ break;
968
+ case "nullable":
969
+ if (requestObject[key] === void 0) {
970
+ return null;
971
+ }
972
+ break;
973
+ }
974
+ return {
975
+ code: HttpStatusCode.BadRequest_400,
976
+ body: `'${key}' is required for this endpoint` + (key === "body" ? ", { 'Content-Type': 'application/json' } header might be missing" : "")
977
+ };
978
+ }
979
+ return result2.data;
723
980
  }
724
- const result = await current.trigger(
725
- diScope,
726
- {
727
- headers: input.headers,
728
- pathParams: input.pathParams,
729
- body: input.body,
730
- query: input.query
731
- },
732
- next
733
- );
734
- if (result) {
735
- return result;
981
+ const result = decoratorSchemas[key].safeParse(requestObject[key]);
982
+ if (!result.success) {
983
+ return {
984
+ code: HttpStatusCode.BadRequest_400,
985
+ body: result.error.issues
986
+ };
736
987
  }
737
- return next();
738
- };
739
- return next();
988
+ return result.data;
989
+ }
990
+ return null;
740
991
  }
741
992
 
742
- function createInProcApiClient(contract, testContainer, registry) {
743
- const testApiReg = createRegistry(testContainer, contract, {
744
- handlerRegisteredCallback: (_entry) => {
745
- },
746
- middlewareHandlerRegisteredCallback: (_entry) => {
993
+ function createInProcApiClient(contract, testContainer, registry, options) {
994
+ const mwHandlers = [];
995
+ const mwReg = registry._middlewareRegistry;
996
+ const mwNdx = 0;
997
+ for (const mwEntry of mwReg.list) {
998
+ if (!options?.filterMiddleware) {
999
+ addMiddlewareDecorators(mwHandlers, mwEntry);
1000
+ mwHandlers.push(mwEntry);
1001
+ continue;
747
1002
  }
748
- });
749
- registry._middlewareRegistry.list.forEach((mwEntry) => {
750
- testApiReg._middlewareRegistry.register(mwEntry);
751
- });
752
- const mwReg = testApiReg._middlewareRegistry;
753
- flatListAllRegistryEntries(registry).forEach((entry) => {
754
- if (!entry.handler) {
755
- return;
1003
+ const isIncluded = options.filterMiddleware(mwEntry.genericPath, mwNdx);
1004
+ if (!isIncluded) {
1005
+ continue;
756
1006
  }
757
- const rt = route(testApiReg, `${entry.methodEndpoint.method} ${entry.methodEndpoint.genericPath}`);
758
- rt.inject(entry.injection).register(entry.handler);
759
- });
1007
+ addMiddlewareDecorators(mwHandlers, mwEntry);
1008
+ mwHandlers.push(mwEntry);
1009
+ }
760
1010
  const client = createClient(contract, async (input) => {
1011
+ if (options?.enhanceRequest) {
1012
+ input = options.enhanceRequest(input);
1013
+ }
761
1014
  const diScope = testContainer.createScope();
762
- const haltExecResponse = await execMiddleware(diScope, mwReg.list, input);
763
- if (haltExecResponse) {
764
- return haltExecResponse;
765
- }
766
- const rt = route(testApiReg, `${input.method} ${input.genericPath}`);
767
- const result = await rt.trigger(diScope, {
768
- headers: input.headers,
769
- pathParams: input.pathParams,
770
- body: input.body,
771
- query: input.query
1015
+ const allHandlerEntries = [...mwHandlers];
1016
+ const endpointHandlerEntry = route(registry, `${input.method} ${input.genericPath}`);
1017
+ if (!endpointHandlerEntry.handler) {
1018
+ throw new Error(`No handler registered for ${input.method} ${input.genericPath}`);
1019
+ }
1020
+ endpointHandlerEntry.decoratorFactories.forEach((decoratorFactory) => {
1021
+ allHandlerEntries.push({
1022
+ genericPath: endpointHandlerEntry.genericPath,
1023
+ triggerNoStaticTypeCheck: async (diScope2, requestObject, context) => {
1024
+ const decorator = decoratorFactory(diScope2);
1025
+ return await triggerEndpointDecoratorNoStaticTypeCheck(
1026
+ endpointHandlerEntry.methodEndpoint,
1027
+ decorator,
1028
+ requestObject,
1029
+ context
1030
+ );
1031
+ }
1032
+ });
772
1033
  });
773
- return result;
1034
+ if (options?.mockEndpointResponse) {
1035
+ const mockResponse = options.mockEndpointResponse(input.genericPath, input.method, diScope);
1036
+ if (mockResponse) {
1037
+ allHandlerEntries.push({
1038
+ genericPath: endpointHandlerEntry.genericPath,
1039
+ triggerNoStaticTypeCheck: async (_diScope, _requestObject, _next) => {
1040
+ return mockResponse;
1041
+ }
1042
+ });
1043
+ } else {
1044
+ allHandlerEntries.push(endpointHandlerEntry);
1045
+ }
1046
+ } else {
1047
+ allHandlerEntries.push(endpointHandlerEntry);
1048
+ }
1049
+ const response = await execHandlerChain(diScope, allHandlerEntries, input);
1050
+ if (!response) {
1051
+ throw new Error(`No response from ${input.method} ${input.genericPath}`);
1052
+ }
1053
+ return response;
774
1054
  });
775
1055
  return client;
776
1056
  }
1057
+ function addMiddlewareDecorators(mwHandlers, mwEntry) {
1058
+ mwEntry.decoratorFactories.forEach((decoratorFactory) => {
1059
+ mwHandlers.push({
1060
+ genericPath: mwEntry.genericPath,
1061
+ triggerNoStaticTypeCheck: async (diScope, requestObject, context) => {
1062
+ const decorator = decoratorFactory(diScope);
1063
+ return await triggerMiddlewareDecoratorNoStaticTypeCheck(
1064
+ mwEntry,
1065
+ decorator,
1066
+ requestObject,
1067
+ context
1068
+ );
1069
+ }
1070
+ });
1071
+ });
1072
+ }
777
1073
 
778
1074
  exports.ApiClient = ApiClient;
779
1075
  exports.ApiContract = ApiContract;
@@ -793,6 +1089,7 @@ exports.createClient = createClient;
793
1089
  exports.createInProcApiClient = createInProcApiClient;
794
1090
  exports.createRegistry = createRegistry;
795
1091
  exports.endpoint = endpoint;
1092
+ exports.execHandlerChain = execHandlerChain;
796
1093
  exports.flatListAllRegistryEntries = flatListAllRegistryEntries;
797
1094
  exports.isHttpResponseObject = isHttpResponseObject;
798
1095
  exports.isHttpStatusCode = isHttpStatusCode;
@@ -802,3 +1099,5 @@ exports.partialPathString = partialPathString;
802
1099
  exports.register = register;
803
1100
  exports.response = response;
804
1101
  exports.route = route;
1102
+ exports.triggerEndpointDecoratorNoStaticTypeCheck = triggerEndpointDecoratorNoStaticTypeCheck;
1103
+ exports.triggerMiddlewareDecoratorNoStaticTypeCheck = triggerMiddlewareDecoratorNoStaticTypeCheck;