@modern-js/plugin-express 1.21.5 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,32 +1,71 @@
1
1
  # @modern-js/plugin-express
2
2
 
3
- ## 1.21.5
4
-
5
- ### Patch Changes
6
-
7
- - Updated dependencies [4876aa7]
8
- - @modern-js/bff-core@1.21.5
9
- - @modern-js/bff-runtime@1.21.5
10
- - @modern-js/types@1.21.5
11
- - @modern-js/utils@1.21.5
12
-
13
- ## 1.21.4
14
-
15
- ### Patch Changes
16
-
17
- - @modern-js/bff-core@1.21.4
18
- - @modern-js/bff-runtime@1.21.4
19
- - @modern-js/types@1.21.4
20
- - @modern-js/utils@1.21.4
21
-
22
- ## 1.21.3
23
-
24
- ### Patch Changes
25
-
26
- - @modern-js/bff-core@1.21.3
27
- - @modern-js/bff-runtime@1.21.3
28
- - @modern-js/types@1.21.3
29
- - @modern-js/utils@1.21.3
3
+ ## 2.0.0-beta.1
4
+
5
+ ### Major Changes
6
+
7
+ - dda38c9: chore: v2
8
+
9
+ ### Patch Changes
10
+
11
+ - 8d24bed25b: fix: compat Hook API in /server namespace
12
+ fix: 在 @modern-js/runtime/server 命名空间下兼容 Hook API
13
+ - 3bbea92b2a: feat: support Hook、Middleware new API
14
+ feat: 支持 Hook、Middleware 的新 API
15
+ - Updated dependencies [2344eb2]
16
+ - Updated dependencies [a2509bfbdb]
17
+ - Updated dependencies [92f0ead]
18
+ - Updated dependencies [edd1cfb1af]
19
+ - Updated dependencies [cc971eabfc]
20
+ - Updated dependencies [5b9049f]
21
+ - Updated dependencies [6bda14ed71]
22
+ - Updated dependencies [92004d1]
23
+ - Updated dependencies [b8bbe036c7]
24
+ - Updated dependencies [40ed587]
25
+ - Updated dependencies [87c1ff8]
26
+ - Updated dependencies [d5a31df781]
27
+ - Updated dependencies [dda38c9]
28
+ - Updated dependencies [102d32e4ba]
29
+ - Updated dependencies [8b8e1bb571]
30
+ - Updated dependencies [3bbea92b2a]
31
+ - Updated dependencies [abf3421]
32
+ - Updated dependencies [543be9558e]
33
+ - Updated dependencies [14b712d]
34
+ - @modern-js/bff-core@2.0.0-beta.1
35
+ - @modern-js/utils@2.0.0-beta.1
36
+ - @modern-js/types@2.0.0-beta.1
37
+ - @modern-js/bff-runtime@2.0.0-beta.1
38
+
39
+ ## 2.0.0-beta.0
40
+
41
+ ### Major Changes
42
+
43
+ - dda38c9: chore: v2
44
+
45
+ ### Patch Changes
46
+
47
+ - 8d24bed25: fix: compat Hook API in /server namespace
48
+ fix: 在 @modern-js/runtime/server 命名空间下兼容 Hook API
49
+ - 3bbea92b2: feat: support Hook、Middleware new API
50
+ feat: 支持 Hook、Middleware 的新 API
51
+ - Updated dependencies [a2509bf]
52
+ - Updated dependencies [edd1cfb1a]
53
+ - Updated dependencies [cc971eabf]
54
+ - Updated dependencies [5b9049f]
55
+ - Updated dependencies [6bda14ed7]
56
+ - Updated dependencies [b8bbe036c]
57
+ - Updated dependencies [d5a31df78]
58
+ - Updated dependencies [dda38c9]
59
+ - Updated dependencies [102d32e4b]
60
+ - Updated dependencies [8b8e1bb57]
61
+ - Updated dependencies [3bbea92b2]
62
+ - Updated dependencies [abf3421]
63
+ - Updated dependencies [543be95]
64
+ - Updated dependencies [14b712d]
65
+ - @modern-js/bff-core@2.0.0-beta.0
66
+ - @modern-js/utils@2.0.0-beta.0
67
+ - @modern-js/types@2.0.0-beta.0
68
+ - @modern-js/bff-runtime@2.0.0-beta.0
30
69
 
31
70
  ## 1.21.2
32
71
 
