astro-routify 1.2.2 → 1.5.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/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
 
@@ -16,6 +15,10 @@ declare const ALLOWED_HTTP_METHODS: Set<string>;
16
15
  */
17
16
  declare function normalizeMethod(method: string): HttpMethod;
18
17
 
18
+ /**
19
+ * Supported types that can be returned from a route handler.
20
+ */
21
+ type HandlerResult = Response | ResultResponse | string | number | boolean | object | ArrayBuffer | Uint8Array | ReadableStream<Uint8Array> | Blob | FormData | URLSearchParams | null | undefined;
19
22
  /**
20
23
  * A standardized shape for internal route result objects.
21
24
  * These are later converted into native `Response` instances.
@@ -74,14 +77,20 @@ declare const methodNotAllowed: <T = string>(body?: T, headers?: HeadersInit) =>
74
77
  * 429 Too Many Requests
75
78
  */
76
79
  declare const tooManyRequests: <T = string>(body?: T, headers?: HeadersInit) => ResultResponse<T>;
80
+ /**
81
+ * Returns a response with JSON body and specified status.
82
+ */
83
+ declare const json: (body: any, status?: number, headers?: HeadersInit) => ResultResponse<any>;
77
84
  /**
78
85
  * 500 Internal Server Error
86
+ *
87
+ * In production, you might want to avoid leaking error details.
79
88
  */
80
89
  declare const internalError: (err: unknown, headers?: HeadersInit) => ResultResponse<string>;
81
90
  /**
82
91
  * Sends a binary or stream-based file response with optional content-disposition.
83
92
  *
84
- * @param content - The file data (Blob, ArrayBuffer, or stream)
93
+ * @param content - The file state (Blob, ArrayBuffer, or stream)
85
94
  * @param contentType - MIME type of the file
86
95
  * @param fileName - Optional download filename
87
96
  * @param headers - Optional extra headers
@@ -89,23 +98,55 @@ declare const internalError: (err: unknown, headers?: HeadersInit) => ResultResp
89
98
  */
90
99
  declare const fileResponse: (content: Blob | ArrayBuffer | ReadableStream<Uint8Array>, contentType: string, fileName?: string, headers?: HeadersInit) => ResultResponse<BodyInit>;
91
100
  /**
92
- * Converts an internal `ResultResponse` into a native `Response` object
101
+ * Type guard to detect ReadableStreams, used for streamed/binary responses.
102
+ *
103
+ * @param value - Any value to test
104
+ * @returns True if it looks like a ReadableStream
105
+ */
106
+ declare function isReadableStream(value: unknown): value is ReadableStream<Uint8Array>;
107
+ /**
108
+ * Converts an internal `ResultResponse` or any `HandlerResult` into a native `Response` object
93
109
  * for use inside Astro API routes.
94
110
  *
95
- * Automatically applies `Content-Type: application/json` for object bodies.
111
+ * Automatically applies appropriate Content-Type headers.
96
112
  *
97
- * @param result - A ResultResponse returned from route handler
113
+ * @param result - A ResultResponse or other supported type returned from route handler
98
114
  * @returns A native Response
99
115
  */
100
- declare function toAstroResponse(result: ResultResponse | undefined): Response;
116
+ declare function toAstroResponse(result: HandlerResult): Response;
101
117
 
102
118
  /**
103
- * A flexible route handler that can return:
104
- * - a native `Response` object,
105
- * - a structured `ResultResponse` object,
106
- * - or a file stream (Blob, ArrayBuffer, or ReadableStream).
119
+ * Enhanced Astro context for Routify.
120
+ */
121
+ interface RoutifyContext<State = Record<string, any>> extends APIContext {
122
+ /**
123
+ * Parsed query parameters from the URL.
124
+ * Note: If multiple parameters have the same key, only the last one is included.
125
+ * Use `searchParams` for full multi-value support.
126
+ */
127
+ query: Record<string, string | string[]>;
128
+ /**
129
+ * Full URLSearchParams object for the incoming request.
130
+ */
131
+ searchParams: URLSearchParams;
132
+ /**
133
+ * Shared state container for middlewares and handlers (e.g., validation results).
134
+ * This is where middlewares can store information for subsequent handlers.
135
+ */
136
+ state: State;
137
+ }
138
+ /**
139
+ * Convenience type alias for RoutifyContext.
107
140
  */
