@x-9lab/xlab 1.6.1 → 2.0.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.
Files changed (72) hide show
  1. package/@types/cluster.d.ts +15 -3
  2. package/@types/components/common/index.d.ts +1 -2
  3. package/@types/components/cron/index.d.ts +4 -4
  4. package/@types/components/log/index.d.ts +37 -2
  5. package/@types/config/index.d.ts +9 -5
  6. package/@types/custom.d.ts +25 -3
  7. package/@types/dot-file.d.ts +6 -0
  8. package/@types/global.d.ts +44 -56
  9. package/@types/index.d.ts +18 -0
  10. package/@types/init-env.d.ts +3 -1
  11. package/@types/middleware/handle-pre-dir.d.ts +1 -5
  12. package/@types/middleware/request-filter.d.ts +0 -1
  13. package/@types/middleware/service-mark.d.ts +1 -6
  14. package/@types/router.d.ts +25 -0
  15. package/@types/server.d.ts +28 -6
  16. package/MIGRATION.md +182 -0
  17. package/README.md +105 -86
  18. package/dist/@config/config.dev.js +7 -3
  19. package/dist/@config/config.js +7 -4
  20. package/dist/@config/config.sand.js +7 -3
  21. package/dist/bin/watch.js +36 -16
  22. package/dist/cluster.js +121 -44
  23. package/dist/components/assets/index.js +9 -5
  24. package/dist/components/cluster/index.js +17 -4
  25. package/dist/components/common/index.js +65 -45
  26. package/dist/components/cron/index.js +50 -27
  27. package/dist/components/header/index.js +32 -17
  28. package/dist/components/header/time.js +6 -2
  29. package/dist/components/index.js +1 -1
  30. package/dist/components/log/index.js +91 -87
  31. package/dist/components/mime/index.js +6 -2
  32. package/dist/components/return-code/index.js +33 -18
  33. package/dist/components/uuid/index.js +22 -13
  34. package/dist/config/getEnv.js +9 -5
  35. package/dist/config/index.js +98 -66
  36. package/dist/config/process-custom-config-files.js +26 -22
  37. package/dist/config/process-def-config-file.js +15 -11
  38. package/dist/custom.js +77 -28
  39. package/dist/default-x-config.js +9 -5
  40. package/dist/dot-file.js +42 -17
  41. package/dist/global.js +37 -31
  42. package/dist/index.js +100 -0
  43. package/dist/init-env.js +17 -9
  44. package/dist/middleware/@bin/html-filter.js +19 -7
  45. package/dist/middleware/bad-request.js +12 -8
  46. package/dist/middleware/compress.js +11 -7
  47. package/dist/middleware/cors.js +20 -7
  48. package/dist/middleware/fresh-filter.js +13 -7
  49. package/dist/middleware/handle-pre-dir.js +22 -17
  50. package/dist/middleware/request-filter.js +39 -25
  51. package/dist/middleware/service-mark.js +22 -25
  52. package/dist/middlewares.js +22 -20
  53. package/dist/router.js +174 -141
  54. package/dist/server.js +202 -93
  55. package/package.json +25 -29
  56. package/@types/business/utils/cookie/1.1.0/clean/index.d.ts +0 -3
  57. package/@types/business/utils/cookie/1.1.0/clean/js/index.d.ts +0 -2
  58. package/@types/components/cache/index.d.ts +0 -2
  59. package/@types/components/cache/lru.d.ts +0 -21
  60. package/@types/components/html-processor/index.d.ts +0 -9
  61. package/@types/components/injection/index.d.ts +0 -25
  62. package/@types/components/js-processor/index.d.ts +0 -5
  63. package/@types/components/md5/index.d.ts +0 -2
  64. package/@types/components/platform/index.d.ts +0 -21
  65. package/@types/components/proxy/index.d.ts +0 -26
  66. package/@types/components/querystring/index.d.ts +0 -25
  67. package/@types/components/redirect/index.d.ts +0 -11
  68. package/@types/components/request/helper.d.ts +0 -3
  69. package/@types/components/request/index.d.ts +0 -51
  70. package/@types/components/request/resolve-uri.d.ts +0 -6
  71. package/@types/components/version/index.d.ts +0 -26
  72. package/@types/env.d.ts +0 -1
