dx-server 0.2.0 → 0.2.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/README.md +61 -86
- package/cjs/index.d.ts +1 -1
- package/cjs/index.js +4 -2
- package/esm/index.d.ts +1 -1
- package/esm/index.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,11 +9,56 @@ yarn add dx-server jchain
|
|
|
9
9
|
|
|
10
10
|
Check below sample with comment for more details.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Simple server
|
|
13
13
|
|
|
14
14
|
```javascript
|
|
15
|
-
import {Server} from 'http'
|
|
16
|
-
import
|
|
15
|
+
import {Server} from 'node:http'
|
|
16
|
+
import chain from 'jchain'
|
|
17
|
+
import {
|
|
18
|
+
reqContext, resContext,
|
|
19
|
+
dxContext, setHtml, setJson, setText,
|
|
20
|
+
bufferBodyContext, jsonBodyContext, queryContext, rawBodyContext, textBodyContext, urlencodedBodyContext,
|
|
21
|
+
router,
|
|
22
|
+
} from 'dx-server'
|
|
23
|
+
|
|
24
|
+
new Server().on('request', async (req, res) => {
|
|
25
|
+
await chain(
|
|
26
|
+
reqContext.chain(req),
|
|
27
|
+
resContext.chain(res),
|
|
28
|
+
dxContext.chain(),
|
|
29
|
+
bufferBodyContext.chain(),
|
|
30
|
+
jsonBodyContext.chain(),
|
|
31
|
+
urlencodedBodyContext.chain(),
|
|
32
|
+
textBodyContext.chain(),
|
|
33
|
+
rawBodyContext.chain(),
|
|
34
|
+
queryContext.chain(),
|
|
35
|
+
next => {
|
|
36
|
+
resContext.value.setHeader('Cache-Control', 'no-cache')
|
|
37
|
+
console.log(reqContext.value.method, reqContext.value.url)
|
|
38
|
+
next()
|
|
39
|
+
},
|
|
40
|
+
async next => {
|
|
41
|
+
try {await next()} catch (e) {
|
|
42
|
+
console.error(e)
|
|
43
|
+
setHtml('internal server error (code: internal)', {status: 500})
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
router.get({
|
|
47
|
+
'/'() {setHtml('hello world')},
|
|
48
|
+
'/health'() {setText('ok')}
|
|
49
|
+
}),
|
|
50
|
+
() => {throw new Error('not found')},
|
|
51
|
+
)()
|
|
52
|
+
}).listen(3000, () => console.log('server is listening at 3000'))
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
More complex server with express.
|
|
56
|
+
This sample additionally requires: `yarn install express morgan`
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
import {Server} from 'node:http'
|
|
61
|
+
import {promisify} from 'node:util'
|
|
17
62
|
import chain from 'jchain'
|
|
18
63
|
import {
|
|
19
64
|
makeContext, reqContext, resContext,
|
|
@@ -36,7 +81,7 @@ import {
|
|
|
36
81
|
|
|
37
82
|
router
|
|
38
83
|
} from 'dx-server'
|
|
39
|
-
import {expressApp
|
|
84
|
+
import {expressApp} from 'dx-server/express'
|
|
40
85
|
import express from 'express'
|
|
41
86
|
import morgan from 'morgan'
|
|
42
87
|
|
|
@@ -66,7 +111,7 @@ const requireAuth = () => {
|
|
|
66
111
|
}
|
|
67
112
|
|
|
68
113
|
const serverChain = chain(
|
|
69
|
-
dxContext.chain({jsonBeautify:
|
|
114
|
+
dxContext.chain({jsonBeautify: process.env.NODE_ENV !== 'production'}), // allows to use setHtml, setJson, setRaw, setBuffer, setFile, setRedirect, etc.
|
|
70
115
|
bufferBodyContext.chain(), // use raw buffer body as Buffer use bufferBodyContext.value. This is required for jsonBodyContext, urlencodedBodyContext, textBodyContext, rawBodyContext
|
|
71
116
|
jsonBodyContext.chain(), // to get body parsed as json use jsonBodyContext.value. Only available if content-type is application/json
|
|
72
117
|
urlencodedBodyContext.chain(), // to get body parsed as urlencoded use urlencodedBodyContext.value. Only available if content-type is application/x-www-form-urlencoded
|
|
@@ -79,55 +124,34 @@ const serverChain = chain(
|
|
|
79
124
|
resContext.value.setHeader('Cache-Control', 'no-cache')
|
|
80
125
|
next()
|
|
81
126
|
},
|
|
82
|
-
async next => {
|
|
83
|
-
// global error catching for all following middlewares
|
|
127
|
+
async next => {// global error catching for all following middlewares
|
|
84
128
|
try {
|
|
85
129
|
await next()
|
|
86
|
-
} catch (e) {
|
|
87
|
-
// only app error message should be shown to user
|
|
130
|
+
} catch (e) {// only app error message should be shown to user
|
|
88
131
|
if (e instanceof ServerError) setHtml(`${e.message} (code: ${e.code})`, {status: e.status})
|
|
89
|
-
else {
|
|
90
|
-
// report system error
|
|
132
|
+
else {// report system error
|
|
91
133
|
console.error(e)
|
|
92
134
|
setHtml('internal server error (code: internal)', {status: 500})
|
|
93
135
|
}
|
|
94
136
|
}
|
|
95
137
|
},
|
|
96
|
-
await expressApp(app => {
|
|
97
|
-
// any express feature can be used
|
|
98
|
-
// required express installed, with for e.g., `yarn add express`
|
|
138
|
+
await expressApp(app => {// any express feature can be used. This requires express installed, with for e.g., `yarn add express`
|
|
99
139
|
app.set('trust proxy', true)
|
|
100
140
|
if (process.env.NODE_ENV !== 'production') app.set('json spaces', 2)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
morgan('common'), // in future, we will provide native implementation of express middlewares
|
|
104
|
-
// cookies, session, etc.
|
|
105
|
-
// session({
|
|
106
|
-
// secret: '123',
|
|
107
|
-
// resave: false,
|
|
108
|
-
// store: redisStore,
|
|
109
|
-
// saveUninitialized: true,
|
|
110
|
-
// // cookie: { secure: true }
|
|
111
|
-
// }),
|
|
112
|
-
),
|
|
113
|
-
await expressRouter(router => {
|
|
114
|
-
// setup express router
|
|
115
|
-
router.use('/public', express.static('public'))
|
|
141
|
+
app.use(morgan('common')) // in future, we will provide native implementation of express middlewares
|
|
142
|
+
app.use('/public', express.static('public'))
|
|
116
143
|
}),
|
|
117
144
|
authContext.chain(),
|
|
118
|
-
// example of catching error for all /api/* routes
|
|
119
|
-
router.post({
|
|
145
|
+
router.post({// example of catching error for all /api/* routes
|
|
120
146
|
async '/api'({next}) {
|
|
121
147
|
try {
|
|
122
148
|
await next()
|
|
123
149
|
} catch (e) {
|
|
124
|
-
// only app error message should be shown to user
|
|
125
|
-
if (e instanceof ServerError) setJson({
|
|
150
|
+
if (e instanceof ServerError) setJson({// only app error message should be shown to user
|
|
126
151
|
error: e.message,
|
|
127
152
|
code: e.code,
|
|
128
153
|
}, {status: e.status})
|
|
129
|
-
else {
|
|
130
|
-
// report system error
|
|
154
|
+
else {// report system error
|
|
131
155
|
console.error(e)
|
|
132
156
|
setJson({
|
|
133
157
|
message: 'internal server error',
|
|
@@ -154,11 +178,6 @@ const serverChain = chain(
|
|
|
154
178
|
setHtml('ok')
|
|
155
179
|
}
|
|
156
180
|
}),
|
|
157
|
-
router.post({ // api not found router
|
|
158
|
-
'/api'() {
|
|
159
|
-
throw new ServerError('not found', 404, 'not_found')
|
|
160
|
-
}
|
|
161
|
-
}, {end: false}),
|
|
162
181
|
() => { // not found router
|
|
163
182
|
throw new ServerError('not found', 404, 'not_found')
|
|
164
183
|
},
|
|
@@ -177,56 +196,12 @@ const tcpServer = new Server()
|
|
|
177
196
|
}
|
|
178
197
|
})
|
|
179
198
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
console.log(`server is listening at ${port}`)
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
Sample error boundary chains:
|
|
186
|
-
```typescript
|
|
187
|
-
import { type Chainable } from 'jchain'
|
|
188
|
-
import {setHtml, setJson} from 'dx-server'
|
|
189
|
-
import {router} from 'dx-server'
|
|
190
|
-
|
|
191
|
-
export const catchError: Chainable = async next => {
|
|
192
|
-
try {
|
|
193
|
-
await next()
|
|
194
|
-
} catch (e) {
|
|
195
|
-
console.error(e)
|
|
196
|
-
setHtml('internal server error', {status: 500})
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export const catchApiError: Chainable = router.post({
|
|
201
|
-
async '/api'({next}) {
|
|
202
|
-
try {
|
|
203
|
-
await next()
|
|
204
|
-
} catch (e) {
|
|
205
|
-
console.error(e)
|
|
206
|
-
setJson({
|
|
207
|
-
message: 'internal server error',
|
|
208
|
-
code: 'internal_server_error'
|
|
209
|
-
}, {status: 500})
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}, {end: false})
|
|
213
|
-
|
|
214
|
-
export const notFound: Chainable = () => {
|
|
215
|
-
setHtml('not found', {status: 404})
|
|
216
|
-
}
|
|
217
|
-
export const notFoundApi: Chainable = router.post({
|
|
218
|
-
'/api'() {
|
|
219
|
-
setJson({
|
|
220
|
-
message: 'not found',
|
|
221
|
-
code: 'not_found'
|
|
222
|
-
}, {status: 404})
|
|
223
|
-
}
|
|
224
|
-
}, {end: false})
|
|
199
|
+
await promisify(tcpServer.listen.bind(tcpServer))(3000)
|
|
200
|
+
console.log('server is listening at 3000')
|
|
225
201
|
```
|
|
226
202
|
|
|
227
203
|
## TODO
|
|
228
204
|
Until these middlewares are available as native dx-server middlewares, express middlewares can be used with `expressApp()`
|
|
229
205
|
- [ ] native static file serve, like 'static-serve'
|
|
230
206
|
- [ ] logger like morgan
|
|
231
|
-
- [ ] cookie, session
|
|
232
207
|
- [ ] cors
|
package/cjs/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { makeContext, reqContext, resContext } from './context.js';
|
|
2
|
-
export { dxContext, setHtml, setJson, setBuffer, setRedirect, setText } from './dx.js';
|
|
2
|
+
export { dxContext, setHtml, setNodeStream, setWebStream, setJson, setBuffer, setRedirect, setText } from './dx.js';
|
|
3
3
|
export { bufferBodyContext, jsonBodyContext, queryContext, rawBodyContext, textBodyContext, urlencodedBodyContext } from './body.js';
|
|
4
4
|
export { router } from './route.js';
|
package/cjs/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
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.dxContext = exports.resContext = exports.reqContext = exports.makeContext = void 0;
|
|
3
|
+
exports.router = exports.urlencodedBodyContext = exports.textBodyContext = exports.rawBodyContext = exports.queryContext = exports.jsonBodyContext = exports.bufferBodyContext = exports.setText = exports.setRedirect = exports.setBuffer = exports.setJson = exports.setWebStream = exports.setNodeStream = exports.setHtml = exports.dxContext = exports.resContext = exports.reqContext = 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, "reqContext", { enumerable: true, get: function () { return context_js_1.reqContext; } });
|
|
@@ -8,6 +8,8 @@ Object.defineProperty(exports, "resContext", { enumerable: true, get: function (
|
|
|
8
8
|
var dx_js_1 = require("./dx.js");
|
|
9
9
|
Object.defineProperty(exports, "dxContext", { enumerable: true, get: function () { return dx_js_1.dxContext; } });
|
|
10
10
|
Object.defineProperty(exports, "setHtml", { enumerable: true, get: function () { return dx_js_1.setHtml; } });
|
|
11
|
+
Object.defineProperty(exports, "setNodeStream", { enumerable: true, get: function () { return dx_js_1.setNodeStream; } });
|
|
12
|
+
Object.defineProperty(exports, "setWebStream", { enumerable: true, get: function () { return dx_js_1.setWebStream; } });
|
|
11
13
|
Object.defineProperty(exports, "setJson", { enumerable: true, get: function () { return dx_js_1.setJson; } });
|
|
12
14
|
Object.defineProperty(exports, "setBuffer", { enumerable: true, get: function () { return dx_js_1.setBuffer; } });
|
|
13
15
|
Object.defineProperty(exports, "setRedirect", { enumerable: true, get: function () { return dx_js_1.setRedirect; } });
|
|
@@ -21,4 +23,4 @@ Object.defineProperty(exports, "textBodyContext", { enumerable: true, get: funct
|
|
|
21
23
|
Object.defineProperty(exports, "urlencodedBodyContext", { enumerable: true, get: function () { return body_js_1.urlencodedBodyContext; } });
|
|
22
24
|
var route_js_1 = require("./route.js");
|
|
23
25
|
Object.defineProperty(exports, "router", { enumerable: true, get: function () { return route_js_1.router; } });
|
|
24
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkNBQWdFO0FBQXhELHlHQUFBLFdBQVcsT0FBQTtBQUFFLHdHQUFBLFVBQVUsT0FBQTtBQUFFLHdHQUFBLFVBQVUsT0FBQTtBQUMzQyxpQ0FTZ0I7QUFSZixrR0FBQSxTQUFTLE9BQUE7QUFDVCxnR0FBQSxPQUFPLE9BQUE7QUFDUCxzR0FBQSxhQUFhLE9BQUE7QUFDYixxR0FBQSxZQUFZLE9BQUE7QUFDWixnR0FBQSxPQUFPLE9BQUE7QUFDUCxrR0FBQSxTQUFTLE9BQUE7QUFDVCxvR0FBQSxXQUFXLE9BQUE7QUFDWCxnR0FBQSxPQUFPLE9BQUE7QUFFUixxQ0FPa0I7QUFOakIsNEdBQUEsaUJBQWlCLE9BQUE7QUFDakIsMEdBQUEsZUFBZSxPQUFBO0FBQ2YsdUdBQUEsWUFBWSxPQUFBO0FBQ1oseUdBQUEsY0FBYyxPQUFBO0FBQ2QsMEdBQUEsZUFBZSxPQUFBO0FBQ2YsZ0hBQUEscUJBQXFCLE9BQUE7QUFFdEIsdUNBQWlDO0FBQXpCLGtHQUFBLE1BQU0sT0FBQSJ9
|
package/esm/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { makeContext, reqContext, resContext } from './context.js';
|
|
2
|
-
export { dxContext, setHtml, setJson, setBuffer, setRedirect, setText } from './dx.js';
|
|
2
|
+
export { dxContext, setHtml, setNodeStream, setWebStream, setJson, setBuffer, setRedirect, setText } from './dx.js';
|
|
3
3
|
export { bufferBodyContext, jsonBodyContext, queryContext, rawBodyContext, textBodyContext, urlencodedBodyContext } from './body.js';
|
|
4
4
|
export { router } from './route.js';
|
package/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { makeContext, reqContext, resContext } from './context.js';
|
|
2
|
-
export { dxContext, setHtml, setJson, setBuffer, setRedirect, setText } from './dx.js';
|
|
2
|
+
export { dxContext, setHtml, setNodeStream, setWebStream, setJson, setBuffer, setRedirect, setText } from './dx.js';
|
|
3
3
|
export { bufferBodyContext, jsonBodyContext, queryContext, rawBodyContext, textBodyContext, urlencodedBodyContext } from './body.js';
|
|
4
4
|
export { router } from './route.js';
|
|
5
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFdBQVcsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFDLE1BQU0sY0FBYyxDQUFBO0FBQ2hFLE9BQU8sRUFDTixTQUFTLEVBQ1QsT0FBTyxFQUNQLGFBQWEsRUFDYixZQUFZLEVBQ1osT0FBTyxFQUNQLFNBQVMsRUFDVCxXQUFXLEVBQ1gsT0FBTyxFQUNQLE1BQU0sU0FBUyxDQUFBO0FBQ2hCLE9BQU8sRUFDTixpQkFBaUIsRUFDakIsZUFBZSxFQUNmLFlBQVksRUFDWixjQUFjLEVBQ2QsZUFBZSxFQUNmLHFCQUFxQixFQUNyQixNQUFNLFdBQVcsQ0FBQTtBQUNsQixPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sWUFBWSxDQUFBIn0=
|