shokupan 0.11.0 → 0.12.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.
Files changed (48) hide show
  1. package/README.md +46 -1815
  2. package/dist/{analyzer-CnKnQ5KV.js → analyzer-BkNQHWj4.js} +2 -2
  3. package/dist/{analyzer-CnKnQ5KV.js.map → analyzer-BkNQHWj4.js.map} +1 -1
  4. package/dist/{analyzer-BAhvpNY_.cjs → analyzer-DM-OlRq8.cjs} +2 -2
  5. package/dist/{analyzer-BAhvpNY_.cjs.map → analyzer-DM-OlRq8.cjs.map} +1 -1
  6. package/dist/{analyzer.impl-CfpMu4-g.cjs → analyzer.impl-CVJ8zfGQ.cjs} +11 -3
  7. package/dist/analyzer.impl-CVJ8zfGQ.cjs.map +1 -0
  8. package/dist/{analyzer.impl-DCiqlXI5.js → analyzer.impl-CsA1bS_s.js} +11 -3
  9. package/dist/analyzer.impl-CsA1bS_s.js.map +1 -0
  10. package/dist/cli.cjs +1 -1
  11. package/dist/cli.js +1 -1
  12. package/dist/context.d.ts +40 -8
  13. package/dist/index.cjs +1011 -300
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.js +1011 -300
  16. package/dist/index.js.map +1 -1
  17. package/dist/plugins/application/api-explorer/static/theme.css +4 -0
  18. package/dist/plugins/application/auth.d.ts +5 -0
  19. package/dist/plugins/application/dashboard/fetch-interceptor.d.ts +12 -0
  20. package/dist/plugins/application/dashboard/plugin.d.ts +9 -0
  21. package/dist/plugins/application/dashboard/static/requests.js +537 -251
  22. package/dist/plugins/application/dashboard/static/tabulator.css +23 -3
  23. package/dist/plugins/application/dashboard/static/theme.css +4 -0
  24. package/dist/plugins/application/mcp-server/plugin.d.ts +39 -0
  25. package/dist/plugins/application/openapi/analyzer.impl.d.ts +4 -0
  26. package/dist/plugins/middleware/compression.d.ts +12 -2
  27. package/dist/plugins/middleware/rate-limit.d.ts +5 -0
  28. package/dist/router.d.ts +6 -5
  29. package/dist/server.d.ts +22 -0
  30. package/dist/shokupan.d.ts +24 -1
  31. package/dist/util/adapter/bun.d.ts +8 -0
  32. package/dist/util/adapter/index.d.ts +4 -0
  33. package/dist/util/adapter/interface.d.ts +12 -0
  34. package/dist/util/adapter/node.d.ts +8 -0
  35. package/dist/util/adapter/wintercg.d.ts +5 -0
  36. package/dist/util/body-parser.d.ts +30 -0
  37. package/dist/util/decorators.d.ts +20 -3
  38. package/dist/util/di.d.ts +3 -8
  39. package/dist/util/metadata.d.ts +18 -0
  40. package/dist/util/request.d.ts +1 -0
  41. package/dist/util/symbol.d.ts +1 -0
  42. package/dist/util/types.d.ts +132 -3
  43. package/package.json +3 -1
  44. package/dist/analyzer.impl-CfpMu4-g.cjs.map +0 -1
  45. package/dist/analyzer.impl-DCiqlXI5.js.map +0 -1
  46. package/dist/plugins/application/dashboard/static/failures.js +0 -85
  47. package/dist/plugins/application/http-server.d.ts +0 -13
  48. package/dist/util/adapter/adapters.d.ts +0 -19
@@ -16,6 +16,21 @@
16
16
  font-weight: bold;
17
17
  }
18
18
 