@@ -2,34 +2,48 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- exports.default = _default;
6
- var _htmlFilter = _interopRequireWildcard(require("./@bin/html-filter"));
7
- var _url = _interopRequireDefault(require("url"));
8
- function _interopRequireDefault(obj) {
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return _default;
9
+ }
10
+ });
11
+ const _htmlfilter = /*#__PURE__*/ _interop_require_wildcard(require("./@bin/html-filter"));
12
+ const _url = /*#__PURE__*/ _interop_require_default(require("url"));
13
+ function _interop_require_default(obj) {
9
14
  return obj && obj.__esModule ? obj : {
10
15
  default: obj
11
16
  };
12
17
  }
13
- function _interopRequireWildcard(obj) {
14
- if (obj && obj.__esModule) {
15
- return obj;
16
- } else {
17
- var newObj = {};
18
- if (obj != null) {
19
- for(var key in obj){
20
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
21
- var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
22
- if (desc.get || desc.set) {
23
- Object.defineProperty(newObj, key, desc);
24
- } else {
25
- newObj[key] = obj[key];
26
- }
27
- }
28
- }
18
+ function _getRequireWildcardCache(nodeInterop) {
19
+ if (typeof WeakMap !== "function") return null;
20
+ var cacheBabelInterop = new WeakMap();
21
+ var cacheNodeInterop = new WeakMap();
22
+ return (_getRequireWildcardCache = function(nodeInterop) {
23
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
24
+ })(nodeInterop);
25
+ }
26
+ function _interop_require_wildcard(obj, nodeInterop) {
27
+ if (!nodeInterop && obj && obj.__esModule) return obj;
28
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") return {
29
+ default: obj
30
+ };
31
+ var cache = _getRequireWildcardCache(nodeInterop);
32
+ if (cache && cache.has(obj)) return cache.get(obj);
33
+ var newObj = {
34
+ __proto__: null
35
+ };
36
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
37
+ for(var key in obj){
38
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
39
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
40
+ if (desc && (desc.get || desc.set)) Object.defineProperty(newObj, key, desc);
41
+ else newObj[key] = obj[key];
29
42
  }
30
- newObj.default = obj;
31
- return newObj;
32
43
  }
44
+ newObj.default = obj;
45
+ if (cache) cache.set(obj, newObj);
46
+ return newObj;
33
47
  }
34
48
  const IS_STATIC_RE = /^\/.*\.(ttf|woff|eot|html|css|js|json|png|jpeg|jpg|gif|bmp|handlebars|mp3|mp4|m3u8|avi|mpg|mpeg|xml|json|tpl)$/i;
35
49
  const IS_IMG_RE = /\.(jpg|jpeg|png|gif)$/i;
@@ -94,13 +108,13 @@ async function filter(ctx, next) {
94
108
  // 提取页面必要的信息
95
109
  // 由于 dir 也可能直接返回 HTML 页面
96
110
  // 所以这里也需要经过 HTML 的过滤器处理
97
- ctx.state.ver = (0, _htmlFilter).filter(ctx.url);
111
+ ctx.state.ver = (0, _htmlfilter.filter)(ctx.url);
98
112
  } else if (isStatic(pathname)) {
99
113
  srcType.static = true;
100
114
  if (isHtml(pathname)) {
101
115
  srcType.html = true;
102
116
  // 提取页面必要的信息
103
- ctx.state.ver = (0, _htmlFilter).filter(ctx.url);
117
+ ctx.state.ver = (0, _htmlfilter.filter)(ctx.url);
104
118
  } else if (isJS(pathname)) {
105
119
  srcType.js = true;
106
120
  } else if (isImg(pathname)) {
@@ -117,6 +131,6 @@ async function filter(ctx, next) {
117
131
  await next();
118
132
  }
119
133
  function _default() {
120
- (0, _htmlFilter).default();
134
+ (0, _htmlfilter.default)();
121
135
  return filter;
122
136
  }
@@ -2,31 +2,28 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- exports.default = _default;
6
- var _utils = require("@x-drive/utils");
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return _default;
9
+ }
10
+ });
11
+ const _utils = require("@x-drive/utils");
12
+ const _config = require("../config");
7
13
  const serverPackge = require("../../package.json");
