@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 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
- return {
23
- source: {
24
- alias: {
25
- '@modern-js/runtime/server': relativeRuntimePath
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();
@@ -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 { requireModule } from '@modern-js/bff-utils';
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 requireModule(filename);
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' ? requireModule(middlewareItem) : middlewareItem;
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, prefix);
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, prefix);
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 { HttpMethod, useAPIHandlerInfos } from '@modern-js/bff-utils';
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
- method,
21
- name
7
+ httpMethod
22
8
  }) => {
23
- const wrappedHandler = async ctx => {
24
- const input = await getInputFromRequest(ctx);
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
- const isNormalMethod = method => Object.keys(HttpMethod).includes(method);
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
- return {
37
- source: {
38
- alias: {
39
- '@modern-js/runtime/server': relativeRuntimePath
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();
@@ -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, _bffUtils.requireModule)(filename);
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, _bffUtils.requireModule)(middlewareItem) : middlewareItem;
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, prefix);
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, prefix);
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 _bffUtils = require("@modern-js/bff-utils");
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
- method,
35
- name
14
+ httpMethod
36
15
  }) => {
37
- const wrappedHandler = async ctx => {
38
- const input = await getInputFromRequest(ctx);
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;
@@ -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
+ };
@@ -1,5 +1,4 @@
1
1
  import type { ServerPlugin } from '@modern-js/server-core';
2
- export declare type Mode = 'function' | 'framework';
3
2
 
4
3
  declare const _default: () => ServerPlugin;
5
4
 
@@ -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, prefix?: string | undefined) => void;
3
+ declare const registerRoutes: (router: Router, handlerInfos: APIHandlerInfo[]) => void;
3
4
  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,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.4.8",
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.15.3",
37
- "@modern-js/adapter-helpers": "^1.2.4",
38
- "@modern-js/bff-runtime": "^1.2.3",
39
- "@modern-js/bff-utils": "^1.2.6",
40
- "@modern-js/utils": "^1.7.3",
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
- "typescript": "^4"
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
  }
package/types.d.ts CHANGED
@@ -13,5 +13,7 @@ declare module '@modern-js/runtime/server' {
13
13
 
14
14
  export function hook(attacher: KoaAttacher): KoaAttacher;
15
15
 
16
+ export * from '@modern-js/bff-core';
17
+
16
18
  export * from '@modern-js/bff-runtime';
17
19
  }