dx-server 0.0.1-pre-11 → 0.0.1-pre-13

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/README.md CHANGED
@@ -9,11 +9,14 @@ yarn add dx-server jchain
9
9
 
10
10
  Check below sample with comment for more details.
11
11
 
12
+ Sample additionally requires: `yarn install express morgan`
13
+
12
14
  ```javascript
13
15
  import {Server} from 'http'
14
16
  import {promisify} from 'util'
17
+ import chain from 'jchain'
15
18
  import {
16
- requestContext, responseContext,
19
+ makeContext, requestContext, responseContext,
17
20
 
18
21
  expressContext, setHtml, setJson,
19
22
 
@@ -25,86 +28,147 @@ import {
25
28
  urlencodedBodyContext,
26
29
 
27
30
  router,
28
- catchApiError, catchError, notFound, notFoundApi,
29
- expressApp,
31
+ expressApp, expressRouter, chainExpressMiddlewares,
30
32
  } from 'dx-server'
33
+ import express from 'express'
34
+ import morgan from 'morgan'
31
35
 
32
- const tcpServer = new Server()
33
- .on('request', async (req, res) => {
34
- try {
35
- await chain(
36
- requestContext.chain(req), // required for most middlewares
37
- responseContext.chain(res), // required for most middlewares
38
- expressContext.chain({jsonBeautify: true}), // allows to use setHtml, setJson, setRaw, setBuffer, setFile, setRedirect, etc.
39
- bufferBodyContext.chain(), // use raw buffer body as Buffer use bufferBodyContext.value. This is required for jsonBodyContext, urlencodedBodyContext, textBodyContext, rawBodyContext
40
- jsonBodyContext.chain(), // to get body parsed as json use jsonBodyContext.value. Only available if content-type is application/json
41
- urlencodedBodyContext.chain(), // to get body parsed as urlencoded use urlencodedBodyContext.value. Only available if content-type is application/x-www-form-urlencoded
42
- textBodyContext.chain(), // to get body parsed as text use textBodyContext.value. Only available if content-type is text/plain
43
- rawBodyContext.chain(), // to get body as raw use rawBodyContext.value. Only available if content-type is application/octet-stream
44
- queryContext.chain(), // to get query params use queryContext.value. Query is parsed via 'qs' package. If no query, return empty object {}
45
- next => {
46
- // this is the difference between express and dx-server
47
- // req, res can be accessed from anywhere via context which uses NodeJS's AsyncLocalStorage under the hood
48
- responseContext.value.setHeader('cache-control', 'no-cache')
49
- next()
50
- },
51
- async next => {
52
- // global error catching for all following middlewares
53
- try {
54
- await next()
55
- } catch (e) {
56
- console.error(e)
57
- setHtml('internal server error', {status: 500})
58
- }
59
- },
60
- expressApp(app => {
61
- // any express feature can be used
62
- // required express installed, with for e.g., `yarn add express`
63
- app.use('/photos', express.static('photos'))
64
- }),
65
- // example of catching error for all /api/* routes
66
- router.post({
67
- async '/api'({next}) {
68
- try {
69
- await next()
70
- } catch (e) {
71
- console.error(e)
72
- setJson({
73
- message: 'internal server error',
74
- code: 'internal_server_error'
75
- }, {status: 500})
76
- }
77
- }
78
- }, {end: false}), // note: {end: false} is required to match all /api/* routes. This option is passed directly to path-to-regexp
79
- router.post({
80
- '/api/me'() { // sample POST router
81
- setJson({name: 'joe'})
36
+ // it is best practice to create custom error class for non-system error
37
+ class ServerError extends Error {
38
+ name = 'ServerError'
39
+
40
+ constructor(message, status = 400, code = 'unknown') {
41
+ super(message)
42
+ this.status = status
43
+ this.code = code
44
+ }
45
+ }
46
+
47
+ // makeContext is a convenient way to create context
48
+ const authContext = makeContext(() => {
49
+ const req = requestContext.value
50
+ // determine if user is authenticated
51
+ // for e.g.
52
+ if (req.headers.authorization) {
53
+ return {id: 1, name: 'joe'}
54
+ }
55
+ })
56
+
57
+ const requireAuth = () => {
58
+ if (!authContext.value) throw new ServerError('unauthorized', 401, 'unauthorized')
59
+ }
60
+
61
+ const serverChain = chain(
62
+ expressContext.chain({jsonBeautify: true}), // allows to use setHtml, setJson, setRaw, setBuffer, setFile, setRedirect, etc.
63
+ bufferBodyContext.chain(), // use raw buffer body as Buffer use bufferBodyContext.value. This is required for jsonBodyContext, urlencodedBodyContext, textBodyContext, rawBodyContext
64
+ jsonBodyContext.chain(), // to get body parsed as json use jsonBodyContext.value. Only available if content-type is application/json
65
+ urlencodedBodyContext.chain(), // to get body parsed as urlencoded use urlencodedBodyContext.value. Only available if content-type is application/x-www-form-urlencoded
66
+ textBodyContext.chain(), // to get body parsed as text use textBodyContext.value. Only available if content-type is text/plain
67
+ rawBodyContext.chain(), // to get body as raw use rawBodyContext.value. Only available if content-type is application/octet-stream
68
+ queryContext.chain(), // to get query params use queryContext.value. Query is parsed via 'qs' package. If no query, return empty object {}
69
+ next => {
70
+ // this is the difference between express and dx-server
71
+ // req, res can be accessed from anywhere via context which uses NodeJS's AsyncLocalStorage under the hood
72
+ responseContext.value.setHeader('cache-control', 'no-cache')
73
+ next()
74
+ },
75
+ async next => {
76
+ // global error catching for all following middlewares
77
+ try {
78
+ await next()
79
+ } catch (e) {
80
+ // only app error message should be shown to user
81
+ if (e instanceof ServerError) setHtml(`${e.message} (code: ${e.code})`, {status: e.status})
82
+ else {
83
+ // report system error
84
+ console.error(e)
85
+ setHtml('internal server error (code: internal)', {status: 500})
82
86
  }
83
- }),
84
- router.get({ // sample GET router
85
- '/'() {
86
- setHtml('ok')
87
- },
88
- '/health'() {
89
- setHtml('ok')
90
- }
91
- }),
92
- router.post({ // api not found router
93
- '/api'() {
87
+ }
88
+ },
89
+ await expressApp(app => {
90
+ // any express feature can be used
91
+ // required express installed, with for e.g., `yarn add express`
92
+ app.set('trust proxy', true)
93
+ if (process.env.NODE_ENV !== 'production') app.set('json spaces', 2)
94
+ }),
95
+ chainExpressMiddlewares(
96
+ morgan('common'), // in future, we will provide native implementation of express middlewares
97
+ // cookies, session, etc.
98
+ // session({
99
+ // secret: '123',
100
+ // resave: false,
101
+ // store: redisStore,
102
+ // saveUninitialized: true,
103
+ // // cookie: { secure: true }
104
+ // }),
105
+ ),
106
+ await expressRouter(router => {
107
+ // setup express router
108
+ router.use('/public', express.static('public'))
109
+ }),
110
+ authContext.chain(),
111
+ // example of catching error for all /api/* routes
112
+ router.post({
113
+ async '/api'({next}) {
114
+ try {
115
+ await next()
116
+ } catch (e) {
117
+ // only app error message should be shown to user
118
+ if (e instanceof ServerError) setJson({
119
+ error: e.message,
120
+ code: e.code,
121
+ }, {status: e.status})
122
+ else {
123
+ // report system error
124
+ console.error(e)
94
125
  setJson({
95
- message: 'not found',
96
- code: 'not_found'
97
- }, {status: 404})
126
+ message: 'internal server error',
127
+ code: 'internal'
128
+ }, {status: 500})
98
129
  }
99
- }, {end: false}),
100
- () => { // not found router
101
- setHtml('not found', {status: 404})
102
- },
103
- )()
104
- } catch (e) {
105
- console.error(e)
106
- }
107
- })
130
+ }
131
+ }
132
+ }, {end: false}), // note: {end: false} is required to match all /api/* routes. This option is passed directly to path-to-regexp
133
+ router.post({
134
+ '/api/sample-public-api'() { // sample POST router
135
+ setJson({name: 'joe'})
136
+ },
137
+ '/api/me'() { // sample private router
138
+ requireAuth()
139
+ setJson({name: authContext.value.name})
140
+ },
141
+ }),
142
+ router.get({ // sample GET router
143
+ '/'() {
144
+ setHtml('ok')
145
+ },
146
+ '/health'() {
147
+ setHtml('ok')
148
+ }
149
+ }),
150
+ router.post({ // api not found router
151
+ '/api'() {
152
+ throw new ServerError('not found', 404, 'not_found')
153
+ }
154
+ }, {end: false}),
155
+ () => { // not found router
156
+ throw new ServerError('not found', 404, 'not_found')
157
+ },
158
+ )
159
+
160
+ const tcpServer = new Server()
161
+ .on('request', async (req, res) => {
162
+ try {
163
+ await chain(
164
+ requestContext.chain(req), // required for most middlewares
165
+ responseContext.chain(res), // required for most middlewares
166
+ serverChain,
167
+ )()
168
+ } catch (e) {
169
+ console.error(e)
170
+ }
171
+ })
108
172
 
109
173
  const port = +(process.env.PORT ?? 3000)
110
174
  await promisify(tcpServer.listen.bind(tcpServer))(port)
@@ -1,3 +1,4 @@
1
- import { type Express, type Router } from 'express';
2
- export declare const expressApp: (setup: (app: Express) => any) => (next: any) => Promise<void>;
3
- export declare const expressRouter: (setup: (router: Router) => any) => (next: any) => Promise<void>;
1
+ import { type Express, type Router, type Request, type Response } from 'express';
2
+ export declare const expressApp: (setup: (app: Express) => any) => Promise<(next: any) => Promise<void>>;
3
+ export declare const expressRouter: (setup: (router: Router) => any) => Promise<(next: any) => Promise<void>>;
4
+ export declare const chainExpressMiddlewares: (...middlewares: ((req: Request, res: Response, next: () => any) => any)[]) => () => void;
package/cjs/expressApp.js CHANGED
@@ -1,13 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.expressRouter = exports.expressApp = void 0;
3
+ exports.chainExpressMiddlewares = exports.expressRouter = exports.expressApp = void 0;
4
4
  const express_1 = require("express");
5
5
  const context_js_1 = require("./context.js");
6
6
  const jdefer_1 = require("jdefer");
7
- const expressApp = (setup) => {
7
+ const jchain_1 = require("jchain");
8
+ const expressApp = async (setup) => {
8
9
  const symbol = Symbol('expressApp');
9
10
  const app = (0, express_1.default)();
10
- setup(app);
11
+ await setup(app);
11
12
  app.use((req, _res, _next) => req[symbol].resolve());
12
13
  app.use((err, req, _res, _next) => req[symbol].reject(err));
13
14
  return async (next) => {
@@ -20,10 +21,10 @@ const expressApp = (setup) => {
20
21
  };
21
22
  };
22
23
  exports.expressApp = expressApp;
23
- const expressRouter = (setup) => {
24
+ const expressRouter = async (setup) => {
24
25
  const symbol = Symbol('expressRouter');
25
26
  const router = express_1.default.Router();
26
- setup(router);
27
+ await setup(router);
27
28
  router.use((req, _res, _next) => req[symbol].resolve());
28
29
  router.use((err, req, _res, _next) => req[symbol].reject(err));
29
30
  return async (next) => {
@@ -36,4 +37,8 @@ const expressRouter = (setup) => {
36
37
  };
37
38
  };
38
39
  exports.expressRouter = expressRouter;
39
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwcmVzc0FwcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9leHByZXNzQXBwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFDQUEwRDtBQUMxRCw2Q0FBNEQ7QUFFNUQsbUNBQThCO0FBRXZCLE1BQU0sVUFBVSxHQUFHLENBQUMsS0FBNEIsRUFBRSxFQUFFO0lBQzFELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUVuQyxNQUFNLEdBQUcsR0FBRyxJQUFBLGlCQUFPLEdBQUUsQ0FBQTtJQUNyQixLQUFLLENBQUMsR0FBRyxDQUFDLENBQUE7SUFDVixHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO0lBQ3BELEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTtJQUMzRCxPQUFPLEtBQUssRUFBQyxJQUFJLEVBQUMsRUFBRTtRQUNuQixNQUFNLEdBQUcsR0FBRywyQkFBYyxDQUFDLEtBQUssQ0FBQTtRQUNoQyxNQUFNLEtBQUssR0FBRyxJQUFBLGdCQUFTLEdBQUUsQ0FBQTtRQUN6QixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFBO1FBQ25CLEdBQUcsQ0FBQyxHQUFHLEVBQUUsNEJBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUMvQixNQUFNLEtBQUssQ0FBQyxPQUFPLENBQUE7UUFDbkIsTUFBTSxJQUFJLEVBQUUsQ0FBQTtJQUNiLENBQUMsQ0FBQTtBQUNGLENBQUMsQ0FBQTtBQWZZLFFBQUEsVUFBVSxjQWV0QjtBQUVNLE1BQU0sYUFBYSxHQUFHLENBQUMsS0FBOEIsRUFBRSxFQUFFO0lBQy9ELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQTtJQUV0QyxNQUFNLE1BQU0sR0FBRyxpQkFBTyxDQUFDLE1BQU0sRUFBRSxDQUFBO0lBQy9CLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUNiLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7SUFDdkQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO0lBQzlELE9BQU8sS0FBSyxFQUFDLElBQUksRUFBQyxFQUFFO1FBQ25CLE1BQU0sR0FBRyxHQUFHLDJCQUFjLENBQUMsS0FBSyxDQUFBO1FBQ2hDLE1BQU0sS0FBSyxHQUFHLElBQUEsZ0JBQVMsR0FBRSxDQUFBO1FBQ3pCLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxLQUFLLENBQUE7UUFDbkIsTUFBTSxDQUFDLEdBQUcsRUFBRSw0QkFBZSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ2xDLE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FBQTtRQUNuQixNQUFNLElBQUksRUFBRSxDQUFBO0lBQ2IsQ0FBQyxDQUFBO0FBQ0YsQ0FBQyxDQUFBO0FBZlksUUFBQSxhQUFhLGlCQWV6QiJ9
40
+ const chainExpressMiddlewares = (...middlewares) => (0, jchain_1.default)(...middlewares.map(middleware => (next => {
41
+ middleware(context_js_1.requestContext.value, context_js_1.responseContext.value, next);
42
+ })));
43
+ exports.chainExpressMiddlewares = chainExpressMiddlewares;
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwcmVzc0FwcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9leHByZXNzQXBwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHFDQUF1RjtBQUN2Riw2Q0FBNEQ7QUFDNUQsbUNBQThCO0FBQzlCLG1DQUEwQztBQUVuQyxNQUFNLFVBQVUsR0FBRyxLQUFLLEVBQUUsS0FBNEIsRUFBRSxFQUFFO0lBQ2hFLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUVuQyxNQUFNLEdBQUcsR0FBRyxJQUFBLGlCQUFPLEdBQUUsQ0FBQTtJQUNyQixNQUFNLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQTtJQUNoQixHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO0lBQ3BELEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTtJQUMzRCxPQUFPLEtBQUssRUFBQyxJQUFJLEVBQUMsRUFBRTtRQUNuQixNQUFNLEdBQUcsR0FBRywyQkFBYyxDQUFDLEtBQUssQ0FBQTtRQUNoQyxNQUFNLEtBQUssR0FBRyxJQUFBLGdCQUFTLEdBQUUsQ0FBQTtRQUN6QixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFBO1FBQ25CLEdBQUcsQ0FBQyxHQUFHLEVBQUUsNEJBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUMvQixNQUFNLEtBQUssQ0FBQyxPQUFPLENBQUE7UUFDbkIsTUFBTSxJQUFJLEVBQUUsQ0FBQTtJQUNiLENBQUMsQ0FBQTtBQUNGLENBQUMsQ0FBQTtBQWZZLFFBQUEsVUFBVSxjQWV0QjtBQUVNLE1BQU0sYUFBYSxHQUFHLEtBQUssRUFBRSxLQUE4QixFQUFFLEVBQUU7SUFDckUsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFBO0lBRXRDLE1BQU0sTUFBTSxHQUFHLGlCQUFPLENBQUMsTUFBTSxFQUFFLENBQUE7SUFDL0IsTUFBTSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDbkIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQTtJQUN2RCxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7SUFDOUQsT0FBTyxLQUFLLEVBQUMsSUFBSSxFQUFDLEVBQUU7UUFDbkIsTUFBTSxHQUFHLEdBQUcsMkJBQWMsQ0FBQyxLQUFLLENBQUE7UUFDaEMsTUFBTSxLQUFLLEdBQUcsSUFBQSxnQkFBUyxHQUFFLENBQUE7UUFDekIsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLEtBQUssQ0FBQTtRQUNuQixNQUFNLENBQUMsR0FBRyxFQUFFLDRCQUFlLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDbEMsTUFBTSxLQUFLLENBQUMsT0FBTyxDQUFBO1FBQ25CLE1BQU0sSUFBSSxFQUFFLENBQUE7SUFDYixDQUFDLENBQUE7QUFDRixDQUFDLENBQUE7QUFmWSxRQUFBLGFBQWEsaUJBZXpCO0FBRU0sTUFBTSx1QkFBdUIsR0FBRyxDQUFDLEdBQUcsV0FBeUUsRUFBRSxFQUFFLENBQUMsSUFBQSxnQkFBSyxFQUM3SCxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFO0lBQ3hDLFVBQVUsQ0FBQywyQkFBYyxDQUFDLEtBQUssRUFBRSw0QkFBZSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQTtBQUM5RCxDQUFDLENBQXNCLENBQUMsQ0FDeEIsQ0FBQTtBQUpZLFFBQUEsdUJBQXVCLDJCQUluQyJ9
package/cjs/index.d.ts CHANGED
@@ -3,4 +3,4 @@ export { expressContext, setHtml, setJson, setBuffer, setRedirect, setText } fro
3
3
  export { bufferBodyContext, jsonBodyContext, queryContext, rawBodyContext, textBodyContext, urlencodedBodyContext } from './body.js';
4
4
  export { router } from './route.js';
5
5
  export { catchApiError, catchError, notFound, notFoundApi } from './error.js';
6
- export { expressApp, expressRouter } from './expressApp.js';
6
+ export { expressApp, expressRouter, chainExpressMiddlewares } from './expressApp.js';
package/cjs/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.expressRouter = exports.expressApp = exports.notFoundApi = exports.notFound = exports.catchError = exports.catchApiError = exports.router = exports.urlencodedBodyContext = exports.textBodyContext = exports.rawBodyContext = exports.queryContext = exports.jsonBodyContext = exports.bufferBodyContext = exports.setText = exports.setRedirect = exports.setBuffer = exports.setJson = exports.setHtml = exports.expressContext = exports.responseContext = exports.requestContext = exports.makeContext = void 0;
3
+ exports.chainExpressMiddlewares = exports.expressRouter = exports.expressApp = exports.notFoundApi = exports.notFound = exports.catchError = exports.catchApiError = exports.router = exports.urlencodedBodyContext = exports.textBodyContext = exports.rawBodyContext = exports.queryContext = exports.jsonBodyContext = exports.bufferBodyContext = exports.setText = exports.setRedirect = exports.setBuffer = exports.setJson = exports.setHtml = exports.expressContext = exports.responseContext = exports.requestContext = exports.makeContext = void 0;
4
4
  var context_js_1 = require("./context.js");
5
5
  Object.defineProperty(exports, "makeContext", { enumerable: true, get: function () { return context_js_1.makeContext; } });
6
6
  Object.defineProperty(exports, "requestContext", { enumerable: true, get: function () { return context_js_1.requestContext; } });
@@ -29,4 +29,5 @@ Object.defineProperty(exports, "notFoundApi", { enumerable: true, get: function
29
29
  var expressApp_js_1 = require("./expressApp.js");
30
30
  Object.defineProperty(exports, "expressApp", { enumerable: true, get: function () { return expressApp_js_1.expressApp; } });
31
31
  Object.defineProperty(exports, "expressRouter", { enumerable: true, get: function () { return expressApp_js_1.expressRouter; } });
32
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkNBQXlFO0FBQWpFLHlHQUFBLFdBQVcsT0FBQTtBQUFFLDRHQUFBLGNBQWMsT0FBQTtBQUFFLDZHQUFBLGVBQWUsT0FBQTtBQUNwRCwyQ0FPcUI7QUFOcEIsNEdBQUEsY0FBYyxPQUFBO0FBQ2QscUdBQUEsT0FBTyxPQUFBO0FBQ1AscUdBQUEsT0FBTyxPQUFBO0FBQ1AsdUdBQUEsU0FBUyxPQUFBO0FBQ1QseUdBQUEsV0FBVyxPQUFBO0FBQ1gscUdBQUEsT0FBTyxPQUFBO0FBRVIscUNBT2tCO0FBTmpCLDRHQUFBLGlCQUFpQixPQUFBO0FBQ2pCLDBHQUFBLGVBQWUsT0FBQTtBQUNmLHVHQUFBLFlBQVksT0FBQTtBQUNaLHlHQUFBLGNBQWMsT0FBQTtBQUNkLDBHQUFBLGVBQWUsT0FBQTtBQUNmLGdIQUFBLHFCQUFxQixPQUFBO0FBRXRCLHVDQUFpQztBQUF6QixrR0FBQSxNQUFNLE9BQUE7QUFDZCx1Q0FBMkU7QUFBbkUseUdBQUEsYUFBYSxPQUFBO0FBQUUsc0dBQUEsVUFBVSxPQUFBO0FBQUUsb0dBQUEsUUFBUSxPQUFBO0FBQUUsdUdBQUEsV0FBVyxPQUFBO0FBQ3hELGlEQUF5RDtBQUFqRCwyR0FBQSxVQUFVLE9BQUE7QUFBRSw4R0FBQSxhQUFhLE9BQUEifQ==
32
+ Object.defineProperty(exports, "chainExpressMiddlewares", { enumerable: true, get: function () { return expressApp_js_1.chainExpressMiddlewares; } });
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkNBQXlFO0FBQWpFLHlHQUFBLFdBQVcsT0FBQTtBQUFFLDRHQUFBLGNBQWMsT0FBQTtBQUFFLDZHQUFBLGVBQWUsT0FBQTtBQUNwRCwyQ0FPcUI7QUFOcEIsNEdBQUEsY0FBYyxPQUFBO0FBQ2QscUdBQUEsT0FBTyxPQUFBO0FBQ1AscUdBQUEsT0FBTyxPQUFBO0FBQ1AsdUdBQUEsU0FBUyxPQUFBO0FBQ1QseUdBQUEsV0FBVyxPQUFBO0FBQ1gscUdBQUEsT0FBTyxPQUFBO0FBRVIscUNBT2tCO0FBTmpCLDRHQUFBLGlCQUFpQixPQUFBO0FBQ2pCLDBHQUFBLGVBQWUsT0FBQTtBQUNmLHVHQUFBLFlBQVksT0FBQTtBQUNaLHlHQUFBLGNBQWMsT0FBQTtBQUNkLDBHQUFBLGVBQWUsT0FBQTtBQUNmLGdIQUFBLHFCQUFxQixPQUFBO0FBRXRCLHVDQUFpQztBQUF6QixrR0FBQSxNQUFNLE9BQUE7QUFDZCx1Q0FBMkU7QUFBbkUseUdBQUEsYUFBYSxPQUFBO0FBQUUsc0dBQUEsVUFBVSxPQUFBO0FBQUUsb0dBQUEsUUFBUSxPQUFBO0FBQUUsdUdBQUEsV0FBVyxPQUFBO0FBQ3hELGlEQUFrRjtBQUExRSwyR0FBQSxVQUFVLE9BQUE7QUFBRSw4R0FBQSxhQUFhLE9BQUE7QUFBRSx3SEFBQSx1QkFBdUIsT0FBQSJ9
@@ -1,3 +1,4 @@
1
- import { type Express, type Router } from 'express';
2
- export declare const expressApp: (setup: (app: Express) => any) => (next: any) => Promise<void>;
3
- export declare const expressRouter: (setup: (router: Router) => any) => (next: any) => Promise<void>;
1
+ import { type Express, type Router, type Request, type Response } from 'express';
2
+ export declare const expressApp: (setup: (app: Express) => any) => Promise<(next: any) => Promise<void>>;
3
+ export declare const expressRouter: (setup: (router: Router) => any) => Promise<(next: any) => Promise<void>>;
4
+ export declare const chainExpressMiddlewares: (...middlewares: ((req: Request, res: Response, next: () => any) => any)[]) => () => void;
package/esm/expressApp.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import express from 'express';
2
2
  import { requestContext, responseContext } from './context.js';
3
3
  import makeDefer from 'jdefer';
4
- export const expressApp = (setup) => {
4
+ import chain from 'jchain';
5
+ export const expressApp = async (setup) => {
5
6
  const symbol = Symbol('expressApp');
6
7
  const app = express();
7
- setup(app);
8
+ await setup(app);
8
9
  app.use((req, _res, _next) => req[symbol].resolve());
9
10
  app.use((err, req, _res, _next) => req[symbol].reject(err));
10
11
  return async (next) => {
@@ -16,10 +17,10 @@ export const expressApp = (setup) => {
16
17
  await next();
17
18
  };
18
19
  };
19
- export const expressRouter = (setup) => {
20
+ export const expressRouter = async (setup) => {
20
21
  const symbol = Symbol('expressRouter');
21
22
  const router = express.Router();
22
- setup(router);
23
+ await setup(router);
23
24
  router.use((req, _res, _next) => req[symbol].resolve());
24
25
  router.use((err, req, _res, _next) => req[symbol].reject(err));
25
26
  return async (next) => {
@@ -31,4 +32,7 @@ export const expressRouter = (setup) => {
31
32
  await next();
32
33
  };
33
34
  };
34
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwcmVzc0FwcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9leHByZXNzQXBwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sT0FBb0MsTUFBTSxTQUFTLENBQUE7QUFDMUQsT0FBTyxFQUFDLGNBQWMsRUFBRSxlQUFlLEVBQUMsTUFBTSxjQUFjLENBQUE7QUFFNUQsT0FBTyxTQUFTLE1BQU0sUUFBUSxDQUFBO0FBRTlCLE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRyxDQUFDLEtBQTRCLEVBQUUsRUFBRTtJQUMxRCxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUE7SUFFbkMsTUFBTSxHQUFHLEdBQUcsT0FBTyxFQUFFLENBQUE7SUFDckIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFBO0lBQ1YsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQTtJQUNwRCxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7SUFDM0QsT0FBTyxLQUFLLEVBQUMsSUFBSSxFQUFDLEVBQUU7UUFDbkIsTUFBTSxHQUFHLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQTtRQUNoQyxNQUFNLEtBQUssR0FBRyxTQUFTLEVBQUUsQ0FBQTtRQUN6QixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFBO1FBQ25CLEdBQUcsQ0FBQyxHQUFHLEVBQUUsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQy9CLE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FBQTtRQUNuQixNQUFNLElBQUksRUFBRSxDQUFBO0lBQ2IsQ0FBQyxDQUFBO0FBQ0YsQ0FBQyxDQUFBO0FBRUQsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLENBQUMsS0FBOEIsRUFBRSxFQUFFO0lBQy9ELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQTtJQUV0QyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUE7SUFDL0IsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQ2IsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQTtJQUN2RCxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7SUFDOUQsT0FBTyxLQUFLLEVBQUMsSUFBSSxFQUFDLEVBQUU7UUFDbkIsTUFBTSxHQUFHLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQTtRQUNoQyxNQUFNLEtBQUssR0FBRyxTQUFTLEVBQUUsQ0FBQTtRQUN6QixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFBO1FBQ25CLE1BQU0sQ0FBQyxHQUFHLEVBQUUsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ2xDLE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FBQTtRQUNuQixNQUFNLElBQUksRUFBRSxDQUFBO0lBQ2IsQ0FBQyxDQUFBO0FBQ0YsQ0FBQyxDQUFBIn0=
35
+ export const chainExpressMiddlewares = (...middlewares) => chain(...middlewares.map(middleware => (next => {
36
+ middleware(requestContext.value, responseContext.value, next);
37
+ })));
38
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwcmVzc0FwcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9leHByZXNzQXBwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sT0FBaUUsTUFBTSxTQUFTLENBQUE7QUFDdkYsT0FBTyxFQUFDLGNBQWMsRUFBRSxlQUFlLEVBQUMsTUFBTSxjQUFjLENBQUE7QUFDNUQsT0FBTyxTQUFTLE1BQU0sUUFBUSxDQUFBO0FBQzlCLE9BQU8sS0FBcUIsTUFBTSxRQUFRLENBQUE7QUFFMUMsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHLEtBQUssRUFBRSxLQUE0QixFQUFFLEVBQUU7SUFDaEUsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBRW5DLE1BQU0sR0FBRyxHQUFHLE9BQU8sRUFBRSxDQUFBO0lBQ3JCLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFBO0lBQ2hCLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7SUFDcEQsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO0lBQzNELE9BQU8sS0FBSyxFQUFDLElBQUksRUFBQyxFQUFFO1FBQ25CLE1BQU0sR0FBRyxHQUFHLGNBQWMsQ0FBQyxLQUFLLENBQUE7UUFDaEMsTUFBTSxLQUFLLEdBQUcsU0FBUyxFQUFFLENBQUE7UUFDekIsR0FBRyxDQUFDLE1BQU0sQ0FBQyxHQUFHLEtBQUssQ0FBQTtRQUNuQixHQUFHLENBQUMsR0FBRyxFQUFFLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUMvQixNQUFNLEtBQUssQ0FBQyxPQUFPLENBQUE7UUFDbkIsTUFBTSxJQUFJLEVBQUUsQ0FBQTtJQUNiLENBQUMsQ0FBQTtBQUNGLENBQUMsQ0FBQTtBQUVELE1BQU0sQ0FBQyxNQUFNLGFBQWEsR0FBRyxLQUFLLEVBQUUsS0FBOEIsRUFBRSxFQUFFO0lBQ3JFLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQTtJQUV0QyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUE7SUFDL0IsTUFBTSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDbkIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQTtJQUN2RCxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7SUFDOUQsT0FBTyxLQUFLLEVBQUMsSUFBSSxFQUFDLEVBQUU7UUFDbkIsTUFBTSxHQUFHLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQTtRQUNoQyxNQUFNLEtBQUssR0FBRyxTQUFTLEVBQUUsQ0FBQTtRQUN6QixHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFBO1FBQ25CLE1BQU0sQ0FBQyxHQUFHLEVBQUUsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ2xDLE1BQU0sS0FBSyxDQUFDLE9BQU8sQ0FBQTtRQUNuQixNQUFNLElBQUksRUFBRSxDQUFBO0lBQ2IsQ0FBQyxDQUFBO0FBQ0YsQ0FBQyxDQUFBO0FBRUQsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxHQUFHLFdBQXlFLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FDN0gsR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRTtJQUN4QyxVQUFVLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRSxlQUFlLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFBO0FBQzlELENBQUMsQ0FBc0IsQ0FBQyxDQUN4QixDQUFBIn0=
package/esm/index.d.ts CHANGED
@@ -3,4 +3,4 @@ export { expressContext, setHtml, setJson, setBuffer, setRedirect, setText } fro
3
3
  export { bufferBodyContext, jsonBodyContext, queryContext, rawBodyContext, textBodyContext, urlencodedBodyContext } from './body.js';
4
4
  export { router } from './route.js';
5
5
  export { catchApiError, catchError, notFound, notFoundApi } from './error.js';
6
- export { expressApp, expressRouter } from './expressApp.js';
6
+ export { expressApp, expressRouter, chainExpressMiddlewares } from './expressApp.js';
package/esm/index.js CHANGED
@@ -3,5 +3,5 @@ export { expressContext, setHtml, setJson, setBuffer, setRedirect, setText } fro
3
3
  export { bufferBodyContext, jsonBodyContext, queryContext, rawBodyContext, textBodyContext, urlencodedBodyContext } from './body.js';
4
4
  export { router } from './route.js';
5
5
  export { catchApiError, catchError, notFound, notFoundApi } from './error.js';
6
- export { expressApp, expressRouter } from './expressApp.js';
7
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFdBQVcsRUFBRSxjQUFjLEVBQUUsZUFBZSxFQUFDLE1BQU0sY0FBYyxDQUFBO0FBQ3pFLE9BQU8sRUFDTixjQUFjLEVBQ2QsT0FBTyxFQUNQLE9BQU8sRUFDUCxTQUFTLEVBQ1QsV0FBVyxFQUNYLE9BQU8sRUFDUCxNQUFNLGNBQWMsQ0FBQTtBQUNyQixPQUFPLEVBQ04saUJBQWlCLEVBQ2pCLGVBQWUsRUFDZixZQUFZLEVBQ1osY0FBYyxFQUNkLGVBQWUsRUFDZixxQkFBcUIsRUFDckIsTUFBTSxXQUFXLENBQUE7QUFDbEIsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLFlBQVksQ0FBQTtBQUNqQyxPQUFPLEVBQUMsYUFBYSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFDLE1BQU0sWUFBWSxDQUFBO0FBQzNFLE9BQU8sRUFBQyxVQUFVLEVBQUUsYUFBYSxFQUFDLE1BQU0saUJBQWlCLENBQUEifQ==
6
+ export { expressApp, expressRouter, chainExpressMiddlewares } from './expressApp.js';
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFdBQVcsRUFBRSxjQUFjLEVBQUUsZUFBZSxFQUFDLE1BQU0sY0FBYyxDQUFBO0FBQ3pFLE9BQU8sRUFDTixjQUFjLEVBQ2QsT0FBTyxFQUNQLE9BQU8sRUFDUCxTQUFTLEVBQ1QsV0FBVyxFQUNYLE9BQU8sRUFDUCxNQUFNLGNBQWMsQ0FBQTtBQUNyQixPQUFPLEVBQ04saUJBQWlCLEVBQ2pCLGVBQWUsRUFDZixZQUFZLEVBQ1osY0FBYyxFQUNkLGVBQWUsRUFDZixxQkFBcUIsRUFDckIsTUFBTSxXQUFXLENBQUE7QUFDbEIsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLFlBQVksQ0FBQTtBQUNqQyxPQUFPLEVBQUMsYUFBYSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFDLE1BQU0sWUFBWSxDQUFBO0FBQzNFLE9BQU8sRUFBQyxVQUFVLEVBQUUsYUFBYSxFQUFFLHVCQUF1QixFQUFDLE1BQU0saUJBQWlCLENBQUEifQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dx-server",
3
- "version": "0.0.1-pre-11",
3
+ "version": "0.0.1-pre-13",
4
4
  "main": "./cjs/index.js",
5
5
  "repository": "git@github.com:tranvansang/dx-server.git",
6
6
  "author": "Sang Tran <t@sang.jp>",