@maiyunnet/kebab 2.0.7 → 2.0.8
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/index.d.ts +11 -1
- package/index.js +13 -1
- package/lib/buffer.d.ts +25 -0
- package/lib/buffer.js +30 -5
- package/lib/captcha.d.ts +15 -0
- package/lib/captcha.js +20 -0
- package/lib/consistent.d.ts +51 -0
- package/lib/consistent.js +59 -0
- package/lib/core.d.ts +134 -0
- package/lib/core.js +176 -0
- package/lib/crypto.d.ts +75 -6
- package/lib/crypto.js +206 -38
- package/lib/db.d.ts +104 -0
- package/lib/db.js +126 -0
- package/lib/dns.d.ts +51 -0
- package/lib/dns.js +54 -2
- package/lib/fs.d.ts +100 -0
- package/lib/fs.js +118 -0
- package/lib/jwt.d.ts +43 -0
- package/lib/jwt.js +45 -0
- package/lib/kv.d.ts +362 -0
- package/lib/kv.js +377 -0
- package/lib/lan.d.ts +6 -0
- package/lib/lan.js +7 -0
- package/lib/net/formdata.d.ts +38 -0
- package/lib/net/formdata.js +43 -0
- package/lib/net/request.d.ts +62 -0
- package/lib/net/request.js +57 -0
- package/lib/net/response.d.ts +21 -0
- package/lib/net/response.js +16 -0
- package/lib/net.d.ts +86 -0
- package/lib/net.js +140 -0
- package/lib/s3.d.ts +52 -0
- package/lib/s3.js +51 -0
- package/lib/scan.d.ts +52 -0
- package/lib/scan.js +84 -0
- package/lib/session.d.ts +31 -0
- package/lib/session.js +52 -1
- package/lib/sql.d.ts +176 -0
- package/lib/sql.js +287 -2
- package/lib/ssh/sftp.d.ts +106 -0
- package/lib/ssh/sftp.js +106 -0
- package/lib/ssh/shell.d.ts +37 -0
- package/lib/ssh/shell.js +31 -0
- package/lib/ssh.d.ts +32 -0
- package/lib/ssh.js +32 -0
- package/lib/text.d.ts +131 -0
- package/lib/text.js +188 -0
- package/lib/time.d.ts +53 -0
- package/lib/time.js +55 -0
- package/lib/ws.d.ts +68 -0
- package/lib/ws.js +74 -0
- package/lib/zip.d.ts +53 -0
- package/lib/zip.js +73 -0
- package/lib/zlib.d.ts +76 -0
- package/lib/zlib.js +78 -0
- package/main.d.ts +6 -1
- package/main.js +11 -1
- package/package.json +1 -1
- package/sys/child.js +104 -0
- package/sys/cmd.js +28 -0
- package/sys/ctr.d.ts +166 -0
- package/sys/ctr.js +177 -0
- package/sys/master.js +63 -0
- package/sys/mod.d.ts +266 -0
- package/sys/mod.js +335 -0
- package/sys/route.d.ts +34 -0
- package/sys/route.js +164 -0
- package/www/example/ctr/test.d.ts +3 -0
- package/www/example/ctr/test.js +63 -1
- package/www/example/mod/test.js +14 -0
- package/www/example/mod/testdata.js +9 -0
- package/www/example/ws/test.js +1 -0
- package/.VSCodeCounter/2025-02-14_14-46-44/details.md +0 -82
- package/.VSCodeCounter/2025-02-14_14-46-44/diff-details.md +0 -15
- package/.VSCodeCounter/2025-02-14_14-46-44/diff.csv +0 -2
- package/.VSCodeCounter/2025-02-14_14-46-44/diff.md +0 -19
- package/.VSCodeCounter/2025-02-14_14-46-44/diff.txt +0 -22
- package/.VSCodeCounter/2025-02-14_14-46-44/results.csv +0 -69
- package/.VSCodeCounter/2025-02-14_14-46-44/results.json +0 -1
- package/.VSCodeCounter/2025-02-14_14-46-44/results.md +0 -48
- package/.VSCodeCounter/2025-02-14_14-46-44/results.txt +0 -118
- package/.vscode/tasks.json +0 -15
package/sys/master.js
CHANGED
|
@@ -33,9 +33,15 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
/**
|
|
37
|
+
* Project: Kebab, User: JianSuoQiYue
|
|
38
|
+
* Date: 2019-5-2 21:03:42
|
|
39
|
+
* Last: 2020-3-7 10:33:17, 2022-07-22 13:40:10, 2022-09-06 22:40:58, 2024-2-7 01:44:59, 2024-7-2 15:17:09, 2025-6-13 13:06:43
|
|
40
|
+
*/
|
|
36
41
|
const os = __importStar(require("os"));
|
|
37
42
|
const cluster = __importStar(require("cluster"));
|
|
38
43
|
const http = __importStar(require("http"));
|
|
44
|
+
// --- 库和定义 ---
|
|
39
45
|
const kebab = __importStar(require("../index"));
|
|
40
46
|
const sRoute = __importStar(require("../sys/route"));
|
|
41
47
|
const lCore = __importStar(require("../lib/core"));
|
|
@@ -44,22 +50,31 @@ const lText = __importStar(require("../lib/text"));
|
|
|
44
50
|
const lCrypto = __importStar(require("../lib/crypto"));
|
|
45
51
|
const lTime = __importStar(require("../lib/time"));
|
|
46
52
|
const lZip = __importStar(require("../lib/zip"));
|
|
53
|
+
/** --- 当前运行中的子进程列表 --- */
|
|
47
54
|
const workerList = {};
|
|
55
|
+
/**
|
|
56
|
+
* --- 最终调用执行的函数块 ---
|
|
57
|
+
*/
|
|
48
58
|
async function run() {
|
|
59
|
+
// --- 读取配置文件 ---
|
|
49
60
|
const configContent = await lFs.getContent(kebab.CONF_CWD + 'config.json', 'utf8');
|
|
50
61
|
if (!configContent) {
|
|
51
62
|
throw `File '${kebab.CONF_CWD}config.json' not found.`;
|
|
52
63
|
}
|
|
64
|
+
/** --- 系统 config.json --- */
|
|
53
65
|
const config = lText.parseJson(configContent);
|
|
54
66
|
for (const key in config) {
|
|
55
67
|
lCore.globalConfig[key] = config[key];
|
|
56
68
|
}
|
|
69
|
+
// --- 监听 RPC 命令 ---
|
|
57
70
|
createRpcListener();
|
|
71
|
+
// --- 30 秒检测一次是否有丢失的子进程 ---
|
|
58
72
|
setInterval(function () {
|
|
59
73
|
checkWorkerLost().catch(function (e) {
|
|
60
74
|
lCore.display('[master] [run] [checkWorkerLost]', e);
|
|
61
75
|
});
|
|
62
76
|
}, 30000);
|
|
77
|
+
// --- 启动进程 ---
|
|
63
78
|
const cpuLength = os.cpus().length;
|
|
64
79
|
lCore.display('[master] [run] CPU LENGTH: ' + cpuLength.toString());
|
|
65
80
|
const cpuLengthMax = cpuLength > lCore.globalConfig.max ? lCore.globalConfig.max : cpuLength;
|
|
@@ -67,16 +82,20 @@ async function run() {
|
|
|
67
82
|
await createChildProcess(i);
|
|
68
83
|
}
|
|
69
84
|
cluster.default.on('listening', function (worker, address) {
|
|
85
|
+
// --- 子进程开始监听 ---
|
|
70
86
|
lCore.display(`[master] Listening: worker ${worker.process.pid ?? 'undefined'}, Address: ${address.address}:${address.port}.`);
|
|
71
87
|
}).on('exit', function (worker, code) {
|
|
72
88
|
(async function () {
|
|
73
89
|
if (!worker.process.pid) {
|
|
74
90
|
return;
|
|
75
91
|
}
|
|
92
|
+
// --- 有子线程退出 ---
|
|
76
93
|
if (code === 0) {
|
|
94
|
+
// --- 正常关闭,证明关闭前主进程已经重启新进程了,这里无需在 fork ---
|
|
77
95
|
lCore.display(`[master] Worker ${worker.process.pid} has been disconnected.`);
|
|
78
96
|
}
|
|
79
97
|
else {
|
|
98
|
+
// --- 中断,致命错误,需要重新启动一个新线程 ---
|
|
80
99
|
lCore.display(`[master] Worker ${worker.process.pid} has collapsed.`);
|
|
81
100
|
const cpu = workerList[worker.process.pid].cpu;
|
|
82
101
|
delete workerList[worker.process.pid];
|
|
@@ -87,10 +106,15 @@ async function run() {
|
|
|
87
106
|
});
|
|
88
107
|
});
|
|
89
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* --- 创建 RPC 监听,用来监听 cmd 或局域网传递过来的数据,并广播给所有子进程,cmd 部分代码在 cmd 中实现 ---
|
|
111
|
+
*/
|
|
90
112
|
function createRpcListener() {
|
|
91
113
|
http.createServer(function (req, res) {
|
|
92
114
|
(async function () {
|
|
115
|
+
/** --- 当前时间戳 --- */
|
|
93
116
|
const time = lTime.stamp();
|
|
117
|
+
/** --- cmd 数据对象 --- */
|
|
94
118
|
const cmd = lCrypto.aesDecrypt((req.url ?? '').slice(1), lCore.globalConfig.rpcSecret);
|
|
95
119
|
if (!cmd) {
|
|
96
120
|
res.end('Error');
|
|
@@ -111,6 +135,7 @@ function createRpcListener() {
|
|
|
111
135
|
}
|
|
112
136
|
switch (msg.action) {
|
|
113
137
|
case 'reload': {
|
|
138
|
+
// --- 为所有子线程发送 reload 信息 ---
|
|
114
139
|
for (const pid in workerList) {
|
|
115
140
|
workerList[pid].worker.send({
|
|
116
141
|
'action': 'reload'
|
|
@@ -119,16 +144,20 @@ function createRpcListener() {
|
|
|
119
144
|
break;
|
|
120
145
|
}
|
|
121
146
|
case 'restart': {
|
|
147
|
+
// --- 为所有子线程发送 stop 信息 ---
|
|
122
148
|
for (const pid in workerList) {
|
|
123
149
|
workerList[pid].worker.send({
|
|
124
150
|
'action': 'stop'
|
|
125
151
|
});
|
|
152
|
+
// --- 开启新线程 ---
|
|
126
153
|
await createChildProcess(workerList[pid].cpu);
|
|
154
|
+
// --- 删除记录 ---
|
|
127
155
|
delete workerList[pid];
|
|
128
156
|
}
|
|
129
157
|
break;
|
|
130
158
|
}
|
|
131
159
|
case 'global': {
|
|
160
|
+
// --- 为所有子进程更新 global 变量 ---
|
|
132
161
|
for (const pid in workerList) {
|
|
133
162
|
workerList[pid].worker.send({
|
|
134
163
|
'action': 'global',
|
|
@@ -136,6 +165,7 @@ function createRpcListener() {
|
|
|
136
165
|
'data': msg.data
|
|
137
166
|
});
|
|
138
167
|
}
|
|
168
|
+
// --- 更新 master 的数据 ---
|
|
139
169
|
if (msg.data === undefined || msg.data === null) {
|
|
140
170
|
delete lCore.global[msg.key];
|
|
141
171
|
break;
|
|
@@ -144,6 +174,7 @@ function createRpcListener() {
|
|
|
144
174
|
break;
|
|
145
175
|
}
|
|
146
176
|
case 'code': {
|
|
177
|
+
// --- 更新 code 代码包 ---
|
|
147
178
|
const rtn = await sRoute.getFormData(req);
|
|
148
179
|
if (!rtn) {
|
|
149
180
|
res.end('Abnormal');
|
|
@@ -162,6 +193,7 @@ function createRpcListener() {
|
|
|
162
193
|
if (path.endsWith('/')) {
|
|
163
194
|
path = path.slice(0, -1);
|
|
164
195
|
}
|
|
196
|
+
/** --- 最终更新的根目录,以 / 结尾,但用户传入的无所谓 --- */
|
|
165
197
|
let to = kebab.ROOT_CWD + path;
|
|
166
198
|
if (!to.endsWith('/')) {
|
|
167
199
|
to += '/';
|
|
@@ -185,22 +217,31 @@ function createRpcListener() {
|
|
|
185
217
|
}
|
|
186
218
|
const ls = await zip.getList();
|
|
187
219
|
for (const path in ls) {
|
|
220
|
+
/** --- 带 / 开头的 zip 中文件完整路径 --- */
|
|
188
221
|
const fpath = path.startsWith('/') ? path : '/' + path;
|
|
222
|
+
/** --- 最后一个 / 的所在位置 --- */
|
|
189
223
|
const lio = fpath.lastIndexOf('/');
|
|
224
|
+
/** --- 纯路径,不以 / 开头,以 / 结尾,若是根路径就是空字符串 --- */
|
|
190
225
|
const pat = fpath.slice(1, lio + 1);
|
|
226
|
+
/** --- 纯文件名 --- */
|
|
191
227
|
const fname = fpath.slice(lio + 1);
|
|
192
228
|
if ((pat === 'conf/' && fname === 'config.json') || fname === 'kebab.json') {
|
|
229
|
+
// --- 特殊文件不能覆盖 ---
|
|
193
230
|
continue;
|
|
194
231
|
}
|
|
195
232
|
if (fname.endsWith('.js.map') || fname.endsWith('.ts') || fname.endsWith('.gitignore')) {
|
|
233
|
+
// --- 测试或开发文件不覆盖 ---
|
|
196
234
|
continue;
|
|
197
235
|
}
|
|
236
|
+
// --- 看文件夹是否存在 ---
|
|
198
237
|
if (pat && !await lFs.isDir(to + pat)) {
|
|
199
238
|
await lFs.mkdir(to + pat);
|
|
200
239
|
}
|
|
240
|
+
// --- 覆盖或创建文件 ---
|
|
201
241
|
await lFs.putContent(to + pat + fname, ls[path]);
|
|
202
242
|
}
|
|
203
243
|
await sRoute.unlinkUploadFiles(rtn.files);
|
|
244
|
+
// --- 检查是否更新 config ---
|
|
204
245
|
if (rtn.post['config'] === '1') {
|
|
205
246
|
const configContent = await lFs.getContent(kebab.CONF_CWD + 'config.json', 'utf8');
|
|
206
247
|
if (configContent) {
|
|
@@ -222,12 +263,18 @@ function createRpcListener() {
|
|
|
222
263
|
});
|
|
223
264
|
}).listen(lCore.globalConfig.rpcPort);
|
|
224
265
|
}
|
|
266
|
+
/**
|
|
267
|
+
* --- 检测是否有死掉丢失的子进程,复活之 ---
|
|
268
|
+
*/
|
|
225
269
|
async function checkWorkerLost() {
|
|
226
270
|
const now = Date.now();
|
|
227
271
|
for (const pid in workerList) {
|
|
228
272
|
if (now - workerList[pid].hbtime < 30000) {
|
|
273
|
+
// --- 距离上次心跳,小于 30 秒,正常 ---
|
|
274
|
+
// --- 子线程 10 秒发送一次心跳 ---
|
|
229
275
|
continue;
|
|
230
276
|
}
|
|
277
|
+
// --- 异常,也可能主线程因为各种原因休眠,不过无论如何都要将原线程关闭,要不然原线程又发心跳包,就捕获不到了 ---
|
|
231
278
|
lCore.display(`[master] Worker ${pid} lost.`);
|
|
232
279
|
workerList[pid].worker.send({
|
|
233
280
|
'action': 'stop'
|
|
@@ -236,6 +283,10 @@ async function checkWorkerLost() {
|
|
|
236
283
|
delete workerList[pid];
|
|
237
284
|
}
|
|
238
285
|
}
|
|
286
|
+
/**
|
|
287
|
+
* --- 创建一个新的子进程 ---
|
|
288
|
+
* @param cpu CPU ID
|
|
289
|
+
*/
|
|
239
290
|
async function createChildProcess(cpu) {
|
|
240
291
|
const worker = cluster.default.fork();
|
|
241
292
|
if (!worker.process.pid) {
|
|
@@ -246,15 +297,19 @@ async function createChildProcess(cpu) {
|
|
|
246
297
|
'cpu': cpu,
|
|
247
298
|
'hbtime': Date.now()
|
|
248
299
|
};
|
|
300
|
+
// --- 如果是支持将线程放到对应的 CPU,则执行相关操作 ---
|
|
249
301
|
if (!os.type().toLowerCase().includes('windows')) {
|
|
302
|
+
// --- 非 Windows ---
|
|
250
303
|
const cpr = await lCore.exec(`taskset -cp ${cpu} ${worker.process.pid}`);
|
|
251
304
|
lCore.display(cpr);
|
|
252
305
|
lCore.display(`[master] Worker ${worker.process.pid} start on cpu #${cpu}.`);
|
|
253
306
|
}
|
|
307
|
+
// --- 监听子进程发来的讯息,并扩散给所有子进程 ---
|
|
254
308
|
worker.on('message', function (msg) {
|
|
255
309
|
(async function () {
|
|
256
310
|
switch (msg.action) {
|
|
257
311
|
case 'reload': {
|
|
312
|
+
// --- 为所有子线程发送 reload 信息 ---
|
|
258
313
|
for (const pid in workerList) {
|
|
259
314
|
workerList[pid].worker.send({
|
|
260
315
|
'action': msg.action
|
|
@@ -263,16 +318,20 @@ async function createChildProcess(cpu) {
|
|
|
263
318
|
break;
|
|
264
319
|
}
|
|
265
320
|
case 'restart': {
|
|
321
|
+
// --- 为所有子进程发送 restart 信息 ---
|
|
266
322
|
for (const pid in workerList) {
|
|
267
323
|
workerList[pid].worker.send({
|
|
268
324
|
'action': 'stop'
|
|
269
325
|
});
|
|
326
|
+
// --- 开启新线程 ---
|
|
270
327
|
await createChildProcess(workerList[pid].cpu);
|
|
328
|
+
// --- 删除记录 ---
|
|
271
329
|
delete workerList[pid];
|
|
272
330
|
}
|
|
273
331
|
break;
|
|
274
332
|
}
|
|
275
333
|
case 'global': {
|
|
334
|
+
// --- 为所有子进程更新 global 变量 ---
|
|
276
335
|
for (const pid in workerList) {
|
|
277
336
|
workerList[pid].worker.send({
|
|
278
337
|
'action': 'global',
|
|
@@ -280,6 +339,7 @@ async function createChildProcess(cpu) {
|
|
|
280
339
|
'data': msg.data
|
|
281
340
|
});
|
|
282
341
|
}
|
|
342
|
+
// --- 更新 master 的数据 ---
|
|
283
343
|
if (msg.data === undefined || msg.data === null) {
|
|
284
344
|
delete lCore.global[msg.key];
|
|
285
345
|
break;
|
|
@@ -288,7 +348,9 @@ async function createChildProcess(cpu) {
|
|
|
288
348
|
break;
|
|
289
349
|
}
|
|
290
350
|
case 'hbtime': {
|
|
351
|
+
// --- 获得子进程发来的 10 秒一次的心跳 ---
|
|
291
352
|
if (!workerList[msg.pid]) {
|
|
353
|
+
// --- 线程存在,主进程记录里没找到 ---
|
|
292
354
|
lCore.display(`[master] Worker ${msg.pid} not found.`);
|
|
293
355
|
break;
|
|
294
356
|
}
|
|
@@ -300,6 +362,7 @@ async function createChildProcess(cpu) {
|
|
|
300
362
|
lCore.display('[createChildProcess] [message]', e);
|
|
301
363
|
});
|
|
302
364
|
});
|
|
365
|
+
// --- 将主线程的全局变量传给这个新建的子线程 ---
|
|
303
366
|
if (Object.keys(lCore.global).length) {
|
|
304
367
|
worker.send({
|
|
305
368
|
'action': 'global',
|
package/sys/mod.d.ts
CHANGED
|
@@ -1,33 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project: Mutton, User: JianSuoQiYue
|
|
3
|
+
* Date: 2019-6-4 21:35
|
|
4
|
+
* Last: 2020-4-14 13:33:51, 2022-07-23 16:01:34, 2022-09-06 22:59:26, 2023-5-24 19:11:37, 2023-6-13 21:47:58, 2023-7-10 18:54:03, 2023-8-23 17:03:16, 2023-12-11 15:21:22, 2023-12-20 23:12:03, 2024-3-8 16:05:29, 2024-3-20 19:58:15, 2024-8-11 21:14:54, 2024-10-5 14:00:22, 2024-12-14 19:58:34
|
|
5
|
+
*/
|
|
1
6
|
import * as lSql from '../lib/sql';
|
|
2
7
|
import * as lDb from '../lib/db';
|
|
3
8
|
import * as sCtr from '../sys/ctr';
|
|
4
9
|
import * as types from '../types';
|
|
10
|
+
/** --- 条数列表 --- */
|
|
5
11
|
declare class Rows<T extends Mod> implements types.Rows<T> {
|
|
6
12
|
private readonly _items;
|
|
7
13
|
constructor(initialItems?: T[]);
|
|
14
|
+
/** --- 总行数 --- */
|
|
8
15
|
get length(): number;
|
|
16
|
+
/** --- 通过索引获取一个对象 --- */
|
|
9
17
|
item(index: number): T;
|
|
18
|
+
/** --- 转换为数组对象 --- */
|
|
10
19
|
toArray(): Array<Record<string, any>>;
|
|
20
|
+
/** --- 根据规则筛掉项,predicate 返回 true 代表保留 --- */
|
|
11
21
|
filter(predicate: (value: T, index: number) => boolean): Rows<T>;
|
|
22
|
+
/** --- 重塑对象内容 --- */
|
|
12
23
|
map<TU>(allbackfn: (value: T, index: number) => TU): TU[];
|
|
13
24
|
[Symbol.iterator](): Iterator<T>;
|
|
14
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* --- 开启软更需要在表添加字段:ALTER TABLE `table_name` ADD `time_remove` bigint NOT NULL DEFAULT '0' AFTER `xxx`; ---
|
|
28
|
+
*/
|
|
15
29
|
export default class Mod {
|
|
30
|
+
/** --- 表名 --- */
|
|
16
31
|
protected static _$table: string;
|
|
32
|
+
/** --- 主键字段名 --- */
|
|
17
33
|
protected static _$primary: string;
|
|
34
|
+
/** --- 设置后将由 _keyGenerator 函数生成唯一字段 --- */
|
|
18
35
|
protected static _$key: string;
|
|
36
|
+
/** ---- 可开启软删软更新软新增 --- */
|
|
19
37
|
protected static _$soft: boolean;
|
|
38
|
+
/** --- 要 update 的内容 --- */
|
|
20
39
|
protected _updates: Record<string, boolean>;
|
|
40
|
+
/** --- 模型获取的属性 --- */
|
|
21
41
|
protected _data: Record<string, any>;
|
|
42
|
+
/** --- 当前选择的分表 _ 后缀,多个代表联查 --- */
|
|
22
43
|
protected _index: string[] | null;
|
|
44
|
+
/** --- 必须追加的数据筛选 key 与 values,仅单表模式有效 --- */
|
|
23
45
|
protected _contain: {
|
|
24
46
|
'key': string;
|
|
25
47
|
'list': string[];
|
|
26
48
|
} | null;
|
|
49
|
+
/** --- 已算出的 total --- */
|
|
27
50
|
protected _total: number[];
|
|
51
|
+
/** --- 数据库连接对象 --- */
|
|
28
52
|
protected _db: lDb.Pool | lDb.Transaction;
|
|
53
|
+
/** --- Sql 对象 --- */
|
|
29
54
|
protected _sql: lSql.Sql;
|
|
55
|
+
/** --- ctr 对象, Mutton: false, Kebab: true --- */
|
|
30
56
|
protected _ctr?: sCtr.Ctr;
|
|
57
|
+
/**
|
|
58
|
+
* --- 构造函数 ---
|
|
59
|
+
* @param ctr Ctr 对象
|
|
60
|
+
* @param opt 选项
|
|
61
|
+
*/
|
|
31
62
|
constructor(opt: {
|
|
32
63
|
'db': lDb.Pool | lDb.Transaction;
|
|
33
64
|
'ctr'?: sCtr.Ctr;
|
|
@@ -43,23 +74,50 @@ export default class Mod {
|
|
|
43
74
|
'raw'?: boolean;
|
|
44
75
|
'pre'?: string;
|
|
45
76
|
});
|
|
77
|
+
/** --- 创建字段对象 --- */
|
|
46
78
|
static column(field: string): {
|
|
47
79
|
'type': 'column';
|
|
48
80
|
'token': string;
|
|
49
81
|
'value': string;
|
|
50
82
|
};
|
|
83
|
+
/**
|
|
84
|
+
* --- 添加一个序列 ---
|
|
85
|
+
* @param db 数据库对象
|
|
86
|
+
* @param cs 字段列表
|
|
87
|
+
* @param vs 数据列表
|
|
88
|
+
* @param opt 选项
|
|
89
|
+
*/
|
|
51
90
|
static insert(db: lDb.Pool | lDb.Transaction, cs: string[] | Record<string, any>, vs?: any[] | any[][], opt?: {
|
|
52
91
|
'pre'?: sCtr.Ctr | string;
|
|
53
92
|
'index'?: string;
|
|
54
93
|
}): Promise<boolean | null | false>;
|
|
94
|
+
/**
|
|
95
|
+
* --- 获取添加一个序列的模拟 SQL ---
|
|
96
|
+
* @param cs 字段列表
|
|
97
|
+
* @param vs 数据列表
|
|
98
|
+
* @param opt 选项
|
|
99
|
+
*/
|
|
55
100
|
static insertSql(cs: string[] | Record<string, any>, vs?: any[] | any[][], opt?: {
|
|
56
101
|
'pre'?: sCtr.Ctr | string;
|
|
57
102
|
'index'?: string;
|
|
58
103
|
}): string;
|
|
104
|
+
/**
|
|
105
|
+
* --- 插入数据如果唯一键冲突则更新 ---
|
|
106
|
+
* @param db 数据库对象
|
|
107
|
+
* @param data 要插入的数据
|
|
108
|
+
* @param update 要更新的数据
|
|
109
|
+
* @param opt 选项
|
|
110
|
+
*/
|
|
59
111
|
static insertDuplicate(db: lDb.Pool | lDb.Transaction, data: Record<string, any>, update: types.Json, opt?: {
|
|
60
112
|
'pre'?: sCtr.Ctr | string;
|
|
61
113
|
'index'?: string;
|
|
62
114
|
}): Promise<boolean | null>;
|
|
115
|
+
/**
|
|
116
|
+
* --- 根据条件移除条目 ---
|
|
117
|
+
* @param db 数据库对象
|
|
118
|
+
* @param where 筛选条件
|
|
119
|
+
* @param opt 选项
|
|
120
|
+
*/
|
|
63
121
|
static removeByWhere(db: lDb.Pool | lDb.Transaction, where: string | types.Json, opt?: {
|
|
64
122
|
'raw'?: boolean;
|
|
65
123
|
'pre'?: sCtr.Ctr | string;
|
|
@@ -67,6 +125,12 @@ export default class Mod {
|
|
|
67
125
|
'by'?: [string | string[], 'DESC' | 'ASC'];
|
|
68
126
|
'limit'?: [number, number?];
|
|
69
127
|
}): Promise<number | false | null>;
|
|
128
|
+
/**
|
|
129
|
+
* --- 根据条件移除条目(仅获取 SQL 对象) ---
|
|
130
|
+
* @param db 数据库对象
|
|
131
|
+
* @param where 筛选条件
|
|
132
|
+
* @param opt 选项
|
|
133
|
+
*/
|
|
70
134
|
static removeByWhereSql(db: lDb.Pool | lDb.Transaction, where: string | types.Json, opt?: {
|
|
71
135
|
'raw'?: boolean;
|
|
72
136
|
'pre'?: sCtr.Ctr | string;
|
|
@@ -74,6 +138,13 @@ export default class Mod {
|
|
|
74
138
|
'by'?: [string | string[], 'DESC' | 'ASC'];
|
|
75
139
|
'limit'?: [number, number?];
|
|
76
140
|
}): lSql.Sql;
|
|
141
|
+
/**
|
|
142
|
+
* --- 根据条件更新数据 ---
|
|
143
|
+
* @param db 数据库对象
|
|
144
|
+
* @param data 要更新的数据
|
|
145
|
+
* @param where 筛选条件
|
|
146
|
+
* @param opt 选项
|
|
147
|
+
*/
|
|
77
148
|
static updateByWhere(db: lDb.Pool | lDb.Transaction, data: types.Json, where: string | types.Json, opt?: {
|
|
78
149
|
'raw'?: boolean;
|
|
79
150
|
'pre'?: sCtr.Ctr | string;
|
|
@@ -81,6 +152,12 @@ export default class Mod {
|
|
|
81
152
|
'by'?: [string | string[], 'DESC' | 'ASC'];
|
|
82
153
|
'limit'?: [number, number?];
|
|
83
154
|
}): Promise<number | false | null>;
|
|
155
|
+
/**
|
|
156
|
+
* --- 根据条件更新数据(仅获取 SQL 对象) ---
|
|
157
|
+
* @param data 要更新的数据
|
|
158
|
+
* @param where 筛选条件
|
|
159
|
+
* @param opt 选项
|
|
160
|
+
*/
|
|
84
161
|
static updateByWhereSql(data: types.Json, where: string | types.Json, opt?: {
|
|
85
162
|
'raw'?: boolean;
|
|
86
163
|
'pre'?: sCtr.Ctr | string;
|
|
@@ -88,6 +165,12 @@ export default class Mod {
|
|
|
88
165
|
'by'?: [string | string[], 'DESC' | 'ASC'];
|
|
89
166
|
'limit'?: [number, number?];
|
|
90
167
|
}): lSql.Sql;
|
|
168
|
+
/**
|
|
169
|
+
* --- select 自定字段 ---
|
|
170
|
+
* @param db 数据库对象
|
|
171
|
+
* @param c 字段字符串或字段数组
|
|
172
|
+
* @param opt 选项
|
|
173
|
+
*/
|
|
91
174
|
static select<T extends Mod>(db: lDb.Pool | lDb.Transaction, c: string | string[], opt?: {
|
|
92
175
|
'ctr'?: sCtr.Ctr;
|
|
93
176
|
'pre'?: string;
|
|
@@ -98,6 +181,12 @@ export default class Mod {
|
|
|
98
181
|
'list': string[];
|
|
99
182
|
};
|
|
100
183
|
}): T & Record<string, any>;
|
|
184
|
+
/**
|
|
185
|
+
* --- 通过 where 条件获取模型 ---
|
|
186
|
+
* @param db 数据库对象
|
|
187
|
+
* @param s 筛选条件数组或字符串
|
|
188
|
+
* @param opt 选项
|
|
189
|
+
*/
|
|
101
190
|
static where<T extends Mod>(db: lDb.Pool | lDb.Transaction, s?: string | types.Json, opt?: {
|
|
102
191
|
'ctr'?: sCtr.Ctr;
|
|
103
192
|
'raw'?: boolean;
|
|
@@ -108,11 +197,23 @@ export default class Mod {
|
|
|
108
197
|
'list': string[];
|
|
109
198
|
};
|
|
110
199
|
}): T & Record<string, any>;
|
|
200
|
+
/**
|
|
201
|
+
* --- 获取创建对象,通常用于新建数据库条目 ---
|
|
202
|
+
* @param db 数据库对象
|
|
203
|
+
* @param opt 选项
|
|
204
|
+
*/
|
|
111
205
|
static getCreate<T extends Mod>(db: lDb.Pool | lDb.Transaction, opt?: {
|
|
112
206
|
'ctr'?: sCtr.Ctr;
|
|
113
207
|
'pre'?: string;
|
|
114
208
|
'index'?: string;
|
|
115
209
|
}): T;
|
|
210
|
+
/**
|
|
211
|
+
* --- 根据主键获取对象 ---
|
|
212
|
+
* @param db 数据库对象
|
|
213
|
+
* @param val 主键值
|
|
214
|
+
* @param lock 是否加锁
|
|
215
|
+
* @param opt 选项
|
|
216
|
+
*/
|
|
116
217
|
static find<T extends Mod>(db: lDb.Pool | lDb.Transaction, val: string | number | null, opt?: {
|
|
117
218
|
'ctr'?: sCtr.Ctr;
|
|
118
219
|
'lock'?: boolean;
|
|
@@ -138,6 +239,12 @@ export default class Mod {
|
|
|
138
239
|
'by'?: [string | string[], 'DESC' | 'ASC'];
|
|
139
240
|
'array'?: false;
|
|
140
241
|
}): Promise<false | null | (T & Record<string, any>)>;
|
|
242
|
+
/**
|
|
243
|
+
* --- 通过 where 条件筛选单条数据返回原生对象 ---
|
|
244
|
+
* @param db 数据库对象
|
|
245
|
+
* @param s 筛选条件数组或字符串
|
|
246
|
+
* @param opt 选项
|
|
247
|
+
*/
|
|
141
248
|
static oneArray(db: lDb.Pool | lDb.Transaction, s: string | types.Json, opt?: {
|
|
142
249
|
'ctr'?: sCtr.Ctr;
|
|
143
250
|
'raw'?: boolean;
|
|
@@ -145,25 +252,71 @@ export default class Mod {
|
|
|
145
252
|
'index'?: string | string[];
|
|
146
253
|
'select'?: string | string[];
|
|
147
254
|
}): Promise<false | null | Record<string, any>>;
|
|
255
|
+
/**
|
|
256
|
+
* --- 根据 where 条件获取主键值列表 ---
|
|
257
|
+
* @param db 数据库对象
|
|
258
|
+
* @param where where 条件
|
|
259
|
+
* @param opt 选项
|
|
260
|
+
*/
|
|
148
261
|
static primarys(db: lDb.Pool | lDb.Transaction, where?: string | types.Json, opt?: {
|
|
149
262
|
'ctr'?: sCtr.Ctr;
|
|
150
263
|
'raw'?: boolean;
|
|
151
264
|
'pre'?: string;
|
|
152
265
|
'index'?: string;
|
|
153
266
|
}): Promise<any[] | false>;
|
|
267
|
+
/**
|
|
268
|
+
* --- 将 key val 组成的数据列表转换为原生对象模式 ---
|
|
269
|
+
* @param obj 要转换的 kv 数据列表
|
|
270
|
+
*/
|
|
154
271
|
static toArrayByRecord<T extends Mod>(obj: Record<string, T>): Record<string, Record<string, any>>;
|
|
155
272
|
set<T extends this, TK extends keyof T>(n: Record<TK, T[TK] | undefined>): void;
|
|
156
273
|
set<T extends this, TK extends keyof T>(n: TK, v: T[TK]): void;
|
|
274
|
+
/**
|
|
275
|
+
* --- 获取一个字段值
|
|
276
|
+
* @param n 字段名
|
|
277
|
+
*/
|
|
157
278
|
get(n: string): any;
|
|
279
|
+
/**
|
|
280
|
+
* --- 创建数据 ---
|
|
281
|
+
* @param notWhere 若要不存在才成功,则要传入限定条件
|
|
282
|
+
* @param table 可对限定条件传入适当的表
|
|
283
|
+
*/
|
|
158
284
|
create(notWhere?: string | types.Json, table?: string): Promise<boolean>;
|
|
285
|
+
/**
|
|
286
|
+
* --- 唯一键冲突则替换,不冲突则创建数据 ---
|
|
287
|
+
*/
|
|
159
288
|
replace(): Promise<boolean>;
|
|
289
|
+
/**
|
|
290
|
+
* --- 刷新当前模型获取最新数据 ---
|
|
291
|
+
* @param lock 是否加锁
|
|
292
|
+
*/
|
|
160
293
|
refresh(lock?: boolean): Promise<boolean | null>;
|
|
294
|
+
/**
|
|
295
|
+
* --- 更新 set 的数据到数据库,有未保存数据时才保存 ---
|
|
296
|
+
*/
|
|
161
297
|
save(): Promise<boolean>;
|
|
298
|
+
/**
|
|
299
|
+
* --- 移除本条目 ---
|
|
300
|
+
* @param raw 是否真实移除
|
|
301
|
+
*/
|
|
162
302
|
remove(raw?: boolean): Promise<boolean>;
|
|
163
303
|
first(lock: boolean, array: true): Promise<false | null | Record<string, any>>;
|
|
164
304
|
first(lock?: boolean, array?: false): Promise<false | null | (this & Record<string, any>)>;
|
|
305
|
+
/**
|
|
306
|
+
* --- 获取数据库第一个原生对象 ---
|
|
307
|
+
* @param lock 是否加锁
|
|
308
|
+
*/
|
|
165
309
|
firstArray(lock?: boolean): Promise<Record<string, any> | false | null>;
|
|
310
|
+
/**
|
|
311
|
+
* --- 联合查询表数据 ---
|
|
312
|
+
* @param f 要联合查询的表列表、单个表、sql 对象
|
|
313
|
+
* @param type 类型
|
|
314
|
+
*/
|
|
166
315
|
union(f: lSql.Sql | string | types.IModUnionItem | string[] | types.IModUnionItem[], type?: string): this;
|
|
316
|
+
/**
|
|
317
|
+
* --- 所有联合查询表数据 ---
|
|
318
|
+
* @param f 要联合查询的表列表、单个表、sql 对象
|
|
319
|
+
*/
|
|
167
320
|
unionAll(f: lSql.Sql | string | types.IModUnionItem | string[] | types.IModUnionItem[]): this;
|
|
168
321
|
all(): Promise<false | Rows<this>>;
|
|
169
322
|
all(key: string): Promise<false | Record<string, this>>;
|
|
@@ -172,34 +325,147 @@ export default class Mod {
|
|
|
172
325
|
explain(all?: false): Promise<false | string>;
|
|
173
326
|
explain(all: true): Promise<false | Record<string, any>>;
|
|
174
327
|
private _formatTotal;
|
|
328
|
+
/**
|
|
329
|
+
* --- 获取总条数,自动抛弃 LIMIT,仅用于获取数据的情况(select) ---
|
|
330
|
+
*/
|
|
175
331
|
total(f?: string): Promise<number>;
|
|
332
|
+
/**
|
|
333
|
+
* --- 根据当前条件,筛选出当前条目该有的数据条数 ---
|
|
334
|
+
*/
|
|
176
335
|
count(): Promise<number>;
|
|
336
|
+
/**
|
|
337
|
+
* @param f 表名
|
|
338
|
+
* @param s ON 信息
|
|
339
|
+
* @param type 类型
|
|
340
|
+
* @param index 给本表增加 index 分表项
|
|
341
|
+
* @param pre 前缀
|
|
342
|
+
*/
|
|
177
343
|
join(f: string, s?: types.Json, type?: string, index?: string, pre?: string): this;
|
|
344
|
+
/**
|
|
345
|
+
* --- left join 方法 ---
|
|
346
|
+
* @param f 表名
|
|
347
|
+
* @param s ON 信息
|
|
348
|
+
* @param index 给本表增加 index 分表项
|
|
349
|
+
*/
|
|
178
350
|
leftJoin(f: string, s: types.Json, index?: string, pre?: string): this;
|
|
351
|
+
/**
|
|
352
|
+
* --- right join 方法 ---
|
|
353
|
+
* @param f 表名
|
|
354
|
+
* @param s ON 信息
|
|
355
|
+
* @param index 给本表增加 index 分表项
|
|
356
|
+
*/
|
|
179
357
|
rightJoin(f: string, s: types.Json, index?: string, pre?: string): this;
|
|
358
|
+
/**
|
|
359
|
+
* --- inner join 方法 ---
|
|
360
|
+
* @param f 表名
|
|
361
|
+
* @param s ON 信息
|
|
362
|
+
* @param index 给本表增加 index 分表项
|
|
363
|
+
*/
|
|
180
364
|
innerJoin(f: string, s: types.Json, index?: string, pre?: string): this;
|
|
365
|
+
/**
|
|
366
|
+
* --- full join 方法 ---
|
|
367
|
+
* @param f 表名
|
|
368
|
+
* @param s ON 信息
|
|
369
|
+
* @param index 给本表增加 index 分表项
|
|
370
|
+
*/
|
|
181
371
|
fullJoin(f: string, s: types.Json, index?: string, pre?: string): this;
|
|
372
|
+
/**
|
|
373
|
+
* --- cross join 方法 ---
|
|
374
|
+
* @param f 表名
|
|
375
|
+
* @param s ON 信息
|
|
376
|
+
* @param index 给本表增加 index 分表项
|
|
377
|
+
*/
|
|
182
378
|
crossJoin(f: string, s: types.Json, index?: string, pre?: string): this;
|
|
379
|
+
/**
|
|
380
|
+
* --- 筛选器 ---
|
|
381
|
+
* @param s 筛选条件数组或字符串
|
|
382
|
+
*/
|
|
183
383
|
having(s: types.Json): this;
|
|
384
|
+
/**
|
|
385
|
+
* --- 筛选器 ---
|
|
386
|
+
* @param s 筛选条件数组或字符串
|
|
387
|
+
* @param raw 是否包含已被软删除的数据
|
|
388
|
+
*/
|
|
184
389
|
filter(s: types.Json, raw?: boolean): this;
|
|
390
|
+
/**
|
|
391
|
+
* --- 是 filter 的别名 ---
|
|
392
|
+
* @param s 筛选条件数组或字符串
|
|
393
|
+
* @param raw 是否包含已被软删除的数据
|
|
394
|
+
*/
|
|
185
395
|
where(s: types.Json, raw?: boolean): this;
|
|
396
|
+
/**
|
|
397
|
+
* --- ORDER BY ---
|
|
398
|
+
* @param c 字段字符串或数组
|
|
399
|
+
* @param d 排序规则
|
|
400
|
+
*/
|
|
186
401
|
by(c: string | Array<string | string[]>, d?: 'DESC' | 'ASC'): this;
|
|
402
|
+
/**
|
|
403
|
+
* --- GROUP BY ---
|
|
404
|
+
* @param c 字段字符串或数组
|
|
405
|
+
*/
|
|
187
406
|
group(c: string | string[]): this;
|
|
407
|
+
/** --- 设置的 limit --- */
|
|
188
408
|
private _limit;
|
|
409
|
+
/**
|
|
410
|
+
* --- LIMIT ---
|
|
411
|
+
* @param a 起始
|
|
412
|
+
* @param b 长度
|
|
413
|
+
*/
|
|
189
414
|
limit(a: number, b?: number): this;
|
|
415
|
+
/**
|
|
416
|
+
* --- 分页 ---
|
|
417
|
+
* @param count 每页条数
|
|
418
|
+
* @param page 当前页数
|
|
419
|
+
*/
|
|
190
420
|
page(count: number, page?: number): this;
|
|
421
|
+
/**
|
|
422
|
+
* --- 在 sql 最后追加字符串 ---
|
|
423
|
+
* @param sql
|
|
424
|
+
*/
|
|
191
425
|
append(sql: string): this;
|
|
426
|
+
/**
|
|
427
|
+
* --- 设置闭包含数据 ---
|
|
428
|
+
* @param contain 设置项
|
|
429
|
+
*/
|
|
192
430
|
contain(contain: {
|
|
193
431
|
'key': string;
|
|
194
432
|
'list': string[];
|
|
195
433
|
}): this;
|
|
434
|
+
/**
|
|
435
|
+
* --- 获取 sql 语句 ---
|
|
436
|
+
*/
|
|
196
437
|
getSql(): string;
|
|
438
|
+
/**
|
|
439
|
+
* --- 获取全部 data ---
|
|
440
|
+
*/
|
|
197
441
|
getData(): any[];
|
|
442
|
+
/**
|
|
443
|
+
* --- 获取带 data 的 sql 语句 ---
|
|
444
|
+
* @param sql sql 语句
|
|
445
|
+
* @param data 数据
|
|
446
|
+
*/
|
|
198
447
|
format(sql?: string, data?: any[]): string;
|
|
448
|
+
/**
|
|
449
|
+
* --- 获取值对象 ---
|
|
450
|
+
*/
|
|
199
451
|
toArray(): Record<string, any>;
|
|
452
|
+
/**
|
|
453
|
+
* --- 获取当前设置要提交的数据 ---
|
|
454
|
+
*/
|
|
200
455
|
updates(): Record<string, any>;
|
|
456
|
+
/**
|
|
457
|
+
* --- 当前是否设置了未保存 --=
|
|
458
|
+
*/
|
|
201
459
|
unsaved(): boolean;
|
|
460
|
+
/**
|
|
461
|
+
* --- 获取字段的可用语种文本 ---
|
|
462
|
+
* @param col 字段名
|
|
463
|
+
* @param lang 当前请求语种,如 sc
|
|
464
|
+
*/
|
|
202
465
|
langText(col: string, lang: string): string;
|
|
466
|
+
/**
|
|
467
|
+
* --- 当 _key 不为空时,则依据继承此方法的方法自动生成填充 key ---
|
|
468
|
+
*/
|
|
203
469
|
protected _keyGenerator(): string;
|
|
204
470
|
}
|
|
205
471
|
export {};
|