leoric 2.7.2 → 2.8.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.
@@ -0,0 +1,360 @@
1
+ import DataTypes, { AbstractDataType, DataType } from "../data_types";
2
+ import {
3
+ Pool, Literal, WhereConditions,
4
+ Collection, ResultSet, InstanceValues, OrderOptions,
5
+ QueryOptions, AttributeMeta, AssociateOptions, Values, Connection,
6
+ } from './common';
7
+ import { AbstractDriver } from '../drivers';
8
+ import { Spell } from '../spell';
9
+
10
+ export type RawQueryResult = typeof AbstractBone | ResultSet | boolean | number;
11
+
12
+ interface SyncOptions {
13
+ force?: boolean;
14
+ alter?: boolean;
15
+ }
16
+
17
+ interface TransactionOptions {
18
+ connection: Connection;
19
+ }
20
+
21
+ export class AbstractBone {
22
+ static DataTypes: typeof DataTypes;
23
+
24
+ /**
25
+ * get the connection pool of the driver
26
+ */
27
+ static pool: Pool;
28
+
29
+ /**
30
+ * The driver that powers the model
31
+ */
32
+ static driver: AbstractDriver;
33
+
34
+ /**
35
+ * The connected models structured as `{ [model.name]: model }`, e.g. `Bone.model.Post => Post`
36
+ */
37
+ static models: { [key: string]: typeof AbstractBone };
38
+
39
+ /**
40
+ * The table name of the model, which needs to be specified by the model subclass.
41
+ */
42
+ static table: string;
43
+
44
+ /**
45
+ * The plural model name in camelCase, e.g. `Post => posts`
46
+ */
47
+ static tableAlias: string;
48
+
49
+ /**
50
+ * The primary key of the model, defaults to `id`.
51
+ */
52
+ static primaryKey: string;
53
+
54
+ /**
55
+ * The primary column of the table, defaults to `id`. This is {@link Bone.primaryKey} in snake case.
56
+ */
57
+ static primaryColumn: string;
58
+
59
+ /**
60
+ * The attribute definitions of the model.
61
+ */
62
+ static attributes: { [key: string]: AbstractDataType<DataType> | AttributeMeta };
63
+
64
+ /**
65
+ * The schema info of current model.
66
+ */
67
+ static columns: Array<AttributeMeta>;
68
+
69
+ /**
70
+ * If the table consists of multiple partition tables then a sharding key is needed to perform actual query. The sharding key can be specified through overridding this property, which will then be used to check the query before it hits database.
71
+ */
72
+ static shardingKey: string;
73
+
74
+ /**
75
+ * If the table name is just an alias and the schema info can only be fetched by one of its partition table names, physic tables should be specified.
76
+ */
77
+ static physicTables: string[];
78
+
79
+ isNewRecord: boolean;
80
+
81
+ /**
82
+ * Override attribute metadata
83
+ * @example
84
+ * Bone.attribute('foo', { type: JSON })
85
+ */
86
+ static attribute(name: string, meta: AttributeMeta): void;
87
+
88
+ /**
89
+ * Rename attribute
90
+ * @example
91
+ * Bone.renameAttribute('foo', 'bar')
92
+ */
93
+ static renameAttribute(originalName: string, newName: string): void;
94
+
95
+ static alias(name: string): string;
96
+ static alias(data: Record<string, Literal>): Record<string, Literal>;
97
+ static unalias(name: string): string;
98
+
99
+ static hasOne(name: string, opts?: AssociateOptions): void;
100
+ static hasMany(name: string, opts?: AssociateOptions): void;
101
+ static belongsTo(name: string, opts?: AssociateOptions): void;
102
+
103
+ /**
104
+ * INSERT rows
105
+ * @example
106
+ * Bone.create({ foo: 1, bar: 'baz' })
107
+ */
108
+ static create<T extends typeof AbstractBone>(this: T, values: Values<T>, options?: QueryOptions): Promise<InstanceType<T>>;
109
+
110
+ /**
111
+ * INSERT or UPDATE rows
112
+ * @example
113
+ * Bone.upsert(values, { hooks: false })
114
+ * @param values values
115
+ * @param opt query options
116
+ */
117
+ static upsert<T extends typeof AbstractBone>(this: T, values: Object, options?: QueryOptions): Spell<T, number>;
118
+
119
+ /**
120
+ * Batch INSERT
121
+ */
122
+ static bulkCreate<T extends typeof AbstractBone>(this: T, records: Array<Record<string, Literal>>, options?: QueryOptions): Promise<Array<InstanceType<T>>>;
123
+
124
+ /**
125
+ * 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.
126
+ */
127
+ static all: Spell<typeof AbstractBone, Collection<AbstractBone>>;
128
+
129
+ /**
130
+ * SELECT rows OFFSET index LIMIT 1
131
+ * @example
132
+ * Bone.get(8)
133
+ * Bone.find({ foo: { $gt: 1 } }).get(42)
134
+ */
135
+ static get<T extends typeof AbstractBone>(this: T, index: number): Spell<T, InstanceType<T> | null>;
136
+
137
+ /**
138
+ * SELECT rows ORDER BY id ASC LIMIT 1
139
+ */
140
+ static first: Spell<typeof AbstractBone, AbstractBone | null>;
141
+
142
+ /**
143
+ * SELECT rows ORDER BY id DESC LIMIT 1
144
+ */
145
+ static last: Spell<typeof AbstractBone, AbstractBone | null>;
146
+
147
+ /**
148
+ * Short of `Bone.find().with(...names)`
149
+ * @example
150
+ * Post.include('author', 'comments').where('posts.id = ?', 1)
151
+ */
152
+ static include<T extends typeof AbstractBone>(this: T, ...names: string[]) : Spell<T>;
153
+
154
+ /**
155
+ * Whitelist SELECT fields by names or filter function
156
+ * @example
157
+ * Bone.select('foo')
158
+ * Bone.select('foo, bar')
159
+ * Bone.select('foo', 'bar')
160
+ * Bone.select('MONTH(date), foo + 1')
161
+ * Bone.select(name => name !== foo)
162
+ */
163
+ static select<T extends typeof AbstractBone>(this: T, ...names: string[]): Spell<T>;
164
+ static select<T extends typeof AbstractBone>(this: T, filter: (name: string) => boolean): Spell<T>;
165
+
166
+ /**
167
+ * JOIN arbitrary models with given ON conditions
168
+ * @example
169
+ * Bone.join(Muscle, 'bones.id == muscles.boneId')
170
+ */
171
+ static join<T extends typeof AbstractBone>(this: T, Model: AbstractBone, onConditions: string, ...values: Literal[]): Spell<T, Collection<InstanceType<T>>>;
172
+ static join<T extends typeof AbstractBone>(this: T, Model: AbstractBone, onConditions: WhereConditions<T>): Spell<T, Collection<InstanceType<T>>>;
173
+
174
+ /**
175
+ * Set WHERE conditions
176
+ * @example
177
+ * Bone.where('foo = ?', 1)
178
+ * Bone.where({ foo: { $eq: 1 } })
179
+ */
180
+ static where<T extends typeof AbstractBone>(this: T, whereConditions: string, ...values: Literal[]): Spell<T, Collection<InstanceType<T>>>;
181
+ static where<T extends typeof AbstractBone>(this: T, whereConditions: WhereConditions<T>): Spell<T, Collection<InstanceType<T>>>;
182
+
183
+ /**
184
+ * Set GROUP fields
185
+ * @example
186
+ * Bone.group('foo')
187
+ * Bone.group('MONTH(createdAt)')
188
+ */
189
+ static group<T extends typeof AbstractBone>(this: T, ...names: string[]): Spell<T, ResultSet>;
190
+
191
+ /**
192
+ * Set ORDER fields
193
+ * @example
194
+ * Bone.order('foo')
195
+ * Bone.order('foo', 'desc')
196
+ * Bone.order({ foo: 'desc' })
197
+ */
198
+ static order<T extends typeof AbstractBone>(this: T, name: string, order?: 'desc' | 'asc'): Spell<T>;
199
+ static order<T extends typeof AbstractBone>(this: T, opts: OrderOptions<T>): Spell<T>;
200
+
201
+ static count<T extends typeof AbstractBone>(this: T, name?: string): Spell<T, ResultSet | number>;
202
+ static average<T extends typeof AbstractBone>(this: T, name?: string): Spell<T, ResultSet | number>;
203
+ static minimum<T extends typeof AbstractBone>(this: T, name?: string): Spell<T, ResultSet | number>;
204
+ static maximum<T extends typeof AbstractBone>(this: T, name?: string): Spell<T, ResultSet | number>;
205
+
206
+ /**
207
+ * Remove rows. If soft delete is applied, an UPDATE query is performed instead of DELETing records directly. Set `forceDelete` to true to force a `DELETE` query.
208
+ */
209
+ static remove<T extends typeof AbstractBone>(this: T, whereConditions: WhereConditions<T>, forceDelete?: boolean, opt?: QueryOptions): Spell<T, number>;
210
+
211
+ /**
212
+ * Grabs a connection and starts a transaction process. Both GeneratorFunction and AsyncFunction are acceptable. If GeneratorFunction is used, the connection of the transaction process will be passed around automatically.
213
+ * @example
214
+ * Bone.transaction(function* () {
215
+ * const bone = yield Bone.create({ foo: 1 })
216
+ * yield Muscle.create({ boneId: bone.id, bar: 1 })
217
+ * });
218
+ */
219
+ static transaction(callback: GeneratorFunction): Promise<RawQueryResult>;
220
+ static transaction(callback: (connection: TransactionOptions) => Promise<RawQueryResult | void>): Promise<RawQueryResult>;
221
+
222
+ static describe(): Promise<{[key: string]: any[]}>;
223
+
224
+ /**
225
+ * DROP the table
226
+ */
227
+ static drop(): Promise<void>;
228
+
229
+ /**
230
+ * TRUNCATE table to clear records.
231
+ */
232
+ static truncate(): Promise<void>;
233
+
234
+ static sync(options: SyncOptions): Promise<void>;
235
+
236
+ static initialize(): void;
237
+
238
+ constructor(values: { [key: string]: Literal }, opts?: { isNewRecord?: boolean });
239
+
240
+ /**
241
+ * @example
242
+ * bone.attribute('foo'); // => 1
243
+ * bone.attribute('foo', 2); // => bone
244
+ */
245
+ attribute(name: string, value: Literal): void;
246
+ attribute(name: string): Literal;
247
+
248
+ /**
249
+ * Get the original attribute value.
250
+ * @example
251
+ * bone.attributeWas('foo') // => 1
252
+ */
253
+ attributeWas(name: string): Literal;
254
+
255
+ /**
256
+ * See if attribute has been changed or not.
257
+ * @deprecated {@link Bone#changed} is preferred
258
+ * @example
259
+ * bone.attributeChanged('foo')
260
+ */
261
+ attributeChanged(name: string): boolean;
262
+
263
+ /**
264
+ * Get changed attributes or check if given attribute is changed or not
265
+ */
266
+ changed(name: string): boolean;
267
+ changed(): Array<string> | false;
268
+
269
+ /**
270
+ * Get attribute changes
271
+ */
272
+ changes(name: string): Record<string, [ Literal, Literal ]>;
273
+ changes(): Record<string, [ Literal, Literal ]>;
274
+
275
+ /**
276
+ * See if attribute was changed previously or not.
277
+ */
278
+ previousChanged(name: string): boolean;
279
+ previousChanged(): Array<string>;
280
+
281
+ previousChanges(name: string): boolean;
282
+ previousChanges(): Array<string>;
283
+
284
+ /**
285
+ * Persist changes of current record to database. If current record has never been saved before, an INSERT query is performed. If the primary key was set and is not changed since, an UPDATE query is performed. If the primary key is changed, an INSERT ... UPDATE query is performed instead.
286
+ *
287
+ * If `affectedRows` is needed, consider using the corresponding methods directly.
288
+ * @example
289
+ * new Bone({ foo: 1 }).save() // => INSERT
290
+ * new Bone({ foo: 1, id: 1 }).save() // => INSERT ... UPDATE
291
+ * (await Bone.fist).attribute('foo', 2).save() // => UPDATE
292
+ * new Bone({ foo: 1, id: 1 }).save({ hooks: false }) // => INSERT ... UPDATE
293
+ */
294
+ save(opts?: QueryOptions): Promise<this>;
295
+
296
+ /**
297
+ * Remove current record. If `deletedAt` attribute exists, then instead of DELETing records from database directly, the records will have their `deletedAt` attribute UPDATEd instead. To force `DELETE`, no matter the existence of `deletedAt` attribute, pass `true` as the argument.
298
+ * @example
299
+ * bone.remove() // => UPDATE ... SET deleted_at = now() WHERE ...
300
+ * bone.remove(true) // => DELETE FROM ... WHERE ...
301
+ * bone.remove(true, { hooks: false })
302
+ */
303
+ remove(forceDelete?: boolean): Promise<number>;
304
+ remove(forceDelete?: boolean, opts?: QueryOptions): Promise<number>;
305
+
306
+ /**
307
+ * update or insert record.
308
+ * @example
309
+ * bone.upsert() // INERT ... VALUES ON DUPLICATE KEY UPDATE ...
310
+ * bone.upsert({ hooks: false })
311
+ * @param opts queryOptions
312
+ */
313
+ upsert(opts?: QueryOptions): Promise<number>;
314
+
315
+ /**
316
+ * update rows
317
+ * @param changes data changes
318
+ * @param opts query options
319
+ */
320
+ update(changes?: { [key: string]: Literal } | { [Property in keyof Extract<this, Literal>]: Literal }, opts?: QueryOptions): Promise<number>;
321
+
322
+ /**
323
+ * create instance
324
+ * @param opts query options
325
+ */
326
+ create(opts?: QueryOptions): Promise<this>;
327
+
328
+ /**
329
+ * reload instance
330
+ */
331
+ reload(): Promise<this>;
332
+
333
+ /**
334
+ * restore data
335
+ * @param opts query options
336
+ */
337
+ restore(opts?: QueryOptions): Promise<this>;
338
+
339
+ /**
340
+ * Gets called when `JSON.stringify(instance)` is invoked.
341
+ * {@link Bone#toJSON} might be called on descents of Bone that does not have attributes defined on them directly, hence for..in is preferred.
342
+ * - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties
343
+ * @example
344
+ * const post = await Post.first
345
+ * post.toJSON() // => { id: 1, ... }
346
+ * @return {Object}
347
+ */
348
+ toJSON(): InstanceValues<this>;
349
+
350
+ /**
351
+ * This is the loyal twin of {@link Bone#toJSON} because when generating the result object, the raw values of attributes are used, instead of the values returned by custom getters (if any).
352
+ * {@link Bone#toObject} might be called on descents of Bone that does not have attributes defined on them directly, hence for..in is preferred.
353
+ * - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties
354
+ * @example
355
+ * const post = await Post.first
356
+ * post.toObject() // => { id: 1, ... }
357
+ * @return {Object}
358
+ */
359
+ toObject(): InstanceValues<this>;
360
+ }
@@ -1,10 +1,14 @@
1
1
 
