@aura-stack/router 0.1.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/LICENSE +21 -0
- package/README.md +128 -0
- package/dist/assert.cjs +50 -0
- package/dist/assert.d.cts +32 -0
- package/dist/assert.d.ts +32 -0
- package/dist/assert.js +12 -0
- package/dist/chunk-6UBPSXKR.js +36 -0
- package/dist/chunk-ENOBC3XN.js +23 -0
- package/dist/chunk-NNCUFWPI.js +78 -0
- package/dist/chunk-RFYOPPMW.js +45 -0
- package/dist/chunk-RVJ2F7OL.js +41 -0
- package/dist/chunk-VBI7H3AK.js +75 -0
- package/dist/context.cjs +151 -0
- package/dist/context.d.cts +84 -0
- package/dist/context.d.ts +84 -0
- package/dist/context.js +15 -0
- package/dist/endpoint.cjs +110 -0
- package/dist/endpoint.d.cts +59 -0
- package/dist/endpoint.d.ts +59 -0
- package/dist/endpoint.js +12 -0
- package/dist/error.cjs +69 -0
- package/dist/error.d.cts +40 -0
- package/dist/error.d.ts +40 -0
- package/dist/error.js +6 -0
- package/dist/index.cjs +264 -0
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +16 -0
- package/dist/middleware.cjs +106 -0
- package/dist/middleware.d.cts +22 -0
- package/dist/middleware.d.ts +22 -0
- package/dist/middleware.js +9 -0
- package/dist/router.cjs +233 -0
- package/dist/router.d.cts +15 -0
- package/dist/router.d.ts +15 -0
- package/dist/router.js +11 -0
- package/dist/types.cjs +18 -0
- package/dist/types.d.cts +134 -0
- package/dist/types.d.ts +134 -0
- package/dist/types.js +0 -0
- package/package.json +55 -0
package/dist/context.cjs
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/context.ts
|
|
21
|
+
var context_exports = {};
|
|
22
|
+
__export(context_exports, {
|
|
23
|
+
getBody: () => getBody,
|
|
24
|
+
getHeaders: () => getHeaders,
|
|
25
|
+
getRouteParams: () => getRouteParams,
|
|
26
|
+
getSearchParams: () => getSearchParams
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(context_exports);
|
|
29
|
+
|
|
30
|
+
// src/assert.ts
|
|
31
|
+
var supportedBodyMethods = ["POST", "PUT", "PATCH"];
|
|
32
|
+
var isSupportedBodyMethod = (method) => {
|
|
33
|
+
return supportedBodyMethods.includes(method);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// src/error.ts
|
|
37
|
+
var statusCode = {
|
|
38
|
+
OK: 200,
|
|
39
|
+
CREATED: 201,
|
|
40
|
+
ACCEPTED: 202,
|
|
41
|
+
NO_CONTENT: 204,
|
|
42
|
+
MULTIPLE_CHOICES: 300,
|
|
43
|
+
MOVED_PERMANENTLY: 301,
|
|
44
|
+
FOUND: 302,
|
|
45
|
+
SEE_OTHER: 303,
|
|
46
|
+
NOT_MODIFIED: 304,
|
|
47
|
+
TEMPORARY_REDIRECT: 307,
|
|
48
|
+
BAD_REQUEST: 400,
|
|
49
|
+
UNAUTHORIZED: 401,
|
|
50
|
+
PAYMENT_REQUIRED: 402,
|
|
51
|
+
FORBIDDEN: 403,
|
|
52
|
+
NOT_FOUND: 404,
|
|
53
|
+
METHOD_NOT_ALLOWED: 405,
|
|
54
|
+
NOT_ACCEPTABLE: 406,
|
|
55
|
+
PROXY_AUTHENTICATION_REQUIRED: 407,
|
|
56
|
+
UNPROCESSABLE_ENTITY: 422,
|
|
57
|
+
INTERNAL_SERVER_ERROR: 500,
|
|
58
|
+
NOT_IMPLEMENTED: 501,
|
|
59
|
+
BAD_GATEWAY: 502,
|
|
60
|
+
SERVICE_UNAVAILABLE: 503,
|
|
61
|
+
HTTP_VERSION_NOT_SUPPORTED: 505
|
|
62
|
+
};
|
|
63
|
+
var statusText = Object.entries(statusCode).reduce(
|
|
64
|
+
(previous, [status, code]) => {
|
|
65
|
+
return { ...previous, [code]: status };
|
|
66
|
+
},
|
|
67
|
+
{}
|
|
68
|
+
);
|
|
69
|
+
var AuraStackRouterError = class extends Error {
|
|
70
|
+
constructor(type, message, name) {
|
|
71
|
+
super(message);
|
|
72
|
+
this.name = name ?? "AuraStackRouterError";
|
|
73
|
+
this.status = statusCode[type];
|
|
74
|
+
this.statusText = statusText[this.status];
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// src/endpoint.ts
|
|
79
|
+
var createRoutePattern = (route) => {
|
|
80
|
+
const pattern = route.replace(/:[^/]+/g, "([^/]+)").replace(/\//g, "\\/");
|
|
81
|
+
return new RegExp(`^${pattern}$`);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// src/context.ts
|
|
85
|
+
var getRouteParams = (route, path) => {
|
|
86
|
+
const routeRegex = createRoutePattern(route);
|
|
87
|
+
if (!routeRegex.test(path)) {
|
|
88
|
+
throw new AuraStackRouterError("BAD_REQUEST", `Missing required route params for route: ${route}`);
|
|
89
|
+
}
|
|
90
|
+
const params = routeRegex.exec(route)?.slice(1).map((seg) => seg.replace(":", ""));
|
|
91
|
+
if (!params) return {};
|
|
92
|
+
const values = routeRegex.exec(path)?.slice(1);
|
|
93
|
+
return params.reduce(
|
|
94
|
+
(previous, now, idx) => ({
|
|
95
|
+
...previous,
|
|
96
|
+
[now]: decodeURIComponent(values?.[idx] ?? "")
|
|
97
|
+
}),
|
|
98
|
+
{}
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
var getSearchParams = (url, config) => {
|
|
102
|
+
const route = new URL(url);
|
|
103
|
+
if (config.schemas?.searchParams) {
|
|
104
|
+
const parsed = config.schemas.searchParams.safeParse(Object.fromEntries(route.searchParams.entries()));
|
|
105
|
+
if (!parsed.success) {
|
|
106
|
+
throw new AuraStackRouterError("UNPROCESSABLE_ENTITY", "Invalid search parameters");
|
|
107
|
+
}
|
|
108
|
+
return parsed.data;
|
|
109
|
+
}
|
|
110
|
+
return new URLSearchParams(route.searchParams.toString());
|
|
111
|
+
};
|
|
112
|
+
var getHeaders = (request) => {
|
|
113
|
+
return new Headers(request.headers);
|
|
114
|
+
};
|
|
115
|
+
var getBody = async (request, config) => {
|
|
116
|
+
if (!isSupportedBodyMethod(request.method)) {
|
|
117
|
+
return void 0;
|
|
118
|
+
}
|
|
119
|
+
const contentType = request.headers.get("Content-Type") ?? "";
|
|
120
|
+
if (contentType.includes("application/json")) {
|
|
121
|
+
const json = await request.json();
|
|
122
|
+
if (config.schemas?.body) {
|
|
123
|
+
const parsed = config.schemas.body.safeParse(json);
|
|
124
|
+
if (!parsed.success) {
|
|
125
|
+
throw new AuraStackRouterError("UNPROCESSABLE_ENTITY", "Invalid request body");
|
|
126
|
+
}
|
|
127
|
+
return parsed.data;
|
|
128
|
+
}
|
|
129
|
+
return json;
|
|
130
|
+
}
|
|
131
|
+
if (contentType.includes("application/x-www-form-urlencoded") || contentType.includes("multipart/form-data")) {
|
|
132
|
+
return await request.formData();
|
|
133
|
+
}
|
|
134
|
+
if (contentType.includes("text/")) {
|
|
135
|
+
return await request.text();
|
|
136
|
+
}
|
|
137
|
+
if (contentType.includes("application/octet-stream")) {
|
|
138
|
+
return await request.arrayBuffer();
|
|
139
|
+
}
|
|
140
|
+
if (contentType.includes("image/") || contentType.includes("video/") || contentType.includes("audio/")) {
|
|
141
|
+
return await request.blob();
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
};
|
|
145
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
146
|
+
0 && (module.exports = {
|
|
147
|
+
getBody,
|
|
148
|
+
getHeaders,
|
|
149
|
+
getRouteParams,
|
|
150
|
+
getSearchParams
|
|
151
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { RoutePattern, Params, EndpointConfig, ContextSearchParams } from './types.cjs';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Extracts route parameters from a given path using the specified route pattern.
|
|
6
|
+
*
|
|
7
|
+
* This function matches the provided path against the route pattern
|
|
8
|
+
* (e.g., "/users/:userId/posts/:postId") and returns an object mapping parameter
|
|
9
|
+
* names to their decoded values.
|
|
10
|
+
*
|
|
11
|
+
* @param route - The route pattern, typically defined in the endpoint configuration.
|
|
12
|
+
* @param path - The actual request path to extract parameters from.
|
|
13
|
+
* @returns An object containing the extracted route parameters as key-value pairs.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const route = "/users/:userId/posts/:postId";
|
|
17
|
+
* const path = "/users/123/posts/456";
|
|
18
|
+
*
|
|
19
|
+
* // Expected: { userId: "123", postId: "456" }
|
|
20
|
+
* const params = getRouteParams(route, path);
|
|
21
|
+
*/
|
|
22
|
+
declare const getRouteParams: <Route extends RoutePattern>(route: Route, path: string) => Params<Route>;
|
|
23
|
+
/**
|
|
24
|
+
* Extracts and validates search parameters from a given URL from the request.
|
|
25
|
+
*
|
|
26
|
+
* If a schema is provided in the endpoint configuration, the search parameters
|
|
27
|
+
* are validated against it using Zod and returned the parsed data. If validation
|
|
28
|
+
* fails, an error is thrown. Otherwise, a URLSearchParams object is returned.
|
|
29
|
+
*
|
|
30
|
+
* @param url - The actual request URL to extract search parameters from.
|
|
31
|
+
* @param config - Configuration object that may include a schema for validation.
|
|
32
|
+
* @returns Either a URLSearchParams object or a parsed object based on the provided schema.
|
|
33
|
+
* @example
|
|
34
|
+
* // With schema
|
|
35
|
+
* const url = "https://example.com/api?search=test&page=2";
|
|
36
|
+
* const config: EndpointConfig = {
|
|
37
|
+
* schemas: {
|
|
38
|
+
* searchParams: z.object({
|
|
39
|
+
* search: z.string(),
|
|
40
|
+
* page: z.number().optional(),
|
|
41
|
+
* }),
|
|
42
|
+
* },
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* // Expected: { search: "test", page: 2 }
|
|
46
|
+
* const searchParams = getSearchParams(url, config);
|
|
47
|
+
*
|
|
48
|
+
* // Without schema
|
|
49
|
+
* const url2 = "https://example.com/api?query=example";
|
|
50
|
+
*
|
|
51
|
+
* // Expected: URLSearchParams { 'query' => 'example' }
|
|
52
|
+
* const searchParams2 = getSearchParams(url2, {} as EndpointConfig);
|
|
53
|
+
*/
|
|
54
|
+
declare const getSearchParams: <Config extends EndpointConfig>(url: string, config: Config) => ContextSearchParams<Config["schemas"]>["searchParams"];
|
|
55
|
+
/**
|
|
56
|
+
* Extracts headers from the given Request object and returns them as a Headers instance.
|
|
57
|
+
*
|
|
58
|
+
* @param request - The Request object from which to extract headers.
|
|
59
|
+
* @returns A Headers instance containing all headers from the request.
|
|
60
|
+
* @example
|
|
61
|
+
* const request = new Request("https://example.com/api", {
|
|
62
|
+
* headers: {
|
|
63
|
+
* "Content-Type": "application/json",
|
|
64
|
+
* "Authorization": "Bearer token",
|
|
65
|
+
* },
|
|
66
|
+
* });
|
|
67
|
+
* const headers = getHeaders(request);
|
|
68
|
+
*/
|
|
69
|
+
declare const getHeaders: (request: Request) => Headers;
|
|
70
|
+
/**
|
|
71
|
+
* Extracts and parses the body of a Request object based on its Content-Type header.
|
|
72
|
+
*
|
|
73
|
+
* If a schema is provided in the endpoint configuration, the body is validated against
|
|
74
|
+
* it using Zod and returned the parsed data. If validation fails, an error is thrown.
|
|
75
|
+
*
|
|
76
|
+
* In some cases, the browser includes text/plain;charset=UTF-8 as the default Content-Type
|
|
77
|
+
*
|
|
78
|
+
* @param request - The Request object from which to extract the body.
|
|
79
|
+
* @param config - Configuration object that may include a schema for validation.
|
|
80
|
+
* @returns The parsed body of the request or an error if validation fails.
|
|
81
|
+
*/
|
|
82
|
+
declare const getBody: <Config extends EndpointConfig>(request: Request, config: Config) => Promise<any>;
|
|
83
|
+
|
|
84
|
+
export { getBody, getHeaders, getRouteParams, getSearchParams };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { RoutePattern, Params, EndpointConfig, ContextSearchParams } from './types.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Extracts route parameters from a given path using the specified route pattern.
|
|
6
|
+
*
|
|
7
|
+
* This function matches the provided path against the route pattern
|
|
8
|
+
* (e.g., "/users/:userId/posts/:postId") and returns an object mapping parameter
|
|
9
|
+
* names to their decoded values.
|
|
10
|
+
*
|
|
11
|
+
* @param route - The route pattern, typically defined in the endpoint configuration.
|
|
12
|
+
* @param path - The actual request path to extract parameters from.
|
|
13
|
+
* @returns An object containing the extracted route parameters as key-value pairs.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const route = "/users/:userId/posts/:postId";
|
|
17
|
+
* const path = "/users/123/posts/456";
|
|
18
|
+
*
|
|
19
|
+
* // Expected: { userId: "123", postId: "456" }
|
|
20
|
+
* const params = getRouteParams(route, path);
|
|
21
|
+
*/
|
|
22
|
+
declare const getRouteParams: <Route extends RoutePattern>(route: Route, path: string) => Params<Route>;
|
|
23
|
+
/**
|
|
24
|
+
* Extracts and validates search parameters from a given URL from the request.
|
|
25
|
+
*
|
|
26
|
+
* If a schema is provided in the endpoint configuration, the search parameters
|
|
27
|
+
* are validated against it using Zod and returned the parsed data. If validation
|
|
28
|
+
* fails, an error is thrown. Otherwise, a URLSearchParams object is returned.
|
|
29
|
+
*
|
|
30
|
+
* @param url - The actual request URL to extract search parameters from.
|
|
31
|
+
* @param config - Configuration object that may include a schema for validation.
|
|
32
|
+
* @returns Either a URLSearchParams object or a parsed object based on the provided schema.
|
|
33
|
+
* @example
|
|
34
|
+
* // With schema
|
|
35
|
+
* const url = "https://example.com/api?search=test&page=2";
|
|
36
|
+
* const config: EndpointConfig = {
|
|
37
|
+
* schemas: {
|
|
38
|
+
* searchParams: z.object({
|
|
39
|
+
* search: z.string(),
|
|
40
|
+
* page: z.number().optional(),
|
|
41
|
+
* }),
|
|
42
|
+
* },
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* // Expected: { search: "test", page: 2 }
|
|
46
|
+
* const searchParams = getSearchParams(url, config);
|
|
47
|
+
*
|
|
48
|
+
* // Without schema
|
|
49
|
+
* const url2 = "https://example.com/api?query=example";
|
|
50
|
+
*
|
|
51
|
+
* // Expected: URLSearchParams { 'query' => 'example' }
|
|
52
|
+
* const searchParams2 = getSearchParams(url2, {} as EndpointConfig);
|
|
53
|
+
*/
|
|
54
|
+
declare const getSearchParams: <Config extends EndpointConfig>(url: string, config: Config) => ContextSearchParams<Config["schemas"]>["searchParams"];
|
|
55
|
+
/**
|
|
56
|
+
* Extracts headers from the given Request object and returns them as a Headers instance.
|
|
57
|
+
*
|
|
58
|
+
* @param request - The Request object from which to extract headers.
|
|
59
|
+
* @returns A Headers instance containing all headers from the request.
|
|
60
|
+
* @example
|
|
61
|
+
* const request = new Request("https://example.com/api", {
|
|
62
|
+
* headers: {
|
|
63
|
+
* "Content-Type": "application/json",
|
|
64
|
+
* "Authorization": "Bearer token",
|
|
65
|
+
* },
|
|
66
|
+
* });
|
|
67
|
+
* const headers = getHeaders(request);
|
|
68
|
+
*/
|
|
69
|
+
declare const getHeaders: (request: Request) => Headers;
|
|
70
|
+
/**
|
|
71
|
+
* Extracts and parses the body of a Request object based on its Content-Type header.
|
|
72
|
+
*
|
|
73
|
+
* If a schema is provided in the endpoint configuration, the body is validated against
|
|
74
|
+
* it using Zod and returned the parsed data. If validation fails, an error is thrown.
|
|
75
|
+
*
|
|
76
|
+
* In some cases, the browser includes text/plain;charset=UTF-8 as the default Content-Type
|
|
77
|
+
*
|
|
78
|
+
* @param request - The Request object from which to extract the body.
|
|
79
|
+
* @param config - Configuration object that may include a schema for validation.
|
|
80
|
+
* @returns The parsed body of the request or an error if validation fails.
|
|
81
|
+
*/
|
|
82
|
+
declare const getBody: <Config extends EndpointConfig>(request: Request, config: Config) => Promise<any>;
|
|
83
|
+
|
|
84
|
+
export { getBody, getHeaders, getRouteParams, getSearchParams };
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getBody,
|
|
3
|
+
getHeaders,
|
|
4
|
+
getRouteParams,
|
|
5
|
+
getSearchParams
|
|
6
|
+
} from "./chunk-NNCUFWPI.js";
|
|
7
|
+
import "./chunk-6UBPSXKR.js";
|
|
8
|
+
import "./chunk-ENOBC3XN.js";
|
|
9
|
+
import "./chunk-RFYOPPMW.js";
|
|
10
|
+
export {
|
|
11
|
+
getBody,
|
|
12
|
+
getHeaders,
|
|
13
|
+
getRouteParams,
|
|
14
|
+
getSearchParams
|
|
15
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/endpoint.ts
|
|
21
|
+
var endpoint_exports = {};
|
|
22
|
+
__export(endpoint_exports, {
|
|
23
|
+
createEndpoint: () => createEndpoint,
|
|
24
|
+
createEndpointConfig: () => createEndpointConfig,
|
|
25
|
+
createRoutePattern: () => createRoutePattern
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(endpoint_exports);
|
|
28
|
+
|
|
29
|
+
// src/assert.ts
|
|
30
|
+
var supportedMethods = ["GET", "POST", "DELETE", "PUT", "PATCH"];
|
|
31
|
+
var isSupportedMethod = (method) => {
|
|
32
|
+
return supportedMethods.includes(method);
|
|
33
|
+
};
|
|
34
|
+
var isValidRoute = (route) => {
|
|
35
|
+
const routePattern = /^\/[a-zA-Z0-9/_:-]*$/;
|
|
36
|
+
return routePattern.test(route);
|
|
37
|
+
};
|
|
38
|
+
var isValidHandler = (handler) => {
|
|
39
|
+
return typeof handler === "function";
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// src/error.ts
|
|
43
|
+
var statusCode = {
|
|
44
|
+
OK: 200,
|
|
45
|
+
CREATED: 201,
|
|
46
|
+
ACCEPTED: 202,
|
|
47
|
+
NO_CONTENT: 204,
|
|
48
|
+
MULTIPLE_CHOICES: 300,
|
|
49
|
+
MOVED_PERMANENTLY: 301,
|
|
50
|
+
FOUND: 302,
|
|
51
|
+
SEE_OTHER: 303,
|
|
52
|
+
NOT_MODIFIED: 304,
|
|
53
|
+
TEMPORARY_REDIRECT: 307,
|
|
54
|
+
BAD_REQUEST: 400,
|
|
55
|
+
UNAUTHORIZED: 401,
|
|
56
|
+
PAYMENT_REQUIRED: 402,
|
|
57
|
+
FORBIDDEN: 403,
|
|
58
|
+
NOT_FOUND: 404,
|
|
59
|
+
METHOD_NOT_ALLOWED: 405,
|
|
60
|
+
NOT_ACCEPTABLE: 406,
|
|
61
|
+
PROXY_AUTHENTICATION_REQUIRED: 407,
|
|
62
|
+
UNPROCESSABLE_ENTITY: 422,
|
|
63
|
+
INTERNAL_SERVER_ERROR: 500,
|
|
64
|
+
NOT_IMPLEMENTED: 501,
|
|
65
|
+
BAD_GATEWAY: 502,
|
|
66
|
+
SERVICE_UNAVAILABLE: 503,
|
|
67
|
+
HTTP_VERSION_NOT_SUPPORTED: 505
|
|
68
|
+
};
|
|
69
|
+
var statusText = Object.entries(statusCode).reduce(
|
|
70
|
+
(previous, [status, code]) => {
|
|
71
|
+
return { ...previous, [code]: status };
|
|
72
|
+
},
|
|
73
|
+
{}
|
|
74
|
+
);
|
|
75
|
+
var AuraStackRouterError = class extends Error {
|
|
76
|
+
constructor(type, message, name) {
|
|
77
|
+
super(message);
|
|
78
|
+
this.name = name ?? "AuraStackRouterError";
|
|
79
|
+
this.status = statusCode[type];
|
|
80
|
+
this.statusText = statusText[this.status];
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// src/endpoint.ts
|
|
85
|
+
var createRoutePattern = (route) => {
|
|
86
|
+
const pattern = route.replace(/:[^/]+/g, "([^/]+)").replace(/\//g, "\\/");
|
|
87
|
+
return new RegExp(`^${pattern}$`);
|
|
88
|
+
};
|
|
89
|
+
var createEndpoint = (method, route, handler, config = {}) => {
|
|
90
|
+
if (!isSupportedMethod(method)) {
|
|
91
|
+
throw new AuraStackRouterError("METHOD_NOT_ALLOWED", `Unsupported HTTP method: ${method}`);
|
|
92
|
+
}
|
|
93
|
+
if (!isValidRoute(route)) {
|
|
94
|
+
throw new AuraStackRouterError("BAD_REQUEST", `Invalid route format: ${route}`);
|
|
95
|
+
}
|
|
96
|
+
if (!isValidHandler(handler)) {
|
|
97
|
+
throw new AuraStackRouterError("BAD_REQUEST", "Handler must be a function");
|
|
98
|
+
}
|
|
99
|
+
return { method, route, handler, config };
|
|
100
|
+
};
|
|
101
|
+
function createEndpointConfig(...args) {
|
|
102
|
+
if (typeof args[0] === "string") return args[1];
|
|
103
|
+
return args[0];
|
|
104
|
+
}
|
|
105
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
106
|
+
0 && (module.exports = {
|
|
107
|
+
createEndpoint,
|
|
108
|
+
createEndpointConfig,
|
|
109
|
+
createRoutePattern
|
|
110
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { RoutePattern, HTTPMethod, EndpointSchemas, RouteHandler, EndpointConfig, RouteEndpoint } from './types.cjs';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Create a RegExp pattern from a route string. This function allows segment the
|
|
6
|
+
* dynamic params in the route. For example, the route `/users/:id` will be
|
|
7
|
+
* converted to a regex pattern that captures the `id` parameter.
|
|
8
|
+
*
|
|
9
|
+
* @param route - The route pattern string
|
|
10
|
+
* @returns A RegExp object that matches the route pattern
|
|
11
|
+
* @example
|
|
12
|
+
* // Expected: /^\/users\/([^/]+)$/
|
|
13
|
+
* const pattern = createRoutePattern("/users/:id");
|
|
14
|
+
*/
|
|
15
|
+
declare const createRoutePattern: (route: RoutePattern) => RegExp;
|
|
16
|
+
/**
|
|
17
|
+
* Defines an API endpoint for the router by specifying the HTTP method, route pattern,
|
|
18
|
+
* handler function, and optional configuration such as validation schemas or middlewares.
|
|
19
|
+
* Validates all parameters for correctness. The resulting endpoint should be passed
|
|
20
|
+
* to the `createRouter` function.
|
|
21
|
+
*
|
|
22
|
+
* @param method - The HTTP method (e.g., GET, POST, PUT, DELETE, PATCH)
|
|
23
|
+
* @param route - The route pattern to associate with the endpoint (supports dynamic params)
|
|
24
|
+
* @param handler - The function to handle requests matching the method and route
|
|
25
|
+
* @param config - Optional configuration including validation schemas, middlewares, etc.
|
|
26
|
+
* @returns An object representing the configured endpoint
|
|
27
|
+
* @example
|
|
28
|
+
* const signIn = createEndpoint("POST", "/auth/signin", async (req, ctx) => {
|
|
29
|
+
* return new Response("Signed in");
|
|
30
|
+
* });
|
|
31
|
+
*/
|
|
32
|
+
declare const createEndpoint: <const Method extends Uppercase<HTTPMethod>, const Route extends Lowercase<RoutePattern>, const Schemas extends EndpointSchemas>(method: Method, route: Route, handler: RouteHandler<Route, {
|
|
33
|
+
schemas: Schemas;
|
|
34
|
+
}>, config?: EndpointConfig<Route, Schemas>) => RouteEndpoint<Method, Route, {}>;
|
|
35
|
+
/**
|
|
36
|
+
* Create an endpoint configuration to be passed to the `createEndpoint` function.
|
|
37
|
+
* This function is primarily for type inference and does not perform any runtime checks.
|
|
38
|
+
*
|
|
39
|
+
* @experimental
|
|
40
|
+
* @param config - The endpoint configuration object
|
|
41
|
+
* @returns The same configuration object, typed as EndpointConfig
|
|
42
|
+
* @example
|
|
43
|
+
* const config = createEndpointConfig({
|
|
44
|
+
* middlewares: [myMiddleware],
|
|
45
|
+
* schemas: {
|
|
46
|
+
* searchParams: z.object({
|
|
47
|
+
* q: z.string().min(3),
|
|
48
|
+
* })
|
|
49
|
+
* }
|
|
50
|
+
* })
|
|
51
|
+
*
|
|
52
|
+
* const search = createEndpoint("GET", "/search", async (request, ctx) => {
|
|
53
|
+
* return new Response("Search results");
|
|
54
|
+
* }, config);
|
|
55
|
+
*/
|
|
56
|
+
declare function createEndpointConfig<Schemas extends EndpointSchemas>(config: EndpointConfig<RoutePattern, Schemas>): EndpointConfig<RoutePattern, Schemas>;
|
|
57
|
+
declare function createEndpointConfig<Route extends RoutePattern, S extends EndpointSchemas>(route: Route, config: EndpointConfig<Route, S>): EndpointConfig<Route, S>;
|
|
58
|
+
|
|
59
|
+
export { createEndpoint, createEndpointConfig, createRoutePattern };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { RoutePattern, HTTPMethod, EndpointSchemas, RouteHandler, EndpointConfig, RouteEndpoint } from './types.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Create a RegExp pattern from a route string. This function allows segment the
|
|
6
|
+
* dynamic params in the route. For example, the route `/users/:id` will be
|
|
7
|
+
* converted to a regex pattern that captures the `id` parameter.
|
|
8
|
+
*
|
|
9
|
+
* @param route - The route pattern string
|
|
10
|
+
* @returns A RegExp object that matches the route pattern
|
|
11
|
+
* @example
|
|
12
|
+
* // Expected: /^\/users\/([^/]+)$/
|
|
13
|
+
* const pattern = createRoutePattern("/users/:id");
|
|
14
|
+
*/
|
|
15
|
+
declare const createRoutePattern: (route: RoutePattern) => RegExp;
|
|
16
|
+
/**
|
|
17
|
+
* Defines an API endpoint for the router by specifying the HTTP method, route pattern,
|
|
18
|
+
* handler function, and optional configuration such as validation schemas or middlewares.
|
|
19
|
+
* Validates all parameters for correctness. The resulting endpoint should be passed
|
|
20
|
+
* to the `createRouter` function.
|
|
21
|
+
*
|
|
22
|
+
* @param method - The HTTP method (e.g., GET, POST, PUT, DELETE, PATCH)
|
|
23
|
+
* @param route - The route pattern to associate with the endpoint (supports dynamic params)
|
|
24
|
+
* @param handler - The function to handle requests matching the method and route
|
|
25
|
+
* @param config - Optional configuration including validation schemas, middlewares, etc.
|
|
26
|
+
* @returns An object representing the configured endpoint
|
|
27
|
+
* @example
|
|
28
|
+
* const signIn = createEndpoint("POST", "/auth/signin", async (req, ctx) => {
|
|
29
|
+
* return new Response("Signed in");
|
|
30
|
+
* });
|
|
31
|
+
*/
|
|
32
|
+
declare const createEndpoint: <const Method extends Uppercase<HTTPMethod>, const Route extends Lowercase<RoutePattern>, const Schemas extends EndpointSchemas>(method: Method, route: Route, handler: RouteHandler<Route, {
|
|
33
|
+
schemas: Schemas;
|
|
34
|
+
}>, config?: EndpointConfig<Route, Schemas>) => RouteEndpoint<Method, Route, {}>;
|
|
35
|
+
/**
|
|
36
|
+
* Create an endpoint configuration to be passed to the `createEndpoint` function.
|
|
37
|
+
* This function is primarily for type inference and does not perform any runtime checks.
|
|
38
|
+
*
|
|
39
|
+
* @experimental
|
|
40
|
+
* @param config - The endpoint configuration object
|
|
41
|
+
* @returns The same configuration object, typed as EndpointConfig
|
|
42
|
+
* @example
|
|
43
|
+
* const config = createEndpointConfig({
|
|
44
|
+
* middlewares: [myMiddleware],
|
|
45
|
+
* schemas: {
|
|
46
|
+
* searchParams: z.object({
|
|
47
|
+
* q: z.string().min(3),
|
|
48
|
+
* })
|
|
49
|
+
* }
|
|
50
|
+
* })
|
|
51
|
+
*
|
|
52
|
+
* const search = createEndpoint("GET", "/search", async (request, ctx) => {
|
|
53
|
+
* return new Response("Search results");
|
|
54
|
+
* }, config);
|
|
55
|
+
*/
|
|
56
|
+
declare function createEndpointConfig<Schemas extends EndpointSchemas>(config: EndpointConfig<RoutePattern, Schemas>): EndpointConfig<RoutePattern, Schemas>;
|
|
57
|
+
declare function createEndpointConfig<Route extends RoutePattern, S extends EndpointSchemas>(route: Route, config: EndpointConfig<Route, S>): EndpointConfig<Route, S>;
|
|
58
|
+
|
|
59
|
+
export { createEndpoint, createEndpointConfig, createRoutePattern };
|
package/dist/endpoint.js
ADDED
package/dist/error.cjs
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/error.ts
|
|
21
|
+
var error_exports = {};
|
|
22
|
+
__export(error_exports, {
|
|
23
|
+
AuraStackRouterError: () => AuraStackRouterError
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(error_exports);
|
|
26
|
+
var statusCode = {
|
|
27
|
+
OK: 200,
|
|
28
|
+
CREATED: 201,
|
|
29
|
+
ACCEPTED: 202,
|
|
30
|
+
NO_CONTENT: 204,
|
|
31
|
+
MULTIPLE_CHOICES: 300,
|
|
32
|
+
MOVED_PERMANENTLY: 301,
|
|
33
|
+
FOUND: 302,
|
|
34
|
+
SEE_OTHER: 303,
|
|
35
|
+
NOT_MODIFIED: 304,
|
|
36
|
+
TEMPORARY_REDIRECT: 307,
|
|
37
|
+
BAD_REQUEST: 400,
|
|
38
|
+
UNAUTHORIZED: 401,
|
|
39
|
+
PAYMENT_REQUIRED: 402,
|
|
40
|
+
FORBIDDEN: 403,
|
|
41
|
+
NOT_FOUND: 404,
|
|
42
|
+
METHOD_NOT_ALLOWED: 405,
|
|
43
|
+
NOT_ACCEPTABLE: 406,
|
|
44
|
+
PROXY_AUTHENTICATION_REQUIRED: 407,
|
|
45
|
+
UNPROCESSABLE_ENTITY: 422,
|
|
46
|
+
INTERNAL_SERVER_ERROR: 500,
|
|
47
|
+
NOT_IMPLEMENTED: 501,
|
|
48
|
+
BAD_GATEWAY: 502,
|
|
49
|
+
SERVICE_UNAVAILABLE: 503,
|
|
50
|
+
HTTP_VERSION_NOT_SUPPORTED: 505
|
|
51
|
+
};
|
|
52
|
+
var statusText = Object.entries(statusCode).reduce(
|
|
53
|
+
(previous, [status, code]) => {
|
|
54
|
+
return { ...previous, [code]: status };
|
|
55
|
+
},
|
|
56
|
+
{}
|
|
57
|
+
);
|
|
58
|
+
var AuraStackRouterError = class extends Error {
|
|
59
|
+
constructor(type, message, name) {
|
|
60
|
+
super(message);
|
|
61
|
+
this.name = name ?? "AuraStackRouterError";
|
|
62
|
+
this.status = statusCode[type];
|
|
63
|
+
this.statusText = statusText[this.status];
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
67
|
+
0 && (module.exports = {
|
|
68
|
+
AuraStackRouterError
|
|
69
|
+
});
|
package/dist/error.d.cts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
/**
|
|
31
|
+
* Defines the errors used in AuraStack Router. Includes HTTP status code and
|
|
32
|
+
* status text.
|
|
33
|
+
*/
|
|
34
|
+
declare class AuraStackRouterError extends Error {
|
|
35
|
+
readonly status: number;
|
|
36
|
+
readonly statusText: keyof typeof statusCode;
|
|
37
|
+
constructor(type: keyof typeof statusCode, message: string, name?: string);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { AuraStackRouterError };
|