@maiyunnet/kebab 7.3.1 → 7.4.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/index.d.ts +1 -1
- package/index.js +1 -1
- package/lib/sql.d.ts +4 -1
- package/lib/sql.js +13 -2
- package/package.json +1 -1
- package/sys/mod.d.ts +2 -0
- package/sys/mod.js +3 -3
- package/sys/route.d.ts +5 -0
- package/sys/route.js +35 -9
- package/www/example/ctr/test.js +6 -0
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* --- 本文件用来定义每个目录实体地址的常量 ---
|
|
7
7
|
*/
|
|
8
8
|
/** --- 当前系统版本号 --- */
|
|
9
|
-
export const VER = '7.
|
|
9
|
+
export const VER = '7.4.1';
|
|
10
10
|
// --- 服务端用的路径 ---
|
|
11
11
|
const imu = decodeURIComponent(import.meta.url).replace('file://', '').replace(/^\/(\w:)/, '$1');
|
|
12
12
|
/** --- /xxx/xxx --- */
|
package/lib/sql.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ export declare class Sql {
|
|
|
25
25
|
private readonly _alias;
|
|
26
26
|
/** --- PostgreSQL 占位符计数器 --- */
|
|
27
27
|
private _placeholderCounter;
|
|
28
|
+
/** --- 是否忽略错误 --- */
|
|
29
|
+
private _ignore;
|
|
28
30
|
constructor(opt: {
|
|
29
31
|
'service': ESERVICE;
|
|
30
32
|
'ctr'?: ctr.Ctr;
|
|
@@ -35,8 +37,9 @@ export declare class Sql {
|
|
|
35
37
|
/**
|
|
36
38
|
* --- 插入数据前导 ---
|
|
37
39
|
* @param table 表名
|
|
40
|
+
* @param ignore 是否忽略错误(MySQL: INSERT IGNORE, PGSQL: ON CONFLICT DO NOTHING)
|
|
38
41
|
*/
|
|
39
|
-
insert(table: string): this;
|
|
42
|
+
insert(table: string, ignore?: boolean): this;
|
|
40
43
|
/**
|
|
41
44
|
* --- 实际插入数据的数据 ---
|
|
42
45
|
* @param cs [] 数据列或字段列
|
package/lib/sql.js
CHANGED
|
@@ -25,6 +25,8 @@ export class Sql {
|
|
|
25
25
|
_alias = [];
|
|
26
26
|
/** --- PostgreSQL 占位符计数器 --- */
|
|
27
27
|
_placeholderCounter = 1;
|
|
28
|
+
/** --- 是否忽略错误 --- */
|
|
29
|
+
_ignore = false;
|
|
28
30
|
// --- 实例化 ---
|
|
29
31
|
constructor(opt) {
|
|
30
32
|
this._ctr = opt.ctr;
|
|
@@ -41,12 +43,18 @@ export class Sql {
|
|
|
41
43
|
/**
|
|
42
44
|
* --- 插入数据前导 ---
|
|
43
45
|
* @param table 表名
|
|
46
|
+
* @param ignore 是否忽略错误(MySQL: INSERT IGNORE, PGSQL: ON CONFLICT DO NOTHING)
|
|
44
47
|
*/
|
|
45
|
-
insert(table) {
|
|
48
|
+
insert(table, ignore = false) {
|
|
46
49
|
this._data = [];
|
|
47
50
|
this._placeholderCounter = 1;
|
|
48
51
|
this._alias.length = 0;
|
|
49
|
-
|
|
52
|
+
this._ignore = ignore;
|
|
53
|
+
let sql = 'INSERT ';
|
|
54
|
+
if (ignore && this._service === ESERVICE.MYSQL) {
|
|
55
|
+
sql += 'IGNORE ';
|
|
56
|
+
}
|
|
57
|
+
sql += 'INTO ' + this.field(table, this._pre);
|
|
50
58
|
this._sql = [sql];
|
|
51
59
|
return this;
|
|
52
60
|
}
|
|
@@ -99,6 +107,9 @@ export class Sql {
|
|
|
99
107
|
sql = sql.slice(0, -2) + ') VALUES (' + values.slice(0, -2) + ')';
|
|
100
108
|
}
|
|
101
109
|
this._sql.push(sql);
|
|
110
|
+
if (this._ignore && this._service === ESERVICE.PGSQL) {
|
|
111
|
+
this._sql.push(' ON CONFLICT DO NOTHING');
|
|
112
|
+
}
|
|
102
113
|
return this;
|
|
103
114
|
}
|
|
104
115
|
/**
|
package/package.json
CHANGED
package/sys/mod.d.ts
CHANGED
|
@@ -97,6 +97,7 @@ export default class Mod {
|
|
|
97
97
|
'pre'?: string;
|
|
98
98
|
'ctr'?: sCtr.Ctr;
|
|
99
99
|
'index'?: string;
|
|
100
|
+
'ignore'?: boolean;
|
|
100
101
|
}): Promise<boolean | null | false>;
|
|
101
102
|
/**
|
|
102
103
|
* --- 获取添加一个序列的模拟 SQL ---
|
|
@@ -109,6 +110,7 @@ export default class Mod {
|
|
|
109
110
|
'pre'?: string;
|
|
110
111
|
'ctr'?: sCtr.Ctr;
|
|
111
112
|
'index'?: string;
|
|
113
|
+
'ignore'?: boolean;
|
|
112
114
|
}): string;
|
|
113
115
|
/**
|
|
114
116
|
* --- 根据条件移除条目 ---
|
package/sys/mod.js
CHANGED
|
@@ -130,7 +130,7 @@ export default class Mod {
|
|
|
130
130
|
});
|
|
131
131
|
if (!vs) {
|
|
132
132
|
// --- 单行 ---
|
|
133
|
-
sq.insert(this._$table + (opt.index ? ('_' + opt.index) : ''));
|
|
133
|
+
sq.insert(this._$table + (opt.index ? ('_' + opt.index) : ''), opt.ignore);
|
|
134
134
|
sq.values(cs);
|
|
135
135
|
const r = await db.execute(sq.getSql(), sq.getData());
|
|
136
136
|
if (r.packet === null) {
|
|
@@ -150,7 +150,7 @@ export default class Mod {
|
|
|
150
150
|
/** --- 总批次数量 --- */
|
|
151
151
|
const batch = Math.ceil(vs.length / line);
|
|
152
152
|
for (let i = 0; i < batch; ++i) {
|
|
153
|
-
sq.insert(this._$table + (opt.index ? ('_' + opt.index) : ''));
|
|
153
|
+
sq.insert(this._$table + (opt.index ? ('_' + opt.index) : ''), opt.ignore);
|
|
154
154
|
sq.values(cs, vs.slice(i * line, (i + 1) * line));
|
|
155
155
|
const r = await db.execute(sq.getSql(), sq.getData());
|
|
156
156
|
if (r.packet === null) {
|
|
@@ -177,7 +177,7 @@ export default class Mod {
|
|
|
177
177
|
'ctr': opt.ctr,
|
|
178
178
|
'pre': opt.pre ?? this._$pre,
|
|
179
179
|
});
|
|
180
|
-
sq.insert(this._$table + (opt.index ? ('_' + opt.index) : '')).values(cs, vs);
|
|
180
|
+
sq.insert(this._$table + (opt.index ? ('_' + opt.index) : ''), opt.ignore).values(cs, vs);
|
|
181
181
|
return sq.format();
|
|
182
182
|
}
|
|
183
183
|
/**
|
package/sys/route.d.ts
CHANGED
|
@@ -63,8 +63,13 @@ export declare function getPost(req: http2.Http2ServerRequest | http.IncomingMes
|
|
|
63
63
|
* @param events 文件处理情况
|
|
64
64
|
*/
|
|
65
65
|
export declare function getFormData(req: http2.Http2ServerRequest | http.IncomingMessage, events?: {
|
|
66
|
+
/**
|
|
67
|
+
* --- 文件开始上传时触发,返回 true 则跳过该文件的保存 ---
|
|
68
|
+
*/
|
|
66
69
|
onfilestart?: (name: string) => boolean | undefined;
|
|
70
|
+
/** --- 文件上传时触发,仅 start 返回 true 时触发 --- */
|
|
67
71
|
onfiledata?: (chunk: Buffer) => void;
|
|
72
|
+
/** --- 文件上传结束时触发,仅 start 返回 true 时触发 --- */
|
|
68
73
|
onfileend?: () => void;
|
|
69
74
|
}): Promise<{
|
|
70
75
|
'post': Record<string, kebab.Json>;
|
package/sys/route.js
CHANGED
|
@@ -867,6 +867,10 @@ export function getPost(req) {
|
|
|
867
867
|
*/
|
|
868
868
|
export function getFormData(req, events = {}) {
|
|
869
869
|
return new Promise(function (resolve) {
|
|
870
|
+
if (req.readableEnded) {
|
|
871
|
+
resolve({ 'post': {}, 'files': {} });
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
870
874
|
const ct = req.headers['content-type'] ?? '';
|
|
871
875
|
if (!ct) {
|
|
872
876
|
resolve({ 'post': {}, 'files': {} });
|
|
@@ -991,22 +995,20 @@ export function getFormData(req, events = {}) {
|
|
|
991
995
|
if (io === -1) {
|
|
992
996
|
// --- 没找到结束标语,将预留 boundary 长度之前的写入到文件 ---
|
|
993
997
|
const writeBuffer = buffer.subarray(0, -boundary.length - 4);
|
|
994
|
-
if (ftmpName
|
|
995
|
-
events.onfiledata?.(writeBuffer);
|
|
996
|
-
}
|
|
997
|
-
else {
|
|
998
|
+
if (ftmpName) {
|
|
998
999
|
ftmpStream.write(writeBuffer);
|
|
999
1000
|
ftmpSize += Buffer.byteLength(writeBuffer);
|
|
1000
1001
|
}
|
|
1002
|
+
else {
|
|
1003
|
+
// --- 跳过该文件 ---
|
|
1004
|
+
events.onfiledata?.(writeBuffer);
|
|
1005
|
+
}
|
|
1001
1006
|
buffer = buffer.subarray(-boundary.length - 4);
|
|
1002
1007
|
return;
|
|
1003
1008
|
}
|
|
1004
1009
|
// --- 找到结束标语,结束标语之前的写入文件,之后的重新放回 buffer ---
|
|
1005
1010
|
const writeBuffer = buffer.subarray(0, io);
|
|
1006
|
-
if (ftmpName
|
|
1007
|
-
events.onfileend?.();
|
|
1008
|
-
}
|
|
1009
|
-
else {
|
|
1011
|
+
if (ftmpName) {
|
|
1010
1012
|
ftmpStream.write(writeBuffer);
|
|
1011
1013
|
ftmpSize += Buffer.byteLength(writeBuffer);
|
|
1012
1014
|
ftmpStream.end(() => {
|
|
@@ -1046,6 +1048,10 @@ export function getFormData(req, events = {}) {
|
|
|
1046
1048
|
rtn.files[name] = val;
|
|
1047
1049
|
}
|
|
1048
1050
|
}
|
|
1051
|
+
else {
|
|
1052
|
+
// --- 跳过该文件 ---
|
|
1053
|
+
events.onfileend?.();
|
|
1054
|
+
}
|
|
1049
1055
|
// --- 重置状态机 ---
|
|
1050
1056
|
state = EState.WAIT;
|
|
1051
1057
|
buffer = buffer.subarray(io + 4 + boundary.length);
|
|
@@ -1054,11 +1060,31 @@ export function getFormData(req, events = {}) {
|
|
|
1054
1060
|
}
|
|
1055
1061
|
}
|
|
1056
1062
|
});
|
|
1057
|
-
req.on('error', function () {
|
|
1063
|
+
req.on('error', function (e) {
|
|
1064
|
+
if ((state === EState.FILE) && ftmpName) {
|
|
1065
|
+
ftmpStream.destroy();
|
|
1066
|
+
}
|
|
1067
|
+
lCore.debug('[ROUTE][GETFORMDATA] request error before getFormData: ' + e.message);
|
|
1068
|
+
lCore.log({}, '[ROUTE][GETFORMDATA] request error before getFormData: ' + (e.stack ?? ''), '-error');
|
|
1058
1069
|
resolve(false);
|
|
1059
1070
|
});
|
|
1060
1071
|
req.on('end', function () {
|
|
1061
1072
|
readEnd = true;
|
|
1073
|
+
if (state === EState.FILE) {
|
|
1074
|
+
if (ftmpName) {
|
|
1075
|
+
ftmpStream.end(() => {
|
|
1076
|
+
--writeFileLength;
|
|
1077
|
+
if (!writeFileLength) {
|
|
1078
|
+
// --- 文件也写完了 ---
|
|
1079
|
+
resolve(rtn);
|
|
1080
|
+
}
|
|
1081
|
+
});
|
|
1082
|
+
return;
|
|
1083
|
+
}
|
|
1084
|
+
// --- 跳过该文件 ---
|
|
1085
|
+
events.onfileend?.();
|
|
1086
|
+
--writeFileLength;
|
|
1087
|
+
}
|
|
1062
1088
|
if (writeFileLength) {
|
|
1063
1089
|
// --- 文件没写完 ---
|
|
1064
1090
|
return;
|
package/www/example/ctr/test.js
CHANGED
|
@@ -2365,6 +2365,12 @@ Result:<pre id="result">Nothing.</pre>`);
|
|
|
2365
2365
|
echo.push(`<pre>sql.insert('user').values(['name', 'age'], ['Ah', '16']);</pre>
|
|
2366
2366
|
<b>getSql() :</b> ${s}<br>
|
|
2367
2367
|
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2368
|
+
<b>format() :</b> ${sql.format(s, sd)}<hr>`);
|
|
2369
|
+
s = sql.insert('user', true).values(['name', 'age'], ['Ah', '16']).getSql();
|
|
2370
|
+
sd = sql.getData();
|
|
2371
|
+
echo.push(`<pre>sql.insert('user', true).values(['name', 'age'], ['Ah', '16']);</pre>
|
|
2372
|
+
<b>getSql() :</b> ${s}<br>
|
|
2373
|
+
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2368
2374
|
<b>format() :</b> ${sql.format(s, sd)}<hr>`);
|
|
2369
2375
|
s = sql.insert('user').values({ 'name': 'Bob', 'age': '24' }).getSql();
|
|
2370
2376
|
sd = sql.getData();
|