@modern-js/plugin-express 1.5.6 → 1.6.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,25 @@
1
1
  # @modern-js/plugin-express
2
2
 
3
+ ## 1.6.0-alpha.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 77a8e9e1b: feat: support bff operators
8
+
9
+ ### Patch Changes
10
+
11
+ - f29e9bacf: feat: simplify context usage, no longer depend on containers
12
+ - Updated dependencies [77a8e9e1b]
13
+ - Updated dependencies [9cd364e06]
14
+ - Updated dependencies [2dacc8929]
15
+ - Updated dependencies [7b9e302e2]
16
+ - Updated dependencies [a90bc96bd]
17
+ - @modern-js/adapter-helpers@1.3.0-alpha.0
18
+ - @modern-js/bff-core@1.1.0-alpha.0
19
+ - @modern-js/bff-runtime@1.3.0-alpha.0
20
+ - @modern-js/utils@1.7.9-alpha.0
21
+ - @modern-js/types@1.5.5-alpha.0
22
+
3
23
  ## 1.5.6
4
24
 
5
25
  ### Patch Changes
@@ -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 { requireModule } from '@modern-js/bff-utils';
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,7 @@ const findAppModule = async apiDir => {
14
13
 
15
14
  for (const filename of paths) {
16
15
  if (await fs.pathExists(filename)) {
17
- return requireModule(filename);
16
+ return compatRequire(filename);
18
17
  }
19
18
  }
20
19
 
@@ -23,7 +22,7 @@ const findAppModule = async apiDir => {
23
22
 
24
23
  const initMiddlewares = (middleware, app) => {
25
24
  middleware.forEach(middlewareItem => {
26
- const middlewareFunc = typeof middlewareItem === 'string' ? requireModule(middlewareItem) : middlewareItem;
25
+ const middlewareFunc = typeof middlewareItem === 'string' ? compatRequire(middlewareItem) : middlewareItem;
27
26
  app.use(middlewareFunc);
28
27
  });
29
28
  };
@@ -50,7 +49,7 @@ const initApp = app => {
50
49
  export default (() => ({
51
50
  name: '@modern-js/plugin-express',
52
51
  pre: ['@modern-js/plugin-bff'],
53
- setup: () => ({
52
+ setup: api => ({
54
53
  async prepareApiServer({
55
54
  pwd,
56
55
  mode,
@@ -58,6 +57,8 @@ export default (() => ({
58
57
  }) {
59
58
  let app;
60
59
  const apiDir = path.join(pwd, './api');
60
+ const appContext = api.useAppContext();
61
+ const apiHandlerInfos = appContext.apiHandlerInfos;
61
62
 
62
63
  if (mode === 'framework') {
63
64
  app = await findAppModule(apiDir);
@@ -77,7 +78,7 @@ export default (() => ({
77
78
  }
78
79
 
79
80
  useRun(app);
80
- registerRoutes(app);
81
+ registerRoutes(app, apiHandlerInfos);
81
82
  } else if (mode === 'function') {
82
83
  app = express();
83
84
  initApp(app);
@@ -90,7 +91,7 @@ export default (() => ({
90
91
  }
91
92
 
92
93
  useRun(app);
93
- registerRoutes(app);
94
+ registerRoutes(app, apiHandlerInfos);
94
95
  } else {
95
96
  throw new Error(`mode must be function or framework`);
96
97
  }
@@ -1,111 +1,16 @@
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; }
1
+ import 'reflect-metadata';
2
+ import { createRouteHandler } from "./utils";
2
3
 
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 { 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
- path,
6
+ routePath,
21
7
  handler,
22
- method,
23
- name
8
+ httpMethod
24
9
  }) => {
25
- const wrappedHandler = async (req, res, next) => {
26
- const input = await getInputFromRequest(req);
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
- const isNormalMethod = method => Object.keys(HttpMethod).includes(method);
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
+ };
@@ -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,7 @@ const findAppModule = async apiDir => {
35
33
 
36
34
  for (const filename of paths) {
37
35
  if (await _utils.fs.pathExists(filename)) {
38
- return (0, _bffUtils.requireModule)(filename);
36
+ return (0, _utils.compatRequire)(filename);
39
37
  }
40
38
  }
41
39
 
@@ -44,7 +42,7 @@ const findAppModule = async apiDir => {
44
42
 
45
43
  const initMiddlewares = (middleware, app) => {
46
44
  middleware.forEach(middlewareItem => {
47
- const middlewareFunc = typeof middlewareItem === 'string' ? (0, _bffUtils.requireModule)(middlewareItem) : middlewareItem;
45
+ const middlewareFunc = typeof middlewareItem === 'string' ? (0, _utils.compatRequire)(middlewareItem) : middlewareItem;
48
46
  app.use(middlewareFunc);
49
47
  });
50
48
  };
@@ -71,7 +69,7 @@ const initApp = app => {
71
69
  var _default = () => ({
72
70
  name: '@modern-js/plugin-express',
73
71
  pre: ['@modern-js/plugin-bff'],
74
- setup: () => ({
72
+ setup: api => ({
75
73
  async prepareApiServer({
76
74
  pwd,
77
75
  mode,
@@ -79,6 +77,8 @@ var _default = () => ({
79
77
  }) {
80
78
  let app;
81
79
  const apiDir = path.join(pwd, './api');
80
+ const appContext = api.useAppContext();
81
+ const apiHandlerInfos = appContext.apiHandlerInfos;
82
82
 
83
83
  if (mode === 'framework') {
84
84
  app = await findAppModule(apiDir);
@@ -98,7 +98,7 @@ var _default = () => ({
98
98
  }
99
99
 
100
100
  useRun(app);
101
- (0, _registerRoutes.default)(app);
101
+ (0, _registerRoutes.default)(app, apiHandlerInfos);
102
102
  } else if (mode === 'function') {
103
103
  app = (0, _express.default)();
104
104
  initApp(app);
@@ -111,7 +111,7 @@ var _default = () => ({
111
111
  }
112
112
 
113
113
  useRun(app);
114
- (0, _registerRoutes.default)(app);
114
+ (0, _registerRoutes.default)(app, apiHandlerInfos);
115
115
  } else {
116
116
  throw new Error(`mode must be function or framework`);
117
117
  }
@@ -5,123 +5,21 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _bffUtils = require("@modern-js/bff-utils");
8
+ require("reflect-metadata");
9
9
 
10
- var _bffRuntime = require("@modern-js/bff-runtime");
10
+ var _utils = require("./utils");
11
11
 
12
- var _typeIs = _interopRequireDefault(require("type-is"));
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
- path,
14
+ routePath,
36
15
  handler,
37
- method,
38
- name
16
+ httpMethod
39
17
  }) => {
40
- const wrappedHandler = async (req, res, next) => {
41
- const input = await getInputFromRequest(req);
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;
@@ -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
+ };
@@ -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,5 @@
1
- import { Express } from 'express';
2
- declare const registerRoutes: (app: Express) => void;
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;
@@ -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.5.6",
14
+ "version": "1.6.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",
@@ -34,20 +34,21 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@babel/runtime": "^7.18.0",
37
- "@modern-js/adapter-helpers": "^1.2.6",
38
- "@modern-js/bff-runtime": "^1.2.4",
39
- "@modern-js/bff-utils": "^1.2.9",
40
- "@modern-js/types": "^1.5.4",
41
- "@modern-js/utils": "^1.7.6",
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/types": "^1.5.5-alpha.0",
41
+ "@modern-js/utils": "^1.7.9-alpha.0",
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.11.2",
49
- "@modern-js/server-core": "1.3.5",
50
- "@modern-js/server-utils": "1.2.10",
49
+ "@modern-js/core": "1.12.2-alpha.0",
50
+ "@modern-js/server-core": "1.4.0-alpha.0",
51
+ "@modern-js/server-utils": "1.2.12-alpha.0",
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": {
package/types.d.ts CHANGED
@@ -15,5 +15,7 @@ declare module '@modern-js/runtime/server' {
15
15
 
16
16
  export function hook(attacher: ExpressAttacher): ExpressAttacher;
17
17
 
18
+ export * from '@modern-js/bff-core';
19
+
18
20
  export * from '@modern-js/bff-runtime';
19
21
  }