leoric 1.13.1 → 1.13.5
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 +42 -0
- package/package.json +5 -4
- package/src/adapters/sequelize.js +4 -1
- package/src/bone.js +1 -1
- package/src/data_types.js +46 -12
- package/src/drivers/abstract/attribute.js +4 -2
- package/src/drivers/sqlite/index.js +1 -0
- package/src/expr_formatter.js +12 -10
- package/src/realm.js +8 -1
- package/src/spell.js +1 -1
- package/types/index.d.ts +113 -98
package/History.md
CHANGED
|
@@ -1,3 +1,45 @@
|
|
|
1
|
+
1.13.5 / 2021-10-26
|
|
2
|
+
===================
|
|
3
|
+
|
|
4
|
+
## What's Changed
|
|
5
|
+
* docs: enhance aggregation query types & fix raw query result type by @cyjake in https://github.com/cyjake/leoric/pull/208
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
**Full Changelog**: https://github.com/cyjake/leoric/compare/v1.13.4...v1.13.5
|
|
9
|
+
|
|
10
|
+
1.13.4 / 2021-10-25
|
|
11
|
+
===================
|
|
12
|
+
|
|
13
|
+
## What's Changed
|
|
14
|
+
* docs: spell & model methods should be generic by @cyjake in https://github.com/cyjake/leoric/pull/206
|
|
15
|
+
* docs: enhance query options, instance type, and toJSON() result type by @cyjake in https://github.com/cyjake/leoric/pull/207
|
|
16
|
+
|
|
17
|
+
This version brings correct (and hopefully better) typescript definitions, with the dts checked continuously at test/types tests. With this version, users that have model types correctly pinned at Bone will get code completion including class fields. Such as:
|
|
18
|
+
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+
**Full Changelog**: https://github.com/cyjake/leoric/compare/v1.13.3...v1.13.4
|
|
22
|
+
|
|
23
|
+
1.13.3 / 2021-10-21
|
|
24
|
+
===================
|
|
25
|
+
|
|
26
|
+
## What's Changed
|
|
27
|
+
* refactor: persist edge cases of type casting in integration tests by @cyjake in https://github.com/cyjake/leoric/pull/202
|
|
28
|
+
* docs: renaming attributes by @cyjake in https://github.com/cyjake/leoric/pull/203
|
|
29
|
+
* fix: JSON.uncast(string) should not serialize twice by @cyjake in https://github.com/cyjake/leoric/pull/205
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
**Full Changelog**: https://github.com/cyjake/leoric/compare/v1.13.2...v1.13.3
|
|
33
|
+
|
|
34
|
+
1.13.2 / 2021-10-18
|
|
35
|
+
===================
|
|
36
|
+
|
|
37
|
+
## What's Changed
|
|
38
|
+
* fix: attribute.uncast([]) and realm.connect with synchronized models by @cyjake in https://github.com/cyjake/leoric/pull/201
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
**Full Changelog**: https://github.com/cyjake/leoric/compare/v1.13.1...v1.13.2
|
|
42
|
+
|
|
1
43
|
1.13.1 / 2021-10-18
|
|
2
44
|
===================
|
|
3
45
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leoric",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.5",
|
|
4
4
|
"description": "JavaScript Object-relational mapping alchemy",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"test:mysql2": "./test/start.sh test/integration/mysql2.test.js",
|
|
21
21
|
"test:postgres": "./test/start.sh test/integration/postgres.test.js",
|
|
22
22
|
"test:sqlite": "./test/start.sh test/integration/sqlite.test.js",
|
|
23
|
-
"test:
|
|
23
|
+
"test:sqlcipher": "./test/start.sh test/integration/sqlcipher.test.js",
|
|
24
|
+
"test:dts": "./test/start.sh dts",
|
|
24
25
|
"test:coverage": "nyc ./test/start.sh && nyc report --reporter=lcov",
|
|
25
26
|
"lint": "eslint ./",
|
|
26
27
|
"lint:fix": "eslint . --fix"
|
|
@@ -58,8 +59,8 @@
|
|
|
58
59
|
"@babel/eslint-parser": "^7.14.7",
|
|
59
60
|
"@cara/minami": "^1.2.3",
|
|
60
61
|
"@journeyapps/sqlcipher": "^5.2.0",
|
|
62
|
+
"@types/mocha": "^9.0.0",
|
|
61
63
|
"@types/node": "^16.10.1",
|
|
62
|
-
"coffee": "^5.4.0",
|
|
63
64
|
"dayjs": "^1.10.3",
|
|
64
65
|
"eslint": "^7.20.0",
|
|
65
66
|
"expect.js": "^0.3.1",
|
|
@@ -71,6 +72,6 @@
|
|
|
71
72
|
"pg": "^8.5.1",
|
|
72
73
|
"sinon": "^10.0.0",
|
|
73
74
|
"sqlite3": "^5.0.2",
|
|
74
|
-
"typescript": "^4.4.
|
|
75
|
+
"typescript": "^4.4.4"
|
|
75
76
|
}
|
|
76
77
|
}
|
|
@@ -154,7 +154,10 @@ module.exports = Bone => {
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
static scope(name, ...args) {
|
|
157
|
-
|
|
157
|
+
const parentName = this.name;
|
|
158
|
+
class ScopeClass extends this {
|
|
159
|
+
static name = parentName;
|
|
160
|
+
};
|
|
158
161
|
ScopeClass.setScope(name, ...args);
|
|
159
162
|
return ScopeClass;
|
|
160
163
|
}
|
package/src/bone.js
CHANGED
|
@@ -820,7 +820,7 @@ class Bone {
|
|
|
820
820
|
* restore rows
|
|
821
821
|
* @param {Object} conditions query conditions
|
|
822
822
|
* @param {Object?} opts query options
|
|
823
|
-
* @returns
|
|
823
|
+
* @returns {Spell}
|
|
824
824
|
*/
|
|
825
825
|
static restore(conditions, opts = {}) {
|
|
826
826
|
const { deletedAt } = this.timestamps;
|
package/src/data_types.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const util = require('util');
|
|
3
4
|
const invokable = require('./utils/invokable');
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -66,6 +67,15 @@ class DataType {
|
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Check if params is instance of DataType or not
|
|
72
|
+
* @param {*} params
|
|
73
|
+
* @returns {boolean}
|
|
74
|
+
*/
|
|
75
|
+
static is(params) {
|
|
76
|
+
return params instanceof DataType;
|
|
77
|
+
}
|
|
78
|
+
|
|
69
79
|
/**
|
|
70
80
|
* cast raw data returned from data packet into js type
|
|
71
81
|
*/
|
|
@@ -181,7 +191,10 @@ class INTEGER extends DataType {
|
|
|
181
191
|
}
|
|
182
192
|
|
|
183
193
|
uncast(value) {
|
|
184
|
-
|
|
194
|
+
const originValue = value;
|
|
195
|
+
if (value == null) return value;
|
|
196
|
+
if (typeof value === 'string') value = parseInt(value, 10);
|
|
197
|
+
if (isNaN(value)) throw new Error(util.format('invalid integer: %s', originValue));
|
|
185
198
|
return value;
|
|
186
199
|
}
|
|
187
200
|
}
|
|
@@ -227,27 +240,31 @@ class DATE extends DataType {
|
|
|
227
240
|
}
|
|
228
241
|
|
|
229
242
|
uncast(value) {
|
|
243
|
+
const originValue = value;
|
|
244
|
+
|
|
230
245
|
if (value == null) return value;
|
|
231
246
|
if (typeof value.toDate === 'function') {
|
|
232
247
|
value = value.toDate();
|
|
233
248
|
}
|
|
234
249
|
|
|
250
|
+
// @deprecated
|
|
251
|
+
// vaguely standard date formats such as 2021-10-15 15:50:02,548
|
|
252
|
+
if (typeof value === 'string' && rDateFormat.test(value)) {
|
|
253
|
+
value = new Date(`${value.replace(' ', 'T').replace(',', '.')}Z`);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// 1634611135776
|
|
257
|
+
// '2021-10-15T08:38:43.877Z'
|
|
258
|
+
if (!(value instanceof Date)) value = new Date(value);
|
|
259
|
+
if (isNaN(value)) throw new Error(util.format('invalid date: %s', originValue));
|
|
260
|
+
|
|
235
261
|
const { precision } = this;
|
|
236
|
-
if (
|
|
262
|
+
if (precision < 3) {
|
|
237
263
|
const result = new Date(value);
|
|
238
264
|
result.setMilliseconds(result.getMilliseconds() % (10 ** precision));
|
|
239
265
|
return result;
|
|
240
266
|
}
|
|
241
|
-
|
|
242
|
-
if (typeof value === 'string') {
|
|
243
|
-
// vaguely standard date formats such as 2021-10-15 15:50:02,548
|
|
244
|
-
if (rDateFormat.test(value)) {
|
|
245
|
-
return new Date(`${value.replace(' ', 'T').replace(',', '.')}Z`);
|
|
246
|
-
}
|
|
247
|
-
// Date.parse('2021-10-15T08:38:43.877Z')
|
|
248
|
-
return new Date(value);
|
|
249
|
-
}
|
|
250
|
-
return value instanceof Date ? value : new Date(value);
|
|
267
|
+
return value;
|
|
251
268
|
}
|
|
252
269
|
}
|
|
253
270
|
|
|
@@ -261,12 +278,29 @@ class DATEONLY extends DataType {
|
|
|
261
278
|
return this.dataType.toUpperCase();
|
|
262
279
|
}
|
|
263
280
|
|
|
281
|
+
cast(value) {
|
|
282
|
+
if (value == null) return value;
|
|
283
|
+
if (value instanceof Date) return value;
|
|
284
|
+
return new Date(value);
|
|
285
|
+
}
|
|
286
|
+
|
|
264
287
|
uncast(value) {
|
|
288
|
+
const originValue = value;
|
|
289
|
+
|
|
265
290
|
if (value == null) return value;
|
|
266
291
|
if (typeof value.toDate === 'function') {
|
|
267
292
|
value = value.toDate();
|
|
268
293
|
}
|
|
269
294
|
|
|
295
|
+
// @deprecated
|
|
296
|
+
// vaguely standard date formats such as 2021-10-15 15:50:02,548
|
|
297
|
+
if (typeof value === 'string' && rDateFormat.test(value)) {
|
|
298
|
+
value = new Date(`${value.replace(' ', 'T').replace(',', '.')}Z`);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (!(value instanceof Date)) value = new Date(value);
|
|
302
|
+
if (isNaN(value)) throw new Error(util.format('invalid date: %s', originValue));;
|
|
303
|
+
|
|
270
304
|
return new Date(value.getFullYear(), value.getMonth(), value.getDate());
|
|
271
305
|
}
|
|
272
306
|
}
|
|
@@ -86,7 +86,7 @@ class Attribute {
|
|
|
86
86
|
|
|
87
87
|
// { foo: STRING }
|
|
88
88
|
// { foo: STRING(255) }
|
|
89
|
-
if (typeof params === 'function' || params
|
|
89
|
+
if (typeof params === 'function' || DataTypes.is(params)) {
|
|
90
90
|
params = { type: params };
|
|
91
91
|
}
|
|
92
92
|
const type = createType(DataTypes, params);
|
|
@@ -127,7 +127,9 @@ class Attribute {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
uncast(value) {
|
|
130
|
-
if (Array.isArray(value)
|
|
130
|
+
if (Array.isArray(value) && this.jsType !== JSON) {
|
|
131
|
+
return value.map(entry => this.type.uncast(entry));
|
|
132
|
+
}
|
|
131
133
|
return this.type.uncast(value);
|
|
132
134
|
}
|
|
133
135
|
}
|
package/src/expr_formatter.js
CHANGED
|
@@ -197,16 +197,18 @@ function coerceLiteral(spell, ast) {
|
|
|
197
197
|
const { args } = ast;
|
|
198
198
|
const firstArg = args[0];
|
|
199
199
|
|
|
200
|
-
if (firstArg.type
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}
|
|
200
|
+
if (firstArg.type !== 'id') return;
|
|
201
|
+
|
|
202
|
+
const model = findModel(spell, firstArg.qualifiers);
|
|
203
|
+
const attribute = model && model.attributes[firstArg.value];
|
|
204
|
+
|
|
205
|
+
if (!attribute) return;
|
|
206
|
+
|
|
207
|
+
for (const arg of args.slice(1)) {
|
|
208
|
+
if (arg.type === 'literal') {
|
|
209
|
+
// { params: { $like: '%foo%' } }
|
|
210
|
+
if (attribute.jsType === JSON && typeof arg.value === 'string') continue;
|
|
211
|
+
arg.value = attribute.uncast(arg.value);
|
|
210
212
|
}
|
|
211
213
|
}
|
|
212
214
|
}
|
package/src/realm.js
CHANGED
|
@@ -91,6 +91,10 @@ class Realm {
|
|
|
91
91
|
const Spine = createSpine(opts);
|
|
92
92
|
const models = {};
|
|
93
93
|
|
|
94
|
+
if (Array.isArray(opts.models)) {
|
|
95
|
+
for (const model of opts.models) models[model.name] = model;
|
|
96
|
+
}
|
|
97
|
+
|
|
94
98
|
const driver = new (findDriver(dialect))({
|
|
95
99
|
client,
|
|
96
100
|
database,
|
|
@@ -130,8 +134,11 @@ class Realm {
|
|
|
130
134
|
models = Object.values(this.models);
|
|
131
135
|
}
|
|
132
136
|
|
|
137
|
+
// models could be connected already if cached
|
|
138
|
+
models = models.filter(model => !model.synchronized);
|
|
139
|
+
|
|
133
140
|
if (models.length > 0) {
|
|
134
|
-
await loadModels(this.Bone, models
|
|
141
|
+
await loadModels(this.Bone, models, this.options);
|
|
135
142
|
}
|
|
136
143
|
this.connected = true;
|
|
137
144
|
return this.Bone;
|
package/src/spell.js
CHANGED
|
@@ -65,7 +65,7 @@ function parseSelect(spell, ...names) {
|
|
|
65
65
|
* @param {Spell} spell
|
|
66
66
|
* @param {Object} obj - key-value pairs of attributes
|
|
67
67
|
* @param {boolean} strict - check attribute exist or not
|
|
68
|
-
* @returns
|
|
68
|
+
* @returns {Object}
|
|
69
69
|
*/
|
|
70
70
|
function formatValueSet(spell, obj, strict = true) {
|
|
71
71
|
const { Model, silent = false, command } = spell;
|
package/types/index.d.ts
CHANGED
|
@@ -44,85 +44,89 @@ interface SpellOptions {
|
|
|
44
44
|
rowCount: 0;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
type SpellFactory = (spell: Spell) => Promise<null | number | Collection<Bone> | ResultSet>;
|
|
48
|
-
|
|
49
47
|
type OrderOptions = { [name: string]: 'desc' | 'asc' };
|
|
50
48
|
|
|
51
49
|
type SetOptions = { [key: string]: Literal };
|
|
52
50
|
|
|
53
51
|
type WithOptions = {
|
|
54
|
-
[qualifier: string]: { select: string[], throughRelation
|
|
52
|
+
[qualifier: string]: { select: string | string[], throughRelation?: string }
|
|
55
53
|
}
|
|
56
54
|
|
|
57
|
-
declare class Spell {
|
|
58
|
-
constructor(Model:
|
|
55
|
+
declare class Spell<T extends typeof Bone, U = InstanceType<T> | Collection<InstanceType<T>> | ResultSet | number | null> extends Promise<U> {
|
|
56
|
+
constructor(Model: T, opts: SpellOptions);
|
|
59
57
|
|
|
60
|
-
select(...names: string
|
|
61
|
-
insert(opts: SetOptions): Spell
|
|
62
|
-
update(opts: SetOptions): Spell
|
|
63
|
-
upsert(opts: SetOptions): Spell
|
|
64
|
-
delete(): Spell
|
|
58
|
+
select(...names: Array<string | RawSql>): Spell<T, U>;
|
|
59
|
+
insert(opts: SetOptions): Spell<T, number>;
|
|
60
|
+
update(opts: SetOptions): Spell<T, number>;
|
|
61
|
+
upsert(opts: SetOptions): Spell<T, number>;
|
|
62
|
+
delete(): Spell<T, number>;
|
|
65
63
|
|
|
66
|
-
from(table: string | Spell): Spell
|
|
64
|
+
from(table: string | Spell<T>): Spell<T, U>;
|
|
67
65
|
|
|
68
|
-
with(opts: WithOptions): Spell
|
|
69
|
-
with(...qualifiers: string[]): Spell
|
|
66
|
+
with(opts: WithOptions): Spell<T, U>;
|
|
67
|
+
with(...qualifiers: string[]): Spell<T, U>;
|
|
70
68
|
|
|
71
|
-
join(Model:
|
|
72
|
-
join(Model:
|
|
69
|
+
join<V extends typeof Bone>(Model: V, onConditions: string, ...values: Literal[]): Spell<T, U>;
|
|
70
|
+
join<V extends typeof Bone>(Model: V, onConditions: WhereConditions<T>): Spell<T, U>;
|
|
73
71
|
|
|
74
|
-
where(conditions:
|
|
75
|
-
where(conditions:
|
|
72
|
+
$where(conditions: WhereConditions<T>): this;
|
|
73
|
+
$where(conditions: string, ...values: Literal[]): this;
|
|
74
|
+
where(conditions: WhereConditions<T>): Spell<T, U>;
|
|
75
|
+
where(conditions: string, ...values: Literal[]): Spell<T, U>;
|
|
76
76
|
|
|
77
|
-
orWhere(conditions:
|
|
78
|
-
orWhere(conditions:
|
|
77
|
+
orWhere(conditions: WhereConditions<T>): Spell<T, U>;
|
|
78
|
+
orWhere(conditions: string, ...values: Literal[]): Spell<T, U>;
|
|
79
79
|
|
|
80
|
-
group(...names: string
|
|
80
|
+
group(...names: Array<string | RawSql>): Spell<T, ResultSet>;
|
|
81
81
|
|
|
82
|
-
having(conditions: string, ...values: Literal[]): Spell
|
|
83
|
-
having(conditions: WhereConditions): Spell
|
|
82
|
+
having(conditions: string, ...values: Literal[]): Spell<T, ResultSet>;
|
|
83
|
+
having(conditions: WhereConditions<T>): Spell<T, ResultSet>;
|
|
84
84
|
|
|
85
|
-
orHaving(conditions: string, ...values: Literal[]): Spell
|
|
86
|
-
orHaving(conditions: WhereConditions): Spell
|
|
85
|
+
orHaving(conditions: string, ...values: Literal[]): Spell<T, ResultSet>;
|
|
86
|
+
orHaving(conditions: WhereConditions<T>): Spell<T, ResultSet>;
|
|
87
87
|
|
|
88
|
-
order(name: string, order?: 'desc' | 'asc'): Spell
|
|
89
|
-
order(opts: OrderOptions): Spell
|
|
88
|
+
order(name: string, order?: 'desc' | 'asc'): Spell<T, U>;
|
|
89
|
+
order(opts: OrderOptions): Spell<T, U>;
|
|
90
90
|
|
|
91
|
-
offset(skip: number): Spell
|
|
92
|
-
limit(skip: number): Spell
|
|
91
|
+
offset(skip: number): Spell<T, U>;
|
|
92
|
+
limit(skip: number): Spell<T, U>;
|
|
93
93
|
|
|
94
|
-
count(name?: string): Spell
|
|
95
|
-
average(name?: string): Spell
|
|
96
|
-
minimum(name?: string): Spell
|
|
97
|
-
maximum(name?: string): Spell
|
|
98
|
-
sum(name?: string): Spell
|
|
94
|
+
count(name?: string): Spell<T, Extract<U, ResultSet | number>>;
|
|
95
|
+
average(name?: string): Spell<T, Extract<U, ResultSet | number>>;
|
|
96
|
+
minimum(name?: string): Spell<T, Extract<U, ResultSet | number>>;
|
|
97
|
+
maximum(name?: string): Spell<T, Extract<U, ResultSet | number>>;
|
|
98
|
+
sum(name?: string): Spell<T, Extract<U, ResultSet | number>>;
|
|
99
99
|
|
|
100
|
-
batch(size?: number): AsyncIterable<
|
|
100
|
+
batch(size?: number): AsyncIterable<T>;
|
|
101
101
|
|
|
102
102
|
toSqlString(): string;
|
|
103
103
|
toString(): string;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
type Literal = null | boolean | number | string | Date |
|
|
106
|
+
type Literal = null | undefined | boolean | number | string | Date | object | ArrayBuffer;
|
|
107
107
|
|
|
108
108
|
type OperatorCondition = {
|
|
109
109
|
[key in '$eq' | '$ne']?: Literal;
|
|
110
110
|
} & {
|
|
111
111
|
[key in '$in' | '$nin' | '$notIn']?: Literal[] | Set<Literal>;
|
|
112
112
|
} & {
|
|
113
|
-
[key in '$like' | '$notLike']?:
|
|
113
|
+
[key in '$like' | '$notLike']?: string;
|
|
114
114
|
} & {
|
|
115
115
|
[key in '$gt' | '$gte' | '$lt' | '$lte']?: number;
|
|
116
116
|
} & {
|
|
117
117
|
[key in '$between' | '$notBetween']?: [number, number] | [Date, Date];
|
|
118
118
|
};
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
[
|
|
120
|
+
type WhereConditions<T extends typeof Bone> = {
|
|
121
|
+
[Property in keyof T['attributes']]?: Literal | Literal[] | OperatorCondition;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
type Values<T extends typeof Bone> = {
|
|
125
|
+
[Property in keyof T['attributes']]?: Literal;
|
|
122
126
|
}
|
|
123
127
|
|
|
124
|
-
|
|
125
|
-
[
|
|
128
|
+
type InstanceValues<T> = {
|
|
129
|
+
[Property in keyof Extract<T, Literal>]?: Extract<T, Literal>[Property]
|
|
126
130
|
}
|
|
127
131
|
|
|
128
132
|
declare class DataType {}
|
|
@@ -148,10 +152,17 @@ interface RelateOptions {
|
|
|
148
152
|
}
|
|
149
153
|
|
|
150
154
|
interface QueryOptions {
|
|
151
|
-
validate?: boolean
|
|
152
|
-
individualHooks?: boolean
|
|
153
|
-
hooks?: boolean
|
|
154
|
-
paranoid?: boolean
|
|
155
|
+
validate?: boolean;
|
|
156
|
+
individualHooks?: boolean;
|
|
157
|
+
hooks?: boolean;
|
|
158
|
+
paranoid?: boolean;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
interface QueryResult {
|
|
162
|
+
insertId?: number;
|
|
163
|
+
affectedRows?: number;
|
|
164
|
+
rows?: Array<Record<string, Literal>>,
|
|
165
|
+
fields?: Array<{ table: string, name: string }>,
|
|
155
166
|
}
|
|
156
167
|
|
|
157
168
|
interface Connection {
|
|
@@ -160,9 +171,8 @@ interface Connection {
|
|
|
160
171
|
*/
|
|
161
172
|
query(
|
|
162
173
|
query: string,
|
|
163
|
-
values: Array<Literal>,
|
|
164
|
-
|
|
165
|
-
): void;
|
|
174
|
+
values: Array<Literal | Literal[]>,
|
|
175
|
+
): Promise<QueryResult>;
|
|
166
176
|
}
|
|
167
177
|
|
|
168
178
|
declare class Pool {
|
|
@@ -188,19 +198,19 @@ declare class Driver {
|
|
|
188
198
|
/**
|
|
189
199
|
* Grab a connection and query the database
|
|
190
200
|
*/
|
|
191
|
-
query(sql: string, values
|
|
201
|
+
query(sql: string, values?: Array<Literal | Literal[]>): Promise<QueryResult>;
|
|
192
202
|
}
|
|
193
203
|
|
|
194
|
-
type ResultSet =
|
|
204
|
+
type ResultSet = {
|
|
205
|
+
[key: string]: Literal
|
|
206
|
+
};
|
|
195
207
|
|
|
196
|
-
declare class Collection<Bone> extends Array<
|
|
208
|
+
declare class Collection<T extends Bone> extends Array<T> {
|
|
197
209
|
save(): Promise<void>;
|
|
198
210
|
toJSON(): Object[];
|
|
199
211
|
toObject(): Object[];
|
|
200
212
|
}
|
|
201
213
|
|
|
202
|
-
type Query = Spell & Promise<Collection<Bone>>;
|
|
203
|
-
|
|
204
214
|
export class Bone {
|
|
205
215
|
/**
|
|
206
216
|
* The connection pool of the specified client, with few `Leoric_` prefixed methods extended to eliminate client differences.
|
|
@@ -218,7 +228,7 @@ export class Bone {
|
|
|
218
228
|
static model: { [key: string]: Bone };
|
|
219
229
|
|
|
220
230
|
/**
|
|
221
|
-
* The table name of
|
|
231
|
+
* The table name of the model, which needs to be specified by the model subclass.
|
|
222
232
|
*/
|
|
223
233
|
static table: string;
|
|
224
234
|
|
|
@@ -228,10 +238,15 @@ export class Bone {
|
|
|
228
238
|
static tableAlias: string;
|
|
229
239
|
|
|
230
240
|
/**
|
|
231
|
-
* The primary key of
|
|
241
|
+
* The primary key of the model, defaults to `id`.
|
|
232
242
|
*/
|
|
233
243
|
static primaryKey: string;
|
|
234
244
|
|
|
245
|
+
/**
|
|
246
|
+
* The primary column of the table, defaults to `id`. This is {@link Bone.primaryKey} in snake case.
|
|
247
|
+
*/
|
|
248
|
+
static primaryColumn: string;
|
|
249
|
+
|
|
235
250
|
/**
|
|
236
251
|
* The attribute definitions of the model.
|
|
237
252
|
*/
|
|
@@ -260,7 +275,7 @@ export class Bone {
|
|
|
260
275
|
* @param conditions query conditions
|
|
261
276
|
* @param opts query options
|
|
262
277
|
*/
|
|
263
|
-
static restore(conditions: Object, opts?: QueryOptions): Spell
|
|
278
|
+
static restore<T extends typeof Bone>(this: T, conditions: Object, opts?: QueryOptions): Spell<T, number>;
|
|
264
279
|
|
|
265
280
|
/**
|
|
266
281
|
* Override attribute metadata
|
|
@@ -288,7 +303,7 @@ export class Bone {
|
|
|
288
303
|
* @example
|
|
289
304
|
* Bone.create({ foo: 1, bar: 'baz' })
|
|
290
305
|
*/
|
|
291
|
-
static create(values: Values
|
|
306
|
+
static create<T extends typeof Bone>(this: T, values: Values<T>, options?: QueryOptions): Promise<InstanceType<T>>;
|
|
292
307
|
|
|
293
308
|
/**
|
|
294
309
|
* INSERT or UPDATE rows
|
|
@@ -297,12 +312,12 @@ export class Bone {
|
|
|
297
312
|
* @param values values
|
|
298
313
|
* @param opt query options
|
|
299
314
|
*/
|
|
300
|
-
static upsert(values: Object, options?: QueryOptions): Spell
|
|
315
|
+
static upsert<T extends typeof Bone>(this: T, values: Object, options?: QueryOptions): Spell<T, number>;
|
|
301
316
|
|
|
302
317
|
/**
|
|
303
318
|
* Batch INSERT
|
|
304
319
|
*/
|
|
305
|
-
static bulkCreate(records: Array<Record<string, Literal>>, options?: QueryOptions): Promise<Array<
|
|
320
|
+
static bulkCreate<T extends typeof Bone>(this: T, records: Array<Record<string, Literal>>, options?: QueryOptions): Promise<Array<InstanceType<T>>>;
|
|
306
321
|
|
|
307
322
|
/**
|
|
308
323
|
* SELECT rows
|
|
@@ -310,21 +325,21 @@ export class Bone {
|
|
|
310
325
|
* Bone.find('foo = ?', 1)
|
|
311
326
|
* Bone.find({ foo: { $eq: 1 } })
|
|
312
327
|
*/
|
|
313
|
-
static find(
|
|
314
|
-
static find(whereConditions:
|
|
315
|
-
static find():
|
|
328
|
+
static find<T extends typeof Bone>(this: T, whereConditions: WhereConditions<T>): Spell<T, Collection<InstanceType<T>>>;
|
|
329
|
+
static find<T extends typeof Bone>(this: T, whereConditions: string, ...values: Literal[]): Spell<T, Collection<InstanceType<T>>>;
|
|
330
|
+
static find<T extends typeof Bone>(this: T, ): Spell<T, Collection<InstanceType<T>>>;
|
|
316
331
|
|
|
317
332
|
/**
|
|
318
333
|
* 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.
|
|
319
334
|
*/
|
|
320
|
-
static all:
|
|
335
|
+
static all: Spell<typeof Bone, Collection<Bone>>;
|
|
321
336
|
|
|
322
337
|
/**
|
|
323
338
|
* Discard all the applied scopes.
|
|
324
339
|
* @example
|
|
325
340
|
* Bone.all.unscoped // includes soft deleted rows
|
|
326
341
|
*/
|
|
327
|
-
static unscoped:
|
|
342
|
+
static unscoped: Spell<typeof Bone>;
|
|
328
343
|
|
|
329
344
|
/**
|
|
330
345
|
* SELECT rows LIMIT 1. Besides limiting the results to one rows, the type of the return value is different from {@link Bone.find} too. If no results were found, {@link Bone.findOne} returns null. If results were found, it returns the found record instead of wrapping them as a collection.
|
|
@@ -332,9 +347,9 @@ export class Bone {
|
|
|
332
347
|
* Bone.findOne('foo = ?', 1)
|
|
333
348
|
* Bone.findOne({ foo: { $eq: 1 } })
|
|
334
349
|
*/
|
|
335
|
-
static findOne(
|
|
336
|
-
static findOne(whereConditions:
|
|
337
|
-
static findOne(): Spell
|
|
350
|
+
static findOne<T extends typeof Bone>(this: T, whereConditions: WhereConditions<T>): Spell<T, InstanceType<T> | null>;
|
|
351
|
+
static findOne<T extends typeof Bone>(this: T, whereConditions: string, ...values: Literal[]): Spell<T, InstanceType<T> | null>;
|
|
352
|
+
static findOne<T extends typeof Bone>(this: T, ): Spell<T, InstanceType<T> | null>;
|
|
338
353
|
|
|
339
354
|
/**
|
|
340
355
|
* SELECT rows OFFSET index LIMIT 1
|
|
@@ -342,24 +357,24 @@ export class Bone {
|
|
|
342
357
|
* Bone.get(8)
|
|
343
358
|
* Bone.find({ foo: { $gt: 1 } }).get(42)
|
|
344
359
|
*/
|
|
345
|
-
static get(index: number): Spell
|
|
360
|
+
static get<T extends typeof Bone>(this: T, index: number): Spell<T, InstanceType<T> | null>;
|
|
346
361
|
|
|
347
362
|
/**
|
|
348
363
|
* SELECT rows ORDER BY id ASC LIMIT 1
|
|
349
364
|
*/
|
|
350
|
-
static first: Spell
|
|
365
|
+
static first: Spell<typeof Bone, Bone | null>;
|
|
351
366
|
|
|
352
367
|
/**
|
|
353
368
|
* SELECT rows ORDER BY id DESC LIMIT 1
|
|
354
369
|
*/
|
|
355
|
-
static last: Spell
|
|
370
|
+
static last: Spell<typeof Bone, Bone | null>;
|
|
356
371
|
|
|
357
372
|
/**
|
|
358
373
|
* Short of `Bone.find().with(...names)`
|
|
359
374
|
* @example
|
|
360
375
|
* Post.include('author', 'comments').where('posts.id = ?', 1)
|
|
361
376
|
*/
|
|
362
|
-
static include(...names: string[]) :
|
|
377
|
+
static include<T extends typeof Bone>(this: T, ...names: string[]) : Spell<T>;
|
|
363
378
|
|
|
364
379
|
/**
|
|
365
380
|
* Whitelist SELECT fields by names or filter function
|
|
@@ -370,16 +385,16 @@ export class Bone {
|
|
|
370
385
|
* Bone.select('MONTH(date), foo + 1')
|
|
371
386
|
* Bone.select(name => name !== foo)
|
|
372
387
|
*/
|
|
373
|
-
static select(...names: string[]):
|
|
374
|
-
static select(filter: (name: string) => boolean):
|
|
388
|
+
static select<T extends typeof Bone>(this: T, ...names: string[]): Spell<T>;
|
|
389
|
+
static select<T extends typeof Bone>(this: T, filter: (name: string) => boolean): Spell<T>;
|
|
375
390
|
|
|
376
391
|
/**
|
|
377
392
|
* JOIN arbitrary models with given ON conditions
|
|
378
393
|
* @example
|
|
379
394
|
* Bone.join(Muscle, 'bones.id == muscles.boneId')
|
|
380
395
|
*/
|
|
381
|
-
static join(Model: Bone, onConditions: string, ...values: Literal[]):
|
|
382
|
-
static join(Model: Bone, onConditions: WhereConditions):
|
|
396
|
+
static join<T extends typeof Bone>(this: T, Model: Bone, onConditions: string, ...values: Literal[]): Spell<T, Collection<InstanceType<T>>>;
|
|
397
|
+
static join<T extends typeof Bone>(this: T, Model: Bone, onConditions: WhereConditions<T>): Spell<T, Collection<InstanceType<T>>>;
|
|
383
398
|
|
|
384
399
|
/**
|
|
385
400
|
* Set WHERE conditions
|
|
@@ -387,8 +402,8 @@ export class Bone {
|
|
|
387
402
|
* Bone.where('foo = ?', 1)
|
|
388
403
|
* Bone.where({ foo: { $eq: 1 } })
|
|
389
404
|
*/
|
|
390
|
-
static where(whereConditions: string, ...values: Literal[]):
|
|
391
|
-
static where(whereConditions: WhereConditions):
|
|
405
|
+
static where<T extends typeof Bone>(this: T, whereConditions: string, ...values: Literal[]): Spell<T, Collection<InstanceType<T>>>;
|
|
406
|
+
static where<T extends typeof Bone>(this: T, whereConditions: WhereConditions<T>): Spell<T, Collection<InstanceType<T>>>;
|
|
392
407
|
|
|
393
408
|
/**
|
|
394
409
|
* Set GROUP fields
|
|
@@ -396,7 +411,7 @@ export class Bone {
|
|
|
396
411
|
* Bone.group('foo')
|
|
397
412
|
* Bone.group('MONTH(createdAt)')
|
|
398
413
|
*/
|
|
399
|
-
static group(...names: string[]): Spell
|
|
414
|
+
static group<T extends typeof Bone>(this: T, ...names: string[]): Spell<T, ResultSet>;
|
|
400
415
|
|
|
401
416
|
/**
|
|
402
417
|
* Set ORDER fields
|
|
@@ -405,24 +420,24 @@ export class Bone {
|
|
|
405
420
|
* Bone.order('foo', 'desc')
|
|
406
421
|
* Bone.order({ foo: 'desc' })
|
|
407
422
|
*/
|
|
408
|
-
static order(name: string, order?: 'desc' | 'asc'):
|
|
409
|
-
static order(opts: OrderOptions):
|
|
423
|
+
static order<T extends typeof Bone>(this: T, name: string, order?: 'desc' | 'asc'): Spell<T>;
|
|
424
|
+
static order<T extends typeof Bone>(this: T, opts: OrderOptions): Spell<T>;
|
|
410
425
|
|
|
411
|
-
static count(name?: string): Spell
|
|
412
|
-
static average(name?: string): Spell
|
|
413
|
-
static minimum(name?: string): Spell
|
|
414
|
-
static maximum(name?: string): Spell
|
|
415
|
-
static sum(name?: string): Spell
|
|
426
|
+
static count<T extends typeof Bone>(this: T, name?: string): Spell<T, ResultSet | number>;
|
|
427
|
+
static average<T extends typeof Bone>(this: T, name?: string): Spell<T, ResultSet | number>;
|
|
428
|
+
static minimum<T extends typeof Bone>(this: T, name?: string): Spell<T, ResultSet | number>;
|
|
429
|
+
static maximum<T extends typeof Bone>(this: T, name?: string): Spell<T, ResultSet | number>;
|
|
430
|
+
static sum<T extends typeof Bone>(this: T, name?: string): Spell<T, ResultSet | number>;
|
|
416
431
|
|
|
417
432
|
/**
|
|
418
433
|
* UPDATE rows.
|
|
419
434
|
*/
|
|
420
|
-
static update(whereConditions: WhereConditions
|
|
435
|
+
static update<T extends typeof Bone>(this: T, whereConditions: WhereConditions<T>, values?: Object, opts?: QueryOptions): Spell<T, number>;
|
|
421
436
|
|
|
422
437
|
/**
|
|
423
438
|
* 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.
|
|
424
439
|
*/
|
|
425
|
-
static remove(whereConditions: WhereConditions
|
|
440
|
+
static remove<T extends typeof Bone>(this: T, whereConditions: WhereConditions<T>, forceDelete?: boolean, opt?: QueryOptions): Spell<T, number>;
|
|
426
441
|
|
|
427
442
|
/**
|
|
428
443
|
* 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.
|
|
@@ -445,7 +460,7 @@ export class Bone {
|
|
|
445
460
|
*/
|
|
446
461
|
static truncate(): Promise<void>;
|
|
447
462
|
|
|
448
|
-
constructor(values:
|
|
463
|
+
constructor(values: { [key: string]: Literal });
|
|
449
464
|
|
|
450
465
|
/**
|
|
451
466
|
* Get or set attribute value. Getting the value of unset attribute gives an error.
|
|
@@ -511,8 +526,8 @@ export class Bone {
|
|
|
511
526
|
* bone.remove(true) // => DELETE FROM ... WHERE ...
|
|
512
527
|
* bone.remove(true, { hooks: false })
|
|
513
528
|
*/
|
|
514
|
-
remove(forceDelete?: boolean):
|
|
515
|
-
remove(forceDelete?: boolean, opts?: QueryOptions):
|
|
529
|
+
remove(forceDelete?: boolean): Promise<number>;
|
|
530
|
+
remove(forceDelete?: boolean, opts?: QueryOptions): Promise<number>;
|
|
516
531
|
|
|
517
532
|
/**
|
|
518
533
|
* update or insert record.
|
|
@@ -521,31 +536,31 @@ export class Bone {
|
|
|
521
536
|
* bone.upsert({ hooks: false })
|
|
522
537
|
* @param opts queryOptions
|
|
523
538
|
*/
|
|
524
|
-
upsert(opts?: QueryOptions):
|
|
539
|
+
upsert(opts?: QueryOptions): Promise<number>;
|
|
525
540
|
|
|
526
541
|
/**
|
|
527
542
|
* update rows
|
|
528
543
|
* @param changes data changes
|
|
529
544
|
* @param opts query options
|
|
530
545
|
*/
|
|
531
|
-
update(changes: Object, opts?: QueryOptions):
|
|
546
|
+
update(changes: Object, opts?: QueryOptions): Promise<number>;
|
|
532
547
|
|
|
533
548
|
/**
|
|
534
549
|
* create instance
|
|
535
550
|
* @param opts query options
|
|
536
551
|
*/
|
|
537
|
-
create(opts?: QueryOptions):
|
|
552
|
+
create(opts?: QueryOptions): Promise<this>;
|
|
538
553
|
|
|
539
554
|
/**
|
|
540
555
|
* reload instance
|
|
541
556
|
*/
|
|
542
|
-
reload(): Promise<
|
|
557
|
+
reload(): Promise<this>;
|
|
543
558
|
|
|
544
559
|
/**
|
|
545
560
|
* restore data
|
|
546
561
|
* @param opts query options
|
|
547
562
|
*/
|
|
548
|
-
restore(opts?: QueryOptions): Promise<
|
|
563
|
+
restore(opts?: QueryOptions): Promise<this>;
|
|
549
564
|
|
|
550
565
|
/**
|
|
551
566
|
* Gets called when `JSON.stringify(instance)` is invoked.
|
|
@@ -556,7 +571,7 @@ export class Bone {
|
|
|
556
571
|
* post.toJSON() // => { id: 1, ... }
|
|
557
572
|
* @return {Object}
|
|
558
573
|
*/
|
|
559
|
-
toJSON():
|
|
574
|
+
toJSON(): InstanceValues<this>;
|
|
560
575
|
|
|
561
576
|
/**
|
|
562
577
|
* 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).
|
|
@@ -567,7 +582,7 @@ export class Bone {
|
|
|
567
582
|
* post.toObject() // => { id: 1, ... }
|
|
568
583
|
* @return {Object}
|
|
569
584
|
*/
|
|
570
|
-
toObject():
|
|
585
|
+
toObject(): InstanceValues<this>;
|
|
571
586
|
}
|
|
572
587
|
|
|
573
588
|
interface ConnectOptions {
|
|
@@ -576,7 +591,7 @@ interface ConnectOptions {
|
|
|
576
591
|
host?: string;
|
|
577
592
|
user?: string;
|
|
578
593
|
database: string;
|
|
579
|
-
models?: string | Bone[];
|
|
594
|
+
models?: string | (typeof Bone)[];
|
|
580
595
|
}
|
|
581
596
|
|
|
582
597
|
interface InitOptions {
|
|
@@ -596,7 +611,7 @@ type RawSql = {
|
|
|
596
611
|
};
|
|
597
612
|
|
|
598
613
|
interface RawQueryOptions {
|
|
599
|
-
replacements?:
|
|
614
|
+
replacements?: { [key:string]: Literal | Literal[] };
|
|
600
615
|
model: Bone;
|
|
601
616
|
connection: Connection;
|
|
602
617
|
}
|