astro-routify 1.2.1 → 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 +17 -0
- package/dist/core/responseHelpers.js +36 -6
- package/dist/core/stream.js +14 -7
- package/dist/index.d.ts +310 -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
|
|
|
@@ -70,8 +69,18 @@ declare const notFound: <T = string>(body?: T, headers?: HeadersInit) => ResultR
|
|
|
70
69
|
* 405 Method Not Allowed
|
|
71
70
|
*/
|
|
72
71
|
declare const methodNotAllowed: <T = string>(body?: T, headers?: HeadersInit) => ResultResponse<T>;
|
|
72
|
+
/**
|
|
73
|
+
* 429 Too Many Requests
|
|
74
|
+
*/
|
|
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>;
|
|
73
80
|
/**
|
|
74
81
|
* 500 Internal Server Error
|
|
82
|
+
*
|
|
83
|
+
* In production, you might want to avoid leaking error details.
|
|
75
84
|
*/
|
|
76
85
|
declare const internalError: (err: unknown, headers?: HeadersInit) => ResultResponse<string>;
|
|
77
86
|
/**
|
|
@@ -84,6 +93,13 @@ declare const internalError: (err: unknown, headers?: HeadersInit) => ResultResp
|
|
|
84
93
|
* @returns A ResultResponse for download-ready content
|
|
85
94
|
*/
|
|
86
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>;
|
|
87
103
|
/**
|
|
88
104
|
* Converts an internal `ResultResponse` into a native `Response` object
|
|
89
105
|
* for use inside Astro API routes.
|
|
@@ -95,13 +111,30 @@ declare const fileResponse: (content: Blob | ArrayBuffer | ReadableStream<Uint8A
|
|
|
95
111
|
*/
|
|
96
112
|
declare function toAstroResponse(result: ResultResponse | undefined): Response;
|
|
97
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;
|
|
98
131
|
/**
|
|
99
132
|
* A flexible route handler that can return:
|
|
100
133
|
* - a native `Response` object,
|
|
101
134
|
* - a structured `ResultResponse` object,
|
|
102
135
|
* - or a file stream (Blob, ArrayBuffer, or ReadableStream).
|
|
103
136
|
*/
|
|
104
|
-
type Handler = (ctx:
|
|
137
|
+
type Handler = (ctx: RoutifyContext) => Promise<ResultResponse | Response> | ResultResponse | Response;
|
|
105
138
|
/**
|
|
106
139
|
* Wraps a `Handler` function into an `APIRoute` that:
|
|
107
140
|
* - logs requests and responses,
|
|
@@ -113,13 +146,6 @@ type Handler = (ctx: APIContext) => Promise<ResultResponse | Response> | ResultR
|
|
|
113
146
|
* @returns An Astro-compatible `APIRoute` function
|
|
114
147
|
*/
|
|
115
148
|
declare function defineHandler(handler: Handler): APIRoute;
|
|
116
|
-
/**
|
|
117
|
-
* Type guard to detect ReadableStreams, used for streamed/binary responses.
|
|
118
|
-
*
|
|
119
|
-
* @param value - Any value to test
|
|
120
|
-
* @returns True if it looks like a ReadableStream
|
|
121
|
-
*/
|
|
122
|
-
declare function isReadableStream(value: unknown): value is ReadableStream<Uint8Array>;
|
|
123
149
|
|
|
124
150
|
/**
|
|
125
151
|
* Represents a single route definition.
|
|
@@ -137,6 +163,14 @@ interface Route {
|
|
|
137
163
|
* The function that handles the request when matched.
|
|
138
164
|
*/
|
|
139
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>;
|
|
140
174
|
}
|
|
141
175
|
/**
|
|
142
176
|
* Defines a route using a `Route` object.
|
|
@@ -145,9 +179,10 @@ interface Route {
|
|
|
145
179
|
* defineRoute({ method: 'GET', path: '/users', handler });
|
|
146
180
|
*
|
|
147
181
|
* @param route - A fully constructed route object
|
|
182
|
+
* @param autoRegister - If true, registers the route to the global registry
|
|
148
183
|
* @returns The validated Route object
|
|
149
184
|
*/
|
|
150
|
-
declare function defineRoute(route: Route): Route;
|
|
185
|
+
declare function defineRoute(route: Route, autoRegister?: boolean): Route;
|
|
151
186
|
/**
|
|
152
187
|
* Defines a route by specifying its method, path, and handler explicitly.
|
|
153
188
|
*
|
|
@@ -157,9 +192,24 @@ declare function defineRoute(route: Route): Route;
|
|
|
157
192
|
* @param method - HTTP method to match
|
|
158
193
|
* @param path - Route path (must start with `/`)
|
|
159
194
|
* @param handler - Function to handle the matched request
|
|
195
|
+
* @param autoRegister - If true, registers the route to the global registry
|
|
160
196
|
* @returns The validated Route object
|
|
161
197
|
*/
|
|
162
|
-
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;
|
|
163
213
|
|
|
164
214
|
/**
|
|
165
215
|
* Optional configuration for the router instance.
|
|
@@ -174,6 +224,15 @@ interface RouterOptions {
|
|
|
174
224
|
* Custom handler to return when no route is matched (404).
|
|
175
225
|
*/
|
|
176
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;
|
|
177
236
|
}
|
|
178
237
|
/**
|
|
179
238
|
* Defines a router that dynamically matches registered routes based on method and path.
|
|
@@ -213,6 +272,7 @@ declare function defineRouter(routes: Route[], options?: RouterOptions): APIRout
|
|
|
213
272
|
declare class RouteGroup {
|
|
214
273
|
private basePath;
|
|
215
274
|
private routes;
|
|
275
|
+
private middlewares;
|
|
216
276
|
/**
|
|
217
277
|
* Creates a new route group with the specified base path.
|
|
218
278
|
* Trailing slashes are automatically removed.
|
|
@@ -224,49 +284,61 @@ declare class RouteGroup {
|
|
|
224
284
|
* Returns the normalized base path used by the group.
|
|
225
285
|
*/
|
|
226
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;
|
|
227
294
|
/**
|
|
228
295
|
* Registers a GET route under the group's base path.
|
|
229
296
|
*
|
|
230
297
|
* @param path - Path relative to the base path (e.g. "/:id")
|
|
231
|
-
* @param
|
|
298
|
+
* @param handlers - Middleware(s) followed by a handler function
|
|
232
299
|
*/
|
|
233
|
-
addGet(path: string,
|
|
300
|
+
addGet(path: string, ...handlers: any[]): this;
|
|
234
301
|
/**
|
|
235
302
|
* Registers a POST route under the group's base path.
|
|
236
303
|
*
|
|
237
304
|
* @param path - Path relative to the base path
|
|
238
|
-
* @param
|
|
305
|
+
* @param handlers - Middleware(s) followed by a handler function
|
|
239
306
|
*/
|
|
240
|
-
addPost(path: string,
|
|
307
|
+
addPost(path: string, ...handlers: any[]): this;
|
|
241
308
|
/**
|
|
242
309
|
* Registers a PUT route under the group's base path.
|
|
243
310
|
*
|
|
244
311
|
* @param path - Path relative to the base path
|
|
245
|
-
* @param
|
|
312
|
+
* @param handlers - Middleware(s) followed by a handler function
|
|
246
313
|
*/
|
|
247
|
-
addPut(path: string,
|
|
314
|
+
addPut(path: string, ...handlers: any[]): this;
|
|
248
315
|
/**
|
|
249
316
|
* Registers a DELETE route under the group's base path.
|
|
250
317
|
*
|
|
251
318
|
* @param path - Path relative to the base path
|
|
252
|
-
* @param
|
|
319
|
+
* @param handlers - Middleware(s) followed by a handler function
|
|
253
320
|
*/
|
|
254
|
-
addDelete(path: string,
|
|
321
|
+
addDelete(path: string, ...handlers: any[]): this;
|
|
255
322
|
/**
|
|
256
323
|
* Registers a PATCH route under the group's base path.
|
|
257
324
|
*
|
|
258
325
|
* @param path - Path relative to the base path
|
|
259
|
-
* @param
|
|
326
|
+
* @param handlers - Middleware(s) followed by a handler function
|
|
260
327
|
*/
|
|
261
|
-
addPatch(path: string,
|
|
328
|
+
addPatch(path: string, ...handlers: any[]): this;
|
|
262
329
|
/**
|
|
263
|
-
*
|
|
330
|
+
* Registers a route under the group's base path.
|
|
264
331
|
*
|
|
265
332
|
* @param method - HTTP verb
|
|
266
|
-
* @param
|
|
267
|
-
* @param
|
|
333
|
+
* @param path - Path relative to the base path
|
|
334
|
+
* @param args - Middleware(s) and handler
|
|
335
|
+
* @returns The current group instance
|
|
268
336
|
*/
|
|
269
|
-
|
|
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;
|
|
270
342
|
/**
|
|
271
343
|
* Returns all the registered routes in the group.
|
|
272
344
|
*/
|
|
@@ -277,23 +349,25 @@ declare class RouteGroup {
|
|
|
277
349
|
*
|
|
278
350
|
* @param basePath - The base path prefix for all routes
|
|
279
351
|
* @param configure - Optional callback to configure the group inline
|
|
352
|
+
* @param autoRegister - If true, registers the group to the global registry
|
|
280
353
|
*
|
|
281
354
|
* @example
|
|
282
355
|
* const users = defineGroup('/users', (group) => {
|
|
283
356
|
* group.addGet('/:id', handler);
|
|
284
|
-
* });
|
|
357
|
+
* }, true);
|
|
285
358
|
*/
|
|
286
|
-
declare function defineGroup(basePath: string, configure?: (group: RouteGroup) => void): RouteGroup;
|
|
359
|
+
declare function defineGroup(basePath: string, configure?: (group: RouteGroup) => void, autoRegister?: boolean): RouteGroup;
|
|
287
360
|
|
|
288
361
|
interface RouteMatch {
|
|
289
|
-
|
|
362
|
+
route: Route | null;
|
|
290
363
|
allowed?: HttpMethod[];
|
|
291
364
|
params: Record<string, string | undefined>;
|
|
292
365
|
}
|
|
293
366
|
declare class RouteTrie {
|
|
294
367
|
private readonly root;
|
|
295
|
-
insert(
|
|
368
|
+
insert(route: Route): void;
|
|
296
369
|
find(path: string, method: HttpMethod): RouteMatch;
|
|
370
|
+
private matchNode;
|
|
297
371
|
private segmentize;
|
|
298
372
|
}
|
|
299
373
|
|
|
@@ -322,12 +396,72 @@ declare class RouteTrie {
|
|
|
322
396
|
*
|
|
323
397
|
* export const GET = router.build();
|
|
324
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
|
+
* ```
|
|
325
407
|
*/
|
|
326
408
|
declare class RouterBuilder {
|
|
327
409
|
private _options;
|
|
328
410
|
private _routes;
|
|
411
|
+
private _groups;
|
|
412
|
+
private _middlewares;
|
|
413
|
+
private _shouldLog;
|
|
329
414
|
private static _registerWarned;
|
|
415
|
+
/**
|
|
416
|
+
* A global RouterBuilder instance for easy, centralized route registration.
|
|
417
|
+
*/
|
|
418
|
+
static readonly global: RouterBuilder;
|
|
330
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;
|
|
331
465
|
/**
|
|
332
466
|
* @deprecated Prefer `addGroup()` or `addRoute()` for structured routing.
|
|
333
467
|
*
|
|
@@ -366,39 +500,39 @@ declare class RouterBuilder {
|
|
|
366
500
|
/**
|
|
367
501
|
* Adds a GET route.
|
|
368
502
|
* @param path Route path (e.g., `/items/:id`)
|
|
369
|
-
* @param
|
|
503
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
370
504
|
*/
|
|
371
|
-
addGet(path: string,
|
|
505
|
+
addGet(path: string, ...handlers: any[]): this;
|
|
372
506
|
/**
|
|
373
507
|
* Adds a POST route.
|
|
374
508
|
* @param path Route path.
|
|
375
|
-
* @param
|
|
509
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
376
510
|
*/
|
|
377
|
-
addPost(path: string,
|
|
511
|
+
addPost(path: string, ...handlers: any[]): this;
|
|
378
512
|
/**
|
|
379
513
|
* Adds a PUT route.
|
|
380
514
|
* @param path Route path.
|
|
381
|
-
* @param
|
|
515
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
382
516
|
*/
|
|
383
|
-
addPut(path: string,
|
|
517
|
+
addPut(path: string, ...handlers: any[]): this;
|
|
384
518
|
/**
|
|
385
519
|
* Adds a DELETE route.
|
|
386
520
|
* @param path Route path.
|
|
387
|
-
* @param
|
|
521
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
388
522
|
*/
|
|
389
|
-
addDelete(path: string,
|
|
523
|
+
addDelete(path: string, ...handlers: any[]): this;
|
|
390
524
|
/**
|
|
391
525
|
* Adds a PATCH route.
|
|
392
526
|
* @param path Route path.
|
|
393
|
-
* @param
|
|
527
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
394
528
|
*/
|
|
395
|
-
addPatch(path: string,
|
|
529
|
+
addPatch(path: string, ...handlers: any[]): this;
|
|
396
530
|
/**
|
|
397
531
|
* Internal helper to add a route with any HTTP method.
|
|
398
532
|
*
|
|
399
533
|
* @param method The HTTP method.
|
|
400
534
|
* @param subPath Path segment (can be relative or absolute).
|
|
401
|
-
* @param
|
|
535
|
+
* @param args Middleware(s) and handler.
|
|
402
536
|
* @returns The current builder instance (for chaining).
|
|
403
537
|
*/
|
|
404
538
|
private add;
|
|
@@ -410,8 +544,76 @@ declare class RouterBuilder {
|
|
|
410
544
|
*
|
|
411
545
|
* @returns A fully resolved Astro route handler.
|
|
412
546
|
*/
|
|
413
|
-
build():
|
|
547
|
+
build(): APIRoute;
|
|
414
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;
|
|
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;
|
|
415
617
|
|
|
416
618
|
/**
|
|
417
619
|
* A writer for streaming raw data to the response body.
|
|
@@ -575,5 +777,70 @@ declare function streamJsonArray(path: string, handler: (ctx: APIContext & {
|
|
|
575
777
|
method?: HttpMethod;
|
|
576
778
|
}): Route;
|
|
577
779
|
|
|
578
|
-
|
|
579
|
-
|
|
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": {
|