@aura-stack/router 0.4.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/dist/assert.cjs CHANGED
@@ -20,6 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/assert.ts
21
21
  var assert_exports = {};
22
22
  __export(assert_exports, {
23
+ isInvalidZodSchemaError: () => isInvalidZodSchemaError,
24
+ isObject: () => isObject,
23
25
  isRouterError: () => isRouterError,
24
26
  isSupportedBodyMethod: () => isSupportedBodyMethod,
25
27
  isSupportedMethod: () => isSupportedMethod,
@@ -76,6 +78,13 @@ var RouterError = class extends AuraStackRouterError {
76
78
  this.name = name ?? "RouterError";
77
79
  }
78
80
  };
81
+ var InvalidZodSchemaError = class {
82
+ constructor(type, errors) {
83
+ this.status = statusCode[type];
84
+ this.statusText = statusText[type];
85
+ this.errors = errors;
86
+ }
87
+ };
79
88
 
80
89
  // src/assert.ts
81
90
  var supportedMethods = /* @__PURE__ */ new Set(["GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD", "TRACE", "CONNECT"]);
@@ -97,8 +106,16 @@ var isValidHandler = (handler) => {
97
106
  var isRouterError = (error) => {
98
107
  return error instanceof RouterError;
99
108
  };
109
+ var isObject = (value) => {
110
+ return typeof value === "object" && value !== null && value !== void 0 && !Array.isArray(value);
111
+ };
112
+ var isInvalidZodSchemaError = (error) => {
113
+ return error instanceof InvalidZodSchemaError;
114
+ };
100
115
  // Annotate the CommonJS export names for ESM import in node:
101
116
  0 && (module.exports = {
117
+ isInvalidZodSchemaError,
118
+ isObject,
102
119
  isRouterError,
103
120
  isSupportedBodyMethod,
104
121
  isSupportedMethod,
package/dist/assert.d.ts CHANGED
@@ -1,6 +1,8 @@
1
- import { RouterError } from './error.js';
1
+ import { RouterError, InvalidZodSchemaError } from './error.js';
2
2
  import { HTTPMethod, RoutePattern, RouteHandler } from './types.js';
3
3
  import 'zod';
4
+ import './headers.js';
5
+ import 'cookie';
4
6
 
5
7
  declare const supportedProtocols: Set<string>;
6
8
  /**
@@ -48,5 +50,13 @@ declare const isValidHandler: (handler: unknown) => handler is RouteHandler<any,
48
50
  * }
49
51
  */
50
52
  declare const isRouterError: (error: unknown) => error is RouterError;
53
+ declare const isObject: (value: unknown) => value is Record<string, unknown>;
54
+ /**
55
+ * Checks if the provided error is an instance of InvalidZodSchemaError.
56
+ *
57
+ * @param error the error to check
58
+ * @returns true if the error is an instance of InvalidZodSchemaError, false otherwise.
59
+ */
60
+ declare const isInvalidZodSchemaError: (error: unknown) => error is InvalidZodSchemaError;
51
61
 
52
- export { isRouterError, isSupportedBodyMethod, isSupportedMethod, isValidHandler, isValidRoute, supportedProtocols };
62
+ export { isInvalidZodSchemaError, isObject, isRouterError, isSupportedBodyMethod, isSupportedMethod, isValidHandler, isValidRoute, supportedProtocols };
package/dist/assert.js CHANGED
@@ -1,13 +1,17 @@
1
1
  import {
2
+ isInvalidZodSchemaError,
3
+ isObject,
2
4
  isRouterError,
3
5
  isSupportedBodyMethod,
4
6
  isSupportedMethod,
5
7
  isValidHandler,
6
8
  isValidRoute,
7
9
  supportedProtocols
8
- } from "./chunk-JNMXLKDG.js";
9
- import "./chunk-GJC3ODME.js";
10
+ } from "./chunk-FU35BPU7.js";
11
+ import "./chunk-B6PMGVSL.js";
10
12
  export {
13
+ isInvalidZodSchemaError,
14
+ isObject,
11
15
  isRouterError,
12
16
  isSupportedBodyMethod,
13
17
  isSupportedMethod,
@@ -2,10 +2,10 @@ import {
2
2
  isSupportedMethod,
3
3
  isValidHandler,
4
4
  isValidRoute
5
- } from "./chunk-JNMXLKDG.js";
5
+ } from "./chunk-FU35BPU7.js";
6
6
  import {
7
7
  RouterError
8
- } from "./chunk-GJC3ODME.js";
8
+ } from "./chunk-B6PMGVSL.js";
9
9
 
10
10
  // src/endpoint.ts
11
11
  var createEndpoint = (method, route, handler, config = {}) => {
@@ -45,10 +45,18 @@ var RouterError = class extends AuraStackRouterError {
45
45
  this.name = name ?? "RouterError";
46
46
  }
47
47
  };
48
+ var InvalidZodSchemaError = class {
49
+ constructor(type, errors) {
50
+ this.status = statusCode[type];
51
+ this.statusText = statusText[type];
52
+ this.errors = errors;
53
+ }
54
+ };
48
55
 
49
56
  export {
50
57
  statusCode,
51
58
  statusText,
52
59
  AuraStackRouterError,
53
- RouterError
60
+ RouterError,
61
+ InvalidZodSchemaError
54
62
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  RouterError
3
- } from "./chunk-GJC3ODME.js";
3
+ } from "./chunk-B6PMGVSL.js";
4
4
 
5
5
  // src/middlewares.ts
6
6
  var executeGlobalMiddlewares = async (context, middlewares) => {
@@ -1,6 +1,7 @@
1
1
  import {
2
+ InvalidZodSchemaError,
2
3
  RouterError
3
- } from "./chunk-GJC3ODME.js";
4
+ } from "./chunk-B6PMGVSL.js";
4
5
 
5
6
  // src/assert.ts
6
7
  var supportedMethods = /* @__PURE__ */ new Set(["GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD", "TRACE", "CONNECT"]);
@@ -22,6 +23,12 @@ var isValidHandler = (handler) => {
22
23
  var isRouterError = (error) => {
23
24
  return error instanceof RouterError;
24
25
  };
26
+ var isObject = (value) => {
27
+ return typeof value === "object" && value !== null && value !== void 0 && !Array.isArray(value);
28
+ };
29
+ var isInvalidZodSchemaError = (error) => {
30
+ return error instanceof InvalidZodSchemaError;
31
+ };
25
32
 
26
33
  export {
27
34
  supportedProtocols,
@@ -29,5 +36,7 @@ export {
29
36
  isSupportedBodyMethod,
30
37
  isValidRoute,
31
38
  isValidHandler,
32
- isRouterError
39
+ isRouterError,
40
+ isObject,
41
+ isInvalidZodSchemaError
33
42
  };
@@ -1,21 +1,24 @@
1
1
  import {
2
2
  getBody,
3
- getHeaders,
4
3
  getRouteParams,
5
4
  getSearchParams
6
- } from "./chunk-PT4GU6PH.js";
5
+ } from "./chunk-XB5P5CQZ.js";
7
6
  import {
7
+ isInvalidZodSchemaError,
8
8
  isRouterError,
9
9
  isSupportedMethod
10
- } from "./chunk-JNMXLKDG.js";
10
+ } from "./chunk-FU35BPU7.js";
11
+ import {
12
+ HeadersBuilder
13
+ } from "./chunk-Z6JJAIWN.js";
11
14
  import {
12
15
  executeGlobalMiddlewares,
13
16
  executeMiddlewares
14
- } from "./chunk-CFAIW6YL.js";
17
+ } from "./chunk-BWIKAYZV.js";
15
18
  import {
16
19
  RouterError,
17
20
  statusText
18
- } from "./chunk-GJC3ODME.js";
21
+ } from "./chunk-B6PMGVSL.js";
19
22
 