19
+ .tabulator-menu .tabulator-menu-separator {
20
+ border-color: var(--card-border);
21
+ }
22
+
23
+ .tabulator-popup-container {
24
+ background-color: var(--bg-card);
25
+ border: 1px solid var(--card-border);
26
+ border-radius: 4px;
27
+ color: var(--text-primary);
28
+ }
29
+
30
+ .tabulator-menu .tabulator-menu-item:not(.tabulator-menu-item-disabled):hover {
31
+ background-color: var(--bg-primary);
32
+ }
33
+
19
34
  .tabulator .tabulator-header .tabulator-col {
20
35
  background-color: var(--bg-card);
21
36
  border-right: 1px solid var(--card-border);
@@ -58,6 +73,7 @@
58
73
  border-bottom: 1px solid var(--card-border);
59
74
  color: var(--text-primary);
60
75
  transition: background-color 100ms ease;
76
+ min-height: unset !important;
61
77
  }
62
78
 
63
79
  /* Higher specificity to override Tabulator default themes */
@@ -72,12 +88,12 @@
72
88
  }
73
89
 
74
90
  .tabulator .tabulator-row.tabulator-selected {
75
- background-color: var(--bg-primary) !important;
91
+ background-color: var(--table-row-selected-color) !important;
76
92
  color: var(--text-primary);
77
93
  }
78
94
 
79
95
  .tabulator .tabulator-row:hover {
80
- background-color: var(--bg-primary) !important;
96
+ background-color: var(--table-row-hover-color) !important;
81
97
  color: var(--text-primary);
82
98
  cursor: pointer;
83
99
  }
@@ -85,7 +101,7 @@
85
101
  /* Cells */
86
102
  .tabulator .tabulator-row .tabulator-cell {
87
103
  border-right: 1px solid var(--card-border);
88
- padding: 10px;
104
+ padding: 6px;
89
105
  align-content: center;
90
106
  }
91
107
 
@@ -115,4 +131,8 @@
115
131
  /* Sorting Icons */
116
132
  .tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-arrow {
117
133
  border-bottom-color: var(--text-secondary);
134
+ }
135
+
136
+ .tabulator [tabulator-field="timestamp"] {
137
+ padding: 0 4px !important;
118
138
  }
@@ -24,6 +24,7 @@
24
24
 
25
25
  --text-primary: #F0F0F0;
26
26
  --text-secondary: var(--palette-dark-accent);
27
+ --text-flavor: #ffcc80;
27
28
  --text-muted: rgba(214, 211, 209, 0.5);
28
29
 
29
30
  --primary: var(--palette-dark-primary);
@@ -34,12 +35,15 @@
34
35
  --card-border: rgba(214, 211, 209, 0.2);
35
36
 
36
37
  --table-header-border-color: rgba(214, 211, 209, 0.2);
38
+ --table-row-hover-color: #382818;
39
+ --table-row-selected-color: #48331e;
37
40
 
38
41
  --link-color: var(--palette-dark-primary);
39
42
  --link-hover: #FFCBA0;
40
43
 
41
44
  --button-bg: var(--palette-dark-primary);
42
45
  --button-text: #1A1614;
46
+
43
47
  }
44
48
 
