@visulima/connect 1.3.4 → 1.3.6

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/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## @visulima/connect [1.3.6](https://github.com/visulima/visulima/compare/@visulima/connect@1.3.5...@visulima/connect@1.3.6) (2023-06-06)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Add npm package provenance, see https://docs.npmjs.com/generating-provenance-statements for more info ([9e7da04](https://github.com/visulima/visulima/commit/9e7da0491584e16a806fc7575c00080f192ec15e))
7
+
8
+ ## @visulima/connect [1.3.5](https://github.com/visulima/visulima/compare/@visulima/connect@1.3.4...@visulima/connect@1.3.5) (2023-05-30)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **nextra-theme-docs:** updates theme to be nextra compatible ([#87](https://github.com/visulima/visulima/issues/87)) ([b9fbeb2](https://github.com/visulima/visulima/commit/b9fbeb2e59d842a8755b0c8f19a67f93778ba979))
14
+
1
15
  ## @visulima/connect [1.3.4](https://github.com/visulima/visulima/compare/@visulima/connect@1.3.3...@visulima/connect@1.3.4) (2023-05-25)
2
16
 
3
17
 
package/README.md CHANGED
@@ -3,10 +3,9 @@
3
3
  <p>
4
4
  The promise-based method routing and middleware layer with zod validation for <a href="https://nextjs.org/" title="Next.js">Next.js</a> (API Routes, Edge API Routes, getServerSideProps, Middleware) and many other frameworks is built on top of
5
5
 
