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 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
+ ![npm](https://img.shields.io/npm/v/astro-routify)
7
+ ![license](https://img.shields.io/npm/l/astro-routify)
8
+ ![downloads](https://img.shields.io/npm/dt/astro-routify)
9
+ ![feedback-welcome](https://img.shields.io/badge/feedback-welcome-blue)
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 { defineRoute, defineRouter, HttpMethod, ok } from "astro-routify";
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
- defineRoute(HttpMethod.GET, "/ping", () => ok("pong")),
16
- defineRoute(HttpMethod.GET, "/users/:id", ({ params }) => ok({ id: params.id }))
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 { RouterBuilder, defineRoute, HttpMethod, ok } from "astro-routify";
44
+ import {RouterBuilder, ok} from 'astro-routify';
24
45
 
25
46
  const builder = new RouterBuilder();
26
- builder.register([
27
- defineRoute(HttpMethod.GET, "/ping", () => ok("pong")),
28
- defineRoute(HttpMethod.POST, "/submit", async ({ request }) => {
29
- const body = await request.json();
30
- return ok({ received: body });
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 endpoints.
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", ({ params }) => {
61
- return ok({ userId: params.id });
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
- defineRoute(HttpMethod.GET, "/health", () => ok("ok"))
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
- Designed specifically for `ALL`:
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
- builder.register([
84
- defineRoute(HttpMethod.GET, "/info", () => ok({ app: "astro-routify" }))
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
- ok(data); // 200 OK
97
- created(data); // 201 Created
98
- noContent(); // 204
99
- notFound("Missing"); // 404
100
- internalError(err); // 500
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
- defineRoute(HttpMethod.GET, "/items/:id", ({ params }) => {
111
- return ok({ itemId: params.id });
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
- defineRoute(HttpMethod.GET, "/ping", () => ok({ pong: true })),
175
- defineRoute(HttpMethod.GET, "/users/:id", ({ params }) => ok({ id: params.id }))
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/benchmarks.html)
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 patterns in the future.
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 { Route } from './defineRoute';
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 routes;
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
- build(options?: RouterOptions): import("astro").APIRoute;
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.routes = [];
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.routes.push(...routeOrRoutes);
53
+ this._routes.push(...routeOrRoutes);
9
54
  }
10
55
  else {
11
- this.routes.push(routeOrRoutes);
56
+ this._routes.push(routeOrRoutes);
12
57
  }
13
58
  }
14
- build(options) {
15
- return defineRouter(this.routes, options);
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;