@igojs/db 6.0.0-beta.7 → 6.0.0-beta.8
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/package.json +1 -1
- package/src/Model.js +16 -10
- package/src/PaginatedOptimizedQuery.js +4 -0
- package/src/Query.js +29 -3
- package/test/JoinTest.js +34 -0
- package/test/ModelTest.js +83 -3
package/package.json
CHANGED
package/src/Model.js
CHANGED
|
@@ -40,7 +40,7 @@ module.exports = function(schema) {
|
|
|
40
40
|
await this.beforeUpdate(values);
|
|
41
41
|
|
|
42
42
|
await newQuery(this.constructor, 'update')
|
|
43
|
-
.
|
|
43
|
+
.unscope()
|
|
44
44
|
.values(values)
|
|
45
45
|
.where(this.primaryObject())
|
|
46
46
|
.execute();
|
|
@@ -56,14 +56,14 @@ module.exports = function(schema) {
|
|
|
56
56
|
|
|
57
57
|
// reload
|
|
58
58
|
async reload(includes) {
|
|
59
|
-
const query = this.constructor.
|
|
59
|
+
const query = this.constructor.unscope();
|
|
60
60
|
includes && query.includes(includes);
|
|
61
61
|
return await query.find(this.id);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
// delete
|
|
65
65
|
delete() {
|
|
66
|
-
return newQuery(this.constructor, 'delete').
|
|
66
|
+
return newQuery(this.constructor, 'delete').unscope().where(this.primaryObject()).execute();
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
async beforeCreate() { }
|
|
@@ -101,9 +101,9 @@ module.exports = function(schema) {
|
|
|
101
101
|
|
|
102
102
|
const { insertId } = result;
|
|
103
103
|
if (insertId) {
|
|
104
|
-
return _this.
|
|
104
|
+
return _this.unscope().find(insertId);
|
|
105
105
|
}
|
|
106
|
-
return _this.
|
|
106
|
+
return _this.unscope().find(obj.primaryObject());
|
|
107
107
|
};
|
|
108
108
|
|
|
109
109
|
return await create();
|
|
@@ -177,12 +177,12 @@ module.exports = function(schema) {
|
|
|
177
177
|
|
|
178
178
|
// delete
|
|
179
179
|
static delete(id, ) {
|
|
180
|
-
return newQuery(this, 'delete').
|
|
180
|
+
return newQuery(this, 'delete').unscope().where({ id: id }).execute();
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
// delete all
|
|
184
184
|
static async deleteAll() {
|
|
185
|
-
return newQuery(this, 'delete').
|
|
185
|
+
return newQuery(this, 'delete').unscope().execute();
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
// destroy all
|
|
@@ -193,7 +193,7 @@ module.exports = function(schema) {
|
|
|
193
193
|
//
|
|
194
194
|
static update(values, ) {
|
|
195
195
|
values.updated_at = new Date();
|
|
196
|
-
return newQuery(this).
|
|
196
|
+
return newQuery(this).unscope().update(values, );
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
// includes
|
|
@@ -214,9 +214,15 @@ module.exports = function(schema) {
|
|
|
214
214
|
console.warn('Invalid join argument for Model.join(). Must be a string, array, or object.');
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
//unscoped
|
|
217
|
+
// unscoped (deprecated, use unscope())
|
|
218
218
|
static unscoped() {
|
|
219
|
-
|
|
219
|
+
console.warn('Model.unscoped() is deprecated, use unscope() instead.');
|
|
220
|
+
return this.unscope();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// unscope
|
|
224
|
+
static unscope(...clauses) {
|
|
225
|
+
return newQuery(this).unscope(...clauses);
|
|
220
226
|
}
|
|
221
227
|
|
|
222
228
|
//scope
|
|
@@ -402,6 +402,10 @@ module.exports = class PaginatedOptimizedQuery extends Query {
|
|
|
402
402
|
fullQuery.query = _.cloneDeep(this.query);
|
|
403
403
|
fullQuery.query.verb = 'select';
|
|
404
404
|
|
|
405
|
+
// Restaurer les joins originaux : _.cloneDeep crée de nouveaux objets pour src_schema,
|
|
406
|
+
// ce qui casse les lookups par identité (===) dans le Map de Query.execute()
|
|
407
|
+
fullQuery.query.joins = this.query.joins;
|
|
408
|
+
|
|
405
409
|
// Conserver uniquement les "vrais" joins (pas les filterJoins)
|
|
406
410
|
// Les filterJoins ne sont utilisés que pour COUNT et IDS
|
|
407
411
|
fullQuery.query.filterJoins = [];
|
package/src/Query.js
CHANGED
|
@@ -50,7 +50,8 @@ module.exports = class Query {
|
|
|
50
50
|
group: null,
|
|
51
51
|
includes: {},
|
|
52
52
|
options: {},
|
|
53
|
-
scopes: [ 'default' ]
|
|
53
|
+
scopes: [ 'default' ],
|
|
54
|
+
unscopes: []
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
// filter on subclass
|
|
@@ -153,9 +154,19 @@ module.exports = class Query {
|
|
|
153
154
|
return this;
|
|
154
155
|
}
|
|
155
156
|
|
|
156
|
-
// UNSCOPED
|
|
157
|
+
// UNSCOPED (deprecated, use unscope())
|
|
157
158
|
unscoped() {
|
|
158
|
-
|
|
159
|
+
console.warn('Query.unscoped() is deprecated, use unscope() instead.');
|
|
160
|
+
return this.unscope();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// UNSCOPE
|
|
164
|
+
unscope(...clauses) {
|
|
165
|
+
if (clauses.length === 0) {
|
|
166
|
+
this.query.scopes.length = 0;
|
|
167
|
+
} else {
|
|
168
|
+
this.query.unscopes.push(...clauses);
|
|
169
|
+
}
|
|
159
170
|
return this;
|
|
160
171
|
}
|
|
161
172
|
|
|
@@ -265,6 +276,21 @@ module.exports = class Query {
|
|
|
265
276
|
}
|
|
266
277
|
schema.scopes[scope](this);
|
|
267
278
|
});
|
|
279
|
+
// Apply unscopes after scopes
|
|
280
|
+
for (const clause of query.unscopes) {
|
|
281
|
+
switch (clause) {
|
|
282
|
+
case 'where': query.where = []; break;
|
|
283
|
+
case 'whereNot': query.whereNot = []; break;
|
|
284
|
+
case 'order': query.order = []; break;
|
|
285
|
+
case 'includes': query.includes = {}; break;
|
|
286
|
+
case 'joins': query.joins = []; break;
|
|
287
|
+
case 'select': query.select = null; break;
|
|
288
|
+
case 'distinct': query.distinct = null; break;
|
|
289
|
+
case 'group': query.group = null; break;
|
|
290
|
+
case 'limit': delete query.limit; break;
|
|
291
|
+
case 'offset': delete query.offset; break;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
268
294
|
}
|
|
269
295
|
|
|
270
296
|
// INCLUDES
|
package/test/JoinTest.js
CHANGED
|
@@ -235,4 +235,38 @@ describe('includes', () => {
|
|
|
235
235
|
});
|
|
236
236
|
});
|
|
237
237
|
|
|
238
|
+
describe('paginatedOptimized join', () => {
|
|
239
|
+
it('should attach joined data in selectFull phase (cloneDeep regression)', async () => {
|
|
240
|
+
const city = await City.create({ name: 'Paris' });
|
|
241
|
+
const library = await Library.create({ title: 'BNF', city_id: city.id });
|
|
242
|
+
const book = await Book.create({ library_id: library.id });
|
|
243
|
+
|
|
244
|
+
const books = await Book.paginatedOptimized()
|
|
245
|
+
.join('library')
|
|
246
|
+
.limit(10)
|
|
247
|
+
.list();
|
|
248
|
+
|
|
249
|
+
assert.strictEqual(books.length, 1);
|
|
250
|
+
assert.strictEqual(books[0].id, book.id);
|
|
251
|
+
assert.strictEqual(books[0].library.id, library.id);
|
|
252
|
+
assert.strictEqual(books[0].library.title, 'BNF');
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('should attach nested joined data in selectFull phase', async () => {
|
|
256
|
+
const city = await City.create({ name: 'Lyon' });
|
|
257
|
+
const library = await Library.create({ title: 'Municipale', city_id: city.id });
|
|
258
|
+
const book = await Book.create({ library_id: library.id });
|
|
259
|
+
|
|
260
|
+
const books = await Book.paginatedOptimized()
|
|
261
|
+
.join({ library: 'city' })
|
|
262
|
+
.limit(10)
|
|
263
|
+
.list();
|
|
264
|
+
|
|
265
|
+
assert.strictEqual(books.length, 1);
|
|
266
|
+
assert.strictEqual(books[0].library.id, library.id);
|
|
267
|
+
assert.strictEqual(books[0].library.city.id, city.id);
|
|
268
|
+
assert.strictEqual(books[0].library.city.name, 'Lyon');
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
238
272
|
});
|
package/test/ModelTest.js
CHANGED
|
@@ -182,7 +182,7 @@ describe('db.Model', () => {
|
|
|
182
182
|
const first = await Book.create();
|
|
183
183
|
const hibook = await Book.create({title: 'hi'});
|
|
184
184
|
await Book.create();
|
|
185
|
-
const book = await Book.
|
|
185
|
+
const book = await Book.unscope().first();
|
|
186
186
|
assert.strictEqual(first.id, book.id);
|
|
187
187
|
assert.strictEqual('hi', hibook.title);
|
|
188
188
|
});
|
|
@@ -203,7 +203,7 @@ describe('db.Model', () => {
|
|
|
203
203
|
await Book.create();
|
|
204
204
|
await Book.create();
|
|
205
205
|
const last = await Book.create();
|
|
206
|
-
const book = await Book.
|
|
206
|
+
const book = await Book.unscope().last();
|
|
207
207
|
assert.strictEqual(last.id, book.id);
|
|
208
208
|
});
|
|
209
209
|
});
|
|
@@ -374,11 +374,91 @@ describe('db.Model', () => {
|
|
|
374
374
|
it('should use a scope', async () => {
|
|
375
375
|
await BookWithScopes.create({code: 'a'});
|
|
376
376
|
await BookWithScopes.create({code: 'abc'});
|
|
377
|
-
const books = await BookWithScopes.
|
|
377
|
+
const books = await BookWithScopes.unscope().scope('a').list();
|
|
378
378
|
assert.strictEqual(books.length, 1);
|
|
379
379
|
});
|
|
380
380
|
});
|
|
381
381
|
|
|
382
|
+
describe('unscope', () => {
|
|
383
|
+
|
|
384
|
+
class Library extends Model({
|
|
385
|
+
table: 'libraries',
|
|
386
|
+
primary: ['id'],
|
|
387
|
+
columns: ['id', 'title'],
|
|
388
|
+
}) {}
|
|
389
|
+
|
|
390
|
+
const scopedSchema = {
|
|
391
|
+
table: 'books',
|
|
392
|
+
primary: ['id'],
|
|
393
|
+
columns: [
|
|
394
|
+
'id',
|
|
395
|
+
'code',
|
|
396
|
+
'title',
|
|
397
|
+
{name: 'details_json', type: 'json', attr: 'details'},
|
|
398
|
+
{name:'is_available', type: 'boolean'},
|
|
399
|
+
'library_id',
|
|
400
|
+
'created_at'
|
|
401
|
+
],
|
|
402
|
+
associations: () => ([
|
|
403
|
+
['belongs_to', 'library', Library, 'library_id', 'id'],
|
|
404
|
+
]),
|
|
405
|
+
scopes: {
|
|
406
|
+
default: query => query.where({ code: 'abc' }).order('`created_at` DESC').includes('library'),
|
|
407
|
+
active: query => query.where({ is_available: true }),
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
class ScopedBook extends Model(scopedSchema) {}
|
|
412
|
+
|
|
413
|
+
it('unscope() without args should remove all scopes', async () => {
|
|
414
|
+
await ScopedBook.create({ code: 'a' });
|
|
415
|
+
await ScopedBook.create({ code: 'abc' });
|
|
416
|
+
const books = await ScopedBook.unscope().list();
|
|
417
|
+
assert.strictEqual(books.length, 2);
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it('unscope("where") should remove where added by scope', async () => {
|
|
421
|
+
await ScopedBook.create({ code: 'a' });
|
|
422
|
+
await ScopedBook.create({ code: 'abc' });
|
|
423
|
+
const books = await ScopedBook.unscope('where').list();
|
|
424
|
+
assert.strictEqual(books.length, 2);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it('unscope("includes") should remove includes added by scope', async () => {
|
|
428
|
+
const library = await Library.create({ title: 'Main' });
|
|
429
|
+
await ScopedBook.create({ code: 'abc', library_id: library.id });
|
|
430
|
+
const books = await ScopedBook.unscope('includes').list();
|
|
431
|
+
assert.strictEqual(books.length, 1);
|
|
432
|
+
assert.strictEqual(books[0].library, undefined);
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
it('unscope("order") should remove order added by scope', async () => {
|
|
436
|
+
const b1 = await ScopedBook.create({ code: 'abc' });
|
|
437
|
+
const b2 = await ScopedBook.create({ code: 'abc' });
|
|
438
|
+
const books = await ScopedBook.unscope('order').list();
|
|
439
|
+
// without DESC order, should be ASC (default)
|
|
440
|
+
assert(books[0].id <= books[1].id);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
it('unscope("where", "order") should remove both', async () => {
|
|
444
|
+
await ScopedBook.create({ code: 'a' });
|
|
445
|
+
const b2 = await ScopedBook.create({ code: 'abc' });
|
|
446
|
+
const books = await ScopedBook.unscope('where', 'order').list();
|
|
447
|
+
assert.strictEqual(books.length, 2);
|
|
448
|
+
assert(books[0].id <= books[1].id);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
it('should work with chaining: unscope("includes").scope("active")', async () => {
|
|
452
|
+
const library = await Library.create({ title: 'Main' });
|
|
453
|
+
await ScopedBook.create({ code: 'abc', is_available: true, library_id: library.id });
|
|
454
|
+
await ScopedBook.create({ code: 'abc', is_available: false, library_id: library.id });
|
|
455
|
+
const books = await ScopedBook.unscope('includes').scope('active').list();
|
|
456
|
+
assert.strictEqual(books.length, 1);
|
|
457
|
+
assert.strictEqual(books[0].is_available, true);
|
|
458
|
+
assert.strictEqual(books[0].library, undefined);
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
|
|
382
462
|
describe('count', () => {
|
|
383
463
|
it('should count rows', async () => {
|
|
384
464
|
for (let n = 0; n < 10; n++) {
|