2
+ import { CommonHintsArgs } from '../hint';
3
+ import { AbstractDataType, DataType } from '../data_types';
4
+ import { AbstractBone } from './abstract_bone';
5
+
2
6
  export type Literal = null | undefined | boolean | number | bigint | string | Date | object | ArrayBuffer;
3
7
 
4
8
  type BaseValidateArgs = boolean | RegExp | Function | Array<Array<Literal>> | string;
5
9
 
6
10
  export type Validator = BaseValidateArgs | {
7
- args: BaseValidateArgs,
11
+ args?: BaseValidateArgs,
8
12
  msg?: string;
9
13
  };
10
14
 
@@ -36,6 +40,10 @@ export interface Connection {
36
40
  ): Promise<QueryResult>;
37
41
  }
38
42
 
43
+ export declare class Pool {
44
+ getConnection(): Connection;
45
+ }
46
+
39
47
  export interface QueryOptions {
40
48
  validate?: boolean;
41
49
  individualHooks?: boolean;
@@ -43,6 +51,9 @@ export interface QueryOptions {
43
51
  paranoid?: boolean;
44
52
  silent?: boolean;
45
53
  connection?: Connection;
54
+ hints?: Array<CommonHintsArgs>;
55
+ hint?: CommonHintsArgs;
56
+ transaction?: Connection;
46
57
  }
47
58
 
48
59
  export interface AssociateOptions {
@@ -54,4 +65,106 @@ export type command = 'select' | 'insert' | 'bulkInsert' | 'update' | 'delete' |
54
65
 
55
66
  export type ResultSet = {
56
67
  [key: string]: Literal
57
- };
68
+ };
69
+
70
+ export interface ColumnMeta extends ColumnBase {
71
+ dataType?: string;
72
+ datetimePrecision?: string;
73
+ }
74
+
75
+ export interface AttributeMeta extends ColumnMeta {
76
+ jsType?: Literal;
77
+ type: AbstractDataType<DataType>;
78
+ virtual?: boolean,
79
+ toSqlString?: () => string;
80
+ validate?: {
81
+ [key: string]: Validator;
82
+ }
83
+ }
84
+
85
+ export interface Attributes { [key: string]: AbstractDataType<DataType> | AttributeMeta }
86
+
87
+ export type OperatorCondition = {
88
+ [key in '$eq' | '$ne']?: Literal;
89
+ } & {
90
+ [key in '$in' | '$nin' | '$notIn']?: Literal[] | Set<Literal>;
91
+ } & {
92
+ [key in '$like' | '$notLike']?: string;
93
+ } & {
94
+ [key in '$gt' | '$gte' | '$lt' | '$lte']?: number;
95
+ } & {
96
+ [key in '$between' | '$notBetween']?: [number, number] | [Date, Date];
97
+ };
98
+
99
+ export type BoneOptions = {
100
+ isNewRecord?: boolean;
101
+ }
102
+
103
+ export declare class Attribute {
104
+ /**
105
+ * attribute name
106
+ */
107
+ name: string;
108
+ /**
109
+ * primaryKey tag
110
+ */
111
+ primaryKey: boolean;
112
+ allowNull: boolean;
113
+ /**
114
+ * attribute column name in table
115
+ */
116
+ columnName: string;
117
+ columnType: string;
118
+ type: typeof DataType;
119
+ defaultValue: Literal;
120
+ dataType: string;
121
+ jsType: Literal;
122
+ virtual: boolean;
123
+
124
+ equals(columnInfo: ColumnMeta): boolean;
125
+ cast(value: Literal): Literal;
126
+ uncast(value: Literal): Literal;
127
+ }
128
+
129
+ export class Raw {
130
+ constructor(value: string);
131
+ value: string;
132
+ type: 'raw';
133
+ }
134
+
135
+ export type SetOptions<T extends typeof AbstractBone> = {
136
+ [key: string]: Literal
137
+ } | {
138
+ [Property in keyof Extract<InstanceType<T>, Literal>]: Literal
139
+ };
140
+
141
+ export type WithOptions = {
142
+ [qualifier: string]: { select: string | string[], throughRelation?: string }
143
+ }
144
+
145
+ type OrderOptions<T extends typeof AbstractBone> = {
146
+ [Property in keyof Extract<InstanceType<T>, Literal>]: 'desc' | 'asc'
147
+ } | { [name: string]: 'desc' | 'asc' } | Array<string | string[] | Raw> | string | Raw;
148
+
149
+ export class Collection<T extends AbstractBone> extends Array<T> {
150
+ save(): Promise<void>;
151
+ toJSON(): InstanceValues<T>[];
152
+ toObject(): InstanceValues<T>[];
153
+ }
154
+
155
+ export type WhereConditions<T extends typeof AbstractBone> = {
156
+ [Property in keyof Extract<InstanceType<T>, Literal>]?: Literal | Literal[] | OperatorCondition;
157
+ } | {
158
+ [key in '$and' | '$or']?: WhereConditions<T>[];
159
+ }
160
+
161
+ export type Values<T extends typeof AbstractBone> = {
162
+ [Property in keyof Extract<InstanceType<T>, Literal>]?: Literal;
163
+ }
164
+
165
+ export type InstanceValues<T> = {
166
+ [Property in keyof Extract<T, Literal>]?: Extract<T, Literal>[Property]
167
+ }
168
+
169
+ export type BeforeHooksType = 'beforeCreate' | 'beforeBulkCreate' | 'beforeUpdate' | 'beforeSave' | 'beforeUpsert' | 'beforeRemove';
170
+ export type AfterHooksType = 'afterCreate' | 'afterBulkCreate' | 'afterUpdate' | 'afterSave' | 'afterUpsert' | 'afterRemove';