next-rest-framework
Version:
Next REST Framework - Type-safe, self-documenting APIs for Next.js
168 lines (163 loc) • 12.8 kB
text/typescript
import { ZodSchema, z } from 'zod';
import { OpenAPIV3_1 } from 'openapi-types';
type DocsProvider = 'redoc' | 'swagger-ui';
type OpenApiObject = Partial<Modify<Omit<OpenAPIV3_1.Document, 'openapi'>, {
info: Partial<OpenAPIV3_1.InfoObject>;
}>>;
type OpenApiPathItem = Partial<Pick<OpenAPIV3_1.PathItemObject, 'summary' | 'description' | 'servers' | 'parameters'>>;
type OpenApiOperation = Partial<Pick<OpenAPIV3_1.OperationObject, 'tags' | 'summary' | 'description' | 'externalDocs' | 'parameters' | 'callbacks' | 'deprecated' | 'security' | 'servers'>>;
interface NextRestFrameworkConfig {
/*!
* Array of paths that are denied by Next REST Framework and not included in the OpenAPI spec.
* Supports wildcards using asterisk `*` and double asterisk `**` for recursive matching.
* Example: `['/api/disallowed-path', '/api/disallowed-path-2/*', '/api/disallowed-path-3/**']`
* Defaults to no paths being disallowed.
*/
deniedPaths?: string[];
/*!
* Array of paths that are allowed by Next REST Framework and included in the OpenAPI spec.
* Supports wildcards using asterisk `*` and double asterisk `**` for recursive matching.
* Example: `['/api/allowed-path', '/api/allowed-path-2/*', '/api/allowed-path-3/**']`
* Defaults to all paths being allowed.
*/
allowedPaths?: string[];
/*! An OpenAPI Object that can be used to override and extend the auto-generated specification: https://swagger.io/specification/#openapi-object */
openApiObject?: OpenApiObject;
/*! Path that will be used for fetching the OpenAPI spec - defaults to `/openapi.json`. This path also determines the path where this file will be generated inside the `public` folder. */
openApiJsonPath?: string;
/*! Customization options for the generated docs. */
docsConfig?: {
/*! Determines whether to render the docs using Redoc (`redoc`) or SwaggerUI `swagger-ui`. Defaults to `redoc`. */
provider?: DocsProvider;
/*! Custom title, used for the visible title and HTML title. */
title?: string;
/*! Custom description, used for the visible description and HTML meta description. */
description?: string;
/*! Custom HTML meta favicon URL. */
faviconUrl?: string;
/*! A URL for a custom logo. */
logoUrl?: string;
/*! Basic customization options for OG meta tags: https://ogp.me/#metadata */
ogConfig?: {
title: string /*! og:title */;
type: string /*! og:type */;
url: string /*! og:url */;
imageUrl: string /*! og:image */;
};
};
/*! Setting this to `true` will suppress all informational logs from Next REST Framework. Defaults to `false`. */
suppressInfo?: boolean;
}
type BaseStatus = number;
type BaseContentType = AnyContentTypeWithAutocompleteForMostCommonOnes;
type BaseQuery = Record<string, string | string[]>;
type BaseParams = Record<string, string>;
type BaseOptions = Record<string, unknown>;
interface OutputObject$1<Body = unknown, Status extends BaseStatus = BaseStatus, ContentType extends BaseContentType = BaseContentType> {
schema: ZodSchema<Body>;
status: Status;
contentType: ContentType;
name?: string;
}
type Modify<T, R> = Omit<T, keyof R> & R;
type AnyCase<T extends string> = T | Uppercase<T> | Lowercase<T>;
type StringWithAutocomplete<T> = T | (string & Record<never, never>);
type AnyContentTypeWithAutocompleteForMostCommonOnes = StringWithAutocomplete<'application/java-archive' | 'application/EDI-X12' | 'application/EDIFACT' | 'application/javascript' | 'application/octet-stream' | 'application/ogg' | 'application/pdf' | 'application/xhtml+xml' | 'application/x-shockwave-flash' | 'application/json' | 'application/ld+json' | 'application/xml' | 'application/zip' | 'application/x-www-form-urlencoded'
/********************/
| 'audio/mpeg' | 'audio/x-ms-wma' | 'audio/vnd.rn-realaudio' | 'audio/x-wav'
/********************/
| 'image/gif' | 'image/jpeg' | 'image/png' | 'image/tiff' | 'image/vnd.microsoft.icon' | 'image/x-icon' | 'image/vnd.djvu' | 'image/svg+xml'
/********************/
| 'multipart/mixed' | 'multipart/alternative' | 'multipart/related' | 'multipart/form-data'
/********************/
| 'text/css' | 'text/csv' | 'text/html' | 'text/javascript' | 'text/plain' | 'text/xml'
/********************/
| 'video/mpeg' | 'video/mp4' | 'video/quicktime' | 'video/x-ms-wmv' | 'video/x-msvideo' | 'video/x-flv' | 'video/webm'
/********************/
| 'application/vnd.android.package-archive' | 'application/vnd.oasis.opendocument.text' | 'application/vnd.oasis.opendocument.spreadsheet' | 'application/vnd.oasis.opendocument.presentation' | 'application/vnd.oasis.opendocument.graphics' | 'application/vnd.ms-excel' | 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | 'application/vnd.ms-powerpoint' | 'application/vnd.openxmlformats-officedocument.presentationml.presentation' | 'application/msword' | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' | 'application/vnd.mozilla.xul+xml'>;
type RpcRequestInit = Omit<RequestInit, 'method' | 'body'>;
type RpcClient<T extends Record<string, RpcOperationDefinition<any, any, any>>> = {
[key in keyof T]: T[key] & {
_meta: never;
};
};
declare const rpcClient: <T extends Record<string, RpcOperationDefinition<any, any, any>>>({ url: _url, init }: {
url: string;
init?: RpcRequestInit | undefined;
}) => RpcClient<T>;
interface OutputObject {
schema: ZodSchema;
name?: string;
}
type RpcMiddleware<InputOptions extends BaseOptions = BaseOptions, OutputOptions extends BaseOptions = BaseOptions> = (params: unknown, options: InputOptions) => Promise<OutputOptions> | OutputOptions | Promise<void> | void;
type RpcOperationHandler<Input = unknown, Options extends BaseOptions = BaseOptions, Outputs extends readonly OutputObject[] = readonly OutputObject[]> = (params: z.infer<ZodSchema<Input>>, options: Options) => Promise<z.infer<Outputs[number]['schema']>> | z.infer<Outputs[number]['schema']>;
interface OperationDefinitionMeta {
openApiOperation?: OpenApiOperation;
input?: ZodSchema;
outputs?: readonly OutputObject[];
middleware1?: RpcOperationHandler;
middleware2?: RpcOperationHandler;
middleware3?: RpcOperationHandler;
handler?: RpcOperationHandler;
}
type RpcOperationDefinition<Input = unknown, Outputs extends readonly OutputObject[] = readonly OutputObject[], HasInput extends boolean = false, TypedResponse = Promise<z.infer<Outputs[number]['schema']>>> = (HasInput extends true ? (body: z.infer<ZodSchema<Input>>) => TypedResponse : () => TypedResponse) & {
_meta: OperationDefinitionMeta;
};
declare const rpcOperation: (openApiOperation?: OpenApiOperation) => {
input: <Input>(input: z.ZodType<Input, z.ZodTypeDef, Input>) => {
outputs: <Output extends readonly OutputObject[]>(outputs: Output) => {
middleware: <Options1 extends BaseOptions>(middleware1: RpcMiddleware<BaseOptions, Options1>) => {
middleware: <Options2 extends BaseOptions>(middleware2: RpcMiddleware<Options1, Options2>) => {
middleware: <Options3 extends BaseOptions>(middleware3: RpcMiddleware<Options2, Options3>) => {
handler: (handler: RpcOperationHandler<Input, Options3, Output>) => RpcOperationDefinition<Input, Output, true, Promise<z.TypeOf<Output[number]["schema"]>>>;
};
handler: (handler: RpcOperationHandler<Input, Options2, Output>) => RpcOperationDefinition<Input, Output, true, Promise<z.TypeOf<Output[number]["schema"]>>>;
};
handler: (handler: RpcOperationHandler<Input, Options1, Output>) => RpcOperationDefinition<Input, Output, true, Promise<z.TypeOf<Output[number]["schema"]>>>;
};
handler: (handler: RpcOperationHandler<Input, BaseOptions, Output>) => RpcOperationDefinition<Input, Output, true, Promise<z.TypeOf<Output[number]["schema"]>>>;
};
middleware: <Options1_1 extends BaseOptions>(middleware1: RpcMiddleware<BaseOptions, Options1_1>) => {
middleware: <Options2_1 extends BaseOptions>(middleware2: RpcMiddleware<Options1_1, Options2_1>) => {
middleware: <Options3_1 extends BaseOptions>(middleware3: RpcMiddleware<Options2_1, Options3_1>) => {
outputs: <Output_1 extends readonly OutputObject[]>(outputs: Output_1) => {
handler: (handler: RpcOperationHandler<Input, Options3_1, Output_1>) => RpcOperationDefinition<Input, Output_1, true, Promise<z.TypeOf<Output_1[number]["schema"]>>>;
};
handler: (handler: RpcOperationHandler<Input, Options2_1, readonly OutputObject[]>) => RpcOperationDefinition<Input, readonly OutputObject[], true, Promise<any>>;
};
outputs: <Output_2 extends readonly OutputObject[]>(outputs: Output_2) => {
handler: (handler: RpcOperationHandler<Input, Options2_1, Output_2>) => RpcOperationDefinition<Input, Output_2, true, Promise<z.TypeOf<Output_2[number]["schema"]>>>;
};
handler: (handler: RpcOperationHandler<Input, Options2_1, readonly OutputObject[]>) => RpcOperationDefinition<Input, readonly OutputObject[], true, Promise<any>>;
};
outputs: <Output_3 extends readonly OutputObject[]>(outputs: Output_3) => {
handler: (handler: RpcOperationHandler<Input, Options1_1, Output_3>) => RpcOperationDefinition<Input, Output_3, true, Promise<z.TypeOf<Output_3[number]["schema"]>>>;
};
handler: (handler: RpcOperationHandler<Input, Options1_1, readonly OutputObject[]>) => RpcOperationDefinition<Input, readonly OutputObject[], true, Promise<any>>;
};
handler: (handler: RpcOperationHandler<Input, BaseOptions, readonly OutputObject[]>) => RpcOperationDefinition<Input, readonly OutputObject[], true, Promise<any>>;
};
outputs: <Output_4 extends readonly OutputObject[]>(outputs: Output_4) => {
middleware: <Options1_2 extends BaseOptions>(middleware1: RpcMiddleware<BaseOptions, Options1_2>) => {
middleware: <Options2_2 extends BaseOptions>(middleware2: RpcMiddleware<Options1_2, Options2_2>) => {
middleware: <Options3_2 extends BaseOptions>(middleware3: RpcMiddleware<Options2_2, Options3_2>) => {
handler: (handler: RpcOperationHandler<unknown, Options3_2, Output_4>) => RpcOperationDefinition<unknown, Output_4, false, Promise<z.TypeOf<Output_4[number]["schema"]>>>;
};
handler: (handler: RpcOperationHandler<unknown, Options2_2, Output_4>) => RpcOperationDefinition<unknown, Output_4, false, Promise<z.TypeOf<Output_4[number]["schema"]>>>;
};
handler: (handler: RpcOperationHandler<unknown, Options1_2, Output_4>) => RpcOperationDefinition<unknown, Output_4, false, Promise<z.TypeOf<Output_4[number]["schema"]>>>;
};
handler: (handler: RpcOperationHandler<unknown, BaseOptions, Output_4>) => RpcOperationDefinition<unknown, Output_4, false, Promise<z.TypeOf<Output_4[number]["schema"]>>>;
};
middleware: <Options1_3 extends BaseOptions>(middleware1: RpcMiddleware<BaseOptions, Options1_3>) => {
middleware: <Options2_3 extends BaseOptions>(middleware2: RpcMiddleware<Options1_3, Options2_3>) => {
middleware: <Options3_3 extends BaseOptions>(middleware3: RpcMiddleware<Options2_3, Options3_3>) => {
handler: (handler: RpcOperationHandler<unknown, Options3_3, readonly OutputObject[]>) => RpcOperationDefinition<unknown, readonly OutputObject[], false, Promise<any>>;
};
handler: (handler: RpcOperationHandler<unknown, Options2_3, readonly OutputObject[]>) => RpcOperationDefinition<unknown, readonly OutputObject[], false, Promise<any>>;
};
handler: (handler: RpcOperationHandler<unknown, Options1_3, readonly OutputObject[]>) => RpcOperationDefinition<unknown, readonly OutputObject[], false, Promise<any>>;
};
handler: (handler: RpcOperationHandler) => RpcOperationDefinition<unknown, readonly OutputObject[], false, Promise<any>>;
};
export { type AnyContentTypeWithAutocompleteForMostCommonOnes as A, type BaseQuery as B, type Modify as M, type NextRestFrameworkConfig as N, type OutputObject$1 as O, type RpcOperationDefinition as R, type BaseParams as a, type BaseOptions as b, type BaseStatus as c, type BaseContentType as d, type OpenApiOperation as e, type AnyCase as f, type OpenApiPathItem as g, type RpcClient as h, rpcClient as i, rpcOperation as r };