@modern-js/bff-core 2.0.0-beta.0 → 2.0.0-beta.2

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,63 @@
1
1
  # @modern-js/bff-core
2
2
 
3
+ ## 2.0.0-beta.2
4
+
5
+ ### Major Changes
6
+
7
+ - dda38c9c3e: chore: v2
8
+
9
+ ### Patch Changes
10
+
11
+ - 2344eb2: fix: esbuild should not handle js files
12
+ fix: esbuild 不应该处理非 js 文件
13
+ - a2509bfbdb: feat: bump esbuild from 0.14.38 to 0.15.7
14
+
15
+ feat: 将 esbuild 从 0.14.38 版本升级至 0.15.7 版本
16
+
17
+ - Updated dependencies [92f0ead]
18
+ - Updated dependencies [edd1cfb1af]
19
+ - Updated dependencies [cc971eabfc]
20
+ - Updated dependencies [5b9049f2e9]
21
+ - Updated dependencies [92004d1]
22
+ - Updated dependencies [b8bbe036c7]
23
+ - Updated dependencies [d5a31df781]
24
+ - Updated dependencies [dda38c9c3e]
25
+ - Updated dependencies [3bbea92b2a]
26
+ - Updated dependencies [abf3421a75]
27
+ - Updated dependencies [543be9558e]
28
+ - Updated dependencies [14b712da84]
29
+ - @modern-js/utils@2.0.0-beta.2
30
+ - @modern-js/bff-runtime@2.0.0-beta.2
31
+
32
+ ## 2.0.0-beta.1
33
+
34
+ ### Major Changes
35
+
36
+ - dda38c9: chore: v2
37
+
38
+ ### Patch Changes
39
+
40
+ - 2344eb2: fix: esbuild should not handle js files
41
+ fix: esbuild 不应该处理非 js 文件
42
+ - a2509bfbdb: feat: bump esbuild from 0.14.38 to 0.15.7
43
+
44
+ feat: 将 esbuild 从 0.14.38 版本升级至 0.15.7 版本
45
+
46
+ - Updated dependencies [92f0ead]
47
+ - Updated dependencies [edd1cfb1af]
48
+ - Updated dependencies [cc971eabfc]
49
+ - Updated dependencies [5b9049f]
50
+ - Updated dependencies [92004d1]
51
+ - Updated dependencies [b8bbe036c7]
52
+ - Updated dependencies [d5a31df781]
53
+ - Updated dependencies [dda38c9]
54
+ - Updated dependencies [3bbea92b2a]
55
+ - Updated dependencies [abf3421]
56
+ - Updated dependencies [543be9558e]
57
+ - Updated dependencies [14b712d]
58
+ - @modern-js/utils@2.0.0-beta.1
59
+ - @modern-js/bff-runtime@2.0.0-beta.1
60
+
3
61
  ## 2.0.0-beta.0
4
62
 
5
63
  ### Major Changes
@@ -9,35 +9,27 @@ export function Api(...args) {
9
9
  getMetadata(key) {
10
10
  return Reflect.getMetadata(key, runner);
11
11
  },
12
-
13
12
  setMetadata(key, value) {
14
13
  return Reflect.defineMetadata(key, value, runner);
15
14
  }
16
-
17
15
  };
18
-
19
16
  for (const operator of operators) {
20
17
  if (operator.metadata) {
21
18
  operator.metadata(metadataHelper);
22
19
  }
23
20
  }
24
-
25
21
  const validateHandlers = operators.filter(operator => operator.validate).map(operator => operator.validate);
26
22
  const pipeHandlers = operators.filter(operator => operator.execute).map(operator => operator.execute);