6
- [next-connect](https://github.com/hoangvvo/next-connect),
7
- [http-errors](https://github.com/jshttp/http-errors),
8
- [regexparam](https://github.com/lukeed/regexparam)
9
-
6
+ [next-connect](https://github.com/hoangvvo/next-connect),
7
+ [http-errors](https://github.com/jshttp/http-errors),
8
+ [regexparam](https://github.com/lukeed/regexparam)
10
9
 
11
10
  </p>
12
11
  </div>
@@ -33,11 +32,11 @@
33
32
 
34
33
  ## Features
35
34
 
36
- - Async middleware
37
- - [Lightweight](https://bundlephobia.com/scan-results?packages=express,@visulima/connect,koa,micro) => Suitable for serverless environment
38
- - [way faster](https://github.com/visulima/packages/connect/tree/main/bench) than Express.js. Compatible with Express.js via [a wrapper](#expressjs-compatibility).
39
- - Works with async handlers (with error catching)
40
- - TypeScript support
35
+ - Async middleware
36
+ - [Lightweight](https://bundlephobia.com/scan-results?packages=express,@visulima/connect,koa,micro) => Suitable for serverless environment
37
+ - [way faster](https://github.com/visulima/packages/connect/tree/main/bench) than Express.js. Compatible with Express.js via [a wrapper](#expressjs-compatibility).
38
+ - Works with async handlers (with error catching)
39
+ - TypeScript support
41
40
 
42
41
  ## Installation
43
42
 
@@ -72,44 +71,44 @@ import cors from "cors";
72
71
  // Default Req and Res are IncomingMessage and ServerResponse
73
72
  // You may want to pass in NextApiRequest and NextApiResponse
74
73
  const router = createNodeRouter<NextApiRequest, NextApiResponse>({
75
- onError: (err, req, res) => {
76
- console.error(err.stack);
77
- res.status(500).end("Something broke!");
78
- },
79
- onNoMatch: (req, res) => {
80
- res.status(404).end("Page is not found");
81
- },
74
+ onError: (err, req, res) => {
75
+ console.error(err.stack);
76
+ res.status(500).end("Something broke!");
77
+ },
78
+ onNoMatch: (req, res) => {
79
+ res.status(404).end("Page is not found");
80
+ },
82
81
  });
83
82
 
84
83
  router
85
- .use(expressWrapper(cors())) // express middleware are supported if you wrap it with expressWrapper
86
- .use(async (req, res, next) => {
87
- const start = Date.now();
88
- await next(); // call next in chain
89
- const end = Date.now();
90
- console.log(`Request took ${end - start}ms`);
91
- })
92
- .get((req, res) => {
93
- res.send("Hello world");
94
- })
95
- .post(async (req, res) => {
96
- // use async/await
97
- const user = await insertUser(req.body.user);
98
- res.json({ user });
99
- })
100
- .put(
101
- async (req, res, next) => {
102
- // You may want to pass in NextApiRequest & { isLoggedIn: true }
103
- // in createNodeRouter generics to define this extra property
104
- if (!req.isLoggedIn) throw new Error("thrown stuff will be caught");
105
- // go to the next in chain
106
- return next();
107
- },
108
- async (req, res) => {
109
- const user = await updateUser(req.body.user);
110
- res.json({ user });
111
- }
112
- );
84
+ .use(expressWrapper(cors())) // express middleware are supported if you wrap it with expressWrapper
85
+ .use(async (req, res, next) => {
86
+ const start = Date.now();
87
+ await next(); // call next in chain
88
+ const end = Date.now();
89
+ console.log(`Request took ${end - start}ms`);
90
+ })
91
+ .get((req, res) => {
92
+ res.send("Hello world");
93
+ })
94
+ .post(async (req, res) => {
95
+ // use async/await
96
+ const user = await insertUser(req.body.user);
97
+ res.json({ user });
98
+ })
99
+ .put(
100
+ async (req, res, next) => {
101
+ // You may want to pass in NextApiRequest & { isLoggedIn: true }
102
+ // in createNodeRouter generics to define this extra property
103
+ if (!req.isLoggedIn) throw new Error("thrown stuff will be caught");
104
+ // go to the next in chain
105
+ return next();
106
+ },
107
+ async (req, res) => {
108
+ const user = await updateUser(req.body.user);
109
+ res.json({ user });
110
+ },
111
+ );
113
112
 
114
113
  export default router.nodeHandler();
115
114
  ```
@@ -121,45 +120,45 @@ export default router.nodeHandler();
121
120
  import { createNodeRouter } from "@visulima/connect";
122
121
 
123
122
  export default function Page({ user, updated }) {
124
- return (
125
- <div>
126
- {updated && <p>User has been updated</p>}
127
- <div>{JSON.stringify(user)}</div>
128
- <form method="POST">{/* User update form */}</form>
129
- </div>
130
- );
123
+ return (
124
+ <div>
125
+ {updated && <p>User has been updated</p>}
126
+ <div>{JSON.stringify(user)}</div>
127
+ <form method="POST">{/* User update form */}</form>
128
+ </div>
129
+ );
131
130
  }
132
131
 
133
132
  const router = createNodeRouter()
134
- .use(async (req, res, next) => {
135
- // this serve as the error handling middleware
136
- try {
137
- return await next();
138
- } catch (e) {
139
- return {
140
- props: { error: e.message },
141
- };
142
- }
143
- })
144
- .use(async (req, res, next) => {
145
- logRequest(req);
146
- return next();
147
- })
148
- .get(async (req, res) => {
149
- const user = await getUser(req.params.id);
150
- if (!user) {
151
- // https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props#notfound
152
- return { props: { notFound: true } };
153
- }
154
- return { props: { user } };
155
- })
156
- .post(async (req, res) => {
157
- const user = await updateUser(req);
158
- return { props: { user, updated: true } };
159
- });
133
+ .use(async (req, res, next) => {
134
+ // this serve as the error handling middleware
135
+ try {
136
+ return await next();
137
+ } catch (e) {
138
+ return {
139
+ props: { error: e.message },
140
+ };
141
+ }
142
+ })
143
+ .use(async (req, res, next) => {
144
+ logRequest(req);
145
+ return next();
146
+ })
147
+ .get(async (req, res) => {
148
+ const user = await getUser(req.params.id);
149
+ if (!user) {
150
+ // https://nextjs.org/docs/api-reference/data-fetching/get-server-side-props#notfound
151
+ return { props: { notFound: true } };
152
+ }
153
+ return { props: { user } };
154
+ })
155
+ .post(async (req, res) => {
156
+ const user = await updateUser(req);
157
+ return { props: { user, updated: true } };
158
+ });
160
159
 
161
160
  export async function getServerSideProps({ req, res }) {
162
- return router.run(req, res);
161
+ return router.run(req, res);
163
162
  }
164
163
  ```
165
164
 
@@ -175,50 +174,50 @@ import cors from "cors";
175
174
  // Default Req and Evt are Request and unknown
176
175
  // You may want to pass in NextRequest and NextFetchEvent
177
176
  const router = createEdgeRouter<NextRequest, NextFetchEvent>({
178
- onError: (err, req, evt) => {
179
- console.error(err.stack);
180
- return new NextResponse("Something broke!", {
181
- status: 500,
182
- });
183
- },
184
- onNoMatch: (req, res) => {
185
- return new NextResponse("Page is not found", {
186
- status: 404,
187
- });
188
- },
177
+ onError: (err, req, evt) => {
178
+ console.error(err.stack);
179
+ return new NextResponse("Something broke!", {
180
+ status: 500,
181
+ });
182
+ },
183
+ onNoMatch: (req, res) => {
184
+ return new NextResponse("Page is not found", {
185
+ status: 404,
186
+ });
187
+ },
189
188
  });
190
189
 
191
190
  router
192
- .use(expressWrapper(cors())) // express middleware are supported if you wrap it with expressWrapper
193
- .use(async (req, evt, next) => {
194
- const start = Date.now();
195
- await next(); // call next in chain
196
- const end = Date.now();
197
- console.log(`Request took ${end - start}ms`);
198
- })
199
- .get((req, res) => {
200
- return new Response("Hello world");
201
- })
202
- .post(async (req, res) => {
203
- // use async/await
204
- const user = await insertUser(req.body.user);
205
- res.json({ user });
206
- return new Response(JSON.stringify({ user }), {
207
- status: 200,
208
- headerList: {
209
- "content-type": "application/json",
210
- },
211
- });
212
- })
213
- .put(async (req, res) => {
214
- const user = await updateUser(req.body.user);
215
- return new Response(JSON.stringify({ user }), {
216
- status: 200,
217
- headerList: {
218
- "content-type": "application/json",
219
- },
191
+ .use(expressWrapper(cors())) // express middleware are supported if you wrap it with expressWrapper
192
+ .use(async (req, evt, next) => {
193
+ const start = Date.now();
194
+ await next(); // call next in chain
195
+ const end = Date.now();
196
+ console.log(`Request took ${end - start}ms`);
197
+ })
198
+ .get((req, res) => {
199
+ return new Response("Hello world");
200
+ })
201
+ .post(async (req, res) => {
202
+ // use async/await
203
+ const user = await insertUser(req.body.user);
204
+ res.json({ user });
205
+ return new Response(JSON.stringify({ user }), {
206
+ status: 200,
207
+ headerList: {
208
+ "content-type": "application/json",
209
+ },
210
+ });
211
+ })
212
+ .put(async (req, res) => {
213
+ const user = await updateUser(req.body.user);
214
+ return new Response(JSON.stringify({ user }), {
215
+ status: 200,
216
+ headerList: {
217
+ "content-type": "application/json",
218
+ },
219
+ });
220
220
  });
221
- });
222
221
 
223
222
  export default router.nodeHandler();
224
223
  ```
@@ -238,28 +237,28 @@ import { createEdgeRouter } from "@visulima/connect";
238
237
  const router = createEdgeRouter<NextRequest, NextFetchEvent>();
239
238
 
240
239
  router.use(async (request, _, next) => {
241
- await logRequest(request);
242
- return next();
240
+ await logRequest(request);
241
+ return next();
243
242
  });
244
243
 
245
244
  router.get("/about", (request) => {
246
- return NextResponse.redirect(new URL("/about-2", request.url));
245
+ return NextResponse.redirect(new URL("/about-2", request.url));
247
246
  });
248
247
 
249
248
  router.use("/dashboard", (request) => {
250
- if (!isAuthenticated(request)) {
251
- return NextResponse.redirect(new URL("/login", request.url));
252
- }
253
- return NextResponse.next();
249
+ if (!isAuthenticated(request)) {
250
+ return NextResponse.redirect(new URL("/login", request.url));
251
+ }
252
+ return NextResponse.next();
254
253
  });
255
254
 
256
255
  router.all((request) => {
257
- // default if none of the above matches
258
- return NextResponse.next();
256
+ // default if none of the above matches
257
+ return NextResponse.next();
259
258
  });
260
259
 
261
260
  export function middleware(request: NextRequest) {
262
- return NextResponse.redirect(new URL("/about-2", request.url));
261
+ return NextResponse.redirect(new URL("/about-2", request.url));
263
262
  }
264
263
  ```
265
264
 
@@ -277,8 +276,8 @@ Create an instance Node.js router.
277
276
 
278
277
  `fn`(s) can either be:
279
278
 
280
- - functions of `(req, res[, next])`
281
- - **or** a router instance
279
+ - functions of `(req, res[, next])`
280
+ - **or** a router instance
282
281
 
283
282
  ```javascript
284
283
  // Mount a middleware function
@@ -294,11 +293,7 @@ router2.use("/foo", fn); // Only run in /foo/**
294
293
  // mount an instance of router
295
294
  const sub1 = createNodeRouter().use(fn1, fn2);
296
295
  const sub2 = createNodeRouter().use("/dashboard", auth);
297
- const sub3 = createNodeRouter()
298
- .use("/waldo", subby)
299
- .get(getty)
300
- .post("/baz", posty)
301
- .put("/", putty);
296
+ const sub3 = createNodeRouter().use("/waldo", subby).get(getty).post("/baz", posty).put("/", putty);
302
297
  router3
303
298
  // - fn1 and fn2 always run
304
299
  // - auth runs only on /dashboard
@@ -320,20 +315,20 @@ router3
320
315
 
321
316
  ```javascript
322
317
  router.get("/api/user", (req, res, next) => {
323
- res.json(req.user);
318
+ res.json(req.user);
324
319
  });
325
320
  router.post("/api/users", (req, res, next) => {
326
- res.end("User created");
321
+ res.end("User created");
327
322
  });
328
323
  router.put("/api/user/:id", (req, res, next) => {
329
- // https://nextjs.org/docs/routing/dynamic-routes
330
- res.end(`User ${req.params.id} updated`);
324
+ // https://nextjs.org/docs/routing/dynamic-routes
325
+ res.end(`User ${req.params.id} updated`);
331
326
  });
332
327
 
333
328
  // Next.js already handles routing (including dynamic routes), we often
334
329
  // omit `pattern` in `.METHOD`
335
330
  router.get((req, res, next) => {
336
- res.end("This matches whatever route");
331
+ res.end("This matches whatever route");
337
332
  });
338
333
  ```
339
334
 
@@ -361,7 +356,7 @@ function onError(err, req, res) {
361
356
  res.status(500).end("Internal server error");
362
357
  }
363
358
 
364
- const router = createNodeRouter({onError});
359
+ const router = createNodeRouter({ onError });
365
360
 
366
361
  export default router.nodeHandler();
367
362
  ```
@@ -376,7 +371,7 @@ function onNoMatch(req, res) {
376
371
  res.status(404).end("page is not found... or is it!?");
377
372
  }
378
373
 
379
- const router = createNodeRouter({onNoMatch});
374
+ const router = createNodeRouter({ onNoMatch });
380
375
 
381
376
  export default router.nodeHandler();
382
377
  ```
@@ -387,15 +382,15 @@ Runs `req` and `res` through the middleware chain and returns a **promise**. It
387
382
 
388
383
  ```js
389
384
  router
390
- .use(async (req, res, next) => {
391
- return (await next()) + 1;
392
- })
393
- .use(async () => {
394
- return (await next()) + 2;
395
- })
396
- .use(async () => {
397
- return 3;
398
- });
385
+ .use(async (req, res, next) => {
386
+ return (await next()) + 1;
387
+ })
388
+ .use(async () => {
389
+ return (await next()) + 2;
390
+ })
391
+ .use(async () => {
392
+ return 3;
393
+ });
399
394
 
400
395
  console.log(await router.run(req, res));
401
396
  // The above will print "6"
@@ -405,10 +400,10 @@ If an error in thrown within the chain, `router.run` will reject. You can also a
405
400
 
406
401
  ```js
407
402
  router
408
- .use(async (req, res, next) => {
409
- return next().catch(errorHandler);
410
- })
411
- .use(thisMiddlewarewareMightThrow);
403
+ .use(async (req, res, next) => {
404
+ return next().catch(errorHandler);
405
+ })
406
+ .use(thisMiddlewarewareMightThrow);
412
407
 
413
408
  await router.run(req, res);
414
409
  ```
@@ -424,56 +419,56 @@ If `next()` is not awaited, errors will not be caught if they are thrown in asyn
424
419
  ```javascript
425
420
  // OK: we don't use async so no need to await
426
421
  router
427
- .use((req, res, next) => {
428
- next();
429
- })
430
- .use((req, res, next) => {
431
- next();
432
- })
433
- .use(() => {
434
- throw new Error("💥");
435
- });
422
+ .use((req, res, next) => {
423
+ next();
424
+ })
425
+ .use((req, res, next) => {
426
+ next();
427
+ })
428
+ .use(() => {
429
+ throw new Error("💥");
430
+ });
436
431
 
437
432
  // BAD: This will lead to UnhandledPromiseRejection
438
433
  router
439
- .use(async (req, res, next) => {
440
- next();
441
- })
442
- .use(async (req, res, next) => {
443
- next();
444
- })
445
- .use(async () => {
446
- throw new Error("💥");
447
- });
434
+ .use(async (req, res, next) => {
435
+ next();
436
+ })
437
+ .use(async (req, res, next) => {
438
+ next();
439
+ })
440
+ .use(async () => {
441
+ throw new Error("💥");
442
+ });
448
443
 
449
444
  // GOOD
450
445
  router
451
- .use(async (req, res, next) => {
452
- await next(); // next() is awaited, so errors are caught properly
453
- })
454
- .use((req, res, next) => {
455
- return next(); // this works as well since we forward the rejected promise
456
- })
457
- .use(async () => {
458
- throw new Error("💥");
459
- // return new Promise.reject("💥");
460
- });
446
+ .use(async (req, res, next) => {
447
+ await next(); // next() is awaited, so errors are caught properly
448
+ })
449
+ .use((req, res, next) => {
450
+ return next(); // this works as well since we forward the rejected promise
451
+ })
452
+ .use(async () => {
453
+ throw new Error("💥");
454
+ // return new Promise.reject("💥");
455
+ });
461
456
  ```
462
457
 
463
458
  Another issue is that the nodeHandler would resolve before all the code in each layer runs.
464
459
 
465
460
  ```javascript
466
461
  const nodeHandler = router
467
- .use(async (req, res, next) => {
468
- next(); // this is not returned or await
469
- })
470
- .get(async () => {
471
- // simulate a long task
472
- await new Promise((resolve) => setTimeout(resolve, 1000));
473
- res.send("ok");
474
- console.log("request is completed");
475
- })
476
- .nodeHandler();
462
+ .use(async (req, res, next) => {
463
+ next(); // this is not returned or await
464
+ })
465
+ .get(async () => {
466
+ // simulate a long task
467
+ await new Promise((resolve) => setTimeout(resolve, 1000));
468
+ res.send("ok");
469
+ console.log("request is completed");
470
+ })
471
+ .nodeHandler();
477
472
 
478
473
  await nodeHandler(req, res);
479
474
  console.log("finally"); // this will run before the get layer gets to finish
@@ -533,7 +528,7 @@ const nodeHandler = createNodeRouter()
533
528
  res.end("bar");
534
529
  });
535
530
 
536
- export async function getServerSideProps({req, res}) {
531
+ export async function getServerSideProps({ req, res }) {
537
532
  await router.run(req, res);
538
533
  return {
539
534
  props: {},
@@ -548,7 +543,7 @@ export async function getServerSideProps({req, res}) {
548
543
  const router = createNodeRouter().use(foo).use(bar);
549
544
  const nodeHandler = router.nodeHandler();
550
545
 
551
- export async function getServerSideProps({req, res}) {
546
+ export async function getServerSideProps({ req, res }) {
552
547
  await nodeHandler(req, res); // BAD: You should call router.run(req, res);
553
548
  return {
554
549
  props: {},
@@ -572,10 +567,10 @@ If you need to create all handlers for all routes in one file (similar to `Expre
572
567
  import { createNodeRouter } from "@visulima/connect";
573
568
 
574
569
  const router = createNodeRouter()
575
- .use("/api/hello", someMiddleware())
576
- .get("/api/user/:userId", (req, res) => {
577
- res.send(`Hello ${req.params.userId}`);
578
- });
570
+ .use("/api/hello", someMiddleware())
571
+ .get("/api/user/:userId", (req, res) => {
572
+ res.send(`Hello ${req.params.userId}`);
573
+ });
579
574
 
580
575
  export default router.nodeHandler();
581
576
  ```
package/dist/index.js CHANGED
@@ -1,23 +1,23 @@
1
1
  'use strict';
2
2
 
3
- var N = require('http-errors');
3
+ var q = require('http-errors');
4
4
  var zod = require('zod');
5
5
  var regexparam = require('regexparam');
6
6
 
7
7
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
8
 
9
- var N__default = /*#__PURE__*/_interopDefault(N);
9
+ var q__default = /*#__PURE__*/_interopDefault(q);
10
10
 
11
- var M=Object.defineProperty;var S=(o,e,t)=>e in o?M(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var a=(o,e,t)=>(S(o,typeof e!="symbol"?e+"":e,t),t);var E=(o,e)=>async(t,s,n)=>{let r=t;try{r=await o.parseAsync(t);}catch(d){let{message:u}=d;throw d instanceof zod.ZodError&&typeof d.format=="function"&&(u=d.issues.map(p=>`${p.path.join("/")} - ${p.message}`).join("/n")),N__default.default(422,u)}return e(r,s,n)},x=E;var i=class{constructor(e="/",t=[]){this.base=e;this.routes=t;}add(e,t,...s){if(typeof t=="function"&&(s.unshift(t),t=""),t==="")this.routes.push({matchAll:!0,method:e,fns:s,isMiddleware:!1});else {let{keys:n,pattern:r}=regexparam.parse(t);this.routes.push({keys:n,pattern:r,method:e,fns:s,isMiddleware:!1});}return this}use(e,...t){(typeof e=="function"||e instanceof i)&&(t.unshift(e),e="/"),t=t.map(r=>{if(r instanceof i){if(typeof e=="string")return r.clone(e);throw new Error("Mounting a router to RegExp base is not supported")}return r});let{keys:s,pattern:n}=regexparam.parse(e,!0);return this.routes.push({keys:s,pattern:n,method:"",fns:t,isMiddleware:!0}),this}clone(e){return new i(e,[...this.routes])}static async exec(e,...t){let s=0,n=()=>e[++s](...t,n);return e[s](...t,n)}find(e,t){let s=!0,n=[],r={},d=e==="HEAD";return Object.values(this.routes).forEach(u=>{if(u.method!==e&&u.method!==""&&!(d&&u.method==="GET"))return;let p=!1;if("matchAll"in u)p=!0;else if(u.keys===!1){let R=u.pattern.exec(t);if(R===null)return;R.groups!==void 0&&Object.keys(R.groups).forEach(l=>{r[l]=R.groups[l];}),p=!0;}else if(u.keys.length>0){let R=u.pattern.exec(t);if(R===null)return;for(let l=0;l<u.keys.length;){let m=u.keys[l];r[m]=R[++l];}p=!0;}else u.pattern.test(t)&&(p=!0);p&&(n.push(...u.fns.flatMap(R=>{if(R instanceof i){let{base:l}=R,m=t.slice(l.length);m.startsWith("/")||(m=`/${m}`);let f=R.find(e,m);return f.middleOnly||(s=!1),Object.assign(r,f.params),f.fns}return R})),u.isMiddleware||(s=!1));}),{fns:n,params:r,middleOnly:s}}};var k=async o=>new Response(o.method==="HEAD"?null:`Route ${o.method} ${o.url} not found`,{status:404}),C=async o=>(console.error(o),new Response("Internal Server Error",{status:500}));function y(o){return (o.nextUrl??new URL(o.url)).pathname}var c=class{constructor(e={}){a(this,"router",new i);a(this,"onNoMatch");a(this,"onError");a(this,"all",this.add.bind(this,""));a(this,"get",this.add.bind(this,"GET"));a(this,"head",this.add.bind(this,"HEAD"));a(this,"post",this.add.bind(this,"POST"));a(this,"put",this.add.bind(this,"PUT"));a(this,"patch",this.add.bind(this,"PATCH"));a(this,"delete",this.add.bind(this,"DELETE"));this.onNoMatch=e.onNoMatch??k,this.onError=e.onError??C;}add(e,t,s,...n){return typeof t=="string"&&typeof s=="function"?n=[s]:typeof s=="object"?typeof t=="function"?n=[x(s,t)]:n=n.map(r=>x(s,r)):typeof s=="function"&&(n=[s]),this.router.add(e,t,...n),this}use(e,...t){return (typeof e=="function"||e instanceof c)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof c?s.router:s)),this}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new c({onNoMatch:this.onNoMatch,onError:this.onError});return e.router=this.router.clone(),e}async run(e,t){let s=this.router.find(e.method,y(e));if(s.fns.length!==0)return this.prepareRequest(e,s),i.exec(s.fns,e,t)}handler(){let{routes:e}=this.router;return async(t,s)=>{let n=this.router.find(t.method,y(t));this.prepareRequest(t,n);try{return await(n.fns.length===0||n.middleOnly?this.onNoMatch(t,s,e):i.exec(n.fns,t,s))}catch(r){return this.onError(r,t,s,e)}}}};function w(o={}){return new c(o)}var v=o=>(e,t,s)=>new Promise((n,r)=>{o(e,t,d=>d?r(d):n());}).then(s),L=v;var j=async(o,e)=>{e.statusCode=404,e.end(o.method==="HEAD"?void 0:`Route ${o.method} ${o.url} not found`);},P=async(o,e,t)=>{t.statusCode=500,console.error(o),t.end("Internal Server Error");};function b(o){let e=o.indexOf("?");return e===-1?o:o.slice(0,Math.max(0,e))}var h=class{constructor(e={}){a(this,"router",new i);a(this,"onNoMatch");a(this,"onError");a(this,"all",this.add.bind(this,""));a(this,"get",this.add.bind(this,"GET"));a(this,"head",this.add.bind(this,"HEAD"));a(this,"post",this.add.bind(this,"POST"));a(this,"put",this.add.bind(this,"PUT"));a(this,"patch",this.add.bind(this,"PATCH"));a(this,"delete",this.add.bind(this,"DELETE"));this.onNoMatch=e.onNoMatch??j,this.onError=e.onError??P;}add(e,t,s,...n){return typeof t=="string"&&typeof s=="function"?n=[s]:typeof s=="object"?typeof t=="function"?n=[x(s,t)]:n=n.map(r=>x(s,r)):typeof s=="function"&&(n=[s]),this.router.add(e,t,...n),this}use(e,...t){return (typeof e=="function"||e instanceof h)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof h?s.router:s)),this}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new h({onNoMatch:this.onNoMatch,onError:this.onError});return e.router=this.router.clone(),e}async run(e,t){let s=this.router.find(e.method,b(e.url));if(s.fns.length!==0)return this.prepareRequest(e,s),i.exec(s.fns,e,t)}handler(){let{routes:e}=this.router;return async(t,s)=>{let n=this.router.find(t.method,b(t.url));this.prepareRequest(t,n);try{await(n.fns.length===0||n.middleOnly?this.onNoMatch(t,s,e):i.exec(n.fns,t,s));}catch(r){await this.onError(r,t,s,e);}}}},q=(o={})=>new h(o);var Z=(o,e,t)=>{o.setHeader("content-type","application/json; charset=utf-8"),o.statusCode=e,o.end(JSON.stringify(t,null,2));},A=Z;
11
+ var S=(o,e)=>async(t,s,n)=>{let r=t;try{r=await o.parseAsync(t);}catch(R){let{message:a}=R;throw R instanceof zod.ZodError&&typeof R.format=="function"&&(a=R.issues.map(d=>`${d.path.join("/")} - ${d.message}`).join("/n")),q__default.default(422,a)}return e(r,s,n)},h=S;var u=class{constructor(e="/",t=[]){this.base=e;this.routes=t;}add(e,t,...s){if(typeof t=="function"&&(s.unshift(t),t=""),t==="")this.routes.push({matchAll:!0,method:e,fns:s,isMiddleware:!1});else {let{keys:n,pattern:r}=regexparam.parse(t);this.routes.push({keys:n,pattern:r,method:e,fns:s,isMiddleware:!1});}return this}use(e,...t){(typeof e=="function"||e instanceof u)&&(t.unshift(e),e="/"),t=t.map(r=>{if(r instanceof u){if(typeof e=="string")return r.clone(e);throw new Error("Mounting a router to RegExp base is not supported")}return r});let{keys:s,pattern:n}=regexparam.parse(e,!0);return this.routes.push({keys:s,pattern:n,method:"",fns:t,isMiddleware:!0}),this}clone(e){return new u(e,[...this.routes])}static async exec(e,...t){let s=0,n=()=>e[++s](...t,n);return e[s](...t,n)}find(e,t){let s=!0,n=[],r={},R=e==="HEAD";return Object.values(this.routes).forEach(a=>{if(a.method!==e&&a.method!==""&&!(R&&a.method==="GET"))return;let d=!1;if("matchAll"in a)d=!0;else if(a.keys===!1){let i=a.pattern.exec(t);if(i===null)return;i.groups!==void 0&&Object.keys(i.groups).forEach(p=>{r[p]=i.groups[p];}),d=!0;}else if(a.keys.length>0){let i=a.pattern.exec(t);if(i===null)return;for(let p=0;p<a.keys.length;){let x=a.keys[p];r[x]=i[++p];}d=!0;}else a.pattern.test(t)&&(d=!0);d&&(n.push(...a.fns.flatMap(i=>{if(i instanceof u){let{base:p}=i,x=t.slice(p.length);x.startsWith("/")||(x=`/${x}`);let m=i.find(e,x);return m.middleOnly||(s=!1),Object.assign(r,m.params),m.fns}return i})),a.isMiddleware||(s=!1));}),{fns:n,params:r,middleOnly:s}}};var N=async o=>new Response(o.method==="HEAD"?null:`Route ${o.method} ${o.url} not found`,{status:404}),g=async o=>(console.error(o),new Response("Internal Server Error",{status:500}));function H(o){return (o.nextUrl??new URL(o.url)).pathname}var l=class{constructor(e={}){this.router=new u;this.all=this.add.bind(this,"");this.get=this.add.bind(this,"GET");this.head=this.add.bind(this,"HEAD");this.post=this.add.bind(this,"POST");this.put=this.add.bind(this,"PUT");this.patch=this.add.bind(this,"PATCH");this.delete=this.add.bind(this,"DELETE");this.onNoMatch=e.onNoMatch??N,this.onError=e.onError??g;}add(e,t,s,...n){return typeof t=="string"&&typeof s=="function"?n=[s]:typeof s=="object"?typeof t=="function"?n=[h(s,t)]:n=n.map(r=>h(s,r)):typeof s=="function"&&(n=[s]),this.router.add(e,t,...n),this}use(e,...t){return (typeof e=="function"||e instanceof l)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof l?s.router:s)),this}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new l({onNoMatch:this.onNoMatch,onError:this.onError});return e.router=this.router.clone(),e}async run(e,t){let s=this.router.find(e.method,H(e));if(s.fns.length!==0)return this.prepareRequest(e,s),u.exec(s.fns,e,t)}handler(){let{routes:e}=this.router;return async(t,s)=>{let n=this.router.find(t.method,H(t));this.prepareRequest(t,n);try{return await(n.fns.length===0||n.middleOnly?this.onNoMatch(t,s,e):u.exec(n.fns,t,s))}catch(r){return this.onError(r,t,s,e)}}}};function E(o={}){return new l(o)}var k=o=>(e,t,s)=>new Promise((n,r)=>{o(e,t,R=>R?r(R):n());}).then(s),C=k;var w=async(o,e)=>{e.statusCode=404,e.end(o.method==="HEAD"?void 0:`Route ${o.method} ${o.url} not found`);},v=async(o,e,t)=>{t.statusCode=500,console.error(o),t.end("Internal Server Error");};function y(o){let e=o.indexOf("?");return e===-1?o:o.slice(0,Math.max(0,e))}var c=class{constructor(e={}){this.router=new u;this.all=this.add.bind(this,"");this.get=this.add.bind(this,"GET");this.head=this.add.bind(this,"HEAD");this.post=this.add.bind(this,"POST");this.put=this.add.bind(this,"PUT");this.patch=this.add.bind(this,"PATCH");this.delete=this.add.bind(this,"DELETE");this.onNoMatch=e.onNoMatch??w,this.onError=e.onError??v;}add(e,t,s,...n){return typeof t=="string"&&typeof s=="function"?n=[s]:typeof s=="object"?typeof t=="function"?n=[h(s,t)]:n=n.map(r=>h(s,r)):typeof s=="function"&&(n=[s]),this.router.add(e,t,...n),this}use(e,...t){return (typeof e=="function"||e instanceof c)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof c?s.router:s)),this}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new c({onNoMatch:this.onNoMatch,onError:this.onError});return e.router=this.router.clone(),e}async run(e,t){let s=this.router.find(e.method,y(e.url));if(s.fns.length!==0)return this.prepareRequest(e,s),u.exec(s.fns,e,t)}handler(){let{routes:e}=this.router;return async(t,s)=>{let n=this.router.find(t.method,y(t.url));this.prepareRequest(t,n);try{await(n.fns.length===0||n.middleOnly?this.onNoMatch(t,s,e):u.exec(n.fns,t,s));}catch(r){await this.onError(r,t,s,e);}}}},b=(o={})=>new c(o);var L=(o,e,t)=>{o.setHeader("content-type","application/json; charset=utf-8"),o.statusCode=e,o.end(JSON.stringify(t,null,2));},j=L;
12
12
 
13
- exports.EdgeRouter = c;
14
- exports.NodeRouter = h;
15
- exports.Router = i;
16
- exports.createEdgeRouter = w;
17
- exports.createNodeRouter = q;
18
- exports.createRouter = q;
19
- exports.expressWrapper = L;
20
- exports.sendJson = A;
21
- exports.withZod = x;
13
+ exports.EdgeRouter = l;
14
+ exports.NodeRouter = c;
15
+ exports.Router = u;
16
+ exports.createEdgeRouter = E;
17
+ exports.createNodeRouter = b;
18
+ exports.createRouter = b;
19
+ exports.expressWrapper = C;
20
+ exports.sendJson = j;
21
+ exports.withZod = h;
22
22
  //# sourceMappingURL=out.js.map
23
23
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapter/with-zod.ts","../src/router.ts","../src/edge.ts","../src/adapter/express.ts","../src/node.ts","../src/utils/send-json.ts"],"names":["createHttpError","ZodError","withZod","schema","handler","request","response","next","transformedRequest","error","message","issue","with_zod_default","parse","Router","base","routes","method","route","fns","keys","pattern","function_","arguments_","index","pathname","middleOnly","parameters","isHead","matched","matches","key","parameterKey","stripPathname","result","onNoMatch","onError","getPathname","EdgeRouter","options","__publicField","routeOrFunction","zodOrRouteOrFunction","findResult","r","context_","createEdgeRouter","expressWrapper","resolve","reject","express_default","_request","url","queryIndex","NodeRouter","createRouter","sendJson","statusCode","jsonBody","send_json_default"],"mappings":"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","sourcesContent":["import createHttpError from \"http-errors\";\nimport type { AnyZodObject, ZodObject } from \"zod\";\nimport { ZodError } from \"zod\";\n\nimport type { Nextable, NextHandler } from \"../types\";\n\nconst withZod = <\n Request,\n Response,\n Handler extends Nextable<any>,\n Schema extends ZodObject<{ body?: AnyZodObject; headers?: AnyZodObject; query?: AnyZodObject }>,\n >(\n schema: Schema,\n handler: Handler,\n ): ((request: Request, response: Response, next: NextHandler) => Promise<Response>) => async (request: Request, response: Response, next) => {\n let transformedRequest: Request = request;\n\n try {\n transformedRequest = (await schema.parseAsync(request)) as Request;\n } catch (error: any) {\n let { message } = error;\n\n // eslint-disable-next-line unicorn/consistent-destructuring\n if (error instanceof ZodError && typeof error.format === \"function\") {\n // eslint-disable-next-line unicorn/consistent-destructuring\n message = error.issues.map((issue) => `${issue.path.join(\"/\")} - ${issue.message}`).join(\"/n\");\n }\n\n throw createHttpError(422, message);\n }\n\n return handler(transformedRequest, response, next);\n };\n\nexport default withZod;\n","/**\n * Agnostic router class\n * Adapted from lukeed/trouter library:\n * https://github.com/lukeed/trouter/blob/master/index.mjs\n */\nimport { parse } from \"regexparam\";\n\nimport type {\n FindResult, FunctionLike, HttpMethod, Nextable, RouteMatch,\n} from \"./types\";\n\nexport type Route<H> = {\n method: HttpMethod | \"\";\n fns: (H | Router<H extends FunctionLike ? H : never>)[];\n isMiddleware: boolean;\n} & (\n | {\n keys: string[] | false;\n pattern: RegExp;\n }\n | { matchAll: true }\n);\n\nexport class Router<H extends FunctionLike> {\n public constructor(public base: string = \"/\", public routes: Route<Nextable<H>>[] = []) {}\n\n public add(method: HttpMethod | \"\", route: Nextable<H> | RouteMatch, ...fns: Nextable<H>[]): this {\n if (typeof route === \"function\") {\n fns.unshift(route);\n // eslint-disable-next-line no-param-reassign\n route = \"\";\n }\n\n if (route === \"\") {\n this.routes.push({\n matchAll: true,\n method,\n fns,\n isMiddleware: false,\n });\n } else {\n const { keys, pattern } = parse(route);\n\n this.routes.push({\n keys,\n pattern,\n method,\n fns,\n isMiddleware: false,\n });\n }\n\n return this;\n }\n\n public use(base: Nextable<H> | RouteMatch | Router<H>, ...fns: (Nextable<H> | Router<H>)[]): this {\n if (typeof base === \"function\" || base instanceof Router) {\n fns.unshift(base);\n // eslint-disable-next-line no-param-reassign\n base = \"/\";\n }\n // mount subrouter\n // eslint-disable-next-line no-param-reassign\n fns = fns.map((function_) => {\n if (function_ instanceof Router) {\n if (typeof base === \"string\") return function_.clone(base);\n throw new Error(\"Mounting a router to RegExp base is not supported\");\n }\n return function_;\n });\n\n const { keys, pattern } = parse(base, true);\n\n this.routes.push({\n keys,\n pattern,\n method: \"\",\n fns,\n isMiddleware: true,\n });\n\n return this;\n }\n\n public clone(base?: string): Router<H> {\n return new Router<H>(base, [...this.routes]);\n }\n\n public static async exec<H extends FunctionLike>(fns: Nextable<H>[], ...arguments_: Parameters<H>): Promise<unknown> {\n let index = 0;\n\n // eslint-disable-next-line no-plusplus\n const next = () => (fns[++index] as FunctionLike)(...arguments_, next);\n\n return (fns[index] as FunctionLike)(...arguments_, next);\n }\n\n // eslint-disable-next-line sonarjs/cognitive-complexity\n public find(method: HttpMethod, pathname: string): FindResult<H> {\n let middleOnly = true;\n\n const fns: Nextable<H>[] = [];\n const parameters: Record<string, string> = {};\n const isHead = method === \"HEAD\";\n\n // eslint-disable-next-line sonarjs/cognitive-complexity\n Object.values(this.routes).forEach((route) => {\n if (\n route.method !== method\n // matches any method\n && route.method !== \"\"\n // The HEAD method requests that the target resource transfer a representation of its state, as for a GET request...\n && !(isHead && route.method === \"GET\")\n ) {\n return;\n }\n\n let matched = false;\n\n if (\"matchAll\" in route) {\n matched = true;\n } else if (route.keys === false) {\n // routes.key is RegExp: https://github.com/lukeed/regexparam/blob/master/src/index.js#L2\n const matches = route.pattern.exec(pathname);\n\n if (matches === null) {\n return;\n }\n\n // eslint-disable-next-line no-void\n if (matches.groups !== void 0) {\n Object.keys(matches.groups).forEach((key) => {\n // @ts-expect-error @TODO: fix this\n parameters[key] = matches.groups[key] as string;\n });\n }\n\n matched = true;\n } else if (route.keys.length > 0) {\n const matches = route.pattern.exec(pathname);\n\n if (matches === null) {\n return;\n }\n\n for (let index = 0; index < route.keys.length;) {\n const parameterKey = route.keys[index];\n\n // @ts-expect-error @TODO: fix this\n // eslint-disable-next-line no-plusplus\n parameters[parameterKey] = matches[++index];\n }\n\n matched = true;\n } else if (route.pattern.test(pathname)) {\n matched = true;\n } // else not a match\n\n if (matched) {\n fns.push(\n ...route.fns.flatMap((function_) => {\n if (function_ instanceof Router) {\n const { base } = function_;\n\n let stripPathname = pathname.slice(base.length);\n\n // fix stripped pathname, not sure why this happens\n // eslint-disable-next-line eqeqeq\n if (!stripPathname.startsWith(\"/\")) {\n stripPathname = `/${stripPathname}`;\n }\n\n // eslint-disable-next-line unicorn/no-array-callback-reference, unicorn/no-array-method-this-argument\n const result = function_.find(method, stripPathname);\n\n if (!result.middleOnly) {\n middleOnly = false;\n }\n\n // merge params\n Object.assign(parameters, result.params);\n\n return result.fns;\n }\n\n return function_;\n }),\n );\n if (!route.isMiddleware) middleOnly = false;\n }\n });\n\n return { fns, params: parameters, middleOnly };\n }\n}\n","import type { AnyZodObject, ZodObject } from \"zod\";\n\nimport withZod from \"./adapter/with-zod\";\nimport type { Route } from \"./router\";\nimport { Router } from \"./router\";\nimport type {\n FindResult,\n FunctionLike,\n HandlerOptions,\n HttpMethod,\n Nextable,\n RouteMatch,\n RoutesExtendedRequestHandler,\n RouteShortcutMethod,\n ValueOrPromise,\n} from \"./types\";\n\n// eslint-disable-next-line max-len\nconst onNoMatch = async (request: Request) => new Response(request.method === \"HEAD\" ? null : `Route ${request.method} ${request.url} not found`, { status: 404 });\n\nconst onError = async (error: unknown) => {\n // eslint-disable-next-line no-console\n console.error(error);\n return new Response(\"Internal Server Error\", { status: 500 });\n};\n\nexport function getPathname(request: Request & { nextUrl?: URL }): string {\n // eslint-disable-next-line compat/compat\n return (request.nextUrl ?? new URL(request.url)).pathname;\n}\n\n// eslint-disable-next-line max-len,@typescript-eslint/no-invalid-void-type\nexport type RequestHandler<R extends Request, Context> = (request: R, context_: Context) => ValueOrPromise<Response | void>;\n\nexport class EdgeRouter<R extends Request = Request, Context = unknown, RResponse extends Response = Response, Schema extends AnyZodObject = ZodObject<any>> {\n private router = new Router<RequestHandler<R, Context>>();\n\n private readonly onNoMatch: RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>;\n\n private readonly onError: (\n error: unknown,\n ...arguments_: Parameters<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>\n ) => ReturnType<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>;\n\n public constructor(options: HandlerOptions<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>> = {}) {\n this.onNoMatch = options.onNoMatch ?? onNoMatch as unknown as RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>;\n this.onError = options.onError\n ?? (onError as unknown as (\n error: unknown,\n ...arguments_: Parameters<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>\n ) => ReturnType<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>);\n }\n\n private add(\n method: HttpMethod | \"\",\n routeOrFunction: Nextable<RequestHandler<R, Context>> | RouteMatch,\n zodOrRouteOrFunction?: Nextable<RequestHandler<R, Context>> | RouteMatch | Schema,\n ...fns: Nextable<RequestHandler<R, Context>>[]\n ) {\n if (typeof routeOrFunction === \"string\" && typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n } else if (typeof zodOrRouteOrFunction === \"object\") {\n // eslint-disable-next-line unicorn/prefer-ternary\n if (typeof routeOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [withZod<R, Context, Nextable<RequestHandler<R, Context>>, Schema>(zodOrRouteOrFunction as Schema, routeOrFunction)];\n } else {\n // eslint-disable-next-line no-param-reassign,max-len\n fns = fns.map((function_) => withZod<R, Context, Nextable<RequestHandler<R, Context>>, Schema>(zodOrRouteOrFunction as Schema, function_));\n }\n } else if (typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n }\n\n this.router.add(method, routeOrFunction, ...fns);\n\n return this;\n }\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"\");\n\n public get: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"GET\");\n\n public head: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"HEAD\");\n\n public post: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"POST\");\n\n public put: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"PUT\");\n\n public patch: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"PATCH\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"DELETE\");\n\n public use(\n base: EdgeRouter<R, Context> | Nextable<RequestHandler<R, Context>> | RouteMatch,\n ...fns: (EdgeRouter<R, Context> | Nextable<RequestHandler<R, Context>>)[]\n ): this {\n if (typeof base === \"function\" || base instanceof EdgeRouter) {\n fns.unshift(base as EdgeRouter<R, Context>);\n // eslint-disable-next-line no-param-reassign\n base = \"/\";\n }\n\n this.router.use(base, ...fns.map((function_) => (function_ instanceof EdgeRouter ? function_.router : function_)));\n\n return this;\n }\n\n // eslint-disable-next-line class-methods-use-this\n private prepareRequest(request: R & { params?: Record<string, unknown> }, findResult: FindResult<RequestHandler<R, Context>>) {\n request.params = {\n ...findResult.params,\n ...request.params, // original params will take precedence\n };\n }\n\n public clone(): EdgeRouter<R, Context, RResponse, Schema> {\n const r = new EdgeRouter<R, Context, RResponse, Schema>({ onNoMatch: this.onNoMatch, onError: this.onError });\n\n r.router = this.router.clone();\n\n return r;\n }\n\n public async run(request: R, context_: Context): Promise<unknown> {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request));\n\n if (result.fns.length === 0) {\n return;\n }\n\n this.prepareRequest(request, result);\n\n // eslint-disable-next-line consistent-return\n return Router.exec(result.fns, request, context_);\n }\n\n public handler(): (request: R, context_: Context) => Promise<any> | ReturnType<FunctionLike> | ValueOrPromise<RResponse> {\n const { routes } = this.router as Router<FunctionLike>;\n\n return async (request: R, context_: Context): Promise<any> => {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request));\n\n this.prepareRequest(request, result);\n\n try {\n return await (result.fns.length === 0 || result.middleOnly\n ? this.onNoMatch(request, context_, routes)\n : Router.exec(result.fns, request, context_));\n } catch (error) {\n return this.onError(error, request, context_, routes);\n }\n };\n }\n}\n\nexport function createEdgeRouter<R extends Request, Context>(\n options: HandlerOptions<RoutesExtendedRequestHandler<R, Context, Response, Route<Nextable<FunctionLike>>[]>> = {},\n): EdgeRouter<R, Context> {\n return new EdgeRouter<R, Context, Response>(options);\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { RequestHandler } from \"../node\";\nimport type { Nextable } from \"../types\";\n\ntype NextFunction = (error?: any) => void;\n\nconst expressWrapper = <Request extends IncomingMessage, Response extends ServerResponse>(\n function_: ExpressRequestHandler<Request, Response>,\n // eslint-disable-next-line compat/compat\n): Nextable<RequestHandler<Request, Response>> => (request, response, next) => new Promise<void>((resolve, reject) => {\n function_(request, response, (error) => (error ? reject(error) : resolve()));\n // eslint-disable-next-line promise/no-callback-in-promise\n }).then(next);\n\nexport type ExpressRequestHandler<Request, Response> = (request: Request, response: Response, next: NextFunction) => void;\n\nexport default expressWrapper;\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { AnyZodObject, ZodObject } from \"zod\";\n\nimport withZod from \"./adapter/with-zod\";\nimport type { Route } from \"./router\";\nimport { Router } from \"./router\";\nimport type {\n FindResult,\n FunctionLike,\n HandlerOptions,\n HttpMethod,\n Nextable,\n RouteMatch,\n RoutesExtendedRequestHandler,\n RouteShortcutMethod,\n ValueOrPromise,\n} from \"./types\";\n\nconst onNoMatch = async (request: IncomingMessage, response: ServerResponse) => {\n response.statusCode = 404;\n response.end(request.method === \"HEAD\" ? undefined : `Route ${request.method} ${request.url} not found`);\n};\n\nconst onError = async (error: unknown, _request: IncomingMessage, response: ServerResponse) => {\n response.statusCode = 500;\n // eslint-disable-next-line no-console\n console.error(error);\n\n response.end(\"Internal Server Error\");\n};\n\nexport function getPathname(url: string): string {\n const queryIndex = url.indexOf(\"?\");\n\n return queryIndex === -1 ? url : url.slice(0, Math.max(0, queryIndex));\n}\n\nexport type RequestHandler<Request extends IncomingMessage, Response extends ServerResponse> = (request: Request, response: Response) => ValueOrPromise<void>;\n\nexport class NodeRouter<\n Request extends IncomingMessage = IncomingMessage,\n Response extends ServerResponse = ServerResponse,\n Schema extends AnyZodObject = ZodObject<any>,\n> {\n private router = new Router<RequestHandler<Request, Response>>();\n\n private readonly onNoMatch: RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>;\n\n private readonly onError: (\n error: unknown,\n ...arguments_: Parameters<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>>\n ) => ReturnType<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>>;\n\n public constructor(options: HandlerOptions<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>> = {}) {\n this.onNoMatch = options.onNoMatch ?? onNoMatch;\n this.onError = options.onError ?? onError;\n }\n\n private add(\n method: HttpMethod | \"\",\n routeOrFunction: Nextable<RequestHandler<Request, Response>> | RouteMatch,\n zodOrRouteOrFunction?: Nextable<RequestHandler<Request, Response>> | RouteMatch | Schema,\n ...fns: Nextable<RequestHandler<Request, Response>>[]\n ) {\n if (typeof routeOrFunction === \"string\" && typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n } else if (typeof zodOrRouteOrFunction === \"object\") {\n // eslint-disable-next-line unicorn/prefer-ternary\n if (typeof routeOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [withZod<Request, Response, Nextable<RequestHandler<Request, Response>>, Schema>(zodOrRouteOrFunction as Schema, routeOrFunction)];\n } else {\n // eslint-disable-next-line no-param-reassign,max-len\n fns = fns.map((function_) => withZod<Request, Response, Nextable<RequestHandler<Request, Response>>, Schema>(zodOrRouteOrFunction as Schema, function_));\n }\n } else if (typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n }\n\n this.router.add(method, routeOrFunction, ...fns);\n\n return this;\n }\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"\");\n\n public get: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"GET\");\n\n public head: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"HEAD\");\n\n public post: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"POST\");\n\n public put: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"PUT\");\n\n public patch: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"PATCH\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"DELETE\");\n\n public use(\n base: Nextable<RequestHandler<Request, Response>> | NodeRouter<Request, Response, Schema> | RouteMatch,\n ...fns: (Nextable<RequestHandler<Request, Response>> | NodeRouter<Request, Response, Schema>)[]\n ): this {\n if (typeof base === \"function\" || base instanceof NodeRouter) {\n fns.unshift(base);\n // eslint-disable-next-line no-param-reassign\n base = \"/\";\n }\n this.router.use(base, ...fns.map((function_) => (function_ instanceof NodeRouter ? function_.router : function_)));\n\n return this;\n }\n\n // eslint-disable-next-line class-methods-use-this\n private prepareRequest(request: Request & { params?: Record<string, unknown> }, findResult: FindResult<RequestHandler<Request, Response>>) {\n request.params = {\n ...findResult.params,\n ...request.params, // original params will take precedence\n };\n }\n\n public clone(): NodeRouter<Request, Response, Schema> {\n const r = new NodeRouter<Request, Response, Schema>({ onNoMatch: this.onNoMatch, onError: this.onError });\n\n r.router = this.router.clone();\n\n return r;\n }\n\n public async run(request: Request, response: Response): Promise<unknown> {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request.url as string));\n\n if (result.fns.length === 0) {\n return;\n }\n\n this.prepareRequest(request, result);\n\n // eslint-disable-next-line consistent-return\n return Router.exec(result.fns, request, response);\n }\n\n public handler(): (request: Request, response: Response) => Promise<void> {\n const { routes } = this.router as Router<FunctionLike>;\n\n return async (request: Request, response: Response) => {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request.url as string));\n\n this.prepareRequest(request, result);\n\n try {\n await (result.fns.length === 0 || result.middleOnly ? this.onNoMatch(request, response, routes) : Router.exec(result.fns, request, response));\n } catch (error) {\n await this.onError(error, request, response, routes);\n }\n };\n }\n}\n\nexport const createRouter = <\n Request extends IncomingMessage,\n Response extends ServerResponse,\n Schema extends AnyZodObject = ZodObject<{ body?: AnyZodObject; headers?: AnyZodObject; query?: AnyZodObject }>,\n>(\n options: HandlerOptions<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>> = {},\n ): NodeRouter<Request, Response, Schema> => new NodeRouter<Request, Response, Schema>(options);\n","import type { ServerResponse } from \"node:http\";\n\n/**\n * Send `JSON` object\n * @param {ServerResponse} response response object\n * @param {number} statusCode\n * @param {any} jsonBody of data\n */\nconst sendJson = (response: ServerResponse, statusCode: number, jsonBody: unknown): void => {\n // Set header to application/json\n response.setHeader(\"content-type\", \"application/json; charset=utf-8\");\n\n response.statusCode = statusCode;\n response.end(JSON.stringify(jsonBody, null, 2));\n};\n\nexport default sendJson;\n"]}
1
+ {"version":3,"sources":["../src/adapter/with-zod.ts","../src/router.ts","../src/edge.ts","../src/adapter/express.ts","../src/node.ts","../src/utils/send-json.ts"],"names":["createHttpError","ZodError","withZod","schema","handler","request","response","next","transformedRequest","error","message","issue","with_zod_default","parse","Router","base","routes","method","route","fns","keys","pattern","function_","arguments_","index","pathname","middleOnly","parameters","isHead","matched","matches","key","parameterKey","stripPathname","result","onNoMatch","onError","getPathname","EdgeRouter","options","routeOrFunction","zodOrRouteOrFunction","findResult","r","context_","createEdgeRouter","expressWrapper","resolve","reject","express_default","_request","url","queryIndex","NodeRouter","createRouter","sendJson","statusCode","jsonBody","send_json_default"],"mappings":"AAAA,OAAOA,MAAqB,cAE5B,OAAS,YAAAC,MAAgB,MAKzB,IAAMC,EAAU,CACZC,EACAC,IACmF,MAAOC,EAAkBC,EAAoBC,IAAS,CACrI,IAAIC,EAA8BH,EAElC,GAAI,CACAG,EAAsB,MAAML,EAAO,WAAWE,CAAO,CACzD,OAASI,EAAP,CACE,GAAI,CAAE,QAAAC,CAAQ,EAAID,EAGlB,MAAIA,aAAiBR,GAAY,OAAOQ,EAAM,QAAW,aAErDC,EAAUD,EAAM,OAAO,IAAKE,GAAU,GAAGA,EAAM,KAAK,KAAK,GAAG,OAAOA,EAAM,SAAS,EAAE,KAAK,IAAI,GAG3FX,EAAgB,IAAKU,CAAO,CACtC,CAEA,OAAON,EAAQI,EAAoBF,EAAUC,CAAI,CACrD,EAEGK,EAAQV,ECzBf,OAAS,SAAAW,MAAa,aAkBf,IAAMC,EAAN,KAAqC,CACjC,YAAmBC,EAAe,IAAYC,EAA+B,CAAC,EAAG,CAA9D,UAAAD,EAA2B,YAAAC,CAAoC,CAElF,IAAIC,EAAyBC,KAAoCC,EAA0B,CAO9F,GANI,OAAOD,GAAU,aACjBC,EAAI,QAAQD,CAAK,EAEjBA,EAAQ,IAGRA,IAAU,GACV,KAAK,OAAO,KAAK,CACb,SAAU,GACV,OAAAD,EACA,IAAAE,EACA,aAAc,EAClB,CAAC,MACE,CACH,GAAM,CAAE,KAAAC,EAAM,QAAAC,CAAQ,EAAIR,EAAMK,CAAK,EAErC,KAAK,OAAO,KAAK,CACb,KAAAE,EACA,QAAAC,EACA,OAAAJ,EACA,IAAAE,EACA,aAAc,EAClB,CAAC,EAGL,OAAO,IACX,CAEO,IAAIJ,KAA+CI,EAAwC,EAC1F,OAAOJ,GAAS,YAAcA,aAAgBD,KAC9CK,EAAI,QAAQJ,CAAI,EAEhBA,EAAO,KAIXI,EAAMA,EAAI,IAAKG,GAAc,CACzB,GAAIA,aAAqBR,EAAQ,CAC7B,GAAI,OAAOC,GAAS,SAAU,OAAOO,EAAU,MAAMP,CAAI,EACzD,MAAM,IAAI,MAAM,mDAAmD,EAEvE,OAAOO,CACX,CAAC,EAED,GAAM,CAAE,KAAAF,EAAM,QAAAC,CAAQ,EAAIR,EAAME,EAAM,EAAI,EAE1C,YAAK,OAAO,KAAK,CACb,KAAAK,EACA,QAAAC,EACA,OAAQ,GACR,IAAAF,EACA,aAAc,EAClB,CAAC,EAEM,IACX,CAEO,MAAMJ,EAA0B,CACnC,OAAO,IAAID,EAAUC,EAAM,CAAC,GAAG,KAAK,MAAM,CAAC,CAC/C,CAEA,aAAoB,KAA6BI,KAAuBI,EAA6C,CACjH,IAAIC,EAAQ,EAGNjB,EAAO,IAAOY,EAAI,EAAEK,CAAK,EAAmB,GAAGD,EAAYhB,CAAI,EAErE,OAAQY,EAAIK,CAAK,EAAmB,GAAGD,EAAYhB,CAAI,CAC3D,CAGO,KAAKU,EAAoBQ,EAAiC,CAC7D,IAAIC,EAAa,GAEXP,EAAqB,CAAC,EACtBQ,EAAqC,CAAC,EACtCC,EAASX,IAAW,OAG1B,cAAO,OAAO,KAAK,MAAM,EAAE,QAASC,GAAU,CAC1C,GACIA,EAAM,SAAWD,GAEdC,EAAM,SAAW,IAEjB,EAAEU,GAAUV,EAAM,SAAW,OAEhC,OAGJ,IAAIW,EAAU,GAEd,GAAI,aAAcX,EACdW,EAAU,WACHX,EAAM,OAAS,GAAO,CAE7B,IAAMY,EAAUZ,EAAM,QAAQ,KAAKO,CAAQ,EAE3C,GAAIK,IAAY,KACZ,OAIAA,EAAQ,SAAW,QACnB,OAAO,KAAKA,EAAQ,MAAM,EAAE,QAASC,GAAQ,CAEzCJ,EAAWI,CAAG,EAAID,EAAQ,OAAOC,CAAG,CACxC,CAAC,EAGLF,EAAU,WACHX,EAAM,KAAK,OAAS,EAAG,CAC9B,IAAMY,EAAUZ,EAAM,QAAQ,KAAKO,CAAQ,EAE3C,GAAIK,IAAY,KACZ,OAGJ,QAASN,EAAQ,EAAGA,EAAQN,EAAM,KAAK,QAAS,CAC5C,IAAMc,EAAed,EAAM,KAAKM,CAAK,EAIrCG,EAAWK,CAAY,EAAIF,EAAQ,EAAEN,CAAK,EAG9CK,EAAU,QACHX,EAAM,QAAQ,KAAKO,CAAQ,IAClCI,EAAU,IAGVA,IACAV,EAAI,KACA,GAAGD,EAAM,IAAI,QAASI,GAAc,CAChC,GAAIA,aAAqBR,EAAQ,CAC7B,GAAM,CAAE,KAAAC,CAAK,EAAIO,EAEbW,EAAgBR,EAAS,MAAMV,EAAK,MAAM,EAIzCkB,EAAc,WAAW,GAAG,IAC7BA,EAAgB,IAAIA,KAIxB,IAAMC,EAASZ,EAAU,KAAKL,EAAQgB,CAAa,EAEnD,OAAKC,EAAO,aACRR,EAAa,IAIjB,OAAO,OAAOC,EAAYO,EAAO,MAAM,EAEhCA,EAAO,IAGlB,OAAOZ,CACX,CAAC,CACL,EACKJ,EAAM,eAAcQ,EAAa,IAE9C,CAAC,EAEM,CAAE,IAAAP,EAAK,OAAQQ,EAAY,WAAAD,CAAW,CACjD,CACJ,EChLA,IAAMS,EAAY,MAAO9B,GAAqB,IAAI,SAASA,EAAQ,SAAW,OAAS,KAAO,SAASA,EAAQ,UAAUA,EAAQ,gBAAiB,CAAE,OAAQ,GAAI,CAAC,EAE3J+B,EAAU,MAAO3B,IAEnB,QAAQ,MAAMA,CAAK,EACZ,IAAI,SAAS,wBAAyB,CAAE,OAAQ,GAAI,CAAC,GAGzD,SAAS4B,EAAYhC,EAA8C,CAEtE,OAAQA,EAAQ,SAAW,IAAI,IAAIA,EAAQ,GAAG,GAAG,QACrD,CAKO,IAAMiC,EAAN,KAAsJ,CAUlJ,YAAYC,EAAgH,CAAC,EAAG,CATvI,KAAQ,OAAS,IAAIzB,EA8CrB,KAAO,IAAqE,KAAK,IAAI,KAAK,KAAM,EAAE,EAElG,KAAO,IAAqE,KAAK,IAAI,KAAK,KAAM,KAAK,EAErG,KAAO,KAAsE,KAAK,IAAI,KAAK,KAAM,MAAM,EAEvG,KAAO,KAAsE,KAAK,IAAI,KAAK,KAAM,MAAM,EAEvG,KAAO,IAAqE,KAAK,IAAI,KAAK,KAAM,KAAK,EAErG,KAAO,MAAuE,KAAK,IAAI,KAAK,KAAM,OAAO,EAEzG,KAAO,OAAwE,KAAK,IAAI,KAAK,KAAM,QAAQ,EAhDvG,KAAK,UAAYyB,EAAQ,WAAcJ,EACvC,KAAK,QAAUI,EAAQ,SACfH,CAIZ,CAEQ,IACJnB,EACAuB,EACAC,KACGtB,EACL,CACE,OAAI,OAAOqB,GAAoB,UAAY,OAAOC,GAAyB,WAEvEtB,EAAM,CAACsB,CAAoB,EACpB,OAAOA,GAAyB,SAEnC,OAAOD,GAAoB,WAE3BrB,EAAM,CAACP,EAAkE6B,EAAgCD,CAAe,CAAC,EAGzHrB,EAAMA,EAAI,IAAKG,GAAcV,EAAkE6B,EAAgCnB,CAAS,CAAC,EAEtI,OAAOmB,GAAyB,aAEvCtB,EAAM,CAACsB,CAAoB,GAG/B,KAAK,OAAO,IAAIxB,EAAQuB,EAAiB,GAAGrB,CAAG,EAExC,IACX,CAgBO,IACHJ,KACGI,EACC,CACJ,OAAI,OAAOJ,GAAS,YAAcA,aAAgBuB,KAC9CnB,EAAI,QAAQJ,CAA8B,EAE1CA,EAAO,KAGX,KAAK,OAAO,IAAIA,EAAM,GAAGI,EAAI,IAAKG,GAAeA,aAAqBgB,EAAahB,EAAU,OAASA,CAAU,CAAC,EAE1G,IACX,CAGQ,eAAejB,EAAmDqC,EAAoD,CAC1HrC,EAAQ,OAAS,CACb,GAAGqC,EAAW,OACd,GAAGrC,EAAQ,MACf,CACJ,CAEO,OAAmD,CACtD,IAAMsC,EAAI,IAAIL,EAA0C,CAAE,UAAW,KAAK,UAAW,QAAS,KAAK,OAAQ,CAAC,EAE5G,OAAAK,EAAE,OAAS,KAAK,OAAO,MAAM,EAEtBA,CACX,CAEA,MAAa,IAAItC,EAAYuC,EAAqC,CAE9D,IAAMV,EAAS,KAAK,OAAO,KAAK7B,EAAQ,OAAsBgC,EAAYhC,CAAO,CAAC,EAElF,GAAI6B,EAAO,IAAI,SAAW,EAI1B,YAAK,eAAe7B,EAAS6B,CAAM,EAG5BpB,EAAO,KAAKoB,EAAO,IAAK7B,EAASuC,CAAQ,CACpD,CAEO,SAAkH,CACrH,GAAM,CAAE,OAAA5B,CAAO,EAAI,KAAK,OAExB,MAAO,OAAOX,EAAYuC,IAAoC,CAE1D,IAAMV,EAAS,KAAK,OAAO,KAAK7B,EAAQ,OAAsBgC,EAAYhC,CAAO,CAAC,EAElF,KAAK,eAAeA,EAAS6B,CAAM,EAEnC,GAAI,CACA,OAAO,MAAOA,EAAO,IAAI,SAAW,GAAKA,EAAO,WAC1C,KAAK,UAAU7B,EAASuC,EAAU5B,CAAM,EACxCF,EAAO,KAAKoB,EAAO,IAAK7B,EAASuC,CAAQ,EACnD,OAASnC,EAAP,CACE,OAAO,KAAK,QAAQA,EAAOJ,EAASuC,EAAU5B,CAAM,CACxD,CACJ,CACJ,CACJ,EAEO,SAAS6B,EACZN,EAA+G,CAAC,EAC1F,CACtB,OAAO,IAAID,EAAiCC,CAAO,CACvD,CC7JA,IAAMO,EACFxB,GAE8C,CAACjB,EAASC,EAAUC,IAAS,IAAI,QAAc,CAACwC,EAASC,IAAW,CAC9G1B,EAAUjB,EAASC,EAAWG,GAAWA,EAAQuC,EAAOvC,CAAK,EAAIsC,EAAQ,CAAE,CAE/E,CAAC,EAAE,KAAKxC,CAAI,EAIT0C,EAAQH,ECCf,IAAMX,EAAY,MAAO9B,EAA0BC,IAA6B,CAC5EA,EAAS,WAAa,IACtBA,EAAS,IAAID,EAAQ,SAAW,OAAS,OAAY,SAASA,EAAQ,UAAUA,EAAQ,eAAe,CAC3G,EAEM+B,EAAU,MAAO3B,EAAgByC,EAA2B5C,IAA6B,CAC3FA,EAAS,WAAa,IAEtB,QAAQ,MAAMG,CAAK,EAEnBH,EAAS,IAAI,uBAAuB,CACxC,EAEO,SAAS+B,EAAYc,EAAqB,CAC7C,IAAMC,EAAaD,EAAI,QAAQ,GAAG,EAElC,OAAOC,IAAe,GAAKD,EAAMA,EAAI,MAAM,EAAG,KAAK,IAAI,EAAGC,CAAU,CAAC,CACzE,CAIO,IAAMC,EAAN,KAIL,CAUS,YAAYd,EAAsH,CAAC,EAAG,CAT7I,KAAQ,OAAS,IAAIzB,EA0CrB,KAAO,IAA4E,KAAK,IAAI,KAAK,KAAM,EAAE,EAEzG,KAAO,IAA4E,KAAK,IAAI,KAAK,KAAM,KAAK,EAE5G,KAAO,KAA6E,KAAK,IAAI,KAAK,KAAM,MAAM,EAE9G,KAAO,KAA6E,KAAK,IAAI,KAAK,KAAM,MAAM,EAE9G,KAAO,IAA4E,KAAK,IAAI,KAAK,KAAM,KAAK,EAE5G,KAAO,MAA8E,KAAK,IAAI,KAAK,KAAM,OAAO,EAEhH,KAAO,OAA+E,KAAK,IAAI,KAAK,KAAM,QAAQ,EA5C9G,KAAK,UAAYyB,EAAQ,WAAaJ,EACtC,KAAK,QAAUI,EAAQ,SAAWH,CACtC,CAEQ,IACJnB,EACAuB,EACAC,KACGtB,EACL,CACE,OAAI,OAAOqB,GAAoB,UAAY,OAAOC,GAAyB,WAEvEtB,EAAM,CAACsB,CAAoB,EACpB,OAAOA,GAAyB,SAEnC,OAAOD,GAAoB,WAE3BrB,EAAM,CAACP,EAAgF6B,EAAgCD,CAAe,CAAC,EAGvIrB,EAAMA,EAAI,IAAKG,GAAcV,EAAgF6B,EAAgCnB,CAAS,CAAC,EAEpJ,OAAOmB,GAAyB,aAEvCtB,EAAM,CAACsB,CAAoB,GAG/B,KAAK,OAAO,IAAIxB,EAAQuB,EAAiB,GAAGrB,CAAG,EAExC,IACX,CAgBO,IACHJ,KACGI,EACC,CACJ,OAAI,OAAOJ,GAAS,YAAcA,aAAgBsC,KAC9ClC,EAAI,QAAQJ,CAAI,EAEhBA,EAAO,KAEX,KAAK,OAAO,IAAIA,EAAM,GAAGI,EAAI,IAAKG,GAAeA,aAAqB+B,EAAa/B,EAAU,OAASA,CAAU,CAAC,EAE1G,IACX,CAGQ,eAAejB,EAAyDqC,EAA2D,CACvIrC,EAAQ,OAAS,CACb,GAAGqC,EAAW,OACd,GAAGrC,EAAQ,MACf,CACJ,CAEO,OAA+C,CAClD,IAAMsC,EAAI,IAAIU,EAAsC,CAAE,UAAW,KAAK,UAAW,QAAS,KAAK,OAAQ,CAAC,EAExG,OAAAV,EAAE,OAAS,KAAK,OAAO,MAAM,EAEtBA,CACX,CAEA,MAAa,IAAItC,EAAkBC,EAAsC,CAErE,IAAM4B,EAAS,KAAK,OAAO,KAAK7B,EAAQ,OAAsBgC,EAAYhC,EAAQ,GAAa,CAAC,EAEhG,GAAI6B,EAAO,IAAI,SAAW,EAI1B,YAAK,eAAe7B,EAAS6B,CAAM,EAG5BpB,EAAO,KAAKoB,EAAO,IAAK7B,EAASC,CAAQ,CACpD,CAEO,SAAmE,CACtE,GAAM,CAAE,OAAAU,CAAO,EAAI,KAAK,OAExB,MAAO,OAAOX,EAAkBC,IAAuB,CAEnD,IAAM4B,EAAS,KAAK,OAAO,KAAK7B,EAAQ,OAAsBgC,EAAYhC,EAAQ,GAAa,CAAC,EAEhG,KAAK,eAAeA,EAAS6B,CAAM,EAEnC,GAAI,CACA,MAAOA,EAAO,IAAI,SAAW,GAAKA,EAAO,WAAa,KAAK,UAAU7B,EAASC,EAAUU,CAAM,EAAIF,EAAO,KAAKoB,EAAO,IAAK7B,EAASC,CAAQ,EAC/I,OAASG,EAAP,CACE,MAAM,KAAK,QAAQA,EAAOJ,EAASC,EAAUU,CAAM,CACvD,CACJ,CACJ,CACJ,EAEasC,EAAe,CAKpBf,EAAsH,CAAC,IAC/E,IAAIc,EAAsCd,CAAO,EChKjG,IAAMgB,EAAW,CAACjD,EAA0BkD,EAAoBC,IAA4B,CAExFnD,EAAS,UAAU,eAAgB,iCAAiC,EAEpEA,EAAS,WAAakD,EACtBlD,EAAS,IAAI,KAAK,UAAUmD,EAAU,KAAM,CAAC,CAAC,CAClD,EAEOC,EAAQH","sourcesContent":["import createHttpError from \"http-errors\";\nimport type { AnyZodObject, ZodObject } from \"zod\";\nimport { ZodError } from \"zod\";\n\nimport type { Nextable, NextHandler } from \"../types\";\n\n// eslint-disable-next-line max-len\nconst withZod = <Request, Response, Handler extends Nextable<any>, Schema extends ZodObject<{ body?: AnyZodObject; headers?: AnyZodObject; query?: AnyZodObject }>>(\n schema: Schema,\n handler: Handler,\n): ((request: Request, response: Response, next: NextHandler) => Promise<Response>) => async (request: Request, response: Response, next) => {\n let transformedRequest: Request = request;\n\n try {\n transformedRequest = (await schema.parseAsync(request)) as Request;\n } catch (error: any) {\n let { message } = error;\n\n // eslint-disable-next-line unicorn/consistent-destructuring\n if (error instanceof ZodError && typeof error.format === \"function\") {\n // eslint-disable-next-line unicorn/consistent-destructuring\n message = error.issues.map((issue) => `${issue.path.join(\"/\")} - ${issue.message}`).join(\"/n\");\n }\n\n throw createHttpError(422, message);\n }\n\n return handler(transformedRequest, response, next);\n };\n\nexport default withZod;\n","/**\n * Agnostic router class\n * Adapted from lukeed/trouter library:\n * https://github.com/lukeed/trouter/blob/master/index.mjs\n */\nimport { parse } from \"regexparam\";\n\nimport type {\n FindResult, FunctionLike, HttpMethod, Nextable, RouteMatch,\n} from \"./types\";\n\nexport type Route<H> = {\n method: HttpMethod | \"\";\n fns: (H | Router<H extends FunctionLike ? H : never>)[];\n isMiddleware: boolean;\n} & (\n | {\n keys: string[] | false;\n pattern: RegExp;\n }\n | { matchAll: true }\n);\n\nexport class Router<H extends FunctionLike> {\n public constructor(public base: string = \"/\", public routes: Route<Nextable<H>>[] = []) {}\n\n public add(method: HttpMethod | \"\", route: Nextable<H> | RouteMatch, ...fns: Nextable<H>[]): this {\n if (typeof route === \"function\") {\n fns.unshift(route);\n // eslint-disable-next-line no-param-reassign\n route = \"\";\n }\n\n if (route === \"\") {\n this.routes.push({\n matchAll: true,\n method,\n fns,\n isMiddleware: false,\n });\n } else {\n const { keys, pattern } = parse(route);\n\n this.routes.push({\n keys,\n pattern,\n method,\n fns,\n isMiddleware: false,\n });\n }\n\n return this;\n }\n\n public use(base: Nextable<H> | RouteMatch | Router<H>, ...fns: (Nextable<H> | Router<H>)[]): this {\n if (typeof base === \"function\" || base instanceof Router) {\n fns.unshift(base);\n // eslint-disable-next-line no-param-reassign\n base = \"/\";\n }\n // mount subrouter\n // eslint-disable-next-line no-param-reassign\n fns = fns.map((function_) => {\n if (function_ instanceof Router) {\n if (typeof base === \"string\") return function_.clone(base);\n throw new Error(\"Mounting a router to RegExp base is not supported\");\n }\n return function_;\n });\n\n const { keys, pattern } = parse(base, true);\n\n this.routes.push({\n keys,\n pattern,\n method: \"\",\n fns,\n isMiddleware: true,\n });\n\n return this;\n }\n\n public clone(base?: string): Router<H> {\n return new Router<H>(base, [...this.routes]);\n }\n\n public static async exec<H extends FunctionLike>(fns: Nextable<H>[], ...arguments_: Parameters<H>): Promise<unknown> {\n let index = 0;\n\n // eslint-disable-next-line no-plusplus\n const next = () => (fns[++index] as FunctionLike)(...arguments_, next);\n\n return (fns[index] as FunctionLike)(...arguments_, next);\n }\n\n // eslint-disable-next-line sonarjs/cognitive-complexity\n public find(method: HttpMethod, pathname: string): FindResult<H> {\n let middleOnly = true;\n\n const fns: Nextable<H>[] = [];\n const parameters: Record<string, string> = {};\n const isHead = method === \"HEAD\";\n\n // eslint-disable-next-line sonarjs/cognitive-complexity\n Object.values(this.routes).forEach((route) => {\n if (\n route.method !== method\n // matches any method\n && route.method !== \"\"\n // The HEAD method requests that the target resource transfer a representation of its state, as for a GET request...\n && !(isHead && route.method === \"GET\")\n ) {\n return;\n }\n\n let matched = false;\n\n if (\"matchAll\" in route) {\n matched = true;\n } else if (route.keys === false) {\n // routes.key is RegExp: https://github.com/lukeed/regexparam/blob/master/src/index.js#L2\n const matches = route.pattern.exec(pathname);\n\n if (matches === null) {\n return;\n }\n\n // eslint-disable-next-line no-void\n if (matches.groups !== void 0) {\n Object.keys(matches.groups).forEach((key) => {\n // @ts-expect-error @TODO: fix this\n parameters[key] = matches.groups[key] as string;\n });\n }\n\n matched = true;\n } else if (route.keys.length > 0) {\n const matches = route.pattern.exec(pathname);\n\n if (matches === null) {\n return;\n }\n\n for (let index = 0; index < route.keys.length;) {\n const parameterKey = route.keys[index];\n\n // @ts-expect-error @TODO: fix this\n // eslint-disable-next-line no-plusplus\n parameters[parameterKey] = matches[++index];\n }\n\n matched = true;\n } else if (route.pattern.test(pathname)) {\n matched = true;\n } // else not a match\n\n if (matched) {\n fns.push(\n ...route.fns.flatMap((function_) => {\n if (function_ instanceof Router) {\n const { base } = function_;\n\n let stripPathname = pathname.slice(base.length);\n\n // fix stripped pathname, not sure why this happens\n // eslint-disable-next-line eqeqeq\n if (!stripPathname.startsWith(\"/\")) {\n stripPathname = `/${stripPathname}`;\n }\n\n // eslint-disable-next-line unicorn/no-array-callback-reference, unicorn/no-array-method-this-argument\n const result = function_.find(method, stripPathname);\n\n if (!result.middleOnly) {\n middleOnly = false;\n }\n\n // merge params\n Object.assign(parameters, result.params);\n\n return result.fns;\n }\n\n return function_;\n }),\n );\n if (!route.isMiddleware) middleOnly = false;\n }\n });\n\n return { fns, params: parameters, middleOnly };\n }\n}\n","import type { AnyZodObject, ZodObject } from \"zod\";\n\nimport withZod from \"./adapter/with-zod\";\nimport type { Route } from \"./router\";\nimport { Router } from \"./router\";\nimport type {\n FindResult,\n FunctionLike,\n HandlerOptions,\n HttpMethod,\n Nextable,\n RouteMatch,\n RoutesExtendedRequestHandler,\n RouteShortcutMethod,\n ValueOrPromise,\n} from \"./types\";\n\n// eslint-disable-next-line max-len\nconst onNoMatch = async (request: Request) => new Response(request.method === \"HEAD\" ? null : `Route ${request.method} ${request.url} not found`, { status: 404 });\n\nconst onError = async (error: unknown) => {\n // eslint-disable-next-line no-console\n console.error(error);\n return new Response(\"Internal Server Error\", { status: 500 });\n};\n\nexport function getPathname(request: Request & { nextUrl?: URL }): string {\n // eslint-disable-next-line compat/compat\n return (request.nextUrl ?? new URL(request.url)).pathname;\n}\n\n// eslint-disable-next-line max-len,@typescript-eslint/no-invalid-void-type\nexport type RequestHandler<R extends Request, Context> = (request: R, context_: Context) => ValueOrPromise<Response | void>;\n\nexport class EdgeRouter<R extends Request = Request, Context = unknown, RResponse extends Response = Response, Schema extends AnyZodObject = ZodObject<any>> {\n private router = new Router<RequestHandler<R, Context>>();\n\n private readonly onNoMatch: RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>;\n\n private readonly onError: (\n error: unknown,\n ...arguments_: Parameters<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>\n ) => ReturnType<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>;\n\n public constructor(options: HandlerOptions<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>> = {}) {\n this.onNoMatch = options.onNoMatch ?? (onNoMatch as unknown as RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>);\n this.onError = options.onError\n ?? (onError as unknown as (\n error: unknown,\n ...arguments_: Parameters<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>\n ) => ReturnType<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>);\n }\n\n private add(\n method: HttpMethod | \"\",\n routeOrFunction: Nextable<RequestHandler<R, Context>> | RouteMatch,\n zodOrRouteOrFunction?: Nextable<RequestHandler<R, Context>> | RouteMatch | Schema,\n ...fns: Nextable<RequestHandler<R, Context>>[]\n ) {\n if (typeof routeOrFunction === \"string\" && typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n } else if (typeof zodOrRouteOrFunction === \"object\") {\n // eslint-disable-next-line unicorn/prefer-ternary\n if (typeof routeOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [withZod<R, Context, Nextable<RequestHandler<R, Context>>, Schema>(zodOrRouteOrFunction as Schema, routeOrFunction)];\n } else {\n // eslint-disable-next-line no-param-reassign,max-len\n fns = fns.map((function_) => withZod<R, Context, Nextable<RequestHandler<R, Context>>, Schema>(zodOrRouteOrFunction as Schema, function_));\n }\n } else if (typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n }\n\n this.router.add(method, routeOrFunction, ...fns);\n\n return this;\n }\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"\");\n\n public get: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"GET\");\n\n public head: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"HEAD\");\n\n public post: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"POST\");\n\n public put: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"PUT\");\n\n public patch: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"PATCH\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"DELETE\");\n\n public use(\n base: EdgeRouter<R, Context> | Nextable<RequestHandler<R, Context>> | RouteMatch,\n ...fns: (EdgeRouter<R, Context> | Nextable<RequestHandler<R, Context>>)[]\n ): this {\n if (typeof base === \"function\" || base instanceof EdgeRouter) {\n fns.unshift(base as EdgeRouter<R, Context>);\n // eslint-disable-next-line no-param-reassign\n base = \"/\";\n }\n\n this.router.use(base, ...fns.map((function_) => (function_ instanceof EdgeRouter ? function_.router : function_)));\n\n return this;\n }\n\n // eslint-disable-next-line class-methods-use-this\n private prepareRequest(request: R & { params?: Record<string, unknown> }, findResult: FindResult<RequestHandler<R, Context>>) {\n request.params = {\n ...findResult.params,\n ...request.params, // original params will take precedence\n };\n }\n\n public clone(): EdgeRouter<R, Context, RResponse, Schema> {\n const r = new EdgeRouter<R, Context, RResponse, Schema>({ onNoMatch: this.onNoMatch, onError: this.onError });\n\n r.router = this.router.clone();\n\n return r;\n }\n\n public async run(request: R, context_: Context): Promise<unknown> {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request));\n\n if (result.fns.length === 0) {\n return;\n }\n\n this.prepareRequest(request, result);\n\n // eslint-disable-next-line consistent-return\n return Router.exec(result.fns, request, context_);\n }\n\n public handler(): (request: R, context_: Context) => Promise<any> | ReturnType<FunctionLike> | ValueOrPromise<RResponse> {\n const { routes } = this.router as Router<FunctionLike>;\n\n return async (request: R, context_: Context): Promise<any> => {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request));\n\n this.prepareRequest(request, result);\n\n try {\n return await (result.fns.length === 0 || result.middleOnly\n ? this.onNoMatch(request, context_, routes)\n : Router.exec(result.fns, request, context_));\n } catch (error) {\n return this.onError(error, request, context_, routes);\n }\n };\n }\n}\n\nexport function createEdgeRouter<R extends Request, Context>(\n options: HandlerOptions<RoutesExtendedRequestHandler<R, Context, Response, Route<Nextable<FunctionLike>>[]>> = {},\n): EdgeRouter<R, Context> {\n return new EdgeRouter<R, Context, Response>(options);\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { RequestHandler } from \"../node\";\nimport type { Nextable } from \"../types\";\n\ntype NextFunction = (error?: any) => void;\n\nconst expressWrapper = <Request extends IncomingMessage, Response extends ServerResponse>(\n function_: ExpressRequestHandler<Request, Response>,\n // eslint-disable-next-line compat/compat\n): Nextable<RequestHandler<Request, Response>> => (request, response, next) => new Promise<void>((resolve, reject) => {\n function_(request, response, (error) => (error ? reject(error) : resolve()));\n // eslint-disable-next-line promise/no-callback-in-promise\n }).then(next);\n\nexport type ExpressRequestHandler<Request, Response> = (request: Request, response: Response, next: NextFunction) => void;\n\nexport default expressWrapper;\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { AnyZodObject, ZodObject } from \"zod\";\n\nimport withZod from \"./adapter/with-zod\";\nimport type { Route } from \"./router\";\nimport { Router } from \"./router\";\nimport type {\n FindResult,\n FunctionLike,\n HandlerOptions,\n HttpMethod,\n Nextable,\n RouteMatch,\n RoutesExtendedRequestHandler,\n RouteShortcutMethod,\n ValueOrPromise,\n} from \"./types\";\n\nconst onNoMatch = async (request: IncomingMessage, response: ServerResponse) => {\n response.statusCode = 404;\n response.end(request.method === \"HEAD\" ? undefined : `Route ${request.method} ${request.url} not found`);\n};\n\nconst onError = async (error: unknown, _request: IncomingMessage, response: ServerResponse) => {\n response.statusCode = 500;\n // eslint-disable-next-line no-console\n console.error(error);\n\n response.end(\"Internal Server Error\");\n};\n\nexport function getPathname(url: string): string {\n const queryIndex = url.indexOf(\"?\");\n\n return queryIndex === -1 ? url : url.slice(0, Math.max(0, queryIndex));\n}\n\nexport type RequestHandler<Request extends IncomingMessage, Response extends ServerResponse> = (request: Request, response: Response) => ValueOrPromise<void>;\n\nexport class NodeRouter<\n Request extends IncomingMessage = IncomingMessage,\n Response extends ServerResponse = ServerResponse,\n Schema extends AnyZodObject = ZodObject<any>,\n> {\n private router = new Router<RequestHandler<Request, Response>>();\n\n private readonly onNoMatch: RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>;\n\n private readonly onError: (\n error: unknown,\n ...arguments_: Parameters<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>>\n ) => ReturnType<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>>;\n\n public constructor(options: HandlerOptions<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>> = {}) {\n this.onNoMatch = options.onNoMatch ?? onNoMatch;\n this.onError = options.onError ?? onError;\n }\n\n private add(\n method: HttpMethod | \"\",\n routeOrFunction: Nextable<RequestHandler<Request, Response>> | RouteMatch,\n zodOrRouteOrFunction?: Nextable<RequestHandler<Request, Response>> | RouteMatch | Schema,\n ...fns: Nextable<RequestHandler<Request, Response>>[]\n ) {\n if (typeof routeOrFunction === \"string\" && typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n } else if (typeof zodOrRouteOrFunction === \"object\") {\n // eslint-disable-next-line unicorn/prefer-ternary\n if (typeof routeOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [withZod<Request, Response, Nextable<RequestHandler<Request, Response>>, Schema>(zodOrRouteOrFunction as Schema, routeOrFunction)];\n } else {\n // eslint-disable-next-line no-param-reassign,max-len\n fns = fns.map((function_) => withZod<Request, Response, Nextable<RequestHandler<Request, Response>>, Schema>(zodOrRouteOrFunction as Schema, function_));\n }\n } else if (typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n }\n\n this.router.add(method, routeOrFunction, ...fns);\n\n return this;\n }\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"\");\n\n public get: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"GET\");\n\n public head: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"HEAD\");\n\n public post: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"POST\");\n\n public put: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"PUT\");\n\n public patch: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"PATCH\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"DELETE\");\n\n public use(\n base: Nextable<RequestHandler<Request, Response>> | NodeRouter<Request, Response, Schema> | RouteMatch,\n ...fns: (Nextable<RequestHandler<Request, Response>> | NodeRouter<Request, Response, Schema>)[]\n ): this {\n if (typeof base === \"function\" || base instanceof NodeRouter) {\n fns.unshift(base);\n // eslint-disable-next-line no-param-reassign\n base = \"/\";\n }\n this.router.use(base, ...fns.map((function_) => (function_ instanceof NodeRouter ? function_.router : function_)));\n\n return this;\n }\n\n // eslint-disable-next-line class-methods-use-this\n private prepareRequest(request: Request & { params?: Record<string, unknown> }, findResult: FindResult<RequestHandler<Request, Response>>) {\n request.params = {\n ...findResult.params,\n ...request.params, // original params will take precedence\n };\n }\n\n public clone(): NodeRouter<Request, Response, Schema> {\n const r = new NodeRouter<Request, Response, Schema>({ onNoMatch: this.onNoMatch, onError: this.onError });\n\n r.router = this.router.clone();\n\n return r;\n }\n\n public async run(request: Request, response: Response): Promise<unknown> {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request.url as string));\n\n if (result.fns.length === 0) {\n return;\n }\n\n this.prepareRequest(request, result);\n\n // eslint-disable-next-line consistent-return\n return Router.exec(result.fns, request, response);\n }\n\n public handler(): (request: Request, response: Response) => Promise<void> {\n const { routes } = this.router as Router<FunctionLike>;\n\n return async (request: Request, response: Response) => {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request.url as string));\n\n this.prepareRequest(request, result);\n\n try {\n await (result.fns.length === 0 || result.middleOnly ? this.onNoMatch(request, response, routes) : Router.exec(result.fns, request, response));\n } catch (error) {\n await this.onError(error, request, response, routes);\n }\n };\n }\n}\n\nexport const createRouter = <\n Request extends IncomingMessage,\n Response extends ServerResponse,\n Schema extends AnyZodObject = ZodObject<{ body?: AnyZodObject; headers?: AnyZodObject; query?: AnyZodObject }>,\n>(\n options: HandlerOptions<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>> = {},\n ): NodeRouter<Request, Response, Schema> => new NodeRouter<Request, Response, Schema>(options);\n","import type { ServerResponse } from \"node:http\";\n\n/**\n * Send `JSON` object\n * @param {ServerResponse} response response object\n * @param {number} statusCode\n * @param {any} jsonBody of data\n */\nconst sendJson = (response: ServerResponse, statusCode: number, jsonBody: unknown): void => {\n // Set header to application/json\n response.setHeader(\"content-type\", \"application/json; charset=utf-8\");\n\n response.statusCode = statusCode;\n response.end(JSON.stringify(jsonBody, null, 2));\n};\n\nexport default sendJson;\n"]}
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
- import N from 'http-errors';
1
+ import q from 'http-errors';
2
2
  import { ZodError } from 'zod';
3
3
  import { parse } from 'regexparam';
4
4
 
5
- var M=Object.defineProperty;var S=(o,e,t)=>e in o?M(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var a=(o,e,t)=>(S(o,typeof e!="symbol"?e+"":e,t),t);var E=(o,e)=>async(t,s,n)=>{let r=t;try{r=await o.parseAsync(t);}catch(d){let{message:u}=d;throw d instanceof ZodError&&typeof d.format=="function"&&(u=d.issues.map(p=>`${p.path.join("/")} - ${p.message}`).join("/n")),N(422,u)}return e(r,s,n)},x=E;var i=class{constructor(e="/",t=[]){this.base=e;this.routes=t;}add(e,t,...s){if(typeof t=="function"&&(s.unshift(t),t=""),t==="")this.routes.push({matchAll:!0,method:e,fns:s,isMiddleware:!1});else {let{keys:n,pattern:r}=parse(t);this.routes.push({keys:n,pattern:r,method:e,fns:s,isMiddleware:!1});}return this}use(e,...t){(typeof e=="function"||e instanceof i)&&(t.unshift(e),e="/"),t=t.map(r=>{if(r instanceof i){if(typeof e=="string")return r.clone(e);throw new Error("Mounting a router to RegExp base is not supported")}return r});let{keys:s,pattern:n}=parse(e,!0);return this.routes.push({keys:s,pattern:n,method:"",fns:t,isMiddleware:!0}),this}clone(e){return new i(e,[...this.routes])}static async exec(e,...t){let s=0,n=()=>e[++s](...t,n);return e[s](...t,n)}find(e,t){let s=!0,n=[],r={},d=e==="HEAD";return Object.values(this.routes).forEach(u=>{if(u.method!==e&&u.method!==""&&!(d&&u.method==="GET"))return;let p=!1;if("matchAll"in u)p=!0;else if(u.keys===!1){let R=u.pattern.exec(t);if(R===null)return;R.groups!==void 0&&Object.keys(R.groups).forEach(l=>{r[l]=R.groups[l];}),p=!0;}else if(u.keys.length>0){let R=u.pattern.exec(t);if(R===null)return;for(let l=0;l<u.keys.length;){let m=u.keys[l];r[m]=R[++l];}p=!0;}else u.pattern.test(t)&&(p=!0);p&&(n.push(...u.fns.flatMap(R=>{if(R instanceof i){let{base:l}=R,m=t.slice(l.length);m.startsWith("/")||(m=`/${m}`);let f=R.find(e,m);return f.middleOnly||(s=!1),Object.assign(r,f.params),f.fns}return R})),u.isMiddleware||(s=!1));}),{fns:n,params:r,middleOnly:s}}};var k=async o=>new Response(o.method==="HEAD"?null:`Route ${o.method} ${o.url} not found`,{status:404}),C=async o=>(console.error(o),new Response("Internal Server Error",{status:500}));function y(o){return (o.nextUrl??new URL(o.url)).pathname}var c=class{constructor(e={}){a(this,"router",new i);a(this,"onNoMatch");a(this,"onError");a(this,"all",this.add.bind(this,""));a(this,"get",this.add.bind(this,"GET"));a(this,"head",this.add.bind(this,"HEAD"));a(this,"post",this.add.bind(this,"POST"));a(this,"put",this.add.bind(this,"PUT"));a(this,"patch",this.add.bind(this,"PATCH"));a(this,"delete",this.add.bind(this,"DELETE"));this.onNoMatch=e.onNoMatch??k,this.onError=e.onError??C;}add(e,t,s,...n){return typeof t=="string"&&typeof s=="function"?n=[s]:typeof s=="object"?typeof t=="function"?n=[x(s,t)]:n=n.map(r=>x(s,r)):typeof s=="function"&&(n=[s]),this.router.add(e,t,...n),this}use(e,...t){return (typeof e=="function"||e instanceof c)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof c?s.router:s)),this}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new c({onNoMatch:this.onNoMatch,onError:this.onError});return e.router=this.router.clone(),e}async run(e,t){let s=this.router.find(e.method,y(e));if(s.fns.length!==0)return this.prepareRequest(e,s),i.exec(s.fns,e,t)}handler(){let{routes:e}=this.router;return async(t,s)=>{let n=this.router.find(t.method,y(t));this.prepareRequest(t,n);try{return await(n.fns.length===0||n.middleOnly?this.onNoMatch(t,s,e):i.exec(n.fns,t,s))}catch(r){return this.onError(r,t,s,e)}}}};function w(o={}){return new c(o)}var v=o=>(e,t,s)=>new Promise((n,r)=>{o(e,t,d=>d?r(d):n());}).then(s),L=v;var j=async(o,e)=>{e.statusCode=404,e.end(o.method==="HEAD"?void 0:`Route ${o.method} ${o.url} not found`);},P=async(o,e,t)=>{t.statusCode=500,console.error(o),t.end("Internal Server Error");};function b(o){let e=o.indexOf("?");return e===-1?o:o.slice(0,Math.max(0,e))}var h=class{constructor(e={}){a(this,"router",new i);a(this,"onNoMatch");a(this,"onError");a(this,"all",this.add.bind(this,""));a(this,"get",this.add.bind(this,"GET"));a(this,"head",this.add.bind(this,"HEAD"));a(this,"post",this.add.bind(this,"POST"));a(this,"put",this.add.bind(this,"PUT"));a(this,"patch",this.add.bind(this,"PATCH"));a(this,"delete",this.add.bind(this,"DELETE"));this.onNoMatch=e.onNoMatch??j,this.onError=e.onError??P;}add(e,t,s,...n){return typeof t=="string"&&typeof s=="function"?n=[s]:typeof s=="object"?typeof t=="function"?n=[x(s,t)]:n=n.map(r=>x(s,r)):typeof s=="function"&&(n=[s]),this.router.add(e,t,...n),this}use(e,...t){return (typeof e=="function"||e instanceof h)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof h?s.router:s)),this}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new h({onNoMatch:this.onNoMatch,onError:this.onError});return e.router=this.router.clone(),e}async run(e,t){let s=this.router.find(e.method,b(e.url));if(s.fns.length!==0)return this.prepareRequest(e,s),i.exec(s.fns,e,t)}handler(){let{routes:e}=this.router;return async(t,s)=>{let n=this.router.find(t.method,b(t.url));this.prepareRequest(t,n);try{await(n.fns.length===0||n.middleOnly?this.onNoMatch(t,s,e):i.exec(n.fns,t,s));}catch(r){await this.onError(r,t,s,e);}}}},q=(o={})=>new h(o);var Z=(o,e,t)=>{o.setHeader("content-type","application/json; charset=utf-8"),o.statusCode=e,o.end(JSON.stringify(t,null,2));},A=Z;
5
+ var S=(o,e)=>async(t,s,n)=>{let r=t;try{r=await o.parseAsync(t);}catch(R){let{message:a}=R;throw R instanceof ZodError&&typeof R.format=="function"&&(a=R.issues.map(d=>`${d.path.join("/")} - ${d.message}`).join("/n")),q(422,a)}return e(r,s,n)},h=S;var u=class{constructor(e="/",t=[]){this.base=e;this.routes=t;}add(e,t,...s){if(typeof t=="function"&&(s.unshift(t),t=""),t==="")this.routes.push({matchAll:!0,method:e,fns:s,isMiddleware:!1});else {let{keys:n,pattern:r}=parse(t);this.routes.push({keys:n,pattern:r,method:e,fns:s,isMiddleware:!1});}return this}use(e,...t){(typeof e=="function"||e instanceof u)&&(t.unshift(e),e="/"),t=t.map(r=>{if(r instanceof u){if(typeof e=="string")return r.clone(e);throw new Error("Mounting a router to RegExp base is not supported")}return r});let{keys:s,pattern:n}=parse(e,!0);return this.routes.push({keys:s,pattern:n,method:"",fns:t,isMiddleware:!0}),this}clone(e){return new u(e,[...this.routes])}static async exec(e,...t){let s=0,n=()=>e[++s](...t,n);return e[s](...t,n)}find(e,t){let s=!0,n=[],r={},R=e==="HEAD";return Object.values(this.routes).forEach(a=>{if(a.method!==e&&a.method!==""&&!(R&&a.method==="GET"))return;let d=!1;if("matchAll"in a)d=!0;else if(a.keys===!1){let i=a.pattern.exec(t);if(i===null)return;i.groups!==void 0&&Object.keys(i.groups).forEach(p=>{r[p]=i.groups[p];}),d=!0;}else if(a.keys.length>0){let i=a.pattern.exec(t);if(i===null)return;for(let p=0;p<a.keys.length;){let x=a.keys[p];r[x]=i[++p];}d=!0;}else a.pattern.test(t)&&(d=!0);d&&(n.push(...a.fns.flatMap(i=>{if(i instanceof u){let{base:p}=i,x=t.slice(p.length);x.startsWith("/")||(x=`/${x}`);let m=i.find(e,x);return m.middleOnly||(s=!1),Object.assign(r,m.params),m.fns}return i})),a.isMiddleware||(s=!1));}),{fns:n,params:r,middleOnly:s}}};var N=async o=>new Response(o.method==="HEAD"?null:`Route ${o.method} ${o.url} not found`,{status:404}),g=async o=>(console.error(o),new Response("Internal Server Error",{status:500}));function H(o){return (o.nextUrl??new URL(o.url)).pathname}var l=class{constructor(e={}){this.router=new u;this.all=this.add.bind(this,"");this.get=this.add.bind(this,"GET");this.head=this.add.bind(this,"HEAD");this.post=this.add.bind(this,"POST");this.put=this.add.bind(this,"PUT");this.patch=this.add.bind(this,"PATCH");this.delete=this.add.bind(this,"DELETE");this.onNoMatch=e.onNoMatch??N,this.onError=e.onError??g;}add(e,t,s,...n){return typeof t=="string"&&typeof s=="function"?n=[s]:typeof s=="object"?typeof t=="function"?n=[h(s,t)]:n=n.map(r=>h(s,r)):typeof s=="function"&&(n=[s]),this.router.add(e,t,...n),this}use(e,...t){return (typeof e=="function"||e instanceof l)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof l?s.router:s)),this}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new l({onNoMatch:this.onNoMatch,onError:this.onError});return e.router=this.router.clone(),e}async run(e,t){let s=this.router.find(e.method,H(e));if(s.fns.length!==0)return this.prepareRequest(e,s),u.exec(s.fns,e,t)}handler(){let{routes:e}=this.router;return async(t,s)=>{let n=this.router.find(t.method,H(t));this.prepareRequest(t,n);try{return await(n.fns.length===0||n.middleOnly?this.onNoMatch(t,s,e):u.exec(n.fns,t,s))}catch(r){return this.onError(r,t,s,e)}}}};function E(o={}){return new l(o)}var k=o=>(e,t,s)=>new Promise((n,r)=>{o(e,t,R=>R?r(R):n());}).then(s),C=k;var w=async(o,e)=>{e.statusCode=404,e.end(o.method==="HEAD"?void 0:`Route ${o.method} ${o.url} not found`);},v=async(o,e,t)=>{t.statusCode=500,console.error(o),t.end("Internal Server Error");};function y(o){let e=o.indexOf("?");return e===-1?o:o.slice(0,Math.max(0,e))}var c=class{constructor(e={}){this.router=new u;this.all=this.add.bind(this,"");this.get=this.add.bind(this,"GET");this.head=this.add.bind(this,"HEAD");this.post=this.add.bind(this,"POST");this.put=this.add.bind(this,"PUT");this.patch=this.add.bind(this,"PATCH");this.delete=this.add.bind(this,"DELETE");this.onNoMatch=e.onNoMatch??w,this.onError=e.onError??v;}add(e,t,s,...n){return typeof t=="string"&&typeof s=="function"?n=[s]:typeof s=="object"?typeof t=="function"?n=[h(s,t)]:n=n.map(r=>h(s,r)):typeof s=="function"&&(n=[s]),this.router.add(e,t,...n),this}use(e,...t){return (typeof e=="function"||e instanceof c)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof c?s.router:s)),this}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new c({onNoMatch:this.onNoMatch,onError:this.onError});return e.router=this.router.clone(),e}async run(e,t){let s=this.router.find(e.method,y(e.url));if(s.fns.length!==0)return this.prepareRequest(e,s),u.exec(s.fns,e,t)}handler(){let{routes:e}=this.router;return async(t,s)=>{let n=this.router.find(t.method,y(t.url));this.prepareRequest(t,n);try{await(n.fns.length===0||n.middleOnly?this.onNoMatch(t,s,e):u.exec(n.fns,t,s));}catch(r){await this.onError(r,t,s,e);}}}},b=(o={})=>new c(o);var L=(o,e,t)=>{o.setHeader("content-type","application/json; charset=utf-8"),o.statusCode=e,o.end(JSON.stringify(t,null,2));},j=L;
6
6
 
7
- export { c as EdgeRouter, h as NodeRouter, i as Router, w as createEdgeRouter, q as createNodeRouter, q as createRouter, L as expressWrapper, A as sendJson, x as withZod };
7
+ export { l as EdgeRouter, c as NodeRouter, u as Router, E as createEdgeRouter, b as createNodeRouter, b as createRouter, C as expressWrapper, j as sendJson, h as withZod };
8
8
  //# sourceMappingURL=out.js.map
9
9
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapter/with-zod.ts","../src/router.ts","../src/edge.ts","../src/adapter/express.ts","../src/node.ts","../src/utils/send-json.ts"],"names":["createHttpError","ZodError","withZod","schema","handler","request","response","next","transformedRequest","error","message","issue","with_zod_default","parse","Router","base","routes","method","route","fns","keys","pattern","function_","arguments_","index","pathname","middleOnly","parameters","isHead","matched","matches","key","parameterKey","stripPathname","result","onNoMatch","onError","getPathname","EdgeRouter","options","__publicField","routeOrFunction","zodOrRouteOrFunction","findResult","r","context_","createEdgeRouter","expressWrapper","resolve","reject","express_default","_request","url","queryIndex","NodeRouter","createRouter","sendJson","statusCode","jsonBody","send_json_default"],"mappings":"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","sourcesContent":["import createHttpError from \"http-errors\";\nimport type { AnyZodObject, ZodObject } from \"zod\";\nimport { ZodError } from \"zod\";\n\nimport type { Nextable, NextHandler } from \"../types\";\n\nconst withZod = <\n Request,\n Response,\n Handler extends Nextable<any>,\n Schema extends ZodObject<{ body?: AnyZodObject; headers?: AnyZodObject; query?: AnyZodObject }>,\n >(\n schema: Schema,\n handler: Handler,\n ): ((request: Request, response: Response, next: NextHandler) => Promise<Response>) => async (request: Request, response: Response, next) => {\n let transformedRequest: Request = request;\n\n try {\n transformedRequest = (await schema.parseAsync(request)) as Request;\n } catch (error: any) {\n let { message } = error;\n\n // eslint-disable-next-line unicorn/consistent-destructuring\n if (error instanceof ZodError && typeof error.format === \"function\") {\n // eslint-disable-next-line unicorn/consistent-destructuring\n message = error.issues.map((issue) => `${issue.path.join(\"/\")} - ${issue.message}`).join(\"/n\");\n }\n\n throw createHttpError(422, message);\n }\n\n return handler(transformedRequest, response, next);\n };\n\nexport default withZod;\n","/**\n * Agnostic router class\n * Adapted from lukeed/trouter library:\n * https://github.com/lukeed/trouter/blob/master/index.mjs\n */\nimport { parse } from \"regexparam\";\n\nimport type {\n FindResult, FunctionLike, HttpMethod, Nextable, RouteMatch,\n} from \"./types\";\n\nexport type Route<H> = {\n method: HttpMethod | \"\";\n fns: (H | Router<H extends FunctionLike ? H : never>)[];\n isMiddleware: boolean;\n} & (\n | {\n keys: string[] | false;\n pattern: RegExp;\n }\n | { matchAll: true }\n);\n\nexport class Router<H extends FunctionLike> {\n public constructor(public base: string = \"/\", public routes: Route<Nextable<H>>[] = []) {}\n\n public add(method: HttpMethod | \"\", route: Nextable<H> | RouteMatch, ...fns: Nextable<H>[]): this {\n if (typeof route === \"function\") {\n fns.unshift(route);\n // eslint-disable-next-line no-param-reassign\n route = \"\";\n }\n\n if (route === \"\") {\n this.routes.push({\n matchAll: true,\n method,\n fns,\n isMiddleware: false,\n });\n } else {\n const { keys, pattern } = parse(route);\n\n this.routes.push({\n keys,\n pattern,\n method,\n fns,\n isMiddleware: false,\n });\n }\n\n return this;\n }\n\n public use(base: Nextable<H> | RouteMatch | Router<H>, ...fns: (Nextable<H> | Router<H>)[]): this {\n if (typeof base === \"function\" || base instanceof Router) {\n fns.unshift(base);\n // eslint-disable-next-line no-param-reassign\n base = \"/\";\n }\n // mount subrouter\n // eslint-disable-next-line no-param-reassign\n fns = fns.map((function_) => {\n if (function_ instanceof Router) {\n if (typeof base === \"string\") return function_.clone(base);\n throw new Error(\"Mounting a router to RegExp base is not supported\");\n }\n return function_;\n });\n\n const { keys, pattern } = parse(base, true);\n\n this.routes.push({\n keys,\n pattern,\n method: \"\",\n fns,\n isMiddleware: true,\n });\n\n return this;\n }\n\n public clone(base?: string): Router<H> {\n return new Router<H>(base, [...this.routes]);\n }\n\n public static async exec<H extends FunctionLike>(fns: Nextable<H>[], ...arguments_: Parameters<H>): Promise<unknown> {\n let index = 0;\n\n // eslint-disable-next-line no-plusplus\n const next = () => (fns[++index] as FunctionLike)(...arguments_, next);\n\n return (fns[index] as FunctionLike)(...arguments_, next);\n }\n\n // eslint-disable-next-line sonarjs/cognitive-complexity\n public find(method: HttpMethod, pathname: string): FindResult<H> {\n let middleOnly = true;\n\n const fns: Nextable<H>[] = [];\n const parameters: Record<string, string> = {};\n const isHead = method === \"HEAD\";\n\n // eslint-disable-next-line sonarjs/cognitive-complexity\n Object.values(this.routes).forEach((route) => {\n if (\n route.method !== method\n // matches any method\n && route.method !== \"\"\n // The HEAD method requests that the target resource transfer a representation of its state, as for a GET request...\n && !(isHead && route.method === \"GET\")\n ) {\n return;\n }\n\n let matched = false;\n\n if (\"matchAll\" in route) {\n matched = true;\n } else if (route.keys === false) {\n // routes.key is RegExp: https://github.com/lukeed/regexparam/blob/master/src/index.js#L2\n const matches = route.pattern.exec(pathname);\n\n if (matches === null) {\n return;\n }\n\n // eslint-disable-next-line no-void\n if (matches.groups !== void 0) {\n Object.keys(matches.groups).forEach((key) => {\n // @ts-expect-error @TODO: fix this\n parameters[key] = matches.groups[key] as string;\n });\n }\n\n matched = true;\n } else if (route.keys.length > 0) {\n const matches = route.pattern.exec(pathname);\n\n if (matches === null) {\n return;\n }\n\n for (let index = 0; index < route.keys.length;) {\n const parameterKey = route.keys[index];\n\n // @ts-expect-error @TODO: fix this\n // eslint-disable-next-line no-plusplus\n parameters[parameterKey] = matches[++index];\n }\n\n matched = true;\n } else if (route.pattern.test(pathname)) {\n matched = true;\n } // else not a match\n\n if (matched) {\n fns.push(\n ...route.fns.flatMap((function_) => {\n if (function_ instanceof Router) {\n const { base } = function_;\n\n let stripPathname = pathname.slice(base.length);\n\n // fix stripped pathname, not sure why this happens\n // eslint-disable-next-line eqeqeq\n if (!stripPathname.startsWith(\"/\")) {\n stripPathname = `/${stripPathname}`;\n }\n\n // eslint-disable-next-line unicorn/no-array-callback-reference, unicorn/no-array-method-this-argument\n const result = function_.find(method, stripPathname);\n\n if (!result.middleOnly) {\n middleOnly = false;\n }\n\n // merge params\n Object.assign(parameters, result.params);\n\n return result.fns;\n }\n\n return function_;\n }),\n );\n if (!route.isMiddleware) middleOnly = false;\n }\n });\n\n return { fns, params: parameters, middleOnly };\n }\n}\n","import type { AnyZodObject, ZodObject } from \"zod\";\n\nimport withZod from \"./adapter/with-zod\";\nimport type { Route } from \"./router\";\nimport { Router } from \"./router\";\nimport type {\n FindResult,\n FunctionLike,\n HandlerOptions,\n HttpMethod,\n Nextable,\n RouteMatch,\n RoutesExtendedRequestHandler,\n RouteShortcutMethod,\n ValueOrPromise,\n} from \"./types\";\n\n// eslint-disable-next-line max-len\nconst onNoMatch = async (request: Request) => new Response(request.method === \"HEAD\" ? null : `Route ${request.method} ${request.url} not found`, { status: 404 });\n\nconst onError = async (error: unknown) => {\n // eslint-disable-next-line no-console\n console.error(error);\n return new Response(\"Internal Server Error\", { status: 500 });\n};\n\nexport function getPathname(request: Request & { nextUrl?: URL }): string {\n // eslint-disable-next-line compat/compat\n return (request.nextUrl ?? new URL(request.url)).pathname;\n}\n\n// eslint-disable-next-line max-len,@typescript-eslint/no-invalid-void-type\nexport type RequestHandler<R extends Request, Context> = (request: R, context_: Context) => ValueOrPromise<Response | void>;\n\nexport class EdgeRouter<R extends Request = Request, Context = unknown, RResponse extends Response = Response, Schema extends AnyZodObject = ZodObject<any>> {\n private router = new Router<RequestHandler<R, Context>>();\n\n private readonly onNoMatch: RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>;\n\n private readonly onError: (\n error: unknown,\n ...arguments_: Parameters<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>\n ) => ReturnType<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>;\n\n public constructor(options: HandlerOptions<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>> = {}) {\n this.onNoMatch = options.onNoMatch ?? onNoMatch as unknown as RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>;\n this.onError = options.onError\n ?? (onError as unknown as (\n error: unknown,\n ...arguments_: Parameters<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>\n ) => ReturnType<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>);\n }\n\n private add(\n method: HttpMethod | \"\",\n routeOrFunction: Nextable<RequestHandler<R, Context>> | RouteMatch,\n zodOrRouteOrFunction?: Nextable<RequestHandler<R, Context>> | RouteMatch | Schema,\n ...fns: Nextable<RequestHandler<R, Context>>[]\n ) {\n if (typeof routeOrFunction === \"string\" && typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n } else if (typeof zodOrRouteOrFunction === \"object\") {\n // eslint-disable-next-line unicorn/prefer-ternary\n if (typeof routeOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [withZod<R, Context, Nextable<RequestHandler<R, Context>>, Schema>(zodOrRouteOrFunction as Schema, routeOrFunction)];\n } else {\n // eslint-disable-next-line no-param-reassign,max-len\n fns = fns.map((function_) => withZod<R, Context, Nextable<RequestHandler<R, Context>>, Schema>(zodOrRouteOrFunction as Schema, function_));\n }\n } else if (typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n }\n\n this.router.add(method, routeOrFunction, ...fns);\n\n return this;\n }\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"\");\n\n public get: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"GET\");\n\n public head: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"HEAD\");\n\n public post: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"POST\");\n\n public put: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"PUT\");\n\n public patch: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"PATCH\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"DELETE\");\n\n public use(\n base: EdgeRouter<R, Context> | Nextable<RequestHandler<R, Context>> | RouteMatch,\n ...fns: (EdgeRouter<R, Context> | Nextable<RequestHandler<R, Context>>)[]\n ): this {\n if (typeof base === \"function\" || base instanceof EdgeRouter) {\n fns.unshift(base as EdgeRouter<R, Context>);\n // eslint-disable-next-line no-param-reassign\n base = \"/\";\n }\n\n this.router.use(base, ...fns.map((function_) => (function_ instanceof EdgeRouter ? function_.router : function_)));\n\n return this;\n }\n\n // eslint-disable-next-line class-methods-use-this\n private prepareRequest(request: R & { params?: Record<string, unknown> }, findResult: FindResult<RequestHandler<R, Context>>) {\n request.params = {\n ...findResult.params,\n ...request.params, // original params will take precedence\n };\n }\n\n public clone(): EdgeRouter<R, Context, RResponse, Schema> {\n const r = new EdgeRouter<R, Context, RResponse, Schema>({ onNoMatch: this.onNoMatch, onError: this.onError });\n\n r.router = this.router.clone();\n\n return r;\n }\n\n public async run(request: R, context_: Context): Promise<unknown> {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request));\n\n if (result.fns.length === 0) {\n return;\n }\n\n this.prepareRequest(request, result);\n\n // eslint-disable-next-line consistent-return\n return Router.exec(result.fns, request, context_);\n }\n\n public handler(): (request: R, context_: Context) => Promise<any> | ReturnType<FunctionLike> | ValueOrPromise<RResponse> {\n const { routes } = this.router as Router<FunctionLike>;\n\n return async (request: R, context_: Context): Promise<any> => {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request));\n\n this.prepareRequest(request, result);\n\n try {\n return await (result.fns.length === 0 || result.middleOnly\n ? this.onNoMatch(request, context_, routes)\n : Router.exec(result.fns, request, context_));\n } catch (error) {\n return this.onError(error, request, context_, routes);\n }\n };\n }\n}\n\nexport function createEdgeRouter<R extends Request, Context>(\n options: HandlerOptions<RoutesExtendedRequestHandler<R, Context, Response, Route<Nextable<FunctionLike>>[]>> = {},\n): EdgeRouter<R, Context> {\n return new EdgeRouter<R, Context, Response>(options);\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { RequestHandler } from \"../node\";\nimport type { Nextable } from \"../types\";\n\ntype NextFunction = (error?: any) => void;\n\nconst expressWrapper = <Request extends IncomingMessage, Response extends ServerResponse>(\n function_: ExpressRequestHandler<Request, Response>,\n // eslint-disable-next-line compat/compat\n): Nextable<RequestHandler<Request, Response>> => (request, response, next) => new Promise<void>((resolve, reject) => {\n function_(request, response, (error) => (error ? reject(error) : resolve()));\n // eslint-disable-next-line promise/no-callback-in-promise\n }).then(next);\n\nexport type ExpressRequestHandler<Request, Response> = (request: Request, response: Response, next: NextFunction) => void;\n\nexport default expressWrapper;\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { AnyZodObject, ZodObject } from \"zod\";\n\nimport withZod from \"./adapter/with-zod\";\nimport type { Route } from \"./router\";\nimport { Router } from \"./router\";\nimport type {\n FindResult,\n FunctionLike,\n HandlerOptions,\n HttpMethod,\n Nextable,\n RouteMatch,\n RoutesExtendedRequestHandler,\n RouteShortcutMethod,\n ValueOrPromise,\n} from \"./types\";\n\nconst onNoMatch = async (request: IncomingMessage, response: ServerResponse) => {\n response.statusCode = 404;\n response.end(request.method === \"HEAD\" ? undefined : `Route ${request.method} ${request.url} not found`);\n};\n\nconst onError = async (error: unknown, _request: IncomingMessage, response: ServerResponse) => {\n response.statusCode = 500;\n // eslint-disable-next-line no-console\n console.error(error);\n\n response.end(\"Internal Server Error\");\n};\n\nexport function getPathname(url: string): string {\n const queryIndex = url.indexOf(\"?\");\n\n return queryIndex === -1 ? url : url.slice(0, Math.max(0, queryIndex));\n}\n\nexport type RequestHandler<Request extends IncomingMessage, Response extends ServerResponse> = (request: Request, response: Response) => ValueOrPromise<void>;\n\nexport class NodeRouter<\n Request extends IncomingMessage = IncomingMessage,\n Response extends ServerResponse = ServerResponse,\n Schema extends AnyZodObject = ZodObject<any>,\n> {\n private router = new Router<RequestHandler<Request, Response>>();\n\n private readonly onNoMatch: RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>;\n\n private readonly onError: (\n error: unknown,\n ...arguments_: Parameters<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>>\n ) => ReturnType<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>>;\n\n public constructor(options: HandlerOptions<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>> = {}) {\n this.onNoMatch = options.onNoMatch ?? onNoMatch;\n this.onError = options.onError ?? onError;\n }\n\n private add(\n method: HttpMethod | \"\",\n routeOrFunction: Nextable<RequestHandler<Request, Response>> | RouteMatch,\n zodOrRouteOrFunction?: Nextable<RequestHandler<Request, Response>> | RouteMatch | Schema,\n ...fns: Nextable<RequestHandler<Request, Response>>[]\n ) {\n if (typeof routeOrFunction === \"string\" && typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n } else if (typeof zodOrRouteOrFunction === \"object\") {\n // eslint-disable-next-line unicorn/prefer-ternary\n if (typeof routeOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [withZod<Request, Response, Nextable<RequestHandler<Request, Response>>, Schema>(zodOrRouteOrFunction as Schema, routeOrFunction)];\n } else {\n // eslint-disable-next-line no-param-reassign,max-len\n fns = fns.map((function_) => withZod<Request, Response, Nextable<RequestHandler<Request, Response>>, Schema>(zodOrRouteOrFunction as Schema, function_));\n }\n } else if (typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n }\n\n this.router.add(method, routeOrFunction, ...fns);\n\n return this;\n }\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"\");\n\n public get: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"GET\");\n\n public head: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"HEAD\");\n\n public post: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"POST\");\n\n public put: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"PUT\");\n\n public patch: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"PATCH\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"DELETE\");\n\n public use(\n base: Nextable<RequestHandler<Request, Response>> | NodeRouter<Request, Response, Schema> | RouteMatch,\n ...fns: (Nextable<RequestHandler<Request, Response>> | NodeRouter<Request, Response, Schema>)[]\n ): this {\n if (typeof base === \"function\" || base instanceof NodeRouter) {\n fns.unshift(base);\n // eslint-disable-next-line no-param-reassign\n base = \"/\";\n }\n this.router.use(base, ...fns.map((function_) => (function_ instanceof NodeRouter ? function_.router : function_)));\n\n return this;\n }\n\n // eslint-disable-next-line class-methods-use-this\n private prepareRequest(request: Request & { params?: Record<string, unknown> }, findResult: FindResult<RequestHandler<Request, Response>>) {\n request.params = {\n ...findResult.params,\n ...request.params, // original params will take precedence\n };\n }\n\n public clone(): NodeRouter<Request, Response, Schema> {\n const r = new NodeRouter<Request, Response, Schema>({ onNoMatch: this.onNoMatch, onError: this.onError });\n\n r.router = this.router.clone();\n\n return r;\n }\n\n public async run(request: Request, response: Response): Promise<unknown> {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request.url as string));\n\n if (result.fns.length === 0) {\n return;\n }\n\n this.prepareRequest(request, result);\n\n // eslint-disable-next-line consistent-return\n return Router.exec(result.fns, request, response);\n }\n\n public handler(): (request: Request, response: Response) => Promise<void> {\n const { routes } = this.router as Router<FunctionLike>;\n\n return async (request: Request, response: Response) => {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request.url as string));\n\n this.prepareRequest(request, result);\n\n try {\n await (result.fns.length === 0 || result.middleOnly ? this.onNoMatch(request, response, routes) : Router.exec(result.fns, request, response));\n } catch (error) {\n await this.onError(error, request, response, routes);\n }\n };\n }\n}\n\nexport const createRouter = <\n Request extends IncomingMessage,\n Response extends ServerResponse,\n Schema extends AnyZodObject = ZodObject<{ body?: AnyZodObject; headers?: AnyZodObject; query?: AnyZodObject }>,\n>(\n options: HandlerOptions<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>> = {},\n ): NodeRouter<Request, Response, Schema> => new NodeRouter<Request, Response, Schema>(options);\n","import type { ServerResponse } from \"node:http\";\n\n/**\n * Send `JSON` object\n * @param {ServerResponse} response response object\n * @param {number} statusCode\n * @param {any} jsonBody of data\n */\nconst sendJson = (response: ServerResponse, statusCode: number, jsonBody: unknown): void => {\n // Set header to application/json\n response.setHeader(\"content-type\", \"application/json; charset=utf-8\");\n\n response.statusCode = statusCode;\n response.end(JSON.stringify(jsonBody, null, 2));\n};\n\nexport default sendJson;\n"]}
1
+ {"version":3,"sources":["../src/adapter/with-zod.ts","../src/router.ts","../src/edge.ts","../src/adapter/express.ts","../src/node.ts","../src/utils/send-json.ts"],"names":["createHttpError","ZodError","withZod","schema","handler","request","response","next","transformedRequest","error","message","issue","with_zod_default","parse","Router","base","routes","method","route","fns","keys","pattern","function_","arguments_","index","pathname","middleOnly","parameters","isHead","matched","matches","key","parameterKey","stripPathname","result","onNoMatch","onError","getPathname","EdgeRouter","options","routeOrFunction","zodOrRouteOrFunction","findResult","r","context_","createEdgeRouter","expressWrapper","resolve","reject","express_default","_request","url","queryIndex","NodeRouter","createRouter","sendJson","statusCode","jsonBody","send_json_default"],"mappings":"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","sourcesContent":["import createHttpError from \"http-errors\";\nimport type { AnyZodObject, ZodObject } from \"zod\";\nimport { ZodError } from \"zod\";\n\nimport type { Nextable, NextHandler } from \"../types\";\n\n// eslint-disable-next-line max-len\nconst withZod = <Request, Response, Handler extends Nextable<any>, Schema extends ZodObject<{ body?: AnyZodObject; headers?: AnyZodObject; query?: AnyZodObject }>>(\n schema: Schema,\n handler: Handler,\n): ((request: Request, response: Response, next: NextHandler) => Promise<Response>) => async (request: Request, response: Response, next) => {\n let transformedRequest: Request = request;\n\n try {\n transformedRequest = (await schema.parseAsync(request)) as Request;\n } catch (error: any) {\n let { message } = error;\n\n // eslint-disable-next-line unicorn/consistent-destructuring\n if (error instanceof ZodError && typeof error.format === \"function\") {\n // eslint-disable-next-line unicorn/consistent-destructuring\n message = error.issues.map((issue) => `${issue.path.join(\"/\")} - ${issue.message}`).join(\"/n\");\n }\n\n throw createHttpError(422, message);\n }\n\n return handler(transformedRequest, response, next);\n };\n\nexport default withZod;\n","/**\n * Agnostic router class\n * Adapted from lukeed/trouter library:\n * https://github.com/lukeed/trouter/blob/master/index.mjs\n */\nimport { parse } from \"regexparam\";\n\nimport type {\n FindResult, FunctionLike, HttpMethod, Nextable, RouteMatch,\n} from \"./types\";\n\nexport type Route<H> = {\n method: HttpMethod | \"\";\n fns: (H | Router<H extends FunctionLike ? H : never>)[];\n isMiddleware: boolean;\n} & (\n | {\n keys: string[] | false;\n pattern: RegExp;\n }\n | { matchAll: true }\n);\n\nexport class Router<H extends FunctionLike> {\n public constructor(public base: string = \"/\", public routes: Route<Nextable<H>>[] = []) {}\n\n public add(method: HttpMethod | \"\", route: Nextable<H> | RouteMatch, ...fns: Nextable<H>[]): this {\n if (typeof route === \"function\") {\n fns.unshift(route);\n // eslint-disable-next-line no-param-reassign\n route = \"\";\n }\n\n if (route === \"\") {\n this.routes.push({\n matchAll: true,\n method,\n fns,\n isMiddleware: false,\n });\n } else {\n const { keys, pattern } = parse(route);\n\n this.routes.push({\n keys,\n pattern,\n method,\n fns,\n isMiddleware: false,\n });\n }\n\n return this;\n }\n\n public use(base: Nextable<H> | RouteMatch | Router<H>, ...fns: (Nextable<H> | Router<H>)[]): this {\n if (typeof base === \"function\" || base instanceof Router) {\n fns.unshift(base);\n // eslint-disable-next-line no-param-reassign\n base = \"/\";\n }\n // mount subrouter\n // eslint-disable-next-line no-param-reassign\n fns = fns.map((function_) => {\n if (function_ instanceof Router) {\n if (typeof base === \"string\") return function_.clone(base);\n throw new Error(\"Mounting a router to RegExp base is not supported\");\n }\n return function_;\n });\n\n const { keys, pattern } = parse(base, true);\n\n this.routes.push({\n keys,\n pattern,\n method: \"\",\n fns,\n isMiddleware: true,\n });\n\n return this;\n }\n\n public clone(base?: string): Router<H> {\n return new Router<H>(base, [...this.routes]);\n }\n\n public static async exec<H extends FunctionLike>(fns: Nextable<H>[], ...arguments_: Parameters<H>): Promise<unknown> {\n let index = 0;\n\n // eslint-disable-next-line no-plusplus\n const next = () => (fns[++index] as FunctionLike)(...arguments_, next);\n\n return (fns[index] as FunctionLike)(...arguments_, next);\n }\n\n // eslint-disable-next-line sonarjs/cognitive-complexity\n public find(method: HttpMethod, pathname: string): FindResult<H> {\n let middleOnly = true;\n\n const fns: Nextable<H>[] = [];\n const parameters: Record<string, string> = {};\n const isHead = method === \"HEAD\";\n\n // eslint-disable-next-line sonarjs/cognitive-complexity\n Object.values(this.routes).forEach((route) => {\n if (\n route.method !== method\n // matches any method\n && route.method !== \"\"\n // The HEAD method requests that the target resource transfer a representation of its state, as for a GET request...\n && !(isHead && route.method === \"GET\")\n ) {\n return;\n }\n\n let matched = false;\n\n if (\"matchAll\" in route) {\n matched = true;\n } else if (route.keys === false) {\n // routes.key is RegExp: https://github.com/lukeed/regexparam/blob/master/src/index.js#L2\n const matches = route.pattern.exec(pathname);\n\n if (matches === null) {\n return;\n }\n\n // eslint-disable-next-line no-void\n if (matches.groups !== void 0) {\n Object.keys(matches.groups).forEach((key) => {\n // @ts-expect-error @TODO: fix this\n parameters[key] = matches.groups[key] as string;\n });\n }\n\n matched = true;\n } else if (route.keys.length > 0) {\n const matches = route.pattern.exec(pathname);\n\n if (matches === null) {\n return;\n }\n\n for (let index = 0; index < route.keys.length;) {\n const parameterKey = route.keys[index];\n\n // @ts-expect-error @TODO: fix this\n // eslint-disable-next-line no-plusplus\n parameters[parameterKey] = matches[++index];\n }\n\n matched = true;\n } else if (route.pattern.test(pathname)) {\n matched = true;\n } // else not a match\n\n if (matched) {\n fns.push(\n ...route.fns.flatMap((function_) => {\n if (function_ instanceof Router) {\n const { base } = function_;\n\n let stripPathname = pathname.slice(base.length);\n\n // fix stripped pathname, not sure why this happens\n // eslint-disable-next-line eqeqeq\n if (!stripPathname.startsWith(\"/\")) {\n stripPathname = `/${stripPathname}`;\n }\n\n // eslint-disable-next-line unicorn/no-array-callback-reference, unicorn/no-array-method-this-argument\n const result = function_.find(method, stripPathname);\n\n if (!result.middleOnly) {\n middleOnly = false;\n }\n\n // merge params\n Object.assign(parameters, result.params);\n\n return result.fns;\n }\n\n return function_;\n }),\n );\n if (!route.isMiddleware) middleOnly = false;\n }\n });\n\n return { fns, params: parameters, middleOnly };\n }\n}\n","import type { AnyZodObject, ZodObject } from \"zod\";\n\nimport withZod from \"./adapter/with-zod\";\nimport type { Route } from \"./router\";\nimport { Router } from \"./router\";\nimport type {\n FindResult,\n FunctionLike,\n HandlerOptions,\n HttpMethod,\n Nextable,\n RouteMatch,\n RoutesExtendedRequestHandler,\n RouteShortcutMethod,\n ValueOrPromise,\n} from \"./types\";\n\n// eslint-disable-next-line max-len\nconst onNoMatch = async (request: Request) => new Response(request.method === \"HEAD\" ? null : `Route ${request.method} ${request.url} not found`, { status: 404 });\n\nconst onError = async (error: unknown) => {\n // eslint-disable-next-line no-console\n console.error(error);\n return new Response(\"Internal Server Error\", { status: 500 });\n};\n\nexport function getPathname(request: Request & { nextUrl?: URL }): string {\n // eslint-disable-next-line compat/compat\n return (request.nextUrl ?? new URL(request.url)).pathname;\n}\n\n// eslint-disable-next-line max-len,@typescript-eslint/no-invalid-void-type\nexport type RequestHandler<R extends Request, Context> = (request: R, context_: Context) => ValueOrPromise<Response | void>;\n\nexport class EdgeRouter<R extends Request = Request, Context = unknown, RResponse extends Response = Response, Schema extends AnyZodObject = ZodObject<any>> {\n private router = new Router<RequestHandler<R, Context>>();\n\n private readonly onNoMatch: RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>;\n\n private readonly onError: (\n error: unknown,\n ...arguments_: Parameters<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>\n ) => ReturnType<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>;\n\n public constructor(options: HandlerOptions<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>> = {}) {\n this.onNoMatch = options.onNoMatch ?? (onNoMatch as unknown as RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>);\n this.onError = options.onError\n ?? (onError as unknown as (\n error: unknown,\n ...arguments_: Parameters<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>\n ) => ReturnType<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>);\n }\n\n private add(\n method: HttpMethod | \"\",\n routeOrFunction: Nextable<RequestHandler<R, Context>> | RouteMatch,\n zodOrRouteOrFunction?: Nextable<RequestHandler<R, Context>> | RouteMatch | Schema,\n ...fns: Nextable<RequestHandler<R, Context>>[]\n ) {\n if (typeof routeOrFunction === \"string\" && typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n } else if (typeof zodOrRouteOrFunction === \"object\") {\n // eslint-disable-next-line unicorn/prefer-ternary\n if (typeof routeOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [withZod<R, Context, Nextable<RequestHandler<R, Context>>, Schema>(zodOrRouteOrFunction as Schema, routeOrFunction)];\n } else {\n // eslint-disable-next-line no-param-reassign,max-len\n fns = fns.map((function_) => withZod<R, Context, Nextable<RequestHandler<R, Context>>, Schema>(zodOrRouteOrFunction as Schema, function_));\n }\n } else if (typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n }\n\n this.router.add(method, routeOrFunction, ...fns);\n\n return this;\n }\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"\");\n\n public get: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"GET\");\n\n public head: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"HEAD\");\n\n public post: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"POST\");\n\n public put: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"PUT\");\n\n public patch: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"PATCH\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"DELETE\");\n\n public use(\n base: EdgeRouter<R, Context> | Nextable<RequestHandler<R, Context>> | RouteMatch,\n ...fns: (EdgeRouter<R, Context> | Nextable<RequestHandler<R, Context>>)[]\n ): this {\n if (typeof base === \"function\" || base instanceof EdgeRouter) {\n fns.unshift(base as EdgeRouter<R, Context>);\n // eslint-disable-next-line no-param-reassign\n base = \"/\";\n }\n\n this.router.use(base, ...fns.map((function_) => (function_ instanceof EdgeRouter ? function_.router : function_)));\n\n return this;\n }\n\n // eslint-disable-next-line class-methods-use-this\n private prepareRequest(request: R & { params?: Record<string, unknown> }, findResult: FindResult<RequestHandler<R, Context>>) {\n request.params = {\n ...findResult.params,\n ...request.params, // original params will take precedence\n };\n }\n\n public clone(): EdgeRouter<R, Context, RResponse, Schema> {\n const r = new EdgeRouter<R, Context, RResponse, Schema>({ onNoMatch: this.onNoMatch, onError: this.onError });\n\n r.router = this.router.clone();\n\n return r;\n }\n\n public async run(request: R, context_: Context): Promise<unknown> {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request));\n\n if (result.fns.length === 0) {\n return;\n }\n\n this.prepareRequest(request, result);\n\n // eslint-disable-next-line consistent-return\n return Router.exec(result.fns, request, context_);\n }\n\n public handler(): (request: R, context_: Context) => Promise<any> | ReturnType<FunctionLike> | ValueOrPromise<RResponse> {\n const { routes } = this.router as Router<FunctionLike>;\n\n return async (request: R, context_: Context): Promise<any> => {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request));\n\n this.prepareRequest(request, result);\n\n try {\n return await (result.fns.length === 0 || result.middleOnly\n ? this.onNoMatch(request, context_, routes)\n : Router.exec(result.fns, request, context_));\n } catch (error) {\n return this.onError(error, request, context_, routes);\n }\n };\n }\n}\n\nexport function createEdgeRouter<R extends Request, Context>(\n options: HandlerOptions<RoutesExtendedRequestHandler<R, Context, Response, Route<Nextable<FunctionLike>>[]>> = {},\n): EdgeRouter<R, Context> {\n return new EdgeRouter<R, Context, Response>(options);\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { RequestHandler } from \"../node\";\nimport type { Nextable } from \"../types\";\n\ntype NextFunction = (error?: any) => void;\n\nconst expressWrapper = <Request extends IncomingMessage, Response extends ServerResponse>(\n function_: ExpressRequestHandler<Request, Response>,\n // eslint-disable-next-line compat/compat\n): Nextable<RequestHandler<Request, Response>> => (request, response, next) => new Promise<void>((resolve, reject) => {\n function_(request, response, (error) => (error ? reject(error) : resolve()));\n // eslint-disable-next-line promise/no-callback-in-promise\n }).then(next);\n\nexport type ExpressRequestHandler<Request, Response> = (request: Request, response: Response, next: NextFunction) => void;\n\nexport default expressWrapper;\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { AnyZodObject, ZodObject } from \"zod\";\n\nimport withZod from \"./adapter/with-zod\";\nimport type { Route } from \"./router\";\nimport { Router } from \"./router\";\nimport type {\n FindResult,\n FunctionLike,\n HandlerOptions,\n HttpMethod,\n Nextable,\n RouteMatch,\n RoutesExtendedRequestHandler,\n RouteShortcutMethod,\n ValueOrPromise,\n} from \"./types\";\n\nconst onNoMatch = async (request: IncomingMessage, response: ServerResponse) => {\n response.statusCode = 404;\n response.end(request.method === \"HEAD\" ? undefined : `Route ${request.method} ${request.url} not found`);\n};\n\nconst onError = async (error: unknown, _request: IncomingMessage, response: ServerResponse) => {\n response.statusCode = 500;\n // eslint-disable-next-line no-console\n console.error(error);\n\n response.end(\"Internal Server Error\");\n};\n\nexport function getPathname(url: string): string {\n const queryIndex = url.indexOf(\"?\");\n\n return queryIndex === -1 ? url : url.slice(0, Math.max(0, queryIndex));\n}\n\nexport type RequestHandler<Request extends IncomingMessage, Response extends ServerResponse> = (request: Request, response: Response) => ValueOrPromise<void>;\n\nexport class NodeRouter<\n Request extends IncomingMessage = IncomingMessage,\n Response extends ServerResponse = ServerResponse,\n Schema extends AnyZodObject = ZodObject<any>,\n> {\n private router = new Router<RequestHandler<Request, Response>>();\n\n private readonly onNoMatch: RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>;\n\n private readonly onError: (\n error: unknown,\n ...arguments_: Parameters<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>>\n ) => ReturnType<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>>;\n\n public constructor(options: HandlerOptions<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>> = {}) {\n this.onNoMatch = options.onNoMatch ?? onNoMatch;\n this.onError = options.onError ?? onError;\n }\n\n private add(\n method: HttpMethod | \"\",\n routeOrFunction: Nextable<RequestHandler<Request, Response>> | RouteMatch,\n zodOrRouteOrFunction?: Nextable<RequestHandler<Request, Response>> | RouteMatch | Schema,\n ...fns: Nextable<RequestHandler<Request, Response>>[]\n ) {\n if (typeof routeOrFunction === \"string\" && typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n } else if (typeof zodOrRouteOrFunction === \"object\") {\n // eslint-disable-next-line unicorn/prefer-ternary\n if (typeof routeOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [withZod<Request, Response, Nextable<RequestHandler<Request, Response>>, Schema>(zodOrRouteOrFunction as Schema, routeOrFunction)];\n } else {\n // eslint-disable-next-line no-param-reassign,max-len\n fns = fns.map((function_) => withZod<Request, Response, Nextable<RequestHandler<Request, Response>>, Schema>(zodOrRouteOrFunction as Schema, function_));\n }\n } else if (typeof zodOrRouteOrFunction === \"function\") {\n // eslint-disable-next-line no-param-reassign\n fns = [zodOrRouteOrFunction];\n }\n\n this.router.add(method, routeOrFunction, ...fns);\n\n return this;\n }\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"\");\n\n public get: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"GET\");\n\n public head: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"HEAD\");\n\n public post: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"POST\");\n\n public put: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"PUT\");\n\n public patch: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"PATCH\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"DELETE\");\n\n public use(\n base: Nextable<RequestHandler<Request, Response>> | NodeRouter<Request, Response, Schema> | RouteMatch,\n ...fns: (Nextable<RequestHandler<Request, Response>> | NodeRouter<Request, Response, Schema>)[]\n ): this {\n if (typeof base === \"function\" || base instanceof NodeRouter) {\n fns.unshift(base);\n // eslint-disable-next-line no-param-reassign\n base = \"/\";\n }\n this.router.use(base, ...fns.map((function_) => (function_ instanceof NodeRouter ? function_.router : function_)));\n\n return this;\n }\n\n // eslint-disable-next-line class-methods-use-this\n private prepareRequest(request: Request & { params?: Record<string, unknown> }, findResult: FindResult<RequestHandler<Request, Response>>) {\n request.params = {\n ...findResult.params,\n ...request.params, // original params will take precedence\n };\n }\n\n public clone(): NodeRouter<Request, Response, Schema> {\n const r = new NodeRouter<Request, Response, Schema>({ onNoMatch: this.onNoMatch, onError: this.onError });\n\n r.router = this.router.clone();\n\n return r;\n }\n\n public async run(request: Request, response: Response): Promise<unknown> {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request.url as string));\n\n if (result.fns.length === 0) {\n return;\n }\n\n this.prepareRequest(request, result);\n\n // eslint-disable-next-line consistent-return\n return Router.exec(result.fns, request, response);\n }\n\n public handler(): (request: Request, response: Response) => Promise<void> {\n const { routes } = this.router as Router<FunctionLike>;\n\n return async (request: Request, response: Response) => {\n // eslint-disable-next-line unicorn/no-array-callback-reference,unicorn/no-array-method-this-argument\n const result = this.router.find(request.method as HttpMethod, getPathname(request.url as string));\n\n this.prepareRequest(request, result);\n\n try {\n await (result.fns.length === 0 || result.middleOnly ? this.onNoMatch(request, response, routes) : Router.exec(result.fns, request, response));\n } catch (error) {\n await this.onError(error, request, response, routes);\n }\n };\n }\n}\n\nexport const createRouter = <\n Request extends IncomingMessage,\n Response extends ServerResponse,\n Schema extends AnyZodObject = ZodObject<{ body?: AnyZodObject; headers?: AnyZodObject; query?: AnyZodObject }>,\n>(\n options: HandlerOptions<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>> = {},\n ): NodeRouter<Request, Response, Schema> => new NodeRouter<Request, Response, Schema>(options);\n","import type { ServerResponse } from \"node:http\";\n\n/**\n * Send `JSON` object\n * @param {ServerResponse} response response object\n * @param {number} statusCode\n * @param {any} jsonBody of data\n */\nconst sendJson = (response: ServerResponse, statusCode: number, jsonBody: unknown): void => {\n // Set header to application/json\n response.setHeader(\"content-type\", \"application/json; charset=utf-8\");\n\n response.statusCode = statusCode;\n response.end(JSON.stringify(jsonBody, null, 2));\n};\n\nexport default sendJson;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visulima/connect",
3
- "version": "1.3.4",
3
+ "version": "1.3.6",
4
4
  "description": "The minimal router and middleware layer for Next.js, Micro, Vercel, or Node.js http/http2 with support for zod validation.",
5
5
  "keywords": [
6
6
  "javascript",
@@ -62,7 +62,7 @@
62
62
  "build:prod": "cross-env NODE_ENV=production tsup",
63
63
  "clean": "rimraf node_modules dist .eslintcache",
64
64
  "coverage": "vitest run --coverage",
65
- "dev": "pnpm predev && pnpm run build --watch",
65
+ "dev": "pnpm run build --watch",
66
66
  "lint:eslint": "cross-env NO_LOGS=true eslint . --ext js,jsx,ts,tsx --max-warnings=0 --config .eslintrc.cjs --cache --cache-strategy content .",
67
67
  "lint:eslint:fix": "pnpm run lint:eslint --fix",
68
68
  "test": "vitest run",
@@ -77,11 +77,11 @@
77
77
  "@anolilab/semantic-release-preset": "^2.2.1",
78
78
  "@rushstack/eslint-plugin-security": "^0.6.0",
79
79
  "@types/http-errors": "^2.0.1",
80
- "@types/node": "18.16.14",
81
- "@typescript-eslint/eslint-plugin": "^5.59.7",
82
- "@typescript-eslint/parser": "^5.59.7",
80
+ "@types/node": "18.16.16",
81
+ "@typescript-eslint/eslint-plugin": "^5.59.8",
82
+ "@typescript-eslint/parser": "^5.59.8",
83
83
  "@vitest/coverage-c8": "^0.31.1",
84
- "c8": "^7.13.0",
84
+ "c8": "^7.14.0",
85
85
  "cross-env": "^7.0.3",
86
86
  "eslint": "^8.41.0",
87
87
  "eslint-plugin-compat": "^4.1.4",
@@ -107,7 +107,6 @@
107
107
  "fastify": "^4.17.0",
108
108
  "isomorphic-fetch": "^3.0.0",
109
109
  "prettier": "^2.8.8",
110
- "read-pkg": "^8.0.0",
111
110
  "rimraf": "^5.0.1",
112
111
  "semantic-release": "^21.0.2",
113
112
  "tsup": "^6.7.0",
@@ -122,6 +121,7 @@
122
121
  "node": ">=16.18.0 <=20.*"
123
122
  },
124
123
  "publishConfig": {
125
- "access": "public"
124
+ "access": "public",
125
+ "provenance": true
126
126
  }
127
127
  }