jetpath
Version:
A performance-first cross-runtime API framework without the boilerplate
334 lines (333 loc) • 10.5 kB
TypeScript
import { IncomingMessage, Server, ServerResponse } from 'node:http';
import type { _JetPath_paths, v } from './functions.js';
import { type CookieOptions, SchemaBuilder } from './classes.js';
import type { BunFile } from 'bun';
import type Stream from 'node:stream';
export type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (x: infer I) => void ? I : never;
export interface JetContext<JetData extends {
body?: Record<string, any>;
params?: Record<string, any>;
query?: Record<string, any>;
} = {
body: {};
params: {};
query: {};
}, JetPluginTypes extends Record<string, unknown>[] = []> {
/**
* an object you can set values to per request
*/
state: Record<string, any>;
/**
* an object you can set values to per request
*/
plugins: UnionToIntersection<JetPluginTypes[number]> & Record<string, any>;
/**
* get body params after /?
*/
/**
* get query params after /?
*/
/**
* get route params in /:thing
*/
params: JetData['params'];
/**
* websocket socket event class
*/
connection: jet_socket;
/**
* reply the request
*/
request: Request;
/**
* API status
*/
code: number;
/**
* send a stream
* @param stream - The stream or file path to send
* @param folder - The folder to save the stream to
* @param ContentType - The content type of the stream
*
* PLEASE PROVIDE A VALID FOLDER PATH FOR SECURITY REASONS
*/
sendStream(stream: Stream | string | BunFile, config?: {
folder?: string;
ContentType?: string;
}): void | never;
/**
* send a file for download
* @param stream - The file path to send
* @param folder - The folder to save the stream to
* @param ContentType - The content type of the stream
*
* PLEASE PROVIDE A VALID FOLDER PATH FOR SECURITY REASONS
*/
download(stream: string | BunFile, config?: {
folder?: string;
ContentType?: string;
}): void;
/**
* send a direct response
* *Only for deno and bun
*/
sendResponse(response?: Response): void;
/**
* reply the request
*/
send(data: unknown, statusCode?: number, ContentType?: string): void;
/**
* redirect the request
*/
redirect(url: string): void;
/**
* get request header values
*/
get(field: string): string | undefined;
/**
* set request header values
*/
set(field: string, value: string): void;
/**
* Parses the request body
*/
getCookie(name: string): string | undefined;
getCookies(): Record<string, string>;
setCookie(name: string, value: string, options: CookieOptions): void;
clearCookie(name: string, options: CookieOptions): void;
parse(options?: {
maxBodySize?: number;
contentType?: string;
}): Promise<JetData['body']>;
parseQuery(): JetData['query'];
/**
* Upgrade the request to a WebSocket connection
*/
upgrade(): void | never;
/**
* get original request
*/
path: string;
payload?: string;
_2?: Record<string, string>;
_3?: any;
_4?: boolean | undefined;
_5?: JetRoute | undefined;
_6?: Response | false;
}
export type JetPluginExecutorInitParams = {
runtime: {
node: boolean;
bun: boolean;
deno: boolean;
};
server: Server<typeof IncomingMessage, typeof ServerResponse>;
routesObject: typeof _JetPath_paths;
JetPath_app: (req: Request) => Response;
};
export type contentType = 'application/x-www-form-urlencoded' | 'multipart/form-data' | 'application/json';
export type methods = 'GET' | 'POST' | 'OPTIONS' | 'DELETE' | 'HEAD' | 'PUT' | 'CONNECT' | 'TRACE' | 'PATCH';
export type allowedMethods = methods[];
export type jetOptions = {
/**
* edge grabber helps capture defined API functions in an edge environment
* and avoids fs system scanning.
* @example
* ```ts
* edgeGrabber: [
* GET_api_users,
* POST_api_users,
* Middleware_api_users,
* ]
* ```
*/
edgeGrabber?: JetRoute[] & JetMiddleware[];
/**
* upgrade the request to a WebSocket connection
*/
upgrade?: boolean;
/**
* source of the app
*/
source?: string;
/**
* global headers
*/
globalHeaders?: Record<string, string>;
/**
* strict mode
*/
strictMode?: 'ON' | 'OFF' | 'WARN';
/**
* generated routes file path
* putting the file on the frontend folder will make it accessible
* during build time
* @default generates nothing
*/
generatedRoutesFilePath?: string;
/**
* keep alive timeout
*/
keepAliveTimeout?: number;
/**
* api documentation options
*/
apiDoc?: {
display?: 'UI' | 'HTTP' | false;
environments?: Record<string, string>;
name?: string;
info?: string;
color?: string;
logo?: string;
path?: string;
password?: string;
username?: string;
};
/**
* credentials options
*/
credentials?: {
cert: string;
key: string;
};
/**
* port
*/
port?: number;
/**
* cors options
*/
cors?: {
allowMethods?: allowedMethods;
secureContext?: {
'Cross-Origin-Opener-Policy': 'same-origin' | 'unsafe-none' | 'same-origin-allow-popups';
'Cross-Origin-Embedder-Policy': 'require-corp' | 'unsafe-none';
};
allowHeaders?: string[];
exposeHeaders?: string[];
keepHeadersOnError?: boolean;
maxAge?: string;
credentials?: boolean;
privateNetworkAccess?: any;
origin?: string[];
} | boolean;
};
export type HTTPBody<Obj extends Record<string, any>> = {
[x in keyof Obj]: {
err?: string;
type?: 'string' | 'number' | 'file' | 'object' | 'boolean' | 'array' | 'date';
arrayType?: 'string' | 'number' | 'file' | 'object' | 'boolean' | 'array' | 'date';
RegExp?: RegExp;
inputAccept?: string;
inputType?: 'date' | 'email' | 'file' | 'password' | 'number' | 'time' | 'tel' | 'datetime' | 'url';
inputDefaultValue?: string | number | boolean;
required?: boolean;
validator?: (value: any) => boolean | string;
objectSchema?: HTTPBody<Record<string, any>>;
};
};
export type Middleware<JetData extends {
body?: Record<string, any>;
params?: Record<string, any>;
query?: Record<string, any>;
} = {
body: {};
params: {};
query: {};
}, JetPluginTypes extends Record<string, unknown>[] = []> = (ctx: JetContext<JetData, JetPluginTypes>) => void | Promise<void> | ((ctx: JetContext<JetData, JetPluginTypes>, error: unknown) => void | Promise<void>) | Promise<((ctx: JetContext<JetData, JetPluginTypes>, error: unknown) => void | Promise<void>) | undefined> | undefined;
export type JetMiddleware<JetData extends {
body?: Record<string, any>;
params?: Record<string, any>;
query?: Record<string, any>;
} = {
body: {};
params: {};
query: {};
}, JetPluginTypes extends Record<string, unknown>[] = []> = Middleware<JetData, JetPluginTypes> | Middleware<JetData, JetPluginTypes>[];
export type JetRoute<JetData extends {
body?: Record<string, any>;
params?: Record<string, any>;
query?: Record<string, any>;
response?: Record<string, any>;
} = {
body: {};
params: {};
query: {};
response: {};
title: '';
description: '';
method: '';
path: '';
jet_middleware: [];
}, JetPluginTypes extends Record<string, unknown>[] = []> = {
(ctx: JetContext<JetData, JetPluginTypes>): Promise<void> | void;
body?: HTTPBody<JetData['body'] & Record<string, any>>;
headers?: Record<string, string>;
title?: string;
description?: string;
method?: string;
path?: string;
jet_middleware?: Middleware[];
params?: HTTPBody<JetData['params'] & Record<string, any>>;
query?: HTTPBody<JetData['query'] & Record<string, any>>;
response?: HTTPBody<JetData['response'] & Record<string, any>>;
};
interface jet_socket {
addEventListener(event: 'message' | 'close' | 'drain' | 'open', listener: (socket: WebSocket, ...params: any[]) => void): void;
}
export type JetFile = {
fileName: string;
content: Uint8Array;
mimeType: string;
};
export type SchemaType = 'string' | 'number' | 'boolean' | 'array' | 'object' | 'date' | 'file';
export interface ValidationOptions {
err?: string;
RegExp?: RegExp;
validator?: (value: any) => boolean | string;
inputDefaultValue?: any;
required?: boolean;
}
export interface FileOptions {
inputAccept?: string;
inputMultiple?: boolean;
err?: string;
}
export interface ArrayOptions extends ValidationOptions {
arrayType?: SchemaType | 'object';
objectSchema?: HTTPBody<any>;
}
export interface ObjectOptions extends ValidationOptions {
objectSchema?: HTTPBody<any>;
}
export type SchemaDefinition = {
type: SchemaType;
} & ValidationOptions & ArrayOptions & ObjectOptions;
export type compilerType<JetData extends {
body?: Record<string, any>;
params?: Record<string, any>;
query?: Record<string, any>;
response?: Record<string, any>;
}, JetPluginTypes extends Record<string, unknown>[] = []> = {
/**
* Sets the API body validation and documentation body for the endpoint
*/
body: (schemaFn: (t: typeof v) => Partial<Record<keyof HTTPBody<NonNullable<JetData['body']>>, SchemaBuilder>>) => compilerType<JetData, JetPluginTypes>;
/**
* Sets the API body validation and documentation body for the endpoint
*/
response: (schemaFn: (t: typeof v) => Partial<Record<keyof HTTPBody<NonNullable<JetData['response']>>, SchemaBuilder>>) => compilerType<JetData, JetPluginTypes>;
/**
* Sets the API documentation query for the endpoint
*/
query: (schemaFn: (t: typeof v) => Partial<Record<keyof HTTPBody<NonNullable<JetData['query']>>, SchemaBuilder>>) => compilerType<JetData, JetPluginTypes>;
/**
* Sets the API documentation title for the endpoint
*/
title: (title: string) => compilerType<JetData, JetPluginTypes>;
/**
* Sets the API documentation description for the endpoint
*/
description: (description: string) => compilerType<JetData, JetPluginTypes>;
};
export {};