27
-
28
23
  async function runner(inputs) {
29
24
  const executeHelper = {
30
25
  result: null,
31
-
32
26
  get inputs() {
33
27
  return inputs;
34
28
  },
35
-
36
29
  set inputs(val) {
37
30
  // eslint-disable-next-line no-param-reassign
38
31
  inputs = val;
39
32
  }
40
-
41
33
  };
42
34
  const stack = [...validateHandlers, ...pipeHandlers];
43
35
  stack.push(async (helper, next) => {
@@ -48,7 +40,6 @@ export function Api(...args) {
48
40
  await compose(stack)(executeHelper);
49
41
  return executeHelper.result;
50
42
  }
51
-
52
43
  runner[HANDLER_WITH_META] = true;
53
44
  return runner;
54
45
  }
@@ -18,27 +18,21 @@ export const generateClient = async ({
18
18
  } else {
19
19
  // 这里约束传入的 requestCreator 包也必须有两个导出 client 和 server,因为目前的机制 client 和 server 要导出不同的 configure 函数;该 api 不对使用者暴露,后续可优化
20
20
  let resolvedPath = requestCreator;
21
-
22
21
  try {
23
22
  resolvedPath = path.dirname(_requireResolve(requestCreator));
24
- } catch (error) {} // eslint-disable-next-line no-param-reassign
25
-
26
-
23
+ } catch (error) {}
24
+ // eslint-disable-next-line no-param-reassign
27
25
  requestCreator = `${resolvedPath}${target ? `/${target}` : ''}`.replace(/\\/g, '/');
28
26
  }
29
-
30
27
  const apiRouter = new ApiRouter({
31
28
  apiDir,
32
29
  prefix
33
30
  });
34
31
  const handlerInfos = apiRouter.getSingleModuleHandlers(resourcePath);
35
-
36
32
  if (!handlerInfos) {
37
33
  return Err(`generate client error: Cannot require module ${resourcePath}`);
38
34
  }
39
-
40
35
  let handlersCode = '';
41
-
42
36
  for (const handlerInfo of handlerInfos) {
43
37
  const {
44
38
  name,
@@ -46,17 +40,14 @@ export const generateClient = async ({
46
40
  routePath
47
41
  } = handlerInfo;
48
42
  let exportStatement = `const ${name} =`;
49
-
50
43
  if (name.toLowerCase() === 'default') {
51
44
  exportStatement = 'default';
52
45
  }
53
-
54
46
  const upperHttpMethod = httpMethod.toUpperCase();
55
47
  const routeName = routePath;
56
48
  handlersCode += `export ${exportStatement} createRequest('${routeName}', '${upperHttpMethod}', process.env.PORT || ${String(port)}${fetcher ? `, fetch` : ''});
57
49
  `;
58
50
  }
59
-
60
51
  const importCode = `import { createRequest } from '${requestCreator}';
61
52
  ${fetcher ? `import { fetch } from '${fetcher}';\n` : ''}`;
62
53
  return Ok(`${importCode}\n${handlersCode}`);
@@ -7,8 +7,9 @@ export const Err = value => {
7
7
  isOk: false
8
8
  };
9
9
  return err;
10
- }; // eslint-disable-next-line @typescript-eslint/no-redeclare
10
+ };
11
11
 
12
+ // eslint-disable-next-line @typescript-eslint/no-redeclare
12
13
  export const Ok = value => {
13
14
  const ok = {
14
15
  kind: 'Ok',
@@ -1,22 +1,15 @@
1
1
  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; }
2
-
3
2
  export class HttpError extends Error {
4
3
  constructor(status, message) {
5
4
  super(message);
6
-
7
5
  _defineProperty(this, "status", void 0);
8
-
9
6
  this.status = status;
10
7
  }
11
-
12
8
  }
13
9
  export class ValidationError extends HttpError {
14
10
  constructor(status, message) {
15
11
  super(status, message);
16
-
17
12
  _defineProperty(this, "code", void 0);
18
-
19
13
  this.code = 'VALIDATION_ERROR';
20
14
  }
21
-
22
15
  }
@@ -1,12 +1,8 @@
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 { HttpMetadata, OperatorType, HttpMethod, TriggerType, ResponseMetaType } from "../types";
8
5
  import { ValidationError } from "../errors/http";
9
-
10
6
  const validateInput = async (schema, input) => {
11
7
  try {
12
8
  return await schema.parseAsync(input);
@@ -14,20 +10,16 @@ const validateInput = async (schema, input) => {
14
10
  const {
15
11
  z: zod
16
12
  } = require('zod');
17
-
18
13
  if (error instanceof zod.ZodError) {
19
14
  throw new ValidationError(400, error.message);
20
15
  }
21
-
22
16
  throw error;
23
17
  }
24
18
  };
25
-
26
19
  export const createHttpOperator = method => {
27
20
  return urlPath => {
28
21
  return {
29
22
  name: method,
30
-
31
23
  metadata({
32
24
  setMetadata
33
25
  }) {
@@ -37,7 +29,6 @@ export const createHttpOperator = method => {
37
29
  method
38
30
  });
39
31
  }
40
-
41
32
  };
42
33
  };
43
34
  };
@@ -53,13 +44,11 @@ export const Head = createHttpOperator(HttpMethod.Head);
53
44
  export const Data = schema => {
54
45
  return {
55
46
  name: HttpMetadata.Data,
56
-
57
47
  metadata({
58
48
  setMetadata
59
49
  }) {
60
50
  setMetadata(HttpMetadata.Data, schema);
61
51
  },
62
-
63
52
  async validate(helper, next) {
64
53
  const {
65
54
  inputs: {
@@ -71,19 +60,16 @@ export const Data = schema => {
71
60
  });
72
61
  return next();
73
62
  }
74
-
75
63
  };
76
64
  };
77
65
  export const Query = schema => {
78
66
  return {
79
67
  name: HttpMetadata.Query,
80
-
81
68
  metadata({
82
69
  setMetadata
83
70
  }) {
84
71
  setMetadata(HttpMetadata.Query, schema);
85
72
  },
86
-
87
73
  async validate(helper, next) {
88
74
  const {
89
75
  inputs: {
@@ -95,19 +81,16 @@ export const Query = schema => {
95
81
  });
96
82
  return next();
97
83
  }
98
-
99
84
  };
100
85
  };
101
86
  export const Params = schema => {
102
87
  return {
103
88
  name: HttpMetadata.Params,
104
-
105
89
  metadata({
106
90
  setMetadata
107
91
  }) {
108
92
  setMetadata(HttpMetadata.Params, schema);
109
93
  },
110
-
111
94
  async validate(helper, next) {
112
95
  const {
113
96
  inputs: {
@@ -119,19 +102,16 @@ export const Params = schema => {
119
102
  });
120
103
  return next();
121
104
  }
122
-
123
105
  };
124
106
  };
125
107
  export const Headers = schema => {
126
108
  return {
127
109
  name: HttpMetadata.Headers,
128
-
129
110
  metadata({
130
111
  setMetadata
131
112
  }) {
132
113
  setMetadata(HttpMetadata.Headers, schema);
133
114
  },
134
-
135
115
  async validate(helper, next) {
136
116
  const {
137
117
  inputs: {
@@ -143,10 +123,8 @@ export const Headers = schema => {
143
123
  });
144
124
  return next();
145
125
  }
146
-
147
126
  };
148
127
  };
149
-
150
128
  const setResponseMeta = (helper, type, value) => {
151
129
  const responseMetaData = helper.getMetadata(HttpMetadata.Response) || [];
152
130
  helper.setMetadata(HttpMetadata.Response, [...responseMetaData, {
@@ -154,34 +132,27 @@ const setResponseMeta = (helper, type, value) => {
154
132
  value
155
133
  }]);
156
134
  };
157
-
158
135
  export const HttpCode = statusCode => {
159
136
  return {
160
137
  name: 'HttpCode',
161
-
162
138
  metadata(helper) {
163
139
  setResponseMeta(helper, ResponseMetaType.StatusCode, statusCode);
164
140
  }
165
-
166
141
  };
167
142
  };
168
143
  export const SetHeaders = headers => {
169
144
  return {
170
145
  name: 'SetHeaders',
171
-
172
146
  metadata(helper) {
173
147
  setResponseMeta(helper, ResponseMetaType.Headers, headers);
174
148
  }
175
-
176
149
  };
177
150
  };
178
151
  export const Redirect = url => {
179
152
  return {
180
153
  name: 'Redirect',
181
-
182
154
  metadata(helper) {
183
155
  setResponseMeta(helper, ResponseMetaType.Redirect, url);
184
156
  }
185
-
186
157
  };
187
158
  };
@@ -1,12 +1,10 @@
1
1
  import { HttpMethod } from "../types";
2
2
  export const AllHttpMethods = Object.values(HttpMethod);
3
3
  export let APIMode;
4
-
5
4
  (function (APIMode) {
6
5
  APIMode["FARMEWORK"] = "framework";
7
6
  APIMode["FUNCTION"] = "function";
8
7
  })(APIMode || (APIMode = {}));
9
-
10
8
  export const FRAMEWORK_MODE_LAMBDA_DIR = 'lambda';
11
9
  export const FRAMEWORK_MODE_APP_DIR = 'app';
12
10
  export const INDEX_SUFFIX = 'index';
@@ -1,5 +1,4 @@
1
1
  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; }
2
-
3
2
  import path from 'path';
4
3
  import { fs, logger } from '@modern-js/utils';
5
4
  import 'reflect-metadata';
@@ -11,47 +10,36 @@ export * from "./types";
11
10
  export * from "./constants";
12
11
  export class ApiRouter {
13
12
  // lambdaDir is the dir which equal to the apiDir in function mode, and equal to the api/lambda dir in framework mode
13
+
14
14
  constructor({
15
15
  apiDir: _apiDir,
16
16
  lambdaDir: _lambdaDir,
17
17
  prefix
18
18
  }) {
19
19
  _defineProperty(this, "apiMode", void 0);
20
-
21
20
  _defineProperty(this, "apiDir", void 0);
22
-
23
21
  _defineProperty(this, "existLambdaDir", void 0);
24
-
25
22
  _defineProperty(this, "lambdaDir", void 0);
26
-
27
23
  _defineProperty(this, "prefix", void 0);
28
-
29
24
  _defineProperty(this, "apiFiles", []);
30
-
31
25
  _defineProperty(this, "getExactApiMode", apiDir => {
32
26
  const exist = this.createExistChecker(apiDir);
33
27
  const existLambdaDir = exist(FRAMEWORK_MODE_LAMBDA_DIR);
34
28
  const existAppDir = exist(FRAMEWORK_MODE_APP_DIR);
35
29
  const existAppFile = exist('app.ts') || exist('app.js');
36
-
37
30
  if (existLambdaDir || existAppDir || existAppFile) {
38
31
  return APIMode.FARMEWORK;
39
32
  }
40
-
41
33
  return APIMode.FUNCTION;
42
34
  });
43
-
44
35
  _defineProperty(this, "createExistChecker", base => target => fs.pathExistsSync(path.resolve(base, target)));
45
-
46
36
  _defineProperty(this, "getExactLambdaDir", apiDir => {
47
37
  if (this.lambdaDir) {
48
38
  return this.lambdaDir;
49
39
  }
50
-
51
40
  const lambdaDir = this.apiMode === APIMode.FARMEWORK ? path.join(apiDir, FRAMEWORK_MODE_LAMBDA_DIR) : apiDir;
52
41
  return lambdaDir;
53
42
  });
54
-
55
43
  this.validateAbsolute(_apiDir, 'apiDir');
56
44
  this.validateAbsolute(_lambdaDir, 'lambdaDir');
57
45
  this.prefix = this.initPrefix(prefix);
@@ -60,45 +48,34 @@ export class ApiRouter {
60
48
  this.lambdaDir = _lambdaDir || this.getExactLambdaDir(this.apiDir);
61
49
  this.existLambdaDir = fs.existsSync(this.lambdaDir);
62
50
  }
63
-
64
51
  isExistLambda() {
65
52
  return this.existLambdaDir;
66
53
  }
67
-
68
54
  getApiMode() {
69
55
  return this.apiMode;
70
56
  }
71
-
72
57
  getLambdaDir() {
73
58
  return this.lambdaDir;
74
59
  }
75
-
76
60
  isApiFile(filename) {
77
61
  if (this.existLambdaDir) {
78
62
  return false;
79
63
  }
80
-
81
64
  if (!this.apiFiles.includes(filename)) {
82
65
  return false;
83
66
  }
84
-
85
67
  return true;
86
68
  }
87
-
88
69
  getSingleModuleHandlers(filename) {
89
70
  const moduleInfo = this.getModuleInfo(filename);
90
-
91
71
  if (moduleInfo) {
92
72
  return this.getModuleHandlerInfos(moduleInfo);
93
73
  }
94
-
95
74
  return null;
96
75
  }
97
-
98
76
  getHandlerInfo(filename, originFuncName, handler) {
99
77
  const httpMethod = this.getHttpMethod(originFuncName, handler);
100
78
  const routeName = this.getRouteName(filename, handler);
101
-
102
79
  if (httpMethod && routeName) {
103
80
  return {
104
81
  handler,
@@ -109,104 +86,80 @@ export class ApiRouter {
109
86
  routePath: this.getRoutePath(this.prefix, routeName)
110
87
  };
111
88
  }
112
-
113
89
  return null;
114
- } // TODO: 性能提升,开发环境,判断下 lambda 目录修改时间
115
-
90
+ }
116
91
 
92
+ // TODO: 性能提升,开发环境,判断下 lambda 目录修改时间
117
93
  getSafeRoutePath(filename, handler) {
118
94
  this.loadApiFiles();
119
95
  this.validateValidApifile(filename);
120
96
  return this.getRouteName(filename, handler);
121
97
  }
122
-
123
98
  getRouteName(filename, handler) {
124
99
  if (handler) {
125
100
  const trigger = Reflect.getMetadata(OperatorType.Trigger, handler);
126
-
127
101
  if (trigger && trigger.type === TriggerType.Http) {
128
102
  if (!trigger.path) {
129
103
  throw new Error(`The http trigger ${trigger.name} needs to specify a path`);
130
104
  }
131
-
132
105
  return trigger.path;
133
106
  }
134
107
  }
135
-
136
108
  const routePath = getPathFromFilename(this.lambdaDir, filename);
137
109
  return routePath;
138
110
  }
139
-
140
111
  getHttpMethod(originHandlerName, handler) {
141
112
  if (handler) {
142
113
  const trigger = Reflect.getMetadata(OperatorType.Trigger, handler);
143
-
144
114
  if (trigger && httpMethods.includes(trigger.method)) {
145
115
  return trigger.method;
146
116
  }
147
117
  }
148
-
149
118
  const upperName = originHandlerName.toUpperCase();
150
-
151
119
  switch (upperName) {
152
120
  case 'GET':
153
121
  return HttpMethod.Get;
154
-
155
122
  case 'POST':
156
123
  return HttpMethod.Post;
157
-
158
124
  case 'PUT':
159
125
  return HttpMethod.Put;
160
-
161
126
  case 'DELETE':
162
127
  case 'DEL':
163
128
  return HttpMethod.Delete;
164
-
165
129
  case 'CONNECT':
166
130
  return HttpMethod.Connect;
167
-
168
131
  case 'TRACE':
169
132
  return HttpMethod.Trace;
170
-
171
133
  case 'PATCH':
172
134
  return HttpMethod.Patch;
173
-
174
135
  case 'OPTION':
175
136
  return HttpMethod.Option;
176
-
177
137
  case 'DEFAULT':
178
138
  {
179
139
  return HttpMethod.Get;
180
140
  }
181
-
182
141
  default:
183
142
  logger.warn(`Only api handlers are allowd to be exported, please remove the function ${originHandlerName} from exports`);
184
143
  return null;
185
144
  }
186
145
  }
187
-
188
146
  loadApiFiles() {
189
147
  if (!this.existLambdaDir) {
190
148
  return [];
191
- } // eslint-disable-next-line no-multi-assign
192
-
193
-
149
+ }
150
+ // eslint-disable-next-line no-multi-assign
194
151
  const apiFiles = this.apiFiles = getFiles(this.lambdaDir, API_FILE_RULES);
195
152
  return apiFiles;
196
153
  }
197
-
198
154
  getApiFiles() {
199
155
  if (!this.existLambdaDir) {
200
156
  return [];
201
157
  }
202
-
203
158
  if (this.apiFiles.length > 0) {
204
159
  return this.apiFiles;
205
160
  }
206
-
207
161
  return this.loadApiFiles();
208
162
  }
209
-
210
163
  getApiHandlers() {
211
164
  const filenames = this.getApiFiles();
212
165
  const moduleInfos = this.getModuleInfos(filenames);
@@ -214,30 +167,25 @@ export class ApiRouter {
214
167
  debug('apiHandlers', apiHandlers.length, apiHandlers);
215
168
  return apiHandlers;
216
169
  }
170
+
217
171
  /**
218
172
  * 如果用户未传入或传入空串,默认为 /api
219
173
  * 如果传入 /,则 prefix 为 /
220
174
  */
221
-
222
-
223
175
  initPrefix(prefix) {
224
176
  if (prefix === '/') {
225
177
  return '';
226
178
  }
227
-
228
179
  return prefix || '/api';
229
180
  }
230
-
231
181
  validateAbsolute(filename, paramsName) {
232
182
  if (typeof filename === 'string' && !path.isAbsolute(filename)) {
233
183
  throw new Error(`The ${paramsName} ${filename} is not a abolute path`);
234
184
  }
235
185
  }
236
-
237
186
  getModuleInfos(filenames) {
238
187
  return filenames.map(filename => this.getModuleInfo(filename)).filter(moduleInfo => Boolean(moduleInfo));
239
188
  }
240
-
241
189
  getModuleInfo(filename) {
242
190
  try {
243
191
  const module = requireHandlerModule(filename);
@@ -254,12 +202,10 @@ export class ApiRouter {
254
202
  }
255
203
  }
256
204
  }
257
-
258
205
  getHandlerInfos(moduleInfos) {
259
206
  let apiHandlers = [];
260
207
  moduleInfos.forEach(moduleInfo => {
261
208
  const handlerInfos = this.getModuleHandlerInfos(moduleInfo);
262
-
263
209
  if (handlerInfos) {
264
210
  apiHandlers = apiHandlers.concat(handlerInfos);
265
211
  }
@@ -267,7 +213,6 @@ export class ApiRouter {
267
213
  const sortedHandlers = sortRoutes(apiHandlers);
268
214
  return sortedHandlers;
269
215
  }
270
-
271
216
  getModuleHandlerInfos(moduleInfo) {
272
217
  const {
273
218
  module,
@@ -279,21 +224,16 @@ export class ApiRouter {
279
224
  return handlerInfo;
280
225
  }).filter(handlerInfo => Boolean(handlerInfo));
281
226
  }
282
-
283
227
  validateValidApifile(filename) {
284
228
  if (!this.apiFiles.includes(filename)) {
285
229
  throw new Error(`The ${filename} is not a valid api file.`);
286
230
  }
287
231
  }
288
-
289
232
  getRoutePath(prefix, routeName) {
290
233
  const finalRouteName = routeName === '/' ? '' : routeName;
291
-
292
234
  if (prefix === '' && finalRouteName === '') {
293
235
  return '/';
294
236
  }
295
-
296
237
  return `${prefix}${finalRouteName}`;
297
238
  }
298
-
299
239
  }