108
- type Handler = (ctx: APIContext) => Promise<ResultResponse | Response> | ResultResponse | Response;
141
+ type Context<State = Record<string, any>> = RoutifyContext<State>;
142
+ /**
143
+ * A middleware function that can modify the context or short-circuit the response.
144
+ */
145
+ type Middleware<State = any> = (ctx: RoutifyContext<State>, next: () => Promise<Response>) => Promise<Response> | Response;
146
+ /**
147
+ * A flexible route handler that can return various types.
148
+ */
149
+ type Handler<State = any> = (ctx: RoutifyContext<State>) => Promise<HandlerResult> | HandlerResult;
109
150
  /**
110
151
  * Wraps a `Handler` function into an `APIRoute` that:
111
152
  * - logs requests and responses,
@@ -117,13 +158,6 @@ type Handler = (ctx: APIContext) => Promise<ResultResponse | Response> | ResultR
117
158
  * @returns An Astro-compatible `APIRoute` function
118
159
  */
119
160
  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
161
 
128
162
  /**
129
163
  * Represents a single route definition.
@@ -141,6 +175,19 @@ interface Route {
141
175
  * The function that handles the request when matched.
142
176
  */
143
177
  handler: Handler;
178
+ /**
179
+ * Optional array of middlewares to run before the handler.
180
+ */
181
+ middlewares?: Middleware[];
182
+ /**
183
+ * Optional metadata for the route (e.g. for OpenAPI generation).
184
+ */
185
+ metadata?: Record<string, any>;
186
+ /**
187
+ * Internal marker to identify the object type during module discovery.
188
+ * @internal
189
+ */
190
+ _routifyType?: 'route';
144
191
  }
145
192
  /**
146
193
  * Defines a route using a `Route` object.
@@ -149,9 +196,10 @@ interface Route {
149
196
  * defineRoute({ method: 'GET', path: '/users', handler });
150
197
  *
151
198
  * @param route - A fully constructed route object
199
+ * @param autoRegister - If true, registers the route to the global registry
152
200
  * @returns The validated Route object
153
201
  */
154
- declare function defineRoute(route: Route): Route;
202
+ declare function defineRoute(route: Route, autoRegister?: boolean): Route;
155
203
  /**
156
204
  * Defines a route by specifying its method, path, and handler explicitly.
157
205
  *
@@ -161,9 +209,24 @@ declare function defineRoute(route: Route): Route;
161
209
  * @param method - HTTP method to match
162
210
  * @param path - Route path (must start with `/`)
163
211
  * @param handler - Function to handle the matched request
212
+ * @param autoRegister - If true, registers the route to the global registry
164
213
  * @returns The validated Route object
165
214
  */
166
- declare function defineRoute(method: HttpMethod, path: string, handler: Handler): Route;
215
+ declare function defineRoute(method: HttpMethod, path: string, handler: Handler, autoRegister?: boolean): Route;
216
+ /**
217
+ * Ensures the route is properly formed and uses a valid method + path format.
218
+ *
219
+ * @param route - Route to validate
220
+ * @throws If method is unsupported or path doesn't start with `/`
221
+ */
222
+ declare function validateRoute({ method, path }: Route): void;
223
+ /**
224
+ * Checks if an object implements the `Route` interface.
225
+ *
226
+ * @param obj - The object to check
227
+ * @returns True if the object is a valid Route
228
+ */
229
+ declare function isRoute(obj: any): obj is Route;
167
230
 
168
231
  /**
169
232
  * Optional configuration for the router instance.
@@ -178,6 +241,15 @@ interface RouterOptions {
178
241
  * Custom handler to return when no route is matched (404).
179
242
  */
180
243
  onNotFound?: () => ReturnType<typeof notFound>;
244
+ /**
245
+ * If true, enables debug logging for route matching.
246
+ * Useful during development to trace which route is being matched.
247
+ */
248
+ debug?: boolean;
249
+ /**
250
+ * Custom error handler for the router.
251
+ */
252
+ onError?: (error: unknown, ctx: RoutifyContext) => HandlerResult | Response;
181
253
  }
182
254
  /**
183
255
  * Defines a router that dynamically matches registered routes based on method and path.
@@ -215,8 +287,10 @@ declare function defineRouter(routes: Route[], options?: RouterOptions): APIRout
215
287
  * .addPost('/', createUser);
216
288
  */