8
- var info = {};
9
- // 业务名称
10
- info.mark = getSysConfig("mark") || getSysConfig("name");
11
- // 业务版本
12
- info.version = getSysConfig("version");
13
- // 服务端版本
14
- info.serverVer = serverPackge.version;
15
- info.serverName = serverPackge.name;
16
- // 业务启动时间
17
- // FIX ME : 服务器不是北京时间的时候这个数据跟实际启动的时间存在时差
18
- info.date = (0, _utils).date(new Date(), "Y-m-d H:i:s");
19
- // 模块版本信息
20
- const CLIENT_MARK = `${info.mark}@${info.version}`;
21
- const SERVER_MARK = `${info.serverName}@${info.serverVer}`;
22
- const MARK = `${CLIENT_MARK},${SERVER_MARK};Startup@${info.date}`;
23
- info = null;
24
- /**
25
- * 处理函数
26
- */ async function handler(ctx, next) {
27
- ctx.set("X-Mark", MARK);
28
- await next();
29
- }
30
14
  function _default() {
31
- return handler;
15
+ const conf = (0, _config.get)();
16
+ // 业务名称与版本
17
+ const CLIENT_MARK = `${conf.mark || conf.name}@${conf.version}`;
18
+ // 服务端版本
19
+ const SERVER_MARK = `${serverPackge.name}@${serverPackge.version}`;
20
+ // 业务启动时间
21
+ // FIX ME : 服务器不是北京时间的时候这个数据跟实际启动的时间存在时差
22
+ const MARK = `${CLIENT_MARK},${SERVER_MARK};Startup@${(0, _utils.date)(new Date(), "Y-m-d H:i:s")}`;
23
+ /**
24
+ * 处理函数
25
+ */ return async function handler(ctx, next) {
26
+ ctx.set("X-Mark", MARK);
27
+ await next();
28
+ };
32
29
  }
@@ -2,18 +2,23 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- exports.default = void 0;
6
- var _utils = require("@x-drive/utils");
7
- var _common = require("./components/common");
8
- var _defaultXConfig = _interopRequireDefault(require("./default-x-config"));
9
- function _interopRequireDefault(obj) {
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return _default;
9
+ }
10
+ });
11
+ const _utils = require("@x-drive/utils");
12
+ const _common = require("./components/common");
13
+ const _config = require("./config");
14
+ const _defaultxconfig = /*#__PURE__*/ _interop_require_default(require("./default-x-config"));
15
+ function _interop_require_default(obj) {
10
16
  return obj && obj.__esModule ? obj : {
11
17
  default: obj
12
18
  };
13
19
  }
14
20
  const cwd = process.cwd();
15
21
  /**内部中间件 */ const INTERNAL_MIDDLEWARE = {
16
- "combo": true,
17
22
  "bad-request": true,
18
23
  "fresh-filter": true,
19
24
  "handle-pre-dir": true,
@@ -23,7 +28,7 @@ const cwd = process.cwd();
23
28
  "cors": true
24
29
  };
