@visulima/connect 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## @visulima/connect [2.1.0](https://github.com/visulima/visulima/compare/@visulima/connect@2.0.1...@visulima/connect@2.1.0) (2023-09-05)
2
+
3
+
4
+ ### Features
5
+
6
+ * added new methods, added new examples, fixed issue with undefined next handler call ([#208](https://github.com/visulima/visulima/issues/208)) ([759be69](https://github.com/visulima/visulima/commit/759be6913d6aad438e6528160d9d695c376e4a81))
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **deps:** update package versions in pnpm-lock file ([6917001](https://github.com/visulima/visulima/commit/69170010084f572f6f4609a68ab653c68e8cfe64))
12
+
13
+
14
+
15
+ ### Dependencies
16
+
17
+ * **@visulima/nextra-theme-docs:** upgraded to 4.0.1
18
+
1
19
  ## @visulima/connect [2.0.1](https://github.com/visulima/visulima/compare/@visulima/connect@2.0.0...@visulima/connect@2.0.1) (2023-08-29)
2
20
 
3
21
 
package/README.md CHANGED
@@ -1,12 +1,15 @@
1
1
  <div align="center">
2
2
  <h3>Visulima connect</h3>
3
3
  <p>
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
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, App Router, getServerSideProps, Middleware) and many other frameworks is built on top of
5
5
 
6
- [next-connect](https://github.com/hoangvvo/next-connect),
7
6
  [http-errors](https://github.com/jshttp/http-errors),
8
7
  [regexparam](https://github.com/lukeed/regexparam)
9
8
 
9
+ and based on
10
+
11
+ [next-connect](https://github.com/hoangvvo/next-connect)
12
+
10
13
  </p>
11
14
  </div>
12
15
 
@@ -110,7 +113,7 @@ router
110
113
  },
111
114
  );
112
115
 
113
- export default router.nodeHandler();
116
+ export default router.handler();
114
117
  ```
115
118
 
116
119
  ### Next.js getServerSideProps
@@ -219,7 +222,7 @@ router
219
222
  });
220
223
  });
221
224
 
222
- export default router.nodeHandler();
225
+ export default router.handler();
223
226
  ```
224
227
 
225
228
  ### Next.js Middleware
@@ -339,7 +342,7 @@ router.get((req, res, next) => {
339
342
 
340
343
  Same as [.METHOD](#methodpattern-fns) but accepts _any_ methods.
341
344
 
342
- ### router.nodeHandler(options)
345
+ ### router.handler(options)
343
346
 
344
347
  Create a nodeHandler to handle incoming requests.
345
348
 
@@ -358,7 +361,7 @@ function onError(err, req, res) {
358
361
 
359
362
  const router = createNodeRouter({ onError });
360
363
 
361
- export default router.nodeHandler();
364
+ export default router.handler();
362
365
  ```
363
366
 
364
367
  **options.onNoMatch**
@@ -373,7 +376,7 @@ function onNoMatch(req, res) {
373
376
 
374
377
  const router = createNodeRouter({ onNoMatch });
375
378
 
376
- export default router.nodeHandler();
379
+ export default router.handler();
377
380
  ```
378
381
 
379
382
  ### router.run(req, res)
@@ -468,7 +471,7 @@ const nodeHandler = router
468
471
  res.send("ok");
469
472
  console.log("request is completed");
470
473
  })
471
- .nodeHandler();
474
+ .handler();
472
475
 
473
476
  await nodeHandler(req, res);
474
477
  console.log("finally"); // this will run before the get layer gets to finish
@@ -487,12 +490,12 @@ export default createNodeRouter().use(a).use(b);
487
490
  // api/foo.js
488
491
  import router from "api-libs/base";
489
492
 
490
- export default router.get(x).nodeHandler();
493
+ export default router.get(x).handler();
491
494
 
492
495
  // api/bar.js
493
496
  import router from "api-libs/base";
494
497
 
495
- export default router.get(y).nodeHandler();
498
+ export default router.get(y).handler();
496
499
  ```
497
500
 
498
501
  This is because, in each API Route, the same router instance is mutated, leading to undefined behaviors.
@@ -505,12 +508,12 @@ export default createNodeRouter().use(a).use(b);
505
508
  // api/foo.js
506
509
  import router from "api-libs/base";
507
510
 
508
- export default router.clone().get(x).nodeHandler();
511
+ export default router.clone().get(x).handler();
509
512
 
510
513
  // api/bar.js
511
514
  import router from "api-libs/base";
512
515
 
513
- export default router.clone().get(y).nodeHandler();
516
+ export default router.clone().get(y).handler();
514
517
  ```
515
518
 
516
519
  3. **DO NOT** use response function like `res.(s)end` or `res.redirect` inside `getServerSideProps`.
@@ -541,7 +544,7 @@ export async function getServerSideProps({ req, res }) {
541
544
  ```javascript
542
545
  // page/index.js
543
546
  const router = createNodeRouter().use(foo).use(bar);
544
- const nodeHandler = router.nodeHandler();
547
+ const nodeHandler = router.handler();
545
548
 
546
549
  export async function getServerSideProps({ req, res }) {
547
550
  await nodeHandler(req, res); // BAD: You should call router.run(req, res);
@@ -572,7 +575,7 @@ const router = createNodeRouter()
572
575
  res.send(`Hello ${req.params.userId}`);
573
576
  });
574
577
 
575
- export default router.nodeHandler();
578
+ export default router.handler();
576
579
  ```
577
580
 
578
581
  While this allows quick migration from Express.js, consider separating routes into different files (`/api/user/[userId].js`, `/api/hello.js`) in the future.
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@ import { IncomingMessage, ServerResponse } from 'node:http';
2
2
  import * as zod from 'zod';
3
3
  import { AnyZodObject, ZodObject } from 'zod';
4
4
 
5
- type HttpMethod = "DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT";
5
+ type HttpMethod = "CONNECT" | "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "TRACE";
6
6
 
7
7
  type FunctionLike = (...arguments_: any[]) => any;
8
8
 
@@ -52,7 +52,7 @@ declare class Router<H extends FunctionLike> {
52
52
  base: string;
53
53
  routes: Route<Nextable<H>>[];
54
54
  constructor(base?: string, routes?: Route<Nextable<H>>[]);
55
- static exec<FL extends FunctionLike>(fns: Nextable<FL>[], ...arguments_: Parameters<FL>): Promise<any>;
55
+ static exec<FL extends FunctionLike>(fns: (Nextable<FL> | undefined)[], ...arguments_: Parameters<FL>): Promise<any>;
56
56
  add(method: HttpMethod | "", route: Nextable<H> | RouteMatch, ...fns: Nextable<H>[]): this;
57
57
  clone(base?: string): Router<H>;
58
58
  find(method: HttpMethod, pathname: string): FindResult<H>;
@@ -65,12 +65,15 @@ declare class NodeRouter<Request extends IncomingMessage = IncomingMessage, Resp
65
65
  private readonly onNoMatch;
66
66
  private router;
67
67
  all: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
68
+ connect: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
68
69
  delete: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
69
70
  get: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
70
71
  head: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
72
+ options: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
71
73
  patch: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
72
74
  post: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
73
75
  put: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
76
+ trace: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
74
77
  constructor(options?: HandlerOptions<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>>);
75
78
  private add;
76
79
  private prepareRequest;
@@ -117,12 +120,15 @@ declare class EdgeRouter<R extends Request = Request, Context = unknown, RRespon
117
120
  private readonly onNoMatch;
118
121
  private router;
119
122
  all: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
123
+ connect: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
120
124
  delete: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
121
125
  get: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
122
126
  head: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
127
+ options: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
123
128
  patch: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
124
129
  post: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
125
130
  put: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
131
+ trace: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
126
132
  constructor(options?: HandlerOptions<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>);
127
133
  private add;
128
134
  private prepareRequest;
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { IncomingMessage, ServerResponse } from 'node:http';
2
2
  import * as zod from 'zod';
3
3
  import { AnyZodObject, ZodObject } from 'zod';
4
4
 
5
- type HttpMethod = "DELETE" | "GET" | "HEAD" | "PATCH" | "POST" | "PUT";
5
+ type HttpMethod = "CONNECT" | "DELETE" | "GET" | "HEAD" | "OPTIONS" | "PATCH" | "POST" | "PUT" | "TRACE";
6
6
 
7
7
  type FunctionLike = (...arguments_: any[]) => any;
8
8
 
@@ -52,7 +52,7 @@ declare class Router<H extends FunctionLike> {
52
52
  base: string;
53
53
  routes: Route<Nextable<H>>[];
54
54
  constructor(base?: string, routes?: Route<Nextable<H>>[]);
55
- static exec<FL extends FunctionLike>(fns: Nextable<FL>[], ...arguments_: Parameters<FL>): Promise<any>;
55
+ static exec<FL extends FunctionLike>(fns: (Nextable<FL> | undefined)[], ...arguments_: Parameters<FL>): Promise<any>;
56
56
  add(method: HttpMethod | "", route: Nextable<H> | RouteMatch, ...fns: Nextable<H>[]): this;
57
57
  clone(base?: string): Router<H>;
58
58
  find(method: HttpMethod, pathname: string): FindResult<H>;
@@ -65,12 +65,15 @@ declare class NodeRouter<Request extends IncomingMessage = IncomingMessage, Resp
65
65
  private readonly onNoMatch;
66
66
  private router;
67
67
  all: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
68
+ connect: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
68
69
  delete: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
69
70
  get: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
70
71
  head: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
72
+ options: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
71
73
  patch: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
72
74
  post: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
73
75
  put: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
76
+ trace: RouteShortcutMethod<this, Schema, RequestHandler$1<Request, Response>>;
74
77
  constructor(options?: HandlerOptions<RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>>);
75
78
  private add;
76
79
  private prepareRequest;
@@ -117,12 +120,15 @@ declare class EdgeRouter<R extends Request = Request, Context = unknown, RRespon
117
120
  private readonly onNoMatch;
118
121
  private router;
119
122
  all: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
123
+ connect: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
120
124
  delete: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
121
125
  get: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
122
126
  head: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
127
+ options: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
123
128
  patch: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
124
129
  post: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
125
130
  put: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
131
+ trace: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>>;
126
132
  constructor(options?: HandlerOptions<RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>>);
127
133
  private add;
128
134
  private prepareRequest;
package/dist/index.js CHANGED
@@ -8,16 +8,16 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
8
 
9
9
  var N__default = /*#__PURE__*/_interopDefault(N);
10
10
 
11
- var M=o=>async(e,t,s)=>await new Promise((n,r)=>{o(e,t,R=>R?r(R):n());}).then(s),S=M;var E=(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")),N__default.default(422,a)}return e(r,s,n)},l=E;var i=class o{constructor(e="/",t=[]){this.base=e;this.routes=t;}static async exec(e,...t){let s=0,n=()=>e[++s](...t,n);return e[s](...t,n)}add(e,t,...s){if(typeof t=="function"&&(s.unshift(t),t=""),t==="")this.routes.push({fns:s,isMiddleware:!1,matchAll:!0,method:e});else {let{keys:n,pattern:r}=regexparam.parse(t);this.routes.push({fns:s,isMiddleware:!1,keys:n,method:e,pattern:r});}return this}clone(e){return new o(e,[...this.routes])}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 u=a.pattern.exec(t);if(u===null)return;u.groups!==void 0&&Object.keys(u.groups).forEach(p=>{r[p]=u.groups[p];}),d=!0;}else if(a.keys.length>0){let u=a.pattern.exec(t);if(u===null)return;for(let p=0;p<a.keys.length;){let c=a.keys[p];r[c]=u[++p];}d=!0;}else a.pattern.test(t)&&(d=!0);d&&(n.push(...a.fns.flatMap(u=>{if(u instanceof o){let{base:p}=u,c=t.slice(p.length);c.startsWith("/")||(c=`/${c}`);let f=u.find(e,c);return f.middleOnly||(s=!1),Object.assign(r,f.params),f.fns}return u})),a.isMiddleware||(s=!1));}),{fns:n,middleOnly:s,params:r}}use(e,...t){(typeof e=="function"||e instanceof o)&&(t.unshift(e),e="/"),t=t.map(r=>{if(r instanceof o){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({fns:t,isMiddleware:!0,keys:s,method:"",pattern:n}),this}};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})),y=o=>(o.nextUrl??new URL(o.url)).pathname,x=class o{constructor(e={}){this.router=new i;this.all=this.add.bind(this,"");this.delete=this.add.bind(this,"DELETE");this.get=this.add.bind(this,"GET");this.head=this.add.bind(this,"HEAD");this.patch=this.add.bind(this,"PATCH");this.post=this.add.bind(this,"POST");this.put=this.add.bind(this,"PUT");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=[l(s,t)]:n=n.map(r=>l(s,r)):typeof s=="function"&&(n=[s]),this.router.add(e,t,...n),this}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new o({onError:this.onError,onNoMatch:this.onNoMatch});return e.router=this.router.clone(),e}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 await this.onError(r,t,s,e)}}}async run(e,t){let s=this.router.find(e.method,y(e));if(s.fns.length!==0)return this.prepareRequest(e,s),await i.exec(s.fns,e,t)}use(e,...t){return (typeof e=="function"||e instanceof o)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof o?s.router:s)),this}},w=(o={})=>new x(o);var v=async(o,e)=>{e.statusCode=404,e.end(o.method==="HEAD"?void 0:`Route ${o.method} ${o.url} not found`);},L=async(o,e,t)=>{t.statusCode=500,console.error(o),t.end("Internal Server Error");},b=o=>{let e=o.indexOf("?");return e===-1?o:o.slice(0,Math.max(0,e))},m=class o{constructor(e={}){this.router=new i;this.all=this.add.bind(this,"");this.delete=this.add.bind(this,"DELETE");this.get=this.add.bind(this,"GET");this.head=this.add.bind(this,"HEAD");this.patch=this.add.bind(this,"PATCH");this.post=this.add.bind(this,"POST");this.put=this.add.bind(this,"PUT");this.onNoMatch=e.onNoMatch??v,this.onError=e.onError??L;}add(e,t,s,...n){return typeof t=="string"&&typeof s=="function"?n=[s]:typeof s=="object"?typeof t=="function"?n=[l(s,t)]:n=n.map(r=>l(s,r)):typeof s=="function"&&(n=[s]),this.router.add(e,t,...n),this}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new o({onError:this.onError,onNoMatch:this.onNoMatch});return e.router=this.router.clone(),e}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);}}}async run(e,t){let s=this.router.find(e.method,b(e.url));if(s.fns.length!==0)return this.prepareRequest(e,s),await i.exec(s.fns,e,t)}use(e,...t){return (typeof e=="function"||e instanceof o)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof o?s.router:s)),this}},q=(o={})=>new m(o);var j=(o,e,t)=>{o.setHeader("content-type","application/json; charset=utf-8"),o.statusCode=e,o.end(JSON.stringify(t,null,2));},P=j;
11
+ var S=o=>async(e,t,s)=>await new Promise((n,r)=>{o(e,t,d=>d?r(d):n());}).then(s),M=S;var g=(o,e)=>async(t,s,n)=>{let r=t;try{r=await o.parseAsync(t);}catch(d){let{message:a}=d;throw d instanceof zod.ZodError&&typeof d.format=="function"&&(a=d.issues.map(R=>`${R.path.join("/")} - ${R.message}`).join("/n")),N__default.default(422,a)}return e(r,s,n)},h=g;var i=class o{constructor(e="/",t=[]){this.base=e;this.routes=t;}static async exec(e,...t){let s=0,n=()=>{let r=e[++s];return r===void 0?Promise.resolve():r(...t,n)};return e[s](...t,n)}add(e,t,...s){if(typeof t=="function"&&(s.unshift(t),t=""),t==="")this.routes.push({fns:s,isMiddleware:!1,matchAll:!0,method:e});else {let{keys:n,pattern:r}=regexparam.parse(t);this.routes.push({fns:s,isMiddleware:!1,keys:n,method:e,pattern:r});}return this}clone(e){return new o(e,[...this.routes])}find(e,t){let s=!0,n=[],r={},d=e==="HEAD";return Object.values(this.routes).forEach(a=>{if(a.method!==e&&a.method!==""&&!(d&&a.method==="GET"))return;let R=!1;if("matchAll"in a)R=!0;else if(a.keys===!1){let u=a.pattern.exec(t);if(u===null)return;u.groups!==void 0&&Object.keys(u.groups).forEach(p=>{r[p]=u.groups[p];}),R=!0;}else if(a.keys.length>0){let u=a.pattern.exec(t);if(u===null)return;for(let p=0;p<a.keys.length;){let c=a.keys[p];r[c]=u[++p];}R=!0;}else a.pattern.test(t)&&(R=!0);R&&(n.push(...a.fns.flatMap(u=>{if(u instanceof o){let{base:p}=u,c=t.slice(p.length);c.startsWith("/")||(c=`/${c}`);let f=u.find(e,c);return f.middleOnly||(s=!1),Object.assign(r,f.params),f.fns}return u})),a.isMiddleware||(s=!1));}),{fns:n,middleOnly:s,params:r}}use(e,...t){(typeof e=="function"||e instanceof o)&&(t.unshift(e),e="/"),t=t.map(r=>{if(r instanceof o){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({fns:t,isMiddleware:!0,keys:s,method:"",pattern:n}),this}};var C=async o=>new Response(o.method==="HEAD"?null:`Route ${o.method} ${o.url} not found`,{status:404}),k=async o=>(console.error(o),new Response("Internal Server Error",{status:500})),H=o=>(o.nextUrl??new URL(o.url)).pathname,x=class o{constructor(e={}){this.router=new i;this.all=this.add.bind(this,"");this.connect=this.add.bind(this,"CONNECT");this.delete=this.add.bind(this,"DELETE");this.get=this.add.bind(this,"GET");this.head=this.add.bind(this,"HEAD");this.options=this.add.bind(this,"OPTIONS");this.patch=this.add.bind(this,"PATCH");this.post=this.add.bind(this,"POST");this.put=this.add.bind(this,"PUT");this.trace=this.add.bind(this,"TRACE");this.onNoMatch=e.onNoMatch??C,this.onError=e.onError??k;}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}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new o({onError:this.onError,onNoMatch:this.onNoMatch});return e.router=this.router.clone(),e}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):i.exec(n.fns,t,s))}catch(r){return await this.onError(r,t,s,e)}}}async run(e,t){let s=this.router.find(e.method,H(e));if(s.fns.length!==0)return this.prepareRequest(e,s),await i.exec(s.fns,e,t)}use(e,...t){return (typeof e=="function"||e instanceof o)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof o?s.router:s)),this}},w=(o={})=>new x(o);var v=async(o,e)=>{e.statusCode=404,e.end(o.method==="HEAD"?void 0:`Route ${o.method} ${o.url} not found`);},L=async(o,e,t)=>{t.statusCode=500,console.error(o),t.end("Internal Server Error");},q=o=>{let e=o.indexOf("?");return e===-1?o:o.slice(0,Math.max(0,e))},m=class o{constructor(e={}){this.router=new i;this.all=this.add.bind(this,"");this.connect=this.add.bind(this,"CONNECT");this.delete=this.add.bind(this,"DELETE");this.get=this.add.bind(this,"GET");this.head=this.add.bind(this,"HEAD");this.options=this.add.bind(this,"OPTIONS");this.patch=this.add.bind(this,"PATCH");this.post=this.add.bind(this,"POST");this.put=this.add.bind(this,"PUT");this.trace=this.add.bind(this,"TRACE");this.onNoMatch=e.onNoMatch??v,this.onError=e.onError??L;}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}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new o({onError:this.onError,onNoMatch:this.onNoMatch});return e.router=this.router.clone(),e}handler(){let{routes:e}=this.router;return async(t,s)=>{let n=this.router.find(t.method,q(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);}}}async run(e,t){let s=this.router.find(e.method,q(e.url));if(s.fns.length!==0)return this.prepareRequest(e,s),await i.exec(s.fns,e,t)}use(e,...t){return (typeof e=="function"||e instanceof o)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof o?s.router:s)),this}},y=(o={})=>new m(o);var P=(o,e,t)=>{o.setHeader("content-type","application/json; charset=utf-8"),o.statusCode=e,o.end(JSON.stringify(t,null,2));},j=P;
12
12
 
13
13
  exports.EdgeRouter = x;
14
14
  exports.NodeRouter = m;
15
15
  exports.Router = i;
16
16
  exports.createEdgeRouter = w;
17
- exports.createNodeRouter = q;
18
- exports.createRouter = q;
19
- exports.expressWrapper = S;
20
- exports.sendJson = P;
21
- exports.withZod = l;
17
+ exports.createNodeRouter = y;
18
+ exports.createRouter = y;
19
+ exports.expressWrapper = M;
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/express.ts","../src/adapter/with-zod.ts","../src/router.ts","../src/edge.ts","../src/node.ts","../src/utils/send-json.ts"],"names":["expressWrapper","function_","request","response","next","resolve","reject","error","express_default","createHttpError","ZodError","withZod","schema","handler","transformedRequest","message","issue","with_zod_default","parse","Router","_Router","base","routes","fns","arguments_","index","method","route","keys","pattern","pathname","middleOnly","parameters","isHead","matched","matches","key","parameterKey","stripPathname","result","onNoMatch","onError","getPathname","EdgeRouter","_EdgeRouter","options","routeOrFunction","zodOrRouteOrFunction","findResult","r","context_","createEdgeRouter","_request","url","queryIndex","NodeRouter","_NodeRouter","createRouter","sendJson","statusCode","jsonBody","send_json_default"],"mappings":"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","sourcesContent":["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 =\n <Request extends IncomingMessage, Response extends ServerResponse>(\n // eslint-disable-next-line no-use-before-define\n function_: ExpressRequestHandler<Request, Response>,\n ): Nextable<RequestHandler<Request, Response>> =>\n async (request, response, next) =>\n // eslint-disable-next-line compat/compat\n await new Promise<void>((resolve, reject): void => {\n function_(request, response, (error) => (error ? reject(error) : resolve()));\n // eslint-disable-next-line promise/no-callback-in-promise\n }).then<Nextable<RequestHandler<Request, Response>>>(next);\n\nexport type ExpressRequestHandler<Request, Response> = (request: Request, response: Response, next: NextFunction) => void;\n\nexport default expressWrapper;\n","import createHttpError from \"http-errors\";\nimport type { AnyZodObject, ZodObject } from \"zod\";\nimport { ZodError } from \"zod\";\n\nimport type { NextHandler, Nextable } from \"../types\";\n\nconst withZod =\n <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>) =>\n 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 as Error;\n\n if (error instanceof ZodError && typeof error.format === \"function\") {\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 { FindResult, FunctionLike, HttpMethod, Nextable, RouteMatch } from \"./types\";\n\nexport type Route<H> = {\n // eslint-disable-next-line no-use-before-define\n fns: (H | Router<H extends FunctionLike ? H : never>)[];\n isMiddleware: boolean;\n method: HttpMethod | \"\";\n} & (\n | {\n keys: string[] | false;\n pattern: RegExp;\n }\n | { matchAll: true }\n);\n\nexport class Router<H extends FunctionLike> {\n public constructor(\n public base = \"/\",\n public routes: Route<Nextable<H>>[] = [],\n ) {}\n\n public static async exec<FL extends FunctionLike>(fns: Nextable<FL>[], ...arguments_: Parameters<FL>): Promise<any> {\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 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 fns,\n isMiddleware: false,\n matchAll: true,\n method,\n });\n } else {\n const { keys, pattern } = parse(route);\n\n this.routes.push({\n fns,\n isMiddleware: false,\n keys,\n method,\n pattern,\n });\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 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\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) {\n middleOnly = false;\n }\n }\n });\n\n return { fns, middleOnly, params: parameters };\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\") {\n return function_.clone(base);\n }\n\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 fns,\n isMiddleware: true,\n keys,\n method: \"\",\n pattern,\n });\n\n return this;\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 RouteShortcutMethod,\n RoutesExtendedRequestHandler,\n ValueOrPromise,\n} from \"./types\";\n\nconst onNoMatch = async (request: Request) =>\n 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\n return new Response(\"Internal Server Error\", { status: 500 });\n};\n\nexport const getPathname = (request: Request & { nextUrl?: URL }): string =>\n // eslint-disable-next-line compat/compat\n (request.nextUrl ?? new URL(request.url)).pathname;\n\n// eslint-disable-next-line @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 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 private readonly onNoMatch: RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>;\n\n private router = new Router<RequestHandler<R, Context>>();\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"DELETE\");\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 patch: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"PATCH\");\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 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 =\n 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\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 // 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>({ onError: this.onError, onNoMatch: this.onNoMatch });\n\n r.router = this.router.clone();\n\n return r;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\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 await this.onError(error, request, context_, routes);\n }\n };\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 await Router.exec(result.fns, request, context_);\n }\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\nexport const createEdgeRouter = <R extends Request, Context>(\n options: HandlerOptions<RoutesExtendedRequestHandler<R, Context, Response, Route<Nextable<FunctionLike>>[]>> = {},\n): EdgeRouter<R, Context> => new EdgeRouter<R, Context, Response>(options);\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 RouteShortcutMethod,\n RoutesExtendedRequestHandler,\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\n // eslint-disable-next-line no-console\n console.error(error);\n\n response.end(\"Internal Server Error\");\n};\n\nexport const 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<never>,\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 private readonly onNoMatch: RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>;\n\n private router = new Router<RequestHandler<Request, Response>>();\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"DELETE\");\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 patch: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"PATCH\");\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 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 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\n fns = fns.map((function_) =>\n withZod<Request, Response, Nextable<RequestHandler<Request, Response>>, Schema>(zodOrRouteOrFunction as Schema, function_),\n );\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 // 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>({ onError: this.onError, onNoMatch: this.onNoMatch });\n\n r.router = this.router.clone();\n\n return r;\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 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 await Router.exec(result.fns, request, response);\n }\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\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/express.ts","../src/adapter/with-zod.ts","../src/router.ts","../src/edge.ts","../src/node.ts","../src/utils/send-json.ts"],"names":["expressWrapper","function_","request","response","next","resolve","reject","error","express_default","createHttpError","ZodError","withZod","schema","handler","transformedRequest","message","issue","with_zod_default","parse","Router","_Router","base","routes","fns","arguments_","index","method","route","keys","pattern","pathname","middleOnly","parameters","isHead","matched","matches","key","parameterKey","stripPathname","result","onNoMatch","onError","getPathname","EdgeRouter","_EdgeRouter","options","routeOrFunction","zodOrRouteOrFunction","findResult","r","context_","createEdgeRouter","_request","url","queryIndex","NodeRouter","_NodeRouter","createRouter","sendJson","statusCode","jsonBody","send_json_default"],"mappings":"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","sourcesContent":["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 =\n <Request extends IncomingMessage, Response extends ServerResponse>(\n // eslint-disable-next-line no-use-before-define\n function_: ExpressRequestHandler<Request, Response>,\n ): Nextable<RequestHandler<Request, Response>> =>\n async (request, response, next) =>\n // eslint-disable-next-line compat/compat\n await new Promise<void>((resolve, reject): void => {\n function_(request, response, (error) => (error ? reject(error) : resolve()));\n // eslint-disable-next-line promise/no-callback-in-promise\n }).then<Nextable<RequestHandler<Request, Response>>>(next);\n\nexport type ExpressRequestHandler<Request, Response> = (request: Request, response: Response, next: NextFunction) => void;\n\nexport default expressWrapper;\n","import createHttpError from \"http-errors\";\nimport type { AnyZodObject, ZodObject } from \"zod\";\nimport { ZodError } from \"zod\";\n\nimport type { NextHandler, Nextable } from \"../types\";\n\nconst withZod =\n <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>) =>\n 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 as Error;\n\n if (error instanceof ZodError && typeof error.format === \"function\") {\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 { FindResult, FunctionLike, HttpMethod, Nextable, RouteMatch } from \"./types\";\n\nexport type Route<H> = {\n // eslint-disable-next-line no-use-before-define\n fns: (H | Router<H extends FunctionLike ? H : never>)[];\n isMiddleware: boolean;\n method: HttpMethod | \"\";\n} & (\n | {\n keys: string[] | false;\n pattern: RegExp;\n }\n | { matchAll: true }\n);\n\nexport class Router<H extends FunctionLike> {\n public constructor(\n public base = \"/\",\n public routes: Route<Nextable<H>>[] = [],\n ) {}\n\n public static async exec<FL extends FunctionLike>(fns: (Nextable<FL> | undefined)[], ...arguments_: Parameters<FL>): Promise<any> {\n let index = 0;\n\n const next = () => {\n // eslint-disable-next-line no-plusplus,@typescript-eslint/naming-convention,no-underscore-dangle\n const function_ = fns[++index];\n\n if (function_ === undefined) {\n return Promise.resolve();\n }\n\n return function_(...arguments_, next);\n };\n\n return (fns[index] as FunctionLike)(...arguments_, next);\n }\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 fns,\n isMiddleware: false,\n matchAll: true,\n method,\n });\n } else {\n const { keys, pattern } = parse(route);\n\n this.routes.push({\n fns,\n isMiddleware: false,\n keys,\n method,\n pattern,\n });\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 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\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\n if (!route.isMiddleware) {\n middleOnly = false;\n }\n }\n });\n\n return { fns, middleOnly, params: parameters };\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\") {\n return function_.clone(base);\n }\n\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 fns,\n isMiddleware: true,\n keys,\n method: \"\",\n pattern,\n });\n\n return this;\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 RouteShortcutMethod,\n RoutesExtendedRequestHandler,\n ValueOrPromise,\n} from \"./types\";\n\nconst onNoMatch = async (request: Request) =>\n 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\n return new Response(\"Internal Server Error\", { status: 500 });\n};\n\nexport const getPathname = (request: Request & { nextUrl?: URL }): string =>\n // eslint-disable-next-line compat/compat\n (request.nextUrl ?? new URL(request.url)).pathname;\n\n// eslint-disable-next-line @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 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 private readonly onNoMatch: RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>;\n\n private router = new Router<RequestHandler<R, Context>>();\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"\");\n\n public connect: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"CONNECT\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"DELETE\");\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 options: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"OPTIONS\");\n\n public patch: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"PATCH\");\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 trace: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"TRACE\");\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 =\n 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\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 // 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>({ onError: this.onError, onNoMatch: this.onNoMatch });\n\n r.router = this.router.clone();\n\n return r;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\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 await this.onError(error, request, context_, routes);\n }\n };\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 await Router.exec(result.fns, request, context_);\n }\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\nexport const createEdgeRouter = <R extends Request, Context>(\n options: HandlerOptions<RoutesExtendedRequestHandler<R, Context, Response, Route<Nextable<FunctionLike>>[]>> = {},\n): EdgeRouter<R, Context> => new EdgeRouter<R, Context, Response>(options);\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 RouteShortcutMethod,\n RoutesExtendedRequestHandler,\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\n // eslint-disable-next-line no-console\n console.error(error);\n\n response.end(\"Internal Server Error\");\n};\n\nexport const 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<never>,\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 private readonly onNoMatch: RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>;\n\n private router = new Router<RequestHandler<Request, Response>>();\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"\");\n\n public connect: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"CONNECT\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"DELETE\");\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 options: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"OPTIONS\");\n\n public patch: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"PATCH\");\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 trace: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"TRACE\");\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 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\n fns = fns.map((function_) =>\n withZod<Request, Response, Nextable<RequestHandler<Request, Response>>, Schema>(zodOrRouteOrFunction as Schema, function_),\n );\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 // 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>({ onError: this.onError, onNoMatch: this.onNoMatch });\n\n r.router = this.router.clone();\n\n return r;\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 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 await Router.exec(result.fns, request, response);\n }\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\n this.router.use(base, ...fns.map((function_) => (function_ instanceof NodeRouter ? function_.router : function_)));\n\n return this;\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 g from 'http-errors';
1
+ import E from 'http-errors';
2
2
  import { ZodError } from 'zod';
3
3
  import { parse } from 'regexparam';
4
4
 
5
- var S=o=>async(e,t,s)=>await new Promise((n,r)=>{o(e,t,R=>R?r(R):n());}).then(s),N=S;var k=(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")),g(422,a)}return e(r,s,n)},l=k;var i=class o{constructor(e="/",t=[]){this.base=e;this.routes=t;}static async exec(e,...t){let s=0,n=()=>e[++s](...t,n);return e[s](...t,n)}add(e,t,...s){if(typeof t=="function"&&(s.unshift(t),t=""),t==="")this.routes.push({fns:s,isMiddleware:!1,matchAll:!0,method:e});else {let{keys:n,pattern:r}=parse(t);this.routes.push({fns:s,isMiddleware:!1,keys:n,method:e,pattern:r});}return this}clone(e){return new o(e,[...this.routes])}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 u=a.pattern.exec(t);if(u===null)return;u.groups!==void 0&&Object.keys(u.groups).forEach(p=>{r[p]=u.groups[p];}),d=!0;}else if(a.keys.length>0){let u=a.pattern.exec(t);if(u===null)return;for(let p=0;p<a.keys.length;){let c=a.keys[p];r[c]=u[++p];}d=!0;}else a.pattern.test(t)&&(d=!0);d&&(n.push(...a.fns.flatMap(u=>{if(u instanceof o){let{base:p}=u,c=t.slice(p.length);c.startsWith("/")||(c=`/${c}`);let H=u.find(e,c);return H.middleOnly||(s=!1),Object.assign(r,H.params),H.fns}return u})),a.isMiddleware||(s=!1));}),{fns:n,middleOnly:s,params:r}}use(e,...t){(typeof e=="function"||e instanceof o)&&(t.unshift(e),e="/"),t=t.map(r=>{if(r instanceof o){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({fns:t,isMiddleware:!0,keys:s,method:"",pattern:n}),this}};var C=async o=>new Response(o.method==="HEAD"?null:`Route ${o.method} ${o.url} not found`,{status:404}),w=async o=>(console.error(o),new Response("Internal Server Error",{status:500})),b=o=>(o.nextUrl??new URL(o.url)).pathname,m=class o{constructor(e={}){this.router=new i;this.all=this.add.bind(this,"");this.delete=this.add.bind(this,"DELETE");this.get=this.add.bind(this,"GET");this.head=this.add.bind(this,"HEAD");this.patch=this.add.bind(this,"PATCH");this.post=this.add.bind(this,"POST");this.put=this.add.bind(this,"PUT");this.onNoMatch=e.onNoMatch??C,this.onError=e.onError??w;}add(e,t,s,...n){return typeof t=="string"&&typeof s=="function"?n=[s]:typeof s=="object"?typeof t=="function"?n=[l(s,t)]:n=n.map(r=>l(s,r)):typeof s=="function"&&(n=[s]),this.router.add(e,t,...n),this}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new o({onError:this.onError,onNoMatch:this.onNoMatch});return e.router=this.router.clone(),e}handler(){let{routes:e}=this.router;return async(t,s)=>{let n=this.router.find(t.method,b(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 await this.onError(r,t,s,e)}}}async run(e,t){let s=this.router.find(e.method,b(e));if(s.fns.length!==0)return this.prepareRequest(e,s),await i.exec(s.fns,e,t)}use(e,...t){return (typeof e=="function"||e instanceof o)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof o?s.router:s)),this}},v=(o={})=>new m(o);var L=async(o,e)=>{e.statusCode=404,e.end(o.method==="HEAD"?void 0:`Route ${o.method} ${o.url} not found`);},j=async(o,e,t)=>{t.statusCode=500,console.error(o),t.end("Internal Server Error");},q=o=>{let e=o.indexOf("?");return e===-1?o:o.slice(0,Math.max(0,e))},f=class o{constructor(e={}){this.router=new i;this.all=this.add.bind(this,"");this.delete=this.add.bind(this,"DELETE");this.get=this.add.bind(this,"GET");this.head=this.add.bind(this,"HEAD");this.patch=this.add.bind(this,"PATCH");this.post=this.add.bind(this,"POST");this.put=this.add.bind(this,"PUT");this.onNoMatch=e.onNoMatch??L,this.onError=e.onError??j;}add(e,t,s,...n){return typeof t=="string"&&typeof s=="function"?n=[s]:typeof s=="object"?typeof t=="function"?n=[l(s,t)]:n=n.map(r=>l(s,r)):typeof s=="function"&&(n=[s]),this.router.add(e,t,...n),this}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new o({onError:this.onError,onNoMatch:this.onNoMatch});return e.router=this.router.clone(),e}handler(){let{routes:e}=this.router;return async(t,s)=>{let n=this.router.find(t.method,q(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);}}}async run(e,t){let s=this.router.find(e.method,q(e.url));if(s.fns.length!==0)return this.prepareRequest(e,s),await i.exec(s.fns,e,t)}use(e,...t){return (typeof e=="function"||e instanceof o)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof o?s.router:s)),this}},M=(o={})=>new f(o);var P=(o,e,t)=>{o.setHeader("content-type","application/json; charset=utf-8"),o.statusCode=e,o.end(JSON.stringify(t,null,2));},Z=P;
5
+ var M=o=>async(e,t,s)=>await new Promise((n,r)=>{o(e,t,d=>d?r(d):n());}).then(s),N=M;var C=(o,e)=>async(t,s,n)=>{let r=t;try{r=await o.parseAsync(t);}catch(d){let{message:a}=d;throw d instanceof ZodError&&typeof d.format=="function"&&(a=d.issues.map(R=>`${R.path.join("/")} - ${R.message}`).join("/n")),E(422,a)}return e(r,s,n)},h=C;var i=class o{constructor(e="/",t=[]){this.base=e;this.routes=t;}static async exec(e,...t){let s=0,n=()=>{let r=e[++s];return r===void 0?Promise.resolve():r(...t,n)};return e[s](...t,n)}add(e,t,...s){if(typeof t=="function"&&(s.unshift(t),t=""),t==="")this.routes.push({fns:s,isMiddleware:!1,matchAll:!0,method:e});else {let{keys:n,pattern:r}=parse(t);this.routes.push({fns:s,isMiddleware:!1,keys:n,method:e,pattern:r});}return this}clone(e){return new o(e,[...this.routes])}find(e,t){let s=!0,n=[],r={},d=e==="HEAD";return Object.values(this.routes).forEach(a=>{if(a.method!==e&&a.method!==""&&!(d&&a.method==="GET"))return;let R=!1;if("matchAll"in a)R=!0;else if(a.keys===!1){let u=a.pattern.exec(t);if(u===null)return;u.groups!==void 0&&Object.keys(u.groups).forEach(p=>{r[p]=u.groups[p];}),R=!0;}else if(a.keys.length>0){let u=a.pattern.exec(t);if(u===null)return;for(let p=0;p<a.keys.length;){let c=a.keys[p];r[c]=u[++p];}R=!0;}else a.pattern.test(t)&&(R=!0);R&&(n.push(...a.fns.flatMap(u=>{if(u instanceof o){let{base:p}=u,c=t.slice(p.length);c.startsWith("/")||(c=`/${c}`);let b=u.find(e,c);return b.middleOnly||(s=!1),Object.assign(r,b.params),b.fns}return u})),a.isMiddleware||(s=!1));}),{fns:n,middleOnly:s,params:r}}use(e,...t){(typeof e=="function"||e instanceof o)&&(t.unshift(e),e="/"),t=t.map(r=>{if(r instanceof o){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({fns:t,isMiddleware:!0,keys:s,method:"",pattern:n}),this}};var k=async o=>new Response(o.method==="HEAD"?null:`Route ${o.method} ${o.url} not found`,{status:404}),w=async o=>(console.error(o),new Response("Internal Server Error",{status:500})),q=o=>(o.nextUrl??new URL(o.url)).pathname,m=class o{constructor(e={}){this.router=new i;this.all=this.add.bind(this,"");this.connect=this.add.bind(this,"CONNECT");this.delete=this.add.bind(this,"DELETE");this.get=this.add.bind(this,"GET");this.head=this.add.bind(this,"HEAD");this.options=this.add.bind(this,"OPTIONS");this.patch=this.add.bind(this,"PATCH");this.post=this.add.bind(this,"POST");this.put=this.add.bind(this,"PUT");this.trace=this.add.bind(this,"TRACE");this.onNoMatch=e.onNoMatch??k,this.onError=e.onError??w;}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}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new o({onError:this.onError,onNoMatch:this.onNoMatch});return e.router=this.router.clone(),e}handler(){let{routes:e}=this.router;return async(t,s)=>{let n=this.router.find(t.method,q(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 await this.onError(r,t,s,e)}}}async run(e,t){let s=this.router.find(e.method,q(e));if(s.fns.length!==0)return this.prepareRequest(e,s),await i.exec(s.fns,e,t)}use(e,...t){return (typeof e=="function"||e instanceof o)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof o?s.router:s)),this}},v=(o={})=>new m(o);var L=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");},y=o=>{let e=o.indexOf("?");return e===-1?o:o.slice(0,Math.max(0,e))},f=class o{constructor(e={}){this.router=new i;this.all=this.add.bind(this,"");this.connect=this.add.bind(this,"CONNECT");this.delete=this.add.bind(this,"DELETE");this.get=this.add.bind(this,"GET");this.head=this.add.bind(this,"HEAD");this.options=this.add.bind(this,"OPTIONS");this.patch=this.add.bind(this,"PATCH");this.post=this.add.bind(this,"POST");this.put=this.add.bind(this,"PUT");this.trace=this.add.bind(this,"TRACE");this.onNoMatch=e.onNoMatch??L,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=[h(s,t)]:n=n.map(r=>h(s,r)):typeof s=="function"&&(n=[s]),this.router.add(e,t,...n),this}prepareRequest(e,t){e.params={...t.params,...e.params};}clone(){let e=new o({onError:this.onError,onNoMatch:this.onNoMatch});return e.router=this.router.clone(),e}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):i.exec(n.fns,t,s));}catch(r){await this.onError(r,t,s,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),await i.exec(s.fns,e,t)}use(e,...t){return (typeof e=="function"||e instanceof o)&&(t.unshift(e),e="/"),this.router.use(e,...t.map(s=>s instanceof o?s.router:s)),this}},S=(o={})=>new f(o);var j=(o,e,t)=>{o.setHeader("content-type","application/json; charset=utf-8"),o.statusCode=e,o.end(JSON.stringify(t,null,2));},A=j;
6
6
 
7
- export { m as EdgeRouter, f as NodeRouter, i as Router, v as createEdgeRouter, M as createNodeRouter, M as createRouter, N as expressWrapper, Z as sendJson, l as withZod };
7
+ export { m as EdgeRouter, f as NodeRouter, i as Router, v as createEdgeRouter, S as createNodeRouter, S as createRouter, N as expressWrapper, A 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/express.ts","../src/adapter/with-zod.ts","../src/router.ts","../src/edge.ts","../src/node.ts","../src/utils/send-json.ts"],"names":["expressWrapper","function_","request","response","next","resolve","reject","error","express_default","createHttpError","ZodError","withZod","schema","handler","transformedRequest","message","issue","with_zod_default","parse","Router","_Router","base","routes","fns","arguments_","index","method","route","keys","pattern","pathname","middleOnly","parameters","isHead","matched","matches","key","parameterKey","stripPathname","result","onNoMatch","onError","getPathname","EdgeRouter","_EdgeRouter","options","routeOrFunction","zodOrRouteOrFunction","findResult","r","context_","createEdgeRouter","_request","url","queryIndex","NodeRouter","_NodeRouter","createRouter","sendJson","statusCode","jsonBody","send_json_default"],"mappings":"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","sourcesContent":["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 =\n <Request extends IncomingMessage, Response extends ServerResponse>(\n // eslint-disable-next-line no-use-before-define\n function_: ExpressRequestHandler<Request, Response>,\n ): Nextable<RequestHandler<Request, Response>> =>\n async (request, response, next) =>\n // eslint-disable-next-line compat/compat\n await new Promise<void>((resolve, reject): void => {\n function_(request, response, (error) => (error ? reject(error) : resolve()));\n // eslint-disable-next-line promise/no-callback-in-promise\n }).then<Nextable<RequestHandler<Request, Response>>>(next);\n\nexport type ExpressRequestHandler<Request, Response> = (request: Request, response: Response, next: NextFunction) => void;\n\nexport default expressWrapper;\n","import createHttpError from \"http-errors\";\nimport type { AnyZodObject, ZodObject } from \"zod\";\nimport { ZodError } from \"zod\";\n\nimport type { NextHandler, Nextable } from \"../types\";\n\nconst withZod =\n <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>) =>\n 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 as Error;\n\n if (error instanceof ZodError && typeof error.format === \"function\") {\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 { FindResult, FunctionLike, HttpMethod, Nextable, RouteMatch } from \"./types\";\n\nexport type Route<H> = {\n // eslint-disable-next-line no-use-before-define\n fns: (H | Router<H extends FunctionLike ? H : never>)[];\n isMiddleware: boolean;\n method: HttpMethod | \"\";\n} & (\n | {\n keys: string[] | false;\n pattern: RegExp;\n }\n | { matchAll: true }\n);\n\nexport class Router<H extends FunctionLike> {\n public constructor(\n public base = \"/\",\n public routes: Route<Nextable<H>>[] = [],\n ) {}\n\n public static async exec<FL extends FunctionLike>(fns: Nextable<FL>[], ...arguments_: Parameters<FL>): Promise<any> {\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 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 fns,\n isMiddleware: false,\n matchAll: true,\n method,\n });\n } else {\n const { keys, pattern } = parse(route);\n\n this.routes.push({\n fns,\n isMiddleware: false,\n keys,\n method,\n pattern,\n });\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 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\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) {\n middleOnly = false;\n }\n }\n });\n\n return { fns, middleOnly, params: parameters };\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\") {\n return function_.clone(base);\n }\n\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 fns,\n isMiddleware: true,\n keys,\n method: \"\",\n pattern,\n });\n\n return this;\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 RouteShortcutMethod,\n RoutesExtendedRequestHandler,\n ValueOrPromise,\n} from \"./types\";\n\nconst onNoMatch = async (request: Request) =>\n 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\n return new Response(\"Internal Server Error\", { status: 500 });\n};\n\nexport const getPathname = (request: Request & { nextUrl?: URL }): string =>\n // eslint-disable-next-line compat/compat\n (request.nextUrl ?? new URL(request.url)).pathname;\n\n// eslint-disable-next-line @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 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 private readonly onNoMatch: RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>;\n\n private router = new Router<RequestHandler<R, Context>>();\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"DELETE\");\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 patch: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"PATCH\");\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 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 =\n 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\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 // 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>({ onError: this.onError, onNoMatch: this.onNoMatch });\n\n r.router = this.router.clone();\n\n return r;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\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 await this.onError(error, request, context_, routes);\n }\n };\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 await Router.exec(result.fns, request, context_);\n }\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\nexport const createEdgeRouter = <R extends Request, Context>(\n options: HandlerOptions<RoutesExtendedRequestHandler<R, Context, Response, Route<Nextable<FunctionLike>>[]>> = {},\n): EdgeRouter<R, Context> => new EdgeRouter<R, Context, Response>(options);\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 RouteShortcutMethod,\n RoutesExtendedRequestHandler,\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\n // eslint-disable-next-line no-console\n console.error(error);\n\n response.end(\"Internal Server Error\");\n};\n\nexport const 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<never>,\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 private readonly onNoMatch: RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>;\n\n private router = new Router<RequestHandler<Request, Response>>();\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"DELETE\");\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 patch: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"PATCH\");\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 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 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\n fns = fns.map((function_) =>\n withZod<Request, Response, Nextable<RequestHandler<Request, Response>>, Schema>(zodOrRouteOrFunction as Schema, function_),\n );\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 // 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>({ onError: this.onError, onNoMatch: this.onNoMatch });\n\n r.router = this.router.clone();\n\n return r;\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 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 await Router.exec(result.fns, request, response);\n }\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\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/express.ts","../src/adapter/with-zod.ts","../src/router.ts","../src/edge.ts","../src/node.ts","../src/utils/send-json.ts"],"names":["expressWrapper","function_","request","response","next","resolve","reject","error","express_default","createHttpError","ZodError","withZod","schema","handler","transformedRequest","message","issue","with_zod_default","parse","Router","_Router","base","routes","fns","arguments_","index","method","route","keys","pattern","pathname","middleOnly","parameters","isHead","matched","matches","key","parameterKey","stripPathname","result","onNoMatch","onError","getPathname","EdgeRouter","_EdgeRouter","options","routeOrFunction","zodOrRouteOrFunction","findResult","r","context_","createEdgeRouter","_request","url","queryIndex","NodeRouter","_NodeRouter","createRouter","sendJson","statusCode","jsonBody","send_json_default"],"mappings":"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","sourcesContent":["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 =\n <Request extends IncomingMessage, Response extends ServerResponse>(\n // eslint-disable-next-line no-use-before-define\n function_: ExpressRequestHandler<Request, Response>,\n ): Nextable<RequestHandler<Request, Response>> =>\n async (request, response, next) =>\n // eslint-disable-next-line compat/compat\n await new Promise<void>((resolve, reject): void => {\n function_(request, response, (error) => (error ? reject(error) : resolve()));\n // eslint-disable-next-line promise/no-callback-in-promise\n }).then<Nextable<RequestHandler<Request, Response>>>(next);\n\nexport type ExpressRequestHandler<Request, Response> = (request: Request, response: Response, next: NextFunction) => void;\n\nexport default expressWrapper;\n","import createHttpError from \"http-errors\";\nimport type { AnyZodObject, ZodObject } from \"zod\";\nimport { ZodError } from \"zod\";\n\nimport type { NextHandler, Nextable } from \"../types\";\n\nconst withZod =\n <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>) =>\n 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 as Error;\n\n if (error instanceof ZodError && typeof error.format === \"function\") {\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 { FindResult, FunctionLike, HttpMethod, Nextable, RouteMatch } from \"./types\";\n\nexport type Route<H> = {\n // eslint-disable-next-line no-use-before-define\n fns: (H | Router<H extends FunctionLike ? H : never>)[];\n isMiddleware: boolean;\n method: HttpMethod | \"\";\n} & (\n | {\n keys: string[] | false;\n pattern: RegExp;\n }\n | { matchAll: true }\n);\n\nexport class Router<H extends FunctionLike> {\n public constructor(\n public base = \"/\",\n public routes: Route<Nextable<H>>[] = [],\n ) {}\n\n public static async exec<FL extends FunctionLike>(fns: (Nextable<FL> | undefined)[], ...arguments_: Parameters<FL>): Promise<any> {\n let index = 0;\n\n const next = () => {\n // eslint-disable-next-line no-plusplus,@typescript-eslint/naming-convention,no-underscore-dangle\n const function_ = fns[++index];\n\n if (function_ === undefined) {\n return Promise.resolve();\n }\n\n return function_(...arguments_, next);\n };\n\n return (fns[index] as FunctionLike)(...arguments_, next);\n }\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 fns,\n isMiddleware: false,\n matchAll: true,\n method,\n });\n } else {\n const { keys, pattern } = parse(route);\n\n this.routes.push({\n fns,\n isMiddleware: false,\n keys,\n method,\n pattern,\n });\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 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\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\n if (!route.isMiddleware) {\n middleOnly = false;\n }\n }\n });\n\n return { fns, middleOnly, params: parameters };\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\") {\n return function_.clone(base);\n }\n\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 fns,\n isMiddleware: true,\n keys,\n method: \"\",\n pattern,\n });\n\n return this;\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 RouteShortcutMethod,\n RoutesExtendedRequestHandler,\n ValueOrPromise,\n} from \"./types\";\n\nconst onNoMatch = async (request: Request) =>\n 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\n return new Response(\"Internal Server Error\", { status: 500 });\n};\n\nexport const getPathname = (request: Request & { nextUrl?: URL }): string =>\n // eslint-disable-next-line compat/compat\n (request.nextUrl ?? new URL(request.url)).pathname;\n\n// eslint-disable-next-line @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 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 private readonly onNoMatch: RoutesExtendedRequestHandler<R, Context, RResponse, Route<Nextable<FunctionLike>>[]>;\n\n private router = new Router<RequestHandler<R, Context>>();\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"\");\n\n public connect: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"CONNECT\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"DELETE\");\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 options: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"OPTIONS\");\n\n public patch: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"PATCH\");\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 trace: RouteShortcutMethod<this, Schema, RequestHandler<R, Context>> = this.add.bind(this, \"TRACE\");\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 =\n 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\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 // 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>({ onError: this.onError, onNoMatch: this.onNoMatch });\n\n r.router = this.router.clone();\n\n return r;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\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 await this.onError(error, request, context_, routes);\n }\n };\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 await Router.exec(result.fns, request, context_);\n }\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\nexport const createEdgeRouter = <R extends Request, Context>(\n options: HandlerOptions<RoutesExtendedRequestHandler<R, Context, Response, Route<Nextable<FunctionLike>>[]>> = {},\n): EdgeRouter<R, Context> => new EdgeRouter<R, Context, Response>(options);\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 RouteShortcutMethod,\n RoutesExtendedRequestHandler,\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\n // eslint-disable-next-line no-console\n console.error(error);\n\n response.end(\"Internal Server Error\");\n};\n\nexport const 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<never>,\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 private readonly onNoMatch: RoutesExtendedRequestHandler<Request, Response, Response, Route<Nextable<FunctionLike>>[]>;\n\n private router = new Router<RequestHandler<Request, Response>>();\n\n public all: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"\");\n\n public connect: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"CONNECT\");\n\n public delete: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"DELETE\");\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 options: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"OPTIONS\");\n\n public patch: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"PATCH\");\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 trace: RouteShortcutMethod<this, Schema, RequestHandler<Request, Response>> = this.add.bind(this, \"TRACE\");\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 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\n fns = fns.map((function_) =>\n withZod<Request, Response, Nextable<RequestHandler<Request, Response>>, Schema>(zodOrRouteOrFunction as Schema, function_),\n );\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 // 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>({ onError: this.onError, onNoMatch: this.onNoMatch });\n\n r.router = this.router.clone();\n\n return r;\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 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 await Router.exec(result.fns, request, response);\n }\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\n this.router.use(base, ...fns.map((function_) => (function_ instanceof NodeRouter ? function_.router : function_)));\n\n return this;\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": "2.0.1",
3
+ "version": "2.1.0",
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",
@@ -82,12 +82,13 @@
82
82
  "regexparam": "^2.0.1"
83
83
  },
84
84
  "devDependencies": {
85
- "@anolilab/eslint-config": "^11.3.3",
86
- "@anolilab/prettier-config": "^5.0.3",
87
- "@anolilab/semantic-release-preset": "^6.0.4",
85
+ "@anolilab/eslint-config": "^11.3.5",
86
+ "@anolilab/prettier-config": "^5.0.4",
87
+ "@anolilab/semantic-release-preset": "^6.0.5",
88
88
  "@rushstack/eslint-plugin-security": "^0.6.0",
89
89
  "@types/http-errors": "^2.0.1",
90
- "@types/node": "18.17.1",
90
+ "@types/node": "18.17.12",
91
+ "@visulima/nextra-theme-docs": "4.0.1",
91
92
  "@vitest/coverage-v8": "^0.34.3",
92
93
  "c8": "^8.0.1",
93
94
  "cross-env": "^7.0.3",
@@ -100,7 +101,7 @@
100
101
  "express": "^4.18.2",
101
102
  "fastify": "^4.22.0",
102
103
  "isomorphic-fetch": "^3.0.0",
103
- "prettier": "^3.0.2",
104
+ "prettier": "^3.0.3",
104
105
  "rimraf": "^5.0.1",
105
106
  "semantic-release": "^21.1.1",
106
107
  "sort-package-json": "^2.5.1",