217
289
  declare class RouteGroup {
290
+ readonly _routifyType = "group";
218
291
  private basePath;
219
292
  private routes;
293
+ private middlewares;
220
294
  /**
221
295
  * Creates a new route group with the specified base path.
222
296
  * Trailing slashes are automatically removed.
@@ -228,49 +302,61 @@ declare class RouteGroup {
228
302
  * Returns the normalized base path used by the group.
229
303
  */
230
304
  getBasePath(): string;
305
+ /**
306
+ * Adds a middleware to all routes in this group.
307
+ *
308
+ * @param middleware - The middleware function to add
309
+ * @returns The current group instance
310
+ */
311
+ use(middleware: Middleware): this;
231
312
  /**
232
313
  * Registers a GET route under the group's base path.
233
314
  *
234
315
  * @param path - Path relative to the base path (e.g. "/:id")
235
- * @param handler - The handler function for this route
316
+ * @param handlers - Middleware(s) followed by a handler function
236
317
  */
237
- addGet(path: string, handler: Handler): this;
318
+ addGet(path: string, ...handlers: any[]): this;
238
319
  /**
239
320
  * Registers a POST route under the group's base path.
240
321
  *
241
322
  * @param path - Path relative to the base path
242
- * @param handler - The handler function for this route
323
+ * @param handlers - Middleware(s) followed by a handler function
243
324
  */
244
- addPost(path: string, handler: Handler): this;
325
+ addPost(path: string, ...handlers: any[]): this;
245
326
  /**
246
327
  * Registers a PUT route under the group's base path.
247
328
  *
248
329
  * @param path - Path relative to the base path
249
- * @param handler - The handler function for this route
330
+ * @param handlers - Middleware(s) followed by a handler function
250
331
  */
251
- addPut(path: string, handler: Handler): this;
332
+ addPut(path: string, ...handlers: any[]): this;
252
333
  /**
253
334
  * Registers a DELETE route under the group's base path.
254
335
  *
255
336
  * @param path - Path relative to the base path
256
- * @param handler - The handler function for this route
337
+ * @param handlers - Middleware(s) followed by a handler function
257
338
  */
258
- addDelete(path: string, handler: Handler): this;
339
+ addDelete(path: string, ...handlers: any[]): this;
259
340
  /**
260
341
  * Registers a PATCH route under the group's base path.
261
342
  *
262
343
  * @param path - Path relative to the base path
263
- * @param handler - The handler function for this route
344
+ * @param handlers - Middleware(s) followed by a handler function
264
345
  */
265
- addPatch(path: string, handler: Handler): this;
346
+ addPatch(path: string, ...handlers: any[]): this;
266
347
  /**
267
- * Internal method to register a route under the group with any HTTP method.
348
+ * Registers a route under the group's base path.
268
349
  *
269
350
  * @param method - HTTP verb
270
- * @param subPath - Route path relative to the base
271
- * @param handler - The handler function for this route
351
+ * @param path - Path relative to the base path
352
+ * @param args - Middleware(s) and handler
353
+ * @returns The current group instance
272
354
  */
273
- private add;
355
+ add(method: HttpMethod, path: string, ...args: any[]): this;
356
+ /**
357
+ * Registers the group and all its current routes to the global registry.
358
+ */
359
+ register(): this;
274
360
  /**
275
361
  * Returns all the registered routes in the group.
276
362
  */
@@ -281,23 +367,25 @@ declare class RouteGroup {
281
367
  *
282
368
  * @param basePath - The base path prefix for all routes
283
369
  * @param configure - Optional callback to configure the group inline
370
+ * @param autoRegister - If true, registers the group to the global registry
284
371
  *
285
372
  * @example
286
373
  * const users = defineGroup('/users', (group) => {
287
374
  * group.addGet('/:id', handler);
288
- * });
375
+ * }, true);
289
376
  */
290
- declare function defineGroup(basePath: string, configure?: (group: RouteGroup) => void): RouteGroup;
377
+ declare function defineGroup(basePath: string, configure?: (group: RouteGroup) => void, autoRegister?: boolean): RouteGroup;
291
378
 
292
379
  interface RouteMatch {
293
- handler: Handler | null;
380
+ route: Route | null;
294
381
  allowed?: HttpMethod[];
295
382
  params: Record<string, string | undefined>;
296
383
  }
297
384
  declare class RouteTrie {
298
385
  private readonly root;
299
- insert(path: string, method: HttpMethod, handler: Handler): void;
386
+ insert(route: Route): void;
300
387
  find(path: string, method: HttpMethod): RouteMatch;
388
+ private matchNode;
301
389
  private segmentize;
302
390
  }
303
391
 
