shokupan 0.0.1

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.
@@ -0,0 +1,36 @@
1
+ import { Middleware } from '../types';
2
+ export interface SecurityHeadersOptions {
3
+ contentSecurityPolicy?: boolean | Record<string, any>;
4
+ crossOriginEmbedderPolicy?: boolean;
5
+ crossOriginOpenerPolicy?: boolean;
6
+ crossOriginResourcePolicy?: boolean;
7
+ dnsPrefetchControl?: boolean | {
8
+ allow: boolean;
9
+ };
10
+ expectCt?: boolean | {
11
+ maxAge?: number;
12
+ enforce?: boolean;
13
+ reportUri?: string;
14
+ };
15
+ frameguard?: boolean | {
16
+ action: 'deny' | 'sameorigin' | 'allow-from';
17
+ domain?: string;
18
+ };
19
+ hidePoweredBy?: boolean;
20
+ hsts?: boolean | {
21
+ maxAge?: number;
22
+ includeSubDomains?: boolean;
23
+ preload?: boolean;
24
+ };
25
+ ieNoOpen?: boolean;
26
+ noSniff?: boolean;
27
+ originAgentCluster?: boolean;
28
+ permittedCrossDomainPolicies?: boolean | {
29
+ permittedPolicies: 'none' | 'master-only' | 'by-content-type' | 'all';
30
+ };
31
+ referrerPolicy?: boolean | {
32
+ policy: string | string[];
33
+ };
34
+ xssFilter?: boolean;
35
+ }
36
+ export declare function SecurityHeaders(options?: SecurityHeadersOptions): Middleware;
@@ -0,0 +1,87 @@
1
+ import { EventEmitter } from 'events';
2
+ import { ShokupanContext } from '../context';
3
+ import { Middleware } from '../types';
4
+ export interface SessionData {
5
+ cookie: Cookie;
6
+ [key: string]: any;
7
+ }
8
+ export interface SessionCookieOptions {
9
+ maxAge?: number;
10
+ signed?: boolean;
11
+ expires?: Date;
12
+ httpOnly?: boolean;
13
+ path?: string;
14
+ domain?: string;
15
+ secure?: boolean | 'auto';
16
+ sameSite?: boolean | 'lax' | 'strict' | 'none';
17
+ priority?: 'low' | 'medium' | 'high';
18
+ }
19
+ export interface SessionOptions {
20
+ secret: string | string[];
21
+ name?: string;
22
+ store?: Store;
23
+ cookie?: SessionCookieOptions;
24
+ genid?: (ctx: ShokupanContext) => string;
25
+ resave?: boolean;
26
+ saveUninitialized?: boolean;
27
+ rolling?: boolean;
28
+ unset?: 'destroy' | 'keep';
29
+ }
30
+ export interface Store extends EventEmitter {
31
+ get(sid: string, callback: (err: any, session?: SessionData | null) => void): void;
32
+ set(sid: string, session: SessionData, callback?: (err?: any) => void): void;
33
+ destroy(sid: string, callback?: (err?: any) => void): void;
34
+ touch?(sid: string, session: SessionData, callback?: (err?: any) => void): void;
35
+ all?(callback: (err: any, obj?: {
36
+ [sid: string]: SessionData;
37
+ } | null) => void): void;
38
+ length?(callback: (err: any, length?: number) => void): void;
39
+ clear?(callback?: (err?: any) => void): void;
40
+ load?(sid: string, fn: (err: any, session?: SessionData | null) => void): void;
41
+ createSession?(req: any, session: SessionData): SessionData;
42
+ }
43
+ declare class Cookie implements SessionCookieOptions {
44
+ maxAge?: number;
45
+ signed?: boolean;
46
+ expires?: Date;
47
+ httpOnly?: boolean;
48
+ path?: string;
49
+ domain?: string;
50
+ secure?: boolean | 'auto';
51
+ sameSite?: boolean | 'lax' | 'strict' | 'none';
52
+ originalMaxAge: number | undefined;
53
+ constructor(options?: SessionCookieOptions);
54
+ serialize(name: string, val: string): string;
55
+ }
56
+ export declare class MemoryStore extends EventEmitter implements Store {
57
+ private sessions;
58
+ get(sid: string, cb: (err: any, session?: SessionData | null) => void): void;
59
+ set(sid: string, sess: SessionData, cb?: (err?: any) => void): void;
60
+ destroy(sid: string, cb?: (err?: any) => void): void;
61
+ touch(sid: string, sess: SessionData, cb?: (err?: any) => void): void;
62
+ all(cb: (err: any, obj?: {
63
+ [sid: string]: SessionData;
64
+ } | null) => void): void;
65
+ clear(cb?: (err?: any) => void): void;
66
+ }
67
+ export interface SessionContext {
68
+ session: SessionData & {
69
+ id: string;
70
+ regenerate(callback: (err: any) => void): void;
71
+ destroy(callback: (err: any) => void): void;
72
+ reload(callback: (err: any) => void): void;
73
+ save(callback: (err: any) => void): void;
74
+ touch(): void;
75
+ };
76
+ sessionID: string;
77
+ sessionStore: Store;
78
+ }
79
+ declare module "../context" {
80
+ interface ShokupanContext {
81
+ session: SessionContext['session'];
82
+ sessionID: string;
83
+ sessionStore: Store;
84
+ }
85
+ }
86
+ export declare function Session(options: SessionOptions): Middleware;
87
+ export {};
@@ -0,0 +1,18 @@
1
+ import { Middleware } from '../types';
2
+ export interface ValidationConfig {
3
+ body?: any;
4
+ query?: any;
5
+ params?: any;
6
+ headers?: any;
7
+ }
8
+ export declare class ValidationError extends Error {
9
+ errors: any[];
10
+ status: number;
11
+ constructor(errors: any[]);
12
+ }
13
+ export declare const valibot: (schema: any, parser: Function) => {
14
+ _valibot: boolean;
15
+ schema: any;
16
+ parser: Function;
17
+ };
18
+ export declare function validate(config: ValidationConfig): Middleware;
@@ -0,0 +1,34 @@
1
+ import { Method } from './types';
2
+ export type ShokupanRequestProps = {
3
+ method: Method;
4
+ url: string;
5
+ headers: Headers;
6
+ body: any;
7
+ };
8
+ /**
9
+ * This class is used to create a request object.
10
+ * It is used to make requests to the router.
11
+ */
12
+ declare class ShokupanRequestBase {
13
+ method: Method;
14
+ url: string;
15
+ headers: Headers;
16
+ body: any;
17
+ json(): Promise<any>;
18
+ text(): Promise<string>;
19
+ formData(): Promise<FormData>;
20
+ constructor(props: ShokupanRequestProps);
21
+ }
22
+ /**
23
+ * This type is used to add properties to the request object.
24
+ */
25
+ export type ShokupanRequest<T> = ShokupanRequestBase & T;
26
+ interface ShokupanConstructor {
27
+ new <T extends Record<string, any>>(props: ShokupanRequestProps): ShokupanRequest<T>;
28
+ }
29
+ /**
30
+ * This class is used to create a request object.
31
+ * It is used to make requests to the router.
32
+ */
33
+ export declare const ShokupanRequest: ShokupanConstructor;
34
+ export {};
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Custom response class to handle response state (headers, status)
3
+ * before the actual Response object is created.
4
+ */
5
+ export declare class ShokupanResponse {
6
+ private _headers;
7
+ private _status;
8
+ /**
9
+ * Get the current headers
10
+ */
11
+ get headers(): Headers;
12
+ /**
13
+ * Get the current status code
14
+ */
15
+ get status(): number;
16
+ /**
17
+ * Set the status code
18
+ */
19
+ set status(code: number);
20
+ /**
21
+ * Set a response header
22
+ * @param key Header name
23
+ * @param value Header value
24
+ */
25
+ set(key: string, value: string): this;
26
+ /**
27
+ * Append to a response header
28
+ * @param key Header name
29
+ * @param value Header value
30
+ */
31
+ append(key: string, value: string): this;
32
+ /**
33
+ * Get a response header value
34
+ * @param key Header name
35
+ */
36
+ get(key: string): string;
37
+ /**
38
+ * Check if a header exists
39
+ * @param key Header name
40
+ */
41
+ has(key: string): boolean;
42
+ }
@@ -0,0 +1,237 @@
1
+ import { OpenAPI } from '@scalar/openapi-types';
2
+ import { Shokupan } from './shokupan';
3
+ import { $appRoot, $childControllers, $childRouters, $isApplication, $isMounted, $isRouter, $mountPath, $parent } from './symbol';
4
+ import { GuardAPISpec, MethodAPISpec, OpenAPIOptions, ProcessResult, RequestOptions, ShokupanRouteConfig, StaticServeOptions, Method, ShokupanController, ShokupanHandler } from './types';
5
+ type HeadersInit = Headers | Record<string, string> | [string, string][];
6
+ export declare const RouterRegistry: Map<string, ShokupanRouter<any>>;
7
+ export declare const ShokupanApplicationTree: {};
8
+ export declare class ShokupanRouter<T extends Record<string, any> = Record<string, any>> {
9
+ private readonly config?;
10
+ private [$isApplication];
11
+ private [$isMounted];
12
+ private [$isRouter];
13
+ private [$appRoot];
14
+ private [$mountPath];
15
+ private [$parent];
16
+ [$childRouters]: ShokupanRouter<T>[];
17
+ [$childControllers]: ShokupanController[];
18
+ get rootConfig(): {
19
+ [x: string]: any;
20
+ port?: number;
21
+ hostname?: string;
22
+ development?: boolean;
23
+ enableAsyncLocalStorage?: boolean;
24
+ httpLogger?: {};
25
+ logger?: {
26
+ verbose?: boolean;
27
+ info?: {};
28
+ debug?: {};
29
+ warning?: {};
30
+ error?: {};
31
+ fatal?: {};
32
+ };
33
+ };
34
+ get root(): Shokupan<any>;
35
+ private routes;
36
+ private currentGuards;
37
+ constructor(config?: ShokupanRouteConfig);
38
+ private isRouterInstance;
39
+ /**
40
+ * Mounts a controller instance to a path prefix.
41
+ *
42
+ * Controller can be a convection router or an arbitrary class.
43
+ *
44
+ * Routes are derived from method names:
45
+ * - get(ctx) -> GET /prefix/
46
+ * - getUsers(ctx) -> GET /prefix/users
47
+ * - postCreate(ctx) -> POST /prefix/create
48
+ */
49
+ mount(prefix: string, controller: ShokupanController | ShokupanController<T> | ShokupanRouter | ShokupanRouter<T>): this;
50
+ /**
51
+ * Returns all routes attached to this router and its descendants.
52
+ */
53
+ getRoutes(): {
54
+ method: Method;
55
+ path: string;
56
+ handler: ShokupanHandler<T>;
57
+ }[];
58
+ /**
59
+ * Makes a sub request to this router.
60
+ * This is useful for triggering other methods or route handlers.
61
+ * @param options The request options.
62
+ * @returns The response.
63
+ */
64
+ subRequest(arg: {
65
+ path: string;
66
+ method?: Method;
67
+ headers?: HeadersInit;
68
+ body?: any;
69
+ } | string): Promise<Response>;
70
+ /**
71
+ * Processes a request directly.
72
+ */
73
+ processRequest(options: RequestOptions): Promise<ProcessResult>;
74
+ /**
75
+ * Find a route matching the given method and path.
76
+ * @param method HTTP method
77
+ * @param path Request path
78
+ * @returns Route handler and parameters if found, otherwise null
79
+ */
80
+ find(method: string, path: string): {
81
+ handler: ShokupanHandler<T>;
82
+ params: Record<string, string>;
83
+ } | null;
84
+ private parsePath;
85
+ /**
86
+ * Adds a route to the router.
87
+ *
88
+ * @param method - HTTP method
89
+ * @param path - URL path
90
+ * @param spec - OpenAPI specification for the route
91
+ * @param handler - Route handler function
92
+ */
93
+ add({ method, path, spec, handler, regex: customRegex, group }: {
94
+ method: Method;
95
+ path: string;
96
+ spec?: MethodAPISpec;
97
+ handler: ShokupanHandler<T>;
98
+ regex?: RegExp;
99
+ group?: string;
100
+ }): this;
101
+ /**
102
+ * Adds a GET route to the router.
103
+ *
104
+ * @param path - URL path
105
+ * @param handler - Route handler function
106
+ */
107
+ get(path: string, ...handlers: ShokupanHandler<T>[]): any;
108
+ /**
109
+ * Adds a GET route to the router.
110
+ *
111
+ * @param path - URL path
112
+ * @param spec - OpenAPI specification for the route
113
+ * @param handlers - Route handler functions
114
+ */
115
+ get(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]): any;
116
+ /**
117
+ * Adds a POST route to the router.
118
+ *
119
+ * @param path - URL path
120
+ * @param handler - Route handler function
121
+ */
122
+ post(path: string, ...handlers: ShokupanHandler<T>[]): any;
123
+ /**
124
+ * Adds a POST route to the router.
125
+ *
126
+ * @param path - URL path
127
+ * @param spec - OpenAPI specification for the route
128
+ * @param handlers - Route handler functions
129
+ */
130
+ post(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]): any;
131
+ /**
132
+ * Adds a PUT route to the router.
133
+ *
134
+ * @param path - URL path
135
+ * @param handler - Route handler function
136
+ */
137
+ put(path: string, ...handlers: ShokupanHandler<T>[]): any;
138
+ /**
139
+ * Adds a PUT route to the router.
140
+ *
141
+ * @param path - URL path
142
+ * @param spec - OpenAPI specification for the route
143
+ * @param handlers - Route handler functions
144
+ */
145
+ put(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]): any;
146
+ /**
147
+ * Adds a DELETE route to the router.
148
+ *
149
+ * @param path - URL path
150
+ * @param handler - Route handler function
151
+ */
152
+ delete(path: string, ...handlers: ShokupanHandler<T>[]): any;
153
+ /**
154
+ * Adds a DELETE route to the router.
155
+ *
156
+ * @param path - URL path
157
+ * @param spec - OpenAPI specification for the route
158
+ * @param handlers - Route handler functions
159
+ */
160
+ delete(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]): any;
161
+ /**
162
+ * Adds a PATCH route to the router.
163
+ *
164
+ * @param path - URL path
165
+ * @param handler - Route handler function
166
+ */
167
+ patch(path: string, ...handlers: ShokupanHandler<T>[]): any;
168
+ /**
169
+ * Adds a PATCH route to the router.
170
+ *
171
+ * @param path - URL path
172
+ * @param spec - OpenAPI specification for the route
173
+ * @param handlers - Route handler functions
174
+ */
175
+ patch(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]): any;
176
+ /**
177
+ * Adds a OPTIONS route to the router.
178
+ *
179
+ * @param path - URL path
180
+ * @param handler - Route handler function
181
+ */
182
+ options(path: string, ...handlers: ShokupanHandler<T>[]): any;
183
+ /**
184
+ * Adds a OPTIONS route to the router.
185
+ *
186
+ * @param path - URL path
187
+ * @param spec - OpenAPI specification for the route
188
+ * @param handlers - Route handler functions
189
+ */
190
+ options(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]): any;
191
+ /**
192
+ * Adds a HEAD route to the router.
193
+ *
194
+ * @param path - URL path
195
+ * @param handler - Route handler function
196
+ */
197
+ head(path: string, ...handlers: ShokupanHandler<T>[]): any;
198
+ /**
199
+ * Adds a HEAD route to the router.
200
+ *
201
+ * @param path - URL path
202
+ * @param spec - OpenAPI specification for the route
203
+ * @param handlers - Route handler functions
204
+ */
205
+ head(path: string, spec: MethodAPISpec, ...handlers: ShokupanHandler<T>[]): any;
206
+ /**
207
+ * Adds a guard to the router that applies to all routes added **after** this point.
208
+ * Guards must return true or call `ctx.next()` to allow the request to continue.
209
+ *
210
+ * @param handler - Guard handler function
211
+ */
212
+ guard(handler: ShokupanHandler<T>): void;
213
+ /**
214
+ * Adds a guard to the router that applies to all routes added **after** this point.
215
+ * Guards must return true or call `ctx.next()` to allow the request to continue.
216
+
217
+ * @param spec - OpenAPI specification for the guard
218
+ * @param handler - Guard handler function
219
+ */
220
+ guard(spec: GuardAPISpec, handler: ShokupanHandler<T>): any;
221
+ /**
222
+ * Statically serves a directory with standard options.
223
+ * @param uriPath URL path prefix
224
+ * @param options Configuration options or root directory string
225
+ */
226
+ static(uriPath: string, options: string | StaticServeOptions<T>): this;
227
+ /**
228
+ * Attach the verb routes with their overload signatures.
229
+ * Use compose to handle multiple handlers (middleware).
230
+ */
231
+ private attachVerb;
232
+ /**
233
+ * Generates an OpenAPI 3.1 Document by recursing through the router and its descendants.
234
+ */
235
+ generateApiSpec(options?: OpenAPIOptions): OpenAPI.Document;
236
+ }
237
+ export {};
@@ -0,0 +1,41 @@
1
+ import { ShokupanRequest } from './request';
2
+ import { ShokupanRouter } from './router';
3
+ import { $dispatch } from './symbol';
4
+ import { Middleware, ProcessResult, RequestOptions, ShokupanConfig } from './types';
5
+ export declare class Shokupan<T = any> extends ShokupanRouter<T> {
6
+ readonly applicationConfig: ShokupanConfig;
7
+ private middleware;
8
+ get logger(): {
9
+ verbose?: boolean;
10
+ info?: {};
11
+ debug?: {};
12
+ warning?: {};
13
+ error?: {};
14
+ fatal?: {};
15
+ };
16
+ constructor(applicationConfig?: ShokupanConfig);
17
+ /**
18
+ * Adds middleware to the application.
19
+ */
20
+ use(middleware: Middleware): this;
21
+ /**
22
+ * Starts the application server.
23
+ *
24
+ * @param port - The port to listen on. If not specified, the port from the configuration is used. If that is not specified, port 3000 is used.
25
+ * @returns The server instance.
26
+ */
27
+ listen(port?: number): Bun.Server;
28
+ [$dispatch](req: ShokupanRequest<T>): Promise<Response>;
29
+ /**
30
+ * Processes a request by wrapping the standard fetch method.
31
+ */
32
+ processRequest(options: RequestOptions): Promise<ProcessResult>;
33
+ /**
34
+ * Handles an incoming request (Bun.serve interface).
35
+ * This logic contains the middleware chain and router dispatch.
36
+ *
37
+ * @param req - The request to handle.
38
+ * @returns The response to send.
39
+ */
40
+ fetch(req: Request): Promise<Response>;
41
+ }
@@ -0,0 +1,13 @@
1
+ export declare const $isApplication: unique symbol;
2
+ export declare const $appRoot: unique symbol;
3
+ export declare const $isMounted: unique symbol;
4
+ export declare const $routeMethods: unique symbol;
5
+ export declare const $routeArgs: unique symbol;
6
+ export declare const $controllerPath: unique symbol;
7
+ export declare const $middleware: unique symbol;
8
+ export declare const $isRouter: unique symbol;
9
+ export declare const $parent: unique symbol;
10
+ export declare const $childRouters: unique symbol;
11
+ export declare const $childControllers: unique symbol;
12
+ export declare const $mountPath: unique symbol;
13
+ export declare const $dispatch: unique symbol;
@@ -0,0 +1,142 @@
1
+ import { OpenAPI } from '@scalar/openapi-types';
2
+ import { ShokupanContext } from './context';
3
+ import { $isRouter } from './symbol';
4
+ export type DeepPartial<T> = T extends object ? {
5
+ [P in keyof T]?: DeepPartial<T[P]>;
6
+ } : T;
7
+ export type MethodAPISpec = OpenAPI.Operation;
8
+ export type GuardAPISpec = DeepPartial<OpenAPI.Operation>;
9
+ export type RouterAPISpec = OpenAPI.Operation & Pick<Required<OpenAPI.Operation>, 'tags'> & {
10
+ group: string;
11
+ };
12
+ export interface OpenAPIOptions {
13
+ info?: OpenAPI.Document['info'];
14
+ servers?: OpenAPI.Document['servers'];
15
+ components?: OpenAPI.Document['components'];
16
+ tags?: OpenAPI.Document['tags'];
17
+ externalDocs?: OpenAPI.Document['externalDocs'];
18
+ defaultTagGroup?: string;
19
+ defaultTag?: string;
20
+ }
21
+ export interface CookieOptions {
22
+ maxAge?: number;
23
+ expires?: Date;
24
+ httpOnly?: boolean;
25
+ secure?: boolean;
26
+ domain?: string;
27
+ path?: string;
28
+ sameSite?: boolean | 'lax' | 'strict' | 'none' | 'Lax' | 'Strict' | 'None';
29
+ priority?: 'low' | 'medium' | 'high' | 'Low' | 'Medium' | 'High';
30
+ }
31
+ export type ShokupanHandler<T extends Record<string, any> = Record<string, any>> = (ctx: ShokupanContext<T>, next?: NextFn) => Promise<any> | any;
32
+ export declare const HTTPMethods: string[];
33
+ export type Method = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "OPTIONS" | "HEAD" | "ALL";
34
+ export declare enum RouteParamType {
35
+ BODY = "BODY",
36
+ PARAM = "PARAM",
37
+ QUERY = "QUERY",
38
+ HEADER = "HEADER",
39
+ REQUEST = "REQUEST",
40
+ CONTEXT = "CONTEXT"
41
+ }
42
+ export type NextFn = () => Promise<any>;
43
+ export type Middleware = (ctx: ShokupanContext<unknown>, next: NextFn) => Promise<any> | any;
44
+ export type ShokupanRouteConfig = DeepPartial<{
45
+ name: string;
46
+ group: string;
47
+ openapi: DeepPartial<OpenAPI.Operation>;
48
+ }>;
49
+ export type ShokupanRoute = {
50
+ method: Method;
51
+ path: string;
52
+ regex: RegExp;
53
+ keys: string[];
54
+ handler: ShokupanHandler;
55
+ handlerSpec?: MethodAPISpec;
56
+ group?: string;
57
+ guards?: {
58
+ handler: ShokupanHandler;
59
+ spec?: GuardAPISpec;
60
+ }[];
61
+ };
62
+ export type ShokupanConfig<T extends Record<string, any> = Record<string, any>> = DeepPartial<{
63
+ port: number;
64
+ hostname: string;
65
+ development: boolean;
66
+ enableAsyncLocalStorage: boolean;
67
+ httpLogger: (ctx: ShokupanContext<T>) => void;
68
+ logger: {
69
+ verbose: boolean;
70
+ info: (msg: string, props: Record<string, any>) => void;
71
+ debug: (msg: string, props: Record<string, any>) => void;
72
+ warning: (msg: string, props: Record<string, any>) => void;
73
+ error: (msg: string, props: Record<string, any>) => void;
74
+ /**
75
+ * Something fatally went wrong and the application cannot continue.
76
+ */
77
+ fatal: (msg: string, props: Record<string, any>) => void;
78
+ };
79
+ [key: string]: any;
80
+ }>;
81
+ export interface RequestOptions {
82
+ path?: string;
83
+ url?: string;
84
+ method?: Method;
85
+ headers?: Record<string, string>;
86
+ body?: any;
87
+ query?: Record<string, string>;
88
+ }
89
+ export interface ProcessResult {
90
+ status: number;
91
+ headers: Record<string, string>;
92
+ data: any;
93
+ }
94
+ export type ShokupanController<T = any> = (new (...args: any[]) => T) & {
95
+ [$isRouter]?: undefined;
96
+ };
97
+ export interface StaticServeHooks<T extends Record<string, any>> {
98
+ onRequest?: (ctx: ShokupanContext<T>) => Promise<Response | void> | Response | void;
99
+ onResponse?: (ctx: ShokupanContext<T>, response: Response) => Promise<Response> | Response;
100
+ }
101
+ export interface StaticServeOptions<T extends Record<string, any>> {
102
+ /**
103
+ * Root directory to serve files from.
104
+ * Can be an absolute path or relative to the CWD.
105
+ */
106
+ root?: string;
107
+ /**
108
+ * Whether to list directory contents if no index file is found.
109
+ * @default false
110
+ */
111
+ listDirectory?: boolean;
112
+ /**
113
+ * Index file(s) to look for when a directory is requested.
114
+ * @default ['index.html', 'index.htm']
115
+ */
116
+ index?: string | string[];
117
+ /**
118
+ * Hooks to intercept requests/responses.
119
+ */
120
+ hooks?: StaticServeHooks<T>;
121
+ /**
122
+ * How to treat dotfiles (files starting with .)
123
+ * 'allow': Serve them
124
+ * 'deny': Return 403
125
+ * 'ignore': Return 404
126
+ * @default 'ignore'
127
+ */
128
+ dotfiles?: 'allow' | 'deny' | 'ignore';
129
+ /**
130
+ * Regex or glob patterns to exclude
131
+ */
132
+ exclude?: (string | RegExp)[];
133
+ /**
134
+ * Try to append these extensions to the path if the file is not found.
135
+ * e.g. ['html', 'htm']
136
+ */
137
+ extensions?: string[];
138
+ /**
139
+ * OpenAPI specification for the static route.
140
+ */
141
+ openapi?: MethodAPISpec;
142
+ }
@@ -0,0 +1,3 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ export declare const asyncContext: AsyncLocalStorage<Map<string, any>>;
3
+ export declare function runInContext<T>(callback: () => T, initialStore?: Map<string, any>): T;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Simple object check.
3
+ */
4
+ export declare function isObject(item: any): item is Record<string, any>;
5
+ /**
6
+ * Deep merge two objects.
7
+ *
8
+ * - Arrays are concatenated.
9
+ * - Objects are merged recursively.
10
+ * - Primitives are overwritten.
11
+ */
12
+ export declare function deepMerge<T extends Record<string, any>>(target: T, ...sources: Partial<T>[]): T;
@@ -0,0 +1,9 @@
1
+ import { Middleware, ShokupanHandler } from '../types';
2
+ /**
3
+ * Wraps a middleware function with an OpenTelemetry span.
4
+ */
5
+ export declare function traceMiddleware(fn: Middleware, name?: string): Middleware;
6
+ /**
7
+ * Wraps a route handler with an OpenTelemetry span.
8
+ */
9
+ export declare function traceHandler(fn: ShokupanHandler | ((...args: any[]) => any), name: string): ShokupanHandler;