@kozojs/core 0.2.3 → 0.2.5
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.
- package/lib/index.d.ts +542 -19
- package/lib/index.js +3425 -332
- package/lib/index.js.map +1 -1
- package/lib/middleware/index.d.ts +83 -2
- package/lib/middleware/index.js +77 -7
- package/lib/middleware/index.js.map +1 -1
- package/lib/wasm/radix.wasm +0 -0
- package/package.json +4 -3
package/lib/index.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import * as hono from 'hono';
|
|
2
|
-
import {
|
|
2
|
+
import { Context } from 'hono';
|
|
3
|
+
import { Hono } from 'hono/quick';
|
|
4
|
+
import { IncomingMessage, ServerResponse, Server } from 'node:http';
|
|
3
5
|
import { z } from 'zod';
|
|
4
6
|
export { z } from 'zod';
|
|
5
7
|
import { TSchema, Static } from '@sinclair/typebox';
|
|
8
|
+
import { ValidateFunction } from 'ajv';
|
|
9
|
+
export { CorsOptions, FileSystemRoutingOptions, HttpBadRequestError, HttpConflictError, HttpError, HttpForbiddenError, HttpInternalServerError, HttpNotFoundError, HttpUnauthorizedError, LoggerOptions, ManifestHttpMethod, ManifestRoute, RateLimitOptions, RoutesManifest, applyFileSystemRouting, clearRateLimitStore, cors, createFileSystemRouting, errorHandler, logger, rateLimit } from './middleware/index.js';
|
|
6
10
|
|
|
7
11
|
type SchemaType = z.ZodType<any> | TSchema;
|
|
8
12
|
type RouteSchema = {
|
|
@@ -12,8 +16,10 @@ type RouteSchema = {
|
|
|
12
16
|
response?: SchemaType | Record<number, SchemaType>;
|
|
13
17
|
};
|
|
14
18
|
type InferSchema<T> = T extends z.ZodType<any> ? z.infer<T> : T extends TSchema ? Static<T> : unknown;
|
|
15
|
-
type
|
|
16
|
-
|
|
19
|
+
/** Infer the response data type from a schema's response field */
|
|
20
|
+
type InferResponse<T> = T extends SchemaType ? InferSchema<T> : T extends Record<number, SchemaType> ? InferSchema<T[200]> : unknown;
|
|
21
|
+
type KozoContext<S extends RouteSchema = {}, TServices extends Services = Services> = {
|
|
22
|
+
services: TServices;
|
|
17
23
|
body: InferSchema<S['body']>;
|
|
18
24
|
query: InferSchema<S['query']>;
|
|
19
25
|
params: InferSchema<S['params']>;
|
|
@@ -21,10 +27,89 @@ type KozoContext<S extends RouteSchema = {}> = {
|
|
|
21
27
|
json: (data: any) => Response;
|
|
22
28
|
text: (data: string, status?: number, headers?: any) => Response;
|
|
23
29
|
};
|
|
24
|
-
type KozoHandler<S extends RouteSchema = {}> = (ctx: KozoContext<S>) => any | Promise<any>;
|
|
30
|
+
type KozoHandler<S extends RouteSchema = {}, TServices extends Services = Services> = (ctx: KozoContext<S, TServices>) => any | Promise<any>;
|
|
25
31
|
interface Services {
|
|
26
32
|
[key: string]: unknown;
|
|
27
33
|
}
|
|
34
|
+
interface KozoEnv {
|
|
35
|
+
Variables: {
|
|
36
|
+
services: Services;
|
|
37
|
+
user?: unknown;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Context object passed to native route handlers (used with `nativeListen`).
|
|
42
|
+
*
|
|
43
|
+
* Offers the same type inference as `KozoContext` but operates directly on
|
|
44
|
+
* Node.js primitives — no Hono adapter, no Web API Request/Response.
|
|
45
|
+
*
|
|
46
|
+
* @typeParam S - Route schema (body, query, params, response)
|
|
47
|
+
* @typeParam TSvc - Services type (injected at constructor)
|
|
48
|
+
*/
|
|
49
|
+
interface NativeKozoContext<S extends RouteSchema = {}, TSvc extends Services = Services> {
|
|
50
|
+
/** Raw Node.js incoming request */
|
|
51
|
+
readonly req: IncomingMessage;
|
|
52
|
+
/** Raw Node.js server response */
|
|
53
|
+
readonly res: ServerResponse;
|
|
54
|
+
/** Route parameters — typed from schema.params */
|
|
55
|
+
readonly params: InferSchema<S['params']>;
|
|
56
|
+
/** Parsed query string — typed from schema.query */
|
|
57
|
+
readonly query: InferSchema<S['query']>;
|
|
58
|
+
/** Parsed request body — typed from schema.body */
|
|
59
|
+
readonly body: InferSchema<S['body']>;
|
|
60
|
+
/** Injected services — typed from Kozo<TServices> */
|
|
61
|
+
readonly services: TSvc;
|
|
62
|
+
/** Send a JSON response (default status 200). Uses fast-json-stringify if schema.response is defined. */
|
|
63
|
+
json(data: InferResponse<S['response']>, status?: number): void;
|
|
64
|
+
/** Send a plain text response. */
|
|
65
|
+
text(data: string, status?: number): void;
|
|
66
|
+
/** Send an HTML response (SSR page rendering). */
|
|
67
|
+
html(data: string, status?: number): void;
|
|
68
|
+
/** Set a response header. Returns `this` for chaining. */
|
|
69
|
+
header(name: string, value: string): this;
|
|
70
|
+
/** Redirect to another URL (default 302). */
|
|
71
|
+
redirect(url: string, status?: number): void;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Handler function type for native routes (used with `nativeListen`).
|
|
75
|
+
*
|
|
76
|
+
* @typeParam S - Route schema
|
|
77
|
+
* @typeParam TSvc - Services shape
|
|
78
|
+
*/
|
|
79
|
+
type NativeKozoHandler<S extends RouteSchema = {}, TSvc extends Services = Services> = (ctx: NativeKozoContext<S, TSvc>) => void | Promise<void>;
|
|
80
|
+
interface HandlerContext<TBody = unknown, TParams extends Record<string, string> = Record<string, string>, TQuery extends Record<string, string> = Record<string, string>> {
|
|
81
|
+
body: TBody;
|
|
82
|
+
params: TParams;
|
|
83
|
+
query: TQuery;
|
|
84
|
+
headers: Record<string, string>;
|
|
85
|
+
services: Services;
|
|
86
|
+
user?: unknown;
|
|
87
|
+
c: any;
|
|
88
|
+
}
|
|
89
|
+
type RouteHandler<TBody = unknown> = (ctx: HandlerContext<TBody>) => Promise<unknown> | unknown;
|
|
90
|
+
interface RouteMeta {
|
|
91
|
+
summary?: string;
|
|
92
|
+
description?: string;
|
|
93
|
+
tags?: string[];
|
|
94
|
+
auth?: boolean;
|
|
95
|
+
rateLimit?: {
|
|
96
|
+
max: number;
|
|
97
|
+
window: number;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
interface RouteModule {
|
|
101
|
+
default: RouteHandler;
|
|
102
|
+
schema?: RouteSchema;
|
|
103
|
+
meta?: RouteMeta;
|
|
104
|
+
middleware?: Array<(ctx: HandlerContext) => Promise<void> | void>;
|
|
105
|
+
}
|
|
106
|
+
type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete';
|
|
107
|
+
interface RouteDefinition {
|
|
108
|
+
path: string;
|
|
109
|
+
method: HttpMethod;
|
|
110
|
+
filePath: string;
|
|
111
|
+
module: RouteModule;
|
|
112
|
+
}
|
|
28
113
|
interface OpenAPIConfigRef {
|
|
29
114
|
info: {
|
|
30
115
|
title: string;
|
|
@@ -40,9 +125,9 @@ interface OpenAPIConfigRef {
|
|
|
40
125
|
description?: string;
|
|
41
126
|
}>;
|
|
42
127
|
}
|
|
43
|
-
interface KozoConfig {
|
|
128
|
+
interface KozoConfig<TServices extends Services = Services> {
|
|
44
129
|
routesDir?: string;
|
|
45
|
-
services?:
|
|
130
|
+
services?: TServices;
|
|
46
131
|
port?: number;
|
|
47
132
|
mode?: 'safe' | 'turbo';
|
|
48
133
|
runtime?: 'node' | 'bun';
|
|
@@ -91,6 +176,102 @@ interface RouteInfo {
|
|
|
91
176
|
*/
|
|
92
177
|
declare function generateTypedClient(routes: RouteInfo[], options?: ClientGeneratorOptions): string;
|
|
93
178
|
|
|
179
|
+
type DatabaseProvider = 'postgresql' | 'mysql' | 'sqlite';
|
|
180
|
+
type DatabaseInstance = Record<string, unknown>;
|
|
181
|
+
/**
|
|
182
|
+
* Shutdown configuration options
|
|
183
|
+
*/
|
|
184
|
+
interface ShutdownOptions {
|
|
185
|
+
/** Maximum time to wait for in-flight requests to complete (default: 30000ms) */
|
|
186
|
+
timeoutMs?: number;
|
|
187
|
+
/** Callback fired when shutdown starts */
|
|
188
|
+
onShutdownStart?: (inflightCount: number) => void;
|
|
189
|
+
/** Callback fired when all requests complete before timeout */
|
|
190
|
+
onShutdownComplete?: () => void;
|
|
191
|
+
/** Callback fired when shutdown times out */
|
|
192
|
+
onShutdownTimeout?: (remainingInflight: number) => void;
|
|
193
|
+
/** Database instance to close (optional) */
|
|
194
|
+
database?: DatabaseInstance;
|
|
195
|
+
/** Database provider type (required if database is provided) */
|
|
196
|
+
databaseProvider?: DatabaseProvider;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Internal state for tracking in-flight requests
|
|
200
|
+
*/
|
|
201
|
+
interface InflightTracker {
|
|
202
|
+
count: number;
|
|
203
|
+
requests: Set<Promise<unknown>>;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Create an in-flight request tracker
|
|
207
|
+
*/
|
|
208
|
+
declare function createInflightTracker(): InflightTracker;
|
|
209
|
+
/**
|
|
210
|
+
* Track a request - call at the start of each request
|
|
211
|
+
*/
|
|
212
|
+
declare function trackRequest(tracker: InflightTracker): () => void;
|
|
213
|
+
/**
|
|
214
|
+
* Shutdown state machine
|
|
215
|
+
*/
|
|
216
|
+
type ShutdownState = 'running' | 'shutting-down' | 'shutdown';
|
|
217
|
+
/**
|
|
218
|
+
* Graceful shutdown manager
|
|
219
|
+
*/
|
|
220
|
+
declare class ShutdownManager {
|
|
221
|
+
private state;
|
|
222
|
+
private abortController;
|
|
223
|
+
private server;
|
|
224
|
+
private tracker;
|
|
225
|
+
private database;
|
|
226
|
+
private databaseProvider;
|
|
227
|
+
constructor();
|
|
228
|
+
/**
|
|
229
|
+
* Get current shutdown state
|
|
230
|
+
*/
|
|
231
|
+
getState(): ShutdownState;
|
|
232
|
+
/**
|
|
233
|
+
* Check if server is shutting down
|
|
234
|
+
*/
|
|
235
|
+
isShuttingDown(): boolean;
|
|
236
|
+
/**
|
|
237
|
+
* Get current in-flight request count
|
|
238
|
+
*/
|
|
239
|
+
getInflightCount(): number;
|
|
240
|
+
/**
|
|
241
|
+
* Set the server instance for shutdown
|
|
242
|
+
*/
|
|
243
|
+
setServer(server: Server): void;
|
|
244
|
+
/**
|
|
245
|
+
* Set database for cleanup
|
|
246
|
+
*/
|
|
247
|
+
setDatabase(db: DatabaseInstance, provider: DatabaseProvider): void;
|
|
248
|
+
/**
|
|
249
|
+
* Get the AbortController signal for request cancellation
|
|
250
|
+
*/
|
|
251
|
+
getAbortSignal(): AbortSignal | undefined;
|
|
252
|
+
/**
|
|
253
|
+
* Create a request tracker middleware
|
|
254
|
+
* Returns an untrack function to call when request completes
|
|
255
|
+
*/
|
|
256
|
+
trackRequest(): () => void;
|
|
257
|
+
/**
|
|
258
|
+
* Initiate graceful shutdown
|
|
259
|
+
*/
|
|
260
|
+
shutdown(options?: ShutdownOptions): Promise<void>;
|
|
261
|
+
/**
|
|
262
|
+
* Wait for all in-flight requests to complete
|
|
263
|
+
*/
|
|
264
|
+
private drainRequests;
|
|
265
|
+
/**
|
|
266
|
+
* Close database connections based on provider
|
|
267
|
+
*/
|
|
268
|
+
private closeDatabase;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Create a shutdown manager instance
|
|
272
|
+
*/
|
|
273
|
+
declare function createShutdownManager(): ShutdownManager;
|
|
274
|
+
|
|
94
275
|
interface Plugin {
|
|
95
276
|
name: string;
|
|
96
277
|
version?: string;
|
|
@@ -98,38 +279,380 @@ interface Plugin {
|
|
|
98
279
|
}
|
|
99
280
|
/**
|
|
100
281
|
* Kozo - High-performance TypeScript framework with Zod schemas
|
|
282
|
+
*
|
|
283
|
+
* @typeParam TServices - Shape of the services object injected into every handler.
|
|
284
|
+
* Pass it once at construction: `createKozo<{ db: Database }>({ services: { db } })`
|
|
285
|
+
* and all handler contexts will have `ctx.services.db` fully typed.
|
|
101
286
|
*/
|
|
102
|
-
declare class Kozo {
|
|
287
|
+
declare class Kozo<TServices extends Services = Services> {
|
|
103
288
|
private app;
|
|
104
289
|
private services;
|
|
105
290
|
private routes;
|
|
106
|
-
|
|
291
|
+
private nativeRoutes;
|
|
292
|
+
private shutdownManager;
|
|
293
|
+
private wasmRouter;
|
|
294
|
+
/** Maps each NativeRouteHandler to its zero-shim uWS counterpart */
|
|
295
|
+
private uwsHandlerMap;
|
|
296
|
+
private _routesDir?;
|
|
297
|
+
constructor(config?: KozoConfig<TServices>);
|
|
107
298
|
use(plugin: Plugin): this;
|
|
299
|
+
/**
|
|
300
|
+
* Load routes from the file system using the configured routesDir.
|
|
301
|
+
* Each route file is dynamically imported, its schema compiled, and handler registered.
|
|
302
|
+
* This is a no-op if routesDir is not configured.
|
|
303
|
+
*/
|
|
304
|
+
loadRoutes(routesDir?: string): Promise<this>;
|
|
108
305
|
generateClient(baseUrl?: string): string;
|
|
109
306
|
generateClient(options?: ClientGeneratorOptions): string;
|
|
110
|
-
get<S extends RouteSchema>(path: string, schema: S, handler: KozoHandler<S>):
|
|
111
|
-
post<S extends RouteSchema>(path: string, schema: S, handler: KozoHandler<S>):
|
|
112
|
-
put<S extends RouteSchema>(path: string, schema: S, handler: KozoHandler<S>):
|
|
113
|
-
patch<S extends RouteSchema>(path: string, schema: S, handler: KozoHandler<S>):
|
|
114
|
-
delete<S extends RouteSchema>(path: string, schema: S, handler: KozoHandler<S>):
|
|
307
|
+
get<S extends RouteSchema>(path: string, schema: S, handler: KozoHandler<S, TServices>): this;
|
|
308
|
+
post<S extends RouteSchema>(path: string, schema: S, handler: KozoHandler<S, TServices>): this;
|
|
309
|
+
put<S extends RouteSchema>(path: string, schema: S, handler: KozoHandler<S, TServices>): this;
|
|
310
|
+
patch<S extends RouteSchema>(path: string, schema: S, handler: KozoHandler<S, TServices>): this;
|
|
311
|
+
delete<S extends RouteSchema>(path: string, schema: S, handler: KozoHandler<S, TServices>): this;
|
|
115
312
|
private register;
|
|
313
|
+
/**
|
|
314
|
+
* Start a raw Node.js HTTP server (no @hono/node-server adapter).
|
|
315
|
+
* Writes directly to ServerResponse — eliminates Web API Request/Response
|
|
316
|
+
* allocation and adapter overhead for maximum throughput.
|
|
317
|
+
*
|
|
318
|
+
* When the Zig WASM radix trie is available (`src/wasm/radix.wasm`),
|
|
319
|
+
* ALL route matching (static + dynamic) runs through the zero-copy
|
|
320
|
+
* trie — one call into WASM per request.
|
|
321
|
+
*
|
|
322
|
+
* When the .wasm file is absent (Edge deploy, CI without Zig, etc.)
|
|
323
|
+
* routing falls back transparently to the JS Map + RegExp approach.
|
|
324
|
+
*
|
|
325
|
+
* Returns { port, server } so the caller can close the server when done.
|
|
326
|
+
*/
|
|
327
|
+
nativeListen(port?: number): Promise<{
|
|
328
|
+
port: number;
|
|
329
|
+
server: Server;
|
|
330
|
+
}>;
|
|
116
331
|
listen(port?: number): Promise<void>;
|
|
332
|
+
/**
|
|
333
|
+
* Graceful shutdown — drains in-flight requests before closing.
|
|
334
|
+
* Use getShutdownManager().setDatabase(db, provider) to register DB cleanup.
|
|
335
|
+
*/
|
|
336
|
+
shutdown(options?: ShutdownOptions): Promise<void>;
|
|
337
|
+
getShutdownManager(): ShutdownManager;
|
|
117
338
|
getApp(): Hono;
|
|
118
339
|
get fetch(): (request: Request, Env?: unknown, executionCtx?: hono.ExecutionContext) => Response | Promise<Response>;
|
|
119
340
|
}
|
|
120
|
-
declare function createKozo(config?: KozoConfig): Kozo
|
|
341
|
+
declare function createKozo<TServices extends Services = Services>(config?: KozoConfig<TServices>): Kozo<TServices>;
|
|
121
342
|
|
|
343
|
+
type CompiledHandler = (c: Context) => Promise<Response> | Response;
|
|
122
344
|
type UserHandler = (c: any) => any;
|
|
123
345
|
type CompiledRoute = {
|
|
124
|
-
validateBody?:
|
|
125
|
-
validateQuery?:
|
|
126
|
-
validateParams?:
|
|
346
|
+
validateBody?: ValidateFunction;
|
|
347
|
+
validateQuery?: ValidateFunction;
|
|
348
|
+
validateParams?: ValidateFunction;
|
|
127
349
|
serialize?: (data: any) => string;
|
|
128
350
|
errors?: any;
|
|
129
351
|
};
|
|
130
352
|
declare class SchemaCompiler {
|
|
131
353
|
static compile(schema: RouteSchema): CompiledRoute;
|
|
132
354
|
}
|
|
133
|
-
declare function compileRouteHandler(
|
|
355
|
+
declare function compileRouteHandler(handler: UserHandler, schema: RouteSchema, services: Services, compiled: CompiledRoute): CompiledHandler;
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Build a NativeKozoContext for a native route handler.
|
|
359
|
+
*
|
|
360
|
+
* Called by the native handler compiler (`compiler.ts`) when the route
|
|
361
|
+
* is registered via `nativeRoute()`. Not intended for direct use.
|
|
362
|
+
*
|
|
363
|
+
* @internal
|
|
364
|
+
*/
|
|
365
|
+
declare function buildNativeContext<S extends RouteSchema, TSvc extends Services>(req: IncomingMessage, res: ServerResponse, params: Record<string, string>, body: any, services: TSvc, serialize?: (data: any) => string): NativeKozoContext<S, TSvc>;
|
|
366
|
+
|
|
367
|
+
/** Fast number → string for Content-Length. Cached for values < 10 000. */
|
|
368
|
+
declare function fastCL(n: number): string;
|
|
369
|
+
/**
|
|
370
|
+
* Write a 200 JSON response.
|
|
371
|
+
*
|
|
372
|
+
* IMPORTANT: `body` MUST be ASCII-safe (i.e. produced by JSON.stringify
|
|
373
|
+
* or fast-json-stringify). We use `body.length` instead of
|
|
374
|
+
* `Buffer.byteLength(body)` — valid because JSON serializers escape
|
|
375
|
+
* non-ASCII to `\uXXXX`, keeping the output 7-bit clean.
|
|
376
|
+
*/
|
|
377
|
+
declare function fastWriteJson(res: ServerResponse, body: string): void;
|
|
378
|
+
/**
|
|
379
|
+
* Write a plain text response.
|
|
380
|
+
*/
|
|
381
|
+
declare function fastWriteText(res: ServerResponse, body: string, status?: number): void;
|
|
382
|
+
/**
|
|
383
|
+
* Write an HTML response (SSR page rendering).
|
|
384
|
+
*/
|
|
385
|
+
declare function fastWriteHtml(res: ServerResponse, body: string, status?: number): void;
|
|
386
|
+
/**
|
|
387
|
+
* Write a JSON response with a custom status code.
|
|
388
|
+
*/
|
|
389
|
+
declare function fastWriteJsonStatus(res: ServerResponse, body: string, status: number): void;
|
|
390
|
+
/**
|
|
391
|
+
* Write a pre-built 404 Not Found response (zero allocation).
|
|
392
|
+
*/
|
|
393
|
+
declare function fastWrite404(res: ServerResponse): void;
|
|
394
|
+
/**
|
|
395
|
+
* Write a pre-built 500 Internal Server Error response (zero allocation).
|
|
396
|
+
*/
|
|
397
|
+
declare function fastWrite500(res: ServerResponse): void;
|
|
398
|
+
/**
|
|
399
|
+
* Write a 400 validation error response.
|
|
400
|
+
* Allocates only the error body string.
|
|
401
|
+
*/
|
|
402
|
+
declare function fastWrite400(field: string, errors: any, res: ServerResponse): void;
|
|
403
|
+
/**
|
|
404
|
+
* Write a KozoError as an RFC 7807 problem+json response.
|
|
405
|
+
* Falls back to 500 for unknown errors.
|
|
406
|
+
*/
|
|
407
|
+
declare function fastWriteError(err: unknown, res: ServerResponse): void;
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Kozo Error System - RFC 7807 Problem Details
|
|
411
|
+
*
|
|
412
|
+
* Standardized error format for all validation and runtime errors.
|
|
413
|
+
* Pre-serialized templates + frozen ResponseInit objects eliminate
|
|
414
|
+
* per-request allocations on the hot path.
|
|
415
|
+
*
|
|
416
|
+
* @see https://datatracker.ietf.org/doc/html/rfc7807
|
|
417
|
+
*/
|
|
418
|
+
interface ValidationError {
|
|
419
|
+
field: string;
|
|
420
|
+
message: string;
|
|
421
|
+
code: string;
|
|
422
|
+
value?: unknown;
|
|
423
|
+
}
|
|
424
|
+
interface ProblemDetails {
|
|
425
|
+
type: string;
|
|
426
|
+
title: string;
|
|
427
|
+
status: number;
|
|
428
|
+
detail?: string;
|
|
429
|
+
instance?: string;
|
|
430
|
+
errors?: ValidationError[];
|
|
431
|
+
}
|
|
432
|
+
declare const ERROR_RESPONSES: {
|
|
433
|
+
readonly VALIDATION_FAILED: {
|
|
434
|
+
readonly type: "https://kozo.dev/errors/validation-failed";
|
|
435
|
+
readonly title: "Validation Failed";
|
|
436
|
+
readonly status: 400;
|
|
437
|
+
};
|
|
438
|
+
readonly INVALID_BODY: {
|
|
439
|
+
readonly type: "https://kozo.dev/errors/invalid-body";
|
|
440
|
+
readonly title: "Invalid Request Body";
|
|
441
|
+
readonly status: 400;
|
|
442
|
+
};
|
|
443
|
+
readonly INVALID_QUERY: {
|
|
444
|
+
readonly type: "https://kozo.dev/errors/invalid-query";
|
|
445
|
+
readonly title: "Invalid Query Parameters";
|
|
446
|
+
readonly status: 400;
|
|
447
|
+
};
|
|
448
|
+
readonly INVALID_PARAMS: {
|
|
449
|
+
readonly type: "https://kozo.dev/errors/invalid-params";
|
|
450
|
+
readonly title: "Invalid Path Parameters";
|
|
451
|
+
readonly status: 400;
|
|
452
|
+
};
|
|
453
|
+
readonly INTERNAL_ERROR: {
|
|
454
|
+
readonly type: "https://kozo.dev/errors/internal-error";
|
|
455
|
+
readonly title: "Internal Server Error";
|
|
456
|
+
readonly status: 500;
|
|
457
|
+
};
|
|
458
|
+
readonly NOT_FOUND: {
|
|
459
|
+
readonly type: "https://kozo.dev/errors/not-found";
|
|
460
|
+
readonly title: "Resource Not Found";
|
|
461
|
+
readonly status: 404;
|
|
462
|
+
};
|
|
463
|
+
readonly UNAUTHORIZED: {
|
|
464
|
+
readonly type: "https://kozo.dev/errors/unauthorized";
|
|
465
|
+
readonly title: "Unauthorized";
|
|
466
|
+
readonly status: 401;
|
|
467
|
+
};
|
|
468
|
+
readonly FORBIDDEN: {
|
|
469
|
+
readonly type: "https://kozo.dev/errors/forbidden";
|
|
470
|
+
readonly title: "Forbidden";
|
|
471
|
+
readonly status: 403;
|
|
472
|
+
};
|
|
473
|
+
};
|
|
474
|
+
/**
|
|
475
|
+
* Convert Ajv validation errors to standardized format
|
|
476
|
+
*/
|
|
477
|
+
declare function formatAjvErrors(errors: any[] | null | undefined): ValidationError[];
|
|
478
|
+
/**
|
|
479
|
+
* Convert Zod validation errors to standardized format
|
|
480
|
+
*/
|
|
481
|
+
declare function formatZodErrors(errors: any): ValidationError[];
|
|
482
|
+
/**
|
|
483
|
+
* Build a 400 Validation Failed response.
|
|
484
|
+
* Called on every invalid request — kept as lean as possible.
|
|
485
|
+
*/
|
|
486
|
+
declare function validationErrorResponse(field: string, ajvErrors: any[] | null | undefined, instance?: string): Response;
|
|
487
|
+
/**
|
|
488
|
+
* Build a 500 Internal Server Error response.
|
|
489
|
+
*/
|
|
490
|
+
declare function internalErrorResponse(err: Error, instance?: string): Response;
|
|
491
|
+
declare function notFoundResponse(instance?: string): Response;
|
|
492
|
+
declare function unauthorizedResponse(instance?: string): Response;
|
|
493
|
+
declare function forbiddenResponse(instance?: string): Response;
|
|
494
|
+
declare class KozoError extends Error {
|
|
495
|
+
readonly statusCode: number;
|
|
496
|
+
readonly code: string;
|
|
497
|
+
constructor(message: string, statusCode: number, code: string);
|
|
498
|
+
toResponse(instance?: string): Response;
|
|
499
|
+
}
|
|
500
|
+
declare class ValidationFailedError extends KozoError {
|
|
501
|
+
readonly errors: ValidationError[];
|
|
502
|
+
constructor(message: string, errors?: ValidationError[]);
|
|
503
|
+
toResponse(instance?: string): Response;
|
|
504
|
+
}
|
|
505
|
+
declare class NotFoundError extends KozoError {
|
|
506
|
+
constructor(message?: string);
|
|
507
|
+
}
|
|
508
|
+
declare class UnauthorizedError extends KozoError {
|
|
509
|
+
constructor(message?: string);
|
|
510
|
+
}
|
|
511
|
+
declare class ForbiddenError extends KozoError {
|
|
512
|
+
constructor(message?: string);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
interface OpenAPIInfo {
|
|
516
|
+
title: string;
|
|
517
|
+
version: string;
|
|
518
|
+
description?: string;
|
|
519
|
+
contact?: {
|
|
520
|
+
name?: string;
|
|
521
|
+
url?: string;
|
|
522
|
+
email?: string;
|
|
523
|
+
};
|
|
524
|
+
license?: {
|
|
525
|
+
name: string;
|
|
526
|
+
url?: string;
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
interface OpenAPIConfig {
|
|
530
|
+
info: OpenAPIInfo;
|
|
531
|
+
servers?: Array<{
|
|
532
|
+
url: string;
|
|
533
|
+
description?: string;
|
|
534
|
+
}>;
|
|
535
|
+
tags?: Array<{
|
|
536
|
+
name: string;
|
|
537
|
+
description?: string;
|
|
538
|
+
}>;
|
|
539
|
+
security?: Array<Record<string, string[]>>;
|
|
540
|
+
}
|
|
541
|
+
interface OpenAPISpec {
|
|
542
|
+
openapi: '3.1.0';
|
|
543
|
+
info: OpenAPIInfo;
|
|
544
|
+
servers?: Array<{
|
|
545
|
+
url: string;
|
|
546
|
+
description?: string;
|
|
547
|
+
}>;
|
|
548
|
+
tags?: Array<{
|
|
549
|
+
name: string;
|
|
550
|
+
description?: string;
|
|
551
|
+
}>;
|
|
552
|
+
paths: Record<string, PathItem>;
|
|
553
|
+
components: {
|
|
554
|
+
schemas: Record<string, SchemaObject>;
|
|
555
|
+
securitySchemes?: Record<string, SecurityScheme>;
|
|
556
|
+
};
|
|
557
|
+
security?: Array<Record<string, string[]>>;
|
|
558
|
+
}
|
|
559
|
+
interface PathItem {
|
|
560
|
+
[method: string]: OperationObject;
|
|
561
|
+
}
|
|
562
|
+
interface OperationObject {
|
|
563
|
+
operationId?: string;
|
|
564
|
+
summary?: string;
|
|
565
|
+
description?: string;
|
|
566
|
+
tags?: string[];
|
|
567
|
+
parameters?: ParameterObject[];
|
|
568
|
+
requestBody?: RequestBodyObject;
|
|
569
|
+
responses: Record<string, ResponseObject>;
|
|
570
|
+
security?: Array<Record<string, string[]>>;
|
|
571
|
+
}
|
|
572
|
+
interface ParameterObject {
|
|
573
|
+
name: string;
|
|
574
|
+
in: 'query' | 'path' | 'header' | 'cookie';
|
|
575
|
+
required?: boolean;
|
|
576
|
+
schema: SchemaObject;
|
|
577
|
+
description?: string;
|
|
578
|
+
}
|
|
579
|
+
interface RequestBodyObject {
|
|
580
|
+
required?: boolean;
|
|
581
|
+
content: {
|
|
582
|
+
'application/json': {
|
|
583
|
+
schema: SchemaObject;
|
|
584
|
+
};
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
interface ResponseObject {
|
|
588
|
+
description: string;
|
|
589
|
+
content?: {
|
|
590
|
+
'application/json': {
|
|
591
|
+
schema: SchemaObject;
|
|
592
|
+
};
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
interface SchemaObject {
|
|
596
|
+
type?: string;
|
|
597
|
+
format?: string;
|
|
598
|
+
properties?: Record<string, SchemaObject>;
|
|
599
|
+
items?: SchemaObject;
|
|
600
|
+
required?: string[];
|
|
601
|
+
enum?: unknown[];
|
|
602
|
+
minimum?: number;
|
|
603
|
+
maximum?: number;
|
|
604
|
+
minLength?: number;
|
|
605
|
+
maxLength?: number;
|
|
606
|
+
pattern?: string;
|
|
607
|
+
description?: string;
|
|
608
|
+
default?: unknown;
|
|
609
|
+
nullable?: boolean;
|
|
610
|
+
oneOf?: SchemaObject[];
|
|
611
|
+
anyOf?: SchemaObject[];
|
|
612
|
+
allOf?: SchemaObject[];
|
|
613
|
+
additionalProperties?: SchemaObject | boolean;
|
|
614
|
+
$ref?: string;
|
|
615
|
+
}
|
|
616
|
+
interface SecurityScheme {
|
|
617
|
+
type: 'apiKey' | 'http' | 'oauth2' | 'openIdConnect';
|
|
618
|
+
scheme?: string;
|
|
619
|
+
bearerFormat?: string;
|
|
620
|
+
name?: string;
|
|
621
|
+
in?: 'query' | 'header' | 'cookie';
|
|
622
|
+
}
|
|
623
|
+
declare class OpenAPIGenerator {
|
|
624
|
+
private config;
|
|
625
|
+
private schemas;
|
|
626
|
+
private schemaCounter;
|
|
627
|
+
constructor(config: OpenAPIConfig);
|
|
628
|
+
/**
|
|
629
|
+
* Generate OpenAPI spec from routes
|
|
630
|
+
*/
|
|
631
|
+
generate(routes: RouteDefinition[]): OpenAPISpec;
|
|
632
|
+
/**
|
|
633
|
+
* Convert Hono path params to OpenAPI format
|
|
634
|
+
* :id -> {id}
|
|
635
|
+
*/
|
|
636
|
+
private honoPathToOpenApi;
|
|
637
|
+
/**
|
|
638
|
+
* Convert route to OpenAPI operation
|
|
639
|
+
*/
|
|
640
|
+
private routeToOperation;
|
|
641
|
+
/**
|
|
642
|
+
* Generate operation ID from path and method
|
|
643
|
+
*/
|
|
644
|
+
private generateOperationId;
|
|
645
|
+
/**
|
|
646
|
+
* Extract tag from path (first segment)
|
|
647
|
+
*/
|
|
648
|
+
private extractTag;
|
|
649
|
+
/**
|
|
650
|
+
* Get HTTP status description
|
|
651
|
+
*/
|
|
652
|
+
private getStatusDescription;
|
|
653
|
+
private capitalize;
|
|
654
|
+
}
|
|
655
|
+
declare function generateSwaggerHtml(specUrl: string, title?: string): string;
|
|
656
|
+
declare function createOpenAPIGenerator(config: OpenAPIConfig): OpenAPIGenerator;
|
|
134
657
|
|
|
135
|
-
export { type ClientGeneratorOptions, type CompiledRoute, Kozo, type KozoConfig, type KozoContext, type KozoHandler, type RouteInfo, type RouteSchema, SchemaCompiler, type Services, compileRouteHandler, createKozo, generateTypedClient };
|
|
658
|
+
export { type ClientGeneratorOptions, type CompiledRoute, ERROR_RESPONSES, ForbiddenError, type InferResponse, type InferSchema, type InflightTracker, Kozo, type KozoConfig, type KozoContext, type KozoEnv, KozoError, type KozoHandler, type NativeKozoContext, type NativeKozoHandler, NotFoundError, type OpenAPIConfig, OpenAPIGenerator, type OpenAPIInfo, type OpenAPISpec, type ProblemDetails, type RouteInfo, type RouteSchema, SchemaCompiler, type Services, ShutdownManager, type ShutdownOptions, type ShutdownState, UnauthorizedError, type ValidationError, ValidationFailedError, buildNativeContext, compileRouteHandler, createInflightTracker, createKozo, createOpenAPIGenerator, createShutdownManager, fastCL, fastWrite400, fastWrite404, fastWrite500, fastWriteError, fastWriteHtml, fastWriteJson, fastWriteJsonStatus, fastWriteText, forbiddenResponse, formatAjvErrors, formatZodErrors, generateSwaggerHtml, generateTypedClient, internalErrorResponse, notFoundResponse, trackRequest, unauthorizedResponse, validationErrorResponse };
|