leoric 2.8.1 → 2.8.3

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/History.md CHANGED
@@ -1,3 +1,23 @@
1
+ 2.8.3 / 2022-09-15
2
+ ==================
3
+
4
+ ## What's Changed
5
+ * fix: AssociationOptions.select? should be supported by @cyjake in https://github.com/cyjake/leoric/pull/343
6
+ * fix: return type of realm.query, realm.transaction, and Bone.transation by @cyjake in https://github.com/cyjake/leoric/pull/344
7
+
8
+
9
+ **Full Changelog**: https://github.com/cyjake/leoric/compare/v2.8.2...v2.8.3
10
+
11
+ 2.8.2 / 2022-09-13
12
+ ==================
13
+
14
+ ## What's Changed
15
+ * fix: AssociateOptions in HasMany, BelongdsTo decorators by @cyjake in https://github.com/cyjake/leoric/pull/341
16
+ * fix: invokable dataType in decorators should work and dts fix by @JimmyDaddy in https://github.com/cyjake/leoric/pull/342
17
+
18
+
19
+ **Full Changelog**: https://github.com/cyjake/leoric/compare/v2.8.1...v2.8.2
20
+
1
21
  2.8.1 / 2022-08-31
2
22
  ==================
3
23
 
package/index.d.ts CHANGED
@@ -8,11 +8,11 @@ import {
8
8
  Connection, QueryOptions,
9
9
  Raw, ColumnMeta, AttributeMeta,
10
10
  BeforeHooksType, AfterHooksType, Collection,
11
+ GeneratorReturnType,
11
12
  } from './src/types/common';
12
13
  import { SpellMeta, Spell, SpellBookFormatResult } from './src/spell';
13
14
  import Bone from './src/bone';
14
15
  import { ConnectOptions, AbstractDriver } from './src/drivers';
15
- import { RawQueryResult } from './src/types/abstract_bone';
16
16
 
