@x-9lab/xlab 1.0.13 → 1.2.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/config/index.d.ts +1 -1
- package/@types/global.d.ts +15 -1
- package/README.md +8 -1
- package/dist/config/index.js +1 -1
- package/dist/middlewares.js +54 -10
- package/dist/router.js +45 -3
- package/package.json +2 -2
package/@types/config/index.d.ts
CHANGED
package/@types/global.d.ts
CHANGED
|
@@ -83,6 +83,15 @@ declare global {
|
|
|
83
83
|
/**操作结果 */
|
|
84
84
|
success?: boolean;
|
|
85
85
|
}
|
|
86
|
+
/**中间件配置 */
|
|
87
|
+
type MiddlewareConfig = {
|
|
88
|
+
/**中间件名称 */
|
|
89
|
+
name?: string;
|
|
90
|
+
/**中间件位置 */
|
|
91
|
+
index?: number;
|
|
92
|
+
/**中间件配置 */
|
|
93
|
+
config?: Record<string, JsonValue>;
|
|
94
|
+
};
|
|
86
95
|
interface IConfig {
|
|
87
96
|
/**服务(应用)名称 */
|
|
88
97
|
name?: string;
|
|
@@ -110,8 +119,13 @@ declare global {
|
|
|
110
119
|
enableComboCache?: boolean;
|
|
111
120
|
/**是否开启定时任务 */
|
|
112
121
|
enableCron?: boolean;
|
|
113
|
-
|
|
122
|
+
/**
|
|
123
|
+
* 开启的中间件列表
|
|
124
|
+
* @deprecated since version 1.1.0, 1.3.0 后将完全删除
|
|
125
|
+
*/
|
|
114
126
|
middleware?: (string | (string | Record<string, any>)[])[];
|
|
127
|
+
/**开启的中间件列表 */
|
|
128
|
+
middlewares?: Record<string, boolean | MiddlewareConfig>;
|
|
115
129
|
/**自定模块配置 */
|
|
116
130
|
custom?: string[];
|
|
117
131
|
/**是否启用严格 ssl */
|
package/README.md
CHANGED
|
@@ -64,6 +64,11 @@ X-9lab 通用服务端
|
|
|
64
64
|
- `method` 接口类型,如 `get` 或 `post`
|
|
65
65
|
- `middleware` 接口中间件
|
|
66
66
|
- `handler` 接口处理函数
|
|
67
|
+
- 特殊文件夹
|
|
68
|
+
- 以 `@` 开头的文件夹, 该文件夹不会被当成接口文件夹,但可在正常的接口中作为普通模块使用
|
|
69
|
+
- 以 `$` 开头的文件夹, 该文件夹中的文件会成为后续接口的通用中间件,可以用于某类型业务的统一处理,如后台某些接口的额外身份处理。为了防止滥用,该文件夹不会递归查找,也就是说不支持子文件夹的组织形式。
|
|
70
|
+
- 整个 api 地址的每个父层都可以有独立的中间件文件,执行顺序会按照目录层级执行
|
|
71
|
+
- 中间件文件夹内的文件只会按照文件名做简单排序,因此请特别注意执行顺序是否符合自己的预期,或采用带序号的文件名
|
|
67
72
|
- 自定义逻辑,存放于 `custom` 目录,模块需要导出一个函数作为执行入口
|
|
68
73
|
- 中间件,存放于 `middleware` 目录
|
|
69
74
|
- 定时任务,存放于 `cron` 目录
|
|
@@ -175,7 +180,9 @@ X-9lab 通用服务端
|
|
|
175
180
|
|staticHtmlFileMaxage|`number`|0|静态 html 文件缓存时间|
|
|
176
181
|
|enableComboCache|`boolean`|true|是否开启 Combo 缓存|
|
|
177
182
|
|enableCron|`boolean`|false|是否开启定时任务|
|
|
178
|
-
|middleware|`Array<string | (string | Record<string, any>)[]>`|[]
|
|
183
|
+
|middleware|`Array<string | (string | Record<string, any>)[]>`|[]|开启的中间件列表。因不方便合并替换,v1.1.0 开始建议使用 `middlewares` 来配置 |
|
|
184
|
+
|middlewares|`Record<string, MiddlewareConfig>`|{}|开启的中间件列表 |
|
|
185
|
+
||MiddlewareConfig||`index` 用于定义中间件位置,不提供将使用配置对象中的默认顺序<br/> `name` 中间件名称,不提供将使用配置对象的键名<br/>`config` 中间件配置|
|
|
179
186
|
|custom|`string[]`||自定模块配置|
|
|
180
187
|
|strictSSL|`boolean`||是否启用严格 ssl|
|
|
181
188
|
|apis|`Record<string, string>`|{}|页端注入的 api 设置|
|
package/dist/config/index.js
CHANGED
package/dist/middlewares.js
CHANGED
|
@@ -25,20 +25,64 @@ const cwd = process.cwd();
|
|
|
25
25
|
"compress": true,
|
|
26
26
|
"cors": true
|
|
27
27
|
};
|
|
28
|
+
/**兼容老的中间件声明 */ function compatibleWithOldVer(list) {
|
|
29
|
+
const middlewares = {};
|
|
30
|
+
list.forEach((item, index)=>{
|
|
31
|
+
var subject;
|
|
32
|
+
var name;
|
|
33
|
+
subject = {
|
|
34
|
+
index
|
|
35
|
+
};
|
|
36
|
+
if ((0, _utils.isString)(item)) {
|
|
37
|
+
name = item;
|
|
38
|
+
} else if ((0, _utils.isArray)(item)) {
|
|
39
|
+
name = item[0];
|
|
40
|
+
if (item[1]) {
|
|
41
|
+
subject.config = item[1];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
middlewares[name] = subject;
|
|
45
|
+
});
|
|
46
|
+
return middlewares;
|
|
47
|
+
}
|
|
48
|
+
/**获取中间件加载执行列表 */ function getExeList() {
|
|
49
|
+
const config = getSysConfig();
|
|
50
|
+
var mConfig;
|
|
51
|
+
if (config.middlewares) {
|
|
52
|
+
mConfig = config.middlewares;
|
|
53
|
+
} else if ((0, _utils.isArray)(config.middleware) && config.middleware.length) {
|
|
54
|
+
masterLog("middlewares", "warn", "middleware 配置已弃用并将在 v1.3.0 之后删除,请使用 middlewares 配置中间件");
|
|
55
|
+
mConfig = compatibleWithOldVer(config.middleware);
|
|
56
|
+
} else {
|
|
57
|
+
mConfig = null;
|
|
58
|
+
}
|
|
59
|
+
if (mConfig) {
|
|
60
|
+
return Object.keys(mConfig).filter((key)=>(0, _utils.isBoolean)(mConfig[key]) ? mConfig[key] : true).map((key, index)=>{
|
|
61
|
+
if ((0, _utils.isBoolean)(mConfig[key])) {
|
|
62
|
+
mConfig[key] = {};
|
|
63
|
+
}
|
|
64
|
+
if (!(0, _utils.isString)(mConfig[key].name)) {
|
|
65
|
+
mConfig[key].name = key;
|
|
66
|
+
}
|
|
67
|
+
if (!(0, _utils.isNumber)(mConfig[key].index)) {
|
|
68
|
+
mConfig[key].index = index;
|
|
69
|
+
}
|
|
70
|
+
return mConfig[key];
|
|
71
|
+
}).sort((now, next)=>now.index - next.index);
|
|
72
|
+
}
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
28
75
|
// [最后3个中间件固定是 系统路由,静态文件服务,错误请求处理模块]
|
|
29
76
|
/**加载中间件 */ function loadMiddleware(app) {
|
|
30
|
-
const
|
|
31
|
-
if ((0, _utils.isArray)(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const conf = isSrtItem ? null : item[1];
|
|
36
|
-
if (INTERNAL_MIDDLEWARE[name]) {
|
|
37
|
-
app.use((0, _common.getRealDefaultMod)(require(`./middleware/${name}`))(conf));
|
|
77
|
+
const list = getExeList();
|
|
78
|
+
if ((0, _utils.isArray)(list) && list.length) {
|
|
79
|
+
list.forEach((item)=>{
|
|
80
|
+
if (INTERNAL_MIDDLEWARE[item.name]) {
|
|
81
|
+
app.use((0, _common.getRealDefaultMod)(require(`./middleware/${item.name}`))(item.config));
|
|
38
82
|
} else {
|
|
39
|
-
app.use((0, _common.getRealDefaultMod)(require(`${cwd}/${_defaultXConfig.default.businessDir}/middleware/${name}`))(
|
|
83
|
+
app.use((0, _common.getRealDefaultMod)(require(`${cwd}/${_defaultXConfig.default.businessDir}/middleware/${item.name}`))(item.config));
|
|
40
84
|
}
|
|
41
|
-
masterLog(`MIDDLEWARE >>> [${name}] launch`);
|
|
85
|
+
masterLog(`MIDDLEWARE >>> [${item.name}] launch`);
|
|
42
86
|
});
|
|
43
87
|
console.log("");
|
|
44
88
|
}
|
package/dist/router.js
CHANGED
|
@@ -10,6 +10,7 @@ const _utils = require("@x-drive/utils");
|
|
|
10
10
|
const _common = require("./components/common");
|
|
11
11
|
const _defaultXConfig = /*#__PURE__*/ _interopRequireDefault(require("./default-x-config"));
|
|
12
12
|
const _path = /*#__PURE__*/ _interopRequireDefault(require("path"));
|
|
13
|
+
const _fs = /*#__PURE__*/ _interopRequireDefault(require("fs"));
|
|
13
14
|
function _interopRequireDefault(obj) {
|
|
14
15
|
return obj && obj.__esModule ? obj : {
|
|
15
16
|
default: obj
|
|
@@ -21,9 +22,41 @@ function _interopRequireDefault(obj) {
|
|
|
21
22
|
}
|
|
22
23
|
return `/api${api}`;
|
|
23
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* 递归处理文件夹
|
|
27
|
+
* @param path 文件目录
|
|
28
|
+
* @param middlewares 接口中间件
|
|
29
|
+
* @param callback 查找到文件时的处理函数
|
|
30
|
+
*/ function walk(dir, middlewares, callback) {
|
|
31
|
+
var files = _fs.default.readdirSync(dir);
|
|
32
|
+
files.forEach(function(item) {
|
|
33
|
+
if (!item.startsWith(".") && !item.endsWith(".d.ts")) {
|
|
34
|
+
var tmpPath = _path.default.join(dir, item);
|
|
35
|
+
var stats = _fs.default.statSync(tmpPath);
|
|
36
|
+
if (stats.isDirectory() && item.startsWith("$")) {
|
|
37
|
+
// 接口级别中间件
|
|
38
|
+
let middlewaresFiles = _fs.default.readdirSync(tmpPath);
|
|
39
|
+
middlewaresFiles.forEach(function(name) {
|
|
40
|
+
let tmpMwPath = _path.default.join(tmpPath, name);
|
|
41
|
+
let fileStat = _fs.default.statSync(tmpMwPath);
|
|
42
|
+
if (!fileStat.isDirectory() && !item.startsWith(".") && !item.endsWith(".d.ts")) {
|
|
43
|
+
middlewares.push(tmpMwPath);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
// 简单做下排序
|
|
47
|
+
middlewares.sort();
|
|
48
|
+
}
|
|
49
|
+
if (stats.isDirectory() && !item.startsWith("@") && !item.startsWith("$")) {
|
|
50
|
+
walk(tmpPath, middlewares, callback);
|
|
51
|
+
} else if (!stats.isDirectory()) {
|
|
52
|
+
callback(tmpPath, item, middlewares);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
24
57
|
/**加载业务服务接口 */ function appRouter(router) {
|
|
25
58
|
const IS_API_REGEXP = /^\/api\//;
|
|
26
|
-
var processBusiness = function(modPath, item) {
|
|
59
|
+
var processBusiness = function(modPath, item, middlewares) {
|
|
27
60
|
var mod = require(_path.default.resolve(modPath));
|
|
28
61
|
if (mod) {
|
|
29
62
|
mod = (0, _common.getRealDefaultMod)(mod);
|
|
@@ -84,17 +117,26 @@ function _interopRequireDefault(obj) {
|
|
|
84
117
|
modName = "get";
|
|
85
118
|
}
|
|
86
119
|
}
|
|
120
|
+
if (middlewares && middlewares.length) {
|
|
121
|
+
let mws = middlewares.map((name)=>(0, _common.getRealDefaultMod)(require(name)));
|
|
122
|
+
mod.splice.apply(mod, [
|
|
123
|
+
1,
|
|
124
|
+
0,
|
|
125
|
+
...mws
|
|
126
|
+
]);
|
|
127
|
+
mws = null;
|
|
128
|
+
}
|
|
87
129
|
router[modName].apply(router, mod);
|
|
88
130
|
masterLog("router", `Handling API >>> [${modName}] ${api}`);
|
|
89
131
|
}
|
|
90
132
|
};
|
|
91
133
|
// 业务基本目录
|
|
92
134
|
var _p = _path.default.resolve(__dirname, "business");
|
|
93
|
-
|
|
135
|
+
walk(_p, [], processBusiness);
|
|
94
136
|
// 支持自定义 api
|
|
95
137
|
_p = _path.default.resolve(process.cwd(), _defaultXConfig.default.businessDir, "business");
|
|
96
138
|
if (process.cwd() !== __dirname && (0, _common.checkFileStat)(_p)) {
|
|
97
|
-
|
|
139
|
+
walk(_p, [], processBusiness);
|
|
98
140
|
}
|
|
99
141
|
processBusiness = null;
|
|
100
142
|
console.log("");
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@x-9lab/xlab",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "9lab 服务端模块",
|
|
5
|
-
"versionDesc": "
|
|
5
|
+
"versionDesc": "业务 api 文件夹支持接口级别通用中间件定义",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "swc src -D ./src/bin --config-file .swcrc -d dist -w",
|
|
8
8
|
"compile": "swc src -D ./src/bin --config-file .swcrc -d dist",
|