@maiyunnet/kebab 2.0.7 → 2.0.9

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.
Files changed (83) hide show
  1. package/index.d.ts +11 -1
  2. package/index.js +13 -1
  3. package/lib/buffer.d.ts +25 -0
  4. package/lib/buffer.js +30 -5
  5. package/lib/captcha.d.ts +15 -0
  6. package/lib/captcha.js +20 -0
  7. package/lib/consistent.d.ts +51 -0
  8. package/lib/consistent.js +59 -0
  9. package/lib/core.d.ts +134 -0
  10. package/lib/core.js +176 -0
  11. package/lib/crypto.d.ts +75 -6
  12. package/lib/crypto.js +206 -38
  13. package/lib/db.d.ts +104 -0
  14. package/lib/db.js +126 -0
  15. package/lib/dns.d.ts +51 -0
  16. package/lib/dns.js +54 -2
  17. package/lib/fs.d.ts +100 -0
  18. package/lib/fs.js +118 -0
  19. package/lib/jwt.d.ts +43 -0
  20. package/lib/jwt.js +45 -0
  21. package/lib/kv.d.ts +362 -0
  22. package/lib/kv.js +377 -0
  23. package/lib/lan.d.ts +6 -0
  24. package/lib/lan.js +7 -0
  25. package/lib/net/formdata.d.ts +38 -0
  26. package/lib/net/formdata.js +43 -0
  27. package/lib/net/request.d.ts +62 -0
  28. package/lib/net/request.js +57 -0
  29. package/lib/net/response.d.ts +21 -0
  30. package/lib/net/response.js +16 -0
  31. package/lib/net.d.ts +86 -0
  32. package/lib/net.js +140 -0
  33. package/lib/s3.d.ts +52 -0
  34. package/lib/s3.js +51 -0
  35. package/lib/scan.d.ts +52 -0
  36. package/lib/scan.js +84 -0
  37. package/lib/session.d.ts +31 -0
  38. package/lib/session.js +52 -1
  39. package/lib/sql.d.ts +176 -0
  40. package/lib/sql.js +287 -2
  41. package/lib/ssh/sftp.d.ts +106 -0
  42. package/lib/ssh/sftp.js +106 -0
  43. package/lib/ssh/shell.d.ts +37 -0
  44. package/lib/ssh/shell.js +31 -0
  45. package/lib/ssh.d.ts +32 -0
  46. package/lib/ssh.js +32 -0
  47. package/lib/text.d.ts +131 -0
  48. package/lib/text.js +188 -0
  49. package/lib/time.d.ts +53 -0
  50. package/lib/time.js +55 -0
  51. package/lib/ws.d.ts +68 -0
  52. package/lib/ws.js +74 -0
  53. package/lib/zip.d.ts +53 -0
  54. package/lib/zip.js +73 -0
  55. package/lib/zlib.d.ts +76 -0
  56. package/lib/zlib.js +78 -0
  57. package/main.d.ts +5 -0
  58. package/main.js +12 -0
  59. package/package.json +3 -2
  60. package/sys/child.js +104 -0
  61. package/sys/cmd.js +28 -0
  62. package/sys/ctr.d.ts +166 -0
  63. package/sys/ctr.js +177 -0
  64. package/sys/master.js +63 -0
  65. package/sys/mod.d.ts +266 -0
  66. package/sys/mod.js +335 -0
  67. package/sys/route.d.ts +34 -0
  68. package/sys/route.js +164 -0
  69. package/www/example/ctr/test.d.ts +3 -0
  70. package/www/example/ctr/test.js +63 -1
  71. package/www/example/mod/test.js +14 -0
  72. package/www/example/mod/testdata.js +9 -0
  73. package/www/example/ws/test.js +1 -0
  74. package/.VSCodeCounter/2025-02-14_14-46-44/details.md +0 -82
  75. package/.VSCodeCounter/2025-02-14_14-46-44/diff-details.md +0 -15
  76. package/.VSCodeCounter/2025-02-14_14-46-44/diff.csv +0 -2
  77. package/.VSCodeCounter/2025-02-14_14-46-44/diff.md +0 -19
  78. package/.VSCodeCounter/2025-02-14_14-46-44/diff.txt +0 -22
  79. package/.VSCodeCounter/2025-02-14_14-46-44/results.csv +0 -69
  80. package/.VSCodeCounter/2025-02-14_14-46-44/results.json +0 -1
  81. package/.VSCodeCounter/2025-02-14_14-46-44/results.md +0 -48
  82. package/.VSCodeCounter/2025-02-14_14-46-44/results.txt +0 -118
  83. package/.vscode/tasks.json +0 -15
package/lib/sql.js CHANGED
@@ -1,4 +1,9 @@
1
1
  "use strict";
2
+ /**
3
+ * Project: Kebab, User: JianSuoQiYue
4
+ * Date: 2019-5-27 20:18:50
5
+ * Last: 2020-3-29 19:37:25, 2022-07-24 22:38:11, 2023-5-24 18:49:18, 2023-6-13 22:20:21, 2023-12-11 13:58:54, 2023-12-14 13:14:40, 2023-12-21 00:04:40, 2024-4-11 19:29:29, 2024-9-2 17:15:28
6
+ */
2
7
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
8
  if (k2 === undefined) k2 = k;
