@modern-js/plugin-koa 1.4.8 → 1.5.0-alpha.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 +39 -0
- package/dist/js/modern/cli/index.js +17 -8
- package/dist/js/modern/plugin.js +9 -14
- package/dist/js/modern/registerRoutes.js +8 -75
- package/dist/js/modern/runtime.js +2 -1
- package/dist/js/modern/utils.js +116 -0
- package/dist/js/node/cli/index.js +17 -8
- package/dist/js/node/plugin.js +8 -14
- package/dist/js/node/registerRoutes.js +8 -82
- package/dist/js/node/runtime.js +18 -1
- package/dist/js/node/utils.js +132 -0
- package/dist/types/plugin.d.ts +0 -1
- package/dist/types/registerRoutes.d.ts +2 -1
- package/dist/types/runtime.d.ts +2 -1
- package/dist/types/utils.d.ts +9 -0
- package/package.json +13 -11
- package/types.d.ts +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# @modern-js/plugin-koa
|
|
2
2
|
|
|
3
|
+
## 1.5.0-alpha.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 77a8e9e1b: feat: support bff operators
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [77a8e9e1b]
|
|
12
|
+
- Updated dependencies [9cd364e06]
|
|
13
|
+
- Updated dependencies [7b9e302e2]
|
|
14
|
+
- Updated dependencies [a90bc96bd]
|
|
15
|
+
- @modern-js/adapter-helpers@1.3.0-alpha.0
|
|
16
|
+
- @modern-js/bff-core@1.1.0-alpha.0
|
|
17
|
+
- @modern-js/bff-runtime@1.3.0-alpha.0
|
|
18
|
+
- @modern-js/utils@1.7.9-alpha.0
|
|
19
|
+
|
|
20
|
+
## 1.4.10
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- a1198d509: feat: bump babel 7.18.0
|
|
25
|
+
- Updated dependencies [a1198d509]
|
|
26
|
+
- @modern-js/adapter-helpers@1.2.6
|
|
27
|
+
- @modern-js/bff-runtime@1.2.4
|
|
28
|
+
- @modern-js/bff-utils@1.2.9
|
|
29
|
+
|
|
30
|
+
## 1.4.9
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- bfccb4c8: fix: bff runtime path not found in development
|
|
35
|
+
- Updated dependencies [d57e7622]
|
|
36
|
+
- Updated dependencies [6451a098]
|
|
37
|
+
- Updated dependencies [d5a2cfd8]
|
|
38
|
+
- Updated dependencies [437367c6]
|
|
39
|
+
- @modern-js/bff-utils@1.2.8
|
|
40
|
+
- @modern-js/utils@1.7.6
|
|
41
|
+
|
|
3
42
|
## 1.4.8
|
|
4
43
|
|
|
5
44
|
### Patch Changes
|
|
@@ -11,7 +11,6 @@ export default (() => ({
|
|
|
11
11
|
const runtimeModulePath = path.resolve(__dirname, '../runtime');
|
|
12
12
|
return {
|
|
13
13
|
config() {
|
|
14
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
15
14
|
const appContext = useAppContext();
|
|
16
15
|
const {
|
|
17
16
|
appDirectory
|
|
@@ -19,17 +18,27 @@ export default (() => ({
|
|
|
19
18
|
bffExportsUtils = createRuntimeExportsUtils(appContext.internalDirectory, 'server');
|
|
20
19
|
const serverRuntimePath = bffExportsUtils.getPath();
|
|
21
20
|
const relativeRuntimePath = getRelativeRuntimePath(appDirectory, serverRuntimePath);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
|
|
22
|
+
if (process.env.NODE_ENV === 'production') {
|
|
23
|
+
return {
|
|
24
|
+
source: {
|
|
25
|
+
alias: {
|
|
26
|
+
'@modern-js/runtime/server': relativeRuntimePath
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
} else {
|
|
31
|
+
return {
|
|
32
|
+
source: {
|
|
33
|
+
alias: {
|
|
34
|
+
'@modern-js/runtime/server': serverRuntimePath
|
|
35
|
+
}
|
|
26
36
|
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
29
39
|
},
|
|
30
40
|
|
|
31
41
|
addRuntimeExports(input) {
|
|
32
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
33
42
|
const {
|
|
34
43
|
appDirectory
|
|
35
44
|
} = useAppContext();
|
package/dist/js/modern/plugin.js
CHANGED
|
@@ -2,8 +2,7 @@ import * as path from 'path';
|
|
|
2
2
|
import Koa from 'koa';
|
|
3
3
|
import Router from 'koa-router';
|
|
4
4
|
import koaBody from 'koa-body';
|
|
5
|
-
import {
|
|
6
|
-
import { fs } from '@modern-js/utils';
|
|
5
|
+
import { fs, compatRequire } from '@modern-js/utils';
|
|
7
6
|
import { run } from "./context";
|
|
8
7
|
import registerRoutes from "./registerRoutes";
|
|
9
8
|
|
|
@@ -13,7 +12,7 @@ const findAppModule = async apiDir => {
|
|
|
13
12
|
|
|
14
13
|
for (const filename of paths) {
|
|
15
14
|
if (await fs.pathExists(filename)) {
|
|
16
|
-
return
|
|
15
|
+
return compatRequire(filename);
|
|
17
16
|
}
|
|
18
17
|
}
|
|
19
18
|
|
|
@@ -22,7 +21,7 @@ const findAppModule = async apiDir => {
|
|
|
22
21
|
|
|
23
22
|
const initMiddlewares = (middleware, app) => {
|
|
24
23
|
middleware.forEach(middlewareItem => {
|
|
25
|
-
const middlewareFunc = typeof middlewareItem === 'string' ?
|
|
24
|
+
const middlewareFunc = typeof middlewareItem === 'string' ? compatRequire(middlewareItem) : middlewareItem;
|
|
26
25
|
app.use(middlewareFunc);
|
|
27
26
|
});
|
|
28
27
|
};
|
|
@@ -30,16 +29,17 @@ const initMiddlewares = (middleware, app) => {
|
|
|
30
29
|
export default (() => ({
|
|
31
30
|
name: '@modern-js/plugin-koa',
|
|
32
31
|
pre: ['@modern-js/plugin-bff'],
|
|
33
|
-
setup:
|
|
32
|
+
setup: api => ({
|
|
34
33
|
async prepareApiServer({
|
|
35
34
|
pwd,
|
|
36
35
|
mode,
|
|
37
|
-
config
|
|
38
|
-
prefix
|
|
36
|
+
config
|
|
39
37
|
}) {
|
|
40
38
|
let app;
|
|
41
39
|
const router = new Router();
|
|
42
40
|
const apiDir = path.join(pwd, './api');
|
|
41
|
+
const appContext = api.useAppContext();
|
|
42
|
+
const apiHandlerInfos = appContext.apiHandlerInfos;
|
|
43
43
|
|
|
44
44
|
if (mode === 'framework') {
|
|
45
45
|
app = await findAppModule(apiDir);
|
|
@@ -59,7 +59,7 @@ export default (() => ({
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
app.use(run);
|
|
62
|
-
registerRoutes(router,
|
|
62
|
+
registerRoutes(router, apiHandlerInfos);
|
|
63
63
|
} else if (mode === 'function') {
|
|
64
64
|
app = new Koa();
|
|
65
65
|
app.use(koaBody({
|
|
@@ -74,18 +74,13 @@ export default (() => ({
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
app.use(run);
|
|
77
|
-
registerRoutes(router,
|
|
77
|
+
registerRoutes(router, apiHandlerInfos);
|
|
78
78
|
} else {
|
|
79
79
|
throw new Error(`mode must be function or framework`);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
app.use(router.routes());
|
|
83
83
|
return (req, res) => {
|
|
84
|
-
app.on('error', err => {
|
|
85
|
-
if (err) {
|
|
86
|
-
throw err;
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
84
|
return Promise.resolve(app.callback()(req, res));
|
|
90
85
|
};
|
|
91
86
|
},
|
|
@@ -1,82 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isSchemaHandler } from '@modern-js/bff-runtime';
|
|
3
|
-
import typeIs from 'type-is';
|
|
4
|
-
import { sortDynamicRoutes } from '@modern-js/adapter-helpers';
|
|
5
|
-
import { createDebugger } from '@modern-js/utils';
|
|
6
|
-
const debug = createDebugger('koa');
|
|
7
|
-
|
|
8
|
-
const registerRoutes = (router, prefix) => {
|
|
9
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
10
|
-
const handlerInfos = useAPIHandlerInfos();
|
|
11
|
-
sortDynamicRoutes(handlerInfos);
|
|
12
|
-
debug('handlerInfos', handlerInfos);
|
|
13
|
-
|
|
14
|
-
if (prefix) {
|
|
15
|
-
router.prefix(prefix);
|
|
16
|
-
}
|
|
1
|
+
import { createRouteHandler } from "./utils";
|
|
17
2
|
|
|
3
|
+
const registerRoutes = (router, handlerInfos) => {
|
|
18
4
|
handlerInfos.forEach(({
|
|
5
|
+
routePath,
|
|
19
6
|
handler,
|
|
20
|
-
|
|
21
|
-
name
|
|
7
|
+
httpMethod
|
|
22
8
|
}) => {
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (isSchemaHandler(handler)) {
|
|
27
|
-
const result = await handler(input);
|
|
28
|
-
|
|
29
|
-
if (result.type !== 'HandleSuccess') {
|
|
30
|
-
if (result.type === 'InputValidationError') {
|
|
31
|
-
ctx.status = 400;
|
|
32
|
-
} else {
|
|
33
|
-
ctx.status = 500;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
ctx.body = result.message;
|
|
37
|
-
} else {
|
|
38
|
-
ctx.body = result.value;
|
|
39
|
-
}
|
|
40
|
-
} else {
|
|
41
|
-
const args = Object.values(input.params).concat(input); // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
42
|
-
// @ts-expect-error
|
|
43
|
-
|
|
44
|
-
ctx.body = await handler(...args);
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
Object.defineProperties(wrappedHandler, Object.getOwnPropertyDescriptors(handler));
|
|
49
|
-
|
|
50
|
-
if (isNormalMethod(method)) {
|
|
51
|
-
const routeName = method.toLowerCase();
|
|
52
|
-
router[routeName](name, wrappedHandler);
|
|
53
|
-
} else {
|
|
54
|
-
throw new Error(`Unknown HTTP Method: ${method}`);
|
|
55
|
-
}
|
|
9
|
+
const routeHandler = createRouteHandler(handler);
|
|
10
|
+
const method = httpMethod.toLowerCase();
|
|
11
|
+
router[method](routePath, routeHandler);
|
|
56
12
|
});
|
|
57
13
|
};
|
|
58
14
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
export default registerRoutes;
|
|
62
|
-
|
|
63
|
-
const getInputFromRequest = async ctx => {
|
|
64
|
-
const draft = {
|
|
65
|
-
params: ctx.params,
|
|
66
|
-
query: ctx.query,
|
|
67
|
-
headers: ctx.headers,
|
|
68
|
-
cookies: ctx.headers.cookie
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
if (typeIs.is(ctx.request.type, ['application/json'])) {
|
|
72
|
-
draft.data = ctx.request.body;
|
|
73
|
-
} else if (typeIs.is(ctx.request.type, ['multipart/form-data'])) {
|
|
74
|
-
draft.formData = ctx.request.files;
|
|
75
|
-
} else if (typeIs.is(ctx.request.type, ['application/x-www-form-urlencoded'])) {
|
|
76
|
-
draft.formUrlencoded = ctx.request.body;
|
|
77
|
-
} else {
|
|
78
|
-
draft.body = ctx.request.body;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return draft;
|
|
82
|
-
};
|
|
15
|
+
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,116 @@
|
|
|
1
|
+
import { httpMethods, isWithMetaHandler, ResponseMetaType, HttpMetadata } from '@modern-js/bff-core';
|
|
2
|
+
import { isSchemaHandler } from '@modern-js/bff-runtime';
|
|
3
|
+
import typeIs from 'type-is';
|
|
4
|
+
|
|
5
|
+
const handleResponseMeta = (ctx, handler) => {
|
|
6
|
+
const responseMeta = Reflect.getMetadata(HttpMetadata.Response, handler);
|
|
7
|
+
|
|
8
|
+
if (Array.isArray(responseMeta)) {
|
|
9
|
+
for (const meta of responseMeta) {
|
|
10
|
+
const metaType = meta.type;
|
|
11
|
+
const metaValue = meta.value;
|
|
12
|
+
|
|
13
|
+
switch (metaType) {
|
|
14
|
+
case ResponseMetaType.Headers:
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
16
|
+
for (const [key, value] of Object.entries(metaValue)) {
|
|
17
|
+
if (typeof value === 'string') {
|
|
18
|
+
ctx.append(key, value);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
break;
|
|
23
|
+
|
|
24
|
+
case ResponseMetaType.Redirect:
|
|
25
|
+
if (typeof metaValue === 'string') {
|
|
26
|
+
ctx.redirect(metaValue);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
break;
|
|
30
|
+
|
|
31
|
+
case ResponseMetaType.StatusCode:
|
|
32
|
+
if (typeof metaValue === 'number') {
|
|
33
|
+
ctx.status = metaValue;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
break;
|
|
37
|
+
|
|
38
|
+
default:
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const createRouteHandler = handler => {
|
|
46
|
+
// eslint-disable-next-line consistent-return
|
|
47
|
+
const apiHandler = async ctx => {
|
|
48
|
+
const input = await getInputFromRequest(ctx);
|
|
49
|
+
|
|
50
|
+
if (isWithMetaHandler(handler)) {
|
|
51
|
+
try {
|
|
52
|
+
handleResponseMeta(ctx, handler);
|
|
53
|
+
const result = await handler(input);
|
|
54
|
+
|
|
55
|
+
if (result) {
|
|
56
|
+
ctx.body = result;
|
|
57
|
+
}
|
|
58
|
+
} catch (error) {
|
|
59
|
+
if (error instanceof Error) {
|
|
60
|
+
if (error.status) {
|
|
61
|
+
ctx.status = error.status;
|
|
62
|
+
} else {
|
|
63
|
+
ctx.status = 500;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return ctx.body = {
|
|
67
|
+
code: error.code,
|
|
68
|
+
message: error.message
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} else if (isSchemaHandler(handler)) {
|
|
73
|
+
const result = await handler(input);
|
|
74
|
+
|
|
75
|
+
if (result.type !== 'HandleSuccess') {
|
|
76
|
+
if (result.type === 'InputValidationError') {
|
|
77
|
+
ctx.status = 400;
|
|
78
|
+
} else {
|
|
79
|
+
ctx.status = 500;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
ctx.body = result.message;
|
|
83
|
+
} else {
|
|
84
|
+
ctx.body = result.value;
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
const args = Object.values(input.params).concat(input);
|
|
88
|
+
ctx.body = await handler(...args);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
Object.defineProperties(apiHandler, Object.getOwnPropertyDescriptors(handler));
|
|
93
|
+
return apiHandler;
|
|
94
|
+
};
|
|
95
|
+
export const isNormalMethod = httpMethod => httpMethods.includes(httpMethod);
|
|
96
|
+
|
|
97
|
+
const getInputFromRequest = async ctx => {
|
|
98
|
+
const draft = {
|
|
99
|
+
params: ctx.params,
|
|
100
|
+
query: ctx.query,
|
|
101
|
+
headers: ctx.headers,
|
|
102
|
+
cookies: ctx.headers.cookie
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
if (typeIs.is(ctx.request.type, ['application/json'])) {
|
|
106
|
+
draft.data = ctx.request.body;
|
|
107
|
+
} else if (typeIs.is(ctx.request.type, ['multipart/form-data'])) {
|
|
108
|
+
draft.formData = ctx.request.files;
|
|
109
|
+
} else if (typeIs.is(ctx.request.type, ['application/x-www-form-urlencoded'])) {
|
|
110
|
+
draft.formUrlencoded = ctx.request.body;
|
|
111
|
+
} else {
|
|
112
|
+
draft.body = ctx.request.body;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return draft;
|
|
116
|
+
};
|
|
@@ -25,7 +25,6 @@ var _default = () => ({
|
|
|
25
25
|
const runtimeModulePath = path.resolve(__dirname, '../runtime');
|
|
26
26
|
return {
|
|
27
27
|
config() {
|
|
28
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
29
28
|
const appContext = useAppContext();
|
|
30
29
|
const {
|
|
31
30
|
appDirectory
|
|
@@ -33,17 +32,27 @@ var _default = () => ({
|
|
|
33
32
|
bffExportsUtils = (0, _utils.createRuntimeExportsUtils)(appContext.internalDirectory, 'server');
|
|
34
33
|
const serverRuntimePath = bffExportsUtils.getPath();
|
|
35
34
|
const relativeRuntimePath = (0, _adapterHelpers.getRelativeRuntimePath)(appDirectory, serverRuntimePath);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
|
|
36
|
+
if (process.env.NODE_ENV === 'production') {
|
|
37
|
+
return {
|
|
38
|
+
source: {
|
|
39
|
+
alias: {
|
|
40
|
+
'@modern-js/runtime/server': relativeRuntimePath
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
} else {
|
|
45
|
+
return {
|
|
46
|
+
source: {
|
|
47
|
+
alias: {
|
|
48
|
+
'@modern-js/runtime/server': serverRuntimePath
|
|
49
|
+
}
|
|
40
50
|
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
43
53
|
},
|
|
44
54
|
|
|
45
55
|
addRuntimeExports(input) {
|
|
46
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
47
56
|
const {
|
|
48
57
|
appDirectory
|
|
49
58
|
} = useAppContext();
|
package/dist/js/node/plugin.js
CHANGED
|
@@ -13,8 +13,6 @@ var _koaRouter = _interopRequireDefault(require("koa-router"));
|
|
|
13
13
|
|
|
14
14
|
var _koaBody = _interopRequireDefault(require("koa-body"));
|
|
15
15
|
|
|
16
|
-
var _bffUtils = require("@modern-js/bff-utils");
|
|
17
|
-
|
|
18
16
|
var _utils = require("@modern-js/utils");
|
|
19
17
|
|
|
20
18
|
var _context = require("./context");
|
|
@@ -33,7 +31,7 @@ const findAppModule = async apiDir => {
|
|
|
33
31
|
|
|
34
32
|
for (const filename of paths) {
|
|
35
33
|
if (await _utils.fs.pathExists(filename)) {
|
|
36
|
-
return (0,
|
|
34
|
+
return (0, _utils.compatRequire)(filename);
|
|
37
35
|
}
|
|
38
36
|
}
|
|
39
37
|
|
|
@@ -42,7 +40,7 @@ const findAppModule = async apiDir => {
|
|
|
42
40
|
|
|
43
41
|
const initMiddlewares = (middleware, app) => {
|
|
44
42
|
middleware.forEach(middlewareItem => {
|
|
45
|
-
const middlewareFunc = typeof middlewareItem === 'string' ? (0,
|
|
43
|
+
const middlewareFunc = typeof middlewareItem === 'string' ? (0, _utils.compatRequire)(middlewareItem) : middlewareItem;
|
|
46
44
|
app.use(middlewareFunc);
|
|
47
45
|
});
|
|
48
46
|
};
|
|
@@ -50,16 +48,17 @@ const initMiddlewares = (middleware, app) => {
|
|
|
50
48
|
var _default = () => ({
|
|
51
49
|
name: '@modern-js/plugin-koa',
|
|
52
50
|
pre: ['@modern-js/plugin-bff'],
|
|
53
|
-
setup:
|
|
51
|
+
setup: api => ({
|
|
54
52
|
async prepareApiServer({
|
|
55
53
|
pwd,
|
|
56
54
|
mode,
|
|
57
|
-
config
|
|
58
|
-
prefix
|
|
55
|
+
config
|
|
59
56
|
}) {
|
|
60
57
|
let app;
|
|
61
58
|
const router = new _koaRouter.default();
|
|
62
59
|
const apiDir = path.join(pwd, './api');
|
|
60
|
+
const appContext = api.useAppContext();
|
|
61
|
+
const apiHandlerInfos = appContext.apiHandlerInfos;
|
|
63
62
|
|
|
64
63
|
if (mode === 'framework') {
|
|
65
64
|
app = await findAppModule(apiDir);
|
|
@@ -79,7 +78,7 @@ var _default = () => ({
|
|
|
79
78
|
}
|
|
80
79
|
|
|
81
80
|
app.use(_context.run);
|
|
82
|
-
(0, _registerRoutes.default)(router,
|
|
81
|
+
(0, _registerRoutes.default)(router, apiHandlerInfos);
|
|
83
82
|
} else if (mode === 'function') {
|
|
84
83
|
app = new _koa.default();
|
|
85
84
|
app.use((0, _koaBody.default)({
|
|
@@ -94,18 +93,13 @@ var _default = () => ({
|
|
|
94
93
|
}
|
|
95
94
|
|
|
96
95
|
app.use(_context.run);
|
|
97
|
-
(0, _registerRoutes.default)(router,
|
|
96
|
+
(0, _registerRoutes.default)(router, apiHandlerInfos);
|
|
98
97
|
} else {
|
|
99
98
|
throw new Error(`mode must be function or framework`);
|
|
100
99
|
}
|
|
101
100
|
|
|
102
101
|
app.use(router.routes());
|
|
103
102
|
return (req, res) => {
|
|
104
|
-
app.on('error', err => {
|
|
105
|
-
if (err) {
|
|
106
|
-
throw err;
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
103
|
return Promise.resolve(app.callback()(req, res));
|
|
110
104
|
};
|
|
111
105
|
},
|
|
@@ -5,93 +5,19 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
var _bffRuntime = require("@modern-js/bff-runtime");
|
|
11
|
-
|
|
12
|
-
var _typeIs = _interopRequireDefault(require("type-is"));
|
|
13
|
-
|
|
14
|
-
var _adapterHelpers = require("@modern-js/adapter-helpers");
|
|
15
|
-
|
|
16
|
-
var _utils = require("@modern-js/utils");
|
|
17
|
-
|
|
18
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
|
-
|
|
20
|
-
const debug = (0, _utils.createDebugger)('koa');
|
|
21
|
-
|
|
22
|
-
const registerRoutes = (router, prefix) => {
|
|
23
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
24
|
-
const handlerInfos = (0, _bffUtils.useAPIHandlerInfos)();
|
|
25
|
-
(0, _adapterHelpers.sortDynamicRoutes)(handlerInfos);
|
|
26
|
-
debug('handlerInfos', handlerInfos);
|
|
27
|
-
|
|
28
|
-
if (prefix) {
|
|
29
|
-
router.prefix(prefix);
|
|
30
|
-
}
|
|
8
|
+
var _utils = require("./utils");
|
|
31
9
|
|
|
10
|
+
const registerRoutes = (router, handlerInfos) => {
|
|
32
11
|
handlerInfos.forEach(({
|
|
12
|
+
routePath,
|
|
33
13
|
handler,
|
|
34
|
-
|
|
35
|
-
name
|
|
14
|
+
httpMethod
|
|
36
15
|
}) => {
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if ((0, _bffRuntime.isSchemaHandler)(handler)) {
|
|
41
|
-
const result = await handler(input);
|
|
42
|
-
|
|
43
|
-
if (result.type !== 'HandleSuccess') {
|
|
44
|
-
if (result.type === 'InputValidationError') {
|
|
45
|
-
ctx.status = 400;
|
|
46
|
-
} else {
|
|
47
|
-
ctx.status = 500;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
ctx.body = result.message;
|
|
51
|
-
} else {
|
|
52
|
-
ctx.body = result.value;
|
|
53
|
-
}
|
|
54
|
-
} else {
|
|
55
|
-
const args = Object.values(input.params).concat(input); // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
56
|
-
// @ts-expect-error
|
|
57
|
-
|
|
58
|
-
ctx.body = await handler(...args);
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
Object.defineProperties(wrappedHandler, Object.getOwnPropertyDescriptors(handler));
|
|
63
|
-
|
|
64
|
-
if (isNormalMethod(method)) {
|
|
65
|
-
const routeName = method.toLowerCase();
|
|
66
|
-
router[routeName](name, wrappedHandler);
|
|
67
|
-
} else {
|
|
68
|
-
throw new Error(`Unknown HTTP Method: ${method}`);
|
|
69
|
-
}
|
|
16
|
+
const routeHandler = (0, _utils.createRouteHandler)(handler);
|
|
17
|
+
const method = httpMethod.toLowerCase();
|
|
18
|
+
router[method](routePath, routeHandler);
|
|
70
19
|
});
|
|
71
20
|
};
|
|
72
21
|
|
|
73
|
-
const isNormalMethod = method => Object.keys(_bffUtils.HttpMethod).includes(method);
|
|
74
|
-
|
|
75
22
|
var _default = registerRoutes;
|
|
76
|
-
exports.default = _default;
|
|
77
|
-
|
|
78
|
-
const getInputFromRequest = async ctx => {
|
|
79
|
-
const draft = {
|
|
80
|
-
params: ctx.params,
|
|
81
|
-
query: ctx.query,
|
|
82
|
-
headers: ctx.headers,
|
|
83
|
-
cookies: ctx.headers.cookie
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
if (_typeIs.default.is(ctx.request.type, ['application/json'])) {
|
|
87
|
-
draft.data = ctx.request.body;
|
|
88
|
-
} else if (_typeIs.default.is(ctx.request.type, ['multipart/form-data'])) {
|
|
89
|
-
draft.formData = ctx.request.files;
|
|
90
|
-
} else if (_typeIs.default.is(ctx.request.type, ['application/x-www-form-urlencoded'])) {
|
|
91
|
-
draft.formUrlencoded = ctx.request.body;
|
|
92
|
-
} else {
|
|
93
|
-
draft.body = ctx.request.body;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return draft;
|
|
97
|
-
};
|
|
23
|
+
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,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.isNormalMethod = exports.createRouteHandler = void 0;
|
|
7
|
+
|
|
8
|
+
var _bffCore = require("@modern-js/bff-core");
|
|
9
|
+
|
|
10
|
+
var _bffRuntime = require("@modern-js/bff-runtime");
|
|
11
|
+
|
|
12
|
+
var _typeIs = _interopRequireDefault(require("type-is"));
|
|
13
|
+
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
|
|
16
|
+
const handleResponseMeta = (ctx, handler) => {
|
|
17
|
+
const responseMeta = Reflect.getMetadata(_bffCore.HttpMetadata.Response, handler);
|
|
18
|
+
|
|
19
|
+
if (Array.isArray(responseMeta)) {
|
|
20
|
+
for (const meta of responseMeta) {
|
|
21
|
+
const metaType = meta.type;
|
|
22
|
+
const metaValue = meta.value;
|
|
23
|
+
|
|
24
|
+
switch (metaType) {
|
|
25
|
+
case _bffCore.ResponseMetaType.Headers:
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
27
|
+
for (const [key, value] of Object.entries(metaValue)) {
|
|
28
|
+
if (typeof value === 'string') {
|
|
29
|
+
ctx.append(key, value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
break;
|
|
34
|
+
|
|
35
|
+
case _bffCore.ResponseMetaType.Redirect:
|
|
36
|
+
if (typeof metaValue === 'string') {
|
|
37
|
+
ctx.redirect(metaValue);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
break;
|
|
41
|
+
|
|
42
|
+
case _bffCore.ResponseMetaType.StatusCode:
|
|
43
|
+
if (typeof metaValue === 'number') {
|
|
44
|
+
ctx.status = metaValue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
break;
|
|
48
|
+
|
|
49
|
+
default:
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const createRouteHandler = handler => {
|
|
57
|
+
// eslint-disable-next-line consistent-return
|
|
58
|
+
const apiHandler = async ctx => {
|
|
59
|
+
const input = await getInputFromRequest(ctx);
|
|
60
|
+
|
|
61
|
+
if ((0, _bffCore.isWithMetaHandler)(handler)) {
|
|
62
|
+
try {
|
|
63
|
+
handleResponseMeta(ctx, handler);
|
|
64
|
+
const result = await handler(input);
|
|
65
|
+
|
|
66
|
+
if (result) {
|
|
67
|
+
ctx.body = result;
|
|
68
|
+
}
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (error instanceof Error) {
|
|
71
|
+
if (error.status) {
|
|
72
|
+
ctx.status = error.status;
|
|
73
|
+
} else {
|
|
74
|
+
ctx.status = 500;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return ctx.body = {
|
|
78
|
+
code: error.code,
|
|
79
|
+
message: error.message
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
} else if ((0, _bffRuntime.isSchemaHandler)(handler)) {
|
|
84
|
+
const result = await handler(input);
|
|
85
|
+
|
|
86
|
+
if (result.type !== 'HandleSuccess') {
|
|
87
|
+
if (result.type === 'InputValidationError') {
|
|
88
|
+
ctx.status = 400;
|
|
89
|
+
} else {
|
|
90
|
+
ctx.status = 500;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
ctx.body = result.message;
|
|
94
|
+
} else {
|
|
95
|
+
ctx.body = result.value;
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
const args = Object.values(input.params).concat(input);
|
|
99
|
+
ctx.body = await handler(...args);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
Object.defineProperties(apiHandler, Object.getOwnPropertyDescriptors(handler));
|
|
104
|
+
return apiHandler;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
exports.createRouteHandler = createRouteHandler;
|
|
108
|
+
|
|
109
|
+
const isNormalMethod = httpMethod => _bffCore.httpMethods.includes(httpMethod);
|
|
110
|
+
|
|
111
|
+
exports.isNormalMethod = isNormalMethod;
|
|
112
|
+
|
|
113
|
+
const getInputFromRequest = async ctx => {
|
|
114
|
+
const draft = {
|
|
115
|
+
params: ctx.params,
|
|
116
|
+
query: ctx.query,
|
|
117
|
+
headers: ctx.headers,
|
|
118
|
+
cookies: ctx.headers.cookie
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
if (_typeIs.default.is(ctx.request.type, ['application/json'])) {
|
|
122
|
+
draft.data = ctx.request.body;
|
|
123
|
+
} else if (_typeIs.default.is(ctx.request.type, ['multipart/form-data'])) {
|
|
124
|
+
draft.formData = ctx.request.files;
|
|
125
|
+
} else if (_typeIs.default.is(ctx.request.type, ['application/x-www-form-urlencoded'])) {
|
|
126
|
+
draft.formUrlencoded = ctx.request.body;
|
|
127
|
+
} else {
|
|
128
|
+
draft.body = ctx.request.body;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return draft;
|
|
132
|
+
};
|
package/dist/types/plugin.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { APIHandlerInfo } from '@modern-js/bff-core';
|
|
1
2
|
import Router from 'koa-router';
|
|
2
|
-
declare const registerRoutes: (router: Router,
|
|
3
|
+
declare const registerRoutes: (router: Router, handlerInfos: APIHandlerInfo[]) => void;
|
|
3
4
|
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,9 @@
|
|
|
1
|
+
import { HttpMethod, APIHandlerInfo } from '@modern-js/bff-core';
|
|
2
|
+
import { Context } from 'koa';
|
|
3
|
+
declare type Handler = APIHandlerInfo['handler'];
|
|
4
|
+
export declare const createRouteHandler: (handler: Handler) => (ctx: Context) => Promise<{
|
|
5
|
+
code: any;
|
|
6
|
+
message: string;
|
|
7
|
+
} | undefined>;
|
|
8
|
+
export declare const isNormalMethod: (httpMethod: HttpMethod) => httpMethod is HttpMethod;
|
|
9
|
+
export {};
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"modern",
|
|
12
12
|
"modern.js"
|
|
13
13
|
],
|
|
14
|
-
"version": "1.
|
|
14
|
+
"version": "1.5.0-alpha.0",
|
|
15
15
|
"jsnext:source": "./src/index.ts",
|
|
16
16
|
"types": "./dist/types/index.d.ts",
|
|
17
17
|
"main": "./dist/js/node/index.js",
|
|
@@ -33,16 +33,18 @@
|
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@babel/runtime": "^7.
|
|
37
|
-
"@modern-js/adapter-helpers": "^1.
|
|
38
|
-
"@modern-js/bff-
|
|
39
|
-
"@modern-js/bff-
|
|
40
|
-
"@modern-js/utils": "^1.7.
|
|
36
|
+
"@babel/runtime": "^7.18.0",
|
|
37
|
+
"@modern-js/adapter-helpers": "^1.3.0-alpha.0",
|
|
38
|
+
"@modern-js/bff-core": "^1.1.0-alpha.0",
|
|
39
|
+
"@modern-js/bff-runtime": "^1.3.0-alpha.0",
|
|
40
|
+
"@modern-js/utils": "^1.7.9-alpha.0",
|
|
41
41
|
"koa-body": "^4.2.0",
|
|
42
42
|
"koa-router": "^10.0.0",
|
|
43
43
|
"type-is": "^1.6.18"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
+
"@modern-js/core": "1.12.2-alpha.0",
|
|
47
|
+
"@modern-js/server-core": "1.4.0-alpha.0",
|
|
46
48
|
"@scripts/build": "0.0.0",
|
|
47
49
|
"@scripts/jest-config": "0.0.0",
|
|
48
50
|
"@types/jest": "^27",
|
|
@@ -52,11 +54,10 @@
|
|
|
52
54
|
"@types/supertest": "^2.0.11",
|
|
53
55
|
"@types/type-is": "^1.6.3",
|
|
54
56
|
"jest": "^27",
|
|
55
|
-
"@modern-js/server-core": "1.3.5",
|
|
56
|
-
"@modern-js/core": "1.10.2",
|
|
57
|
-
"supertest": "^6.1.6",
|
|
58
57
|
"koa": "^2.13.3",
|
|
59
|
-
"
|
|
58
|
+
"supertest": "^6.1.6",
|
|
59
|
+
"typescript": "^4",
|
|
60
|
+
"zod": "^3.17.3"
|
|
60
61
|
},
|
|
61
62
|
"modernConfig": {
|
|
62
63
|
"output": {
|
|
@@ -87,7 +88,8 @@
|
|
|
87
88
|
"files": [
|
|
88
89
|
"src/**/*",
|
|
89
90
|
"tsconfig.json",
|
|
90
|
-
"package.json"
|
|
91
|
+
"package.json",
|
|
92
|
+
"tests/**/*"
|
|
91
93
|
],
|
|
92
94
|
"output": []
|
|
93
95
|
}
|