@aura-stack/router 0.3.0 → 0.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/README.md +2 -2
- package/dist/assert.cjs +17 -0
- package/dist/assert.d.ts +12 -2
- package/dist/assert.js +6 -2
- package/dist/{chunk-6PZEXNTS.js → chunk-4UYDR5IO.js} +2 -2
- package/dist/{chunk-GJC3ODME.js → chunk-B6PMGVSL.js} +9 -1
- package/dist/{chunk-FWDOXDWG.js → chunk-BWIKAYZV.js} +9 -9
- package/dist/{chunk-JNMXLKDG.js → chunk-FU35BPU7.js} +11 -2
- package/dist/{chunk-JIA6NLL6.js → chunk-TEDN6QMU.js} +39 -19
- package/dist/{chunk-PT4GU6PH.js → chunk-XB5P5CQZ.js} +22 -9
- package/dist/chunk-Z6JJAIWN.js +37 -0
- package/dist/context.cjs +27 -8
- package/dist/context.d.ts +12 -20
- package/dist/context.js +5 -5
- package/dist/cookie.cjs +24 -0
- package/dist/cookie.d.ts +1 -0
- package/dist/cookie.js +2 -0
- package/dist/endpoint.d.ts +2 -0
- package/dist/endpoint.js +3 -3
- package/dist/error.cjs +9 -0
- package/dist/error.d.ts +7 -1
- package/dist/error.js +3 -1
- package/dist/headers.cjs +61 -0
- package/dist/headers.d.ts +20 -0
- package/dist/headers.js +6 -0
- package/dist/index.cjs +105 -28
- package/dist/index.d.ts +4 -2
- package/dist/index.js +14 -8
- package/dist/middlewares.cjs +8 -8
- package/dist/middlewares.d.ts +5 -3
- package/dist/middlewares.js +2 -2
- package/dist/router.cjs +101 -28
- package/dist/router.d.ts +2 -0
- package/dist/router.js +6 -5
- package/dist/types.d.ts +29 -6
- package/package.json +39 -13
- package/dist/assert.d.cts +0 -52
- package/dist/context.d.cts +0 -85
- package/dist/endpoint.d.cts +0 -60
- package/dist/error.d.cts +0 -65
- package/dist/index.d.cts +0 -6
- package/dist/middlewares.d.cts +0 -23
- package/dist/router.d.cts +0 -37
- package/dist/types.d.cts +0 -191
package/dist/router.cjs
CHANGED
|
@@ -74,6 +74,47 @@ var RouterError = class extends AuraStackRouterError {
|
|
|
74
74
|
this.name = name ?? "RouterError";
|
|
75
75
|
}
|
|
76
76
|
};
|
|
77
|
+
var InvalidZodSchemaError = class {
|
|
78
|
+
constructor(type, errors) {
|
|
79
|
+
this.status = statusCode[type];
|
|
80
|
+
this.statusText = statusText[type];
|
|
81
|
+
this.errors = errors;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// src/headers.ts
|
|
86
|
+
var import_cookie = require("cookie");
|
|
87
|
+
var HeadersBuilder = class {
|
|
88
|
+
constructor(initialHeaders) {
|
|
89
|
+
this.headers = new Headers(initialHeaders);
|
|
90
|
+
}
|
|
91
|
+
setHeader(name, value) {
|
|
92
|
+
this.headers.set(name, value);
|
|
93
|
+
return this;
|
|
94
|
+
}
|
|
95
|
+
setCookie(name, value, options) {
|
|
96
|
+
this.headers.append("Set-Cookie", (0, import_cookie.serialize)(name, value, options));
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
getHeader(name) {
|
|
100
|
+
return this.headers.get(name);
|
|
101
|
+
}
|
|
102
|
+
getCookie(name) {
|
|
103
|
+
const cookies = (0, import_cookie.parse)(this.headers.get("cookie") ?? "");
|
|
104
|
+
return cookies[name];
|
|
105
|
+
}
|
|
106
|
+
getSetCookie(name) {
|
|
107
|
+
const cookies = this.headers.getSetCookie();
|
|
108
|
+
const cookie = cookies.find((cookie2) => cookie2.startsWith(name + "="));
|
|
109
|
+
return cookie ? (0, import_cookie.parseSetCookie)(cookie).value : void 0;
|
|
110
|
+
}
|
|
111
|
+
toHeaders() {
|
|
112
|
+
return new Headers(this.headers);
|
|
113
|
+
}
|
|
114
|
+
toCookies() {
|
|
115
|
+
return (0, import_cookie.parse)(this.headers.get("cookie") ?? "");
|
|
116
|
+
}
|
|
117
|
+
};
|
|
77
118
|
|
|
78
119
|
// src/assert.ts
|
|
79
120
|
var supportedMethods = /* @__PURE__ */ new Set(["GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD", "TRACE", "CONNECT"]);
|
|
@@ -87,13 +128,31 @@ var isSupportedBodyMethod = (method) => {
|
|
|
87
128
|
var isRouterError = (error) => {
|
|
88
129
|
return error instanceof RouterError;
|
|
89
130
|
};
|
|
131
|
+
var isInvalidZodSchemaError = (error) => {
|
|
132
|
+
return error instanceof InvalidZodSchemaError;
|
|
133
|
+
};
|
|
90
134
|
|
|
91
135
|
// src/context.ts
|
|
136
|
+
var formatZodError = (error) => {
|
|
137
|
+
if (!error.issues || error.issues.length === 0) {
|
|
138
|
+
return {};
|
|
139
|
+
}
|
|
140
|
+
return error.issues.reduce((previous, issue) => {
|
|
141
|
+
const key = issue.path.join(".");
|
|
142
|
+
return {
|
|
143
|
+
...previous,
|
|
144
|
+
[key]: {
|
|
145
|
+
code: issue.code,
|
|
146
|
+
message: issue.message
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}, {});
|
|
150
|
+
};
|
|
92
151
|
var getRouteParams = (params, config) => {
|
|
93
152
|
if (config.schemas?.params) {
|
|
94
153
|
const parsed = config.schemas.params.safeParse(params);
|
|
95
154
|
if (!parsed.success) {
|
|
96
|
-
throw new
|
|
155
|
+
throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
|
|
97
156
|
}
|
|
98
157
|
return parsed.data;
|
|
99
158
|
}
|
|
@@ -104,15 +163,12 @@ var getSearchParams = (url, config) => {
|
|
|
104
163
|
if (config.schemas?.searchParams) {
|
|
105
164
|
const parsed = config.schemas.searchParams.safeParse(Object.fromEntries(route.searchParams.entries()));
|
|
106
165
|
if (!parsed.success) {
|
|
107
|
-
throw new
|
|
166
|
+
throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
|
|
108
167
|
}
|
|
109
168
|
return parsed.data;
|
|
110
169
|
}
|
|
111
170
|
return new URLSearchParams(route.searchParams.toString());
|
|
112
171
|
};
|
|
113
|
-
var getHeaders = (request) => {
|
|
114
|
-
return new Headers(request.headers);
|
|
115
|
-
};
|
|
116
172
|
var getBody = async (request, config) => {
|
|
117
173
|
if (!isSupportedBodyMethod(request.method)) {
|
|
118
174
|
return null;
|
|
@@ -124,7 +180,7 @@ var getBody = async (request, config) => {
|
|
|
124
180
|
if (config.schemas?.body) {
|
|
125
181
|
const parsed = config.schemas.body.safeParse(json);
|
|
126
182
|
if (!parsed.success) {
|
|
127
|
-
throw new
|
|
183
|
+
throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
|
|
128
184
|
}
|
|
129
185
|
return parsed.data;
|
|
130
186
|
}
|
|
@@ -154,31 +210,31 @@ var createContentTypeRegex = (contentTypes, contenType) => {
|
|
|
154
210
|
};
|
|
155
211
|
|
|
156
212
|
// src/middlewares.ts
|
|
157
|
-
var executeGlobalMiddlewares = async (
|
|
158
|
-
if (!middlewares) return
|
|
213
|
+
var executeGlobalMiddlewares = async (context, middlewares) => {
|
|
214
|
+
if (!middlewares) return context;
|
|
159
215
|
for (const middleware of middlewares) {
|
|
160
216
|
if (typeof middleware !== "function") {
|
|
161
217
|
throw new RouterError("BAD_REQUEST", "Global middlewares must be functions");
|
|
162
218
|
}
|
|
163
|
-
const executed = await middleware(
|
|
219
|
+
const executed = await middleware(context);
|
|
164
220
|
if (executed instanceof Response) {
|
|
165
221
|
return executed;
|
|
166
222
|
}
|
|
167
|
-
|
|
223
|
+
context = executed;
|
|
168
224
|
}
|
|
169
|
-
if (!
|
|
225
|
+
if (!context || !(context.request instanceof Request)) {
|
|
170
226
|
throw new RouterError("BAD_REQUEST", "Global middleware must return a Request or Response object");
|
|
171
227
|
}
|
|
172
|
-
return
|
|
228
|
+
return context;
|
|
173
229
|
};
|
|
174
|
-
var executeMiddlewares = async (
|
|
230
|
+
var executeMiddlewares = async (context, middlewares = []) => {
|
|
175
231
|
try {
|
|
176
232
|
let ctx = context;
|
|
177
233
|
for (const middleware of middlewares) {
|
|
178
234
|
if (typeof middleware !== "function") {
|
|
179
235
|
throw new RouterError("BAD_REQUEST", "Middleware must be a function");
|
|
180
236
|
}
|
|
181
|
-
ctx = await middleware(
|
|
237
|
+
ctx = await middleware(ctx);
|
|
182
238
|
}
|
|
183
239
|
return ctx;
|
|
184
240
|
} catch {
|
|
@@ -250,6 +306,17 @@ var handleError = async (error, request, config) => {
|
|
|
250
306
|
);
|
|
251
307
|
}
|
|
252
308
|
}
|
|
309
|
+
if (isInvalidZodSchemaError(error)) {
|
|
310
|
+
const { errors, status, statusText: statusText2 } = error;
|
|
311
|
+
return Response.json(
|
|
312
|
+
{
|
|
313
|
+
message: "Invalid request data",
|
|
314
|
+
error: "validation_error",
|
|
315
|
+
details: errors
|
|
316
|
+
},
|
|
317
|
+
{ status, statusText: statusText2 }
|
|
318
|
+
);
|
|
319
|
+
}
|
|
253
320
|
if (isRouterError(error)) {
|
|
254
321
|
const { message, status, statusText: statusText2 } = error;
|
|
255
322
|
return Response.json({ message }, { status, statusText: statusText2 });
|
|
@@ -261,29 +328,35 @@ var handleRequest = async (method, request, config, root) => {
|
|
|
261
328
|
if (!isSupportedMethod(request.method)) {
|
|
262
329
|
throw new RouterError("METHOD_NOT_ALLOWED", `The HTTP method '${request.method}' is not supported`);
|
|
263
330
|
}
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
331
|
+
const globalContext = { request, context: config.context ?? {} };
|
|
332
|
+
const globalRequestContext = await executeGlobalMiddlewares(globalContext, config.middlewares);
|
|
333
|
+
if (globalRequestContext instanceof Response) return globalRequestContext;
|
|
334
|
+
const url = new URL(globalRequestContext.request.url);
|
|
267
335
|
const pathnameWithBase = url.pathname;
|
|
268
|
-
if (
|
|
269
|
-
throw new RouterError("METHOD_NOT_ALLOWED", `The HTTP method '${
|
|
336
|
+
if (globalRequestContext.request.method !== method) {
|
|
337
|
+
throw new RouterError("METHOD_NOT_ALLOWED", `The HTTP method '${globalRequestContext.request.method}' is not allowed`);
|
|
270
338
|
}
|
|
271
339
|
const { endpoint, params } = search(method, root, pathnameWithBase);
|
|
272
|
-
if (endpoint.method !==
|
|
273
|
-
throw new RouterError("METHOD_NOT_ALLOWED", `The HTTP method '${
|
|
340
|
+
if (endpoint.method !== globalRequestContext.request.method) {
|
|
341
|
+
throw new RouterError("METHOD_NOT_ALLOWED", `The HTTP method '${globalRequestContext.request.method}' is not allowed`);
|
|
274
342
|
}
|
|
275
343
|
const dynamicParams = getRouteParams(params, endpoint.config);
|
|
276
|
-
const body = await getBody(
|
|
277
|
-
const searchParams = getSearchParams(
|
|
278
|
-
const headers =
|
|
279
|
-
|
|
344
|
+
const body = await getBody(globalRequestContext.request, endpoint.config);
|
|
345
|
+
const searchParams = getSearchParams(globalRequestContext.request.url, endpoint.config);
|
|
346
|
+
const headers = new HeadersBuilder(globalRequestContext.request.headers);
|
|
347
|
+
let context = {
|
|
280
348
|
params: dynamicParams,
|
|
281
349
|
searchParams,
|
|
282
350
|
headers,
|
|
283
|
-
body
|
|
351
|
+
body,
|
|
352
|
+
request: globalRequestContext.request,
|
|
353
|
+
url,
|
|
354
|
+
method: globalRequestContext.request.method,
|
|
355
|
+
route: endpoint.route,
|
|
356
|
+
context: config.context ?? {}
|
|
284
357
|
};
|
|
285
|
-
await executeMiddlewares(
|
|
286
|
-
const response = await endpoint.handler(
|
|
358
|
+
context = await executeMiddlewares(context, endpoint.config.middlewares);
|
|
359
|
+
const response = await endpoint.handler(context);
|
|
287
360
|
return response;
|
|
288
361
|
} catch (error) {
|
|
289
362
|
return handleError(error, request, config);
|
package/dist/router.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { RouteEndpoint, RouterConfig, GetHttpHandlers, HTTPMethod, RoutePattern, EndpointSchemas, MiddlewareFunction } from './types.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
import './error.js';
|
|
4
|
+
import './headers.js';
|
|
5
|
+
import 'cookie';
|
|
4
6
|
|
|
5
7
|
interface TrieNode {
|
|
6
8
|
statics: Map<string, TrieNode>;
|
package/dist/router.js
CHANGED
|
@@ -3,11 +3,12 @@ import {
|
|
|
3
3
|
createRouter,
|
|
4
4
|
insert,
|
|
5
5
|
search
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-TEDN6QMU.js";
|
|
7
|
+
import "./chunk-XB5P5CQZ.js";
|
|
8
|
+
import "./chunk-FU35BPU7.js";
|
|
9
|
+
import "./chunk-Z6JJAIWN.js";
|
|
10
|
+
import "./chunk-BWIKAYZV.js";
|
|
11
|
+
import "./chunk-B6PMGVSL.js";
|
|
11
12
|
export {
|
|
12
13
|
createNode,
|
|
13
14
|
createRouter,
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ZodObject, z } from 'zod';
|
|
2
2
|
import { RouterError } from './error.js';
|
|
3
|
+
import { HeadersBuilder } from './headers.js';
|
|
4
|
+
import 'cookie';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Route pattern must start with a slash and can contain parameters prefixed with a colon.
|
|
@@ -50,6 +52,13 @@ interface EndpointSchemas {
|
|
|
50
52
|
searchParams?: ZodObject<any>;
|
|
51
53
|
params?: ZodObject<any>;
|
|
52
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Global context type that can be extended when creating the router. It allows passing
|
|
57
|
+
* additional data to all route handlers and middlewares. For a type-inference use module
|
|
58
|
+
* augmentation to extend the GlobalContext interface.
|
|
59
|
+
*/
|
|
60
|
+
interface GlobalContext {
|
|
61
|
+
}
|
|
53
62
|
/**
|
|
54
63
|
* Configuration for an endpoint, including optional schemas for request validation and middlewares.
|
|
55
64
|
*/
|
|
@@ -95,25 +104,34 @@ type ContextParams<Schemas extends EndpointConfig["schemas"], Default = Record<s
|
|
|
95
104
|
*/
|
|
96
105
|
interface RequestContext<RouteParams = Record<string, string>, Config extends EndpointConfig = EndpointConfig> {
|
|
97
106
|
params: ContextParams<Config["schemas"], RouteParams>["params"];
|
|
98
|
-
headers:
|
|
107
|
+
headers: HeadersBuilder;
|
|
99
108
|
body: ContextBody<Config["schemas"]>["body"];
|
|
100
109
|
searchParams: ContextSearchParams<Config["schemas"]>["searchParams"];
|
|
110
|
+
request: Request;
|
|
111
|
+
url: URL;
|
|
112
|
+
method: HTTPMethod;
|
|
113
|
+
route: RoutePattern;
|
|
114
|
+
context: GlobalContext;
|
|
115
|
+
}
|
|
116
|
+
interface GlobalMiddlewareContext {
|
|
117
|
+
request: Request;
|
|
118
|
+
context: GlobalContext;
|
|
101
119
|
}
|
|
102
120
|
/**
|
|
103
121
|
* Global middleware function type that represent a function that runs before the route matching.
|
|
104
122
|
*/
|
|
105
|
-
type GlobalMiddleware = (
|
|
123
|
+
type GlobalMiddleware = (ctx: GlobalMiddlewareContext) => Response | GlobalMiddlewareContext | Promise<Response | GlobalMiddlewareContext>;
|
|
106
124
|
/**
|
|
107
125
|
* Middleware function type that represent a function that runs before the route handler
|
|
108
126
|
* defined in the `createEndpoint/createEndpointConfig` function or globally in the `createRouter` function.
|
|
109
127
|
*/
|
|
110
|
-
type MiddlewareFunction<RouteParams = Record<string, string>, Config extends EndpointConfig = EndpointConfig> = (
|
|
128
|
+
type MiddlewareFunction<RouteParams = Record<string, string>, Config extends EndpointConfig = EndpointConfig> = (ctx: Prettify<RequestContext<RouteParams, Config>>) => Response | RequestContext<RouteParams, Config> | Promise<Response | RequestContext<RouteParams, Config>>;
|
|
111
129
|
/**
|
|
112
130
|
* Defines a route handler function that processes an incoming request and returns a response.
|
|
113
131
|
* The handler receives the request object and a context containing route parameters, headers,
|
|
114
132
|
* and optionally validated body and search parameters based on the endpoint configuration.
|
|
115
133
|
*/
|
|
116
|
-
type RouteHandler<Route extends RoutePattern, Config extends EndpointConfig> = (
|
|
134
|
+
type RouteHandler<Route extends RoutePattern, Config extends EndpointConfig> = (ctx: Prettify<RequestContext<GetRouteParams<Route>, Config>>) => Response | Promise<Response>;
|
|
117
135
|
/**
|
|
118
136
|
* Represents a route endpoint definition, specifying the HTTP method, route pattern,
|
|
119
137
|
* handler function with inferred context types, and associated configuration.
|
|
@@ -135,10 +153,15 @@ type InferMethod<Endpoints extends RouteEndpoint[]> = Endpoints extends unknown[
|
|
|
135
153
|
type GetHttpHandlers<Endpoints extends RouteEndpoint[]> = {
|
|
136
154
|
[Method in InferMethod<Endpoints>]: (req: Request) => Response | Promise<Response>;
|
|
137
155
|
};
|
|
156
|
+
type GlobalCtx = keyof GlobalContext extends never ? {
|
|
157
|
+
context?: GlobalContext;
|
|
158
|
+
} : {
|
|
159
|
+
context: GlobalContext;
|
|
160
|
+
};
|
|
138
161
|
/**
|
|
139
162
|
* Configuration options for `createRouter` function.
|
|
140
163
|
*/
|
|
141
|
-
interface RouterConfig {
|
|
164
|
+
interface RouterConfig extends GlobalCtx {
|
|
142
165
|
/**
|
|
143
166
|
* Prefix path for all routes/endpoints defined in the router.
|
|
144
167
|
*
|
|
@@ -188,4 +211,4 @@ interface RouterConfig {
|
|
|
188
211
|
onError?: (error: Error | RouterError, request: Request) => Response | Promise<Response>;
|
|
189
212
|
}
|
|
190
213
|
|
|
191
|
-
export type { ContentType, ContextBody, ContextParams, ContextSearchParams, EndpointConfig, EndpointSchemas, GetHttpHandlers, GetRouteParams, GlobalMiddleware, HTTPMethod, InferMethod, MiddlewareFunction, Prettify, RequestContext, RouteEndpoint, RouteHandler, RoutePattern, RouterConfig };
|
|
214
|
+
export type { ContentType, ContextBody, ContextParams, ContextSearchParams, EndpointConfig, EndpointSchemas, GetHttpHandlers, GetRouteParams, GlobalContext, GlobalCtx, GlobalMiddleware, GlobalMiddlewareContext, HTTPMethod, InferMethod, MiddlewareFunction, Prettify, RequestContext, RouteEndpoint, RouteHandler, RoutePattern, RouterConfig };
|
package/package.json
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aura-stack/router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A lightweight TypeScript library for building, managing, and validating API routes and endpoints in Node.js applications.",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/aura-stack-ts/router"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public",
|
|
12
|
+
"registry": "https://registry.npmjs.org/@aura-stack/router"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"router",
|
|
16
|
+
"endpoints",
|
|
17
|
+
"api",
|
|
18
|
+
"aura",
|
|
19
|
+
"aura stack",
|
|
20
|
+
"typescript",
|
|
21
|
+
"nodejs"
|
|
22
|
+
],
|
|
23
|
+
"author": "Aura Stack <auraauthoss@gmail.com> | Hernan Alvarado <hernanvid123@gmail.com>",
|
|
24
|
+
"homepage": "https://github.com/aura-stack-ts/router",
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/aura-stack-ts/router/issues"
|
|
27
|
+
},
|
|
28
|
+
"license": "MIT",
|
|
6
29
|
"files": [
|
|
7
30
|
"dist"
|
|
8
31
|
],
|
|
@@ -27,19 +50,18 @@
|
|
|
27
50
|
"import": "./dist/error.js",
|
|
28
51
|
"require": "./dist/error.cjs"
|
|
29
52
|
},
|
|
53
|
+
"./headers": {
|
|
54
|
+
"types": "./dist/headers.d.ts",
|
|
55
|
+
"import": "./dist/headers.js",
|
|
56
|
+
"require": "./dist/headers.cjs"
|
|
57
|
+
},
|
|
58
|
+
"./cookie": {
|
|
59
|
+
"types": "./dist/cookie.d.ts",
|
|
60
|
+
"import": "./dist/cookie.js",
|
|
61
|
+
"require": "./dist/cookie.cjs"
|
|
62
|
+
},
|
|
30
63
|
"./types": "./dist/types.d.ts"
|
|
31
64
|
},
|
|
32
|
-
"keywords": [
|
|
33
|
-
"router",
|
|
34
|
-
"endpoints",
|
|
35
|
-
"api",
|
|
36
|
-
"aura",
|
|
37
|
-
"aura stack",
|
|
38
|
-
"typescript",
|
|
39
|
-
"nodejs"
|
|
40
|
-
],
|
|
41
|
-
"author": "Aura Stack <auraauthoss@gmail.com> | Hernan Alvarado <hernanvid123@gmail.com>",
|
|
42
|
-
"license": "MIT",
|
|
43
65
|
"devDependencies": {
|
|
44
66
|
"prettier": "^3.6.2",
|
|
45
67
|
"tsup": "^8.5.0",
|
|
@@ -47,6 +69,9 @@
|
|
|
47
69
|
"vitest": "^3.2.4",
|
|
48
70
|
"zod": "^4.1.11"
|
|
49
71
|
},
|
|
72
|
+
"dependencies": {
|
|
73
|
+
"cookie": "^1.1.1"
|
|
74
|
+
},
|
|
50
75
|
"scripts": {
|
|
51
76
|
"dev": "tsup --watch",
|
|
52
77
|
"dev:docs": "pnpm --filter docs dev",
|
|
@@ -58,6 +83,7 @@
|
|
|
58
83
|
"test:bench": "vitest --run bench",
|
|
59
84
|
"type-check": "tsc --noEmit",
|
|
60
85
|
"clean": "rm -rf dist",
|
|
61
|
-
"clean:cts": "rm -rf dist/*.cts"
|
|
86
|
+
"clean:cts": "rm -rf dist/*.cts",
|
|
87
|
+
"prepublish": "pnpm clean:cts"
|
|
62
88
|
}
|
|
63
89
|
}
|
package/dist/assert.d.cts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { RouterError } from './error.cjs';
|
|
2
|
-
import { HTTPMethod, RoutePattern, RouteHandler } from './types.cjs';
|
|
3
|
-
import 'zod';
|
|
4
|
-
|
|
5
|
-
declare const supportedProtocols: Set<string>;
|
|
6
|
-
/**
|
|
7
|
-
* Checks if the provided method is a supported HTTP method.
|
|
8
|
-
*
|
|
9
|
-
* @param method - The HTTP method to check.
|
|
10
|
-
* @returns True if the method is supported, false otherwise.
|
|
11
|
-
*/
|
|
12
|
-
declare const isSupportedMethod: (method: string) => method is HTTPMethod;
|
|
13
|
-
/**
|
|
14
|
-
* Check if the provided method can includes a body as per HTTP specification.
|
|
15
|
-
* @param method - The HTTP method to check.
|
|
16
|
-
* @returns True if the method can include a body, false otherwise.
|
|
17
|
-
*/
|
|
18
|
-
declare const isSupportedBodyMethod: (method: string) => method is HTTPMethod;
|
|
19
|
-
/**
|
|
20
|
-
* Checks if the provided route is a valid route pattern.
|
|
21
|
-
*
|
|
22
|
-
* @param route - The route pattern to check.
|
|
23
|
-
* @returns True if the route is valid, false otherwise.
|
|
24
|
-
*/
|
|
25
|
-
declare const isValidRoute: (route: string) => route is RoutePattern;
|
|
26
|
-
/**
|
|
27
|
-
* Checks if the provided handler is a valid route handler function.
|
|
28
|
-
*
|
|
29
|
-
* @param handler - The handler to check.
|
|
30
|
-
* @returns True if the handler is valid, false otherwise.
|
|
31
|
-
*/
|
|
32
|
-
declare const isValidHandler: (handler: unknown) => handler is RouteHandler<any, any>;
|
|
33
|
-
/**
|
|
34
|
-
* Asserts that the error is an instance of RouterError. It is useful if you want
|
|
35
|
-
* to check if the error thrown by the router is an RouterError or by other sources.
|
|
36
|
-
*
|
|
37
|
-
* @param error - The error to check
|
|
38
|
-
* @returns True if the error is an instance of RouterError, false otherwise.
|
|
39
|
-
* @example
|
|
40
|
-
* import { isRouterError } from "aura-stack/router";
|
|
41
|
-
*
|
|
42
|
-
* try {
|
|
43
|
-
* // Some router operation that may throw an error
|
|
44
|
-
* } catch (error) {
|
|
45
|
-
* if (isRouterError(error)) {
|
|
46
|
-
* // Handle RouterError
|
|
47
|
-
* }
|
|
48
|
-
* }
|
|
49
|
-
*/
|
|
50
|
-
declare const isRouterError: (error: unknown) => error is RouterError;
|
|
51
|
-
|
|
52
|
-
export { isRouterError, isSupportedBodyMethod, isSupportedMethod, isValidHandler, isValidRoute, supportedProtocols };
|
package/dist/context.d.cts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { EndpointConfig, ContextSearchParams } from './types.cjs';
|
|
2
|
-
import 'zod';
|
|
3
|
-
import './error.cjs';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Extracts route parameters from a given path using the specified route pattern.
|
|
7
|
-
*
|
|
8
|
-
* This function matches the provided path against the route pattern
|
|
9
|
-
* (e.g., "/users/:userId/posts/:postId") and returns an object mapping parameter
|
|
10
|
-
* names to their decoded values.
|
|
11
|
-
*
|
|
12
|
-
* @param route - The route pattern, typically defined in the endpoint configuration.
|
|
13
|
-
* @param path - The actual request path to extract parameters from.
|
|
14
|
-
* @returns An object containing the extracted route parameters as key-value pairs.
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* const route = "/users/:userId/posts/:postId";
|
|
18
|
-
* const path = "/users/123/posts/456";
|
|
19
|
-
*
|
|
20
|
-
* // Expected: { userId: "123", postId: "456" }
|
|
21
|
-
* const params = getRouteParams(route, path);
|
|
22
|
-
*/
|
|
23
|
-
declare const getRouteParams: (params: Record<string, string>, config: EndpointConfig) => Record<string, unknown>;
|
|
24
|
-
/**
|
|
25
|
-
* Extracts and validates search parameters from a given URL from the request.
|
|
26
|
-
*
|
|
27
|
-
* If a schema is provided in the endpoint configuration, the search parameters
|
|
28
|
-
* are validated against it using Zod and returned the parsed data. If validation
|
|
29
|
-
* fails, an error is thrown. Otherwise, a URLSearchParams object is returned.
|
|
30
|
-
*
|
|
31
|
-
* @param url - The actual request URL to extract search parameters from.
|
|
32
|
-
* @param config - Configuration object that may include a schema for validation.
|
|
33
|
-
* @returns Either a URLSearchParams object or a parsed object based on the provided schema.
|
|
34
|
-
* @example
|
|
35
|
-
* // With schema
|
|
36
|
-
* const url = "https://example.com/api?search=test&page=2";
|
|
37
|
-
* const config: EndpointConfig = {
|
|
38
|
-
* schemas: {
|
|
39
|
-
* searchParams: z.object({
|
|
40
|
-
* search: z.string(),
|
|
41
|
-
* page: z.number().optional(),
|
|
42
|
-
* }),
|
|
43
|
-
* },
|
|
44
|
-
* }
|
|
45
|
-
*
|
|
46
|
-
* // Expected: { search: "test", page: 2 }
|
|
47
|
-
* const searchParams = getSearchParams(url, config);
|
|
48
|
-
*
|
|
49
|
-
* // Without schema
|
|
50
|
-
* const url2 = "https://example.com/api?query=example";
|
|
51
|
-
*
|
|
52
|
-
* // Expected: URLSearchParams { 'query' => 'example' }
|
|
53
|
-
* const searchParams2 = getSearchParams(url2, {} as EndpointConfig);
|
|
54
|
-
*/
|
|
55
|
-
declare const getSearchParams: <Config extends EndpointConfig>(url: string, config: Config) => ContextSearchParams<Config["schemas"]>["searchParams"];
|
|
56
|
-
/**
|
|
57
|
-
* Extracts headers from the given Request object and returns them as a Headers instance.
|
|
58
|
-
*
|
|
59
|
-
* @param request - The Request object from which to extract headers.
|
|
60
|
-
* @returns A Headers instance containing all headers from the request.
|
|
61
|
-
* @example
|
|
62
|
-
* const request = new Request("https://example.com/api", {
|
|
63
|
-
* headers: {
|
|
64
|
-
* "Content-Type": "application/json",
|
|
65
|
-
* "Authorization": "Bearer token",
|
|
66
|
-
* },
|
|
67
|
-
* });
|
|
68
|
-
* const headers = getHeaders(request);
|
|
69
|
-
*/
|
|
70
|
-
declare const getHeaders: (request: Request) => Headers;
|
|
71
|
-
/**
|
|
72
|
-
* Extracts and parses the body of a Request object based on its Content-Type header.
|
|
73
|
-
*
|
|
74
|
-
* If a schema is provided in the endpoint configuration, the body is validated against
|
|
75
|
-
* it using Zod and returned the parsed data. If validation fails, an error is thrown.
|
|
76
|
-
*
|
|
77
|
-
* In some cases, the browser includes text/plain;charset=UTF-8 as the default Content-Type
|
|
78
|
-
*
|
|
79
|
-
* @param request - The Request object from which to extract the body.
|
|
80
|
-
* @param config - Configuration object that may include a schema for validation.
|
|
81
|
-
* @returns The parsed body of the request or an error if validation fails.
|
|
82
|
-
*/
|
|
83
|
-
declare const getBody: <Config extends EndpointConfig>(request: Request, config: Config) => Promise<any>;
|
|
84
|
-
|
|
85
|
-
export { getBody, getHeaders, getRouteParams, getSearchParams };
|
package/dist/endpoint.d.cts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { HTTPMethod, RoutePattern, EndpointSchemas, RouteHandler, EndpointConfig, RouteEndpoint } from './types.cjs';
|
|
2
|
-
import 'zod';
|
|
3
|
-
import './error.cjs';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Defines an API endpoint for the router by specifying the HTTP method, route pattern,
|
|
7
|
-
* handler function, and optional configuration such as validation schemas or middlewares.
|
|
8
|
-
* Validates all parameters for correctness. The resulting endpoint should be passed
|
|
9
|
-
* to the `createRouter` function.
|
|
10
|
-
*
|
|
11
|
-
* @param method - The HTTP method (e.g., GET, POST, PUT, DELETE, PATCH)
|
|
12
|
-
* @param route - The route pattern to associate with the endpoint (supports dynamic params)
|
|
13
|
-
* @param handler - The function to handle requests matching the method and route
|
|
14
|
-
* @param config - Optional configuration including validation schemas, middlewares, etc.
|
|
15
|
-
* @returns An object representing the configured endpoint
|
|
16
|
-
* @example
|
|
17
|
-
* const signIn = createEndpoint("POST", "/auth/signin", async (req, ctx) => {
|
|
18
|
-
* return new Response("Signed in");
|
|
19
|
-
* });
|
|
20
|
-
*/
|
|
21
|
-
declare const createEndpoint: <const Method extends Uppercase<HTTPMethod>, const Route extends RoutePattern, const Schemas extends EndpointSchemas>(method: Method, route: Route, handler: RouteHandler<Route, {
|
|
22
|
-
schemas: Schemas;
|
|
23
|
-
}>, config?: EndpointConfig<Route, Schemas>) => RouteEndpoint<Method, Route, {}>;
|
|
24
|
-
/**
|
|
25
|
-
* Create an endpoint configuration to be passed to the `createEndpoint` function.
|
|
26
|
-
* This function is primarily for type inference and does not perform any runtime checks.
|
|
27
|
-
*
|
|
28
|
-
* This overload is recommended when the route pattern does not need to be specified explicitly,
|
|
29
|
-
* otherwise use the overload that accepts the route pattern as the first argument.
|
|
30
|
-
*
|
|
31
|
-
* @param config - The endpoint configuration object
|
|
32
|
-
* @returns The same configuration object, typed as EndpointConfig
|
|
33
|
-
* @example
|
|
34
|
-
* // Without route pattern
|
|
35
|
-
* const config = createEndpointConfig({
|
|
36
|
-
* middlewares: [myMiddleware],
|
|
37
|
-
* schemas: {
|
|
38
|
-
* searchParams: z.object({
|
|
39
|
-
* q: z.string().min(3),
|
|
40
|
-
* })
|
|
41
|
-
* }
|
|
42
|
-
* })
|
|
43
|
-
*
|
|
44
|
-
* const search = createEndpoint("GET", "/search", async (request, ctx) => {
|
|
45
|
-
* return new Response("Search results");
|
|
46
|
-
* }, config);
|
|
47
|
-
*
|
|
48
|
-
* // Overload with route pattern
|
|
49
|
-
* const config = createEndpointConfig("/users/:userId", {
|
|
50
|
-
* middlewares: [myMiddleware],
|
|
51
|
-
* })
|
|
52
|
-
*
|
|
53
|
-
* const getUser = createEndpoint("GET", "/users/:userId", async (request, ctx) => {
|
|
54
|
-
* return new Response("User details");
|
|
55
|
-
* }, config);
|
|
56
|
-
*/
|
|
57
|
-
declare function createEndpointConfig<Schemas extends EndpointSchemas>(config: EndpointConfig<RoutePattern, Schemas>): EndpointConfig<RoutePattern, Schemas>;
|
|
58
|
-
declare function createEndpointConfig<Route extends RoutePattern, Schemas extends EndpointSchemas>(route: Route, config: EndpointConfig<Route, Schemas>): EndpointConfig<Route, Schemas>;
|
|
59
|
-
|
|
60
|
-
export { createEndpoint, createEndpointConfig };
|
package/dist/error.d.cts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The HTTP status codes used in AuraStack Router.
|
|
3
|
-
*/
|
|
4
|
-
declare const statusCode: {
|
|
5
|
-
OK: number;
|
|
6
|
-
CREATED: number;
|
|
7
|
-
ACCEPTED: number;
|
|
8
|
-
NO_CONTENT: number;
|
|
9
|
-
MULTIPLE_CHOICES: number;
|
|
10
|
-
MOVED_PERMANENTLY: number;
|
|
11
|
-
FOUND: number;
|
|
12
|
-
SEE_OTHER: number;
|
|
13
|
-
NOT_MODIFIED: number;
|
|
14
|
-
TEMPORARY_REDIRECT: number;
|
|
15
|
-
BAD_REQUEST: number;
|
|
16
|
-
UNAUTHORIZED: number;
|
|
17
|
-
PAYMENT_REQUIRED: number;
|
|
18
|
-
FORBIDDEN: number;
|
|
19
|
-
NOT_FOUND: number;
|
|
20
|
-
METHOD_NOT_ALLOWED: number;
|
|
21
|
-
NOT_ACCEPTABLE: number;
|
|
22
|
-
PROXY_AUTHENTICATION_REQUIRED: number;
|
|
23
|
-
UNPROCESSABLE_ENTITY: number;
|
|
24
|
-
INTERNAL_SERVER_ERROR: number;
|
|
25
|
-
NOT_IMPLEMENTED: number;
|
|
26
|
-
BAD_GATEWAY: number;
|
|
27
|
-
SERVICE_UNAVAILABLE: number;
|
|
28
|
-
HTTP_VERSION_NOT_SUPPORTED: number;
|
|
29
|
-
};
|
|
30
|
-
type StatusCode = keyof typeof statusCode;
|
|
31
|
-
/**
|
|
32
|
-
* Reverse mapping of status codes to their corresponding status text.
|
|
33
|
-
*/
|
|
34
|
-
declare const statusText: Record<"OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "UNPROCESSABLE_ENTITY" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "HTTP_VERSION_NOT_SUPPORTED", "OK" | "CREATED" | "ACCEPTED" | "NO_CONTENT" | "MULTIPLE_CHOICES" | "MOVED_PERMANENTLY" | "FOUND" | "SEE_OTHER" | "NOT_MODIFIED" | "TEMPORARY_REDIRECT" | "BAD_REQUEST" | "UNAUTHORIZED" | "PAYMENT_REQUIRED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "NOT_ACCEPTABLE" | "PROXY_AUTHENTICATION_REQUIRED" | "UNPROCESSABLE_ENTITY" | "INTERNAL_SERVER_ERROR" | "NOT_IMPLEMENTED" | "BAD_GATEWAY" | "SERVICE_UNAVAILABLE" | "HTTP_VERSION_NOT_SUPPORTED">;
|
|
35
|
-
/**
|
|
36
|
-
* Defines the errors used in AuraStack Router. Includes HTTP status code and
|
|
37
|
-
* status text.
|
|
38
|
-
* @deprecated Use RouterError instead
|
|
39
|
-
*/
|
|
40
|
-
declare class AuraStackRouterError extends Error {
|
|
41
|
-
/**
|
|
42
|
-
* The HTTP status code associated with the error.
|
|
43
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status
|
|
44
|
-
* @example
|
|
45
|
-
* NOT_FOUND: 404
|
|
46
|
-
* METHOD_NOT_ALLOWED: 405
|
|
47
|
-
* INTERNAL_SERVER_ERROR: 500
|
|
48
|
-
*/
|
|
49
|
-
readonly status: number;
|
|
50
|
-
/**
|
|
51
|
-
* The HTTP status text associated with the status code of the error.
|
|
52
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status
|
|
53
|
-
* @example
|
|
54
|
-
* NOT_FOUND: NOT_FOUND
|
|
55
|
-
* METHOD_NOT_ALLOWED: METHOD_NOT_ALLOWED
|
|
56
|
-
* INTERNAL_SERVER_ERROR: INTERNAL_SERVER_ERROR
|
|
57
|
-
*/
|
|
58
|
-
readonly statusText: StatusCode;
|
|
59
|
-
constructor(type: StatusCode, message: string, name?: string);
|
|
60
|
-
}
|
|
61
|
-
declare class RouterError extends AuraStackRouterError {
|
|
62
|
-
constructor(type: StatusCode, message: string, name?: string);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export { AuraStackRouterError, RouterError, statusCode, statusText };
|