25
30
  /**获取中间件加载执行列表 */ function getExeList() {
26
- const config = getSysConfig();
31
+ const config = (0, _config.get)();
27
32
  var mConfig;
28
33
  if (config.middlewares) {
29
34
  mConfig = config.middlewares;
@@ -31,37 +36,34 @@ const cwd = process.cwd();
31
36
  mConfig = null;
32
37
  }
33
38
  if (mConfig) {
34
- return Object.keys(mConfig).filter((key)=>(0, _utils).isBoolean(mConfig[key]) ? mConfig[key] : true
35
- ).map((key, index)=>{
36
- if ((0, _utils).isBoolean(mConfig[key])) {
39
+ return Object.keys(mConfig).filter((key)=>(0, _utils.isBoolean)(mConfig[key]) ? mConfig[key] : true).map((key, index)=>{
40
+ if ((0, _utils.isBoolean)(mConfig[key])) {
37
41
  mConfig[key] = {};
38
42
  }
39
- if (!(0, _utils).isString(mConfig[key].name)) {
43
+ if (!(0, _utils.isString)(mConfig[key].name)) {
40
44
  mConfig[key].name = key;
41
45
  }
42
- if (!(0, _utils).isNumber(mConfig[key].index)) {
46
+ if (!(0, _utils.isNumber)(mConfig[key].index)) {
43
47
  mConfig[key].index = index;
44
48
  }
45
49
  return mConfig[key];
46
- }).sort((now, next)=>now.index - next.index
47
- );
50
+ }).sort((now, next)=>now.index - next.index);
48
51
  }
49
52
  return [];
50
53
  }
51
54
  // [最后3个中间件固定是 系统路由,静态文件服务,错误请求处理模块]
52
55
  /**加载中间件 */ function loadMiddleware(app) {
53
56
  const list = getExeList();
54
- if ((0, _utils).isArray(list) && list.length) {
57
+ if ((0, _utils.isArray)(list) && list.length) {
55
58
  list.forEach((item)=>{
56
59
  if (INTERNAL_MIDDLEWARE[item.name]) {
57
- app.use((0, _common).getRealDefaultMod(require(`./middleware/${item.name}`))(item.config));
60
+ app.use((0, _common.getRealDefaultMod)(require(`./middleware/${item.name}`))(item.config));
58
61
  } else {
59
- app.use((0, _common).getRealDefaultMod(require(`${cwd}/${_defaultXConfig.default.businessDir}/middleware/${item.name}`))(item.config));
62
+ app.use((0, _common.getRealDefaultMod)(require(`${cwd}/${_defaultxconfig.default.businessDir}/middleware/${item.name}`))(item.config));
60
63
  }
61
- masterLog(`MIDDLEWARE >>> [${item.name}] launch`);
64
+ (0, _config.log)(`MIDDLEWARE >>> [${item.name}] launch`);
62
65
  });
63
66
  console.log("");
64
67
  }
65
68
  }
66
- var _default = loadMiddleware;
67
- exports.default = _default;
69
+ const _default = loadMiddleware;
package/dist/router.js CHANGED
@@ -2,170 +2,203 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- exports.default = void 0;
6
- var _utils = require("@x-drive/utils");
7
- var _common = require("./components/common");
8
- var _defaultXConfig = _interopRequireDefault(require("./default-x-config"));
9
- var _path = _interopRequireDefault(require("path"));
10
- var _fs = _interopRequireDefault(require("fs"));
11
- function _interopRequireDefault(obj) {
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: Object.getOwnPropertyDescriptor(all, name).get
9
+ });
10
+ }
11
+ _export(exports, {
12
+ get default () {
13
+ return _default;
14
+ },
15
+ get defineApi () {
16
+ return defineApi;
17
+ }
18
+ });
19
+ const _utils = require("@x-drive/utils");
20
+ const _common = require("./components/common");
21
+ const _config = require("./config");
22
+ const _defaultxconfig = /*#__PURE__*/ _interop_require_default(require("./default-x-config"));
23
+ const _path = /*#__PURE__*/ _interop_require_default(require("path"));
24
+ const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
25
+ function _interop_require_default(obj) {
12
26
  return obj && obj.__esModule ? obj : {
13
27
  default: obj
14
28
  };
15
29
  }
16
30
  /**API 服务目录 */ const API_BUSINESS_DIR = "business";
31
+ /**API 地址前缀检测 */ const IS_API_REGEXP = /^\/api\//;
32
+ /**支持的请求方法, 同时也是「文件名即方法」约定支持的文件名 */ const HTTP_METHODS = [
33
+ "get",
34
+ "post",
35
+ "put",
36
+ "delete",
37
+ "patch",
38
+ "head",
39
+ "options",
40
+ "all"
41
+ ];
42
+ /**
43
+ * 定义一个业务接口
44
+
45
+ * 运行时恒等返回, 仅为路由模块提供类型推导
46
+ */ function defineApi(def) {
47
+ return def;
48
+ }
17
49
  /**生成 api */ function buildApi(api) {
18
50
  if (!api.startsWith("/")) {
19
51
  api = `/${api}`;
20
52
  }
21
53
  return `/api${api}`;
22
54
  }
23
- /**
24
- * 递归处理文件夹
25
- * @param path 文件目录
26
- * @param middlewares 接口中间件
27
- * @param callback 查找到文件时的处理函数
28
- */ function walk(dir, middlewares, callback) {
29
- var files = _fs.default.readdirSync(dir);
30
- files.forEach(function(item) {
31
- if (!item.startsWith(".") && !item.endsWith(".d.ts")) {
32
- var tmpPath = _path.default.join(dir, item);
33
- var stats = _fs.default.statSync(tmpPath);
34
- if (stats.isDirectory() && item.startsWith("$")) {
35
- // 接口级别中间件
36
- let middlewaresFiles = _fs.default.readdirSync(tmpPath);
37
- let mws = [];
38
- middlewaresFiles.forEach(function(name) {
39
- let tmpMwPath = _path.default.join(tmpPath, name);
40
- let fileStat = _fs.default.statSync(tmpMwPath);
41
- if (!fileStat.isDirectory() && !item.startsWith(".") && !item.endsWith(".d.ts")) {
42
- mws.push(tmpMwPath);
43
- }
44
- });
45
- // 简单做下排序
46
- mws.sort();
47
- const partPath = dir.split(API_BUSINESS_DIR)[1] || _path.default.posix.sep;
48
- middlewares[partPath] = mws;
49
- }
50
- if (stats.isDirectory() && !item.startsWith("@") && !item.startsWith("$")) {
51
- walk(tmpPath, middlewares, callback);
52
- } else if (!stats.isDirectory()) {
53
- callback(tmpPath, item, middlewares);
55
+ /**把相对路径统一为以 / 开头的 url 风格路径 */ function toUrlPath(rel) {
56
+ return "/" + rel.split(_path.default.sep).filter(Boolean).join("/");
57
+ }
58
+ /**
59
+ * 递归收集业务目录下的路由文件与目录级中间件
60
+ * @param dir 当前目录
61
+ * @param root business 根目录
62
+ * @param middlewares 目录级中间件收集对象
63
+ * @param files 路由文件收集数组
64
+ */ function collect(dir, root, middlewares, files) {
65
+ _fs.default.readdirSync(dir).forEach(function(item) {
66
+ if (item.startsWith(".") || item.endsWith(".d.ts")) {
67
+ return;
68
+ }
69
+ const tmpPath = _path.default.join(dir, item);
70
+ const stats = _fs.default.statSync(tmpPath);
71
+ if (stats.isDirectory()) {
72
+ if (item.startsWith("$")) {
73
+ // 目录级中间件, 生效于所在层级及以下; 不递归, 按文件名排序执行
74
+ const mws = _fs.default.readdirSync(tmpPath).filter(function(name) {
75
+ return !name.startsWith(".") && !name.endsWith(".d.ts") && _fs.default.statSync(_path.default.join(tmpPath, name)).isFile();
76
+ }).sort().map((name)=>_path.default.join(tmpPath, name));
77
+ const key = toUrlPath(_path.default.relative(root, dir));
78
+ middlewares[key] = (middlewares[key] || []).concat(mws);
79
+ } else if (!item.startsWith("@")) {
80
+ collect(tmpPath, root, middlewares, files);
54
81
  }
82
+ } else {
83
+ files.push(tmpPath);
55
84
  }
56
85
  });
57
86
  }
58
- /**加载业务服务接口 */ function appRouter(router) {
59
- const IS_API_REGEXP = /^\/api\//;
60
- var processBusiness = function(modPath, item, middlewares) {
61
- var mod = require(_path.default.resolve(modPath));
62
- if (mod) {
63
- mod = (0, _common).getRealDefaultMod(mod);
64
- let api_path = modPath.split(API_BUSINESS_DIR);
65
- let api;
66
- let apiPart;
67
- let modName;
68
- // 根据路径生成 url 规则
69
- api = api_path[1].replace(".js", "").split(_path.default.posix.sep);
70
- // 文件名是 index
71
- const lastIsIndex = api[api.length - 1] === "index";
72
- // 文件名是 index 的则会被从 api 上先强行去掉
73
- // 如果需要命名成 index 的需要自己用 object 形式,用 api 字段定义
74
- if (lastIsIndex) {
75
- api.pop();
76
- }
77
- // 如果模块返回的是数组,则使用文件名做为方法名,并在 api 上去掉文件名
78
- if ((0, _utils).isArray(mod)) {
79
- if (!lastIsIndex) {
80
- api.pop();
81
- }
82
- apiPart = api;
83
- api = buildApi(api.join("/"));
84
- mod.unshift(api);
85
- } else {
86
- apiPart = api;
87
- // 不是数组则把文件当作正常的 api 地址
88
- api = buildApi(api.join("/"));
89
- }
90
- // 是对象则取对应的字段
91
- if ((0, _utils).isObject(mod)) {
92
- const subjectMod = mod;
93
- if ((0, _utils).isFunction(subjectMod.handler) || (0, _utils).isAsyncFunction(subjectMod.handler)) {
94
- modName = subjectMod.method || "get";
95
- api = subjectMod.api || api;
96
- apiPart = api.split("/");
97
- if (apiPart[0] !== "") {
98
- apiPart.unshift("");
99
- }
100
- // 如果没有声明忽略检测则保证接口一定是以 api 开头的
101
- if (!subjectMod.ignoreApiNameCheck && !IS_API_REGEXP.test(api)) {
102
- api = buildApi(api);
103
- }
104
- if ((0, _utils).isArray(subjectMod.middleware)) {
105
- mod = [
106
- api,
107
- ...subjectMod.middleware,
108
- subjectMod.handler
109
- ];
110
- } else {
111
- mod = [
112
- api,
113
- subjectMod.handler
114
- ];
115
- }
116
- }
117
- }
118
- var dirMws = [];
119
- var prevPart = "";
120
- for(let i = 0; i < apiPart.length; i++){
121
- if (!apiPart[i] || apiPart[i] === "api") {
122
- continue;
123
- }
124
- const part = `${prevPart}${_path.default.posix.sep}${apiPart[i]}`;
125
- if (middlewares[part]) {
126
- dirMws = dirMws.concat(middlewares[part]);
87
+ /**
88
+ * 把一个路由模块归一化为注册单元
89
+
90
+ * 支持的导出形态:
91
+ * 1. 函数: 绑定为处理函数, 方法由文件名约定决定
92
+ * 2. 对象(推荐配合 defineApi): { method?, api?, middleware?, handler, ignoreApiNameCheck? }
93
+ *
94
+ * 文件名约定: `index` 从 api 上去掉; 文件名是请求方法名(get/post/...)时,
95
+ * 从 api 上去掉并作为该接口的请求方法
96
+ * @param modPath 模块文件地址
97
+ * @param root business 根目录
98
+ */ function normalize(modPath, root) {
99
+ var mod = (0, _common.getRealDefaultMod)(require(_path.default.resolve(modPath)));
100
+ if (!mod) {
101
+ return null;
102
+ }
103
+ if ((0, _utils.isArray)(mod)) {
104
+ throw new Error(`[xlab] 数组形式的路由定义已在 v2 移除: ${modPath}\n` + "请改用 defineApi 对象形式或「文件名即方法」约定, 参见 MIGRATION.md");
105
+ }
106
+ const rel = _path.default.relative(root, modPath);
107
+ const ext = _path.default.extname(rel);
108
+ const parts = rel.slice(0, rel.length - ext.length).split(_path.default.sep).filter(Boolean);
109
+ const fileName = parts[parts.length - 1];
110
+ var method = "get";
111
+ if (fileName === "index") {
112
+ parts.pop();
113
+ } else if (HTTP_METHODS.indexOf(fileName) !== -1) {
114
+ method = fileName;
115
+ parts.pop();
116
+ }
117
+ var api = buildApi(parts.join("/"));
118
+ var middlewares = [];
119
+ var handler = null;
120
+ if ((0, _utils.isFunction)(mod) || (0, _utils.isAsyncFunction)(mod)) {
121
+ handler = mod;
122
+ } else if ((0, _utils.isObject)(mod)) {
123
+ const def = mod;
124
+ if ((0, _utils.isFunction)(def.handler) || (0, _utils.isAsyncFunction)(def.handler)) {
125
+ handler = def.handler;
126
+ method = def.method || method;
127
+ if ((0, _utils.isString)(def.api)) {
128
+ api = def.api;
129
+ if (!api.startsWith("/")) {
130
+ api = `/${api}`;
127
131
  }
128
- prevPart = part;
129
- }
130
- // 直接返回函数则直接绑定
131
- if ((0, _utils).isFunction(mod) || (0, _utils).isAsyncFunction(mod)) {
132
- mod = [
133
- api,
134
- mod
135
- ];
136
- }
137
- if (!modName) {
138
- modName = item.replace(".js", "");
139
- if (modName === "index") {
140
- modName = "get";
132
+ // 如果没有声明忽略检测则保证接口一定是以 api 开头的
133
+ if (!def.ignoreApiNameCheck && !IS_API_REGEXP.test(api)) {
134
+ api = buildApi(api);
141
135
  }
142
136
  }
143
- if (dirMws && dirMws.length) {
144
- let mws = dirMws.map((name)=>(0, _common).getRealDefaultMod(require(name))
145
- );
146
- mod.splice.apply(mod, [
147
- 1,
148
- 0,
149
- ...mws
150
- ]);
151
- mws = null;
137
+ if ((0, _utils.isArray)(def.middleware)) {
138
+ middlewares = def.middleware;
152
139
  }
153
- router[modName].apply(router, mod);
154
- masterLog("router", `Handling API >>> [${modName}] ${api}`);
155
140
  }
141
+ }
142
+ if (!handler) {
143
+ return null;
144
+ }
145
+ return {
146
+ method,
147
+ api,
148
+ middlewares,
149
+ handler
156
150
  };
157
- // 业务基本目录
151
+ }
152
+ /**
153
+ * 解析一个 api 命中的目录级中间件链
154
+ * @param api api 地址
155
+ * @param middlewares 目录级中间件映射
156
+ */ function resolveDirMiddlewares(api, middlewares) {
157
+ var chain = [];
158
+ if (middlewares["/"]) {
159
+ chain = chain.concat(middlewares["/"]);
160
+ }
161
+ const parts = api.split("/").filter((part)=>part && part !== "api");
162
+ var prev = "";
163
+ for (const part of parts){
164
+ prev = `${prev}/${part}`;
165
+ if (middlewares[prev]) {
166
+ chain = chain.concat(middlewares[prev]);
167
+ }
168
+ }
169
+ return chain.map((file)=>(0, _common.getRealDefaultMod)(require(file)));
170
+ }
171
+ /**加载业务服务接口 */ function appRouter(router) {
172
+ function register(root) {
173
+ const middlewares = {};
174
+ const files = [];
175
+ collect(root, root, middlewares, files);
176
+ files.forEach(function(modPath) {
177
+ const route = normalize(modPath, root);
178
+ if (!route) {
179
+ (0, _config.log)("router", "warn", `Ignore invalid api module: ${modPath}`);
180
+ return;
181
+ }
182
+ const dirMws = resolveDirMiddlewares(route.api, middlewares);
183
+ router[route.method === "delete" ? "del" : route.method].apply(router, [
184
+ route.api,
185
+ ...dirMws,
186
+ ...route.middlewares,
187
+ route.handler
188
+ ]);
189
+ (0, _config.log)("router", `Handling API >>> [${route.method}] ${route.api}`);
190
+ });
191
+ }
192
+ // 框架内置业务
158
193
  var _p = _path.default.resolve(__dirname, API_BUSINESS_DIR);
159
- if ((0, _common).checkFileStat(_p)) {
160
- walk(_p, {}, processBusiness);
194
+ if ((0, _common.checkFileStat)(_p)) {
195
+ register(_p);
161
196
  }
162
- // 支持自定义 api
163
- _p = _path.default.resolve(process.cwd(), _defaultXConfig.default.businessDir, API_BUSINESS_DIR);
164
- if (process.cwd() !== __dirname && (0, _common).checkFileStat(_p)) {
165
- walk(_p, {}, processBusiness);
197
+ // 业务自定义业务
198
+ _p = _path.default.resolve(process.cwd(), _defaultxconfig.default.businessDir, API_BUSINESS_DIR);
199
+ if (process.cwd() !== __dirname && (0, _common.checkFileStat)(_p)) {
200
+ register(_p);
166
201
  }
167
- processBusiness = null;
168
202
  console.log("");
169
203
  }
170
- var _default = appRouter;
171
- exports.default = _default;
204
+ const _default = appRouter;