45
49
  * {
@@ -0,0 +1,39 @@
1
+ import { Shokupan } from '../../../shokupan';
2
+ import { ShokupanPlugin } from '../../../util/types';
3
+ export interface MCPServerPluginOptions {
4
+ /**
5
+ * The path to mount the MCP server to.
6
+ */
7
+ path?: string;
8
+ /**
9
+ * The root directory to scan for OpenAPI documents.
10
+ */
11
+ rootDir?: string;
12
+ /**
13
+ * Whether to allow the introspection tool.
14
+ */
15
+ allowIntrospection?: boolean;
16
+ /**
17
+ * Whether to allow tool execution.
18
+ */
19
+ allowToolExecution?: boolean;
20
+ }
21
+ /**
22
+ * Attaches an MCP server to the application.
23
+ * This MCP server is focus-designed to provide introspection and tool execution capabilities.
24
+ *
25
+ * If your application design requires anything custom, implement your own MCP server.
26
+ */
27
+ export declare class MCPServerPlugin implements ShokupanPlugin {
28
+ private options;
29
+ private router;
30
+ private mcpServer;
31
+ private transport;
32
+ private analyzer;
33
+ constructor(options?: MCPServerPluginOptions);
34
+ onInit(app: Shokupan): void;
35
+ private setupRoutes;
36
+ private registerTools;
37
+ private registerResources;
38
+ private registerPrompts;
39
+ }
@@ -109,6 +109,10 @@ export declare class OpenAPIAnalyzer {
109
109
  /**
110
110
  * Main analysis entry point
111
111
  */
112
+ /**
113
+ * Main analysis entry point
114
+ */
115
+ private cachedResult?;
112
116
  /**
113
117
  * Main analysis entry point
114
118
  */
@@ -1,13 +1,23 @@
1
1
  import { Middleware } from '../../util/types';
2
2
  export interface CompressionOptions {
3
3
  /**
4
- * Minimum byte size to compress
4
+ * Minimum byte size to compress responses
5
5
  */
6
6
  threshold?: number;
7
7
  /**
8
- * Allowed algorithms
8
+ * Allowed algorithms for response compression
9
9
  */
10
10
  allowedAlgorithms?: string[];
11
+ /**
12
+ * Enable request decompression
13
+ * @default true
14
+ */
15
+ decompress?: boolean;
16
+ /**
17
+ * Maximum size of decompressed request body in bytes to prevent zipbomb style attacks
18
+ * @default 10485760 (10MB)
19
+ */
20
+ maxDecompressedSize?: number;
11
21
  }
12
22
  /**
13
23
  * Compression middleware.
@@ -49,6 +49,11 @@ export interface RateLimitOptions {
49
49
  * List of trusted proxy IPs
50
50
  */
51
51
  trustedProxies?: string[];
52
+ /**
53
+ * Interval in milliseconds to clean up expired entries.
54
+ * Defaults to windowMs.
55
+ */
56
+ cleanupInterval?: number;
52
57
  }
53
58
  /**
54
59
  * Rate limit middleware.
package/dist/router.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { ShokupanContext } from './context';
2
2
  import { Shokupan } from './shokupan';
3
- import { SurrealDatastore } from './util/datastore';
4
3
  import { $appRoot, $childControllers, $childRouters, $isApplication, $isMounted, $isRouter, $mountPath, $parent, $routes } from './util/symbol';
5
4
  import { GuardAPISpec, HeadersInit, JSXRenderer, Method, MethodAPISpec, Middleware, OpenAPIOptions, ProcessResult, RequestOptions, RouteMetadata, RouteParams, ShokupanController, ShokupanHandler, ShokupanHooks, ShokupanRoute, ShokupanRouteConfig, StaticServeOptions } from './util/types';
6
5
  export declare const RouterRegistry: Map<string, ShokupanRouter<any>>;
@@ -95,7 +94,6 @@ export declare class ShokupanRouter<T extends Record<string, any> = Record<strin
95
94
  get hasBeforeValidateHook(): boolean;
96
95
  get hasAfterValidateHook(): boolean;
97
96
  requestTimeout?: number;
98
- get db(): SurrealDatastore | undefined;
99
97
  private hookCache;
100
98
  private hooksInitialized;
101
99
  middleware: Middleware[];
@@ -112,6 +110,7 @@ export declare class ShokupanRouter<T extends Record<string, any> = Record<strin
112
110
  reusePort: boolean;
113
111
  controllersOnly: boolean;
114
112
  enableTracing?: boolean;
113
+ queryParserMode?: "extended" | "simple" | "strict";
115
114
  jsonParser?: "native" | "parse-json" | "secure-json-parse";
116
115
  autoBackpressureFeedback?: boolean;
117
116
  autoBackpressureLevel?: number;
@@ -131,11 +130,12 @@ export declare class ShokupanRouter<T extends Record<string, any> = Record<strin
131
130
  fatal: (msg: string, props: Record<string, any>) => void;
132
131
  };
133
132
  readTimeout: number;
133
+ maxBodySize?: number;
134
134
  requestTimeout: number;
135
135
  writeTimeout: number;
136
136
  renderer: JSXRenderer;
137
137
  serverFactory: import('.').ServerFactory;
138
- adapter?: "bun" | "node" | "wintercg" | import('./util/adapter/adapters').ServerAdapter;
138
+ adapter?: "bun" | "node" | "wintercg" | import('./util/adapter').ServerAdapter;
139
139
  fileSystem?: import('./util/adapter/filesystem').FileSystemAdapter;
140
140
  hooks: ShokupanHooks<Record<string, any>> | ShokupanHooks<Record<string, any>>[];
141
141
  validateStatusCodes: boolean;
@@ -173,6 +173,7 @@ export declare class ShokupanRouter<T extends Record<string, any> = Record<strin
173
173
  spec_url: string;
174
174
  }>;
175
175
  };
176
+ securityHeaders?: boolean | any;
176
177
  }>;
177
178
  get root(): Shokupan<any>;
178
179
  [$routes]: ShokupanRoute[];
@@ -185,7 +186,7 @@ export declare class ShokupanRouter<T extends Record<string, any> = Record<strin
185
186
  * Middleware will run for all routes matched by this router.
186
187
  */
187
188
  use(middleware: Middleware): this;
188
- getComponentRegistry(): {
189
+ get registry(): {
189
190
  metadata: RouteMetadata;
190
191
  middleware: {
191
192
  name: string;
@@ -245,7 +246,7 @@ export declare class ShokupanRouter<T extends Record<string, any> = Record<strin
245
246
  /**
246
247
  * Registers a controller instance to the router.
247
248
  */
248
- registerControllerInstance(controller: any): void;
249
+ bindController(controller: any): void;
249
250
  /**
250
251
  * Returns all registered event handlers.
251
252
  */
@@ -0,0 +1,22 @@
1
+ import { Shokupan } from './shokupan';
2
+ /**
3
+ * Shokupan Server
4
+ *
5
+ * Responsible for the lifecycle of the HTTP server (listen, stop)
6
+ * and managing the underlying adapter (Bun, Node, etc).
7
+ */
8
+ export declare class ShokupanServer {
9
+ private app;
10
+ private server?;
11
+ private adapter?;
12
+ constructor(app: Shokupan);
13
+ /**
14
+ * Starts the application server.
15
+ * @param port The port to listen on.
16
+ */
17
+ listen(port?: number): Promise<any>;
18
+ /**
19
+ * Stops the server.
20
+ */
21
+ stop(closeActiveConnections?: boolean): Promise<void>;
22
+ }
@@ -76,9 +76,11 @@ export declare class Shokupan<T = any> extends ShokupanRouter<T> {
76
76
  private asyncApiSpecPromise?;
77
77
  private composedMiddleware?;
78
78
  private cpuMonitor?;
79
- private server?;
79
+ server?: Server<any>;
80
+ private httpServer?;
80
81
  private datastore?;
81
82
  dbPromise?: Promise<any>;
83
+ private rootTrie?;
82
84
  get db(): SurrealDatastore | undefined;
83
85
  get logger(): {
84
86
  verbose: boolean;
@@ -114,6 +116,17 @@ export declare class Shokupan<T = any> extends ShokupanRouter<T> {
114
116
  * This happens after generateOpenApi() but before the server starts listening (or at least before it finishes startup if async).
115
117
  */
116
118
  onSpecAvailable(callback: (spec: any) => void | Promise<void>): this;
119
+ /**
120
+ * Starts the application server.
121
+ *
122
+ * @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.
123
+ * @returns The server instance.
124
+ */
125
+ /**
126
+ * Prepare the application for listening.
127
+ * Use this if you want to initialize the app without starting the server immediately.
128
+ */
129
+ start(): Promise<void>;
117
130
  /**
118
131
  * Starts the application server.
119
132
  *
@@ -155,4 +168,14 @@ export declare class Shokupan<T = any> extends ShokupanRouter<T> {
155
168
  */
156
169
  fetch(req: Request, server?: Server<any>): Promise<Response>;
157
170
  private handleRequest;
171
+ /**
172
+ * Compiles all routes into a master Trie for O(1) router lookup.
173
+ * Use this if adding routes dynamically after start (not recommended but possible).
174
+ */
175
+ compile(): void;
176
+ private flattenRoutes;
177
+ find(method: string, path: string): {
178
+ handler: import('.').ShokupanHandler<T>;
179
+ params: Record<string, string>;
180
+ };
158
181
  }
@@ -0,0 +1,8 @@
1
+ import { Server } from 'bun';
2
+ import { Shokupan } from '../../shokupan';
3
+ import { ServerAdapter } from './interface';
4
+ export declare class BunAdapter implements ServerAdapter {
5
+ private server?;
6
+ listen(port: number, app: Shokupan): Promise<Server<any>>;
7
+ stop(): Promise<void>;
8
+ }
@@ -0,0 +1,4 @@
1
+ export * from './bun';
2
+ export * from './interface';
3
+ export * from './node';
4
+ export * from './wintercg';
@@ -0,0 +1,12 @@
1
+ import { Server } from 'bun';
2
+ import { Shokupan } from '../../shokupan';
3
+ export interface ServerAdapter {
4
+ /**
5
+ * Start listening on the specified port.
6
+ */
7
+ listen(port: number, app: Shokupan): Promise<Server<any>>;
8
+ /**
9
+ * Stop the server.
10
+ */
11
+ stop?(): Promise<void>;
12
+ }
@@ -0,0 +1,8 @@
1
+ import { Server } from 'bun';
2
+ import { Shokupan } from '../../shokupan';
3
+ import { ServerAdapter } from './interface';
4
+ export declare class NodeAdapter implements ServerAdapter {
5
+ private server?;
6
+ listen(port: number, app: Shokupan): Promise<Server<any>>;
7
+ stop(): Promise<void>;
8
+ }
@@ -0,0 +1,5 @@
1
+ import { Shokupan } from '../../shokupan';
2
+ import { ServerAdapter } from './interface';
3
+ export declare class WinterCGAdapter implements ServerAdapter {
4
+ listen(port: number, app: Shokupan): Promise<any>;
5
+ }
@@ -0,0 +1,30 @@
1
+ import { ShokupanRequest } from './request';
2
+ import { ShokupanConfig } from './types';
3
+ /**
4
+ * Utility class for parsing request bodies.
5
+ * Handles size limits, parsing, and caching logic detached from the Context.
6
+ */
7
+ export declare class BodyParser {
8
+ /**
9
+ * Parses the body of a request based on Content-Type header.
10
+ * @param req The ShokupanRequest object
11
+ * @param config Application configuration for limits and parser options
12
+ * @returns The parsed body or throws an error
13
+ */
14
+ static parse(req: ShokupanRequest<any>, config?: ShokupanConfig): Promise<{
15
+ type: string;
16
+ body: any;
17
+ }>;
18
+ /**
19
+ * Parsing helper for JSON
20
+ */
21
+ static parseJson(req: ShokupanRequest<any>, parserType: 'native' | 'parse-json' | 'secure-json-parse', maxBodySize: number): Promise<any>;
22
+ /**
23
+ * Parsing helper for FormData
24
+ */
25
+ static parseFormData(req: ShokupanRequest<any>, maxBodySize: number): Promise<FormData>;
26
+ /**
27
+ * Reads raw body as string with size enforcement
28
+ */
29
+ static readRawBody(req: ShokupanRequest<any>, maxBodySize: number): Promise<string>;
30
+ }
@@ -5,9 +5,26 @@ import { AsyncAPISpec, GuardAPISpec, MethodAPISpec, Middleware } from './types';
5
5
  */
6
6
  export declare function Controller(path?: string): (target: any) => void;
7
7
  /**
8
- * Decorator: Applies middleware to a class or method.
8
+ * Registers this class as a **Singleton** service.
9
+ * A single instance will be created and shared across the process.
9
10
  */
10
- export declare function Use(...middleware: Middleware[]): (target: any, propertyKey?: string, descriptor?: PropertyDescriptor) => void;
11
+ export declare function Injectable(scope: 'singleton'): ClassDecorator;
12
+ /**
13
+ * Registers this class as an **Instanced** (Transient) service.
14
+ * A new instance will be created every time dependency is resolved.
15
+ */
16
+ export declare function Injectable(scope: 'instanced'): ClassDecorator;
17
+ /**
18
+ * Property/Parameter Decorator: Injects a service.
19
+ * Used on class properties or constructor parameters.
20
+ */
21
+ export declare function Inject(token: any): PropertyDecorator & ParameterDecorator;
22
+ /**
23
+ * Decorator: Applies middleware OR injects dependencies.
24
+ * - Class/Method: Middleware
25
+ * - Property/Parameter: Dependency Injection
26
+ */
27
+ export declare function Use(tokenOrMiddleware?: any | Middleware, ...moreMiddleware: Middleware[]): (target: any, propertyKey?: string, indexOrDescriptor?: PropertyDescriptor | number) => void;
11
28
  /**
12
29
  * Decorator: Binds a parameter to the request body.
13
30
  */
@@ -76,4 +93,4 @@ export declare function Event(eventName: string): (target: any, propertyKey: str
76
93
  /**
77
94
  * Decorator: Applies a rate limit to a class or method.
78
95
  */
79
- export declare function RateLimit(options: RateLimitOptions): (target: any, propertyKey?: string, descriptor?: PropertyDescriptor) => void;
96
+ export declare function RateLimit(options: RateLimitOptions): (target: any, propertyKey?: string, indexOrDescriptor?: PropertyDescriptor | number) => void;
package/dist/util/di.d.ts CHANGED
@@ -6,13 +6,8 @@ export declare class Container {
6
6
  static register<T>(target: new (...args: any[]) => T, instance: T): void;
7
7
  static get<T>(target: new (...args: any[]) => T): T | undefined;
8
8
  static has(target: any): boolean;
9
+ private static cache;
10
+ private static resolvingStack;
9
11
  static resolve<T>(target: new (...args: any[]) => T): T;
12
+ static teardown(): Promise<void>;
10
13
  }
11
- /**
12
- * Decorator to mark a class as injectable (Service).
13
- */
14
- export declare function Injectable(): (target: any) => void;
15
- /**
16
- * Property Decorator: Injects a service.
17
- */
18
- export declare function Inject(token: any): (target: any, key: string) => void;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Lightweight Polyfill for Reflect Metadata API.
3
+ *
4
+ * Replaces the need for 'reflect-metadata' package to reduce bundle size
5
+ * while maintaining compatibility with TypeScript's emitDecoratorMetadata.
6
+ */
7
+ export declare function defineMetadata(key: string | symbol, value: any, target: any, propertyKey?: string | symbol): void;
8
+ export declare function getMetadata(key: string | symbol, target: any, propertyKey?: string | symbol): any;
9
+ declare global {
10
+ namespace Reflect {
11
+ function defineMetadata(metadataKey: any, metadataValue: any, target: Object, propertyKey?: string | symbol): void;
12
+ function getMetadata(metadataKey: any, target: Object, propertyKey?: string | symbol): any;
13
+ function metadata(metadataKey: any, metadataValue: any): {
14
+ (target: Function): void;
15
+ (target: Object, propertyKey: string | symbol): void;
16
+ };
17
+ }
18
+ }
@@ -18,6 +18,7 @@ declare class ShokupanRequestBase {
18
18
  text(): Promise<string>;
19
19
  formData(): Promise<FormData>;
20
20
  constructor(props: ShokupanRequestProps);
21
+ clone(): ShokupanRequest<any>;
21
22
  }
22
23
  /**
23
24
  * This type is used to add properties to the request object.
@@ -29,6 +29,7 @@ export declare const $cachedProtocol: unique symbol;
29
29
  export declare const $cachedHost: unique symbol;
30
30
  export declare const $cachedOrigin: unique symbol;
31
31
  export declare const $cachedQuery: unique symbol;
32
+ export declare const $cachedCookies: unique symbol;
32
33
  export declare const $ws: unique symbol;
33
34
  export declare const $socket: unique symbol;
34
35
  export declare const $io: unique symbol;
@@ -3,6 +3,8 @@ import { Server } from 'bun';
3
3
  import { Server as NodeServer } from 'node:http';
4
4
  import { ConnectOptions, Engines } from 'surrealdb';
5
5
  import { ShokupanContext } from '../context';
6
+ import { ServerAdapter } from './adapter';
7
+ import { FileSystemAdapter } from './adapter/filesystem';
6
8
  import { $isRouter } from './symbol';
7
9
  export type HeadersInit = Headers | Record<string, string> | [string, string][];
8
10
  export interface ShokupanPluginOptions {
@@ -118,6 +120,112 @@ export interface CookieOptions {
118
120
  sameSite?: boolean | 'lax' | 'strict' | 'none' | 'Lax' | 'Strict' | 'None';
119
121
  priority?: 'low' | 'medium' | 'high' | 'Low' | 'Medium' | 'High';
120
122
  }
123
+ /**
124
+ * Helper interface for generic streaming operations.
125
+ * Provides methods to write data, pipe streams, and handle abort events.
126
+ */
127
+ export interface StreamHelper {
128
+ /**
129
+ * Write data to the stream.
130
+ * @param data Data to write (Uint8Array or string, strings are auto-encoded to UTF-8)
131
+ */
132
+ write(data: Uint8Array | string): Promise<void>;
133
+ /**
134
+ * Pipe a ReadableStream to this stream.
135
+ * @param stream ReadableStream to pipe
136
+ */
137
+ pipe(stream: ReadableStream): Promise<void>;
138
+ /**
139
+ * Sleep for a specified duration.
140
+ * @param ms Milliseconds to sleep
141
+ */
142
+ sleep(ms: number): Promise<void>;
143
+ /**
144
+ * Register a callback to be executed when the stream is aborted.
145
+ * @param callback Callback function
146
+ */
147
+ onAbort(callback: () => void): void;
148
+ }
149
+ /**
150
+ * Helper interface for text streaming operations.
151
+ * Provides methods to write text with or without newlines.
152
+ */
153
+ export interface TextStreamHelper {
154
+ /**
155
+ * Write text to the stream without a newline.
156
+ * @param text Text to write
157
+ */
158
+ write(text: string): Promise<void>;
159
+ /**
160
+ * Write text to the stream with a newline.
161
+ * @param text Text to write
162
+ */
163
+ writeln(text: string): Promise<void>;
164
+ /**
165
+ * Sleep for a specified duration.
166
+ * @param ms Milliseconds to sleep
167
+ */
168
+ sleep(ms: number): Promise<void>;
169
+ /**
170
+ * Register a callback to be executed when the stream is aborted.
171
+ * @param callback Callback function
172
+ */
173
+ onAbort(callback: () => void): void;
174
+ }
175
+ /**
176
+ * Helper interface for Server-Sent Events (SSE) streaming.
177
+ * Provides methods to write SSE-formatted messages.
178
+ */
179
+ export interface SSEStreamHelper {
180
+ /**
181
+ * Write a Server-Sent Event message.
182
+ * @param message SSE message with data, event, id, and retry fields
183
+ */
184
+ writeSSE(message: SSEMessage): Promise<void>;
185
+ /**
186
+ * Sleep for a specified duration.
187
+ * @param ms Milliseconds to sleep
188
+ */
189
+ sleep(ms: number): Promise<void>;
190
+ /**
191
+ * Register a callback to be executed when the stream is aborted.
192
+ * @param callback Callback function
193
+ */
194
+ onAbort(callback: () => void): void;
195
+ }
196
+ /**
197
+ * Server-Sent Event message format.
198
+ */
199
+ export interface SSEMessage {
200
+ /**
201
+ * The data payload of the event.
202
+ */
203
+ data: string;
204
+ /**
205
+ * Optional event type.
206
+ */
207
+ event?: string;
208
+ /**
209
+ * Optional event ID.
210
+ */
211
+ id?: string;
212
+ /**
213
+ * Optional reconnection time in milliseconds.
214
+ */
215
+ retry?: number;
216
+ }
217
+ /**
218
+ * Error handler for stream operations.
219
+ */
220
+ export type StreamErrorHandler = (err: Error, stream: StreamHelper) => void | Promise<void>;
221
+ /**
222
+ * Error handler for text stream operations.
223
+ */
224
+ export type TextStreamErrorHandler = (err: Error, stream: TextStreamHelper) => void | Promise<void>;
225
+ /**
226
+ * Error handler for SSE stream operations.
227
+ */
228
+ export type SSEStreamErrorHandler = (err: Error, stream: SSEStreamHelper) => void | Promise<void>;
121
229
  export type ShokupanHandler<State extends Record<string, any> = Record<string, any>, Params extends Record<string, string> = Record<string, string>> = ((ctx: ShokupanContext<State, Params>, next?: NextFn) => Promise<any> | any) & {
122
230
  originalHandler?: ShokupanHandler<State, Params>;
123
231
  };
@@ -129,7 +237,8 @@ export declare enum RouteParamType {
129
237
  QUERY = "QUERY",
130
238
  HEADER = "HEADER",
131
239
  REQUEST = "REQUEST",
132
- CONTEXT = "CONTEXT"
240
+ CONTEXT = "CONTEXT",
241
+ SERVICE = "SERVICE"
133
242
  }
134
243
  export interface ServerFactory {
135
244
  (options: any): Server<any> | Promise<Server<any>> | NodeServer | Promise<NodeServer>;
@@ -310,6 +419,14 @@ export type ShokupanConfig<T extends Record<string, any> = Record<string, any>>
310
419
  * @default false
311
420
  */
312
421
  enableTracing?: boolean;
422
+ /**
423
+ * Query parser mode.
424
+ * - `extended`: Arrays for duplicate keys (default).
425
+ * - `simple`: First value only for duplicate keys.
426
+ * - `strict`: Throws 400 error on duplicate keys.
427
+ * @default 'extended'
428
+ */
429
+ queryParserMode?: 'extended' | 'simple' | 'strict';
313
430
  /**
314
431
  * JSON parser to use for parsing request bodies.
315
432
  *
@@ -407,6 +524,12 @@ export type ShokupanConfig<T extends Record<string, any> = Record<string, any>>
407
524
  * @default 30000
408
525
  */
409
526
  readTimeout: number;
527
+ /**
528
+ * Maximum allowed request body size in bytes.
529
+ * Requests larger than this will be rejected with 413 Payload Too Large.
530
+ * @default 10485760 (10MB)
531
+ */
532
+ maxBodySize?: number;
410
533
  /**
411
534
  * Timeout for processing the request (milliseconds).
412
535
  * Maps to `server.timeout(req, seconds)`.
@@ -433,11 +556,11 @@ export type ShokupanConfig<T extends Record<string, any> = Record<string, any>>
433
556
  * The server adapter to use.
434
557
  * overrides `serverFactory`.
435
558
  */
436
- adapter?: 'bun' | 'node' | 'wintercg' | import('./adapter/adapters').ServerAdapter;
559
+ adapter?: 'bun' | 'node' | 'wintercg' | ServerAdapter;
437
560
  /**
438
561
  * The file system adapter to use for `ctx.file`.
439
562
  */
440
- fileSystem?: import('./adapter/filesystem').FileSystemAdapter;
563
+ fileSystem?: FileSystemAdapter;
441
564
  /**
442
565
  * Lifecycle hooks.
443
566
  */
@@ -509,6 +632,12 @@ export type ShokupanConfig<T extends Record<string, any> = Record<string, any>>
509
632
  spec_url: string;
510
633
  }>;
511
634
  };
635
+ /**
636
+ * Configuration for Security Headers.
637
+ * Can be a boolean to enable/disable defaults, or an object options.
638
+ * @default true
639
+ */
640
+ securityHeaders?: boolean | any;
512
641
  /**
513
642
  * Any other config options are allowed, but will be ignored.
514
643
  * @deprecated