@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.d.cts
CHANGED
|
@@ -17,6 +17,7 @@ declare enum HttpStatusCode {
|
|
|
17
17
|
Forbidden_403 = 403,
|
|
18
18
|
NotFound_404 = 404,
|
|
19
19
|
Conflict_409 = 409,
|
|
20
|
+
UnprocessableEntity_422 = 422,
|
|
20
21
|
InternalServerError_500 = 500,
|
|
21
22
|
NotImplemented_501 = 501,
|
|
22
23
|
BadGateway_502 = 502,
|
|
@@ -61,6 +62,7 @@ declare class HttpMethodEndpoint<const TDef extends IHttpMethodEndpointDefinitio
|
|
|
61
62
|
get pathSegments(): readonly string[];
|
|
62
63
|
private _cachedGenericPath;
|
|
63
64
|
get genericPath(): string;
|
|
65
|
+
createPath(pathParams: Record<string, string>): string;
|
|
64
66
|
private _method;
|
|
65
67
|
get method(): HttpMethod;
|
|
66
68
|
get lowerCasedMethod(): LowerCasedHttpMethod;
|
|
@@ -107,7 +109,7 @@ type ExtractConcatenatedParamNamesFromMethodFirstPath<TPath extends string> = TP
|
|
|
107
109
|
type ExtractConcatenatedParamNamesFromPathSegments<TPath extends string> = TPath extends `/${infer Segment}/${infer Rest}` ? Segment extends `:${infer ParamName}` ? `:${ParamName}${ExtractConcatenatedParamNamesFromPathSegments<`/${Rest}`> extends `:${infer RestParams}` ? `:${RestParams}` : ""}` : ExtractConcatenatedParamNamesFromPathSegments<`/${Rest}`> : TPath extends `/${infer Segment}` ? Segment extends `:${infer ParamName}` ? `:${ParamName}` : "" : "";
|
|
108
110
|
type ExtractConcatenatedParamNamesFromPath<TPath extends string> = TPath extends `${string} ${string}` ? ExtractConcatenatedParamNamesFromMethodFirstPath<TPath> : TPath extends `/${string}` ? ExtractConcatenatedParamNamesFromPathSegments<TPath> : never;
|
|
109
111
|
|
|
110
|
-
type HttpMethodEndpointHandlerInput<TEndpointDefinition extends IHttpMethodEndpointDefinition, TPathParams extends string
|
|
112
|
+
type HttpMethodEndpointHandlerInput<TEndpointDefinition extends IHttpMethodEndpointDefinition, TPathParams extends string> = {
|
|
111
113
|
method: HttpMethod;
|
|
112
114
|
pathSegments: readonly string[];
|
|
113
115
|
path: string;
|
|
@@ -116,7 +118,6 @@ type HttpMethodEndpointHandlerInput<TEndpointDefinition extends IHttpMethodEndpo
|
|
|
116
118
|
pathParams: TypedPathParams<TPathParams>;
|
|
117
119
|
query: TEndpointDefinition['query'] extends z$1.ZodType ? z$1.output<TEndpointDefinition['query']> : null;
|
|
118
120
|
body: TEndpointDefinition['body'] extends z$1.ZodType ? z$1.output<TEndpointDefinition['body']> : null;
|
|
119
|
-
injected: Readonly<TInjected>;
|
|
120
121
|
};
|
|
121
122
|
type ClientHttpMethodEndpointHandlerInput = {
|
|
122
123
|
method: HttpMethod;
|
|
@@ -125,8 +126,14 @@ type ClientHttpMethodEndpointHandlerInput = {
|
|
|
125
126
|
genericPath: string;
|
|
126
127
|
headers: Record<string, string>;
|
|
127
128
|
pathParams: Record<string, string>;
|
|
128
|
-
query
|
|
129
|
-
body
|
|
129
|
+
query: any;
|
|
130
|
+
body: any;
|
|
131
|
+
};
|
|
132
|
+
type HttpRequestObject = {
|
|
133
|
+
headers: Record<string, string>;
|
|
134
|
+
pathParams: Record<string, string>;
|
|
135
|
+
query: Record<string, string>;
|
|
136
|
+
body: object;
|
|
130
137
|
};
|
|
131
138
|
|
|
132
139
|
type HttpMethodEndpointHandlerOutput<TEndpointDefinition extends IHttpMethodEndpointDefinition> = {
|
|
@@ -166,102 +173,88 @@ type HttpResponseObject = {
|
|
|
166
173
|
headers?: any;
|
|
167
174
|
body?: any;
|
|
168
175
|
};
|
|
176
|
+
type BadRequestValidationErrorResponse = {
|
|
177
|
+
code: HttpStatusCode.BadRequest_400;
|
|
178
|
+
body: z$1.core.$ZodIssue[] | string;
|
|
179
|
+
};
|
|
169
180
|
declare function isHttpResponseObject(obj: any): obj is HttpResponseObject;
|
|
170
181
|
|
|
171
|
-
|
|
182
|
+
declare const __overlap__error__: unique symbol;
|
|
183
|
+
type EndpointHandlerContextOverlapGuard<TInjected> = [
|
|
184
|
+
Extract<keyof TInjected, keyof EndpointHandlerContext<unknown>>
|
|
185
|
+
] extends [never] ? {} : {
|
|
186
|
+
[__overlap__error__]: `❌ ERROR: property "${Extract<keyof TInjected & keyof EndpointHandlerContext<unknown>, string>}" already part of Endpoint Context. Choose a different property name to avoid conflict.`;
|
|
187
|
+
};
|
|
188
|
+
type MiddlewareHandlerContextOverlapGuard<TInjected> = [
|
|
189
|
+
Extract<keyof TInjected, keyof MiddlewareHandlerContext<unknown>>
|
|
190
|
+
] extends [never] ? {} : {
|
|
191
|
+
[__overlap__error__]: `❌ ERROR: property "${Extract<keyof TInjected & keyof MiddlewareHandlerContext<unknown>, string>}" already part of Middleware Context. Choose a different property name to avoid conflict.`;
|
|
192
|
+
};
|
|
193
|
+
type MiddlewareHandlerContext<TInjected = {}> = {
|
|
194
|
+
next: () => Promise<void>;
|
|
195
|
+
originalRequest: any;
|
|
196
|
+
} & Readonly<TInjected>;
|
|
197
|
+
type EndpointHandlerContext<TInjected = {}> = {
|
|
198
|
+
originalRequest: any;
|
|
199
|
+
} & Readonly<TInjected>;
|
|
200
|
+
type DecoratorHandlerContext = {
|
|
201
|
+
next: () => Promise<void>;
|
|
202
|
+
originalRequest: any;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
type HttpMethodEndpointHandler<TDef extends IHttpMethodEndpointDefinition, TPathParams extends string, TInjected> = (input: HttpMethodEndpointHandlerInput<TDef, TPathParams>, context: EndpointHandlerContext<TInjected>) => Promise<HttpMethodEndpointHandlerOutput<TDef>>;
|
|
172
206
|
type ClientHttpMethodEndpointHandler = (input: ClientHttpMethodEndpointHandlerInput) => Promise<ClientHttpMethodEndpointHandlerOutput>;
|
|
173
207
|
|
|
174
|
-
type StringLiteral<
|
|
175
|
-
type
|
|
208
|
+
type StringLiteral<T extends string> = string extends T ? never : T;
|
|
209
|
+
type CapitalizedStringLiteral<T extends string> = string extends T ? never : T extends `${Uppercase<infer F>}${infer _}` ? F extends Lowercase<F> ? never : T : `❌ ERROR: Must start with uppercase letter`;
|
|
176
210
|
type DILifetime = 'singleton' | 'transient' | 'scoped';
|
|
177
|
-
type
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
*/
|
|
181
|
-
type DIScope<R extends DIServiceRegistry> = {
|
|
182
|
-
[K in keyof R as `get${string & K}`]: () => R[K];
|
|
211
|
+
type DIRegistryEntry<T> = {
|
|
212
|
+
factory: (scope: any) => T;
|
|
213
|
+
lifetime: DILifetime;
|
|
183
214
|
};
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
* it adds a method named `getK` that returns an instance of the corresponding service type.
|
|
188
|
-
*
|
|
189
|
-
* For example, if R is `{ LoggerService: LoggerService }`, this type will be:
|
|
190
|
-
* { getLoggerService: () => LoggerService }
|
|
191
|
-
*/
|
|
192
|
-
type DITypedContainer<R extends DIServiceRegistry> = DIContainer<R> & {
|
|
193
|
-
[K in keyof R as `get${string & K}`]: () => R[K];
|
|
215
|
+
type DIRegistry = Record<string, DIRegistryEntry<any>>;
|
|
216
|
+
type DIScope<R extends DIRegistry> = {
|
|
217
|
+
[K in keyof R as `get${string & K}`]: () => R[K] extends DIRegistryEntry<infer T> ? T : never;
|
|
194
218
|
};
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
declare class DIContainer<R extends DIServiceRegistry = {}> {
|
|
199
|
-
private registry;
|
|
200
|
-
private singletons;
|
|
201
|
-
private proxy;
|
|
202
|
-
/**
|
|
203
|
-
* The constructor returns a Proxy. This is the runtime magic that intercepts
|
|
204
|
-
* calls to methods like `getLoggerService()`. It parses the method name,
|
|
205
|
-
* finds the corresponding service class in the registry, and resolves it.
|
|
206
|
-
*/
|
|
207
|
-
constructor();
|
|
208
|
-
/**
|
|
209
|
-
* Registers a service with explicit service name (fully type-safe).
|
|
210
|
-
*/
|
|
211
|
-
register<T, N extends string>(serviceNameLiteral: StringLiteral<N>, factory: (container: DITypedContainer<R>) => T, lifetime?: DILifetime): DITypedContainer<R & Record<N, T>>;
|
|
212
|
-
/**
|
|
213
|
-
* Resolves a service by service name.
|
|
214
|
-
*/
|
|
215
|
-
private resolveByName;
|
|
216
|
-
/**
|
|
217
|
-
* Creates a scoped container with typed method access to services.
|
|
218
|
-
*/
|
|
219
|
+
declare class DIContainerBase<R extends DIRegistry> {
|
|
220
|
+
protected _map: Map<string, DIRegistryEntry<any>>;
|
|
221
|
+
protected _singletonInstances: Map<string, any>;
|
|
219
222
|
createScope(): DIScope<R>;
|
|
220
|
-
|
|
223
|
+
}
|
|
224
|
+
declare class DIContainer<R extends DIRegistry = {}> extends DIContainerBase<R> {
|
|
225
|
+
register<K extends string, T>(serviceNameCapitalizedLiteral: CapitalizedStringLiteral<K>, factory: (scope: DIScope<R>) => T, lifetime: DILifetime): DIContainer<R & Record<K, DIRegistryEntry<T>>>;
|
|
226
|
+
createTestClone(): DIContainerTestClone<R, this>;
|
|
227
|
+
}
|
|
228
|
+
declare class DIContainerTestClone<R extends DIRegistry, TDIContainer extends DIContainer<R>> extends DIContainerBase<R> {
|
|
229
|
+
constructor(original: TDIContainer);
|
|
230
|
+
override<K extends keyof R & string>(serviceNameLiteral: K, factory: (scope: DIScope<R>) => R[K] extends DIRegistryEntry<infer T> ? T : never): this;
|
|
221
231
|
}
|
|
222
232
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
private _methodEndpoint;
|
|
227
|
-
get methodEndpoint(): HttpMethodEndpoint<TDef>;
|
|
228
|
-
private _dicontainer;
|
|
229
|
-
get dicontainer(): TDIContainer;
|
|
230
|
-
constructor(methodEndpoint: HttpMethodEndpoint<TDef>, dicontainer: TDIContainer);
|
|
231
|
-
private _handler;
|
|
232
|
-
get handler(): HttpMethodEndpointHandler<TDef, TPathParams, TInjected> | null;
|
|
233
|
-
register(handler: HttpMethodEndpointHandler<TDef, TPathParams, TInjected>): void;
|
|
234
|
-
private _onHandlerRegisteredCallback;
|
|
235
|
-
_onHandlerRegistered(callback: OnHandlerRegisteredCallback<TDef, TDIContainer, TPathParams>): void;
|
|
236
|
-
prepare(callback: PrepareRegistryEntryCallback<TDef, TDIContainer, TPathParams>): this;
|
|
237
|
-
private _injection;
|
|
238
|
-
get injection(): any;
|
|
239
|
-
inject<TNewInjected>(injection: (dicontainer: TDIContainer) => TNewInjected): MethodEndpointHandlerRegistryEntry<TDef, TDIContainer, TPathParams, TNewInjected>;
|
|
240
|
-
trigger(data: {
|
|
241
|
-
headers: Record<string, string>;
|
|
242
|
-
pathParams: Record<string, string>;
|
|
243
|
-
query: object;
|
|
244
|
-
body: object;
|
|
245
|
-
}): Promise<any>;
|
|
233
|
+
interface ICanTriggerAsync {
|
|
234
|
+
triggerNoStaticTypeCheck(diScope: DIScope<any>, requestObject: HttpRequestObject, context: any): Promise<any>;
|
|
235
|
+
get genericPath(): string;
|
|
246
236
|
}
|
|
247
237
|
|
|
248
|
-
type
|
|
238
|
+
type MiddlewareHandlerSchemas = {
|
|
249
239
|
headers?: z$1.ZodType;
|
|
250
240
|
query?: z$1.ZodType;
|
|
251
241
|
body?: z$1.ZodType;
|
|
242
|
+
responses: HttpMethodEndpointResponses;
|
|
252
243
|
};
|
|
253
|
-
type MiddlewareHandlerInput<TPathParams extends string,
|
|
244
|
+
type MiddlewareHandlerInput<TPathParams extends string, TMiddlewareSchemas extends MiddlewareHandlerSchemas> = {
|
|
254
245
|
method: HttpMethod;
|
|
255
246
|
pathSegments: readonly string[];
|
|
256
247
|
path: string;
|
|
257
248
|
genericPath: string;
|
|
258
|
-
headers:
|
|
249
|
+
headers: TMiddlewareSchemas['headers'] extends z$1.ZodType ? z$1.output<TMiddlewareSchemas['headers']> : Record<string, string>;
|
|
259
250
|
pathParams: TypedPathParams<TPathParams>;
|
|
260
|
-
query:
|
|
261
|
-
body:
|
|
262
|
-
injected: Readonly<TInjected>;
|
|
251
|
+
query: TMiddlewareSchemas['query'] extends z$1.ZodType ? z$1.output<TMiddlewareSchemas['query']> : null;
|
|
252
|
+
body: TMiddlewareSchemas['body'] extends z$1.ZodType ? z$1.output<TMiddlewareSchemas['body']> : null;
|
|
263
253
|
};
|
|
264
|
-
type
|
|
254
|
+
type MiddlewareHandlerOutput<TMiddlewareSchemas extends MiddlewareHandlerSchemas> = void | {
|
|
255
|
+
[THttpStatusCode in keyof TMiddlewareSchemas['responses'] & HttpStatusCode]: TMiddlewareSchemas['responses'][THttpStatusCode] extends HttpMethodEndpointResponse<THttpStatusCode, infer TRespDef> ? CreateHandlerOutput<THttpStatusCode, TRespDef> : never;
|
|
256
|
+
}[keyof TMiddlewareSchemas['responses'] & HttpStatusCode];
|
|
257
|
+
type MiddlewareHandlerInputInternal = {
|
|
265
258
|
method: HttpMethod;
|
|
266
259
|
pathSegments: readonly string[];
|
|
267
260
|
path: string;
|
|
@@ -270,29 +263,37 @@ type MiddlewareHandlerInputInternal<TInjected> = {
|
|
|
270
263
|
pathParams: Record<string, string>;
|
|
271
264
|
query: Record<string, any> | null;
|
|
272
265
|
body: Record<string, any> | null;
|
|
273
|
-
injected: Readonly<TInjected>;
|
|
274
266
|
};
|
|
275
|
-
type MiddlewareHandler<TPathParams extends string,
|
|
276
|
-
type MiddlewareHandlerInternal<TInjected> = (input: MiddlewareHandlerInputInternal
|
|
267
|
+
type MiddlewareHandler<TPathParams extends string, TMiddlewareSchemas extends MiddlewareHandlerSchemas, TInjected> = (input: MiddlewareHandlerInput<TPathParams, TMiddlewareSchemas>, context: MiddlewareHandlerContext<TInjected>) => Promise<MiddlewareHandlerOutput<TMiddlewareSchemas>>;
|
|
268
|
+
type MiddlewareHandlerInternal<TInjected> = (input: MiddlewareHandlerInputInternal, context: MiddlewareHandlerContext<TInjected>) => Promise<HttpResponseObject | void>;
|
|
277
269
|
declare function middleware<TApiDef extends IApiContractDefinition & ValidateApiContractDefinition<TApiDef>, TDIContainer extends DIContainer, TPathParams extends string, const TPath extends MiddlewarePath<TApiDef>, TInjected = {}>(apiReg: ApiHandlersRegistry<TApiDef, TDIContainer, TPathParams>, path: TPath): MiddlewareHandlersRegistryEntry<TApiDef, TDIContainer, TPathParams, TPath, TInjected>;
|
|
278
270
|
type MiddlewarePath<TDef, BasePath extends string = ""> = (BasePath extends "" ? "" : never) | {
|
|
279
271
|
[K in keyof TDef & string]: TDef[K] extends HttpMethodEndpoint<infer _TEndpointDef> ? `${K} ${BasePath}` : TDef[K] extends object ? `${BasePath}/${K}` | MiddlewarePath<TDef[K], `${BasePath}/${K}`> : never;
|
|
280
272
|
}[keyof TDef & string];
|
|
281
|
-
declare class MiddlewareHandlersRegistryEntryInternal<TDIContainer extends DIContainer, TInjected> {
|
|
273
|
+
declare class MiddlewareHandlersRegistryEntryInternal<TDIContainer extends DIContainer, TInjected> implements ICanTriggerAsync {
|
|
282
274
|
private readonly _dicontainer;
|
|
275
|
+
get dicontainer(): TDIContainer;
|
|
283
276
|
private readonly _middlewareGenericPath;
|
|
284
277
|
get genericPath(): string;
|
|
285
|
-
private
|
|
286
|
-
|
|
278
|
+
private readonly _middlewarePathSegments;
|
|
279
|
+
get pathSegments(): readonly string[];
|
|
280
|
+
private readonly _middlewareMethod;
|
|
281
|
+
get method(): string;
|
|
282
|
+
private readonly _middlewareSchemas;
|
|
283
|
+
get middlewareSchemas(): MiddlewareHandlerSchemas;
|
|
287
284
|
private readonly _handler;
|
|
288
|
-
constructor(diContainer: TDIContainer, middlewarePath: string,
|
|
285
|
+
constructor(diContainer: TDIContainer, middlewarePath: string, middlewareSchemas: MiddlewareHandlerSchemas, decoratorFactories: ((scope: DIScope<any>) => IEndpointHandlerDecorator<any>)[], injection: (dicontainer: TDIContainer) => TInjected, handler: MiddlewareHandlerInternal<TInjected>);
|
|
286
|
+
private readonly _decoratorFactories;
|
|
287
|
+
get decoratorFactories(): ((scope: DIScope<any>) => IEndpointHandlerDecorator<any>)[];
|
|
289
288
|
private _injection;
|
|
290
|
-
trigger(
|
|
291
|
-
headers: Record<string, string>;
|
|
292
|
-
pathParams:
|
|
293
|
-
query:
|
|
294
|
-
body:
|
|
295
|
-
},
|
|
289
|
+
trigger<TPathParams extends string, const TMiddlewareSchemas extends MiddlewareHandlerSchemas>(diScope: ReturnType<TDIContainer['createScope']>, requestObject: {
|
|
290
|
+
headers: TMiddlewareSchemas['headers'] extends z$1.ZodType ? z$1.output<TMiddlewareSchemas['headers']> : Record<string, string>;
|
|
291
|
+
pathParams: TypedPathParams<TPathParams>;
|
|
292
|
+
query: TMiddlewareSchemas['query'] extends z$1.ZodType ? z$1.output<TMiddlewareSchemas['query']> : null;
|
|
293
|
+
body: TMiddlewareSchemas['body'] extends z$1.ZodType ? z$1.output<TMiddlewareSchemas['body']> : null;
|
|
294
|
+
}, context: MiddlewareHandlerContext<any>): Promise<any>;
|
|
295
|
+
triggerNoStaticTypeCheck(diScope: DIScope<any>, requestObject: HttpRequestObject, context: MiddlewareHandlerContext<any>): Promise<any>;
|
|
296
|
+
createPath(pathParams: Record<string, string>): string;
|
|
296
297
|
}
|
|
297
298
|
declare class MiddlewareHandlersRegistryEntry<TApiDef extends IApiContractDefinition & ValidateApiContractDefinition<TApiDef>, TDIContainer extends DIContainer, TPathParams extends string, const TPath extends MiddlewarePath<TApiDef>, TInjected> {
|
|
298
299
|
private readonly _registry;
|
|
@@ -300,18 +301,167 @@ declare class MiddlewareHandlersRegistryEntry<TApiDef extends IApiContractDefini
|
|
|
300
301
|
constructor(registry: MiddlewareHandlersRegistry<TDIContainer>, path: TPath);
|
|
301
302
|
private _injection;
|
|
302
303
|
get injection(): any;
|
|
303
|
-
inject<TNewInjected>(injection: (
|
|
304
|
-
register<const
|
|
304
|
+
inject<TNewInjected>(injection: (diScope: ReturnType<TDIContainer['createScope']>) => TNewInjected & MiddlewareHandlerContextOverlapGuard<TNewInjected>): MiddlewareHandlersRegistryEntry<TApiDef, TDIContainer, TPathParams, TPath, TNewInjected>;
|
|
305
|
+
register<const TMiddlewareSchemas extends MiddlewareHandlerSchemas>(middlewareSchemas: TMiddlewareSchemas, handler: MiddlewareHandler<`${TPathParams}${ExtractConcatenatedParamNamesFromPath<TPath>}`, TMiddlewareSchemas, TInjected>): void;
|
|
306
|
+
private readonly _decoratorFactories;
|
|
307
|
+
get decoratorFactories(): ((scope: DIScope<any>) => IEndpointHandlerDecorator<any>)[];
|
|
308
|
+
/**
|
|
309
|
+
*
|
|
310
|
+
* @param decoratorFactory must be a function that takes exactly the DI scope type and returns an instance of a class that implements IEndpointHandlerDecorator
|
|
311
|
+
* @returns this
|
|
312
|
+
*
|
|
313
|
+
* Initially, the method was defined as:
|
|
314
|
+
* ```ts
|
|
315
|
+
* decorate<
|
|
316
|
+
* TDecoratorSchemas extends IDecoratorHandlerSchemas,
|
|
317
|
+
* TDecorator extends IEndpointHandlerDecorator<TDecoratorSchemas>
|
|
318
|
+
* > (
|
|
319
|
+
* decoratorFactory: IEndpointHandlerDecoratorFactory<TDecoratorSchemas, TDIContainer, TDecorator>
|
|
320
|
+
* ): this {
|
|
321
|
+
* this._decoratorFactories.push(decoratorFactory);
|
|
322
|
+
* return this;
|
|
323
|
+
* }
|
|
324
|
+
* ```
|
|
325
|
+
*
|
|
326
|
+
* and the type IEndpointHandlerDecoratorFactory was defined as:
|
|
327
|
+
* ```ts
|
|
328
|
+
* type IEndpointHandlerDecoratorFactory<
|
|
329
|
+
* TDecoratorSchemas extends IDecoratorHandlerSchemas,
|
|
330
|
+
* TDIContainer extends DIContainer,
|
|
331
|
+
* TDecorator extends IEndpointHandlerDecorator<TDecoratorSchemas>
|
|
332
|
+
* > = (diScope: ReturnType<TDIContainer['createScope']>) => TDecorator;
|
|
333
|
+
* ```
|
|
334
|
+
*
|
|
335
|
+
* However, TypeScript was incorrectly inferring the types when using the 'decorate' method.
|
|
336
|
+
* The end developer would have had to explicitly provide the generic types, which is not ideal.
|
|
337
|
+
*
|
|
338
|
+
* With the current definition, TypeScript can infer the types from the decoratorFactory parameter,
|
|
339
|
+
* making it easier to use.
|
|
340
|
+
*/
|
|
341
|
+
decorate<TDecorator extends {
|
|
342
|
+
handle(input: any, context: any): Promise<any>;
|
|
343
|
+
}>(decoratorFactory: ((diScope: ReturnType<TDIContainer['createScope']>) => TDecorator) extends infer TExpected ? TDecorator extends IEndpointHandlerDecorator<infer _TSchemas> ? TExpected : "❌ ERROR: The decoratorFactory must return an instance of a class that implements IEndpointHandlerDecorator" : never): this;
|
|
344
|
+
decorateWith<TDecorator extends {
|
|
345
|
+
handle(input: any, context: any): Promise<any>;
|
|
346
|
+
}>(decoratorStaticMethodFactory: ({
|
|
347
|
+
new (...args: any[]): TDecorator;
|
|
348
|
+
create(diScope: ReturnType<TDIContainer['createScope']>): TDecorator;
|
|
349
|
+
} extends infer TExpected ? TDecorator extends IEndpointHandlerDecorator<infer _TSchemas> ? TExpected : "❌ ERROR: The decoratorStaticMethodFactory must be a class that implements IEndpointHandlerDecorator and has a static 'create' method that takes exactly the DI scope type and returns an instance of the class" : never)): this;
|
|
305
350
|
}
|
|
306
351
|
type OnMiddlewareHandlerRegisteredCallback<TDIContainer extends DIContainer, TInjected> = (entry: MiddlewareHandlersRegistryEntryInternal<TDIContainer, TInjected>) => void;
|
|
307
352
|
declare class MiddlewareHandlersRegistry<TDIContainer extends DIContainer> {
|
|
308
353
|
readonly dicontainer: TDIContainer;
|
|
309
354
|
constructor(dicontainer: TDIContainer, callback: OnMiddlewareHandlerRegisteredCallback<TDIContainer, unknown>);
|
|
355
|
+
private readonly _list;
|
|
356
|
+
get list(): Readonly<MiddlewareHandlersRegistryEntryInternal<TDIContainer, unknown>[]>;
|
|
310
357
|
register<TInjected>(entry: MiddlewareHandlersRegistryEntryInternal<TDIContainer, TInjected>): void;
|
|
311
358
|
private _onHandlerRegisteredCallback;
|
|
312
359
|
_onHandlerRegistered(callback: OnMiddlewareHandlerRegisteredCallback<TDIContainer, unknown>): void;
|
|
313
360
|
}
|
|
314
361
|
|
|
362
|
+
interface IDecoratorHandlerSchemas {
|
|
363
|
+
headers?: z.ZodType;
|
|
364
|
+
query?: z.ZodType;
|
|
365
|
+
body?: z.ZodType;
|
|
366
|
+
responses: HttpMethodEndpointResponses;
|
|
367
|
+
}
|
|
368
|
+
type DecoratorHandlerInput<TDecoratorSchemas extends IDecoratorHandlerSchemas> = {
|
|
369
|
+
method: HttpMethod;
|
|
370
|
+
pathSegments: readonly string[];
|
|
371
|
+
path: string;
|
|
372
|
+
genericPath: string;
|
|
373
|
+
headers: TDecoratorSchemas['headers'] extends z.ZodType ? z.output<TDecoratorSchemas['headers']> : Record<string, string>;
|
|
374
|
+
pathParams: Record<string, string>;
|
|
375
|
+
query: TDecoratorSchemas['query'] extends z.ZodType ? z.output<TDecoratorSchemas['query']> : null;
|
|
376
|
+
body: TDecoratorSchemas['body'] extends z.ZodType ? z.output<TDecoratorSchemas['body']> : null;
|
|
377
|
+
};
|
|
378
|
+
type DecoratorHandlerOutput<TDecoratorSchemas extends IDecoratorHandlerSchemas> = void | {
|
|
379
|
+
[THttpStatusCode in keyof TDecoratorSchemas['responses'] & HttpStatusCode]: TDecoratorSchemas['responses'][THttpStatusCode] extends HttpMethodEndpointResponse<THttpStatusCode, infer TRespDef> ? CreateHandlerOutput<THttpStatusCode, TRespDef> : never;
|
|
380
|
+
}[keyof TDecoratorSchemas['responses'] & HttpStatusCode];
|
|
381
|
+
interface IEndpointHandlerDecorator<TDecoratorSchemas extends IDecoratorHandlerSchemas> {
|
|
382
|
+
handle(input: DecoratorHandlerInput<TDecoratorSchemas>, context: DecoratorHandlerContext): Promise<DecoratorHandlerOutput<TDecoratorSchemas>>;
|
|
383
|
+
}
|
|
384
|
+
type EndpointHandlerDecoratorFactory<TDecoratorSchemas extends IDecoratorHandlerSchemas, TDIContainer extends DIContainer, TDecorator extends IEndpointHandlerDecorator<TDecoratorSchemas>> = (diScope: ReturnType<TDIContainer['createScope']>) => TDecorator;
|
|
385
|
+
declare function triggerEndpointDecoratorNoStaticTypeCheck(endpoint: HttpMethodEndpoint<any>, decorator: IEndpointHandlerDecorator<any>, requestObject: HttpRequestObject, context: DecoratorHandlerContext): Promise<void | HttpResponseObject>;
|
|
386
|
+
declare function triggerMiddlewareDecoratorNoStaticTypeCheck(middlewareEntry: MiddlewareHandlersRegistryEntryInternal<any, unknown>, decorator: IEndpointHandlerDecorator<any>, requestObject: HttpRequestObject, context: DecoratorHandlerContext): Promise<void | HttpResponseObject>;
|
|
387
|
+
|
|
388
|
+
type PrepareRegistryEntryCallback<TDef extends IHttpMethodEndpointDefinition & ValidateHttpMethodEndpointDefinition<TDef>, TDIContainer extends DIContainer, TPathParams extends string> = (entry: MethodEndpointHandlerRegistryEntry<TDef, TDIContainer, TPathParams, any>) => void;
|
|
389
|
+
type OnHandlerRegisteredCallback<TDef extends IHttpMethodEndpointDefinition & ValidateHttpMethodEndpointDefinition<TDef>, TDIContainer extends DIContainer, TPathParams extends string> = (entry: MethodEndpointHandlerRegistryEntry<TDef, TDIContainer, TPathParams, any>) => void;
|
|
390
|
+
declare class MethodEndpointHandlerRegistryEntry<TDef extends IHttpMethodEndpointDefinition & ValidateHttpMethodEndpointDefinition<TDef>, TDIContainer extends DIContainer, TPathParams extends string, TInjected = {}> implements ICanTriggerAsync {
|
|
391
|
+
private _methodEndpoint;
|
|
392
|
+
get methodEndpoint(): HttpMethodEndpoint<TDef>;
|
|
393
|
+
private _dicontainer;
|
|
394
|
+
get dicontainer(): TDIContainer;
|
|
395
|
+
constructor(methodEndpoint: HttpMethodEndpoint<TDef>, dicontainer: TDIContainer);
|
|
396
|
+
get genericPath(): string;
|
|
397
|
+
private _handler;
|
|
398
|
+
get handler(): HttpMethodEndpointHandler<TDef, TPathParams, TInjected> | null;
|
|
399
|
+
register(handler: HttpMethodEndpointHandler<TDef, TPathParams, TInjected>): this;
|
|
400
|
+
private _onHandlerRegisteredCallback;
|
|
401
|
+
_onHandlerRegistered(callback: OnHandlerRegisteredCallback<TDef, TDIContainer, TPathParams>): void;
|
|
402
|
+
prepare(callback: PrepareRegistryEntryCallback<TDef, TDIContainer, TPathParams>): this;
|
|
403
|
+
private _injection;
|
|
404
|
+
get injection(): any;
|
|
405
|
+
inject<TNewInjected>(injection: (diScope: ReturnType<TDIContainer['createScope']>) => TNewInjected & EndpointHandlerContextOverlapGuard<TNewInjected>): MethodEndpointHandlerRegistryEntry<TDef, TDIContainer, TPathParams, TNewInjected>;
|
|
406
|
+
private readonly _decoratorFactories;
|
|
407
|
+
get decoratorFactories(): ((scope: DIScope<any>) => IEndpointHandlerDecorator<any>)[];
|
|
408
|
+
/**
|
|
409
|
+
*
|
|
410
|
+
* @param decoratorFactory must be a function that takes exactly the DI scope type and returns an instance of a class that implements IEndpointHandlerDecorator
|
|
411
|
+
* @returns this
|
|
412
|
+
*
|
|
413
|
+
* Initially, the method was defined as:
|
|
414
|
+
* ```ts
|
|
415
|
+
* decorate<
|
|
416
|
+
* TDecoratorSchemas extends IDecoratorHandlerSchemas,
|
|
417
|
+
* TDecorator extends IEndpointHandlerDecorator<TDecoratorSchemas>
|
|
418
|
+
* > (
|
|
419
|
+
* decoratorFactory: IEndpointHandlerDecoratorFactory<TDecoratorSchemas, TDIContainer, TDecorator>
|
|
420
|
+
* ): this {
|
|
421
|
+
* this._decoratorFactories.push(decoratorFactory);
|
|
422
|
+
* return this;
|
|
423
|
+
* }
|
|
424
|
+
* ```
|
|
425
|
+
*
|
|
426
|
+
* and the type IEndpointHandlerDecoratorFactory was defined as:
|
|
427
|
+
* ```ts
|
|
428
|
+
* type IEndpointHandlerDecoratorFactory<
|
|
429
|
+
* TDecoratorSchemas extends IDecoratorHandlerSchemas,
|
|
430
|
+
* TDIContainer extends DIContainer,
|
|
431
|
+
* TDecorator extends IEndpointHandlerDecorator<TDecoratorSchemas>
|
|
432
|
+
* > = (diScope: ReturnType<TDIContainer['createScope']>) => TDecorator;
|
|
433
|
+
* ```
|
|
434
|
+
*
|
|
435
|
+
* However, TypeScript was incorrectly inferring the types when using the 'decorate' method.
|
|
436
|
+
* The end developer would have had to explicitly provide the generic types, which is not ideal.
|
|
437
|
+
*
|
|
438
|
+
* With the current definition, TypeScript can infer the types from the decoratorFactory parameter,
|
|
439
|
+
* making it easier to use.
|
|
440
|
+
*/
|
|
441
|
+
decorate<TDecorator extends {
|
|
442
|
+
handle(input: any, context: any): Promise<any>;
|
|
443
|
+
}, const TDecoratingArgs extends {} = {}>(decoratorFactory: ((diScope: ReturnType<TDIContainer['createScope']>, decoratingArgs: TDecoratingArgs) => TDecorator) extends infer TExpected ? TDecorator extends IEndpointHandlerDecorator<infer _TSchemas> ? TExpected : "❌ ERROR: The decoratorFactory must return an instance of a class that implements IEndpointHandlerDecorator" : never, decoratingArgs: TDecoratingArgs): this;
|
|
444
|
+
decorateWith<TDecorator extends {
|
|
445
|
+
handle(input: any, context: any): Promise<any>;
|
|
446
|
+
}, const TDecoratingArgs extends {} = {}>(decoratorStaticMethodFactory: ({
|
|
447
|
+
new (...args: any[]): TDecorator;
|
|
448
|
+
create(diScope: ReturnType<TDIContainer['createScope']>, decoratingArgs: TDecoratingArgs): TDecorator;
|
|
449
|
+
} extends infer TExpected ? TDecorator extends IEndpointHandlerDecorator<infer _TSchemas> ? TExpected : "❌ ERROR: The decoratorStaticMethodFactory must be a class that implements IEndpointHandlerDecorator and has a static 'create' method that takes exactly the DI scope type and returns an instance of the class" : never), decoratingArgs: TDecoratingArgs): this;
|
|
450
|
+
trigger(diScope: ReturnType<TDIContainer['createScope']>, requestObject: {
|
|
451
|
+
headers: TDef['headers'] extends z.ZodType ? z.output<TDef['headers']> : Record<string, string>;
|
|
452
|
+
pathParams: TypedPathParams<TPathParams>;
|
|
453
|
+
query: TDef['query'] extends z.ZodType ? z.output<TDef['query']> : null;
|
|
454
|
+
body: TDef['body'] extends z.ZodType ? z.output<TDef['body']> : null;
|
|
455
|
+
}): Promise<any>;
|
|
456
|
+
exec(injected: TInjected, requestObject: {
|
|
457
|
+
headers: TDef['headers'] extends z.ZodType ? z.output<TDef['headers']> : Record<string, string>;
|
|
458
|
+
pathParams: TypedPathParams<TPathParams>;
|
|
459
|
+
query: TDef['query'] extends z.ZodType ? z.output<TDef['query']> : null;
|
|
460
|
+
body: TDef['body'] extends z.ZodType ? z.output<TDef['body']> : null;
|
|
461
|
+
}): Promise<HttpMethodEndpointHandlerOutput<TDef> | BadRequestValidationErrorResponse>;
|
|
462
|
+
triggerNoStaticTypeCheck(diScope: DIScope<any>, requestObject: HttpRequestObject, context: EndpointHandlerContext<any>): Promise<any>;
|
|
463
|
+
}
|
|
464
|
+
|
|
315
465
|
declare function flatListAllRegistryEntries<TDef extends IApiContractDefinition & ValidateApiContractDefinition<TDef>, TDIContainer extends DIContainer>(registry: ApiHandlersRegistry<TDef, TDIContainer>): MethodEndpointHandlerRegistryEntry<any, any, any, any>[];
|
|
316
466
|
declare function createRegistry<TDef extends IApiContractDefinition & ValidateApiContractDefinition<TDef>, TDIContainer extends DIContainer>(diContainer: TDIContainer, contract: ApiContract<TDef>, settings: IRegistrySettings<TDIContainer>): ApiHandlersRegistry<TDef, TDIContainer, "">;
|
|
317
467
|
type GenericOnHandlerRegisteredCallback<TDIContainer extends DIContainer> = OnHandlerRegisteredCallback<IHttpMethodEndpointDefinition & ValidateHttpMethodEndpointDefinition<IHttpMethodEndpointDefinition>, TDIContainer, string>;
|
|
@@ -358,6 +508,8 @@ type NavigateToEndpoint<TDef, TSegments extends readonly string[]> = TSegments e
|
|
|
358
508
|
declare function register<const TApiDef extends IApiContractDefinition & ValidateApiContractDefinition<TApiDef>, TDIContainer extends DIContainer, TPathParams extends string, const TPath extends MethodFirstPath<TApiDef>>(apiReg: ApiHandlersRegistry<TApiDef, TDIContainer, TPathParams>, path: TPath, handler: HttpMethodEndpointHandler<ExtractEndpointFromPath<TApiDef, TPath>, `${TPathParams}${ExtractConcatenatedParamNamesFromMethodFirstPath<TPath>}`, {}>): void;
|
|
359
509
|
declare function register<const TDef extends IHttpMethodEndpointDefinition & ValidateHttpMethodEndpointDefinition<TDef>, TDIContainer extends DIContainer, TPathParams extends string>(endpointEntry: MethodEndpointHandlerRegistryEntry<TDef, TDIContainer, TPathParams>, handler: HttpMethodEndpointHandler<TDef, TPathParams, {}>): void;
|
|
360
510
|
|
|
511
|
+
declare function execHandlerChain(diScope: DIScope<any>, allHandlerEntries: ICanTriggerAsync[], input: ClientHttpMethodEndpointHandlerInput): Promise<any>;
|
|
512
|
+
|
|
361
513
|
type InferInputProp<T extends IHttpMethodEndpointDefinition, P extends keyof T> = T[P] extends z$1.ZodType<any, any> ? Record<P, z$1.input<T[P]>> : {};
|
|
362
514
|
type Merge3<A, B, C> = A & B & C;
|
|
363
515
|
type HttpMethodCallInput<T extends IHttpMethodEndpointDefinition> = Merge3<InferInputProp<T, "headers">, InferInputProp<T, "query">, InferInputProp<T, "body">> extends infer M ? keyof M extends never ? never : M : never;
|
|
@@ -379,6 +531,11 @@ type ApiClientDef<ObjType extends object> = {
|
|
|
379
531
|
type ApiClient<TDef extends IApiContractDefinition & ValidateApiContractDefinition<TDef>> = Omit<ApiClientDef<InnerApiClient<TDef> & TDef>, "__CONTEXT__">;
|
|
380
532
|
declare const ApiClient: new <TDef extends IApiContractDefinition & ValidateApiContractDefinition<TDef>>(contract: ApiContract<TDef>, clientGenericHandler: ClientHttpMethodEndpointHandler) => ApiClient<TDef>;
|
|
381
533
|
|
|
382
|
-
|
|
534
|
+
interface InProcApiClientOptions<TDef extends IApiContractDefinition & ValidateApiContractDefinition<TDef>, TDIContainer extends DIContainer> {
|
|
535
|
+
enhanceRequest?: (input: ClientHttpMethodEndpointHandlerInput) => ClientHttpMethodEndpointHandlerInput;
|
|
536
|
+
filterMiddleware?: (genericPath: string, middlewareIndex: number) => boolean;
|
|
537
|
+
mockEndpointResponse?: (genericPath: string, method: string, diScope: ReturnType<TDIContainer['createScope']>) => HttpResponseObject | null;
|
|
538
|
+
}
|
|
539
|
+
declare function createInProcApiClient<TDef extends IApiContractDefinition & ValidateApiContractDefinition<TDef>, TDIContainer extends DIContainer, TDIContainerTestClone extends DIContainerTestClone<any, TDIContainer>>(contract: ApiContract<TDef>, testContainer: TDIContainerTestClone, registry: ApiHandlersRegistry<TDef, TDIContainer>, options?: InProcApiClientOptions<TDef, TDIContainer>): ApiClient<TDef>;
|
|
383
540
|
|
|
384
|
-
export { ApiClient, type ApiClientDef, ApiContract, ApiHandlersRegistry, type ApiHandlersRegistryDef, type ClientHttpMethodEndpointHandler, type ClientHttpMethodEndpointHandlerInput, type ClientHttpMethodEndpointHandlerOutput, type
|
|
541
|
+
export { ApiClient, type ApiClientDef, ApiContract, ApiHandlersRegistry, type ApiHandlersRegistryDef, type BadRequestValidationErrorResponse, type CapitalizedStringLiteral, type ClientHttpMethodEndpointHandler, type ClientHttpMethodEndpointHandlerInput, type ClientHttpMethodEndpointHandlerOutput, type CreateHandlerOutput, DIContainer, DIContainerBase, DIContainerTestClone, type DILifetime, type DIRegistry, type DIRegistryEntry, type DIScope, type DecoratorHandlerContext, type DecoratorHandlerInput, type DecoratorHandlerOutput, type EndpointHandlerContext, type EndpointHandlerContextOverlapGuard, type EndpointHandlerDecoratorFactory, type ExtractConcatenatedParamNamesFromMethodFirstPath, type ExtractConcatenatedParamNamesFromPath, type ExtractConcatenatedParamNamesFromPathSegments, type ExtractEndpointFromPath, type GenericOnHandlerRegisteredCallback, type HttpMethod, type HttpMethodCallFunc, type HttpMethodCallInput, HttpMethodEndpoint, type HttpMethodEndpointHandler, type HttpMethodEndpointHandlerInput, type HttpMethodEndpointHandlerOutput, HttpMethodEndpointResponse, type HttpMethodEndpointResponses, type HttpRequestObject, type HttpResponseObject, HttpStatusCode, type IApiContractDefinition, type IClientContext, type IDecoratorHandlerSchemas, type IEndpointHandlerDecorator, type IHttpMethodEndpointDefinition, type IHttpMethodEndpointResponseDefinition, type IRegistrySettings, type InProcApiClientOptions, type LowerCasedHttpMethod, MethodEndpointHandlerRegistryEntry, type MethodFirstPath, type MiddlewareHandler, type MiddlewareHandlerContext, type MiddlewareHandlerContextOverlapGuard, type MiddlewareHandlerInput, type MiddlewareHandlerInputInternal, type MiddlewareHandlerInternal, type MiddlewareHandlerOutput, type MiddlewareHandlerSchemas, MiddlewareHandlersRegistry, MiddlewareHandlersRegistryEntry, MiddlewareHandlersRegistryEntryInternal, type MiddlewarePath, type OnHandlerRegisteredCallback, type OnMiddlewareHandlerRegisteredCallback, type PartialPath, type PartialPathResult, type PathParamFunc, type PrepareRegistryEntryCallback, type StringLiteral, type TypedPathParams, type ValidateApiContractDefinition, type ValidateHttpMethodEndpointDefinition, apiContract, createClient, createInProcApiClient, createRegistry, endpoint, execHandlerChain, flatListAllRegistryEntries, isHttpResponseObject, isHttpStatusCode, middleware, partial, partialPathString, register, response, route, triggerEndpointDecoratorNoStaticTypeCheck, triggerMiddlewareDecoratorNoStaticTypeCheck };
|