@whook/whook
Version:
Build strong and efficient REST web services.
163 lines (150 loc) • 4.52 kB
text/typescript
import { type ExpressiveJSONSchema } from 'ya-json-schema-types';
import {
type OpenAPIExtension,
type OpenAPIOperation,
PATH_ITEM_METHODS,
} from 'ya-open-api-types';
import { type WhookRequestBody, type WhookResponse } from './http.js';
import {
type Dependencies,
type ServiceInitializer,
type ProviderInitializer,
} from 'knifecycle';
import { type WhookHandlerWrapper } from './wrappers.js';
import { type WhookEnvironmentsConfig } from '../libs/environments.js';
import {
type WhookModuleAsideComponents,
type WhookModuleAsideSchemas,
} from '../index.js';
export const DEFAULT_ROUTE_CONFIG: WhookRouteConfig = {
environments: 'all',
private: false,
};
export interface WhookBaseRouteConfig {
environments?: WhookEnvironmentsConfig;
private?: boolean;
targetHandler?: string;
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface WhookRouteConfig extends WhookBaseRouteConfig {}
export interface WhookRouteDefinition {
path: `/${string}`;
method: (typeof PATH_ITEM_METHODS)[number];
operation: OpenAPIOperation<ExpressiveJSONSchema, OpenAPIExtension> & {
operationId: string;
};
config?: WhookRouteConfig;
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface WhookRouteHandlerExtraParameters {}
export type WhookRouteHandlerParameters = (
| object
| {
body: WhookRequestBody;
}
) & {
path: Record<string, unknown>;
query: Record<string, unknown>;
cookies: Record<string, unknown>;
headers: Record<string, unknown>;
} & WhookRouteHandlerExtraParameters;
export type WhookRouteHandler<
P extends WhookRouteHandlerParameters = WhookRouteHandlerParameters,
D extends WhookRouteDefinition = WhookRouteDefinition,
> = (parameters: P, definition?: D) => Promise<WhookResponse>;
export type WhookRouteHandlerInitializer<
D extends Dependencies = Record<string, unknown>,
S extends WhookRouteHandler = WhookRouteHandler,
> = ServiceInitializer<D, S> | ProviderInitializer<D, S>;
export const ROUTE_ASIDE_COMPONENTS_MAP = {
schemas: 'Schema',
parameters: 'Parameter',
headers: 'Header',
requestBodies: 'RequestBody',
responses: 'Response',
callbacks: 'Callback',
} as const;
// May allow to type routes files later
// https://github.com/nfroidure/whook/issues/196
export interface WhookRouteModule
extends WhookModuleAsideSchemas, WhookModuleAsideComponents {
default: WhookRouteHandlerInitializer;
definition: WhookRouteDefinition;
}
export type WhookRouteHandlerWrapper<T extends WhookRouteHandler> =
WhookHandlerWrapper<T>;
export interface WhookRouteTypeDefinition {
requestBody?: unknown;
responses?: {
default?: {
headers?: unknown;
body?: unknown;
};
[key: number]: {
headers?: unknown;
body?: unknown;
};
};
parameters?: {
path?: object;
query?: object;
headers?: object;
cookies?: object;
};
}
export type WhookRouteTypedHandler<
T extends WhookRouteTypeDefinition,
D extends WhookRouteDefinition,
O extends object = object,
> = (
parameters: (Partial<
NonNullable<T['parameters']>['path']
> extends NonNullable<T['parameters']>['path']
? {
path?: NonNullable<T['parameters']>['path'];
}
: {
path: NonNullable<T['parameters']>['path'];
}) &
(Partial<NonNullable<T['parameters']>['query']> extends NonNullable<
T['parameters']
>['query']
? {
query?: NonNullable<T['parameters']>['query'];
}
: {
query: NonNullable<T['parameters']>['query'];
}) &
(Partial<NonNullable<T['parameters']>['headers']> extends NonNullable<
T['parameters']
>['headers']
? {
headers?: NonNullable<T['parameters']>['headers'];
}
: {
headers: NonNullable<T['parameters']>['headers'];
}) &
(Partial<NonNullable<T['parameters']>['cookies']> extends NonNullable<
T['parameters']
>['cookies']
? {
cookies?: NonNullable<T['parameters']>['cookies'];
}
: {
cookies: NonNullable<T['parameters']>['cookies'];
}) &
WhookRouteHandlerExtraParameters &
(T['requestBody'] extends object | string | number | boolean
? {
body: T['requestBody'];
options?: O;
}
: { options?: O }),
definition?: D,
) => Promise<
{
[Status in keyof T['responses']]: {
status: Status;
} & T['responses'][Status];
}[keyof T['responses']]
>;