@@ -18,12 +18,12 @@ export default (() => ({
18
18
  bffExportsUtils = createRuntimeExportsUtils(appContext.internalDirectory, 'server');
19
19
  const serverRuntimePath = bffExportsUtils.getPath();
20
20
  const relativeRuntimePath = getRelativeRuntimePath(appDirectory, serverRuntimePath);
21
-
22
21
  if (process.env.NODE_ENV === 'production') {
23
22
  return {
24
23
  source: {
25
24
  alias: {
26
- '@modern-js/runtime/server': relativeRuntimePath
25
+ '@modern-js/runtime/server': relativeRuntimePath,
26
+ '@modern-js/runtime/express': relativeRuntimePath
27
27
  }
28
28
  }
29
29
  };
@@ -31,13 +31,13 @@ export default (() => ({
31
31
  return {
32
32
  source: {
33
33
  alias: {
34
- '@modern-js/runtime/server': serverRuntimePath
34
+ '@modern-js/runtime/server': serverRuntimePath,
35
+ '@modern-js/runtime/express': serverRuntimePath
35
36
  }
36
37
  }
37
38
  };
38
39
  }
39
40
  },
40
-
41
41
  addRuntimeExports(input) {
42
42
  const currentFile = bffExportsUtils.getPath();
43
43
  const relativeRuntimeModulePath = path.relative(path.dirname(currentFile), runtimeModulePath);
@@ -51,7 +51,6 @@ export default (() => ({
51
51
  `);
52
52
  return input;
53
53
  }
54
-
55
54
  };
56
55
  }
57
56
  }));
@@ -6,11 +6,9 @@ import finalhandler from 'finalhandler';
6
6
  import { run } from "./context";
7
7
  import registerRoutes from "./registerRoutes";
8
8
  const debug = createDebugger('express');
9
-
10
9
  const findAppModule = async apiDir => {
11
10
  const exts = ['.ts', '.js'];
12
11
  const paths = exts.map(ext => path.resolve(apiDir, `app${ext}`));
13
-
14
12
  for (const filename of paths) {
15
13
  if (await fs.pathExists(filename)) {
16
14
  // 每次获取 app.ts 的时候,避免使用缓存的 app.ts
@@ -18,17 +16,14 @@ const findAppModule = async apiDir => {
18
16
  return [compatRequire(filename), require(filename)];
19
17
  }
20
18
  }
21
-
22
19
  return [];
23
20
  };
24
-
25
21
  const initMiddlewares = (middleware, app) => {
26
22
  middleware.forEach(middlewareItem => {
27
23
  const middlewareFunc = typeof middlewareItem === 'string' ? compatRequire(middlewareItem) : middlewareItem;
28
24
  app.use(middlewareFunc);
29
25
  });
30
26
  };
31
-
32
27
  const useRun = app => {
33
28
  app.use((req, res, next) => {
34
29
  run({
@@ -37,7 +32,6 @@ const useRun = app => {
37
32
  }, next);
38
33
  });
39
34
  };
40
-
41
35
  const initApp = app => {
42
36
  app.use(cookieParser());
43
37
  app.use(express.text());
@@ -47,10 +41,10 @@ const initApp = app => {
47
41
  app.use(express.json());
48
42
  return app;
49
43
  };
50
-
51
44
  export default (() => ({
52
45
  name: '@modern-js/plugin-express',
53
46
  pre: ['@modern-js/plugin-bff'],
47
+ post: ['@modern-js/plugin-server'],
54
48
  setup: api => ({
55
49
  async prepareApiServer({
56
50
  pwd,
@@ -61,34 +55,27 @@ export default (() => ({
61
55
  const appContext = api.useAppContext();
62
56
  const apiHandlerInfos = appContext.apiHandlerInfos;
63
57
  const mode = appContext.apiMode;
64
-
65
58
  if (mode === 'framework') {
66
59
  const appModule = await findAppModule(apiDir);
67
60
  app = appModule[0];
68
61
  const hooks = appModule[1];
69
-
70
62
  if (!app || !app.use) {
71
63
  // console.warn('There is not api/app.ts.');
72
64
  app = express();
73
65
  }
74
-
75
66
  initApp(app);
76
-
77
67
  if (config) {
78
68
  const {
79
69
  middleware
80
70
  } = config;
81
71
  initMiddlewares(middleware, app);
82
72
  }
83
-
84
73
  useRun(app);
85
74
  registerRoutes(app, apiHandlerInfos);
86
-
87
75
  if (hooks) {
88
76
  const {
89
77
  afterLambdaRegisted
90
78
  } = hooks;
91
-
92
79
  if (afterLambdaRegisted) {
93
80
  afterLambdaRegisted(app);
94
81
  }
@@ -96,47 +83,46 @@ export default (() => ({
96
83
  } else if (mode === 'function') {
97
84
  app = express();
98
85
  initApp(app);
99
-
100
86
  if (config) {
101
87
  const {
102
88
  middleware
103
89
  } = config;
104
90
  initMiddlewares(middleware, app);
105
91
  }
106
-
107
92
  useRun(app);
108
93
  registerRoutes(app, apiHandlerInfos);
109
94
  } else {
110
95
  throw new Error(`mode must be function or framework`);
111
96
  }
112
-
113
97
  return (req, res) => new Promise((resolve, reject) => {
114
98
  const handler = err => {
115
99
  if (err) {
116
100
  return reject(err);
117
- } // finalhanlder will trigger 'finish' event
118
-
119
-
120
- return finalhandler(req, res, {})(null); // return resolve();
101
+ }
102
+ // finalhanlder will trigger 'finish' event
103
+ return finalhandler(req, res, {})(null);
104
+ // return resolve();
121
105
  };
122
106
 
123
107
  res.on('finish', err => {
124
108
  if (err) {
125
109
  return reject(err);
126
110
  }
127
-
128
111
  return resolve();
129
112
  });
130
113
  return app(req, res, handler);
131
114
  });
132
115
  },
133
-
134
116
  prepareWebServer({
135
117
  config
136
- }) {
118
+ }, next) {
119
+ var _userConfig$server;
120
+ const userConfig = api.useConfigContext();
121
+ if (userConfig !== null && userConfig !== void 0 && (_userConfig$server = userConfig.server) !== null && _userConfig$server !== void 0 && _userConfig$server.disableFrameworkExt) {
122
+ return next();
123
+ }
137
124
  const app = express();
138
125
  initApp(app);
139
-
140
126
  if (config) {
141
127
  const {
142
128
  middleware
@@ -144,31 +130,32 @@ export default (() => ({
144
130
  debug('web middleware', middleware);
145
131
  initMiddlewares(middleware, app);
146
132
  }
147
-
148
- return (req, res) => new Promise((resolve, reject) => {
133
+ return ctx => new Promise((resolve, reject) => {
134
+ const {
135
+ source: {
136
+ req,
137
+ res
138
+ }
139
+ } = ctx;
149
140
  const handler = err => {
150
141
  if (err) {
151
142
  return reject(err);
152
143
  }
153
-
154
144
  if (res.headersSent && res.statusCode !== 200) {
155
145
  finalhandler(req, res, {})(null);
156
146
  }
157
-
158
147
  return resolve();
159
- }; // when user call res.send
160
-
148
+ };
161
149
 
150
+ // when user call res.send
162
151
  res.on('finish', err => {
163
152
  if (err) {
164
153
  return reject(err);
165
154
  }
166
-
167
155
  return resolve();
168
156
  });
169
157
  return app(req, res, handler);
170
158
  });
171
159
  }
172
-
173
160
  })
174
161
  }));
@@ -1,6 +1,5 @@
1
1
  import 'reflect-metadata';
2
2
  import { createRouteHandler } from "./utils";
3
-
4
3
  const registerRoutes = (app, handlerInfos) => {
5
4
  handlerInfos.forEach(({
6
5
  routePath,
@@ -10,7 +9,6 @@ const registerRoutes = (app, handlerInfos) => {
10
9
  const routeHandler = createRouteHandler(handler);
11
10
  const method = httpMethod.toLowerCase();
12
11
  const routeMiddlwares = Reflect.getMetadata('middleware', handler) || [];
13
-
14
12
  if (routeMiddlwares.length > 0) {
15
13
  app[method](routePath, routeMiddlwares, routeHandler);
16
14
  } else {
@@ -18,5 +16,4 @@ const registerRoutes = (app, handlerInfos) => {
18
16
  }
19
17
  });
20
18
  };
21
-
22
19
  export default registerRoutes;
@@ -2,7 +2,6 @@ import { useContext } from "../context";
2
2
  export const Pipe = func => {
3
3
  return {
4
4
  name: 'pipe',
5
-
6
5
  // eslint-disable-next-line consistent-return
7
6
  async execute(executeHelper, next) {
8
7
  const {
@@ -12,24 +11,18 @@ export const Pipe = func => {
12
11
  const {
13
12
  res
14
13
  } = ctx;
15
-
16
14
  if (typeof func === 'function') {
17
15
  let isPiped = true;
18
-
19
16
  const end = value => {
20
17
  isPiped = false;
21
-
22
18
  if (typeof value === 'function') {
23
19
  value(res);
24
20
  return;
25
- } // eslint-disable-next-line consistent-return
26
-
27
-
21
+ }
22
+ // eslint-disable-next-line consistent-return
28
23
  return value;
29
24
  };
30
-
31
25
  const output = await func(inputs, end);
32
-
33
26
  if (!isPiped) {
34
27
  if (output) {
35
28
  return executeHelper.result = output;
@@ -38,24 +31,24 @@ export const Pipe = func => {
38
31
  return;
39
32
  }
40
33
  }
41
-
42
34
  executeHelper.inputs = output;
43
35
  await next();
44
36
  }
45
37
  }
46
-
47
38
  };
48
- }; // eslint-disable-next-line @typescript-eslint/no-redeclare
39
+ };
40
+
41
+ // eslint-disable-next-line @typescript-eslint/no-redeclare
49
42
 
50
43
  export const Middleware = middleware => {
51
44
  return {
52
45
  name: 'middleware',
53
-
54
46
  metadata(helper) {
55
47
  const middlewares = helper.getMetadata('pipe') || [];
56
48
  middlewares.push(middleware);
57
49
  helper.setMetadata('middleware', middlewares);
58
50
  }
59
-
60
51
  };
61
- }; // eslint-disable-next-line @typescript-eslint/no-redeclare
52
+ };
53
+
54
+ // eslint-disable-next-line @typescript-eslint/no-redeclare
@@ -1,104 +1,85 @@
1
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
2
  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
3
  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
4
  import 'reflect-metadata';
8
5
  import { httpMethods, isWithMetaHandler, HttpMetadata, ResponseMetaType, ValidationError } from '@modern-js/bff-core';
9
6
  import { isSchemaHandler } from '@modern-js/bff-runtime';
10
7
  import typeIs from 'type-is';
11
8
  import formidable from 'formidable';
12
-
13
9
  const handleResponseMeta = (res, handler) => {
14
10
  const responseMeta = Reflect.getMetadata(HttpMetadata.Response, handler);
15
-
16
11
  if (Array.isArray(responseMeta)) {
17
12
  for (const meta of responseMeta) {
18
13
  const metaType = meta.type;
19
14
  const metaValue = meta.value;
20
-
21
15
  switch (metaType) {
22
16
  case ResponseMetaType.Headers:
23
17
  // eslint-disable-next-line @typescript-eslint/ban-types
24
18
  for (const [key, value] of Object.entries(metaValue)) {
25
19
  res.append(key, value);
26
20
  }
27
-
28
21
  break;
29
-
30
22
  case ResponseMetaType.Redirect:
31
23
  res.redirect(metaValue);
32
24
  break;
33
-
34
25
  case ResponseMetaType.StatusCode:
35
26
  res.status(metaValue);
36
27
  break;
37
-
38
28
  default:
39
29
  break;
40
30
  }
41
31
  }
42
32
  }
43
33
  };
44
-
45
34
  export const createRouteHandler = handler => {
46
35
  const apiHandler = async (req, res, next) => {
47
36
  const input = await getInputFromRequest(req);
48
-
49
37
  if (isWithMetaHandler(handler)) {
50
38
  try {
51
39
  handleResponseMeta(res, handler);
52
-
53
40
  if (res.headersSent) {
54
41
  return;
55
42
  }
56
-
57
43
  const result = await handler(input);
58
-
59
44
  if (result && typeof result === 'object') {
60
45
  // eslint-disable-next-line consistent-return
61
46
  return res.json(result);
62
47
  }
63
48
  } catch (error) {
64
49
  if (error instanceof ValidationError) {
65
- res.status(error.status); // eslint-disable-next-line consistent-return
66
-
50
+ res.status(error.status);
51
+ // eslint-disable-next-line consistent-return
67
52
  return res.json({
68
53
  message: error.message
69
54
  });
70
55
  }
71
-
72
56
  throw error;
73
57
  }
74
58
  } else if (isSchemaHandler(handler)) {
75
59
  const result = await handler(input);
76
-
77
60
  if (result.type !== 'HandleSuccess') {
78
61
  if (result.type === 'InputValidationError') {
79
62
  res.status(400);
80
63
  } else {
81
64
  res.status(500);
82
- } // eslint-disable-next-line consistent-return
83
-
84
-
65
+ }
66
+ // eslint-disable-next-line consistent-return
85
67
  return res.json(result.message);
86
68
  } else {
87
- res.status(200); // eslint-disable-next-line consistent-return
88
-
69
+ res.status(200);
70
+ // eslint-disable-next-line consistent-return
89
71
  return res.json(result.value);
90
72
  }
91
73
  } else {
92
74
  const args = Object.values(input.params).concat(input);
93
-
94
75
  try {
95
- const body = await handler(...args); // this should never happen
76
+ const body = await handler(...args);
96
77
 
78
+ // this should never happen
97
79
  if (res.headersSent) {
98
80
  // eslint-disable-next-line consistent-return
99
81
  return await Promise.resolve();
100
82
  }
101
-
102
83
  if (typeof body !== 'undefined') {
103
84
  // eslint-disable-next-line consistent-return
104
85
  return res.json(body);
@@ -109,12 +90,10 @@ export const createRouteHandler = handler => {
109
90
  }
110
91
  }
111
92
  };
112
-
113
93
  Object.defineProperties(apiHandler, Object.getOwnPropertyDescriptors(handler));
114
94
  return apiHandler;
115
95
  };
116
96
  export const isNormalMethod = httpMethod => httpMethods.includes(httpMethod);
117
-
118
97
  const getInputFromRequest = async request => {
119
98
  const draft = {
120
99
  params: request.params,
@@ -122,7 +101,6 @@ const getInputFromRequest = async request => {
122
101
  headers: request.headers,
123
102
  cookies: request.headers.cookie
124
103
  };
125
-
126
104
  if (typeIs(request, ['application/json'])) {
127
105
  draft.data = request.body;
128
106
  } else if (typeIs(request, ['multipart/form-data'])) {
@@ -132,10 +110,8 @@ const getInputFromRequest = async request => {
132
110
  } else {
133
111
  draft.body = request.body;
134
112
  }
135
-
136
113
  return draft;
137
114
  };
138
-
139
115
  const resolveFormData = request => {
140
116
  const form = formidable({
141
117
  multiples: true
@@ -145,7 +121,6 @@ const resolveFormData = request => {
145
121
  if (err) {
146
122
  reject(err);
147
123
  }
148
-
149
124
  resolve(_objectSpread(_objectSpread({}, fields), files));
150
125
  });
151
126
  });
@@ -4,17 +4,11 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var path = _interopRequireWildcard(require("path"));
9
-
10
8
  var _utils = require("@modern-js/utils");
11
-
12
9
  var _bffCore = require("@modern-js/bff-core");
13
-
14
10
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
-
16
11
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
17
-
18
12
  var _default = () => ({
19
13
  name: '@modern-js/plugin-express',
20
14
  setup: api => {
@@ -32,12 +26,12 @@ var _default = () => ({
32
26
  bffExportsUtils = (0, _utils.createRuntimeExportsUtils)(appContext.internalDirectory, 'server');
33
27
  const serverRuntimePath = bffExportsUtils.getPath();
34
28
  const relativeRuntimePath = (0, _bffCore.getRelativeRuntimePath)(appDirectory, serverRuntimePath);
35
-
36
29
  if (process.env.NODE_ENV === 'production') {
37
30
  return {
38
31
  source: {
39
32
  alias: {
40
- '@modern-js/runtime/server': relativeRuntimePath
33
+ '@modern-js/runtime/server': relativeRuntimePath,
34
+ '@modern-js/runtime/express': relativeRuntimePath
41
35
  }
42
36
  }
43
37
  };
@@ -45,13 +39,13 @@ var _default = () => ({
45
39
  return {
46
40
  source: {
47
41
  alias: {
48
- '@modern-js/runtime/server': serverRuntimePath
42
+ '@modern-js/runtime/server': serverRuntimePath,
43
+ '@modern-js/runtime/express': serverRuntimePath
49
44
  }
50
45
  }
51
46
  };
52
47
  }
53
48
  },
54
-
55
49
  addRuntimeExports(input) {
56
50
  const currentFile = bffExportsUtils.getPath();
57
51
  const relativeRuntimeModulePath = path.relative(path.dirname(currentFile), runtimeModulePath);
@@ -65,9 +59,7 @@ var _default = () => ({
65
59
  `);
66
60
  return input;
67
61
  }
68
-
69
62
  };
70
63
  }
71
64
  });
72
-
73
65
  exports.default = _default;
@@ -4,9 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.useContext = exports.run = void 0;
7
-
8
7
  var _bffCore = require("@modern-js/bff-core");
9
-
10
8
  const {
11
9
  run,
12
10
  useContext
@@ -5,11 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  var _exportNames = {};
7
7
  exports.default = void 0;
8
-
9
8
  var _plugin = _interopRequireDefault(require("./plugin"));
10
-
11
9
  var _context = require("./context");
12
-
13
10
  Object.keys(_context).forEach(function (key) {
14
11
  if (key === "default" || key === "__esModule") return;
15
12
  if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
@@ -21,8 +18,6 @@ Object.keys(_context).forEach(function (key) {
21
18
  }
22
19
  });
23
20
  });
24
-
25
21
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
26
-
27
22
  var _default = _plugin.default;
28
23
  exports.default = _default;
@@ -4,33 +4,20 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var path = _interopRequireWildcard(require("path"));
9
-
10
8
  var _express = _interopRequireDefault(require("express"));
11
-
12
9
  var _cookieParser = _interopRequireDefault(require("cookie-parser"));
13
-
14
10
  var _utils = require("@modern-js/utils");
15
-
16
11
  var _finalhandler = _interopRequireDefault(require("finalhandler"));
17
-
18
12
  var _context = require("./context");
19
-
20
13
  var _registerRoutes = _interopRequireDefault(require("./registerRoutes"));
21
-
22
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23
-
24
15
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
25
-
26
16
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
27
-
28
17
  const debug = (0, _utils.createDebugger)('express');
29
-
30
18
  const findAppModule = async apiDir => {
31
19
  const exts = ['.ts', '.js'];
32
20
  const paths = exts.map(ext => path.resolve(apiDir, `app${ext}`));
33
-
34
21
  for (const filename of paths) {
35
22
  if (await _utils.fs.pathExists(filename)) {
36
23
  // 每次获取 app.ts 的时候,避免使用缓存的 app.ts
@@ -38,17 +25,14 @@ const findAppModule = async apiDir => {
38
25
  return [(0, _utils.compatRequire)(filename), require(filename)];
39
26
  }
40
27
  }
41
-
42
28
  return [];
43
29
  };
44
-
45
30
  const initMiddlewares = (middleware, app) => {
46
31
  middleware.forEach(middlewareItem => {
47
32
  const middlewareFunc = typeof middlewareItem === 'string' ? (0, _utils.compatRequire)(middlewareItem) : middlewareItem;
48
33
  app.use(middlewareFunc);
49
34
  });
50
35
  };
51
-
52
36
  const useRun = app => {
53
37
  app.use((req, res, next) => {
54
38
  (0, _context.run)({
@@ -57,7 +41,6 @@ const useRun = app => {
57
41
  }, next);
58
42
  });
59
43
  };
60
-
61
44
  const initApp = app => {
62
45
  app.use((0, _cookieParser.default)());
63
46
  app.use(_express.default.text());
@@ -67,10 +50,10 @@ const initApp = app => {
67
50
  app.use(_express.default.json());
68
51
  return app;
69
52
  };
70
-
71
53
  var _default = () => ({
72
54
  name: '@modern-js/plugin-express',
73
55
  pre: ['@modern-js/plugin-bff'],
56
+ post: ['@modern-js/plugin-server'],
74
57
  setup: api => ({
75
58
  async prepareApiServer({
76
59
  pwd,
@@ -81,34 +64,27 @@ var _default = () => ({
81
64
  const appContext = api.useAppContext();
82
65
  const apiHandlerInfos = appContext.apiHandlerInfos;
83
66
  const mode = appContext.apiMode;
84
-
85
67
  if (mode === 'framework') {
86
68
  const appModule = await findAppModule(apiDir);
87
69
  app = appModule[0];
88
70
  const hooks = appModule[1];
89
-
90
71
  if (!app || !app.use) {
91
72
  // console.warn('There is not api/app.ts.');
92
73
  app = (0, _express.default)();
93
74
  }
94
-
95
75
  initApp(app);
96
-
97
76
  if (config) {
98
77
  const {
99
78
  middleware
100
79
  } = config;
101
80
  initMiddlewares(middleware, app);
102
81
  }
103
-
104
82
  useRun(app);
105
83
  (0, _registerRoutes.default)(app, apiHandlerInfos);
106
-
107
84
  if (hooks) {
108
85
  const {
109
86
  afterLambdaRegisted
110
87
  } = hooks;
111
-
112
88
  if (afterLambdaRegisted) {
113
89
  afterLambdaRegisted(app);
114
90
  }
@@ -116,47 +92,46 @@ var _default = () => ({
116
92
  } else if (mode === 'function') {
117
93
  app = (0, _express.default)();
118
94
  initApp(app);
119
-
120
95
  if (config) {
121
96
  const {
122
97
  middleware
123
98
  } = config;
124
99
  initMiddlewares(middleware, app);
125
100
  }
126
-
127
101
  useRun(app);
128
102
  (0, _registerRoutes.default)(app, apiHandlerInfos);
129
103
  } else {
130
104
  throw new Error(`mode must be function or framework`);
131
105
  }
132
-
133
106
  return (req, res) => new Promise((resolve, reject) => {
134
107
  const handler = err => {
135
108
  if (err) {
136
109
  return reject(err);
137
- } // finalhanlder will trigger 'finish' event
138
-
139
-
140
- return (0, _finalhandler.default)(req, res, {})(null); // return resolve();
110
+ }
111
+ // finalhanlder will trigger 'finish' event
112
+ return (0, _finalhandler.default)(req, res, {})(null);
113
+ // return resolve();
141
114
  };
142
115
 
143
116
  res.on('finish', err => {
144
117
  if (err) {
145
118
  return reject(err);
146
119
  }
147
-
148
120
  return resolve();
149
121
  });
150
122
  return app(req, res, handler);
151
123
  });
152
124
  },
153
-
154
125
  prepareWebServer({
155
126
  config
156
- }) {
127
+ }, next) {
128
+ var _userConfig$server;
129
+ const userConfig = api.useConfigContext();
130
+ if (userConfig !== null && userConfig !== void 0 && (_userConfig$server = userConfig.server) !== null && _userConfig$server !== void 0 && _userConfig$server.disableFrameworkExt) {
131
+ return next();
132
+ }
157
133
  const app = (0, _express.default)();
158
134
  initApp(app);
159
-
160
135
  if (config) {
161
136
  const {
162
137
  middleware
@@ -164,33 +139,33 @@ var _default = () => ({
164
139
  debug('web middleware', middleware);
165
140
  initMiddlewares(middleware, app);
166
141
  }
167
-
168
- return (req, res) => new Promise((resolve, reject) => {
142
+ return ctx => new Promise((resolve, reject) => {
143
+ const {
144
+ source: {
145
+ req,
146
+ res
147
+ }
148
+ } = ctx;
169
149
  const handler = err => {
170
150
  if (err) {
171
151
  return reject(err);
172
152
  }
173
-
174
153
  if (res.headersSent && res.statusCode !== 200) {
175
154
  (0, _finalhandler.default)(req, res, {})(null);
176
155
  }
177
-
178
156
  return resolve();
179
- }; // when user call res.send
180
-
157
+ };
181
158
 
159
+ // when user call res.send
182
160
  res.on('finish', err => {
183
161
  if (err) {
184
162
  return reject(err);
185
163
  }
186
-
187
164
  return resolve();
188
165
  });
189
166
  return app(req, res, handler);
190
167
  });
191
168
  }
192
-
193
169
  })
194
170
  });
195
-
196
171
  exports.default = _default;
@@ -4,11 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  require("reflect-metadata");
9
-
10
8
  var _utils = require("./utils");
11
-
12
9
  const registerRoutes = (app, handlerInfos) => {
13
10
  handlerInfos.forEach(({
14
11
  routePath,
@@ -18,7 +15,6 @@ const registerRoutes = (app, handlerInfos) => {
18
15
  const routeHandler = (0, _utils.createRouteHandler)(handler);
19
16
  const method = httpMethod.toLowerCase();
20
17
  const routeMiddlwares = Reflect.getMetadata('middleware', handler) || [];
21
-
22
18
  if (routeMiddlwares.length > 0) {
23
19
  app[method](routePath, routeMiddlwares, routeHandler);
24
20
  } else {
@@ -26,6 +22,5 @@ const registerRoutes = (app, handlerInfos) => {
26
22
  }
27
23
  });
28
24
  };
29
-
30
25
  var _default = registerRoutes;
31
26
  exports.default = _default;
@@ -4,7 +4,5 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.hook = void 0;
7
-
8
7
  const hook = attacher => attacher;
9
-
10
8
  exports.hook = hook;
@@ -19,9 +19,7 @@ Object.defineProperty(exports, "useContext", {
19
19
  return _context.useContext;
20
20
  }
21
21
  });
22
-
23
22
  var _bffCore = require("@modern-js/bff-core");
24
-
25
23
  Object.keys(_bffCore).forEach(function (key) {
26
24
  if (key === "default" || key === "__esModule") return;
27
25
  if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
@@ -33,13 +31,9 @@ Object.keys(_bffCore).forEach(function (key) {
33
31
  }
34
32
  });
35
33
  });
36
-
37
34
  var _context = require("../context");
38
-
39
35
  var _hook = require("./hook");
40
-
41
36
  var _operators = require("./operators");
42
-
43
37
  Object.keys(_operators).forEach(function (key) {
44
38
  if (key === "default" || key === "__esModule") return;
45
39
  if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
@@ -4,13 +4,10 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.Pipe = exports.Middleware = void 0;
7
-
8
7
  var _context = require("../context");
9
-
10
8
  const Pipe = func => {
11
9
  return {
12
10
  name: 'pipe',
13
-
14
11
  // eslint-disable-next-line consistent-return
15
12
  async execute(executeHelper, next) {
16
13
  const {
@@ -20,24 +17,18 @@ const Pipe = func => {
20
17
  const {
21
18
  res
22
19
  } = ctx;
23
-
24
20
  if (typeof func === 'function') {
25
21
  let isPiped = true;
26
-
27
22
  const end = value => {
28
23
  isPiped = false;
29
-
30
24
  if (typeof value === 'function') {
31
25
  value(res);
32
26
  return;
33
- } // eslint-disable-next-line consistent-return
34
-
35
-
27
+ }
28
+ // eslint-disable-next-line consistent-return
36
29
  return value;
37
30
  };
38
-
39
31
  const output = await func(inputs, end);
40
-
41
32
  if (!isPiped) {
42
33
  if (output) {
43
34
  return executeHelper.result = output;
@@ -46,30 +37,25 @@ const Pipe = func => {
46
37
  return;
47
38
  }
48
39
  }
49
-
50
40
  executeHelper.inputs = output;
51
41
  await next();
52
42
  }
53
43
  }
54
-
55
44
  };
56
- }; // eslint-disable-next-line @typescript-eslint/no-redeclare
57
-
45
+ };
58
46
 
47
+ // eslint-disable-next-line @typescript-eslint/no-redeclare
59
48
  exports.Pipe = Pipe;
60
-
61
49
  const Middleware = middleware => {
62
50
  return {
63
51
  name: 'middleware',
64
-
65
52
  metadata(helper) {
66
53
  const middlewares = helper.getMetadata('pipe') || [];
67
54
  middlewares.push(middleware);
68
55
  helper.setMetadata('middleware', middlewares);
69
56
  }
70
-
71
57
  };
72
- }; // eslint-disable-next-line @typescript-eslint/no-redeclare
73
-
58
+ };
74
59
 
60
+ // eslint-disable-next-line @typescript-eslint/no-redeclare
75
61
  exports.Middleware = Middleware;
@@ -4,114 +4,89 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.isNormalMethod = exports.createRouteHandler = void 0;
7
-
8
7
  require("reflect-metadata");
9
-
10
8
  var _bffCore = require("@modern-js/bff-core");
11
-
12
9
  var _bffRuntime = require("@modern-js/bff-runtime");
13
-
14
10
  var _typeIs = _interopRequireDefault(require("type-is"));
15
-
16
11
  var _formidable = _interopRequireDefault(require("formidable"));
17
-
18
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
-
20
13
  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
14
  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
15
  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
16
  const handleResponseMeta = (res, handler) => {
27
17
  const responseMeta = Reflect.getMetadata(_bffCore.HttpMetadata.Response, handler);
28
-
29
18
  if (Array.isArray(responseMeta)) {
30
19
  for (const meta of responseMeta) {
31
20
  const metaType = meta.type;
32
21
  const metaValue = meta.value;
33
-
34
22
  switch (metaType) {
35
23
  case _bffCore.ResponseMetaType.Headers:
36
24
  // eslint-disable-next-line @typescript-eslint/ban-types
37
25
  for (const [key, value] of Object.entries(metaValue)) {
38
26
  res.append(key, value);
39
27
  }
40
-
41
28
  break;
42
-
43
29
  case _bffCore.ResponseMetaType.Redirect:
44
30
  res.redirect(metaValue);
45
31
  break;
46
-
47
32
  case _bffCore.ResponseMetaType.StatusCode:
48
33
  res.status(metaValue);
49
34
  break;
50
-
51
35
  default:
52
36
  break;
53
37
  }
54
38
  }
55
39
  }
56
40
  };
57
-
58
41
  const createRouteHandler = handler => {
59
42
  const apiHandler = async (req, res, next) => {
60
43
  const input = await getInputFromRequest(req);
61
-
62
44
  if ((0, _bffCore.isWithMetaHandler)(handler)) {
63
45
  try {
64
46
  handleResponseMeta(res, handler);
65
-
66
47
  if (res.headersSent) {
67
48
  return;
68
49
  }
69
-
70
50
  const result = await handler(input);
71
-
72
51
  if (result && typeof result === 'object') {
73
52
  // eslint-disable-next-line consistent-return
74
53
  return res.json(result);
75
54
  }
76
55
  } catch (error) {
77
56
  if (error instanceof _bffCore.ValidationError) {
78
- res.status(error.status); // eslint-disable-next-line consistent-return
79
-
57
+ res.status(error.status);
58
+ // eslint-disable-next-line consistent-return
80
59
  return res.json({
81
60
  message: error.message
82
61
  });
83
62
  }
84
-
85
63
  throw error;
86
64
  }
87
65
  } else if ((0, _bffRuntime.isSchemaHandler)(handler)) {
88
66
  const result = await handler(input);
89
-
90
67
  if (result.type !== 'HandleSuccess') {
91
68
  if (result.type === 'InputValidationError') {
92
69
  res.status(400);
93
70
  } else {
94
71
  res.status(500);
95
- } // eslint-disable-next-line consistent-return
96
-
97
-
72
+ }
73
+ // eslint-disable-next-line consistent-return
98
74
  return res.json(result.message);
99
75
  } else {
100
- res.status(200); // eslint-disable-next-line consistent-return
101
-
76
+ res.status(200);
77
+ // eslint-disable-next-line consistent-return
102
78
  return res.json(result.value);
103
79
  }
104
80
  } else {
105
81
  const args = Object.values(input.params).concat(input);
106
-
107
82
  try {
108
- const body = await handler(...args); // this should never happen
83
+ const body = await handler(...args);
109
84
 
85
+ // this should never happen
110
86
  if (res.headersSent) {
111
87
  // eslint-disable-next-line consistent-return
112
88
  return await Promise.resolve();
113
89
  }
114
-
115
90
  if (typeof body !== 'undefined') {
116
91
  // eslint-disable-next-line consistent-return
117
92
  return res.json(body);
@@ -122,17 +97,12 @@ const createRouteHandler = handler => {
122
97
  }
123
98
  }
124
99
  };
125
-
126
100
  Object.defineProperties(apiHandler, Object.getOwnPropertyDescriptors(handler));
127
101
  return apiHandler;
128
102
  };
129
-
130
103
  exports.createRouteHandler = createRouteHandler;
131
-
132
104
  const isNormalMethod = httpMethod => _bffCore.httpMethods.includes(httpMethod);
133
-
134
105
  exports.isNormalMethod = isNormalMethod;
135
-
136
106
  const getInputFromRequest = async request => {
137
107
  const draft = {
138
108
  params: request.params,
@@ -140,7 +110,6 @@ const getInputFromRequest = async request => {
140
110
  headers: request.headers,
141
111
  cookies: request.headers.cookie
142
112
  };
143
-
144
113
  if ((0, _typeIs.default)(request, ['application/json'])) {
145
114
  draft.data = request.body;
146
115
  } else if ((0, _typeIs.default)(request, ['multipart/form-data'])) {
@@ -150,10 +119,8 @@ const getInputFromRequest = async request => {
150
119
  } else {
151
120
  draft.body = request.body;
152
121
  }
153
-
154
122
  return draft;
155
123
  };
156
-
157
124
  const resolveFormData = request => {
158
125
  const form = (0, _formidable.default)({
159
126
  multiples: true
@@ -163,7 +130,6 @@ const resolveFormData = request => {
163
130
  if (err) {
164
131
  reject(err);
165
132
  }
166
-
167
133
  resolve(_objectSpread(_objectSpread({}, fields), files));
168
134
  });
169
135
  });
@@ -1,5 +1,3 @@
1
1
  import type { CliPlugin } from '@modern-js/core';
2
-
3
2
  declare const _default: () => CliPlugin;
4
-
5
3
  export default _default;
@@ -1,5 +1,3 @@
1
1
  import type { ServerPlugin } from '@modern-js/server-core';
2
-
3
2
  declare const _default: () => ServerPlugin;
4
-
5
3
  export default _default;
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "1.21.5",
14
+ "version": "2.0.0-beta.1",
15
15
  "jsnext:source": "./src/index.ts",
16
16
  "types": "./dist/types/index.d.ts",
17
17
  "main": "./dist/js/node/index.js",
@@ -39,10 +39,10 @@
39
39
  "formidable": "^1.2.2",
40
40
  "reflect-metadata": "^0.1.13",
41
41
  "type-is": "^1.6.18",
42
- "@modern-js/bff-core": "1.21.5",
43
- "@modern-js/bff-runtime": "1.21.5",
44
- "@modern-js/types": "1.21.5",
45
- "@modern-js/utils": "1.21.5"
42
+ "@modern-js/bff-core": "2.0.0-beta.1",
43
+ "@modern-js/bff-runtime": "2.0.0-beta.1",
44
+ "@modern-js/types": "2.0.0-beta.1",
45
+ "@modern-js/utils": "2.0.0-beta.1"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/cookie-parser": "^1.4.2",
@@ -58,10 +58,10 @@
58
58
  "supertest": "^6.1.6",
59
59
  "typescript": "^4",
60
60
  "zod": "^3.17.3",
61
- "@modern-js/core": "1.21.5",
62
- "@modern-js/server-core": "1.21.5",
63
- "@scripts/build": "1.21.5",
64
- "@scripts/jest-config": "1.21.5"
61
+ "@modern-js/core": "2.0.0-beta.1",
62
+ "@modern-js/server-core": "2.0.0-beta.1",
63
+ "@scripts/build": "2.0.0-beta.1",
64
+ "@scripts/jest-config": "2.0.0-beta.1"
65
65
  },
66
66
  "modernConfig": {
67
67
  "output": {
@@ -75,32 +75,9 @@
75
75
  "registry": "https://registry.npmjs.org/",
76
76
  "access": "public"
77
77
  },
78
- "wireit": {
79
- "build": {
80
- "command": "modern build",
81
- "files": [
82
- "src/**/*",
83
- "tsconfig.json",
84
- "package.json"
85
- ],
86
- "output": [
87
- "dist/**/*"
88
- ]
89
- },
90
- "test": {
91
- "command": "jest --passWithNoTests",
92
- "files": [
93
- "src/**/*",
94
- "tsconfig.json",
95
- "package.json",
96
- "tests/**/*"
97
- ],
98
- "output": []
99
- }
100
- },
101
78
  "scripts": {
102
79
  "new": "modern new",
103
- "build": "wireit",
104
- "test": "wireit"
80
+ "build": "modern build",
81
+ "test": "jest --passWithNoTests"
105
82
  }
106
83
  }
package/types.d.ts CHANGED
@@ -1,10 +1,40 @@
1
1
  /// <reference path="./dist/types/index.d.ts" />
2
2
 
3
+ declare module '@modern-js/runtime/express' {
4
+ import { Request, Response, RequestHandler } from 'express';
5
+
6
+ type Context = { req: Request; res: Response };
7
+
8
+ export const Pipe: import('./src/runtime').Pipe;
9
+ export const Middleware: import('./src/runtime').Middleware;
10
+
11
+ export function useContext(): Context;
12
+
13
+ export type { RequestHandler };
14
+
15
+ export * from '@modern-js/bff-core';
16
+ }
17
+
18
+ // Todo: remove on next version
3
19
  declare module '@modern-js/runtime/server' {
4
20
  import { Request, Response, RequestHandler } from 'express';
5
21
 
22
+ import type { AfterMatchContext, AfterRenderContext, NextFunction } from '@modern-js/types';
23
+
24
+ export type AfterRenderHook = (
25
+ context: AfterRenderContext,
26
+ next: NextFunction,
27
+ ) => void;
28
+
29
+ export type AfterMatchHook = (
30
+ context: AfterMatchContext,
31
+ next: NextFunction,
32
+ ) => void;
33
+
6
34
  type ExpressOptions = {
7
35
  addMiddleware: (...input: RequestHandler[]) => void;
36
+ afterRender: (hook: AfterRenderHook) => void;
37
+ afterMatch: (hook: AfterMatchHook) => void;
8
38
  };
9
39
 
10
40
  type ExpressAttacher = (options: ExpressOptions) => void;
@@ -18,5 +48,7 @@ declare module '@modern-js/runtime/server' {
18
48
 
19
49
  export function hook(attacher: ExpressAttacher): ExpressAttacher;
20
50
 
51
+ export type { RequestHandler };
52
+
21
53
  export * from '@modern-js/bff-core';
22
54
  }