@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/@types/cluster.d.ts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import type { Server } from "http";
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import type Koa from "koa";
|
|
3
|
+
/**
|
|
4
|
+
* 启动服务监听
|
|
5
|
+
|
|
6
|
+
* master 且配置了 workers 时 fork 集群, 否则当前进程直接 listen
|
|
7
|
+
* @param app Koa 实例
|
|
8
|
+
* @return 直接监听时返回 http.Server, master fork 模式下无返回
|
|
9
|
+
*/
|
|
10
|
+
declare function start(app: Koa): Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
|
|
5
11
|
export default start;
|
|
12
|
+
/**
|
|
13
|
+
* 通知全部 worker 退出并等待其结束
|
|
14
|
+
* @param timeout 等待超时(毫秒), 超时后不再等待
|
|
15
|
+
*/
|
|
16
|
+
declare function shutdownWorkers(timeout?: number): Promise<void>;
|
|
17
|
+
export { shutdownWorkers };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import { sleep, labelReplace, fix0, numberFormat } from "@x-drive/utils";
|
|
3
2
|
import fs from "fs";
|
|
4
3
|
export { labelReplace, fix0, numberFormat, sleep };
|
|
@@ -83,7 +82,7 @@ export { toJsonp };
|
|
|
83
82
|
* 查找到文件时的处理函数
|
|
84
83
|
* @param tmpPath 文件地址
|
|
85
84
|
*/
|
|
86
|
-
|
|
85
|
+
type WalkCallback = (tmpPath: string, item: string) => void;
|
|
87
86
|
/**
|
|
88
87
|
* 递归处理文件夹
|
|
89
88
|
* @param path 文件目录
|
|
@@ -2,14 +2,14 @@ declare global {
|
|
|
2
2
|
namespace XLab {
|
|
3
3
|
/**定时任务配置对象 */
|
|
4
4
|
interface IConfigCronItem {
|
|
5
|
-
|
|
5
|
+
/**定时任务执行间隔, 单位秒 */
|
|
6
6
|
delay?: number;
|
|
7
7
|
/**是否启用 */
|
|
8
8
|
enable?: boolean;
|
|
9
9
|
}
|
|
10
10
|
interface IConfig {
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* 定时任务配置, 键名为任务文件名
|
|
13
13
|
* @see `@components/cron`
|
|
14
14
|
*/
|
|
15
15
|
crons?: {
|
|
@@ -25,7 +25,7 @@ interface ICronJob {
|
|
|
25
25
|
(): void;
|
|
26
26
|
/**定时任务 */
|
|
27
27
|
default?: () => void;
|
|
28
|
-
|
|
28
|
+
/**获取定时任务间隔时间, 单位毫秒 */
|
|
29
29
|
getDelay?: () => number;
|
|
30
30
|
/**获取定时任务开启状态 */
|
|
31
31
|
enable?: () => boolean;
|
|
@@ -42,5 +42,5 @@ export { on };
|
|
|
42
42
|
* 停止一个或所有的计时器
|
|
43
43
|
* @param name 计时器名称
|
|
44
44
|
*/
|
|
45
|
-
declare function kill(name
|
|
45
|
+
declare function kill(name?: string): void;
|
|
46
46
|
export { kill };
|
|
@@ -1,4 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
import log4js from "log4js";
|
|
2
|
+
/**日志配置 */
|
|
3
|
+
interface ILogConfig {
|
|
4
|
+
/**日志名称,文件日志的文件名 */
|
|
5
|
+
name?: string;
|
|
6
|
+
/**日志输出等级 */
|
|
7
|
+
level?: string;
|
|
8
|
+
/**文件日志存放目录 */
|
|
9
|
+
dir?: string;
|
|
10
|
+
/**是否输出文件日志 */
|
|
11
|
+
fileLog?: boolean;
|
|
12
|
+
/**自定义 layout 配置 */
|
|
13
|
+
layout?: Record<string, any>;
|
|
14
|
+
}
|
|
15
|
+
/**日志模块 */
|
|
16
|
+
declare class Log {
|
|
17
|
+
/**当前实例配置 */
|
|
18
|
+
private config;
|
|
19
|
+
/**日志实例缓存 */
|
|
20
|
+
private loggers;
|
|
21
|
+
constructor(config?: ILogConfig);
|
|
22
|
+
/**
|
|
23
|
+
* 获取分类日志实例
|
|
24
|
+
* @param cat 实例分类名称
|
|
25
|
+
* @return 日志实例对象
|
|
26
|
+
*/
|
|
27
|
+
getLogger(cat: string): log4js.Logger;
|
|
28
|
+
}
|
|
2
29
|
export { Log };
|
|
3
|
-
|
|
30
|
+
/**框架全局日志实例 */
|
|
31
|
+
declare const globalLog: Log;
|
|
4
32
|
export { globalLog };
|
|
33
|
+
/**
|
|
34
|
+
* 获取分类日志实例
|
|
35
|
+
* @param cat 实例分类名称
|
|
36
|
+
* @return 日志实例对象
|
|
37
|
+
*/
|
|
38
|
+
declare function getLogger(cat: string): log4js.Logger;
|
|
39
|
+
export { getLogger };
|
package/@types/config/index.d.ts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 通用日志方法, 只在 master 进程上输出
|
|
3
3
|
* @param cat 业务类型
|
|
4
4
|
* @param type 日志等级
|
|
5
5
|
*/
|
|
6
|
-
declare function commonLog(cat
|
|
6
|
+
declare function commonLog(cat?: string, type?: string, ...rest: any[]): void;
|
|
7
7
|
export { commonLog as log };
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* 装载系统配置
|
|
10
|
+
|
|
11
|
+
* 解析命令行参数与环境, 按「内置默认 -> 业务生产配置 -> 环境配置 -> 本地配置 -> 命令行参数」
|
|
12
|
+
* 顺序合并配置, 重复调用直接返回已装载的配置
|
|
10
13
|
*/
|
|
11
|
-
declare
|
|
12
|
-
export default
|
|
14
|
+
declare function loadConfig(): XLab.IConfig;
|
|
15
|
+
export default loadConfig;
|
|
16
|
+
/**获取系统配置对象 */
|
|
13
17
|
declare function get(): XLab.IConfig;
|
|
14
18
|
export { get };
|
|
15
19
|
/**更新配置 */
|
package/@types/custom.d.ts
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**自定义模块生命周期钩子 */
|
|
2
|
+
interface ICustomHooks {
|
|
3
|
+
/**服务装配前执行, 接收 custom 配置中声明的参数 */
|
|
4
|
+
setup?: (conf?: XLab.CompositeValue) => void | Promise<void>;
|
|
5
|
+
/**服务启动完成(listen 成功)后执行 */
|
|
6
|
+
ready?: () => void | Promise<void>;
|
|
7
|
+
/**服务退出前执行 */
|
|
8
|
+
shutdown?: () => void | Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export type { ICustomHooks };
|
|
11
|
+
/**
|
|
12
|
+
* 装载自定义业务模块并执行 setup 阶段
|
|
13
|
+
|
|
14
|
+
* 模块支持两种导出形态:
|
|
15
|
+
* 1. 导出函数, 视为 setup 钩子
|
|
16
|
+
* 2. 导出 `{ setup?, ready?, shutdown? }` 钩子对象
|
|
17
|
+
*/
|
|
18
|
+
declare function loadCustom(): Promise<void>;
|
|
19
|
+
export { loadCustom };
|
|
20
|
+
/**执行全部 ready 钩子 */
|
|
21
|
+
declare function runReady(): Promise<void>;
|
|
22
|
+
export { runReady };
|
|
23
|
+
/**执行全部 shutdown 钩子 */
|
|
24
|
+
declare function runShutdown(): Promise<void>;
|
|
25
|
+
export { runShutdown };
|
package/@types/dot-file.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 获取 `.xlab` 系列文件定义的环境数据
|
|
3
|
+
* @return 环境数据对象
|
|
4
|
+
*/
|
|
5
|
+
declare function getXlabEnv(): Record<string, XLab.JsonValue>;
|
|
6
|
+
export { getXlabEnv };
|
|
1
7
|
/**处理根目录下可能存在的配置文件 */
|
|
2
8
|
declare function processDotFile(env: string, logger: any): void;
|
|
3
9
|
export { processDotFile };
|
package/@types/global.d.ts
CHANGED
|
@@ -1,53 +1,5 @@
|
|
|
1
1
|
import type { InternalComponents } from "./components";
|
|
2
|
-
import type Koa from "koa";
|
|
3
2
|
declare global {
|
|
4
|
-
/**全局日志对象 */
|
|
5
|
-
var log: any;
|
|
6
|
-
/**只在 master 上输出的日志 */
|
|
7
|
-
var masterLog: any;
|
|
8
|
-
/**
|
|
9
|
-
* 获取应用实例对象
|
|
10
|
-
*/
|
|
11
|
-
function getApp(): Koa;
|
|
12
|
-
/**
|
|
13
|
-
* 获取内置组件
|
|
14
|
-
* @param name 模块名
|
|
15
|
-
* @return 模块对象
|
|
16
|
-
*/
|
|
17
|
-
function requireMod<T extends InternalComponents[K], K extends keyof InternalComponents>(name: K): T;
|
|
18
|
-
/**
|
|
19
|
-
* 全局获取 model 的方法
|
|
20
|
-
* @param name model 名称
|
|
21
|
-
* @return model 模块
|
|
22
|
-
*/
|
|
23
|
-
function requireModel<T extends XLab.IModels[K], K extends keyof XLab.IModels>(name: K): T;
|
|
24
|
-
/**
|
|
25
|
-
* 全局获取 service 的方法
|
|
26
|
-
* @param name service 名称
|
|
27
|
-
* @return service 模块
|
|
28
|
-
*/
|
|
29
|
-
function requireService<T extends XLab.IServices[K], K extends keyof XLab.IServices>(name: K): T;
|
|
30
|
-
/**
|
|
31
|
-
* 获取系统配置
|
|
32
|
-
*/
|
|
33
|
-
function getSysConfig(): XLab.IConfig;
|
|
34
|
-
/**
|
|
35
|
-
* 获取系统配置
|
|
36
|
-
* @param key 配置项
|
|
37
|
-
*/
|
|
38
|
-
function getSysConfig<T extends XLab.IConfig[K], K extends keyof XLab.IConfig>(key?: K): T;
|
|
39
|
-
/**
|
|
40
|
-
* 获取系统配置
|
|
41
|
-
* @param key 配置项
|
|
42
|
-
*/
|
|
43
|
-
function getSysConfig(key?: any): any;
|
|
44
|
-
/**
|
|
45
|
-
* 更新系统配置
|
|
46
|
-
* @param conf 配置项
|
|
47
|
-
*/
|
|
48
|
-
function setSysConfig(conf: XLab.IConfig): void;
|
|
49
|
-
/**全局注入挂在对象 */
|
|
50
|
-
var XLAB: Record<string, XLab.JsonValue>;
|
|
51
3
|
namespace XLab {
|
|
52
4
|
/**JSON 基本数据类型 */
|
|
53
5
|
type JsonValue = boolean | string | number | null | undefined | JsonArray | JsonObject;
|
|
@@ -94,6 +46,8 @@ declare global {
|
|
|
94
46
|
interface IConfig {
|
|
95
47
|
/**服务(应用)名称 */
|
|
96
48
|
name?: string;
|
|
49
|
+
/**服务标识, 默认取 name */
|
|
50
|
+
mark?: string;
|
|
97
51
|
/**版本 */
|
|
98
52
|
version?: string;
|
|
99
53
|
/**环境标识 */
|
|
@@ -120,15 +74,10 @@ declare global {
|
|
|
120
74
|
enableCron?: boolean;
|
|
121
75
|
/**是否允许 worker 上也执行定时任务 */
|
|
122
76
|
enableWorkerCron?: boolean;
|
|
123
|
-
/**
|
|
124
|
-
* 开启的中间件列表
|
|
125
|
-
* @deprecated since version 1.1.0, 已弃用, 请使用改用 `middlewares` 配置项
|
|
126
|
-
*/
|
|
127
|
-
middleware?: (string | (string | Record<string, any>)[])[];
|
|
128
77
|
/**开启的中间件列表 */
|
|
129
78
|
middlewares?: Record<string, boolean | MiddlewareConfig>;
|
|
130
79
|
/**自定模块配置 */
|
|
131
|
-
custom?: string[];
|
|
80
|
+
custom?: (string | [string, CompositeValue])[];
|
|
132
81
|
/**是否启用严格 ssl */
|
|
133
82
|
strictSSL?: boolean;
|
|
134
83
|
/**页端注入的 api 设置 */
|
|
@@ -163,6 +112,8 @@ declare global {
|
|
|
163
112
|
cron?: {
|
|
164
113
|
def?: number;
|
|
165
114
|
};
|
|
115
|
+
/**优雅退出时等待在途请求/worker 结束的超时时间(毫秒), 默认 10000 */
|
|
116
|
+
shutdownTimeout?: number;
|
|
166
117
|
/**注入参数列表 */
|
|
167
118
|
injection?: string[];
|
|
168
119
|
/**首页缓存时间 */
|
|
@@ -218,3 +169,42 @@ declare global {
|
|
|
218
169
|
}
|
|
219
170
|
}
|
|
220
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* 获取内置组件
|
|
174
|
+
* @param name 模块名
|
|
175
|
+
* @return 模块对象
|
|
176
|
+
*/
|
|
177
|
+
declare function requireMod<T extends InternalComponents[K], K extends keyof InternalComponents>(name: K): T;
|
|
178
|
+
export { requireMod };
|
|
179
|
+
/**
|
|
180
|
+
* 获取业务 model (business/@models)
|
|
181
|
+
* @param name model 名称
|
|
182
|
+
* @return model 模块
|
|
183
|
+
*/
|
|
184
|
+
declare function requireModel<T extends XLab.IModels[K], K extends keyof XLab.IModels>(name: K): T;
|
|
185
|
+
declare function requireModel(name: string): any;
|
|
186
|
+
export { requireModel };
|
|
187
|
+
/**
|
|
188
|
+
* 获取业务 service (business/@services)
|
|
189
|
+
* @param name service 名称
|
|
190
|
+
* @return service 模块
|
|
191
|
+
*/
|
|
192
|
+
declare function requireService<T extends XLab.IServices[K], K extends keyof XLab.IServices>(name: K): T;
|
|
193
|
+
declare function requireService(name: string): any;
|
|
194
|
+
export { requireService };
|
|
195
|
+
/**
|
|
196
|
+
* 获取全部系统配置
|
|
197
|
+
*/
|
|
198
|
+
declare function getSysConfig(): XLab.IConfig;
|
|
199
|
+
/**
|
|
200
|
+
* 获取系统配置
|
|
201
|
+
* @param key 配置项
|
|
202
|
+
*/
|
|
203
|
+
declare function getSysConfig<T extends XLab.IConfig[K], K extends keyof XLab.IConfig>(key?: K): T;
|
|
204
|
+
export { getSysConfig };
|
|
205
|
+
/**
|
|
206
|
+
* 更新系统配置
|
|
207
|
+
* @param conf 配置项
|
|
208
|
+
*/
|
|
209
|
+
declare function setSysConfig(conf: XLab.IConfig): void;
|
|
210
|
+
export { setSysConfig };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@x-9lab/xlab` 包入口
|
|
3
|
+
*
|
|
4
|
+
* v2 起框架 API 由此显式导出, 不再挂载到 global。
|
|
5
|
+
* 业务代码使用 `require("@x-9lab/xlab")` / `import ... from "@x-9lab/xlab"` 获取。
|
|
6
|
+
*/
|
|
7
|
+
export { app, getApp, boot, shutdown, exit } from "./server";
|
|
8
|
+
export { requireMod, requireModel, requireService, getSysConfig, setSysConfig } from "./global";
|
|
9
|
+
export { Log, globalLog, getLogger } from "./components/log";
|
|
10
|
+
export { log as masterLog } from "./config";
|
|
11
|
+
export { getXlabEnv } from "./dot-file";
|
|
12
|
+
export { defineApi } from "./router";
|
|
13
|
+
export type { IApiDefinition } from "./router";
|
|
14
|
+
export type { ICustomHooks } from "./custom";
|
|
15
|
+
export type { ICronJob } from "./components/cron";
|
|
16
|
+
export type { InternalComponents } from "./components";
|
|
17
|
+
import app from "./server";
|
|
18
|
+
export default app;
|
package/@types/init-env.d.ts
CHANGED
|
@@ -1,7 +1,2 @@
|
|
|
1
1
|
import type Koa from "koa";
|
|
2
|
-
|
|
3
|
-
* 处理函数
|
|
4
|
-
*/
|
|
5
|
-
declare function handler(ctx: Koa.Context, next: Koa.Next): Promise<void>;
|
|
6
|
-
export default function (): typeof handler;
|
|
7
|
-
export {};
|
|
2
|
+
export default function (): (ctx: Koa.Context, next: Koa.Next) => Promise<void>;
|
package/@types/router.d.ts
CHANGED
|
@@ -1,4 +1,29 @@
|
|
|
1
1
|
import type Router from "koa-router";
|
|
2
|
+
/**支持的请求方法, 同时也是「文件名即方法」约定支持的文件名 */
|
|
3
|
+
declare const HTTP_METHODS: readonly ["get", "post", "put", "delete", "patch", "head", "options", "all"];
|
|
4
|
+
/**支持的请求方法 */
|
|
5
|
+
type HttpMethod = typeof HTTP_METHODS[number];
|
|
6
|
+
/**路由定义对象 */
|
|
7
|
+
interface IApiDefinition {
|
|
8
|
+
/**API 请求方法, 不指定时由文件名约定或默认 get 决定 */
|
|
9
|
+
method?: HttpMethod;
|
|
10
|
+
/**业务 api 地址, 不指定时由文件路径生成 */
|
|
11
|
+
api?: string;
|
|
12
|
+
/**接口中间件 */
|
|
13
|
+
middleware?: Router.IMiddleware[];
|
|
14
|
+
/**业务处理函数 */
|
|
15
|
+
handler: Router.IMiddleware;
|
|
16
|
+
/**是否忽略 API 名称检测(不强制 /api 前缀) */
|
|
17
|
+
ignoreApiNameCheck?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export type { IApiDefinition };
|
|
20
|
+
/**
|
|
21
|
+
* 定义一个业务接口
|
|
22
|
+
|
|
23
|
+
* 运行时恒等返回, 仅为路由模块提供类型推导
|
|
24
|
+
*/
|
|
25
|
+
declare function defineApi(def: IApiDefinition): IApiDefinition;
|
|
26
|
+
export { defineApi };
|
|
2
27
|
/**加载业务服务接口 */
|
|
3
28
|
declare function appRouter(router: Router): void;
|
|
4
29
|
export default appRouter;
|
package/@types/server.d.ts
CHANGED
|
@@ -1,12 +1,34 @@
|
|
|
1
|
-
import "./global";
|
|
2
|
-
import "./init-env";
|
|
3
1
|
import koa from "koa";
|
|
2
|
+
/**服务实例 */
|
|
4
3
|
declare const app: koa<koa.DefaultState, koa.DefaultContext>;
|
|
5
4
|
export { app };
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
/**
|
|
6
|
+
* 获取应用实例对象
|
|
7
|
+
* @return 实例对象
|
|
8
|
+
*/
|
|
9
|
+
declare function getApp(): koa<koa.DefaultState, koa.DefaultContext>;
|
|
10
|
+
export { getApp };
|
|
11
|
+
/**
|
|
12
|
+
* 退出服务
|
|
13
|
+
|
|
14
|
+
* 停止定时任务 -> 通知 worker 退出(master) -> 等待在途请求 -> 执行 shutdown 钩子 -> 退出进程
|
|
15
|
+
* @param code 进程退出码
|
|
16
|
+
*/
|
|
17
|
+
declare function shutdown(code?: number): Promise<void>;
|
|
18
|
+
export { shutdown };
|
|
19
|
+
/**
|
|
20
|
+
* 退出服务
|
|
21
|
+
* @deprecated 请使用 shutdown
|
|
22
|
+
*/
|
|
10
23
|
declare function exit(): void;
|
|
11
24
|
export { exit };
|
|
25
|
+
/**
|
|
26
|
+
* 启动服务
|
|
27
|
+
|
|
28
|
+
* 按固定顺序执行启动阶段:
|
|
29
|
+
* initEnv -> loadConfig -> dotFile -> custom(setup) -> middleware
|
|
30
|
+
* -> router -> static/badRequest -> cron -> listen -> custom(ready)
|
|
31
|
+
*/
|
|
32
|
+
declare function boot(): Promise<void>;
|
|
33
|
+
export { boot };
|
|
12
34
|
export default app;
|
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
v1 → v2 升级指南
|
|
2
|
+
========
|
|
3
|
+
|
|
4
|
+
v2 是一次 breaking 升级,核心变化:**框架 API 不再挂载到 global,改为从包显式导入**;新增显式生命周期与优雅退出;路由定义形态收敛。本文按步骤指引业务完成迁移,预计单个业务的迁移工作量在半天以内。
|
|
5
|
+
|
|
6
|
+
## 前置要求
|
|
7
|
+
|
|
8
|
+
- Node.js **>= 20**(koa 3 要求 >= 18,Node 18 已 EOL)
|
|
9
|
+
- 部署脚本/容器基础镜像同步检查 Node 版本
|
|
10
|
+
|
|
11
|
+
## 升级步骤
|
|
12
|
+
|
|
13
|
+
### 1. 升级依赖
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
yarn add @x-9lab/xlab@^2.0.0
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
启动方式不变:`package.json` 里仍然是 `"start-dev": "xlab"`,`xlab.config.js`、`.xlab` 系列文件、`@server` 目录约定均不变。
|
|
20
|
+
|
|
21
|
+
### 2. 全局 API 改为导入(必做)
|
|
22
|
+
|
|
23
|
+
v1 挂在 global 上的所有 API 均已移除,对照表:
|
|
24
|
+
|
|
25
|
+
| v1(global) | v2(从 `@x-9lab/xlab` 导入) |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `log.getLogger(cat)` | `getLogger(cat)` |
|
|
28
|
+
| `masterLog(cat, type?, ...msg)` | `masterLog(cat, type?, ...msg)` |
|
|
29
|
+
| `getSysConfig(key?)` | `getSysConfig(key?)` |
|
|
30
|
+
| `setSysConfig(conf)` | `setSysConfig(conf)` |
|
|
31
|
+
| `requireMod(name)` | `requireMod(name)` |
|
|
32
|
+
| `requireModel(name)` | `requireModel(name)` |
|
|
33
|
+
| `requireService(name)` | `requireService(name)` |
|
|
34
|
+
| `getApp()` | `getApp()` |
|
|
35
|
+
| `XLAB`(`.xlab` 数据) | `getXlabEnv()` |
|
|
36
|
+
|
|
37
|
+
除 `log` 与 `XLAB` 外名称均不变,迁移就是在文件头部加一行导入:
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
// v1
|
|
41
|
+
const { ErrorTypes } = requireMod("return-code");
|
|
42
|
+
|
|
43
|
+
// v2
|
|
44
|
+
const { requireMod } = require("@x-9lab/xlab");
|
|
45
|
+
const { ErrorTypes } = requireMod("return-code");
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
// v1
|
|
50
|
+
const secret = XLAB.MY_SECRET;
|
|
51
|
+
log.getLogger("biz").info("hi");
|
|
52
|
+
|
|
53
|
+
// v2
|
|
54
|
+
const { getXlabEnv, getLogger } = require("@x-9lab/xlab");
|
|
55
|
+
const secret = getXlabEnv().MY_SECRET;
|
|
56
|
+
getLogger("biz").info("hi");
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
可以用下面的命令快速找出需要迁移的文件:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
grep -rln "requireMod\|requireModel\|requireService\|getSysConfig\|setSysConfig\|masterLog\|getApp\|XLAB\|log\.getLogger" @server/
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**类型支持不变**:`XLab` 命名空间仍是全局类型,`XLab.IModels` / `XLab.IServices` / `XLab.IConfig` 的 declaration merging 扩展方式与 v1 完全一致,业务的 `.d.ts` 无需修改。纯 JS 项目在 JSDoc 中使用 `XLab.IConfig` 等类型时,若编辑器提示找不到命名空间,在任一被 tsconfig/jsconfig 覆盖的文件中加一行 `/// <reference types="@x-9lab/xlab" />` 即可。
|
|
66
|
+
|
|
67
|
+
**注意**:业务代码里 `require("@x-9lab/xlab")` 拿到的必须与运行中的服务是同一个包实例(正常通过依赖安装即满足;不要全局安装一份再混用)。
|
|
68
|
+
|
|
69
|
+
### 3. 数组形式的路由改写(必做,如有)
|
|
70
|
+
|
|
71
|
+
数组导出(文件名当方法名)已移除,启动时命中会直接报错。改写方式二选一:
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
// v1: @server/business/user/post.js —— 数组形式
|
|
75
|
+
module.exports = [checkAuth, function (ctx) { /* ... */ }];
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
方式一,「文件名即方法」约定(v2 新增):文件名是 `get/post/put/delete/patch/head/options/all` 之一时,自动作为请求方法且不进入 api 路径。无中间件的场景直接导出函数即可:
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
// v2: @server/business/user/post.js -> POST /api/user
|
|
82
|
+
module.exports = function (ctx) { /* ... */ };
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
方式二,对象形式(推荐,配合 `defineApi` 获得类型推导):
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
// v2: @server/business/user/post.js -> POST /api/user
|
|
89
|
+
const { defineApi } = require("@x-9lab/xlab");
|
|
90
|
+
module.exports = defineApi({
|
|
91
|
+
"middleware": [checkAuth]
|
|
92
|
+
, handler(ctx) { /* ... */ }
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
函数与对象两种导出形态的行为与 v1 一致,无需改动。
|
|
97
|
+
|
|
98
|
+
### 4. custom 模块与生命周期钩子(可选)
|
|
99
|
+
|
|
100
|
+
v1 的「导出一个函数」形态仍然兼容(视为 `setup`)。v2 起可以导出钩子对象:
|
|
101
|
+
|
|
102
|
+
```js
|
|
103
|
+
// @server/custom/db.js
|
|
104
|
+
module.exports = {
|
|
105
|
+
async setup(conf) { /* 服务装配前, 收到 config.custom 里声明的参数 */ }
|
|
106
|
+
, async ready() { /* listen 成功后 */ }
|
|
107
|
+
, async shutdown() { /* 进程退出前, 用于释放连接等 */ }
|
|
108
|
+
};
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 5. 检查行为变化(必读)
|
|
112
|
+
|
|
113
|
+
以下变化不需要改代码,但需要确认对业务无影响:
|
|
114
|
+
|
|
115
|
+
1. **优雅退出**:收到 SIGTERM/SIGINT 后,服务会停止定时任务 → 等待在途请求(默认 10s,可用配置项 `shutdownTimeout` 调整,单位毫秒)→ 执行 `shutdown` 钩子 → 退出。**部署侧注意**:k8s 的 `terminationGracePeriodSeconds`、pm2 的 `kill_timeout` 需要大于 `shutdownTimeout`,否则会被强杀。
|
|
116
|
+
2. **worker 崩溃重启退避**:cluster 模式下 worker 10 秒内连续快速崩溃 5 次后不再自动拉起(v1 无条件立即重启,会造成 crash-loop)。依赖「无限重启」兜底的业务需要检查告警。
|
|
117
|
+
3. **business 根级 `$` 中间件开始生效**:v1 因 bug 从不生效,v2 按文档约定对全部业务路由生效。如果 business 根下有 `$` 目录,确认其中间件对所有接口执行是否符合预期。
|
|
118
|
+
4. **`crons` 按任务配置开始生效**:配置项 `crons: { 任务文件名: { delay, enable } }` v1 只有类型声明没有实现,v2 起真实生效,优先级高于任务模块自身的 `getDelay()` / `enable()`。注意 `delay` 单位是**秒**(与 `cron.def` 一致),模块 `getDelay()` 返回值仍是毫秒。
|
|
119
|
+
5. **`middleware` 数组配置移除**:v1.1.0 起已弃用且实际不被读取,配置里如仍保留该字段可直接删除,只认 `middlewares`。
|
|
120
|
+
6. **`custom` 的执行时机**:v1 对 async 自定义模块不等待;v2 会 await 完 `setup` 才继续装配中间件与路由,时序更明确。
|
|
121
|
+
7. **方法名文件的 api 路径会变化(重要)**:v1 中名为 `get.js` / `post.js` 等的函数或对象形态路由文件,文件名会进入 api 路径(如 `business/foo/post.js` → `POST /api/foo/post`);v2 按「文件名即方法」约定,文件名不再进入路径(→ `POST /api/foo`)。**这是路由地址的静默变更**,升级前用下面命令找出此类文件,逐个确认调用方,必要时用 `defineApi` 的 `api` 字段固定回原地址:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
find @server/business -type f \( -name "get.js" -o -name "post.js" -o -name "put.js" -o -name "delete.js" -o -name "patch.js" -o -name "head.js" -o -name "options.js" -o -name "all.js" \)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
8. **其余路由生成规则不变**:`index` 文件名去除、`@` 目录不参与路由、`:name` 路径参数等均与 v1 一致。
|
|
128
|
+
|
|
129
|
+
### 6. 验证
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# 开发环境跑起来,观察启动日志中的 API 注册与中间件加载是否与 v1 一致
|
|
133
|
+
yarn start-dev
|
|
134
|
+
|
|
135
|
+
# 逐条核对启动日志里的 "Handling API >>>" 输出与线上路由清单
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## 完整 API 一览(v2)
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
import {
|
|
142
|
+
boot, shutdown // 生命周期
|
|
143
|
+
, app, getApp // Koa 应用实例
|
|
144
|
+
, getSysConfig, setSysConfig
|
|
145
|
+
, requireMod, requireModel, requireService
|
|
146
|
+
, getLogger, masterLog, Log, globalLog
|
|
147
|
+
, getXlabEnv // .xlab 环境数据
|
|
148
|
+
, defineApi // 路由定义帮助函数
|
|
149
|
+
} from "@x-9lab/xlab";
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## 常见问题
|
|
153
|
+
|
|
154
|
+
**Q: 迁移时想先跑起来再逐步改,有没有临时兼容方案?**
|
|
155
|
+
可以在业务自己的 `@server/@env/index.js`(启动最早执行)里临时把 API 挂回 global,迁移完成后删除:
|
|
156
|
+
|
|
157
|
+
```js
|
|
158
|
+
const xlab = require("@x-9lab/xlab");
|
|
159
|
+
["requireMod", "requireModel", "requireService", "getSysConfig", "setSysConfig", "getApp"]
|
|
160
|
+
.forEach(name => { global[name] = xlab[name]; });
|
|
161
|
+
global.masterLog = xlab.masterLog;
|
|
162
|
+
global.log = xlab.globalLog;
|
|
163
|
+
global.XLAB = xlab.getXlabEnv();
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Q: `getApp()` 还能用吗?**
|
|
167
|
+
能,且不再是弃用状态;也可以直接 `const { app } = require("@x-9lab/xlab")`。
|
|
168
|
+
|
|
169
|
+
**Q: 日志格式变了吗?**
|
|
170
|
+
日志库从 log4js 1.x 升级到 6.x,框架通过默认 layout 保持了 v1 的输出格式(时间戳仍为 `yyyy-MM-dd hh:mm:ss.SSS` 空格分隔),日志采集无需调整;`new Log({ layout })` 自定义 layout 的行为不变。
|