astro-routify 1.2.2 → 1.4.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.
- package/README.md +221 -4
- package/dist/core/RouteTrie.d.ts +4 -3
- package/dist/core/RouteTrie.js +101 -32
- package/dist/core/RouterBuilder.d.ts +96 -13
- package/dist/core/RouterBuilder.js +210 -21
- package/dist/core/decorators.d.ts +29 -0
- package/dist/core/decorators.js +49 -0
- package/dist/core/defineGroup.d.ts +32 -17
- package/dist/core/defineGroup.js +65 -23
- package/dist/core/defineHandler.d.ts +18 -8
- package/dist/core/defineHandler.js +1 -12
- package/dist/core/defineRoute.d.ts +27 -3
- package/dist/core/defineRoute.js +31 -9
- package/dist/core/defineRouter.d.ts +11 -1
- package/dist/core/defineRouter.js +63 -16
- package/dist/core/internal/createJsonStreamRoute.js +12 -4
- package/dist/core/middlewares.d.ts +47 -0
- package/dist/core/middlewares.js +110 -0
- package/dist/core/openapi.d.ts +17 -0
- package/dist/core/openapi.js +57 -0
- package/dist/core/registry.d.ts +15 -0
- package/dist/core/registry.js +26 -0
- package/dist/core/responseHelpers.d.ts +13 -0
- package/dist/core/responseHelpers.js +32 -6
- package/dist/core/stream.js +14 -7
- package/dist/index.d.ts +306 -43
- package/dist/index.js +5 -1
- package/package.json +5 -3
package/dist/core/stream.js
CHANGED
|
@@ -35,8 +35,8 @@ export function stream(path, handler, options) {
|
|
|
35
35
|
write: (chunk) => {
|
|
36
36
|
if (closed || !controllerRef)
|
|
37
37
|
return;
|
|
38
|
-
const bytes = typeof chunk === 'string'
|
|
39
|
-
encoder.encode(`data: ${chunk}\n\n`)
|
|
38
|
+
const bytes = typeof chunk === 'string'
|
|
39
|
+
? (contentType === 'text/event-stream' ? encoder.encode(`data: ${chunk}\n\n`) : encoder.encode(chunk))
|
|
40
40
|
: chunk;
|
|
41
41
|
controllerRef.enqueue(bytes);
|
|
42
42
|
},
|
|
@@ -56,17 +56,24 @@ export function stream(path, handler, options) {
|
|
|
56
56
|
const body = new ReadableStream({
|
|
57
57
|
start(controller) {
|
|
58
58
|
controllerRef = controller;
|
|
59
|
+
const onAbort = () => {
|
|
60
|
+
closed = true;
|
|
61
|
+
try {
|
|
62
|
+
controller.close();
|
|
63
|
+
}
|
|
64
|
+
catch { /* noop */ }
|
|
65
|
+
console.debug('Request aborted — streaming stopped.');
|
|
66
|
+
};
|
|
67
|
+
ctx.request.signal.addEventListener('abort', onAbort, { once: true });
|
|
59
68
|
Promise.resolve(handler({ ...ctx, response: writer }))
|
|
60
69
|
.catch((err) => {
|
|
61
70
|
try {
|
|
62
71
|
controller.error(err);
|
|
63
72
|
}
|
|
64
73
|
catch { /* noop */ }
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
controller.close();
|
|
69
|
-
console.debug('Request aborted — streaming stopped.');
|
|
74
|
+
})
|
|
75
|
+
.finally(() => {
|
|
76
|
+
ctx.request.signal.removeEventListener('abort', onAbort);
|
|
70
77
|
});
|
|
71
78
|
},
|
|
72
79
|
cancel() {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as astro from 'astro';
|
|
2
1
|
import { APIContext, APIRoute } from 'astro';
|
|
3
2
|
import { HeadersInit, BodyInit } from 'undici';
|
|
4
3
|
|
|
@@ -74,8 +73,14 @@ declare const methodNotAllowed: <T = string>(body?: T, headers?: HeadersInit) =>
|
|
|
74
73
|
* 429 Too Many Requests
|
|
75
74
|
*/
|
|
76
75
|
declare const tooManyRequests: <T = string>(body?: T, headers?: HeadersInit) => ResultResponse<T>;
|
|
76
|
+
/**
|
|
77
|
+
* Returns a response with JSON body and specified status.
|
|
78
|
+
*/
|
|
79
|
+
declare const json: (body: any, status?: number, headers?: HeadersInit) => ResultResponse<any>;
|
|
77
80
|
/**
|
|
78
81
|
* 500 Internal Server Error
|
|
82
|
+
*
|
|
83
|
+
* In production, you might want to avoid leaking error details.
|
|
79
84
|
*/
|
|
80
85
|
declare const internalError: (err: unknown, headers?: HeadersInit) => ResultResponse<string>;
|
|
81
86
|
/**
|
|
@@ -88,6 +93,13 @@ declare const internalError: (err: unknown, headers?: HeadersInit) => ResultResp
|
|
|
88
93
|
* @returns A ResultResponse for download-ready content
|
|
89
94
|
*/
|
|
90
95
|
declare const fileResponse: (content: Blob | ArrayBuffer | ReadableStream<Uint8Array>, contentType: string, fileName?: string, headers?: HeadersInit) => ResultResponse<BodyInit>;
|
|
96
|
+
/**
|
|
97
|
+
* Type guard to detect ReadableStreams, used for streamed/binary responses.
|
|
98
|
+
*
|
|
99
|
+
* @param value - Any value to test
|
|
100
|
+
* @returns True if it looks like a ReadableStream
|
|
101
|
+
*/
|
|
102
|
+
declare function isReadableStream(value: unknown): value is ReadableStream<Uint8Array>;
|
|
91
103
|
/**
|
|
92
104
|
* Converts an internal `ResultResponse` into a native `Response` object
|
|
93
105
|
* for use inside Astro API routes.
|
|
@@ -99,13 +111,30 @@ declare const fileResponse: (content: Blob | ArrayBuffer | ReadableStream<Uint8A
|
|
|
99
111
|
*/
|
|
100
112
|
declare function toAstroResponse(result: ResultResponse | undefined): Response;
|
|
101
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Enhanced Astro context for Routify.
|
|
116
|
+
*/
|
|
117
|
+
interface RoutifyContext extends APIContext {
|
|
118
|
+
/**
|
|
119
|
+
* Parsed query parameters from the URL.
|
|
120
|
+
*/
|
|
121
|
+
query: Record<string, string>;
|
|
122
|
+
/**
|
|
123
|
+
* Shared data container for middlewares and handlers (e.g., validation results).
|
|
124
|
+
*/
|
|
125
|
+
data: Record<string, any>;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* A middleware function that can modify the context or short-circuit the response.
|
|
129
|
+
*/
|
|
130
|
+
type Middleware = (ctx: RoutifyContext, next: () => Promise<Response>) => Promise<Response> | Response;
|
|
102
131
|
/**
|
|
103
132
|
* A flexible route handler that can return:
|
|
104
133
|
* - a native `Response` object,
|
|
105
134
|
* - a structured `ResultResponse` object,
|
|
106
135
|
* - or a file stream (Blob, ArrayBuffer, or ReadableStream).
|
|
107
136
|
*/
|
|
108
|
-
type Handler = (ctx:
|
|
137
|
+
type Handler = (ctx: RoutifyContext) => Promise<ResultResponse | Response> | ResultResponse | Response;
|
|
109
138
|
/**
|
|
110
139
|
* Wraps a `Handler` function into an `APIRoute` that:
|
|
111
140
|
* - logs requests and responses,
|
|
@@ -117,13 +146,6 @@ type Handler = (ctx: APIContext) => Promise<ResultResponse | Response> | ResultR
|
|
|
117
146
|
* @returns An Astro-compatible `APIRoute` function
|
|
118
147
|
*/
|
|
119
148
|
declare function defineHandler(handler: Handler): APIRoute;
|
|
120
|
-
/**
|
|
121
|
-
* Type guard to detect ReadableStreams, used for streamed/binary responses.
|
|
122
|
-
*
|
|
123
|
-
* @param value - Any value to test
|
|
124
|
-
* @returns True if it looks like a ReadableStream
|
|
125
|
-
*/
|
|
126
|
-
declare function isReadableStream(value: unknown): value is ReadableStream<Uint8Array>;
|
|
127
149
|
|
|
128
150
|
/**
|
|
129
151
|
* Represents a single route definition.
|
|
@@ -141,6 +163,14 @@ interface Route {
|
|
|
141
163
|
* The function that handles the request when matched.
|
|
142
164
|
*/
|
|
143
165
|
handler: Handler;
|
|
166
|
+
/**
|
|
167
|
+
* Optional array of middlewares to run before the handler.
|
|
168
|
+
*/
|
|
169
|
+
middlewares?: Middleware[];
|
|
170
|
+
/**
|
|
171
|
+
* Optional metadata for the route (e.g., for OpenAPI generation).
|
|
172
|
+
*/
|
|
173
|
+
metadata?: Record<string, any>;
|
|
144
174
|
}
|
|
145
175
|
/**
|
|
146
176
|
* Defines a route using a `Route` object.
|
|
@@ -149,9 +179,10 @@ interface Route {
|
|
|
149
179
|
* defineRoute({ method: 'GET', path: '/users', handler });
|
|
150
180
|
*
|
|
151
181
|
* @param route - A fully constructed route object
|
|
182
|
+
* @param autoRegister - If true, registers the route to the global registry
|
|
152
183
|
* @returns The validated Route object
|
|
153
184
|
*/
|
|
154
|
-
declare function defineRoute(route: Route): Route;
|
|
185
|
+
declare function defineRoute(route: Route, autoRegister?: boolean): Route;
|
|
155
186
|
/**
|
|
156
187
|
* Defines a route by specifying its method, path, and handler explicitly.
|
|
157
188
|
*
|
|
@@ -161,9 +192,24 @@ declare function defineRoute(route: Route): Route;
|
|
|
161
192
|
* @param method - HTTP method to match
|
|
162
193
|
* @param path - Route path (must start with `/`)
|
|
163
194
|
* @param handler - Function to handle the matched request
|
|
195
|
+
* @param autoRegister - If true, registers the route to the global registry
|
|
164
196
|
* @returns The validated Route object
|
|
165
197
|
*/
|
|
166
|
-
declare function defineRoute(method: HttpMethod, path: string, handler: Handler): Route;
|
|
198
|
+
declare function defineRoute(method: HttpMethod, path: string, handler: Handler, autoRegister?: boolean): Route;
|
|
199
|
+
/**
|
|
200
|
+
* Ensures the route is properly formed and uses a valid method + path format.
|
|
201
|
+
*
|
|
202
|
+
* @param route - Route to validate
|
|
203
|
+
* @throws If method is unsupported or path doesn't start with `/`
|
|
204
|
+
*/
|
|
205
|
+
declare function validateRoute({ method, path }: Route): void;
|
|
206
|
+
/**
|
|
207
|
+
* Checks if an object implements the `Route` interface.
|
|
208
|
+
*
|
|
209
|
+
* @param obj - The object to check
|
|
210
|
+
* @returns True if the object is a valid Route
|
|
211
|
+
*/
|
|
212
|
+
declare function isRoute(obj: any): obj is Route;
|
|
167
213
|
|
|
168
214
|
/**
|
|
169
215
|
* Optional configuration for the router instance.
|
|
@@ -178,6 +224,15 @@ interface RouterOptions {
|
|
|
178
224
|
* Custom handler to return when no route is matched (404).
|
|
179
225
|
*/
|
|
180
226
|
onNotFound?: () => ReturnType<typeof notFound>;
|
|
227
|
+
/**
|
|
228
|
+
* If true, enables debug logging for route matching.
|
|
229
|
+
* Useful during development to trace which route is being matched.
|
|
230
|
+
*/
|
|
231
|
+
debug?: boolean;
|
|
232
|
+
/**
|
|
233
|
+
* Custom error handler for the router.
|
|
234
|
+
*/
|
|
235
|
+
onError?: (error: unknown, ctx: RoutifyContext) => ReturnType<typeof internalError> | Response;
|
|
181
236
|
}
|
|
182
237
|
/**
|
|
183
238
|
* Defines a router that dynamically matches registered routes based on method and path.
|
|
@@ -217,6 +272,7 @@ declare function defineRouter(routes: Route[], options?: RouterOptions): APIRout
|
|
|
217
272
|
declare class RouteGroup {
|
|
218
273
|
private basePath;
|
|
219
274
|
private routes;
|
|
275
|
+
private middlewares;
|
|
220
276
|
/**
|
|
221
277
|
* Creates a new route group with the specified base path.
|
|
222
278
|
* Trailing slashes are automatically removed.
|
|
@@ -228,49 +284,61 @@ declare class RouteGroup {
|
|
|
228
284
|
* Returns the normalized base path used by the group.
|
|
229
285
|
*/
|
|
230
286
|
getBasePath(): string;
|
|
287
|
+
/**
|
|
288
|
+
* Adds a middleware to all routes in this group.
|
|
289
|
+
*
|
|
290
|
+
* @param middleware - The middleware function to add
|
|
291
|
+
* @returns The current group instance
|
|
292
|
+
*/
|
|
293
|
+
use(middleware: Middleware): this;
|
|
231
294
|
/**
|
|
232
295
|
* Registers a GET route under the group's base path.
|
|
233
296
|
*
|
|
234
297
|
* @param path - Path relative to the base path (e.g. "/:id")
|
|
235
|
-
* @param
|
|
298
|
+
* @param handlers - Middleware(s) followed by a handler function
|
|
236
299
|
*/
|
|
237
|
-
addGet(path: string,
|
|
300
|
+
addGet(path: string, ...handlers: any[]): this;
|
|
238
301
|
/**
|
|
239
302
|
* Registers a POST route under the group's base path.
|
|
240
303
|
*
|
|
241
304
|
* @param path - Path relative to the base path
|
|
242
|
-
* @param
|
|
305
|
+
* @param handlers - Middleware(s) followed by a handler function
|
|
243
306
|
*/
|
|
244
|
-
addPost(path: string,
|
|
307
|
+
addPost(path: string, ...handlers: any[]): this;
|
|
245
308
|
/**
|
|
246
309
|
* Registers a PUT route under the group's base path.
|
|
247
310
|
*
|
|
248
311
|
* @param path - Path relative to the base path
|
|
249
|
-
* @param
|
|
312
|
+
* @param handlers - Middleware(s) followed by a handler function
|
|
250
313
|
*/
|
|
251
|
-
addPut(path: string,
|
|
314
|
+
addPut(path: string, ...handlers: any[]): this;
|
|
252
315
|
/**
|
|
253
316
|
* Registers a DELETE route under the group's base path.
|
|
254
317
|
*
|
|
255
318
|
* @param path - Path relative to the base path
|
|
256
|
-
* @param
|
|
319
|
+
* @param handlers - Middleware(s) followed by a handler function
|
|
257
320
|
*/
|
|
258
|
-
addDelete(path: string,
|
|
321
|
+
addDelete(path: string, ...handlers: any[]): this;
|
|
259
322
|
/**
|
|
260
323
|
* Registers a PATCH route under the group's base path.
|
|
261
324
|
*
|
|
262
325
|
* @param path - Path relative to the base path
|
|
263
|
-
* @param
|
|
326
|
+
* @param handlers - Middleware(s) followed by a handler function
|
|
264
327
|
*/
|
|
265
|
-
addPatch(path: string,
|
|
328
|
+
addPatch(path: string, ...handlers: any[]): this;
|
|
266
329
|
/**
|
|
267
|
-
*
|
|
330
|
+
* Registers a route under the group's base path.
|
|
268
331
|
*
|
|
269
332
|
* @param method - HTTP verb
|
|
270
|
-
* @param
|
|
271
|
-
* @param
|
|
333
|
+
* @param path - Path relative to the base path
|
|
334
|
+
* @param args - Middleware(s) and handler
|
|
335
|
+
* @returns The current group instance
|
|
272
336
|
*/
|
|
273
|
-
|
|
337
|
+
add(method: HttpMethod, path: string, ...args: any[]): this;
|
|
338
|
+
/**
|
|
339
|
+
* Registers the group and all its current routes to the global registry.
|
|
340
|
+
*/
|
|
341
|
+
register(): this;
|
|
274
342
|
/**
|
|
275
343
|
* Returns all the registered routes in the group.
|
|
276
344
|
*/
|
|
@@ -281,23 +349,25 @@ declare class RouteGroup {
|
|
|
281
349
|
*
|
|
282
350
|
* @param basePath - The base path prefix for all routes
|
|
283
351
|
* @param configure - Optional callback to configure the group inline
|
|
352
|
+
* @param autoRegister - If true, registers the group to the global registry
|
|
284
353
|
*
|
|
285
354
|
* @example
|
|
286
355
|
* const users = defineGroup('/users', (group) => {
|
|
287
356
|
* group.addGet('/:id', handler);
|
|
288
|
-
* });
|
|
357
|
+
* }, true);
|
|
289
358
|
*/
|
|
290
|
-
declare function defineGroup(basePath: string, configure?: (group: RouteGroup) => void): RouteGroup;
|
|
359
|
+
declare function defineGroup(basePath: string, configure?: (group: RouteGroup) => void, autoRegister?: boolean): RouteGroup;
|
|
291
360
|
|
|
292
361
|
interface RouteMatch {
|
|
293
|
-
|
|
362
|
+
route: Route | null;
|
|
294
363
|
allowed?: HttpMethod[];
|
|
295
364
|
params: Record<string, string | undefined>;
|
|
296
365
|
}
|
|
297
366
|
declare class RouteTrie {
|
|
298
367
|
private readonly root;
|
|
299
|
-
insert(
|
|
368
|
+
insert(route: Route): void;
|
|
300
369
|
find(path: string, method: HttpMethod): RouteMatch;
|
|
370
|
+
private matchNode;
|
|
301
371
|
private segmentize;
|
|
302
372
|
}
|
|
303
373
|
|
|
@@ -326,12 +396,72 @@ declare class RouteTrie {
|
|
|
326
396
|
*
|
|
327
397
|
* export const GET = router.build();
|
|
328
398
|
* ```
|
|
399
|
+
*
|
|
400
|
+
* @example Auto-discovering routes via Vite glob:
|
|
401
|
+
* ```ts
|
|
402
|
+
* const router = new RouterBuilder()
|
|
403
|
+
* .addModules(import.meta.glob('./**\/*.routes.ts', { eager: true }));
|
|
404
|
+
*
|
|
405
|
+
* export const ALL = router.build();
|
|
406
|
+
* ```
|
|
329
407
|
*/
|
|
330
408
|
declare class RouterBuilder {
|
|
331
409
|
private _options;
|
|
332
410
|
private _routes;
|
|
411
|
+
private _groups;
|
|
412
|
+
private _middlewares;
|
|
413
|
+
private _shouldLog;
|
|
333
414
|
private static _registerWarned;
|
|
415
|
+
/**
|
|
416
|
+
* A global RouterBuilder instance for easy, centralized route registration.
|
|
417
|
+
*/
|
|
418
|
+
static readonly global: RouterBuilder;
|
|
334
419
|
constructor(options?: RouterOptions);
|
|
420
|
+
/**
|
|
421
|
+
* Adds a global middleware to all routes registered in this builder.
|
|
422
|
+
*
|
|
423
|
+
* @param middleware - The middleware function.
|
|
424
|
+
* @returns The current builder instance.
|
|
425
|
+
*/
|
|
426
|
+
use(middleware: Middleware): this;
|
|
427
|
+
/**
|
|
428
|
+
* Creates and adds a new route group to the builder.
|
|
429
|
+
*
|
|
430
|
+
* @param basePath - The base path for the group.
|
|
431
|
+
* @param configure - Optional callback to configure the group.
|
|
432
|
+
* @returns The created RouteGroup instance.
|
|
433
|
+
*/
|
|
434
|
+
group(basePath: string, configure?: (group: RouteGroup) => void): RouteGroup;
|
|
435
|
+
/**
|
|
436
|
+
* Adds all routes and groups that have been auto-registered via `defineRoute(..., true)`
|
|
437
|
+
* or `defineGroup(..., true)`.
|
|
438
|
+
*
|
|
439
|
+
* @returns The current builder instance.
|
|
440
|
+
*/
|
|
441
|
+
addRegistered(): this;
|
|
442
|
+
/**
|
|
443
|
+
* Bulk registers routes and groups from a module collection.
|
|
444
|
+
* Ideal for use with Vite's `import.meta.glob` (with `{ eager: true }`).
|
|
445
|
+
*
|
|
446
|
+
* It will search for both default and named exports that are either `Route` or `RouteGroup`.
|
|
447
|
+
*
|
|
448
|
+
* @param modules A record of modules (e.g. from `import.meta.glob`).
|
|
449
|
+
* @returns The current builder instance.
|
|
450
|
+
*/
|
|
451
|
+
addModules(modules: Record<string, any>): this;
|
|
452
|
+
/**
|
|
453
|
+
* Prints all registered routes to the console.
|
|
454
|
+
* Useful for debugging during development.
|
|
455
|
+
*
|
|
456
|
+
* @returns The current builder instance.
|
|
457
|
+
*/
|
|
458
|
+
logRoutes(): this;
|
|
459
|
+
/**
|
|
460
|
+
* Disables the automatic logging of routes that happens in development mode.
|
|
461
|
+
*
|
|
462
|
+
* @returns The current builder instance.
|
|
463
|
+
*/
|
|
464
|
+
disableLogging(): this;
|
|
335
465
|
/**
|
|
336
466
|
* @deprecated Prefer `addGroup()` or `addRoute()` for structured routing.
|
|
337
467
|
*
|
|
@@ -370,39 +500,39 @@ declare class RouterBuilder {
|
|
|
370
500
|
/**
|
|
371
501
|
* Adds a GET route.
|
|
372
502
|
* @param path Route path (e.g., `/items/:id`)
|
|
373
|
-
* @param
|
|
503
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
374
504
|
*/
|
|
375
|
-
addGet(path: string,
|
|
505
|
+
addGet(path: string, ...handlers: any[]): this;
|
|
376
506
|
/**
|
|
377
507
|
* Adds a POST route.
|
|
378
508
|
* @param path Route path.
|
|
379
|
-
* @param
|
|
509
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
380
510
|
*/
|
|
381
|
-
addPost(path: string,
|
|
511
|
+
addPost(path: string, ...handlers: any[]): this;
|
|
382
512
|
/**
|
|
383
513
|
* Adds a PUT route.
|
|
384
514
|
* @param path Route path.
|
|
385
|
-
* @param
|
|
515
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
386
516
|
*/
|
|
387
|
-
addPut(path: string,
|
|
517
|
+
addPut(path: string, ...handlers: any[]): this;
|
|
388
518
|
/**
|
|
389
519
|
* Adds a DELETE route.
|
|
390
520
|
* @param path Route path.
|
|
391
|
-
* @param
|
|
521
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
392
522
|
*/
|
|
393
|
-
addDelete(path: string,
|
|
523
|
+
addDelete(path: string, ...handlers: any[]): this;
|
|
394
524
|
/**
|
|
395
525
|
* Adds a PATCH route.
|
|
396
526
|
* @param path Route path.
|
|
397
|
-
* @param
|
|
527
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
398
528
|
*/
|
|
399
|
-
addPatch(path: string,
|
|
529
|
+
addPatch(path: string, ...handlers: any[]): this;
|
|
400
530
|
/**
|
|
401
531
|
* Internal helper to add a route with any HTTP method.
|
|
402
532
|
*
|
|
403
533
|
* @param method The HTTP method.
|
|
404
534
|
* @param subPath Path segment (can be relative or absolute).
|
|
405
|
-
* @param
|
|
535
|
+
* @param args Middleware(s) and handler.
|
|
406
536
|
* @returns The current builder instance (for chaining).
|
|
407
537
|
*/
|
|
408
538
|
private add;
|
|
@@ -414,8 +544,76 @@ declare class RouterBuilder {
|
|
|
414
544
|
*
|
|
415
545
|
* @returns A fully resolved Astro route handler.
|
|
416
546
|
*/
|
|
417
|
-
build():
|
|
547
|
+
build(): APIRoute;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* A convenience helper to create a router.
|
|
551
|
+
*
|
|
552
|
+
* If modules are provided (e.g. from Vite's `import.meta.glob`), they will be registered.
|
|
553
|
+
* If no modules are provided, it will automatically include all routes that were
|
|
554
|
+
* registered via the auto-registration flags (`defineRoute(..., true)`).
|
|
555
|
+
*
|
|
556
|
+
* @example Auto-discovery via glob:
|
|
557
|
+
* ```ts
|
|
558
|
+
* export const ALL = createRouter(import.meta.glob('./**\/*.ts', { eager: true }));
|
|
559
|
+
* ```
|
|
560
|
+
*
|
|
561
|
+
* @example Auto-registration via global registry:
|
|
562
|
+
* ```ts
|
|
563
|
+
* export const ALL = createRouter();
|
|
564
|
+
* ```
|
|
565
|
+
*
|
|
566
|
+
* @param modulesOrOptions Either modules to register or router options.
|
|
567
|
+
* @param options Router options (if first arg is modules).
|
|
568
|
+
* @returns An Astro-compatible route handler.
|
|
569
|
+
*/
|
|
570
|
+
declare function createRouter(modulesOrOptions?: Record<string, any> | RouterOptions, options?: RouterOptions): APIRoute;
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* A global registry for routes and groups to support "agnostic" auto-registration.
|
|
574
|
+
* This allows routes to be defined anywhere in the project and automatically
|
|
575
|
+
* picked up by the router.
|
|
576
|
+
*/
|
|
577
|
+
declare class InternalRegistry {
|
|
578
|
+
private static instance;
|
|
579
|
+
private items;
|
|
580
|
+
private constructor();
|
|
581
|
+
static getInstance(): InternalRegistry;
|
|
582
|
+
register(item: any): void;
|
|
583
|
+
getItems(): any[];
|
|
584
|
+
clear(): void;
|
|
418
585
|
}
|
|
586
|
+
declare const globalRegistry: InternalRegistry;
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* @Get decorator - auto-registers a GET route.
|
|
590
|
+
*/
|
|
591
|
+
declare const Get: (path: string) => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => void;
|
|
592
|
+
/**
|
|
593
|
+
* @Post decorator - auto-registers a POST route.
|
|
594
|
+
*/
|
|
595
|
+
declare const Post: (path: string) => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => void;
|
|
596
|
+
/**
|
|
597
|
+
* @Put decorator - auto-registers a PUT route.
|
|
598
|
+
*/
|
|
599
|
+
declare const Put: (path: string) => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => void;
|
|
600
|
+
/**
|
|
601
|
+
* @Delete decorator - auto-registers a DELETE route.
|
|
602
|
+
*/
|
|
603
|
+
declare const Delete: (path: string) => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => void;
|
|
604
|
+
/**
|
|
605
|
+
* @Patch decorator - auto-registers a PATCH route.
|
|
606
|
+
*/
|
|
607
|
+
declare const Patch: (path: string) => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => void;
|
|
608
|
+
/**
|
|
609
|
+
* @RouteGroup decorator - can be used on classes to auto-register a group.
|
|
610
|
+
* Note: This requires the class to have a static method or property that returns the routes,
|
|
611
|
+
* or it can be used in conjunction with method decorators.
|
|
612
|
+
*
|
|
613
|
+
* For now, we'll implement a simple version that can be used on a class
|
|
614
|
+
* if the class is intended to be a group.
|
|
615
|
+
*/
|
|
616
|
+
declare function Group(basePath: string): (constructor: Function) => void;
|
|
419
617
|
|
|
420
618
|
/**
|
|
421
619
|
* A writer for streaming raw data to the response body.
|
|
@@ -579,5 +777,70 @@ declare function streamJsonArray(path: string, handler: (ctx: APIContext & {
|
|
|
579
777
|
method?: HttpMethod;
|
|
580
778
|
}): Route;
|
|
581
779
|
|
|
582
|
-
|
|
583
|
-
|
|
780
|
+
/**
|
|
781
|
+
* CORS options.
|
|
782
|
+
*/
|
|
783
|
+
interface CorsOptions {
|
|
784
|
+
origin?: string | string[] | ((origin: string) => boolean | string);
|
|
785
|
+
methods?: string[];
|
|
786
|
+
allowedHeaders?: string[];
|
|
787
|
+
exposedHeaders?: string[];
|
|
788
|
+
credentials?: boolean;
|
|
789
|
+
maxAge?: number;
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Middleware to enable Cross-Origin Resource Sharing (CORS).
|
|
793
|
+
*/
|
|
794
|
+
declare function cors(options?: CorsOptions): Middleware;
|
|
795
|
+
/**
|
|
796
|
+
* Middleware to add common security headers (Helmet-like).
|
|
797
|
+
*/
|
|
798
|
+
declare function securityHeaders(): Middleware;
|
|
799
|
+
/**
|
|
800
|
+
* Interface for schemas compatible with Zod, Valibot, etc.
|
|
801
|
+
*/
|
|
802
|
+
interface Validatable {
|
|
803
|
+
safeParse: (data: any) => {
|
|
804
|
+
success: true;
|
|
805
|
+
data: any;
|
|
806
|
+
} | {
|
|
807
|
+
success: false;
|
|
808
|
+
error: any;
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Validation schema for request components.
|
|
813
|
+
*/
|
|
814
|
+
interface ValidationSchema {
|
|
815
|
+
body?: Validatable;
|
|
816
|
+
query?: Validatable;
|
|
817
|
+
params?: Validatable;
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Middleware for request validation.
|
|
821
|
+
* Supports any schema library with a `safeParse` method (like Zod).
|
|
822
|
+
*
|
|
823
|
+
* Validated data is stored in `ctx.data.body`, `ctx.data.query`, etc.
|
|
824
|
+
*/
|
|
825
|
+
declare function validate(schema: ValidationSchema): Middleware;
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* Basic options for OpenAPI generation.
|
|
829
|
+
*/
|
|
830
|
+
interface OpenAPIOptions {
|
|
831
|
+
title: string;
|
|
832
|
+
version: string;
|
|
833
|
+
description?: string;
|
|
834
|
+
basePath?: string;
|
|
835
|
+
}
|
|
836
|
+
/**
|
|
837
|
+
* Generates an OpenAPI 3.0.0 specification from a list of Routify routes.
|
|
838
|
+
*
|
|
839
|
+
* @param router - The router handler function (returned by builder.build() or createRouter())
|
|
840
|
+
* @param options - Basic info for the OpenAPI spec
|
|
841
|
+
* @returns A JSON object representing the OpenAPI specification
|
|
842
|
+
*/
|
|
843
|
+
declare function generateOpenAPI(router: any, options: OpenAPIOptions): any;
|
|
844
|
+
|
|
845
|
+
export { ALLOWED_HTTP_METHODS, Delete, Get, Group, HttpMethod, Patch, Post, Put, RouteGroup, RouteTrie, RouterBuilder, badRequest, cors, createRouter, created, defineGroup, defineHandler, defineRoute, defineRouter, fileResponse, forbidden, generateOpenAPI, globalRegistry, internalError, isReadableStream, isRoute, json, methodNotAllowed, noContent, normalizeMethod, notFound, notModified, ok, securityHeaders, stream, streamJsonArray, streamJsonND, toAstroResponse, tooManyRequests, unauthorized, validate, validateRoute };
|
|
846
|
+
export type { CorsOptions, Handler, JsonStreamWriter, Middleware, OpenAPIOptions, ResultResponse, Route, RouterOptions, RoutifyContext, StreamOptions, StreamWriter, Validatable, ValidationSchema };
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,11 @@ export * from './core/defineGroup';
|
|
|
5
5
|
export * from './core/RouteTrie';
|
|
6
6
|
export * from './core/HttpMethod';
|
|
7
7
|
export * from './core/responseHelpers';
|
|
8
|
-
export
|
|
8
|
+
export { RouterBuilder, createRouter } from './core/RouterBuilder';
|
|
9
|
+
export { globalRegistry } from './core/registry';
|
|
10
|
+
export * from './core/decorators';
|
|
9
11
|
export * from './core/stream';
|
|
10
12
|
export * from './core/streamJsonND';
|
|
11
13
|
export * from './core/streamJsonArray';
|
|
14
|
+
export * from './core/middlewares';
|
|
15
|
+
export * from './core/openapi';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro-routify",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "A high-performance API router for Astro using a Trie-based matcher.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -28,7 +28,9 @@
|
|
|
28
28
|
"ndjson",
|
|
29
29
|
"json-stream",
|
|
30
30
|
"response-helpers",
|
|
31
|
-
"astro-api"
|
|
31
|
+
"astro-api",
|
|
32
|
+
"withastro",
|
|
33
|
+
"utils"
|
|
32
34
|
],
|
|
33
35
|
"author": "Alex Mora",
|
|
34
36
|
"license": "MIT",
|
|
@@ -40,7 +42,7 @@
|
|
|
40
42
|
"rollup": "^4.46.2",
|
|
41
43
|
"rollup-plugin-dts": "^6.2.1",
|
|
42
44
|
"typescript": "^5.3.3",
|
|
43
|
-
"undici": "^7.
|
|
45
|
+
"undici": "^7.20.0",
|
|
44
46
|
"vitest": "^3.2.4"
|
|
45
47
|
},
|
|
46
48
|
"engines": {
|