imodel 0.0.0 → 0.1.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/index.mjs ADDED
@@ -0,0 +1,5072 @@
1
+ /*!
2
+ * imodel v0.1.0
3
+ * (c) 2019-2025 undefined
4
+ * @license undefined
5
+ */
6
+
7
+ let isDevelopment = false;
8
+ /**
9
+ *
10
+ * @param {boolean} [d]
11
+ */
12
+ function setDevelopment(d) {
13
+ isDevelopment = Boolean(d);
14
+ }
15
+
16
+ const deleted = Symbol();
17
+ const undeleted = Symbol();
18
+ const withDeleted = Symbol();
19
+ /** @typedef {typeof deleted} deleted */
20
+ /** @typedef {typeof undeleted} undeleted */
21
+ /** @typedef {typeof withDeleted} withDeleted */
22
+ /** @typedef {deleted | undeleted | withDeleted} FindRange */
23
+
24
+ /** @import { FindRange } from './FindRange.mjs' */
25
+ /** @import { TableDefine, Queryable } from './types' */
26
+ /** @type {Set<FindRange | undefined>} */
27
+ const virtualDeletionSet = new Set([undeleted, withDeleted]);
28
+ /**
29
+ *
30
+ * @param {TableDefine} model
31
+ * @returns
32
+ */
33
+ function canPseudo(model) {
34
+ if (!model.pseudo) {
35
+ return false;
36
+ }
37
+ if (!(model.pseudo in model.fields)) {
38
+ return false;
39
+ }
40
+ return true;
41
+ }
42
+ /**
43
+ *
44
+ * @param {Queryable} model
45
+ * @returns
46
+ */
47
+ function isPseudo(model) {
48
+ if (!canPseudo(model)) {
49
+ return false;
50
+ }
51
+ return !virtualDeletionSet.has(model.options.range);
52
+ }
53
+
54
+ const now = Symbol();
55
+ const increment$1 = Symbol();
56
+ const decrement$1 = Symbol();
57
+ const multiply$1 = Symbol();
58
+ const divide$1 = Symbol();
59
+
60
+ var values = /*#__PURE__*/Object.freeze({
61
+ __proto__: null,
62
+ decrement: decrement$1,
63
+ divide: divide$1,
64
+ increment: increment$1,
65
+ multiply: multiply$1,
66
+ now: now
67
+ });
68
+
69
+ /** @import { Fields, FieldType } from './types' */
70
+ /**
71
+ *
72
+ * @param {Fields} fields
73
+ * @returns {Fields<keyof FieldType>}
74
+ */
75
+ function toBaseFields(fields) {
76
+ /** @type {Fields<keyof FieldType>} */
77
+ const allFields = {};
78
+ for (const [k, v] of Object.entries(fields)) {
79
+ const {
80
+ type
81
+ } = v;
82
+ if (typeof type === 'string') {
83
+ // @ts-ignore
84
+ allFields[k] = v;
85
+ continue;
86
+ }
87
+ if (!type.table) {
88
+ allFields[k] = {
89
+ ...v,
90
+ type: 'object',
91
+ primary: false
92
+ };
93
+ }
94
+ }
95
+ return allFields;
96
+ }
97
+
98
+ /** @import { Options, Queryable } from '../types' */
99
+ /**
100
+ *
101
+ * @param {Queryable} model
102
+ * @returns {Options}
103
+ */
104
+ function getOptions(model) {
105
+ const options = {
106
+ ...model.options
107
+ };
108
+ if (!model.pseudo) {
109
+ return options;
110
+ }
111
+ if (!(model.pseudo in model.fields)) {
112
+ return options;
113
+ }
114
+ if (options.range === undeleted) {
115
+ options.where = [...options.where, {
116
+ field: model.pseudo,
117
+ operator: '<>',
118
+ value: 0
119
+ }];
120
+ } else if (options.range !== withDeleted) {
121
+ options.where = [...options.where, {
122
+ field: model.pseudo,
123
+ operator: '=',
124
+ value: 0
125
+ }];
126
+ }
127
+ return options;
128
+ }
129
+
130
+ /** @typedef {SetValue.Increment | SetValue.Decrement | SetValue.Multiply | SetValue.Divide | string | number | bigint | boolean | null | typeof now} SetValue */
131
+ /** @typedef {{[values.increment]: number | bigint}} SetValue.Increment */
132
+ /** @typedef {{[values.decrement]: number | bigint}} SetValue.Decrement */
133
+ /** @typedef {{[values.multiply]: number | bigint}} SetValue.Multiply */
134
+ /** @typedef {{[values.divide]: number | bigint}} SetValue.Divide */
135
+ /**
136
+ * @param {number | bigint} value
137
+ * @returns {SetValue.Increment}
138
+ */
139
+ function increment(value) {
140
+ return {
141
+ [increment$1]: value
142
+ };
143
+ }
144
+ /**
145
+ * @param {number | bigint} value
146
+ * @returns {SetValue.Decrement}
147
+ */
148
+ function decrement(value) {
149
+ return {
150
+ [decrement$1]: value
151
+ };
152
+ }
153
+ /**
154
+ * @param {number | bigint} value
155
+ * @returns {SetValue.Multiply}
156
+ */
157
+ function multiply(value) {
158
+ return {
159
+ [multiply$1]: value
160
+ };
161
+ }
162
+ /**
163
+ * @param {number | bigint} value
164
+ * @returns {SetValue.Divide}
165
+ */
166
+ function divide(value) {
167
+ return {
168
+ [divide$1]: value
169
+ };
170
+ }
171
+
172
+ /** @import { SetValue } from '../../set.mjs' */
173
+ /** @import { Fields } from '../../types' */
174
+ /**
175
+ *
176
+ * @param {Fields} fields
177
+ * @param {Record<string, SetValue> | null | undefined} [update]
178
+ * @returns {Record<string, SetValue>}
179
+ */
180
+ function getSetNewValue(fields, update) {
181
+ const data = {
182
+ ...update
183
+ };
184
+ for (const [name, field] of Object.entries(fields)) {
185
+ if (!field.primary && field.timestampUpdating) {
186
+ data[name] = now;
187
+ }
188
+ }
189
+ return Object.fromEntries(Object.entries(data).filter(([k, v]) => {
190
+ const field = k in fields && fields[k];
191
+ if (!field) {
192
+ return;
193
+ }
194
+ if (field.immutable || field.serial && field.type === 'id') {
195
+ return;
196
+ }
197
+ return true;
198
+ }));
199
+ }
200
+
201
+ /** @import { Fields } from '../../types' */
202
+ /**
203
+ *
204
+ * @param {Record<string, any>} data
205
+ * @param {Fields} fields
206
+ * @returns {Record<string, any>}
207
+ */
208
+ function getInsertValue(data, fields) {
209
+ const insertValue = {};
210
+ for (const [k, field] of Object.entries(fields)) {
211
+ if (field.timestampCreating) {
212
+ insertValue[k] = now;
213
+ continue;
214
+ }
215
+ const val = data[k];
216
+ if (val !== undefined) {
217
+ insertValue[k] = val;
218
+ continue;
219
+ }
220
+ const def = field.default;
221
+ if (def === undefined) {
222
+ continue;
223
+ }
224
+ if (typeof def === 'function') {
225
+ insertValue[k] = def(data);
226
+ continue;
227
+ }
228
+ insertValue[k] = def;
229
+ }
230
+ return insertValue;
231
+ }
232
+
233
+ /** @import { ColumnOptions } from '../../types' */
234
+ /**
235
+ * @template {ColumnOptions} T
236
+ * @param {T} v
237
+ * @returns {T}
238
+ */
239
+ function timestampDef(v) {
240
+ const isTime = v.timestampCreating || v.timestampUpdating;
241
+ if (!isTime) {
242
+ return v;
243
+ }
244
+ return {
245
+ ...v,
246
+ default: now
247
+ };
248
+ }
249
+
250
+ /** @import { FieldDefine, Fields, FieldType, TableDefine } from '../../types' */
251
+ /**
252
+ *
253
+ * @param {Fields} fields
254
+ * @returns {[Fields<keyof FieldType>, [string, FieldDefine<TableDefine>][]]}
255
+ */
256
+ function separateFields(fields) {
257
+ /** @type {Fields<keyof FieldType>} */
258
+ const base = Object.create(null);
259
+ /** @type {[string, FieldDefine<TableDefine>][]} */
260
+ const sub = [];
261
+ for (const [k, v] of Object.entries(fields)) {
262
+ const {
263
+ type
264
+ } = v;
265
+ if (typeof type === 'string') {
266
+ // @ts-ignore
267
+ base[k] = v;
268
+ } else if (!type.table) {
269
+ base[k] = {
270
+ ...v,
271
+ type: 'object',
272
+ primary: false
273
+ };
274
+ } else {
275
+ // @ts-ignore
276
+ sub.push([k, v]);
277
+ }
278
+ }
279
+ return [base, sub];
280
+ }
281
+
282
+ /**
283
+ *
284
+ * @param {*} item
285
+ * @param {[string, string][]} mapList
286
+ * @returns
287
+ */
288
+ function createFilter(item, mapList) {
289
+ /** @type {[string, any][]} */
290
+ const values = mapList.map(([k, v]) => [k, item[v]]);
291
+ return sub => {
292
+ for (const [k, v] of values) {
293
+ if (sub[k] !== v) {
294
+ return false;
295
+ }
296
+ }
297
+ return true;
298
+ };
299
+ }
300
+
301
+ /** @import { Environment, FieldDefine, Fields, GetName, IConnection, TableDefine } from '../types' */
302
+ /**
303
+ *
304
+ * @param {any} p
305
+ * @param {Fields} fields
306
+ * @returns
307
+ */
308
+ function getOtherValues(p, fields) {
309
+ const s = {};
310
+ for (const k of Reflect.ownKeys(p)) {
311
+ if (k in fields) {
312
+ continue;
313
+ }
314
+ s[k] = p[k];
315
+ }
316
+ return s;
317
+ }
318
+ /**
319
+ *
320
+ * @param {any} value
321
+ * @param {any} others
322
+ * @returns
323
+ */
324
+ function defaultMap(value, others) {
325
+ return {
326
+ ...value,
327
+ ...others
328
+ };
329
+ }
330
+ /**
331
+ *
332
+ * @param {IConnection} conn
333
+ * @param {GetName} getName
334
+ * @param {Environment} env
335
+ * @param {[string, FieldDefine<TableDefine>][]} fields
336
+ * @param {Record<string, any>[]} newList
337
+ * @param {Record<string, any>[]} list
338
+ * @returns {Promise<Record<string, any>[]>}
339
+ */
340
+ async function createSub(conn, getName, env, fields, newList, list) {
341
+ // TODO: 可创建字段过滤
342
+ if (!list.length) {
343
+ return list;
344
+ }
345
+ /** @type {[Record<string, any>, Record<string, any>][]} */
346
+ const allList = list.map((v, i) => [v, newList[i]]);
347
+ /** @type {PromiseLike<any>[]} */
348
+ const promises = [];
349
+ for (const [key, {
350
+ type,
351
+ array,
352
+ constraints
353
+ }] of fields) {
354
+ const {
355
+ fields
356
+ } = type;
357
+ const constraintEntries = Object.entries(constraints || {});
358
+ const noField = constraintEntries.find(([k, v]) => v.noField)?.[0];
359
+ /** @type {Record<string, any>} */
360
+ const commonValue = {};
361
+ /** @type {[string, string][]} */
362
+ const commonKeys = [];
363
+ for (const [k, {
364
+ field,
365
+ value: val
366
+ }] of constraintEntries) {
367
+ if (field) {
368
+ commonKeys.push([k, field]);
369
+ } else if (val !== undefined) {
370
+ commonValue[k] = val;
371
+ }
372
+ }
373
+ /** @type {Record<string, any>[][]} */
374
+ const allFieldValues = [];
375
+ for (const [main, records] of allList) {
376
+ const record = records?.[key];
377
+ // eslint-disable-next-line no-nested-ternary
378
+ const newList = Array.isArray(record) ? array ? record : [record[0]] : [record];
379
+ const values = newList.filter(v => v && typeof v === 'object');
380
+ if (!values.length) {
381
+ continue;
382
+ }
383
+ const commonValues = {
384
+ ...Object.fromEntries(commonKeys.map(([k, v]) => [k, main[v]])),
385
+ ...commonValue
386
+ };
387
+ const list = values.map(value => ({
388
+ ...value,
389
+ ...commonValues
390
+ }));
391
+ allFieldValues.push(noField ? list.map((v, i) => ({
392
+ ...v,
393
+ [noField]: i + 1
394
+ })) : list);
395
+ }
396
+ /** @type {Record<string, any>[]} */
397
+ const fieldValues = allFieldValues.flat();
398
+ if (!fieldValues.length) {
399
+ if (array) {
400
+ for (const [value] of allList) {
401
+ value[key] = [];
402
+ }
403
+ continue;
404
+ }
405
+ for (const [value] of allList) {
406
+ value[key] = null;
407
+ }
408
+ continue;
409
+ }
410
+ const [baseFields, tableFields] = separateFields(fields);
411
+ const insertKeys = Object.entries(baseFields).filter(([, o]) => !o.serial || o.type !== 'id').map(v => v[0]);
412
+ const insertValues = fieldValues.map(d => getInsertValue(d, fields));
413
+ const {
414
+ table
415
+ } = type;
416
+ const result = table && typeof table === 'object' ? table.insert(env, conn, '', baseFields, insertValues, insertKeys) : conn.insert(env, getName(table), baseFields, insertValues, insertKeys);
417
+ promises.push(result.then(r => createSub(conn, getName, env, tableFields, fieldValues, r)));
418
+ promises.push(array ? result.then(values => {
419
+ for (const [value] of allList) {
420
+ value[key] = values.filter(createFilter(value, commonKeys));
421
+ }
422
+ }) : result.then(values => {
423
+ for (const [value] of allList) {
424
+ value[key] = values.find(createFilter(value, commonKeys)) || null;
425
+ }
426
+ }));
427
+ }
428
+ return Promise.all(promises).then(() => list);
429
+ }
430
+ // TODO: 嵌套
431
+ /**
432
+ *
433
+ * @param {IConnection} conn
434
+ * @param {GetName} getName
435
+ * @param {Environment} env
436
+ * @param {TableDefine} model
437
+ * @param {any} p
438
+ * @param {(a,b) => object} mapDo
439
+ * @returns {Promise<any>}
440
+ */
441
+ async function create(conn, getName, env, model, p, mapDo = defaultMap) {
442
+ const {
443
+ table,
444
+ fields
445
+ } = model;
446
+ const isArray = Array.isArray(p);
447
+ const param = Object.create(null);
448
+ /** @type {any[]} */
449
+ const records = [];
450
+ for (const item of isArray ? p : [p]) {
451
+ const data = {
452
+ ...param
453
+ };
454
+ for (let k of Object.getOwnPropertyNames(item)) {
455
+ if (k in data) {
456
+ continue;
457
+ }
458
+ data[k] = item[k];
459
+ }
460
+ records.push(data);
461
+ }
462
+ const [baseFields, tableFields] = separateFields(fields);
463
+ const insertValues = records.map(d => getInsertValue(d, baseFields));
464
+ let insertKeys = [];
465
+ if (!insertKeys.length && !isArray) {
466
+ insertKeys = Object.entries(insertValues[0]).filter(([k, v]) => v !== undefined && k in baseFields).map(([k]) => k);
467
+ }
468
+ if (!insertKeys.length) {
469
+ insertKeys = Object.entries(baseFields).filter(([, o]) => !o.serial || o.type !== 'id').map(([k]) => k);
470
+ }
471
+ const list = table && typeof table === 'object' ? await table.insert(env, conn, '', baseFields, insertValues, insertKeys) : await conn.insert(env, getName(table), baseFields, insertValues, insertKeys);
472
+ await createSub(conn, getName, env, tableFields, records, list);
473
+ const value = list.map((v, i) => mapDo(v, getOtherValues(records[i], fields)));
474
+ return isArray ? value : value[0];
475
+ }
476
+
477
+ /** @import { Fields } from './types' */
478
+ /**
479
+ *
480
+ * @param {Fields} fields
481
+ * @returns {string[]}
482
+ */
483
+ function getPrimaryKeys(fields) {
484
+ const list = Object.entries(fields);
485
+ const primaryKeys = list.filter(([v, o]) => typeof o.type === 'string' && o.primary);
486
+ if (primaryKeys.length) {
487
+ return primaryKeys.map(([k]) => k);
488
+ }
489
+ const idKeys = list.filter(([v, o]) => o.serial && o.type === 'id');
490
+ if (idKeys.length) {
491
+ return idKeys.map(([k]) => k);
492
+ }
493
+ return [list[0][0]];
494
+ }
495
+
496
+ /** @import { Constraint, Fields, FieldType } from '../../types' */
497
+ /**
498
+ * @param {Fields<keyof FieldType>} fields
499
+ * @param {Fields<keyof FieldType>} parentFields
500
+ * @param {Record<string, string | Constraint> | undefined} constraints
501
+ * @returns {[string, string][]?}
502
+ */
503
+ function getMapList(fields, parentFields, constraints) {
504
+ if (!constraints) {
505
+ return null;
506
+ }
507
+ /** @type {[string, string][]} */
508
+ const where = [];
509
+ for (const [k, v] of Object.entries(constraints)) {
510
+ if (!(k in fields)) {
511
+ continue;
512
+ }
513
+ const field = typeof v === 'string' ? v : v.field;
514
+ if (typeof field !== 'string') {
515
+ continue;
516
+ }
517
+ if (!(field in parentFields)) {
518
+ continue;
519
+ }
520
+ where.push([k, field]);
521
+ }
522
+ if (!where.length) {
523
+ return null;
524
+ }
525
+ return where;
526
+ }
527
+
528
+ /** @import { Constraint, Fields, FieldType } from '../../types' */
529
+ /**
530
+ *
531
+ * @param {Record<string, Constraint> | undefined} value
532
+ * @param {Fields<keyof FieldType>} fields
533
+ * @returns {[string, unknown][]}
534
+ */
535
+ function getValueEntries(value, fields) {
536
+ if (!value) {
537
+ return [];
538
+ }
539
+ /** @type {[string, unknown][]} */
540
+ const where = [];
541
+ for (const [k, v] of Object.entries(value)) {
542
+ if (!(k in fields)) {
543
+ continue;
544
+ }
545
+ if (!v || typeof v !== 'object') {
546
+ continue;
547
+ }
548
+ const {
549
+ value
550
+ } = v;
551
+ if (value === undefined) {
552
+ continue;
553
+ }
554
+ where.push([k, value]);
555
+ }
556
+ return where;
557
+ }
558
+
559
+ /** @import { WhereValue } from '../../Where.mjs' */
560
+ /**
561
+ *
562
+ * @param {Record<string, string>[]} list
563
+ * @param {[string, string][]} map
564
+ * @returns {WhereValue}
565
+ */
566
+ function subList2where(list, map) {
567
+ const valueKeys = map.map(([, v]) => v);
568
+ return {
569
+ field: map.map(([k]) => k),
570
+ value: list.map(d => valueKeys.map(v => d[v]))
571
+ };
572
+ }
573
+
574
+ /** @import { WhereValue } from '../../Where.mjs' */
575
+ /**
576
+ *
577
+ * @param {[string, unknown][]} value
578
+ * @returns {WhereValue[]}
579
+ */
580
+ function valueEntries2where(value) {
581
+ return value.map(([k, v]) => ({
582
+ field: k,
583
+ operator: '=',
584
+ value: v
585
+ }));
586
+ }
587
+
588
+ /** @import { Environment, FieldDefine, Fields, FieldType, GetName, IConnection, MatchArg, Queryable, TableDefine } from '../types' */
589
+ /**
590
+ *
591
+ * @param {IConnection} conn
592
+ * @param {GetName} getName
593
+ * @param {any[]} list
594
+ * @param {[string, FieldDefine<TableDefine>][]} fields
595
+ * @param {Fields<keyof FieldType>} baseFields
596
+ * @param {Environment} env
597
+ * @param {boolean} [hasResult]
598
+ * @returns
599
+ */
600
+ async function deleteSub(conn, getName, list, fields, baseFields, env, hasResult) {
601
+ if (!list.length) {
602
+ return list;
603
+ }
604
+ /** @type {any[]} */
605
+ const promises = [];
606
+ for (const [key, {
607
+ type,
608
+ array,
609
+ constraints
610
+ }] of fields) {
611
+ const constraintEntries = Object.entries(constraints || {});
612
+ const {
613
+ fields
614
+ } = type;
615
+ const [subfields, tableFields] = separateFields(fields);
616
+ const mapList = getMapList(subfields, baseFields, constraints);
617
+ if (!mapList) {
618
+ continue;
619
+ }
620
+ const value = getValueEntries(constraints, subfields);
621
+ const where = [subList2where(list, mapList), ...valueEntries2where(value)];
622
+ const {
623
+ table
624
+ } = type;
625
+ /** @type {MatchArg} */
626
+ const argv = {
627
+ table: typeof table === 'string' ? getName(table) : '',
628
+ fields: subfields,
629
+ where
630
+ };
631
+ if (!tableFields.length && !hasResult) {
632
+ const result = table && typeof table === 'object' ? table.delete(env, conn, argv) : conn.delete(env, argv);
633
+ promises.push(result);
634
+ continue;
635
+ }
636
+ const result = table && typeof table === 'object' ? table.deleteReturn(env, conn, argv, Object.keys(subfields)) : conn.deleteReturn(env, argv, Object.keys(subfields));
637
+ promises.push(result.then(l => deleteSub(conn, getName, l, tableFields, subfields, env, hasResult)));
638
+ constraintEntries.find(([k, v]) => v.noField)?.[0];
639
+ promises.push(array ? result.then(subList => {
640
+ for (const item of list) {
641
+ // TODO: 排序
642
+ item[key] = subList.filter(createFilter(item, mapList));
643
+ }
644
+ }) : result.then(subList => {
645
+ for (const item of list) {
646
+ item[key] = subList.find(createFilter(item, mapList)) || null;
647
+ }
648
+ }));
649
+ }
650
+ await Promise.all(promises);
651
+ return list;
652
+ }
653
+ // TODO: 嵌套
654
+ /**
655
+ * @param {IConnection} conn
656
+ * @param {GetName} getName
657
+ * @param {Queryable} queryable
658
+ * @param {Environment} env
659
+ * @returns {Promise<number>}
660
+ */
661
+ async function deleteMany(conn, getName, queryable, env) {
662
+ const {
663
+ table,
664
+ fields
665
+ } = queryable;
666
+ const {
667
+ where
668
+ } = queryable.options;
669
+ const [baseFields, tableFields] = separateFields(fields);
670
+ if (!tableFields.length) {
671
+ return table && typeof table === 'object' ? table.delete(env, conn, {
672
+ table: '',
673
+ fields: baseFields,
674
+ where
675
+ }) : conn.delete(env, {
676
+ table: getName(table),
677
+ fields: baseFields,
678
+ where
679
+ });
680
+ }
681
+ const list = table && typeof table === 'object' ? await table.deleteReturn(env, conn, {
682
+ table: '',
683
+ fields: baseFields,
684
+ where
685
+ }, Object.keys(baseFields)) : await conn.deleteReturn(env, {
686
+ table: getName(table),
687
+ fields: baseFields,
688
+ where
689
+ }, Object.keys(baseFields));
690
+ if (!list) {
691
+ return 0;
692
+ }
693
+ await deleteSub(conn, getName, list, tableFields, baseFields, env);
694
+ return list.length;
695
+ }
696
+
697
+ /* eslint-disable no-labels */
698
+ /** @import { Constraint, Environment, FieldDefine, GetName, IConnection, TableDefine } from '../types' */
699
+ /** @import { WhereValue } from '../Where.mjs' */
700
+ /**
701
+ *
702
+ * @param {Record<string, any>[]} newList
703
+ * @param {Record<string, any>[]} oldList
704
+ * @param {Iterable<string>} keys
705
+ * @param {Record<string, any>[]} notFound
706
+ * @param {Record<string, any>[]} found
707
+ */
708
+ function classify(newList, oldList, keys, notFound, found) {
709
+ newValue: for (const n of newList) {
710
+ oldValue: for (let i = 0; i < oldList.length; i++) {
711
+ const old = oldList[i];
712
+ for (const k of keys) {
713
+ if (n[k] === undefined) {
714
+ continue;
715
+ }
716
+ if (old[k] !== n[k]) {
717
+ continue oldValue;
718
+ }
719
+ }
720
+ oldList.splice(i, 1);
721
+ found.push([n, old]);
722
+ continue newValue;
723
+ }
724
+ notFound.push(n);
725
+ }
726
+ }
727
+ /**
728
+ *
729
+ * @param {IConnection} conn
730
+ * @param {GetName} getName
731
+ * @param {Environment} env
732
+ * @param {[Record<string, any>, Record<string, any>, Record<string, any>][]} updatedOldNewList
733
+ * @param {string} key
734
+ * @param {TableDefine} type
735
+ * @param {boolean} array
736
+ * @param {Record<string, Constraint>?} [constraints]
737
+ * @returns
738
+ */
739
+ async function updateItem(conn, getName, env, updatedOldNewList, key, type, array, constraints) {
740
+ /** @type {any[]} */
741
+ const promises = [];
742
+ const constraintEntries = Object.entries(constraints || {});
743
+ const noField = constraintEntries.find(([k, v]) => v.noField)?.[0];
744
+ /** @type {Record<string, any>} */
745
+ const commonValue = {};
746
+ /** @type {[string, string][]} */
747
+ const commonMapKeys = [];
748
+ for (const [k, {
749
+ field,
750
+ value: val
751
+ }] of constraintEntries) {
752
+ if (field) {
753
+ commonMapKeys.push([k, field]);
754
+ } else if (val !== undefined) {
755
+ commonValue[k] = val;
756
+ }
757
+ }
758
+ /** @type {Record<string, any>[][]} */
759
+ const oldListValues = [];
760
+ /** @type {Record<string, any>[][]} */
761
+ const newListValues = [];
762
+ let has = false;
763
+ for (const [main, oldData, newData] of updatedOldNewList) {
764
+ const oldRecords = oldData?.[key];
765
+ const newRecords = newData?.[key];
766
+ // eslint-disable-next-line no-nested-ternary
767
+ const oldList = Array.isArray(oldRecords) ? array ? oldRecords : [oldRecords[0]] : [oldRecords];
768
+ if (newRecords || !array && newRecords === null) {
769
+ has = true;
770
+ }
771
+ // eslint-disable-next-line no-nested-ternary
772
+ const newList = Array.isArray(newRecords) ? array ? newRecords : [newRecords[0]] : [newRecords];
773
+ const oldValues = oldList.filter(v => v && typeof v === 'object');
774
+ const newValues = newList.filter(v => v && typeof v === 'object');
775
+ if (!oldValues.length && !newValues.values) {
776
+ continue;
777
+ }
778
+ const commonValues = {
779
+ ...Object.fromEntries(commonMapKeys.map(([k, v]) => [k, main[v]])),
780
+ ...commonValue
781
+ };
782
+ if (oldValues) {
783
+ const list = oldValues.map(value => ({
784
+ ...value,
785
+ ...commonValues
786
+ }));
787
+ oldListValues.push(noField ? list.map((v, i) => ({
788
+ ...v,
789
+ [noField]: i + 1
790
+ })) : list);
791
+ }
792
+ if (newValues) {
793
+ const list = newValues.map(value => ({
794
+ ...value,
795
+ ...commonValues
796
+ }));
797
+ newListValues.push(noField ? list.map((v, i) => ({
798
+ ...v,
799
+ [noField]: i + 1
800
+ })) : list);
801
+ }
802
+ }
803
+ if (!has) {
804
+ return;
805
+ }
806
+ const oldList = oldListValues.flat();
807
+ const newList = newListValues.flat();
808
+ const {
809
+ fields
810
+ } = type;
811
+ /** @type {Record<string, any>} */
812
+ const commonKeys = {};
813
+ for (const [k, v] of Object.entries(constraints || {})) {
814
+ const {
815
+ field,
816
+ value
817
+ } = v;
818
+ if (field || value !== undefined) {
819
+ commonKeys[k] = 1;
820
+ }
821
+ }
822
+ const [baseFields, tableFields] = separateFields(fields);
823
+ const primaryKeys = getPrimaryKeys(baseFields);
824
+ // 分离出新建、修改、删除
825
+ // TODO: 优化分离逻辑
826
+ const needDelete = oldList;
827
+ /** @type {[Record<string, any>, Record<string, any>][]} */
828
+ const eq = [];
829
+ /** @type {Record<string, any>[]} */
830
+ const needCreate = [];
831
+ /** @type {[Record<string, any>, Record<string, any>][]} */
832
+ const needUpdate = [];
833
+ /** @type {Record<string, any>[]} */
834
+ const unmatched = [];
835
+ const aKeys = Object.keys(baseFields).filter(v => !(v in commonKeys));
836
+ classify(newList, needDelete, aKeys, unmatched, eq);
837
+ const pKeys = primaryKeys.filter(v => !(v in commonKeys));
838
+ classify(unmatched, needDelete, pKeys, needCreate, needUpdate);
839
+ const tTable = type.table;
840
+ const table = tTable && typeof tTable === 'object' ? tTable : getName(tTable);
841
+ if (needDelete.length) {
842
+ // 批量删除
843
+ /** @type {WhereValue[]} */
844
+ const where = primaryKeys.filter(v => v in commonKeys).map(k => ({
845
+ field: k,
846
+ operator: '=',
847
+ value: commonKeys[k] ?? null
848
+ }));
849
+ if (pKeys.length === 1) {
850
+ const [key] = pKeys;
851
+ where.push({
852
+ field: key,
853
+ operator: 'in',
854
+ value: needDelete.map(v => v[key] ?? null)
855
+ });
856
+ } else if (pKeys.length) {
857
+ where.push({
858
+ field: pKeys,
859
+ operator: 'in',
860
+ value: needDelete.map(v => pKeys.map(k => v[k] ?? null))
861
+ });
862
+ }
863
+ const promise = typeof table === 'string' ? conn.deleteReturn(env, {
864
+ table,
865
+ fields: baseFields,
866
+ where
867
+ }, Object.keys(baseFields)) : table.deleteReturn(env, conn, {
868
+ table: '',
869
+ fields: baseFields,
870
+ where
871
+ }, Object.keys(baseFields));
872
+ promises.push(promise.then(list => deleteSub(conn, getName, list, tableFields, baseFields, env)));
873
+ }
874
+ /** @type {typeof updatedOldNewList} */
875
+ const list = eq.map(([n, o]) => [{
876
+ ...n
877
+ }, o, n]);
878
+ /** @type {any[]} */
879
+ const listPromises = [list.map(v => v[0])];
880
+ /** @type {(typeof updatedOldNewList | PromiseLike<typeof updatedOldNewList>)[]} */
881
+ const subPromises = [list];
882
+ // 批量修改
883
+ if (needUpdate.length) {
884
+ const keys = new Set(needUpdate.map(v => Object.keys(v[0])).flat());
885
+ const update = getSetNewValue(baseFields);
886
+ for (const k of Object.keys(update)) {
887
+ keys.delete(k);
888
+ }
889
+ const setKeys = Object.entries(baseFields).filter(([, v]) => typeof v.type === 'string' && !v.primary && !v.immutable).map(v => v[0]).filter(v => keys.has(v));
890
+ /** @type {WhereValue[]} */
891
+ const where = Object.entries(commonKeys).filter(([k]) => primaryKeys.includes(k)).map(([k, v]) => ({
892
+ field: k,
893
+ operator: '=',
894
+ value: v
895
+ }));
896
+ for (const [value, old] of needUpdate) {
897
+ for (const key of setKeys) {
898
+ if (value[key] !== undefined) {
899
+ continue;
900
+ }
901
+ value[key] = old[key];
902
+ }
903
+ }
904
+ const list = typeof table === 'string' ? conn.updateManyReturn(env, table, baseFields, update, pKeys, setKeys, needUpdate.map(v => v[0]), where, Object.keys(baseFields)) : table.updateManyReturn(env, conn, '', baseFields, update, pKeys, setKeys, needUpdate.map(v => v[0]), where, Object.keys(baseFields));
905
+ listPromises.push(list);
906
+ subPromises.push(list.then(u => u.map((u, i) => [u, ...needUpdate[i]])));
907
+ }
908
+ // 批量新建
909
+ if (needCreate.length) {
910
+ const key = Object.entries(baseFields);
911
+ const list = typeof table === 'string' ? conn.insert(env, table, baseFields, needCreate.map(d => getInsertValue(d, baseFields)), key.filter(([, o]) => !o.serial || o.type !== 'id').map(v => v[0])) : table.insert(env, conn, '', baseFields, needCreate.map(d => getInsertValue(d, baseFields)), key.filter(([, o]) => !o.serial || o.type !== 'id').map(v => v[0]));
912
+ listPromises.push(list);
913
+ promises.push(list.then(list => createSub(conn, getName, env, tableFields, needCreate, list)));
914
+ }
915
+ promises.push(Promise.all(subPromises).then(
916
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
917
+ v => updateSub(conn, getName, tableFields, v.flat(), env)));
918
+ const allList = Promise.all(listPromises).then(v => v.flat());
919
+ promises.push(array ? allList.then(async values => {
920
+ for (const [value] of updatedOldNewList) {
921
+ let data = values.filter(createFilter(value, commonMapKeys));
922
+ if (noField) {
923
+ data = data.sort(({
924
+ [noField]: a
925
+ }, {
926
+ [noField]: b
927
+ }) => a - b);
928
+ }
929
+ value[key] = data;
930
+ }
931
+ }) : allList.then(async values => {
932
+ for (const [value] of updatedOldNewList) {
933
+ value[key] = values.find(createFilter(value, commonMapKeys)) || null;
934
+ }
935
+ }));
936
+ await Promise.all(promises);
937
+ }
938
+ /**
939
+ *
940
+ * @param {IConnection} conn
941
+ * @param {GetName} getName
942
+ * @param {[string, FieldDefine<TableDefine>][]} fields
943
+ * @param {[Record<string, any>, Record<string, any>, Record<string, any>][]} list
944
+ * @param {Environment} env
945
+ * @returns
946
+ */
947
+ async function updateSub(conn, getName, fields, list, env) {
948
+ if (!list.length) {
949
+ return;
950
+ }
951
+ /** @type {any[]} */
952
+ const promises = [];
953
+ for (const [key, {
954
+ type,
955
+ array,
956
+ immutable,
957
+ constraints
958
+ }] of fields) {
959
+ if (immutable) {
960
+ continue;
961
+ }
962
+ promises.push(updateItem(conn, getName, env, list, key, type, array, constraints));
963
+ }
964
+ await Promise.all(promises);
965
+ }
966
+ /**
967
+ *
968
+ * @param {IConnection} conn
969
+ * @param {GetName} getName
970
+ * @param {TableDefine} model
971
+ * @param {Record<string, any>} data
972
+ * @param {Record<string, any>} newData
973
+ * @param {Environment} env
974
+ * @returns
975
+ */
976
+ async function updateData (conn, getName, model, data, newData, env) {
977
+ const keys = Object.keys(newData);
978
+ if (!keys.length) {
979
+ return false;
980
+ }
981
+ const {
982
+ table,
983
+ fields
984
+ } = model;
985
+ const savedData = data;
986
+ const has = keys.filter(v => v in fields && (typeof fields[v]?.type === 'string' || !fields[v]?.type.table)).length;
987
+ /** @type {WhereValue[]} */
988
+ const where = getPrimaryKeys(fields).map(k => ({
989
+ field: k,
990
+ operator: '=',
991
+ value: savedData[k]
992
+ }));
993
+ const [baseFields, tableFields] = separateFields(fields);
994
+ let list = [];
995
+ if (!has) {
996
+ list = [data];
997
+ } else if (table && typeof table === 'object') {
998
+ list = await table.updateReturn(env, conn, {
999
+ table: '',
1000
+ fields: baseFields,
1001
+ where
1002
+ }, getSetNewValue(fields, newData), Object.keys(baseFields));
1003
+ } else {
1004
+ list = await conn.updateReturn(env, {
1005
+ table: getName(table),
1006
+ fields: baseFields,
1007
+ where
1008
+ }, getSetNewValue(fields, newData), Object.keys(baseFields));
1009
+ }
1010
+ const oldList = [data];
1011
+ const newList = [newData];
1012
+ /** @type {[Record<string, any>, Record<string, any>, Record<string, any>][]} */
1013
+ const updatedOldNewList = list.map((v, k) => [v, oldList[k], newList[k]]);
1014
+ await updateSub(conn, getName, tableFields, updatedOldNewList, env);
1015
+ return list[0];
1016
+ }
1017
+
1018
+ /** @import { SetValue } from '../../set.mjs' */
1019
+ /** @import { Fields } from '../../types' */
1020
+ /**
1021
+ *
1022
+ * @param {Fields} fields
1023
+ * @param {Record<string, SetValue>} update
1024
+ * @returns
1025
+ */
1026
+ function setDeleteTimestamp(fields, update) {
1027
+ for (const [name, field] of Object.entries(fields)) {
1028
+ if (!field.primary && field.timestampDeleting) {
1029
+ update[name] = now;
1030
+ }
1031
+ }
1032
+ return update;
1033
+ }
1034
+
1035
+ /** @import { WhereValue } from '../Where.mjs' */
1036
+ /** @import { SetValue } from '../set.mjs' */
1037
+ /** @import { Environment, IConnection, GetName, TableDefine } from '../types' */
1038
+ /**
1039
+ *
1040
+ * @param {IConnection} conn
1041
+ * @param {GetName} getName
1042
+ * @param {TableDefine} tableDef
1043
+ * @param {any} data
1044
+ * @param {Record<string, SetValue>} update
1045
+ * @param {Environment} env
1046
+ * @returns
1047
+ */
1048
+ async function pseudoDestroy (conn, getName, tableDef, data, update, env) {
1049
+ const {
1050
+ table,
1051
+ fields
1052
+ } = tableDef;
1053
+ const baseFields = toBaseFields(fields);
1054
+ /** @type {WhereValue[]} */
1055
+ const where = getPrimaryKeys(fields).map(k => ({
1056
+ field: k,
1057
+ operator: '=',
1058
+ value: data[k]
1059
+ }));
1060
+ const pseudo = tableDef.pseudo || '';
1061
+ where.push({
1062
+ field: pseudo,
1063
+ operator: '=',
1064
+ value: 0
1065
+ });
1066
+ const value = {
1067
+ ...update
1068
+ };
1069
+ const pseudoValue = Number(new Date());
1070
+ value[pseudo] = pseudoValue;
1071
+ setDeleteTimestamp(fields, value);
1072
+ const [dataUpdated] = table && typeof table === 'object' ? await table.updateReturn(env, conn, {
1073
+ table: '',
1074
+ fields: baseFields,
1075
+ where
1076
+ }, value, Object.keys(baseFields)) : await conn.updateReturn(env, {
1077
+ table: getName(table),
1078
+ fields: baseFields,
1079
+ where
1080
+ }, value, Object.keys(baseFields));
1081
+ if (!dataUpdated) {
1082
+ return null;
1083
+ }
1084
+ return dataUpdated;
1085
+ }
1086
+
1087
+ /** @import { WhereValue } from '../Where.mjs' */
1088
+ /** @import { IConnection, TableDefine, Environment, GetName } from '../types' */
1089
+ /**
1090
+ *
1091
+ * @param {IConnection} conn
1092
+ * @param {GetName} getName
1093
+ * @param {TableDefine} tableDef
1094
+ * @param {any} data
1095
+ * @param {Environment} env
1096
+ * @returns
1097
+ */
1098
+ async function completelyDelete (conn, getName, tableDef, data, env) {
1099
+ const {
1100
+ table,
1101
+ fields
1102
+ } = tableDef;
1103
+ const [baseFields, tableFields] = separateFields(fields);
1104
+ /** @type {WhereValue[]} */
1105
+ const where = getPrimaryKeys(fields).map(k => ({
1106
+ field: k,
1107
+ operator: '=',
1108
+ value: data[k]
1109
+ }));
1110
+ const list = table && typeof table === 'object' ? await table.deleteReturn(env, conn, {
1111
+ table: '',
1112
+ fields: baseFields,
1113
+ where
1114
+ }, Object.keys(baseFields)) : await conn.deleteReturn(env, {
1115
+ table: getName(table),
1116
+ fields: baseFields,
1117
+ where
1118
+ }, Object.keys(baseFields));
1119
+ const [deleted] = await deleteSub(conn, getName, list, tableFields, baseFields, env, true);
1120
+ return deleted || null;
1121
+ }
1122
+
1123
+ const Destroy = Symbol();
1124
+ const PseudoDestroy = Symbol();
1125
+ const Save = Symbol();
1126
+ const Create = Symbol();
1127
+ const Build = Symbol();
1128
+
1129
+ /** @import { Fields, FieldType, Select } from '../types' */
1130
+ /**
1131
+ * @param {Fields<keyof FieldType>} fields
1132
+ * @param {Record<string, Select>?} [select]
1133
+ * @returns {[string, Select][]}
1134
+ */
1135
+ function toSelect(fields, select) {
1136
+ const list = select ? Object.entries(select) : [];
1137
+ return list.length ? list : Object.keys(fields).map(k => [k, {
1138
+ field: k
1139
+ }]);
1140
+ }
1141
+
1142
+ /** @import { Fields, FieldType } from '../../types' */
1143
+ /**
1144
+ *
1145
+ * @param {Fields<keyof FieldType>} fields
1146
+ * @param {string} [noField]
1147
+ * @returns {[string, boolean][]}
1148
+ */
1149
+ function getDefaultSort(fields, noField) {
1150
+ /** @type {[string, boolean, number][]} */
1151
+ const sorted = Object.entries(fields).map(([f, d]) => [f, (d.sort || 0) < 0, Math.abs(d.sort || 0)]);
1152
+ /** @type {[string, boolean][]} */
1153
+ const sort = sorted.filter(v => v[2]).sort(([,, a], [,, b]) => a - b).map(([a, b]) => [a, b]);
1154
+ if (noField) {
1155
+ sort.unshift([noField, false]);
1156
+ }
1157
+ return sort;
1158
+ }
1159
+
1160
+ /** @import { Environment, FieldDefine, Fields, FieldType, GetName, IConnection, TableDefine } from '../types' */
1161
+ /**
1162
+ *
1163
+ * @param {IConnection} conn
1164
+ * @param {GetName} getName
1165
+ * @param {any[]} list
1166
+ * @param {[string, FieldDefine<TableDefine>][]} fields
1167
+ * @param {Fields<keyof FieldType>} baseFields
1168
+ * @param {Environment} env
1169
+ * @returns {Promise<any[]>}
1170
+ */
1171
+ async function findSub(conn, getName, list, fields, baseFields, env) {
1172
+ if (!list.length) {
1173
+ return list;
1174
+ }
1175
+ /** @type {PromiseLike<any>[]} */
1176
+ const promises = [];
1177
+ for (const [key, {
1178
+ type,
1179
+ array,
1180
+ constraints
1181
+ }] of fields) {
1182
+ const constraintEntries = Object.entries(constraints || {});
1183
+ const noField = constraintEntries.find(([k, v]) => v.noField)?.[0];
1184
+ const {
1185
+ fields
1186
+ } = type;
1187
+ const [subfields, tableFields] = separateFields(fields);
1188
+ const mapList = getMapList(subfields, baseFields, constraints);
1189
+ if (!mapList) {
1190
+ continue;
1191
+ }
1192
+ const value = getValueEntries(constraints, subfields);
1193
+ const where = [subList2where(list, mapList), ...valueEntries2where(value)];
1194
+ const {
1195
+ table
1196
+ } = type;
1197
+ /** @type {PromiseLike<object[] | object>} */
1198
+ const result = table && typeof table === 'object' ? table.select(env, conn, {
1199
+ table: '',
1200
+ fields: subfields,
1201
+ where,
1202
+ sort: getDefaultSort(subfields, noField),
1203
+ select: toSelect(subfields)
1204
+ }) : conn.select(env, {
1205
+ table: getName(table),
1206
+ fields: subfields,
1207
+ where,
1208
+ sort: getDefaultSort(subfields, noField),
1209
+ select: toSelect(subfields)
1210
+ });
1211
+ promises.push(result.then(list => findSub(conn, getName, list, tableFields, subfields, env)));
1212
+ promises.push(array ? result.then(subList => {
1213
+ for (const item of list) {
1214
+ item[key] = subList.filter(createFilter(item, mapList));
1215
+ }
1216
+ }) : result.then(subList => {
1217
+ for (const item of list) {
1218
+ item[key] = subList.find(createFilter(item, mapList)) || null;
1219
+ }
1220
+ }));
1221
+ }
1222
+ return Promise.all(promises).then(() => list);
1223
+ }
1224
+ /**
1225
+ *
1226
+ * @template {TableDefine} T
1227
+ * @param {IConnection} conn
1228
+ * @param {GetName} getName
1229
+ * @param {T} p
1230
+ * @param {Environment} env
1231
+ * @returns {Promise<any>}
1232
+ */
1233
+ async function find(conn, getName, p, env) {
1234
+ const {
1235
+ table,
1236
+ fields
1237
+ } = p;
1238
+ // @ts-ignore
1239
+ const {
1240
+ where,
1241
+ sort,
1242
+ offset,
1243
+ limit,
1244
+ alias
1245
+ } = getOptions(p);
1246
+ const [baseFields, tableFields] = separateFields(fields);
1247
+ const list = table && typeof table === 'object' ? await table.select(env, conn, {
1248
+ table: '',
1249
+ fields: baseFields,
1250
+ alias,
1251
+ where,
1252
+ offset,
1253
+ limit,
1254
+ sort: sort?.length ? sort : getDefaultSort(baseFields),
1255
+ select: toSelect(baseFields)
1256
+ }) : await conn.select(env, {
1257
+ table: getName(table),
1258
+ fields: baseFields,
1259
+ alias,
1260
+ where,
1261
+ offset,
1262
+ limit,
1263
+ sort: sort?.length ? sort : getDefaultSort(baseFields),
1264
+ select: toSelect(baseFields)
1265
+ });
1266
+ if (!list.length) {
1267
+ return [];
1268
+ }
1269
+ await findSub(conn, getName, list, tableFields, baseFields, env);
1270
+ if (typeof p[Build] !== 'function') {
1271
+ return list;
1272
+ }
1273
+ /** @type {(data: any, saved: boolean, env: any) => any} */
1274
+ const R = p[Build].bind(p);
1275
+ return list.map(it => R(it, true, env));
1276
+ }
1277
+
1278
+ /** @import { Environment, TableDefine, IConnection, GetName } from '../types' */
1279
+ /**
1280
+ *
1281
+ * @template {TableDefine} T
1282
+ * @param {IConnection} conn
1283
+ * @param {GetName} getName
1284
+ * @param {T} p
1285
+ * @param {Environment} env
1286
+ * @returns {Promise<any>}
1287
+ */
1288
+ async function first(conn, getName, p, env) {
1289
+ const {
1290
+ table,
1291
+ fields
1292
+ } = p;
1293
+ // @ts-ignore
1294
+ const {
1295
+ where,
1296
+ sort,
1297
+ alias
1298
+ } = getOptions(p);
1299
+ const [baseFields, tableFields] = separateFields(fields);
1300
+ const list = table && typeof table === 'object' ? await table.select(env, conn, {
1301
+ table: '',
1302
+ fields: baseFields,
1303
+ alias,
1304
+ where,
1305
+ limit: 1,
1306
+ sort: sort?.length ? sort : getDefaultSort(baseFields),
1307
+ select: toSelect(baseFields)
1308
+ }) : await conn.select(env, {
1309
+ table: getName(table),
1310
+ fields: baseFields,
1311
+ alias,
1312
+ where,
1313
+ limit: 1,
1314
+ sort: sort?.length ? sort : getDefaultSort(baseFields),
1315
+ select: toSelect(baseFields)
1316
+ });
1317
+ const [item] = await findSub(conn, getName, list, tableFields, baseFields, env);
1318
+ if (!item) {
1319
+ return null;
1320
+ }
1321
+ if (typeof p[Build] !== 'function') {
1322
+ return item;
1323
+ }
1324
+ return p[Build](item, true, env);
1325
+ }
1326
+
1327
+ /** @import { Environment, GetName, IConnection, Queryable } from '../types' */
1328
+ /**
1329
+ * @param {IConnection} conn
1330
+ * @param {GetName} getName
1331
+ * @param {Queryable} queryable
1332
+ * @param {Record<string, any> | boolean | undefined} update
1333
+ * @param {Environment} env
1334
+ */
1335
+ async function pseudoDeleteMany(conn, getName, queryable, update, env) {
1336
+ const {
1337
+ table,
1338
+ fields
1339
+ } = queryable;
1340
+ const {
1341
+ where
1342
+ } = getOptions(queryable);
1343
+ const value = typeof update !== 'object' ? {} : {
1344
+ ...update
1345
+ };
1346
+ const pseudoValue = Number(new Date());
1347
+ const pseudo = queryable.pseudo || '';
1348
+ value[pseudo] = pseudoValue;
1349
+ setDeleteTimestamp(fields, value);
1350
+ const baseFields = toBaseFields(fields);
1351
+ const list = table && typeof table === 'object' ? await table.updateReturn(env, conn, {
1352
+ table: '',
1353
+ fields: baseFields,
1354
+ where
1355
+ }, value, Object.keys(baseFields)) : await conn.updateReturn(env, {
1356
+ table: getName(table),
1357
+ fields: baseFields,
1358
+ where
1359
+ }, value, Object.keys(baseFields));
1360
+ return list.length;
1361
+ }
1362
+
1363
+ /* eslint-disable max-lines */
1364
+ /* eslint-disable max-len */
1365
+ /** @import { WhereValue } from '../Where.mjs' */
1366
+ /** @import { SetValue } from '../set.mjs' */
1367
+ /** @import { Environment, IConnection } from '../types' */
1368
+ /** @import { Fields, FieldType, FieldValue, IndexOptions, MainFieldType, TableDefine } from '../types/table' */
1369
+ /** @import { Queryable } from '../types/options' */
1370
+ /** @import { Column, ColumnOptions } from '../types/column' */
1371
+ /** @import { GetName, TableType } from '../types/connection' */
1372
+ /**
1373
+ *
1374
+ * @param {Record<string, any> | null | undefined} update
1375
+ * @param {Fields} fields
1376
+ * @param {boolean} [skip]
1377
+ * @returns {Record<string, SetValue>}
1378
+ */
1379
+ function getSetValue$1(update, fields, skip) {
1380
+ /** @type {Record<string, SetValue>} */
1381
+ const data = {
1382
+ ...update
1383
+ };
1384
+ for (const [name, field] of Object.entries(fields)) {
1385
+ if (!field.primary && field.timestampUpdating) {
1386
+ data[name] = now;
1387
+ }
1388
+ }
1389
+ return Object.fromEntries(Object.entries(data).filter(([k, v]) => {
1390
+ const field = k in fields && fields[k];
1391
+ if (!field) {
1392
+ return;
1393
+ }
1394
+ if (!skip && field.immutable || field.serial && field.type === 'id') {
1395
+ return;
1396
+ }
1397
+ return true;
1398
+ }));
1399
+ }
1400
+ /**
1401
+ *
1402
+ * @param {Fields<keyof FieldType>} fields
1403
+ * @param {Record<string, any>} update
1404
+ * @param {string[]} pKeys
1405
+ * @param {string[]} setKeys
1406
+ * @returns {[string[], string[]]}
1407
+ */
1408
+ function getKeys(fields, update, pKeys, setKeys) {
1409
+ const allFields = Object.keys(fields);
1410
+ const mainKeys = new Set(pKeys);
1411
+ const whereFields = allFields.filter(f => mainKeys.has(f));
1412
+ const updateFields = Object.keys(update);
1413
+ const noSetFields = new Set([...whereFields, ...updateFields]);
1414
+ const setKeySet = new Set(setKeys);
1415
+ const setFields = allFields.filter(f => setKeySet.has(f) && !noSetFields.has(f));
1416
+ return [whereFields, setFields];
1417
+ }
1418
+ /**
1419
+ *
1420
+ * @param {AbortSignal} signal
1421
+ * @returns
1422
+ */
1423
+ function signal2promise(signal) {
1424
+ return new Promise((_, r) => {
1425
+ if (signal.aborted) {
1426
+ r(signal.reason);
1427
+ return;
1428
+ }
1429
+ signal.addEventListener('abort', () => r(signal.reason), {
1430
+ once: true
1431
+ });
1432
+ });
1433
+ }
1434
+ /** @type {GetName} */
1435
+ const defGetName = s => s || '';
1436
+ /**
1437
+ * @template {{}} [E={}]
1438
+ */
1439
+ class Connection {
1440
+ /** @type {Environment<E>} */
1441
+ #env;
1442
+ /** @type {() => Promise<IConnection<E>>} */
1443
+ #getConnection;
1444
+ /** @type {E?} */
1445
+ #baseTransaction;
1446
+ /** @type {Record<string, string>?} */
1447
+ #names;
1448
+ #getName = defGetName;
1449
+ /**
1450
+ *
1451
+ * @param {PromiseLike<IConnection<E>> | IConnection<E>} connection
1452
+ * @param {E?} [transaction]
1453
+ * @param {Record<string, string>?} [names]
1454
+ */
1455
+ constructor(connection, transaction = null, names = null) {
1456
+ this.#baseTransaction = transaction;
1457
+ this.#getConnection = async () => connection;
1458
+ let getName = defGetName;
1459
+ if (names) {
1460
+ this.#names = names;
1461
+ const allNames = Object.assign(Object.create(null), names);
1462
+ getName = n => allNames[n || ''] || n;
1463
+ } else {
1464
+ this.#names = null;
1465
+ }
1466
+ this.#getName = getName;
1467
+ this.#env = {
1468
+ isDevelopment,
1469
+ values,
1470
+ transaction,
1471
+ getName,
1472
+ names: names && {
1473
+ ...names
1474
+ }
1475
+ };
1476
+ }
1477
+ /**
1478
+ *
1479
+ * @param {object} [options]
1480
+ * @param {Record<string, string>?} [options.names]
1481
+ * @returns {Connection<E>}
1482
+ */
1483
+ clone({
1484
+ names
1485
+ } = {}) {
1486
+ // eslint-disable-next-line no-nested-ternary
1487
+ const newNames = this.#names ? names ? {
1488
+ ...this.#names,
1489
+ ...names
1490
+ } : this.#names : names;
1491
+ return new Connection(this.#getConnection(), this.#baseTransaction, newNames);
1492
+ }
1493
+ /** @return {Promise<string>} */
1494
+ async dbType() {
1495
+ const conn = await this.#getConnection();
1496
+ return conn.dbType;
1497
+ }
1498
+ /** @return {Promise<string>} */
1499
+ async dbVersion() {
1500
+ const conn = await this.#getConnection();
1501
+ return conn.dbVersion(this.#env);
1502
+ }
1503
+ /**
1504
+ *
1505
+ * @param {...any} values
1506
+ * @returns {Promise<any[]>}
1507
+ */
1508
+ async query(...values) {
1509
+ const conn = await this.#getConnection();
1510
+ return conn.query(this.#env, ...values);
1511
+ }
1512
+ /**
1513
+ *
1514
+ * @param {...any} values
1515
+ * @returns {Promise<number>}
1516
+ */
1517
+ async exec(...values) {
1518
+ const conn = await this.#getConnection();
1519
+ return conn.exec(this.#env, ...values);
1520
+ }
1521
+ /**
1522
+ *
1523
+ * @param {string} table
1524
+ * @returns {Promise<TableType?>}
1525
+ */
1526
+ async type(table) {
1527
+ const conn = await this.#getConnection();
1528
+ return conn.type(this.#env, this.#getName(table));
1529
+ }
1530
+ /**
1531
+ * @template T
1532
+ * @overload
1533
+ * @param {Build<T>} build
1534
+ * @param {object} data
1535
+ * @param {object | boolean} [saved]
1536
+ * @returns {T}
1537
+ */
1538
+ /**
1539
+ * @template {Fields} T
1540
+ * @overload
1541
+ * @param {TableDefine<T>} table
1542
+ * @param {object} data
1543
+ * @param {object | boolean} [saved]
1544
+ * @returns {FieldValue<T>}
1545
+ */
1546
+ /**
1547
+ * @param {Build | TableDefine} p
1548
+ * @param {object} data
1549
+ * @param {object | boolean} [saved]
1550
+ * @returns {any}
1551
+ */
1552
+ build(p, data, saved) {
1553
+ if (typeof p[Build] === 'function') {
1554
+ return p[Build](data, saved || false, this.#env);
1555
+ }
1556
+ if (typeof saved === 'boolean') {
1557
+ return {
1558
+ ...data
1559
+ };
1560
+ }
1561
+ return {
1562
+ ...data,
1563
+ ...saved
1564
+ };
1565
+ }
1566
+ /**
1567
+ * @template {TableDefine} T
1568
+ * @overload
1569
+ * @param {T} model
1570
+ * @param {object[]} list
1571
+ * @returns {Promise<object[]>}
1572
+ */
1573
+ /**
1574
+ * @template {TableDefine} T
1575
+ * @overload
1576
+ * @param {T} model
1577
+ * @param {object} value
1578
+ * @returns {Promise<T extends Build<infer R> ? R : object>}
1579
+ */
1580
+ /**
1581
+ * @template {TableDefine} T
1582
+ * @overload
1583
+ * @param {T} model
1584
+ * @param {object | object[]} value
1585
+ * @returns {Promise<object[] | (T extends Build<infer R> ? R : object)>}
1586
+ */
1587
+ /**
1588
+ * @template {TableDefine} T
1589
+ * @param {T} model
1590
+ * @param {object | object[]} p
1591
+ * @returns {Promise<object[] | (T extends Build<infer R> ? R : object)>}
1592
+ */
1593
+ async create(model, p) {
1594
+ if (Array.isArray(p) || typeof model[Create] !== 'function') {
1595
+ const modelBuild = model[Build];
1596
+ const md = typeof modelBuild === 'function' ? modelBuild.bind(model) : undefined;
1597
+ const conn = await this.#getConnection();
1598
+ return create(conn, this.#getName, this.#env, model, p, md);
1599
+ }
1600
+ // @ts-ignore
1601
+ const m = /** @type {Create} */model;
1602
+ return m[Create](this, p, async data => {
1603
+ const conn = await this.#getConnection();
1604
+ return create(conn, this.#getName, this.#env, model, data);
1605
+ }, model);
1606
+ }
1607
+ /**
1608
+ *
1609
+ * @template {TableDefine} T
1610
+ * @param {T} sql
1611
+ * @returns {Promise<T extends Build<infer R > ? R[] : T extends TableDefine<infer F> ? FieldValue<F>[] : never>}
1612
+ */
1613
+ async find(sql) {
1614
+ const conn = await this.#getConnection();
1615
+ return find(conn, this.#getName, sql, this.#env);
1616
+ }
1617
+ /**
1618
+ *
1619
+ * @template {TableDefine} T
1620
+ * @param {T} sql
1621
+ * @returns {Promise<T extends Build<infer R > ? R : T extends TableDefine<infer F> ? FieldValue<F> : never>}
1622
+ */
1623
+ async first(sql) {
1624
+ const conn = await this.#getConnection();
1625
+ return first(conn, this.#getName, sql, this.#env);
1626
+ }
1627
+ /**
1628
+ * @template T
1629
+ * @param {TableDefine} model
1630
+ * @param {T} data
1631
+ * @returns {Promise<(T extends Save ? T : object)?>}
1632
+ */
1633
+ async save(model, data) {
1634
+ if (typeof data[Save] !== 'function') {
1635
+ const conn = await this.#getConnection();
1636
+ return create(conn, this.#getName, this.#env, model, data);
1637
+ }
1638
+ const r = /** @type {Save}*/data;
1639
+ // @ts-ignore
1640
+ return r[Save](this, async (doc, newData) => {
1641
+ const conn = await this.#getConnection();
1642
+ if (newData) {
1643
+ return updateData(conn, this.#getName, model, doc, newData, this.#env);
1644
+ }
1645
+ return create(conn, this.#getName, this.#env, model, doc);
1646
+ }, model);
1647
+ }
1648
+ /**
1649
+ *
1650
+ * @template T
1651
+ * @param {TableDefine} tableDef
1652
+ * @param {T} data
1653
+ * @returns {Promise<(T extends Destroy ? T : object)?>}
1654
+ */
1655
+ async completelyDestroy(tableDef, data) {
1656
+ if (typeof data[Destroy] !== 'function') {
1657
+ const conn = await this.#getConnection();
1658
+ return completelyDelete(conn, this.#getName, tableDef, data, this.#env);
1659
+ }
1660
+ const r = /** @type {Destroy} */data;
1661
+ // @ts-ignore
1662
+ return r[Destroy](this, async data => {
1663
+ const conn = await this.#getConnection();
1664
+ return completelyDelete(conn, this.#getName, tableDef, data, this.#env);
1665
+ }, tableDef);
1666
+ }
1667
+ /**
1668
+ *
1669
+ * @template {object} T
1670
+ * @param {TableDefine} tableDef
1671
+ * @param {T} data
1672
+ * @param {Record<string, SetValue>} value
1673
+ * @returns {Promise<(T extends PseudoDestroy ? T : object)?>}
1674
+ */
1675
+ async pseudoDestroy(tableDef, data, value) {
1676
+ if (!canPseudo(tableDef)) {
1677
+ return null;
1678
+ }
1679
+ const update = {
1680
+ ...value
1681
+ };
1682
+ if (typeof data[PseudoDestroy] !== 'function') {
1683
+ const conn = await this.#getConnection();
1684
+ return pseudoDestroy(conn, this.#getName, tableDef, data, update, this.#env);
1685
+ }
1686
+ const r = /** @type {PseudoDestroy} */data;
1687
+ // @ts-ignore
1688
+ return r[PseudoDestroy](this, update, async data => {
1689
+ const conn = await this.#getConnection();
1690
+ return pseudoDestroy(conn, this.#getName, tableDef, data, update, this.#env);
1691
+ }, tableDef);
1692
+ }
1693
+ /**
1694
+ * @template {Destroy & PseudoDestroy} T
1695
+ * @overload
1696
+ * @param {TableDefine} table
1697
+ * @param {T} data
1698
+ * @param {Record<string, any> | boolean} [update]
1699
+ * @returns {Promise<T?>}
1700
+ */
1701
+ /**
1702
+ * @template {Destroy & PseudoDestroy} T
1703
+ * @overload
1704
+ * @param {TableDefine} table
1705
+ * @param {T} data
1706
+ * @param {Record<string, any> | boolean} [update]
1707
+ * @returns {Promise<T | object | null>}
1708
+ */
1709
+ /**
1710
+ * @overload
1711
+ * @param {TableDefine} table
1712
+ * @param {any} data
1713
+ * @param {Record<string, any> | boolean} [update]
1714
+ * @returns {Promise<object?>}
1715
+ */
1716
+ /**
1717
+ * @param {TableDefine} tableDef
1718
+ * @param {any} data
1719
+ * @param {Record<string, any> | boolean} [update]
1720
+ * @returns {Promise<object?>}
1721
+ */
1722
+ async destroy(tableDef, data, update) {
1723
+ if (update === false || !canPseudo(tableDef)) {
1724
+ return this.completelyDestroy(tableDef, data);
1725
+ }
1726
+ if (!canPseudo(tableDef)) {
1727
+ return null;
1728
+ }
1729
+ return this.pseudoDestroy(tableDef, data, update !== true && update || {});
1730
+ }
1731
+ /**
1732
+ * @param {Queryable} queryable
1733
+ * @param {Record<string, SetValue> | boolean} [update]
1734
+ * @returns {Promise<number>}
1735
+ */
1736
+ async destroyMany(queryable, update) {
1737
+ const conn = await this.#getConnection();
1738
+ if (update === false || !isPseudo(queryable)) {
1739
+ return deleteMany(conn, this.#getName, queryable, this.#env);
1740
+ }
1741
+ return pseudoDeleteMany(conn, this.#getName, queryable, update, this.#env);
1742
+ }
1743
+ /**
1744
+ * @template {object | object[]} T
1745
+ * @param {TableDefine} tableDefine
1746
+ * @param {T} data
1747
+ * @param {string[]} [keys]
1748
+ * @returns {Promise<T extends object[] ? object[] : object>}
1749
+ */
1750
+ async insert({
1751
+ table,
1752
+ fields
1753
+ }, data, keys) {
1754
+ const baseFields = toBaseFields(fields);
1755
+ const isArray = Array.isArray(data);
1756
+ const insertValues = (isArray ? data : [data]).map(d => getInsertValue(d, fields));
1757
+ if (!insertValues.length) {
1758
+ throw new Error();
1759
+ }
1760
+ let insertKeys = [...new Set(keys || [])].filter(k => k in baseFields);
1761
+ if (!insertKeys.length && !isArray) {
1762
+ insertKeys = Object.entries(insertValues[0]).filter(([k, v]) => v !== undefined && k in baseFields).map(([k]) => k);
1763
+ }
1764
+ if (!insertKeys.length) {
1765
+ insertKeys = Object.entries(baseFields).filter(([, o]) => !o.serial || o.type !== 'id').map(v => v[0]);
1766
+ }
1767
+ const conn = await this.#getConnection();
1768
+ const p = table && typeof table === 'object' ? await table.insert(this.#env, conn, '', baseFields, insertValues, insertKeys) : await conn.insert(this.#env, this.#getName(table), baseFields, insertValues, insertKeys);
1769
+ return isArray ? (/** @type {*}*/p) : p[0];
1770
+ }
1771
+ /**
1772
+ * @param {TableDefine} tableDefine
1773
+ * @param {Record<string, any>} update
1774
+ * @param {WhereValue[]?} [where]
1775
+ * @param {boolean} [skip]
1776
+ * @returns {Promise<number>}
1777
+ */
1778
+ async update({
1779
+ table,
1780
+ fields
1781
+ }, update, where, skip) {
1782
+ const conn = await this.#getConnection();
1783
+ return table && typeof table === 'object' ? table.update(this.#env, conn, {
1784
+ table: '',
1785
+ fields: toBaseFields(fields),
1786
+ where: where || undefined
1787
+ }, getSetValue$1(update, fields, skip)) : conn.update(this.#env, {
1788
+ table: this.#getName(table),
1789
+ fields: toBaseFields(fields),
1790
+ where: where || undefined
1791
+ }, getSetValue$1(update, fields, skip));
1792
+ }
1793
+ /**
1794
+ * @template {Fields<MainFieldType>} T
1795
+ * @param {TableDefine<T>} tableDefine
1796
+ * @param {Record<string, any>} update
1797
+ * @param {string[]?} [returning]
1798
+ * @param {WhereValue[]?} [where]
1799
+ * @param {boolean} [skip]
1800
+ * @returns {Promise<any[]>}
1801
+ */
1802
+ async updateReturn({
1803
+ table,
1804
+ fields
1805
+ }, update, returning, where, skip) {
1806
+ const conn = await this.#getConnection();
1807
+ const baseFields = toBaseFields(fields);
1808
+ return table && typeof table === 'object' ? table.updateReturn(this.#env, conn, {
1809
+ table: '',
1810
+ fields: baseFields,
1811
+ where: where || undefined
1812
+ }, getSetValue$1(update, fields, skip), returning?.length ? returning : Object.keys(baseFields)) : conn.updateReturn(this.#env, {
1813
+ table: this.#getName(table),
1814
+ fields: baseFields,
1815
+ where: where || undefined
1816
+ }, getSetValue$1(update, fields, skip), returning?.length ? returning : Object.keys(baseFields));
1817
+ }
1818
+ /**
1819
+ * @param {TableDefine} tableDefine
1820
+ * @param {string[]} pKeys
1821
+ * @param {string[]} setKeys
1822
+ * @param {Record<string, any>[]} list
1823
+ * @param {boolean} [skip]
1824
+ * @returns {Promise<number>}
1825
+ */
1826
+ async updateMany({
1827
+ table,
1828
+ fields
1829
+ }, pKeys, setKeys, list, skip) {
1830
+ const baseFields = toBaseFields(fields);
1831
+ const update = skip ? {} : getSetNewValue(fields);
1832
+ const [whereFields, setFields] = getKeys(baseFields, update, pKeys, setKeys);
1833
+ const conn = await this.#getConnection();
1834
+ return table && typeof table === 'object' ? table.updateMany(this.#env, conn, '', baseFields, update, whereFields, setFields, list, []) : conn.updateMany(this.#env, this.#getName(table), baseFields, update, whereFields, setFields, list, []);
1835
+ }
1836
+ /**
1837
+ * @template {Fields<MainFieldType>} T
1838
+ * @param {TableDefine<T>} tableDefine
1839
+ * @param {string[]} pKeys
1840
+ * @param {string[]} setKeys
1841
+ * @param {Record<string, any>[]} list
1842
+ * @param {string[]?} [returning]
1843
+ * @param {boolean} [skip]
1844
+ * @returns {Promise<any[]>}
1845
+ */
1846
+ async updateManyReturn({
1847
+ table,
1848
+ fields
1849
+ }, pKeys, setKeys, list, returning, skip) {
1850
+ const baseFields = toBaseFields(fields);
1851
+ const update = skip ? {} : getSetNewValue(fields);
1852
+ const [whereFields, setFields] = getKeys(baseFields, update, pKeys, setKeys);
1853
+ const conn = await this.#getConnection();
1854
+ return table && typeof table === 'object' ? table.updateManyReturn(this.#env, conn, '', baseFields, update, whereFields, setFields, list, [], returning?.length ? returning : Object.keys(baseFields)) : conn.updateManyReturn(this.#env, this.#getName(table), baseFields, update, whereFields, setFields, list, [], returning?.length ? returning : Object.keys(baseFields));
1855
+ }
1856
+ /**
1857
+ * @param {TableDefine} tableDefine
1858
+ * @param {WhereValue[]} [where]
1859
+ * @returns {Promise<number>}
1860
+ */
1861
+ async delete({
1862
+ table,
1863
+ fields
1864
+ }, where) {
1865
+ const conn = await this.#getConnection();
1866
+ return table && typeof table === 'object' ? table.delete(this.#env, conn, {
1867
+ table: '',
1868
+ fields: toBaseFields(fields),
1869
+ where
1870
+ }) : conn.delete(this.#env, {
1871
+ table: this.#getName(table),
1872
+ fields: toBaseFields(fields),
1873
+ where
1874
+ });
1875
+ }
1876
+ /**
1877
+ * @template {Fields<MainFieldType>} T
1878
+ * @param {TableDefine<T>} tableDefine
1879
+ * @param {string[]?} [returning]
1880
+ * @param {WhereValue[]} [where]
1881
+ * @returns {Promise<any[]>}
1882
+ */
1883
+ async deleteReturn({
1884
+ table,
1885
+ fields
1886
+ }, returning, where) {
1887
+ const conn = await this.#getConnection();
1888
+ const baseFields = toBaseFields(fields);
1889
+ return table && typeof table === 'object' ? table.deleteReturn(this.#env, conn, {
1890
+ table: '',
1891
+ fields: baseFields,
1892
+ where
1893
+ }, returning?.length ? returning : Object.keys(baseFields)) : conn.deleteReturn(this.#env, {
1894
+ table: this.#getName(table),
1895
+ fields: baseFields,
1896
+ where
1897
+ }, returning?.length ? returning : Object.keys(baseFields));
1898
+ }
1899
+ /**
1900
+ *
1901
+ * @param {Queryable} queryable
1902
+ * @returns {Promise<number>}
1903
+ */
1904
+ async count(queryable) {
1905
+ const {
1906
+ table,
1907
+ fields
1908
+ } = queryable;
1909
+ const options = getOptions(queryable);
1910
+ const conn = await this.#getConnection();
1911
+ return table && typeof table === 'object' ? table.count(this.#env, conn, {
1912
+ ...options,
1913
+ table: '',
1914
+ fields: toBaseFields(fields)
1915
+ }) : conn.count(this.#env, {
1916
+ ...options,
1917
+ table: this.#getName(table),
1918
+ fields: toBaseFields(fields)
1919
+ });
1920
+ }
1921
+ /**
1922
+ * @param {Queryable} queryable
1923
+ * @returns {Promise<any[]>}
1924
+ */
1925
+ async select(queryable) {
1926
+ const {
1927
+ table
1928
+ } = queryable;
1929
+ const fields = toBaseFields(queryable.fields);
1930
+ const options = getOptions(queryable);
1931
+ const conn = await this.#getConnection();
1932
+ const select = toSelect(fields, options.select);
1933
+ const {
1934
+ sort
1935
+ } = options;
1936
+ return table && typeof table === 'object' ? table.select(this.#env, conn, {
1937
+ ...options,
1938
+ table: '',
1939
+ fields,
1940
+ select,
1941
+ sort: sort?.length ? sort : getDefaultSort(fields)
1942
+ }) : conn.select(this.#env, {
1943
+ ...options,
1944
+ table: this.#getName(table),
1945
+ fields,
1946
+ select,
1947
+ sort: sort?.length ? sort : getDefaultSort(fields)
1948
+ });
1949
+ }
1950
+ /**
1951
+ * @param {string} table
1952
+ * @param {string} column
1953
+ * @param {string} type
1954
+ * @param {ColumnOptions<any>} options
1955
+ * @returns {Promise<number>}
1956
+ */
1957
+ async addColumn(table, column, type, options) {
1958
+ const conn = await this.#getConnection();
1959
+ return conn.addColumn(this.#env, this.#getName(table), column, type, timestampDef(options));
1960
+ }
1961
+ /**
1962
+ * @param {string} table
1963
+ * @param {string} column
1964
+ * @param {string} type
1965
+ * @param {ColumnOptions<any>} options
1966
+ * @returns {Promise<number>}
1967
+ */
1968
+ async changeColumn(table, column, type, options) {
1969
+ const conn = await this.#getConnection();
1970
+ return conn.changeColumn(this.#env, this.#getName(table), column, type, timestampDef(options));
1971
+ }
1972
+ /**
1973
+ * @param {string} table
1974
+ * @param {string} column
1975
+ * @param {boolean} nullable
1976
+ * @returns {Promise<number>}
1977
+ */
1978
+ async changeColumnNull(table, column, nullable) {
1979
+ const conn = await this.#getConnection();
1980
+ return conn.changeColumnNull(this.#env, this.#getName(table), column, nullable);
1981
+ }
1982
+ /**
1983
+ * @param {string} table
1984
+ * @param {string} column
1985
+ * @returns {Promise<number>}
1986
+ */
1987
+ async dropColumn(table, column) {
1988
+ const conn = await this.#getConnection();
1989
+ return conn.dropColumn(this.#env, this.#getName(table), column);
1990
+ }
1991
+ /**
1992
+ * @param {string} table
1993
+ * @param {string} column
1994
+ * @param {string} newName
1995
+ * @returns {Promise<number>}
1996
+ */
1997
+ async renameColumn(table, column, newName) {
1998
+ const conn = await this.#getConnection();
1999
+ return conn.renameColumn(this.#env, this.#getName(table), column, newName);
2000
+ }
2001
+ /**
2002
+ * @param {string} table
2003
+ * @param {string} name
2004
+ * @param {string[]} fields
2005
+ * @param {IndexOptions} [options]
2006
+ * @returns {Promise<number>}
2007
+ */
2008
+ async addIndex(table, name, fields, options = {}) {
2009
+ const conn = await this.#getConnection();
2010
+ return conn.addIndex(this.#env, this.#getName(table), name, fields, options);
2011
+ }
2012
+ /**
2013
+ * @param {string} table
2014
+ * @param {string} name
2015
+ * @returns {Promise<number>}
2016
+ */
2017
+ async dropIndex(table, name) {
2018
+ const conn = await this.#getConnection();
2019
+ return conn.dropIndex(this.#env, this.#getName(table), name);
2020
+ }
2021
+ /**
2022
+ * @param {string} table
2023
+ * @param {Column<any>[]} fields
2024
+ * @returns {Promise<number>}
2025
+ */
2026
+ async createTable(table, fields) {
2027
+ const conn = await this.#getConnection();
2028
+ return conn.createTable(this.#env, this.#getName(table), fields.map(timestampDef));
2029
+ }
2030
+ /**
2031
+ * @param {string} table
2032
+ * @returns {Promise<number>}
2033
+ */
2034
+ async dropTable(table) {
2035
+ const conn = await this.#getConnection();
2036
+ return conn.dropTable(this.#env, this.#getName(table));
2037
+ }
2038
+ /**
2039
+ * @param {string} table
2040
+ * @param {string} newName
2041
+ * @returns {Promise<number>}
2042
+ */
2043
+ async renameTable(table, newName) {
2044
+ const conn = await this.#getConnection();
2045
+ return conn.renameTable(this.#env, this.#getName(table), newName);
2046
+ }
2047
+ /**
2048
+ * @param {string} view
2049
+ * @param {Queryable} queryable
2050
+ * @returns {Promise<number>}
2051
+ */
2052
+ async createView(view, queryable) {
2053
+ const conn = await this.#getConnection();
2054
+ const {
2055
+ table
2056
+ } = queryable;
2057
+ const fields = toBaseFields(queryable.fields);
2058
+ const options = getOptions(queryable);
2059
+ const select = toSelect(fields, options.select);
2060
+ return conn.createView(this.#env, this.#getName(view), {
2061
+ ...options,
2062
+ table: typeof table === 'string' ? table : '',
2063
+ fields,
2064
+ select
2065
+ });
2066
+ }
2067
+ /**
2068
+ * @param {string} view
2069
+ * @returns {Promise<number>}
2070
+ */
2071
+ async dropView(view) {
2072
+ const conn = await this.#getConnection();
2073
+ return conn.dropView(this.#env, this.#getName(view));
2074
+ }
2075
+ /**
2076
+ * @param {string} view
2077
+ * @param {Queryable} queryable
2078
+ * @returns {Promise<number>}
2079
+ */
2080
+ async createMaterializedView(view, queryable) {
2081
+ const conn = await this.#getConnection();
2082
+ const {
2083
+ table
2084
+ } = queryable;
2085
+ const fields = toBaseFields(queryable.fields);
2086
+ const options = getOptions(queryable);
2087
+ const select = toSelect(fields, options.select);
2088
+ return conn.createMaterializedView(this.#env, this.#getName(view), {
2089
+ ...options,
2090
+ table: typeof table === 'string' ? table : '',
2091
+ fields,
2092
+ select
2093
+ });
2094
+ }
2095
+ /**
2096
+ * @param {string} view
2097
+ * @returns {Promise<number>}
2098
+ */
2099
+ async dropMaterializedView(view) {
2100
+ const conn = await this.#getConnection();
2101
+ return conn.dropMaterializedView(this.#env, this.#getName(view));
2102
+ }
2103
+ /** @type {AbortController[]} */
2104
+ #layers = [];
2105
+ /**
2106
+ * @template T
2107
+ * @param {(signal: AbortSignal) => PromiseLike<T> | T} fn
2108
+ * @returns {Promise<T>}
2109
+ */
2110
+ async #transaction(fn) {
2111
+ const layers = this.#layers;
2112
+ /**
2113
+ *
2114
+ * @param {number} k
2115
+ */
2116
+ function end(k) {
2117
+ const list = layers.splice(k, layers.length - k);
2118
+ layers.pop();
2119
+ if (!list.length) {
2120
+ return;
2121
+ }
2122
+ const error = new Error();
2123
+ console.error(error);
2124
+ for (const ac of list) {
2125
+ ac.abort(error);
2126
+ }
2127
+ }
2128
+ const run = async () => {
2129
+ const ac = new AbortController();
2130
+ const k = layers.push(ac);
2131
+ try {
2132
+ return await Promise.race([fn(ac.signal), signal2promise(ac.signal)]);
2133
+ } finally {
2134
+ if (layers[k - 1] === ac) {
2135
+ end(k);
2136
+ }
2137
+ // TODO: 减少一层
2138
+ // TODO: 检测层数
2139
+ }
2140
+ };
2141
+ if (layers.length || this.#baseTransaction) {
2142
+ return run();
2143
+ }
2144
+ // TODO
2145
+ const conn = await this.#getConnection();
2146
+ return conn.transaction(this.#env, async t => {
2147
+ if (layers.length) {
2148
+ throw new Error();
2149
+ }
2150
+ this.#env.transaction = t;
2151
+ try {
2152
+ return await run();
2153
+ } finally {
2154
+ this.#env.transaction = null;
2155
+ }
2156
+ });
2157
+ }
2158
+ abort() {
2159
+ const layers = this.#layers;
2160
+ const list = layers.splice(0, layers.length);
2161
+ if (!list.length) {
2162
+ return true;
2163
+ }
2164
+ const error = new Error();
2165
+ console.error(error);
2166
+ for (const ac of list) {
2167
+ ac.abort(error);
2168
+ }
2169
+ return false;
2170
+ }
2171
+ /**
2172
+ * @template T
2173
+ * @overload
2174
+ * @param {(t: Connection) => PromiseLike<T> | T} fn
2175
+ * @returns {Promise<T>}
2176
+ */
2177
+ /**
2178
+ * @overload
2179
+ * @returns {[Promise<void>, commit: () => Promise<void>, rollback: (e?: any) => Promise<void>]}
2180
+ */
2181
+ /**
2182
+ *
2183
+ * @param {(t: Connection, signal: AbortSignal) => any} [fn]
2184
+ * @returns {any}
2185
+ */
2186
+ transaction(fn) {
2187
+ if (typeof fn === 'function') {
2188
+ return this.#transaction(signal => fn(this, signal));
2189
+ }
2190
+ /** @type {(p: AbortSignal) => void} */
2191
+ let throwAborted = () => {};
2192
+ /** @type {Promise<void>} */
2193
+ const abortedPromise = new Promise((_, r) => {
2194
+ throwAborted = r;
2195
+ });
2196
+ abortedPromise.catch(() => {});
2197
+ /** @type {() => void} */
2198
+ let commit = () => {};
2199
+ /** @type {(e?: any) => void} */
2200
+ let rollback = () => {};
2201
+ /** @type {Promise<void>} */
2202
+ const donePromise = new Promise((r1, r2) => {
2203
+ commit = r1;
2204
+ rollback = r2;
2205
+ });
2206
+ const dbiPromise = this.#transaction(v => {
2207
+ if (v.aborted) {
2208
+ throwAborted(v.reason);
2209
+ } else {
2210
+ v.addEventListener('abort', () => throwAborted(v.reason));
2211
+ }
2212
+ return donePromise;
2213
+ }).then(() => {}, () => {});
2214
+ return [abortedPromise, async () => {
2215
+ commit();
2216
+ return dbiPromise;
2217
+ }, async () => {
2218
+ rollback();
2219
+ return dbiPromise;
2220
+ }];
2221
+ }
2222
+ }
2223
+
2224
+ /**
2225
+ *
2226
+ * @param {ClassAccessorDecoratorContext} ctx
2227
+ */
2228
+ function check(ctx) {
2229
+ if (!ctx || ctx.kind !== 'accessor') {
2230
+ throw new Error('模型属性只能是访问器(accessor)');
2231
+ }
2232
+ if (ctx.static) {
2233
+ throw new Error('模型属性不能是静态属性');
2234
+ }
2235
+ if (ctx.private) {
2236
+ throw new Error('模型属性不能是私有属性');
2237
+ }
2238
+ const {
2239
+ name
2240
+ } = ctx;
2241
+ if (typeof name !== 'string') {
2242
+ throw new Error('模型属性不能是符号');
2243
+ }
2244
+ return name;
2245
+ }
2246
+
2247
+ /** @import { ClassDecorator } from './index.mjs' */
2248
+ const fieldKey = Symbol();
2249
+ const propsKey = Symbol();
2250
+ const typeKey = Symbol();
2251
+ /** @import { Constraint, FieldDefineOption, TableDefine } from '../types' */
2252
+ /** @import { FieldDecorator } from './index.mjs' */
2253
+ /**
2254
+ *
2255
+ * @overload
2256
+ * @param {string} table
2257
+ * @returns {ClassDecorator}
2258
+ */
2259
+ /**
2260
+ * @template {Record<string, any>} T
2261
+ * @overload
2262
+ * @param {TableDefine & {new(...a: any): T}} type
2263
+ * @param {Record<string, Constraint>} constraints
2264
+ * @param {true} array
2265
+ * @param {FieldDefineOption} [options]
2266
+ * @returns {FieldDecorator<T[]>}
2267
+ */
2268
+ /**
2269
+ * @template {Record<string, any>} T
2270
+ * @overload
2271
+ * @param {TableDefine & {new(...a: any): T}} type
2272
+ * @param {Record<string, Constraint>} constraints
2273
+ * @param {false} [array]
2274
+ * @param {FieldDefineOption} [options]
2275
+ * @returns {FieldDecorator<T>}
2276
+ */
2277
+ /**
2278
+ * @template {Record<string, any>} T
2279
+ * @overload
2280
+ * @param {TableDefine & {new(...a: any): T}} type
2281
+ * @param {Record<string, Constraint>} constraints
2282
+ * @param {FieldDefineOption} [options]
2283
+ * @returns {FieldDecorator<T>}
2284
+ */
2285
+ /**
2286
+ * @template {Record<string, any>} T
2287
+ * @template {boolean} [A=boolean]
2288
+ * @overload
2289
+ * @param {TableDefine & {new(...a: any): T}} type
2290
+ * @param {Record<string, Constraint>} constraints
2291
+ * @param {A} array
2292
+ * @param {FieldDefineOption} [options]
2293
+ * @returns {FieldDecorator<A extends false ? T : A extends true ? T[] : T | T[]>}
2294
+ */
2295
+ /**
2296
+ * @template {object} T
2297
+ * @overload
2298
+ * @param {TableDefine} type
2299
+ * @param {Record<string, Constraint>} constraints
2300
+ * @param {true} array
2301
+ * @param {FieldDefineOption} [options]
2302
+ * @returns {FieldDecorator<T[]>}
2303
+ */
2304
+ /**
2305
+ * @template {object} T
2306
+ * @overload
2307
+ * @param {TableDefine} type
2308
+ * @param {Record<string, Constraint>} constraints
2309
+ * @param {false} [array]
2310
+ * @param {FieldDefineOption} [options]
2311
+ * @returns {FieldDecorator<T>}
2312
+ */
2313
+ /**
2314
+ * @template {object} T
2315
+ * @overload
2316
+ * @param {TableDefine} type
2317
+ * @param {Record<string, Constraint>} constraints
2318
+ * @param {FieldDefineOption} [options]
2319
+ * @returns {FieldDecorator<T>}
2320
+ */
2321
+ /**
2322
+ * @template {object} T
2323
+ * @template {boolean} [A=boolean]
2324
+ * @overload
2325
+ * @param {TableDefine} type
2326
+ * @param {Record<string, Constraint>} constraints
2327
+ * @param {A} array
2328
+ * @param {FieldDefineOption} [options]
2329
+ * @returns {FieldDecorator<A extends false ? T :A extends true ? T[] : T | T[]>}
2330
+ */
2331
+ /**
2332
+ *
2333
+ * @param {TableDefine | string} type
2334
+ * @param {Record<string, Constraint>} [constraints]
2335
+ * @param {*} [p1]
2336
+ * @param {*} [p2]
2337
+ */
2338
+ function submodel(type, constraints, p1, p2) {
2339
+ if (typeof type === 'string') {
2340
+ const table = type;
2341
+ /**
2342
+ *
2343
+ * @param {*} ModelClass
2344
+ * @param {ClassDecoratorContext} ctx
2345
+ */
2346
+ return (ModelClass, ctx) => {
2347
+ if (typeof ModelClass !== 'function' || ctx?.kind !== 'class') {
2348
+ throw new Error('模型只能是类(class)');
2349
+ }
2350
+ const {
2351
+ metadata
2352
+ } = ctx;
2353
+ const fields = metadata[fieldKey];
2354
+ if (metadata[typeKey]) {
2355
+ throw new Error('已经被定义');
2356
+ }
2357
+ metadata[typeKey] = 'model';
2358
+ const classField = ModelClass.fields;
2359
+ if (!fields && !classField) {
2360
+ throw new Error('字段未定义');
2361
+ }
2362
+ Object.defineProperty(ModelClass, 'table', {
2363
+ value: table,
2364
+ configurable: true,
2365
+ enumerable: true
2366
+ });
2367
+ if (!fields) {
2368
+ return;
2369
+ }
2370
+ const props = metadata[propsKey] || {};
2371
+ const setFields = Object.fromEntries(Object.entries(fields).map(([k, v]) => [k, {
2372
+ ...v,
2373
+ ...props[k]
2374
+ }]));
2375
+ ctx.addInitializer(function () {
2376
+ if (ModelClass[typeKey]) {
2377
+ throw new Error('已经被定义');
2378
+ }
2379
+ ModelClass[typeKey] = 'model';
2380
+ Object.defineProperty(this, 'fields', {
2381
+ value: {
2382
+ ...classField,
2383
+ ...setFields
2384
+ },
2385
+ enumerable: true,
2386
+ configurable: true
2387
+ });
2388
+ });
2389
+ };
2390
+ }
2391
+ /** @type { {nullable?: boolean; array?: boolean; default?: any; } & FieldDefineOption} */
2392
+ const ctx = typeof p1 === 'object' && p1 || p2 || {};
2393
+ const array = p1 === true;
2394
+ const {
2395
+ array: _array,
2396
+ nullable,
2397
+ default: def,
2398
+ precision,
2399
+ scale,
2400
+ size,
2401
+ unique,
2402
+ index,
2403
+ primary,
2404
+ serial,
2405
+ immutable,
2406
+ text,
2407
+ sort,
2408
+ ...p
2409
+ } = ctx;
2410
+ const define = {
2411
+ ...p,
2412
+ constraints,
2413
+ type: {
2414
+ table: type.table,
2415
+ fields: type.fields,
2416
+ pseudo: type.pseudo,
2417
+ indexes: type.indexes
2418
+ },
2419
+ array,
2420
+ nullable: false,
2421
+ immutable
2422
+ };
2423
+ /**
2424
+ *
2425
+ * @param {*} _
2426
+ * @param {ClassAccessorDecoratorContext} ctx
2427
+ */
2428
+ return (_, ctx) => {
2429
+ const name = check(ctx);
2430
+ const {
2431
+ metadata
2432
+ } = ctx;
2433
+ const fields = metadata[fieldKey];
2434
+ if (fields) {
2435
+ fields[name] = define;
2436
+ } else {
2437
+ metadata[fieldKey] = Object.assign(Object.create(null), {
2438
+ [name]: define
2439
+ });
2440
+ }
2441
+ return {
2442
+ get() {
2443
+ return this.$get(name);
2444
+ },
2445
+ set(value) {
2446
+ return this.$set(name, value);
2447
+ }
2448
+ };
2449
+ };
2450
+ }
2451
+
2452
+ /** @import { FieldDefineOption, FieldType, ToType } from '../types' */
2453
+ /** @import { FieldDecorator } from './index.mjs' */
2454
+ /**
2455
+ * @template {keyof FieldType} T
2456
+ * @overload
2457
+ * @param {T} type
2458
+ * @param {{
2459
+ * nullable?: false;
2460
+ * array?: false;
2461
+ * default?: ToType<T, false, false>;
2462
+ * [k: string]: any;
2463
+ * } & FieldDefineOption} [options]
2464
+ * @returns {FieldDecorator<ToType<T, false, false>>}
2465
+ */
2466
+ /**
2467
+ * @template {keyof FieldType} T
2468
+ * @overload
2469
+ * @param {T} type
2470
+ * @param {{
2471
+ * nullable?: false;
2472
+ * array: true;
2473
+ * default?: ToType<T, true, false>;
2474
+ * [k: string]: any;
2475
+ * } & FieldDefineOption} options
2476
+ * @returns {FieldDecorator<ToType<T, true, false>>}
2477
+ */
2478
+ /**
2479
+ * @template {keyof FieldType} T
2480
+ * @overload
2481
+ * @param {T} type
2482
+ * @param {true} array
2483
+ * @param {{
2484
+ * nullable?: false;
2485
+ * default?: ToType<T, true, false>;
2486
+ * [k: string]: any;
2487
+ * } & FieldDefineOption} options
2488
+ * @returns {FieldDecorator<ToType<T, true, false>>}
2489
+ */
2490
+ /**
2491
+ * @template {keyof FieldType} T
2492
+ * @overload
2493
+ * @param {T} type
2494
+ * @param {{
2495
+ * nullable: true;
2496
+ * array?: false;
2497
+ * default?: ToType<T, false, true>;
2498
+ * [k: string]: any;
2499
+ * } & FieldDefineOption} options
2500
+ * @returns {FieldDecorator<ToType<T, false, true>>}
2501
+ */
2502
+ /**
2503
+ * @template {keyof FieldType} T
2504
+ * @overload
2505
+ * @param {T} type
2506
+ * @param {{
2507
+ * nullable: true;
2508
+ * array: true;
2509
+ * default?: ToType<T, true, true>;
2510
+ * [k: string]: any;
2511
+ * } & FieldDefineOption} options
2512
+ * @returns {FieldDecorator<ToType<T, true, true>>}
2513
+ */
2514
+ /**
2515
+ * @template {keyof FieldType} T
2516
+ * @overload
2517
+ * @param {T} type
2518
+ * @param {true} array
2519
+ * @param {{
2520
+ * nullable: true;
2521
+ * default?: ToType<T, true, true>;
2522
+ * [k: string]: any;
2523
+ * } & FieldDefineOption} options
2524
+ * @returns {FieldDecorator<ToType<T, true, true>>}
2525
+ */
2526
+ /**
2527
+ * @template {keyof FieldType} T
2528
+ * @template {boolean} A
2529
+ * @overload
2530
+ * @param {T} type
2531
+ * @param {{
2532
+ * nullable: true;
2533
+ * array: A;
2534
+ * default?: ToType<T, A, true>;
2535
+ * [k: string]: any;
2536
+ * } & FieldDefineOption} options
2537
+ * @returns {FieldDecorator<ToType<T, A, true>>}
2538
+ */
2539
+ /**
2540
+ * @template {keyof FieldType} T
2541
+ * @template {boolean} A
2542
+ * @overload
2543
+ * @param {T} type
2544
+ * @param {{
2545
+ * nullable?: false;
2546
+ * array: A;
2547
+ * default?: ToType<T, A, false>;
2548
+ * [k: string]: any;
2549
+ * } & FieldDefineOption} options
2550
+ * @returns {FieldDecorator<ToType<T, A, false>>}
2551
+ */
2552
+ /**
2553
+ * @template {keyof FieldType} T
2554
+ * @template {boolean} N
2555
+ * @overload
2556
+ * @param {T} type
2557
+ * @param {{
2558
+ * nullable: N;
2559
+ * array?: false;
2560
+ * default?: ToType<T, false, N>;
2561
+ * [k: string]: any;
2562
+ * } & FieldDefineOption} options
2563
+ * @returns {FieldDecorator<ToType<T, false, N>>}
2564
+ */
2565
+ /**
2566
+ * @template {keyof FieldType} T
2567
+ * @template {boolean} N
2568
+ * @overload
2569
+ * @param {T} type
2570
+ * @param {{
2571
+ * nullable: N;
2572
+ * array: true;
2573
+ * default?: ToType<T, true, N>;
2574
+ * [k: string]: any;
2575
+ * } & FieldDefineOption} options
2576
+ * @returns {FieldDecorator<ToType<T, true, N>>}
2577
+ */
2578
+ /**
2579
+ * @template {keyof FieldType} T
2580
+ * @template {boolean} N
2581
+ * @overload
2582
+ * @param {T} type
2583
+ * @param {true} array
2584
+ * @param {{
2585
+ * nullable: N;
2586
+ * default?: ToType<T, true, N>;
2587
+ * [k: string]: any;
2588
+ * } & FieldDefineOption} options
2589
+ * @returns {FieldDecorator<ToType<T, true, N>>}
2590
+ */
2591
+ /**
2592
+ * @template {keyof FieldType} T
2593
+ * @template {boolean} A
2594
+ * @template {boolean} N
2595
+ * @overload
2596
+ * @param {T} type
2597
+ * @param {{
2598
+ * nullable: N;
2599
+ * array: A;
2600
+ * default?: ToType<T, A, N>;
2601
+ * [k: string]: any;
2602
+ * } & FieldDefineOption} options
2603
+ * @returns {FieldDecorator<ToType<T, A, N>>}
2604
+ */
2605
+ /**
2606
+ * @template {keyof FieldType} T
2607
+ * @overload
2608
+ * @param {T} type
2609
+ * @param {{
2610
+ * nullable?: boolean;
2611
+ * array?: boolean;
2612
+ * default?: ToType<T, boolean, boolean>;
2613
+ * [k: string]: any;
2614
+ * } & FieldDefineOption} options
2615
+ * @returns {FieldDecorator<ToType<T, boolean, boolean>>}
2616
+ */
2617
+ /**
2618
+ *
2619
+ * @param {*} type
2620
+ * @param {*} [p1]
2621
+ * @param {*} [p2]
2622
+ */
2623
+ function field$1(type, p1, p2) {
2624
+ if (typeof type !== 'string') {
2625
+ throw new Error('无效的类型');
2626
+ }
2627
+ /** @type { {nullable?: boolean; array?: boolean; default?: any; } & FieldDefineOption} */
2628
+ const ctx = typeof p1 === 'object' && p1 || p2 || {};
2629
+ const array = p1 === true || ctx.array;
2630
+ const {
2631
+ array: _array,
2632
+ nullable,
2633
+ default: def,
2634
+ precision,
2635
+ scale,
2636
+ size,
2637
+ unique,
2638
+ index,
2639
+ primary,
2640
+ serial,
2641
+ immutable,
2642
+ text,
2643
+ sort,
2644
+ ...p
2645
+ } = ctx;
2646
+ const define = {
2647
+ ...p,
2648
+ type,
2649
+ array: Boolean(array),
2650
+ nullable: Boolean(nullable),
2651
+ precision,
2652
+ scale,
2653
+ size,
2654
+ default: def,
2655
+ index,
2656
+ unique: Boolean(unique),
2657
+ primary,
2658
+ serial,
2659
+ immutable,
2660
+ text,
2661
+ sort
2662
+ };
2663
+ /**
2664
+ *
2665
+ * @param {*} _
2666
+ * @param {ClassAccessorDecoratorContext} ctx
2667
+ */
2668
+ return (_, ctx) => {
2669
+ const name = check(ctx);
2670
+ const {
2671
+ metadata
2672
+ } = ctx;
2673
+ const fields = metadata[fieldKey];
2674
+ if (fields) {
2675
+ fields[name] = define;
2676
+ } else {
2677
+ metadata[fieldKey] = Object.assign(Object.create(null), {
2678
+ [name]: define
2679
+ });
2680
+ }
2681
+ return {
2682
+ get() {
2683
+ return this.$get(name);
2684
+ },
2685
+ set(value) {
2686
+ return this.$set(name, value);
2687
+ }
2688
+ };
2689
+ };
2690
+ }
2691
+
2692
+ /** @import { ToFieldType } from '../types' */
2693
+ /** @import { FieldDecorator } from './index.mjs' */
2694
+ /**
2695
+ * @param {object} [options]
2696
+ * @param {number?} [options.sort]
2697
+ * @returns {FieldDecorator<ToFieldType<'id'>>}
2698
+ */
2699
+ function id({
2700
+ sort
2701
+ } = {}) {
2702
+ const define = {
2703
+ type: 'id',
2704
+ index: true,
2705
+ unique: true,
2706
+ primary: true,
2707
+ serial: true,
2708
+ immutable: true,
2709
+ sort
2710
+ };
2711
+ /**
2712
+ *
2713
+ * @param {*} _
2714
+ * @param {ClassAccessorDecoratorContext} ctx
2715
+ */
2716
+ return (_, ctx) => {
2717
+ const name = check(ctx);
2718
+ const {
2719
+ metadata
2720
+ } = ctx;
2721
+ const fields = metadata[fieldKey];
2722
+ if (fields) {
2723
+ fields[name] = define;
2724
+ } else {
2725
+ metadata[fieldKey] = Object.assign(Object.create(null), {
2726
+ [name]: define
2727
+ });
2728
+ }
2729
+ return {
2730
+ get() {
2731
+ return this.$get(name);
2732
+ },
2733
+ set(value) {
2734
+ return this.$set(name, value);
2735
+ }
2736
+ };
2737
+ };
2738
+ }
2739
+
2740
+ /** @import { FieldDecorator } from './index.mjs' */
2741
+ /**
2742
+ *
2743
+ * @param {ClassAccessorDecoratorContext} ctx
2744
+ * @param {*} precision
2745
+ * @param {'timestampCreating' | 'timestampUpdating' | 'timestampDeleting'} prop
2746
+ */
2747
+ function defineTimestamp(ctx, precision, prop) {
2748
+ const name = check(ctx);
2749
+ const {
2750
+ metadata
2751
+ } = ctx;
2752
+ const fields = metadata[fieldKey];
2753
+ const define = {
2754
+ type: 'timestamp',
2755
+ array: false,
2756
+ nullable: true,
2757
+ precision,
2758
+ [prop]: true
2759
+ };
2760
+ if (fields) {
2761
+ fields[name] = define;
2762
+ } else {
2763
+ metadata[fieldKey] = Object.assign(Object.create(null), {
2764
+ [name]: define
2765
+ });
2766
+ }
2767
+ return {
2768
+ get() {
2769
+ return this.$get(name);
2770
+ },
2771
+ set(value) {
2772
+ return this.$set(name, value);
2773
+ }
2774
+ };
2775
+ }
2776
+ /**
2777
+ * @param {number} [precision]
2778
+ * @returns {FieldDecorator<Date?>}
2779
+ */
2780
+ function creating(precision) {
2781
+ return (_, ctx) => defineTimestamp(ctx, precision, 'timestampCreating');
2782
+ }
2783
+ /**
2784
+ * @param {number} [precision]
2785
+ * @returns {FieldDecorator<Date?>}
2786
+ */
2787
+ function updating(precision) {
2788
+ return (_, ctx) => defineTimestamp(ctx, precision, 'timestampUpdating');
2789
+ }
2790
+ /**
2791
+ * @param {number} [precision]
2792
+ * @returns {FieldDecorator<Date?>}
2793
+ */
2794
+ function deleting(precision) {
2795
+ return (_, ctx) => defineTimestamp(ctx, precision, 'timestampDeleting');
2796
+ }
2797
+
2798
+ /**
2799
+ *
2800
+ * @param {ClassAccessorDecoratorContext} ctx
2801
+ * @param {string} prop
2802
+ * @param {any} value
2803
+ */
2804
+ function setProp(ctx, prop, value) {
2805
+ const name = check(ctx);
2806
+ const {
2807
+ metadata
2808
+ } = ctx;
2809
+ /** @type {Record<string, any>} */
2810
+ // @ts-ignore
2811
+ let fields = metadata[propsKey];
2812
+ if (!fields) {
2813
+ fields = Object.create(null);
2814
+ metadata[propsKey] = fields;
2815
+ }
2816
+ const field = fields[name];
2817
+ if (field) {
2818
+ fields[name][prop] = value;
2819
+ } else {
2820
+ fields[name] = {
2821
+ [prop]: value
2822
+ };
2823
+ }
2824
+ }
2825
+
2826
+ /** @import { FieldDecorator } from './index.mjs' */
2827
+ /**
2828
+ * @param {string} prop
2829
+ * @param {any} value
2830
+ * @returns {FieldDecorator<any>}
2831
+ */
2832
+ function prop(prop, value) {
2833
+ return (_, ctx) => setProp(ctx, prop, value);
2834
+ }
2835
+
2836
+ /** @import { FieldDecorator } from './index.mjs' */
2837
+ /**
2838
+ *
2839
+ * @param {number} [primary]
2840
+ * @returns {FieldDecorator<any>}
2841
+ */
2842
+ function primary(primary) {
2843
+ return (_, ctx) => setProp(ctx, 'primary', primary || true);
2844
+ }
2845
+
2846
+ /** @import { FieldDecorator } from './index.mjs' */
2847
+ /** @returns {FieldDecorator<any>} */
2848
+ function immutable() {
2849
+ return (_, ctx) => setProp(ctx, 'immutable', true);
2850
+ }
2851
+
2852
+ /** @import { IndexOptions } from '../types' */
2853
+ /** @import { ClassDecorator, FieldDecorator } from './index.mjs' */
2854
+ /**
2855
+ * 索引信息
2856
+ * @param {string | true} [index]
2857
+ * @param {boolean} [unique]
2858
+ * @returns {FieldDecorator<any>}
2859
+ */
2860
+ function indexProp(index, unique) {
2861
+ /**
2862
+ *
2863
+ * @param {ClassAccessorDecoratorContext} ctx
2864
+ */
2865
+ return function (_, ctx) {
2866
+ const name = check(ctx);
2867
+ const {
2868
+ metadata
2869
+ } = ctx;
2870
+ /** @type {Record<string, any>} */
2871
+ // @ts-ignore
2872
+ let fields = metadata[propsKey];
2873
+ if (!fields) {
2874
+ fields = Object.create(null);
2875
+ metadata[propsKey] = fields;
2876
+ }
2877
+ const field = fields[name];
2878
+ if (field) {
2879
+ field.index = index;
2880
+ if (unique) {
2881
+ field.unique = true;
2882
+ }
2883
+ } else {
2884
+ fields[name] = {
2885
+ index,
2886
+ unique
2887
+ };
2888
+ }
2889
+ };
2890
+ }
2891
+ /**
2892
+ * 索引信息
2893
+ * @param {string[]} fields
2894
+ * @param {IndexOptions} options
2895
+ * @returns {ClassDecorator}
2896
+ */
2897
+ function indexClass(fields, options) {
2898
+ return (ModelClass, ctx) => {
2899
+ if (typeof ModelClass !== 'function' || ctx?.kind !== 'class') {
2900
+ throw new Error('指定字段的用法,只能用在类(class)上');
2901
+ }
2902
+ ctx.addInitializer(function () {
2903
+ const r = Reflect.getOwnPropertyDescriptor(this, 'indexes');
2904
+ if (!r) {
2905
+ Reflect.defineProperty(this, 'indexes', {
2906
+ // @ts-ignore
2907
+ value: [...(this.indexes || [])],
2908
+ configurable: true,
2909
+ enumerable: true
2910
+ });
2911
+ }
2912
+ // @ts-ignore
2913
+ this.indexes.push({
2914
+ ...options,
2915
+ fields
2916
+ });
2917
+ });
2918
+ };
2919
+ }
2920
+ /**
2921
+ * 索引信息
2922
+ * @overload
2923
+ * @param {string[]} fields
2924
+ * @param {IndexOptions} [options]
2925
+ * @returns {ClassDecorator}
2926
+ */
2927
+ /**
2928
+ * 索引信息
2929
+ * @overload
2930
+ * @param {string} [name]
2931
+ * @param {boolean} [unique]
2932
+ * @returns {FieldDecorator<any>}
2933
+ */
2934
+ /**
2935
+ * 索引信息
2936
+ * @overload
2937
+ * @param {boolean} [unique]
2938
+ * @returns {FieldDecorator<any>}
2939
+ */
2940
+ /**
2941
+ * 索引信息
2942
+ * @param {string | boolean | string[]} [a]
2943
+ * @param {boolean | IndexOptions} [b]
2944
+ * @returns {FieldDecorator<any> | ClassDecorator}
2945
+ */
2946
+ function index(a, b) {
2947
+ if (Array.isArray(a)) {
2948
+ return indexClass(a, typeof b === 'object' && b || {});
2949
+ }
2950
+ const unique = a === true || b === true;
2951
+ const index = typeof a === 'string' && a || true;
2952
+ return indexProp(index, unique);
2953
+ }
2954
+
2955
+ /** @import { FieldDecorator } from './index.mjs' */
2956
+ /**
2957
+ * 默认排序顺序,绝对值表示在排序列表中的顺序,负数表示逆序排序, 0 表示不排序
2958
+ * @param {number} sort
2959
+ * @returns {FieldDecorator<any>}
2960
+ */
2961
+ function sort(sort) {
2962
+ return (_, ctx) => setProp(ctx, 'sort', sort);
2963
+ }
2964
+
2965
+ /** @import { ClassDecorator } from './index.mjs' */
2966
+ /**
2967
+ *
2968
+ * @param {string} pseudo
2969
+ * @returns {ClassDecorator}
2970
+ */
2971
+ function pseudo(pseudo) {
2972
+ /**
2973
+ *
2974
+ * @param {*} ModelClass
2975
+ * @param {ClassDecoratorContext} ctx
2976
+ */
2977
+ return (ModelClass, ctx) => {
2978
+ if (typeof ModelClass !== 'function' || ctx?.kind !== 'class') {
2979
+ throw new Error('模型只能是类(class)');
2980
+ }
2981
+ ctx.addInitializer(function () {
2982
+ Object.defineProperty(this, 'pseudo', {
2983
+ value: pseudo,
2984
+ configurable: true,
2985
+ enumerable: true
2986
+ });
2987
+ });
2988
+ };
2989
+ }
2990
+
2991
+ /** @typedef {{toWhereValue(): WhereValue[][]}} WhereLike */
2992
+ /** @typedef {WhereLike | Record<string, any> | (WhereLike | Record<string, any>)[]} Wheres */
2993
+ /**
2994
+ * @typedef {object} WhereItem
2995
+ * @prop {null} [where]
2996
+ * @prop {null} [or]
2997
+ * @prop {string | {table?: string; field: string} | (string | {table?: string; field: string})[]} field
2998
+ * @prop {any} value
2999
+ * @prop {boolean} [not]
3000
+ * @prop {string?} [operator]
3001
+ */
3002
+ /**
3003
+ * @typedef {object} WhereRaw
3004
+ * @prop {null} [field]
3005
+ * @prop {null} [or]
3006
+ * @prop {readonly string[]} where
3007
+ * @prop {readonly any[]} values
3008
+ * @prop {boolean} [not]
3009
+ */
3010
+ /**
3011
+ * @typedef {object} WhereOr
3012
+ * @prop {null} [where]
3013
+ * @prop {null} [field]
3014
+ * @prop {WhereValue[][]} or
3015
+ * @prop {boolean} [not]
3016
+ */
3017
+ /** @typedef {WhereItem | WhereRaw | WhereOr} WhereValue */
3018
+ /**
3019
+ *
3020
+ * @param {*} v
3021
+ * @returns {v is TemplateStringsArray}
3022
+ */
3023
+ function isTemplateStringsArray(v) {
3024
+ // @ts-ignore
3025
+ return Array.isArray(v) && Array.isArray(v.raw);
3026
+ }
3027
+ /**
3028
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3029
+ * @returns {WhereValue[]?}
3030
+ */
3031
+ function parse(items) {
3032
+ if (!items.length) {
3033
+ return null;
3034
+ }
3035
+ const [first] = items;
3036
+ if (isTemplateStringsArray(first)) {
3037
+ if (first.raw.length !== items.length) {
3038
+ // TODO: 报错
3039
+ return [{
3040
+ where: first.raw,
3041
+ values: items.slice(1)
3042
+ }];
3043
+ }
3044
+ }
3045
+ if (items.length === 1) {
3046
+ /** @type {WhereValue[][]} */
3047
+ const result = [];
3048
+ const list = /** @type {(WhereLike | Record<string, any>)[]} */items.flat(Infinity);
3049
+ for (const item of list) {
3050
+ if (!item) {
3051
+ continue;
3052
+ }
3053
+ if (typeof item !== 'object') {
3054
+ // TODO: 报错
3055
+ continue;
3056
+ }
3057
+ if (typeof item.toWhereValue === 'function') {
3058
+ const values = item.toWhereValue();
3059
+ if (values.length <= 1) {
3060
+ result.push(values[0] || []);
3061
+ } else {
3062
+ result.push([{
3063
+ or: values
3064
+ }]);
3065
+ }
3066
+ continue;
3067
+ }
3068
+ for (const [k, v] of Object.entries(item)) {
3069
+ result.push([{
3070
+ field: k,
3071
+ value: v,
3072
+ not: false
3073
+ }]);
3074
+ }
3075
+ }
3076
+ return result.flat();
3077
+ }
3078
+ if (items.length === 2) {
3079
+ items.splice(1, 0, '');
3080
+ }
3081
+ if (items.length === 3) {
3082
+ items.push(false);
3083
+ }
3084
+ if (items.length > 4) {
3085
+ // TODO: 报错
3086
+ return null;
3087
+ }
3088
+ const [field, operator, value, not] = items;
3089
+ // @ts-ignore
3090
+ return [{
3091
+ field,
3092
+ operator,
3093
+ value,
3094
+ not: Boolean(not)
3095
+ }];
3096
+ }
3097
+ /**
3098
+ * @param {WhereValue[]?} [items]
3099
+ * @returns {WhereValue[]?}
3100
+ */
3101
+ function toNot(items) {
3102
+ if (!items) {
3103
+ return null;
3104
+ }
3105
+ return items.map(v => ({
3106
+ ...v,
3107
+ not: !v.not
3108
+ }));
3109
+ }
3110
+ class Where {
3111
+ /**
3112
+ * @overload
3113
+ * @param {Wheres} matches
3114
+ * @returns {WhereValue[]?}
3115
+ */
3116
+ /**
3117
+ * @overload
3118
+ * @param {string | string[]} field
3119
+ * @param {any} value
3120
+ * @returns {WhereValue[]?}
3121
+ */
3122
+ /**
3123
+ * @overload
3124
+ * @param {string | string[]} field
3125
+ * @param {string} operator
3126
+ * @param {any} value
3127
+ * @param {boolean} [not]
3128
+ * @returns {WhereValue[]?}
3129
+ */
3130
+ /**
3131
+ * @overload
3132
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3133
+ * @returns {WhereValue[]?}
3134
+ */
3135
+ /**
3136
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3137
+ * @returns {WhereValue[]?}
3138
+ */
3139
+ static parse(...items) {
3140
+ return parse(items);
3141
+ }
3142
+ /**
3143
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3144
+ * @returns {WhereValue[]?}
3145
+ */
3146
+ static parseParams(items) {
3147
+ return parse(items);
3148
+ }
3149
+ /** @type {WhereValue[]} */
3150
+ #last = [];
3151
+ #values = [this.#last];
3152
+ toWhereValue() {
3153
+ return this.#values.filter(v => v.length);
3154
+ }
3155
+ /**
3156
+ * @param {WhereValue[]?} items
3157
+ * @returns {this}
3158
+ */
3159
+ #and(items) {
3160
+ if (!items) {
3161
+ return this;
3162
+ }
3163
+ this.#last.push(...items);
3164
+ return this;
3165
+ }
3166
+ /**
3167
+ * @param {WhereValue[]?} items
3168
+ * @returns {this}
3169
+ */
3170
+ #or(items) {
3171
+ if (!items) {
3172
+ return this;
3173
+ }
3174
+ const last = [...items];
3175
+ this.#last = last;
3176
+ this.#values.push(last);
3177
+ return this;
3178
+ }
3179
+ /**
3180
+ * @overload
3181
+ * @param {Wheres} matches
3182
+ * @returns {this}
3183
+ */
3184
+ /**
3185
+ *
3186
+ * @overload
3187
+ * @param {TemplateStringsArray} where
3188
+ * @param {...any} values
3189
+ * @returns {this}
3190
+ */
3191
+ /**
3192
+ * @overload
3193
+ * @param {string} field
3194
+ * @param {any} value
3195
+ * @returns {this}
3196
+ */
3197
+ /**
3198
+ * @overload
3199
+ * @param {string[]} field
3200
+ * @param {any[]} value
3201
+ * @returns {this}
3202
+ */
3203
+ /**
3204
+ * @overload
3205
+ * @param {string} field
3206
+ * @param {string} operator
3207
+ * @param {any} value
3208
+ * @param {boolean} [not]
3209
+ * @returns {this}
3210
+ */
3211
+ /**
3212
+ * @overload
3213
+ * @param {string[]} field
3214
+ * @param {string} operator
3215
+ * @param {any[]} value
3216
+ * @param {boolean} [not]
3217
+ * @returns {this}
3218
+ */
3219
+ /**
3220
+ * @overload
3221
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3222
+ * @returns {this}
3223
+ */
3224
+ /**
3225
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3226
+ * @returns {this}
3227
+ */
3228
+ and(...items) {
3229
+ return this.#and(parse(items));
3230
+ }
3231
+ /**
3232
+ * @overload
3233
+ * @param {Wheres} matches
3234
+ * @returns {Where}
3235
+ */
3236
+ /**
3237
+ *
3238
+ * @overload
3239
+ * @param {TemplateStringsArray} where
3240
+ * @param {...any} values
3241
+ * @returns {Where}
3242
+ */
3243
+ /**
3244
+ * @overload
3245
+ * @param {string} field
3246
+ * @param {any} value
3247
+ * @returns {Where}
3248
+ */
3249
+ /**
3250
+ * @overload
3251
+ * @param {string[]} field
3252
+ * @param {any[]} value
3253
+ * @returns {Where}
3254
+ */
3255
+ /**
3256
+ * @overload
3257
+ * @param {string} field
3258
+ * @param {string} operator
3259
+ * @param {any} value
3260
+ * @param {boolean} [not]
3261
+ * @returns {Where}
3262
+ */
3263
+ /**
3264
+ * @overload
3265
+ * @param {string[]} field
3266
+ * @param {string} operator
3267
+ * @param {any[]} value
3268
+ * @param {boolean} [not]
3269
+ * @returns {Where}
3270
+ */
3271
+ /**
3272
+ * @overload
3273
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3274
+ * @returns {Where}
3275
+ */
3276
+ /**
3277
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3278
+ * @returns {Where}
3279
+ */
3280
+ static and(...items) {
3281
+ return new Where().#and(parse(items));
3282
+ }
3283
+ /**
3284
+ * @overload
3285
+ * @param {Wheres} matches
3286
+ * @returns {this}
3287
+ */
3288
+ /**
3289
+ *
3290
+ * @overload
3291
+ * @param {TemplateStringsArray} where
3292
+ * @param {...any} values
3293
+ * @returns {this}
3294
+ */
3295
+ /**
3296
+ * @overload
3297
+ * @param {string} field
3298
+ * @param {any} value
3299
+ * @returns {this}
3300
+ */
3301
+ /**
3302
+ * @overload
3303
+ * @param {string[]} field
3304
+ * @param {any[]} value
3305
+ * @returns {this}
3306
+ */
3307
+ /**
3308
+ * @overload
3309
+ * @param {string} field
3310
+ * @param {string} operator
3311
+ * @param {any} value
3312
+ * @param {boolean} [not]
3313
+ * @returns {this}
3314
+ */
3315
+ /**
3316
+ * @overload
3317
+ * @param {string[]} field
3318
+ * @param {string} operator
3319
+ * @param {any[]} value
3320
+ * @param {boolean} [not]
3321
+ * @returns {this}
3322
+ */
3323
+ /**
3324
+ * @overload
3325
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3326
+ * @returns {this}
3327
+ */
3328
+ /**
3329
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3330
+ * @returns {this}
3331
+ */
3332
+ or(...items) {
3333
+ return this.#or(parse(items));
3334
+ }
3335
+ /**
3336
+ * @overload
3337
+ * @param {Wheres} matches
3338
+ * @returns {Where}
3339
+ */
3340
+ /**
3341
+ *
3342
+ * @overload
3343
+ * @param {TemplateStringsArray} where
3344
+ * @param {...any} values
3345
+ * @returns {Where}
3346
+ */
3347
+ /**
3348
+ * @overload
3349
+ * @param {string} field
3350
+ * @param {any} value
3351
+ * @returns {Where}
3352
+ */
3353
+ /**
3354
+ * @overload
3355
+ * @param {string[]} field
3356
+ * @param {any[]} value
3357
+ * @returns {Where}
3358
+ */
3359
+ /**
3360
+ * @overload
3361
+ * @param {string} field
3362
+ * @param {string} operator
3363
+ * @param {any} value
3364
+ * @param {boolean} [not]
3365
+ * @returns {Where}
3366
+ */
3367
+ /**
3368
+ * @overload
3369
+ * @param {string[]} field
3370
+ * @param {string} operator
3371
+ * @param {any[]} value
3372
+ * @param {boolean} [not]
3373
+ * @returns {Where}
3374
+ */
3375
+ /**
3376
+ * @overload
3377
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3378
+ * @returns {Where}
3379
+ */
3380
+ /**
3381
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3382
+ * @returns {Where}
3383
+ */
3384
+ static or(...items) {
3385
+ return new Where().#or(parse(items));
3386
+ }
3387
+ /**
3388
+ * @overload
3389
+ * @param {Wheres} matches
3390
+ * @returns {this}
3391
+ */
3392
+ /**
3393
+ *
3394
+ * @overload
3395
+ * @param {TemplateStringsArray} where
3396
+ * @param {...any} values
3397
+ * @returns {this}
3398
+ */
3399
+ /**
3400
+ * @overload
3401
+ * @param {string} field
3402
+ * @param {any} value
3403
+ * @returns {this}
3404
+ */
3405
+ /**
3406
+ * @overload
3407
+ * @param {string[]} field
3408
+ * @param {any[]} value
3409
+ * @returns {this}
3410
+ */
3411
+ /**
3412
+ * @overload
3413
+ * @param {string} field
3414
+ * @param {string} operator
3415
+ * @param {any} value
3416
+ * @param {boolean} [not]
3417
+ * @returns {this}
3418
+ */
3419
+ /**
3420
+ * @overload
3421
+ * @param {string[]} field
3422
+ * @param {string} operator
3423
+ * @param {any[]} value
3424
+ * @param {boolean} [not]
3425
+ * @returns {this}
3426
+ */
3427
+ /**
3428
+ * @overload
3429
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3430
+ * @returns {this}
3431
+ */
3432
+ /**
3433
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3434
+ * @returns {this}
3435
+ */
3436
+ not(...items) {
3437
+ return this.#and(toNot(parse(items)));
3438
+ }
3439
+ /**
3440
+ * @overload
3441
+ * @param {Wheres} matches
3442
+ * @returns {Where}
3443
+ */
3444
+ /**
3445
+ *
3446
+ * @overload
3447
+ * @param {TemplateStringsArray} where
3448
+ * @param {...any} values
3449
+ * @returns {Where}
3450
+ */
3451
+ /**
3452
+ * @overload
3453
+ * @param {string} field
3454
+ * @param {any} value
3455
+ * @returns {Where}
3456
+ */
3457
+ /**
3458
+ * @overload
3459
+ * @param {string[]} field
3460
+ * @param {any[]} value
3461
+ * @returns {Where}
3462
+ */
3463
+ /**
3464
+ * @overload
3465
+ * @param {string} field
3466
+ * @param {string} operator
3467
+ * @param {any} value
3468
+ * @param {boolean} [not]
3469
+ * @returns {Where}
3470
+ */
3471
+ /**
3472
+ * @overload
3473
+ * @param {string[]} field
3474
+ * @param {string} operator
3475
+ * @param {any[]} value
3476
+ * @param {boolean} [not]
3477
+ * @returns {Where}
3478
+ */
3479
+ /**
3480
+ * @overload
3481
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3482
+ * @returns {Where}
3483
+ */
3484
+ /**
3485
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3486
+ * @returns {Where}
3487
+ */
3488
+ static not(...items) {
3489
+ return new Where().#and(toNot(parse(items)));
3490
+ }
3491
+ /**
3492
+ * @overload
3493
+ * @param {Wheres} matches
3494
+ * @returns {this}
3495
+ */
3496
+ /**
3497
+ *
3498
+ * @overload
3499
+ * @param {TemplateStringsArray} where
3500
+ * @param {...any} values
3501
+ * @returns {this}
3502
+ */
3503
+ /**
3504
+ * @overload
3505
+ * @param {string} field
3506
+ * @param {any} value
3507
+ * @returns {this}
3508
+ */
3509
+ /**
3510
+ * @overload
3511
+ * @param {string[]} field
3512
+ * @param {any[]} value
3513
+ * @returns {this}
3514
+ */
3515
+ /**
3516
+ * @overload
3517
+ * @param {string} field
3518
+ * @param {string} operator
3519
+ * @param {any} value
3520
+ * @param {boolean} [not]
3521
+ * @returns {this}
3522
+ */
3523
+ /**
3524
+ * @overload
3525
+ * @param {string[]} field
3526
+ * @param {string} operator
3527
+ * @param {any[]} value
3528
+ * @param {boolean} [not]
3529
+ * @returns {this}
3530
+ */
3531
+ /**
3532
+ * @overload
3533
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3534
+ * @returns {this}
3535
+ */
3536
+ /**
3537
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3538
+ * @returns {this}
3539
+ */
3540
+ orNot(...items) {
3541
+ return this.#or(toNot(parse(items)));
3542
+ }
3543
+ /**
3544
+ * @overload
3545
+ * @param {Wheres} matches
3546
+ * @returns {Where}
3547
+ */
3548
+ /**
3549
+ *
3550
+ * @overload
3551
+ * @param {TemplateStringsArray} where
3552
+ * @param {...any} values
3553
+ * @returns {Where}
3554
+ */
3555
+ /**
3556
+ * @overload
3557
+ * @param {string} field
3558
+ * @param {any} value
3559
+ * @returns {Where}
3560
+ */
3561
+ /**
3562
+ * @overload
3563
+ * @param {string[]} field
3564
+ * @param {any[]} value
3565
+ * @returns {Where}
3566
+ */
3567
+ /**
3568
+ * @overload
3569
+ * @param {string} field
3570
+ * @param {string} operator
3571
+ * @param {any} value
3572
+ * @param {boolean} [not]
3573
+ * @returns {Where}
3574
+ */
3575
+ /**
3576
+ * @overload
3577
+ * @param {string[]} field
3578
+ * @param {string} operator
3579
+ * @param {any[]} value
3580
+ * @param {boolean} [not]
3581
+ * @returns {Where}
3582
+ */
3583
+ /**
3584
+ * @overload
3585
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3586
+ * @returns {Where}
3587
+ */
3588
+ /**
3589
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3590
+ * @returns {Where}
3591
+ */
3592
+ static orNot(...items) {
3593
+ return new Where().#or(toNot(parse(items)));
3594
+ }
3595
+ }
3596
+
3597
+ /** @import { Fields, Options, Queryable, Select } from './types' */
3598
+ /** @import { WhereValue, Wheres } from './Where.mjs' */
3599
+ /**
3600
+ *
3601
+ * @param {number} [value]
3602
+ * @returns {number | undefined}
3603
+ */
3604
+ function getInt(value) {
3605
+ if (typeof value === 'number' && !isNaN(value) && isFinite(value) && value >= 1) {
3606
+ return Math.floor(value);
3607
+ }
3608
+ }
3609
+ /**
3610
+ * 选择字段
3611
+ * @param {string} fn
3612
+ * @param {Record<string, Select>} select
3613
+ * @param {(string | string[] | Record<string, string>)[]} newSelect
3614
+ */
3615
+ function selectFn(fn, select, newSelect) {
3616
+ for (let s of newSelect.flat()) {
3617
+ if (!s) {
3618
+ continue;
3619
+ }
3620
+ if (typeof s === 'string') {
3621
+ select[s] = {
3622
+ field: s,
3623
+ fn: 'sum'
3624
+ };
3625
+ continue;
3626
+ }
3627
+ if (typeof s !== 'object') {
3628
+ continue;
3629
+ }
3630
+ for (let [k, v] of Object.entries(s)) {
3631
+ if (!v) {
3632
+ delete select[k];
3633
+ } else if (typeof v === 'string') {
3634
+ select[k] = {
3635
+ field: v,
3636
+ fn
3637
+ };
3638
+ } else {
3639
+ select[k] = {
3640
+ field: k,
3641
+ fn
3642
+ };
3643
+ }
3644
+ }
3645
+ }
3646
+ return select;
3647
+ }
3648
+ /**
3649
+ * @template {Fields} T
3650
+ * @template {object} [TB=object]
3651
+ * @typedef {object} QueryOptions
3652
+ * @property {string} table
3653
+ * @property {T} fields
3654
+ * @property {string} [pseudo]
3655
+ * @property {((a: object, b?: object | boolean) => TB)?} [build]
3656
+ */
3657
+ /**
3658
+ * @template {Fields} T
3659
+ * @template {object} [TB=object]
3660
+ * @implements {Queryable<T>}
3661
+ */
3662
+ class Query {
3663
+ /**
3664
+ * @template {Fields} F
3665
+ * @template {new (o: QueryOptions<F>) => Query<F>} T
3666
+ * @this {T}
3667
+ * @param {string} table
3668
+ * @param {F} fields
3669
+ * @param {string} [pseudo]
3670
+ * @returns {InstanceType<T>}
3671
+ */
3672
+ static table(table, fields, pseudo) {
3673
+ const Q = /** @type {any} */this;
3674
+ return new Q({
3675
+ table,
3676
+ fields,
3677
+ pseudo
3678
+ });
3679
+ }
3680
+ /** @readonly @type {string} */
3681
+
3682
+ /** @readonly @type {T} */
3683
+
3684
+ /** @readonly @type {string} */
3685
+
3686
+ /** @type {((a: object, b?: object | boolean) => TB)?} */
3687
+ #build;
3688
+ /** @type {Options} */
3689
+ #options = {
3690
+ where: []
3691
+ };
3692
+ /** @type {string[]} 主键字段 */
3693
+ #primaryFields = [];
3694
+ get options() {
3695
+ return this.#options;
3696
+ }
3697
+ /**
3698
+ * @param {QueryOptions<T, TB> | Query<T, TB>} options
3699
+ */
3700
+ constructor(options) {
3701
+ if (options instanceof Query) {
3702
+ this.table = options.table;
3703
+ this.fields = options.fields;
3704
+ this.pseudo = options.pseudo;
3705
+ this.#build = options.#build;
3706
+ this.#options = {
3707
+ ...options.#options
3708
+ };
3709
+ this.#primaryFields = options.#primaryFields;
3710
+ this.#primary = options.#primary;
3711
+ } else {
3712
+ const {
3713
+ table,
3714
+ fields,
3715
+ pseudo,
3716
+ build
3717
+ } = options;
3718
+ this.table = table;
3719
+ this.fields = fields;
3720
+ this.pseudo = typeof pseudo === 'string' ? pseudo : '';
3721
+ this.#build = typeof build === 'function' ? build : null;
3722
+ this.#primaryFields = Object.entries(fields).filter(([, v]) => v.primary).sort(([, a], [, b]) => Number(a.primary) - Number(b.primary)).map(([v]) => v);
3723
+ if (typeof options[Build] === 'function') {
3724
+ this.#build = options[Build].bind(options);
3725
+ } else if (typeof build === 'function') {
3726
+ this.#build = build.bind(options);
3727
+ } else {
3728
+ this.#build = null;
3729
+ }
3730
+ }
3731
+ }
3732
+ /**
3733
+ * @param {QueryOptions<T, TB> | Query<T, TB>} options
3734
+ * @returns {Query<T, TB>}
3735
+ */
3736
+ _create(options) {
3737
+ return new Query(options);
3738
+ }
3739
+ /**
3740
+ * @returns {ReturnType<this['_create']>}
3741
+ */
3742
+ clone() {
3743
+ /** @type {ReturnType<this['_create']>} */
3744
+ // @ts-ignore
3745
+ const t = this._create(this);
3746
+ return t;
3747
+ }
3748
+ /** @returns {this} */
3749
+ deleted() {
3750
+ this.#options.range = deleted;
3751
+ return this;
3752
+ }
3753
+ /** @returns {this} */
3754
+ undeleted() {
3755
+ this.#options.range = undeleted;
3756
+ return this;
3757
+ }
3758
+ /** @returns {this} */
3759
+ withDeleted() {
3760
+ this.#options.range = withDeleted;
3761
+ return this;
3762
+ }
3763
+ /**
3764
+ * 增加排序项
3765
+ * @param {...string | boolean | [string, boolean?]} sort
3766
+ * @returns {this}
3767
+ */
3768
+ sort(...sort) {
3769
+ if (!sort.length) {
3770
+ this.#options.sort = [];
3771
+ return this;
3772
+ }
3773
+ /** @type {[string, boolean][]} */
3774
+ const list = [];
3775
+ for (let i = 0; i < sort.length; i++) {
3776
+ let value = sort[i];
3777
+ let desc = sort[i + 1] === true;
3778
+ if (Array.isArray(value)) {
3779
+ desc = value[1] === true;
3780
+ [value] = value;
3781
+ }
3782
+ if (typeof value !== 'string') {
3783
+ continue;
3784
+ }
3785
+ list.push([value, desc]);
3786
+ }
3787
+ if (list.length) {
3788
+ this.#options.sort = [...(this.#options.sort || []), ...list];
3789
+ }
3790
+ return this;
3791
+ }
3792
+ /**
3793
+ * 设置获取到的最大数量
3794
+ * @param {number} [limit]
3795
+ * @returns {this}
3796
+ */
3797
+ limit(limit) {
3798
+ this.#options.limit = getInt(limit);
3799
+ return this;
3800
+ }
3801
+ /**
3802
+ * 跳过的记录数
3803
+ * @param {number} [offset]
3804
+ * @returns {this}
3805
+ */
3806
+ offset(offset) {
3807
+ this.#options.offset = getInt(offset);
3808
+ return this;
3809
+ }
3810
+ /**
3811
+ * @overload
3812
+ * @param {Wheres} matches
3813
+ * @returns {this}
3814
+ */
3815
+ /**
3816
+ *
3817
+ * @overload
3818
+ * @param {TemplateStringsArray} where
3819
+ * @param {...any} values
3820
+ * @returns {this}
3821
+ */
3822
+ /**
3823
+ * @overload
3824
+ * @param {string} field
3825
+ * @param {any} value
3826
+ * @returns {this}
3827
+ */
3828
+ /**
3829
+ * @overload
3830
+ * @param {string[]} field
3831
+ * @param {any[]} value
3832
+ * @returns {this}
3833
+ */
3834
+ /**
3835
+ * @overload
3836
+ * @param {string} field
3837
+ * @param {string} operator
3838
+ * @param {any} value
3839
+ * @param {boolean} [not]
3840
+ * @returns {this}
3841
+ */
3842
+ /**
3843
+ * @overload
3844
+ * @param {string[]} field
3845
+ * @param {string} operator
3846
+ * @param {any[]} value
3847
+ * @param {boolean} [not]
3848
+ * @returns {this}
3849
+ */
3850
+ /**
3851
+ * @overload
3852
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3853
+ * @returns {this}
3854
+ */
3855
+ /**
3856
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
3857
+ * @returns {this}
3858
+ */
3859
+ where(...items) {
3860
+ const list = Where.parseParams(items);
3861
+ this.#options.where = [...this.#options.where, ...(list || [])];
3862
+ return this;
3863
+ }
3864
+ /**
3865
+ * 选择字段
3866
+ * @param {...string | string[] | Record<string, Select.Param>} newSelect
3867
+ * @returns {this}
3868
+ */
3869
+ select(...newSelect) {
3870
+ const select = {
3871
+ ...this.#options.select
3872
+ };
3873
+ for (let s of newSelect.flat()) {
3874
+ if (!s) {
3875
+ continue;
3876
+ }
3877
+ if (typeof s === 'string') {
3878
+ select[s] = {
3879
+ field: s
3880
+ };
3881
+ continue;
3882
+ }
3883
+ if (typeof s !== 'object') {
3884
+ continue;
3885
+ }
3886
+ for (let [k, v] of Object.entries(s)) {
3887
+ if (!v) {
3888
+ delete select[k];
3889
+ } else if (typeof v === 'string') {
3890
+ select[k] = {
3891
+ field: v
3892
+ };
3893
+ } else if (typeof v === 'object') {
3894
+ const {
3895
+ field,
3896
+ table,
3897
+ fn
3898
+ } = v;
3899
+ if (typeof field !== 'string') {
3900
+ continue;
3901
+ }
3902
+ select[k] = {
3903
+ field,
3904
+ table: typeof table === 'string' ? table : '',
3905
+ fn: typeof fn === 'string' ? fn : ''
3906
+ };
3907
+ } else {
3908
+ select[k] = {
3909
+ field: k
3910
+ };
3911
+ }
3912
+ }
3913
+ }
3914
+ this.#options.select = select;
3915
+ return this;
3916
+ }
3917
+ /**
3918
+ * 字段求和
3919
+ * @param {...string | string[] | Record<string, string>} newSelect
3920
+ * @returns {this}
3921
+ */
3922
+ sum(...newSelect) {
3923
+ const select = {
3924
+ ...this.#options.select
3925
+ };
3926
+ this.#options.select = selectFn('sum', select, newSelect);
3927
+ return this;
3928
+ }
3929
+ /**
3930
+ * 字段最小值
3931
+ * @param {...string | string[] | Record<string, string>} newSelect
3932
+ * @returns {this}
3933
+ */
3934
+ min(...newSelect) {
3935
+ const select = {
3936
+ ...this.#options.select
3937
+ };
3938
+ this.#options.select = selectFn('min', select, newSelect);
3939
+ return this;
3940
+ }
3941
+ /**
3942
+ * 字段最大值
3943
+ * @param {...string | string[] | Record<string, string>} newSelect
3944
+ * @returns {this}
3945
+ */
3946
+ max(...newSelect) {
3947
+ const select = {
3948
+ ...this.#options.select
3949
+ };
3950
+ this.#options.select = selectFn('max', select, newSelect);
3951
+ return this;
3952
+ }
3953
+ /**
3954
+ * 字段平均值
3955
+ * @param {...string | string[] | Record<string, string>} newSelect
3956
+ * @returns {this}
3957
+ */
3958
+ avg(...newSelect) {
3959
+ const select = {
3960
+ ...this.#options.select
3961
+ };
3962
+ this.#options.select = selectFn('max', select, newSelect);
3963
+ return this;
3964
+ }
3965
+ /**
3966
+ * 字段计数
3967
+ * @param {...string | string[] | Record<string, string>} newSelect
3968
+ * @returns {this}
3969
+ */
3970
+ count(...newSelect) {
3971
+ const select = {
3972
+ ...this.#options.select
3973
+ };
3974
+ this.#options.select = selectFn('max', select, newSelect);
3975
+ return this;
3976
+ }
3977
+ /**
3978
+ *
3979
+ * @param {Record<string, any>} update
3980
+ * @returns {this}
3981
+ */
3982
+ set(update) {
3983
+ this.#options.update = {
3984
+ ...this.#options.update,
3985
+ ...update
3986
+ };
3987
+ return this;
3988
+ }
3989
+ /**
3990
+ *
3991
+ * @param {string} alias
3992
+ * @returns
3993
+ */
3994
+ as(alias) {
3995
+ const t = this.clone();
3996
+ t.#options.alias = alias;
3997
+ return t;
3998
+ }
3999
+ /**
4000
+ *
4001
+ * @param {object} a
4002
+ * @param {object | boolean | null} [b]
4003
+ * @returns {TB}
4004
+ */
4005
+ [Build](a, b) {
4006
+ const build = this.#build;
4007
+ if (typeof build === 'function') {
4008
+ return build(a, b);
4009
+ }
4010
+ if (b && typeof b === 'object') {
4011
+ return {
4012
+ ...a,
4013
+ ...b
4014
+ };
4015
+ }
4016
+ return {
4017
+ ...a
4018
+ };
4019
+ }
4020
+ /**
4021
+ *
4022
+ * @param {string} [text]
4023
+ * @returns {this}
4024
+ */
4025
+ contains(text) {
4026
+ if (!text) {
4027
+ return this;
4028
+ }
4029
+ const fields = [];
4030
+ for (const [name, {
4031
+ text,
4032
+ type,
4033
+ array
4034
+ }] of Object.entries(this.fields)) {
4035
+ if (!text || array) {
4036
+ continue;
4037
+ }
4038
+ if (type !== 'text') {
4039
+ continue;
4040
+ }
4041
+ fields.push(name);
4042
+ }
4043
+ if (!fields) {
4044
+ return this;
4045
+ }
4046
+ /** @type {WhereValue[]} */
4047
+ const matches = fields.map(v => ({
4048
+ field: v,
4049
+ operator: 'contains',
4050
+ value: text
4051
+ }));
4052
+ this.#options.where = [...this.#options.where, ...matches];
4053
+ return this;
4054
+ }
4055
+ /** @type {string | number | bigint | object | undefined} */
4056
+ #primary;
4057
+ /**
4058
+ * @param {any} [primary]
4059
+ * @returns {this}
4060
+ */
4061
+ primary(primary) {
4062
+ if (this.#primary) {
4063
+ return this;
4064
+ }
4065
+ if (!primary) {
4066
+ return this;
4067
+ }
4068
+ const primaryFields = this.#primaryFields;
4069
+ if (!primaryFields.length) {
4070
+ return this;
4071
+ }
4072
+ if (primaryFields.length === 1) {
4073
+ const [field] = primaryFields;
4074
+ const m = this.where(field, '=', primary);
4075
+ m.#primary = primary;
4076
+ return m;
4077
+ }
4078
+ if (typeof primary === 'object') {
4079
+ let m = this;
4080
+ for (const p of primaryFields) {
4081
+ m = m.where(p, '=', primary[p]);
4082
+ }
4083
+ m.#primary = primary;
4084
+ return m;
4085
+ }
4086
+ const values = `${primary}`.split('$');
4087
+ if (values.length !== primaryFields.length) ;
4088
+ let m = this;
4089
+ for (let i = 0; i < primaryFields.length; i++) {
4090
+ m = m.where(primaryFields[i], '=', values[i]);
4091
+ }
4092
+ m.#primary = primary;
4093
+ return m;
4094
+ }
4095
+ }
4096
+
4097
+ /* eslint-disable max-lines */
4098
+ /** @import { Fields, IndexInfo, FieldDefine } from './types' */
4099
+ /**
4100
+ * @param {any} a
4101
+ * @param {any} b
4102
+ */
4103
+ function eq(a, b) {
4104
+ if (a === b) {
4105
+ return true;
4106
+ }
4107
+ if (!Array.isArray(a) || !Array.isArray(b)) {
4108
+ return false;
4109
+ }
4110
+ if (a.length !== b.length) {
4111
+ return;
4112
+ }
4113
+ const {
4114
+ length
4115
+ } = a;
4116
+ for (let i = 0; i < length; i++) {
4117
+ if (a[i] !== b[i]) {
4118
+ return false;
4119
+ }
4120
+ }
4121
+ return true;
4122
+ }
4123
+ /** @typedef {PromiseLike<void> | void} VoidReturn */
4124
+ const timeRegex = /^(?: *|T?)(\d+)(?::(\d+)(?::(\d+(?:.\d*)?))?)? *$/;
4125
+ /**
4126
+ * @param {string} type
4127
+ * @param {any} value
4128
+ */
4129
+ function getBaseValue(type, value) {
4130
+ // TODO: 类型完善
4131
+ switch (type) {
4132
+ case 'i8':
4133
+ case 'i16':
4134
+ case 'i32':
4135
+ case 'i52':
4136
+ case 'u8':
4137
+ case 'u16':
4138
+ case 'u32':
4139
+ case 'u52':
4140
+ {
4141
+ let v = value;
4142
+ if (typeof v === 'string') {
4143
+ v = parseInt(v, 10);
4144
+ } else if (typeof v === 'bigint' || typeof v === 'boolean') {
4145
+ v = Number(v);
4146
+ } else if (typeof v !== 'number') {
4147
+ return;
4148
+ }
4149
+ v = Math.floor(v);
4150
+ if (Number.isNaN(v)) {
4151
+ return;
4152
+ }
4153
+ return v;
4154
+ }
4155
+ case 'i64':
4156
+ case 'u64':
4157
+ {
4158
+ let v = value;
4159
+ if (typeof v === 'string') {
4160
+ const r = /^(-?\d+)/.exec(v);
4161
+ if (!r) {
4162
+ return;
4163
+ }
4164
+ v = BigInt(r[1]);
4165
+ } else if (typeof v === 'boolean') {
4166
+ v = BigInt(v);
4167
+ } else if (typeof v === 'number') {
4168
+ if (Number.isNaN(v)) {
4169
+ return;
4170
+ }
4171
+ v = BigInt(Math.floor(v));
4172
+ } else if (typeof v !== 'bigint') {
4173
+ return;
4174
+ }
4175
+ return v;
4176
+ }
4177
+ case 'id':
4178
+ {
4179
+ let v = value;
4180
+ if (typeof v === 'string') {
4181
+ const r = /^(-?\d+)/.exec(v);
4182
+ if (!r) {
4183
+ return;
4184
+ }
4185
+ v = BigInt(r[1]);
4186
+ } else if (typeof v === 'boolean') {
4187
+ v = BigInt(v);
4188
+ } else if (typeof v === 'number') {
4189
+ if (Number.isNaN(v)) {
4190
+ return;
4191
+ }
4192
+ v = BigInt(Math.floor(v));
4193
+ } else if (typeof v !== 'bigint') {
4194
+ return;
4195
+ }
4196
+ return v;
4197
+ }
4198
+ case 'f32':
4199
+ case 'f64':
4200
+ case 'decimal':
4201
+ case 'numeric':
4202
+ case 'money':
4203
+ {
4204
+ let v = value;
4205
+ if (typeof v === 'string') {
4206
+ v = parseFloat(v);
4207
+ } else if (typeof v === 'bigint' || typeof v === 'boolean') {
4208
+ v = Number(v);
4209
+ } else if (typeof v !== 'number') {
4210
+ return;
4211
+ }
4212
+ if (Number.isNaN(v)) {
4213
+ return;
4214
+ }
4215
+ return v;
4216
+ }
4217
+ case 'date':
4218
+ case 'datetime':
4219
+ case 'timestamp':
4220
+ {
4221
+ let v = value;
4222
+ if (typeof v === 'string') {
4223
+ v = new Date(Date.parse(v));
4224
+ } else if (typeof v === 'bigint' || typeof v === 'number') {
4225
+ v = new Date(Number(v));
4226
+ } else if (!(v instanceof Date)) {
4227
+ return;
4228
+ }
4229
+ if (Number.isNaN(Number(v))) {
4230
+ return;
4231
+ }
4232
+ return v;
4233
+ }
4234
+ case 'time':
4235
+ case 'timetz':
4236
+ {
4237
+ let v = value;
4238
+ if (typeof v === 'string') {
4239
+ const r = timeRegex.exec(v);
4240
+ if (!r) {
4241
+ return;
4242
+ }
4243
+ const t = new Date();
4244
+ t.setHours(parseFloat(r[1]), Number(r[2]) || 0, parseFloat(r[3]) || 0);
4245
+ return t;
4246
+ } else if (typeof v === 'bigint' || typeof v === 'number') {
4247
+ v = new Date(Number(v));
4248
+ } else if (!(v instanceof Date)) {
4249
+ return;
4250
+ }
4251
+ if (Number.isNaN(Number(v))) {
4252
+ return;
4253
+ }
4254
+ return v;
4255
+ }
4256
+ }
4257
+ return value;
4258
+ }
4259
+ /**
4260
+ * @param {string} type
4261
+ * @param {boolean} array
4262
+ * @param {any} [value]
4263
+ * @param {boolean} [isSet]
4264
+ */
4265
+ function getBaseTypeValue(type, array, value, isSet) {
4266
+ if (array) {
4267
+ // TODO: 是否允许空
4268
+ return [value].flatMap(v => getBaseValue(type, v)).filter(v => v !== undefined);
4269
+ }
4270
+ const val = getBaseValue(type, value);
4271
+ // TODO: 是否允许空
4272
+ if (typeof val !== undefined) {
4273
+ return val;
4274
+ }
4275
+ if (isSet) {
4276
+ return val;
4277
+ }
4278
+ // TODO: 默认值
4279
+ return value;
4280
+ }
4281
+ /**
4282
+ * @param {FieldDefine} field
4283
+ * @param {any} value
4284
+ */
4285
+ function getInitValue(field, value) {
4286
+ const {
4287
+ type
4288
+ } = field;
4289
+ if (typeof type === 'string') {
4290
+ return getBaseTypeValue(type, field.array, value, true);
4291
+ }
4292
+ if (!type.table) {
4293
+ return getBaseTypeValue('object', field.array, value, true);
4294
+ }
4295
+ const {
4296
+ constraints
4297
+ } = field;
4298
+ const values = [value].flat().filter(Boolean);
4299
+ if (!values.length) {
4300
+ return [];
4301
+ }
4302
+ const constraintEntries = Object.entries(constraints || {});
4303
+ const noField = constraintEntries.find(([k, v]) => v.noField)?.[0];
4304
+ const keys = new Set(constraintEntries.filter(([k, v]) => v.field || v.value !== undefined).map(([k]) => k));
4305
+ const {
4306
+ fields
4307
+ } = type;
4308
+ if (noField) {
4309
+ keys.add(noField);
4310
+ }
4311
+ return values.map(data => {
4312
+ const doc = {};
4313
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
4314
+ const values = data instanceof Model ? data.$savedData : data;
4315
+ for (const [key, field] of Object.entries(fields)) {
4316
+ if (keys.has(key)) {
4317
+ continue;
4318
+ }
4319
+ const {
4320
+ type
4321
+ } = field;
4322
+ if (typeof type === 'string') {
4323
+ doc[key] = getBaseTypeValue(type, field.array, values[key]);
4324
+ } else if (!type.table) {
4325
+ doc[key] = getBaseTypeValue('object', field.array, values[key]);
4326
+ }
4327
+ }
4328
+ return doc;
4329
+ });
4330
+ }
4331
+ /**
4332
+ * @param {FieldDefine} field
4333
+ * @param {any} value
4334
+ * @param {boolean} [immutable]
4335
+ */
4336
+ function getSetValue(field, value, immutable) {
4337
+ if (immutable && field.immutable) {
4338
+ return;
4339
+ }
4340
+ const {
4341
+ type
4342
+ } = field;
4343
+ if (typeof type === 'string') {
4344
+ if (immutable && field.primary) {
4345
+ return;
4346
+ }
4347
+ return getBaseTypeValue(type, field.array, value, true);
4348
+ }
4349
+ if (!type.table) {
4350
+ return getBaseTypeValue('object', field.array, value, true);
4351
+ }
4352
+ const values = [value].flat().filter(Boolean);
4353
+ if (!values.length) {
4354
+ return [];
4355
+ }
4356
+ const constraintEntries = Object.entries(field.constraints || {});
4357
+ const noField = constraintEntries.find(([k, v]) => v.noField)?.[0];
4358
+ const {
4359
+ fields
4360
+ } = type;
4361
+ const keys = new Set(constraintEntries.filter(([k, v]) => v.field || v.value !== undefined).map(([k]) => k));
4362
+ if (noField) {
4363
+ keys.add(noField);
4364
+ }
4365
+ return values.map(data => {
4366
+ const doc = {};
4367
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
4368
+ const values = data instanceof Model ? data.$savedData : data;
4369
+ for (const [key, field] of Object.entries(fields)) {
4370
+ if (keys.has(key)) {
4371
+ continue;
4372
+ }
4373
+ let value = values[key];
4374
+ if (value === undefined) {
4375
+ continue;
4376
+ }
4377
+ const {
4378
+ type
4379
+ } = field;
4380
+ if (typeof type === 'string') {
4381
+ if (typeof type !== 'string') {
4382
+ continue;
4383
+ }
4384
+ value = getBaseTypeValue(type, field.array, value);
4385
+ if (value === undefined) {
4386
+ continue;
4387
+ }
4388
+ doc[key] = value;
4389
+ } else if (!type.table) {
4390
+ if (typeof type !== 'string') {
4391
+ continue;
4392
+ }
4393
+ // TODO:
4394
+ value = getBaseTypeValue('object', field.array, value);
4395
+ if (value === undefined) {
4396
+ continue;
4397
+ }
4398
+ doc[key] = value;
4399
+ }
4400
+ }
4401
+ return doc;
4402
+ });
4403
+ }
4404
+ /**
4405
+ * @implements {Save}
4406
+ * @implements {Destroy}
4407
+ * @implements {PseudoDestroy}
4408
+ */
4409
+ class Model {
4410
+ /** @readonly @type {string | undefined} */
4411
+
4412
+ /** @readonly @type {string} */
4413
+ static table = '';
4414
+ /** @readonly @type {Fields} */
4415
+ static fields = {};
4416
+ /** @readonly @type {readonly IndexInfo[]} */
4417
+ static indexes = [];
4418
+ /**
4419
+ * @template {typeof Model} T
4420
+ * @this {T}
4421
+ * @returns {Query<T['fields'], InstanceType<T>>}
4422
+ */
4423
+ static toQuery() {
4424
+ // @ts-ignore
4425
+ return new Query(this);
4426
+ }
4427
+ /**
4428
+ * @template {typeof Model} T
4429
+ * @this {T}
4430
+ * @param {string[]} [fields]
4431
+ * @returns {T}
4432
+ */
4433
+ static bindFields(fields = Object.keys(this.fields)) {
4434
+ const {
4435
+ prototype
4436
+ } = this;
4437
+ /** @type {string[]} */
4438
+ const list = Array.isArray(fields) ? fields : Object.keys(fields);
4439
+ for (const key of list) {
4440
+ if (!key || typeof key === 'string' && key[0] === '$') {
4441
+ continue;
4442
+ }
4443
+ if (key in prototype) {
4444
+ continue;
4445
+ }
4446
+ Object.defineProperty(prototype, key, {
4447
+ get() {
4448
+ return this.$get(key);
4449
+ },
4450
+ set(value) {
4451
+ this.$set(key, value);
4452
+ },
4453
+ configurable: true,
4454
+ enumerable: true
4455
+ });
4456
+ }
4457
+ return this;
4458
+ }
4459
+ /**
4460
+ * @template {typeof Model} T
4461
+ * @this {T}
4462
+ * @param {Connection} t
4463
+ * @param {object} p
4464
+ * @param {(data: object) => Promise<object>} run
4465
+ * @returns {Promise<InstanceType<T>>}
4466
+ */
4467
+ static async [Create](t, p, run) {
4468
+ const Mod = this;
4469
+ /** @type {InstanceType<T>} */
4470
+ // @ts-ignore
4471
+ const doc = new Mod(p);
4472
+ return doc.#do(() => doc.$_onBeforeSave(t, false), () => run({
4473
+ ...doc.#data,
4474
+ ...doc.#newData
4475
+ }), () => doc.$_onAfterSave(t, false)).then(() => doc);
4476
+ }
4477
+ /**
4478
+ * @template {typeof Model} T
4479
+ * @this {T}
4480
+ * @param {object} a
4481
+ * @param {object | boolean} [b]
4482
+ * @returns {InstanceType<T>}
4483
+ */
4484
+ static [Build](a, b) {
4485
+ const Mod = this;
4486
+ /** @type {InstanceType<T>} */
4487
+ // @ts-ignore
4488
+ const doc = new Mod(a, b);
4489
+ return doc;
4490
+ }
4491
+ /** @type {typeof Model} */
4492
+ #model;
4493
+ /** @type {Record<string, any>} */
4494
+ #data = {};
4495
+ /** @type {Record<string, any>} */
4496
+ #newData = {};
4497
+ #saved = false;
4498
+ #deleted = false;
4499
+ #executing = false;
4500
+ /** @type {Record<string, any> | undefined} */
4501
+ #oldData;
4502
+ get $model() {
4503
+ return this.#model;
4504
+ }
4505
+ get $saved() {
4506
+ return this.#saved;
4507
+ }
4508
+ get $deleted() {
4509
+ return this.#deleted;
4510
+ }
4511
+ get $oldData() {
4512
+ return this.#oldData;
4513
+ }
4514
+ get $savedData() {
4515
+ return {
4516
+ ...this.#data
4517
+ };
4518
+ }
4519
+ get $changedData() {
4520
+ return {
4521
+ ...this.#newData
4522
+ };
4523
+ }
4524
+ /**
4525
+ * @param {object} data
4526
+ * @param {boolean | object} [saved]
4527
+ */
4528
+ constructor(data, saved = false) {
4529
+ const model = new.target;
4530
+ this.#model = model;
4531
+ const {
4532
+ fields
4533
+ } = model;
4534
+ const values = {};
4535
+ for (const [key, field] of Object.entries(fields)) {
4536
+ const {
4537
+ type
4538
+ } = field;
4539
+ // eslint-disable-next-line no-nested-ternary
4540
+ values[key] = typeof type === 'string' ? getBaseTypeValue(type, field.array)
4541
+ // eslint-disable-next-line no-nested-ternary
4542
+ : !type.table ? getBaseTypeValue('object', field.array) : field.array ? [] : null;
4543
+ }
4544
+ if (!saved) {
4545
+ this.#data = values;
4546
+ this.#saved = false;
4547
+ this.#setAll(data);
4548
+ return;
4549
+ }
4550
+ for (const [key, value] of Object.entries(data)) {
4551
+ const field = key in fields && fields[key];
4552
+ const val = field ? getInitValue(field, value) : value;
4553
+ if (val === undefined) {
4554
+ continue;
4555
+ }
4556
+ values[key] = val;
4557
+ }
4558
+ this.#data = values;
4559
+ this.#oldData = data;
4560
+ this.#saved = true;
4561
+ if (typeof saved !== 'object') {
4562
+ return;
4563
+ }
4564
+ this.#setAll(saved);
4565
+ }
4566
+ $clone() {
4567
+ const Model = this.#model;
4568
+ const saved = this.$saved;
4569
+ if (!saved) {
4570
+ return new Model({
4571
+ ...this.#newData
4572
+ });
4573
+ }
4574
+ return new Model({
4575
+ ...this.#data
4576
+ }, {
4577
+ ...this.#newData
4578
+ });
4579
+ }
4580
+ toJSON() {
4581
+ return {
4582
+ ...this.#data,
4583
+ ...this.#newData
4584
+ };
4585
+ }
4586
+ get $fieldChanged() {
4587
+ const changed = new Set(Object.getOwnPropertyNames(this.#newData));
4588
+ if (!changed.size) {
4589
+ return false;
4590
+ }
4591
+ const fields = Object.getOwnPropertyNames(this.#model.fields);
4592
+ return fields.findIndex(f => changed.has(f)) >= 0;
4593
+ }
4594
+ /**
4595
+ * @param {Record<string, any>} values
4596
+ */
4597
+ #setAll(values) {
4598
+ const data = this.#data;
4599
+ const newData = this.#newData;
4600
+ const model = this.#model;
4601
+ const {
4602
+ fields
4603
+ } = model;
4604
+ const isSaved = this.#saved;
4605
+ for (const [key, value] of Object.entries(values)) {
4606
+ const field = key in fields && fields[key];
4607
+ const val = field ? getSetValue(field, value, isSaved) : value;
4608
+ if (val === undefined) {
4609
+ continue;
4610
+ }
4611
+ if (eq(data[key], val)) {
4612
+ delete newData[key];
4613
+ } else {
4614
+ newData[key] = val;
4615
+ }
4616
+ }
4617
+ }
4618
+ /**
4619
+ * @param {string} key
4620
+ * @param {any} value
4621
+ */
4622
+ #set(key, value) {
4623
+ const model = this.#model;
4624
+ const {
4625
+ fields
4626
+ } = model;
4627
+ const field = key in fields && fields[key];
4628
+ const val = field ? getSetValue(field, value, this.#saved) : value;
4629
+ if (val === undefined) {
4630
+ return;
4631
+ }
4632
+ if (eq(this.#data[key], val)) {
4633
+ delete this.#newData[key];
4634
+ } else {
4635
+ this.#newData[key] = val;
4636
+ }
4637
+ }
4638
+ /**
4639
+ * @overload
4640
+ * @param {Record<string, any>} key
4641
+ * @param {any} [value]
4642
+ * @returns {boolean}
4643
+ */
4644
+ /**
4645
+ * @overload
4646
+ * @param {string} key
4647
+ * @param {any} value
4648
+ * @returns {boolean}
4649
+ */
4650
+ /**
4651
+ * @param {string | Record<string, any>} key
4652
+ * @param {any} [value]
4653
+ * @returns {boolean}
4654
+ */
4655
+ $set(key, value) {
4656
+ if (!key) {
4657
+ return false;
4658
+ }
4659
+ if (this.#executing) {
4660
+ return false;
4661
+ }
4662
+ this.#executing = true;
4663
+ try {
4664
+ if (typeof key !== 'object') {
4665
+ this.#set(key, value);
4666
+ return true;
4667
+ }
4668
+ this.#setAll(key);
4669
+ return true;
4670
+ } finally {
4671
+ this.#executing = false;
4672
+ }
4673
+ }
4674
+ /**
4675
+ * @template {Record<string, any>} T
4676
+ * @overload
4677
+ * @param {string} [key]
4678
+ * @param {boolean} [saved]
4679
+ * @returns {T}
4680
+ */
4681
+ /**
4682
+ * @template T
4683
+ * @overload
4684
+ * @param {string} key
4685
+ * @param {boolean} [saved]
4686
+ * @returns {T | undefined}
4687
+ */
4688
+ /**
4689
+ * @template T
4690
+ * @param {string} [key]
4691
+ * @param {boolean} [saved]
4692
+ * @returns {any}
4693
+ */
4694
+ $get(key, saved) {
4695
+ if (!key) {
4696
+ return {
4697
+ ...this.#data,
4698
+ ...this.#newData
4699
+ };
4700
+ }
4701
+ if (!saved && key in this.#newData) {
4702
+ return this.#newData[key];
4703
+ }
4704
+ if (saved !== false) {
4705
+ return this.#data[key];
4706
+ }
4707
+ }
4708
+ /**
4709
+ * @param {(this: this)=> PromiseLike<boolean> | boolean} q
4710
+ * @returns {PromiseLike<boolean> | boolean}
4711
+ */
4712
+ $exec(q) {
4713
+ if (this.#executing) {
4714
+ return false;
4715
+ }
4716
+ this.#executing = true;
4717
+ return (async () => {
4718
+ try {
4719
+ return await q.call(this);
4720
+ } finally {
4721
+ this.#executing = false;
4722
+ }
4723
+ })();
4724
+ }
4725
+ /**
4726
+ * @param {Connection} t
4727
+ * @param {boolean} update
4728
+ * @returns {VoidReturn}
4729
+ */
4730
+ $onBeforeSave(t, update) {}
4731
+ /**
4732
+ * @param {Connection} t
4733
+ * @param {boolean} update
4734
+ * @returns {VoidReturn}
4735
+ */
4736
+ $onAfterSave(t, update) {}
4737
+ /**
4738
+ * @param {Connection} t
4739
+ * @param {boolean} update
4740
+ * @returns {VoidReturn}
4741
+ */
4742
+ $_onBeforeSave(t, update) {
4743
+ return this.$onBeforeSave(t, update);
4744
+ }
4745
+ /**
4746
+ * @param {Connection} t
4747
+ * @param {boolean} update
4748
+ * @returns {VoidReturn}
4749
+ */
4750
+ $_onAfterSave(t, update) {
4751
+ return this.$onAfterSave(t, update);
4752
+ }
4753
+ /**
4754
+ * @param {Connection} t
4755
+ * @param {object?} update
4756
+ * @returns {VoidReturn}
4757
+ */
4758
+ $onBeforeDelete(t, update) {}
4759
+ /**
4760
+ * @param {Connection} t
4761
+ * @param {object?} update
4762
+ * @returns {VoidReturn}
4763
+ */
4764
+ $onAfterDelete(t, update) {}
4765
+ /**
4766
+ * @param {Connection} t
4767
+ * @param {object?} update
4768
+ * @returns {VoidReturn}
4769
+ */
4770
+ $_onBeforeDelete(t, update) {
4771
+ return this.$onBeforeDelete(t, update);
4772
+ }
4773
+ /**
4774
+ * @param {Connection} t
4775
+ * @param {object?} update
4776
+ * @returns {VoidReturn}
4777
+ */
4778
+ $_onAfterDelete(t, update) {
4779
+ return this.$onAfterDelete(t, update);
4780
+ }
4781
+ #running = false;
4782
+ /**
4783
+ * @param {() => any} before
4784
+ * @param {() => Promise<object?>} q
4785
+ * @param {() => any} after
4786
+ * @returns {Promise<this?>}
4787
+ */
4788
+ async #do(before, q, after) {
4789
+ if (this.#running) {
4790
+ return null;
4791
+ }
4792
+ this.#running = true;
4793
+ try {
4794
+ await before();
4795
+ const r = await this.$exec(() => q().then(v => this.#update(v)));
4796
+ if (!r) {
4797
+ return null;
4798
+ }
4799
+ await after();
4800
+ return this;
4801
+ } finally {
4802
+ this.#running = false;
4803
+ }
4804
+ }
4805
+ /**
4806
+ * @param {any} [values]
4807
+ * @returns {boolean}
4808
+ */
4809
+ #update(values) {
4810
+ if (this.#deleted) {
4811
+ return false;
4812
+ }
4813
+ if (!values) {
4814
+ return false;
4815
+ }
4816
+ const oldData = this.#data;
4817
+ this.#oldData = oldData;
4818
+ this.#data = {
4819
+ ...oldData,
4820
+ ...values
4821
+ };
4822
+ const {
4823
+ fields
4824
+ } = this.#model;
4825
+ this.#newData = Object.fromEntries(Object.entries(this.#newData).filter(([k]) => !(k in fields)));
4826
+ this.#saved = true;
4827
+ return true;
4828
+ }
4829
+ /**
4830
+ * @param {Connection} t
4831
+ * @param {(data: any, newData?: any) => Promise<object?>} run
4832
+ * @returns {Promise<this?>}
4833
+ */
4834
+ async [Save](t, run) {
4835
+ const update = this.#saved;
4836
+ return this.#do(() => this.$_onBeforeSave(t, update), () => update ? run(this.#data, this.#newData) : run({
4837
+ ...this.#data,
4838
+ ...this.#newData
4839
+ }), () => this.$_onAfterSave(t, update));
4840
+ }
4841
+ /**
4842
+ * @param {Connection} t
4843
+ * @param {(data: any) => Promise<object?>} run
4844
+ * @returns {Promise<this?>}
4845
+ */
4846
+ async [Destroy](t, run) {
4847
+ if (this.#deleted) {
4848
+ return null;
4849
+ }
4850
+ return this.#do(() => this.$_onBeforeDelete(t, null), () => run(this.#data).then(v => {
4851
+ this.#deleted = Boolean(v);
4852
+ return v;
4853
+ }), () => this.$_onAfterDelete(t, null));
4854
+ }
4855
+ /**
4856
+ * @param {Connection} t
4857
+ * @param {object} update
4858
+ * @param {(data: any) => Promise<object?>} run
4859
+ * @returns {Promise<this?>}
4860
+ */
4861
+ async [PseudoDestroy](t, update, run) {
4862
+ if (this.#deleted) {
4863
+ return null;
4864
+ }
4865
+ return this.#do(() => this.$_onBeforeDelete(t, update), () => run(this.#data), () => this.$_onAfterDelete(t, update));
4866
+ }
4867
+ }
4868
+ /**
4869
+ * @param {string} key
4870
+ * @param {(this: typeof Model) => any} get
4871
+ * @returns {void}
4872
+ */
4873
+ function defGetter$1(key, get) {
4874
+ Object.defineProperty(Model, key, {
4875
+ get,
4876
+ enumerable: true,
4877
+ configurable: true
4878
+ });
4879
+ }
4880
+ defGetter$1('table', function () {
4881
+ return this.name;
4882
+ });
4883
+ defGetter$1('fields', function () {
4884
+ return [];
4885
+ });
4886
+ defGetter$1('indexes', function () {
4887
+ return [];
4888
+ });
4889
+
4890
+ /** @import { FieldDefine, FieldType, IndexInfo } from './types' */
4891
+ class Submodel {
4892
+ #type = Submodel;
4893
+ /** @readonly @type {string} */
4894
+ static table = '';
4895
+ /** @readonly @type {Record<string, FieldDefine<keyof FieldType>>} */
4896
+ static fields = {};
4897
+ /** @readonly @type {readonly IndexInfo[]} */
4898
+ static indexes = [];
4899
+ }
4900
+ /**
4901
+ * @param {string} key
4902
+ * @param {(this: typeof Submodel) => any} get
4903
+ * @returns {void}
4904
+ */
4905
+ function defGetter(key, get) {
4906
+ Object.defineProperty(Submodel, key, {
4907
+ get,
4908
+ enumerable: true,
4909
+ configurable: true
4910
+ });
4911
+ }
4912
+ defGetter('table', function () {
4913
+ return this.name;
4914
+ });
4915
+ defGetter('fields', function () {
4916
+ return [];
4917
+ });
4918
+ defGetter('indexes', function () {
4919
+ return [];
4920
+ });
4921
+
4922
+ /** @import { FieldDefine, FieldDefineOption, MainFieldType, ToType } from './types' */
4923
+ /**
4924
+ * @template {MainFieldType} T
4925
+ * @overload
4926
+ * @param {T} type
4927
+ * @param {{
4928
+ * nullable?: false;
4929
+ * array?: false;
4930
+ * default?: ToType<T, false, false>;
4931
+ * } & FieldDefineOption} [options]
4932
+ * @returns {FieldDefine<T, false, false>}
4933
+ */
4934
+ /**
4935
+ * @template {MainFieldType} T
4936
+ * @overload
4937
+ * @param {T} type
4938
+ * @param {{
4939
+ * nullable?: false;
4940
+ * array: true;
4941
+ * default?: ToType<T, true, false>;
4942
+ * } & FieldDefineOption} options
4943
+ * @returns {FieldDefine<T, true, false>}
4944
+ */
4945
+ /**
4946
+ * @template {MainFieldType} T
4947
+ * @overload
4948
+ * @param {T} type
4949
+ * @param {{
4950
+ * nullable: true;
4951
+ * array?: false;
4952
+ * default?: ToType<T, false, true>;
4953
+ * } & FieldDefineOption} options
4954
+ * @returns {FieldDefine<T, false, true>}
4955
+ */
4956
+ /**
4957
+ * @template {MainFieldType} T
4958
+ * @overload
4959
+ * @param {T} type
4960
+ * @param {{
4961
+ * nullable: true;
4962
+ * array: true;
4963
+ * default?: ToType<T, true, true>;
4964
+ * } & FieldDefineOption} options
4965
+ * @returns {FieldDefine<T, true, true>}
4966
+ */
4967
+ /**
4968
+ * @template {MainFieldType} T
4969
+ * @template {boolean} A
4970
+ * @overload
4971
+ * @param {T} type
4972
+ * @param {{
4973
+ * nullable: true;
4974
+ * array: A;
4975
+ * default?: ToType<T, A, true>;
4976
+ * } & FieldDefineOption} options
4977
+ * @returns {FieldDefine<T, A, true>}
4978
+ */
4979
+ /**
4980
+ * @template {MainFieldType} T
4981
+ * @template {boolean} A
4982
+ * @overload
4983
+ * @param {T} type
4984
+ * @param {{
4985
+ * nullable?: false;
4986
+ * array: A;
4987
+ * default?: ToType<T, A, false>;
4988
+ * } & FieldDefineOption} options
4989
+ * @returns {FieldDefine<T, A, false>}
4990
+ */
4991
+ /**
4992
+ * @template {MainFieldType} T
4993
+ * @template {boolean} N
4994
+ * @overload
4995
+ * @param {T} type
4996
+ * @param {{
4997
+ * nullable: N;
4998
+ * array?: false;
4999
+ * default?: ToType<T, false, N>;
5000
+ * } & FieldDefineOption} options
5001
+ * @returns {FieldDefine<T, false, N>}
5002
+ */
5003
+ /**
5004
+ * @template {MainFieldType} T
5005
+ * @template {boolean} N
5006
+ * @overload
5007
+ * @param {T} type
5008
+ * @param {{
5009
+ * nullable: N;
5010
+ * array: true;
5011
+ * default?: ToType<T, true, N>;
5012
+ * } & FieldDefineOption} options
5013
+ * @returns {FieldDefine<T, true, N>}
5014
+ */
5015
+ /**
5016
+ * @template {MainFieldType} T
5017
+ * @template {boolean} A
5018
+ * @template {boolean} N
5019
+ * @overload
5020
+ * @param {T} type
5021
+ * @param {{
5022
+ * nullable: N;
5023
+ * array: A;
5024
+ * default?: ToType<T, A, N>;
5025
+ * } & FieldDefineOption} options
5026
+ * @returns {FieldDefine<T, A, N>}
5027
+ */
5028
+ /**
5029
+ * @template {MainFieldType} T
5030
+ * @overload
5031
+ * @param {T} type
5032
+ * @param {{
5033
+ * nullable?: boolean;
5034
+ * array?: boolean;
5035
+ * default?: ToType<T, boolean, boolean>;
5036
+ * } & FieldDefineOption} options
5037
+ * @returns {FieldDefine<T, boolean, boolean>}
5038
+ */
5039
+ /**
5040
+ * @template {MainFieldType} T
5041
+ * @param {T} type
5042
+ * @param {{ nullable?: boolean; array?: boolean; default?: any; } & FieldDefineOption} options
5043
+ * @returns {FieldDefine<T, boolean, boolean>}
5044
+ */
5045
+ function field(type, {
5046
+ array,
5047
+ nullable,
5048
+ default: def,
5049
+ index,
5050
+ primary,
5051
+ serial,
5052
+ immutable,
5053
+ text,
5054
+ sort,
5055
+ ...p
5056
+ } = {}) {
5057
+ return {
5058
+ ...p,
5059
+ type,
5060
+ array: Boolean(array),
5061
+ nullable: Boolean(nullable),
5062
+ default: def,
5063
+ index,
5064
+ primary,
5065
+ serial,
5066
+ immutable,
5067
+ text,
5068
+ sort
5069
+ };
5070
+ }
5071
+
5072
+ export { Build, Connection, Create, Destroy, Model, PseudoDestroy, Query, Save, Submodel, Where, creating, decrement, field as define, deleted, deleting, divide, field$1 as field, getPrimaryKeys, id, immutable, increment, index, isDevelopment, isPseudo, submodel as model, multiply, now, primary, prop, pseudo, setDevelopment, sort, submodel, toNot, undeleted, updating, values, withDeleted };