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/README.md
CHANGED
|
@@ -92,11 +92,15 @@ endpoint system.
|
|
|
92
92
|
|
|
93
93
|
### `defineRoute()`
|
|
94
94
|
|
|
95
|
-
Declare a single route:
|
|
95
|
+
Declare a single route. Now supports middlewares and metadata:
|
|
96
96
|
|
|
97
97
|
```ts
|
|
98
|
-
defineRoute(
|
|
99
|
-
|
|
98
|
+
defineRoute({
|
|
99
|
+
method: 'GET',
|
|
100
|
+
path: '/users/:id',
|
|
101
|
+
middlewares: [authMiddleware],
|
|
102
|
+
metadata: { summary: 'Get user by ID' },
|
|
103
|
+
handler: ({params}) => ok({userId: params.id})
|
|
100
104
|
});
|
|
101
105
|
```
|
|
102
106
|
|
|
@@ -110,6 +114,125 @@ export const GET = defineRouter([
|
|
|
110
114
|
]);
|
|
111
115
|
```
|
|
112
116
|
|
|
117
|
+
### Advanced Matching
|
|
118
|
+
|
|
119
|
+
`astro-routify` supports advanced routing patterns including wildcards and regex constraints.
|
|
120
|
+
|
|
121
|
+
#### 1. Wildcards
|
|
122
|
+
- `*` matches exactly one segment.
|
|
123
|
+
- `**` matches zero or more segments (catch-all).
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
builder.addGet('/files/*/download', () => ok('one segment'));
|
|
127
|
+
builder.addGet('/static/**', () => ok('all segments'));
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### 2. Regex Constraints
|
|
131
|
+
You can constrain parameters using regex by wrapping the pattern in parentheses: `:param(regex)`.
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
// Matches only numeric IDs
|
|
135
|
+
builder.addGet('/users/:id(\\d+)', ({ params }) => ok(params.id));
|
|
136
|
+
|
|
137
|
+
// Matches hex colors
|
|
138
|
+
builder.addGet('/color/:hex(^([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$)', ({ params }) => ok(params.hex));
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
#### 3. Matching Priority
|
|
142
|
+
When multiple routes could match a path, the router follows a deterministic priority order:
|
|
143
|
+
1. **Static Match** (e.g., `/p/static`)
|
|
144
|
+
2. **Regex Match** (e.g., `/p/:id(\\d+)`)
|
|
145
|
+
3. **Param Match** (e.g., `/p/:id`)
|
|
146
|
+
4. **Wildcard Match** (e.g., `/p/*`)
|
|
147
|
+
5. **Catch-all Match** (e.g., `/**`)
|
|
148
|
+
|
|
149
|
+
### 🛡️ Middleware & Security
|
|
150
|
+
|
|
151
|
+
`astro-routify` provides a powerful middleware system and built-in security helpers.
|
|
152
|
+
|
|
153
|
+
#### 1. Middleware Support
|
|
154
|
+
Middleware can be applied globally, to groups, or to individual routes.
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
const builder = new RouterBuilder();
|
|
158
|
+
|
|
159
|
+
// Global middleware
|
|
160
|
+
builder.use(async (ctx, next) => {
|
|
161
|
+
const start = performance.now();
|
|
162
|
+
const res = await next();
|
|
163
|
+
console.log(`Duration: ${performance.now() - start}ms`);
|
|
164
|
+
return res;
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Group middleware
|
|
168
|
+
builder.group('/admin')
|
|
169
|
+
.use(checkAuth)
|
|
170
|
+
.addGet('/dashboard', (ctx) => ok('Admin only'));
|
|
171
|
+
|
|
172
|
+
// Route middleware
|
|
173
|
+
builder.addPost('/user', validate(UserSchema), (ctx) => {
|
|
174
|
+
return ok(ctx.data.body);
|
|
175
|
+
});
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### 2. Request Validation
|
|
179
|
+
Built-in `validate()` middleware works with Zod, Valibot, or any library implementing a `safeParse` method.
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
import { validate } from 'astro-routify';
|
|
183
|
+
import { z } from 'zod';
|
|
184
|
+
|
|
185
|
+
const UserSchema = z.object({
|
|
186
|
+
name: z.string(),
|
|
187
|
+
email: z.string().email()
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
builder.addPost('/register', validate({ body: UserSchema }), (ctx) => {
|
|
191
|
+
const user = ctx.data.body; // Fully typed if using TypeScript correctly
|
|
192
|
+
return ok(user);
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
#### 3. Security Middlewares (CORS & Headers)
|
|
197
|
+
Protect your API with `cors()` and `securityHeaders()`.
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
import { cors, securityHeaders } from 'astro-routify';
|
|
201
|
+
|
|
202
|
+
builder.use(cors({ origin: 'https://example.com' }));
|
|
203
|
+
builder.use(securityHeaders());
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### 🛠 Advanced Configuration
|
|
207
|
+
|
|
208
|
+
#### Centralized Error Handling
|
|
209
|
+
Handle all API errors in one place:
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
export const ALL = createRouter({
|
|
213
|
+
onError: (err, ctx) => {
|
|
214
|
+
console.error(err);
|
|
215
|
+
return json({ error: 'Something went wrong' }, 500);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
#### OpenAPI (Swagger) Generation
|
|
221
|
+
Automatically generate API documentation:
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import { generateOpenAPI } from 'astro-routify';
|
|
225
|
+
|
|
226
|
+
const router = builder.build();
|
|
227
|
+
const spec = generateOpenAPI(router, {
|
|
228
|
+
title: 'My API',
|
|
229
|
+
version: '1.0.0'
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// Serve the spec
|
|
233
|
+
builder.addGet('/openapi.json', () => ok(spec));
|
|
234
|
+
```
|
|
235
|
+
|
|
113
236
|
> 🧠 `defineRouter()` supports all HTTP methods — but Astro only executes the method you export (`GET`, `POST`, etc.)
|
|
114
237
|
|
|
115
238
|
### `RouterBuilder` (Catch-All & Fluent Builder)
|
|
@@ -130,18 +253,112 @@ builder
|
|
|
130
253
|
export const ALL = builder.build();
|
|
131
254
|
```
|
|
132
255
|
|
|
133
|
-
|
|
256
|
+
#### 🏗 Vertical Slices & Auto-Discovery
|
|
257
|
+
|
|
258
|
+
To avoid a long list of manual registrations, you can use `addModules` combined with Vite's `import.meta.glob`. This allows
|
|
259
|
+
you to define routes anywhere in your project (near your components) and have them automatically registered.
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
// src/pages/api/[...all].ts
|
|
263
|
+
import { RouterBuilder, createRouter } from 'astro-routify';
|
|
264
|
+
|
|
265
|
+
// 1. Using the builder
|
|
266
|
+
const builder = new RouterBuilder();
|
|
267
|
+
builder.addModules(import.meta.glob('../../**/*.routes.ts', { eager: true }));
|
|
268
|
+
export const ALL = builder.build();
|
|
269
|
+
|
|
270
|
+
// 2. Or using the one-liner helper
|
|
271
|
+
export const ALL = createRouter(
|
|
272
|
+
import.meta.glob('../../**/*.routes.ts', { eager: true }),
|
|
273
|
+
{ debug: true } // optional: enable match logging
|
|
274
|
+
);
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
#### 🛡️ Agnostic Auto-Registration (Global Registry)
|
|
278
|
+
|
|
279
|
+
If you want to avoid passing glob results or knowing the relative path to your routes, you can use the **global registry**. By setting the `autoRegister` flag or using **decorators**, routes will register themselves as soon as their module is loaded.
|
|
280
|
+
|
|
281
|
+
##### 1. Enable Auto-Registration in your routes
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
// src/components/User/User.routes.ts
|
|
285
|
+
import { defineRoute, defineGroup, ok, Get } from 'astro-routify';
|
|
286
|
+
|
|
287
|
+
// Option A: Using the flag
|
|
288
|
+
export const GET_USER = defineRoute('GET', '/users/:id', ({params}) => ok({id: params.id}), true);
|
|
289
|
+
|
|
290
|
+
// Option B: Using a group flag
|
|
291
|
+
defineGroup('/admin', (g) => {
|
|
292
|
+
g.addGet('/stats', () => ok({}));
|
|
293
|
+
}, true);
|
|
294
|
+
|
|
295
|
+
// Option C: Using Decorators (requires experimentalDecorators: true)
|
|
296
|
+
class UserRoutes {
|
|
297
|
+
@Get('/profile')
|
|
298
|
+
static getProfile() { return ok({ name: 'Alex' }); }
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
##### 2. Initialize the router agnostically
|
|
303
|
+
|
|
304
|
+
In your catch-all endpoint, simply call `import.meta.glob` to trigger the loading of your route files, and then call `createRouter()` without module arguments.
|
|
305
|
+
|
|
306
|
+
```ts
|
|
307
|
+
// src/pages/api/[...all].ts
|
|
308
|
+
import { createRouter } from 'astro-routify';
|
|
309
|
+
|
|
310
|
+
// Trigger loading of all route files (agnostic of relative path using /src root alias)
|
|
311
|
+
import.meta.glob('/src/**/*.routes.ts', { eager: true });
|
|
312
|
+
|
|
313
|
+
// createRouter() will automatically include all auto-registered routes
|
|
314
|
+
export const ALL = createRouter({ debug: true });
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
You can also use the global `RouterBuilder` instance directly:
|
|
318
|
+
|
|
319
|
+
```ts
|
|
320
|
+
import { RouterBuilder } from 'astro-routify';
|
|
321
|
+
import.meta.glob('/src/**/*.routes.ts', { eager: true });
|
|
322
|
+
|
|
323
|
+
export const ALL = RouterBuilder.global.build();
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
You can also still manually add routes or groups:
|
|
134
327
|
|
|
135
328
|
```ts
|
|
136
329
|
const users = defineGroup("/users")
|
|
137
330
|
.addGet("/:id", ({params}) => ok({id: params.id}));
|
|
138
331
|
|
|
139
332
|
builder.addGroup(users);
|
|
333
|
+
builder.addGet("/ping", () => ok("pong"));
|
|
140
334
|
```
|
|
141
335
|
|
|
142
336
|
> 🔁 While `.register()` is still available, it's **deprecated** in favor of `.addGroup()` and `.addRoute()` for better
|
|
143
337
|
> structure and reusability.
|
|
144
338
|
|
|
339
|
+
Your route files can export single routes, groups, or arrays:
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
// src/components/User/UserList.routes.ts
|
|
343
|
+
import { defineRoute, defineGroup, ok } from 'astro-routify';
|
|
344
|
+
|
|
345
|
+
export const GET = defineRoute('GET', '/users', () => ok([]));
|
|
346
|
+
|
|
347
|
+
export const AdminRoutes = defineGroup('/admin')
|
|
348
|
+
.addPost('/reset', () => ok('done'));
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
#### 🛠 Development & Debugging
|
|
352
|
+
|
|
353
|
+
`astro-routify` provides built-in logging to help you see your route table during development.
|
|
354
|
+
|
|
355
|
+
- **Auto-logging**: In development mode (`NODE_ENV=development`), `RouterBuilder` automatically prints the registered routes to the console when `build()` is called.
|
|
356
|
+
- **Match Tracing**: Set `debug: true` in `RouterOptions` to see a log of every incoming request and which route it matched (or why it failed with 404/405).
|
|
357
|
+
|
|
358
|
+
```ts
|
|
359
|
+
const router = new RouterBuilder({ debug: true });
|
|
360
|
+
```
|
|
361
|
+
|
|
145
362
|
---
|
|
146
363
|
|
|
147
364
|
## 🔁 Response Helpers
|
package/dist/core/RouteTrie.d.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { HttpMethod } from './HttpMethod';
|
|
2
|
-
import type {
|
|
2
|
+
import type { Route } from './defineRoute';
|
|
3
3
|
interface RouteMatch {
|
|
4
|
-
|
|
4
|
+
route: Route | null;
|
|
5
5
|
allowed?: HttpMethod[];
|
|
6
6
|
params: Record<string, string | undefined>;
|
|
7
7
|
}
|
|
8
8
|
export declare class RouteTrie {
|
|
9
9
|
private readonly root;
|
|
10
|
-
insert(
|
|
10
|
+
insert(route: Route): void;
|
|
11
11
|
find(path: string, method: HttpMethod): RouteMatch;
|
|
12
|
+
private matchNode;
|
|
12
13
|
private segmentize;
|
|
13
14
|
}
|
|
14
15
|
export {};
|
package/dist/core/RouteTrie.js
CHANGED
|
@@ -1,56 +1,125 @@
|
|
|
1
1
|
export class RouteTrie {
|
|
2
2
|
constructor() {
|
|
3
|
-
this.root = { children: new Map(),
|
|
3
|
+
this.root = { children: new Map(), routes: new Map() };
|
|
4
4
|
}
|
|
5
|
-
insert(
|
|
6
|
-
|
|
5
|
+
insert(route) {
|
|
6
|
+
if (!route || typeof route.path !== 'string') {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
const segments = this.segmentize(route.path);
|
|
7
10
|
let node = this.root;
|
|
8
11
|
for (const segment of segments) {
|
|
9
|
-
if (segment
|
|
10
|
-
if (!node.
|
|
11
|
-
node.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
if (segment === '**') {
|
|
13
|
+
if (!node.catchAllChild) {
|
|
14
|
+
node.catchAllChild = { children: new Map(), routes: new Map() };
|
|
15
|
+
}
|
|
16
|
+
node = node.catchAllChild;
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
else if (segment === '*') {
|
|
20
|
+
if (!node.wildcardChild) {
|
|
21
|
+
node.wildcardChild = { children: new Map(), routes: new Map() };
|
|
22
|
+
}
|
|
23
|
+
node = node.wildcardChild;
|
|
24
|
+
}
|
|
25
|
+
else if (segment.startsWith(':')) {
|
|
26
|
+
const regexMatch = segment.match(/^:([a-zA-Z0-9_]+)\((.*)\)$/);
|
|
27
|
+
if (regexMatch) {
|
|
28
|
+
const paramName = regexMatch[1];
|
|
29
|
+
const regexStr = regexMatch[2];
|
|
30
|
+
if (!node.regexChildren)
|
|
31
|
+
node.regexChildren = [];
|
|
32
|
+
let regexNode = node.regexChildren.find((rc) => rc.regex.source === regexStr && rc.paramName === paramName)?.node;
|
|
33
|
+
if (!regexNode) {
|
|
34
|
+
regexNode = { children: new Map(), routes: new Map() };
|
|
35
|
+
node.regexChildren.push({
|
|
36
|
+
regex: new RegExp(regexStr),
|
|
37
|
+
paramName,
|
|
38
|
+
node: regexNode,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
node = regexNode;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
const paramName = segment.slice(1);
|
|
45
|
+
if (!node.paramChild) {
|
|
46
|
+
node.paramChild = { children: new Map(), routes: new Map(), paramName };
|
|
47
|
+
}
|
|
48
|
+
node = node.paramChild;
|
|
16
49
|
}
|
|
17
|
-
node = node.paramChild;
|
|
18
50
|
}
|
|
19
51
|
else {
|
|
20
52
|
if (!node.children.has(segment)) {
|
|
21
|
-
node.children.set(segment, { children: new Map(),
|
|
53
|
+
node.children.set(segment, { children: new Map(), routes: new Map() });
|
|
22
54
|
}
|
|
23
55
|
node = node.children.get(segment);
|
|
24
56
|
}
|
|
25
57
|
}
|
|
26
|
-
node.
|
|
58
|
+
node.routes.set(route.method, route);
|
|
27
59
|
}
|
|
28
60
|
find(path, method) {
|
|
29
61
|
const segments = this.segmentize(path);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
62
|
+
return this.matchNode(this.root, segments, 0, method);
|
|
63
|
+
}
|
|
64
|
+
matchNode(node, segments, index, method) {
|
|
65
|
+
if (index === segments.length) {
|
|
66
|
+
let route = node.routes.get(method) ?? null;
|
|
67
|
+
let allowed = route ? undefined : [...node.routes.keys()];
|
|
68
|
+
// If no route here, check if there's a catch-all that matches "empty" remaining
|
|
69
|
+
if (!route && node.catchAllChild) {
|
|
70
|
+
route = node.catchAllChild.routes.get(method) ?? null;
|
|
71
|
+
allowed = route ? undefined : [...node.catchAllChild.routes.keys()];
|
|
35
72
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
73
|
+
return { route, allowed, params: {} };
|
|
74
|
+
}
|
|
75
|
+
const segment = segments[index];
|
|
76
|
+
// 1. Static Match
|
|
77
|
+
const staticChild = node.children.get(segment);
|
|
78
|
+
if (staticChild) {
|
|
79
|
+
const match = this.matchNode(staticChild, segments, index + 1, method);
|
|
80
|
+
if (match.route || (match.allowed && match.allowed.length > 0))
|
|
81
|
+
return match;
|
|
82
|
+
}
|
|
83
|
+
// 2. Regex Match
|
|
84
|
+
if (node.regexChildren) {
|
|
85
|
+
for (const rc of node.regexChildren) {
|
|
86
|
+
if (rc.regex.test(segment)) {
|
|
87
|
+
const match = this.matchNode(rc.node, segments, index + 1, method);
|
|
88
|
+
if (match.route || (match.allowed && match.allowed.length > 0)) {
|
|
89
|
+
match.params[rc.paramName] = segment;
|
|
90
|
+
return match;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
39
93
|
}
|
|
40
|
-
|
|
41
|
-
|
|
94
|
+
}
|
|
95
|
+
// 3. Param Match
|
|
96
|
+
if (node.paramChild) {
|
|
97
|
+
const match = this.matchNode(node.paramChild, segments, index + 1, method);
|
|
98
|
+
if (match.route || (match.allowed && match.allowed.length > 0)) {
|
|
99
|
+
match.params[node.paramChild.paramName] = segment;
|
|
100
|
+
return match;
|
|
42
101
|
}
|
|
43
102
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
103
|
+
// 4. Wildcard Match (*)
|
|
104
|
+
if (node.wildcardChild) {
|
|
105
|
+
const match = this.matchNode(node.wildcardChild, segments, index + 1, method);
|
|
106
|
+
if (match.route || (match.allowed && match.allowed.length > 0))
|
|
107
|
+
return match;
|
|
108
|
+
}
|
|
109
|
+
// 5. Catch-all Match (**)
|
|
110
|
+
if (node.catchAllChild) {
|
|
111
|
+
const route = node.catchAllChild.routes.get(method) ?? null;
|
|
112
|
+
return {
|
|
113
|
+
route,
|
|
114
|
+
allowed: route ? undefined : [...node.catchAllChild.routes.keys()],
|
|
115
|
+
params: {},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return { route: null, params: {} };
|
|
52
119
|
}
|
|
53
120
|
segmentize(path) {
|
|
54
|
-
|
|
121
|
+
if (typeof path !== 'string')
|
|
122
|
+
return [];
|
|
123
|
+
return path.split('/').filter(Boolean);
|
|
55
124
|
}
|
|
56
125
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { APIRoute } from 'astro';
|
|
1
2
|
import { type Route } from './defineRoute';
|
|
2
3
|
import { type RouterOptions } from './defineRouter';
|
|
3
4
|
import { RouteGroup } from './defineGroup';
|
|
4
|
-
import { type
|
|
5
|
+
import { type Middleware } from './defineHandler';
|
|
5
6
|
/**
|
|
6
7
|
* A fluent builder for creating and composing API routes in Astro.
|
|
7
8
|
*
|
|
@@ -27,12 +28,72 @@ import { type Handler } from './defineHandler';
|
|
|
27
28
|
*
|
|
28
29
|
* export const GET = router.build();
|
|
29
30
|
* ```
|
|
31
|
+
*
|
|
32
|
+
* @example Auto-discovering routes via Vite glob:
|
|
33
|
+
* ```ts
|
|
34
|
+
* const router = new RouterBuilder()
|
|
35
|
+
* .addModules(import.meta.glob('./**\/*.routes.ts', { eager: true }));
|
|
36
|
+
*
|
|
37
|
+
* export const ALL = router.build();
|
|
38
|
+
* ```
|
|
30
39
|
*/
|
|
31
40
|
export declare class RouterBuilder {
|
|
32
41
|
private _options;
|
|
33
42
|
private _routes;
|
|
43
|
+
private _groups;
|
|
44
|
+
private _middlewares;
|
|
45
|
+
private _shouldLog;
|
|
34
46
|
private static _registerWarned;
|
|
47
|
+
/**
|
|
48
|
+
* A global RouterBuilder instance for easy, centralized route registration.
|
|
49
|
+
*/
|
|
50
|
+
static readonly global: RouterBuilder;
|
|
35
51
|
constructor(options?: RouterOptions);
|
|
52
|
+
/**
|
|
53
|
+
* Adds a global middleware to all routes registered in this builder.
|
|
54
|
+
*
|
|
55
|
+
* @param middleware - The middleware function.
|
|
56
|
+
* @returns The current builder instance.
|
|
57
|
+
*/
|
|
58
|
+
use(middleware: Middleware): this;
|
|
59
|
+
/**
|
|
60
|
+
* Creates and adds a new route group to the builder.
|
|
61
|
+
*
|
|
62
|
+
* @param basePath - The base path for the group.
|
|
63
|
+
* @param configure - Optional callback to configure the group.
|
|
64
|
+
* @returns The created RouteGroup instance.
|
|
65
|
+
*/
|
|
66
|
+
group(basePath: string, configure?: (group: RouteGroup) => void): RouteGroup;
|
|
67
|
+
/**
|
|
68
|
+
* Adds all routes and groups that have been auto-registered via `defineRoute(..., true)`
|
|
69
|
+
* or `defineGroup(..., true)`.
|
|
70
|
+
*
|
|
71
|
+
* @returns The current builder instance.
|
|
72
|
+
*/
|
|
73
|
+
addRegistered(): this;
|
|
74
|
+
/**
|
|
75
|
+
* Bulk registers routes and groups from a module collection.
|
|
76
|
+
* Ideal for use with Vite's `import.meta.glob` (with `{ eager: true }`).
|
|
77
|
+
*
|
|
78
|
+
* It will search for both default and named exports that are either `Route` or `RouteGroup`.
|
|
79
|
+
*
|
|
80
|
+
* @param modules A record of modules (e.g. from `import.meta.glob`).
|
|
81
|
+
* @returns The current builder instance.
|
|
82
|
+
*/
|
|
83
|
+
addModules(modules: Record<string, any>): this;
|
|
84
|
+
/**
|
|
85
|
+
* Prints all registered routes to the console.
|
|
86
|
+
* Useful for debugging during development.
|
|
87
|
+
*
|
|
88
|
+
* @returns The current builder instance.
|
|
89
|
+
*/
|
|
90
|
+
logRoutes(): this;
|
|
91
|
+
/**
|
|
92
|
+
* Disables the automatic logging of routes that happens in development mode.
|
|
93
|
+
*
|
|
94
|
+
* @returns The current builder instance.
|
|
95
|
+
*/
|
|
96
|
+
disableLogging(): this;
|
|
36
97
|
/**
|
|
37
98
|
* @deprecated Prefer `addGroup()` or `addRoute()` for structured routing.
|
|
38
99
|
*
|
|
@@ -71,39 +132,39 @@ export declare class RouterBuilder {
|
|
|
71
132
|
/**
|
|
72
133
|
* Adds a GET route.
|
|
73
134
|
* @param path Route path (e.g., `/items/:id`)
|
|
74
|
-
* @param
|
|
135
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
75
136
|
*/
|
|
76
|
-
addGet(path: string,
|
|
137
|
+
addGet(path: string, ...handlers: any[]): this;
|
|
77
138
|
/**
|
|
78
139
|
* Adds a POST route.
|
|
79
140
|
* @param path Route path.
|
|
80
|
-
* @param
|
|
141
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
81
142
|
*/
|
|
82
|
-
addPost(path: string,
|
|
143
|
+
addPost(path: string, ...handlers: any[]): this;
|
|
83
144
|
/**
|
|
84
145
|
* Adds a PUT route.
|
|
85
146
|
* @param path Route path.
|
|
86
|
-
* @param
|
|
147
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
87
148
|
*/
|
|
88
|
-
addPut(path: string,
|
|
149
|
+
addPut(path: string, ...handlers: any[]): this;
|
|
89
150
|
/**
|
|
90
151
|
* Adds a DELETE route.
|
|
91
152
|
* @param path Route path.
|
|
92
|
-
* @param
|
|
153
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
93
154
|
*/
|
|
94
|
-
addDelete(path: string,
|
|
155
|
+
addDelete(path: string, ...handlers: any[]): this;
|
|
95
156
|
/**
|
|
96
157
|
* Adds a PATCH route.
|
|
97
158
|
* @param path Route path.
|
|
98
|
-
* @param
|
|
159
|
+
* @param handlers Middleware(s) followed by a request handler function.
|
|
99
160
|
*/
|
|
100
|
-
addPatch(path: string,
|
|
161
|
+
addPatch(path: string, ...handlers: any[]): this;
|
|
101
162
|
/**
|
|
102
163
|
* Internal helper to add a route with any HTTP method.
|
|
103
164
|
*
|
|
104
165
|
* @param method The HTTP method.
|
|
105
166
|
* @param subPath Path segment (can be relative or absolute).
|
|
106
|
-
* @param
|
|
167
|
+
* @param args Middleware(s) and handler.
|
|
107
168
|
* @returns The current builder instance (for chaining).
|
|
108
169
|
*/
|
|
109
170
|
private add;
|
|
@@ -115,5 +176,27 @@ export declare class RouterBuilder {
|
|
|
115
176
|
*
|
|
116
177
|
* @returns A fully resolved Astro route handler.
|
|
117
178
|
*/
|
|
118
|
-
build():
|
|
179
|
+
build(): APIRoute;
|
|
119
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* A convenience helper to create a router.
|
|
183
|
+
*
|
|
184
|
+
* If modules are provided (e.g. from Vite's `import.meta.glob`), they will be registered.
|
|
185
|
+
* If no modules are provided, it will automatically include all routes that were
|
|
186
|
+
* registered via the auto-registration flags (`defineRoute(..., true)`).
|
|
187
|
+
*
|
|
188
|
+
* @example Auto-discovery via glob:
|
|
189
|
+
* ```ts
|
|
190
|
+
* export const ALL = createRouter(import.meta.glob('./**\/*.ts', { eager: true }));
|
|
191
|
+
* ```
|
|
192
|
+
*
|
|
193
|
+
* @example Auto-registration via global registry:
|
|
194
|
+
* ```ts
|
|
195
|
+
* export const ALL = createRouter();
|
|
196
|
+
* ```
|
|
197
|
+
*
|
|
198
|
+
* @param modulesOrOptions Either modules to register or router options.
|
|
199
|
+
* @param options Router options (if first arg is modules).
|
|
200
|
+
* @returns An Astro-compatible route handler.
|
|
201
|
+
*/
|
|
202
|
+
export declare function createRouter(modulesOrOptions?: Record<string, any> | RouterOptions, options?: RouterOptions): APIRoute;
|