@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.
- package/@types/cluster.d.ts +15 -3
- package/@types/components/common/index.d.ts +1 -2
- package/@types/components/cron/index.d.ts +4 -4
- package/@types/components/log/index.d.ts +37 -2
- package/@types/config/index.d.ts +9 -5
- package/@types/custom.d.ts +25 -3
- package/@types/dot-file.d.ts +6 -0
- package/@types/global.d.ts +44 -56
- package/@types/index.d.ts +18 -0
- package/@types/init-env.d.ts +3 -1
- package/@types/middleware/handle-pre-dir.d.ts +1 -5
- package/@types/middleware/request-filter.d.ts +0 -1
- package/@types/middleware/service-mark.d.ts +1 -6
- package/@types/router.d.ts +25 -0
- package/@types/server.d.ts +28 -6
- package/MIGRATION.md +182 -0
- package/README.md +105 -86
- package/dist/@config/config.dev.js +7 -3
- package/dist/@config/config.js +7 -4
- package/dist/@config/config.sand.js +7 -3
- package/dist/bin/watch.js +36 -16
- package/dist/cluster.js +121 -44
- package/dist/components/assets/index.js +9 -5
- package/dist/components/cluster/index.js +17 -4
- package/dist/components/common/index.js +65 -45
- package/dist/components/cron/index.js +50 -27
- package/dist/components/header/index.js +32 -17
- package/dist/components/header/time.js +6 -2
- package/dist/components/index.js +1 -1
- package/dist/components/log/index.js +91 -87
- package/dist/components/mime/index.js +6 -2
- package/dist/components/return-code/index.js +33 -18
- package/dist/components/uuid/index.js +22 -13
- package/dist/config/getEnv.js +9 -5
- package/dist/config/index.js +98 -66
- package/dist/config/process-custom-config-files.js +26 -22
- package/dist/config/process-def-config-file.js +15 -11
- package/dist/custom.js +77 -28
- package/dist/default-x-config.js +9 -5
- package/dist/dot-file.js +42 -17
- package/dist/global.js +37 -31
- package/dist/index.js +100 -0
- package/dist/init-env.js +17 -9
- package/dist/middleware/@bin/html-filter.js +19 -7
- package/dist/middleware/bad-request.js +12 -8
- package/dist/middleware/compress.js +11 -7
- package/dist/middleware/cors.js +20 -7
- package/dist/middleware/fresh-filter.js +13 -7
- package/dist/middleware/handle-pre-dir.js +22 -17
- package/dist/middleware/request-filter.js +39 -25
- package/dist/middleware/service-mark.js +22 -25
- package/dist/middlewares.js +22 -20
- package/dist/router.js +174 -141
- package/dist/server.js +202 -93
- package/package.json +25 -29
- package/@types/business/utils/cookie/1.1.0/clean/index.d.ts +0 -3
- package/@types/business/utils/cookie/1.1.0/clean/js/index.d.ts +0 -2
- package/@types/components/cache/index.d.ts +0 -2
- package/@types/components/cache/lru.d.ts +0 -21
- package/@types/components/html-processor/index.d.ts +0 -9
- package/@types/components/injection/index.d.ts +0 -25
- package/@types/components/js-processor/index.d.ts +0 -5
- package/@types/components/md5/index.d.ts +0 -2
- package/@types/components/platform/index.d.ts +0 -21
- package/@types/components/proxy/index.d.ts +0 -26
- package/@types/components/querystring/index.d.ts +0 -25
- package/@types/components/redirect/index.d.ts +0 -11
- package/@types/components/request/helper.d.ts +0 -3
- package/@types/components/request/index.d.ts +0 -51
- package/@types/components/request/resolve-uri.d.ts +0 -6
- package/@types/components/version/index.d.ts +0 -26
- 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
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
|
14
|
-
if (
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
6
|
-
|
|
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
|
-
|
|
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
|
}
|
package/dist/middlewares.js
CHANGED
|
@@ -2,18 +2,23 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
-
exports
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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 =
|
|
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
|
|
35
|
-
|
|
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
|
|
43
|
+
if (!(0, _utils.isString)(mConfig[key].name)) {
|
|
40
44
|
mConfig[key].name = key;
|
|
41
45
|
}
|
|
42
|
-
if (!(0, _utils
|
|
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
|
|
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
|
|
60
|
+
app.use((0, _common.getRealDefaultMod)(require(`./middleware/${item.name}`))(item.config));
|
|
58
61
|
} else {
|
|
59
|
-
app.use((0, _common
|
|
62
|
+
app.use((0, _common.getRealDefaultMod)(require(`${cwd}/${_defaultxconfig.default.businessDir}/middleware/${item.name}`))(item.config));
|
|
60
63
|
}
|
|
61
|
-
|
|
64
|
+
(0, _config.log)(`MIDDLEWARE >>> [${item.name}] launch`);
|
|
62
65
|
});
|
|
63
66
|
console.log("");
|
|
64
67
|
}
|
|
65
68
|
}
|
|
66
|
-
|
|
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
|
-
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
*
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
middlewares
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
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 (
|
|
144
|
-
|
|
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
|
|
160
|
-
|
|
194
|
+
if ((0, _common.checkFileStat)(_p)) {
|
|
195
|
+
register(_p);
|
|
161
196
|
}
|
|
162
|
-
//
|
|
163
|
-
_p = _path.default.resolve(process.cwd(),
|
|
164
|
-
if (process.cwd() !== __dirname && (0, _common
|
|
165
|
-
|
|
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
|
-
|
|
171
|
-
exports.default = _default;
|
|
204
|
+
const _default = appRouter;
|