@congruent-stack/congruent-api 0.7.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 +550 -157
- package/dist/index.d.cts +252 -95
- package/dist/index.d.mts +252 -95
- package/dist/index.mjs +546 -158
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -17,6 +17,11 @@ class HttpMethodEndpoint {
|
|
|
17
17
|
}
|
|
18
18
|
return this._cachedGenericPath;
|
|
19
19
|
}
|
|
20
|
+
createPath(pathParams) {
|
|
21
|
+
return `/${this.pathSegments.map(
|
|
22
|
+
(segment) => segment.startsWith(":") ? pathParams[segment.slice(1)] ?? "?" : segment
|
|
23
|
+
).join("/")}`;
|
|
24
|
+
}
|
|
20
25
|
_method = null;
|
|
21
26
|
get method() {
|
|
22
27
|
return this._method;
|
|
@@ -110,6 +115,7 @@ var HttpStatusCode = /* @__PURE__ */ ((HttpStatusCode2) => {
|
|
|
110
115
|
HttpStatusCode2[HttpStatusCode2["Forbidden_403"] = 403] = "Forbidden_403";
|
|
111
116
|
HttpStatusCode2[HttpStatusCode2["NotFound_404"] = 404] = "NotFound_404";
|
|
112
117
|
HttpStatusCode2[HttpStatusCode2["Conflict_409"] = 409] = "Conflict_409";
|
|
118
|
+
HttpStatusCode2[HttpStatusCode2["UnprocessableEntity_422"] = 422] = "UnprocessableEntity_422";
|
|
113
119
|
HttpStatusCode2[HttpStatusCode2["InternalServerError_500"] = 500] = "InternalServerError_500";
|
|
114
120
|
HttpStatusCode2[HttpStatusCode2["NotImplemented_501"] = 501] = "NotImplemented_501";
|
|
115
121
|
HttpStatusCode2[HttpStatusCode2["BadGateway_502"] = 502] = "BadGateway_502";
|
|
@@ -138,6 +144,9 @@ class MethodEndpointHandlerRegistryEntry {
|
|
|
138
144
|
this._methodEndpoint = methodEndpoint;
|
|
139
145
|
this._dicontainer = dicontainer;
|
|
140
146
|
}
|
|
147
|
+
get genericPath() {
|
|
148
|
+
return this._methodEndpoint.genericPath;
|
|
149
|
+
}
|
|
141
150
|
_handler = null;
|
|
142
151
|
get handler() {
|
|
143
152
|
return this._handler;
|
|
@@ -147,6 +156,7 @@ class MethodEndpointHandlerRegistryEntry {
|
|
|
147
156
|
if (this._onHandlerRegisteredCallback) {
|
|
148
157
|
this._onHandlerRegisteredCallback(this);
|
|
149
158
|
}
|
|
159
|
+
return this;
|
|
150
160
|
}
|
|
151
161
|
_onHandlerRegisteredCallback = null;
|
|
152
162
|
_onHandlerRegistered(callback) {
|
|
@@ -156,7 +166,7 @@ class MethodEndpointHandlerRegistryEntry {
|
|
|
156
166
|
callback(this);
|
|
157
167
|
return this;
|
|
158
168
|
}
|
|
159
|
-
_injection = (
|
|
169
|
+
_injection = (_diScope) => ({});
|
|
160
170
|
get injection() {
|
|
161
171
|
return this._injection;
|
|
162
172
|
}
|
|
@@ -164,61 +174,152 @@ class MethodEndpointHandlerRegistryEntry {
|
|
|
164
174
|
this._injection = injection;
|
|
165
175
|
return this;
|
|
166
176
|
}
|
|
167
|
-
|
|
177
|
+
_decoratorFactories = [];
|
|
178
|
+
get decoratorFactories() {
|
|
179
|
+
return this._decoratorFactories;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
*
|
|
183
|
+
* @param decoratorFactory must be a function that takes exactly the DI scope type and returns an instance of a class that implements IEndpointHandlerDecorator
|
|
184
|
+
* @returns this
|
|
185
|
+
*
|
|
186
|
+
* Initially, the method was defined as:
|
|
187
|
+
* ```ts
|
|
188
|
+
* decorate<
|
|
189
|
+
* TDecoratorSchemas extends IDecoratorHandlerSchemas,
|
|
190
|
+
* TDecorator extends IEndpointHandlerDecorator<TDecoratorSchemas>
|
|
191
|
+
* > (
|
|
192
|
+
* decoratorFactory: IEndpointHandlerDecoratorFactory<TDecoratorSchemas, TDIContainer, TDecorator>
|
|
193
|
+
* ): this {
|
|
194
|
+
* this._decoratorFactories.push(decoratorFactory);
|
|
195
|
+
* return this;
|
|
196
|
+
* }
|
|
197
|
+
* ```
|
|
198
|
+
*
|
|
199
|
+
* and the type IEndpointHandlerDecoratorFactory was defined as:
|
|
200
|
+
* ```ts
|
|
201
|
+
* type IEndpointHandlerDecoratorFactory<
|
|
202
|
+
* TDecoratorSchemas extends IDecoratorHandlerSchemas,
|
|
203
|
+
* TDIContainer extends DIContainer,
|
|
204
|
+
* TDecorator extends IEndpointHandlerDecorator<TDecoratorSchemas>
|
|
205
|
+
* > = (diScope: ReturnType<TDIContainer['createScope']>) => TDecorator;
|
|
206
|
+
* ```
|
|
207
|
+
*
|
|
208
|
+
* However, TypeScript was incorrectly inferring the types when using the 'decorate' method.
|
|
209
|
+
* The end developer would have had to explicitly provide the generic types, which is not ideal.
|
|
210
|
+
*
|
|
211
|
+
* With the current definition, TypeScript can infer the types from the decoratorFactory parameter,
|
|
212
|
+
* making it easier to use.
|
|
213
|
+
*/
|
|
214
|
+
decorate(decoratorFactory, decoratingArgs) {
|
|
215
|
+
this._decoratorFactories.push((scope) => decoratorFactory(scope, decoratingArgs));
|
|
216
|
+
return this;
|
|
217
|
+
}
|
|
218
|
+
decorateWith(decoratorStaticMethodFactory, decoratingArgs) {
|
|
219
|
+
this._decoratorFactories.push((scope) => decoratorStaticMethodFactory.create(scope, decoratingArgs));
|
|
220
|
+
return this;
|
|
221
|
+
}
|
|
222
|
+
async trigger(diScope, requestObject) {
|
|
223
|
+
return this.triggerNoStaticTypeCheck(diScope, requestObject, { originalRequest: requestObject });
|
|
224
|
+
}
|
|
225
|
+
async exec(injected, requestObject) {
|
|
168
226
|
if (!this._handler) {
|
|
169
227
|
throw new Error("Handler not set for this endpoint");
|
|
170
228
|
}
|
|
171
229
|
let badRequestResponse = null;
|
|
172
|
-
const headers = parseRequestDefinitionField(this._methodEndpoint.definition, "headers",
|
|
230
|
+
const headers = parseRequestDefinitionField(this._methodEndpoint.definition, "headers", requestObject);
|
|
173
231
|
if (isHttpResponseObject(headers)) {
|
|
174
232
|
badRequestResponse = headers;
|
|
175
233
|
return badRequestResponse;
|
|
176
234
|
}
|
|
177
|
-
const query = parseRequestDefinitionField(this._methodEndpoint.definition, "query",
|
|
235
|
+
const query = parseRequestDefinitionField(this._methodEndpoint.definition, "query", requestObject);
|
|
178
236
|
if (isHttpResponseObject(query)) {
|
|
179
237
|
badRequestResponse = query;
|
|
180
238
|
return badRequestResponse;
|
|
181
239
|
}
|
|
182
|
-
const body = parseRequestDefinitionField(this._methodEndpoint.definition, "body",
|
|
240
|
+
const body = parseRequestDefinitionField(this._methodEndpoint.definition, "body", requestObject);
|
|
183
241
|
if (isHttpResponseObject(body)) {
|
|
184
242
|
badRequestResponse = body;
|
|
185
243
|
return badRequestResponse;
|
|
186
244
|
}
|
|
187
|
-
const path =
|
|
188
|
-
(segment) => segment.startsWith(":") ? data.pathParams[segment.slice(1)] ?? "?" : segment
|
|
189
|
-
).join("/")}`;
|
|
245
|
+
const path = this._methodEndpoint.createPath(requestObject.pathParams);
|
|
190
246
|
return await this._handler({
|
|
191
247
|
method: this._methodEndpoint.method,
|
|
192
248
|
path,
|
|
193
249
|
genericPath: this._methodEndpoint.genericPath,
|
|
194
250
|
pathSegments: this._methodEndpoint.pathSegments,
|
|
195
251
|
headers,
|
|
196
|
-
pathParams:
|
|
252
|
+
pathParams: requestObject.pathParams,
|
|
197
253
|
query,
|
|
198
|
-
body
|
|
199
|
-
|
|
200
|
-
|
|
254
|
+
body
|
|
255
|
+
}, injected);
|
|
256
|
+
}
|
|
257
|
+
async triggerNoStaticTypeCheck(diScope, requestObject, context) {
|
|
258
|
+
if (!this._handler) {
|
|
259
|
+
throw new Error("Handler not set for this endpoint");
|
|
260
|
+
}
|
|
261
|
+
let badRequestResponse = null;
|
|
262
|
+
const headers = parseRequestDefinitionField(this._methodEndpoint.definition, "headers", requestObject);
|
|
263
|
+
if (isHttpResponseObject(headers)) {
|
|
264
|
+
badRequestResponse = headers;
|
|
265
|
+
return badRequestResponse;
|
|
266
|
+
}
|
|
267
|
+
const query = parseRequestDefinitionField(this._methodEndpoint.definition, "query", requestObject);
|
|
268
|
+
if (isHttpResponseObject(query)) {
|
|
269
|
+
badRequestResponse = query;
|
|
270
|
+
return badRequestResponse;
|
|
271
|
+
}
|
|
272
|
+
const body = parseRequestDefinitionField(this._methodEndpoint.definition, "body", requestObject);
|
|
273
|
+
if (isHttpResponseObject(body)) {
|
|
274
|
+
badRequestResponse = body;
|
|
275
|
+
return badRequestResponse;
|
|
276
|
+
}
|
|
277
|
+
const path = this._methodEndpoint.createPath(requestObject.pathParams);
|
|
278
|
+
Object.assign(context, this._injection(diScope));
|
|
279
|
+
return await this._handler({
|
|
280
|
+
method: this._methodEndpoint.method,
|
|
281
|
+
path,
|
|
282
|
+
genericPath: this._methodEndpoint.genericPath,
|
|
283
|
+
pathSegments: this._methodEndpoint.pathSegments,
|
|
284
|
+
headers,
|
|
285
|
+
pathParams: requestObject.pathParams,
|
|
286
|
+
query,
|
|
287
|
+
body
|
|
288
|
+
}, context);
|
|
201
289
|
}
|
|
202
290
|
}
|
|
203
|
-
function parseRequestDefinitionField(definition, key,
|
|
291
|
+
function parseRequestDefinitionField(definition, key, requestObject) {
|
|
204
292
|
if (definition[key]) {
|
|
205
|
-
if (!(key in
|
|
206
|
-
|
|
293
|
+
if (!(key in requestObject) || requestObject[key] === null || requestObject[key] === void 0) {
|
|
294
|
+
const result2 = definition[key].safeParse(requestObject[key]);
|
|
295
|
+
if (!result2.success) {
|
|
296
|
+
switch (definition[key].type) {
|
|
297
|
+
case "optional":
|
|
298
|
+
if (requestObject[key] === null) {
|
|
299
|
+
return void 0;
|
|
300
|
+
}
|
|
301
|
+
break;
|
|
302
|
+
case "nullable":
|
|
303
|
+
if (requestObject[key] === void 0) {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
207
308
|
return {
|
|
208
309
|
code: HttpStatusCode.BadRequest_400,
|
|
209
310
|
body: `'${key}' is required for this endpoint` + (key === "body" ? ", { 'Content-Type': 'application/json' } header might be missing" : "")
|
|
210
311
|
};
|
|
211
312
|
}
|
|
212
|
-
return
|
|
313
|
+
return result2.data;
|
|
213
314
|
}
|
|
214
|
-
const result = definition[key].safeParse(
|
|
315
|
+
const result = definition[key].safeParse(requestObject[key]);
|
|
215
316
|
if (!result.success) {
|
|
216
317
|
return {
|
|
217
318
|
code: HttpStatusCode.BadRequest_400,
|
|
218
319
|
body: result.error.issues
|
|
219
320
|
};
|
|
220
321
|
}
|
|
221
|
-
return result.data
|
|
322
|
+
return result.data;
|
|
222
323
|
}
|
|
223
324
|
return null;
|
|
224
325
|
}
|
|
@@ -233,11 +334,33 @@ function middleware(apiReg, path) {
|
|
|
233
334
|
}
|
|
234
335
|
class MiddlewareHandlersRegistryEntryInternal {
|
|
235
336
|
_dicontainer;
|
|
337
|
+
get dicontainer() {
|
|
338
|
+
return this._dicontainer;
|
|
339
|
+
}
|
|
236
340
|
_middlewareGenericPath;
|
|
237
341
|
get genericPath() {
|
|
238
342
|
return this._middlewareGenericPath;
|
|
239
343
|
}
|
|
240
|
-
|
|
344
|
+
_middlewarePathSegments;
|
|
345
|
+
get pathSegments() {
|
|
346
|
+
return this._middlewarePathSegments;
|
|
347
|
+
}
|
|
348
|
+
_middlewareMethod;
|
|
349
|
+
get method() {
|
|
350
|
+
return this._middlewareMethod;
|
|
351
|
+
}
|
|
352
|
+
_middlewareSchemas;
|
|
353
|
+
get middlewareSchemas() {
|
|
354
|
+
return this._middlewareSchemas;
|
|
355
|
+
}
|
|
356
|
+
_handler;
|
|
357
|
+
constructor(diContainer, middlewarePath, middlewareSchemas, decoratorFactories, injection, handler) {
|
|
358
|
+
this._dicontainer = diContainer;
|
|
359
|
+
this._middlewareGenericPath = middlewarePath;
|
|
360
|
+
this._middlewareSchemas = middlewareSchemas;
|
|
361
|
+
this._decoratorFactories.push(...decoratorFactories);
|
|
362
|
+
this._injection = injection;
|
|
363
|
+
this._handler = handler;
|
|
241
364
|
const splitResult = this._middlewareGenericPath.split(" ");
|
|
242
365
|
let method = "";
|
|
243
366
|
let pathSegments = [];
|
|
@@ -248,54 +371,56 @@ class MiddlewareHandlersRegistryEntryInternal {
|
|
|
248
371
|
}
|
|
249
372
|
pathSegments = splitResult[1].split("/").map((segment) => segment.trim()).filter((segment) => segment !== "");
|
|
250
373
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
pathSegments
|
|
254
|
-
};
|
|
374
|
+
this._middlewareMethod = method;
|
|
375
|
+
this._middlewarePathSegments = pathSegments;
|
|
255
376
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
this._dicontainer = diContainer;
|
|
260
|
-
this._middlewareGenericPath = middlewarePath;
|
|
261
|
-
this._inputSchemas = inputSchemas;
|
|
262
|
-
this._injection = injection;
|
|
263
|
-
this._handler = handler;
|
|
377
|
+
_decoratorFactories = [];
|
|
378
|
+
get decoratorFactories() {
|
|
379
|
+
return this._decoratorFactories;
|
|
264
380
|
}
|
|
265
381
|
_injection = (_dicontainer) => ({});
|
|
266
|
-
async trigger(
|
|
382
|
+
async trigger(diScope, requestObject, context) {
|
|
383
|
+
return this.triggerNoStaticTypeCheck(diScope, requestObject, context);
|
|
384
|
+
}
|
|
385
|
+
async triggerNoStaticTypeCheck(diScope, requestObject, context) {
|
|
267
386
|
let badRequestResponse = null;
|
|
268
|
-
const headers = middlewareParseRequestDefinitionField(this.
|
|
387
|
+
const headers = middlewareParseRequestDefinitionField(this._middlewareSchemas, "headers", requestObject);
|
|
269
388
|
if (isHttpResponseObject(headers)) {
|
|
270
389
|
badRequestResponse = headers;
|
|
271
390
|
return badRequestResponse;
|
|
272
391
|
}
|
|
273
|
-
const query = middlewareParseRequestDefinitionField(this.
|
|
392
|
+
const query = middlewareParseRequestDefinitionField(this._middlewareSchemas, "query", requestObject);
|
|
274
393
|
if (isHttpResponseObject(query)) {
|
|
275
394
|
badRequestResponse = query;
|
|
276
395
|
return badRequestResponse;
|
|
277
396
|
}
|
|
278
|
-
const body = middlewareParseRequestDefinitionField(this.
|
|
397
|
+
const body = middlewareParseRequestDefinitionField(this._middlewareSchemas, "body", requestObject);
|
|
279
398
|
if (isHttpResponseObject(body)) {
|
|
280
399
|
badRequestResponse = body;
|
|
281
400
|
return badRequestResponse;
|
|
282
401
|
}
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
402
|
+
const path = this.createPath(requestObject.pathParams);
|
|
403
|
+
Object.assign(context, this._injection(diScope));
|
|
404
|
+
return await this._handler(
|
|
405
|
+
{
|
|
406
|
+
method: this.method,
|
|
407
|
+
// TODO: might be empty, as middleware can be registered with path only, without method
|
|
408
|
+
path,
|
|
409
|
+
genericPath: this.genericPath,
|
|
410
|
+
pathSegments: this.pathSegments,
|
|
411
|
+
headers,
|
|
412
|
+
pathParams: requestObject.pathParams,
|
|
413
|
+
query,
|
|
414
|
+
body
|
|
415
|
+
},
|
|
416
|
+
context
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
createPath(pathParams) {
|
|
420
|
+
const path = `/${this.pathSegments.map(
|
|
421
|
+
(segment) => segment.startsWith(":") ? pathParams[segment.slice(1)] ?? "?" : segment
|
|
286
422
|
).join("/")}`;
|
|
287
|
-
return
|
|
288
|
-
method,
|
|
289
|
-
// TODO: might be empty, as middleware can be registered with path only, without method, possible fix: take it from express.request.method
|
|
290
|
-
path,
|
|
291
|
-
genericPath: this.genericPath,
|
|
292
|
-
pathSegments,
|
|
293
|
-
headers,
|
|
294
|
-
pathParams: data.pathParams,
|
|
295
|
-
query,
|
|
296
|
-
body,
|
|
297
|
-
injected: this._injection(this._dicontainer.createScope())
|
|
298
|
-
}, next);
|
|
423
|
+
return path;
|
|
299
424
|
}
|
|
300
425
|
}
|
|
301
426
|
class MiddlewareHandlersRegistryEntry {
|
|
@@ -305,7 +430,7 @@ class MiddlewareHandlersRegistryEntry {
|
|
|
305
430
|
this._registry = registry;
|
|
306
431
|
this._path = path;
|
|
307
432
|
}
|
|
308
|
-
_injection = (
|
|
433
|
+
_injection = (_diScope) => ({});
|
|
309
434
|
get injection() {
|
|
310
435
|
return this._injection;
|
|
311
436
|
}
|
|
@@ -313,16 +438,62 @@ class MiddlewareHandlersRegistryEntry {
|
|
|
313
438
|
this._injection = injection;
|
|
314
439
|
return this;
|
|
315
440
|
}
|
|
316
|
-
register(
|
|
441
|
+
register(middlewareSchemas, handler) {
|
|
317
442
|
const internalEntry = new MiddlewareHandlersRegistryEntryInternal(
|
|
318
443
|
this._registry.dicontainer,
|
|
319
444
|
this._path,
|
|
320
|
-
|
|
445
|
+
middlewareSchemas,
|
|
446
|
+
this._decoratorFactories,
|
|
321
447
|
this._injection,
|
|
322
448
|
handler
|
|
323
449
|
);
|
|
324
450
|
this._registry.register(internalEntry);
|
|
325
451
|
}
|
|
452
|
+
_decoratorFactories = [];
|
|
453
|
+
get decoratorFactories() {
|
|
454
|
+
return this._decoratorFactories;
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
*
|
|
458
|
+
* @param decoratorFactory must be a function that takes exactly the DI scope type and returns an instance of a class that implements IEndpointHandlerDecorator
|
|
459
|
+
* @returns this
|
|
460
|
+
*
|
|
461
|
+
* Initially, the method was defined as:
|
|
462
|
+
* ```ts
|
|
463
|
+
* decorate<
|
|
464
|
+
* TDecoratorSchemas extends IDecoratorHandlerSchemas,
|
|
465
|
+
* TDecorator extends IEndpointHandlerDecorator<TDecoratorSchemas>
|
|
466
|
+
* > (
|
|
467
|
+
* decoratorFactory: IEndpointHandlerDecoratorFactory<TDecoratorSchemas, TDIContainer, TDecorator>
|
|
468
|
+
* ): this {
|
|
469
|
+
* this._decoratorFactories.push(decoratorFactory);
|
|
470
|
+
* return this;
|
|
471
|
+
* }
|
|
472
|
+
* ```
|
|
473
|
+
*
|
|
474
|
+
* and the type IEndpointHandlerDecoratorFactory was defined as:
|
|
475
|
+
* ```ts
|
|
476
|
+
* type IEndpointHandlerDecoratorFactory<
|
|
477
|
+
* TDecoratorSchemas extends IDecoratorHandlerSchemas,
|
|
478
|
+
* TDIContainer extends DIContainer,
|
|
479
|
+
* TDecorator extends IEndpointHandlerDecorator<TDecoratorSchemas>
|
|
480
|
+
* > = (diScope: ReturnType<TDIContainer['createScope']>) => TDecorator;
|
|
481
|
+
* ```
|
|
482
|
+
*
|
|
483
|
+
* However, TypeScript was incorrectly inferring the types when using the 'decorate' method.
|
|
484
|
+
* The end developer would have had to explicitly provide the generic types, which is not ideal.
|
|
485
|
+
*
|
|
486
|
+
* With the current definition, TypeScript can infer the types from the decoratorFactory parameter,
|
|
487
|
+
* making it easier to use.
|
|
488
|
+
*/
|
|
489
|
+
decorate(decoratorFactory) {
|
|
490
|
+
this._decoratorFactories.push(decoratorFactory);
|
|
491
|
+
return this;
|
|
492
|
+
}
|
|
493
|
+
decorateWith(decoratorStaticMethodFactory) {
|
|
494
|
+
this._decoratorFactories.push(decoratorStaticMethodFactory.create);
|
|
495
|
+
return this;
|
|
496
|
+
}
|
|
326
497
|
}
|
|
327
498
|
class MiddlewareHandlersRegistry {
|
|
328
499
|
dicontainer;
|
|
@@ -330,8 +501,13 @@ class MiddlewareHandlersRegistry {
|
|
|
330
501
|
this.dicontainer = dicontainer;
|
|
331
502
|
this._onHandlerRegisteredCallback = callback;
|
|
332
503
|
}
|
|
504
|
+
_list = [];
|
|
505
|
+
get list() {
|
|
506
|
+
return this._list;
|
|
507
|
+
}
|
|
333
508
|
register(entry) {
|
|
334
509
|
if (this._onHandlerRegisteredCallback) {
|
|
510
|
+
this._list.push(entry);
|
|
335
511
|
this._onHandlerRegisteredCallback(entry);
|
|
336
512
|
}
|
|
337
513
|
}
|
|
@@ -340,25 +516,38 @@ class MiddlewareHandlersRegistry {
|
|
|
340
516
|
this._onHandlerRegisteredCallback = callback;
|
|
341
517
|
}
|
|
342
518
|
}
|
|
343
|
-
function middlewareParseRequestDefinitionField(
|
|
344
|
-
if (
|
|
345
|
-
if (!(key in
|
|
346
|
-
|
|
519
|
+
function middlewareParseRequestDefinitionField(middlewareSchemas, key, requestObject) {
|
|
520
|
+
if (middlewareSchemas[key]) {
|
|
521
|
+
if (!(key in requestObject) || requestObject[key] === null || requestObject[key] === void 0) {
|
|
522
|
+
const result2 = middlewareSchemas[key].safeParse(requestObject[key]);
|
|
523
|
+
if (!result2.success) {
|
|
524
|
+
switch (middlewareSchemas[key].type) {
|
|
525
|
+
case "optional":
|
|
526
|
+
if (requestObject[key] === null) {
|
|
527
|
+
return void 0;
|
|
528
|
+
}
|
|
529
|
+
break;
|
|
530
|
+
case "nullable":
|
|
531
|
+
if (requestObject[key] === void 0) {
|
|
532
|
+
return null;
|
|
533
|
+
}
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
347
536
|
return {
|
|
348
537
|
code: HttpStatusCode.BadRequest_400,
|
|
349
538
|
body: `'${key}' is required for this endpoint` + (key === "body" ? ", { 'Content-Type': 'application/json' } header might be missing" : "")
|
|
350
539
|
};
|
|
351
540
|
}
|
|
352
|
-
return
|
|
541
|
+
return result2.data;
|
|
353
542
|
}
|
|
354
|
-
const result =
|
|
543
|
+
const result = middlewareSchemas[key].safeParse(requestObject[key]);
|
|
355
544
|
if (!result.success) {
|
|
356
545
|
return {
|
|
357
546
|
code: HttpStatusCode.BadRequest_400,
|
|
358
547
|
body: result.error.issues
|
|
359
548
|
};
|
|
360
549
|
}
|
|
361
|
-
return result.data
|
|
550
|
+
return result.data;
|
|
362
551
|
}
|
|
363
552
|
return null;
|
|
364
553
|
}
|
|
@@ -482,6 +671,41 @@ function registerEntryHandler(endpointEntry, handler) {
|
|
|
482
671
|
endpointEntry.register(handler);
|
|
483
672
|
}
|
|
484
673
|
|
|
674
|
+
async function execHandlerChain(diScope, allHandlerEntries, input) {
|
|
675
|
+
const queue = [...allHandlerEntries];
|
|
676
|
+
let response = void 0;
|
|
677
|
+
const next = async () => {
|
|
678
|
+
if (response) {
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
const current = queue.shift();
|
|
682
|
+
if (!current) {
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
if (!input.genericPath.startsWith(current.genericPath)) {
|
|
686
|
+
await next();
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
const currResponse = await current.triggerNoStaticTypeCheck(
|
|
690
|
+
diScope,
|
|
691
|
+
input,
|
|
692
|
+
{
|
|
693
|
+
next
|
|
694
|
+
}
|
|
695
|
+
);
|
|
696
|
+
if (response) {
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
if (currResponse) {
|
|
700
|
+
response = currResponse;
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
await next();
|
|
704
|
+
};
|
|
705
|
+
await next();
|
|
706
|
+
return response;
|
|
707
|
+
}
|
|
708
|
+
|
|
485
709
|
function partialPathString(_apiReg, path) {
|
|
486
710
|
return path;
|
|
487
711
|
}
|
|
@@ -526,12 +750,12 @@ class InnerApiClient {
|
|
|
526
750
|
delete currObj[key];
|
|
527
751
|
InnerApiClient._initialize(client, val, clientGenericHandler);
|
|
528
752
|
} else if (val instanceof HttpMethodEndpoint) {
|
|
529
|
-
currObj[key] = (
|
|
753
|
+
currObj[key] = (requestObject) => {
|
|
530
754
|
const pathParams = { ...client.__CONTEXT__.pathParameters };
|
|
531
755
|
client.__CONTEXT__ = InnerApiClient._initNewContext();
|
|
532
|
-
const headers = clientParseRequestDefinitionField(val.definition, "headers",
|
|
533
|
-
const query = clientParseRequestDefinitionField(val.definition, "query",
|
|
534
|
-
const body = clientParseRequestDefinitionField(val.definition, "body",
|
|
756
|
+
const headers = clientParseRequestDefinitionField(val.definition, "headers", requestObject);
|
|
757
|
+
const query = clientParseRequestDefinitionField(val.definition, "query", requestObject);
|
|
758
|
+
const body = clientParseRequestDefinitionField(val.definition, "body", requestObject);
|
|
535
759
|
const path = `/${val.pathSegments.map(
|
|
536
760
|
(segment) => segment.startsWith(":") ? pathParams[segment.slice(1)] ?? "?" : segment
|
|
537
761
|
).join("/")}`;
|
|
@@ -553,132 +777,296 @@ class InnerApiClient {
|
|
|
553
777
|
}
|
|
554
778
|
}
|
|
555
779
|
const ApiClient = InnerApiClient;
|
|
556
|
-
function clientParseRequestDefinitionField(definition, key,
|
|
780
|
+
function clientParseRequestDefinitionField(definition, key, requestObject) {
|
|
557
781
|
if (definition[key]) {
|
|
558
|
-
if (!(key in
|
|
559
|
-
|
|
560
|
-
|
|
782
|
+
if (!(key in requestObject) || requestObject[key] === null || requestObject[key] === void 0) {
|
|
783
|
+
const result2 = definition[key].safeParse(requestObject[key]);
|
|
784
|
+
if (!result2.success) {
|
|
785
|
+
switch (definition[key].type) {
|
|
786
|
+
case "optional":
|
|
787
|
+
if (requestObject[key] === null) {
|
|
788
|
+
return void 0;
|
|
789
|
+
}
|
|
790
|
+
break;
|
|
791
|
+
case "nullable":
|
|
792
|
+
if (requestObject[key] === void 0) {
|
|
793
|
+
return null;
|
|
794
|
+
}
|
|
795
|
+
break;
|
|
796
|
+
}
|
|
797
|
+
throw new Error(`'${key}' is required for this endpoint`);
|
|
561
798
|
}
|
|
562
|
-
return
|
|
799
|
+
return result2.data;
|
|
563
800
|
}
|
|
564
|
-
const result = definition[key].safeParse(
|
|
801
|
+
const result = definition[key].safeParse(requestObject[key]);
|
|
565
802
|
if (!result.success) {
|
|
566
803
|
throw new Error(`Validation for '${key}' failed`, { cause: result.error });
|
|
567
804
|
}
|
|
568
|
-
return result.data
|
|
805
|
+
return result.data;
|
|
569
806
|
}
|
|
570
807
|
return null;
|
|
571
808
|
}
|
|
572
809
|
|
|
573
|
-
class
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
810
|
+
class DIContainerBase {
|
|
811
|
+
_map = /* @__PURE__ */ new Map();
|
|
812
|
+
_singletonInstances = /* @__PURE__ */ new Map();
|
|
813
|
+
createScope() {
|
|
814
|
+
const proxy = new Proxy({
|
|
815
|
+
_map: this._map,
|
|
816
|
+
_singletonInstances: this._singletonInstances,
|
|
817
|
+
_scopedInstances: /* @__PURE__ */ new Map(),
|
|
818
|
+
_isBuildingSingleton: false
|
|
819
|
+
}, {
|
|
820
|
+
get: (target, prop) => {
|
|
821
|
+
if (prop.startsWith("get")) {
|
|
822
|
+
const serviceName = prop.slice(3);
|
|
823
|
+
if (target._map.has(serviceName)) {
|
|
824
|
+
const entry = target._map.get(serviceName);
|
|
825
|
+
switch (entry.lifetime) {
|
|
826
|
+
case "transient":
|
|
827
|
+
return () => {
|
|
828
|
+
if (target._isBuildingSingleton) {
|
|
829
|
+
throw new Error(`Cannot resolve transient service '${serviceName}' while building a singleton`);
|
|
830
|
+
}
|
|
831
|
+
return entry.factory(proxy);
|
|
832
|
+
};
|
|
833
|
+
case "scoped":
|
|
834
|
+
return () => {
|
|
835
|
+
if (target._isBuildingSingleton) {
|
|
836
|
+
throw new Error(`Cannot resolve scoped service '${serviceName}' while building a singleton`);
|
|
837
|
+
}
|
|
838
|
+
if (!target._scopedInstances.has(serviceName)) {
|
|
839
|
+
const instance = entry.factory(proxy);
|
|
840
|
+
target._scopedInstances.set(serviceName, instance);
|
|
841
|
+
}
|
|
842
|
+
return target._scopedInstances.get(serviceName);
|
|
843
|
+
};
|
|
844
|
+
case "singleton":
|
|
845
|
+
return () => {
|
|
846
|
+
if (!target._singletonInstances.has(serviceName)) {
|
|
847
|
+
target._isBuildingSingleton = true;
|
|
848
|
+
try {
|
|
849
|
+
const instance = entry.factory(proxy);
|
|
850
|
+
target._singletonInstances.set(serviceName, instance);
|
|
851
|
+
} finally {
|
|
852
|
+
target._isBuildingSingleton = false;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
return target._singletonInstances.get(serviceName);
|
|
856
|
+
};
|
|
857
|
+
default:
|
|
858
|
+
throw new Error(`Unsupported lifetime: ${entry.lifetime}`);
|
|
859
|
+
}
|
|
589
860
|
} else {
|
|
590
861
|
throw new Error(`Service not registered: ${serviceName}`);
|
|
591
862
|
}
|
|
592
863
|
}
|
|
593
|
-
|
|
864
|
+
throw new Error(`Property access denied by Proxy: ${String(prop)}`);
|
|
594
865
|
}
|
|
595
866
|
});
|
|
596
|
-
return
|
|
867
|
+
return proxy;
|
|
597
868
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
this.
|
|
869
|
+
}
|
|
870
|
+
class DIContainer extends DIContainerBase {
|
|
871
|
+
register(serviceNameCapitalizedLiteral, factory, lifetime) {
|
|
872
|
+
const entry = { factory, lifetime };
|
|
873
|
+
this._map.set(serviceNameCapitalizedLiteral, entry);
|
|
603
874
|
return this;
|
|
604
875
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
876
|
+
createTestClone() {
|
|
877
|
+
return new DIContainerTestClone(this);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
class DIContainerTestClone extends DIContainerBase {
|
|
881
|
+
constructor(original) {
|
|
882
|
+
super();
|
|
883
|
+
original["_map"].forEach((value, key) => {
|
|
884
|
+
this._map.set(key, {
|
|
885
|
+
factory: (_scope) => {
|
|
886
|
+
throw new Error(`Service registration not overridden: ${key}`);
|
|
887
|
+
},
|
|
888
|
+
lifetime: value.lifetime
|
|
889
|
+
});
|
|
890
|
+
});
|
|
891
|
+
}
|
|
892
|
+
override(serviceNameLiteral, factory) {
|
|
893
|
+
const registration = this._map.get(serviceNameLiteral);
|
|
610
894
|
if (!registration) {
|
|
611
|
-
throw new Error(`Service not registered: ${
|
|
895
|
+
throw new Error(`Service not registered: ${serviceNameLiteral}`);
|
|
612
896
|
}
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
const instance = registration.factory(this.proxy);
|
|
616
|
-
this.singletons.set(serviceName, instance);
|
|
617
|
-
}
|
|
618
|
-
return this.singletons.get(serviceName);
|
|
619
|
-
}
|
|
620
|
-
return registration.factory(this.proxy);
|
|
897
|
+
this._map.set(serviceNameLiteral, { factory, lifetime: registration.lifetime });
|
|
898
|
+
return this;
|
|
621
899
|
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
async function triggerEndpointDecoratorNoStaticTypeCheck(endpoint, decorator, requestObject, context) {
|
|
903
|
+
let badRequestResponse = null;
|
|
904
|
+
const headers = decoratorParseRequestDefinitionField(endpoint.definition, "headers", requestObject);
|
|
905
|
+
if (isHttpResponseObject(headers)) {
|
|
906
|
+
badRequestResponse = headers;
|
|
907
|
+
return badRequestResponse;
|
|
908
|
+
}
|
|
909
|
+
const query = decoratorParseRequestDefinitionField(endpoint.definition, "query", requestObject);
|
|
910
|
+
if (isHttpResponseObject(query)) {
|
|
911
|
+
badRequestResponse = query;
|
|
912
|
+
return badRequestResponse;
|
|
913
|
+
}
|
|
914
|
+
const body = decoratorParseRequestDefinitionField(endpoint.definition, "body", requestObject);
|
|
915
|
+
if (isHttpResponseObject(body)) {
|
|
916
|
+
badRequestResponse = body;
|
|
917
|
+
return badRequestResponse;
|
|
918
|
+
}
|
|
919
|
+
const path = endpoint.createPath(requestObject.pathParams);
|
|
920
|
+
return decorator.handle({
|
|
921
|
+
...requestObject,
|
|
922
|
+
method: endpoint.method,
|
|
923
|
+
genericPath: endpoint.genericPath,
|
|
924
|
+
path,
|
|
925
|
+
pathSegments: endpoint.pathSegments
|
|
926
|
+
}, context);
|
|
927
|
+
}
|
|
928
|
+
async function triggerMiddlewareDecoratorNoStaticTypeCheck(middlewareEntry, decorator, requestObject, context) {
|
|
929
|
+
let badRequestResponse = null;
|
|
930
|
+
const headers = decoratorParseRequestDefinitionField(middlewareEntry.middlewareSchemas, "headers", requestObject);
|
|
931
|
+
if (isHttpResponseObject(headers)) {
|
|
932
|
+
badRequestResponse = headers;
|
|
933
|
+
return badRequestResponse;
|
|
934
|
+
}
|
|
935
|
+
const query = decoratorParseRequestDefinitionField(middlewareEntry.middlewareSchemas, "query", requestObject);
|
|
936
|
+
if (isHttpResponseObject(query)) {
|
|
937
|
+
badRequestResponse = query;
|
|
938
|
+
return badRequestResponse;
|
|
939
|
+
}
|
|
940
|
+
const body = decoratorParseRequestDefinitionField(middlewareEntry.middlewareSchemas, "body", requestObject);
|
|
941
|
+
if (isHttpResponseObject(body)) {
|
|
942
|
+
badRequestResponse = body;
|
|
943
|
+
return badRequestResponse;
|
|
944
|
+
}
|
|
945
|
+
const path = middlewareEntry.createPath(requestObject.pathParams);
|
|
946
|
+
return decorator.handle({
|
|
947
|
+
...requestObject,
|
|
948
|
+
method: middlewareEntry.method,
|
|
949
|
+
// TODO: might be empty, as middleware can be registered with path only, without method
|
|
950
|
+
genericPath: middlewareEntry.genericPath,
|
|
951
|
+
path,
|
|
952
|
+
pathSegments: middlewareEntry.pathSegments
|
|
953
|
+
}, context);
|
|
954
|
+
}
|
|
955
|
+
function decoratorParseRequestDefinitionField(decoratorSchemas, key, requestObject) {
|
|
956
|
+
if (decoratorSchemas[key]) {
|
|
957
|
+
if (!(key in requestObject) || requestObject[key] === null || requestObject[key] === void 0) {
|
|
958
|
+
const result2 = decoratorSchemas[key].safeParse(requestObject[key]);
|
|
959
|
+
if (!result2.success) {
|
|
960
|
+
switch (decoratorSchemas[key].type) {
|
|
961
|
+
case "optional":
|
|
962
|
+
if (requestObject[key] === null) {
|
|
963
|
+
return void 0;
|
|
964
|
+
}
|
|
965
|
+
break;
|
|
966
|
+
case "nullable":
|
|
967
|
+
if (requestObject[key] === void 0) {
|
|
968
|
+
return null;
|
|
969
|
+
}
|
|
970
|
+
break;
|
|
646
971
|
}
|
|
647
|
-
return
|
|
972
|
+
return {
|
|
973
|
+
code: HttpStatusCode.BadRequest_400,
|
|
974
|
+
body: `'${key}' is required for this endpoint` + (key === "body" ? ", { 'Content-Type': 'application/json' } header might be missing" : "")
|
|
975
|
+
};
|
|
648
976
|
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
977
|
+
return result2.data;
|
|
978
|
+
}
|
|
979
|
+
const result = decoratorSchemas[key].safeParse(requestObject[key]);
|
|
980
|
+
if (!result.success) {
|
|
981
|
+
return {
|
|
982
|
+
code: HttpStatusCode.BadRequest_400,
|
|
983
|
+
body: result.error.issues
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
return result.data;
|
|
654
987
|
}
|
|
988
|
+
return null;
|
|
655
989
|
}
|
|
656
990
|
|
|
657
|
-
function createInProcApiClient(contract, testContainer, registry) {
|
|
658
|
-
const
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
991
|
+
function createInProcApiClient(contract, testContainer, registry, options) {
|
|
992
|
+
const mwHandlers = [];
|
|
993
|
+
const mwReg = registry._middlewareRegistry;
|
|
994
|
+
const mwNdx = 0;
|
|
995
|
+
for (const mwEntry of mwReg.list) {
|
|
996
|
+
if (!options?.filterMiddleware) {
|
|
997
|
+
addMiddlewareDecorators(mwHandlers, mwEntry);
|
|
998
|
+
mwHandlers.push(mwEntry);
|
|
999
|
+
continue;
|
|
662
1000
|
}
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
return;
|
|
1001
|
+
const isIncluded = options.filterMiddleware(mwEntry.genericPath, mwNdx);
|
|
1002
|
+
if (!isIncluded) {
|
|
1003
|
+
continue;
|
|
667
1004
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
}
|
|
1005
|
+
addMiddlewareDecorators(mwHandlers, mwEntry);
|
|
1006
|
+
mwHandlers.push(mwEntry);
|
|
1007
|
+
}
|
|
671
1008
|
const client = createClient(contract, async (input) => {
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
1009
|
+
if (options?.enhanceRequest) {
|
|
1010
|
+
input = options.enhanceRequest(input);
|
|
1011
|
+
}
|
|
1012
|
+
const diScope = testContainer.createScope();
|
|
1013
|
+
const allHandlerEntries = [...mwHandlers];
|
|
1014
|
+
const endpointHandlerEntry = route(registry, `${input.method} ${input.genericPath}`);
|
|
1015
|
+
if (!endpointHandlerEntry.handler) {
|
|
1016
|
+
throw new Error(`No handler registered for ${input.method} ${input.genericPath}`);
|
|
1017
|
+
}
|
|
1018
|
+
endpointHandlerEntry.decoratorFactories.forEach((decoratorFactory) => {
|
|
1019
|
+
allHandlerEntries.push({
|
|
1020
|
+
genericPath: endpointHandlerEntry.genericPath,
|
|
1021
|
+
triggerNoStaticTypeCheck: async (diScope2, requestObject, context) => {
|
|
1022
|
+
const decorator = decoratorFactory(diScope2);
|
|
1023
|
+
return await triggerEndpointDecoratorNoStaticTypeCheck(
|
|
1024
|
+
endpointHandlerEntry.methodEndpoint,
|
|
1025
|
+
decorator,
|
|
1026
|
+
requestObject,
|
|
1027
|
+
context
|
|
1028
|
+
);
|
|
1029
|
+
}
|
|
1030
|
+
});
|
|
678
1031
|
});
|
|
679
|
-
|
|
1032
|
+
if (options?.mockEndpointResponse) {
|
|
1033
|
+
const mockResponse = options.mockEndpointResponse(input.genericPath, input.method, diScope);
|
|
1034
|
+
if (mockResponse) {
|
|
1035
|
+
allHandlerEntries.push({
|
|
1036
|
+
genericPath: endpointHandlerEntry.genericPath,
|
|
1037
|
+
triggerNoStaticTypeCheck: async (_diScope, _requestObject, _next) => {
|
|
1038
|
+
return mockResponse;
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
} else {
|
|
1042
|
+
allHandlerEntries.push(endpointHandlerEntry);
|
|
1043
|
+
}
|
|
1044
|
+
} else {
|
|
1045
|
+
allHandlerEntries.push(endpointHandlerEntry);
|
|
1046
|
+
}
|
|
1047
|
+
const response = await execHandlerChain(diScope, allHandlerEntries, input);
|
|
1048
|
+
if (!response) {
|
|
1049
|
+
throw new Error(`No response from ${input.method} ${input.genericPath}`);
|
|
1050
|
+
}
|
|
1051
|
+
return response;
|
|
680
1052
|
});
|
|
681
1053
|
return client;
|
|
682
1054
|
}
|
|
1055
|
+
function addMiddlewareDecorators(mwHandlers, mwEntry) {
|
|
1056
|
+
mwEntry.decoratorFactories.forEach((decoratorFactory) => {
|
|
1057
|
+
mwHandlers.push({
|
|
1058
|
+
genericPath: mwEntry.genericPath,
|
|
1059
|
+
triggerNoStaticTypeCheck: async (diScope, requestObject, context) => {
|
|
1060
|
+
const decorator = decoratorFactory(diScope);
|
|
1061
|
+
return await triggerMiddlewareDecoratorNoStaticTypeCheck(
|
|
1062
|
+
mwEntry,
|
|
1063
|
+
decorator,
|
|
1064
|
+
requestObject,
|
|
1065
|
+
context
|
|
1066
|
+
);
|
|
1067
|
+
}
|
|
1068
|
+
});
|
|
1069
|
+
});
|
|
1070
|
+
}
|
|
683
1071
|
|
|
684
|
-
export { ApiClient, ApiContract, ApiHandlersRegistry, DIContainer, HttpMethodEndpoint, HttpMethodEndpointResponse, HttpStatusCode, MethodEndpointHandlerRegistryEntry, MiddlewareHandlersRegistry, MiddlewareHandlersRegistryEntry, MiddlewareHandlersRegistryEntryInternal, apiContract, createClient, createInProcApiClient, createRegistry, endpoint, flatListAllRegistryEntries, isHttpResponseObject, isHttpStatusCode, middleware, partial, partialPathString, register, response, route };
|
|
1072
|
+
export { ApiClient, ApiContract, ApiHandlersRegistry, DIContainer, DIContainerBase, DIContainerTestClone, HttpMethodEndpoint, HttpMethodEndpointResponse, HttpStatusCode, MethodEndpointHandlerRegistryEntry, MiddlewareHandlersRegistry, MiddlewareHandlersRegistryEntry, MiddlewareHandlersRegistryEntryInternal, apiContract, createClient, createInProcApiClient, createRegistry, endpoint, execHandlerChain, flatListAllRegistryEntries, isHttpResponseObject, isHttpStatusCode, middleware, partial, partialPathString, register, response, route, triggerEndpointDecoratorNoStaticTypeCheck, triggerMiddlewareDecoratorNoStaticTypeCheck };
|