imodel 0.18.0 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * imodel v0.18.0
2
+ * imodel v0.19.1
3
3
  * (c) 2019-2026 undefined
4
4
  * @license undefined
5
5
  */
@@ -620,6 +620,7 @@ interface Hook<T extends Hooks[keyof Hooks]> {
620
620
  */
621
621
  declare function toNot(items?: WhereValue[] | null): WhereValue[] | null;
622
622
  type WhereItem = {
623
+ exists?: false | null | undefined;
623
624
  where?: null | undefined;
624
625
  or?: null | undefined;
625
626
  field: string | {
@@ -634,7 +635,16 @@ type WhereItem = {
634
635
  not?: boolean | undefined;
635
636
  operator?: string | null | undefined;
636
637
  };
638
+ type WhereExists = {
639
+ where?: null | undefined;
640
+ or?: null | undefined;
641
+ field?: null | undefined;
642
+ exists: true;
643
+ subquery: SelectItem[];
644
+ not?: boolean | undefined;
645
+ };
637
646
  type WhereRaw = {
647
+ exists?: false | null | undefined;
638
648
  field?: null | undefined;
639
649
  or?: null | undefined;
640
650
  where: readonly string[];
@@ -642,12 +652,13 @@ type WhereRaw = {
642
652
  not?: boolean | undefined;
643
653
  };
644
654
  type WhereOr = {
655
+ exists?: false | null | undefined;
645
656
  where?: null | undefined;
646
657
  field?: null | undefined;
647
658
  or: WhereValue[][];
648
659
  not?: boolean | undefined;
649
660
  };
650
- type WhereValue = WhereItem | WhereRaw | WhereOr;
661
+ type WhereValue = WhereItem | WhereExists | WhereRaw | WhereOr;
651
662
  type WhereLike = {
652
663
  toWhereValue(): WhereValue[][];
653
664
  };
@@ -738,6 +749,58 @@ declare class Where {
738
749
  * @returns {Where}
739
750
  */
740
751
  static and(items: [Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]): Where;
752
+ /**
753
+ * @overload
754
+ * @param {Wheres} matches
755
+ * @returns {Where}
756
+ */
757
+ static where(matches: Wheres): Where;
758
+ /**
759
+ *
760
+ * @overload
761
+ * @param {TemplateStringsArray} where
762
+ * @param {...any} values
763
+ * @returns {Where}
764
+ */
765
+ static where(where: TemplateStringsArray, ...values: any[]): Where;
766
+ /**
767
+ * @overload
768
+ * @param {string} field
769
+ * @param {any} value
770
+ * @returns {Where}
771
+ */
772
+ static where(field: string, value: any): Where;
773
+ /**
774
+ * @overload
775
+ * @param {string[]} field
776
+ * @param {any[]} value
777
+ * @returns {Where}
778
+ */
779
+ static where(field: string[], value: any[]): Where;
780
+ /**
781
+ * @overload
782
+ * @param {string} field
783
+ * @param {string} operator
784
+ * @param {any} value
785
+ * @param {boolean} [not]
786
+ * @returns {Where}
787
+ */
788
+ static where(field: string, operator: string, value: any, not?: boolean | undefined): Where;
789
+ /**
790
+ * @overload
791
+ * @param {string[]} field
792
+ * @param {string} operator
793
+ * @param {any[]} value
794
+ * @param {boolean} [not]
795
+ * @returns {Where}
796
+ */
797
+ static where(field: string[], operator: string, value: any[], not?: boolean | undefined): Where;
798
+ /**
799
+ * @overload
800
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
801
+ * @returns {Where}
802
+ */
803
+ static where(items: [Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]): Where;
741
804
  /**
742
805
  * @overload
743
806
  * @param {Wheres} matches
@@ -894,6 +957,18 @@ declare class Where {
894
957
  * @returns {Where}
895
958
  */
896
959
  static orNot(items: [Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]): Where;
960
+ /**
961
+ *
962
+ * @param {...SelectItem} subquery
963
+ * @returns {Where}
964
+ */
965
+ static exists(...subquery: SelectItem[]): Where;
966
+ /**
967
+ *
968
+ * @param {...SelectItem} subquery
969
+ * @returns {Where}
970
+ */
971
+ static notExists(...subquery: SelectItem[]): Where;
897
972
  toWhereValue(): WhereValue[][];
898
973
  /**
899
974
  * @overload
@@ -1103,6 +1178,18 @@ declare class Where {
1103
1178
  * @returns {this}
1104
1179
  */
1105
1180
  orNot(items: [Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]): this;
1181
+ /**
1182
+ *
1183
+ * @param {...SelectItem} subquery
1184
+ * @returns {this}
1185
+ */
1186
+ exists(...subquery: SelectItem[]): this;
1187
+ /**
1188
+ *
1189
+ * @param {...SelectItem} subquery
1190
+ * @returns {this}
1191
+ */
1192
+ notExists(...subquery: SelectItem[]): this;
1106
1193
  #private;
1107
1194
  }
1108
1195
 
@@ -2118,10 +2205,10 @@ declare class Query<T extends Fields, TB extends unknown = any> extends Subquery
2118
2205
  */
2119
2206
  contains(text?: string): this;
2120
2207
  /**
2121
- * @param {any} [primary]
2208
+ * @param {...any | any[]} primaries
2122
2209
  * @returns {this}
2123
2210
  */
2124
- primary(primary?: any, ...args: any[]): this;
2211
+ primary(...primaries: (any | any[])[]): this;
2125
2212
  /**
2126
2213
  *
2127
2214
  * @param {...string | string[]} groups
@@ -2180,6 +2267,15 @@ declare function bindHooks(hooks: Readonly<Partial<Hooks>>, that: any): Readonly
2180
2267
  */
2181
2268
  /** @import {FieldDefine, Fields, TableDefine,} from './types/table' */
2182
2269
  declare class Scene {
2270
+ /**
2271
+ * @template {TableDefine<Fields, string>} T
2272
+ * @param {{scene?: Scene} | Scene} source
2273
+ * @param {T} table
2274
+ * @returns {T}
2275
+ */
2276
+ static table<T extends TableDefine<Fields, string>>(source: {
2277
+ scene?: Scene;
2278
+ } | Scene, table: T): T;
2183
2279
  /**
2184
2280
  *
2185
2281
  * @param {Map<string, Scene.Define>} map
@@ -2564,6 +2660,13 @@ declare function field<T extends MainFieldType>(type: T, options: {
2564
2660
  default?: ToType<T, boolean, boolean> | symbol;
2565
2661
  } & FieldDefineOption): FieldDefine<T, boolean, boolean>;
2566
2662
 
2663
+ /**
2664
+ *
2665
+ * @param {any} v
2666
+ * @returns
2667
+ */
2668
+ declare function toBool(v: any): boolean;
2669
+
2567
2670
  /**
2568
2671
  *
2569
2672
  * @param {boolean} [d]
@@ -2571,4 +2674,4 @@ declare function field<T extends MainFieldType>(type: T, options: {
2571
2674
  declare function setDevelopment(d?: boolean): void;
2572
2675
  declare let isDevelopment: boolean;
2573
2676
 
2574
- export { Build, type ClassDecorator, type Column, type ColumnOptions, Connection, type Constraint, Create, type DBColumn, type DBIndex, type DBTable, Destroy, type Environment, type FieldDecorator, type FieldDefine, type FieldDefineOption, type FieldDefineType, type FieldSpecific, type FieldSpecificValue, type FieldType, type FieldTypeDefine, type FieldValue, type Fields, type FindArg, type FindRange, type GetName, type Hook, type Hooks, type IConnection, type Index, type IndexInfo, type IndexOptions, type JOIN, type Join, type JoinType, type MainFieldType, type MaybePromise, type MethodDecorator, Model, type Options, PseudoDestroy, Query, type QueryOptions, type Queryable, Save, Scene, Select, type SelectItem, SetValue, type Skip, Submodel, type Support, type TableConnect, type TableConnection, type TableDefine, type TableType, type TableValue, type ToFieldType, type ToType, type TransactionFn, type VirtualTable, Where, type WhereItem, type WhereLike, type WhereOr, type WhereRaw, type WhereValue, type Wheres, afterCreate, afterCreateMany, afterDelete, afterUpdate, beforeCreate, beforeCreateMany, beforeDelete, beforeUpdate, bindHooks, coefficient, column, creating, decrement, defaultValue, field as define, deleted, deleting, divide, field$1 as field, getPrimaryFields, getPrimaryKeys, hooks, immutable, increment, index, isDevelopment, isPseudo, mergeHooks, model, multiply, now, primary, prop, pseudo, setDevelopment, sort, model as submodel, toNot, toPrimaries, toPrimary, uncreatable, undeleted, updating, uuid, values, where, withDeleted };
2677
+ export { Build, type ClassDecorator, type Column, type ColumnOptions, Connection, type Constraint, Create, type DBColumn, type DBIndex, type DBTable, Destroy, type Environment, type FieldDecorator, type FieldDefine, type FieldDefineOption, type FieldDefineType, type FieldSpecific, type FieldSpecificValue, type FieldType, type FieldTypeDefine, type FieldValue, type Fields, type FindArg, type FindRange, type GetName, type Hook, type Hooks, type IConnection, type Index, type IndexInfo, type IndexOptions, type JOIN, type Join, type JoinType, type MainFieldType, type MaybePromise, type MethodDecorator, Model, type Options, PseudoDestroy, Query, type QueryOptions, type Queryable, Save, Scene, Select, type SelectItem, SetValue, type Skip, Submodel, type Support, type TableConnect, type TableConnection, type TableDefine, type TableType, type TableValue, type ToFieldType, type ToType, type TransactionFn, type VirtualTable, Where, type WhereExists, type WhereItem, type WhereLike, type WhereOr, type WhereRaw, type WhereValue, type Wheres, afterCreate, afterCreateMany, afterDelete, afterUpdate, beforeCreate, beforeCreateMany, beforeDelete, beforeUpdate, bindHooks, coefficient, column, creating, decrement, defaultValue, field as define, deleted, deleting, divide, field$1 as field, getPrimaryFields, getPrimaryKeys, hooks, immutable, increment, index, isDevelopment, isPseudo, mergeHooks, model, multiply, now, primary, prop, pseudo, setDevelopment, sort, model as submodel, toBool, toNot, toPrimaries, toPrimary, uncreatable, undeleted, updating, uuid, values, where, withDeleted };
package/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * imodel v0.18.0
2
+ * imodel v0.19.1
3
3
  * (c) 2019-2026 undefined
4
4
  * @license undefined
5
5
  */
@@ -26,6 +26,7 @@ class Subquery {
26
26
  /** @typedef {WhereLike | Record<string, any> | (WhereLike | Record<string, any>)[]} Wheres */
27
27
  /**
28
28
  * @typedef {object} WhereItem
29
+ * @prop {false?} [exists]
29
30
  * @prop {null} [where]
30
31
  * @prop {null} [or]
31
32
  * @prop {string | {table?: string; field: string} | (string | {table?: string; field: string})[]} field
@@ -34,8 +35,18 @@ class Subquery {
34
35
  * @prop {boolean} [not]
35
36
  * @prop {string?} [operator]
36
37
  */
38
+ /**
39
+ * @typedef {object} WhereExists
40
+ * @prop {null} [where]
41
+ * @prop {null} [or]
42
+ * @prop {null} [field]
43
+ * @prop {true} exists
44
+ * @prop {SelectItem[]} subquery
45
+ * @prop {boolean} [not]
46
+ */
37
47
  /**
38
48
  * @typedef {object} WhereRaw
49
+ * @prop {false?} [exists]
39
50
  * @prop {null} [field]
40
51
  * @prop {null} [or]
41
52
  * @prop {readonly string[]} where
@@ -44,12 +55,13 @@ class Subquery {
44
55
  */
45
56
  /**
46
57
  * @typedef {object} WhereOr
58
+ * @prop {false?} [exists]
47
59
  * @prop {null} [where]
48
60
  * @prop {null} [field]
49
61
  * @prop {WhereValue[][]} or
50
62
  * @prop {boolean} [not]
51
63
  */
52
- /** @typedef {WhereItem | WhereRaw | WhereOr} WhereValue */
64
+ /** @typedef {WhereItem | WhereExists | WhereRaw | WhereOr} WhereValue */
53
65
  /**
54
66
  *
55
67
  * @param {*} v
@@ -317,6 +329,58 @@ class Where {
317
329
  static and(...items) {
318
330
  return new Where().#and(parse(items));
319
331
  }
332
+ /**
333
+ * @overload
334
+ * @param {Wheres} matches
335
+ * @returns {Where}
336
+ */
337
+ /**
338
+ *
339
+ * @overload
340
+ * @param {TemplateStringsArray} where
341
+ * @param {...any} values
342
+ * @returns {Where}
343
+ */
344
+ /**
345
+ * @overload
346
+ * @param {string} field
347
+ * @param {any} value
348
+ * @returns {Where}
349
+ */
350
+ /**
351
+ * @overload
352
+ * @param {string[]} field
353
+ * @param {any[]} value
354
+ * @returns {Where}
355
+ */
356
+ /**
357
+ * @overload
358
+ * @param {string} field
359
+ * @param {string} operator
360
+ * @param {any} value
361
+ * @param {boolean} [not]
362
+ * @returns {Where}
363
+ */
364
+ /**
365
+ * @overload
366
+ * @param {string[]} field
367
+ * @param {string} operator
368
+ * @param {any[]} value
369
+ * @param {boolean} [not]
370
+ * @returns {Where}
371
+ */
372
+ /**
373
+ * @overload
374
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
375
+ * @returns {Where}
376
+ */
377
+ /**
378
+ * @param {[Wheres] | [TemplateStringsArray, ...any] | [string | string[], any] | [string | string[], string, any, boolean?]} items
379
+ * @returns {Where}
380
+ */
381
+ static where(...items) {
382
+ return new Where().#and(parse(items));
383
+ }
320
384
  /**
321
385
  * @overload
322
386
  * @param {Wheres} matches
@@ -629,6 +693,52 @@ class Where {
629
693
  static orNot(...items) {
630
694
  return new Where().#or(toNot(parse(items)));
631
695
  }
696
+ /**
697
+ *
698
+ * @param {...SelectItem} subquery
699
+ * @returns {this}
700
+ */
701
+ exists(...subquery) {
702
+ return this.#and([{
703
+ exists: true,
704
+ subquery
705
+ }]);
706
+ }
707
+ /**
708
+ *
709
+ * @param {...SelectItem} subquery
710
+ * @returns {Where}
711
+ */
712
+ static exists(...subquery) {
713
+ return new Where().#and([{
714
+ exists: true,
715
+ subquery
716
+ }]);
717
+ }
718
+ /**
719
+ *
720
+ * @param {...SelectItem} subquery
721
+ * @returns {this}
722
+ */
723
+ notExists(...subquery) {
724
+ return this.#and([{
725
+ exists: true,
726
+ subquery,
727
+ not: true
728
+ }]);
729
+ }
730
+ /**
731
+ *
732
+ * @param {...SelectItem} subquery
733
+ * @returns {Where}
734
+ */
735
+ static notExists(...subquery) {
736
+ return new Where().#and([{
737
+ exists: true,
738
+ subquery,
739
+ not: true
740
+ }]);
741
+ }
632
742
  }