@@ -326,12 +414,72 @@ declare class RouteTrie {
326
414
  *
327
415
  * export const GET = router.build();
328
416
  * ```
417
+ *
418
+ * @example Auto-discovering routes via Vite glob:
419
+ * ```ts
420
+ * const router = new RouterBuilder()
421
+ * .addModules(import.meta.glob('./**\/*.routes.ts', { eager: true }));
422
+ *
423
+ * export const ALL = router.build();
424
+ * ```
329
425
  */
330
426
  declare class RouterBuilder {
331
427
  private _options;
332
428
  private _routes;
429
+ private _groups;
430
+ private _middlewares;
431
+ private _shouldLog;
333
432
  private static _registerWarned;
433
+ /**
434
+ * A global RouterBuilder instance for easy, centralized route registration.
435
+ */
436
+ static readonly global: RouterBuilder;
334
437
  constructor(options?: RouterOptions);
438
+ /**
439
+ * Adds a global middleware to all routes registered in this builder.
440
+ *
441
+ * @param middleware - The middleware function.
442
+ * @returns The current builder instance.
443
+ */
444
+ use(middleware: Middleware): this;
445
+ /**
446
+ * Creates and adds a new route group to the builder.
447
+ *
448
+ * @param basePath - The base path for the group.
449
+ * @param configure - Optional callback to configure the group.
450
+ * @returns The created RouteGroup instance.
451
+ */
452
+ group(basePath: string, configure?: (group: RouteGroup) => void): RouteGroup;
453
+ /**
454
+ * Adds all routes and groups that have been auto-registered via `defineRoute(..., true)`
455
+ * or `defineGroup(..., true)`.
456
+ *
457
+ * @returns The current builder instance.
458
+ */
459
+ addRegistered(): this;
460
+ /**
461
+ * Bulk registers routes and groups from a module collection.
462
+ * Ideal for use with Vite's `import.meta.glob` (with `{ eager: true }`).
463
+ *
464
+ * It will search for both default and named exports that are either `Route` or `RouteGroup`.
465
+ *
466
+ * @param modules A record of modules (e.g. from `import.meta.glob`).
467
+ * @returns The current builder instance.
468
+ */
469
+ addModules(modules: Record<string, any>): this;
470
+ /**
471
+ * Prints all registered routes to the console.
472
+ * Useful for debugging during development.
473
+ *
474
+ * @returns The current builder instance.
475
+ */
476
+ logRoutes(): this;
477
+ /**
478
+ * Disables the automatic logging of routes that happens in development mode.
479
+ *
480
+ * @returns The current builder instance.
481
+ */
482
+ disableLogging(): this;
335
483
  /**
336
484
  * @deprecated Prefer `addGroup()` or `addRoute()` for structured routing.
337
485
  *
@@ -370,39 +518,39 @@ declare class RouterBuilder {
370
518
  /**
371
519
  * Adds a GET route.
372
520
  * @param path Route path (e.g., `/items/:id`)
373
- * @param handler Request handler function.
521
+ * @param handlers Middleware(s) followed by a request handler function.
374
522
  */
375
- addGet(path: string, handler: Handler): this;
523
+ addGet(path: string, ...handlers: any[]): this;
376
524
  /**
377
525
  * Adds a POST route.
378
526
  * @param path Route path.
379
- * @param handler Request handler function.
527
+ * @param handlers Middleware(s) followed by a request handler function.
380
528
  */
381
- addPost(path: string, handler: Handler): this;
529
+ addPost(path: string, ...handlers: any[]): this;
382
530
  /**
383
531
  * Adds a PUT route.
384
532
  * @param path Route path.
385
- * @param handler Request handler function.
533
+ * @param handlers Middleware(s) followed by a request handler function.
386
534
  */
387
- addPut(path: string, handler: Handler): this;
535
+ addPut(path: string, ...handlers: any[]): this;
388
536
  /**
389
537
  * Adds a DELETE route.
390
538
  * @param path Route path.
391
- * @param handler Request handler function.
539
+ * @param handlers Middleware(s) followed by a request handler function.
392
540
  */
393
- addDelete(path: string, handler: Handler): this;
541
+ addDelete(path: string, ...handlers: any[]): this;
394
542
  /**
395
543
  * Adds a PATCH route.
396
544
  * @param path Route path.
397
- * @param handler Request handler function.
545
+ * @param handlers Middleware(s) followed by a request handler function.
398
546
  */
399
- addPatch(path: string, handler: Handler): this;
547
+ addPatch(path: string, ...handlers: any[]): this;
400
548
  /**
401
549
  * Internal helper to add a route with any HTTP method.
402
550
  *
403
551
  * @param method The HTTP method.
404
552
  * @param subPath Path segment (can be relative or absolute).
405
- * @param handler Request handler.
553
+ * @param args Middleware(s) and handler.
406
554
  * @returns The current builder instance (for chaining).
407
555
  */
408
556
  private add;
@@ -414,11 +562,79 @@ declare class RouterBuilder {
414
562
  *
415
563
  * @returns A fully resolved Astro route handler.
416
564
  */
417
- build(): astro.APIRoute;
565
+ build(): APIRoute;
566
+ }
567
+ /**
568
+ * A convenience helper to create a router.
569
+ *
570
+ * If modules are provided (e.g. from Vite's `import.meta.glob`), they will be registered.
571
+ * If no modules are provided, it will automatically include all routes that were
572
+ * registered via the auto-registration flags (`defineRoute(..., true)`).
573
+ *
574
+ * @example Auto-discovery via glob:
575
+ * ```ts
576
+ * export const ALL = createRouter(import.meta.glob('./**\/*.ts', { eager: true }));
577
+ * ```
578
+ *
579
+ * @example Auto-registration via global registry:
580
+ * ```ts
581
+ * export const ALL = createRouter();
582
+ * ```
583
+ *
584
+ * @param modulesOrOptions Either modules to register or router options.
585
+ * @param options Router options (if first arg is modules).
586
+ * @returns An Astro-compatible route handler.
587
+ */
588
+ declare function createRouter(modulesOrOptions?: Record<string, any> | RouterOptions, options?: RouterOptions): APIRoute;
589
+
590
+ /**
591
+ * A global registry for routes and groups to support "agnostic" auto-registration.
592
+ * This allows routes to be defined anywhere in the project and automatically
593
+ * picked up by the router.
594
+ */
595
+ declare class InternalRegistry {
596
+ private static instance;
597
+ private items;
598
+ private constructor();
599
+ static getInstance(): InternalRegistry;
600
+ register(item: any): void;
601
+ getItems(): any[];
602
+ clear(): void;
418
603
  }
604
+ declare const globalRegistry: InternalRegistry;
419
605
 
420
606
  /**
421
- * A writer for streaming raw data to the response body.
607
+ * @Get decorator - auto-registers a GET route.
608
+ */
609
+ declare const Get: (path: string) => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => void;
610
+ /**
611
+ * @Post decorator - auto-registers a POST route.
612
+ */
613
+ declare const Post: (path: string) => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => void;
614
+ /**
615
+ * @Put decorator - auto-registers a PUT route.
616
+ */
617
+ declare const Put: (path: string) => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => void;
618
+ /**
619
+ * @Delete decorator - auto-registers a DELETE route.
620
+ */
621
+ declare const Delete: (path: string) => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => void;
622
+ /**
623
+ * @Patch decorator - auto-registers a PATCH route.
624
+ */
625
+ declare const Patch: (path: string) => (target: any, propertyKey: string, descriptor?: PropertyDescriptor) => void;
626
+ /**
627
+ * @RouteGroup decorator - can be used on classes to auto-register a group.
628
+ * Note: This requires the class to have a static method or property that returns the routes,
629
+ * or it can be used in conjunction with method decorators.
630
+ *
631
+ * For now, we'll implement a simple version that can be used on a class
632
+ * if the class is intended to be a group.
633
+ */
634
+ declare function Group(basePath: string): (constructor: Function) => void;
635
+
636
+ /**
637
+ * A writer for streaming raw state to the response body.
422
638
  *
423
639
  * This is used inside the `stream()` route handler to emit bytes
424
640
  * or strings directly to the client with backpressure awareness.
@@ -462,7 +678,7 @@ interface StreamOptions {
462
678
  keepAlive?: boolean;
463
679
  }
464
680
  /**
465
- * Defines a generic streaming route that can write raw chunks of data
681
+ * Defines a generic streaming route that can write raw chunks of state
466
682
  * to the response in real time using a `ReadableStream`.
467
683
  *
468
684
  * Suitable for Server-Sent Events (SSE), long-polling, streamed HTML,
@@ -471,7 +687,7 @@ interface StreamOptions {
471
687
  * @example
472
688
  * stream('/clock', async ({ response }) => {
473
689
  * const timer = setInterval(() => {
474
- * response.write(`data: ${new Date().toISOString()}\n\n`);
690
+ * response.write(`state: ${new Date().toISOString()}\n\n`);
475
691
  * }, 1000);
476
692
  *
477
693
  * setTimeout(() => {
@@ -491,7 +707,7 @@ declare function stream(path: string, handler: (ctx: APIContext & {
491
707
 
492
708
  type JsonValue = any;
493
709
  /**
494
- * A writer interface for streaming JSON data to the response body.
710
+ * A writer interface for streaming JSON state to the response body.
495
711
  * Supports both NDJSON and array formats.
496
712
  */
497
713
  interface JsonStreamWriter {
@@ -555,7 +771,7 @@ declare function streamJsonND(path: string, handler: (ctx: APIContext & {
555
771
  * Defines a JSON streaming route that emits a valid JSON array.
556
772
  *
557
773
  * This helper returns a valid `application/json` response containing
558
- * a streamable array of JSON values. Useful for large data exports
774
+ * a streamable array of JSON values. Useful for large state exports
559
775
  * or APIs where the full array can be streamed as it's generated.
560
776
  *
561
777
  * Unlike `streamJsonND()`, this wraps all values in `[` and `]`
@@ -579,5 +795,70 @@ declare function streamJsonArray(path: string, handler: (ctx: APIContext & {
579
795
  method?: HttpMethod;
580
796
  }): Route;
581
797
 
582
- export { ALLOWED_HTTP_METHODS, HttpMethod, RouteGroup, RouteTrie, RouterBuilder, badRequest, created, defineGroup, defineHandler, defineRoute, defineRouter, fileResponse, forbidden, internalError, isReadableStream, methodNotAllowed, noContent, normalizeMethod, notFound, notModified, ok, stream, streamJsonArray, streamJsonND, toAstroResponse, tooManyRequests, unauthorized };
583
- export type { Handler, JsonStreamWriter, ResultResponse, Route, RouterOptions, StreamOptions, StreamWriter };
798
+ /**
799
+ * CORS options.
800
+ */
801
+ interface CorsOptions {
802
+ origin?: string | string[] | ((origin: string) => boolean | string);
803
+ methods?: string[];
804
+ allowedHeaders?: string[];
805
+ exposedHeaders?: string[];
806
+ credentials?: boolean;
807
+ maxAge?: number;
808
+ }
809
+ /**
810
+ * Middleware to enable Cross-Origin Resource Sharing (CORS).
811
+ */
812
+ declare function cors(options?: CorsOptions): Middleware;
813
+ /**
814
+ * Middleware to add common security headers (Helmet-like).
815
+ */
816
+ declare function securityHeaders(): Middleware;
817
+ /**
818
+ * Interface for schemas compatible with Zod, Valibot, etc.
819
+ */
820
+ interface Validatable {
821
+ safeParse: (data: any) => {
822
+ success: true;
823
+ data: any;
824
+ } | {
825
+ success: false;
826
+ error: any;
827
+ };
828
+ }
829
+ /**
830
+ * Validation schema for request components.
831
+ */
832
+ interface ValidationSchema {
833
+ body?: Validatable;
834
+ query?: Validatable;
835
+ params?: Validatable;
836
+ }
837
+ /**
838
+ * Middleware for request validation.
839
+ * Supports any schema library with a `safeParse` method (like Zod).
840
+ *
841
+ * Validated state is stored in `ctx.state.body`, `ctx.state.query`, etc.
842
+ */
843
+ declare function validate(schema: ValidationSchema): Middleware;
844
+
845
+ /**
846
+ * Basic options for OpenAPI generation.
847
+ */
848
+ interface OpenAPIOptions {
849
+ title: string;
850
+ version: string;
851
+ description?: string;
852
+ basePath?: string;
853
+ }
854
+ /**
855
+ * Generates an OpenAPI 3.0.0 specification from a list of Routify routes.
856
+ *
857
+ * @param router - The router handler function (returned by builder.build() or createRouter())
858
+ * @param options - Basic info for the OpenAPI spec
859
+ * @returns A JSON object representing the OpenAPI specification
860
+ */
861
+ declare function generateOpenAPI(router: any, options: OpenAPIOptions): any;
862
+
863
+ 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 };
864
+ export type { Context, CorsOptions, Handler, HandlerResult, 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 * from './core/RouterBuilder';
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.2.2",
3
+ "version": "1.5.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.13.0",
45
+ "undici": "^7.20.0",
44
46
  "vitest": "^3.2.4"
45
47
  },
46
48
  "engines": {