shokupan 0.13.1 → 0.14.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 (97) hide show
  1. package/dist/{analyzer-BOtveWL-.cjs → analyzer-BZSVGTmP.cjs} +5 -4
  2. package/dist/analyzer-BZSVGTmP.cjs.map +1 -0
  3. package/dist/{analyzer-B0fMzeIo.js → analyzer-Faojwm7c.js} +5 -4
  4. package/dist/analyzer-Faojwm7c.js.map +1 -0
  5. package/dist/{analyzer.impl-CUDO6vpn.cjs → analyzer.impl-5aCqtook.cjs} +28 -11
  6. package/dist/analyzer.impl-5aCqtook.cjs.map +1 -0
  7. package/dist/{analyzer.impl-DmHe92Oi.js → analyzer.impl-COdN69gL.js} +28 -11
  8. package/dist/analyzer.impl-COdN69gL.js.map +1 -0
  9. package/dist/ast-analyzer-worker-C3jrQ8VR.js +184 -0
  10. package/dist/ast-analyzer-worker-C3jrQ8VR.js.map +1 -0
  11. package/dist/ast-analyzer-worker-D_uYkqmY.cjs +184 -0
  12. package/dist/ast-analyzer-worker-D_uYkqmY.cjs.map +1 -0
  13. package/dist/cli.cjs +1 -1
  14. package/dist/cli.js +1 -1
  15. package/dist/context.d.ts +39 -4
  16. package/dist/decorators/di.d.ts +31 -0
  17. package/dist/decorators/hooks.d.ts +28 -0
  18. package/dist/decorators/http.d.ts +60 -0
  19. package/dist/decorators/index.d.ts +8 -0
  20. package/dist/decorators/mcp.d.ts +48 -0
  21. package/dist/decorators/util/container.d.ts +36 -0
  22. package/dist/decorators/websocket.d.ts +172 -0
  23. package/dist/index-BP7v0Hiv.cjs +12216 -0
  24. package/dist/index-BP7v0Hiv.cjs.map +1 -0
  25. package/dist/index-CUNBeZKj.js +12176 -0
  26. package/dist/index-CUNBeZKj.js.map +1 -0
  27. package/dist/index.cjs +137 -10518
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.ts +1 -2
  30. package/dist/index.js +137 -10477
  31. package/dist/index.js.map +1 -1
  32. package/dist/{json-parser-COdZ0fqY.cjs → json-parser-BA0mUgMF.cjs} +3 -3
  33. package/dist/json-parser-BA0mUgMF.cjs.map +1 -0
  34. package/dist/{json-parser-B3dnQmCC.js → json-parser-BFM-SnBR.js} +3 -3
  35. package/dist/json-parser-BFM-SnBR.js.map +1 -0
  36. package/dist/knex-DDPXR-sQ.js +218 -0
  37. package/dist/knex-DDPXR-sQ.js.map +1 -0
  38. package/dist/knex-DghF-jjm.cjs +240 -0
  39. package/dist/knex-DghF-jjm.cjs.map +1 -0
  40. package/dist/level-BU87Jbus.js +184 -0
  41. package/dist/level-BU87Jbus.js.map +1 -0
  42. package/dist/level-DNFl2n-m.cjs +184 -0
  43. package/dist/level-DNFl2n-m.cjs.map +1 -0
  44. package/dist/plugins/application/api-explorer/static/explorer-client.mjs +54 -28
  45. package/dist/plugins/application/asyncapi/plugin.d.ts +1 -0
  46. package/dist/plugins/application/asyncapi/static/asyncapi-client.mjs +22 -11
  47. package/dist/plugins/application/dashboard/fetch-interceptor.d.ts +3 -1
  48. package/dist/plugins/application/dashboard/metrics-collector.d.ts +5 -3
  49. package/dist/plugins/application/dashboard/plugin.d.ts +36 -3
  50. package/dist/plugins/application/dashboard/static/requests.js +517 -53
  51. package/dist/plugins/application/dashboard/static/tabs.js +2 -2
  52. package/dist/plugins/application/error-view/index.d.ts +25 -0
  53. package/dist/plugins/application/error-view/reason-phrases.d.ts +1 -0
  54. package/dist/plugins/application/openapi/analyzer.d.ts +3 -1
  55. package/dist/plugins/application/openapi/analyzer.impl.d.ts +4 -2
  56. package/dist/router.d.ts +52 -21
  57. package/dist/shokupan.d.ts +25 -11
  58. package/dist/sqlite-CLrcTkti.js +180 -0
  59. package/dist/sqlite-CLrcTkti.js.map +1 -0
  60. package/dist/sqlite-n7FQ6Ja6.cjs +180 -0
  61. package/dist/sqlite-n7FQ6Ja6.cjs.map +1 -0
  62. package/dist/surreal-6QONU6xa.cjs +210 -0
  63. package/dist/surreal-6QONU6xa.cjs.map +1 -0
  64. package/dist/surreal-w7DeGVI-.js +188 -0
  65. package/dist/surreal-w7DeGVI-.js.map +1 -0
  66. package/dist/util/adapter/datastore/knex.d.ts +29 -0
  67. package/dist/util/adapter/datastore/level.d.ts +26 -0
  68. package/dist/util/adapter/datastore/sqlite.d.ts +24 -0
  69. package/dist/util/adapter/datastore/surreal.d.ts +29 -0
  70. package/dist/util/adapter/datastore.d.ts +59 -0
  71. package/dist/util/adapter/h3.d.ts +8 -0
  72. package/dist/util/adapter/index.d.ts +1 -0
  73. package/dist/util/ast-analyzer-worker.d.ts +77 -0
  74. package/dist/util/ast-worker-thread.d.ts +1 -0
  75. package/dist/util/cookie-parser.d.ts +6 -0
  76. package/dist/util/env-loader.d.ts +7 -0
  77. package/dist/util/html.d.ts +15 -0
  78. package/dist/util/ide.d.ts +9 -0
  79. package/dist/util/logger.d.ts +25 -0
  80. package/dist/util/query-string.d.ts +8 -0
  81. package/dist/util/response-transformer.d.ts +87 -0
  82. package/dist/util/symbol.d.ts +1 -0
  83. package/dist/util/types.d.ts +116 -42
  84. package/dist/websocket.d.ts +163 -0
  85. package/package.json +27 -1
  86. package/dist/analyzer-B0fMzeIo.js.map +0 -1
  87. package/dist/analyzer-BOtveWL-.cjs.map +0 -1
  88. package/dist/analyzer.impl-CUDO6vpn.cjs.map +0 -1
  89. package/dist/analyzer.impl-DmHe92Oi.js.map +0 -1
  90. package/dist/json-parser-B3dnQmCC.js.map +0 -1
  91. package/dist/json-parser-COdZ0fqY.cjs.map +0 -1
  92. package/dist/plugins/application/error-view/views/error.d.ts +0 -2
  93. package/dist/plugins/application/error-view/views/status.d.ts +0 -2
  94. package/dist/util/decorators.d.ts +0 -134
  95. package/dist/util/di.d.ts +0 -13
  96. /package/dist/{util → decorators/util}/metadata.d.ts +0 -0
  97. /package/dist/{util → decorators/util}/stack.d.ts +0 -0
