@x-9lab/xlab 1.6.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/@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 -54
- 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 +170 -0
- package/README.md +37 -17
- package/dist/@config/config.dev.js +7 -3
- package/dist/@config/config.js +7 -3
- package/dist/@config/config.sand.js +7 -3
- package/dist/bin/watch.js +13 -9
- 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 -10
- 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 -19
- package/dist/router.js +174 -141
- package/dist/server.js +195 -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
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;
|
package/dist/server.js
CHANGED
|
@@ -2,120 +2,222 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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 app () {
|
|
13
|
+
return app;
|
|
14
|
+
},
|
|
15
|
+
get boot () {
|
|
16
|
+
return boot;
|
|
17
|
+
},
|
|
18
|
+
get default () {
|
|
19
|
+
return _default;
|
|
20
|
+
},
|
|
21
|
+
get exit () {
|
|
22
|
+
return exit;
|
|
23
|
+
},
|
|
24
|
+
get getApp () {
|
|
25
|
+
return getApp;
|
|
26
|
+
},
|
|
27
|
+
get shutdown () {
|
|
28
|
+
return shutdown;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const _log = require("./components/log");
|
|
32
|
+
const _cron = require("./components/cron");
|
|
33
|
+
const _defaultxconfig = /*#__PURE__*/ _interop_require_default(require("./default-x-config"));
|
|
34
|
+
const _dotfile = require("./dot-file");
|
|
35
|
+
const _config = /*#__PURE__*/ _interop_require_wildcard(require("./config"));
|
|
36
|
+
const _custom = require("./custom");
|
|
37
|
+
const _initenv = /*#__PURE__*/ _interop_require_default(require("./init-env"));
|
|
38
|
+
const _cluster = /*#__PURE__*/ _interop_require_wildcard(require("./cluster"));
|
|
39
|
+
const _router = /*#__PURE__*/ _interop_require_default(require("./router"));
|
|
40
|
+
const _middlewares = /*#__PURE__*/ _interop_require_default(require("./middlewares"));
|
|
41
|
+
const _badrequest = /*#__PURE__*/ _interop_require_default(require("./middleware/bad-request"));
|
|
42
|
+
const _utils = require("@x-drive/utils");
|
|
43
|
+
const _koastatic = /*#__PURE__*/ _interop_require_default(require("koa-static"));
|
|
44
|
+
const _koarouter = /*#__PURE__*/ _interop_require_default(require("koa-router"));
|
|
45
|
+
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
|
|
46
|
+
const _koa = /*#__PURE__*/ _interop_require_default(require("koa"));
|
|
47
|
+
function _interop_require_default(obj) {
|
|
23
48
|
return obj && obj.__esModule ? obj : {
|
|
24
49
|
default: obj
|
|
25
50
|
};
|
|
26
51
|
}
|
|
27
|
-
function
|
|
28
|
-
if (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
52
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
53
|
+
if (typeof WeakMap !== "function") return null;
|
|
54
|
+
var cacheBabelInterop = new WeakMap();
|
|
55
|
+
var cacheNodeInterop = new WeakMap();
|
|
56
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
57
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
58
|
+
})(nodeInterop);
|
|
59
|
+
}
|
|
60
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
61
|
+
if (!nodeInterop && obj && obj.__esModule) return obj;
|
|
62
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") return {
|
|
63
|
+
default: obj
|
|
64
|
+
};
|
|
65
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
66
|
+
if (cache && cache.has(obj)) return cache.get(obj);
|
|
67
|
+
var newObj = {
|
|
68
|
+
__proto__: null
|
|
69
|
+
};
|
|
70
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
71
|
+
for(var key in obj){
|
|
72
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
73
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
74
|
+
if (desc && (desc.get || desc.set)) Object.defineProperty(newObj, key, desc);
|
|
75
|
+
else newObj[key] = obj[key];
|
|
43
76
|
}
|
|
44
|
-
newObj.default = obj;
|
|
45
|
-
return newObj;
|
|
46
77
|
}
|
|
78
|
+
newObj.default = obj;
|
|
79
|
+
if (cache) cache.set(obj, newObj);
|
|
80
|
+
return newObj;
|
|
47
81
|
}
|
|
48
|
-
process.env.TZ = _config.default.timezone;
|
|
49
82
|
const logger = _log.globalLog.getLogger("system");
|
|
50
|
-
|
|
51
|
-
// 只在 master 上输出的日志
|
|
52
|
-
global.masterLog = _config.log;
|
|
53
|
-
// 服务实例
|
|
54
|
-
const app = new _koa.default();
|
|
55
|
-
/**
|
|
56
|
-
* 获取应用实例对象
|
|
57
|
-
* @deprecated v1.7.0 后将弃用,请直接从模块中引用
|
|
58
|
-
* @return 实例对象
|
|
59
|
-
*/ global.getApp = function() {
|
|
60
|
-
return app;
|
|
61
|
-
};
|
|
83
|
+
/**服务实例 */ const app = new _koa.default();
|
|
62
84
|
// 不输出X-Powered-By
|
|
63
85
|
// @ts-ignore
|
|
64
86
|
app.poweredBy = false;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
87
|
+
/**
|
|
88
|
+
* 获取应用实例对象
|
|
89
|
+
* @return 实例对象
|
|
90
|
+
*/ function getApp() {
|
|
91
|
+
return app;
|
|
68
92
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
/**http 服务实例, master fork 模式下为空 */ var server = null;
|
|
94
|
+
/**是否已启动 */ var booted = false;
|
|
95
|
+
/**是否正在退出 */ var shuttingDown = false;
|
|
96
|
+
/**
|
|
97
|
+
* 关闭 http 服务, 等待在途请求结束, 超时强制返回
|
|
98
|
+
* @param timeout 超时时间(毫秒)
|
|
99
|
+
*/ function closeServer(timeout) {
|
|
100
|
+
return new Promise(function(resolve) {
|
|
101
|
+
const timer = setTimeout(function() {
|
|
102
|
+
logger.warn(`等待在途请求结束超时(${timeout}ms), 强制关闭`);
|
|
103
|
+
resolve();
|
|
104
|
+
}, timeout);
|
|
105
|
+
server.close(function() {
|
|
106
|
+
clearTimeout(timer);
|
|
107
|
+
resolve();
|
|
108
|
+
});
|
|
109
|
+
// 主动断开空闲的 keep-alive 连接, 避免拖住 close 回调
|
|
110
|
+
if ((0, _utils.isExecutable)(server.closeIdleConnections)) {
|
|
111
|
+
server.closeIdleConnections();
|
|
112
|
+
}
|
|
113
|
+
});
|
|
80
114
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
115
|
+
/**
|
|
116
|
+
* 退出服务
|
|
117
|
+
|
|
118
|
+
* 停止定时任务 -> 通知 worker 退出(master) -> 等待在途请求 -> 执行 shutdown 钩子 -> 退出进程
|
|
119
|
+
* @param code 进程退出码
|
|
120
|
+
*/ async function shutdown(code = 0) {
|
|
121
|
+
if (shuttingDown) {
|
|
122
|
+
return;
|
|
84
123
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
124
|
+
shuttingDown = true;
|
|
125
|
+
const config = (0, _config.get)();
|
|
126
|
+
(0, _config.log)("system", `Shutting down (pid ${process.pid}) ...`);
|
|
127
|
+
try {
|
|
128
|
+
(0, _cron.kill)();
|
|
129
|
+
if (config.isMaster && config.workers) {
|
|
130
|
+
await (0, _cluster.shutdownWorkers)(config.shutdownTimeout);
|
|
91
131
|
}
|
|
132
|
+
if (server) {
|
|
133
|
+
await closeServer(config.shutdownTimeout || 10 * 1000);
|
|
134
|
+
}
|
|
135
|
+
await (0, _custom.runShutdown)();
|
|
136
|
+
} catch (e) {
|
|
137
|
+
logger.error("Shutdown error:", e);
|
|
92
138
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
(0, _cron).on(_path.default.resolve(process.cwd(), _defaultXConfig.default.businessDir, "cron"));
|
|
101
|
-
}
|
|
139
|
+
process.exit(code);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* 退出服务
|
|
143
|
+
* @deprecated 请使用 shutdown
|
|
144
|
+
*/ function exit() {
|
|
145
|
+
shutdown();
|
|
102
146
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
147
|
+
/**
|
|
148
|
+
* 启动服务
|
|
149
|
+
|
|
150
|
+
* 按固定顺序执行启动阶段:
|
|
151
|
+
* initEnv -> loadConfig -> dotFile -> custom(setup) -> middleware
|
|
152
|
+
* -> router -> static/badRequest -> cron -> listen -> custom(ready)
|
|
153
|
+
*/ async function boot() {
|
|
154
|
+
if (booted) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
booted = true;
|
|
158
|
+
// 1. 业务环境预处理(@server/@env)
|
|
159
|
+
(0, _initenv.default)();
|
|
160
|
+
// 2. 配置装载
|
|
161
|
+
const config = (0, _config.default)();
|
|
162
|
+
process.env.TZ = config.timezone;
|
|
163
|
+
// 3. .xlab 环境数据
|
|
164
|
+
(0, _dotfile.processDotFile)(config.env, logger);
|
|
165
|
+
// 4. 自定义初始化(setup 钩子)
|
|
166
|
+
if (config.custom) {
|
|
167
|
+
await (0, _custom.loadCustom)();
|
|
168
|
+
}
|
|
169
|
+
// 5. 中间件
|
|
170
|
+
(0, _middlewares.default)(app);
|
|
171
|
+
// 6. 业务路由
|
|
172
|
+
const koaRouter = new _koarouter.default();
|
|
173
|
+
app.use(koaRouter.routes());
|
|
174
|
+
(0, _router.default)(koaRouter);
|
|
175
|
+
// 7. 静态文件服务
|
|
176
|
+
var staticServeOpts = {};
|
|
177
|
+
if (config.isProd) {
|
|
178
|
+
staticServeOpts.maxage = config.staticMaxage;
|
|
179
|
+
}
|
|
180
|
+
staticServeOpts.setHeaders = function(res, filePath) {
|
|
181
|
+
if (config.isProd && config.staticHtmlFileMaxage && filePath.endsWith(".html")) {
|
|
182
|
+
res.setHeader("Cache-Control", `max-age=${config.staticHtmlFileMaxage}`);
|
|
183
|
+
}
|
|
184
|
+
if (config.staticCros) {
|
|
185
|
+
const { origin } = res.req.headers;
|
|
186
|
+
if (origin) {
|
|
187
|
+
res.setHeader("X-Cros-Static", origin);
|
|
188
|
+
res.setHeader("Access-Control-Allow-Origin", origin);
|
|
189
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
app.use((0, _koastatic.default)(_path.default.resolve(process.cwd(), config.root), staticServeOpts));
|
|
194
|
+
// 8. 异常状态处理中间件
|
|
195
|
+
app.use(_badrequest.default);
|
|
196
|
+
// 9. 定时任务
|
|
197
|
+
if (config.enableCron) {
|
|
198
|
+
if (config.isMaster || config.enableWorkerCron) {
|
|
199
|
+
(0, _cron.on)(_path.default.resolve(process.cwd(), _defaultxconfig.default.businessDir, "cron"));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// 10. 监听
|
|
203
|
+
server = (0, _cluster.default)(app);
|
|
204
|
+
// 11. 进程信号与异常处理
|
|
205
|
+
process.on("SIGTERM", function() {
|
|
206
|
+
shutdown();
|
|
207
|
+
}).on("SIGINT", function() {
|
|
208
|
+
shutdown();
|
|
209
|
+
}).on("uncaughtException", (err)=>{
|
|
106
210
|
logger.error(`uncaughtException:${err.message}\n`, err.stack);
|
|
107
211
|
}).on("unhandledRejection", (err)=>{
|
|
108
212
|
logger.error(`unhandledRejection:${err.message}\n`, err.stack);
|
|
109
213
|
});
|
|
214
|
+
// 12. ready 钩子
|
|
215
|
+
await (0, _custom.runReady)();
|
|
110
216
|
}
|
|
111
|
-
|
|
112
|
-
process.exit();
|
|
113
|
-
}
|
|
114
|
-
var _default = app;
|
|
115
|
-
exports.default = _default;
|
|
217
|
+
const _default = app;
|
|
116
218
|
if (require.main === module) {
|
|
117
|
-
boot()
|
|
219
|
+
boot().catch(function(err) {
|
|
220
|
+
logger.error("Boot failed:", err);
|
|
221
|
+
process.exit(1);
|
|
222
|
+
});
|
|
118
223
|
}
|
|
119
|
-
exports.app = app;
|
|
120
|
-
exports.boot = boot;
|
|
121
|
-
exports.exit = exit;
|