633
743
 
634
744
  const deleted = Symbol();
@@ -4855,7 +4965,20 @@ function coefficient(...value) {
4855
4965
  };
4856
4966
  }
4857
4967
 
4858
- /** @import { Fields, Options, Queryable, Select, TableConnect, VirtualTable } from './types' */
4968
+ const falseValues = new Set(['', '0', 'n', 'f', 'no', 'off', 'false', '否', '', '假', '不是', '不行', '不可以']);
4969
+ /**
4970
+ *
4971
+ * @param {any} v
4972
+ * @returns
4973
+ */
4974
+ function toBool(v) {
4975
+ if (typeof v !== 'string') {
4976
+ return Boolean(v);
4977
+ }
4978
+ return !falseValues.has(v.toLowerCase());
4979
+ }
4980
+
4981
+ /** @import { FieldDefine, Fields, Options, Queryable, Select, TableConnect, VirtualTable } from './types' */
4859
4982
  /** @import { WhereValue, Wheres } from './Where.mjs' */
4860
4983
  /**
4861
4984
  *
@@ -4953,7 +5076,7 @@ class Query extends Subquery {
4953
5076
  #options = {
4954
5077
  where: []
4955
5078
  };
4956
- /** @type {string[]} 主键字段 */
5079
+ /** @type {[string, FieldDefine][]} 主键字段 */
4957
5080
  #primaryFields = [];