20
23
  // src/router.ts
21
24
  var createNode = () => ({
@@ -81,6 +84,17 @@ var handleError = async (error, request, config) => {
81
84
  );
82
85
  }
83
86
  }
87
+ if (isInvalidZodSchemaError(error)) {
88
+ const { errors, status, statusText: statusText2 } = error;
89
+ return Response.json(
90
+ {
91
+ message: "Invalid request data",
92
+ error: "validation_error",
93
+ details: errors
94
+ },
95
+ { status, statusText: statusText2 }
96
+ );
97
+ }
84
98
  if (isRouterError(error)) {
85
99
  const { message, status, statusText: statusText2 } = error;
86
100
  return Response.json({ message }, { status, statusText: statusText2 });
@@ -107,7 +121,7 @@ var handleRequest = async (method, request, config, root) => {
107
121
  const dynamicParams = getRouteParams(params, endpoint.config);
108
122
  const body = await getBody(globalRequestContext.request, endpoint.config);
109
123
  const searchParams = getSearchParams(globalRequestContext.request.url, endpoint.config);
110
- const headers = getHeaders(globalRequestContext.request);
124
+ const headers = new HeadersBuilder(globalRequestContext.request.headers);
111
125
  let context = {
112
126
  params: dynamicParams,
113
127
  searchParams,
@@ -1,16 +1,32 @@
1
1
  import {
2
2
  isSupportedBodyMethod
3
- } from "./chunk-JNMXLKDG.js";
3
+ } from "./chunk-FU35BPU7.js";
4
4
  import {
5
+ InvalidZodSchemaError,
5
6
  RouterError
6
- } from "./chunk-GJC3ODME.js";
7
+ } from "./chunk-B6PMGVSL.js";
7
8
 
8
9
  // src/context.ts
10
+ var formatZodError = (error) => {
11
+ if (!error.issues || error.issues.length === 0) {
12
+ return {};
13
+ }
14
+ return error.issues.reduce((previous, issue) => {
15
+ const key = issue.path.join(".");
16
+ return {
17
+ ...previous,
18
+ [key]: {
19
+ code: issue.code,
20
+ message: issue.message
21
+ }
22
+ };
23
+ }, {});
24
+ };
9
25
  var getRouteParams = (params, config) => {
10
26
  if (config.schemas?.params) {
11
27
  const parsed = config.schemas.params.safeParse(params);
12
28
  if (!parsed.success) {
13
- throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid route parameters");
29
+ throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
14
30
  }
15
31
  return parsed.data;
16
32
  }
@@ -21,15 +37,12 @@ var getSearchParams = (url, config) => {
21
37
  if (config.schemas?.searchParams) {
22
38
  const parsed = config.schemas.searchParams.safeParse(Object.fromEntries(route.searchParams.entries()));
23
39
  if (!parsed.success) {
24
- throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid search parameters");
40
+ throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
25
41
  }
26
42
  return parsed.data;
27
43
  }
28
44
  return new URLSearchParams(route.searchParams.toString());
29
45
  };
30
- var getHeaders = (request) => {
31
- return new Headers(request.headers);
32
- };
33
46
  var getBody = async (request, config) => {
34
47
  if (!isSupportedBodyMethod(request.method)) {
35
48
  return null;
@@ -41,7 +54,7 @@ var getBody = async (request, config) => {
41
54
  if (config.schemas?.body) {
42
55
  const parsed = config.schemas.body.safeParse(json);
43
56
  if (!parsed.success) {
44
- throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid request body");
57
+ throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
45
58
  }
46
59
  return parsed.data;
47
60
  }
@@ -71,8 +84,8 @@ var createContentTypeRegex = (contentTypes, contenType) => {
71
84
  };
72
85
 
73
86
  export {
87
+ formatZodError,
74
88
  getRouteParams,
75
89
  getSearchParams,
76
- getHeaders,
77
90
  getBody
78
91
  };
@@ -0,0 +1,37 @@
1
+ // src/headers.ts
2
+ import { serialize, parse, parseSetCookie } from "cookie";
3
+ var HeadersBuilder = class {
4
+ constructor(initialHeaders) {
5
+ this.headers = new Headers(initialHeaders);
6
+ }
7
+ setHeader(name, value) {
8
+ this.headers.set(name, value);
9
+ return this;
10
+ }
11
+ setCookie(name, value, options) {
12
+ this.headers.append("Set-Cookie", serialize(name, value, options));
13
+ return this;
14
+ }
15
+ getHeader(name) {
16
+ return this.headers.get(name);
17
+ }
18
+ getCookie(name) {
19
+ const cookies = parse(this.headers.get("cookie") ?? "");
20
+ return cookies[name];
21
+ }
22
+ getSetCookie(name) {
23
+ const cookies = this.headers.getSetCookie();
24
+ const cookie = cookies.find((cookie2) => cookie2.startsWith(name + "="));
25
+ return cookie ? parseSetCookie(cookie).value : void 0;
26
+ }
27
+ toHeaders() {
28
+ return new Headers(this.headers);
29
+ }
30
+ toCookies() {
31
+ return parse(this.headers.get("cookie") ?? "");
32
+ }
33
+ };
34
+
35
+ export {
36
+ HeadersBuilder
37
+ };
package/dist/context.cjs CHANGED
@@ -20,8 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/context.ts
21
21
  var context_exports = {};
22
22
  __export(context_exports, {
23
+ formatZodError: () => formatZodError,
23
24
  getBody: () => getBody,
24
- getHeaders: () => getHeaders,
25
25
  getRouteParams: () => getRouteParams,
26
26
  getSearchParams: () => getSearchParams
27
27
  });
@@ -74,6 +74,13 @@ 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
+ };
77
84
 
78
85
  // src/assert.ts
79
86
  var supportedBodyMethods = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH"]);
@@ -82,11 +89,26 @@ var isSupportedBodyMethod = (method) => {
82
89
  };
83
90
 
84
91
  // src/context.ts
92
+ var formatZodError = (error) => {
93
+ if (!error.issues || error.issues.length === 0) {
94
+ return {};
95
+ }
96
+ return error.issues.reduce((previous, issue) => {
97
+ const key = issue.path.join(".");
98
+ return {
99
+ ...previous,
100
+ [key]: {
101
+ code: issue.code,
102
+ message: issue.message
103
+ }
104
+ };
105
+ }, {});
106
+ };
85
107
  var getRouteParams = (params, config) => {
86
108
  if (config.schemas?.params) {
87
109
  const parsed = config.schemas.params.safeParse(params);
88
110
  if (!parsed.success) {
89
- throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid route parameters");
111
+ throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
90
112
  }
91
113
  return parsed.data;
92
114
  }
@@ -97,15 +119,12 @@ var getSearchParams = (url, config) => {
97
119
  if (config.schemas?.searchParams) {
98
120
  const parsed = config.schemas.searchParams.safeParse(Object.fromEntries(route.searchParams.entries()));
99
121
  if (!parsed.success) {
100
- throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid search parameters");
122
+ throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
101
123
  }
102
124
  return parsed.data;
103
125
  }
104
126
  return new URLSearchParams(route.searchParams.toString());
105
127
  };
106
- var getHeaders = (request) => {
107
- return new Headers(request.headers);
108
- };
109
128
  var getBody = async (request, config) => {
110
129
  if (!isSupportedBodyMethod(request.method)) {
111
130
  return null;
@@ -117,7 +136,7 @@ var getBody = async (request, config) => {
117
136
  if (config.schemas?.body) {
118
137
  const parsed = config.schemas.body.safeParse(json);
119
138
  if (!parsed.success) {
120
- throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid request body");
139
+ throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
121
140
  }
122
141
  return parsed.data;
123
142
  }
@@ -147,8 +166,8 @@ var createContentTypeRegex = (contentTypes, contenType) => {
147
166
  };
148
167
  // Annotate the CommonJS export names for ESM import in node:
149
168
  0 && (module.exports = {
169
+ formatZodError,
150
170
  getBody,
151
- getHeaders,
152
171
  getRouteParams,
153
172
  getSearchParams
154
173
  });
package/dist/context.d.ts CHANGED
@@ -1,7 +1,14 @@
1
+ import { ZodError } from 'zod';
1
2
  import { EndpointConfig, ContextSearchParams } from './types.js';
2
- import 'zod';
3
3
  import './error.js';
4
+ import './headers.js';
5
+ import 'cookie';
4
6
 
7
+ /**
8
+ * @experimental
9
+ * @param error ZodError instance
10
+ */
11
+ declare const formatZodError: (error: ZodError<Record<string, unknown>>) => {};
5
12
  /**
6
13
  * Extracts route parameters from a given path using the specified route pattern.
7
14
  *
@@ -53,21 +60,6 @@ declare const getRouteParams: (params: Record<string, string>, config: EndpointC
53
60
  * const searchParams2 = getSearchParams(url2, {} as EndpointConfig);
54
61
  */
55
62
  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
63
  /**
72
64
  * Extracts and parses the body of a Request object based on its Content-Type header.
73
65
  *
@@ -82,4 +74,4 @@ declare const getHeaders: (request: Request) => Headers;
82
74
  */
83
75
  declare const getBody: <Config extends EndpointConfig>(request: Request, config: Config) => Promise<any>;
84
76
 
85
- export { getBody, getHeaders, getRouteParams, getSearchParams };
77
+ export { formatZodError, getBody, getRouteParams, getSearchParams };
package/dist/context.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import {
2
+ formatZodError,
2
3
  getBody,
3
- getHeaders,
4
4
  getRouteParams,
5
5
  getSearchParams
6
- } from "./chunk-PT4GU6PH.js";
7
- import "./chunk-JNMXLKDG.js";
8
- import "./chunk-GJC3ODME.js";
6
+ } from "./chunk-XB5P5CQZ.js";
7
+ import "./chunk-FU35BPU7.js";
8
+ import "./chunk-B6PMGVSL.js";
9
9
  export {
10
+ formatZodError,
10
11
  getBody,
11
- getHeaders,
12
12
  getRouteParams,
13
13
  getSearchParams
14
14
  };
@@ -0,0 +1,24 @@
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 __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
15
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
16
+
17
+ // src/cookie.ts
18
+ var cookie_exports = {};
19
+ module.exports = __toCommonJS(cookie_exports);
20
+ __reExport(cookie_exports, require("cookie"), module.exports);
21
+ // Annotate the CommonJS export names for ESM import in node:
22
+ 0 && (module.exports = {
23
+ ...require("cookie")
24
+ });
@@ -0,0 +1 @@
1
+ export * from 'cookie';
package/dist/cookie.js ADDED
@@ -0,0 +1,2 @@
1
+ // src/cookie.ts
2
+ export * from "cookie";
@@ -1,6 +1,8 @@
1
1
  import { HTTPMethod, RoutePattern, EndpointSchemas, RouteHandler, EndpointConfig, RouteEndpoint } from './types.js';
2
2
  import 'zod';
3
3
  import './error.js';
4
+ import './headers.js';
5
+ import 'cookie';
4
6
 
5
7
  /**
6
8
  * Defines an API endpoint for the router by specifying the HTTP method, route pattern,
package/dist/endpoint.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createEndpoint,
3
3
  createEndpointConfig
4
- } from "./chunk-6PZEXNTS.js";
5
- import "./chunk-JNMXLKDG.js";
6
- import "./chunk-GJC3ODME.js";
4
+ } from "./chunk-4UYDR5IO.js";
5
+ import "./chunk-FU35BPU7.js";
6
+ import "./chunk-B6PMGVSL.js";
7
7
  export {
8
8
  createEndpoint,
9
9
  createEndpointConfig
package/dist/error.cjs CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var error_exports = {};
22
22
  __export(error_exports, {
23
23
  AuraStackRouterError: () => AuraStackRouterError,
24
+ InvalidZodSchemaError: () => InvalidZodSchemaError,
24
25
  RouterError: () => RouterError,
25
26
  statusCode: () => statusCode,
26
27
  statusText: () => statusText
@@ -72,9 +73,17 @@ var RouterError = class extends AuraStackRouterError {
72
73
  this.name = name ?? "RouterError";
73
74
  }
74
75
  };
76
+ var InvalidZodSchemaError = class {
77
+ constructor(type, errors) {
78
+ this.status = statusCode[type];
79
+ this.statusText = statusText[type];
80
+ this.errors = errors;
81
+ }
82
+ };
75
83
  // Annotate the CommonJS export names for ESM import in node:
76
84
  0 && (module.exports = {
77
85
  AuraStackRouterError,
86
+ InvalidZodSchemaError,
78
87
  RouterError,
79
88
  statusCode,
80
89
  statusText
package/dist/error.d.ts CHANGED
@@ -61,5 +61,11 @@ declare class AuraStackRouterError extends Error {
61
61
  declare class RouterError extends AuraStackRouterError {
62
62
  constructor(type: StatusCode, message: string, name?: string);
63
63
  }
64
+ declare class InvalidZodSchemaError {
65
+ readonly status: number;
66
+ readonly statusText: StatusCode;
67
+ readonly errors: Record<string, string>;
68
+ constructor(type: StatusCode, errors: Record<string, string>);
69
+ }
64
70
 
65
- export { AuraStackRouterError, RouterError, statusCode, statusText };
71
+ export { AuraStackRouterError, InvalidZodSchemaError, RouterError, statusCode, statusText };
package/dist/error.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import {
2
2
  AuraStackRouterError,
3
+ InvalidZodSchemaError,
3
4
  RouterError,
4
5
  statusCode,
5
6
  statusText
6
- } from "./chunk-GJC3ODME.js";
7
+ } from "./chunk-B6PMGVSL.js";
7
8
  export {
8
9
  AuraStackRouterError,
10
+ InvalidZodSchemaError,
9
11
  RouterError,
10
12
  statusCode,
11
13
  statusText
@@ -0,0 +1,61 @@
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/headers.ts
21
+ var headers_exports = {};
22
+ __export(headers_exports, {
23
+ HeadersBuilder: () => HeadersBuilder
24
+ });
25
+ module.exports = __toCommonJS(headers_exports);
26
+ var import_cookie = require("cookie");
27
+ var HeadersBuilder = class {
28
+ constructor(initialHeaders) {
29
+ this.headers = new Headers(initialHeaders);
30
+ }
31
+ setHeader(name, value) {
32
+ this.headers.set(name, value);
33
+ return this;
34
+ }
35
+ setCookie(name, value, options) {
36
+ this.headers.append("Set-Cookie", (0, import_cookie.serialize)(name, value, options));
37
+ return this;
38
+ }
39
+ getHeader(name) {
40
+ return this.headers.get(name);
41
+ }
42
+ getCookie(name) {
43
+ const cookies = (0, import_cookie.parse)(this.headers.get("cookie") ?? "");
44
+ return cookies[name];
45
+ }
46
+ getSetCookie(name) {
47
+ const cookies = this.headers.getSetCookie();
48
+ const cookie = cookies.find((cookie2) => cookie2.startsWith(name + "="));
49
+ return cookie ? (0, import_cookie.parseSetCookie)(cookie).value : void 0;
50
+ }
51
+ toHeaders() {
52
+ return new Headers(this.headers);
53
+ }
54
+ toCookies() {
55
+ return (0, import_cookie.parse)(this.headers.get("cookie") ?? "");
56
+ }
57
+ };
58
+ // Annotate the CommonJS export names for ESM import in node:
59
+ 0 && (module.exports = {
60
+ HeadersBuilder
61
+ });
@@ -0,0 +1,20 @@
1
+ import { SerializeOptions, Cookies } from 'cookie';
2
+
3
+ /**
4
+ * A builder class for constructing and manipulating HTTP headers.
5
+ * It includes methods to set, delete, and retrieve headers, as well as
6
+ * manage cookies within the headers.
7
+ */
8
+ declare class HeadersBuilder {
9
+ private headers;
10
+ constructor(initialHeaders?: HeadersInit);
11
+ setHeader(name: string, value: string): HeadersBuilder;
12
+ setCookie(name: string, value: string, options?: SerializeOptions): HeadersBuilder;
13
+ getHeader(name: string): string | null;
14
+ getCookie(name: string): string | undefined;
15
+ getSetCookie(name: string): string | undefined;
16
+ toHeaders(): Headers;
17
+ toCookies(): Cookies;
18
+ }
19
+
20
+ export { HeadersBuilder };
@@ -0,0 +1,6 @@
1
+ import {
2
+ HeadersBuilder
3
+ } from "./chunk-Z6JJAIWN.js";
4
+ export {
5
+ HeadersBuilder
6
+ };
package/dist/index.cjs CHANGED
@@ -20,10 +20,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ HeadersBuilder: () => HeadersBuilder,
23
24
  RouterError: () => RouterError,
24
25
  createEndpoint: () => createEndpoint,
25
26
  createEndpointConfig: () => createEndpointConfig,
26
27
  createRouter: () => createRouter,
28
+ isInvalidZodSchemaError: () => isInvalidZodSchemaError,
27
29
  isRouterError: () => isRouterError,
28
30
  statusCode: () => statusCode,
29
31
  statusText: () => statusText
@@ -77,6 +79,13 @@ var RouterError = class extends AuraStackRouterError {
77
79
  this.name = name ?? "RouterError";
78
80
  }
79
81
  };
82
+ var InvalidZodSchemaError = class {
83
+ constructor(type, errors) {
84
+ this.status = statusCode[type];
85
+ this.statusText = statusText[type];
86
+ this.errors = errors;
87
+ }
88
+ };
80
89
 
81
90
  // src/assert.ts
82
91
  var supportedMethods = /* @__PURE__ */ new Set(["GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD", "TRACE", "CONNECT"]);
@@ -97,6 +106,9 @@ var isValidHandler = (handler) => {
97
106
  var isRouterError = (error) => {
98
107
  return error instanceof RouterError;
99
108
  };
109
+ var isInvalidZodSchemaError = (error) => {
110
+ return error instanceof InvalidZodSchemaError;
111
+ };
100
112
 
101
113
  // src/endpoint.ts
102
114
  var createEndpoint = (method, route, handler, config = {}) => {
@@ -116,45 +128,61 @@ function createEndpointConfig(...args) {
116
128
  return args[0];
117
129
  }
118
130
 
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
+ // src/headers.ts
132
+ var import_cookie = require("cookie");
133
+ var HeadersBuilder = class {
134
+ constructor(initialHeaders) {
135
+ this.headers = new Headers(initialHeaders);
131
136
  }
132
- if (!context || !(context.request instanceof Request)) {
133
- throw new RouterError("BAD_REQUEST", "Global middleware must return a Request or Response object");
137
+ setHeader(name, value) {
138
+ this.headers.set(name, value);
139
+ return this;
134
140
  }
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");
141
+ setCookie(name, value, options) {
142
+ this.headers.append("Set-Cookie", (0, import_cookie.serialize)(name, value, options));
143
+ return this;
144
+ }
145
+ getHeader(name) {
146
+ return this.headers.get(name);
147
+ }
148
+ getCookie(name) {
149
+ const cookies = (0, import_cookie.parse)(this.headers.get("cookie") ?? "");
150
+ return cookies[name];
151
+ }
152
+ getSetCookie(name) {
153
+ const cookies = this.headers.getSetCookie();
154
+ const cookie = cookies.find((cookie2) => cookie2.startsWith(name + "="));
155
+ return cookie ? (0, import_cookie.parseSetCookie)(cookie).value : void 0;
156
+ }
157
+ toHeaders() {
158
+ return new Headers(this.headers);
159
+ }
160
+ toCookies() {
161
+ return (0, import_cookie.parse)(this.headers.get("cookie") ?? "");
149
162
  }
150
163
  };
151
164
 
152
165
  // src/context.ts
166
+ var formatZodError = (error) => {
167
+ if (!error.issues || error.issues.length === 0) {
168
+ return {};
169
+ }
170
+ return error.issues.reduce((previous, issue) => {
171
+ const key = issue.path.join(".");
172
+ return {
173
+ ...previous,
174
+ [key]: {
175
+ code: issue.code,
176
+ message: issue.message
177
+ }
178
+ };
179
+ }, {});
180
+ };
153
181
  var getRouteParams = (params, config) => {
154
182
  if (config.schemas?.params) {
155
183
  const parsed = config.schemas.params.safeParse(params);
156
184
  if (!parsed.success) {
157
- throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid route parameters");
185
+ throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
158
186
  }
159
187
  return parsed.data;
160
188
  }
@@ -165,15 +193,12 @@ var getSearchParams = (url, config) => {
165
193
  if (config.schemas?.searchParams) {
166
194
  const parsed = config.schemas.searchParams.safeParse(Object.fromEntries(route.searchParams.entries()));
167
195
  if (!parsed.success) {
168
- throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid search parameters");
196
+ throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
169
197
  }
170
198
  return parsed.data;
171
199
  }
172
200
  return new URLSearchParams(route.searchParams.toString());
173
201
  };
174
- var getHeaders = (request) => {
175
- return new Headers(request.headers);
176
- };
177
202
  var getBody = async (request, config) => {
178
203
  if (!isSupportedBodyMethod(request.method)) {
179
204
  return null;
@@ -185,7 +210,7 @@ var getBody = async (request, config) => {
185
210
  if (config.schemas?.body) {
186
211
  const parsed = config.schemas.body.safeParse(json);
187
212
  if (!parsed.success) {
188
- throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid request body");
213
+ throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
189
214
  }
190
215
  return parsed.data;
191
216
  }
@@ -214,6 +239,39 @@ var createContentTypeRegex = (contentTypes, contenType) => {
214
239
  return regex.test(contenType);
215
240
  };
216
241
 
242
+ // src/middlewares.ts
243
+ var executeGlobalMiddlewares = async (context, middlewares) => {
244
+ if (!middlewares) return context;
245
+ for (const middleware of middlewares) {
246
+ if (typeof middleware !== "function") {
247
+ throw new RouterError("BAD_REQUEST", "Global middlewares must be functions");
248
+ }
249
+ const executed = await middleware(context);
250
+ if (executed instanceof Response) {
251
+ return executed;
252
+ }
253
+ context = executed;
254
+ }
255
+ if (!context || !(context.request instanceof Request)) {
256
+ throw new RouterError("BAD_REQUEST", "Global middleware must return a Request or Response object");
257
+ }
258
+ return context;
259
+ };
260
+ var executeMiddlewares = async (context, middlewares = []) => {
261
+ try {
262
+ let ctx = context;
263
+ for (const middleware of middlewares) {
264
+ if (typeof middleware !== "function") {
265
+ throw new RouterError("BAD_REQUEST", "Middleware must be a function");
266
+ }
267
+ ctx = await middleware(ctx);
268
+ }
269
+ return ctx;
270
+ } catch {
271
+ throw new RouterError("BAD_REQUEST", "Handler threw an error");
272
+ }
273
+ };
274
+
217
275
  // src/router.ts
218
276
  var createNode = () => ({
219
277
  statics: /* @__PURE__ */ new Map(),
@@ -278,6 +336,17 @@ var handleError = async (error, request, config) => {
278
336
  );
279
337
  }
280
338
  }
339
+ if (isInvalidZodSchemaError(error)) {
340
+ const { errors, status, statusText: statusText2 } = error;
341
+ return Response.json(
342
+ {
343
+ message: "Invalid request data",
344
+ error: "validation_error",
345
+ details: errors
346
+ },
347
+ { status, statusText: statusText2 }
348
+ );
349
+ }
281
350
  if (isRouterError(error)) {
282
351
  const { message, status, statusText: statusText2 } = error;
283
352
  return Response.json({ message }, { status, statusText: statusText2 });
@@ -304,7 +373,7 @@ var handleRequest = async (method, request, config, root) => {
304
373
  const dynamicParams = getRouteParams(params, endpoint.config);
305
374
  const body = await getBody(globalRequestContext.request, endpoint.config);
306
375
  const searchParams = getSearchParams(globalRequestContext.request.url, endpoint.config);
307
- const headers = getHeaders(globalRequestContext.request);
376
+ const headers = new HeadersBuilder(globalRequestContext.request.headers);
308
377
  let context = {
309
378
  params: dynamicParams,
310
379
  searchParams,
@@ -339,10 +408,12 @@ var createRouter = (endpoints, config = {}) => {
339
408
  };
340
409
  // Annotate the CommonJS export names for ESM import in node:
341
410
  0 && (module.exports = {
411
+ HeadersBuilder,
342
412
  RouterError,
343
413
  createEndpoint,
344
414
  createEndpointConfig,
345
415
  createRouter,
416
+ isInvalidZodSchemaError,
346
417
  isRouterError,
347
418
  statusCode,
348
419
  statusText
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export { createEndpoint, createEndpointConfig } from './endpoint.js';
2
2
  export { createRouter } from './router.js';
3
- export { isRouterError } from './assert.js';
3
+ export { isInvalidZodSchemaError, isRouterError } from './assert.js';
4
4
  export { RouterError, statusCode, statusText } from './error.js';
5
+ export { HeadersBuilder } from './headers.js';
5
6
  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';
7
+ import 'cookie';
6
8
  import 'zod';
package/dist/index.js CHANGED
@@ -1,25 +1,31 @@
1
+ import {
2
+ createRouter
3
+ } from "./chunk-TEDN6QMU.js";
4
+ import "./chunk-XB5P5CQZ.js";
1
5
  import {
2
6
  createEndpoint,
3
7
  createEndpointConfig
4
- } from "./chunk-6PZEXNTS.js";
5
- import {
6
- createRouter
7
- } from "./chunk-CL5D7UJU.js";
8
- import "./chunk-PT4GU6PH.js";
8
+ } from "./chunk-4UYDR5IO.js";
9
9
  import {
10
+ isInvalidZodSchemaError,
10
11
  isRouterError
11
- } from "./chunk-JNMXLKDG.js";
12
- import "./chunk-CFAIW6YL.js";
12
+ } from "./chunk-FU35BPU7.js";
13
+ import {
14
+ HeadersBuilder
15
+ } from "./chunk-Z6JJAIWN.js";
16
+ import "./chunk-BWIKAYZV.js";
13
17
  import {
14
18
  RouterError,
15
19
  statusCode,
16
20
  statusText
17
- } from "./chunk-GJC3ODME.js";
21
+ } from "./chunk-B6PMGVSL.js";
18
22
  export {
23
+ HeadersBuilder,
19
24
  RouterError,
20
25
  createEndpoint,
21
26
  createEndpointConfig,
22
27
  createRouter,
28
+ isInvalidZodSchemaError,
23
29
  isRouterError,
24
30
  statusCode,
25
31
  statusText
@@ -1,6 +1,8 @@
1
1
  import { GlobalMiddlewareContext, RouterConfig, EndpointConfig, RequestContext, MiddlewareFunction } from './types.js';
2
2
  import 'zod';
3
3
  import './error.js';
4
+ import './headers.js';
5
+ import 'cookie';
4
6
 
5
7
  /**
6
8
  * Executes the middlewares in sequence, passing the request to each middleware.
@@ -9,7 +11,7 @@ import './error.js';
9
11
  * @param middlewares - Array of global middleware functions to be executed
10
12
  * @returns - The modified request after all middlewares have been executed
11
13
  */
12
- declare const executeGlobalMiddlewares: (context: GlobalMiddlewareContext, middlewares: RouterConfig["middlewares"]) => Promise<GlobalMiddlewareContext | Response>;
14
+ declare const executeGlobalMiddlewares: (context: GlobalMiddlewareContext, middlewares: RouterConfig["middlewares"]) => Promise<Response | GlobalMiddlewareContext>;
13
15
  /**
14
16
  * Executes middlewares in sequence, passing the request and context to each middleware.
15
17
  *
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  executeGlobalMiddlewares,
3
3
  executeMiddlewares
4
- } from "./chunk-CFAIW6YL.js";
5
- import "./chunk-GJC3ODME.js";
4
+ } from "./chunk-BWIKAYZV.js";
5
+ import "./chunk-B6PMGVSL.js";
6
6
  export {
7
7
  executeGlobalMiddlewares,
8
8
  executeMiddlewares
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,46 +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
- // src/middlewares.ts
92
- var executeGlobalMiddlewares = async (context, middlewares) => {
93
- if (!middlewares) return context;
94
- for (const middleware of middlewares) {
95
- if (typeof middleware !== "function") {
96
- throw new RouterError("BAD_REQUEST", "Global middlewares must be functions");
97
- }
98
- const executed = await middleware(context);
99
- if (executed instanceof Response) {
100
- return executed;
101
- }
102
- context = executed;
103
- }
104
- if (!context || !(context.request instanceof Request)) {
105
- throw new RouterError("BAD_REQUEST", "Global middleware must return a Request or Response object");
135
+ // src/context.ts
136
+ var formatZodError = (error) => {
137
+ if (!error.issues || error.issues.length === 0) {
138
+ return {};
106
139
  }
107
- return context;
108
- };
109
- var executeMiddlewares = async (context, middlewares = []) => {
110
- try {
111
- let ctx = context;
112
- for (const middleware of middlewares) {
113
- if (typeof middleware !== "function") {
114
- throw new RouterError("BAD_REQUEST", "Middleware must be a function");
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
115
147
  }
116
- ctx = await middleware(ctx);
117
- }
118
- return ctx;
119
- } catch {
120
- throw new RouterError("BAD_REQUEST", "Handler threw an error");
121
- }
148
+ };
149
+ }, {});
122
150
  };
123
-
124
- // src/context.ts
125
151
  var getRouteParams = (params, config) => {
126
152
  if (config.schemas?.params) {
127
153
  const parsed = config.schemas.params.safeParse(params);
128
154
  if (!parsed.success) {
129
- throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid route parameters");
155
+ throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
130
156
  }
131
157
  return parsed.data;
132
158
  }
@@ -137,15 +163,12 @@ var getSearchParams = (url, config) => {
137
163
  if (config.schemas?.searchParams) {
138
164
  const parsed = config.schemas.searchParams.safeParse(Object.fromEntries(route.searchParams.entries()));
139
165
  if (!parsed.success) {
140
- throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid search parameters");
166
+ throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
141
167
  }
142
168
  return parsed.data;
143
169
  }
144
170
  return new URLSearchParams(route.searchParams.toString());
145
171
  };
146
- var getHeaders = (request) => {
147
- return new Headers(request.headers);
148
- };
149
172
  var getBody = async (request, config) => {
150
173
  if (!isSupportedBodyMethod(request.method)) {
151
174
  return null;
@@ -157,7 +180,7 @@ var getBody = async (request, config) => {
157
180
  if (config.schemas?.body) {
158
181
  const parsed = config.schemas.body.safeParse(json);
159
182
  if (!parsed.success) {
160
- throw new RouterError("UNPROCESSABLE_ENTITY", "Invalid request body");
183
+ throw new InvalidZodSchemaError("UNPROCESSABLE_ENTITY", formatZodError(parsed.error));
161
184
  }
162
185
  return parsed.data;
163
186
  }
@@ -186,6 +209,39 @@ var createContentTypeRegex = (contentTypes, contenType) => {
186
209
  return regex.test(contenType);
187
210
  };
188
211
 
212
+ // src/middlewares.ts
213
+ var executeGlobalMiddlewares = async (context, middlewares) => {
214
+ if (!middlewares) return context;
215
+ for (const middleware of middlewares) {
216
+ if (typeof middleware !== "function") {
217
+ throw new RouterError("BAD_REQUEST", "Global middlewares must be functions");
218
+ }
219
+ const executed = await middleware(context);
220
+ if (executed instanceof Response) {
221
+ return executed;
222
+ }
223
+ context = executed;
224
+ }
225
+ if (!context || !(context.request instanceof Request)) {
226
+ throw new RouterError("BAD_REQUEST", "Global middleware must return a Request or Response object");
227
+ }
228
+ return context;
229
+ };
230
+ var executeMiddlewares = async (context, middlewares = []) => {
231
+ try {
232
+ let ctx = context;
233
+ for (const middleware of middlewares) {
234
+ if (typeof middleware !== "function") {
235
+ throw new RouterError("BAD_REQUEST", "Middleware must be a function");
236
+ }
237
+ ctx = await middleware(ctx);
238
+ }
239
+ return ctx;
240
+ } catch {
241
+ throw new RouterError("BAD_REQUEST", "Handler threw an error");
242
+ }
243
+ };
244
+
189
245
  // src/router.ts
190
246
  var createNode = () => ({
191
247
  statics: /* @__PURE__ */ new Map(),
@@ -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 });
@@ -276,7 +343,7 @@ var handleRequest = async (method, request, config, root) => {
276
343
  const dynamicParams = getRouteParams(params, endpoint.config);
277
344
  const body = await getBody(globalRequestContext.request, endpoint.config);
278
345
  const searchParams = getSearchParams(globalRequestContext.request.url, endpoint.config);
279
- const headers = getHeaders(globalRequestContext.request);
346
+ const headers = new HeadersBuilder(globalRequestContext.request.headers);
280
347
  let context = {
281
348
  params: dynamicParams,
282
349
  searchParams,
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-CL5D7UJU.js";
7
- import "./chunk-PT4GU6PH.js";
8
- import "./chunk-JNMXLKDG.js";
9
- import "./chunk-CFAIW6YL.js";
10
- import "./chunk-GJC3ODME.js";
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.
@@ -102,7 +104,7 @@ type ContextParams<Schemas extends EndpointConfig["schemas"], Default = Record<s
102
104
  */
103
105
  interface RequestContext<RouteParams = Record<string, string>, Config extends EndpointConfig = EndpointConfig> {
104
106
  params: ContextParams<Config["schemas"], RouteParams>["params"];
105
- headers: Headers;
107
+ headers: HeadersBuilder;
106
108
  body: ContextBody<Config["schemas"]>["body"];
107
109
  searchParams: ContextSearchParams<Config["schemas"]>["searchParams"];
108
110
  request: Request;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aura-stack/router",
3
- "version": "0.4.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
6
  "repository": {
@@ -50,6 +50,16 @@
50
50
  "import": "./dist/error.js",
51
51
  "require": "./dist/error.cjs"
52
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
+ },
53
63
  "./types": "./dist/types.d.ts"
54
64
  },
55
65
  "devDependencies": {
@@ -59,6 +69,9 @@
59
69
  "vitest": "^3.2.4",
60
70
  "zod": "^4.1.11"
61
71
  },
72
+ "dependencies": {
73
+ "cookie": "^1.1.1"
74
+ },
62
75
  "scripts": {
63
76
  "dev": "tsup --watch",
64
77
  "dev:docs": "pnpm --filter docs dev",