@modern-js/plugin-express 1.5.6 → 1.6.1-beta.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 +20 -0
- package/dist/js/modern/plugin.js +9 -7
- package/dist/js/modern/registerRoutes.js +9 -104
- package/dist/js/modern/runtime.js +2 -1
- package/dist/js/modern/utils.js +139 -0
- package/dist/js/node/plugin.js +8 -7
- package/dist/js/node/registerRoutes.js +9 -111
- package/dist/js/node/runtime.js +18 -1
- package/dist/js/node/utils.js +157 -0
- package/dist/types/plugin.d.ts +0 -1
- package/dist/types/registerRoutes.d.ts +4 -2
- package/dist/types/runtime.d.ts +2 -1
- package/dist/types/utils.d.ts +8 -0
- package/package.json +14 -11
- package/types.d.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @modern-js/plugin-express
|
|
2
2
|
|
|
3
|
+
## 1.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 77a8e9e: feat: support bff operators
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- f29e9ba: feat: simplify context usage, no longer depend on containers
|
|
12
|
+
- Updated dependencies [77a8e9e]
|
|
13
|
+
- Updated dependencies [2dacc89]
|
|
14
|
+
- Updated dependencies [b220f1d]
|
|
15
|
+
- Updated dependencies [7b9e302]
|
|
16
|
+
- Updated dependencies [a90bc96]
|
|
17
|
+
- @modern-js/adapter-helpers@1.3.0
|
|
18
|
+
- @modern-js/bff-core@1.1.0
|
|
19
|
+
- @modern-js/bff-runtime@1.3.0
|
|
20
|
+
- @modern-js/types@1.5.5
|
|
21
|
+
- @modern-js/utils@1.7.9
|
|
22
|
+
|
|
3
23
|
## 1.5.6
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
package/dist/js/modern/plugin.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
2
|
import express from 'express';
|
|
3
3
|
import cookieParser from 'cookie-parser';
|
|
4
|
-
import {
|
|
5
|
-
import { fs, createDebugger } from '@modern-js/utils';
|
|
4
|
+
import { fs, createDebugger, compatRequire } from '@modern-js/utils';
|
|
6
5
|
import finalhandler from 'finalhandler';
|
|
7
6
|
import { run } from "./context";
|
|
8
7
|
import registerRoutes from "./registerRoutes";
|
|
@@ -14,7 +13,8 @@ const findAppModule = async apiDir => {
|
|
|
14
13
|
|
|
15
14
|
for (const filename of paths) {
|
|
16
15
|
if (await fs.pathExists(filename)) {
|
|
17
|
-
|
|
16
|
+
delete require.cache[filename];
|
|
17
|
+
return compatRequire(filename);
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -23,7 +23,7 @@ const findAppModule = async apiDir => {
|
|
|
23
23
|
|
|
24
24
|
const initMiddlewares = (middleware, app) => {
|
|
25
25
|
middleware.forEach(middlewareItem => {
|
|
26
|
-
const middlewareFunc = typeof middlewareItem === 'string' ?
|
|
26
|
+
const middlewareFunc = typeof middlewareItem === 'string' ? compatRequire(middlewareItem) : middlewareItem;
|
|
27
27
|
app.use(middlewareFunc);
|
|
28
28
|
});
|
|
29
29
|
};
|
|
@@ -50,7 +50,7 @@ const initApp = app => {
|
|
|
50
50
|
export default (() => ({
|
|
51
51
|
name: '@modern-js/plugin-express',
|
|
52
52
|
pre: ['@modern-js/plugin-bff'],
|
|
53
|
-
setup:
|
|
53
|
+
setup: api => ({
|
|
54
54
|
async prepareApiServer({
|
|
55
55
|
pwd,
|
|
56
56
|
mode,
|
|
@@ -58,6 +58,8 @@ export default (() => ({
|
|
|
58
58
|
}) {
|
|
59
59
|
let app;
|
|
60
60
|
const apiDir = path.join(pwd, './api');
|
|
61
|
+
const appContext = api.useAppContext();
|
|
62
|
+
const apiHandlerInfos = appContext.apiHandlerInfos;
|
|
61
63
|
|
|
62
64
|
if (mode === 'framework') {
|
|
63
65
|
app = await findAppModule(apiDir);
|
|
@@ -77,7 +79,7 @@ export default (() => ({
|
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
useRun(app);
|
|
80
|
-
registerRoutes(app);
|
|
82
|
+
registerRoutes(app, apiHandlerInfos);
|
|
81
83
|
} else if (mode === 'function') {
|
|
82
84
|
app = express();
|
|
83
85
|
initApp(app);
|
|
@@ -90,7 +92,7 @@ export default (() => ({
|
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
useRun(app);
|
|
93
|
-
registerRoutes(app);
|
|
95
|
+
registerRoutes(app, apiHandlerInfos);
|
|
94
96
|
} else {
|
|
95
97
|
throw new Error(`mode must be function or framework`);
|
|
96
98
|
}
|
|
@@ -1,111 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { createRouteHandler } from "./utils";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
6
|
-
|
|
7
|
-
import { HttpMethod, useAPIHandlerInfos } from '@modern-js/bff-utils';
|
|
8
|
-
import { isSchemaHandler } from '@modern-js/bff-runtime';
|
|
9
|
-
import typeIs from 'type-is';
|
|
10
|
-
import formidable from 'formidable';
|
|
11
|
-
import { sortDynamicRoutes } from '@modern-js/adapter-helpers';
|
|
12
|
-
import { createDebugger } from '@modern-js/utils';
|
|
13
|
-
const debug = createDebugger('express');
|
|
14
|
-
|
|
15
|
-
const registerRoutes = app => {
|
|
16
|
-
const handlerInfos = useAPIHandlerInfos();
|
|
17
|
-
sortDynamicRoutes(handlerInfos);
|
|
18
|
-
debug('handlerInfos', handlerInfos);
|
|
4
|
+
const registerRoutes = (app, handlerInfos) => {
|
|
19
5
|
handlerInfos.forEach(({
|
|
20
|
-
|
|
6
|
+
routePath,
|
|
21
7
|
handler,
|
|
22
|
-
|
|
23
|
-
name
|
|
8
|
+
httpMethod
|
|
24
9
|
}) => {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (isSchemaHandler(handler)) {
|
|
29
|
-
const result = await handler(input);
|
|
30
|
-
|
|
31
|
-
if (result.type !== 'HandleSuccess') {
|
|
32
|
-
if (result.type === 'InputValidationError') {
|
|
33
|
-
res.status(400);
|
|
34
|
-
} else {
|
|
35
|
-
res.status(500);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return res.json(result.message);
|
|
39
|
-
} else {
|
|
40
|
-
res.status(200);
|
|
41
|
-
return res.json(result.value);
|
|
42
|
-
}
|
|
43
|
-
} else {
|
|
44
|
-
const args = Object.values(input.params).concat(input);
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
48
|
-
// @ts-expect-error
|
|
49
|
-
const body = await handler(...args); // this should never happen
|
|
50
|
-
|
|
51
|
-
if (res.headersSent) {
|
|
52
|
-
return await Promise.resolve();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return res.json(body);
|
|
56
|
-
} catch (e) {
|
|
57
|
-
return next(e);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
Object.defineProperties(wrappedHandler, Object.getOwnPropertyDescriptors(handler));
|
|
63
|
-
|
|
64
|
-
if (isNormalMethod(method)) {
|
|
65
|
-
const routeName = method.toLowerCase();
|
|
66
|
-
app[routeName](path || name, wrappedHandler);
|
|
67
|
-
} else {
|
|
68
|
-
throw new Error(`Unknown HTTP Method: ${method}`);
|
|
69
|
-
}
|
|
10
|
+
const routeHandler = createRouteHandler(handler);
|
|
11
|
+
const method = httpMethod.toLowerCase();
|
|
12
|
+
app[method](routePath, routeHandler);
|
|
70
13
|
});
|
|
71
14
|
};
|
|
72
15
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
export default registerRoutes;
|
|
76
|
-
|
|
77
|
-
const getInputFromRequest = async request => {
|
|
78
|
-
const draft = {
|
|
79
|
-
params: request.params,
|
|
80
|
-
query: request.query,
|
|
81
|
-
headers: request.headers,
|
|
82
|
-
cookies: request.headers.cookie
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
if (typeIs(request, ['application/json'])) {
|
|
86
|
-
draft.data = request.body;
|
|
87
|
-
} else if (typeIs(request, ['multipart/form-data'])) {
|
|
88
|
-
draft.formData = await resolveFormData(request);
|
|
89
|
-
} else if (typeIs(request, ['application/x-www-form-urlencoded'])) {
|
|
90
|
-
draft.formUrlencoded = request.body;
|
|
91
|
-
} else {
|
|
92
|
-
draft.body = request.body;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return draft;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const resolveFormData = request => {
|
|
99
|
-
const form = formidable({
|
|
100
|
-
multiples: true
|
|
101
|
-
});
|
|
102
|
-
return new Promise((resolve, reject) => {
|
|
103
|
-
form.parse(request, (err, fields, files) => {
|
|
104
|
-
if (err) {
|
|
105
|
-
reject(err);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
resolve(_objectSpread(_objectSpread({}, fields), files));
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
};
|
|
16
|
+
export default registerRoutes;
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { useContext } from "./context";
|
|
1
|
+
export { useContext } from "./context";
|
|
2
|
+
export * from '@modern-js/bff-core';
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
2
|
+
|
|
3
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
4
|
+
|
|
5
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
6
|
+
|
|
7
|
+
import 'reflect-metadata';
|
|
8
|
+
import { httpMethods, isWithMetaHandler, HttpMetadata, ResponseMetaType } from '@modern-js/bff-core';
|
|
9
|
+
import { isSchemaHandler } from '@modern-js/bff-runtime';
|
|
10
|
+
import typeIs from 'type-is';
|
|
11
|
+
import formidable from 'formidable';
|
|
12
|
+
|
|
13
|
+
const handleResponseMeta = (res, handler) => {
|
|
14
|
+
const responseMeta = Reflect.getMetadata(HttpMetadata.Response, handler);
|
|
15
|
+
|
|
16
|
+
if (Array.isArray(responseMeta)) {
|
|
17
|
+
for (const meta of responseMeta) {
|
|
18
|
+
const metaType = meta.type;
|
|
19
|
+
const metaValue = meta.value;
|
|
20
|
+
|
|
21
|
+
switch (metaType) {
|
|
22
|
+
case ResponseMetaType.Headers:
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
24
|
+
for (const [key, value] of Object.entries(metaValue)) {
|
|
25
|
+
res.append(key, value);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
break;
|
|
29
|
+
|
|
30
|
+
case ResponseMetaType.Redirect:
|
|
31
|
+
res.redirect(metaValue);
|
|
32
|
+
break;
|
|
33
|
+
|
|
34
|
+
case ResponseMetaType.StatusCode:
|
|
35
|
+
res.status(metaValue);
|
|
36
|
+
break;
|
|
37
|
+
|
|
38
|
+
default:
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const createRouteHandler = handler => {
|
|
46
|
+
const apiHandler = async (req, res, next) => {
|
|
47
|
+
const input = await getInputFromRequest(req);
|
|
48
|
+
|
|
49
|
+
if (isWithMetaHandler(handler)) {
|
|
50
|
+
try {
|
|
51
|
+
handleResponseMeta(res, handler);
|
|
52
|
+
const result = await handler(input);
|
|
53
|
+
return res.json(result);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
if (error instanceof Error) {
|
|
56
|
+
if (error.status) {
|
|
57
|
+
res.status(error.status);
|
|
58
|
+
} else {
|
|
59
|
+
res.status(500);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return res.json({
|
|
63
|
+
code: error.code,
|
|
64
|
+
message: error.message
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
} else if (isSchemaHandler(handler)) {
|
|
69
|
+
const result = await handler(input);
|
|
70
|
+
|
|
71
|
+
if (result.type !== 'HandleSuccess') {
|
|
72
|
+
if (result.type === 'InputValidationError') {
|
|
73
|
+
res.status(400);
|
|
74
|
+
} else {
|
|
75
|
+
res.status(500);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return res.json(result.message);
|
|
79
|
+
} else {
|
|
80
|
+
res.status(200);
|
|
81
|
+
return res.json(result.value);
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
const args = Object.values(input.params).concat(input);
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const body = await handler(...args); // this should never happen
|
|
88
|
+
|
|
89
|
+
if (res.headersSent) {
|
|
90
|
+
return await Promise.resolve();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return res.json(body);
|
|
94
|
+
} catch (e) {
|
|
95
|
+
return next(e);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
Object.defineProperties(apiHandler, Object.getOwnPropertyDescriptors(handler));
|
|
101
|
+
return apiHandler;
|
|
102
|
+
};
|
|
103
|
+
export const isNormalMethod = httpMethod => httpMethods.includes(httpMethod);
|
|
104
|
+
|
|
105
|
+
const getInputFromRequest = async request => {
|
|
106
|
+
const draft = {
|
|
107
|
+
params: request.params,
|
|
108
|
+
query: request.query,
|
|
109
|
+
headers: request.headers,
|
|
110
|
+
cookies: request.headers.cookie
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
if (typeIs(request, ['application/json'])) {
|
|
114
|
+
draft.data = request.body;
|
|
115
|
+
} else if (typeIs(request, ['multipart/form-data'])) {
|
|
116
|
+
draft.formData = await resolveFormData(request);
|
|
117
|
+
} else if (typeIs(request, ['application/x-www-form-urlencoded'])) {
|
|
118
|
+
draft.formUrlencoded = request.body;
|
|
119
|
+
} else {
|
|
120
|
+
draft.body = request.body;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return draft;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const resolveFormData = request => {
|
|
127
|
+
const form = formidable({
|
|
128
|
+
multiples: true
|
|
129
|
+
});
|
|
130
|
+
return new Promise((resolve, reject) => {
|
|
131
|
+
form.parse(request, (err, fields, files) => {
|
|
132
|
+
if (err) {
|
|
133
|
+
reject(err);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
resolve(_objectSpread(_objectSpread({}, fields), files));
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
};
|
package/dist/js/node/plugin.js
CHANGED
|
@@ -11,8 +11,6 @@ var _express = _interopRequireDefault(require("express"));
|
|
|
11
11
|
|
|
12
12
|
var _cookieParser = _interopRequireDefault(require("cookie-parser"));
|
|
13
13
|
|
|
14
|
-
var _bffUtils = require("@modern-js/bff-utils");
|
|
15
|
-
|
|
16
14
|
var _utils = require("@modern-js/utils");
|
|
17
15
|
|
|
18
16
|
var _finalhandler = _interopRequireDefault(require("finalhandler"));
|
|
@@ -35,7 +33,8 @@ const findAppModule = async apiDir => {
|
|
|
35
33
|
|
|
36
34
|
for (const filename of paths) {
|
|
37
35
|
if (await _utils.fs.pathExists(filename)) {
|
|
38
|
-
|
|
36
|
+
delete require.cache[filename];
|
|
37
|
+
return (0, _utils.compatRequire)(filename);
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
40
|
|
|
@@ -44,7 +43,7 @@ const findAppModule = async apiDir => {
|
|
|
44
43
|
|
|
45
44
|
const initMiddlewares = (middleware, app) => {
|
|
46
45
|
middleware.forEach(middlewareItem => {
|
|
47
|
-
const middlewareFunc = typeof middlewareItem === 'string' ? (0,
|
|
46
|
+
const middlewareFunc = typeof middlewareItem === 'string' ? (0, _utils.compatRequire)(middlewareItem) : middlewareItem;
|
|
48
47
|
app.use(middlewareFunc);
|
|
49
48
|
});
|
|
50
49
|
};
|
|
@@ -71,7 +70,7 @@ const initApp = app => {
|
|
|
71
70
|
var _default = () => ({
|
|
72
71
|
name: '@modern-js/plugin-express',
|
|
73
72
|
pre: ['@modern-js/plugin-bff'],
|
|
74
|
-
setup:
|
|
73
|
+
setup: api => ({
|
|
75
74
|
async prepareApiServer({
|
|
76
75
|
pwd,
|
|
77
76
|
mode,
|
|
@@ -79,6 +78,8 @@ var _default = () => ({
|
|
|
79
78
|
}) {
|
|
80
79
|
let app;
|
|
81
80
|
const apiDir = path.join(pwd, './api');
|
|
81
|
+
const appContext = api.useAppContext();
|
|
82
|
+
const apiHandlerInfos = appContext.apiHandlerInfos;
|
|
82
83
|
|
|
83
84
|
if (mode === 'framework') {
|
|
84
85
|
app = await findAppModule(apiDir);
|
|
@@ -98,7 +99,7 @@ var _default = () => ({
|
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
useRun(app);
|
|
101
|
-
(0, _registerRoutes.default)(app);
|
|
102
|
+
(0, _registerRoutes.default)(app, apiHandlerInfos);
|
|
102
103
|
} else if (mode === 'function') {
|
|
103
104
|
app = (0, _express.default)();
|
|
104
105
|
initApp(app);
|
|
@@ -111,7 +112,7 @@ var _default = () => ({
|
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
useRun(app);
|
|
114
|
-
(0, _registerRoutes.default)(app);
|
|
115
|
+
(0, _registerRoutes.default)(app, apiHandlerInfos);
|
|
115
116
|
} else {
|
|
116
117
|
throw new Error(`mode must be function or framework`);
|
|
117
118
|
}
|
|
@@ -5,123 +5,21 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
require("reflect-metadata");
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _utils = require("./utils");
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
var _formidable = _interopRequireDefault(require("formidable"));
|
|
15
|
-
|
|
16
|
-
var _adapterHelpers = require("@modern-js/adapter-helpers");
|
|
17
|
-
|
|
18
|
-
var _utils = require("@modern-js/utils");
|
|
19
|
-
|
|
20
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
|
-
|
|
22
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
23
|
-
|
|
24
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
25
|
-
|
|
26
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
27
|
-
|
|
28
|
-
const debug = (0, _utils.createDebugger)('express');
|
|
29
|
-
|
|
30
|
-
const registerRoutes = app => {
|
|
31
|
-
const handlerInfos = (0, _bffUtils.useAPIHandlerInfos)();
|
|
32
|
-
(0, _adapterHelpers.sortDynamicRoutes)(handlerInfos);
|
|
33
|
-
debug('handlerInfos', handlerInfos);
|
|
12
|
+
const registerRoutes = (app, handlerInfos) => {
|
|
34
13
|
handlerInfos.forEach(({
|
|
35
|
-
|
|
14
|
+
routePath,
|
|
36
15
|
handler,
|
|
37
|
-
|
|
38
|
-
name
|
|
16
|
+
httpMethod
|
|
39
17
|
}) => {
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if ((0, _bffRuntime.isSchemaHandler)(handler)) {
|
|
44
|
-
const result = await handler(input);
|
|
45
|
-
|
|
46
|
-
if (result.type !== 'HandleSuccess') {
|
|
47
|
-
if (result.type === 'InputValidationError') {
|
|
48
|
-
res.status(400);
|
|
49
|
-
} else {
|
|
50
|
-
res.status(500);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return res.json(result.message);
|
|
54
|
-
} else {
|
|
55
|
-
res.status(200);
|
|
56
|
-
return res.json(result.value);
|
|
57
|
-
}
|
|
58
|
-
} else {
|
|
59
|
-
const args = Object.values(input.params).concat(input);
|
|
60
|
-
|
|
61
|
-
try {
|
|
62
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
63
|
-
// @ts-expect-error
|
|
64
|
-
const body = await handler(...args); // this should never happen
|
|
65
|
-
|
|
66
|
-
if (res.headersSent) {
|
|
67
|
-
return await Promise.resolve();
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return res.json(body);
|
|
71
|
-
} catch (e) {
|
|
72
|
-
return next(e);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
Object.defineProperties(wrappedHandler, Object.getOwnPropertyDescriptors(handler));
|
|
78
|
-
|
|
79
|
-
if (isNormalMethod(method)) {
|
|
80
|
-
const routeName = method.toLowerCase();
|
|
81
|
-
app[routeName](path || name, wrappedHandler);
|
|
82
|
-
} else {
|
|
83
|
-
throw new Error(`Unknown HTTP Method: ${method}`);
|
|
84
|
-
}
|
|
18
|
+
const routeHandler = (0, _utils.createRouteHandler)(handler);
|
|
19
|
+
const method = httpMethod.toLowerCase();
|
|
20
|
+
app[method](routePath, routeHandler);
|
|
85
21
|
});
|
|
86
22
|
};
|
|
87
23
|
|
|
88
|
-
const isNormalMethod = method => Object.keys(_bffUtils.HttpMethod).includes(method);
|
|
89
|
-
|
|
90
24
|
var _default = registerRoutes;
|
|
91
|
-
exports.default = _default;
|
|
92
|
-
|
|
93
|
-
const getInputFromRequest = async request => {
|
|
94
|
-
const draft = {
|
|
95
|
-
params: request.params,
|
|
96
|
-
query: request.query,
|
|
97
|
-
headers: request.headers,
|
|
98
|
-
cookies: request.headers.cookie
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
if ((0, _typeIs.default)(request, ['application/json'])) {
|
|
102
|
-
draft.data = request.body;
|
|
103
|
-
} else if ((0, _typeIs.default)(request, ['multipart/form-data'])) {
|
|
104
|
-
draft.formData = await resolveFormData(request);
|
|
105
|
-
} else if ((0, _typeIs.default)(request, ['application/x-www-form-urlencoded'])) {
|
|
106
|
-
draft.formUrlencoded = request.body;
|
|
107
|
-
} else {
|
|
108
|
-
draft.body = request.body;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return draft;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const resolveFormData = request => {
|
|
115
|
-
const form = (0, _formidable.default)({
|
|
116
|
-
multiples: true
|
|
117
|
-
});
|
|
118
|
-
return new Promise((resolve, reject) => {
|
|
119
|
-
form.parse(request, (err, fields, files) => {
|
|
120
|
-
if (err) {
|
|
121
|
-
reject(err);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
resolve(_objectSpread(_objectSpread({}, fields), files));
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
};
|
|
25
|
+
exports.default = _default;
|
package/dist/js/node/runtime.js
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
var _exportNames = {
|
|
7
|
+
useContext: true
|
|
8
|
+
};
|
|
6
9
|
Object.defineProperty(exports, "useContext", {
|
|
7
10
|
enumerable: true,
|
|
8
11
|
get: function () {
|
|
@@ -10,4 +13,18 @@ Object.defineProperty(exports, "useContext", {
|
|
|
10
13
|
}
|
|
11
14
|
});
|
|
12
15
|
|
|
13
|
-
var _context = require("./context");
|
|
16
|
+
var _context = require("./context");
|
|
17
|
+
|
|
18
|
+
var _bffCore = require("@modern-js/bff-core");
|
|
19
|
+
|
|
20
|
+
Object.keys(_bffCore).forEach(function (key) {
|
|
21
|
+
if (key === "default" || key === "__esModule") return;
|
|
22
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
23
|
+
if (key in exports && exports[key] === _bffCore[key]) return;
|
|
24
|
+
Object.defineProperty(exports, key, {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _bffCore[key];
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.isNormalMethod = exports.createRouteHandler = void 0;
|
|
7
|
+
|
|
8
|
+
require("reflect-metadata");
|
|
9
|
+
|
|
10
|
+
var _bffCore = require("@modern-js/bff-core");
|
|
11
|
+
|
|
12
|
+
var _bffRuntime = require("@modern-js/bff-runtime");
|
|
13
|
+
|
|
14
|
+
var _typeIs = _interopRequireDefault(require("type-is"));
|
|
15
|
+
|
|
16
|
+
var _formidable = _interopRequireDefault(require("formidable"));
|
|
17
|
+
|
|
18
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
|
+
|
|
20
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
21
|
+
|
|
22
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
23
|
+
|
|
24
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
25
|
+
|
|
26
|
+
const handleResponseMeta = (res, handler) => {
|
|
27
|
+
const responseMeta = Reflect.getMetadata(_bffCore.HttpMetadata.Response, handler);
|
|
28
|
+
|
|
29
|
+
if (Array.isArray(responseMeta)) {
|
|
30
|
+
for (const meta of responseMeta) {
|
|
31
|
+
const metaType = meta.type;
|
|
32
|
+
const metaValue = meta.value;
|
|
33
|
+
|
|
34
|
+
switch (metaType) {
|
|
35
|
+
case _bffCore.ResponseMetaType.Headers:
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
37
|
+
for (const [key, value] of Object.entries(metaValue)) {
|
|
38
|
+
res.append(key, value);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
break;
|
|
42
|
+
|
|
43
|
+
case _bffCore.ResponseMetaType.Redirect:
|
|
44
|
+
res.redirect(metaValue);
|
|
45
|
+
break;
|
|
46
|
+
|
|
47
|
+
case _bffCore.ResponseMetaType.StatusCode:
|
|
48
|
+
res.status(metaValue);
|
|
49
|
+
break;
|
|
50
|
+
|
|
51
|
+
default:
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const createRouteHandler = handler => {
|
|
59
|
+
const apiHandler = async (req, res, next) => {
|
|
60
|
+
const input = await getInputFromRequest(req);
|
|
61
|
+
|
|
62
|
+
if ((0, _bffCore.isWithMetaHandler)(handler)) {
|
|
63
|
+
try {
|
|
64
|
+
handleResponseMeta(res, handler);
|
|
65
|
+
const result = await handler(input);
|
|
66
|
+
return res.json(result);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
if (error instanceof Error) {
|
|
69
|
+
if (error.status) {
|
|
70
|
+
res.status(error.status);
|
|
71
|
+
} else {
|
|
72
|
+
res.status(500);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return res.json({
|
|
76
|
+
code: error.code,
|
|
77
|
+
message: error.message
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
} else if ((0, _bffRuntime.isSchemaHandler)(handler)) {
|
|
82
|
+
const result = await handler(input);
|
|
83
|
+
|
|
84
|
+
if (result.type !== 'HandleSuccess') {
|
|
85
|
+
if (result.type === 'InputValidationError') {
|
|
86
|
+
res.status(400);
|
|
87
|
+
} else {
|
|
88
|
+
res.status(500);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return res.json(result.message);
|
|
92
|
+
} else {
|
|
93
|
+
res.status(200);
|
|
94
|
+
return res.json(result.value);
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
const args = Object.values(input.params).concat(input);
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
const body = await handler(...args); // this should never happen
|
|
101
|
+
|
|
102
|
+
if (res.headersSent) {
|
|
103
|
+
return await Promise.resolve();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return res.json(body);
|
|
107
|
+
} catch (e) {
|
|
108
|
+
return next(e);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
Object.defineProperties(apiHandler, Object.getOwnPropertyDescriptors(handler));
|
|
114
|
+
return apiHandler;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
exports.createRouteHandler = createRouteHandler;
|
|
118
|
+
|
|
119
|
+
const isNormalMethod = httpMethod => _bffCore.httpMethods.includes(httpMethod);
|
|
120
|
+
|
|
121
|
+
exports.isNormalMethod = isNormalMethod;
|
|
122
|
+
|
|
123
|
+
const getInputFromRequest = async request => {
|
|
124
|
+
const draft = {
|
|
125
|
+
params: request.params,
|
|
126
|
+
query: request.query,
|
|
127
|
+
headers: request.headers,
|
|
128
|
+
cookies: request.headers.cookie
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
if ((0, _typeIs.default)(request, ['application/json'])) {
|
|
132
|
+
draft.data = request.body;
|
|
133
|
+
} else if ((0, _typeIs.default)(request, ['multipart/form-data'])) {
|
|
134
|
+
draft.formData = await resolveFormData(request);
|
|
135
|
+
} else if ((0, _typeIs.default)(request, ['application/x-www-form-urlencoded'])) {
|
|
136
|
+
draft.formUrlencoded = request.body;
|
|
137
|
+
} else {
|
|
138
|
+
draft.body = request.body;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return draft;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const resolveFormData = request => {
|
|
145
|
+
const form = (0, _formidable.default)({
|
|
146
|
+
multiples: true
|
|
147
|
+
});
|
|
148
|
+
return new Promise((resolve, reject) => {
|
|
149
|
+
form.parse(request, (err, fields, files) => {
|
|
150
|
+
if (err) {
|
|
151
|
+
reject(err);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
resolve(_objectSpread(_objectSpread({}, fields), files));
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
};
|
package/dist/types/plugin.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import type { APIHandlerInfo } from '@modern-js/bff-core';
|
|
3
|
+
import type { Express } from 'express';
|
|
4
|
+
declare const registerRoutes: (app: Express, handlerInfos: APIHandlerInfo[]) => void;
|
|
3
5
|
export default registerRoutes;
|
package/dist/types/runtime.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { useContext } from './context';
|
|
1
|
+
export { useContext } from './context';
|
|
2
|
+
export * from '@modern-js/bff-core';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { HttpMethod } from '@modern-js/bff-core';
|
|
3
|
+
import type { APIHandlerInfo } from '@modern-js/bff-core';
|
|
4
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
5
|
+
declare type Handler = APIHandlerInfo['handler'];
|
|
6
|
+
export declare const createRouteHandler: (handler: Handler) => (req: Request, res: Response, next: NextFunction) => Promise<void | Response<any, Record<string, any>>>;
|
|
7
|
+
export declare const isNormalMethod: (httpMethod: HttpMethod) => httpMethod is HttpMethod;
|
|
8
|
+
export {};
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"modern",
|
|
12
12
|
"modern.js"
|
|
13
13
|
],
|
|
14
|
-
"version": "1.
|
|
14
|
+
"version": "1.6.1-beta.0",
|
|
15
15
|
"jsnext:source": "./src/index.ts",
|
|
16
16
|
"types": "./dist/types/index.d.ts",
|
|
17
17
|
"main": "./dist/js/node/index.js",
|
|
@@ -34,20 +34,21 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@babel/runtime": "^7.18.0",
|
|
37
|
-
"@modern-js/adapter-helpers": "^1.
|
|
38
|
-
"@modern-js/bff-
|
|
39
|
-
"@modern-js/bff-
|
|
40
|
-
"@modern-js/types": "^1.5.
|
|
41
|
-
"@modern-js/utils": "^1.7.
|
|
37
|
+
"@modern-js/adapter-helpers": "^1.3.0",
|
|
38
|
+
"@modern-js/bff-core": "^1.1.0",
|
|
39
|
+
"@modern-js/bff-runtime": "^1.3.0",
|
|
40
|
+
"@modern-js/types": "^1.5.5",
|
|
41
|
+
"@modern-js/utils": "^1.7.11",
|
|
42
42
|
"cookie-parser": "^1.4.5",
|
|
43
43
|
"finalhandler": "^1.1.2",
|
|
44
44
|
"formidable": "^1.2.2",
|
|
45
|
+
"reflect-metadata": "^0.1.13",
|
|
45
46
|
"type-is": "^1.6.18"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
|
-
"@modern-js/core": "1.
|
|
49
|
-
"@modern-js/server-core": "1.
|
|
50
|
-
"@modern-js/server-utils": "1.2.
|
|
49
|
+
"@modern-js/core": "1.12.4",
|
|
50
|
+
"@modern-js/server-core": "1.4.0",
|
|
51
|
+
"@modern-js/server-utils": "1.2.11",
|
|
51
52
|
"@scripts/build": "0.0.0",
|
|
52
53
|
"@scripts/jest-config": "0.0.0",
|
|
53
54
|
"@types/cookie-parser": "^1.4.2",
|
|
@@ -61,7 +62,8 @@
|
|
|
61
62
|
"express": "^4.17.1",
|
|
62
63
|
"jest": "^27",
|
|
63
64
|
"supertest": "^6.1.6",
|
|
64
|
-
"typescript": "^4"
|
|
65
|
+
"typescript": "^4",
|
|
66
|
+
"zod": "^3.17.3"
|
|
65
67
|
},
|
|
66
68
|
"modernConfig": {
|
|
67
69
|
"output": {
|
|
@@ -73,7 +75,8 @@
|
|
|
73
75
|
},
|
|
74
76
|
"publishConfig": {
|
|
75
77
|
"registry": "https://registry.npmjs.org/",
|
|
76
|
-
"access": "public"
|
|
78
|
+
"access": "public",
|
|
79
|
+
"types": "./dist/types/index.d.ts"
|
|
77
80
|
},
|
|
78
81
|
"wireit": {
|
|
79
82
|
"build": {
|