4
9
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -40,14 +45,22 @@ exports.aoMix = aoMix;
40
45
  exports.column = column;
41
46
  const lText = __importStar(require("../lib/text"));
42
47
  const lCore = __importStar(require("../lib/core"));
48
+ // --- 第三方 ---
43
49
  const mysql2 = __importStar(require("mysql2/promise"));
50
+ // --- 库和定义 ---
44
51
  const ctr = __importStar(require("../sys/ctr"));
52
+ /** --- filed 用 token --- */
45
53
  let columnToken = '';
46
54
  class Sql {
55
+ // --- 实例化 ---
47
56
  constructor(pre, opt = {}) {
57
+ /** --- 前置 --- */
48
58
  this._pre = '';
59
+ /** --- 预拼装 Sql 数组 --- */
49
60
  this._sql = [];
61
+ /** --- 所有 data 数据 --- */
50
62
  this._data = [];
63
+ /** --- where 的 data 的开始处和结束处 --- */
51
64
  this._whereDataPosition = [0, 0];
52
65
  this._pre = pre ?? '';
53
66
  if (opt.data) {
@@ -57,21 +70,37 @@ class Sql {
57
70
  this._sql = opt.sql;
58
71
  }
59
72
  }
73
+ // --- 前导 ---
74
+ /**
75
+ * --- 插入数据前导 ---
76
+ * @param table 表名
77
+ */
60
78
  insert(table) {
61
79
  this._data = [];
62
80
  const sql = 'INSERT INTO ' + this.field(table, this._pre);
63
81
  this._sql = [sql];
64
82
  return this;
65
83
  }
84
+ /**
85
+ * --- 替换已经存在的唯一索引数据,不存在则插入 ---
86
+ * @param table 表名
87
+ */
66
88
  replace(table) {
67
89
  this._data = [];
68
90
  const sql = 'REPLACE INTO ' + this.field(table, this._pre);
69
91
  this._sql = [sql];
70
92
  return this;
71
93
  }
94
+ /**
95
+ * --- 实际插入数据的数据 ---
96
+ * @param cs [] 数据列或字段列
97
+ * @param vs [] | [][] 数据
98
+ */
72
99
  values(cs, vs = []) {
73
100
  let sql = ' (';
74
101
  if (Array.isArray(cs)) {
102
+ // --- ['id', 'name'], [['1', 'wow'], ['2', 'oh']] ---
103
+ // --- ['id', 'name'], ['1', 'wow'] ---
75
104
  for (const i of cs) {
76
105
  sql += this.field(i) + ', ';
77
106
  }
@@ -79,10 +108,14 @@ class Sql {
79
108
  if (!Array.isArray(vs[0])) {
80
109
  vs = [vs];
81
110
  }
111
+ // --- INSERT INTO xx (id, name) VALUES (?, ?) ---
112
+ // --- INSERT INTO xx (id, name) VALUES (?, ?), (?, ?) ---
82
113
  for (const v of vs) {
83
114
  sql += '(';
84
115
  for (const v1 of v) {
116
+ // --- v1 是项目值,如 {'x': 1, 'y': 2}, 'string', 0 ---
85
117
  if (v1 === undefined || Number.isNaN(v1)) {
118
+ // --- 异常情况 ---
86
119
  lCore.log({
87
120
  'path': '',
88
121
  'urlFull': '',
@@ -92,6 +125,7 @@ class Sql {
92
125
  'cookie': {},
93
126
  'headers': {}
94
127
  }, '(sql.values) value error', '-error').catch(() => {
128
+ //
95
129
  });
96
130
  sql += `'', `;
97
131
  }
@@ -105,12 +139,14 @@ class Sql {
105
139
  else if (Array.isArray(v1)) {
106
140
  if (v1[0]?.[0]?.x === undefined && typeof v1[0] === 'string' &&
107
141
  v1[0].includes('(') && v1[0].includes(')')) {
142
+ // --- v1: ['POINT(?)', ['20']] ---
108
143
  sql += this.field(v1[0]) + ', ';
109
144
  if (v1[1]) {
110
145
  this._data.push(...v1[1]);
111
146
  }
112
147
  }
113
148
  else if (v1[0]?.[0]?.y !== undefined) {
149
+ // --- v1: [[{'x': 1, 'y': 2}, { ... }], [{ ... }, { ... }]] ---
114
150
  sql += 'ST_POLYGONFROMTEXT(?), ';
115
151
  this._data.push(`POLYGON(${v1.map((item) => {
116
152
  return `(${item.map((it) => {
@@ -119,28 +155,34 @@ class Sql {
119
155
  }).join(', ')})`);
120
156
  }
121
157
  else {
158
+ // --- v1: json ---
122
159
  sql += '?, ';
123
160
  this._data.push(lText.stringifyJson(v1));
124
161
  }
125
162
  }
126
163
  else if (v1.x !== undefined) {
127
164
  if (v1.y !== undefined) {
165
+ // --- v1: {'x': 1, 'y': 2} ---
128
166
  sql += 'ST_POINTFROMTEXT(?), ';
129
167
  this._data.push(`POINT(${v1.x} ${v1.y})`);
130
168
  }
131
169
  else {
170
+ // --- v1: json ---
132
171
  sql += '?, ';
133
172
  this._data.push(lText.stringifyJson(v1));
134
173
  }
135
174
  }
136
175
  else if (v1 instanceof Buffer) {
176
+ // --- Buffer ---
137
177
  sql += '?, ';
138
178
  this._data.push(v);
139
179
  }
140
180
  else if (this._isField(v1)) {
181
+ // --- 3 ---
141
182
  sql += this.field(v1.value) + ', ';
142
183
  }
143
184
  else {
185
+ // --- json ---
144
186
  sql += '?, ';
145
187
  this._data.push(lText.stringifyJson(v1));
146
188
  }
@@ -150,11 +192,14 @@ class Sql {
150
192
  sql = sql.slice(0, -2);
151
193
  }
152
194
  else {
195
+ // --- {'id': '1', 'name': 'wow'} ---
196
+ // --- INSERT INTO xx (id, name) VALUES (?, ?) ---
153
197
  let values = '';
154
198
  for (const k in cs) {
155
199
  const v = cs[k];
156
200
  sql += this.field(k) + ', ';
157
201
  if (v === undefined || Number.isNaN(v)) {
202
+ // --- 异常情况 ---
158
203
  lCore.log({
159
204
  'path': '',
160
205
  'urlFull': '',
@@ -164,6 +209,7 @@ class Sql {
164
209
  'cookie': {},
165
210
  'headers': {}
166
211
  }, '(sql.values) value error', '-error').catch(() => {
212
+ //
167
213
  });
168
214
  values += `'', `;
169
215
  }
@@ -177,12 +223,14 @@ class Sql {
177
223
  else if (Array.isArray(v)) {
178
224
  if (v[0]?.[0]?.x === undefined && typeof v[0] === 'string' &&
179
225
  v[0].includes('(') && v[0].includes(')')) {
226
+ // --- v: ['POINT(?)', ['20']] ---
180
227
  values += this.field(v[0]) + ', ';
181
228
  if (v[1] !== undefined) {
182
229
  this._data.push(...v[1]);
183
230
  }
184
231
  }
185
232
  else if (v[0]?.[0]?.y !== undefined) {
233
+ // --- v: [[{'x': 1, 'y': 2}, { ... }], [{ ... }, { ... }]] ---
186
234
  values += 'ST_POLYGONFROMTEXT(?), ';
187
235
  this._data.push(`POLYGON(${v.map((item) => {
188
236
  return `(${item.map((it) => {
@@ -191,28 +239,34 @@ class Sql {
191
239
  }).join(', ')})`);
192
240
  }
193
241
  else {
242
+ // --- v: json ---
194
243
  values += '?, ';
195
244
  this._data.push(lText.stringifyJson(v));
196
245
  }
197
246
  }
198
247
  else if (v.x !== undefined) {
199
248
  if (v.y !== undefined) {
249
+ // --- v: {'x': 1, 'y': 2} ---
200
250
  values += 'ST_POINTFROMTEXT(?), ';
201
251
  this._data.push(`POINT(${v.x} ${v.y})`);
202
252
  }
203
253
  else {
254
+ // --- v: json ---
204
255
  values += '?, ';
205
256
  this._data.push(lText.stringifyJson(v));
206
257
  }
207
258
  }
208
259
  else if (v instanceof Buffer) {
260
+ // --- Buffer ---
209
261
  values += '?, ';
210
262
  this._data.push(v);
211
263
  }
212
264
  else if (this._isField(v)) {
265
+ // --- 3 ---
213
266
  values += this.field(v.value) + ', ';
214
267
  }
215
268
  else {
269
+ // --- json ---
216
270
  values += '?, ';
217
271
  this._data.push(lText.stringifyJson(v));
218
272
  }
@@ -222,6 +276,12 @@ class Sql {
222
276
  this._sql.push(sql);
223
277
  return this;
224
278
  }
279
+ /**
280
+ * --- 不存在则插入,衔接在 insert 之后 ---
281
+ * @param table 表名
282
+ * @param insert {'xx': 'xx', 'xx': 'xx'}
283
+ * @param where [{'xx': 'xx', 'xx': 'xx'}], {'xx': 'xx'}
284
+ */
225
285
  notExists(table, insert, where) {
226
286
  let sql = '(';
227
287
  const values = [];
@@ -245,6 +305,10 @@ class Sql {
245
305
  this._sql.push(sql);
246
306
  return this;
247
307
  }
308
+ /**
309
+ * --- 当不能 insert 时,update(仅能配合 insert 方法用) ---
310
+ * @param s 更新数据
311
+ */
248
312
  duplicate(s) {
249
313
  if (Array.isArray(s) ? s.length : Object.keys(s).length) {
250
314
  const sql = ' ON DUPLICATE KEY UPDATE ' + this._updateSub(s);
@@ -252,6 +316,11 @@ class Sql {
252
316
  }
253
317
  return this;
254
318
  }
319
+ /**
320
+ * --- '*', 'xx' ---
321
+ * @param c 字段字符串或字段数组
322
+ * @param f 表,允许多张表
323
+ */
255
324
  select(c, f) {
256
325
  this._data = [];
257
326
  let sql = 'SELECT ';
@@ -259,8 +328,10 @@ class Sql {
259
328
  sql += this.field(c);
260
329
  }
261
330
  else {
331
+ // --- c: ['id', 'name'] ---
262
332
  for (const i of c) {
263
333
  if (Array.isArray(i)) {
334
+ // --- i: ['xx', ['x']] ---
264
335
  sql += this.field(i[0]) + ', ';
265
336
  this._data.push(...i[1]);
266
337
  }
@@ -275,6 +346,7 @@ class Sql {
275
346
  sql += this.field(f, this._pre);
276
347
  }
277
348
  else {
349
+ // --- f: ['user', 'order'] ---
278
350
  for (const i of f) {
279
351
  sql += this.field(i, this._pre) + ', ';
280
352
  }
@@ -283,6 +355,11 @@ class Sql {
283
355
  this._sql = [sql];
284
356
  return this;
285
357
  }
358
+ /**
359
+ * --- UPDATE SQL 方法 ---
360
+ * @param f 表名
361
+ * @param s 设定 update 的值
362
+ */
286
363
  update(f, s) {
287
364
  this._data = [];
288
365
  const sql = `UPDATE ${this.field(f, this._pre)} SET ${this._updateSub(s)}`;
@@ -290,11 +367,27 @@ class Sql {
290
367
  return this;
291
368
  }
292
369
  _updateSub(s) {
370
+ /*
371
+ [
372
+ ['total', '+', '1'], // 1, '1' 可能也是 1 数字类型
373
+ {
374
+ 'type': '6', // 2
375
+ 'type': column('type2'), // 3
376
+ // 'type': ['type3'], // 4 - 此写法已被禁止,请用 (3) 代替
377
+ 'type': ['(CASE `id` WHEN 1 THEN ? WHEN 2 THEN ? END)', ['val1', 'val2']], // 5
378
+ 'point': { 'x': 0, 'y': 0 }, // 6
379
+ 'polygon': [ [ { 'x': 0, 'y': 0 }, { ... } ], [ ... ] ], // 7
380
+ 'json': { 'a': 1, 'b': { 'c': 2 }, 'c': [ { 'c': 2 } ] }, // 8 - 对象类 json,可能为空对象
381
+ 'json2': ['abc'] // 9 - 数组类 json,可能为空数组
382
+ }
383
+ ]
384
+ */
293
385
  s = aoMix(s);
294
386
  let sql = '';
295
387
  for (const k in s) {
296
388
  const v = s[k];
297
389
  if (/^[0-9]+$/.test(k)) {
390
+ // --- 1 ---
298
391
  const nv = v[2];
299
392
  const isf = this._isField(nv);
300
393
  if (isf) {
@@ -316,8 +409,10 @@ class Sql {
316
409
  }
317
410
  }
318
411
  else {
412
+ // --- 2, 3, 4, 5, 6, 7, 8 ---
319
413
  sql += this.field(k) + ' = ';
320
414
  if (v === undefined || Number.isNaN(v)) {
415
+ // --- 异常情况 ---
321
416
  lCore.log({
322
417
  'path': '',
323
418
  'urlFull': '',
@@ -327,6 +422,7 @@ class Sql {
327
422
  'cookie': {},
328
423
  'headers': {}
329
424
  }, '(sql._updateSub) value error, key: ' + k, '-error').catch(() => {
425
+ //
330
426
  });
331
427
  sql += '"", ';
332
428
  }
@@ -334,18 +430,21 @@ class Sql {
334
430
  sql += 'NULL, ';
335
431
  }
336
432
  else if (typeof v === 'string' || typeof v === 'number') {
433
+ // --- 2 ---
337
434
  sql += '?, ';
338
435
  this._data.push(v);
339
436
  }
340
437
  else if (Array.isArray(v)) {
341
438
  if (v[0]?.[0]?.x === undefined && typeof v[0] === 'string' &&
342
439
  v[0].includes('(') && v[0].includes(')')) {
440
+ // --- 4, 5: ['(CASE `id` WHEN 1 THEN ? WHEN 2 THEN ? END)', ['val1', 'val2']] ---
343
441
  sql += this.field(v[0]) + ', ';
344
442
  if (v[1] !== undefined) {
345
443
  this._data.push(...v[1]);
346
444
  }
347
445
  }
348
446
  else if (v[0]?.[0]?.y !== undefined) {
447
+ // --- 7 ---
349
448
  sql += 'ST_POLYGONFROMTEXT(?), ';
350
449
  this._data.push(`POLYGON(${v.map((item) => {
351
450
  return `(${item.map((it) => {
@@ -354,33 +453,41 @@ class Sql {
354
453
  }).join(', ')})`);
355
454
  }
356
455
  else {
456
+ // --- v: json ---
357
457
  sql += '?, ';
358
458
  this._data.push(lText.stringifyJson(v));
359
459
  }
360
460
  }
361
461
  else if (v.x !== undefined) {
362
462
  if (v.y !== undefined) {
463
+ // --- 6: v: {'x': 1, 'y': 2} ---
363
464
  sql += 'ST_POINTFROMTEXT(?), ';
364
465
  this._data.push(`POINT(${v.x} ${v.y})`);
365
466
  }
366
467
  else {
468
+ // --- v: json ---
367
469
  if (this._isField(v)) {
470
+ // --- 3 ---
368
471
  sql += this.field(v.value) + ', ';
369
472
  }
370
473
  else {
474
+ // --- 8 ---
371
475
  sql += '?, ';
372
476
  this._data.push(lText.stringifyJson(v));
373
477
  }
374
478
  }
375
479
  }
376
480
  else if (v instanceof Buffer) {
481
+ // --- Buffer ---
377
482
  sql += '?, ';
378
483
  this._data.push(v);
379
484
  }
380
485
  else if (this._isField(v)) {
486
+ // --- 3 ---
381
487
  sql += this.field(v.value) + ', ';
382
488
  }
383
489
  else {
490
+ // --- json ---
384
491
  sql += '?, ';
385
492
  this._data.push(lText.stringifyJson(v));
386
493
  }
@@ -389,23 +496,45 @@ class Sql {
389
496
  sql = sql.slice(0, -2);
390
497
  return sql;
391
498
  }
499
+ /**
500
+ * --- 'xx' ---
501
+ * @param f 表名
502
+ */
392
503
  delete(f) {
393
504
  this._data = [];
394
505
  this._sql = ['DELETE FROM ' + this.field(f, this._pre)];
395
506
  return this;
396
507
  }
508
+ /**
509
+ * --- 联查另一个 sql 对象 ---
510
+ * @param sql sql 对象
511
+ * @param type 类型
512
+ */
397
513
  union(lsql, type = '') {
398
514
  this._data = this._data.concat(lsql.getData());
399
515
  this._sql.push(' UNION ' + (type ? type + ' ' : ''));
400
516
  this._sql.push(lsql.getSql());
401
517
  return this;
402
518
  }
519
+ /**
520
+ * --- 所有联查另一个 sql 对象 ---
521
+ * @param sql sql 对象
522
+ */
403
523
  unionAll(lsql) {
404
524
  return this.union(lsql, 'ALL');
405
525
  }
526
+ /**
527
+ * --- join 方法 ---
528
+ * @param f 表名
529
+ * @param s ON 信息
530
+ * @param type 类型
531
+ * @param suf 表后缀
532
+ * @param pre 表前缀,仅在 join 非默认表前缀时填写
533
+ */
406
534
  join(f, s = [], type = 'INNER', suf = '', pre = '') {
407
535
  let field = this.field(f, pre || this._pre, suf ? ('#' + suf) : '');
408
536
  if (pre) {
537
+ // --- 处理不同 pre 的 as 前缀问题 ---
409
538
  field = field.replace(new RegExp(`AS \`${pre}(.+?)\``), `AS \`${this._pre}$1\``);
410
539
  }
411
540
  let sql = ' ' + type + ' JOIN ' + field;
@@ -415,28 +544,68 @@ class Sql {
415
544
  this._sql.push(sql);
416
545
  return this;
417
546
  }
547
+ /**
548
+ * --- left join 方法 ---
549
+ * @param f 表名
550
+ * @param s ON 信息
551
+ * @param suf 表后缀
552
+ * @param pre 表前缀,仅在 join 非默认表前缀时填写
553
+ */
418
554
  leftJoin(f, s = [], suf = '', pre = '') {
419
555
  return this.join(f, s, 'LEFT', suf, pre);
420
556
  }
557
+ /**
558
+ * --- right join 方法 ---
559
+ * @param f 表名
560
+ * @param s ON 信息
561
+ * @param suf 表后缀
562
+ * @param pre 表前缀,仅在 join 非默认表前缀时填写
563
+ */
421
564
  rightJoin(f, s = [], suf = '', pre = '') {
422
565
  return this.join(f, s, 'RIGHT', suf, pre);
423
566
  }
567
+ /**
568
+ * --- inner join 方法 ---
569
+ * @param f 表名
570
+ * @param s ON 信息
571
+ * @param suf 表后缀
572
+ * @param pre 表前缀,仅在 join 非默认表前缀时填写
573
+ */
424
574
  innerJoin(f, s = [], suf = '', pre = '') {
425
575
  return this.join(f, s, 'INNER', suf, pre);
426
576
  }
577
+ /**
578
+ * --- full join 方法 ---
579
+ * @param f 表名
580
+ * @param s ON 信息
581
+ * @param suf 表后缀
582
+ * @param pre 表前缀,仅在 join 非默认表前缀时填写
583
+ */
427
584
  fullJoin(f, s = [], suf = '', pre = '') {
428
585
  return this.join(f, s, 'FULL', suf, pre);
429
586
  }
587
+ /**
588
+ * --- cross join 方法 ---
589
+ * @param f 表名
590
+ * @param s ON 信息
591
+ * @param suf 表后缀
592
+ * @param pre 表前缀,仅在 join 非默认表前缀时填写
593
+ */
430
594
  crossJoin(f, s = [], suf = '', pre = '') {
431
595
  return this.join(f, s, 'CROSS', suf, pre);
432
596
  }
597
+ /**
598
+ * --- having 后置筛选器,用法类似 where ---
599
+ */
433
600
  having(s = '') {
434
601
  if (typeof s === 'string') {
602
+ // --- string ---
435
603
  if (s !== '') {
436
604
  this._sql.push(' HAVING ' + s);
437
605
  }
438
606
  }
439
607
  else {
608
+ // --- array ---
440
609
  if (s.length) {
441
610
  const whereSub = this._whereSub(s);
442
611
  if (whereSub !== '') {
@@ -446,15 +615,28 @@ class Sql {
446
615
  }
447
616
  return this;
448
617
  }
618
+ /**
619
+ * --- 筛选器 ---
620
+ * --- 1. 'city': 'bj', 'type': '2' ---
621
+ * --- 2. ['type', '>', '1'] ---
622
+ * --- 3. ['type', 'in', ['1', '2']] ---
623
+ * --- 4. 'type': ['1', '2'] ---
624
+ * --- 5. '$or': [{'city': 'bj'}, {'city': 'sh'}, [['age', '>', '10']]], 'type': '2' ---
625
+ * --- 6. 'city_in': column('city_out') ---
626
+ * --- 7. ['JSON_CONTAINS(`uid`, ?)', ['hello']] ---
627
+ * @param s 筛选数据
628
+ */
449
629
  where(s) {
450
630
  this._whereDataPosition[0] = this._data.length;
451
631
  if (typeof s === 'string') {
632
+ // --- string ---
452
633
  if (s !== '') {
453
634
  this._sql.push(' WHERE ' + s);
454
635
  this._whereDataPosition[1] = this._data.length;
455
636
  }
456
637
  }
457
638
  else {
639
+ // --- array ---
458
640
  let go = false;
459
641
  if (Array.isArray(s)) {
460
642
  if (s.length) {
@@ -483,13 +665,16 @@ class Sql {
483
665
  for (const k in s) {
484
666
  const v = s[k];
485
667
  if (/^[0-9]+$/.test(k)) {
668
+ // --- 2, 3, 7 ---
486
669
  if (v[2] === undefined) {
670
+ // --- 7 ---
487
671
  sql += this.field(v[0]) + ' AND ';
488
672
  if (v[1] !== undefined) {
489
673
  data.push(...v[1]);
490
674
  }
491
675
  }
492
676
  else if (v[2] === null) {
677
+ // --- 3: null ---
493
678
  let opera = v[1];
494
679
  if (opera === '!=' || opera === '!==' || opera === '<>') {
495
680
  opera = 'IS NOT';
@@ -503,6 +688,7 @@ class Sql {
503
688
  sql += this.field(v[0]) + ' ' + opera + ' NULL AND ';
504
689
  }
505
690
  else if (Array.isArray(v[2])) {
691
+ // --- 3 ---
506
692
  sql += this.field(v[0]) + ' ' + v[1].toUpperCase() + ' (';
507
693
  for (const v1 of v[2]) {
508
694
  sql += '?, ';
@@ -511,9 +697,11 @@ class Sql {
511
697
  sql = sql.slice(0, -2) + ') AND ';
512
698
  }
513
699
  else {
700
+ // --- 2, 6 ---
514
701
  const nv = v[2];
515
702
  const isf = this._isField(nv);
516
703
  if (isf) {
704
+ // --- 6. field ---
517
705
  sql += this.field(v[0]) + ' ' + v[1] + ' ' + this.field(nv.value) + ' AND ';
518
706
  }
519
707
  else {
@@ -523,10 +711,13 @@ class Sql {
523
711
  }
524
712
  }
525
713
  else {
714
+ // --- 1, 4, 5, 6 ---
526
715
  if (k.startsWith('$')) {
716
+ // --- 5 - '$or': [{'city': 'bj'}, {'city': 'sh'}] ---
527
717
  const sp = ' ' + k.slice(1).split('-')[0].toUpperCase() + ' ';
528
718
  sql += '(';
529
719
  for (let v1 of v) {
720
+ // --- v1 是 {'city': 'bj'} ---
530
721
  v1 = aoMix(v1);
531
722
  if (Object.keys(v1).length > 1) {
532
723
  sql += '(' + this._whereSub(v1, data) + ')' + sp;
@@ -538,17 +729,21 @@ class Sql {
538
729
  sql = sql.slice(0, -sp.length) + ') AND ';
539
730
  }
540
731
  else {
732
+ // --- 1, 4, 6 ---
541
733
  if (v === null) {
542
734
  sql += this.field(k) + ' IS NULL AND ';
543
735
  }
544
736
  else if (typeof v === 'string' || typeof v === 'number') {
737
+ // --- 1 ---
545
738
  sql += this.field(k) + ' = ? AND ';
546
739
  data.push(v);
547
740
  }
548
741
  else if (this._isField(v)) {
742
+ // --- 6 ---
549
743
  sql += this.field(k) + ' = ' + this.field(v.value) + ' AND ';
550
744
  }
551
745
  else {
746
+ // --- 4 - 'type': ['1', '2'] ---
552
747
  if (v.length > 0) {
553
748
  sql += this.field(k) + ' IN (';
554
749
  for (const v1 of v) {
@@ -569,6 +764,11 @@ class Sql {
569
764
  }
570
765
  return sql.slice(0, -5);
571
766
  }
767
+ /**
768
+ * --- ORDER BY ---
769
+ * @param c 字段字符串或数组
770
+ * @param d 排序规则
771
+ */
572
772
  by(c, d = 'DESC') {
573
773
  let sql = ' ORDER BY ';
574
774
  if (typeof c === 'string') {
@@ -588,6 +788,10 @@ class Sql {
588
788
  this._sql.push(sql);
589
789
  return this;
590
790
  }
791
+ /**
792
+ * --- GROUP BY ---
793
+ * @param c 字段字符串或数组
794
+ */
591
795
  group(c) {
592
796
  let sql = ' GROUP BY ';
593
797
  if (typeof c === 'string') {
@@ -602,19 +806,32 @@ class Sql {
602
806
  this._sql.push(sql);
603
807
  return this;
604
808
  }
809
+ /**
810
+ * --- LIMIT ---
811
+ * @param a 起始
812
+ * @param b 长度
813
+ */
605
814
  limit(a, b = 0) {
606
815
  this._sql.push(' LIMIT ' + a.toString() + (b > 0 ? ', ' + b.toString() : ''));
607
816
  return this;
608
817
  }
818
+ /**
819
+ * --- 追加消极锁,通常不建议使用 ---
820
+ */
609
821
  lock() {
610
822
  this._sql.push(' FOR UPDATE');
611
823
  return this;
612
824
  }
825
+ /**
826
+ * --- 创建一个本对象的一个新的 sql 对象拷贝 ---
827
+ * @param f 可为空,可设置新对象的 table 名变化
828
+ */
613
829
  copy(f, opt = {}) {
614
830
  const sql = lCore.clone(this._sql);
615
831
  const data = lCore.clone(this._data);
616
832
  if (opt.where !== undefined) {
617
833
  if (typeof opt.where === 'string') {
834
+ // --- string ---
618
835
  for (let i = 0; i < sql.length; ++i) {
619
836
  if (!sql[i].startsWith(' WHERE ')) {
620
837
  continue;
@@ -625,6 +842,7 @@ class Sql {
625
842
  }
626
843
  }
627
844
  else {
845
+ // --- array ---
628
846
  let go = false;
629
847
  if (Array.isArray(opt.where)) {
630
848
  if (opt.where.length) {
@@ -636,16 +854,19 @@ class Sql {
636
854
  go = true;
637
855
  }
638
856
  }
857
+ // --- 找到原来的 where ---
639
858
  for (let i = 0; i < sql.length; ++i) {
640
859
  if (!sql[i].startsWith(' WHERE ')) {
641
860
  continue;
642
861
  }
643
862
  if (go) {
863
+ // --- 修改 where ---
644
864
  const d = [];
645
865
  sql[i] = ' WHERE ' + this._whereSub(opt.where, d);
646
866
  data.splice(this._whereDataPosition[0], this._whereDataPosition[1] - this._whereDataPosition[0], ...d);
647
867
  }
648
868
  else {
869
+ // --- 清除 where ---
649
870
  sql.splice(i, 1);
650
871
  data.splice(this._whereDataPosition[0], this._whereDataPosition[1] - this._whereDataPosition[0]);
651
872
  }
@@ -653,12 +874,14 @@ class Sql {
653
874
  }
654
875
  }
655
876
  }
877
+ // --- 替换表名 ---
656
878
  if (f && sql[0]) {
657
879
  let table = '';
658
880
  if (typeof f === 'string') {
659
881
  table = this.field(f, this._pre);
660
882
  }
661
883
  else {
884
+ // --- f: ['user', 'order'] ---
662
885
  for (const i of f) {
663
886
  table += this.field(i, this._pre) + ', ';
664
887
  }
@@ -671,22 +894,48 @@ class Sql {
671
894
  'sql': sql
672
895
  });
673
896
  }
897
+ // --- 操作 ---
898
+ /**
899
+ * --- 获取 sql 语句 ---
900
+ */
674
901
  getSql() {
675
902
  return this._sql.join('');
676
903
  }
904
+ /**
905
+ * --- 获取全部 data ---
906
+ */
677
907
  getData() {
678
908
  return this._data;
679
909
  }
910
+ /**
911
+ * --- 获取定义的 pre ---
912
+ */
680
913
  getPre() {
681
914
  return this._pre;
682
915
  }
916
+ /**
917
+ * --- 获取带 data 的 sql 语句 ---
918
+ * @param sql
919
+ * @param data
920
+ */
683
921
  format(sql, data) {
684
922
  return mysql2.format(sql ?? this.getSql(), data ?? this.getData());
685
923
  }
924
+ // --- 特殊方法 ---
925
+ /**
926
+ * --- 在 sql 最后追加字符串 ---
927
+ * @param sql
928
+ */
686
929
  append(sql) {
687
930
  this._sql.push(sql);
688
931
  return this;
689
932
  }
933
+ /**
934
+ * --- 对字段进行包裹 ---
935
+ * @param str
936
+ * @param pre 表前缀,仅请在 field 表名时倒入前缀
937
+ * @param suf 表后缀,仅请在 field 表名时倒入后缀,前面加 # 代表要强制 AS
938
+ */
690
939
  field(str, pre = '', suf = '') {
691
940
  let left = '';
692
941
  let right = '';
@@ -697,26 +946,33 @@ class Sql {
697
946
  if (typeof str === 'number') {
698
947
  str = str.toString();
699
948
  }
700
- str = str.trim();
701
- str = str.replace(/ {2,}/g, ' ');
949
+ str = str.trim(); // --- 去除前导尾随 ---
950
+ str = str.replace(/ {2,}/g, ' '); // --- 去除多余的空格 ---
702
951
  str = str.replace(/ +([),])/g, ' $1');
703
952
  str = str.replace(/([(,]) +/g, '$1 ');
704
953
  str = str.replace(/(\W)(JOIN|WHERE|UNION)(\W)/ig, '$1$3');
954
+ // --- 先判断 suf 强制性 AS ---
705
955
  let sufAs = false;
706
956
  if (suf.startsWith('#')) {
957
+ // --- 强制 AS ---
707
958
  suf = suf.slice(1);
708
959
  sufAs = true;
709
960
  }
961
+ // --- 先判断有没有别名(也就是 as) ---
710
962
  const loStr = str.toLowerCase();
711
963
  const asPos = loStr.indexOf(' as ');
712
964
  if (asPos === -1) {
965
+ // --- 没有 as ---
713
966
  let spacePos = str.lastIndexOf(' ');
967
+ // --- 有可能有 aa + bb + cc + 10 这种情况 ---
714
968
  if (!/^[a-zA-Z_)]$/.test(str[spacePos - 1])) {
969
+ // --- 连接符 ---
715
970
  spacePos = -1;
716
971
  }
717
972
  if (spacePos !== -1) {
718
973
  const spaceRight = str.slice(spacePos + 1);
719
974
  if (/^[a-zA-Z_`][\w`]*$/.test(spaceRight)) {
975
+ // --- OK ---
720
976
  left = str.slice(0, spacePos);
721
977
  right = spaceRight;
722
978
  }
@@ -731,10 +987,12 @@ class Sql {
731
987
  }
732
988
  }
733
989
  else {
990
+ // --- 有 as ---
734
991
  left = str.slice(0, asPos);
735
992
  right = str.slice(asPos + 4);
736
993
  }
737
994
  if (right) {
995
+ // --- 处理右侧 ---
738
996
  if (right.startsWith('`')) {
739
997
  right = '`' + pre + right.slice(1);
740
998
  }
@@ -744,10 +1002,13 @@ class Sql {
744
1002
  right = ' AS ' + right;
745
1003
  }
746
1004
  else {
1005
+ // --- 没有右侧 ---
747
1006
  if (sufAs) {
1007
+ // --- 强制 AS ---
748
1008
  right = ' AS ' + this.field(left, pre);
749
1009
  }
750
1010
  }
1011
+ // --- 处理 left ---
751
1012
  if (/^[\w`_.*]+$/.test(left)) {
752
1013
  const l = left.split('.');
753
1014
  if (l[0] === '*') {
@@ -757,20 +1018,29 @@ class Sql {
757
1018
  l[0] = l[0].replace(/`/g, '');
758
1019
  }
759
1020
  if (l[1] === undefined) {
1021
+ // --- xxx ---
760
1022
  if (/^[A-Z0-9_]+$/.test(l[0])) {
1023
+ // --- 纯大写是内置函数,不能加 ` ---
761
1024
  return l[0] + right;
762
1025
  }
763
1026
  return '`' + pre + l[0] + suf + '`' + right;
764
1027
  }
1028
+ // --- x.xxx ---
1029
+ // --- 只有在此模式才知道 . 前面的一定是表名,因此自动加 sql 级的 _pre ---
765
1030
  const w = l[1] === '*' ? '*' : (l[1].startsWith('`') ? l[1] : ('`' + l[1] + '`'));
766
1031
  return '`' + this._pre + l[0] + suf + '`.' + w + right;
767
1032
  }
768
1033
  else {
1034
+ // return left.replace(/([(, ])([a-zA-Z`_][\w`_.]*)(?=[), ])/g, (
769
1035
  return left.replace(/(^|[(, ])([a-zA-Z`_][\w`_.]*)(?=[), ]|$)/g, (t, t1, t2) => {
770
1036
  return t1 + this.field(t2, pre, suf);
771
1037
  }) + right;
772
1038
  }
773
1039
  }
1040
+ /**
1041
+ * --- 判断传入值是否是 field,还是别的对象 ---
1042
+ * @param str
1043
+ */
774
1044
  _isField(arg) {
775
1045
  if (arg.type !== 'column' || arg.token !== columnToken || arg.value === undefined) {
776
1046
  return false;
@@ -779,12 +1049,26 @@ class Sql {
779
1049
  }
780
1050
  }
781
1051
  exports.Sql = Sql;
1052
+ /**
1053
+ * --- 创建 sql 对象 ---
1054
+ * @param ctrPre ctr 对象或 pre 表前缀
1055
+ * @param opt 参数
1056
+ */
782
1057
  function get(ctrPre, opt = {}) {
783
1058
  return new Sql(ctrPre instanceof ctr.Ctr ? ctrPre.getPrototype('_config').sql.pre : ctrPre, opt);
784
1059
  }
1060
+ /**
1061
+ * --- 返回代入后的完整 SQL 字符串 ---
1062
+ * @param sql SQL 字符串
1063
+ * @param data DATA 数据
1064
+ */
785
1065
  function format(sql, data) {
786
1066
  return mysql2.format(sql, data);
787
1067
  }
1068
+ /**
1069
+ * --- 将数组兑换为组合的对象(Array/Object mix) ---
1070
+ * @param arr 要转换的数组
1071
+ */
788
1072
  function aoMix(arr) {
789
1073
  if (!Array.isArray(arr)) {
790
1074
  return arr;
@@ -804,6 +1088,7 @@ function aoMix(arr) {
804
1088
  }
805
1089
  return mix;
806
1090
  }
1091
+ /** --- 创建字段对象 --- */
807
1092
  function column(field) {
808
1093
  if (!columnToken) {
809
1094
  columnToken = lCore.random(8, lCore.RANDOM_LUNS);