@visulima/connect 1.0.1 → 1.1.1
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 +14 -0
- package/README.md +83 -81
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/index.mjs +1 -0
- package/package.json +1 -1
- package/src/index.ts +6 -2
- package/src/types.d.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## @visulima/connect [1.1.1](https://github.com/visulima/visulima/compare/@visulima/connect@1.1.0...@visulima/connect@1.1.1) (2022-11-09)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **connect:** added missing type to the types.d ([33f7fa8](https://github.com/visulima/visulima/commit/33f7fa8282d23e00cd3bb4aeb7691f4b615b9afc))
|
|
7
|
+
|
|
8
|
+
## @visulima/connect [1.1.0](https://github.com/visulima/visulima/compare/@visulima/connect@1.0.1...@visulima/connect@1.1.0) (2022-11-07)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **connect:** renamed createRouter to createNodeRouter ([92f6d3f](https://github.com/visulima/visulima/commit/92f6d3f4d3430c281ae7106f7d09bb5b744df341))
|
|
14
|
+
|
|
1
15
|
## @visulima/connect [1.0.1](https://github.com/visulima/visulima/compare/@visulima/connect@1.0.0...@visulima/connect@1.0.1) (2022-10-27)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -66,12 +66,12 @@ Below are some use cases.
|
|
|
66
66
|
```typescript
|
|
67
67
|
// pages/api/hello.js
|
|
68
68
|
import type { NextApiRequest, NextApiResponse } from "next";
|
|
69
|
-
import {
|
|
69
|
+
import { createNodeRouter, expressWrapper } from "@visulima/connect";
|
|
70
70
|
import cors from "cors";
|
|
71
71
|
|
|
72
72
|
// Default Req and Res are IncomingMessage and ServerResponse
|
|
73
73
|
// You may want to pass in NextApiRequest and NextApiResponse
|
|
74
|
-
const router =
|
|
74
|
+
const router = createNodeRouter<NextApiRequest, NextApiResponse>({
|
|
75
75
|
onError: (err, req, res) => {
|
|
76
76
|
console.error(err.stack);
|
|
77
77
|
res.status(500).end("Something broke!");
|
|
@@ -100,7 +100,7 @@ router
|
|
|
100
100
|
.put(
|
|
101
101
|
async (req, res, next) => {
|
|
102
102
|
// You may want to pass in NextApiRequest & { isLoggedIn: true }
|
|
103
|
-
// in
|
|
103
|
+
// in createNodeRouter generics to define this extra property
|
|
104
104
|
if (!req.isLoggedIn) throw new Error("thrown stuff will be caught");
|
|
105
105
|
// go to the next in chain
|
|
106
106
|
return next();
|
|
@@ -111,16 +111,14 @@ router
|
|
|
111
111
|
}
|
|
112
112
|
);
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
// onError and onNoMatch
|
|
116
|
-
export default router.handler();
|
|
114
|
+
export default router.nodeHandler();
|
|
117
115
|
```
|
|
118
116
|
|
|
119
117
|
### Next.js getServerSideProps
|
|
120
118
|
|
|
121
119
|
```jsx
|
|
122
120
|
// page/users/[id].js
|
|
123
|
-
import {
|
|
121
|
+
import { createNodeRouter } from "@visulima/connect";
|
|
124
122
|
|
|
125
123
|
export default function Page({ user, updated }) {
|
|
126
124
|
return (
|
|
@@ -132,7 +130,7 @@ export default function Page({ user, updated }) {
|
|
|
132
130
|
);
|
|
133
131
|
}
|
|
134
132
|
|
|
135
|
-
const router =
|
|
133
|
+
const router = createNodeRouter()
|
|
136
134
|
.use(async (req, res, next) => {
|
|
137
135
|
// this serve as the error handling middleware
|
|
138
136
|
try {
|
|
@@ -222,7 +220,7 @@ router
|
|
|
222
220
|
});
|
|
223
221
|
});
|
|
224
222
|
|
|
225
|
-
export default router.
|
|
223
|
+
export default router.nodeHandler();
|
|
226
224
|
```
|
|
227
225
|
|
|
228
226
|
### Next.js Middleware
|
|
@@ -267,9 +265,9 @@ export function middleware(request: NextRequest) {
|
|
|
267
265
|
|
|
268
266
|
## API
|
|
269
267
|
|
|
270
|
-
The following APIs are rewritten in terms of `NodeRouter` (`
|
|
268
|
+
The following APIs are rewritten in terms of `NodeRouter` (`createNodeRouter`), but they apply to `EdgeRouter` (`createEdgeRouter`) as well.
|
|
271
269
|
|
|
272
|
-
### router =
|
|
270
|
+
### router = createNodeRouter()
|
|
273
271
|
|
|
274
272
|
Create an instance Node.js router.
|
|
275
273
|
|
|
@@ -285,31 +283,31 @@ Create an instance Node.js router.
|
|
|
285
283
|
```javascript
|
|
286
284
|
// Mount a middleware function
|
|
287
285
|
router1.use(async (req, res, next) => {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
286
|
+
req.hello = "world";
|
|
287
|
+
await next(); // call to proceed to the next in chain
|
|
288
|
+
console.log("request is done"); // call after all downstream nodeHandler has run
|
|
291
289
|
});
|
|
292
290
|
|
|
293
291
|
// Or include a base
|
|
294
292
|
router2.use("/foo", fn); // Only run in /foo/**
|
|
295
293
|
|
|
296
294
|
// mount an instance of router
|
|
297
|
-
const sub1 =
|
|
298
|
-
const sub2 =
|
|
299
|
-
const sub3 =
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
295
|
+
const sub1 = createNodeRouter().use(fn1, fn2);
|
|
296
|
+
const sub2 = createNodeRouter().use("/dashboard", auth);
|
|
297
|
+
const sub3 = createNodeRouter()
|
|
298
|
+
.use("/waldo", subby)
|
|
299
|
+
.get(getty)
|
|
300
|
+
.post("/baz", posty)
|
|
301
|
+
.put("/", putty);
|
|
304
302
|
router3
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
303
|
+
// - fn1 and fn2 always run
|
|
304
|
+
// - auth runs only on /dashboard
|
|
305
|
+
.use(sub1, sub2)
|
|
306
|
+
// `subby` runs on ANY /foo/waldo?/*
|
|
307
|
+
// `getty` runs on GET /foo/*
|
|
308
|
+
// `posty` runs on POST /foo/baz
|
|
309
|
+
// `putty` runs on PUT /foo
|
|
310
|
+
.use("/foo", sub3);
|
|
313
311
|
```
|
|
314
312
|
|
|
315
313
|
### router.METHOD(pattern, ...fns)
|
|
@@ -340,47 +338,47 @@ router.get((req, res, next) => {
|
|
|
340
338
|
```
|
|
341
339
|
|
|
342
340
|
> **Note**
|
|
343
|
-
> You should understand Next.js [file-system based routing](https://nextjs.org/docs/routing/introduction). For example, having a `router.put("/api/foo",
|
|
341
|
+
> You should understand Next.js [file-system based routing](https://nextjs.org/docs/routing/introduction). For example, having a `router.put("/api/foo", nodeHandler)` inside `page/api/index.js` _does not_ serve that nodeHandler at `/api/foo`.
|
|
344
342
|
|
|
345
343
|
### router.all(pattern, ...fns)
|
|
346
344
|
|
|
347
345
|
Same as [.METHOD](#methodpattern-fns) but accepts _any_ methods.
|
|
348
346
|
|
|
349
|
-
### router.
|
|
347
|
+
### router.nodeHandler(options)
|
|
350
348
|
|
|
351
|
-
Create a
|
|
349
|
+
Create a nodeHandler to handle incoming requests.
|
|
352
350
|
|
|
353
351
|
**options.onError**
|
|
354
352
|
|
|
355
|
-
Accepts a function as a catch-all error
|
|
353
|
+
Accepts a function as a catch-all error nodeHandler; executed whenever a nodeHandler throws an error.
|
|
356
354
|
By default, it responds with a generic `500 Internal Server Error` while logging the error to `console`.
|
|
357
355
|
|
|
358
356
|
```javascript
|
|
359
357
|
function onError(err, req, res) {
|
|
360
|
-
|
|
361
|
-
|
|
358
|
+
logger.log(err);
|
|
359
|
+
// OR: console.error(err);
|
|
362
360
|
|
|
363
|
-
|
|
361
|
+
res.status(500).end("Internal server error");
|
|
364
362
|
}
|
|
365
363
|
|
|
366
|
-
const router =
|
|
364
|
+
const router = createNodeRouter({onError});
|
|
367
365
|
|
|
368
|
-
export default router.
|
|
366
|
+
export default router.nodeHandler();
|
|
369
367
|
```
|
|
370
368
|
|
|
371
369
|
**options.onNoMatch**
|
|
372
370
|
|
|
373
|
-
Accepts a function of `(req, res)` as a
|
|
371
|
+
Accepts a function of `(req, res)` as a nodeHandler when no route is matched.
|
|
374
372
|
By default, it responds with a `404` status and a `Route [Method] [Url] not found` body.
|
|
375
373
|
|
|
376
374
|
```javascript
|
|
377
375
|
function onNoMatch(req, res) {
|
|
378
|
-
|
|
376
|
+
res.status(404).end("page is not found... or is it!?");
|
|
379
377
|
}
|
|
380
378
|
|
|
381
|
-
const router =
|
|
379
|
+
const router = createNodeRouter({onNoMatch});
|
|
382
380
|
|
|
383
|
-
export default router.
|
|
381
|
+
export default router.nodeHandler();
|
|
384
382
|
```
|
|
385
383
|
|
|
386
384
|
### router.run(req, res)
|
|
@@ -462,10 +460,10 @@ router
|
|
|
462
460
|
});
|
|
463
461
|
```
|
|
464
462
|
|
|
465
|
-
Another issue is that the
|
|
463
|
+
Another issue is that the nodeHandler would resolve before all the code in each layer runs.
|
|
466
464
|
|
|
467
465
|
```javascript
|
|
468
|
-
const
|
|
466
|
+
const nodeHandler = router
|
|
469
467
|
.use(async (req, res, next) => {
|
|
470
468
|
next(); // this is not returned or await
|
|
471
469
|
})
|
|
@@ -475,9 +473,9 @@ const handler = router
|
|
|
475
473
|
res.send("ok");
|
|
476
474
|
console.log("request is completed");
|
|
477
475
|
})
|
|
478
|
-
.
|
|
476
|
+
.nodeHandler();
|
|
479
477
|
|
|
480
|
-
await
|
|
478
|
+
await nodeHandler(req, res);
|
|
481
479
|
console.log("finally"); // this will run before the get layer gets to finish
|
|
482
480
|
|
|
483
481
|
// This will result in:
|
|
@@ -489,15 +487,17 @@ console.log("finally"); // this will run before the get layer gets to finish
|
|
|
489
487
|
|
|
490
488
|
```javascript
|
|
491
489
|
// api-libs/base.js
|
|
492
|
-
export default
|
|
490
|
+
export default createNodeRouter().use(a).use(b);
|
|
493
491
|
|
|
494
492
|
// api/foo.js
|
|
495
493
|
import router from "api-libs/base";
|
|
496
|
-
|
|
494
|
+
|
|
495
|
+
export default router.get(x).nodeHandler();
|
|
497
496
|
|
|
498
497
|
// api/bar.js
|
|
499
498
|
import router from "api-libs/base";
|
|
500
|
-
|
|
499
|
+
|
|
500
|
+
export default router.get(y).nodeHandler();
|
|
501
501
|
```
|
|
502
502
|
|
|
503
503
|
This is because, in each API Route, the same router instance is mutated, leading to undefined behaviors.
|
|
@@ -505,52 +505,54 @@ If you want to achieve something like that, you can use `router.clone` to return
|
|
|
505
505
|
|
|
506
506
|
```javascript
|
|
507
507
|
// api-libs/base.js
|
|
508
|
-
export default
|
|
508
|
+
export default createNodeRouter().use(a).use(b);
|
|
509
509
|
|
|
510
510
|
// api/foo.js
|
|
511
511
|
import router from "api-libs/base";
|
|
512
|
-
|
|
512
|
+
|
|
513
|
+
export default router.clone().get(x).nodeHandler();
|
|
513
514
|
|
|
514
515
|
// api/bar.js
|
|
515
516
|
import router from "api-libs/base";
|
|
516
|
-
|
|
517
|
+
|
|
518
|
+
export default router.clone().get(y).nodeHandler();
|
|
517
519
|
```
|
|
518
520
|
|
|
519
521
|
3. **DO NOT** use response function like `res.(s)end` or `res.redirect` inside `getServerSideProps`.
|
|
520
522
|
|
|
521
523
|
```javascript
|
|
522
524
|
// page/index.js
|
|
523
|
-
const
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
525
|
+
const nodeHandler = createNodeRouter()
|
|
526
|
+
.use((req, res) => {
|
|
527
|
+
// BAD: res.redirect is not a function (not defined in `getServerSideProps`)
|
|
528
|
+
// See https://github.com/hoangvvo/@visulima/connect/issues/194#issuecomment-1172961741 for a solution
|
|
529
|
+
res.redirect("foo");
|
|
530
|
+
})
|
|
531
|
+
.use((req, res) => {
|
|
532
|
+
// BAD: `getServerSideProps` gives undefined behavior if we try to send a response
|
|
533
|
+
res.end("bar");
|
|
534
|
+
});
|
|
533
535
|
|
|
534
|
-
export async function getServerSideProps({
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
536
|
+
export async function getServerSideProps({req, res}) {
|
|
537
|
+
await router.run(req, res);
|
|
538
|
+
return {
|
|
539
|
+
props: {},
|
|
540
|
+
};
|
|
539
541
|
}
|
|
540
542
|
```
|
|
541
543
|
|
|
542
|
-
|
|
544
|
+
4. **DO NOT** use `nodeHandler()` directly in `getServerSideProps`.
|
|
543
545
|
|
|
544
546
|
```javascript
|
|
545
547
|
// page/index.js
|
|
546
|
-
const router =
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
export async function getServerSideProps({
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
548
|
+
const router = createNodeRouter().use(foo).use(bar);
|
|
549
|
+
const nodeHandler = router.nodeHandler();
|
|
550
|
+
|
|
551
|
+
export async function getServerSideProps({req, res}) {
|
|
552
|
+
await nodeHandler(req, res); // BAD: You should call router.run(req, res);
|
|
553
|
+
return {
|
|
554
|
+
props: {},
|
|
555
|
+
};
|
|
554
556
|
}
|
|
555
557
|
```
|
|
556
558
|
|
|
@@ -561,24 +563,24 @@ export async function getServerSideProps({ req, res }) {
|
|
|
561
563
|
<details>
|
|
562
564
|
<summary>Match multiple routes</summary>
|
|
563
565
|
|
|
564
|
-
If you created the file `/api/<specific route>.js` folder, the
|
|
566
|
+
If you created the file `/api/<specific route>.js` folder, the nodeHandler will only run on that specific route.
|
|
565
567
|
|
|
566
568
|
If you need to create all handlers for all routes in one file (similar to `Express.js`). You can use [Optional catch-all API routes](https://nextjs.org/docs/api-routes/dynamic-api-routes#optional-catch-all-api-routes).
|
|
567
569
|
|
|
568
570
|
```javascript
|
|
569
571
|
// pages/api/[[...slug]].js
|
|
570
|
-
import {
|
|
572
|
+
import { createNodeRouter } from "@visulima/connect";
|
|
571
573
|
|
|
572
|
-
const router =
|
|
574
|
+
const router = createNodeRouter()
|
|
573
575
|
.use("/api/hello", someMiddleware())
|
|
574
576
|
.get("/api/user/:userId", (req, res) => {
|
|
575
577
|
res.send(`Hello ${req.params.userId}`);
|
|
576
578
|
});
|
|
577
579
|
|
|
578
|
-
export default router.
|
|
580
|
+
export default router.nodeHandler();
|
|
579
581
|
```
|
|
580
582
|
|
|
581
|
-
While this allows quick migration from Express.js, consider
|
|
583
|
+
While this allows quick migration from Express.js, consider separating routes into different files (`/api/user/[userId].js`, `/api/hello.js`) in the future.
|
|
582
584
|
|
|
583
585
|
</details>
|
|
584
586
|
|
package/dist/index.d.ts
CHANGED
|
@@ -138,4 +138,4 @@ declare const withZod: <Request_1 extends object, Response_1 extends unknown, Ha
|
|
|
138
138
|
|
|
139
139
|
declare const sendJson: (response: ServerResponse, statusCode: number, jsonBody: any) => void;
|
|
140
140
|
|
|
141
|
-
export { RequestHandler$1 as EdgeRequestHandler, EdgeRouter, ExpressRequestHandler, FindResult, FunctionLike, HandlerOptions, HttpMethod, NextHandler, Nextable,
|
|
141
|
+
export { RequestHandler$1 as EdgeRequestHandler, EdgeRouter, ExpressRequestHandler, FindResult, FunctionLike, HandlerOptions, HttpMethod, NextHandler, Nextable, RequestHandler as NodeRequestHandler, NodeRouter, Route, RouteShortcutMethod, Router, ValueOrPromise, createEdgeRouter, createRouter as createNodeRouter, createRouter, expressWrapper, sendJson, withZod };
|
package/dist/index.js
CHANGED
|
@@ -331,5 +331,6 @@ var send_json_default = sendJson;
|
|
|
331
331
|
|
|
332
332
|
|
|
333
333
|
|
|
334
|
-
|
|
334
|
+
|
|
335
|
+
exports.EdgeRouter = EdgeRouter; exports.NodeRouter = NodeRouter; exports.Router = Router; exports.createEdgeRouter = createEdgeRouter; exports.createNodeRouter = createRouter; exports.createRouter = createRouter; exports.expressWrapper = express_default; exports.sendJson = send_json_default; exports.withZod = with_zod_default;
|
|
335
336
|
//# sourceMappingURL=index.js.map
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
export type { RequestHandler as EdgeRequestHandler } from "./edge";
|
|
2
2
|
export { createEdgeRouter, EdgeRouter } from "./edge";
|
|
3
|
+
|
|
3
4
|
export type { ExpressRequestHandler } from "./adapter/express";
|
|
4
5
|
export { default as expressWrapper } from "./adapter/express";
|
|
5
6
|
|
|
6
|
-
export type { RequestHandler } from "./node";
|
|
7
|
-
export { createRouter, NodeRouter } from "./node";
|
|
7
|
+
export type { RequestHandler as NodeRequestHandler } from "./node";
|
|
8
|
+
export { createRouter as createNodeRouter, NodeRouter } from "./node";
|
|
9
|
+
|
|
10
|
+
// @deprecated Use `createNodeRouter` instead
|
|
11
|
+
export { createRouter } from "./node";
|
|
8
12
|
|
|
9
13
|
export type { Route } from "./router";
|
|
10
14
|
export { Router } from "./router";
|
package/src/types.d.ts
CHANGED