astro-routify 1.0.0 → 1.2.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 +160 -36
- package/dist/core/RouterBuilder.d.ts +114 -3
- package/dist/core/RouterBuilder.js +133 -6
- package/dist/core/defineGroup.d.ts +87 -0
- package/dist/core/defineGroup.js +111 -0
- package/dist/core/defineHandler.d.ts +23 -0
- package/dist/core/defineHandler.js +40 -0
- package/dist/core/defineRoute.d.ts +32 -0
- package/dist/core/defineRoute.js +14 -1
- package/dist/core/defineRouter.d.ts +33 -1
- package/dist/core/defineRouter.js +32 -3
- package/dist/core/internal/createJsonStreamRoute.d.ts +64 -0
- package/dist/core/internal/createJsonStreamRoute.js +92 -0
- package/dist/core/responseHelpers.d.ts +63 -1
- package/dist/core/responseHelpers.js +68 -0
- package/dist/core/stream.d.ts +75 -0
- package/dist/core/stream.js +91 -0
- package/dist/core/streamJsonArray.d.ts +31 -0
- package/dist/core/streamJsonArray.js +30 -0
- package/dist/core/streamJsonND.d.ts +34 -0
- package/dist/core/streamJsonND.js +33 -0
- package/dist/index.d.ts +512 -6
- package/dist/index.js +4 -0
- package/package.json +13 -7
package/README.md
CHANGED
|
@@ -3,50 +3,89 @@
|
|
|
3
3
|
**A high-performance API router for [Astro](https://astro.build/) built on a Trie matcher.**
|
|
4
4
|
Define API routes using clean, flat structures — no folders or boilerplate logic.
|
|
5
5
|
|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+
|
|
6
11
|
---
|
|
7
12
|
|
|
13
|
+
## Installing
|
|
14
|
+
|
|
15
|
+
```shell
|
|
16
|
+
npm install astro-routify
|
|
17
|
+
```
|
|
18
|
+
|
|
8
19
|
## ⚡️ Quickstart
|
|
9
20
|
|
|
10
21
|
```ts
|
|
11
22
|
// src/pages/api/index.ts
|
|
12
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
defineRoute,
|
|
25
|
+
defineRouter,
|
|
26
|
+
defineGroup,
|
|
27
|
+
HttpMethod,
|
|
28
|
+
ok,
|
|
29
|
+
} from 'astro-routify';
|
|
30
|
+
|
|
31
|
+
const userGroup = defineGroup('/users', (group) => {
|
|
32
|
+
group.addGet('/:id', ({params}) => ok({id: params.id}));
|
|
33
|
+
});
|
|
13
34
|
|
|
14
35
|
export const GET = defineRouter([
|
|
15
|
-
|
|
16
|
-
|
|
36
|
+
defineRoute(HttpMethod.GET, '/ping', () => ok('pong')),
|
|
37
|
+
...userGroup.getRoutes(),
|
|
17
38
|
]);
|
|
18
39
|
```
|
|
19
40
|
|
|
20
41
|
Or to handle everything in a single place:
|
|
21
42
|
|
|
22
43
|
```ts
|
|
23
|
-
import {
|
|
44
|
+
import {RouterBuilder, ok} from 'astro-routify';
|
|
24
45
|
|
|
25
46
|
const builder = new RouterBuilder();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
47
|
+
|
|
48
|
+
builder
|
|
49
|
+
.addGet('/ping', () => ok('pong'))
|
|
50
|
+
.addPost('/submit', async ({request}) => {
|
|
51
|
+
const body = await request.json();
|
|
52
|
+
return ok({received: body});
|
|
53
|
+
});
|
|
33
54
|
|
|
34
55
|
export const ALL = builder.build(); // catch-all
|
|
35
56
|
```
|
|
36
57
|
|
|
58
|
+
## 💡 Full Example
|
|
59
|
+
|
|
60
|
+
You can find an implementation example in the [astro-routify-example](https://github.com/oamm/astro-routify-example)
|
|
61
|
+
repository.
|
|
62
|
+
It showcases a minimal Astro app with API endpoints configured under:
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
/src/pages/api/[...path].ts
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This setup demonstrates how to route requests dynamically using astro-routify, while still leveraging Astro's native
|
|
69
|
+
endpoint system.
|
|
70
|
+
|
|
37
71
|
---
|
|
38
72
|
|
|
39
73
|
## 🚀 Features
|
|
40
74
|
|
|
41
75
|
- ⚡ Fully compatible with Astro’s native APIContext — no extra setup needed.
|
|
42
|
-
- 🧩 Use middleware, access cookies, headers, and request bodies exactly as you would in a normal Astro
|
|
43
|
-
|
|
76
|
+
- 🧩 Use middleware, access cookies, headers, and request bodies exactly as you would in a normal Astro endpoint.
|
|
44
77
|
- ✅ Flat-file, code-based routing (no folders required)
|
|
45
78
|
- ✅ Dynamic segments (`:id`)
|
|
46
79
|
- ✅ ALL-mode for monolithic routing (`RouterBuilder`)
|
|
47
80
|
- ✅ Built-in response helpers (`ok`, `created`, etc.)
|
|
48
81
|
- ✅ Trie-based matcher for fast route lookup
|
|
49
82
|
- ✅ Fully typed — no magic strings
|
|
83
|
+
- 🔁 **Streaming support**
|
|
84
|
+
- `stream()` — raw streaming with backpressure support (e.g. SSE, logs, custom protocols)
|
|
85
|
+
- `streamJsonND()` — newline-delimited JSON streaming (NDJSON)
|
|
86
|
+
- `streamJsonArray()` — server-side streamed JSON arrays
|
|
87
|
+
|
|
88
|
+
> 🔄 See [CHANGELOG.md](./CHANGELOG.md) for recent updates and improvements.
|
|
50
89
|
|
|
51
90
|
---
|
|
52
91
|
|
|
@@ -57,8 +96,8 @@ export const ALL = builder.build(); // catch-all
|
|
|
57
96
|
Declare a single route:
|
|
58
97
|
|
|
59
98
|
```ts
|
|
60
|
-
defineRoute(HttpMethod.GET, "/users/:id", ({
|
|
61
|
-
|
|
99
|
+
defineRoute(HttpMethod.GET, "/users/:id", ({params}) => {
|
|
100
|
+
return ok({userId: params.id});
|
|
62
101
|
});
|
|
63
102
|
```
|
|
64
103
|
|
|
@@ -68,24 +107,42 @@ Group multiple routes under one HTTP method handler:
|
|
|
68
107
|
|
|
69
108
|
```ts
|
|
70
109
|
export const GET = defineRouter([
|
|
71
|
-
|
|
110
|
+
defineRoute(HttpMethod.GET, "/health", () => ok("ok"))
|
|
72
111
|
]);
|
|
73
112
|
```
|
|
74
113
|
|
|
75
114
|
> 🧠 `defineRouter()` supports all HTTP methods — but Astro only executes the method you export (`GET`, `POST`, etc.)
|
|
76
115
|
|
|
77
|
-
### `RouterBuilder` (Catch-All)
|
|
116
|
+
### `RouterBuilder` (Catch-All & Fluent Builder)
|
|
78
117
|
|
|
79
|
-
|
|
118
|
+
Use `RouterBuilder` when you want to build routes dynamically, catch all HTTP methods via `ALL`, or organize routes more
|
|
119
|
+
fluently with helpers.
|
|
80
120
|
|
|
81
121
|
```ts
|
|
82
122
|
const builder = new RouterBuilder();
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
123
|
+
|
|
124
|
+
builder
|
|
125
|
+
.addGet("/ping", () => ok("pong"))
|
|
126
|
+
.addPost("/submit", async ({request}) => {
|
|
127
|
+
const body = await request.json();
|
|
128
|
+
return ok({received: body});
|
|
129
|
+
});
|
|
130
|
+
|
|
86
131
|
export const ALL = builder.build();
|
|
87
132
|
```
|
|
88
133
|
|
|
134
|
+
You can also group routes:
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
const users = defineGroup("/users")
|
|
138
|
+
.addGet("/:id", ({params}) => ok({id: params.id}));
|
|
139
|
+
|
|
140
|
+
builder.addGroup(users);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
> 🔁 While `.register()` is still available, it's **deprecated** in favor of `.addGroup()` and `.addRoute()` for better
|
|
144
|
+
> structure and reusability.
|
|
145
|
+
|
|
89
146
|
---
|
|
90
147
|
|
|
91
148
|
## 🔁 Response Helpers
|
|
@@ -93,11 +150,63 @@ export const ALL = builder.build();
|
|
|
93
150
|
Avoid boilerplate `new Response(JSON.stringify(...))`:
|
|
94
151
|
|
|
95
152
|
```ts
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
153
|
+
import {fileResponse} from 'astro-routify';
|
|
154
|
+
|
|
155
|
+
ok(data); // 200 OK
|
|
156
|
+
created(data); // 201 Created
|
|
157
|
+
noContent(); // 204
|
|
158
|
+
notFound("Missing"); // 404
|
|
159
|
+
internalError(err); // 500
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### 📄 File downloads
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
fileResponse(content, "application/pdf", "report.pdf"); // sets Content-Type and Content-Disposition
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### 🔄 Streaming responses
|
|
169
|
+
|
|
170
|
+
#### Raw stream (e.g., Server-Sent Events)
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
stream('/clock', async ({response}) => {
|
|
174
|
+
const timer = setInterval(() => {
|
|
175
|
+
response.write(`data: ${new Date().toISOString()}\n\n`);
|
|
176
|
+
}, 1000);
|
|
177
|
+
|
|
178
|
+
setTimeout(() => {
|
|
179
|
+
clearInterval(timer);
|
|
180
|
+
response.close();
|
|
181
|
+
}, 5000);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
#### JSON NDStream (newline-delimited)
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
|
|
190
|
+
streamJsonND('/updates', async ({response}) => {
|
|
191
|
+
response.send({step: 1});
|
|
192
|
+
await delay(500);
|
|
193
|
+
response.send({step: 2});
|
|
194
|
+
response.close();
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### JSON Array stream
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
|
|
203
|
+
streamJsonArray('/items', async ({response}) => {
|
|
204
|
+
for (let i = 0; i < 3; i++) {
|
|
205
|
+
response.send({id: i});
|
|
206
|
+
}
|
|
207
|
+
response.close();
|
|
208
|
+
});
|
|
209
|
+
|
|
101
210
|
```
|
|
102
211
|
|
|
103
212
|
---
|
|
@@ -107,9 +216,17 @@ internalError(err); // 500
|
|
|
107
216
|
Any route param like `:id` is extracted into `ctx.params`:
|
|
108
217
|
|
|
109
218
|
```ts
|
|
110
|
-
|
|
111
|
-
|
|
219
|
+
const builder = new RouterBuilder();
|
|
220
|
+
|
|
221
|
+
builder.addGet("/users/:id", ({params}) => ok({userId: params.id}));
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
//OR
|
|
225
|
+
|
|
226
|
+
defineRoute(HttpMethod.GET, "/items/:id", ({params}) => {
|
|
227
|
+
return ok({itemId: params.id});
|
|
112
228
|
});
|
|
229
|
+
|
|
113
230
|
```
|
|
114
231
|
|
|
115
232
|
---
|
|
@@ -140,7 +257,6 @@ export const GET = async ({request}) => {
|
|
|
140
257
|
});
|
|
141
258
|
}
|
|
142
259
|
|
|
143
|
-
|
|
144
260
|
if (path === '/api/ping') {
|
|
145
261
|
return new Response(JSON.stringify({pong: true}), {
|
|
146
262
|
status: 200,
|
|
@@ -148,7 +264,6 @@ export const GET = async ({request}) => {
|
|
|
148
264
|
});
|
|
149
265
|
}
|
|
150
266
|
|
|
151
|
-
|
|
152
267
|
return new Response('Not Found', {status: 404});
|
|
153
268
|
};
|
|
154
269
|
```
|
|
@@ -169,11 +284,19 @@ src/
|
|
|
169
284
|
### ✅ With `astro-routify`
|
|
170
285
|
|
|
171
286
|
```ts
|
|
172
|
-
//src/pages/api/[...slug].ts
|
|
287
|
+
// src/pages/api/[...slug].ts
|
|
288
|
+
|
|
289
|
+
const builder = new RouterBuilder();
|
|
290
|
+
builder.addGet("/ping", () => ok({pong: true}));
|
|
291
|
+
builder.addGet("/users/:id", ({params}) => ok({userId: params.id}));
|
|
292
|
+
|
|
293
|
+
// OR
|
|
294
|
+
|
|
173
295
|
export const ALL = defineRouter([
|
|
174
|
-
|
|
175
|
-
|
|
296
|
+
defineRoute(HttpMethod.GET, "/ping", () => ok({pong: true})),
|
|
297
|
+
defineRoute(HttpMethod.GET, "/users/:id", ({params}) => ok({id: params.id}))
|
|
176
298
|
]);
|
|
299
|
+
|
|
177
300
|
```
|
|
178
301
|
|
|
179
302
|
---
|
|
@@ -196,11 +319,10 @@ Tests ran on a mid-range development setup:
|
|
|
196
319
|
- **GPU**: NVIDIA GeForce GTX 1080 (8 GB)
|
|
197
320
|
- **OS**: Windows 10 Pro 64-bit
|
|
198
321
|
- **Node.js**: v20.x
|
|
199
|
-
- **Benchmark Tool**: [Vitest Bench](https://vitest.dev/guide/
|
|
322
|
+
- **Benchmark Tool**: [Vitest Bench](https://vitest.dev/guide/features.html#benchmarking)
|
|
200
323
|
|
|
201
324
|
Results may vary slightly on different hardware.
|
|
202
325
|
|
|
203
|
-
|
|
204
326
|
### 🔬 Realistic route shapes (5000 registered routes):
|
|
205
327
|
|
|
206
328
|
```
|
|
@@ -225,11 +347,13 @@ Results may vary slightly on different hardware.
|
|
|
225
347
|
```
|
|
226
348
|
|
|
227
349
|
> ⚡ Performance stays consistently fast even with 10k+ routes
|
|
350
|
+
|
|
228
351
|
---
|
|
229
352
|
|
|
230
353
|
## 🛠 Designed to Scale
|
|
231
354
|
|
|
232
|
-
While focused on simplicity and speed today, `astro-routify` is designed to evolve — enabling more advanced routing
|
|
355
|
+
While focused on simplicity and speed today, `astro-routify` is designed to evolve — enabling more advanced routing
|
|
356
|
+
patterns in the future.
|
|
233
357
|
|
|
234
358
|
---
|
|
235
359
|
|
|
@@ -1,8 +1,119 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Route } from './defineRoute';
|
|
2
2
|
import { type RouterOptions } from './defineRouter';
|
|
3
|
+
import { RouteGroup } from './defineGroup';
|
|
4
|
+
import { type Handler } from './defineHandler';
|
|
5
|
+
/**
|
|
6
|
+
* A fluent builder for creating and composing API routes in Astro.
|
|
7
|
+
*
|
|
8
|
+
* `RouterBuilder` supports both simple method-based additions (`addGet`, `addPost`, etc.)
|
|
9
|
+
* and organized groups via `defineGroup()` + `addGroup()` for scalable applications.
|
|
10
|
+
*
|
|
11
|
+
* @example Basic usage:
|
|
12
|
+
* ```ts
|
|
13
|
+
* const router = new RouterBuilder()
|
|
14
|
+
* .addGet('/ping', () => ok('pong'))
|
|
15
|
+
* .addPost('/submit', handler);
|
|
16
|
+
*
|
|
17
|
+
* export const ALL = router.build();
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @example Using groups:
|
|
21
|
+
* ```ts
|
|
22
|
+
* const users = defineGroup('/users')
|
|
23
|
+
* .addGet('/:id', userHandler);
|
|
24
|
+
*
|
|
25
|
+
* const router = new RouterBuilder({ basePath: '/api' })
|
|
26
|
+
* .addGroup(users);
|
|
27
|
+
*
|
|
28
|
+
* export const GET = router.build();
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
3
31
|
export declare class RouterBuilder {
|
|
4
|
-
private
|
|
32
|
+
private _options;
|
|
33
|
+
private _routes;
|
|
34
|
+
private static _registerWarned;
|
|
35
|
+
constructor(options?: RouterOptions);
|
|
36
|
+
/**
|
|
37
|
+
* @deprecated Prefer `addGroup()` or `addRoute()` for structured routing.
|
|
38
|
+
*
|
|
39
|
+
* Registers a single route manually.
|
|
40
|
+
*
|
|
41
|
+
* This method is deprecated in favor of a more scalable and organized approach using
|
|
42
|
+
* `defineGroup()` + `addGroup()` or `addRoute()` for ad-hoc additions.
|
|
43
|
+
*
|
|
44
|
+
* @param route A single `Route` object to register.
|
|
45
|
+
*/
|
|
5
46
|
register(route: Route): void;
|
|
47
|
+
/**
|
|
48
|
+
* @deprecated Prefer `addGroup()` or `addRoute()` for structured routing.
|
|
49
|
+
*
|
|
50
|
+
* Registers multiple routes at once.
|
|
51
|
+
*
|
|
52
|
+
* This method is deprecated and discouraged for larger codebases in favor of group-based composition.
|
|
53
|
+
*
|
|
54
|
+
* @param routes An array of `Route` objects to register.
|
|
55
|
+
*/
|
|
6
56
|
register(routes: Route[]): void;
|
|
7
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Adds a single route to the router.
|
|
59
|
+
*
|
|
60
|
+
* @param route The route to add.
|
|
61
|
+
* @returns The current builder instance (for chaining).
|
|
62
|
+
*/
|
|
63
|
+
addRoute(route: Route): this;
|
|
64
|
+
/**
|
|
65
|
+
* Adds a group of pre-defined routes (from `defineGroup()`).
|
|
66
|
+
*
|
|
67
|
+
* @param group A `RouteGroup` instance.
|
|
68
|
+
* @returns The current builder instance (for chaining).
|
|
69
|
+
*/
|
|
70
|
+
addGroup(group: RouteGroup): this;
|
|
71
|
+
/**
|
|
72
|
+
* Adds a GET route.
|
|
73
|
+
* @param path Route path (e.g., `/items/:id`)
|
|
74
|
+
* @param handler Request handler function.
|
|
75
|
+
*/
|
|
76
|
+
addGet(path: string, handler: Handler): this;
|
|
77
|
+
/**
|
|
78
|
+
* Adds a POST route.
|
|
79
|
+
* @param path Route path.
|
|
80
|
+
* @param handler Request handler function.
|
|
81
|
+
*/
|
|
82
|
+
addPost(path: string, handler: Handler): this;
|
|
83
|
+
/**
|
|
84
|
+
* Adds a PUT route.
|
|
85
|
+
* @param path Route path.
|
|
86
|
+
* @param handler Request handler function.
|
|
87
|
+
*/
|
|
88
|
+
addPut(path: string, handler: Handler): this;
|
|
89
|
+
/**
|
|
90
|
+
* Adds a DELETE route.
|
|
91
|
+
* @param path Route path.
|
|
92
|
+
* @param handler Request handler function.
|
|
93
|
+
*/
|
|
94
|
+
addDelete(path: string, handler: Handler): this;
|
|
95
|
+
/**
|
|
96
|
+
* Adds a PATCH route.
|
|
97
|
+
* @param path Route path.
|
|
98
|
+
* @param handler Request handler function.
|
|
99
|
+
*/
|
|
100
|
+
addPatch(path: string, handler: Handler): this;
|
|
101
|
+
/**
|
|
102
|
+
* Internal helper to add a route with any HTTP method.
|
|
103
|
+
*
|
|
104
|
+
* @param method The HTTP method.
|
|
105
|
+
* @param subPath Path segment (can be relative or absolute).
|
|
106
|
+
* @param handler Request handler.
|
|
107
|
+
* @returns The current builder instance (for chaining).
|
|
108
|
+
*/
|
|
109
|
+
private add;
|
|
110
|
+
/**
|
|
111
|
+
* Finalizes the router and returns an Astro-compatible route handler.
|
|
112
|
+
*
|
|
113
|
+
* This function should be used to export a method like `GET`, `POST`, or `ALL`
|
|
114
|
+
* inside Astro API endpoints.
|
|
115
|
+
*
|
|
116
|
+
* @returns A fully resolved Astro route handler.
|
|
117
|
+
*/
|
|
118
|
+
build(): import("astro").APIRoute;
|
|
8
119
|
}
|
|
@@ -1,17 +1,144 @@
|
|
|
1
|
+
import { defineRoute } from './defineRoute';
|
|
1
2
|
import { defineRouter } from './defineRouter';
|
|
3
|
+
import { HttpMethod } from './HttpMethod';
|
|
4
|
+
/**
|
|
5
|
+
* A fluent builder for creating and composing API routes in Astro.
|
|
6
|
+
*
|
|
7
|
+
* `RouterBuilder` supports both simple method-based additions (`addGet`, `addPost`, etc.)
|
|
8
|
+
* and organized groups via `defineGroup()` + `addGroup()` for scalable applications.
|
|
9
|
+
*
|
|
10
|
+
* @example Basic usage:
|
|
11
|
+
* ```ts
|
|
12
|
+
* const router = new RouterBuilder()
|
|
13
|
+
* .addGet('/ping', () => ok('pong'))
|
|
14
|
+
* .addPost('/submit', handler);
|
|
15
|
+
*
|
|
16
|
+
* export const ALL = router.build();
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @example Using groups:
|
|
20
|
+
* ```ts
|
|
21
|
+
* const users = defineGroup('/users')
|
|
22
|
+
* .addGet('/:id', userHandler);
|
|
23
|
+
*
|
|
24
|
+
* const router = new RouterBuilder({ basePath: '/api' })
|
|
25
|
+
* .addGroup(users);
|
|
26
|
+
*
|
|
27
|
+
* export const GET = router.build();
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
2
30
|
export class RouterBuilder {
|
|
3
|
-
constructor() {
|
|
4
|
-
this.
|
|
31
|
+
constructor(options) {
|
|
32
|
+
this._routes = [];
|
|
33
|
+
this._options = {
|
|
34
|
+
basePath: 'api',
|
|
35
|
+
...options,
|
|
36
|
+
};
|
|
5
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* @deprecated Prefer `addGroup()` or `addRoute()` for structured routing.
|
|
40
|
+
*
|
|
41
|
+
* Registers one or more routes, supporting both a single `Route` or an array of them.
|
|
42
|
+
*
|
|
43
|
+
* Internally used by the two overloads above. Emits a console warning once per runtime.
|
|
44
|
+
*
|
|
45
|
+
* @param routeOrRoutes Either a single `Route` or an array of `Route`s.
|
|
46
|
+
*/
|
|
6
47
|
register(routeOrRoutes) {
|
|
48
|
+
if (!RouterBuilder._registerWarned) {
|
|
49
|
+
console.warn('[RouterBuilder] register() is deprecated. Use defineGroup() + addGroup() for route grouping and better structure.');
|
|
50
|
+
RouterBuilder._registerWarned = true;
|
|
51
|
+
}
|
|
7
52
|
if (Array.isArray(routeOrRoutes)) {
|
|
8
|
-
this.
|
|
53
|
+
this._routes.push(...routeOrRoutes);
|
|
9
54
|
}
|
|
10
55
|
else {
|
|
11
|
-
this.
|
|
56
|
+
this._routes.push(routeOrRoutes);
|
|
12
57
|
}
|
|
13
58
|
}
|
|
14
|
-
|
|
15
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Adds a single route to the router.
|
|
61
|
+
*
|
|
62
|
+
* @param route The route to add.
|
|
63
|
+
* @returns The current builder instance (for chaining).
|
|
64
|
+
*/
|
|
65
|
+
addRoute(route) {
|
|
66
|
+
this._routes.push(route);
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Adds a group of pre-defined routes (from `defineGroup()`).
|
|
71
|
+
*
|
|
72
|
+
* @param group A `RouteGroup` instance.
|
|
73
|
+
* @returns The current builder instance (for chaining).
|
|
74
|
+
*/
|
|
75
|
+
addGroup(group) {
|
|
76
|
+
this._routes.push(...group.getRoutes());
|
|
77
|
+
return this;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Adds a GET route.
|
|
81
|
+
* @param path Route path (e.g., `/items/:id`)
|
|
82
|
+
* @param handler Request handler function.
|
|
83
|
+
*/
|
|
84
|
+
addGet(path, handler) {
|
|
85
|
+
return this.add(HttpMethod.GET, path, handler);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Adds a POST route.
|
|
89
|
+
* @param path Route path.
|
|
90
|
+
* @param handler Request handler function.
|
|
91
|
+
*/
|
|
92
|
+
addPost(path, handler) {
|
|
93
|
+
return this.add(HttpMethod.POST, path, handler);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Adds a PUT route.
|
|
97
|
+
* @param path Route path.
|
|
98
|
+
* @param handler Request handler function.
|
|
99
|
+
*/
|
|
100
|
+
addPut(path, handler) {
|
|
101
|
+
return this.add(HttpMethod.PUT, path, handler);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Adds a DELETE route.
|
|
105
|
+
* @param path Route path.
|
|
106
|
+
* @param handler Request handler function.
|
|
107
|
+
*/
|
|
108
|
+
addDelete(path, handler) {
|
|
109
|
+
return this.add(HttpMethod.DELETE, path, handler);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Adds a PATCH route.
|
|
113
|
+
* @param path Route path.
|
|
114
|
+
* @param handler Request handler function.
|
|
115
|
+
*/
|
|
116
|
+
addPatch(path, handler) {
|
|
117
|
+
return this.add(HttpMethod.PATCH, path, handler);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Internal helper to add a route with any HTTP method.
|
|
121
|
+
*
|
|
122
|
+
* @param method The HTTP method.
|
|
123
|
+
* @param subPath Path segment (can be relative or absolute).
|
|
124
|
+
* @param handler Request handler.
|
|
125
|
+
* @returns The current builder instance (for chaining).
|
|
126
|
+
*/
|
|
127
|
+
add(method, subPath, handler) {
|
|
128
|
+
const normalizedPath = subPath.startsWith('/') ? subPath : `/${subPath}`;
|
|
129
|
+
this._routes.push(defineRoute(method, normalizedPath, handler));
|
|
130
|
+
return this;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Finalizes the router and returns an Astro-compatible route handler.
|
|
134
|
+
*
|
|
135
|
+
* This function should be used to export a method like `GET`, `POST`, or `ALL`
|
|
136
|
+
* inside Astro API endpoints.
|
|
137
|
+
*
|
|
138
|
+
* @returns A fully resolved Astro route handler.
|
|
139
|
+
*/
|
|
140
|
+
build() {
|
|
141
|
+
return defineRouter(this._routes, this._options);
|
|
16
142
|
}
|
|
17
143
|
}
|
|
144
|
+
RouterBuilder._registerWarned = false;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { type Route } from './defineRoute';
|
|
2
|
+
import { Handler } from "./defineHandler";
|
|
3
|
+
/**
|
|
4
|
+
* Represents a group of routes under a shared base path.
|
|
5
|
+
*
|
|
6
|
+
* Use this class to organize related endpoints, applying a consistent prefix
|
|
7
|
+
* and reducing duplication when defining similar routes.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const users = new RouteGroup('/users')
|
|
11
|
+
* .addGet('/:id', handler)
|
|
12
|
+
* .addPost('/', createUser);
|
|
13
|
+
*/
|
|
14
|
+
export declare class RouteGroup {
|
|
15
|
+
private basePath;
|
|
16
|
+
private routes;
|
|
17
|
+
/**
|
|
18
|
+
* Creates a new route group with the specified base path.
|
|
19
|
+
* Trailing slashes are automatically removed.
|
|
20
|
+
*
|
|
21
|
+
* @param basePath - The common prefix for all routes in the group (e.g. "/users")
|
|
22
|
+
*/
|
|
23
|
+
constructor(basePath: string);
|
|
24
|
+
/**
|
|
25
|
+
* Returns the normalized base path used by the group.
|
|
26
|
+
*/
|
|
27
|
+
getBasePath(): string;
|
|
28
|
+
/**
|
|
29
|
+
* Registers a GET route under the group's base path.
|
|
30
|
+
*
|
|
31
|
+
* @param path - Path relative to the base path (e.g. "/:id")
|
|
32
|
+
* @param handler - The handler function for this route
|
|
33
|
+
*/
|
|
34
|
+
addGet(path: string, handler: Handler): this;
|
|
35
|
+
/**
|
|
36
|
+
* Registers a POST route under the group's base path.
|
|
37
|
+
*
|
|
38
|
+
* @param path - Path relative to the base path
|
|
39
|
+
* @param handler - The handler function for this route
|
|
40
|
+
*/
|
|
41
|
+
addPost(path: string, handler: Handler): this;
|
|
42
|
+
/**
|
|
43
|
+
* Registers a PUT route under the group's base path.
|
|
44
|
+
*
|
|
45
|
+
* @param path - Path relative to the base path
|
|
46
|
+
* @param handler - The handler function for this route
|
|
47
|
+
*/
|
|
48
|
+
addPut(path: string, handler: Handler): this;
|
|
49
|
+
/**
|
|
50
|
+
* Registers a DELETE route under the group's base path.
|
|
51
|
+
*
|
|
52
|
+
* @param path - Path relative to the base path
|
|
53
|
+
* @param handler - The handler function for this route
|
|
54
|
+
*/
|
|
55
|
+
addDelete(path: string, handler: Handler): this;
|
|
56
|
+
/**
|
|
57
|
+
* Registers a PATCH route under the group's base path.
|
|
58
|
+
*
|
|
59
|
+
* @param path - Path relative to the base path
|
|
60
|
+
* @param handler - The handler function for this route
|
|
61
|
+
*/
|
|
62
|
+
addPatch(path: string, handler: Handler): this;
|
|
63
|
+
/**
|
|
64
|
+
* Internal method to register a route under the group with any HTTP method.
|
|
65
|
+
*
|
|
66
|
+
* @param method - HTTP verb
|
|
67
|
+
* @param subPath - Route path relative to the base
|
|
68
|
+
* @param handler - The handler function for this route
|
|
69
|
+
*/
|
|
70
|
+
private add;
|
|
71
|
+
/**
|
|
72
|
+
* Returns all the registered routes in the group.
|
|
73
|
+
*/
|
|
74
|
+
getRoutes(): Route[];
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Helper to define a `RouteGroup` with optional inline configuration.
|
|
78
|
+
*
|
|
79
|
+
* @param basePath - The base path prefix for all routes
|
|
80
|
+
* @param configure - Optional callback to configure the group inline
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* const users = defineGroup('/users', (group) => {
|
|
84
|
+
* group.addGet('/:id', handler);
|
|
85
|
+
* });
|
|
86
|
+
*/
|
|
87
|
+
export declare function defineGroup(basePath: string, configure?: (group: RouteGroup) => void): RouteGroup;
|