@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.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, TInjected> = {
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?: any;
129
- body?: any;
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
- type HttpMethodEndpointHandler<TDef extends IHttpMethodEndpointDefinition, TPathParams extends string, TInjected> = (input: HttpMethodEndpointHandlerInput<TDef, TPathParams, TInjected>) => Promise<HttpMethodEndpointHandlerOutput<TDef>>;
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<S> = S extends string ? string extends S ? never : S : never;
175
- type DIClass<T> = new (...args: any[]) => T;
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 DIServiceRegistry = Record<string, any>;
178
- /**
179
- * A scoped container that provides typed method access to services.
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
- * This is the core of the static typing. It's a "mapped type" that takes a
186
- * ServiceRegistry `R` and creates a new type. For each key `K` in the registry,
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
- * A Dependency Injection (DI) Container that provides static typing for resolved services.
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
- createTestClone(): this;
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
- type PrepareRegistryEntryCallback<TDef extends IHttpMethodEndpointDefinition & ValidateHttpMethodEndpointDefinition<TDef>, TDIContainer extends DIContainer, TPathParams extends string> = (entry: MethodEndpointHandlerRegistryEntry<TDef, TDIContainer, TPathParams, any>) => void;
224
- type OnHandlerRegisteredCallback<TDef extends IHttpMethodEndpointDefinition & ValidateHttpMethodEndpointDefinition<TDef>, TDIContainer extends DIContainer, TPathParams extends string> = (entry: MethodEndpointHandlerRegistryEntry<TDef, TDIContainer, TPathParams, any>) => void;
225
- declare class MethodEndpointHandlerRegistryEntry<TDef extends IHttpMethodEndpointDefinition & ValidateHttpMethodEndpointDefinition<TDef>, TDIContainer extends DIContainer, TPathParams extends string, TInjected = {}> {
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 MiddlewareHandlerInputSchemas = {
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, InputSchemas extends MiddlewareHandlerInputSchemas, TInjected> = {
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: InputSchemas['headers'] extends z$1.ZodType ? z$1.output<InputSchemas['headers']> : Record<string, string>;
249
+ headers: TMiddlewareSchemas['headers'] extends z$1.ZodType ? z$1.output<TMiddlewareSchemas['headers']> : Record<string, string>;
259
250
  pathParams: TypedPathParams<TPathParams>;
260
- query: InputSchemas['query'] extends z$1.ZodType ? z$1.output<InputSchemas['query']> : null;
261
- body: InputSchemas['body'] extends z$1.ZodType ? z$1.output<InputSchemas['body']> : null;
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 MiddlewareHandlerInputInternal<TInjected> = {
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, InputSchemas extends MiddlewareHandlerInputSchemas, TInjected> = (input: MiddlewareHandlerInput<TPathParams, InputSchemas, TInjected>, next: () => void) => Promise<HttpResponseObject | void>;
276
- type MiddlewareHandlerInternal<TInjected> = (input: MiddlewareHandlerInputInternal<TInjected>, next: () => void) => Promise<HttpResponseObject | void>;
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 _splitMiddlewarePath;
286
- private readonly _inputSchemas;
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, inputSchemas: MiddlewareHandlerInputSchemas, injection: (dicontainer: TDIContainer) => TInjected, handler: MiddlewareHandlerInternal<TInjected>);
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(data: {
291
- headers: Record<string, string>;
292
- pathParams: Record<string, string>;
293
- query: object;
294
- body: object;
295
- }, next: () => void): Promise<any>;
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: (dicontainer: TDIContainer) => TNewInjected): MiddlewareHandlersRegistryEntry<TApiDef, TDIContainer, TPathParams, TPath, TNewInjected>;
304
- register<const InputSchemas extends MiddlewareHandlerInputSchemas>(inputSchemas: InputSchemas, handler: MiddlewareHandler<`${TPathParams}${ExtractConcatenatedParamNamesFromPath<TPath>}`, InputSchemas, TInjected>): void;
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
- declare function createInProcApiClient<TDef extends IApiContractDefinition & ValidateApiContractDefinition<TDef>, TDIContainer extends DIContainer>(contract: ApiContract<TDef>, testContainer: TDIContainer, registry: ApiHandlersRegistry<TDef, TDIContainer>): ApiClient<TDef>;
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 DIClass, DIContainer, type DILifetime, type DIScope, 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 HttpResponseObject, HttpStatusCode, type IApiContractDefinition, type IClientContext, type IHttpMethodEndpointDefinition, type IHttpMethodEndpointResponseDefinition, type IRegistrySettings, type LowerCasedHttpMethod, MethodEndpointHandlerRegistryEntry, type MethodFirstPath, type MiddlewareHandler, type MiddlewareHandlerInput, type MiddlewareHandlerInputInternal, type MiddlewareHandlerInputSchemas, type MiddlewareHandlerInternal, MiddlewareHandlersRegistry, MiddlewareHandlersRegistryEntry, MiddlewareHandlersRegistryEntryInternal, type MiddlewarePath, type OnHandlerRegisteredCallback, type OnMiddlewareHandlerRegisteredCallback, type PartialPath, type PartialPathResult, type PathParamFunc, type PrepareRegistryEntryCallback, type TypedPathParams, type ValidateApiContractDefinition, type ValidateHttpMethodEndpointDefinition, apiContract, createClient, createInProcApiClient, createRegistry, endpoint, flatListAllRegistryEntries, isHttpResponseObject, isHttpStatusCode, middleware, partial, partialPathString, register, response, route };
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 };