ilana-orm 1.0.15 → 1.0.17
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/README.md +139 -108
- package/cli/ilana.js +289 -1
- package/database/schema-builder.js +18 -12
- package/index.js +1 -0
- package/index.mjs +1 -0
- package/orm/Factory.js +20 -18
- package/orm/Model.d.ts +26 -3
- package/orm/Model.js +138 -25
- package/orm/QueryBuilder.d.ts +24 -2
- package/orm/QueryBuilder.js +437 -75
- package/orm/Relation.d.ts +15 -3
- package/orm/Relation.js +74 -11
- package/orm/Relation.mjs +1 -1
- package/package.json +1 -1
package/orm/Model.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Model.js
|
|
2
2
|
const QueryBuilder = require('./QueryBuilder');
|
|
3
|
-
const { HasOne, HasMany, BelongsTo, BelongsToMany, HasManyThrough, MorphTo, MorphMany } = require('./Relation');
|
|
3
|
+
const { HasOne, HasMany, BelongsTo, BelongsToMany, HasManyThrough, MorphTo, MorphMany, MorphOne } = require('./Relation');
|
|
4
4
|
const ModelRegistry = require('./ModelRegistry');
|
|
5
5
|
const Database = require('../database/connection');
|
|
6
6
|
|
|
@@ -86,7 +86,8 @@ class Model {
|
|
|
86
86
|
const allKeys = new Set([
|
|
87
87
|
...Object.keys(this.attributes || {}),
|
|
88
88
|
...this.fillable,
|
|
89
|
-
...(this._deferred ? Object.keys(this._deferred) : [])
|
|
89
|
+
...(this._deferred ? Object.keys(this._deferred) : []),
|
|
90
|
+
...(this.appends || [])
|
|
90
91
|
]);
|
|
91
92
|
|
|
92
93
|
for (const key of allKeys) {
|
|
@@ -105,6 +106,16 @@ class Model {
|
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
_toPascalCase(key) {
|
|
110
|
+
return key.replace(/(^|_)([a-z])/g, (_, __, c) => c.toUpperCase());
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
_selfFk() {
|
|
114
|
+
return this.constructor.name
|
|
115
|
+
.replace(/([A-Z])/g, (m, l, i) => i === 0 ? l.toLowerCase() : '_' + l.toLowerCase())
|
|
116
|
+
+ '_id';
|
|
117
|
+
}
|
|
118
|
+
|
|
108
119
|
// --- Static registry & resolving ---
|
|
109
120
|
static register() {
|
|
110
121
|
ModelRegistry.register(this.name, this);
|
|
@@ -150,6 +161,7 @@ class Model {
|
|
|
150
161
|
}
|
|
151
162
|
|
|
152
163
|
static with(...rels) { return this.query().with(...rels); }
|
|
164
|
+
static withCount(...rels) { return this.query().withCount(...rels); }
|
|
153
165
|
static on(connectionOrTrx) {
|
|
154
166
|
if (connectionOrTrx && typeof connectionOrTrx.raw === 'function') {
|
|
155
167
|
// It's a transaction object
|
|
@@ -166,8 +178,14 @@ class Model {
|
|
|
166
178
|
static async findBy(column, value) { return this.query().where(column, value).first(); }
|
|
167
179
|
static async first() { return this.query().first(); }
|
|
168
180
|
static async firstOrFail() { return this.query().firstOrFail(); }
|
|
169
|
-
static latest(col) { return this.query().latest(col || 'created_at'); }
|
|
170
|
-
static oldest(col) { return this.query().oldest(col || 'created_at'); }
|
|
181
|
+
static latest(col) { return this.query().latest(col || this.createdAt || 'created_at'); }
|
|
182
|
+
static oldest(col) { return this.query().oldest(col || this.createdAt || 'created_at'); }
|
|
183
|
+
static withTrashed() { return this.query().withTrashed(); }
|
|
184
|
+
static onlyTrashed() { return this.query().onlyTrashed(); }
|
|
185
|
+
static async upsert(data, uniqueBy, update) { return this.query().upsert(data, uniqueBy, update); }
|
|
186
|
+
static withoutGlobalScopes() {
|
|
187
|
+
return new QueryBuilder(this.getTableName(), this, this.getConnectionName());
|
|
188
|
+
}
|
|
171
189
|
|
|
172
190
|
static make(attrs = {}) {
|
|
173
191
|
const inst = new this(attrs);
|
|
@@ -192,7 +210,16 @@ class Model {
|
|
|
192
210
|
}
|
|
193
211
|
|
|
194
212
|
static async insert(data) { return this.query().insert(data); }
|
|
195
|
-
static async destroy(ids) {
|
|
213
|
+
static async destroy(ids) {
|
|
214
|
+
const idList = Array.isArray(ids) ? ids : [ids];
|
|
215
|
+
if (this.softDeletes) {
|
|
216
|
+
const models = await this.query().whereIn(this.primaryKey, idList).get();
|
|
217
|
+
let count = 0;
|
|
218
|
+
for (const model of models) { await model.delete(); count++; }
|
|
219
|
+
return count;
|
|
220
|
+
}
|
|
221
|
+
return this.query().whereIn(this.primaryKey, idList).delete();
|
|
222
|
+
}
|
|
196
223
|
static async firstOrCreate(a, v) { return (await this.query().where(a).first()) || this.create({ ...a, ...v }); }
|
|
197
224
|
static async firstOrNew(a, v) {
|
|
198
225
|
const existing = await this.query().where(a).first();
|
|
@@ -211,8 +238,13 @@ class Model {
|
|
|
211
238
|
}
|
|
212
239
|
|
|
213
240
|
// scopes
|
|
214
|
-
static addGlobalScope(n, s) {
|
|
215
|
-
|
|
241
|
+
static addGlobalScope(n, s) {
|
|
242
|
+
if (!Object.hasOwn(this, 'globalScopes')) this.globalScopes = new Map();
|
|
243
|
+
this.globalScopes.set(n, s);
|
|
244
|
+
}
|
|
245
|
+
static removeGlobalScope(n) {
|
|
246
|
+
if (Object.hasOwn(this, 'globalScopes')) this.globalScopes.delete(n);
|
|
247
|
+
}
|
|
216
248
|
static withoutGlobalScope(n) {
|
|
217
249
|
const qb = new QueryBuilder(this.getTableName(), this, this.getConnectionName());
|
|
218
250
|
const scopes = new Map(this.globalScopes);
|
|
@@ -220,10 +252,17 @@ class Model {
|
|
|
220
252
|
scopes.forEach(s => s(qb));
|
|
221
253
|
return qb;
|
|
222
254
|
}
|
|
223
|
-
static applyGlobalScopes(qb) {
|
|
255
|
+
static applyGlobalScopes(qb) {
|
|
256
|
+
const scopes = Object.hasOwn(this, 'globalScopes') ? this.globalScopes : new Map();
|
|
257
|
+
scopes.forEach(s => s(qb));
|
|
258
|
+
}
|
|
224
259
|
|
|
225
260
|
// events
|
|
226
|
-
static _addEventHandler(evt, fn) {
|
|
261
|
+
static _addEventHandler(evt, fn) {
|
|
262
|
+
if (!Object.hasOwn(this, 'events')) this.events = {};
|
|
263
|
+
this.events[evt] = this.events[evt] || [];
|
|
264
|
+
this.events[evt].push(fn);
|
|
265
|
+
}
|
|
227
266
|
static creating(fn) { this._addEventHandler('creating', fn); }
|
|
228
267
|
static created(fn) { this._addEventHandler('created', fn); }
|
|
229
268
|
static updating(fn) { this._addEventHandler('updating', fn); }
|
|
@@ -254,7 +293,8 @@ class Model {
|
|
|
254
293
|
}
|
|
255
294
|
// static async fireEvent(evt, mdl) { for (const h of this.events[evt] || []) if (await h(mdl) === false) return false; }
|
|
256
295
|
static async fireEvent(evt, mdl) {
|
|
257
|
-
const
|
|
296
|
+
const ownEvents = Object.hasOwn(this, 'events') ? this.events : {};
|
|
297
|
+
const handlers = ownEvents[evt] || [];
|
|
258
298
|
for (const handler of handlers) {
|
|
259
299
|
if (await handler(mdl) === false) return false;
|
|
260
300
|
}
|
|
@@ -278,6 +318,46 @@ class Model {
|
|
|
278
318
|
return this;
|
|
279
319
|
}
|
|
280
320
|
|
|
321
|
+
async load(...relations) {
|
|
322
|
+
const qb = new QueryBuilder(this.constructor.getTableName(), this.constructor, this.constructor.getConnectionName());
|
|
323
|
+
qb.eagerLoad = relations.flat();
|
|
324
|
+
await qb.loadRelations([this]);
|
|
325
|
+
return this;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async loadMissing(...relations) {
|
|
329
|
+
const toLoad = relations.flat().filter(r => !(r.split('.')[0] in this.relations));
|
|
330
|
+
if (toLoad.length) await this.load(...toLoad);
|
|
331
|
+
return this;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
getRelation(key) {
|
|
335
|
+
return this.relations[key];
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
relationLoaded(key) {
|
|
339
|
+
return Object.prototype.hasOwnProperty.call(this.relations, key);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
makeHidden(keys) {
|
|
343
|
+
const list = Array.isArray(keys) ? keys : [keys];
|
|
344
|
+
this.hidden = [...(this.hidden || []), ...list];
|
|
345
|
+
return this;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
makeVisible(keys) {
|
|
349
|
+
const list = Array.isArray(keys) ? keys : [keys];
|
|
350
|
+
this.hidden = (this.hidden || []).filter(k => !list.includes(k));
|
|
351
|
+
return this;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
append(keys) {
|
|
355
|
+
const list = Array.isArray(keys) ? keys : [keys];
|
|
356
|
+
this.appends = [...(this.appends || []), ...list];
|
|
357
|
+
this._createAttributeGetters();
|
|
358
|
+
return this;
|
|
359
|
+
}
|
|
360
|
+
|
|
281
361
|
isFillable(k) {
|
|
282
362
|
if (Array.isArray(this.fillable) && this.fillable.length) return this.fillable.includes(k);
|
|
283
363
|
if (this.guarded.includes('*')) return false;
|
|
@@ -285,23 +365,36 @@ class Model {
|
|
|
285
365
|
}
|
|
286
366
|
|
|
287
367
|
getAttribute(k) {
|
|
368
|
+
const accessor = `get${this._toPascalCase(k)}Attribute`;
|
|
369
|
+
if (typeof this[accessor] === 'function') {
|
|
370
|
+
return this[accessor]();
|
|
371
|
+
}
|
|
288
372
|
const val = this.attributes[k];
|
|
289
373
|
const cast = this.casts[k];
|
|
374
|
+
if (cast && typeof cast === 'object' && typeof cast.get === 'function') {
|
|
375
|
+
return cast.get(val);
|
|
376
|
+
}
|
|
290
377
|
if (cast === 'json' || cast === 'array') {
|
|
291
378
|
try { return JSON.parse(val); } catch { return val; }
|
|
292
379
|
}
|
|
293
380
|
if (cast === 'date' && val != null) return val;
|
|
381
|
+
if (cast === 'boolean') return val == null ? val : Boolean(val);
|
|
382
|
+
if (cast === 'number' || cast === 'float') return val == null ? val : Number(val);
|
|
294
383
|
return val;
|
|
295
384
|
}
|
|
296
385
|
|
|
297
386
|
setAttribute(k, v) {
|
|
387
|
+
const mutator = `set${this._toPascalCase(k)}Attribute`;
|
|
388
|
+
if (typeof this[mutator] === 'function') {
|
|
389
|
+
v = this[mutator](v);
|
|
390
|
+
}
|
|
298
391
|
const cast = this.casts[k];
|
|
299
392
|
let val = v;
|
|
300
|
-
if (cast === '
|
|
393
|
+
if (cast && typeof cast === 'object' && typeof cast.set === 'function') {
|
|
394
|
+
val = cast.set(v);
|
|
395
|
+
} else if (cast === 'json' || cast === 'array') {
|
|
301
396
|
val = typeof v === 'string' ? v : JSON.stringify(v);
|
|
302
|
-
}
|
|
303
|
-
if (cast === 'date' && v instanceof Date) {
|
|
304
|
-
// Format date for database storage (YYYY-MM-DD HH:mm:ss)
|
|
397
|
+
} else if (cast === 'date' && v instanceof Date) {
|
|
305
398
|
const year = v.getFullYear();
|
|
306
399
|
const month = String(v.getMonth() + 1).padStart(2, '0');
|
|
307
400
|
const day = String(v.getDate()).padStart(2, '0');
|
|
@@ -311,7 +404,6 @@ class Model {
|
|
|
311
404
|
val = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
312
405
|
}
|
|
313
406
|
this.attributes[k] = val;
|
|
314
|
-
// Only mark as dirty if not during initialization and model exists
|
|
315
407
|
if (!this._deferred && this.exists) {
|
|
316
408
|
this._dirty.add(k);
|
|
317
409
|
}
|
|
@@ -323,6 +415,10 @@ class Model {
|
|
|
323
415
|
this._dirty.clear();
|
|
324
416
|
}
|
|
325
417
|
|
|
418
|
+
getOriginal(key) {
|
|
419
|
+
return key !== undefined ? this.original[key] : { ...this.original };
|
|
420
|
+
}
|
|
421
|
+
|
|
326
422
|
_getCurrentTimestamp() {
|
|
327
423
|
const now = new Date();
|
|
328
424
|
const config = this._getConfig();
|
|
@@ -379,9 +475,12 @@ class Model {
|
|
|
379
475
|
if (await this.constructor.fireEvent('creating', this) === false) return false;
|
|
380
476
|
if (await this.constructor.fireEvent('saving', this) === false) return false;
|
|
381
477
|
|
|
478
|
+
const createdAtCol = this.constructor.createdAt || 'created_at';
|
|
479
|
+
const updatedAtCol = this.constructor.updatedAt || 'updated_at';
|
|
480
|
+
|
|
382
481
|
if (this.constructor.timestamps) {
|
|
383
482
|
const now = this._getCurrentTimestamp();
|
|
384
|
-
this.setAttribute(
|
|
483
|
+
this.setAttribute(createdAtCol, now).setAttribute(updatedAtCol, now);
|
|
385
484
|
}
|
|
386
485
|
|
|
387
486
|
// Generate UUID if needed
|
|
@@ -403,16 +502,19 @@ class Model {
|
|
|
403
502
|
await this.constructor.fireEvent('saved', this);
|
|
404
503
|
this.syncOriginal();
|
|
405
504
|
} else if (this.isDirty()) {
|
|
505
|
+
const createdAtCol = this.constructor.createdAt || 'created_at';
|
|
506
|
+
const updatedAtCol = this.constructor.updatedAt || 'updated_at';
|
|
507
|
+
|
|
406
508
|
// Updating existing record
|
|
407
509
|
if (await this.constructor.fireEvent('updating', this) === false) return false;
|
|
408
510
|
if (await this.constructor.fireEvent('saving', this) === false) return false;
|
|
409
511
|
|
|
410
512
|
if (this.constructor.timestamps) {
|
|
411
|
-
this.setAttribute(
|
|
513
|
+
this.setAttribute(updatedAtCol, this._getCurrentTimestamp());
|
|
412
514
|
}
|
|
413
515
|
|
|
414
516
|
const updateData = this.getDirty();
|
|
415
|
-
delete updateData
|
|
517
|
+
delete updateData[createdAtCol]; // Never update created_at
|
|
416
518
|
|
|
417
519
|
if (Object.keys(updateData).length > 0) {
|
|
418
520
|
await this.constructor.query().where(this.constructor.primaryKey, this.getKey()).update(updateData);
|
|
@@ -448,8 +550,10 @@ class Model {
|
|
|
448
550
|
|
|
449
551
|
await this.constructor.fireEvent('deleting', this);
|
|
450
552
|
|
|
553
|
+
const deletedAtCol = this.constructor.deletedAt || 'deleted_at';
|
|
554
|
+
|
|
451
555
|
if (this.constructor.softDeletes) {
|
|
452
|
-
this.setAttribute(
|
|
556
|
+
this.setAttribute(deletedAtCol, new Date());
|
|
453
557
|
await this.save();
|
|
454
558
|
} else {
|
|
455
559
|
await this.constructor.query().where(this.constructor.primaryKey, this.getKey()).delete();
|
|
@@ -461,13 +565,14 @@ class Model {
|
|
|
461
565
|
}
|
|
462
566
|
|
|
463
567
|
async restore() {
|
|
464
|
-
|
|
568
|
+
const deletedAtCol = this.constructor.deletedAt || 'deleted_at';
|
|
569
|
+
if (!this.constructor.softDeletes || !this.getAttribute(deletedAtCol)) {
|
|
465
570
|
return false;
|
|
466
571
|
}
|
|
467
572
|
|
|
468
573
|
await this.constructor.fireEvent('restoring', this);
|
|
469
574
|
|
|
470
|
-
this.setAttribute(
|
|
575
|
+
this.setAttribute(deletedAtCol, null);
|
|
471
576
|
await this.save();
|
|
472
577
|
|
|
473
578
|
await this.constructor.fireEvent('restored', this);
|
|
@@ -475,7 +580,8 @@ class Model {
|
|
|
475
580
|
}
|
|
476
581
|
|
|
477
582
|
trashed() {
|
|
478
|
-
|
|
583
|
+
const deletedAtCol = this.constructor.deletedAt || 'deleted_at';
|
|
584
|
+
return this.constructor.softDeletes && this.getAttribute(deletedAtCol) !== null;
|
|
479
585
|
}
|
|
480
586
|
|
|
481
587
|
only(keys) {
|
|
@@ -556,15 +662,18 @@ class Model {
|
|
|
556
662
|
// relations - convert classes to strings to avoid circular dependencies
|
|
557
663
|
hasOne(related, fk, lk) {
|
|
558
664
|
const relatedName = this._resolveRelatedName(related);
|
|
559
|
-
return new HasOne(this, relatedName, fk ||
|
|
665
|
+
return new HasOne(this, relatedName, fk || this._selfFk(), lk || this.constructor.primaryKey);
|
|
560
666
|
}
|
|
561
667
|
hasMany(related, fk, lk) {
|
|
562
668
|
const relatedName = this._resolveRelatedName(related);
|
|
563
|
-
return new HasMany(this, relatedName, fk ||
|
|
669
|
+
return new HasMany(this, relatedName, fk || this._selfFk(), lk || this.constructor.primaryKey);
|
|
564
670
|
}
|
|
565
671
|
belongsTo(related, fk, ok) {
|
|
566
672
|
const relatedName = this._resolveRelatedName(related);
|
|
567
|
-
|
|
673
|
+
const defaultFk = typeof relatedName === 'string'
|
|
674
|
+
? relatedName.replace(/([A-Z])/g, (m, l, i) => i === 0 ? l.toLowerCase() : '_' + l.toLowerCase()) + '_id'
|
|
675
|
+
: undefined;
|
|
676
|
+
return new BelongsTo(this, relatedName, fk || defaultFk, ok || this.constructor.primaryKey);
|
|
568
677
|
}
|
|
569
678
|
belongsToMany(related, pivot, fp, rp, pk, rk) {
|
|
570
679
|
const relatedName = this._resolveRelatedName(related);
|
|
@@ -590,6 +699,10 @@ class Model {
|
|
|
590
699
|
return new HasManyThrough(this, relatedName, throughName, fk, sk, lk, slk);
|
|
591
700
|
}
|
|
592
701
|
morphTo(type, id) { return new MorphTo(this, type, id); }
|
|
702
|
+
morphOne(related, type, id) {
|
|
703
|
+
const relatedName = typeof related === 'function' && related.name ? related.name : related;
|
|
704
|
+
return new MorphOne(this, relatedName, type, id, this.constructor.name);
|
|
705
|
+
}
|
|
593
706
|
morphMany(related, type, id) {
|
|
594
707
|
const relatedName = typeof related === 'function' && related.name ? related.name : related;
|
|
595
708
|
return new MorphMany(this, relatedName, type, id, this.constructor.name);
|
package/orm/QueryBuilder.d.ts
CHANGED
|
@@ -56,27 +56,44 @@ export default class QueryBuilder {
|
|
|
56
56
|
whereDate(column: string, operator: string, value: string): this;
|
|
57
57
|
whereMonth(column: string, month: number): this;
|
|
58
58
|
whereYear(column: string, year: number): this;
|
|
59
|
-
|
|
59
|
+
whereNotBetween(column: string, range: [any, any]): this;
|
|
60
|
+
orWhereNull(column: string): this;
|
|
61
|
+
orWhereNotNull(column: string): this;
|
|
62
|
+
orWhereIn(column: string, values: any[]): this;
|
|
63
|
+
orWhereNotIn(column: string, values: any[]): this;
|
|
64
|
+
orWhereRaw(sql: string, bindings?: any[]): this;
|
|
65
|
+
whereDay(column: string, operatorOrValue: any, value?: any): this;
|
|
66
|
+
whereTime(column: string, operatorOrValue: any, value?: any): this;
|
|
60
67
|
when<T>(condition: T, callback: (query: this, condition: T) => void, otherwise?: (query: this) => void): this;
|
|
68
|
+
unless<T>(condition: T, callback: (query: this) => void, otherwise?: (query: this, condition: T) => void): this;
|
|
61
69
|
|
|
62
70
|
// Joins
|
|
63
71
|
join(table: string, first: string, operator: string, second: string): this;
|
|
64
72
|
leftJoin(table: string, first: string, operator: string, second: string): this;
|
|
65
73
|
rightJoin(table: string, first: string, operator: string, second: string): this;
|
|
74
|
+
innerJoin(table: string, first: string, operator: string, second: string): this;
|
|
75
|
+
crossJoin(table: string): this;
|
|
66
76
|
|
|
67
77
|
// Ordering and limits
|
|
68
78
|
orderBy(column: string, direction?: 'asc' | 'desc'): this;
|
|
79
|
+
orderByRaw(sql: string): this;
|
|
69
80
|
latest(column?: string): this;
|
|
70
81
|
oldest(column?: string): this;
|
|
82
|
+
inRandomOrder(): this;
|
|
71
83
|
limit(count: number): this;
|
|
72
84
|
offset(count: number): this;
|
|
73
85
|
take(count: number): this;
|
|
74
86
|
skip(count: number): this;
|
|
87
|
+
from(table: string): this;
|
|
88
|
+
forPage(page: number, perPage?: number): this;
|
|
75
89
|
|
|
76
90
|
// Grouping
|
|
77
91
|
groupBy(...columns: string[]): this;
|
|
78
92
|
having(column: string, operator: string, value: any): this;
|
|
79
93
|
having(rawSql: string): this;
|
|
94
|
+
havingRaw(sql: string, bindings?: any[]): this;
|
|
95
|
+
whereExists(callback: (query: QueryBuilder) => void): this;
|
|
96
|
+
whereNotExists(callback: (query: QueryBuilder) => void): this;
|
|
80
97
|
|
|
81
98
|
// Locking
|
|
82
99
|
lockForUpdate(): this;
|
|
@@ -85,7 +102,8 @@ export default class QueryBuilder {
|
|
|
85
102
|
noWait(): this;
|
|
86
103
|
|
|
87
104
|
// Selection
|
|
88
|
-
select(...columns:
|
|
105
|
+
select(...columns: any[]): this;
|
|
106
|
+
addSelect(...columns: any[]): this;
|
|
89
107
|
distinct(): this;
|
|
90
108
|
|
|
91
109
|
// Raw queries
|
|
@@ -105,14 +123,18 @@ export default class QueryBuilder {
|
|
|
105
123
|
withConstraints(relations: { [key: string]: (query: QueryBuilder) => void }): this;
|
|
106
124
|
withCount(...relations: string[]): this;
|
|
107
125
|
whereHas(relation: string, callback?: (query: QueryBuilder) => void): this;
|
|
126
|
+
doesntHave(relation: string): this;
|
|
127
|
+
whereDoesntHave(relation: string, callback?: (query: QueryBuilder) => void): this;
|
|
108
128
|
|
|
109
129
|
// Execution methods
|
|
110
130
|
get(): Promise<Collection<Model>>;
|
|
111
131
|
first(): Promise<Model | null>;
|
|
132
|
+
firstOrFail(): Promise<Model>;
|
|
112
133
|
find(id: any): Promise<Model | null>;
|
|
113
134
|
findOrFail(id: any): Promise<Model>;
|
|
114
135
|
pluck(column: string): Promise<any[]>;
|
|
115
136
|
exists(): Promise<boolean>;
|
|
137
|
+
doesntExist(): Promise<boolean>;
|
|
116
138
|
|
|
117
139
|
// Pagination
|
|
118
140
|
paginate(page?: number, perPage?: number): Promise<PaginationResult<Model>>;
|