@@ -0,0 +1,59 @@
1
+ export interface QueryOptions {
2
+ /**
3
+ * strict equality matches
4
+ */
5
+ where?: Record<string, any>;
6
+ /**
7
+ * less than matches
8
+ */
9
+ lt?: Record<string, number | string>;
10
+ /**
11
+ * greater than matches
12
+ */
13
+ gt?: Record<string, number | string>;
14
+ /**
15
+ * sort results by field
16
+ */
17
+ sort?: Record<string, 'asc' | 'desc'>;
18
+ limit?: number;
19
+ offset?: number;
20
+ }
21
+ export interface DatastoreAdapter {
22
+ name: string;
23
+ connect(): Promise<void>;
24
+ disconnect(): Promise<void>;
25
+ setupSchema(): Promise<void>;
26
+ /**
27
+ * Get a single record by global ID (table + id)
28
+ */
29
+ get<T>(table: string, id: string): Promise<T | null>;
30
+ /**
31
+ * Create a new record. Fails if exists.
32
+ */
33
+ create<T>(table: string, id: string, data: T): Promise<T>;
34
+ /**
35
+ * Update an existing record. Fails if not exists.
36
+ * Merges data.
37
+ */
38
+ update<T>(table: string, id: string, data: Partial<T>): Promise<T>;
39
+ /**
40
+ * Create or update a record.
41
+ */
42
+ upsert<T>(table: string, id: string, data: T): Promise<T>;
43
+ /**
44
+ * Delete a single record
45
+ */
46
+ delete(table: string, id: string): Promise<void>;
47
+ /**
48
+ * Count records matching query
49
+ */
50
+ count(table: string, query?: QueryOptions): Promise<number>;
51
+ /**
52
+ * Delete multiple records matching query
53
+ */
54
+ deleteMany(table: string, query?: QueryOptions): Promise<void>;
55
+ /**
56
+ * Find multiple records matching query
57
+ */
58
+ findMany<T>(table: string, query?: QueryOptions): Promise<T[]>;
59
+ }
@@ -0,0 +1,8 @@
1
+ import { Server } from 'bun';
2
+ import { Shokupan } from '../../shokupan';
3
+ import { ServerAdapter } from './interface';
4
+ export declare class H3Adapter implements ServerAdapter {
5
+ private nodeServer?;
6
+ listen(port: number, app: Shokupan): Promise<Server<any>>;
7
+ stop(): Promise<void>;
8
+ }
@@ -1,4 +1,5 @@
1
1
  export * from './bun';
