@axeom/core 0.1.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.
- package/LICENSE +21 -0
- package/dist/index.cjs +804 -0
- package/dist/index.d.cts +291 -0
- package/dist/index.d.ts +291 -0
- package/dist/index.js +769 -0
- package/package.json +30 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { Logger } from '@axeom/logger-lib';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base error class for all Axeom-related failures.
|
|
5
|
+
* These are automatically caught and converted into structured JSON responses.
|
|
6
|
+
*/
|
|
7
|
+
declare class AxeomError extends Error {
|
|
8
|
+
message: string;
|
|
9
|
+
status: number;
|
|
10
|
+
code: string;
|
|
11
|
+
details?: any | undefined;
|
|
12
|
+
constructor(message: string, status?: number, code?: string, details?: any | undefined);
|
|
13
|
+
}
|
|
14
|
+
declare class NotFoundError extends AxeomError {
|
|
15
|
+
constructor(message?: string, details?: any);
|
|
16
|
+
}
|
|
17
|
+
declare class UnauthorizedError extends AxeomError {
|
|
18
|
+
constructor(message?: string, details?: any);
|
|
19
|
+
}
|
|
20
|
+
declare class BadRequestError extends AxeomError {
|
|
21
|
+
constructor(message?: string, details?: any);
|
|
22
|
+
}
|
|
23
|
+
declare class ForbiddenError extends AxeomError {
|
|
24
|
+
constructor(message?: string, details?: any);
|
|
25
|
+
}
|
|
26
|
+
declare class InternalServerError extends AxeomError {
|
|
27
|
+
constructor(message?: string);
|
|
28
|
+
}
|
|
29
|
+
declare class ConflictError extends AxeomError {
|
|
30
|
+
constructor(message?: string, details?: any);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type ExtractParams<T> = T extends `${string}/:${infer P}/${infer Rest}` ? P | ExtractParams<`/${Rest}`> : T extends `${string}/:${infer P}` ? P : never;
|
|
34
|
+
type ParamsObject<T extends string> = {
|
|
35
|
+
[K in ExtractParams<T>]: string;
|
|
36
|
+
};
|
|
37
|
+
type Prettify<T> = T extends Function | any[] ? T : {
|
|
38
|
+
[K in keyof T]: T[K] extends object ? Prettify<T[K]> : T[K];
|
|
39
|
+
} & {};
|
|
40
|
+
/**
|
|
41
|
+
* Contract for schema validation. Implementing this allows custom object types
|
|
42
|
+
* to be used in RouteSchema.
|
|
43
|
+
*/
|
|
44
|
+
interface Validator<T = any> {
|
|
45
|
+
_output: T;
|
|
46
|
+
parse: (data: unknown) => T | Promise<T>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Defines the validation structure for a route's parameters, query, and body.
|
|
50
|
+
*/
|
|
51
|
+
type RouteSchema = {
|
|
52
|
+
body?: Validator;
|
|
53
|
+
query?: Validator;
|
|
54
|
+
params?: Validator;
|
|
55
|
+
responses?: Record<number, any>;
|
|
56
|
+
summary?: string;
|
|
57
|
+
description?: string;
|
|
58
|
+
tags?: string[];
|
|
59
|
+
};
|
|
60
|
+
type Infer<S> = S extends Validator<infer T> ? T : any;
|
|
61
|
+
type RouteInput<Path extends string, S extends RouteSchema> = Prettify<(S["body"] extends Validator ? {
|
|
62
|
+
body: Infer<S["body"]>;
|
|
63
|
+
} : {
|
|
64
|
+
body?: never;
|
|
65
|
+
}) & (S["query"] extends Validator ? {
|
|
66
|
+
query: Infer<S["query"]>;
|
|
67
|
+
} : {
|
|
68
|
+
query?: Record<string, string | undefined>;
|
|
69
|
+
}) & (keyof ParamsObject<Path> extends never ? {
|
|
70
|
+
params?: ParamsObject<Path>;
|
|
71
|
+
} : {
|
|
72
|
+
params: ParamsObject<Path>;
|
|
73
|
+
})>;
|
|
74
|
+
type RouteMetadata<Path extends string, S extends RouteSchema, Return> = {
|
|
75
|
+
input: RouteInput<Path, S>;
|
|
76
|
+
output: Return;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Automatically prefixes all keys in a metadata object (e.g., "GET /users" -> "GET /v1/users")
|
|
80
|
+
*/
|
|
81
|
+
type PrefixT<Prefix extends string, T> = {
|
|
82
|
+
[K in keyof T as K extends `${infer Method} ${infer Path}` ? `${Method} ${Prefix}${Path}` extends `${infer M} ${infer P}` ? `${M} ${P extends `/${string}` ? P : `/${P}`}` : never : never]: T[K];
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* The request context passed to every route handler.
|
|
86
|
+
* Provides access to parsed body, query, params, and decorators.
|
|
87
|
+
*/
|
|
88
|
+
type Context<Path extends string, S extends RouteSchema = {}, T extends Record<string, any> = {}, D extends Record<string, any> = {}> = Prettify<{
|
|
89
|
+
/** The URL path parameters. */
|
|
90
|
+
params: S["params"] extends Validator ? Infer<S["params"]> : ParamsObject<Path>;
|
|
91
|
+
/** The URL search parameters. */
|
|
92
|
+
query: S["query"] extends Validator ? Infer<S["query"]> : Record<string, string | undefined>;
|
|
93
|
+
/** The parsed request body. */
|
|
94
|
+
body: S["body"] extends Validator ? Infer<S["body"]> : any;
|
|
95
|
+
/** Standard Web Headers object. */
|
|
96
|
+
headers: Headers;
|
|
97
|
+
/** The original Web Request object. */
|
|
98
|
+
request: Request;
|
|
99
|
+
/** The start time of the request in milliseconds. */
|
|
100
|
+
time: number;
|
|
101
|
+
/** Marks the duration for a specific label, returning the elapsed time since start. */
|
|
102
|
+
setDuration: (label: string) => number;
|
|
103
|
+
/** Helper to set a response header. */
|
|
104
|
+
setResponseHeader: (name: string, value: string) => void;
|
|
105
|
+
/** Internal helper to retrieve manual headers. */
|
|
106
|
+
getResponseHeaders: () => Record<string, string>;
|
|
107
|
+
} & T & D>;
|
|
108
|
+
/**
|
|
109
|
+
* A function that handles an incoming request for a specific route.
|
|
110
|
+
*/
|
|
111
|
+
type Handler<Path extends string = string, S extends RouteSchema = {}, T extends Record<string, any> = {}, D extends Record<string, any> = {}, Return = any> = (ctx: Context<Path, S, T, D>) => Return | Promise<Return>;
|
|
112
|
+
interface Route<T extends Record<string, any> = any, D extends Record<string, any> = any> {
|
|
113
|
+
method: string;
|
|
114
|
+
path: string;
|
|
115
|
+
regex: RegExp;
|
|
116
|
+
handler: Handler<any, any, T, D, any>;
|
|
117
|
+
paramNames: string[];
|
|
118
|
+
schema?: RouteSchema;
|
|
119
|
+
derives: Array<(ctx: any) => any>;
|
|
120
|
+
decorators: Record<string, any>;
|
|
121
|
+
onRequests?: Array<(ctx: any) => void | Promise<void>>;
|
|
122
|
+
onResponses?: Array<(res: Response, ctx: any) => Response | void | undefined | Promise<Response | void | undefined>>;
|
|
123
|
+
beforeHandles: Array<(ctx: Context<any, any, T, D>) => Response | void | undefined | Promise<Response | void | undefined>>;
|
|
124
|
+
afterHandles: Array<(ctx: Context<any, any, T, D>) => Response | void | undefined | Promise<Response | void | undefined>>;
|
|
125
|
+
metadata?: Record<string, any>;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Manages route registration and path matching using a Radix Tree.
|
|
130
|
+
*/
|
|
131
|
+
declare class Router<T extends Record<string, any>, D extends Record<string, any>> {
|
|
132
|
+
private tree;
|
|
133
|
+
private routes;
|
|
134
|
+
/**
|
|
135
|
+
* Registers a new route with its associated state (hooks, derivations, and decorators).
|
|
136
|
+
*/
|
|
137
|
+
add<Path extends string, S extends RouteSchema, Return>(method: string, path: Path, handler: Handler<Path, S, T, D, Return>, state: {
|
|
138
|
+
derives: any[];
|
|
139
|
+
decorators: any;
|
|
140
|
+
onRequests: any[];
|
|
141
|
+
onResponses: any[];
|
|
142
|
+
beforeHandles: any[];
|
|
143
|
+
afterHandles: any[];
|
|
144
|
+
}, schema?: S, metadata?: Record<string, any>): Route<T, D>;
|
|
145
|
+
/**
|
|
146
|
+
* Finds a matching route for the given method and pathname.
|
|
147
|
+
*/
|
|
148
|
+
match(method: string, pathname: string): {
|
|
149
|
+
route: Route<T, D>;
|
|
150
|
+
match: string[];
|
|
151
|
+
} | null;
|
|
152
|
+
addRoute(route: Route<T, D>): void;
|
|
153
|
+
getRoutes(): Route<T, D>[];
|
|
154
|
+
setRoutes(routes: Route<T, D>[]): void;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Internal symbol used to store the server instance in the context.
|
|
159
|
+
*/
|
|
160
|
+
declare const $SERVER: unique symbol;
|
|
161
|
+
/**
|
|
162
|
+
* The primary engine of the Axeom framework.
|
|
163
|
+
*
|
|
164
|
+
* Axeom is a WinterTC-compliant, type-safe web framework designed for high-performance
|
|
165
|
+
* and modularity. It supports automatic runtime detection (Bun, Deno, Node) and
|
|
166
|
+
* provides a powerful plugin system.
|
|
167
|
+
*
|
|
168
|
+
* @template T - A record of route strings to their respective metadata, used for type-safe client generation.
|
|
169
|
+
* @template D - A record of objects and utilities available on the request context (decorators).
|
|
170
|
+
*/
|
|
171
|
+
declare class Axeom<T extends Record<string, any> = {}, D extends Record<string, any> = {
|
|
172
|
+
logger: Logger;
|
|
173
|
+
error: {
|
|
174
|
+
NotFound: (msg?: string) => NotFoundError;
|
|
175
|
+
Unauthorized: (msg?: string) => UnauthorizedError;
|
|
176
|
+
BadRequest: (msg?: string) => BadRequestError;
|
|
177
|
+
Forbidden: (msg?: string) => ForbiddenError;
|
|
178
|
+
Conflict: (msg?: string) => ConflictError;
|
|
179
|
+
};
|
|
180
|
+
}> {
|
|
181
|
+
router: Router<T, D>;
|
|
182
|
+
private hooks;
|
|
183
|
+
private server;
|
|
184
|
+
private derives;
|
|
185
|
+
private decorators;
|
|
186
|
+
private errorHandler;
|
|
187
|
+
/**
|
|
188
|
+
* Adds dynamic properties to the context by running a function before the route handler.
|
|
189
|
+
* Derivations can be asynchronous and can return a Response to short-circuit the request.
|
|
190
|
+
*
|
|
191
|
+
* @param fn - A function that receives the current context and returns new properties to merge.
|
|
192
|
+
*/
|
|
193
|
+
derive<NewD extends Record<string, any>>(fn: (ctx: Context<any, any, T, D>) => NewD | Response | Promise<NewD | Response>): Axeom<T, D & Exclude<NewD, Response>>;
|
|
194
|
+
/**
|
|
195
|
+
* Registers a plugin.
|
|
196
|
+
* Plugins are functions that receive the Axeom instance and can register routes,
|
|
197
|
+
* hooks, or decorators.
|
|
198
|
+
*
|
|
199
|
+
* @param plugin - The plugin function to execute.
|
|
200
|
+
*/
|
|
201
|
+
use<NewT extends Record<string, any>, NewD extends Record<string, any>>(plugin: (app: Axeom<T, D>) => Axeom<NewT, NewD>): Axeom<T & NewT, NewD>;
|
|
202
|
+
/**
|
|
203
|
+
* Groups routes under a common path prefix.
|
|
204
|
+
* This provides isolation for derivations and hooks within the group.
|
|
205
|
+
*
|
|
206
|
+
* @param prefix - The path prefix (e.g., "/api/v1").
|
|
207
|
+
* @param run - A function where you define the routes for this group.
|
|
208
|
+
*/
|
|
209
|
+
group<Prefix extends string, NewT extends Record<string, any>, NewD extends Record<string, any>>(prefix: Prefix, run: (app: Axeom<T, D>) => Axeom<NewT, NewD>): Axeom<T & PrefixT<Prefix, NewT>, NewD>;
|
|
210
|
+
/**
|
|
211
|
+
* Adds static properties to the context.
|
|
212
|
+
* Decorators are available on every request context immediately.
|
|
213
|
+
*
|
|
214
|
+
* @param obj - An object containing properties to add to the context.
|
|
215
|
+
*/
|
|
216
|
+
decorate<NewD extends Record<string, any>>(obj: NewD): Axeom<T, D & NewD>;
|
|
217
|
+
protected addRoute<Method extends string, Path extends string, S extends RouteSchema = {}, Return = any>(method: Method, path: Path, handler: Handler<Path, S, T, D, Return>, schema?: S, metadata?: Record<string, any>): Axeom<T & { [K in `${Method} ${Path}`]: RouteMetadata<Path, S, Return>; }, D>;
|
|
218
|
+
get<Path extends string, S extends RouteSchema = {}, Return = any>(path: Path, handler: Handler<Path, S, T, D, Return>, schema?: S): Axeom<T & { [K in `GET ${Path}`]: RouteMetadata<Path, S, Return>; }, D>;
|
|
219
|
+
post<Path extends string, S extends RouteSchema = {}, Return = any>(path: Path, handler: Handler<Path, S, T, D, Return>, schema?: S): Axeom<T & { [K in `POST ${Path}`]: RouteMetadata<Path, S, Return>; }, D>;
|
|
220
|
+
put<Path extends string, S extends RouteSchema = {}, Return = any>(path: Path, handler: Handler<Path, S, T, D, Return>, schema?: S): Axeom<T & { [K in `PUT ${Path}`]: RouteMetadata<Path, S, Return>; }, D>;
|
|
221
|
+
patch<Path extends string, S extends RouteSchema = {}, Return = any>(path: Path, handler: Handler<Path, S, T, D, Return>, schema?: S): Axeom<T & { [K in `PATCH ${Path}`]: RouteMetadata<Path, S, Return>; }, D>;
|
|
222
|
+
delete<Path extends string, S extends RouteSchema = {}, Return = any>(path: Path, handler: Handler<Path, S, T, D, Return>, schema?: S): Axeom<T & { [K in `DELETE ${Path}`]: RouteMetadata<Path, S, Return>; }, D>;
|
|
223
|
+
/**
|
|
224
|
+
* Main entry point for handling requests.
|
|
225
|
+
*
|
|
226
|
+
* This is the standard WinterTC interface that converts a Request into a Response.
|
|
227
|
+
* It executes the entire request lifecycle including hooks, derivations, and validation.
|
|
228
|
+
*
|
|
229
|
+
* @param incomingRequest - The standard Web Request object.
|
|
230
|
+
* @param options - Optional runtime configuration (e.g. server instance).
|
|
231
|
+
* @returns A promise resolving to a standard Web Response object.
|
|
232
|
+
*/
|
|
233
|
+
handle(incomingRequest: Request, options?: {
|
|
234
|
+
server?: any;
|
|
235
|
+
}): Promise<Response>;
|
|
236
|
+
/**
|
|
237
|
+
* Internal method used by adapters to handle both HTTP and WebSocket handshakes.
|
|
238
|
+
* Returns the final response and the context used for the request.
|
|
239
|
+
*/
|
|
240
|
+
_handleHandshake(incomingRequest: Request, options?: {
|
|
241
|
+
server?: any;
|
|
242
|
+
}): Promise<{
|
|
243
|
+
response: Response;
|
|
244
|
+
context?: any;
|
|
245
|
+
}>;
|
|
246
|
+
/**
|
|
247
|
+
* Registers a global error handler.
|
|
248
|
+
*/
|
|
249
|
+
onError(fn: (error: any, ctx: Context<any, any, T, D>) => any): this;
|
|
250
|
+
/**
|
|
251
|
+
* Registers a global hook that runs as soon as a request is received.
|
|
252
|
+
*/
|
|
253
|
+
onRequest(fn: (ctx: Context<any, any, T, D>) => void | Promise<void>): this;
|
|
254
|
+
/**
|
|
255
|
+
* Registers a hook that runs before the router attempts to match a path.
|
|
256
|
+
* Useful for global redirects or early security checks.
|
|
257
|
+
*/
|
|
258
|
+
onBeforeMatch(fn: (req: Request) => Response | void | undefined | Promise<Response | void | undefined>): this;
|
|
259
|
+
/**
|
|
260
|
+
* Registers a global hook that runs after a Response has been created.
|
|
261
|
+
* Allows modifying headers or the body before it's sent.
|
|
262
|
+
*/
|
|
263
|
+
onResponse(fn: (res: Response, ctx: Context<any, any, T, D>) => Response | void | undefined | Promise<Response | void | undefined>): this;
|
|
264
|
+
/**
|
|
265
|
+
* Registers a hook that runs before the route handler is executed.
|
|
266
|
+
*/
|
|
267
|
+
onBeforeHandle(fn: (ctx: Context<any, any, T, D>) => Response | void | undefined | Promise<Response | void | undefined>): this;
|
|
268
|
+
/**
|
|
269
|
+
* Registers a hook that runs after the route handler is executed.
|
|
270
|
+
*/
|
|
271
|
+
onAfterHandle(fn: (ctx: Context<any, any, T, D>) => Response | void | undefined | Promise<Response | void | undefined>): this;
|
|
272
|
+
/**
|
|
273
|
+
* Registers a Server-Sent Events (SSE) route.
|
|
274
|
+
*
|
|
275
|
+
* @param path - The path for the SSE stream.
|
|
276
|
+
* @param handler - A function returning an async iterable that yields data chunks.
|
|
277
|
+
*/
|
|
278
|
+
sse<T = any>(path: string, handler: (ctx: any) => AsyncIterable<T> | Promise<AsyncIterable<T>>): Axeom<T_1 & {
|
|
279
|
+
[x: `GET ${string}`]: RouteMetadata<string, {}, Response>;
|
|
280
|
+
}, D>;
|
|
281
|
+
/**
|
|
282
|
+
* Automatically detect the runtime and start a server.
|
|
283
|
+
* Currently supports: Bun, Deno.
|
|
284
|
+
* For Node, use a specific adapter like @axeom/express.
|
|
285
|
+
*
|
|
286
|
+
* @param portOrOptions - The port number or a server options object.
|
|
287
|
+
*/
|
|
288
|
+
listen(portOrOptions?: number | any): any;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export { $SERVER, Axeom, AxeomError, BadRequestError, ConflictError, type Context, type ExtractParams, ForbiddenError, type Handler, type Infer, InternalServerError, NotFoundError, type ParamsObject, type PrefixT, type Prettify, type Route, type RouteInput, type RouteMetadata, type RouteSchema, UnauthorizedError, type Validator, Axeom as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { Logger } from '@axeom/logger-lib';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base error class for all Axeom-related failures.
|
|
5
|
+
* These are automatically caught and converted into structured JSON responses.
|
|
6
|
+
*/
|
|
7
|
+
declare class AxeomError extends Error {
|
|
8
|
+
message: string;
|
|
9
|
+
status: number;
|
|
10
|
+
code: string;
|
|
11
|
+
details?: any | undefined;
|
|
12
|
+
constructor(message: string, status?: number, code?: string, details?: any | undefined);
|
|
13
|
+
}
|
|
14
|
+
declare class NotFoundError extends AxeomError {
|
|
15
|
+
constructor(message?: string, details?: any);
|
|
16
|
+
}
|
|
17
|
+
declare class UnauthorizedError extends AxeomError {
|
|
18
|
+
constructor(message?: string, details?: any);
|
|
19
|
+
}
|
|
20
|
+
declare class BadRequestError extends AxeomError {
|
|
21
|
+
constructor(message?: string, details?: any);
|
|
22
|
+
}
|
|
23
|
+
declare class ForbiddenError extends AxeomError {
|
|
24
|
+
constructor(message?: string, details?: any);
|
|
25
|
+
}
|
|
26
|
+
declare class InternalServerError extends AxeomError {
|
|
27
|
+
constructor(message?: string);
|
|
28
|
+
}
|
|
29
|
+
declare class ConflictError extends AxeomError {
|
|
30
|
+
constructor(message?: string, details?: any);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type ExtractParams<T> = T extends `${string}/:${infer P}/${infer Rest}` ? P | ExtractParams<`/${Rest}`> : T extends `${string}/:${infer P}` ? P : never;
|
|
34
|
+
type ParamsObject<T extends string> = {
|
|
35
|
+
[K in ExtractParams<T>]: string;
|
|
36
|
+
};
|
|
37
|
+
type Prettify<T> = T extends Function | any[] ? T : {
|
|
38
|
+
[K in keyof T]: T[K] extends object ? Prettify<T[K]> : T[K];
|
|
39
|
+
} & {};
|
|
40
|
+
/**
|
|
41
|
+
* Contract for schema validation. Implementing this allows custom object types
|
|
42
|
+
* to be used in RouteSchema.
|
|
43
|
+
*/
|
|
44
|
+
interface Validator<T = any> {
|
|
45
|
+
_output: T;
|
|
46
|
+
parse: (data: unknown) => T | Promise<T>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Defines the validation structure for a route's parameters, query, and body.
|
|
50
|
+
*/
|
|
51
|
+
type RouteSchema = {
|
|
52
|
+
body?: Validator;
|
|
53
|
+
query?: Validator;
|
|
54
|
+
params?: Validator;
|
|
55
|
+
responses?: Record<number, any>;
|
|
56
|
+
summary?: string;
|
|
57
|
+
description?: string;
|
|
58
|
+
tags?: string[];
|
|
59
|
+
};
|
|
60
|
+
type Infer<S> = S extends Validator<infer T> ? T : any;
|
|
61
|
+
type RouteInput<Path extends string, S extends RouteSchema> = Prettify<(S["body"] extends Validator ? {
|
|
62
|
+
body: Infer<S["body"]>;
|
|
63
|
+
} : {
|
|
64
|
+
body?: never;
|
|
65
|
+
}) & (S["query"] extends Validator ? {
|
|
66
|
+
query: Infer<S["query"]>;
|
|
67
|
+
} : {
|
|
68
|
+
query?: Record<string, string | undefined>;
|
|
69
|
+
}) & (keyof ParamsObject<Path> extends never ? {
|
|
70
|
+
params?: ParamsObject<Path>;
|
|
71
|
+
} : {
|
|
72
|
+
params: ParamsObject<Path>;
|
|
73
|
+
})>;
|
|
74
|
+
type RouteMetadata<Path extends string, S extends RouteSchema, Return> = {
|
|
75
|
+
input: RouteInput<Path, S>;
|
|
76
|
+
output: Return;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Automatically prefixes all keys in a metadata object (e.g., "GET /users" -> "GET /v1/users")
|
|
80
|
+
*/
|
|
81
|
+
type PrefixT<Prefix extends string, T> = {
|
|
82
|
+
[K in keyof T as K extends `${infer Method} ${infer Path}` ? `${Method} ${Prefix}${Path}` extends `${infer M} ${infer P}` ? `${M} ${P extends `/${string}` ? P : `/${P}`}` : never : never]: T[K];
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* The request context passed to every route handler.
|
|
86
|
+
* Provides access to parsed body, query, params, and decorators.
|
|
87
|
+
*/
|
|
88
|
+
type Context<Path extends string, S extends RouteSchema = {}, T extends Record<string, any> = {}, D extends Record<string, any> = {}> = Prettify<{
|
|
89
|
+
/** The URL path parameters. */
|
|
90
|
+
params: S["params"] extends Validator ? Infer<S["params"]> : ParamsObject<Path>;
|
|
91
|
+
/** The URL search parameters. */
|
|
92
|
+
query: S["query"] extends Validator ? Infer<S["query"]> : Record<string, string | undefined>;
|
|
93
|
+
/** The parsed request body. */
|
|
94
|
+
body: S["body"] extends Validator ? Infer<S["body"]> : any;
|
|
95
|
+
/** Standard Web Headers object. */
|
|
96
|
+
headers: Headers;
|
|
97
|
+
/** The original Web Request object. */
|
|
98
|
+
request: Request;
|
|
99
|
+
/** The start time of the request in milliseconds. */
|
|
100
|
+
time: number;
|
|
101
|
+
/** Marks the duration for a specific label, returning the elapsed time since start. */
|
|
102
|
+
setDuration: (label: string) => number;
|
|
103
|
+
/** Helper to set a response header. */
|
|
104
|
+
setResponseHeader: (name: string, value: string) => void;
|
|
105
|
+
/** Internal helper to retrieve manual headers. */
|
|
106
|
+
getResponseHeaders: () => Record<string, string>;
|
|
107
|
+
} & T & D>;
|
|
108
|
+
/**
|
|
109
|
+
* A function that handles an incoming request for a specific route.
|
|
110
|
+
*/
|
|
111
|
+
type Handler<Path extends string = string, S extends RouteSchema = {}, T extends Record<string, any> = {}, D extends Record<string, any> = {}, Return = any> = (ctx: Context<Path, S, T, D>) => Return | Promise<Return>;
|
|
112
|
+
interface Route<T extends Record<string, any> = any, D extends Record<string, any> = any> {
|
|
113
|
+
method: string;
|
|
114
|
+
path: string;
|
|
115
|
+
regex: RegExp;
|
|
116
|
+
handler: Handler<any, any, T, D, any>;
|
|
117
|
+
paramNames: string[];
|
|
118
|
+
schema?: RouteSchema;
|
|
119
|
+
derives: Array<(ctx: any) => any>;
|
|
120
|
+
decorators: Record<string, any>;
|
|
121
|
+
onRequests?: Array<(ctx: any) => void | Promise<void>>;
|
|
122
|
+
onResponses?: Array<(res: Response, ctx: any) => Response | void | undefined | Promise<Response | void | undefined>>;
|
|
123
|
+
beforeHandles: Array<(ctx: Context<any, any, T, D>) => Response | void | undefined | Promise<Response | void | undefined>>;
|
|
124
|
+
afterHandles: Array<(ctx: Context<any, any, T, D>) => Response | void | undefined | Promise<Response | void | undefined>>;
|
|
125
|
+
metadata?: Record<string, any>;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Manages route registration and path matching using a Radix Tree.
|
|
130
|
+
*/
|
|
131
|
+
declare class Router<T extends Record<string, any>, D extends Record<string, any>> {
|
|
132
|
+
private tree;
|
|
133
|
+
private routes;
|
|
134
|
+
/**
|
|
135
|
+
* Registers a new route with its associated state (hooks, derivations, and decorators).
|
|
136
|
+
*/
|
|
137
|
+
add<Path extends string, S extends RouteSchema, Return>(method: string, path: Path, handler: Handler<Path, S, T, D, Return>, state: {
|
|
138
|
+
derives: any[];
|
|
139
|
+
decorators: any;
|
|
140
|
+
onRequests: any[];
|
|
141
|
+
onResponses: any[];
|
|
142
|
+
beforeHandles: any[];
|
|
143
|
+
afterHandles: any[];
|
|
144
|
+
}, schema?: S, metadata?: Record<string, any>): Route<T, D>;
|
|
145
|
+
/**
|
|
146
|
+
* Finds a matching route for the given method and pathname.
|
|
147
|
+
*/
|
|
148
|
+
match(method: string, pathname: string): {
|
|
149
|
+
route: Route<T, D>;
|
|
150
|
+
match: string[];
|
|
151
|
+
} | null;
|
|
152
|
+
addRoute(route: Route<T, D>): void;
|
|
153
|
+
getRoutes(): Route<T, D>[];
|
|
154
|
+
setRoutes(routes: Route<T, D>[]): void;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Internal symbol used to store the server instance in the context.
|
|
159
|
+
*/
|
|
160
|
+
declare const $SERVER: unique symbol;
|
|
161
|
+
/**
|
|
162
|
+
* The primary engine of the Axeom framework.
|
|
163
|
+
*
|
|
164
|
+
* Axeom is a WinterTC-compliant, type-safe web framework designed for high-performance
|
|
165
|
+
* and modularity. It supports automatic runtime detection (Bun, Deno, Node) and
|
|
166
|
+
* provides a powerful plugin system.
|
|
167
|
+
*
|
|
168
|
+
* @template T - A record of route strings to their respective metadata, used for type-safe client generation.
|
|
169
|
+
* @template D - A record of objects and utilities available on the request context (decorators).
|
|
170
|
+
*/
|
|
171
|
+
declare class Axeom<T extends Record<string, any> = {}, D extends Record<string, any> = {
|
|
172
|
+
logger: Logger;
|
|
173
|
+
error: {
|
|
174
|
+
NotFound: (msg?: string) => NotFoundError;
|
|
175
|
+
Unauthorized: (msg?: string) => UnauthorizedError;
|
|
176
|
+
BadRequest: (msg?: string) => BadRequestError;
|
|
177
|
+
Forbidden: (msg?: string) => ForbiddenError;
|
|
178
|
+
Conflict: (msg?: string) => ConflictError;
|
|
179
|
+
};
|
|
180
|
+
}> {
|
|
181
|
+
router: Router<T, D>;
|
|
182
|
+
private hooks;
|
|
183
|
+
private server;
|
|
184
|
+
private derives;
|
|
185
|
+
private decorators;
|
|
186
|
+
private errorHandler;
|
|
187
|
+
/**
|
|
188
|
+
* Adds dynamic properties to the context by running a function before the route handler.
|
|
189
|
+
* Derivations can be asynchronous and can return a Response to short-circuit the request.
|
|
190
|
+
*
|
|
191
|
+
* @param fn - A function that receives the current context and returns new properties to merge.
|
|
192
|
+
*/
|
|
193
|
+
derive<NewD extends Record<string, any>>(fn: (ctx: Context<any, any, T, D>) => NewD | Response | Promise<NewD | Response>): Axeom<T, D & Exclude<NewD, Response>>;
|
|
194
|
+
/**
|
|
195
|
+
* Registers a plugin.
|
|
196
|
+
* Plugins are functions that receive the Axeom instance and can register routes,
|
|
197
|
+
* hooks, or decorators.
|
|
198
|
+
*
|
|
199
|
+
* @param plugin - The plugin function to execute.
|
|
200
|
+
*/
|
|
201
|
+
use<NewT extends Record<string, any>, NewD extends Record<string, any>>(plugin: (app: Axeom<T, D>) => Axeom<NewT, NewD>): Axeom<T & NewT, NewD>;
|
|
202
|
+
/**
|
|
203
|
+
* Groups routes under a common path prefix.
|
|
204
|
+
* This provides isolation for derivations and hooks within the group.
|
|
205
|
+
*
|
|
206
|
+
* @param prefix - The path prefix (e.g., "/api/v1").
|
|
207
|
+
* @param run - A function where you define the routes for this group.
|
|
208
|
+
*/
|
|
209
|
+
group<Prefix extends string, NewT extends Record<string, any>, NewD extends Record<string, any>>(prefix: Prefix, run: (app: Axeom<T, D>) => Axeom<NewT, NewD>): Axeom<T & PrefixT<Prefix, NewT>, NewD>;
|
|
210
|
+
/**
|
|
211
|
+
* Adds static properties to the context.
|
|
212
|
+
* Decorators are available on every request context immediately.
|
|
213
|
+
*
|
|
214
|
+
* @param obj - An object containing properties to add to the context.
|
|
215
|
+
*/
|
|
216
|
+
decorate<NewD extends Record<string, any>>(obj: NewD): Axeom<T, D & NewD>;
|
|
217
|
+
protected addRoute<Method extends string, Path extends string, S extends RouteSchema = {}, Return = any>(method: Method, path: Path, handler: Handler<Path, S, T, D, Return>, schema?: S, metadata?: Record<string, any>): Axeom<T & { [K in `${Method} ${Path}`]: RouteMetadata<Path, S, Return>; }, D>;
|
|
218
|
+
get<Path extends string, S extends RouteSchema = {}, Return = any>(path: Path, handler: Handler<Path, S, T, D, Return>, schema?: S): Axeom<T & { [K in `GET ${Path}`]: RouteMetadata<Path, S, Return>; }, D>;
|
|
219
|
+
post<Path extends string, S extends RouteSchema = {}, Return = any>(path: Path, handler: Handler<Path, S, T, D, Return>, schema?: S): Axeom<T & { [K in `POST ${Path}`]: RouteMetadata<Path, S, Return>; }, D>;
|
|
220
|
+
put<Path extends string, S extends RouteSchema = {}, Return = any>(path: Path, handler: Handler<Path, S, T, D, Return>, schema?: S): Axeom<T & { [K in `PUT ${Path}`]: RouteMetadata<Path, S, Return>; }, D>;
|
|
221
|
+
patch<Path extends string, S extends RouteSchema = {}, Return = any>(path: Path, handler: Handler<Path, S, T, D, Return>, schema?: S): Axeom<T & { [K in `PATCH ${Path}`]: RouteMetadata<Path, S, Return>; }, D>;
|
|
222
|
+
delete<Path extends string, S extends RouteSchema = {}, Return = any>(path: Path, handler: Handler<Path, S, T, D, Return>, schema?: S): Axeom<T & { [K in `DELETE ${Path}`]: RouteMetadata<Path, S, Return>; }, D>;
|
|
223
|
+
/**
|
|
224
|
+
* Main entry point for handling requests.
|
|
225
|
+
*
|
|
226
|
+
* This is the standard WinterTC interface that converts a Request into a Response.
|
|
227
|
+
* It executes the entire request lifecycle including hooks, derivations, and validation.
|
|
228
|
+
*
|
|
229
|
+
* @param incomingRequest - The standard Web Request object.
|
|
230
|
+
* @param options - Optional runtime configuration (e.g. server instance).
|
|
231
|
+
* @returns A promise resolving to a standard Web Response object.
|
|
232
|
+
*/
|
|
233
|
+
handle(incomingRequest: Request, options?: {
|
|
234
|
+
server?: any;
|
|
235
|
+
}): Promise<Response>;
|
|
236
|
+
/**
|
|
237
|
+
* Internal method used by adapters to handle both HTTP and WebSocket handshakes.
|
|
238
|
+
* Returns the final response and the context used for the request.
|
|
239
|
+
*/
|
|
240
|
+
_handleHandshake(incomingRequest: Request, options?: {
|
|
241
|
+
server?: any;
|
|
242
|
+
}): Promise<{
|
|
243
|
+
response: Response;
|
|
244
|
+
context?: any;
|
|
245
|
+
}>;
|
|
246
|
+
/**
|
|
247
|
+
* Registers a global error handler.
|
|
248
|
+
*/
|
|
249
|
+
onError(fn: (error: any, ctx: Context<any, any, T, D>) => any): this;
|
|
250
|
+
/**
|
|
251
|
+
* Registers a global hook that runs as soon as a request is received.
|
|
252
|
+
*/
|
|
253
|
+
onRequest(fn: (ctx: Context<any, any, T, D>) => void | Promise<void>): this;
|
|
254
|
+
/**
|
|
255
|
+
* Registers a hook that runs before the router attempts to match a path.
|
|
256
|
+
* Useful for global redirects or early security checks.
|
|
257
|
+
*/
|
|
258
|
+
onBeforeMatch(fn: (req: Request) => Response | void | undefined | Promise<Response | void | undefined>): this;
|
|
259
|
+
/**
|
|
260
|
+
* Registers a global hook that runs after a Response has been created.
|
|
261
|
+
* Allows modifying headers or the body before it's sent.
|
|
262
|
+
*/
|
|
263
|
+
onResponse(fn: (res: Response, ctx: Context<any, any, T, D>) => Response | void | undefined | Promise<Response | void | undefined>): this;
|
|
264
|
+
/**
|
|
265
|
+
* Registers a hook that runs before the route handler is executed.
|
|
266
|
+
*/
|
|
267
|
+
onBeforeHandle(fn: (ctx: Context<any, any, T, D>) => Response | void | undefined | Promise<Response | void | undefined>): this;
|
|
268
|
+
/**
|
|
269
|
+
* Registers a hook that runs after the route handler is executed.
|
|
270
|
+
*/
|
|
271
|
+
onAfterHandle(fn: (ctx: Context<any, any, T, D>) => Response | void | undefined | Promise<Response | void | undefined>): this;
|
|
272
|
+
/**
|
|
273
|
+
* Registers a Server-Sent Events (SSE) route.
|
|
274
|
+
*
|
|
275
|
+
* @param path - The path for the SSE stream.
|
|
276
|
+
* @param handler - A function returning an async iterable that yields data chunks.
|
|
277
|
+
*/
|
|
278
|
+
sse<T = any>(path: string, handler: (ctx: any) => AsyncIterable<T> | Promise<AsyncIterable<T>>): Axeom<T_1 & {
|
|
279
|
+
[x: `GET ${string}`]: RouteMetadata<string, {}, Response>;
|
|
280
|
+
}, D>;
|
|
281
|
+
/**
|
|
282
|
+
* Automatically detect the runtime and start a server.
|
|
283
|
+
* Currently supports: Bun, Deno.
|
|
284
|
+
* For Node, use a specific adapter like @axeom/express.
|
|
285
|
+
*
|
|
286
|
+
* @param portOrOptions - The port number or a server options object.
|
|
287
|
+
*/
|
|
288
|
+
listen(portOrOptions?: number | any): any;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export { $SERVER, Axeom, AxeomError, BadRequestError, ConflictError, type Context, type ExtractParams, ForbiddenError, type Handler, type Infer, InternalServerError, NotFoundError, type ParamsObject, type PrefixT, type Prettify, type Route, type RouteInput, type RouteMetadata, type RouteSchema, UnauthorizedError, type Validator, Axeom as default };
|