4958
5081
  get options() {
4959
5082
  return this.#options;
@@ -4977,7 +5100,6 @@ class Query extends Subquery {
4977
5100
  ...options.#options
4978
5101
  };
4979
5102
  this.#primaryFields = options.#primaryFields;
4980
- this.#primary = options.#primary;
4981
5103
  } else {
4982
5104
  const {
4983
5105
  connect,
@@ -4991,7 +5113,7 @@ class Query extends Subquery {
4991
5113
  this.fields = fields;
4992
5114
  this.pseudo = typeof pseudo === 'string' ? pseudo : '';
4993
5115
  this.#build = typeof build === 'function' ? build : null;
4994
- this.#primaryFields = Object.entries(fields).filter(([, v]) => v.primary).sort(([, a], [, b]) => Number(a.primary) - Number(b.primary)).map(([v]) => v);
5116
+ this.#primaryFields = Object.entries(fields).filter(([, v]) => v.primary).sort(([, a], [, b]) => Number(a.primary) - Number(b.primary));
4995
5117
  if (noBuild) {
4996
5118
  this.#build = null;
4997
5119
  } else if (typeof options[Build] === 'function') {
@@ -5326,17 +5448,13 @@ class Query extends Subquery {
5326
5448
  this.#options.where = [...this.#options.where, ...matches];
5327
5449
  return this;
5328
5450
  }
5329
- /** @type {string | number | bigint | object | undefined} */
5330
- #primary;
5331
5451
  /**
5332
- * @param {any} [primary]
5452
+ * @param {...any | any[]} primaries
5333
5453
  * @returns {this}
5334
5454
  */
5335
- primary(primary) {
5336
- if (this.#primary) {
5337
- return this;
5338
- }
5339
- if (!primary) {
5455
+ primary(...primaries) {
5456
+ const primary = primaries?.flat();
5457
+ if (!primary.length) {
5340
5458
  return this;
5341
5459
  }
5342
5460
  const primaryFields = this.#primaryFields;
@@ -5344,27 +5462,26 @@ class Query extends Subquery {
5344
5462
  return this;
5345
5463
  }
5346
5464
  if (primaryFields.length === 1) {
5347
- const [field] = primaryFields;
5348
- const m = this.where(field, '=', primary);
5349
- m.#primary = primary;
5350
- return m;
5465
+ const [[field]] = primaryFields;
5466
+ return this.where(field, 'in', primary);
5351
5467
  }
5352
- if (typeof primary === 'object') {
5353
- let m = this;
5354
- for (const p of primaryFields) {
5355
- m = m.where(p, '=', primary[p]);
5468
+ const list = primary.map(primary => {
5469
+ if (typeof primary === 'object') {
5470
+ return primaryFields.map(([p]) => primary[p]);
5356
5471
  }
5357
- m.#primary = primary;
5358
- return m;
5359
- }
5360
- const values = `${primary}`.split('$');
5361
- if (values.length !== primaryFields.length) ;
5362
- let m = this;
5363
- for (let i = 0; i < primaryFields.length; i++) {
5364
- m = m.where(primaryFields[i], '=', values[i]);
5365
- }
5366
- m.#primary = primary;
5367
- return m;
5472
+ const values = `${primary}`.split('$');
5473
+ if (values.length !== primaryFields.length) ;
5474
+ return primaryFields.map(([, {
5475
+ type
5476
+ }], i) => {
5477
+ const value = values[i] ?? null;
5478
+ if (type !== 'bool' || value === null) {
5479
+ return value;
5480
+ }
5481
+ return toBool(value);
5482
+ });
5483
+ });
5484
+ return this.where(primaryFields.map(f => f[0]), 'in', list);
5368
5485
  }
5369
5486
  /**
5370
5487
  *
@@ -6510,7 +6627,8 @@ class Scene {
6510
6627
  return {
6511
6628
  ...table,
6512
6629
  table: tableMap.table,
6513
- fields: this.#cloneField(table.fields, tableMap)
6630
+ fields: this.#cloneField(table.fields, tableMap),
6631
+ scene: this
6514
6632
  // TODO: 索引?
6515
6633
  };
6516
6634
  }
@@ -6550,6 +6668,19 @@ class Scene {
6550
6668
  table(table) {
6551
6669
  return this.#getModel(table);
6552
6670
  }
6671
+ /**
6672
+ * @template {TableDefine<Fields, string>} T
6673
+ * @param {{scene?: Scene} | Scene} source
6674
+ * @param {T} table
6675
+ * @returns {T}
6676
+ */
6677
+ static table(source, table) {
6678
+ const scene = source instanceof Scene ? source : source?.scene;
6679
+ if (!(scene instanceof Scene)) {
6680
+ return table;
6681
+ }
6682
+ return scene.table(table);
6683
+ }
6553
6684
  }
6554
6685
 
6555
6686
  /** @import { FieldDefine, FieldDefineOption, MainFieldType, ToType } from './types' */
@@ -6702,4 +6833,4 @@ function field(type, {
6702
6833
  };
6703
6834
  }
6704
6835
 
6705
- export { Build, Connection, Create, Destroy, Model, PseudoDestroy, Query, Save, Scene, Submodel, Where, afterCreate, afterCreateMany, afterDelete, afterUpdate, beforeCreate, beforeCreateMany, beforeDelete, beforeUpdate, bindHooks, coefficient, column, creating, decrement, defaultValue, field as define, deleted, deleting, divide, field$1 as field, getPrimaryFields, getPrimaryKeys, hooks, immutable, increment, index, isDevelopment, isPseudo, mergeHooks, model, multiply, now, primary, prop, pseudo, setDevelopment, sort, model as submodel, toNot, toPrimaries, toPrimary, uncreatable, undeleted, updating, uuid, values, where, withDeleted };
6836
+ export { Build, Connection, Create, Destroy, Model, PseudoDestroy, Query, Save, Scene, Submodel, Where, afterCreate, afterCreateMany, afterDelete, afterUpdate, beforeCreate, beforeCreateMany, beforeDelete, beforeUpdate, bindHooks, coefficient, column, creating, decrement, defaultValue, field as define, deleted, deleting, divide, field$1 as field, getPrimaryFields, getPrimaryKeys, hooks, immutable, increment, index, isDevelopment, isPseudo, mergeHooks, model, multiply, now, primary, prop, pseudo, setDevelopment, sort, model as submodel, toBool, toNot, toPrimaries, toPrimary, uncreatable, undeleted, updating, uuid, values, where, withDeleted };
package/migrate.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * imodel v0.18.0
2
+ * imodel v0.19.1
3
3
  * (c) 2019-2026 undefined
4
4
  * @license undefined
5
5
  */
package/migrate.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * imodel v0.18.0
2
+ * imodel v0.19.1
3
3
  * (c) 2019-2026 undefined
4
4
  * @license undefined
5
5
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "imodel",
3
- "version": "0.18.0",
3
+ "version": "0.19.1",
4
4
  "main": "index.mjs",
5
5
  "type": "module",
6
6
  "repository": {