2
+ export * from './h3';
2
3
  export * from './interface';
3
4
  export * from './node';
4
5
  export * from './wintercg';
@@ -0,0 +1,77 @@
1
+ import { EventEmitter } from 'events';
2
+ export type ASTAnalyzerState = 'idle' | 'analyzing' | 'completed' | 'failed';
3
+ export interface ASTAnalyzerResult {
4
+ applications: any[];
5
+ }
6
+ export interface ASTAnalyzerEvents {
7
+ 'started': () => void;
8
+ 'completed': (result: ASTAnalyzerResult) => void;
9
+ 'failed': (error: Error) => void;
10
+ 'progress': (message: string) => void;
11
+ }
12
+ /**
13
+ * Worker-based AST analyzer that runs TypeScript analysis in a separate thread.
14
+ * This prevents blocking the main event loop during intensive AST parsing.
15
+ */
16
+ export declare class ASTAnalyzerWorker extends EventEmitter {
17
+ private state;
18
+ private result;
19
+ private error;
20
+ private worker;
21
+ private analysisPromise;
22
+ private rootDir;
23
+ private entrypoint?;
24
+ private timeout;
25
+ private startTime;
26
+ constructor(rootDir: string, entrypoint?: string, timeout?: number);
27
+ /**
28
+ * Get the current state of the analyzer.
29
+ */
30
+ getState(): ASTAnalyzerState;
31
+ /**
32
+ * Get the cached result if analysis completed successfully.
33
+ */
34
+ getResult(): ASTAnalyzerResult | null;
35
+ /**
36
+ * Get the error if analysis failed.
37
+ */
38
+ getError(): Error | null;
39
+ /**
40
+ * Check if analysis is currently running.
41
+ */
42
+ isAnalyzing(): boolean;
43
+ /**
44
+ * Check if analysis has completed successfully.
45
+ */
46
+ isCompleted(): boolean;
47
+ /**
48
+ * Check if analysis has failed.
49
+ */
50
+ isFailed(): boolean;
51
+ /**
52
+ * Get analysis duration in milliseconds (if completed or failed).
53
+ */
54
+ getDuration(): number | null;
55
+ /**
56
+ * Start AST analysis in a worker thread.
57
+ * Returns immediately and emits events as analysis progresses.
58
+ */
59
+ analyze(): Promise<ASTAnalyzerResult>;
60
+ /**
61
+ * Wait for analysis to complete (if it's running) or return immediately if already done.
62
+ */
63
+ waitForCompletion(): Promise<ASTAnalyzerResult>;
64
+ /**
65
+ * Terminate the worker thread if running.
66
+ */
67
+ terminate(): void;
68
+ }
69
+ /**
70
+ * Get or create the global AST analyzer instance.
71
+ * This ensures all plugins share the same analysis results.
72
+ */
73
+ export declare function getGlobalAnalyzer(rootDir?: string, entrypoint?: string, timeout?: number): ASTAnalyzerWorker;
74
+ /**
75
+ * Reset the global analyzer instance (useful for testing).
76
+ */
77
+ export declare function resetGlobalAnalyzer(): void;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Fast Cookie Parser
3
+ *
4
+ * Optimized for speed by minimizing allocations and avoiding regex/split.
5
+ */
6
+ export declare function parseCookies(str: string): Record<string, string>;
@@ -1,3 +1,4 @@
1
+ import { Logger } from './logger';
1
2
  export type EnvLoaderOptions = {
2
3
  /**
3
4
  * If provided, k8s secrets will be loaded from the given paths
@@ -9,6 +10,10 @@ export type EnvLoaderOptions = {
9
10
  * @default []
10
11
  */
11
12
  k8sConfigMapMountPaths?: string[];
13
+ /**
14
+ * Optional logger instance
15
+ */
16
+ logger?: Logger;
12
17
  };
