@aura-stack/router 0.2.0 → 0.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 +2 -2
- package/dist/assert.cjs +61 -3
- package/dist/assert.d.ts +21 -1
- package/dist/assert.js +8 -3
- package/dist/chunk-6PZEXNTS.js +31 -0
- package/dist/chunk-CFAIW6YL.js +41 -0
- package/dist/chunk-CL5D7UJU.js +149 -0
- package/dist/{chunk-RFYOPPMW.js → chunk-GJC3ODME.js} +15 -6
- package/dist/{chunk-JRJKKBSH.js → chunk-JNMXLKDG.js} +12 -2
- package/dist/chunk-PT4GU6PH.js +78 -0
- package/dist/context.cjs +50 -47
- package/dist/context.d.ts +6 -5
- package/dist/context.js +3 -4
- package/dist/endpoint.cjs +29 -29
- package/dist/endpoint.d.ts +17 -16
- package/dist/endpoint.js +5 -7
- package/dist/error.cjs +19 -7
- package/dist/error.d.ts +28 -3
- package/dist/error.js +9 -3
- package/dist/index.cjs +218 -130
- package/dist/index.d.ts +3 -1
- package/dist/index.js +19 -9
- package/dist/middlewares.cjs +23 -17
- package/dist/middlewares.d.ts +4 -3
- package/dist/middlewares.js +2 -2
- package/dist/router.cjs +206 -118
- package/dist/router.d.ts +24 -2
- package/dist/router.js +13 -8
- package/dist/types.d.ts +91 -13
- package/package.json +32 -13
- package/dist/assert.d.cts +0 -32
- package/dist/chunk-DR4C6QTF.js +0 -72
- package/dist/chunk-O6SY753N.js +0 -41
- package/dist/chunk-OXDCFAMF.js +0 -78
- package/dist/chunk-YUX3YHXF.js +0 -36
- package/dist/context.d.cts +0 -84
- package/dist/endpoint.d.cts +0 -59
- package/dist/error.d.cts +0 -40
- package/dist/index.d.cts +0 -4
- package/dist/middlewares.d.cts +0 -22
- package/dist/router.d.cts +0 -15
- package/dist/types.d.cts +0 -134
package/dist/index.cjs
CHANGED
|
@@ -20,29 +20,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
RouterError: () => RouterError,
|
|
23
24
|
createEndpoint: () => createEndpoint,
|
|
24
25
|
createEndpointConfig: () => createEndpointConfig,
|
|
25
|
-
createRouter: () => createRouter
|
|
26
|
+
createRouter: () => createRouter,
|
|
27
|
+
isRouterError: () => isRouterError,
|
|
28
|
+
statusCode: () => statusCode,
|
|
29
|
+
statusText: () => statusText
|
|
26
30
|
});
|
|
27
31
|
module.exports = __toCommonJS(index_exports);
|
|
28
32
|
|
|
29
|
-
// src/assert.ts
|
|
30
|
-
var supportedMethods = /* @__PURE__ */ new Set(["GET", "POST", "DELETE", "PUT", "PATCH"]);
|
|
31
|
-
var supportedBodyMethods = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH"]);
|
|
32
|
-
var isSupportedMethod = (method) => {
|
|
33
|
-
return supportedMethods.has(method);
|
|
34
|
-
};
|
|
35
|
-
var isSupportedBodyMethod = (method) => {
|
|
36
|
-
return supportedBodyMethods.has(method);
|
|
37
|
-
};
|
|
38
|
-
var isValidRoute = (route) => {
|
|
39
|
-
const routePattern = /^\/[a-zA-Z0-9/_:-]*$/;
|
|
40
|
-
return routePattern.test(route);
|
|
41
|
-
};
|
|
42
|
-
var isValidHandler = (handler) => {
|
|
43
|
-
return typeof handler === "function";
|
|
44
|
-
};
|
|
45
|
-
|
|
46
33
|
// src/error.ts
|
|
47
34
|
var statusCode = {
|
|
48
35
|
OK: 200,
|
|
@@ -70,35 +57,57 @@ var statusCode = {
|
|
|
70
57
|
SERVICE_UNAVAILABLE: 503,
|
|
71
58
|
HTTP_VERSION_NOT_SUPPORTED: 505
|
|
72
59
|
};
|
|
73
|
-
var statusText = Object.
|
|
74
|
-
(previous,
|
|
75
|
-
return { ...previous, [
|
|
60
|
+
var statusText = Object.keys(statusCode).reduce(
|
|
61
|
+
(previous, status) => {
|
|
62
|
+
return { ...previous, [status]: status };
|
|
76
63
|
},
|
|
77
64
|
{}
|
|
78
65
|
);
|
|
79
66
|
var AuraStackRouterError = class extends Error {
|
|
80
67
|
constructor(type, message, name) {
|
|
81
68
|
super(message);
|
|
82
|
-
this.name = name ?? "
|
|
69
|
+
this.name = name ?? "RouterError";
|
|
83
70
|
this.status = statusCode[type];
|
|
84
|
-
this.statusText = statusText[
|
|
71
|
+
this.statusText = statusText[type];
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
var RouterError = class extends AuraStackRouterError {
|
|
75
|
+
constructor(type, message, name) {
|
|
76
|
+
super(type, message, name);
|
|
77
|
+
this.name = name ?? "RouterError";
|
|
85
78
|
}
|
|
86
79
|
};
|
|
87
80
|
|
|
88
|
-
// src/
|
|
89
|
-
var
|
|
90
|
-
|
|
91
|
-
|
|
81
|
+
// src/assert.ts
|
|
82
|
+
var supportedMethods = /* @__PURE__ */ new Set(["GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD", "TRACE", "CONNECT"]);
|
|
83
|
+
var supportedBodyMethods = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH"]);
|
|
84
|
+
var isSupportedMethod = (method) => {
|
|
85
|
+
return supportedMethods.has(method);
|
|
86
|
+
};
|
|
87
|
+
var isSupportedBodyMethod = (method) => {
|
|
88
|
+
return supportedBodyMethods.has(method);
|
|
92
89
|
};
|
|
90
|
+
var isValidRoute = (route) => {
|
|
91
|
+
const routePattern = /^\/[a-zA-Z0-9/_:-]*$/;
|
|
92
|
+
return routePattern.test(route);
|
|
93
|
+
};
|
|
94
|
+
var isValidHandler = (handler) => {
|
|
95
|
+
return typeof handler === "function";
|
|
96
|
+
};
|
|
97
|
+
var isRouterError = (error) => {
|
|
98
|
+
return error instanceof RouterError;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// src/endpoint.ts
|
|
93
102
|
var createEndpoint = (method, route, handler, config = {}) => {
|
|
94
103
|
if (!isSupportedMethod(method)) {
|
|
95
|
-
throw new
|
|
104
|
+
throw new RouterError("METHOD_NOT_ALLOWED", `Unsupported HTTP method: ${method}`);
|
|
96
105
|
}
|
|
97
106
|
if (!isValidRoute(route)) {
|
|
98
|
-
throw new
|
|
107
|
+
throw new RouterError("BAD_REQUEST", `Invalid route format: ${route}`);
|
|
99
108
|
}
|
|
100
109
|
if (!isValidHandler(handler)) {
|
|
101
|
-
throw new
|
|
110
|
+
throw new RouterError("BAD_REQUEST", "Handler must be a function");
|
|
102
111
|
}
|
|
103
112
|
return { method, route, handler, config };
|
|
104
113
|
};
|
|
@@ -107,29 +116,56 @@ function createEndpointConfig(...args) {
|
|
|
107
116
|
return args[0];
|
|
108
117
|
}
|
|
109
118
|
|
|
119
|
+
// src/middlewares.ts
|
|
120
|
+
var executeGlobalMiddlewares = async (context, middlewares) => {
|
|
121
|
+
if (!middlewares) return context;
|
|
122
|
+
for (const middleware of middlewares) {
|
|
123
|
+
if (typeof middleware !== "function") {
|
|
124
|
+
throw new RouterError("BAD_REQUEST", "Global middlewares must be functions");
|
|
125
|
+
}
|
|
126
|
+
const executed = await middleware(context);
|
|
127
|
+
if (executed instanceof Response) {
|
|
128
|
+
return executed;
|
|
129
|
+
}
|
|
130
|
+
context = executed;
|
|
131
|
+
}
|
|
132
|
+
if (!context || !(context.request instanceof Request)) {
|
|
133
|
+
throw new RouterError("BAD_REQUEST", "Global middleware must return a Request or Response object");
|
|
134
|
+
}
|
|
135
|
+
return context;
|
|
136
|
+
};
|
|
137
|
+
var executeMiddlewares = async (context, middlewares = []) => {
|
|
138
|
+
try {
|
|
139
|
+
let ctx = context;
|
|
140
|
+
for (const middleware of middlewares) {
|
|
141
|
+
if (typeof middleware !== "function") {
|
|
142
|
+
throw new RouterError("BAD_REQUEST", "Middleware must be a function");
|
|
143
|
+
}
|
|
144
|
+
ctx = await middleware(ctx);
|
|
145
|
+
}
|
|
146
|
+
return ctx;
|
|
147
|
+
} catch {
|
|
148
|
+
throw new RouterError("BAD_REQUEST", "Handler threw an error");
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
110
152
|
// src/context.ts
|
|
111
|
-
var getRouteParams = (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
153
|
+
var getRouteParams = (params, config) => {
|
|
154
|
+
if (config.schemas?.params) {
|
|
155
|
+
const parsed = config.schemas.params.safeParse(params);
|
|
156
|
+
if (!parsed.success) {
|
|
157
|
+
throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid route parameters");
|
|
158
|
+
}
|
|
159
|
+
return parsed.data;
|
|
115
160
|
}
|
|
116
|
-
|
|
117
|
-
if (!params) return {};
|
|
118
|
-
const values = routeRegex.exec(path)?.slice(1);
|
|
119
|
-
return params.reduce(
|
|
120
|
-
(previous, now, idx) => ({
|
|
121
|
-
...previous,
|
|
122
|
-
[now]: decodeURIComponent(values?.[idx] ?? "")
|
|
123
|
-
}),
|
|
124
|
-
{}
|
|
125
|
-
);
|
|
161
|
+
return params;
|
|
126
162
|
};
|
|
127
163
|
var getSearchParams = (url, config) => {
|
|
128
164
|
const route = new URL(url);
|
|
129
165
|
if (config.schemas?.searchParams) {
|
|
130
166
|
const parsed = config.schemas.searchParams.safeParse(Object.fromEntries(route.searchParams.entries()));
|
|
131
167
|
if (!parsed.success) {
|
|
132
|
-
throw new
|
|
168
|
+
throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid search parameters");
|
|
133
169
|
}
|
|
134
170
|
return parsed.data;
|
|
135
171
|
}
|
|
@@ -140,122 +176,174 @@ var getHeaders = (request) => {
|
|
|
140
176
|
};
|
|
141
177
|
var getBody = async (request, config) => {
|
|
142
178
|
if (!isSupportedBodyMethod(request.method)) {
|
|
143
|
-
return
|
|
179
|
+
return null;
|
|
144
180
|
}
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
181
|
+
const clone = request.clone();
|
|
182
|
+
const contentType = clone.headers.get("Content-Type") ?? "";
|
|
183
|
+
if (contentType.includes("application/json") || config.schemas?.body) {
|
|
184
|
+
const json = await clone.json();
|
|
148
185
|
if (config.schemas?.body) {
|
|
149
186
|
const parsed = config.schemas.body.safeParse(json);
|
|
150
187
|
if (!parsed.success) {
|
|
151
|
-
throw new
|
|
188
|
+
throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid request body");
|
|
152
189
|
}
|
|
153
190
|
return parsed.data;
|
|
154
191
|
}
|
|
155
192
|
return json;
|
|
156
193
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
194
|
+
try {
|
|
195
|
+
if (createContentTypeRegex(["application/x-www-form-urlencoded", "multipart/form-data"], contentType)) {
|
|
196
|
+
return await clone.formData();
|
|
197
|
+
}
|
|
198
|
+
if (createContentTypeRegex(["text/", "application/xml"], contentType)) {
|
|
199
|
+
return await clone.text();
|
|
200
|
+
}
|
|
201
|
+
if (createContentTypeRegex(["application/octet-stream"], contentType)) {
|
|
202
|
+
return await clone.arrayBuffer();
|
|
203
|
+
}
|
|
204
|
+
if (createContentTypeRegex(["image/", "video/", "audio/", "application/pdf"], contentType)) {
|
|
205
|
+
return await clone.blob();
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
} catch {
|
|
209
|
+
throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid request body, the content-type does not match the body format");
|
|
162
210
|
}
|
|
163
|
-
|
|
164
|
-
|
|
211
|
+
};
|
|
212
|
+
var createContentTypeRegex = (contentTypes, contenType) => {
|
|
213
|
+
const regex = new RegExp(`${contentTypes.join("|")}`);
|
|
214
|
+
return regex.test(contenType);
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// src/router.ts
|
|
218
|
+
var createNode = () => ({
|
|
219
|
+
statics: /* @__PURE__ */ new Map(),
|
|
220
|
+
endpoints: /* @__PURE__ */ new Map()
|
|
221
|
+
});
|
|
222
|
+
var insert = (root, endpoint) => {
|
|
223
|
+
if (!root || !endpoint) return;
|
|
224
|
+
let node = root;
|
|
225
|
+
const segments = endpoint.route === "/" ? [] : endpoint.route.split("/").filter(Boolean);
|
|
226
|
+
for (const segment of segments) {
|
|
227
|
+
if (segment.startsWith(":")) {
|
|
228
|
+
const name = segment.slice(1);
|
|
229
|
+
if (!node.param) {
|
|
230
|
+
node.param = { name, node: createNode() };
|
|
231
|
+
} else if (node.param.name !== name) {
|
|
232
|
+
throw new RouterError(
|
|
233
|
+
"BAD_REQUEST",
|
|
234
|
+
`Conflicting in the route by the dynamic segment "${node.param.name}" and "${name}"`
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
node = node.param.node;
|
|
238
|
+
} else {
|
|
239
|
+
if (!node.statics.has(segment)) {
|
|
240
|
+
node.statics.set(segment, createNode());
|
|
241
|
+
}
|
|
242
|
+
node = node.statics.get(segment);
|
|
243
|
+
}
|
|
165
244
|
}
|
|
166
|
-
if (
|
|
167
|
-
|
|
245
|
+
if (node.endpoints.has(endpoint.method)) {
|
|
246
|
+
throw new RouterError("BAD_REQUEST", `Duplicate endpoint for ${endpoint?.method} ${endpoint?.route}`);
|
|
168
247
|
}
|
|
169
|
-
|
|
248
|
+
node.endpoints.set(endpoint.method, endpoint);
|
|
170
249
|
};
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
for (const
|
|
176
|
-
if (
|
|
177
|
-
|
|
250
|
+
var search = (method, root, pathname) => {
|
|
251
|
+
let node = root;
|
|
252
|
+
const params = {};
|
|
253
|
+
const segments = pathname === "/" ? [] : pathname.split("/").filter(Boolean);
|
|
254
|
+
for (const segment of segments) {
|
|
255
|
+
if (node?.statics.has(segment)) {
|
|
256
|
+
node = node.statics.get(segment);
|
|
257
|
+
} else if (node?.param) {
|
|
258
|
+
params[node.param.name] = decodeURIComponent(segment);
|
|
259
|
+
node = node.param.node;
|
|
260
|
+
} else {
|
|
261
|
+
throw new RouterError("NOT_FOUND", `No route found for path: ${pathname}`);
|
|
178
262
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
263
|
+
}
|
|
264
|
+
if (!node.endpoints.has(method)) {
|
|
265
|
+
throw new RouterError("NOT_FOUND", `No route found for path: ${pathname}`);
|
|
266
|
+
}
|
|
267
|
+
return { endpoint: node.endpoints.get(method), params };
|
|
268
|
+
};
|
|
269
|
+
var handleError = async (error, request, config) => {
|
|
270
|
+
if (config.onError) {
|
|
271
|
+
try {
|
|
272
|
+
const response = await config.onError(error, request);
|
|
273
|
+
return response;
|
|
274
|
+
} catch {
|
|
275
|
+
return Response.json(
|
|
276
|
+
{ message: "A critical failure occurred during error handling" },
|
|
277
|
+
{ status: 500, statusText: statusText.INTERNAL_SERVER_ERROR }
|
|
278
|
+
);
|
|
182
279
|
}
|
|
183
|
-
request = executed;
|
|
184
280
|
}
|
|
185
|
-
if (
|
|
186
|
-
|
|
281
|
+
if (isRouterError(error)) {
|
|
282
|
+
const { message, status, statusText: statusText2 } = error;
|
|
283
|
+
return Response.json({ message }, { status, statusText: statusText2 });
|
|
187
284
|
}
|
|
188
|
-
return
|
|
285
|
+
return Response.json({ message: "Internal Server Error" }, { status: 500, statusText: statusText.INTERNAL_SERVER_ERROR });
|
|
189
286
|
};
|
|
190
|
-
var
|
|
287
|
+
var handleRequest = async (method, request, config, root) => {
|
|
191
288
|
try {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if (typeof middleware !== "function") {
|
|
195
|
-
throw new AuraStackRouterError("BAD_REQUEST", "Middleware must be a function");
|
|
196
|
-
}
|
|
197
|
-
ctx = await middleware(request, ctx);
|
|
289
|
+
if (!isSupportedMethod(request.method)) {
|
|
290
|
+
throw new RouterError("METHOD_NOT_ALLOWED", `The HTTP method '${request.method}' is not supported`);
|
|
198
291
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
292
|
+
const globalContext = { request, context: config.context ?? {} };
|
|
293
|
+
const globalRequestContext = await executeGlobalMiddlewares(globalContext, config.middlewares);
|
|
294
|
+
if (globalRequestContext instanceof Response) return globalRequestContext;
|
|
295
|
+
const url = new URL(globalRequestContext.request.url);
|
|
296
|
+
const pathnameWithBase = url.pathname;
|
|
297
|
+
if (globalRequestContext.request.method !== method) {
|
|
298
|
+
throw new RouterError("METHOD_NOT_ALLOWED", `The HTTP method '${globalRequestContext.request.method}' is not allowed`);
|
|
299
|
+
}
|
|
300
|
+
const { endpoint, params } = search(method, root, pathnameWithBase);
|
|
301
|
+
if (endpoint.method !== globalRequestContext.request.method) {
|
|
302
|
+
throw new RouterError("METHOD_NOT_ALLOWED", `The HTTP method '${globalRequestContext.request.method}' is not allowed`);
|
|
303
|
+
}
|
|
304
|
+
const dynamicParams = getRouteParams(params, endpoint.config);
|
|
305
|
+
const body = await getBody(globalRequestContext.request, endpoint.config);
|
|
306
|
+
const searchParams = getSearchParams(globalRequestContext.request.url, endpoint.config);
|
|
307
|
+
const headers = getHeaders(globalRequestContext.request);
|
|
308
|
+
let context = {
|
|
309
|
+
params: dynamicParams,
|
|
310
|
+
searchParams,
|
|
311
|
+
headers,
|
|
312
|
+
body,
|
|
313
|
+
request: globalRequestContext.request,
|
|
314
|
+
url,
|
|
315
|
+
method: globalRequestContext.request.method,
|
|
316
|
+
route: endpoint.route,
|
|
317
|
+
context: config.context ?? {}
|
|
318
|
+
};
|
|
319
|
+
context = await executeMiddlewares(context, endpoint.config.middlewares);
|
|
320
|
+
const response = await endpoint.handler(context);
|
|
321
|
+
return response;
|
|
322
|
+
} catch (error) {
|
|
323
|
+
return handleError(error, request, config);
|
|
202
324
|
}
|
|
203
325
|
};
|
|
204
|
-
|
|
205
|
-
// src/router.ts
|
|
206
326
|
var createRouter = (endpoints, config = {}) => {
|
|
327
|
+
const root = createNode();
|
|
207
328
|
const server = {};
|
|
208
|
-
const
|
|
329
|
+
const methods = /* @__PURE__ */ new Set();
|
|
209
330
|
for (const endpoint of endpoints) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
groups.get(endpoint.method)?.push(endpoint);
|
|
331
|
+
const withBasePath = config.basePath ? `${config.basePath}${endpoint.route}` : endpoint.route;
|
|
332
|
+
insert(root, { ...endpoint, route: withBasePath });
|
|
333
|
+
methods.add(endpoint.method);
|
|
214
334
|
}
|
|
215
|
-
for (const method of
|
|
216
|
-
server[method] =
|
|
217
|
-
try {
|
|
218
|
-
const globalRequest = await executeGlobalMiddlewares(request, config.middlewares);
|
|
219
|
-
if (globalRequest instanceof Response) {
|
|
220
|
-
return globalRequest;
|
|
221
|
-
}
|
|
222
|
-
const url = new URL(globalRequest.url);
|
|
223
|
-
const pathname = url.pathname;
|
|
224
|
-
const endpoint = groups.get(method)?.find((endpoint2) => {
|
|
225
|
-
const withBasePath = config.basePath ? `${config.basePath}${endpoint2.route}` : endpoint2.route;
|
|
226
|
-
const regex = createRoutePattern(withBasePath);
|
|
227
|
-
return regex.test(pathname);
|
|
228
|
-
});
|
|
229
|
-
if (endpoint) {
|
|
230
|
-
const withBasePath = config.basePath ? `${config.basePath}${endpoint.route}` : endpoint.route;
|
|
231
|
-
const body = await getBody(globalRequest, endpoint.config);
|
|
232
|
-
const params = getRouteParams(withBasePath, pathname);
|
|
233
|
-
const searchParams = getSearchParams(globalRequest.url, endpoint.config);
|
|
234
|
-
const headers = getHeaders(globalRequest);
|
|
235
|
-
const context = {
|
|
236
|
-
params,
|
|
237
|
-
searchParams,
|
|
238
|
-
headers,
|
|
239
|
-
body
|
|
240
|
-
};
|
|
241
|
-
await executeMiddlewares(globalRequest, context, endpoint.config.middlewares);
|
|
242
|
-
return endpoint.handler(globalRequest, context);
|
|
243
|
-
}
|
|
244
|
-
return Response.json({ message: "Not Found" }, { status: 404 });
|
|
245
|
-
} catch (error) {
|
|
246
|
-
if (error instanceof AuraStackRouterError) {
|
|
247
|
-
const { message, status, statusText: statusText2 } = error;
|
|
248
|
-
return Response.json({ message }, { status, statusText: statusText2 });
|
|
249
|
-
}
|
|
250
|
-
return Response.json({ message: "Internal Server Error" }, { status: 500 });
|
|
251
|
-
}
|
|
252
|
-
};
|
|
335
|
+
for (const method of methods) {
|
|
336
|
+
server[method] = (request) => handleRequest(method, request, config, root);
|
|
253
337
|
}
|
|
254
338
|
return server;
|
|
255
339
|
};
|
|
256
340
|
// Annotate the CommonJS export names for ESM import in node:
|
|
257
341
|
0 && (module.exports = {
|
|
342
|
+
RouterError,
|
|
258
343
|
createEndpoint,
|
|
259
344
|
createEndpointConfig,
|
|
260
|
-
createRouter
|
|
345
|
+
createRouter,
|
|
346
|
+
isRouterError,
|
|
347
|
+
statusCode,
|
|
348
|
+
statusText
|
|
261
349
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { createEndpoint, createEndpointConfig } from './endpoint.js';
|
|
2
2
|
export { createRouter } from './router.js';
|
|
3
|
-
export {
|
|
3
|
+
export { isRouterError } from './assert.js';
|
|
4
|
+
export { RouterError, statusCode, statusText } from './error.js';
|
|
5
|
+
export { ContentType, ContextBody, ContextParams, ContextSearchParams, EndpointConfig, EndpointSchemas, GetHttpHandlers, GetRouteParams, GlobalContext, GlobalCtx, GlobalMiddleware, GlobalMiddlewareContext, HTTPMethod, InferMethod, MiddlewareFunction, Prettify, RequestContext, RouteEndpoint, RouteHandler, RoutePattern, RouterConfig } from './types.js';
|
|
4
6
|
import 'zod';
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createRouter
|
|
3
|
-
} from "./chunk-DR4C6QTF.js";
|
|
4
|
-
import "./chunk-OXDCFAMF.js";
|
|
5
1
|
import {
|
|
6
2
|
createEndpoint,
|
|
7
3
|
createEndpointConfig
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
} from "./chunk-6PZEXNTS.js";
|
|
5
|
+
import {
|
|
6
|
+
createRouter
|
|
7
|
+
} from "./chunk-CL5D7UJU.js";
|
|
8
|
+
import "./chunk-PT4GU6PH.js";
|
|
9
|
+
import {
|
|
10
|
+
isRouterError
|
|
11
|
+
} from "./chunk-JNMXLKDG.js";
|
|
12
|
+
import "./chunk-CFAIW6YL.js";
|
|
13
|
+
import {
|
|
14
|
+
RouterError,
|
|
15
|
+
statusCode,
|
|
16
|
+
statusText
|
|
17
|
+
} from "./chunk-GJC3ODME.js";
|
|
12
18
|
export {
|
|
19
|
+
RouterError,
|
|
13
20
|
createEndpoint,
|
|
14
21
|
createEndpointConfig,
|
|
15
|
-
createRouter
|
|
22
|
+
createRouter,
|
|
23
|
+
isRouterError,
|
|
24
|
+
statusCode,
|
|
25
|
+
statusText
|
|
16
26
|
};
|
package/dist/middlewares.cjs
CHANGED
|
@@ -52,51 +52,57 @@ var statusCode = {
|
|
|
52
52
|
SERVICE_UNAVAILABLE: 503,
|
|
53
53
|
HTTP_VERSION_NOT_SUPPORTED: 505
|
|
54
54
|
};
|
|
55
|
-
var statusText = Object.
|
|
56
|
-
(previous,
|
|
57
|
-
return { ...previous, [
|
|
55
|
+
var statusText = Object.keys(statusCode).reduce(
|
|
56
|
+
(previous, status) => {
|
|
57
|
+
return { ...previous, [status]: status };
|
|
58
58
|
},
|
|
59
59
|
{}
|
|
60
60
|
);
|
|
61
61
|
var AuraStackRouterError = class extends Error {
|
|
62
62
|
constructor(type, message, name) {
|
|
63
63
|
super(message);
|
|
64
|
-
this.name = name ?? "
|
|
64
|
+
this.name = name ?? "RouterError";
|
|
65
65
|
this.status = statusCode[type];
|
|
66
|
-
this.statusText = statusText[
|
|
66
|
+
this.statusText = statusText[type];
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
var RouterError = class extends AuraStackRouterError {
|
|
70
|
+
constructor(type, message, name) {
|
|
71
|
+
super(type, message, name);
|
|
72
|
+
this.name = name ?? "RouterError";
|
|
67
73
|
}
|
|
68
74
|
};
|
|
69
75
|
|
|
70
76
|
// src/middlewares.ts
|
|
71
|
-
var executeGlobalMiddlewares = async (
|
|
72
|
-
if (!middlewares) return
|
|
77
|
+
var executeGlobalMiddlewares = async (context, middlewares) => {
|
|
78
|
+
if (!middlewares) return context;
|
|
73
79
|
for (const middleware of middlewares) {
|
|
74
80
|
if (typeof middleware !== "function") {
|
|
75
|
-
throw new
|
|
81
|
+
throw new RouterError("BAD_REQUEST", "Global middlewares must be functions");
|
|
76
82
|
}
|
|
77
|
-
const executed = await middleware(
|
|
83
|
+
const executed = await middleware(context);
|
|
78
84
|
if (executed instanceof Response) {
|
|
79
85
|
return executed;
|
|
80
86
|
}
|
|
81
|
-
|
|
87
|
+
context = executed;
|
|
82
88
|
}
|
|
83
|
-
if (!
|
|
84
|
-
throw new
|
|
89
|
+
if (!context || !(context.request instanceof Request)) {
|
|
90
|
+
throw new RouterError("BAD_REQUEST", "Global middleware must return a Request or Response object");
|
|
85
91
|
}
|
|
86
|
-
return
|
|
92
|
+
return context;
|
|
87
93
|
};
|
|
88
|
-
var executeMiddlewares = async (
|
|
94
|
+
var executeMiddlewares = async (context, middlewares = []) => {
|
|
89
95
|
try {
|
|
90
96
|
let ctx = context;
|
|
91
97
|
for (const middleware of middlewares) {
|
|
92
98
|
if (typeof middleware !== "function") {
|
|
93
|
-
throw new
|
|
99
|
+
throw new RouterError("BAD_REQUEST", "Middleware must be a function");
|
|
94
100
|
}
|
|
95
|
-
ctx = await middleware(
|
|
101
|
+
ctx = await middleware(ctx);
|
|
96
102
|
}
|
|
97
103
|
return ctx;
|
|
98
104
|
} catch {
|
|
99
|
-
throw new
|
|
105
|
+
throw new RouterError("BAD_REQUEST", "Handler threw an error");
|
|
100
106
|
}
|
|
101
107
|
};
|
|
102
108
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/middlewares.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { RouterConfig, EndpointConfig, RequestContext, MiddlewareFunction } from './types.js';
|
|
1
|
+
import { GlobalMiddlewareContext, RouterConfig, EndpointConfig, RequestContext, MiddlewareFunction } from './types.js';
|
|
2
2
|
import 'zod';
|
|
3
|
+
import './error.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Executes the middlewares in sequence, passing the request to each middleware.
|
|
@@ -8,7 +9,7 @@ import 'zod';
|
|
|
8
9
|
* @param middlewares - Array of global middleware functions to be executed
|
|
9
10
|
* @returns - The modified request after all middlewares have been executed
|
|
10
11
|
*/
|
|
11
|
-
declare const executeGlobalMiddlewares: (
|
|
12
|
+
declare const executeGlobalMiddlewares: (context: GlobalMiddlewareContext, middlewares: RouterConfig["middlewares"]) => Promise<GlobalMiddlewareContext | Response>;
|
|
12
13
|
/**
|
|
13
14
|
* Executes middlewares in sequence, passing the request and context to each middleware.
|
|
14
15
|
*
|
|
@@ -17,6 +18,6 @@ declare const executeGlobalMiddlewares: (request: Request, middlewares: RouterCo
|
|
|
17
18
|
* @param middlewares - Array of middleware functions to be executed
|
|
18
19
|
* @returns The modified context after all middlewares have been executed
|
|
19
20
|
*/
|
|
20
|
-
declare const executeMiddlewares: <const RouteParams extends Record<string, string>, const Config extends EndpointConfig>(
|
|
21
|
+
declare const executeMiddlewares: <const RouteParams extends Record<string, string>, const Config extends EndpointConfig>(context: RequestContext<RouteParams, Config>, middlewares?: MiddlewareFunction<RouteParams, Config>[]) => Promise<RequestContext<RouteParams, Config>>;
|
|
21
22
|
|
|
22
23
|
export { executeGlobalMiddlewares, executeMiddlewares };
|
package/dist/middlewares.js
CHANGED