17
17
  export {
18
18
  LENGTH_VARIANTS as LENGTH_VARIANTS,
@@ -43,15 +43,14 @@ interface SyncOptions {
43
43
 
44
44
  interface RawQueryOptions {
45
45
  replacements?: { [key:string]: Literal | Literal[] };
46
- model: Bone;
47
- connection: Connection;
46
+ connection?: Connection;
48
47
  }
49
48
 
50
49
  export default class Realm {
51
50
  Bone: typeof Bone;
52
51
  DataTypes: typeof DataTypes;
53
52
  driver: AbstractDriver;
54
- models: Record<string, Bone>;
53
+ models: Record<string, typeof Bone>;
55
54
  connected?: boolean;
56
55
 
57
56
  constructor(options: ConnectOptions);
@@ -75,10 +74,10 @@ export default class Realm {
75
74
 
76
75
  escape(value: Literal): string;
77
76
 
78
- query(sql: string, values?: Array<Literal>, options?: RawQueryOptions): RawQueryResult;
77
+ query<T extends typeof Bone>(sql: string, values?: Array<Literal>, options?: RawQueryOptions & { model?: T }): Promise<{ rows: T extends typeof Bone ? InstanceType<T>[] : Object[], fields?: Object[], affectedRows?: number }>;
79
78
 
80
- transaction(callback: GeneratorFunction): Promise<RawQueryResult>;
81
- transaction(callback: (connection: Connection) => Promise<RawQueryResult>): Promise<RawQueryResult>;
79
+ transaction<T extends (connection: Connection) => Generator>(callback: T): Promise<GeneratorReturnType<ReturnType<T>>>;
80
+ transaction<T extends (connection: Connection) => Promise<any>>(callback: T): Promise<ReturnType<T>>;
82
81
 
83
82
  sync(options?: SyncOptions): Promise<void>;
84
83
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leoric",
3
- "version": "2.8.1",
3
+ "version": "2.8.3",
4
4
  "description": "JavaScript Object-relational mapping alchemy",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -25,6 +25,10 @@ interface BaseSequelizeConditions<T extends typeof SequelizeBone> extends QueryO
25
25
  offset?: number;
26
26
  }
27
27
 
28
+ type SequelizeUpdateOptions<T extends typeof SequelizeBone> = BaseSequelizeConditions<T> & {
29
+ fields?: string[];
30
+ }
31
+
28
32
  interface SequelizeConditions<T extends typeof SequelizeBone> extends BaseSequelizeConditions<T> {
29
33
  group?: string | string[] | Raw;
30
34
  having?: WhereConditions<T> | string | { [key:string]: Literal | Literal[] } | Raw;
@@ -165,8 +169,8 @@ export class SequelizeBone extends AbstractBone {
165
169
 
166
170
  static restore<T extends typeof SequelizeBone>(this: T, options: BaseSequelizeConditions<T>): Spell<T, number>;
167
171
 
168
- static update<T extends typeof SequelizeBone>(this: T, values: SetOptions<T>, options: BaseSequelizeConditions<T>): Promise<number>;
169
- static bulkUpdate<T extends typeof SequelizeBone>(this: T, values: SetOptions<T>, options: BaseSequelizeConditions<T>): Spell<T, number>;
172
+ static update<T extends typeof SequelizeBone>(this: T, values: SetOptions<T>, options: SequelizeUpdateOptions<T>): Promise<number>;
173
+ static bulkUpdate<T extends typeof SequelizeBone>(this: T, values: SetOptions<T>, options: SequelizeUpdateOptions<T>): Spell<T, number>;
170
174
 
171
175
  /**
172
176
  * An alias of instance constructor. Some legacy code access model name from instance with `this.Model.name`.
package/src/bone.js CHANGED
@@ -224,6 +224,7 @@ class Bone {
224
224
  this.#raw = Object.assign({}, this.getRaw(), target.getRaw());
225
225
  this.#rawSaved = Object.assign({}, this.getRawSaved(), target.getRawSaved());
226
226
  this.#rawPrevious = Object.assign({}, this.getRawPrevious(), target.getRawPrevious());
227
+ this.#rawUnset = target._getRawUnset();
227
228
  }
228
229
 
229
230
  /**
@@ -1066,9 +1067,7 @@ class Bone {
1066
1067
  * The primary key of the model, in camelCase.
1067
1068
  * @type {string}
1068
1069
  */
1069
- static get primaryKey() {
1070
- return 'id';
1071
- }
1070
+ static primaryKey = 'id';
1072
1071
 
1073
1072
  /**
1074
1073
  * The primary column of the model, in snake_case, usually.
@@ -1254,7 +1253,7 @@ class Bone {
1254
1253
  }
1255
1254
  const { className } = opts;
1256
1255
  const Model = this.models[className];
1257
- if (!Model) throw new Error(`unable to find model "${className}"`);
1256
+ if (!Model) throw new Error(`unable to find associated model "${className}" (model ${this.name})`);
1258
1257
  if (opts.foreignKey && Model.attributes[opts.foreignKey] && Model.attributes[opts.foreignKey].virtual) {
1259
1258
  throw new Error(`unable to use virtual attribute ${opts.foreignKey} as foreign key in model ${Model.name}`);
1260
1259
  }
@@ -1589,9 +1588,9 @@ class Bone {
1589
1588
  await this.driver.query('BEGIN', [], { connection, Model: this, command: 'BEGIN' });
1590
1589
  while (true) {
1591
1590
  const { value: spell, done } = gen.next(result);
1592
- if (done) break;
1593
1591
  if (spell instanceof Spell) spell.connection = connection;
1594
- result = typeof spell.then === 'function' ? await spell : spell;
1592
+ result = spell && typeof spell.then === 'function' ? await spell : spell;
1593
+ if (done) break;
1595
1594
  }
1596
1595
  await this.driver.query('COMMIT', [], { connection, Model: this, command: 'COMMIT' });
1597
1596
  } catch (err) {
package/src/decorators.js CHANGED
@@ -44,14 +44,12 @@ function findType(tsType) {
44
44
  throw new Error(`unknown typescript type ${tsType}`);
45
45
  }
46
46
  }
47
- function Column(options) {
47
+ function Column(options = {}) {
48
48
  return function (target, propertyKey) {
49
- if (options == null) {
50
- options = {};
51
- }
52
49
  // target refers to model prototype, an internal instance of `Bone {}`
53
- if (options['prototype'] instanceof data_types_1.DataType)
50
+ if (options['prototype'] instanceof data_types_1.DataType || options instanceof data_types_1.DataType) {
54
51
  options = { type: options };
52
+ }
55
53
  if (!('type' in options)) {
56
54
  const tsType = Reflect.getMetadata('design:type', target, propertyKey);
57
55
  options['type'] = findType(tsType);
@@ -68,9 +66,10 @@ function Column(options) {
68
66
  }
69
67
  exports.Column = Column;
70
68
  const { hasMany, hasOne, belongsTo } = constants_1.ASSOCIATE_METADATA_MAP;
71
- function HasMany(options) {
69
+ function HasMany(options = {}) {
72
70
  return function (target, propertyKey) {
73
71
  const model = target.constructor;
72
+ // it seems it's not possible to get the type of array element at runtime
74
73
  Reflect.defineMetadata(hasMany, {
75
74
  ...Reflect.getMetadata(hasMany, model),
76
75
  [propertyKey]: options,
@@ -78,9 +77,14 @@ function HasMany(options) {
78
77
  };
79
78
  }
80
79
  exports.HasMany = HasMany;
81
- function HasOne(options) {
80
+ function HasOne(options = {}) {
82
81
  return function (target, propertyKey) {
83
82
  const model = target.constructor;
83
+ if (options.className == null) {
84
+ const tsType = Reflect.getMetadata('design:type', target, propertyKey);
85
+ if (tsType.name !== 'Function')
86
+ options.className = tsType.name;
87
+ }
84
88
  Reflect.defineMetadata(hasOne, {
85
89
  ...Reflect.getMetadata(hasOne, model),
86
90
  [propertyKey]: options,
@@ -88,9 +92,24 @@ function HasOne(options) {
88
92
  };
89
93
  }
90
94
  exports.HasOne = HasOne;
91
- function BelongsTo(options) {
95
+ /**
96
+ * design:type will be `Function { [native code] }` in following example
97
+ *
98
+ * @example
99
+ * import type Foo from './foo';
100
+ * class Bar extends Bone {
101
+ * @BelongsTo()
102
+ * foo?: Foo;
103
+ * }
104
+ */
105
+ function BelongsTo(options = {}) {
92
106
  return function (target, propertyKey) {
93
107
  const model = target.constructor;
108
+ if (options.className == null) {
109
+ const tsType = Reflect.getMetadata('design:type', target, propertyKey);
110
+ if (tsType.name !== 'Function')
111
+ options.className = tsType.name;
112
+ }
94
113
  Reflect.defineMetadata(belongsTo, {
95
114
  ...Reflect.getMetadata(belongsTo, model),
96
115
  [propertyKey]: options,
@@ -1 +1 @@
1
- {"version":3,"file":"decorators.js","sourceRoot":"","sources":["decorators.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4BAA0B;AAG1B,2DAA8D;AAC9D,2CAAqD;AAWrD,SAAS,QAAQ,CAAC,MAAM;IACtB,MAAM,EACJ,MAAM,EAAE,OAAO,EACf,IAAI,EACJ,MAAM,EACN,OAAO,GACR,GAAG,oBAAS,CAAC;IAEd,QAAQ,MAAM,EAAE;QACd,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,MAAM;YACT,OAAO,OAAO,CAAC;QACjB,KAAK,IAAI;YACP,OAAO,IAAI,CAAC;QACd,KAAK,MAAM;YACT,OAAO,MAAM,CAAC;QAChB,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;QACjB;YACE,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,EAAE,CAAC,CAAC;KACxD;AACH,CAAC;AAED,SAAgB,MAAM,CAAC,OAAuD;IAC5E,OAAO,UAAS,MAAY,EAAE,WAAmB;QAC/C,IAAI,OAAO,IAAI,IAAI,EAAE;YACnB,OAAO,GAAG,EAAE,CAAC;SACd;QACD,sEAAsE;QACtE,IAAI,OAAO,CAAC,WAAW,CAAC,YAAY,qBAAQ;YAAE,OAAO,GAAG,EAAE,IAAI,EAAE,OAA8B,EAAE,CAAC;QAEjG,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC,EAAE;YACxB,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;YACvE,OAAO,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;SACpC;QAED,gDAAgD;QAChD,IAAI,CAAC,CAAC,MAAM,IAAI,OAAO,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,OAAO,EAAE,CAAC,CAAC;QAE/E,sEAAsE;QACtE,MAAM,KAAK,GAAG,MAAM,CAAC,WAAkB,CAAC;QACxC,MAAM,EAAE,UAAU,GAAG,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;QACvD,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;QACrD,UAAU,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,WAAW,EAAE,UAAU,EAAE,CAAC;IAC3D,CAAC,CAAC;AACJ,CAAC;AAtBD,wBAsBC;AAED,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,kCAAsB,CAAC;AAE9D,SAAgB,OAAO,CAAC,OAA0B;IAChD,OAAO,UAAS,MAAY,EAAE,WAAmB;QAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC;QACjC,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE;YAC9B,GAAG,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC;YACtC,CAAC,WAAW,CAAC,EAAE,OAAO;SACvB,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC,CAAA;AACH,CAAC;AARD,0BAQC;AAED,SAAgB,MAAM,CAAC,OAA0B;IAC/C,OAAO,UAAS,MAAY,EAAE,WAAmB;QAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC;QACjC,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE;YAC7B,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC;YACrC,CAAC,WAAW,CAAC,EAAE,OAAO;SACvB,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC,CAAA;AACH,CAAC;AARD,wBAQC;AAED,SAAgB,SAAS,CAAC,OAA0B;IAClD,OAAO,UAAS,MAAY,EAAE,WAAmB;QAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC;QACjC,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE;YAChC,GAAG,OAAO,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC;YACxC,CAAC,WAAW,CAAC,EAAE,OAAO;SACvB,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC,CAAA;AACH,CAAC;AARD,8BAQC"}
1
+ {"version":3,"file":"decorators.js","sourceRoot":"","sources":["decorators.ts"],"names":[],"mappings":"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"}
package/src/decorators.ts CHANGED
@@ -37,13 +37,12 @@ function findType(tsType) {
37
37
  }
38
38
  }
39
39
 
40
- export function Column(options?: ColumnOption | DATA_TYPE<DataType> | DataType) {
40
+ export function Column(options: ColumnOption | DATA_TYPE<DataType> | DataType = {}) {
41
41
  return function(target: Bone, propertyKey: string) {
42
- if (options == null) {
43
- options = {};
44
- }
45
42
  // target refers to model prototype, an internal instance of `Bone {}`
46
- if (options['prototype'] instanceof DataType) options = { type: options as DATA_TYPE<DataType> };
43
+ if (options['prototype'] instanceof DataType || options instanceof DataType) {
44
+ options = { type: options as DATA_TYPE<DataType> };
45
+ }
47
46
 
48
47
  if (!('type' in options)) {
49
48
  const tsType = Reflect.getMetadata('design:type', target, propertyKey);
@@ -63,9 +62,10 @@ export function Column(options?: ColumnOption | DATA_TYPE<DataType> | DataType)
63
62
 
64
63
  const { hasMany, hasOne, belongsTo } = ASSOCIATE_METADATA_MAP;
65
64
 
66
- export function HasMany(options?: AssociateOptions) {
65
+ export function HasMany(options: AssociateOptions = {}) {
67
66
  return function(target: Bone, propertyKey: string) {
68
67
  const model = target.constructor;
68
+ // it seems it's not possible to get the type of array element at runtime
69
69
  Reflect.defineMetadata(hasMany, {
70
70
  ...Reflect.getMetadata(hasMany, model),
71
71
  [propertyKey]: options,
@@ -73,9 +73,13 @@ export function HasMany(options?: AssociateOptions) {
73
73
  }
74
74
  }
75
75
 
76
- export function HasOne(options?: AssociateOptions) {
76
+ export function HasOne(options: AssociateOptions = {}) {
77
77
  return function(target: Bone, propertyKey: string) {
78
78
  const model = target.constructor;
79
+ if (options.className == null) {
80
+ const tsType = Reflect.getMetadata('design:type', target, propertyKey);
81
+ if (tsType.name !== 'Function') options.className = tsType.name;
82
+ }
79
83
  Reflect.defineMetadata(hasOne, {
80
84
  ...Reflect.getMetadata(hasOne, model),
81
85
  [propertyKey]: options,
@@ -83,9 +87,23 @@ export function HasOne(options?: AssociateOptions) {
83
87
  }
84
88
  }
85
89
 
86
- export function BelongsTo(options?: AssociateOptions) {
90
+ /**
91
+ * design:type will be `Function { [native code] }` in following example
92
+ *
93
+ * @example
94
+ * import type Foo from './foo';
95
+ * class Bar extends Bone {
96
+ * @BelongsTo()
97
+ * foo?: Foo;
98
+ * }
99
+ */
100
+ export function BelongsTo(options: AssociateOptions = {}) {
87
101
  return function(target: Bone, propertyKey: string) {
88
102
  const model = target.constructor;
103
+ if (options.className == null) {
104
+ const tsType = Reflect.getMetadata('design:type', target, propertyKey);
105
+ if (tsType.name !== 'Function') options.className = tsType.name;
106
+ }
89
107
  Reflect.defineMetadata(belongsTo, {
90
108
  ...Reflect.getMetadata(belongsTo, model),
91
109
  [propertyKey]: options,
package/src/realm.js CHANGED
@@ -230,8 +230,8 @@ class Realm {
230
230
  }
231
231
 
232
232
  return {
233
+ ...restRes,
233
234
  rows: results.length > 0 ? results : rows,
234
- ...restRes
235
235
  };
236
236
  }
237
237
 
@@ -2,13 +2,12 @@ import DataTypes, { AbstractDataType, DataType } from "../data_types";
2
2
  import {
3
3
  Pool, Literal, WhereConditions,
4
4
  Collection, ResultSet, InstanceValues, OrderOptions,
5
- QueryOptions, AttributeMeta, AssociateOptions, Values, Connection,
5
+ QueryOptions, AttributeMeta, AssociateOptions, Values, Connection, BulkCreateOptions,
6
+ GeneratorReturnType,
6
7
  } from './common';
7
8
  import { AbstractDriver } from '../drivers';
8
9
  import { Spell } from '../spell';
9
10
 
10
- export type RawQueryResult = typeof AbstractBone | ResultSet | boolean | number;
11
-
12
11
  interface SyncOptions {
13
12
  force?: boolean;
14
13
  alter?: boolean;
@@ -119,7 +118,7 @@ export class AbstractBone {
119
118
  /**
120
119
  * Batch INSERT
121
120
  */
122
- static bulkCreate<T extends typeof AbstractBone>(this: T, records: Array<Record<string, Literal>>, options?: QueryOptions): Promise<Array<InstanceType<T>>>;
121
+ static bulkCreate<T extends typeof AbstractBone>(this: T, records: Array<Record<string, Literal>>, options?: BulkCreateOptions): Promise<Array<InstanceType<T>>>;
123
122
 
124
123
  /**
125
124
  * SELECT all rows. In production, when the table is at large, it is not recommended to access records in this way. To iterate over all records, {@link Bone.batch} shall be considered as the better alternative. For tables with soft delete enabled, which means they've got `deletedAt` attribute, use {@link Bone.unscoped} to discard the default scope.
@@ -216,9 +215,9 @@ export class AbstractBone {
216
215
  * yield Muscle.create({ boneId: bone.id, bar: 1 })
217
216
  * });
218
217
  */
219
- static transaction(callback: GeneratorFunction): Promise<RawQueryResult>;
220
- static transaction(callback: (connection: TransactionOptions) => Promise<RawQueryResult | void>): Promise<RawQueryResult>;
221
-
218
+ static transaction<T extends (connection: Connection) => Generator>(callback: T): Promise<GeneratorReturnType<ReturnType<T>>>;
219
+ static transaction<T extends (connection: Connection) => Promise<any>>(callback: T): Promise<ReturnType<T>>;
220
+
222
221
  static describe(): Promise<{[key: string]: any[]}>;
223
222
 
224
223
  /**
@@ -357,4 +356,4 @@ export class AbstractBone {
357
356
  * @return {Object}
358
357
  */
359
358
  toObject(): InstanceValues<this>;
360
- }
359
+ }
@@ -5,7 +5,7 @@ import { AbstractBone } from './abstract_bone';
5
5
 
6
6
  export type Literal = null | undefined | boolean | number | bigint | string | Date | object | ArrayBuffer;
7
7
 
8
- type BaseValidateArgs = boolean | RegExp | Function | Array<Array<Literal>> | string;
8
+ type BaseValidateArgs = boolean | RegExp | Function | Array<Array<Literal>> | string | Array<Literal>;
9
9
 
10
10
  export type Validator = BaseValidateArgs | {
11
11
  args?: BaseValidateArgs,
@@ -53,12 +53,22 @@ export interface QueryOptions {
53
53
  connection?: Connection;
54
54
  hints?: Array<CommonHintsArgs>;
55
55
  hint?: CommonHintsArgs;
56
- transaction?: Connection;
56
+ transaction?: Connection | {
57
+ connection: Connection
58
+ };
59
+ }
60
+
61
+ export type BulkCreateOptions = QueryOptions & {
62
+ updateOnDuplicate?: string[];
63
+ fields?: string[];
57
64
  }
58
65
 
59
66
  export interface AssociateOptions {
60
67
  className?: string;
61
68
  foreignKey?: string;
69
+ through?: string;
70
+ where?: Record<string, Literal>;
71
+ select?: string[] | ((name: string) => boolean);
62
72
  }
63
73
 
64
74
  export type command = 'select' | 'insert' | 'bulkInsert' | 'update' | 'delete' | 'upsert';
@@ -168,3 +178,6 @@ export type InstanceValues<T> = {
168
178
 
169
179
  export type BeforeHooksType = 'beforeCreate' | 'beforeBulkCreate' | 'beforeUpdate' | 'beforeSave' | 'beforeUpsert' | 'beforeRemove';
170
180
  export type AfterHooksType = 'afterCreate' | 'afterBulkCreate' | 'afterUpdate' | 'afterSave' | 'afterUpsert' | 'afterRemove';
181
+
182
+ // https://stackoverflow.com/a/67232225/179691
183
+ type GeneratorReturnType<T extends Generator> = T extends Generator<any, infer R, any> ? R: never;