13
18
  type Listener<T> = (value: T) => void;
14
19
  /**
@@ -50,6 +55,7 @@ declare const $secretSubjects: unique symbol;
50
55
  declare const $options: unique symbol;
51
56
  declare const $watchers: unique symbol;
52
57
  declare const $watchersStarted: unique symbol;
58
+ declare const $logger: unique symbol;
53
59
  declare const $getSecretValueInternal: unique symbol;
54
60
  declare const $getOrCreateSubject: unique symbol;
55
61
  declare const $loadSecrets: unique symbol;
@@ -65,6 +71,7 @@ export declare abstract class EnvLoader {
65
71
  private [$options];
66
72
  private [$watchers];
67
73
  private [$watchersStarted];
74
+ private [$logger];
68
75
  constructor(options?: EnvLoaderOptions);
69
76
  /**
70
77
  * Initialize the loader: read secrets.
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Escapes unsafe characters in a string for use in HTML using named character references.
3
+ *
4
+ * @param unsafe - The input value to escape. If not a string, it will be coerced to one.
5
+ * @returns The escaped string.
6
+ */
7
+ export declare function escapeHtml(unsafe: unknown): string;
8
+ /**
9
+ * Safely serializes data to JSON for embedding in a <script> tag.
10
+ * Prevents Script Injection via </script> tags.
11
+ *
12
+ * @param data - The data to serialize.
13
+ * @returns The JSON string with </script> escaped.
14
+ */
15
+ export declare function safeScriptJson(data: any): string;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Utility for generating links to open files in various editors.
3
+ * Controlled by the `IDE` environment variable or app-level configuration.
4
+ */
5
+ export declare function configureIde(config: {
6
+ ide?: string;
7
+ }): void;
8
+ export declare function getEditorLinkPattern(): string;
9
+ export declare function generateEditorLink(filePath: string, line?: number, column?: number): string;
@@ -0,0 +1,25 @@
1
+ export interface Logger {
2
+ debug(module: string, msg: string, props?: Record<string, any>): void;
3
+ info(module: string, msg: string, props?: Record<string, any>): void;
4
+ warn(module: string, msg: string, props?: Record<string, any>): void;
5
+ error(module: string, msg: string, props?: Record<string, any>): void;
6
+ fatal(module: string, msg: string, props?: Record<string, any>): void;
7
+ }
8
+ export declare class JsonLogger implements Logger {
9
+ private write;
10
+ debug(module: string, msg: string, props?: Record<string, any>): void;
11
+ info(module: string, msg: string, props?: Record<string, any>): void;
12
+ warn(module: string, msg: string, props?: Record<string, any>): void;
13
+ error(module: string, msg: string, props?: Record<string, any>): void;
14
+ fatal(module: string, msg: string, props?: Record<string, any>): void;
15
+ }
16
+ export declare class ConsolaLogger implements Logger {
17
+ private consola;
18
+ constructor(level?: number);
19
+ debug(module: string, msg: string, props?: Record<string, any>): void;
20
+ info(module: string, msg: string, props?: Record<string, any>): void;
21
+ warn(module: string, msg: string, props?: Record<string, any>): void;
22
+ error(module: string, msg: string, props?: Record<string, any>): void;
23
+ fatal(module: string, msg: string, props?: Record<string, any>): void;
24
+ }
25
+ export declare function createLogger(env?: string): Logger;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Fast Querystring Parser
3
+ *
4
+ * Optimized for speed by minimizing allocations and avoiding regex.
5
+ * Benchmarked faster than 'fast-querystring' and significantly faster than native 'URLSearchParams'.
6
+ */
7
+ export type QueryParserMode = 'simple' | 'extended' | 'strict';
8
+ export declare function parseQuery(url: string, mode?: QueryParserMode): Record<string, any>;
@@ -0,0 +1,87 @@
1
+ import { BodyInit } from 'bun';
2
+ /**
3
+ * Response transformer function
4
+ * Converts data to a specific format and returns response metadata
5
+ */
6
+ export interface ResponseTransformer {
7
+ /**
8
+ * MIME type(s) this transformer handles
9
+ * Can be a string or array of strings
10
+ */
11
+ contentType: string | string[];
12
+ /**
13
+ * Serialize the data
14
+ * @param data The data to serialize
15
+ * @returns Serialized body and optional headers
16
+ */
17
+ serialize: (data: any) => {
18
+ body: BodyInit;
19
+ headers?: Record<string, string>;
20
+ } | Promise<{
21
+ body: BodyInit;
22
+ headers?: Record<string, string>;
23
+ }>;
24
+ /**
25
+ * Optional: Quality value for content negotiation (0-1)
26
+ * Higher values = preferred format when multiple matches exist
27
+ */
28
+ quality?: number;
29
+ }
30
+ /**
31
+ * Response transformer registry
32
+ * Manages registered transformers and performs content negotiation
33
+ */
34
+ export declare class ResponseTransformerRegistry {
35
+ private transformers;
36
+ private defaultTransformer?;
37
+ /**
38
+ * Register a response transformer
39
+ * @param transformer The transformer to register
40
+ */
41
+ register(transformer: ResponseTransformer): void;
42
+ /**
43
+ * Get a transformer by exact content type match
44
+ * @param contentType The content type to look up
45
+ * @returns The transformer or undefined
46
+ */
47
+ getTransformer(contentType: string): ResponseTransformer | undefined;
48
+ /**
49
+ * Set the default transformer content type
50
+ * @param contentType The content type to use as default
51
+ */
52
+ setDefault(contentType: string): void;
53
+ /**
54
+ * Get the default transformer
55
+ * @returns The default transformer or undefined
56
+ */
57
+ getDefault(): ResponseTransformer | undefined;
58
+ /**
59
+ * Perform content negotiation based on Accept header
60
+ * @param acceptHeader The Accept header value
61
+ * @returns The best matching transformer or undefined
62
+ */
63
+ negotiate(acceptHeader: string): ResponseTransformer | undefined;
64
+ /**
65
+ * Parse Accept header into structured entries
66
+ * @param acceptHeader The Accept header value
67
+ * @returns Array of parsed accept entries
68
+ */
69
+ private parseAcceptHeader;
70
+ /**
71
+ * Find exact content type match
72
+ * @param accept The accept entry to match
73
+ * @returns The matching transformer or undefined
74
+ */
75
+ private findExactMatch;
76
+ /**
77
+ * Find wildcard content type match
78
+ * @param accept The accept entry to match
79
+ * @returns The matching transformer or undefined
80
+ */
81
+ private findWildcardMatch;
82
+ /**
83
+ * Get all registered content types
84
+ * @returns Array of registered content types
85
+ */
86
+ getRegisteredTypes(): string[];
87
+ }
@@ -14,6 +14,7 @@ export declare const $mountPath: unique symbol;
14
14
  export declare const $dispatch: unique symbol;
15
15
  export declare const $routes: unique symbol;
16
16
  export declare const $routeSpec: unique symbol;
17
+ export declare const $controllerHooks: unique symbol;
17
18
  export declare const $url: unique symbol;
18
19
  export declare const $requestId: unique symbol;
19
20
  export declare const $debug: unique symbol;
@@ -1,10 +1,10 @@
1
1
  import { OpenAPI } from '@scalar/openapi-types';
2
2
  import { Server } from 'bun';
3
3
  import { Server as NodeServer } from 'node:http';
4
- import { ConnectOptions, Engines } from 'surrealdb';
5
4
  import { ShokupanContext } from '../context';
6
5
  import { ServerAdapter } from './adapter';
7
6
  import { FileSystemAdapter } from './adapter/filesystem';
7
+ import { Logger } from './logger';
8
8
  import { $isRouter } from './symbol';
9
9
  export type HeadersInit = Headers | Record<string, string> | [string, string][];
10
10
  export interface ShokupanPluginOptions {
@@ -43,6 +43,39 @@ type ParsePathParams<Path extends string> = Path extends `${infer _Start}:${infe
43
43
  [K in Param]: string;
44
44
  } : {};
45
45
  export type RouteParams<Path extends string> = string extends Path ? Record<string, string> : ParsePathParams<Path> extends Record<string, never> ? Record<string, string> : ParsePathParams<Path>;
46
+ /**
47
+ * Type guard to check if a state property exists and narrow its type.
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * if (hasStateProperty(ctx, 'userId')) {
52
+ * // ctx.state.userId is now typed as defined (not undefined)
53
+ * console.log(ctx.state.userId);
54
+ * }
55
+ * ```
56
+ */
57
+ export declare function hasStateProperty<S extends Record<string, any>, K extends string>(state: S, key: K): key is K & keyof S;
58
+ /**
59
+ * Runtime assertion that a state property exists.
60
+ * Throws an error if the property is missing.
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * requireStateProperty(ctx.state, 'userId');
65
+ * // Now TypeScript knows ctx.state.userId exists
66
+ * const id = ctx.state.userId;
67
+ * ```
68
+ */
69
+ export declare function requireStateProperty<S extends Record<string, any>, K extends keyof S>(state: S, key: K, message?: string): asserts state is S & Record<K, NonNullable<S[K]>>;
70
+ /**
71
+ * Type-safe state getter with optional default value.
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * const userId = getStateProperty(ctx.state, 'userId', 'anonymous');
76
+ * ```
77
+ */
78
+ export declare function getStateProperty<S extends Record<string, any>, K extends keyof S, D = undefined>(state: S, key: K, defaultValue?: D): S[K] | D;
46
79
  export interface RouteMetadata {
47
80
  file: string;
48
81
  line: number;
@@ -243,6 +276,9 @@ export declare enum RouteParamType {
243
276
  export interface ServerFactory {
244
277
  (options: any): Server<any> | Promise<Server<any>> | NodeServer | Promise<NodeServer>;
245
278
  }
279
+ export interface ErrorHandler<T = any> {
280
+ (err: T, ctx: ShokupanContext): Response | Promise<Response>;
281
+ }
246
282
  export type NextFn = () => Promise<any>;
247
283
  export type Middleware = ((ctx: ShokupanContext<unknown>, next: NextFn) => Promise<any> | any) & {
248
284
  isBuiltin?: boolean;
@@ -357,6 +393,10 @@ export type ShokupanRoute = {
357
393
  * Middleware stack metadata for this route (Controller/Method level)
358
394
  */
359
395
  middleware?: Middleware[];
396
+ /**
397
+ * Whether this route is a WebSocket route
398
+ */
399
+ isSocket?: boolean;
360
400
  };
361
401
  export type ShokupanConfig<T extends Record<string, any> = Record<string, any>> = Partial<{
362
402
  /**
@@ -412,6 +452,18 @@ export type ShokupanConfig<T extends Record<string, any> = Record<string, any>>
412
452
  * @default true
413
453
  */
414
454
  blockOnAsyncApiGen: boolean;
455
+ /**
456
+ * Whether to use async AST scanning with worker threads.
457
+ * When enabled, AST analysis runs in a separate thread to avoid blocking server startup.
458
+ * @default true
459
+ */
460
+ enableAsyncAstScanning?: boolean;
461
+ /**
462
+ * Maximum time (ms) to wait for AST analysis before timing out.
463
+ * Only applies when enableAsyncAstScanning is true.
464
+ * @default 30000 (30 seconds)
465
+ */
466
+ astAnalysisTimeout?: number;
415
467
  /**
416
468
  * Whether to reuse the port.
417
469
  * @default false
@@ -461,6 +513,20 @@ export type ShokupanConfig<T extends Record<string, any> = Record<string, any>>
461
513
  * @default 60
462
514
  */
463
515
  autoBackpressureLevel?: number;
516
+ /**
517
+ * Whether to enable automatic content negotiation for ctx.json() and other response methods.
518
+ * When enabled, ctx.json() will use the response transformer registry to negotiate the best
519
+ * response format based on the Accept header.
520
+ * @default false
521
+ */
522
+ enableAutoContentNegotiation?: boolean;
523
+ /**
524
+ * Default response transformer content type.
525
+ * If set, ctx.respond() and auto-negotiated ctx.json() will use this transformer
526
+ * when no Accept header matches or when Accept is any.
527
+ * @default 'application/json'
528
+ */
529
+ defaultResponseTransformer?: string;
464
530
  /**
465
531
  * Whether to enable middleware and handler tracking.
466
532
  * When enabled, `ctx.handlerStack` will be populated with the handlers the request has passed through.
@@ -479,15 +545,15 @@ export type ShokupanConfig<T extends Record<string, any> = Record<string, any>>
479
545
  * This enables websocket messages to run through the HTTP server.
480
546
  * e.g.
481
547
  * ```json
482
- * {
483
- * "method": "POST",
484
- * "path": "/api/v1/myHttpEndpoint",
485
- * "headers": {},
486
- * "body": {
548
+ * {
549
+ * "method": "POST",
550
+ * "path": "/api/v1/myHttpEndpoint",
551
+ * "headers": {},
552
+ * "body": {
487
553
  * "type": "text",
488
- * "data": "Hello, world!"
554
+ * "data": "Hello, world!"
489
555
  * }
490
- * }
556
+ * }
491
557
  * ```
492
558
  * @default false
493
559
  */
@@ -515,17 +581,7 @@ export type ShokupanConfig<T extends Record<string, any> = Record<string, any>>
515
581
  /**
516
582
  * Logger object.
517
583
  */
518
- logger: {
519
- verbose: boolean;
520
- info: (msg: string, props: Record<string, any>) => void;
521
- debug: (msg: string, props: Record<string, any>) => void;
522
- warning: (msg: string, props: Record<string, any>) => void;
523
- error: (msg: string, props: Record<string, any>) => void;
524
- /**
525
- * Something fatally went wrong and the application cannot continue.
526
- */
527
- fatal: (msg: string, props: Record<string, any>) => void;
528
- };
584
+ logger: Logger;
529
585
  /**
530
586
  * Timeout for reading the request body (milliseconds).
531
587
  * Maps to Bun's `idleTimeout`.
@@ -564,7 +620,7 @@ export type ShokupanConfig<T extends Record<string, any> = Record<string, any>>
564
620
  * The server adapter to use.
565
621
  * overrides `serverFactory`.
566
622
  */
567
- adapter?: 'bun' | 'node' | 'wintercg' | ServerAdapter;
623
+ adapter?: 'bun' | 'node' | 'wintercg' | 'h3' | ServerAdapter;
568
624
  /**
569
625
  * The file system adapter to use for `ctx.file`.
570
626
  */
@@ -579,31 +635,19 @@ export type ShokupanConfig<T extends Record<string, any> = Record<string, any>>
579
635
  */
580
636
  validateStatusCodes: boolean;
581
637
  /**
582
- * Configuration for SurrealDB.
638
+ * @deprecated Use `datastore` config instead.
583
639
  */
584
- surreal?: {
585
- /**
586
- * SurrealDB engines.
587
- * @default Embedded
588
- */
589
- engines?: Engines;
590
- /**
591
- * SurrealDB connection URL.
592
- * @default 'rocksdb://database'
593
- */
594
- url?: string;
595
- /**
596
- * SurrealDB connection options.
597
- */
598
- connectOptions?: ConnectOptions;
599
- /**
600
- * SurrealDB namespace.
601
- */
602
- namespace?: string;
640
+ surreal?: any;
641
+ datastore?: {
642
+ adapter: 'surreal' | 'sqlite' | 'level' | 'knex';
603
643
  /**
604
- * SurrealDB database.
644
+ * Options for the specific adapter.
645
+ * - For 'surreal', this matches SurrealAdapterOptions
646
+ * - For 'sqlite', this matches SqliteAdapterOptions
647
+ * - For 'level', this matches LevelAdapterOptions
648
+ * - For 'knex', this matches KnexAdapterOptions (Knex.Config)
605
649
  */
606
- database?: string;
650
+ options?: any;
607
651
  };
608
652
  /**
609
653
  * Configuration for the AI Plugin manifest (.well-known/ai-plugin.json).
@@ -651,6 +695,18 @@ export type ShokupanConfig<T extends Record<string, any> = Record<string, any>>
651
695
  * @deprecated
652
696
  */
653
697
  [key: string]: any;
698
+ /**
699
+ * IDE configuration for file links.
700
+ * Can be a specific editor name (vscode, intellij, etc.) or an autodetection mode.
701
+ * Overrides process.env.IDE.
702
+ *
703
+ * Options:
704
+ * - 'vscode', 'vscode-insiders', 'vscodium', 'cursor', 'intellij', 'sublime', 'neovim'
705
+ * - 'vscode.dev': Force generic vscode.dev links
706
+ * - 'autodetect-vscode.dev': Auto-detect git remote and generate specific vscode.dev links
707
+ * - 'autodetect-repo': Auto-detect git remote and generate web repository links
708
+ */
709
+ ide?: string;
654
710
  }>;
655
711
  export interface RequestOptions {
656
712
  path?: string;
@@ -717,5 +773,23 @@ export interface StaticServeOptions<T extends Record<string, any>> {
717
773
  * OpenAPI specification for the static route.
718
774
  */
719
775
  openapi?: MethodAPISpec;
776
+ /**
777
+ * Enable ETags for static files.
778
+ */
779
+ etag?: boolean;
780
+ /**
781
+ * Maximum age for the cache.
782
+ */
783
+ maxAge?: number;
784
+ /**
785
+ * Whether the file is immutable.
786
+ * maxAge must be set to a value > 0 for this to have any effect.
787
+ */
788
+ immutable?: boolean;
789
+ /**
790
+ * Whether to use the cache.
791
+ * @default true
792
+ */
793
+ useCache?: boolean;
720
794
  }
721
795
  export {};