@h3ravel/arquebus 0.1.4
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/LICENSE +21 -0
- package/README.md +94 -0
- package/bin/cli.js +203 -0
- package/bin/utils.js +141 -0
- package/dist/browser/index.cjs +1405 -0
- package/dist/browser/index.cjs.map +1 -0
- package/dist/browser/index.d.cts +229 -0
- package/dist/browser/index.d.ts +227 -0
- package/dist/browser/index.js +1341 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/index.cjs +4585 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +457 -0
- package/dist/index.d.ts +457 -0
- package/dist/index.js +4513 -0
- package/dist/index.js.map +1 -0
- package/package.json +151 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,4513 @@
|
|
|
1
|
+
// src/migrations/migration-repository.js
|
|
2
|
+
var MigrationRepository = class {
|
|
3
|
+
resolver;
|
|
4
|
+
table;
|
|
5
|
+
connection = null;
|
|
6
|
+
constructor(resolver, table) {
|
|
7
|
+
this.resolver = resolver;
|
|
8
|
+
this.table = table;
|
|
9
|
+
}
|
|
10
|
+
async getRan() {
|
|
11
|
+
return await this.getTable().orderBy("batch", "asc").orderBy("migration", "asc").pluck("migration");
|
|
12
|
+
}
|
|
13
|
+
async getMigrations(steps) {
|
|
14
|
+
const query = this.getTable().where("batch", ">=", "1");
|
|
15
|
+
return await query.orderBy("batch", "desc").orderBy("migration", "desc").take(steps).get();
|
|
16
|
+
}
|
|
17
|
+
async getMigrationsByBatch(batch) {
|
|
18
|
+
return await this.getTable().where("batch", batch).orderBy("migration", "desc").get();
|
|
19
|
+
}
|
|
20
|
+
async getLast() {
|
|
21
|
+
const query = this.getTable().where("batch", await this.getLastBatchNumber());
|
|
22
|
+
return await query.orderBy("migration", "desc").get();
|
|
23
|
+
}
|
|
24
|
+
async getMigrationBatches() {
|
|
25
|
+
const migrations = await this.getTable().select("batch", "migration").orderBy("batch", "asc").orderBy("migration", "asc").get();
|
|
26
|
+
const migrationBatches = {};
|
|
27
|
+
migrations.map((migration) => {
|
|
28
|
+
migrationBatches[migration.migration] = migration.batch;
|
|
29
|
+
});
|
|
30
|
+
return migrationBatches;
|
|
31
|
+
}
|
|
32
|
+
async log(file, batch) {
|
|
33
|
+
await this.getTable().insert({
|
|
34
|
+
migration: file,
|
|
35
|
+
batch
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async delete(migration) {
|
|
39
|
+
await this.getTable().where("migration", migration.migration).delete();
|
|
40
|
+
}
|
|
41
|
+
async getNextBatchNumber() {
|
|
42
|
+
return await this.getLastBatchNumber() + 1;
|
|
43
|
+
}
|
|
44
|
+
async getLastBatchNumber() {
|
|
45
|
+
return await this.getTable().max("batch");
|
|
46
|
+
}
|
|
47
|
+
async createRepository() {
|
|
48
|
+
const schema = this.getConnection().schema;
|
|
49
|
+
await schema.createTable(this.table, function(table) {
|
|
50
|
+
table.increments("id");
|
|
51
|
+
table.string("migration");
|
|
52
|
+
table.integer("batch");
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
repositoryExists() {
|
|
56
|
+
const schema = this.getConnection().schema;
|
|
57
|
+
return schema.hasTable(this.table);
|
|
58
|
+
}
|
|
59
|
+
async deleteRepository() {
|
|
60
|
+
const schema = this.getConnection().schema;
|
|
61
|
+
await schema.drop(this.table);
|
|
62
|
+
}
|
|
63
|
+
getTable() {
|
|
64
|
+
return this.getConnection().table(this.table);
|
|
65
|
+
}
|
|
66
|
+
getConnection() {
|
|
67
|
+
return this.resolver.connection(this.connection);
|
|
68
|
+
}
|
|
69
|
+
setSource(name) {
|
|
70
|
+
this.connection = name;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var migration_repository_default = MigrationRepository;
|
|
74
|
+
|
|
75
|
+
// src/migrations/migrator.js
|
|
76
|
+
import * as color from "colorette";
|
|
77
|
+
import fs from "fs";
|
|
78
|
+
import path from "path";
|
|
79
|
+
import { promisify } from "util";
|
|
80
|
+
async function glob(folderPath) {
|
|
81
|
+
const files = await promisify(fs.readdir)(folderPath);
|
|
82
|
+
const allFiles = [];
|
|
83
|
+
for (const file of files) {
|
|
84
|
+
const filePath = `${folderPath}/${file}`;
|
|
85
|
+
const stats = await promisify(fs.stat)(filePath);
|
|
86
|
+
if (stats.isFile()) {
|
|
87
|
+
allFiles.push(filePath);
|
|
88
|
+
} else if (stats.isDirectory()) {
|
|
89
|
+
const subFiles = await glob(filePath);
|
|
90
|
+
allFiles.push(...subFiles);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return allFiles;
|
|
94
|
+
}
|
|
95
|
+
var Migrator = class {
|
|
96
|
+
events = null;
|
|
97
|
+
repository;
|
|
98
|
+
files;
|
|
99
|
+
resolver;
|
|
100
|
+
connection = null;
|
|
101
|
+
paths = [];
|
|
102
|
+
output = null;
|
|
103
|
+
constructor(repository, resolver = null, files = null, dispatcher = null) {
|
|
104
|
+
this.repository = repository;
|
|
105
|
+
this.files = files;
|
|
106
|
+
this.resolver = resolver;
|
|
107
|
+
this.events = dispatcher;
|
|
108
|
+
}
|
|
109
|
+
async run(paths = [], options = {}) {
|
|
110
|
+
const files = await this.getMigrationFiles(paths);
|
|
111
|
+
const ran = await this.repository.getRan();
|
|
112
|
+
const migrations = this.pendingMigrations(files, ran);
|
|
113
|
+
await this.runPending(migrations, options);
|
|
114
|
+
return migrations;
|
|
115
|
+
}
|
|
116
|
+
pendingMigrations(files, ran) {
|
|
117
|
+
return Object.values(files).filter((file) => !ran.includes(this.getMigrationName(file)));
|
|
118
|
+
}
|
|
119
|
+
async runPending(migrations, options = {}) {
|
|
120
|
+
if (migrations.length === 0) {
|
|
121
|
+
this.write("Nothing to migrate");
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
let batch = await this.repository.getNextBatchNumber();
|
|
125
|
+
const pretend = options.pretend || false;
|
|
126
|
+
const step = options.step || false;
|
|
127
|
+
this.write("Running migrations.");
|
|
128
|
+
for (const file of migrations) {
|
|
129
|
+
await this.runUp(file, batch, pretend);
|
|
130
|
+
if (step) {
|
|
131
|
+
batch++;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async runUp(file, batch, pretend) {
|
|
136
|
+
const migration = this.resolvePath(file);
|
|
137
|
+
const name = this.getMigrationName(file);
|
|
138
|
+
await this.writeTask(name, () => this.runMigration(migration, "up"));
|
|
139
|
+
await this.repository.log(name, batch);
|
|
140
|
+
}
|
|
141
|
+
async rollback(paths = [], options = {}) {
|
|
142
|
+
const migrations = await this.getMigrationsForRollback(options);
|
|
143
|
+
if (migrations.length === 0) {
|
|
144
|
+
this.write("Nothing to rollback.");
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
147
|
+
return await this.rollbackMigrations(migrations, paths, options);
|
|
148
|
+
}
|
|
149
|
+
async getMigrationsForRollback(options) {
|
|
150
|
+
if (options.step > 0) {
|
|
151
|
+
return await this.repository.getMigrations(options.step);
|
|
152
|
+
}
|
|
153
|
+
if (options.batch > 0) {
|
|
154
|
+
return await this.repository.getMigrationsByBatch(options.batch);
|
|
155
|
+
}
|
|
156
|
+
return await this.repository.getLast();
|
|
157
|
+
}
|
|
158
|
+
async rollbackMigrations(migrations, paths, options) {
|
|
159
|
+
const rolledBack = [];
|
|
160
|
+
const files = await this.getMigrationFiles(paths);
|
|
161
|
+
this.write("Rolling back migrations.");
|
|
162
|
+
for (const migration of migrations) {
|
|
163
|
+
const file = files[migration.migration];
|
|
164
|
+
if (!file) {
|
|
165
|
+
this.writeTwoColumns(migration.migration, color.yellow("Migration not found"));
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
rolledBack.push(file);
|
|
169
|
+
await this.runDown(file, migration, options.pretend || false);
|
|
170
|
+
}
|
|
171
|
+
return rolledBack;
|
|
172
|
+
}
|
|
173
|
+
async runDown(file, migration, pretend) {
|
|
174
|
+
const instance = this.resolvePath(file);
|
|
175
|
+
const name = this.getMigrationName(file);
|
|
176
|
+
await this.writeTask(name, () => this.runMigration(instance, "down"));
|
|
177
|
+
await this.repository.delete(migration);
|
|
178
|
+
}
|
|
179
|
+
reset(paths = [], pretend = false) {
|
|
180
|
+
const migrations = this.repository.getRan().reverse();
|
|
181
|
+
if (migrations.length === 0) {
|
|
182
|
+
this.write(Info, "Nothing to rollback.");
|
|
183
|
+
return [];
|
|
184
|
+
}
|
|
185
|
+
return this.resetMigrations(migrations, paths, pretend);
|
|
186
|
+
}
|
|
187
|
+
resetMigrations(migrations, paths, pretend = false) {
|
|
188
|
+
migrations = migrations.map((m) => ({ migration: m }));
|
|
189
|
+
return this.rollbackMigrations(migrations, paths, { pretend });
|
|
190
|
+
}
|
|
191
|
+
async runMigration(migration, method) {
|
|
192
|
+
const connection = this.resolveConnection(migration.getConnection());
|
|
193
|
+
const callback = async (trx) => {
|
|
194
|
+
if (typeof migration[method] === "function") {
|
|
195
|
+
await this.runMethod(trx, migration, method);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
if (migration.withinTransaction) {
|
|
199
|
+
await connection.transaction(callback);
|
|
200
|
+
} else {
|
|
201
|
+
await callback(connection);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
async runMethod(connection, migration, method) {
|
|
205
|
+
try {
|
|
206
|
+
await migration[method](connection.schema, connection);
|
|
207
|
+
} finally {
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
resolvePath(path3) {
|
|
211
|
+
return new migrationClass();
|
|
212
|
+
}
|
|
213
|
+
getMigrationClass(migrationName) {
|
|
214
|
+
return migrationName.split("_").slice(4).map((str) => str.charAt(0).toUpperCase() + str.slice(1)).join("");
|
|
215
|
+
}
|
|
216
|
+
async getMigrationFiles(paths) {
|
|
217
|
+
const files = [];
|
|
218
|
+
for (const path3 of paths) {
|
|
219
|
+
if (path3.endsWith(".js")) {
|
|
220
|
+
files.push(path3);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
files.push(...await glob(path3));
|
|
224
|
+
}
|
|
225
|
+
return files.filter(Boolean).reduce((result, file) => {
|
|
226
|
+
result[this.getMigrationName(file)] = file;
|
|
227
|
+
return result;
|
|
228
|
+
}, {});
|
|
229
|
+
}
|
|
230
|
+
getMigrationName(filePath) {
|
|
231
|
+
return path.basename(filePath).replace(".js", "");
|
|
232
|
+
}
|
|
233
|
+
path(path3) {
|
|
234
|
+
this.paths = Array.from(/* @__PURE__ */ new Set([...this.paths, path3]));
|
|
235
|
+
}
|
|
236
|
+
getPaths() {
|
|
237
|
+
return this.paths;
|
|
238
|
+
}
|
|
239
|
+
getConnection() {
|
|
240
|
+
return this.connection;
|
|
241
|
+
}
|
|
242
|
+
resolveConnection(connection) {
|
|
243
|
+
return this.resolver.connection(connection || this.connection);
|
|
244
|
+
}
|
|
245
|
+
getRepository() {
|
|
246
|
+
return this.repository;
|
|
247
|
+
}
|
|
248
|
+
repositoryExists() {
|
|
249
|
+
return this.repository.repositoryExists();
|
|
250
|
+
}
|
|
251
|
+
async hasRunAnyMigrations() {
|
|
252
|
+
const ran = await this.repository.getRan();
|
|
253
|
+
const exists = await this.repositoryExists();
|
|
254
|
+
return exists && ran.length > 0;
|
|
255
|
+
}
|
|
256
|
+
deleteRepository() {
|
|
257
|
+
this.repository.deleteRepository();
|
|
258
|
+
}
|
|
259
|
+
setOutput(output) {
|
|
260
|
+
this.output = output;
|
|
261
|
+
return this;
|
|
262
|
+
}
|
|
263
|
+
write(...args) {
|
|
264
|
+
if (this.output) {
|
|
265
|
+
console.log(...args);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
writeTwoColumns(name, ...args) {
|
|
269
|
+
const value = args.join(" ");
|
|
270
|
+
const regex = /\x1b\[\d+m/g;
|
|
271
|
+
const width = Math.min(process.stdout.columns, 100);
|
|
272
|
+
const dots = Math.max(width - name.replace(regex, "").length - value.replace(regex, "").length - 10, 0);
|
|
273
|
+
return this.write(name, color.gray(".".repeat(dots)), value);
|
|
274
|
+
}
|
|
275
|
+
async writeTask(description, task) {
|
|
276
|
+
const startTime = process.hrtime();
|
|
277
|
+
let result = false;
|
|
278
|
+
try {
|
|
279
|
+
result = await (task || (() => true))();
|
|
280
|
+
} catch (e) {
|
|
281
|
+
throw e;
|
|
282
|
+
} finally {
|
|
283
|
+
const endTime = process.hrtime(startTime);
|
|
284
|
+
const duration = (endTime[0] * 1e9 + endTime[1]) / 1e6;
|
|
285
|
+
this.writeTwoColumns(color.green(description), color.gray(`${Math.floor(duration)}ms`), result !== false ? color.green("\u2714") : color.red("\u2718"));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
var migrator_default = Migrator;
|
|
290
|
+
|
|
291
|
+
// src/utils.js
|
|
292
|
+
import { camel, dash, snake, trim } from "radashi";
|
|
293
|
+
import advancedFormat from "dayjs/plugin/advancedFormat";
|
|
294
|
+
import dayjs from "dayjs";
|
|
295
|
+
dayjs.extend(advancedFormat);
|
|
296
|
+
var now = (format = "YYYY-MM-DD HH:mm:ss") => dayjs().format(format);
|
|
297
|
+
var getRelationName = (relationMethod) => {
|
|
298
|
+
return snake(relationMethod.substring(8));
|
|
299
|
+
};
|
|
300
|
+
var getScopeName = (scopeMethod) => {
|
|
301
|
+
return snake(scopeMethod.substring(5));
|
|
302
|
+
};
|
|
303
|
+
var getRelationMethod = (relation) => {
|
|
304
|
+
return camel(`relation_${relation}`);
|
|
305
|
+
};
|
|
306
|
+
var getScopeMethod = (scope) => {
|
|
307
|
+
return camel(`scope_${scope}`);
|
|
308
|
+
};
|
|
309
|
+
var getAttrMethod = (attr) => {
|
|
310
|
+
return camel(`attribute_${attr}`);
|
|
311
|
+
};
|
|
312
|
+
var getGetterMethod = (attr) => {
|
|
313
|
+
return camel(`get_${attr}_attribute`);
|
|
314
|
+
};
|
|
315
|
+
var getSetterMethod = (attr) => {
|
|
316
|
+
return camel(`set_${attr}_attribute`);
|
|
317
|
+
};
|
|
318
|
+
var getAttrName = (attrMethod) => {
|
|
319
|
+
return attrMethod.substring(3, attrMethod.length - 9).toLowerCase();
|
|
320
|
+
};
|
|
321
|
+
var tap = (instance, callback) => {
|
|
322
|
+
const result = callback(instance);
|
|
323
|
+
return result instanceof Promise ? result.then(() => instance) : instance;
|
|
324
|
+
};
|
|
325
|
+
function compose(Base, ...mixins) {
|
|
326
|
+
return mixins.reduce(
|
|
327
|
+
(cls, mixin) => mixin(cls),
|
|
328
|
+
Base
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
var flattenDeep = (arr) => Array.isArray(arr) ? arr.reduce((a, b) => a.concat(flattenDeep(b)), []) : [arr];
|
|
332
|
+
var kebabCase = (str) => trim(dash(str.replace(/[^a-zA-Z0-9_-]/g, "-")), "_-");
|
|
333
|
+
var snakeCase = (str) => trim(snake(str.replace(/[^a-zA-Z0-9_-]/g, "-")), "_-");
|
|
334
|
+
|
|
335
|
+
// src/casts/attribute.js
|
|
336
|
+
var Attribute = class _Attribute {
|
|
337
|
+
get;
|
|
338
|
+
set;
|
|
339
|
+
withCaching = false;
|
|
340
|
+
withObjectCaching = true;
|
|
341
|
+
constructor({ get: get2 = null, set: set2 = null }) {
|
|
342
|
+
this.get = get2;
|
|
343
|
+
this.set = set2;
|
|
344
|
+
}
|
|
345
|
+
static make(get2 = null, set2 = null) {
|
|
346
|
+
return new _Attribute(get2, set2);
|
|
347
|
+
}
|
|
348
|
+
static get(get2) {
|
|
349
|
+
return new _Attribute(get2);
|
|
350
|
+
}
|
|
351
|
+
static set(set2) {
|
|
352
|
+
return new _Attribute(null, set2);
|
|
353
|
+
}
|
|
354
|
+
withoutObjectCaching() {
|
|
355
|
+
this.withObjectCaching = false;
|
|
356
|
+
return this;
|
|
357
|
+
}
|
|
358
|
+
shouldCache() {
|
|
359
|
+
this.withCaching = true;
|
|
360
|
+
return this;
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
var attribute_default = Attribute;
|
|
364
|
+
|
|
365
|
+
// src/arquebus.js
|
|
366
|
+
import Knex from "knex";
|
|
367
|
+
|
|
368
|
+
// src/relations/relation.js
|
|
369
|
+
var Relation = class {
|
|
370
|
+
query;
|
|
371
|
+
parent;
|
|
372
|
+
related;
|
|
373
|
+
eagerKeysWereEmpty = false;
|
|
374
|
+
static constraints = true;
|
|
375
|
+
constructor(query, parent) {
|
|
376
|
+
this.query = query;
|
|
377
|
+
this.parent = parent;
|
|
378
|
+
this.related = this.query.model;
|
|
379
|
+
}
|
|
380
|
+
static extend(trait) {
|
|
381
|
+
for (const methodName in trait) {
|
|
382
|
+
this.prototype[methodName] = trait[methodName];
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
static noConstraints(callback) {
|
|
386
|
+
const previous = this.constraints;
|
|
387
|
+
this.constraints = false;
|
|
388
|
+
try {
|
|
389
|
+
return callback();
|
|
390
|
+
} finally {
|
|
391
|
+
this.constraints = previous;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
asProxy() {
|
|
395
|
+
const handler = {
|
|
396
|
+
get: function(target, prop) {
|
|
397
|
+
if (typeof target[prop] !== "undefined") {
|
|
398
|
+
return target[prop];
|
|
399
|
+
}
|
|
400
|
+
if (typeof prop === "string") {
|
|
401
|
+
if (typeof target.query[prop] === "function") {
|
|
402
|
+
return (...args) => {
|
|
403
|
+
target.query[prop](...args);
|
|
404
|
+
return target.asProxy();
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
return new Proxy(this, handler);
|
|
411
|
+
}
|
|
412
|
+
getRelated() {
|
|
413
|
+
return this.related;
|
|
414
|
+
}
|
|
415
|
+
getKeys(models, key2) {
|
|
416
|
+
return models.map((model) => key2 ? model.attributes[key2] : model.getKey()).sort();
|
|
417
|
+
}
|
|
418
|
+
getRelationQuery() {
|
|
419
|
+
return this.query;
|
|
420
|
+
}
|
|
421
|
+
whereInEager(whereIn, key2, modelKeys, query = null) {
|
|
422
|
+
(query || this.query)[whereIn](key2, modelKeys);
|
|
423
|
+
if (modelKeys.length === 0) {
|
|
424
|
+
this.eagerKeysWereEmpty = true;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
whereInMethod(model, key2) {
|
|
428
|
+
return "whereIn";
|
|
429
|
+
const segments = key2.split(".");
|
|
430
|
+
return model.getKeyName() === segments.pop() && ["int", "integer"].includes(model.getKeyType()) ? "whereIntegerInRaw" : "whereIn";
|
|
431
|
+
}
|
|
432
|
+
getEager() {
|
|
433
|
+
return this.eagerKeysWereEmpty ? this.query.getModel().newCollection() : this.get();
|
|
434
|
+
}
|
|
435
|
+
async get(columns = "*") {
|
|
436
|
+
return await this.query.get(columns);
|
|
437
|
+
}
|
|
438
|
+
async first(columns = "*") {
|
|
439
|
+
return await this.query.first(columns);
|
|
440
|
+
}
|
|
441
|
+
async paginate(...args) {
|
|
442
|
+
return await this.query.paginate(...args);
|
|
443
|
+
}
|
|
444
|
+
async count(...args) {
|
|
445
|
+
return await this.query.clearSelect().count(...args);
|
|
446
|
+
}
|
|
447
|
+
toSql() {
|
|
448
|
+
return this.query.toSql();
|
|
449
|
+
}
|
|
450
|
+
addConstraints() {
|
|
451
|
+
}
|
|
452
|
+
getRelationCountHash(incrementJoinCount = true) {
|
|
453
|
+
return "arquebus_reserved_" + (incrementJoinCount ? this.constructor.selfJoinCount++ : this.constructor.selfJoinCount);
|
|
454
|
+
}
|
|
455
|
+
getRelationExistenceQuery(query, parentQuery, columns = ["*"]) {
|
|
456
|
+
return query.select(columns).whereColumn(this.getQualifiedParentKeyName(), "=", this.getExistenceCompareKey());
|
|
457
|
+
}
|
|
458
|
+
getRelationExistenceCountQuery(query, parentQuery) {
|
|
459
|
+
const db = this.related.getConnection();
|
|
460
|
+
return this.getRelationExistenceQuery(query, parentQuery, db.raw("count(*)"));
|
|
461
|
+
}
|
|
462
|
+
getQualifiedParentKeyName() {
|
|
463
|
+
return this.parent.getQualifiedKeyName();
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
var relation_default = Relation;
|
|
467
|
+
|
|
468
|
+
// src/relations/concerns/supports-default-models.js
|
|
469
|
+
var SupportsDefaultModels = (Relation2) => {
|
|
470
|
+
return class extends Relation2 {
|
|
471
|
+
_withDefault;
|
|
472
|
+
withDefault(callback = true) {
|
|
473
|
+
this._withDefault = callback;
|
|
474
|
+
return this;
|
|
475
|
+
}
|
|
476
|
+
getDefaultFor(parent) {
|
|
477
|
+
if (!this._withDefault) {
|
|
478
|
+
return null;
|
|
479
|
+
}
|
|
480
|
+
const instance = this.newRelatedInstanceFor(parent);
|
|
481
|
+
if (typeof this._withDefault === "function") {
|
|
482
|
+
return this._withDefault(instance, parent) || instance;
|
|
483
|
+
}
|
|
484
|
+
if (typeof this._withDefault === "object") {
|
|
485
|
+
for (const key2 in this._withDefault) {
|
|
486
|
+
instance.setAttribute(key2, this._withDefault[key2]);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
return instance;
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
};
|
|
493
|
+
var supports_default_models_default = SupportsDefaultModels;
|
|
494
|
+
|
|
495
|
+
// src/relations/belongs-to.js
|
|
496
|
+
var BelongsTo = class extends compose(relation_default, supports_default_models_default) {
|
|
497
|
+
foreignKey;
|
|
498
|
+
ownerKey;
|
|
499
|
+
child;
|
|
500
|
+
relationName;
|
|
501
|
+
constructor(query, child, foreignKey, ownerKey, relationName) {
|
|
502
|
+
super(query, child);
|
|
503
|
+
this.foreignKey = foreignKey;
|
|
504
|
+
this.ownerKey = ownerKey;
|
|
505
|
+
this.child = child;
|
|
506
|
+
this.relationName = relationName;
|
|
507
|
+
this.addConstraints();
|
|
508
|
+
return this.asProxy();
|
|
509
|
+
}
|
|
510
|
+
async getResults() {
|
|
511
|
+
if (this.child[this.foreignKey] === null) {
|
|
512
|
+
return this.getDefaultFor(this.parent);
|
|
513
|
+
}
|
|
514
|
+
const result = await this.query.first();
|
|
515
|
+
return result || this.getDefaultFor(this.parent);
|
|
516
|
+
}
|
|
517
|
+
match(models, results, relation) {
|
|
518
|
+
const foreign = this.foreignKey;
|
|
519
|
+
const owner = this.ownerKey;
|
|
520
|
+
const dictionary = {};
|
|
521
|
+
results.map((result) => {
|
|
522
|
+
const attribute = result.attributes[owner];
|
|
523
|
+
dictionary[attribute] = result;
|
|
524
|
+
});
|
|
525
|
+
models.map((model) => {
|
|
526
|
+
const attribute = model[foreign];
|
|
527
|
+
if (dictionary[attribute] !== void 0) {
|
|
528
|
+
model.setRelation(relation, dictionary[attribute]);
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
return models;
|
|
532
|
+
}
|
|
533
|
+
getQualifiedForeignKeyName() {
|
|
534
|
+
return this.child.qualifyColumn(this.foreignKey);
|
|
535
|
+
}
|
|
536
|
+
getRelationExistenceQuery(query, parentQuery, columns = ["*"]) {
|
|
537
|
+
if (parentQuery.getQuery()._single.table == query.getQuery()._single.table) {
|
|
538
|
+
return this.getRelationExistenceQueryForSelfRelation(query, parentQuery, columns);
|
|
539
|
+
}
|
|
540
|
+
return query.select(columns).whereColumn(this.getQualifiedForeignKeyName(), "=", query.qualifyColumn(this.ownerKey));
|
|
541
|
+
}
|
|
542
|
+
getRelationExistenceQueryForSelfRelation(query, parentQuery, columns = ["*"]) {
|
|
543
|
+
const hash = this.getRelationCountHash();
|
|
544
|
+
query.select(columns).from(query.getModel().getTable() + " as " + hash);
|
|
545
|
+
query.getModel().setTable(hash);
|
|
546
|
+
return query.whereColumn(hash + "." + this.ownerKey, "=", this.getQualifiedForeignKeyName());
|
|
547
|
+
}
|
|
548
|
+
initRelation(models, relation) {
|
|
549
|
+
models.map((model) => {
|
|
550
|
+
model.setRelation(relation, this.getDefaultFor(model));
|
|
551
|
+
});
|
|
552
|
+
return models;
|
|
553
|
+
}
|
|
554
|
+
addEagerConstraints(models) {
|
|
555
|
+
const key2 = `${this.related.getTable()}.${this.ownerKey}`;
|
|
556
|
+
this.query.whereIn(key2, this.getEagerModelKeys(models));
|
|
557
|
+
}
|
|
558
|
+
getEagerModelKeys(models) {
|
|
559
|
+
const keys = [];
|
|
560
|
+
models.map((model) => {
|
|
561
|
+
const value = model[this.foreignKey];
|
|
562
|
+
if (value !== null && value !== void 0) {
|
|
563
|
+
keys.push(value);
|
|
564
|
+
}
|
|
565
|
+
});
|
|
566
|
+
keys.sort();
|
|
567
|
+
return [...new Set(keys)];
|
|
568
|
+
}
|
|
569
|
+
associate(model) {
|
|
570
|
+
const ownerKey = model instanceof Model ? model.attributes[this.ownerKey] : model;
|
|
571
|
+
this.child[this.foreignKey] = ownerKey;
|
|
572
|
+
if (model instanceof Model) {
|
|
573
|
+
this.child.setRelation(this.relationName, model);
|
|
574
|
+
} else {
|
|
575
|
+
this.child.unsetRelation(this.relationName);
|
|
576
|
+
}
|
|
577
|
+
return this.child;
|
|
578
|
+
}
|
|
579
|
+
dissociate() {
|
|
580
|
+
this.child[this.foreignKey] = null;
|
|
581
|
+
return this.child.setRelation(this.relationName, null);
|
|
582
|
+
}
|
|
583
|
+
addConstraints() {
|
|
584
|
+
if (this.constructor.constraints) {
|
|
585
|
+
const table = this.related.getTable();
|
|
586
|
+
this.query.where(table + "." + this.ownerKey, "=", this.child[this.foreignKey]);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
newRelatedInstanceFor(parent) {
|
|
590
|
+
return this.related.newInstance();
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
var belongs_to_default = BelongsTo;
|
|
594
|
+
|
|
595
|
+
// src/relations/belongs-to-many.js
|
|
596
|
+
import { isEqual, omit as omit2 } from "radashi";
|
|
597
|
+
|
|
598
|
+
// src/collection.js
|
|
599
|
+
import { Collection as BaseCollection, collect } from "collect.js";
|
|
600
|
+
import { diff as difference, isArray, isEmpty, omit, pick } from "radashi";
|
|
601
|
+
var Collection = class _Collection extends BaseCollection {
|
|
602
|
+
async load(...relations) {
|
|
603
|
+
if (this.isNotEmpty()) {
|
|
604
|
+
const query = this.first().constructor.query().with(...relations);
|
|
605
|
+
const items = await query.eagerLoadRelations(this.items);
|
|
606
|
+
return new this.constructor(items);
|
|
607
|
+
}
|
|
608
|
+
return this;
|
|
609
|
+
}
|
|
610
|
+
async loadAggregate(relations, column, action = null) {
|
|
611
|
+
if (this.isEmpty()) {
|
|
612
|
+
return this;
|
|
613
|
+
}
|
|
614
|
+
const models = (await this.first().newModelQuery().whereIn(this.first().getKeyName(), this.modelKeys()).select(this.first().getKeyName()).withAggregate(relations, column, action).get()).keyBy(this.first().getKeyName());
|
|
615
|
+
const attributes = difference(Object.keys(models.first().getAttributes()), [models.first().getKeyName()]);
|
|
616
|
+
this.each((model) => {
|
|
617
|
+
const extraAttributes = pick(models.get(model.getKey()).getAttributes(), attributes);
|
|
618
|
+
model.fill(extraAttributes).syncOriginalAttributes(attributes);
|
|
619
|
+
});
|
|
620
|
+
return this;
|
|
621
|
+
}
|
|
622
|
+
loadCount(relations) {
|
|
623
|
+
return this.loadAggregate(relations, "*", "count");
|
|
624
|
+
}
|
|
625
|
+
loadMax(relation, column) {
|
|
626
|
+
return this.loadAggregate(relation, column, "max");
|
|
627
|
+
}
|
|
628
|
+
loadMin(relation, column) {
|
|
629
|
+
return this.loadAggregate(relation, column, "min");
|
|
630
|
+
}
|
|
631
|
+
loadSum(relation, column) {
|
|
632
|
+
return this.loadAggregate(relation, column, "sum");
|
|
633
|
+
}
|
|
634
|
+
loadAvg(relation, column) {
|
|
635
|
+
return this.loadAggregate(relation, column, "avg");
|
|
636
|
+
}
|
|
637
|
+
mapThen(callback) {
|
|
638
|
+
return Promise.all(this.map(callback));
|
|
639
|
+
}
|
|
640
|
+
modelKeys() {
|
|
641
|
+
return this.all().map((item) => item.getKey());
|
|
642
|
+
}
|
|
643
|
+
contains(key2, operator = null, value = null) {
|
|
644
|
+
if (arguments.length > 1) {
|
|
645
|
+
return super.contains(key2, operator, value);
|
|
646
|
+
}
|
|
647
|
+
if (key2 instanceof model_default) {
|
|
648
|
+
return super.contains((model) => {
|
|
649
|
+
return model.is(key2);
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
return super.contains((model) => {
|
|
653
|
+
return model.getKey() == key2;
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
diff(items) {
|
|
657
|
+
const diff = new this.constructor();
|
|
658
|
+
const dictionary = this.getDictionary(items);
|
|
659
|
+
this.items.map((item) => {
|
|
660
|
+
if (dictionary[item.getKey()] === void 0) {
|
|
661
|
+
diff.add(item);
|
|
662
|
+
}
|
|
663
|
+
});
|
|
664
|
+
return diff;
|
|
665
|
+
}
|
|
666
|
+
except(keys) {
|
|
667
|
+
const dictionary = omit(this.getDictionary(), keys);
|
|
668
|
+
return new this.constructor(Object.values(dictionary));
|
|
669
|
+
}
|
|
670
|
+
intersect(items) {
|
|
671
|
+
const intersect = new this.constructor();
|
|
672
|
+
if (isEmpty(items)) {
|
|
673
|
+
return intersect;
|
|
674
|
+
}
|
|
675
|
+
const dictionary = this.getDictionary(items);
|
|
676
|
+
for (let item of this.items) {
|
|
677
|
+
if (dictionary[item.getKey()] !== void 0) {
|
|
678
|
+
intersect.add(item);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return intersect;
|
|
682
|
+
}
|
|
683
|
+
unique(key2 = null, strict = false) {
|
|
684
|
+
if (key2 !== null) {
|
|
685
|
+
return super.unique(key2, strict);
|
|
686
|
+
}
|
|
687
|
+
return new this.constructor(Object.values(this.getDictionary()));
|
|
688
|
+
}
|
|
689
|
+
find(key2, defaultValue = null) {
|
|
690
|
+
if (key2 instanceof model_default) {
|
|
691
|
+
key2 = key2.getKey();
|
|
692
|
+
}
|
|
693
|
+
if (isArray(key2)) {
|
|
694
|
+
if (this.isEmpty()) {
|
|
695
|
+
return new this.constructor();
|
|
696
|
+
}
|
|
697
|
+
return this.whereIn(this.first().getKeyName(), key2);
|
|
698
|
+
}
|
|
699
|
+
collect(this.items).first((model) => {
|
|
700
|
+
return model.getKey() == key2;
|
|
701
|
+
});
|
|
702
|
+
return this.items.filter((model) => {
|
|
703
|
+
return model.getKey() == key2;
|
|
704
|
+
})[0] || defaultValue;
|
|
705
|
+
}
|
|
706
|
+
async fresh(...args) {
|
|
707
|
+
if (this.isEmpty()) {
|
|
708
|
+
return new this.constructor();
|
|
709
|
+
}
|
|
710
|
+
const model = this.first();
|
|
711
|
+
const freshModels = (await model.newQuery().with(...args).whereIn(model.getKeyName(), this.modelKeys()).get()).getDictionary();
|
|
712
|
+
return this.filter((model2) => {
|
|
713
|
+
return model2.exists && freshModels[model2.getKey()] !== void 0;
|
|
714
|
+
}).map((model2) => {
|
|
715
|
+
return freshModels[model2.getKey()];
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
makeVisible(attributes) {
|
|
719
|
+
return this.each((item) => {
|
|
720
|
+
item.makeVisible(attributes);
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
makeHidden(attributes) {
|
|
724
|
+
return this.each((item) => {
|
|
725
|
+
item.makeHidden(attributes);
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
append(attributes) {
|
|
729
|
+
return this.each((item) => {
|
|
730
|
+
item.append(attributes);
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
only(keys) {
|
|
734
|
+
if (keys === null) {
|
|
735
|
+
return new _Collection(this.items);
|
|
736
|
+
}
|
|
737
|
+
const dictionary = pick(this.getDictionary(), keys);
|
|
738
|
+
return new this.constructor(Object.values(dictionary));
|
|
739
|
+
}
|
|
740
|
+
getDictionary(items = null) {
|
|
741
|
+
items = items === null ? this.items : items;
|
|
742
|
+
const dictionary = {};
|
|
743
|
+
items.map((value) => {
|
|
744
|
+
dictionary[value.getKey()] = value;
|
|
745
|
+
});
|
|
746
|
+
return dictionary;
|
|
747
|
+
}
|
|
748
|
+
toQuery() {
|
|
749
|
+
const model = this.first();
|
|
750
|
+
if (!model) {
|
|
751
|
+
throw new Error("Unable to create query for empty collection.");
|
|
752
|
+
}
|
|
753
|
+
const modelName = model.constructor.name;
|
|
754
|
+
if (this.filter((model2) => {
|
|
755
|
+
return !(model2 instanceof modelName);
|
|
756
|
+
}).isNotEmpty()) {
|
|
757
|
+
throw new Error("Unable to create query for collection with mixed types.");
|
|
758
|
+
}
|
|
759
|
+
return model.newModelQuery().whereKey(this.modelKeys());
|
|
760
|
+
}
|
|
761
|
+
toData() {
|
|
762
|
+
return this.all().map((item) => typeof item.toData == "function" ? item.toData() : item);
|
|
763
|
+
}
|
|
764
|
+
toJSON() {
|
|
765
|
+
return this.toData();
|
|
766
|
+
}
|
|
767
|
+
toJson(...args) {
|
|
768
|
+
return JSON.stringify(this.toData(), ...args);
|
|
769
|
+
}
|
|
770
|
+
[Symbol.iterator]() {
|
|
771
|
+
const items = this.items;
|
|
772
|
+
let length = this.items.length;
|
|
773
|
+
let n = 0;
|
|
774
|
+
return {
|
|
775
|
+
next() {
|
|
776
|
+
return n < length ? {
|
|
777
|
+
value: items[n++],
|
|
778
|
+
done: false
|
|
779
|
+
} : {
|
|
780
|
+
done: true
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
var collection_default = Collection;
|
|
787
|
+
|
|
788
|
+
// src/relations/concerns/interacts-with-pivot-table.js
|
|
789
|
+
import { diff as difference2, isArray as isArray2, merge } from "radashi";
|
|
790
|
+
import { collect as collect2 } from "collect.js";
|
|
791
|
+
var InteractsWithPivotTable = (Relation2) => {
|
|
792
|
+
return class extends Relation2 {
|
|
793
|
+
newExistingPivot(attributes = []) {
|
|
794
|
+
return this.newPivot(attributes, true);
|
|
795
|
+
}
|
|
796
|
+
newPivot(attributes = [], exists = false) {
|
|
797
|
+
const pivot = this.related.newPivot(this.parent, attributes, this.getTable(), exists, this.using);
|
|
798
|
+
return pivot.setPivotKeys(this.foreignPivotKey, this.relatedPivotKey);
|
|
799
|
+
}
|
|
800
|
+
async attach(id, attributes = {}, touch = true) {
|
|
801
|
+
if (this.using) {
|
|
802
|
+
await this.attachUsingCustomClass(id, attributes);
|
|
803
|
+
} else {
|
|
804
|
+
await this.newPivotStatement().insert(this.formatAttachRecords(this.parseIds(id), attributes));
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
async detach(ids = null, touch = true) {
|
|
808
|
+
let results;
|
|
809
|
+
if (this.using && ids !== null && this.pivotWheres.length == 0 && this.pivotWhereIns.length == 0 && this.pivotWhereNulls.length == 0) {
|
|
810
|
+
results = await this.detachUsingCustomClass(ids);
|
|
811
|
+
} else {
|
|
812
|
+
const query = this.newPivotQuery();
|
|
813
|
+
if (ids !== null) {
|
|
814
|
+
ids = this.parseIds(ids);
|
|
815
|
+
if (ids.length == 0) {
|
|
816
|
+
return 0;
|
|
817
|
+
}
|
|
818
|
+
query.whereIn(this.getQualifiedRelatedPivotKeyName(), ids);
|
|
819
|
+
}
|
|
820
|
+
results = await query.delete();
|
|
821
|
+
}
|
|
822
|
+
return results;
|
|
823
|
+
}
|
|
824
|
+
async sync(ids, detaching = true) {
|
|
825
|
+
let changes = {
|
|
826
|
+
attached: [],
|
|
827
|
+
detached: [],
|
|
828
|
+
updated: []
|
|
829
|
+
};
|
|
830
|
+
let records;
|
|
831
|
+
const results = await this.getCurrentlyAttachedPivots();
|
|
832
|
+
const current = results.length === 0 ? [] : results.map((result) => result.toData()).pluck(this.relatedPivotKey).all().map((i) => String(i));
|
|
833
|
+
const detach = difference2(current, Object.keys(records = this.formatRecordsList(this.parseIds(ids))));
|
|
834
|
+
if (detaching && detach.length > 0) {
|
|
835
|
+
await this.detach(detach);
|
|
836
|
+
changes.detached = this.castKeys(detach);
|
|
837
|
+
}
|
|
838
|
+
changes = merge(changes, await this.attachNew(records, current, false));
|
|
839
|
+
return changes;
|
|
840
|
+
}
|
|
841
|
+
syncWithoutDetaching(ids) {
|
|
842
|
+
return this.sync(ids, false);
|
|
843
|
+
}
|
|
844
|
+
syncWithPivotValues(ids, values, detaching = true) {
|
|
845
|
+
return this.sync(collect2(this.parseIds(ids)).mapWithKeys((id) => {
|
|
846
|
+
return [id, values];
|
|
847
|
+
}), detaching);
|
|
848
|
+
}
|
|
849
|
+
withPivot(columns) {
|
|
850
|
+
this.pivotColumns = this.pivotColumns.concat(isArray2(columns) ? columns : Array.prototype.slice.call(arguments));
|
|
851
|
+
return this;
|
|
852
|
+
}
|
|
853
|
+
async attachNew(records, current, touch = true) {
|
|
854
|
+
const changes = {
|
|
855
|
+
attached: [],
|
|
856
|
+
updated: []
|
|
857
|
+
};
|
|
858
|
+
for (const id in records) {
|
|
859
|
+
const attributes = records[id];
|
|
860
|
+
if (!current.includes(id)) {
|
|
861
|
+
await this.attach(id, attributes, touch);
|
|
862
|
+
changes.attached.push(this.castKey(id));
|
|
863
|
+
} else if (Object.keys(attributes).length > 0 && await this.updateExistingPivot(id, attributes, touch)) {
|
|
864
|
+
changes.updated.push(this.castKey(id));
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
return changes;
|
|
868
|
+
}
|
|
869
|
+
async updateExistingPivot(id, attributes, touch = true) {
|
|
870
|
+
if (this.using && this.pivotWheres.length > 0 && this.pivotWhereInspivotWheres.length > 0 && this.pivotWhereNullspivotWheres.length > 0) {
|
|
871
|
+
return await this.updateExistingPivotUsingCustomClass(id, attributes, touch);
|
|
872
|
+
}
|
|
873
|
+
if (this.hasPivotColumn(this.updatedAt())) {
|
|
874
|
+
attributes = this.addTimestampsToAttachment(attributes, true);
|
|
875
|
+
}
|
|
876
|
+
const updated = this.newPivotStatementForId(this.parseId(id)).update(this.castAttributes(attributes));
|
|
877
|
+
return updated;
|
|
878
|
+
}
|
|
879
|
+
addTimestampsToAttachment(record, exists = false) {
|
|
880
|
+
let fresh = this.parent.freshTimestamp();
|
|
881
|
+
if (this.using) {
|
|
882
|
+
const pivotModel = new this.using();
|
|
883
|
+
fresh = pivotModel.fromDateTime(fresh);
|
|
884
|
+
}
|
|
885
|
+
if (!exists && this.hasPivotColumn(this.createdAt())) {
|
|
886
|
+
record[this.createdAt()] = fresh;
|
|
887
|
+
}
|
|
888
|
+
if (this.hasPivotColumn(this.updatedAt())) {
|
|
889
|
+
record[this.updatedAt()] = fresh;
|
|
890
|
+
}
|
|
891
|
+
return record;
|
|
892
|
+
}
|
|
893
|
+
async updateExistingPivotUsingCustomClass(id, attributes, touch) {
|
|
894
|
+
const pivot = await this.getCurrentlyAttachedPivots().where(this.foreignPivotKey, this.parent[this.parentKey]).where(this.relatedPivotKey, this.parseId(id)).first();
|
|
895
|
+
const updated = pivot ? pivot.fill(attributes).isDirty() : false;
|
|
896
|
+
if (updated) {
|
|
897
|
+
await pivot.save();
|
|
898
|
+
}
|
|
899
|
+
return parseInt(updated);
|
|
900
|
+
}
|
|
901
|
+
formatRecordsList(records) {
|
|
902
|
+
return collect2(records).mapWithKeys((attributes, id) => {
|
|
903
|
+
if (!isArray2(attributes)) {
|
|
904
|
+
[id, attributes] = [attributes, {}];
|
|
905
|
+
}
|
|
906
|
+
return [id, attributes];
|
|
907
|
+
}).all();
|
|
908
|
+
}
|
|
909
|
+
async getCurrentlyAttachedPivots() {
|
|
910
|
+
const query = this.newPivotQuery();
|
|
911
|
+
const results = await query.get();
|
|
912
|
+
return results.map((record) => {
|
|
913
|
+
const modelClass = this.using || Pivot;
|
|
914
|
+
const pivot = modelClass.fromRawAttributes(this.parent, record, this.getTable(), true);
|
|
915
|
+
return pivot.setPivotKeys(this.foreignPivotKey, this.relatedPivotKey);
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
castKeys(keys) {
|
|
919
|
+
return keys.map((v) => {
|
|
920
|
+
return this.castKey(v);
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
castKey(key2) {
|
|
924
|
+
return this.getTypeSwapValue(this.related.getKeyType(), key2);
|
|
925
|
+
}
|
|
926
|
+
getTypeSwapValue(type, value) {
|
|
927
|
+
switch (type.toLowerCase()) {
|
|
928
|
+
case "int":
|
|
929
|
+
case "integer":
|
|
930
|
+
return parseInt(value);
|
|
931
|
+
case "real":
|
|
932
|
+
case "float":
|
|
933
|
+
case "double":
|
|
934
|
+
return parseFloat(value);
|
|
935
|
+
case "string":
|
|
936
|
+
return String(value);
|
|
937
|
+
default:
|
|
938
|
+
return value;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
newPivotQuery() {
|
|
942
|
+
const query = this.newPivotStatement();
|
|
943
|
+
this.pivotWheres.map((args) => {
|
|
944
|
+
query.where(...args);
|
|
945
|
+
});
|
|
946
|
+
this.pivotWhereIns.map((args) => {
|
|
947
|
+
query.whereIn(...args);
|
|
948
|
+
});
|
|
949
|
+
this.pivotWhereNulls.map((args) => {
|
|
950
|
+
query.whereNull(...args);
|
|
951
|
+
});
|
|
952
|
+
return query.where(this.getQualifiedForeignPivotKeyName(), this.parent[this.parentKey]);
|
|
953
|
+
}
|
|
954
|
+
async detachUsingCustomClass(ids) {
|
|
955
|
+
let results = 0;
|
|
956
|
+
for (const id in this.parseIds(ids)) {
|
|
957
|
+
results += await this.newPivot({
|
|
958
|
+
[this.foreignPivotKey]: this.parent[this.parentKey],
|
|
959
|
+
[this.relatedPivotKey]: id
|
|
960
|
+
}, true).delete();
|
|
961
|
+
}
|
|
962
|
+
;
|
|
963
|
+
return results;
|
|
964
|
+
}
|
|
965
|
+
newPivotStatement() {
|
|
966
|
+
const builder = this.parent.newQuery();
|
|
967
|
+
builder.setTable(this.table);
|
|
968
|
+
return builder;
|
|
969
|
+
}
|
|
970
|
+
async attachUsingCustomClass(id, attributes) {
|
|
971
|
+
const records = this.formatAttachRecords(this.parseIds(id), attributes);
|
|
972
|
+
await Promise.all(records.map(async (record) => {
|
|
973
|
+
await this.newPivot(record, false).save();
|
|
974
|
+
}));
|
|
975
|
+
}
|
|
976
|
+
formatAttachRecords(ids, attributes) {
|
|
977
|
+
const records = [];
|
|
978
|
+
const hasTimestamps = this.hasPivotColumn(this.createdAt()) || this.hasPivotColumn(this.updatedAt());
|
|
979
|
+
for (const key2 in ids) {
|
|
980
|
+
const value = ids[key2];
|
|
981
|
+
records.push(this.formatAttachRecord(key2, value, attributes, hasTimestamps));
|
|
982
|
+
}
|
|
983
|
+
return records;
|
|
984
|
+
}
|
|
985
|
+
formatAttachRecord(key2, value, attributes, hasTimestamps) {
|
|
986
|
+
const [id, newAttributes] = this.extractAttachIdAndAttributes(key2, value, attributes);
|
|
987
|
+
return merge(this.baseAttachRecord(id, hasTimestamps), newAttributes);
|
|
988
|
+
}
|
|
989
|
+
baseAttachRecord(id, timed) {
|
|
990
|
+
let record = {};
|
|
991
|
+
record[this.relatedPivotKey] = id;
|
|
992
|
+
record[this.foreignPivotKey] = this.parent[this.parentKey];
|
|
993
|
+
if (timed) {
|
|
994
|
+
record = this.addTimestampsToAttachment(record);
|
|
995
|
+
}
|
|
996
|
+
this.pivotValues.map((value) => {
|
|
997
|
+
record[value.column] = value.value;
|
|
998
|
+
});
|
|
999
|
+
return record;
|
|
1000
|
+
}
|
|
1001
|
+
extractAttachIdAndAttributes(key2, value, newAttributes) {
|
|
1002
|
+
return isArray2(value) ? [key2, { ...value, ...newAttributes }] : [value, newAttributes];
|
|
1003
|
+
}
|
|
1004
|
+
hasPivotColumn = function(column) {
|
|
1005
|
+
return this.pivotColumns.includes(column);
|
|
1006
|
+
};
|
|
1007
|
+
parseIds(value) {
|
|
1008
|
+
if (value instanceof Model) {
|
|
1009
|
+
return [value[this.relatedKey]];
|
|
1010
|
+
}
|
|
1011
|
+
if (value instanceof collection_default) {
|
|
1012
|
+
return value.pluck(this.relatedKey).all();
|
|
1013
|
+
}
|
|
1014
|
+
return isArray2(value) ? value : [value];
|
|
1015
|
+
}
|
|
1016
|
+
};
|
|
1017
|
+
};
|
|
1018
|
+
var interacts_with_pivot_table_default = InteractsWithPivotTable;
|
|
1019
|
+
|
|
1020
|
+
// src/relations/belongs-to-many.js
|
|
1021
|
+
import { collect as collect3 } from "collect.js";
|
|
1022
|
+
var BelongsToMany = class extends compose(relation_default, interacts_with_pivot_table_default) {
|
|
1023
|
+
table;
|
|
1024
|
+
foreignPivotKey;
|
|
1025
|
+
relatedPivotKey;
|
|
1026
|
+
parentKey;
|
|
1027
|
+
relatedKey;
|
|
1028
|
+
pivotColumns = [];
|
|
1029
|
+
pivotValues = [];
|
|
1030
|
+
pivotWheres = [];
|
|
1031
|
+
pivotWhereIns = [];
|
|
1032
|
+
pivotWhereNulls = [];
|
|
1033
|
+
accessor = "pivot";
|
|
1034
|
+
// withTimestamps = false;
|
|
1035
|
+
using;
|
|
1036
|
+
pivotCreatedAt;
|
|
1037
|
+
pivotUpdatedAt;
|
|
1038
|
+
constructor(query, parent, table, foreignPivotKey, relatedPivotKey, parentKey, relatedKey) {
|
|
1039
|
+
super(query, parent);
|
|
1040
|
+
this.table = table;
|
|
1041
|
+
this.foreignPivotKey = foreignPivotKey;
|
|
1042
|
+
this.relatedPivotKey = relatedPivotKey;
|
|
1043
|
+
this.parentKey = parentKey;
|
|
1044
|
+
this.relatedKey = relatedKey;
|
|
1045
|
+
this.addConstraints();
|
|
1046
|
+
return this.asProxy();
|
|
1047
|
+
}
|
|
1048
|
+
initRelation(models, relation) {
|
|
1049
|
+
models.map((model) => {
|
|
1050
|
+
model.setRelation(relation, new collection_default([]));
|
|
1051
|
+
});
|
|
1052
|
+
return models;
|
|
1053
|
+
}
|
|
1054
|
+
addConstraints() {
|
|
1055
|
+
this.performJoin();
|
|
1056
|
+
if (this.constructor.constraints) {
|
|
1057
|
+
this.addWhereConstraints();
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
performJoin(query = null) {
|
|
1061
|
+
query = query || this.query;
|
|
1062
|
+
query.join(this.getTable(), this.getQualifiedRelatedKeyName(), "=", this.qualifyPivotColumn(this.relatedPivotKey));
|
|
1063
|
+
return this;
|
|
1064
|
+
}
|
|
1065
|
+
getTable() {
|
|
1066
|
+
return this.table;
|
|
1067
|
+
}
|
|
1068
|
+
getQualifiedRelatedKeyName() {
|
|
1069
|
+
return this.related.qualifyColumn(this.relatedKey);
|
|
1070
|
+
}
|
|
1071
|
+
async getResults() {
|
|
1072
|
+
return this.parent[this.parentKey] !== null ? await this.get() : new collection_default([]);
|
|
1073
|
+
}
|
|
1074
|
+
addWhereConstraints() {
|
|
1075
|
+
this.query.where(this.getQualifiedForeignPivotKeyName(), "=", this.parent[this.parentKey]);
|
|
1076
|
+
return this;
|
|
1077
|
+
}
|
|
1078
|
+
async get(columns = ["*"]) {
|
|
1079
|
+
const builder = this.query.applyScopes();
|
|
1080
|
+
columns = builder.query?._statements?.find((item) => item.grouping == "columns") ? [] : columns;
|
|
1081
|
+
let models = await builder.select(this.shouldSelect(columns)).getModels();
|
|
1082
|
+
this.hydratePivotRelation(models);
|
|
1083
|
+
if (models.length > 0) {
|
|
1084
|
+
models = await builder.eagerLoadRelations(models);
|
|
1085
|
+
}
|
|
1086
|
+
return new collection_default(models);
|
|
1087
|
+
}
|
|
1088
|
+
async first(columns = ["*"]) {
|
|
1089
|
+
const results = await this.take(1).get(columns);
|
|
1090
|
+
return results.count() > 0 ? results.first() : null;
|
|
1091
|
+
}
|
|
1092
|
+
async firstOrFail(columns = ["*"]) {
|
|
1093
|
+
const model = await this.first(columns);
|
|
1094
|
+
if (model !== null) {
|
|
1095
|
+
return model;
|
|
1096
|
+
}
|
|
1097
|
+
throw new ModelNotFoundError().setModel(this.related.constructor);
|
|
1098
|
+
}
|
|
1099
|
+
async paginate(page = 1, perPage = 15, columns = ["*"]) {
|
|
1100
|
+
this.query.select(this.shouldSelect(columns));
|
|
1101
|
+
return tap(await this.query.paginate(page, perPage), (paginator) => {
|
|
1102
|
+
this.hydratePivotRelation(paginator.items());
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
async chunk(count, callback) {
|
|
1106
|
+
return await this.prepareQueryBuilder().chunk(count, async (results, page) => {
|
|
1107
|
+
this.hydratePivotRelation(results.all());
|
|
1108
|
+
return await callback(results, page);
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
setUsing(model) {
|
|
1112
|
+
this.using = model;
|
|
1113
|
+
return this;
|
|
1114
|
+
}
|
|
1115
|
+
as(accessor) {
|
|
1116
|
+
this.accessor = accessor;
|
|
1117
|
+
return this;
|
|
1118
|
+
}
|
|
1119
|
+
prepareQueryBuilder() {
|
|
1120
|
+
return this.query.select(this.shouldSelect());
|
|
1121
|
+
}
|
|
1122
|
+
hydratePivotRelation(models) {
|
|
1123
|
+
models.map((model) => {
|
|
1124
|
+
model.setRelation(this.accessor, this.newExistingPivot(this.migratePivotAttributes(model)));
|
|
1125
|
+
});
|
|
1126
|
+
}
|
|
1127
|
+
migratePivotAttributes(model) {
|
|
1128
|
+
const values = {};
|
|
1129
|
+
for (const key2 in model.attributes) {
|
|
1130
|
+
const value = model.attributes[key2];
|
|
1131
|
+
if (key2.startsWith("pivot_")) {
|
|
1132
|
+
values[key2.substring(6)] = value;
|
|
1133
|
+
model.attributes = omit2(model.attributes, [key2]);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
return values;
|
|
1137
|
+
}
|
|
1138
|
+
withTimestamps(createdAt = null, updatedAt = null) {
|
|
1139
|
+
this.pivotCreatedAt = createdAt;
|
|
1140
|
+
this.pivotUpdatedAt = updatedAt;
|
|
1141
|
+
return this.withPivot(this.createdAt(), this.updatedAt());
|
|
1142
|
+
}
|
|
1143
|
+
shouldSelect(columns = ["*"]) {
|
|
1144
|
+
if (isEqual(columns, ["*"])) {
|
|
1145
|
+
columns = [this.related.getTable() + ".*"];
|
|
1146
|
+
}
|
|
1147
|
+
return columns.concat(this.aliasedPivotColumns());
|
|
1148
|
+
}
|
|
1149
|
+
aliasedPivotColumns() {
|
|
1150
|
+
const defaults = [this.foreignPivotKey, this.relatedPivotKey];
|
|
1151
|
+
return collect3(defaults.concat(this.pivotColumns)).map((column) => {
|
|
1152
|
+
return this.qualifyPivotColumn(column) + " as pivot_" + column;
|
|
1153
|
+
}).unique().all();
|
|
1154
|
+
}
|
|
1155
|
+
qualifyPivotColumn(column) {
|
|
1156
|
+
return column.includes(".") ? column : this.getTable() + "." + column;
|
|
1157
|
+
}
|
|
1158
|
+
match(models, results, relation) {
|
|
1159
|
+
const dictionary = this.buildDictionary(results);
|
|
1160
|
+
models.map((model) => {
|
|
1161
|
+
const key2 = model.getKey();
|
|
1162
|
+
if (dictionary[key2] !== void 0) {
|
|
1163
|
+
model.setRelation(relation, dictionary[key2]);
|
|
1164
|
+
}
|
|
1165
|
+
});
|
|
1166
|
+
return models;
|
|
1167
|
+
}
|
|
1168
|
+
buildDictionary(results) {
|
|
1169
|
+
const dictionary = {};
|
|
1170
|
+
results.map((result) => {
|
|
1171
|
+
const value = result[this.accessor][this.foreignPivotKey];
|
|
1172
|
+
if (dictionary[value] === void 0) {
|
|
1173
|
+
dictionary[value] = new collection_default([]);
|
|
1174
|
+
}
|
|
1175
|
+
dictionary[value].push(result);
|
|
1176
|
+
});
|
|
1177
|
+
return dictionary;
|
|
1178
|
+
}
|
|
1179
|
+
addEagerConstraints(models) {
|
|
1180
|
+
this.query.whereIn(this.getQualifiedForeignPivotKeyName(), this.getKeys(models, this.parentKey));
|
|
1181
|
+
}
|
|
1182
|
+
getQualifiedForeignPivotKeyName() {
|
|
1183
|
+
return this.qualifyPivotColumn(this.foreignPivotKey);
|
|
1184
|
+
}
|
|
1185
|
+
getQualifiedRelatedPivotKeyName() {
|
|
1186
|
+
return this.qualifyPivotColumn(this.relatedPivotKey);
|
|
1187
|
+
}
|
|
1188
|
+
wherePivot(column, operator = null, value = null, boolean = "and") {
|
|
1189
|
+
this.pivotWheres.push(Array.prototype.slice.call(arguments));
|
|
1190
|
+
return this.where(this.qualifyPivotColumn(column), operator, value, boolean);
|
|
1191
|
+
}
|
|
1192
|
+
wherePivotBetween(column, values, boolean = "and", not = false) {
|
|
1193
|
+
return this.whereBetween(this.qualifyPivotColumn(column), values, boolean, not);
|
|
1194
|
+
}
|
|
1195
|
+
orWherePivotBetween(column, values) {
|
|
1196
|
+
return this.wherePivotBetween(column, values, "or");
|
|
1197
|
+
}
|
|
1198
|
+
wherePivotNotBetween(column, values, boolean = "and") {
|
|
1199
|
+
return this.wherePivotBetween(column, values, boolean, true);
|
|
1200
|
+
}
|
|
1201
|
+
orWherePivotNotBetween(column, values) {
|
|
1202
|
+
return this.wherePivotBetween(column, values, "or", true);
|
|
1203
|
+
}
|
|
1204
|
+
wherePivotIn(column, values, boolean = "and", not = false) {
|
|
1205
|
+
return this.whereIn(this.qualifyPivotColumn(column), values, boolean, not);
|
|
1206
|
+
}
|
|
1207
|
+
orWherePivot(column, operator = null, value = null) {
|
|
1208
|
+
return this.wherePivot(column, operator, value, "or");
|
|
1209
|
+
}
|
|
1210
|
+
orWherePivotIn(column, values) {
|
|
1211
|
+
return this.wherePivotIn(column, values, "or");
|
|
1212
|
+
}
|
|
1213
|
+
wherePivotNotIn(column, values, boolean = "and") {
|
|
1214
|
+
return this.wherePivotIn(column, values, boolean, true);
|
|
1215
|
+
}
|
|
1216
|
+
orWherePivotNotIn(column, values) {
|
|
1217
|
+
return this.wherePivotNotIn(column, values, "or");
|
|
1218
|
+
}
|
|
1219
|
+
wherePivotNull(column, boolean = "and", not = false) {
|
|
1220
|
+
return this.whereNull(this.qualifyPivotColumn(column), boolean, not);
|
|
1221
|
+
}
|
|
1222
|
+
wherePivotNotNull(column, boolean = "and") {
|
|
1223
|
+
return this.wherePivotNull(column, boolean, true);
|
|
1224
|
+
}
|
|
1225
|
+
orWherePivotNull(column, not = false) {
|
|
1226
|
+
return this.wherePivotNull(column, "or", not);
|
|
1227
|
+
}
|
|
1228
|
+
orWherePivotNotNull(column) {
|
|
1229
|
+
return this.orWherePivotNull(column, true);
|
|
1230
|
+
}
|
|
1231
|
+
orderByPivot(column, direction = "asc") {
|
|
1232
|
+
return this.orderBy(this.qualifyPivotColumn(column), direction);
|
|
1233
|
+
}
|
|
1234
|
+
createdAt() {
|
|
1235
|
+
return this.pivotCreatedAt || this.parent.getCreatedAtColumn();
|
|
1236
|
+
}
|
|
1237
|
+
updatedAt() {
|
|
1238
|
+
return this.pivotUpdatedAt || this.parent.getUpdatedAtColumn();
|
|
1239
|
+
}
|
|
1240
|
+
getExistenceCompareKey() {
|
|
1241
|
+
return this.getQualifiedForeignPivotKeyName();
|
|
1242
|
+
}
|
|
1243
|
+
// touchIfTouching() {
|
|
1244
|
+
// if (this.touchingParent()) {
|
|
1245
|
+
// this.getParent().touch();
|
|
1246
|
+
// }
|
|
1247
|
+
// if (this.getParent().touches(this.relationName)) {
|
|
1248
|
+
// this.touch();
|
|
1249
|
+
// }
|
|
1250
|
+
// }
|
|
1251
|
+
getRelationExistenceQuery(query, parentQuery, columns = ["*"]) {
|
|
1252
|
+
if (parentQuery.getQuery()._single.table == query.getQuery()._single.table) {
|
|
1253
|
+
return this.getRelationExistenceQueryForSelfJoin(query, parentQuery, columns);
|
|
1254
|
+
}
|
|
1255
|
+
this.performJoin(query);
|
|
1256
|
+
return super.getRelationExistenceQuery(query, parentQuery, columns);
|
|
1257
|
+
}
|
|
1258
|
+
getRelationExistenceQueryForSelfJoin(query, parentQuery, columns = ["*"]) {
|
|
1259
|
+
const hash = this.getRelationCountHash();
|
|
1260
|
+
query.select(columns).from(this.related.getTable() + " as " + hash);
|
|
1261
|
+
this.related.setTable(hash);
|
|
1262
|
+
this.performJoin(query);
|
|
1263
|
+
return super.getRelationExistenceQuery(query, parentQuery, columns);
|
|
1264
|
+
}
|
|
1265
|
+
};
|
|
1266
|
+
var belongs_to_many_default = BelongsToMany;
|
|
1267
|
+
|
|
1268
|
+
// src/errors.js
|
|
1269
|
+
import { isArray as isArray3 } from "radashi";
|
|
1270
|
+
var BaseError = class extends Error {
|
|
1271
|
+
constructor(message, entity) {
|
|
1272
|
+
super(message);
|
|
1273
|
+
Error.captureStackTrace(this, this.constructor);
|
|
1274
|
+
this.name = this.constructor.name;
|
|
1275
|
+
this.message = message;
|
|
1276
|
+
}
|
|
1277
|
+
};
|
|
1278
|
+
var ModelNotFoundError2 = class extends BaseError {
|
|
1279
|
+
model;
|
|
1280
|
+
ids;
|
|
1281
|
+
setModel(model, ids = []) {
|
|
1282
|
+
this.model = model;
|
|
1283
|
+
this.ids = isArray3(ids) ? ids : [ids];
|
|
1284
|
+
this.message = `No query results for model [${model}]`;
|
|
1285
|
+
if (this.ids.length > 0) {
|
|
1286
|
+
this.message += " " + this.ids.join(", ");
|
|
1287
|
+
} else {
|
|
1288
|
+
this.message += ".";
|
|
1289
|
+
}
|
|
1290
|
+
return this;
|
|
1291
|
+
}
|
|
1292
|
+
getModel() {
|
|
1293
|
+
return this.model;
|
|
1294
|
+
}
|
|
1295
|
+
getIds() {
|
|
1296
|
+
return this.ids;
|
|
1297
|
+
}
|
|
1298
|
+
};
|
|
1299
|
+
var RelationNotFoundError = class extends BaseError {
|
|
1300
|
+
};
|
|
1301
|
+
var InvalidArgumentError = class extends BaseError {
|
|
1302
|
+
};
|
|
1303
|
+
|
|
1304
|
+
// src/builder.js
|
|
1305
|
+
import { diff as difference3, flat as flatten, isArray as isArray4, isString, assign as merge2, omit as omit3, snake as snake2 } from "radashi";
|
|
1306
|
+
import { Collection as BaseCollection2 } from "collect.js";
|
|
1307
|
+
|
|
1308
|
+
// src/paginator.js
|
|
1309
|
+
var Paginator = class {
|
|
1310
|
+
static formatter = null;
|
|
1311
|
+
_items;
|
|
1312
|
+
_total;
|
|
1313
|
+
_perPage;
|
|
1314
|
+
_lastPage;
|
|
1315
|
+
_currentPage;
|
|
1316
|
+
static setFormatter(formatter) {
|
|
1317
|
+
if (typeof formatter !== "function" && formatter !== null && formatter !== void 0) {
|
|
1318
|
+
throw new Error("Paginator formatter must be a function or null");
|
|
1319
|
+
}
|
|
1320
|
+
this.formatter = formatter;
|
|
1321
|
+
}
|
|
1322
|
+
constructor(items, total, perPage, currentPage = null, options = {}) {
|
|
1323
|
+
this.options = options;
|
|
1324
|
+
for (const key2 in options) {
|
|
1325
|
+
const value = options[key2];
|
|
1326
|
+
this[key2] = value;
|
|
1327
|
+
}
|
|
1328
|
+
this._total = total;
|
|
1329
|
+
this._perPage = parseInt(perPage);
|
|
1330
|
+
this._lastPage = Math.max(Math.ceil(total / perPage), 1);
|
|
1331
|
+
this._currentPage = currentPage;
|
|
1332
|
+
this.setItems(items);
|
|
1333
|
+
}
|
|
1334
|
+
setItems(items) {
|
|
1335
|
+
this._items = items instanceof collection_default ? items : new collection_default(items);
|
|
1336
|
+
this.hasMore = this._items.count() > this._perPage;
|
|
1337
|
+
this._items = this._items.slice(0, this._perPage);
|
|
1338
|
+
}
|
|
1339
|
+
firstItem() {
|
|
1340
|
+
return this.count() > 0 ? (this._currentPage - 1) * this._perPage + 1 : null;
|
|
1341
|
+
}
|
|
1342
|
+
lastItem() {
|
|
1343
|
+
return this.count() > 0 ? this.firstItem() + this.count() - 1 : null;
|
|
1344
|
+
}
|
|
1345
|
+
hasMorePages() {
|
|
1346
|
+
return this._currentPage < this._lastPage;
|
|
1347
|
+
}
|
|
1348
|
+
get(index) {
|
|
1349
|
+
return this._items.get(index);
|
|
1350
|
+
}
|
|
1351
|
+
count() {
|
|
1352
|
+
return this._items.count();
|
|
1353
|
+
}
|
|
1354
|
+
items() {
|
|
1355
|
+
return this._items;
|
|
1356
|
+
}
|
|
1357
|
+
map(callback) {
|
|
1358
|
+
return this._items.map(callback);
|
|
1359
|
+
}
|
|
1360
|
+
currentPage() {
|
|
1361
|
+
return this._currentPage;
|
|
1362
|
+
}
|
|
1363
|
+
onFirstPage() {
|
|
1364
|
+
return this._currentPage === 1;
|
|
1365
|
+
}
|
|
1366
|
+
perPage() {
|
|
1367
|
+
return this._perPage;
|
|
1368
|
+
}
|
|
1369
|
+
lastPage() {
|
|
1370
|
+
return this._lastPage;
|
|
1371
|
+
}
|
|
1372
|
+
total() {
|
|
1373
|
+
return this._total;
|
|
1374
|
+
}
|
|
1375
|
+
toData() {
|
|
1376
|
+
if (this.constructor.formatter && typeof this.constructor.formatter === "function") {
|
|
1377
|
+
return this.constructor.formatter(this);
|
|
1378
|
+
}
|
|
1379
|
+
return {
|
|
1380
|
+
current_page: this._currentPage,
|
|
1381
|
+
data: this._items.toData(),
|
|
1382
|
+
per_page: this._perPage,
|
|
1383
|
+
total: this._total,
|
|
1384
|
+
last_page: this._lastPage,
|
|
1385
|
+
count: this.count()
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1388
|
+
toJSON() {
|
|
1389
|
+
return this.toData();
|
|
1390
|
+
}
|
|
1391
|
+
toJson(...args) {
|
|
1392
|
+
return JSON.stringify(this.toData(), ...args);
|
|
1393
|
+
}
|
|
1394
|
+
};
|
|
1395
|
+
var paginator_default = Paginator;
|
|
1396
|
+
|
|
1397
|
+
// src/scope.js
|
|
1398
|
+
var Scope = class _Scope {
|
|
1399
|
+
constructor() {
|
|
1400
|
+
if (this.constructor === _Scope) {
|
|
1401
|
+
throw new Error("Scope cannot be instantiated");
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
apply(builder, model) {
|
|
1405
|
+
throw new Error("apply not implemented");
|
|
1406
|
+
}
|
|
1407
|
+
};
|
|
1408
|
+
var scope_default = Scope;
|
|
1409
|
+
|
|
1410
|
+
// src/builder.js
|
|
1411
|
+
var Builder = class _Builder {
|
|
1412
|
+
query;
|
|
1413
|
+
connection;
|
|
1414
|
+
model;
|
|
1415
|
+
actions;
|
|
1416
|
+
localMacros = {};
|
|
1417
|
+
eagerLoad = {};
|
|
1418
|
+
globalScopes = {};
|
|
1419
|
+
constructor(query) {
|
|
1420
|
+
this.query = query;
|
|
1421
|
+
return this.asProxy();
|
|
1422
|
+
}
|
|
1423
|
+
asProxy() {
|
|
1424
|
+
const handler = {
|
|
1425
|
+
get: function(target, prop) {
|
|
1426
|
+
if (typeof target[prop] !== "undefined") {
|
|
1427
|
+
return target[prop];
|
|
1428
|
+
}
|
|
1429
|
+
if ([
|
|
1430
|
+
"select",
|
|
1431
|
+
"from",
|
|
1432
|
+
"where",
|
|
1433
|
+
"orWhere",
|
|
1434
|
+
"whereColumn",
|
|
1435
|
+
"whereRaw",
|
|
1436
|
+
"whereNot",
|
|
1437
|
+
"orWhereNot",
|
|
1438
|
+
"whereIn",
|
|
1439
|
+
"orWhereIn",
|
|
1440
|
+
"whereNotIn",
|
|
1441
|
+
"orWhereNotIn",
|
|
1442
|
+
"whereNull",
|
|
1443
|
+
"orWhereNull",
|
|
1444
|
+
"whereNotNull",
|
|
1445
|
+
"orWhereNotNull",
|
|
1446
|
+
"whereExists",
|
|
1447
|
+
"orWhereExists",
|
|
1448
|
+
"whereNotExists",
|
|
1449
|
+
"orWhereNotExists",
|
|
1450
|
+
"whereBetween",
|
|
1451
|
+
"orWhereBetween",
|
|
1452
|
+
"whereNotBetween",
|
|
1453
|
+
"orWhereNotBetween",
|
|
1454
|
+
"whereLike",
|
|
1455
|
+
"orWhereLike",
|
|
1456
|
+
"whereILike",
|
|
1457
|
+
"orWhereILike",
|
|
1458
|
+
"whereJsonObject",
|
|
1459
|
+
"whereJsonPath",
|
|
1460
|
+
"whereJsonSupersetOf",
|
|
1461
|
+
"whereJsonSubsetOf",
|
|
1462
|
+
"join",
|
|
1463
|
+
"joinRaw",
|
|
1464
|
+
"leftJoin",
|
|
1465
|
+
"leftOuterJoin",
|
|
1466
|
+
"rightJoin",
|
|
1467
|
+
"rightOuterJoin",
|
|
1468
|
+
"crossJoin",
|
|
1469
|
+
"transacting",
|
|
1470
|
+
"groupBy",
|
|
1471
|
+
"groupByRaw",
|
|
1472
|
+
"returning",
|
|
1473
|
+
"having",
|
|
1474
|
+
"havingRaw",
|
|
1475
|
+
"havingBetween",
|
|
1476
|
+
"limit",
|
|
1477
|
+
"offset",
|
|
1478
|
+
"orderBy",
|
|
1479
|
+
"orderByRaw",
|
|
1480
|
+
// 'inRandomOrder',
|
|
1481
|
+
"union",
|
|
1482
|
+
"insert",
|
|
1483
|
+
"forUpdate",
|
|
1484
|
+
"forShare",
|
|
1485
|
+
"distinct",
|
|
1486
|
+
"clearOrder",
|
|
1487
|
+
"clear",
|
|
1488
|
+
"clearSelect",
|
|
1489
|
+
"clearWhere",
|
|
1490
|
+
"clearHaving",
|
|
1491
|
+
"clearGroup"
|
|
1492
|
+
].includes(prop)) {
|
|
1493
|
+
return (...args) => {
|
|
1494
|
+
target.query[prop](...args);
|
|
1495
|
+
return target.asProxy();
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
if ([
|
|
1499
|
+
"avg",
|
|
1500
|
+
"max",
|
|
1501
|
+
"min",
|
|
1502
|
+
"sum",
|
|
1503
|
+
"count"
|
|
1504
|
+
].includes(prop)) {
|
|
1505
|
+
return (column) => {
|
|
1506
|
+
const instance = target.asProxy();
|
|
1507
|
+
instance.applyScopes();
|
|
1508
|
+
column = !column && prop === "count" ? "*" : column;
|
|
1509
|
+
return instance.query[prop](column);
|
|
1510
|
+
};
|
|
1511
|
+
}
|
|
1512
|
+
if (typeof prop === "string") {
|
|
1513
|
+
if (target.hasMacro(prop)) {
|
|
1514
|
+
const instance = target.asProxy();
|
|
1515
|
+
return (...args) => {
|
|
1516
|
+
return instance.localMacros[prop](instance, ...args);
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
if (target.hasNamedScope(prop)) {
|
|
1520
|
+
const instance = target.asProxy();
|
|
1521
|
+
return (...args) => {
|
|
1522
|
+
instance.callNamedScope(prop, args);
|
|
1523
|
+
return instance;
|
|
1524
|
+
};
|
|
1525
|
+
}
|
|
1526
|
+
if (prop.startsWith("where")) {
|
|
1527
|
+
const column = snake2(prop.substring(5));
|
|
1528
|
+
return (...args) => {
|
|
1529
|
+
target.query.where(column, ...args);
|
|
1530
|
+
return target.asProxy();
|
|
1531
|
+
};
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
};
|
|
1536
|
+
return new Proxy(this, handler);
|
|
1537
|
+
}
|
|
1538
|
+
orWhere(...args) {
|
|
1539
|
+
if (typeof args[0] === "function") {
|
|
1540
|
+
const callback = args[0];
|
|
1541
|
+
this.query.orWhere((query) => {
|
|
1542
|
+
this.query = query;
|
|
1543
|
+
callback(this);
|
|
1544
|
+
});
|
|
1545
|
+
return this;
|
|
1546
|
+
}
|
|
1547
|
+
this.query.orWhere(...args);
|
|
1548
|
+
return this;
|
|
1549
|
+
}
|
|
1550
|
+
async chunk(count, callback) {
|
|
1551
|
+
let page = 1;
|
|
1552
|
+
let countResults;
|
|
1553
|
+
do {
|
|
1554
|
+
this.enforceOrderBy();
|
|
1555
|
+
const builder = this.clone();
|
|
1556
|
+
const results = await builder.forPage(page, count).get();
|
|
1557
|
+
countResults = results.count();
|
|
1558
|
+
if (countResults == 0) {
|
|
1559
|
+
break;
|
|
1560
|
+
}
|
|
1561
|
+
const bool = await callback(results, page);
|
|
1562
|
+
if (bool === false) {
|
|
1563
|
+
return false;
|
|
1564
|
+
}
|
|
1565
|
+
page++;
|
|
1566
|
+
} while (countResults === count);
|
|
1567
|
+
return true;
|
|
1568
|
+
}
|
|
1569
|
+
enforceOrderBy() {
|
|
1570
|
+
if (this.query._statements.filter((item) => item.grouping === "order").length === 0) {
|
|
1571
|
+
this.orderBy(this.model.getQualifiedKeyName(), "asc");
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
clone() {
|
|
1575
|
+
const query = this.query.clone();
|
|
1576
|
+
const builder = new this.constructor(query);
|
|
1577
|
+
builder.connection = this.connection;
|
|
1578
|
+
builder.setModel(this.model);
|
|
1579
|
+
builder.globalScopes = { ...this.globalScopes };
|
|
1580
|
+
builder.localMacros = { ...this.localMacros };
|
|
1581
|
+
builder.eagerLoad = { ...this.eagerLoad };
|
|
1582
|
+
return builder;
|
|
1583
|
+
}
|
|
1584
|
+
forPage(page, perPage = 15) {
|
|
1585
|
+
return this.offset((page - 1) * perPage).limit(perPage);
|
|
1586
|
+
}
|
|
1587
|
+
insert(...args) {
|
|
1588
|
+
return this.query.insert(...args);
|
|
1589
|
+
}
|
|
1590
|
+
update(values) {
|
|
1591
|
+
this.applyScopes();
|
|
1592
|
+
return this.query.update(this.addUpdatedAtColumn(values));
|
|
1593
|
+
}
|
|
1594
|
+
increment(column, amount = 1, extra = {}) {
|
|
1595
|
+
this.applyScopes();
|
|
1596
|
+
const db = this.model.getConnection();
|
|
1597
|
+
return this.query.update(this.addUpdatedAtColumn({
|
|
1598
|
+
...extra,
|
|
1599
|
+
[column]: db.raw(`${column} + ${amount}`)
|
|
1600
|
+
}));
|
|
1601
|
+
}
|
|
1602
|
+
decrement(column, amount = 1, extra = {}) {
|
|
1603
|
+
this.applyScopes();
|
|
1604
|
+
const db = this.model.getConnection();
|
|
1605
|
+
return this.query.update(this.addUpdatedAtColumn({
|
|
1606
|
+
...extra,
|
|
1607
|
+
[column]: db.raw(`${column} - ${amount}`)
|
|
1608
|
+
}));
|
|
1609
|
+
}
|
|
1610
|
+
addUpdatedAtColumn(values) {
|
|
1611
|
+
if (!this.model.usesTimestamps() || this.model.getUpdatedAtColumn() === null) {
|
|
1612
|
+
return values;
|
|
1613
|
+
}
|
|
1614
|
+
const column = this.model.getUpdatedAtColumn();
|
|
1615
|
+
values = merge2({ [column]: this.model.freshTimestampString() }, values);
|
|
1616
|
+
return values;
|
|
1617
|
+
}
|
|
1618
|
+
delete() {
|
|
1619
|
+
if (this.onDeleteCallback) {
|
|
1620
|
+
return this.onDeleteCallback(this);
|
|
1621
|
+
}
|
|
1622
|
+
return this.query.delete();
|
|
1623
|
+
}
|
|
1624
|
+
onDelete(callback) {
|
|
1625
|
+
this.onDeleteCallback = callback;
|
|
1626
|
+
}
|
|
1627
|
+
forceDelete() {
|
|
1628
|
+
return this.query.delete();
|
|
1629
|
+
}
|
|
1630
|
+
async create(attributes = {}) {
|
|
1631
|
+
return await tap(this.newModelInstance(attributes), async (instance) => {
|
|
1632
|
+
await instance.save({
|
|
1633
|
+
client: this.query
|
|
1634
|
+
});
|
|
1635
|
+
});
|
|
1636
|
+
}
|
|
1637
|
+
newModelInstance(attributes = {}) {
|
|
1638
|
+
return this.model.newInstance(attributes).setConnection(this.model.getConnectionName());
|
|
1639
|
+
}
|
|
1640
|
+
getQuery() {
|
|
1641
|
+
return this.query;
|
|
1642
|
+
}
|
|
1643
|
+
getModel() {
|
|
1644
|
+
return this.model;
|
|
1645
|
+
}
|
|
1646
|
+
setModel(model) {
|
|
1647
|
+
this.model = model;
|
|
1648
|
+
if (typeof this.query?.client?.table == "function") {
|
|
1649
|
+
this.query = this.query.client.table(this.model.getTable());
|
|
1650
|
+
} else {
|
|
1651
|
+
this.query = this.query?.table(this.model.getTable());
|
|
1652
|
+
}
|
|
1653
|
+
return this;
|
|
1654
|
+
}
|
|
1655
|
+
qualifyColumn(column) {
|
|
1656
|
+
return this.model.qualifyColumn(column);
|
|
1657
|
+
}
|
|
1658
|
+
setTable(table) {
|
|
1659
|
+
this.query = this.query.table(table);
|
|
1660
|
+
return this;
|
|
1661
|
+
}
|
|
1662
|
+
applyScopes() {
|
|
1663
|
+
if (!this.globalScopes) {
|
|
1664
|
+
return this;
|
|
1665
|
+
}
|
|
1666
|
+
const builder = this;
|
|
1667
|
+
for (const identifier in builder.globalScopes) {
|
|
1668
|
+
const scope = builder.globalScopes[identifier];
|
|
1669
|
+
if (scope instanceof scope_default) {
|
|
1670
|
+
scope.apply(builder, builder.getModel());
|
|
1671
|
+
} else {
|
|
1672
|
+
scope(builder);
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
return builder;
|
|
1676
|
+
}
|
|
1677
|
+
hasNamedScope(name) {
|
|
1678
|
+
return this.model && this.model.hasNamedScope(name);
|
|
1679
|
+
}
|
|
1680
|
+
callNamedScope(scope, parameters) {
|
|
1681
|
+
return this.model.callNamedScope(scope, [this, ...parameters]);
|
|
1682
|
+
}
|
|
1683
|
+
callScope(scope, parameters = []) {
|
|
1684
|
+
const result = scope(this, ...parameters) || this;
|
|
1685
|
+
return result;
|
|
1686
|
+
}
|
|
1687
|
+
scopes(scopes) {
|
|
1688
|
+
scopes.map((scopeName) => {
|
|
1689
|
+
const scopeMethod = getScopeMethod(scopeName);
|
|
1690
|
+
if (typeof this.model[scopeMethod] === "function") {
|
|
1691
|
+
this.globalScopes[scopeName] = this.model[scopeMethod];
|
|
1692
|
+
}
|
|
1693
|
+
});
|
|
1694
|
+
return this;
|
|
1695
|
+
}
|
|
1696
|
+
withGlobalScope(identifier, scope) {
|
|
1697
|
+
this.globalScopes[identifier] = scope;
|
|
1698
|
+
if (typeof scope.extend === "function") {
|
|
1699
|
+
scope.extend(this);
|
|
1700
|
+
}
|
|
1701
|
+
return this;
|
|
1702
|
+
}
|
|
1703
|
+
withoutGlobalScope(scope) {
|
|
1704
|
+
if (typeof scope !== "string") {
|
|
1705
|
+
scope = scope.constructor.name;
|
|
1706
|
+
}
|
|
1707
|
+
this.globalScopes = omit3(this.globalScopes, [scope]);
|
|
1708
|
+
return this;
|
|
1709
|
+
}
|
|
1710
|
+
macro(name, callback) {
|
|
1711
|
+
this.localMacros[name] = callback;
|
|
1712
|
+
return;
|
|
1713
|
+
}
|
|
1714
|
+
hasMacro(name) {
|
|
1715
|
+
return name in this.localMacros;
|
|
1716
|
+
}
|
|
1717
|
+
getMacro(name) {
|
|
1718
|
+
return this.localMacros[name];
|
|
1719
|
+
}
|
|
1720
|
+
with(...args) {
|
|
1721
|
+
let eagerLoads = {};
|
|
1722
|
+
if (typeof args[1] === "function") {
|
|
1723
|
+
let eagerLoad = this.parseWithRelations({
|
|
1724
|
+
[args[0]]: args[1]
|
|
1725
|
+
});
|
|
1726
|
+
this.eagerLoad = merge2(this.eagerLoad, eagerLoad);
|
|
1727
|
+
return this;
|
|
1728
|
+
}
|
|
1729
|
+
const relations = flattenDeep(args);
|
|
1730
|
+
if (relations.length === 0) {
|
|
1731
|
+
return this;
|
|
1732
|
+
}
|
|
1733
|
+
for (const relation of relations) {
|
|
1734
|
+
let eagerLoad;
|
|
1735
|
+
if (typeof relation === "string") {
|
|
1736
|
+
eagerLoad = {
|
|
1737
|
+
[relation]: (q) => q
|
|
1738
|
+
};
|
|
1739
|
+
} else if (typeof relation === "object") {
|
|
1740
|
+
eagerLoad = relation;
|
|
1741
|
+
}
|
|
1742
|
+
eagerLoads = merge2(eagerLoads, eagerLoad);
|
|
1743
|
+
}
|
|
1744
|
+
this.eagerLoad = merge2(this.eagerLoad, this.parseWithRelations(eagerLoads));
|
|
1745
|
+
return this;
|
|
1746
|
+
}
|
|
1747
|
+
has(relation, operator = ">=", count = 1, boolean = "and", callback = null) {
|
|
1748
|
+
if (isString(relation)) {
|
|
1749
|
+
if (relation.includes(".")) {
|
|
1750
|
+
return this.hasNested(relation, operator, count, boolean, callback);
|
|
1751
|
+
}
|
|
1752
|
+
relation = this.getRelationWithoutConstraints(getRelationMethod(relation));
|
|
1753
|
+
}
|
|
1754
|
+
const method = this.canUseExistsForExistenceCheck(operator, count) ? "getRelationExistenceQuery" : "getRelationExistenceCountQuery";
|
|
1755
|
+
const hasQuery = relation[method](relation.getRelated().newModelQuery(), this);
|
|
1756
|
+
if (callback) {
|
|
1757
|
+
callback(hasQuery);
|
|
1758
|
+
}
|
|
1759
|
+
return this.addHasWhere(hasQuery, relation, operator, count, boolean);
|
|
1760
|
+
}
|
|
1761
|
+
orHas(relation, operator = ">=", count = 1) {
|
|
1762
|
+
return this.has(relation, operator, count, "or");
|
|
1763
|
+
}
|
|
1764
|
+
doesntHave(relation, boolean = "and", callback = null) {
|
|
1765
|
+
return this.has(relation, "<", 1, boolean, callback);
|
|
1766
|
+
}
|
|
1767
|
+
orDoesntHave(relation) {
|
|
1768
|
+
return this.doesntHave(relation, "or");
|
|
1769
|
+
}
|
|
1770
|
+
whereHas(relation, callback = null, operator = ">=", count = 1) {
|
|
1771
|
+
return this.has(relation, operator, count, "and", callback);
|
|
1772
|
+
}
|
|
1773
|
+
orWhereHas(relation, callback = null, operator = ">=", count = 1) {
|
|
1774
|
+
return this.has(relation, operator, count, "or", callback);
|
|
1775
|
+
}
|
|
1776
|
+
whereRelation(relation, ...args) {
|
|
1777
|
+
const column = args.shift();
|
|
1778
|
+
return this.whereHas(relation, (query) => {
|
|
1779
|
+
if (typeof column === "function") {
|
|
1780
|
+
column(query);
|
|
1781
|
+
} else {
|
|
1782
|
+
query.where(column, ...args);
|
|
1783
|
+
}
|
|
1784
|
+
});
|
|
1785
|
+
}
|
|
1786
|
+
orWhereRelation(relation, ...args) {
|
|
1787
|
+
const column = args.shift();
|
|
1788
|
+
return this.orWhereHas(relation, function(query) {
|
|
1789
|
+
if (typeof column === "function") {
|
|
1790
|
+
column(query);
|
|
1791
|
+
} else {
|
|
1792
|
+
query.where(column, ...args);
|
|
1793
|
+
}
|
|
1794
|
+
});
|
|
1795
|
+
}
|
|
1796
|
+
hasNested(relations, operator = ">=", count = 1, boolean = "and", callback = null) {
|
|
1797
|
+
relations = relations.split(".");
|
|
1798
|
+
const doesntHave = operator === "<" && count === 1;
|
|
1799
|
+
if (doesntHave) {
|
|
1800
|
+
operator = ">=";
|
|
1801
|
+
count = 1;
|
|
1802
|
+
}
|
|
1803
|
+
const closure = (q) => {
|
|
1804
|
+
relations.length > 1 ? q.whereHas(relations.shift(), closure) : q.has(relations.shift(), operator, count, "and", callback);
|
|
1805
|
+
};
|
|
1806
|
+
return this.has(relations.shift(), doesntHave ? "<" : ">=", 1, boolean, closure);
|
|
1807
|
+
}
|
|
1808
|
+
canUseExistsForExistenceCheck(operator, count) {
|
|
1809
|
+
return (operator === ">=" || operator === "<") && count === 1;
|
|
1810
|
+
}
|
|
1811
|
+
addHasWhere(hasQuery, relation, operator, count, boolean) {
|
|
1812
|
+
hasQuery.mergeConstraintsFrom(relation.getQuery());
|
|
1813
|
+
return this.canUseExistsForExistenceCheck(operator, count) ? this.addWhereExistsQuery(hasQuery.getQuery(), boolean, operator === "<" && count === 1) : this.addWhereCountQuery(hasQuery.getQuery(), operator, count, boolean);
|
|
1814
|
+
}
|
|
1815
|
+
addWhereExistsQuery(query, boolean = "and", not = false) {
|
|
1816
|
+
const type = not ? "NotExists" : "Exists";
|
|
1817
|
+
const method = boolean === "and" ? "where" + type : "orWhere" + type;
|
|
1818
|
+
this[method](query.connector);
|
|
1819
|
+
return this;
|
|
1820
|
+
}
|
|
1821
|
+
addWhereCountQuery(query, operator = ">=", count = 1, boolean = "and") {
|
|
1822
|
+
const db = this.model.getConnection();
|
|
1823
|
+
return this.where(db.raw("(" + query.toSQL().sql + ")"), operator, typeof count === "number" ? db.raw(count) : count, boolean);
|
|
1824
|
+
}
|
|
1825
|
+
withAggregate(relations, column, action = null) {
|
|
1826
|
+
if (relations.length === 0) {
|
|
1827
|
+
return this;
|
|
1828
|
+
}
|
|
1829
|
+
relations = flattenDeep([relations]);
|
|
1830
|
+
let eagerLoads = {};
|
|
1831
|
+
for (const relation of relations) {
|
|
1832
|
+
let eagerLoad;
|
|
1833
|
+
if (typeof relation === "string") {
|
|
1834
|
+
eagerLoad = {
|
|
1835
|
+
[relation]: (q) => q
|
|
1836
|
+
};
|
|
1837
|
+
} else if (typeof relation === "object") {
|
|
1838
|
+
eagerLoad = relation;
|
|
1839
|
+
}
|
|
1840
|
+
eagerLoads = merge2(eagerLoads, eagerLoad);
|
|
1841
|
+
}
|
|
1842
|
+
relations = eagerLoads;
|
|
1843
|
+
const db = this.model.getConnection();
|
|
1844
|
+
const columns = this.query._statements.filter((item) => item.grouping == "columns").map((item) => item.value).flat();
|
|
1845
|
+
if (columns.length === 0) {
|
|
1846
|
+
this.query.select([this.query._single.table + ".*"]);
|
|
1847
|
+
}
|
|
1848
|
+
const parses = this.parseWithRelations(relations);
|
|
1849
|
+
for (let name in parses) {
|
|
1850
|
+
const constraints = parses[name];
|
|
1851
|
+
const segments = name.split(" ");
|
|
1852
|
+
let alias, expression;
|
|
1853
|
+
if (segments.length === 3 && segments[1].toLocaleLowerCase() === "as") {
|
|
1854
|
+
[name, alias] = [segments[0], segments[2]];
|
|
1855
|
+
}
|
|
1856
|
+
const relation = this.getRelationWithoutConstraints(getRelationMethod(name));
|
|
1857
|
+
if (action) {
|
|
1858
|
+
const hashedColumn = this.query._single.table === relation.query.query._single.table ? `${relation.getRelationCountHash(false)}.${column}` : column;
|
|
1859
|
+
const wrappedColumn = column === "*" ? column : relation.getRelated().qualifyColumn(hashedColumn);
|
|
1860
|
+
expression = action === "exists" ? wrappedColumn : `${action}(${wrappedColumn})`;
|
|
1861
|
+
} else {
|
|
1862
|
+
expression = column;
|
|
1863
|
+
}
|
|
1864
|
+
const query = relation.getRelationExistenceQuery(relation.getRelated().newModelQuery(), this, db.raw(expression));
|
|
1865
|
+
constraints(query);
|
|
1866
|
+
alias = alias || snake2(`${name} ${action} ${column}`.replace("/[^[:alnum:][:space:]_]/u", ""));
|
|
1867
|
+
if (action === "exists") {
|
|
1868
|
+
this.select(db.raw(`exists(${query.toSql().sql}) as ${alias}`));
|
|
1869
|
+
} else {
|
|
1870
|
+
this.selectSub(action ? query : query.limit(1), alias);
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
return this;
|
|
1874
|
+
}
|
|
1875
|
+
toSql() {
|
|
1876
|
+
const query = this.clone();
|
|
1877
|
+
query.applyScopes();
|
|
1878
|
+
return query.query.toSQL();
|
|
1879
|
+
}
|
|
1880
|
+
mergeConstraintsFrom(from) {
|
|
1881
|
+
return this;
|
|
1882
|
+
const whereBindings = from.getQuery().getRawBindings()["where"] || [];
|
|
1883
|
+
const wheres = from.getQuery()._single.table !== this.getQuery()._single.table ? this.requalifyWhereTables(from.getQuery().wheres, from.getQuery().from, this.getModel().getTable()) : from.getQuery().wheres;
|
|
1884
|
+
return this.where([], []);
|
|
1885
|
+
}
|
|
1886
|
+
selectSub(query, as) {
|
|
1887
|
+
const [querySub, bindings] = this.createSub(query);
|
|
1888
|
+
const db = this.model.getConnection();
|
|
1889
|
+
return this.select(db.raw("(" + querySub + ") as " + as, bindings));
|
|
1890
|
+
}
|
|
1891
|
+
createSub(query) {
|
|
1892
|
+
return this.parseSub(query);
|
|
1893
|
+
}
|
|
1894
|
+
parseSub(query) {
|
|
1895
|
+
if (query instanceof _Builder || query instanceof relation_default) {
|
|
1896
|
+
return [query.toSql().sql, query.toSql().bindings];
|
|
1897
|
+
} else if (isString(query)) {
|
|
1898
|
+
return [query, []];
|
|
1899
|
+
} else {
|
|
1900
|
+
throw new Error("A subquery must be a query builder instance, a Closure, or a string.");
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
prependDatabaseNameIfCrossDatabaseQuery(query) {
|
|
1904
|
+
if (query.query._single.table !== this.query._single.table) {
|
|
1905
|
+
const databaseName = query.query._single.table;
|
|
1906
|
+
if (!query.query._single.table.startsWith(databaseName) && !query.query._single.table.contains(".")) {
|
|
1907
|
+
query.from(databaseName + "." + query.from);
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
return query;
|
|
1911
|
+
}
|
|
1912
|
+
getRelationWithoutConstraints(relation) {
|
|
1913
|
+
return relation_default.noConstraints(() => {
|
|
1914
|
+
return this.getModel()[relation]();
|
|
1915
|
+
});
|
|
1916
|
+
}
|
|
1917
|
+
withCount(...args) {
|
|
1918
|
+
return this.withAggregate(flattenDeep(args), "*", "count");
|
|
1919
|
+
}
|
|
1920
|
+
withMax(relation, column) {
|
|
1921
|
+
return this.withAggregate(relation, column, "max");
|
|
1922
|
+
}
|
|
1923
|
+
withMin(relation, column) {
|
|
1924
|
+
return this.withAggregate(relation, column, "min");
|
|
1925
|
+
}
|
|
1926
|
+
withAvg(relation, column) {
|
|
1927
|
+
return this.withAggregate(relation, column, "avg");
|
|
1928
|
+
}
|
|
1929
|
+
withSum(relation, column) {
|
|
1930
|
+
return this.withAggregate(relation, column, "sum");
|
|
1931
|
+
}
|
|
1932
|
+
withExists(relation) {
|
|
1933
|
+
return this.withAggregate(relation, "*", "exists");
|
|
1934
|
+
}
|
|
1935
|
+
parseWithRelations(relations) {
|
|
1936
|
+
if (relations.length === 0) {
|
|
1937
|
+
return [];
|
|
1938
|
+
}
|
|
1939
|
+
let results = {};
|
|
1940
|
+
const constraintsMap = this.prepareNestedWithRelationships(relations);
|
|
1941
|
+
for (const name in constraintsMap) {
|
|
1942
|
+
results = this.addNestedWiths(name, results);
|
|
1943
|
+
results[name] = constraintsMap[name];
|
|
1944
|
+
}
|
|
1945
|
+
return results;
|
|
1946
|
+
}
|
|
1947
|
+
addNestedWiths(name, results) {
|
|
1948
|
+
const progress = [];
|
|
1949
|
+
name.split(".").map((segment) => {
|
|
1950
|
+
progress.push(segment);
|
|
1951
|
+
const last = progress.join(".");
|
|
1952
|
+
if (results[last] === void 0) {
|
|
1953
|
+
results[last] = () => {
|
|
1954
|
+
};
|
|
1955
|
+
}
|
|
1956
|
+
});
|
|
1957
|
+
return results;
|
|
1958
|
+
}
|
|
1959
|
+
prepareNestedWithRelationships(relations, prefix = "") {
|
|
1960
|
+
let preparedRelationships = {};
|
|
1961
|
+
if (prefix !== "") {
|
|
1962
|
+
prefix += ".";
|
|
1963
|
+
}
|
|
1964
|
+
for (const key2 in relations) {
|
|
1965
|
+
const value = relations[key2];
|
|
1966
|
+
if (isString(value) || Number.isFinite(parseInt(value))) {
|
|
1967
|
+
continue;
|
|
1968
|
+
}
|
|
1969
|
+
const [attribute, attributeSelectConstraint] = this.parseNameAndAttributeSelectionConstraint(key2, value);
|
|
1970
|
+
preparedRelationships = merge2(preparedRelationships, {
|
|
1971
|
+
[`${prefix}${attribute}`]: attributeSelectConstraint
|
|
1972
|
+
}, this.prepareNestedWithRelationships(value, `${prefix}${attribute}`));
|
|
1973
|
+
relations = omit3(relations, [key2]);
|
|
1974
|
+
}
|
|
1975
|
+
for (const key2 in relations) {
|
|
1976
|
+
const value = relations[key2];
|
|
1977
|
+
let attribute = key2, attributeSelectConstraint = value;
|
|
1978
|
+
if (isString(value)) {
|
|
1979
|
+
[attribute, attributeSelectConstraint] = this.parseNameAndAttributeSelectionConstraint(value);
|
|
1980
|
+
}
|
|
1981
|
+
preparedRelationships[`${prefix}${attribute}`] = this.combineConstraints([
|
|
1982
|
+
attributeSelectConstraint,
|
|
1983
|
+
preparedRelationships[`${prefix}${attribute}`] || (() => {
|
|
1984
|
+
})
|
|
1985
|
+
]);
|
|
1986
|
+
}
|
|
1987
|
+
return preparedRelationships;
|
|
1988
|
+
}
|
|
1989
|
+
combineConstraints(constraints) {
|
|
1990
|
+
return (builder) => {
|
|
1991
|
+
constraints.map((constraint) => {
|
|
1992
|
+
builder = constraint(builder) || builder;
|
|
1993
|
+
});
|
|
1994
|
+
return builder;
|
|
1995
|
+
};
|
|
1996
|
+
}
|
|
1997
|
+
parseNameAndAttributeSelectionConstraint(name, value) {
|
|
1998
|
+
return name.includes(":") ? this.createSelectWithConstraint(name) : [name, value];
|
|
1999
|
+
}
|
|
2000
|
+
createSelectWithConstraint(name) {
|
|
2001
|
+
return [name.split(":")[0], (query) => {
|
|
2002
|
+
query.select(name.split(":")[1].split(",").map((column) => {
|
|
2003
|
+
if (column.includes(".")) {
|
|
2004
|
+
return column;
|
|
2005
|
+
}
|
|
2006
|
+
return query instanceof belongs_to_many_default ? query.related.getTable() + "." + column : column;
|
|
2007
|
+
}));
|
|
2008
|
+
}];
|
|
2009
|
+
}
|
|
2010
|
+
related(relation) {
|
|
2011
|
+
if (typeof this.model[getRelationMethod(relation)] !== "function") {
|
|
2012
|
+
const message = `Model [${this.model.constructor.name}]'s relation [${relation}] doesn't exist.`;
|
|
2013
|
+
throw new RelationNotFoundError(message);
|
|
2014
|
+
}
|
|
2015
|
+
return this.model[getRelationMethod(relation)]();
|
|
2016
|
+
}
|
|
2017
|
+
take(...args) {
|
|
2018
|
+
return this.limit(...args);
|
|
2019
|
+
}
|
|
2020
|
+
skip(...args) {
|
|
2021
|
+
return this.offset(...args);
|
|
2022
|
+
}
|
|
2023
|
+
async first(...columns) {
|
|
2024
|
+
this.applyScopes();
|
|
2025
|
+
this.limit(1);
|
|
2026
|
+
let models = await this.getModels(columns);
|
|
2027
|
+
if (models.length > 0) {
|
|
2028
|
+
models = await this.eagerLoadRelations(models);
|
|
2029
|
+
}
|
|
2030
|
+
return models[0] || null;
|
|
2031
|
+
}
|
|
2032
|
+
async firstOrFail(...columns) {
|
|
2033
|
+
const data = await this.first(...columns);
|
|
2034
|
+
if (data === null) {
|
|
2035
|
+
throw new ModelNotFoundError2().setModel(this.model.constructor.name);
|
|
2036
|
+
}
|
|
2037
|
+
return data;
|
|
2038
|
+
}
|
|
2039
|
+
async findOrFail(ids, columns = "*") {
|
|
2040
|
+
const data = await this.find(ids, columns);
|
|
2041
|
+
if (isArray4(ids)) {
|
|
2042
|
+
if (data.count() !== ids.length) {
|
|
2043
|
+
throw new ModelNotFoundError2().setModel(this.model.constructor.name, difference3(ids, data.modelKeys()));
|
|
2044
|
+
}
|
|
2045
|
+
return data;
|
|
2046
|
+
}
|
|
2047
|
+
if (data === null) {
|
|
2048
|
+
throw new ModelNotFoundError2().setModel(this.model.constructor.name, ids);
|
|
2049
|
+
}
|
|
2050
|
+
return data;
|
|
2051
|
+
}
|
|
2052
|
+
async findOrNew(id, columns = ["*"]) {
|
|
2053
|
+
const model = await this.find(id, columns);
|
|
2054
|
+
if (model !== null) {
|
|
2055
|
+
return model;
|
|
2056
|
+
}
|
|
2057
|
+
return this.newModelInstance();
|
|
2058
|
+
}
|
|
2059
|
+
async firstOrNew(attributes = {}, values = {}) {
|
|
2060
|
+
const instance = await this.where(attributes).first();
|
|
2061
|
+
if (instance !== null) {
|
|
2062
|
+
return instance;
|
|
2063
|
+
}
|
|
2064
|
+
return this.newModelInstance(merge2(attributes, values));
|
|
2065
|
+
}
|
|
2066
|
+
async firstOrCreate(attributes = {}, values = {}) {
|
|
2067
|
+
const instance = await this.where(attributes).first();
|
|
2068
|
+
if (instance !== null) {
|
|
2069
|
+
return instance;
|
|
2070
|
+
}
|
|
2071
|
+
return tap(this.newModelInstance(merge2(attributes, values)), async (instance2) => {
|
|
2072
|
+
await instance2.save({
|
|
2073
|
+
client: this.query
|
|
2074
|
+
});
|
|
2075
|
+
});
|
|
2076
|
+
}
|
|
2077
|
+
async updateOrCreate(attributes, values = {}) {
|
|
2078
|
+
return await tap(await this.firstOrNew(attributes), async (instance) => {
|
|
2079
|
+
await instance.fill(values).save({
|
|
2080
|
+
client: this.query
|
|
2081
|
+
});
|
|
2082
|
+
});
|
|
2083
|
+
}
|
|
2084
|
+
latest(column = null) {
|
|
2085
|
+
if (column === null) {
|
|
2086
|
+
column = this.model.getCreatedAtColumn() || "created_at";
|
|
2087
|
+
}
|
|
2088
|
+
this.query.orderBy(column, "desc");
|
|
2089
|
+
return this;
|
|
2090
|
+
}
|
|
2091
|
+
oldest(column = null) {
|
|
2092
|
+
if (column === null) {
|
|
2093
|
+
column = this.model.getCreatedAtColumn() || "created_at";
|
|
2094
|
+
}
|
|
2095
|
+
this.query.orderBy(column, "asc");
|
|
2096
|
+
return this;
|
|
2097
|
+
}
|
|
2098
|
+
async find(id, columns = "*") {
|
|
2099
|
+
if (isArray4(id) || id instanceof collection_default) {
|
|
2100
|
+
return await this.findMany(id, columns);
|
|
2101
|
+
}
|
|
2102
|
+
return await this.where(this.model.getKeyName(), id).first(columns);
|
|
2103
|
+
}
|
|
2104
|
+
async findMany(ids, columns = "*") {
|
|
2105
|
+
if (ids instanceof collection_default) {
|
|
2106
|
+
ids = ids.modelKeys();
|
|
2107
|
+
}
|
|
2108
|
+
ids = isArray4(ids) ? ids : [ids];
|
|
2109
|
+
if (ids.length === 0) {
|
|
2110
|
+
return new collection_default([]);
|
|
2111
|
+
}
|
|
2112
|
+
return await this.whereIn(this.model.getKeyName(), ids).get(columns);
|
|
2113
|
+
}
|
|
2114
|
+
async pluck(column) {
|
|
2115
|
+
const data = await this.query.pluck(column);
|
|
2116
|
+
return new collection_default(data);
|
|
2117
|
+
}
|
|
2118
|
+
async destroy(ids) {
|
|
2119
|
+
if (ids instanceof collection_default) {
|
|
2120
|
+
ids = ids.modelKeys();
|
|
2121
|
+
}
|
|
2122
|
+
if (ids instanceof BaseCollection2) {
|
|
2123
|
+
ids = ids.all();
|
|
2124
|
+
}
|
|
2125
|
+
ids = isArray4(ids) ? ids : Array.prototype.slice.call(arguments);
|
|
2126
|
+
if (ids.length === 0) {
|
|
2127
|
+
return 0;
|
|
2128
|
+
}
|
|
2129
|
+
const instance = this.model.newInstance();
|
|
2130
|
+
const key2 = instance.getKeyName();
|
|
2131
|
+
let count = 0;
|
|
2132
|
+
const models = await this.model.newModelQuery().whereIn(key2, ids).get();
|
|
2133
|
+
for (const model of models) {
|
|
2134
|
+
if (await model.delete()) {
|
|
2135
|
+
count++;
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
return count;
|
|
2139
|
+
}
|
|
2140
|
+
async get(columns = "*") {
|
|
2141
|
+
this.applyScopes();
|
|
2142
|
+
let models = await this.getModels(columns);
|
|
2143
|
+
if (models.length > 0) {
|
|
2144
|
+
models = await this.eagerLoadRelations(models);
|
|
2145
|
+
}
|
|
2146
|
+
return new collection_default(models);
|
|
2147
|
+
}
|
|
2148
|
+
async all(columns = "*") {
|
|
2149
|
+
return await this.model.newModelQuery().get(columns);
|
|
2150
|
+
}
|
|
2151
|
+
async paginate(page, perPage) {
|
|
2152
|
+
page = page || 1;
|
|
2153
|
+
perPage = perPage || this?.model?.perPage || 15;
|
|
2154
|
+
this.applyScopes();
|
|
2155
|
+
const query = this.query.clone();
|
|
2156
|
+
const total = await query.clearOrder().clearSelect().count(this.primaryKey);
|
|
2157
|
+
let results;
|
|
2158
|
+
if (total > 0) {
|
|
2159
|
+
const skip = (page - 1) * perPage;
|
|
2160
|
+
this.take(perPage).skip(skip);
|
|
2161
|
+
results = await this.getModels();
|
|
2162
|
+
if (results.length > 0) {
|
|
2163
|
+
results = await this.eagerLoadRelations(results);
|
|
2164
|
+
}
|
|
2165
|
+
} else {
|
|
2166
|
+
results = [];
|
|
2167
|
+
}
|
|
2168
|
+
return new paginator_default(results, parseInt(total), perPage, page);
|
|
2169
|
+
}
|
|
2170
|
+
async getModels(...columns) {
|
|
2171
|
+
columns = flatten(columns);
|
|
2172
|
+
if (columns.length > 0) {
|
|
2173
|
+
if (this.query._statements.filter((item) => item.grouping == "columns").length == 0 && columns[0] !== "*") {
|
|
2174
|
+
this.query.select(...columns);
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
return this.hydrate(await this.query.get()).all();
|
|
2178
|
+
}
|
|
2179
|
+
getRelation(name) {
|
|
2180
|
+
if (typeof this.model[getRelationMethod(name)] !== "function") {
|
|
2181
|
+
const message = `Model [${this.model.constructor.name}]'s relation [${name}] doesn't exist.`;
|
|
2182
|
+
throw new RelationNotFoundError(message);
|
|
2183
|
+
}
|
|
2184
|
+
const relation = relation_default.noConstraints(() => this.model.newInstance(this.model.attributes)[getRelationMethod(name)]());
|
|
2185
|
+
const nested = this.relationsNestedUnder(name);
|
|
2186
|
+
if (Object.keys(nested).length > 0) {
|
|
2187
|
+
relation.query.with(nested);
|
|
2188
|
+
}
|
|
2189
|
+
return relation.asProxy();
|
|
2190
|
+
}
|
|
2191
|
+
relationsNestedUnder(relation) {
|
|
2192
|
+
const nested = {};
|
|
2193
|
+
for (const name in this.eagerLoad) {
|
|
2194
|
+
const constraints = this.eagerLoad[name];
|
|
2195
|
+
if (this.isNestedUnder(relation, name)) {
|
|
2196
|
+
nested[name.substring((relation + ".").length)] = constraints;
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
return nested;
|
|
2200
|
+
}
|
|
2201
|
+
isNestedUnder(relation, name) {
|
|
2202
|
+
return name.includes(".") && name.startsWith(relation + ".");
|
|
2203
|
+
}
|
|
2204
|
+
async eagerLoadRelation(models, name, constraints) {
|
|
2205
|
+
const relation = this.getRelation(name);
|
|
2206
|
+
relation.addEagerConstraints(models);
|
|
2207
|
+
constraints(relation);
|
|
2208
|
+
return relation.match(relation.initRelation(models, name), await relation.get(), name);
|
|
2209
|
+
}
|
|
2210
|
+
async eagerLoadRelations(models) {
|
|
2211
|
+
for (const name in this.eagerLoad) {
|
|
2212
|
+
const constraints = this.eagerLoad[name];
|
|
2213
|
+
if (!name.includes(".")) {
|
|
2214
|
+
models = await this.eagerLoadRelation(models, name, constraints);
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2217
|
+
return models;
|
|
2218
|
+
}
|
|
2219
|
+
hydrate(items) {
|
|
2220
|
+
return new collection_default(items.map((item) => {
|
|
2221
|
+
if (!this.model) {
|
|
2222
|
+
return item;
|
|
2223
|
+
}
|
|
2224
|
+
const model = this.model.newFromBuilder(item);
|
|
2225
|
+
return model;
|
|
2226
|
+
}));
|
|
2227
|
+
}
|
|
2228
|
+
};
|
|
2229
|
+
var builder_default = Builder;
|
|
2230
|
+
|
|
2231
|
+
// src/concerns/has-attributes.js
|
|
2232
|
+
import { flat as flatten2, omit as omit4 } from "radashi";
|
|
2233
|
+
|
|
2234
|
+
// src/casts-attributes.js
|
|
2235
|
+
var CastsAttributes = class _CastsAttributes {
|
|
2236
|
+
constructor() {
|
|
2237
|
+
if (this.constructor === _CastsAttributes) {
|
|
2238
|
+
throw new Error("CastsAttributes cannot be instantiated");
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
static get() {
|
|
2242
|
+
throw new Error("get not implemented");
|
|
2243
|
+
}
|
|
2244
|
+
static set() {
|
|
2245
|
+
throw new Error("set not implemented");
|
|
2246
|
+
}
|
|
2247
|
+
};
|
|
2248
|
+
var casts_attributes_default = CastsAttributes;
|
|
2249
|
+
|
|
2250
|
+
// src/concerns/has-attributes.js
|
|
2251
|
+
import collect4 from "collect.js";
|
|
2252
|
+
import dayjs2 from "dayjs";
|
|
2253
|
+
var HasAttributes = (Model2) => {
|
|
2254
|
+
return class extends Model2 {
|
|
2255
|
+
static castTypeCache = {};
|
|
2256
|
+
attributes = {};
|
|
2257
|
+
original = {};
|
|
2258
|
+
casts = {};
|
|
2259
|
+
changes = {};
|
|
2260
|
+
appends = [];
|
|
2261
|
+
setAppends(appends) {
|
|
2262
|
+
this.appends = appends;
|
|
2263
|
+
return this;
|
|
2264
|
+
}
|
|
2265
|
+
append(...keys) {
|
|
2266
|
+
const appends = flattenDeep(keys);
|
|
2267
|
+
this.appends = [...this.appends, ...appends];
|
|
2268
|
+
return this;
|
|
2269
|
+
}
|
|
2270
|
+
normalizeCastClassResponse(key2, value) {
|
|
2271
|
+
return value?.constructor?.name === "Object" ? value : {
|
|
2272
|
+
[key2]: value
|
|
2273
|
+
};
|
|
2274
|
+
}
|
|
2275
|
+
syncOriginal() {
|
|
2276
|
+
this.original = this.getAttributes();
|
|
2277
|
+
return this;
|
|
2278
|
+
}
|
|
2279
|
+
syncChanges() {
|
|
2280
|
+
this.changes = this.getDirty();
|
|
2281
|
+
return this;
|
|
2282
|
+
}
|
|
2283
|
+
syncOriginalAttribute(attribute) {
|
|
2284
|
+
this.syncOriginalAttributes(attribute);
|
|
2285
|
+
}
|
|
2286
|
+
syncOriginalAttributes(...attributes) {
|
|
2287
|
+
attributes = flattenDeep(attributes);
|
|
2288
|
+
const modelAttributes = this.getAttributes();
|
|
2289
|
+
for (const attribute of attributes) {
|
|
2290
|
+
this.original[attribute] = modelAttributes[attribute];
|
|
2291
|
+
}
|
|
2292
|
+
return this;
|
|
2293
|
+
}
|
|
2294
|
+
isDirty(...attributes) {
|
|
2295
|
+
const changes = this.getDirty();
|
|
2296
|
+
attributes = flattenDeep(attributes);
|
|
2297
|
+
if (attributes.length === 0) {
|
|
2298
|
+
return Object.keys(changes).length > 0;
|
|
2299
|
+
}
|
|
2300
|
+
for (const attribute of attributes) {
|
|
2301
|
+
if (attribute in changes) {
|
|
2302
|
+
return true;
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
return false;
|
|
2306
|
+
}
|
|
2307
|
+
getDirty() {
|
|
2308
|
+
const dirty = {};
|
|
2309
|
+
const attributes = this.getAttributes();
|
|
2310
|
+
for (const key2 in attributes) {
|
|
2311
|
+
const value = attributes[key2];
|
|
2312
|
+
if (!this.originalIsEquivalent(key2)) {
|
|
2313
|
+
dirty[key2] = value;
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
return dirty;
|
|
2317
|
+
}
|
|
2318
|
+
originalIsEquivalent(key2) {
|
|
2319
|
+
if (this.original[key2] === void 0) {
|
|
2320
|
+
return false;
|
|
2321
|
+
}
|
|
2322
|
+
const attribute = this.attributes[key2];
|
|
2323
|
+
const original = this.original[key2];
|
|
2324
|
+
if (attribute === original) {
|
|
2325
|
+
return true;
|
|
2326
|
+
} else {
|
|
2327
|
+
return false;
|
|
2328
|
+
}
|
|
2329
|
+
}
|
|
2330
|
+
setAttributes(attributes) {
|
|
2331
|
+
this.attributes = { ...attributes };
|
|
2332
|
+
}
|
|
2333
|
+
setRawAttributes(attributes, sync = false) {
|
|
2334
|
+
this.attributes = attributes;
|
|
2335
|
+
if (sync) {
|
|
2336
|
+
this.syncOriginal();
|
|
2337
|
+
}
|
|
2338
|
+
return this;
|
|
2339
|
+
}
|
|
2340
|
+
getAttributes() {
|
|
2341
|
+
return { ...this.attributes };
|
|
2342
|
+
}
|
|
2343
|
+
setAttribute(key2, value) {
|
|
2344
|
+
const setterMethod = getSetterMethod(key2);
|
|
2345
|
+
if (typeof this[setterMethod] === "function") {
|
|
2346
|
+
this[setterMethod](value);
|
|
2347
|
+
return this;
|
|
2348
|
+
}
|
|
2349
|
+
const attrMethod = getAttrMethod(key2);
|
|
2350
|
+
if (typeof this[attrMethod] === "function") {
|
|
2351
|
+
const attribute = this[attrMethod]();
|
|
2352
|
+
const callback = attribute.set || ((value2) => {
|
|
2353
|
+
this.attributes[key2] = value2;
|
|
2354
|
+
});
|
|
2355
|
+
this.attributes = {
|
|
2356
|
+
...this.attributes,
|
|
2357
|
+
...this.normalizeCastClassResponse(key2, callback(value, this.attributes))
|
|
2358
|
+
};
|
|
2359
|
+
return this;
|
|
2360
|
+
}
|
|
2361
|
+
const casts = this.getCasts();
|
|
2362
|
+
const castType = casts[key2];
|
|
2363
|
+
if (this.isCustomCast(castType)) {
|
|
2364
|
+
value = castType.set(this, key2, value, this.attributes);
|
|
2365
|
+
}
|
|
2366
|
+
if (castType === "json") {
|
|
2367
|
+
value = JSON.stringify(value);
|
|
2368
|
+
}
|
|
2369
|
+
if (castType === "collection") {
|
|
2370
|
+
value = JSON.stringify(value);
|
|
2371
|
+
}
|
|
2372
|
+
if (value !== null && this.isDateAttribute(key2)) {
|
|
2373
|
+
value = this.fromDateTime(value);
|
|
2374
|
+
}
|
|
2375
|
+
this.attributes[key2] = value;
|
|
2376
|
+
return this;
|
|
2377
|
+
}
|
|
2378
|
+
getAttribute(key2) {
|
|
2379
|
+
if (!key2) {
|
|
2380
|
+
return;
|
|
2381
|
+
}
|
|
2382
|
+
const getterMethod = getGetterMethod(key2);
|
|
2383
|
+
if (typeof this[getterMethod] === "function") {
|
|
2384
|
+
return this[getterMethod](this.attributes[key2], this.attributes);
|
|
2385
|
+
}
|
|
2386
|
+
const attrMethod = getAttrMethod(key2);
|
|
2387
|
+
if (typeof this[attrMethod] === "function") {
|
|
2388
|
+
const caster = this[attrMethod]();
|
|
2389
|
+
return caster.get(this.attributes[key2], this.attributes);
|
|
2390
|
+
}
|
|
2391
|
+
if (key2 in this.attributes) {
|
|
2392
|
+
if (this.hasCast(key2)) {
|
|
2393
|
+
return this.castAttribute(key2, this.attributes[key2]);
|
|
2394
|
+
}
|
|
2395
|
+
if (this.getDates().includes(key2)) {
|
|
2396
|
+
return this.asDateTime(this.attributes[key2]);
|
|
2397
|
+
}
|
|
2398
|
+
return this.attributes[key2];
|
|
2399
|
+
}
|
|
2400
|
+
if (key2 in this.relations) {
|
|
2401
|
+
return this.relations[key2];
|
|
2402
|
+
}
|
|
2403
|
+
return;
|
|
2404
|
+
}
|
|
2405
|
+
castAttribute(key2, value) {
|
|
2406
|
+
const castType = this.getCastType(key2);
|
|
2407
|
+
if (!castType) {
|
|
2408
|
+
return value;
|
|
2409
|
+
}
|
|
2410
|
+
if (value === null) {
|
|
2411
|
+
return value;
|
|
2412
|
+
}
|
|
2413
|
+
switch (castType) {
|
|
2414
|
+
case "int":
|
|
2415
|
+
case "integer":
|
|
2416
|
+
return parseInt(value);
|
|
2417
|
+
case "real":
|
|
2418
|
+
case "float":
|
|
2419
|
+
case "double":
|
|
2420
|
+
return parseFloat(value);
|
|
2421
|
+
case "decimal":
|
|
2422
|
+
return this.asDecimal(value, castType.split(":")[1]);
|
|
2423
|
+
case "string":
|
|
2424
|
+
return String(value);
|
|
2425
|
+
case "bool":
|
|
2426
|
+
case "boolean":
|
|
2427
|
+
return Boolean(value);
|
|
2428
|
+
case "object":
|
|
2429
|
+
case "json":
|
|
2430
|
+
try {
|
|
2431
|
+
return JSON.parse(value);
|
|
2432
|
+
} catch (e) {
|
|
2433
|
+
return null;
|
|
2434
|
+
}
|
|
2435
|
+
case "collection":
|
|
2436
|
+
try {
|
|
2437
|
+
return collect4(JSON.parse(value));
|
|
2438
|
+
} catch (e) {
|
|
2439
|
+
return collect4([]);
|
|
2440
|
+
}
|
|
2441
|
+
case "date":
|
|
2442
|
+
return this.asDate(value);
|
|
2443
|
+
case "datetime":
|
|
2444
|
+
case "custom_datetime":
|
|
2445
|
+
return this.asDateTime(value);
|
|
2446
|
+
case "timestamp":
|
|
2447
|
+
return this.asTimestamp(value);
|
|
2448
|
+
}
|
|
2449
|
+
if (this.isCustomCast(castType)) {
|
|
2450
|
+
return castType.get(this, key2, value, this.attributes);
|
|
2451
|
+
}
|
|
2452
|
+
return value;
|
|
2453
|
+
}
|
|
2454
|
+
attributesToData() {
|
|
2455
|
+
let attributes = { ...this.attributes };
|
|
2456
|
+
for (const key2 in attributes) {
|
|
2457
|
+
if (this.hidden.includes(key2)) {
|
|
2458
|
+
attributes = omit4(attributes, [key2]);
|
|
2459
|
+
}
|
|
2460
|
+
if (this.visible.length > 0 && this.visible.includes(key2) === false) {
|
|
2461
|
+
attributes = omit4(attributes, [key2]);
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
for (const key2 of this.getDates()) {
|
|
2465
|
+
if (attributes[key2] === void 0) {
|
|
2466
|
+
continue;
|
|
2467
|
+
}
|
|
2468
|
+
attributes[key2] = this.serializeDate(this.asDateTime(attributes[key2]));
|
|
2469
|
+
}
|
|
2470
|
+
const casts = this.getCasts();
|
|
2471
|
+
for (const key2 in casts) {
|
|
2472
|
+
const value = casts[key2];
|
|
2473
|
+
if (key2 in attributes === false) {
|
|
2474
|
+
continue;
|
|
2475
|
+
}
|
|
2476
|
+
attributes[key2] = this.castAttribute(key2, attributes[key2]);
|
|
2477
|
+
if (key2 in attributes && ["date", "datetime"].includes(value)) {
|
|
2478
|
+
attributes[key2] = this.serializeDate(attributes[key2]);
|
|
2479
|
+
}
|
|
2480
|
+
if (key2 in attributes && this.isCustomDateTimeCast(value)) {
|
|
2481
|
+
attributes[key2] = dayjs2(attributes[key2]).format(value.split(":")[1]);
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
for (const key2 of this.appends) {
|
|
2485
|
+
attributes[key2] = this.mutateAttribute(key2, null);
|
|
2486
|
+
}
|
|
2487
|
+
return attributes;
|
|
2488
|
+
}
|
|
2489
|
+
mutateAttribute(key2, value) {
|
|
2490
|
+
if (typeof this[getGetterMethod(key2)] === "function") {
|
|
2491
|
+
return this[getGetterMethod(key2)](value);
|
|
2492
|
+
} else if (typeof this[getAttrMethod(key2)] === "function") {
|
|
2493
|
+
const caster = this[getAttrMethod(key2)]();
|
|
2494
|
+
return caster.get(key2, this.attributes);
|
|
2495
|
+
} else if (key2 in this) {
|
|
2496
|
+
return this[key2];
|
|
2497
|
+
}
|
|
2498
|
+
return value;
|
|
2499
|
+
}
|
|
2500
|
+
mutateAttributeForArray(key2, value) {
|
|
2501
|
+
}
|
|
2502
|
+
isDateAttribute(key2) {
|
|
2503
|
+
return this.getDates().includes(key2) || this.isDateCastable(key2);
|
|
2504
|
+
}
|
|
2505
|
+
serializeDate(date) {
|
|
2506
|
+
return date ? dayjs2(date).toISOString() : null;
|
|
2507
|
+
}
|
|
2508
|
+
getDates() {
|
|
2509
|
+
return this.usesTimestamps() ? [
|
|
2510
|
+
this.getCreatedAtColumn(),
|
|
2511
|
+
this.getUpdatedAtColumn()
|
|
2512
|
+
] : [];
|
|
2513
|
+
}
|
|
2514
|
+
getCasts() {
|
|
2515
|
+
if (this.getIncrementing()) {
|
|
2516
|
+
return {
|
|
2517
|
+
[this.getKeyName()]: this.getKeyType(),
|
|
2518
|
+
...this.casts
|
|
2519
|
+
};
|
|
2520
|
+
}
|
|
2521
|
+
return this.casts;
|
|
2522
|
+
}
|
|
2523
|
+
getCastType(key2) {
|
|
2524
|
+
const castType = this.getCasts()[key2];
|
|
2525
|
+
let castTypeCacheKey;
|
|
2526
|
+
if (typeof castType === "string") {
|
|
2527
|
+
castTypeCacheKey = castType;
|
|
2528
|
+
} else if (new castType() instanceof casts_attributes_default) {
|
|
2529
|
+
castTypeCacheKey = castType.name;
|
|
2530
|
+
}
|
|
2531
|
+
if (castTypeCacheKey && this.constructor.castTypeCache[castTypeCacheKey] !== void 0) {
|
|
2532
|
+
return this.constructor.castTypeCache[castTypeCacheKey];
|
|
2533
|
+
}
|
|
2534
|
+
let convertedCastType;
|
|
2535
|
+
if (this.isCustomDateTimeCast(castType)) {
|
|
2536
|
+
convertedCastType = "custom_datetime";
|
|
2537
|
+
} else if (this.isDecimalCast(castType)) {
|
|
2538
|
+
convertedCastType = "decimal";
|
|
2539
|
+
} else if (this.isCustomCast(castType)) {
|
|
2540
|
+
convertedCastType = castType;
|
|
2541
|
+
} else {
|
|
2542
|
+
convertedCastType = castType.toLocaleLowerCase().trim();
|
|
2543
|
+
}
|
|
2544
|
+
return this.constructor.castTypeCache[castTypeCacheKey] = convertedCastType;
|
|
2545
|
+
}
|
|
2546
|
+
hasCast(key2, types = []) {
|
|
2547
|
+
if (key2 in this.casts) {
|
|
2548
|
+
types = flatten2(types);
|
|
2549
|
+
return types.length > 0 ? types.includes(this.getCastType(key2)) : true;
|
|
2550
|
+
}
|
|
2551
|
+
return false;
|
|
2552
|
+
}
|
|
2553
|
+
withDayjs(date) {
|
|
2554
|
+
return dayjs2(date);
|
|
2555
|
+
}
|
|
2556
|
+
isCustomCast(cast) {
|
|
2557
|
+
return typeof cast === "function" && new cast() instanceof casts_attributes_default;
|
|
2558
|
+
}
|
|
2559
|
+
isCustomDateTimeCast(cast) {
|
|
2560
|
+
if (typeof cast !== "string") {
|
|
2561
|
+
return false;
|
|
2562
|
+
}
|
|
2563
|
+
return cast.startsWith("date:") || cast.startsWith("datetime:");
|
|
2564
|
+
}
|
|
2565
|
+
isDecimalCast(cast) {
|
|
2566
|
+
if (typeof cast !== "string") {
|
|
2567
|
+
return false;
|
|
2568
|
+
}
|
|
2569
|
+
return cast.startsWith("decimal:");
|
|
2570
|
+
}
|
|
2571
|
+
isDateCastable(key2) {
|
|
2572
|
+
return this.hasCast(key2, ["date", "datetime"]);
|
|
2573
|
+
}
|
|
2574
|
+
fromDateTime(value) {
|
|
2575
|
+
return dayjs2(this.asDateTime(value)).format(this.getDateFormat());
|
|
2576
|
+
}
|
|
2577
|
+
getDateFormat() {
|
|
2578
|
+
return this.dateFormat || "YYYY-MM-DD HH:mm:ss";
|
|
2579
|
+
}
|
|
2580
|
+
asDecimal(value, decimals) {
|
|
2581
|
+
return parseFloat(value).toFixed(decimals);
|
|
2582
|
+
}
|
|
2583
|
+
asDateTime(value) {
|
|
2584
|
+
if (value === null) {
|
|
2585
|
+
return null;
|
|
2586
|
+
}
|
|
2587
|
+
if (value instanceof Date) {
|
|
2588
|
+
return value;
|
|
2589
|
+
}
|
|
2590
|
+
if (typeof value === "number") {
|
|
2591
|
+
return new Date(value * 1e3);
|
|
2592
|
+
}
|
|
2593
|
+
return new Date(value);
|
|
2594
|
+
}
|
|
2595
|
+
asDate(value) {
|
|
2596
|
+
const date = this.asDateTime(value);
|
|
2597
|
+
return dayjs2(date).startOf("day").toDate();
|
|
2598
|
+
}
|
|
2599
|
+
};
|
|
2600
|
+
};
|
|
2601
|
+
var has_attributes_default = HasAttributes;
|
|
2602
|
+
|
|
2603
|
+
// src/concerns/has-global-scopes.js
|
|
2604
|
+
import { get, set } from "radashi";
|
|
2605
|
+
var HasGlobalScopes = (Model2) => {
|
|
2606
|
+
return class extends Model2 {
|
|
2607
|
+
static addGlobalScope(scope, implementation = null) {
|
|
2608
|
+
if (typeof scope === "string" && implementation instanceof scope_default) {
|
|
2609
|
+
this.globalScopes = set(this.globalScopes, this.name + "." + scope, implementation);
|
|
2610
|
+
return implementation;
|
|
2611
|
+
} else if (scope instanceof scope_default) {
|
|
2612
|
+
this.globalScopes = set(this.globalScopes, this.name + "." + scope.constructor.name, scope);
|
|
2613
|
+
return scope;
|
|
2614
|
+
}
|
|
2615
|
+
throw new InvalidArgumentError("Global scope must be an instance of Scope.");
|
|
2616
|
+
}
|
|
2617
|
+
static hasGlobalScope(scope) {
|
|
2618
|
+
return this.getGlobalScope(scope) !== null;
|
|
2619
|
+
}
|
|
2620
|
+
static getGlobalScope(scope) {
|
|
2621
|
+
if (typeof scope === "string") {
|
|
2622
|
+
return get(this.globalScopes, this.name + "." + scope);
|
|
2623
|
+
}
|
|
2624
|
+
return get(this.globalScopes, this.name + "." + scope.constructor.name);
|
|
2625
|
+
}
|
|
2626
|
+
static getAllGlobalScopes() {
|
|
2627
|
+
return this.globalScopes;
|
|
2628
|
+
}
|
|
2629
|
+
static setAllGlobalScopes(scopes) {
|
|
2630
|
+
this.globalScopes = scopes;
|
|
2631
|
+
}
|
|
2632
|
+
getGlobalScopes() {
|
|
2633
|
+
return get(this.constructor.globalScopes, this.constructor.name, {});
|
|
2634
|
+
}
|
|
2635
|
+
};
|
|
2636
|
+
};
|
|
2637
|
+
var has_global_scopes_default = HasGlobalScopes;
|
|
2638
|
+
|
|
2639
|
+
// src/hooks.js
|
|
2640
|
+
var Hooks = class {
|
|
2641
|
+
hooks = {
|
|
2642
|
+
creating: [],
|
|
2643
|
+
created: [],
|
|
2644
|
+
updating: [],
|
|
2645
|
+
updated: [],
|
|
2646
|
+
saving: [],
|
|
2647
|
+
saved: [],
|
|
2648
|
+
deleting: [],
|
|
2649
|
+
deleted: [],
|
|
2650
|
+
restoring: [],
|
|
2651
|
+
restored: [],
|
|
2652
|
+
trashed: [],
|
|
2653
|
+
forceDeleting: [],
|
|
2654
|
+
forceDeleted: []
|
|
2655
|
+
};
|
|
2656
|
+
add(hook, callback) {
|
|
2657
|
+
if (typeof this.hooks[hook] === "undefined") {
|
|
2658
|
+
this.hooks[hook] = [];
|
|
2659
|
+
}
|
|
2660
|
+
this.hooks[hook].push(callback);
|
|
2661
|
+
}
|
|
2662
|
+
async exec(hook, data) {
|
|
2663
|
+
if (typeof this.hooks[hook] === "undefined") {
|
|
2664
|
+
return true;
|
|
2665
|
+
}
|
|
2666
|
+
for (const callback of this.hooks[hook]) {
|
|
2667
|
+
await callback(...data);
|
|
2668
|
+
}
|
|
2669
|
+
return true;
|
|
2670
|
+
}
|
|
2671
|
+
};
|
|
2672
|
+
var hooks_default = Hooks;
|
|
2673
|
+
|
|
2674
|
+
// src/concerns/has-hooks.js
|
|
2675
|
+
var HasHooks = (Model2) => {
|
|
2676
|
+
return class extends Model2 {
|
|
2677
|
+
static hooks = null;
|
|
2678
|
+
static addHook(hook, callback) {
|
|
2679
|
+
if (this.hooks instanceof hooks_default === false) {
|
|
2680
|
+
this.hooks = new hooks_default();
|
|
2681
|
+
}
|
|
2682
|
+
this.hooks.add(hook, callback);
|
|
2683
|
+
}
|
|
2684
|
+
static creating(callback) {
|
|
2685
|
+
this.addHook("creating", callback);
|
|
2686
|
+
}
|
|
2687
|
+
static created(callback) {
|
|
2688
|
+
this.addHook("created", callback);
|
|
2689
|
+
}
|
|
2690
|
+
static updating(callback) {
|
|
2691
|
+
this.addHook("updating", callback);
|
|
2692
|
+
}
|
|
2693
|
+
static updated(callback) {
|
|
2694
|
+
this.addHook("updated", callback);
|
|
2695
|
+
}
|
|
2696
|
+
static saving(callback) {
|
|
2697
|
+
this.addHook("saving", callback);
|
|
2698
|
+
}
|
|
2699
|
+
static saved(callback) {
|
|
2700
|
+
this.addHook("saved", callback);
|
|
2701
|
+
}
|
|
2702
|
+
static deleting(callback) {
|
|
2703
|
+
this.addHook("deleting", callback);
|
|
2704
|
+
}
|
|
2705
|
+
static deleted(callback) {
|
|
2706
|
+
this.addHook("deleted", callback);
|
|
2707
|
+
}
|
|
2708
|
+
static restoring(callback) {
|
|
2709
|
+
this.addHook("restoring", callback);
|
|
2710
|
+
}
|
|
2711
|
+
static restored(callback) {
|
|
2712
|
+
this.addHook("restored", callback);
|
|
2713
|
+
}
|
|
2714
|
+
static trashed(callback) {
|
|
2715
|
+
this.addHook("trashed", callback);
|
|
2716
|
+
}
|
|
2717
|
+
static forceDeleted(callback) {
|
|
2718
|
+
this.addHook("forceDeleted", callback);
|
|
2719
|
+
}
|
|
2720
|
+
async execHooks(hook, options) {
|
|
2721
|
+
if (this.constructor.hooks instanceof hooks_default === false) {
|
|
2722
|
+
return;
|
|
2723
|
+
}
|
|
2724
|
+
return await this.constructor.hooks.exec(hook, [this, options]);
|
|
2725
|
+
}
|
|
2726
|
+
};
|
|
2727
|
+
};
|
|
2728
|
+
var has_hooks_default = HasHooks;
|
|
2729
|
+
|
|
2730
|
+
// src/relations/has-one-or-many.js
|
|
2731
|
+
import collect5 from "collect.js";
|
|
2732
|
+
var HasOneOrMany = (Relation2) => {
|
|
2733
|
+
return class extends Relation2 {
|
|
2734
|
+
getRelationValue(dictionary, key2, type) {
|
|
2735
|
+
const value = dictionary[key2];
|
|
2736
|
+
return type === "one" ? value[0] : new collection_default(value);
|
|
2737
|
+
}
|
|
2738
|
+
matchOneOrMany(models, results, relation, type) {
|
|
2739
|
+
const dictionary = this.buildDictionary(results);
|
|
2740
|
+
models.map((model) => {
|
|
2741
|
+
const key2 = model.attributes[this.localKey];
|
|
2742
|
+
if (dictionary[key2] !== void 0) {
|
|
2743
|
+
model.setRelation(relation, this.getRelationValue(dictionary, key2, type));
|
|
2744
|
+
}
|
|
2745
|
+
});
|
|
2746
|
+
return models;
|
|
2747
|
+
}
|
|
2748
|
+
buildDictionary(results) {
|
|
2749
|
+
const foreign = this.getForeignKeyName();
|
|
2750
|
+
return collect5(results).mapToDictionary((result) => [
|
|
2751
|
+
result[foreign],
|
|
2752
|
+
result
|
|
2753
|
+
]).all();
|
|
2754
|
+
}
|
|
2755
|
+
async save(model) {
|
|
2756
|
+
this.setForeignAttributesForCreate(model);
|
|
2757
|
+
return await model.save() ? model : false;
|
|
2758
|
+
}
|
|
2759
|
+
async saveMany(models) {
|
|
2760
|
+
await Promise.all(models.map(async (model) => {
|
|
2761
|
+
await this.save(model);
|
|
2762
|
+
}));
|
|
2763
|
+
return models instanceof collection_default ? models : new collection_default(models);
|
|
2764
|
+
}
|
|
2765
|
+
async create(attributes = {}) {
|
|
2766
|
+
return await tap(this.related.constructor.init(attributes), async (instance) => {
|
|
2767
|
+
this.setForeignAttributesForCreate(instance);
|
|
2768
|
+
await instance.save();
|
|
2769
|
+
});
|
|
2770
|
+
}
|
|
2771
|
+
async createMany(records) {
|
|
2772
|
+
const instances = await Promise.all(records.map(async (record) => {
|
|
2773
|
+
return await this.create(record);
|
|
2774
|
+
}));
|
|
2775
|
+
return instances instanceof collection_default ? instances : new collection_default(instances);
|
|
2776
|
+
}
|
|
2777
|
+
setForeignAttributesForCreate(model) {
|
|
2778
|
+
model[this.getForeignKeyName()] = this.getParentKey();
|
|
2779
|
+
}
|
|
2780
|
+
getForeignKeyName() {
|
|
2781
|
+
const segments = this.getQualifiedForeignKeyName().split(".");
|
|
2782
|
+
return segments[segments.length - 1];
|
|
2783
|
+
}
|
|
2784
|
+
getParentKey() {
|
|
2785
|
+
return this.parent.attributes[this.localKey];
|
|
2786
|
+
}
|
|
2787
|
+
getQualifiedForeignKeyName() {
|
|
2788
|
+
return this.foreignKey;
|
|
2789
|
+
}
|
|
2790
|
+
getExistenceCompareKey() {
|
|
2791
|
+
return this.getQualifiedForeignKeyName();
|
|
2792
|
+
}
|
|
2793
|
+
addConstraints() {
|
|
2794
|
+
if (this.constructor.constraints) {
|
|
2795
|
+
const query = this.getRelationQuery();
|
|
2796
|
+
query.where(this.foreignKey, "=", this.getParentKey());
|
|
2797
|
+
query.whereNotNull(this.foreignKey);
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
};
|
|
2801
|
+
};
|
|
2802
|
+
var has_one_or_many_default = HasOneOrMany;
|
|
2803
|
+
|
|
2804
|
+
// src/relations/has-many.js
|
|
2805
|
+
import { collect as collect6 } from "collect.js";
|
|
2806
|
+
var HasMany = class extends compose(relation_default, has_one_or_many_default) {
|
|
2807
|
+
foreignKey;
|
|
2808
|
+
localKey;
|
|
2809
|
+
constructor(query, parent, foreignKey, localKey) {
|
|
2810
|
+
super(query, parent);
|
|
2811
|
+
this.foreignKey = foreignKey;
|
|
2812
|
+
this.localKey = localKey;
|
|
2813
|
+
this.addConstraints();
|
|
2814
|
+
return this.asProxy();
|
|
2815
|
+
}
|
|
2816
|
+
initRelation(models, relation) {
|
|
2817
|
+
models.map((model) => {
|
|
2818
|
+
model.setRelation(relation, new collection_default([]));
|
|
2819
|
+
});
|
|
2820
|
+
return models;
|
|
2821
|
+
}
|
|
2822
|
+
async getResults() {
|
|
2823
|
+
return this.getParentKey() !== null ? await this.query.get() : new collection_default([]);
|
|
2824
|
+
}
|
|
2825
|
+
getForeignKeyName() {
|
|
2826
|
+
const segments = this.foreignKey.split(".");
|
|
2827
|
+
return segments.pop();
|
|
2828
|
+
}
|
|
2829
|
+
buildDictionary(results) {
|
|
2830
|
+
const foreign = this.getForeignKeyName();
|
|
2831
|
+
return collect6(results).mapToDictionary((result) => [
|
|
2832
|
+
result[foreign],
|
|
2833
|
+
result
|
|
2834
|
+
]).all();
|
|
2835
|
+
}
|
|
2836
|
+
match(models, results, relation) {
|
|
2837
|
+
return this.matchOneOrMany(models, results, relation, "many");
|
|
2838
|
+
}
|
|
2839
|
+
addEagerConstraints(models) {
|
|
2840
|
+
this.query.whereIn(this.foreignKey, this.getKeys(models, this.localKey));
|
|
2841
|
+
}
|
|
2842
|
+
};
|
|
2843
|
+
var has_many_default = HasMany;
|
|
2844
|
+
|
|
2845
|
+
// src/relations/has-one.js
|
|
2846
|
+
var HasOne = class extends compose(relation_default, has_one_or_many_default, supports_default_models_default) {
|
|
2847
|
+
foreignKey;
|
|
2848
|
+
localKey;
|
|
2849
|
+
constructor(query, parent, foreignKey, localKey) {
|
|
2850
|
+
super(query, parent);
|
|
2851
|
+
this.foreignKey = foreignKey;
|
|
2852
|
+
this.localKey = localKey;
|
|
2853
|
+
this.addConstraints();
|
|
2854
|
+
return this.asProxy();
|
|
2855
|
+
}
|
|
2856
|
+
initRelation(models, relation) {
|
|
2857
|
+
models.map((model) => {
|
|
2858
|
+
model.setRelation(relation, this.getDefaultFor(model));
|
|
2859
|
+
});
|
|
2860
|
+
return models;
|
|
2861
|
+
}
|
|
2862
|
+
matchOne(models, results, relation) {
|
|
2863
|
+
return this.matchOneOrMany(models, results, relation, "one");
|
|
2864
|
+
}
|
|
2865
|
+
getForeignKeyName() {
|
|
2866
|
+
const segments = this.foreignKey.split(".");
|
|
2867
|
+
return segments.pop();
|
|
2868
|
+
}
|
|
2869
|
+
async getResults() {
|
|
2870
|
+
if (this.getParentKey() === null) {
|
|
2871
|
+
return this.getDefaultFor(this.parent);
|
|
2872
|
+
}
|
|
2873
|
+
const results = await this.query.first();
|
|
2874
|
+
return results || this.getDefaultFor(this.parent);
|
|
2875
|
+
}
|
|
2876
|
+
match(models, results, relation) {
|
|
2877
|
+
return this.matchOneOrMany(models, results, relation, "one");
|
|
2878
|
+
}
|
|
2879
|
+
addEagerConstraints(models) {
|
|
2880
|
+
this.query.whereIn(this.foreignKey, this.getKeys(models, this.localKey));
|
|
2881
|
+
}
|
|
2882
|
+
newRelatedInstanceFor(parent) {
|
|
2883
|
+
return this.related.newInstance().setAttribute(this.getForeignKeyName(), parent[this.localKey]);
|
|
2884
|
+
}
|
|
2885
|
+
};
|
|
2886
|
+
var has_one_default = HasOne;
|
|
2887
|
+
|
|
2888
|
+
// src/relations/has-many-through.js
|
|
2889
|
+
import { isArray as isArray5 } from "radashi";
|
|
2890
|
+
var HasManyThrough = class extends relation_default {
|
|
2891
|
+
throughParent;
|
|
2892
|
+
farParent;
|
|
2893
|
+
firstKey;
|
|
2894
|
+
secondKey;
|
|
2895
|
+
localKey;
|
|
2896
|
+
secondLocalKey;
|
|
2897
|
+
constructor(query, farParent, throughParent, firstKey, secondKey, localKey, secondLocalKey) {
|
|
2898
|
+
super(query, throughParent);
|
|
2899
|
+
this.localKey = localKey;
|
|
2900
|
+
this.firstKey = firstKey;
|
|
2901
|
+
this.secondKey = secondKey;
|
|
2902
|
+
this.farParent = farParent;
|
|
2903
|
+
this.throughParent = throughParent;
|
|
2904
|
+
this.secondLocalKey = secondLocalKey;
|
|
2905
|
+
return this.asProxy();
|
|
2906
|
+
}
|
|
2907
|
+
addConstraints() {
|
|
2908
|
+
const localValue = this.farParent[this.localKey];
|
|
2909
|
+
this.performJoin();
|
|
2910
|
+
if (this.constructor.constraints) {
|
|
2911
|
+
this.query.where(this.getQualifiedFirstKeyName(), "=", localValue);
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
performJoin(query = null) {
|
|
2915
|
+
query = query || this.query;
|
|
2916
|
+
const farKey = this.getQualifiedFarKeyName();
|
|
2917
|
+
query.join(this.throughParent.getTable(), this.getQualifiedParentKeyName(), "=", farKey);
|
|
2918
|
+
if (this.throughParentSoftDeletes()) {
|
|
2919
|
+
query.withGlobalScope("SoftDeletableHasManyThrough", (query2) => {
|
|
2920
|
+
query2.whereNull(this.throughParent.getQualifiedDeletedAtColumn());
|
|
2921
|
+
});
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
getQualifiedParentKeyName() {
|
|
2925
|
+
return this.parent.qualifyColumn(this.secondLocalKey);
|
|
2926
|
+
}
|
|
2927
|
+
throughParentSoftDeletes() {
|
|
2928
|
+
return this.throughParent.pluginInitializers["SoftDeletes"] !== void 0;
|
|
2929
|
+
}
|
|
2930
|
+
withTrashedParents() {
|
|
2931
|
+
this.query.withoutGlobalScope("SoftDeletableHasManyThrough");
|
|
2932
|
+
return this;
|
|
2933
|
+
}
|
|
2934
|
+
addEagerConstraints(models) {
|
|
2935
|
+
const whereIn = this.whereInMethod(this.farParent, this.localKey);
|
|
2936
|
+
this.whereInEager(whereIn, this.getQualifiedFirstKeyName(), this.getKeys(models, this.localKey));
|
|
2937
|
+
}
|
|
2938
|
+
initRelation(models, relation) {
|
|
2939
|
+
for (const model of models) {
|
|
2940
|
+
model.setRelation(relation, this.related.newCollection());
|
|
2941
|
+
}
|
|
2942
|
+
return models;
|
|
2943
|
+
}
|
|
2944
|
+
match(models, results, relation) {
|
|
2945
|
+
const dictionary = this.buildDictionary(results);
|
|
2946
|
+
for (const model of models) {
|
|
2947
|
+
if (dictionary[key = this.getDictionaryKey(model.getAttribute(this.localKey))] !== void 0) {
|
|
2948
|
+
model.setRelation(relation, this.related.newCollection(dictionary[key]));
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
return models;
|
|
2952
|
+
}
|
|
2953
|
+
buildDictionary(results) {
|
|
2954
|
+
const dictionary = {};
|
|
2955
|
+
for (const result of results) {
|
|
2956
|
+
if (dictionary[result.laravel_through_key] === void 0) {
|
|
2957
|
+
dictionary[result.laravel_through_key] = [];
|
|
2958
|
+
}
|
|
2959
|
+
dictionary[result.laravel_through_key].push(result);
|
|
2960
|
+
}
|
|
2961
|
+
return dictionary;
|
|
2962
|
+
}
|
|
2963
|
+
async firstOrNew(attributes) {
|
|
2964
|
+
let instance = await this.where(attributes).first();
|
|
2965
|
+
return instance || this.related.newInstance(attributes);
|
|
2966
|
+
}
|
|
2967
|
+
async updateOrCreate(attributes, values = {}) {
|
|
2968
|
+
return tap(await this.firstOrCreate(attributes, values), async (instance) => {
|
|
2969
|
+
if (!instance.wasRecentlyCreated) {
|
|
2970
|
+
await instance.fill(values).save();
|
|
2971
|
+
}
|
|
2972
|
+
});
|
|
2973
|
+
}
|
|
2974
|
+
async firstWhere(column, operator = null, value = null, boolean = "and") {
|
|
2975
|
+
return await this.where(column, operator, value, boolean).first();
|
|
2976
|
+
}
|
|
2977
|
+
async first(columns = ["*"]) {
|
|
2978
|
+
const results = await this.take(1).get(columns);
|
|
2979
|
+
return results.count() > 0 ? results.first() : null;
|
|
2980
|
+
}
|
|
2981
|
+
async firstOrFail(columns = ["*"]) {
|
|
2982
|
+
const model = await this.first(columns);
|
|
2983
|
+
if (model) {
|
|
2984
|
+
return model;
|
|
2985
|
+
}
|
|
2986
|
+
throw new ModelNotFoundError2().setModel(this.related.constructor);
|
|
2987
|
+
}
|
|
2988
|
+
async firstOr(columns = ["*"], callback = null) {
|
|
2989
|
+
if (typeof columns === "function") {
|
|
2990
|
+
callback = columns;
|
|
2991
|
+
columns = ["*"];
|
|
2992
|
+
}
|
|
2993
|
+
const model = await this.first(columns);
|
|
2994
|
+
if (model) {
|
|
2995
|
+
return model;
|
|
2996
|
+
}
|
|
2997
|
+
return callback();
|
|
2998
|
+
}
|
|
2999
|
+
async find(id, columns = ["*"]) {
|
|
3000
|
+
if (isArray5(id)) {
|
|
3001
|
+
return await this.findMany(id, columns);
|
|
3002
|
+
}
|
|
3003
|
+
return await this.where(this.getRelated().getQualifiedKeyName(), "=", id).first(columns);
|
|
3004
|
+
}
|
|
3005
|
+
async findMany(ids, columns = ["*"]) {
|
|
3006
|
+
if (ids.length === 0) {
|
|
3007
|
+
return this.getRelated().newCollection();
|
|
3008
|
+
}
|
|
3009
|
+
return await this.whereIn(this.getRelated().getQualifiedKeyName(), ids).get(columns);
|
|
3010
|
+
}
|
|
3011
|
+
async findOrFail(id, columns = ["*"]) {
|
|
3012
|
+
const result = await this.find(id, columns);
|
|
3013
|
+
if (isArray5(id)) {
|
|
3014
|
+
if (result.count() === id.length) {
|
|
3015
|
+
return result;
|
|
3016
|
+
}
|
|
3017
|
+
} else if (result) {
|
|
3018
|
+
return result;
|
|
3019
|
+
}
|
|
3020
|
+
throw new ModelNotFoundError2().setModel(this.related.constructor, id);
|
|
3021
|
+
}
|
|
3022
|
+
async getResults() {
|
|
3023
|
+
return this.farParent[this.localKey] ? await this.get() : this.related.newCollection();
|
|
3024
|
+
}
|
|
3025
|
+
async get(columns = ["*"]) {
|
|
3026
|
+
const builder = this.prepareQueryBuilder(columns);
|
|
3027
|
+
let models = await builder.getModels();
|
|
3028
|
+
if (models.count() > 0) {
|
|
3029
|
+
models = await builder.eagerLoadRelations(models);
|
|
3030
|
+
}
|
|
3031
|
+
return this.related.newCollection(models);
|
|
3032
|
+
}
|
|
3033
|
+
async paginate(perPage = null, columns = ["*"], pageName = "page", page = null) {
|
|
3034
|
+
this.query.addSelect(this.shouldSelect(columns));
|
|
3035
|
+
return await this.query.paginate(perPage, columns, pageName, page);
|
|
3036
|
+
}
|
|
3037
|
+
shouldSelect(columns = ["*"]) {
|
|
3038
|
+
if (columns == ["*"]) {
|
|
3039
|
+
columns = [this.related.getTable() + ".*"];
|
|
3040
|
+
}
|
|
3041
|
+
return [...columns, this.getQualifiedFirstKeyName() + " as laravel_through_key"];
|
|
3042
|
+
}
|
|
3043
|
+
async chunk(count, callback) {
|
|
3044
|
+
return await this.prepareQueryBuilder().chunk(count, callback);
|
|
3045
|
+
}
|
|
3046
|
+
prepareQueryBuilder(columns = ["*"]) {
|
|
3047
|
+
const builder = this.query.applyScopes();
|
|
3048
|
+
return builder.addSelect(this.shouldSelect(builder.getQuery().columns ? [] : columns));
|
|
3049
|
+
}
|
|
3050
|
+
getRelationExistenceQuery(query, parentQuery, columns = ["*"]) {
|
|
3051
|
+
if (parentQuery.getQuery().from === query.getQuery().from) {
|
|
3052
|
+
return this.getRelationExistenceQueryForSelfRelation(query, parentQuery, columns);
|
|
3053
|
+
}
|
|
3054
|
+
if (parentQuery.getQuery().from === this.throughParent.getTable()) {
|
|
3055
|
+
return this.getRelationExistenceQueryForThroughSelfRelation(query, parentQuery, columns);
|
|
3056
|
+
}
|
|
3057
|
+
this.performJoin(query);
|
|
3058
|
+
return query.select(columns).where(this.getQualifiedLocalKeyName(), "=", this.getQualifiedFirstKeyName());
|
|
3059
|
+
}
|
|
3060
|
+
getRelationExistenceQueryForSelfRelation(query, parentQuery, columns = ["*"]) {
|
|
3061
|
+
const hash = this.getRelationCountHash();
|
|
3062
|
+
query.from(query.getModel().getTable() + " as " + hash);
|
|
3063
|
+
query.join(this.throughParent.getTable(), this.getQualifiedParentKeyName(), "=", hash + "." + this.secondKey);
|
|
3064
|
+
if (this.throughParentSoftDeletes()) {
|
|
3065
|
+
query.whereNull(this.throughParent.getQualifiedDeletedAtColumn());
|
|
3066
|
+
}
|
|
3067
|
+
query.getModel().setTable(hash);
|
|
3068
|
+
return query.select(columns).whereColumn(parentQuery.getQuery().from + "." + this.localKey, "=", this.getQualifiedFirstKeyName());
|
|
3069
|
+
}
|
|
3070
|
+
getRelationExistenceQueryForThroughSelfRelation(query, parentQuery, columns = ["*"]) {
|
|
3071
|
+
const hash = this.getRelationCountHash();
|
|
3072
|
+
const table = this.throughParent.getTable() + " as " + hash;
|
|
3073
|
+
query.join(table, hash + "." + this.secondLocalKey, "=", this.getQualifiedFarKeyName());
|
|
3074
|
+
if (this.throughParentSoftDeletes()) {
|
|
3075
|
+
query.whereNull(hash + "." + this.throughParent.getDeletedAtColumn());
|
|
3076
|
+
}
|
|
3077
|
+
return query.select(columns).where(parentQuery.getQuery().from + "." + this.localKey, "=", hash + "." + this.firstKey);
|
|
3078
|
+
}
|
|
3079
|
+
getQualifiedFarKeyName() {
|
|
3080
|
+
return this.getQualifiedForeignKeyName();
|
|
3081
|
+
}
|
|
3082
|
+
getFirstKeyName() {
|
|
3083
|
+
return this.firstKey;
|
|
3084
|
+
}
|
|
3085
|
+
getQualifiedFirstKeyName() {
|
|
3086
|
+
return this.throughParent.qualifyColumn(this.firstKey);
|
|
3087
|
+
}
|
|
3088
|
+
getForeignKeyName() {
|
|
3089
|
+
return this.secondKey;
|
|
3090
|
+
}
|
|
3091
|
+
getQualifiedForeignKeyName() {
|
|
3092
|
+
return this.related.qualifyColumn(this.secondKey);
|
|
3093
|
+
}
|
|
3094
|
+
getLocalKeyName() {
|
|
3095
|
+
return this.localKey;
|
|
3096
|
+
}
|
|
3097
|
+
getQualifiedLocalKeyName() {
|
|
3098
|
+
return this.farParent.qualifyColumn(this.localKey);
|
|
3099
|
+
}
|
|
3100
|
+
getSecondLocalKeyName() {
|
|
3101
|
+
return this.secondLocalKey;
|
|
3102
|
+
}
|
|
3103
|
+
};
|
|
3104
|
+
var has_many_through_default = HasManyThrough;
|
|
3105
|
+
|
|
3106
|
+
// src/relations/has-one-through.js
|
|
3107
|
+
var HasOneThrough = class extends compose(has_many_through_default, supports_default_models_default) {
|
|
3108
|
+
async getResults() {
|
|
3109
|
+
return await this.first() || this.getDefaultFor(this.farParent);
|
|
3110
|
+
}
|
|
3111
|
+
initRelation(models, relation) {
|
|
3112
|
+
for (const model of models) {
|
|
3113
|
+
model.setRelation(relation, this.getDefaultFor(model));
|
|
3114
|
+
}
|
|
3115
|
+
return models;
|
|
3116
|
+
}
|
|
3117
|
+
match(models, results, relation) {
|
|
3118
|
+
const dictionary = this.buildDictionary(results);
|
|
3119
|
+
for (const model of models) {
|
|
3120
|
+
const key2 = this.getDictionaryKey(model.getAttribute(this.localKey));
|
|
3121
|
+
if (dictionary[key2] !== void 0) {
|
|
3122
|
+
const value = dictionary[key2];
|
|
3123
|
+
model.setRelation(relation, value[0]);
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
return models;
|
|
3127
|
+
}
|
|
3128
|
+
newRelatedInstanceFor(parent) {
|
|
3129
|
+
return this.related.newInstance();
|
|
3130
|
+
}
|
|
3131
|
+
};
|
|
3132
|
+
var has_one_through_default = HasOneThrough;
|
|
3133
|
+
|
|
3134
|
+
// src/concerns/has-relations.js
|
|
3135
|
+
import { omit as omit5 } from "radashi";
|
|
3136
|
+
var HasRelations = (Model2) => {
|
|
3137
|
+
return class extends Model2 {
|
|
3138
|
+
relations = {};
|
|
3139
|
+
getRelation(relation) {
|
|
3140
|
+
return this.relations[relation];
|
|
3141
|
+
}
|
|
3142
|
+
setRelation(relation, value) {
|
|
3143
|
+
this.relations[relation] = value;
|
|
3144
|
+
return this;
|
|
3145
|
+
}
|
|
3146
|
+
unsetRelation(relation) {
|
|
3147
|
+
this.relations = omit5(this.relations, [relation]);
|
|
3148
|
+
return this;
|
|
3149
|
+
}
|
|
3150
|
+
relationLoaded(relation) {
|
|
3151
|
+
return this.relations[relation] !== void 0;
|
|
3152
|
+
}
|
|
3153
|
+
related(relation) {
|
|
3154
|
+
if (typeof this[getRelationMethod(relation)] !== "function") {
|
|
3155
|
+
const message = `Model [${this.constructor.name}]'s relation [${relation}] doesn't exist.`;
|
|
3156
|
+
throw new RelationNotFoundError(message);
|
|
3157
|
+
}
|
|
3158
|
+
return this[getRelationMethod(relation)]();
|
|
3159
|
+
}
|
|
3160
|
+
async getRelated(relation) {
|
|
3161
|
+
return await this.related(relation).getResults();
|
|
3162
|
+
}
|
|
3163
|
+
relationsToData() {
|
|
3164
|
+
const data = {};
|
|
3165
|
+
for (const key2 in this.relations) {
|
|
3166
|
+
if (this.hidden.includes(key2)) {
|
|
3167
|
+
continue;
|
|
3168
|
+
}
|
|
3169
|
+
if (this.visible.length > 0 && this.visible.includes(key2) === false) {
|
|
3170
|
+
continue;
|
|
3171
|
+
}
|
|
3172
|
+
data[key2] = this.relations[key2] instanceof Array ? this.relations[key2].map((item) => item.toData()) : this.relations[key2] === null ? null : this.relations[key2].toData();
|
|
3173
|
+
}
|
|
3174
|
+
return data;
|
|
3175
|
+
}
|
|
3176
|
+
guessBelongsToRelation() {
|
|
3177
|
+
let e = new Error();
|
|
3178
|
+
let frame = e.stack.split("\n")[2];
|
|
3179
|
+
let functionName = frame.split(" ")[5];
|
|
3180
|
+
return getRelationName(functionName);
|
|
3181
|
+
}
|
|
3182
|
+
joiningTable(related, instance = null) {
|
|
3183
|
+
const segments = [
|
|
3184
|
+
instance ? instance.joiningTableSegment() : snakeCase(related.name),
|
|
3185
|
+
this.joiningTableSegment()
|
|
3186
|
+
];
|
|
3187
|
+
return segments.sort().join("_").toLocaleLowerCase();
|
|
3188
|
+
}
|
|
3189
|
+
joiningTableSegment() {
|
|
3190
|
+
return snakeCase(this.constructor.name);
|
|
3191
|
+
}
|
|
3192
|
+
hasOne(related, foreignKey = null, localKey = null) {
|
|
3193
|
+
const query = related.query();
|
|
3194
|
+
const instance = new related();
|
|
3195
|
+
foreignKey = foreignKey || this.getForeignKey();
|
|
3196
|
+
localKey = localKey || this.getKeyName();
|
|
3197
|
+
return new has_one_default(query, this, instance.getTable() + "." + foreignKey, localKey);
|
|
3198
|
+
}
|
|
3199
|
+
hasMany(related, foreignKey = null, localKey = null) {
|
|
3200
|
+
const query = related.query();
|
|
3201
|
+
const instance = new related();
|
|
3202
|
+
foreignKey = foreignKey || this.getForeignKey();
|
|
3203
|
+
localKey = localKey || this.getKeyName();
|
|
3204
|
+
return new has_many_default(query, this, instance.getTable() + "." + foreignKey, localKey);
|
|
3205
|
+
}
|
|
3206
|
+
belongsTo(related, foreignKey = null, ownerKey = null, relation = null) {
|
|
3207
|
+
const query = related.query();
|
|
3208
|
+
const instance = new related();
|
|
3209
|
+
foreignKey = foreignKey || instance.getForeignKey();
|
|
3210
|
+
ownerKey = ownerKey || instance.getKeyName();
|
|
3211
|
+
relation = relation || this.guessBelongsToRelation();
|
|
3212
|
+
return new belongs_to_default(query, this, foreignKey, ownerKey, relation);
|
|
3213
|
+
}
|
|
3214
|
+
belongsToMany(related, table = null, foreignPivotKey = null, relatedPivotKey = null, parentKey = null, relatedKey = null) {
|
|
3215
|
+
const query = related.query();
|
|
3216
|
+
const instance = new related();
|
|
3217
|
+
table = table || this.joiningTable(related, instance);
|
|
3218
|
+
foreignPivotKey = foreignPivotKey || this.getForeignKey();
|
|
3219
|
+
relatedPivotKey = relatedPivotKey || instance.getForeignKey();
|
|
3220
|
+
parentKey = parentKey || this.getKeyName();
|
|
3221
|
+
relatedKey = relatedKey || instance.getKeyName();
|
|
3222
|
+
return new belongs_to_many_default(query, this, table, foreignPivotKey, relatedPivotKey, parentKey, relatedKey);
|
|
3223
|
+
}
|
|
3224
|
+
hasOneThrough(related, through, firstKey = null, secondKey = null, localKey = null, secondLocalKey = null) {
|
|
3225
|
+
through = new through();
|
|
3226
|
+
const query = related.query();
|
|
3227
|
+
firstKey = firstKey || this.getForeignKey();
|
|
3228
|
+
secondKey = secondKey || through.getForeignKey();
|
|
3229
|
+
return new has_one_through_default(query, this, through, firstKey, secondKey, localKey || this.getKeyName(), secondLocalKey || through.getKeyName());
|
|
3230
|
+
}
|
|
3231
|
+
hasManyThrough(related, through, firstKey = null, secondKey = null, localKey = null, secondLocalKey = null) {
|
|
3232
|
+
through = new through();
|
|
3233
|
+
const query = related.query();
|
|
3234
|
+
firstKey = firstKey || this.getForeignKey();
|
|
3235
|
+
secondKey = secondKey || through.getForeignKey();
|
|
3236
|
+
return new has_many_through_default(query, this, through, firstKey, secondKey, localKey || this.getKeyName(), secondLocalKey || through.getKeyName());
|
|
3237
|
+
}
|
|
3238
|
+
};
|
|
3239
|
+
};
|
|
3240
|
+
var has_relations_default = HasRelations;
|
|
3241
|
+
|
|
3242
|
+
// src/concerns/has-timestamps.js
|
|
3243
|
+
var HasTimestamps = (Model2) => {
|
|
3244
|
+
return class extends Model2 {
|
|
3245
|
+
static CREATED_AT = "created_at";
|
|
3246
|
+
static UPDATED_AT = "updated_at";
|
|
3247
|
+
static DELETED_AT = "deleted_at";
|
|
3248
|
+
timestamps = true;
|
|
3249
|
+
dateFormat = "YYYY-MM-DD HH:mm:ss";
|
|
3250
|
+
usesTimestamps() {
|
|
3251
|
+
return this.timestamps;
|
|
3252
|
+
}
|
|
3253
|
+
updateTimestamps() {
|
|
3254
|
+
const time = this.freshTimestampString();
|
|
3255
|
+
const updatedAtColumn = this.getUpdatedAtColumn();
|
|
3256
|
+
if (updatedAtColumn && !this.isDirty(updatedAtColumn)) {
|
|
3257
|
+
this.setUpdatedAt(time);
|
|
3258
|
+
}
|
|
3259
|
+
const createdAtColumn = this.getCreatedAtColumn();
|
|
3260
|
+
if (!this.exists && createdAtColumn && !this.isDirty(createdAtColumn)) {
|
|
3261
|
+
this.setCreatedAt(time);
|
|
3262
|
+
}
|
|
3263
|
+
return this;
|
|
3264
|
+
}
|
|
3265
|
+
getCreatedAtColumn() {
|
|
3266
|
+
return this.constructor.CREATED_AT;
|
|
3267
|
+
}
|
|
3268
|
+
getUpdatedAtColumn() {
|
|
3269
|
+
return this.constructor.UPDATED_AT;
|
|
3270
|
+
}
|
|
3271
|
+
setCreatedAt(value) {
|
|
3272
|
+
this.attributes[this.getCreatedAtColumn()] = value;
|
|
3273
|
+
return this;
|
|
3274
|
+
}
|
|
3275
|
+
setUpdatedAt(value) {
|
|
3276
|
+
this.attributes[this.getUpdatedAtColumn()] = value;
|
|
3277
|
+
return this;
|
|
3278
|
+
}
|
|
3279
|
+
freshTimestamp() {
|
|
3280
|
+
const time = /* @__PURE__ */ new Date();
|
|
3281
|
+
time.setMilliseconds(0);
|
|
3282
|
+
return time;
|
|
3283
|
+
}
|
|
3284
|
+
freshTimestampString() {
|
|
3285
|
+
return this.fromDateTime(this.freshTimestamp());
|
|
3286
|
+
}
|
|
3287
|
+
};
|
|
3288
|
+
};
|
|
3289
|
+
var has_timestamps_default = HasTimestamps;
|
|
3290
|
+
|
|
3291
|
+
// src/concerns/hides-attributes.js
|
|
3292
|
+
import { diff as difference4 } from "radashi";
|
|
3293
|
+
var HidesAttributes = (Model2) => {
|
|
3294
|
+
return class extends Model2 {
|
|
3295
|
+
hidden = [];
|
|
3296
|
+
visible = [];
|
|
3297
|
+
makeVisible(...keys) {
|
|
3298
|
+
const visible = flattenDeep(keys);
|
|
3299
|
+
if (this.visible.length > 0) {
|
|
3300
|
+
this.visible = [...this.visible, ...visible];
|
|
3301
|
+
}
|
|
3302
|
+
this.hidden = difference4(this.hidden, visible);
|
|
3303
|
+
return this;
|
|
3304
|
+
}
|
|
3305
|
+
makeHidden(...keys) {
|
|
3306
|
+
const hidden = flattenDeep(keys);
|
|
3307
|
+
if (this.hidden.length > 0) {
|
|
3308
|
+
this.hidden = [...this.hidden, ...hidden];
|
|
3309
|
+
}
|
|
3310
|
+
return this;
|
|
3311
|
+
}
|
|
3312
|
+
getHidden() {
|
|
3313
|
+
return this.hidden;
|
|
3314
|
+
}
|
|
3315
|
+
getVisible() {
|
|
3316
|
+
return this.visible;
|
|
3317
|
+
}
|
|
3318
|
+
setHidden(hidden) {
|
|
3319
|
+
this.hidden = hidden;
|
|
3320
|
+
return this;
|
|
3321
|
+
}
|
|
3322
|
+
setVisible(visible) {
|
|
3323
|
+
this.visible = visible;
|
|
3324
|
+
return this;
|
|
3325
|
+
}
|
|
3326
|
+
};
|
|
3327
|
+
};
|
|
3328
|
+
var hides_attributes_default = HidesAttributes;
|
|
3329
|
+
|
|
3330
|
+
// src/concerns/unique-ids.js
|
|
3331
|
+
var UniqueIds = (Model2) => {
|
|
3332
|
+
return class extends Model2 {
|
|
3333
|
+
useUniqueIds = false;
|
|
3334
|
+
usesUniqueIds() {
|
|
3335
|
+
return this.useUniqueIds;
|
|
3336
|
+
}
|
|
3337
|
+
uniqueIds() {
|
|
3338
|
+
return [];
|
|
3339
|
+
}
|
|
3340
|
+
newUniqueId() {
|
|
3341
|
+
return null;
|
|
3342
|
+
}
|
|
3343
|
+
setUniqueIds() {
|
|
3344
|
+
const uniqueIds = this.uniqueIds();
|
|
3345
|
+
for (const column of uniqueIds) {
|
|
3346
|
+
if (this[column] === null || this[column] === void 0) {
|
|
3347
|
+
this[column] = this.newUniqueId();
|
|
3348
|
+
}
|
|
3349
|
+
}
|
|
3350
|
+
}
|
|
3351
|
+
};
|
|
3352
|
+
};
|
|
3353
|
+
var unique_ids_default = UniqueIds;
|
|
3354
|
+
|
|
3355
|
+
// src/model.js
|
|
3356
|
+
import collect7 from "collect.js";
|
|
3357
|
+
import { assign as merge3 } from "radashi";
|
|
3358
|
+
import pluralize from "pluralize";
|
|
3359
|
+
var BaseModel = compose(class {
|
|
3360
|
+
}, has_attributes_default, hides_attributes_default, has_relations_default, has_timestamps_default, has_hooks_default, has_global_scopes_default, unique_ids_default);
|
|
3361
|
+
var Model = class _Model extends BaseModel {
|
|
3362
|
+
primaryKey = "id";
|
|
3363
|
+
// protected
|
|
3364
|
+
builder = null;
|
|
3365
|
+
// protected
|
|
3366
|
+
table = null;
|
|
3367
|
+
// protected
|
|
3368
|
+
connection = null;
|
|
3369
|
+
// protected
|
|
3370
|
+
keyType = "int";
|
|
3371
|
+
// protected
|
|
3372
|
+
incrementing = true;
|
|
3373
|
+
// protected
|
|
3374
|
+
perPage = 15;
|
|
3375
|
+
// protected
|
|
3376
|
+
exists = false;
|
|
3377
|
+
eagerLoad = {};
|
|
3378
|
+
with = [];
|
|
3379
|
+
withCount = [];
|
|
3380
|
+
// protected
|
|
3381
|
+
trx = null;
|
|
3382
|
+
static globalScopes = {};
|
|
3383
|
+
static pluginInitializers = {};
|
|
3384
|
+
static _booted = {};
|
|
3385
|
+
static resolver = null;
|
|
3386
|
+
static query(trx = null) {
|
|
3387
|
+
const instance = new this();
|
|
3388
|
+
return instance.newQuery(trx);
|
|
3389
|
+
}
|
|
3390
|
+
static on(connection = null) {
|
|
3391
|
+
const instance = new this();
|
|
3392
|
+
instance.setConnection(connection);
|
|
3393
|
+
return instance.newQuery();
|
|
3394
|
+
}
|
|
3395
|
+
static init(attributes = {}) {
|
|
3396
|
+
return new this(attributes);
|
|
3397
|
+
}
|
|
3398
|
+
static extend(plugin, options) {
|
|
3399
|
+
plugin(this, options);
|
|
3400
|
+
}
|
|
3401
|
+
static make(attributes = {}) {
|
|
3402
|
+
const instance = new this();
|
|
3403
|
+
for (let attribute in attributes) {
|
|
3404
|
+
if (typeof instance[getRelationMethod(attribute)] !== "function") {
|
|
3405
|
+
instance.setAttribute(attribute, attributes[attribute]);
|
|
3406
|
+
} else {
|
|
3407
|
+
const relation = instance[getRelationMethod(attribute)]();
|
|
3408
|
+
const related = relation.getRelated().constructor;
|
|
3409
|
+
if (relation instanceof has_one_default || relation instanceof belongs_to_default) {
|
|
3410
|
+
instance.setRelation(attribute, related.make(attributes[attribute]));
|
|
3411
|
+
} else if ((relation instanceof has_many_default || relation instanceof belongs_to_many_default) && Array.isArray(attributes[attribute])) {
|
|
3412
|
+
instance.setRelation(attribute, new collection_default(attributes[attribute].map((item) => related.make(item))));
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
}
|
|
3416
|
+
return instance;
|
|
3417
|
+
}
|
|
3418
|
+
constructor(attributes = {}) {
|
|
3419
|
+
super();
|
|
3420
|
+
this.bootIfNotBooted();
|
|
3421
|
+
this.initializePlugins();
|
|
3422
|
+
this.syncOriginal();
|
|
3423
|
+
this.fill(attributes);
|
|
3424
|
+
return this.asProxy();
|
|
3425
|
+
}
|
|
3426
|
+
bootIfNotBooted() {
|
|
3427
|
+
if (this.constructor._booted[this.constructor.name] === void 0) {
|
|
3428
|
+
this.constructor._booted[this.constructor.name] = true;
|
|
3429
|
+
this.constructor.booting();
|
|
3430
|
+
this.initialize();
|
|
3431
|
+
this.constructor.boot();
|
|
3432
|
+
this.constructor.booted();
|
|
3433
|
+
}
|
|
3434
|
+
}
|
|
3435
|
+
static booting() {
|
|
3436
|
+
}
|
|
3437
|
+
static boot() {
|
|
3438
|
+
}
|
|
3439
|
+
static booted() {
|
|
3440
|
+
}
|
|
3441
|
+
static setConnectionResolver(resolver) {
|
|
3442
|
+
this.resolver = resolver;
|
|
3443
|
+
}
|
|
3444
|
+
initialize() {
|
|
3445
|
+
}
|
|
3446
|
+
initializePlugins() {
|
|
3447
|
+
if (typeof this.constructor.pluginInitializers[this.constructor.name] === "undefined") {
|
|
3448
|
+
return;
|
|
3449
|
+
}
|
|
3450
|
+
for (const method of this.constructor.pluginInitializers[this.constructor.name]) {
|
|
3451
|
+
this[method]();
|
|
3452
|
+
}
|
|
3453
|
+
}
|
|
3454
|
+
addPluginInitializer(method) {
|
|
3455
|
+
if (!this.constructor.pluginInitializers[this.constructor.name]) {
|
|
3456
|
+
this.constructor.pluginInitializers[this.constructor.name] = [];
|
|
3457
|
+
}
|
|
3458
|
+
this.constructor.pluginInitializers[this.constructor.name].push(method);
|
|
3459
|
+
}
|
|
3460
|
+
newInstance(attributes = {}, exists = false) {
|
|
3461
|
+
const model = new this.constructor();
|
|
3462
|
+
model.exists = exists;
|
|
3463
|
+
model.setConnection(this.getConnectionName());
|
|
3464
|
+
model.setTable(this.getTable());
|
|
3465
|
+
model.fill(attributes);
|
|
3466
|
+
return model;
|
|
3467
|
+
}
|
|
3468
|
+
newFromBuilder(attributes = {}, connection = null) {
|
|
3469
|
+
const model = this.newInstance({}, true);
|
|
3470
|
+
model.setRawAttributes(attributes, true);
|
|
3471
|
+
model.setConnection(connection || this.getConnectionName());
|
|
3472
|
+
return model;
|
|
3473
|
+
}
|
|
3474
|
+
asProxy() {
|
|
3475
|
+
const handler = {
|
|
3476
|
+
get: function(target, prop) {
|
|
3477
|
+
if (target[prop] !== void 0) {
|
|
3478
|
+
return target[prop];
|
|
3479
|
+
}
|
|
3480
|
+
if (typeof prop === "string") {
|
|
3481
|
+
return target.getAttribute(prop);
|
|
3482
|
+
}
|
|
3483
|
+
},
|
|
3484
|
+
set: function(target, prop, value) {
|
|
3485
|
+
if (target[prop] !== void 0 && typeof target !== "function") {
|
|
3486
|
+
target[prop] = value;
|
|
3487
|
+
return target;
|
|
3488
|
+
}
|
|
3489
|
+
if (typeof prop === "string") {
|
|
3490
|
+
return target.setAttribute(prop, value);
|
|
3491
|
+
}
|
|
3492
|
+
return target;
|
|
3493
|
+
}
|
|
3494
|
+
};
|
|
3495
|
+
return new Proxy(this, handler);
|
|
3496
|
+
}
|
|
3497
|
+
getKey() {
|
|
3498
|
+
return this.getAttribute(this.getKeyName());
|
|
3499
|
+
}
|
|
3500
|
+
getKeyName() {
|
|
3501
|
+
return this.primaryKey;
|
|
3502
|
+
}
|
|
3503
|
+
getForeignKey() {
|
|
3504
|
+
return snakeCase(this.constructor.name) + "_" + this.getKeyName();
|
|
3505
|
+
}
|
|
3506
|
+
getConnectionName() {
|
|
3507
|
+
return this.connection;
|
|
3508
|
+
}
|
|
3509
|
+
getTable() {
|
|
3510
|
+
return this.table || pluralize(snakeCase(this.constructor.name));
|
|
3511
|
+
}
|
|
3512
|
+
getConnection() {
|
|
3513
|
+
if (this.constructor.resolver) {
|
|
3514
|
+
return this.constructor.resolver.getConnection(this.connection);
|
|
3515
|
+
}
|
|
3516
|
+
return arquebus_default.connection(this.connection);
|
|
3517
|
+
}
|
|
3518
|
+
setConnection(connection) {
|
|
3519
|
+
this.connection = connection;
|
|
3520
|
+
return this;
|
|
3521
|
+
}
|
|
3522
|
+
getKeyType() {
|
|
3523
|
+
return this.keyType;
|
|
3524
|
+
}
|
|
3525
|
+
newQuery(trx = null) {
|
|
3526
|
+
return this.addGlobalScopes(this.newQueryWithoutScopes(trx));
|
|
3527
|
+
}
|
|
3528
|
+
newQueryWithoutScopes(trx = null) {
|
|
3529
|
+
return this.newModelQuery(trx).with(this.with).withCount(this.withCount);
|
|
3530
|
+
}
|
|
3531
|
+
newModelQuery(trx = null) {
|
|
3532
|
+
const builder = new builder_default(trx || this.getConnection());
|
|
3533
|
+
return builder.setModel(this);
|
|
3534
|
+
}
|
|
3535
|
+
addGlobalScopes(builder) {
|
|
3536
|
+
const globalScopes = this.getGlobalScopes();
|
|
3537
|
+
for (const identifier in globalScopes) {
|
|
3538
|
+
const scope = globalScopes[identifier];
|
|
3539
|
+
builder.withGlobalScope(identifier, scope);
|
|
3540
|
+
}
|
|
3541
|
+
return builder;
|
|
3542
|
+
}
|
|
3543
|
+
hasNamedScope(name) {
|
|
3544
|
+
const scope = getScopeMethod(name);
|
|
3545
|
+
return typeof this[scope] === "function";
|
|
3546
|
+
}
|
|
3547
|
+
callNamedScope(scope, parameters) {
|
|
3548
|
+
const scopeMethod = getScopeMethod(scope);
|
|
3549
|
+
return this[scopeMethod](...parameters);
|
|
3550
|
+
}
|
|
3551
|
+
setTable(table) {
|
|
3552
|
+
this.table = table;
|
|
3553
|
+
return this;
|
|
3554
|
+
}
|
|
3555
|
+
newCollection(models = []) {
|
|
3556
|
+
return new collection_default(models);
|
|
3557
|
+
}
|
|
3558
|
+
async load(...relations) {
|
|
3559
|
+
const query = this.constructor.query().with(...relations);
|
|
3560
|
+
await query.eagerLoadRelations([this]);
|
|
3561
|
+
return this;
|
|
3562
|
+
}
|
|
3563
|
+
async loadAggregate(relations, column, callback = null) {
|
|
3564
|
+
await new collection_default([this]).loadAggregate(relations, column, callback);
|
|
3565
|
+
return this;
|
|
3566
|
+
}
|
|
3567
|
+
async loadCount(...relations) {
|
|
3568
|
+
relations = flattenDeep(relations);
|
|
3569
|
+
return await this.loadAggregate(relations, "*", "count");
|
|
3570
|
+
}
|
|
3571
|
+
async loadMax(relations, column) {
|
|
3572
|
+
return await this.loadAggregate(relations, column, "max");
|
|
3573
|
+
}
|
|
3574
|
+
async loadMin(relations, column) {
|
|
3575
|
+
return await this.loadAggregate(relations, column, "min");
|
|
3576
|
+
}
|
|
3577
|
+
async loadSum(relations, column) {
|
|
3578
|
+
return await this.loadAggregate(relations, column, "sum");
|
|
3579
|
+
}
|
|
3580
|
+
async increment(column, amount = 1, extra = {}, options = {}) {
|
|
3581
|
+
return await this.incrementOrDecrement(column, amount, extra, "increment", options);
|
|
3582
|
+
}
|
|
3583
|
+
async decrement(column, amount = 1, extra = {}, options = {}) {
|
|
3584
|
+
return await this.incrementOrDecrement(column, amount, extra, "decrement", options);
|
|
3585
|
+
}
|
|
3586
|
+
async incrementOrDecrement(column, amount, extra, method, options) {
|
|
3587
|
+
const query = this.newModelQuery(options.client);
|
|
3588
|
+
if (!this.exists) {
|
|
3589
|
+
return await query[method](column, amount, extra);
|
|
3590
|
+
}
|
|
3591
|
+
this.attributes[column] = this[column] + (method === "increment" ? amount : amount * -1);
|
|
3592
|
+
for (let key2 in extra) {
|
|
3593
|
+
this.attributes[key2] = extra[key2];
|
|
3594
|
+
}
|
|
3595
|
+
await this.execHooks("updating", options);
|
|
3596
|
+
return await tap(await query.where(this.getKeyName(), this.getKey())[method](column, amount, extra), async () => {
|
|
3597
|
+
this.syncChanges();
|
|
3598
|
+
await this.execHooks("updated", options);
|
|
3599
|
+
this.syncOriginalAttribute(column);
|
|
3600
|
+
});
|
|
3601
|
+
}
|
|
3602
|
+
toData() {
|
|
3603
|
+
return merge3(this.attributesToData(), this.relationsToData());
|
|
3604
|
+
}
|
|
3605
|
+
toJSON() {
|
|
3606
|
+
return this.toData();
|
|
3607
|
+
}
|
|
3608
|
+
toJson(...args) {
|
|
3609
|
+
return JSON.stringify(this.toData(), ...args);
|
|
3610
|
+
}
|
|
3611
|
+
toString() {
|
|
3612
|
+
return this.toJson();
|
|
3613
|
+
}
|
|
3614
|
+
fill(attributes) {
|
|
3615
|
+
for (const key2 in attributes) {
|
|
3616
|
+
this.setAttribute(key2, attributes[key2]);
|
|
3617
|
+
}
|
|
3618
|
+
return this;
|
|
3619
|
+
}
|
|
3620
|
+
transacting(trx) {
|
|
3621
|
+
this.trx = trx;
|
|
3622
|
+
return this;
|
|
3623
|
+
}
|
|
3624
|
+
trashed() {
|
|
3625
|
+
return this[this.getDeletedAtColumn()] !== null;
|
|
3626
|
+
}
|
|
3627
|
+
getIncrementing() {
|
|
3628
|
+
return this.incrementing;
|
|
3629
|
+
}
|
|
3630
|
+
setIncrementing(value) {
|
|
3631
|
+
this.incrementing = value;
|
|
3632
|
+
return this;
|
|
3633
|
+
}
|
|
3634
|
+
async save(options = {}) {
|
|
3635
|
+
const query = this.newModelQuery(options.client);
|
|
3636
|
+
let saved;
|
|
3637
|
+
await this.execHooks("saving", options);
|
|
3638
|
+
if (this.exists) {
|
|
3639
|
+
if (this.isDirty() === false) {
|
|
3640
|
+
saved = true;
|
|
3641
|
+
} else {
|
|
3642
|
+
await this.execHooks("updating", options);
|
|
3643
|
+
if (this.usesTimestamps()) {
|
|
3644
|
+
this.updateTimestamps();
|
|
3645
|
+
}
|
|
3646
|
+
const dirty = this.getDirty();
|
|
3647
|
+
if (Object.keys(dirty).length > 0) {
|
|
3648
|
+
await query.where(this.getKeyName(), this.getKey()).query.update(dirty);
|
|
3649
|
+
this.syncChanges();
|
|
3650
|
+
await this.execHooks("updated", options);
|
|
3651
|
+
}
|
|
3652
|
+
saved = true;
|
|
3653
|
+
}
|
|
3654
|
+
} else {
|
|
3655
|
+
if (this.usesUniqueIds()) {
|
|
3656
|
+
this.setUniqueIds();
|
|
3657
|
+
}
|
|
3658
|
+
await this.execHooks("creating", options);
|
|
3659
|
+
if (this.usesTimestamps()) {
|
|
3660
|
+
this.updateTimestamps();
|
|
3661
|
+
}
|
|
3662
|
+
const attributes = this.getAttributes();
|
|
3663
|
+
if (this.getIncrementing()) {
|
|
3664
|
+
const keyName = this.getKeyName();
|
|
3665
|
+
const data = await query.insert([attributes], [keyName]);
|
|
3666
|
+
this.setAttribute(keyName, data[0]?.[keyName] || data[0]);
|
|
3667
|
+
} else {
|
|
3668
|
+
if (Object.keys(attributes).length > 0) {
|
|
3669
|
+
await query.insert(attributes);
|
|
3670
|
+
}
|
|
3671
|
+
}
|
|
3672
|
+
this.exists = true;
|
|
3673
|
+
await this.execHooks("created", options);
|
|
3674
|
+
saved = true;
|
|
3675
|
+
}
|
|
3676
|
+
if (saved) {
|
|
3677
|
+
await this.execHooks("saved", options);
|
|
3678
|
+
this.syncOriginal();
|
|
3679
|
+
}
|
|
3680
|
+
return saved;
|
|
3681
|
+
}
|
|
3682
|
+
async update(attributes = {}, options = {}) {
|
|
3683
|
+
if (!this.exists) {
|
|
3684
|
+
return false;
|
|
3685
|
+
}
|
|
3686
|
+
for (let key2 in attributes) {
|
|
3687
|
+
this[key2] = attributes[key2];
|
|
3688
|
+
}
|
|
3689
|
+
return await this.save(options);
|
|
3690
|
+
}
|
|
3691
|
+
async delete(options = {}) {
|
|
3692
|
+
await this.execHooks("deleting", options);
|
|
3693
|
+
await this.performDeleteOnModel(options);
|
|
3694
|
+
await this.execHooks("deleted", options);
|
|
3695
|
+
return true;
|
|
3696
|
+
}
|
|
3697
|
+
async performDeleteOnModel(options = {}) {
|
|
3698
|
+
await this.setKeysForSaveQuery(this.newModelQuery(options.client)).delete();
|
|
3699
|
+
this.exists = false;
|
|
3700
|
+
}
|
|
3701
|
+
setKeysForSaveQuery(query) {
|
|
3702
|
+
query.where(this.getKeyName(), "=", this.getKey());
|
|
3703
|
+
return query;
|
|
3704
|
+
}
|
|
3705
|
+
async forceDelete(options = {}) {
|
|
3706
|
+
return await this.delete(options);
|
|
3707
|
+
}
|
|
3708
|
+
fresh() {
|
|
3709
|
+
if (!this.exists) {
|
|
3710
|
+
return;
|
|
3711
|
+
}
|
|
3712
|
+
return this.constructor.query().where(this.getKeyName(), this.getKey()).first();
|
|
3713
|
+
}
|
|
3714
|
+
async refresh() {
|
|
3715
|
+
if (!this.exists) {
|
|
3716
|
+
return;
|
|
3717
|
+
}
|
|
3718
|
+
const model = await this.constructor.query().where(this.getKeyName(), this.getKey()).first();
|
|
3719
|
+
this.attributes = { ...model.attributes };
|
|
3720
|
+
await this.load(collect7(this.relations).reject((relation) => {
|
|
3721
|
+
return relation instanceof Pivot;
|
|
3722
|
+
}).keys().all());
|
|
3723
|
+
this.syncOriginal();
|
|
3724
|
+
return this;
|
|
3725
|
+
}
|
|
3726
|
+
newPivot(parent, attributes, table, exists, using = null) {
|
|
3727
|
+
return using ? using.fromRawAttributes(parent, attributes, table, exists) : Pivot.fromAttributes(parent, attributes, table, exists);
|
|
3728
|
+
}
|
|
3729
|
+
qualifyColumn(column) {
|
|
3730
|
+
if (column.includes(".")) {
|
|
3731
|
+
return column;
|
|
3732
|
+
}
|
|
3733
|
+
return `${this.getTable()}.${column}`;
|
|
3734
|
+
}
|
|
3735
|
+
getQualifiedKeyName() {
|
|
3736
|
+
return this.qualifyColumn(this.getKeyName());
|
|
3737
|
+
}
|
|
3738
|
+
async push(options = {}) {
|
|
3739
|
+
const saved = await this.save(options);
|
|
3740
|
+
if (!saved) {
|
|
3741
|
+
return false;
|
|
3742
|
+
}
|
|
3743
|
+
for (const relation in this.relations) {
|
|
3744
|
+
let models = this.relations[relation];
|
|
3745
|
+
models = models instanceof collection_default ? models.all() : [models];
|
|
3746
|
+
for (const model of models) {
|
|
3747
|
+
if (!await model.push(options)) {
|
|
3748
|
+
return false;
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
;
|
|
3752
|
+
}
|
|
3753
|
+
return true;
|
|
3754
|
+
}
|
|
3755
|
+
is(model) {
|
|
3756
|
+
return model && model instanceof _Model && this.getKey() === model.getKey() && this.getTable() === model.getTable() && this.getConnectionName() === model.getConnectionName();
|
|
3757
|
+
}
|
|
3758
|
+
isNot(model) {
|
|
3759
|
+
return !this.is(model);
|
|
3760
|
+
}
|
|
3761
|
+
};
|
|
3762
|
+
var Pivot = class extends Model {
|
|
3763
|
+
incrementing = false;
|
|
3764
|
+
guarded = [];
|
|
3765
|
+
pivotParent = null;
|
|
3766
|
+
foreignKey = null;
|
|
3767
|
+
relatedKey = null;
|
|
3768
|
+
setPivotKeys(foreignKey, relatedKey) {
|
|
3769
|
+
this.foreignKey = foreignKey;
|
|
3770
|
+
this.relatedKey = relatedKey;
|
|
3771
|
+
return this;
|
|
3772
|
+
}
|
|
3773
|
+
static fromRawAttributes(parent, attributes, table, exists = false) {
|
|
3774
|
+
const instance = this.fromAttributes(parent, {}, table, exists);
|
|
3775
|
+
instance.timestamps = instance.hasTimestampAttributes(attributes);
|
|
3776
|
+
instance.attributes = attributes;
|
|
3777
|
+
instance.exists = exists;
|
|
3778
|
+
return instance;
|
|
3779
|
+
}
|
|
3780
|
+
static fromAttributes(parent, attributes, table, exists = false) {
|
|
3781
|
+
const instance = new this();
|
|
3782
|
+
instance.timestamps = instance.hasTimestampAttributes(attributes);
|
|
3783
|
+
instance.setConnection(parent.connection).setTable(table).fill(attributes).syncOriginal();
|
|
3784
|
+
instance.pivotParent = parent;
|
|
3785
|
+
instance.exists = exists;
|
|
3786
|
+
return instance;
|
|
3787
|
+
}
|
|
3788
|
+
hasTimestampAttributes(attributes = null) {
|
|
3789
|
+
return (attributes || this.attributes)[this.constructor.CREATED_AT] !== void 0;
|
|
3790
|
+
}
|
|
3791
|
+
};
|
|
3792
|
+
var model_default = Model;
|
|
3793
|
+
|
|
3794
|
+
// src/query-builder.js
|
|
3795
|
+
var QueryBuilder = class _QueryBuilder {
|
|
3796
|
+
connector = null;
|
|
3797
|
+
constructor(config, connector) {
|
|
3798
|
+
this.connector = connector(config);
|
|
3799
|
+
return this.asProxy();
|
|
3800
|
+
}
|
|
3801
|
+
asProxy() {
|
|
3802
|
+
const handler = {
|
|
3803
|
+
get: function(target, prop) {
|
|
3804
|
+
if (typeof target[prop] !== "undefined") {
|
|
3805
|
+
return target[prop];
|
|
3806
|
+
}
|
|
3807
|
+
if (["destroy", "schema"].includes(prop)) {
|
|
3808
|
+
return target.connector.schema;
|
|
3809
|
+
}
|
|
3810
|
+
if ([
|
|
3811
|
+
"select",
|
|
3812
|
+
"from",
|
|
3813
|
+
"where",
|
|
3814
|
+
"orWhere",
|
|
3815
|
+
"whereColumn",
|
|
3816
|
+
"whereRaw",
|
|
3817
|
+
"whereNot",
|
|
3818
|
+
"orWhereNot",
|
|
3819
|
+
"whereIn",
|
|
3820
|
+
"orWhereIn",
|
|
3821
|
+
"whereNotIn",
|
|
3822
|
+
"orWhereNotIn",
|
|
3823
|
+
"whereNull",
|
|
3824
|
+
"orWhereNull",
|
|
3825
|
+
"whereNotNull",
|
|
3826
|
+
"orWhereNotNull",
|
|
3827
|
+
"whereExists",
|
|
3828
|
+
"orWhereExists",
|
|
3829
|
+
"whereNotExists",
|
|
3830
|
+
"orWhereNotExists",
|
|
3831
|
+
"whereBetween",
|
|
3832
|
+
"orWhereBetween",
|
|
3833
|
+
"whereNotBetween",
|
|
3834
|
+
"orWhereNotBetween",
|
|
3835
|
+
"whereLike",
|
|
3836
|
+
"orWhereLike",
|
|
3837
|
+
"whereILike",
|
|
3838
|
+
"orWhereILike",
|
|
3839
|
+
"whereJsonObject",
|
|
3840
|
+
"whereJsonPath",
|
|
3841
|
+
"whereJsonSupersetOf",
|
|
3842
|
+
"whereJsonSubsetOf",
|
|
3843
|
+
"join",
|
|
3844
|
+
"joinRaw",
|
|
3845
|
+
"leftJoin",
|
|
3846
|
+
"leftOuterJoin",
|
|
3847
|
+
"rightJoin",
|
|
3848
|
+
"rightOuterJoin",
|
|
3849
|
+
"crossJoin",
|
|
3850
|
+
"transacting",
|
|
3851
|
+
"groupBy",
|
|
3852
|
+
"groupByRaw",
|
|
3853
|
+
"returning",
|
|
3854
|
+
"having",
|
|
3855
|
+
"havingRaw",
|
|
3856
|
+
"havingBetween",
|
|
3857
|
+
"limit",
|
|
3858
|
+
"offset",
|
|
3859
|
+
"orderBy",
|
|
3860
|
+
"orderByRaw",
|
|
3861
|
+
// 'inRandomOrder',
|
|
3862
|
+
"union",
|
|
3863
|
+
"insert",
|
|
3864
|
+
"forUpdate",
|
|
3865
|
+
"forShare",
|
|
3866
|
+
"distinct",
|
|
3867
|
+
"clearOrder",
|
|
3868
|
+
"clear",
|
|
3869
|
+
"clearSelect",
|
|
3870
|
+
"clearWhere",
|
|
3871
|
+
"clearHaving",
|
|
3872
|
+
"clearGroup"
|
|
3873
|
+
].includes(prop)) {
|
|
3874
|
+
return (...args) => {
|
|
3875
|
+
target.connector[prop](...args);
|
|
3876
|
+
return target.asProxy();
|
|
3877
|
+
};
|
|
3878
|
+
}
|
|
3879
|
+
return target.connector[prop];
|
|
3880
|
+
},
|
|
3881
|
+
set: function(target, prop, value) {
|
|
3882
|
+
if (typeof target[prop] !== "undefined") {
|
|
3883
|
+
target[prop] = value;
|
|
3884
|
+
return target;
|
|
3885
|
+
}
|
|
3886
|
+
target.connector[prop] = value;
|
|
3887
|
+
return target;
|
|
3888
|
+
}
|
|
3889
|
+
};
|
|
3890
|
+
return new Proxy(this, handler);
|
|
3891
|
+
}
|
|
3892
|
+
async beginTransaction() {
|
|
3893
|
+
const trx = await this.connector.transaction();
|
|
3894
|
+
return new _QueryBuilder(null, () => trx);
|
|
3895
|
+
}
|
|
3896
|
+
table(table) {
|
|
3897
|
+
const c = this.connector.table(table);
|
|
3898
|
+
return new _QueryBuilder(null, () => c);
|
|
3899
|
+
}
|
|
3900
|
+
transaction(callback) {
|
|
3901
|
+
if (callback) {
|
|
3902
|
+
return this.connector.transaction((trx) => {
|
|
3903
|
+
return callback(new _QueryBuilder(null, () => trx));
|
|
3904
|
+
});
|
|
3905
|
+
}
|
|
3906
|
+
return callback;
|
|
3907
|
+
}
|
|
3908
|
+
async find(id, columns = ["*"]) {
|
|
3909
|
+
return await this.connector.where("id", id).first(...columns);
|
|
3910
|
+
}
|
|
3911
|
+
async get(columns = ["*"]) {
|
|
3912
|
+
return await this.connector;
|
|
3913
|
+
}
|
|
3914
|
+
async exists() {
|
|
3915
|
+
return await this.connector.first() !== null;
|
|
3916
|
+
}
|
|
3917
|
+
skip(...args) {
|
|
3918
|
+
return this.offset(...args);
|
|
3919
|
+
}
|
|
3920
|
+
take(...args) {
|
|
3921
|
+
return this.limit(...args);
|
|
3922
|
+
}
|
|
3923
|
+
async chunk(count, callback) {
|
|
3924
|
+
if (this.connector._statements.filter((item) => item.grouping === "order").length === 0) {
|
|
3925
|
+
throw new Error("You must specify an orderBy clause when using this function.");
|
|
3926
|
+
}
|
|
3927
|
+
let page = 1;
|
|
3928
|
+
let countResults;
|
|
3929
|
+
do {
|
|
3930
|
+
const builder = this.clone();
|
|
3931
|
+
const results = await builder.forPage(page, count).get();
|
|
3932
|
+
countResults = results.length;
|
|
3933
|
+
if (countResults == 0) {
|
|
3934
|
+
break;
|
|
3935
|
+
}
|
|
3936
|
+
const bool = await callback(results, page);
|
|
3937
|
+
if (bool === false) {
|
|
3938
|
+
return false;
|
|
3939
|
+
}
|
|
3940
|
+
page++;
|
|
3941
|
+
} while (countResults === count);
|
|
3942
|
+
return true;
|
|
3943
|
+
}
|
|
3944
|
+
async paginate(page = 1, perPage = 15) {
|
|
3945
|
+
const query = this.clone();
|
|
3946
|
+
const total = await query.clearOrder().count("*");
|
|
3947
|
+
let results;
|
|
3948
|
+
if (total > 0) {
|
|
3949
|
+
const skip = (page - 1) * perPage;
|
|
3950
|
+
this.take(perPage).skip(skip);
|
|
3951
|
+
results = await this.get();
|
|
3952
|
+
} else {
|
|
3953
|
+
results = [];
|
|
3954
|
+
}
|
|
3955
|
+
return new paginator_default(results, parseInt(total), perPage, page);
|
|
3956
|
+
}
|
|
3957
|
+
forPage(page = 1, perPage = 15) {
|
|
3958
|
+
return this.offset((page - 1) * perPage).limit(perPage);
|
|
3959
|
+
}
|
|
3960
|
+
toSQL(...args) {
|
|
3961
|
+
return this.connector.toSQL(...args);
|
|
3962
|
+
}
|
|
3963
|
+
async count(column) {
|
|
3964
|
+
const [{ aggregate }] = await this.connector.count(column, { as: "aggregate" });
|
|
3965
|
+
return Number(aggregate);
|
|
3966
|
+
}
|
|
3967
|
+
async min(column) {
|
|
3968
|
+
const [{ aggregate }] = await this.connector.min(column, { as: "aggregate" });
|
|
3969
|
+
return Number(aggregate);
|
|
3970
|
+
}
|
|
3971
|
+
async max(column) {
|
|
3972
|
+
const [{ aggregate }] = await this.connector.max(column, { as: "aggregate" });
|
|
3973
|
+
return Number(aggregate);
|
|
3974
|
+
}
|
|
3975
|
+
async sum(column) {
|
|
3976
|
+
const [{ aggregate }] = await this.connector.sum(column, { as: "aggregate" });
|
|
3977
|
+
return Number(aggregate);
|
|
3978
|
+
}
|
|
3979
|
+
async avg(column) {
|
|
3980
|
+
const [{ aggregate }] = await this.connector.avg(column, { as: "aggregate" });
|
|
3981
|
+
return Number(aggregate);
|
|
3982
|
+
}
|
|
3983
|
+
clone() {
|
|
3984
|
+
const c = this.connector.clone();
|
|
3985
|
+
return new _QueryBuilder(null, () => c);
|
|
3986
|
+
}
|
|
3987
|
+
async delete() {
|
|
3988
|
+
return await this.connector.delete();
|
|
3989
|
+
}
|
|
3990
|
+
async insert(...args) {
|
|
3991
|
+
return await this.connector.insert(...args);
|
|
3992
|
+
}
|
|
3993
|
+
async update(...args) {
|
|
3994
|
+
return await this.connector.update(...args);
|
|
3995
|
+
}
|
|
3996
|
+
destroy(...args) {
|
|
3997
|
+
return this.connector.destroy(...args);
|
|
3998
|
+
}
|
|
3999
|
+
get _statements() {
|
|
4000
|
+
return this.connector._statements;
|
|
4001
|
+
}
|
|
4002
|
+
get _single() {
|
|
4003
|
+
return this.connector._single;
|
|
4004
|
+
}
|
|
4005
|
+
get from() {
|
|
4006
|
+
return this.connector.from;
|
|
4007
|
+
}
|
|
4008
|
+
};
|
|
4009
|
+
var query_builder_default = QueryBuilder;
|
|
4010
|
+
|
|
4011
|
+
// src/arquebus.js
|
|
4012
|
+
var arquebus = class _arquebus {
|
|
4013
|
+
static connectorFactory = null;
|
|
4014
|
+
static instance = null;
|
|
4015
|
+
constructor() {
|
|
4016
|
+
this.manager = {};
|
|
4017
|
+
this.connections = {};
|
|
4018
|
+
this.models = {};
|
|
4019
|
+
}
|
|
4020
|
+
static getInstance() {
|
|
4021
|
+
if (this.instance === null) {
|
|
4022
|
+
this.instance = new _arquebus();
|
|
4023
|
+
}
|
|
4024
|
+
return this.instance;
|
|
4025
|
+
}
|
|
4026
|
+
static connection(connection = null) {
|
|
4027
|
+
return this.getInstance().getConnection(connection);
|
|
4028
|
+
}
|
|
4029
|
+
static setConnectorFactory(connectorFactory) {
|
|
4030
|
+
this.connectorFactory = connectorFactory;
|
|
4031
|
+
}
|
|
4032
|
+
static getConnectorFactory() {
|
|
4033
|
+
return this.connectorFactory || Knex;
|
|
4034
|
+
}
|
|
4035
|
+
static addConnection(config, name = "default") {
|
|
4036
|
+
return this.getInstance().addConnection(config, name);
|
|
4037
|
+
}
|
|
4038
|
+
static beginTransaction(connection = null) {
|
|
4039
|
+
return this.getInstance().beginTransaction(connection);
|
|
4040
|
+
}
|
|
4041
|
+
static transaction(callback, connection = null) {
|
|
4042
|
+
return this.getInstance().transaction(callback, connection);
|
|
4043
|
+
}
|
|
4044
|
+
static table(name, connection = null) {
|
|
4045
|
+
return this.getInstance().table(name, connection);
|
|
4046
|
+
}
|
|
4047
|
+
static schema(connection = null) {
|
|
4048
|
+
return this.getInstance().schema(connection);
|
|
4049
|
+
}
|
|
4050
|
+
static async destroyAll() {
|
|
4051
|
+
await this.getInstance().destroyAll();
|
|
4052
|
+
}
|
|
4053
|
+
static createModel(name, options) {
|
|
4054
|
+
return this.getInstance().createModel(name, options);
|
|
4055
|
+
}
|
|
4056
|
+
connection(connection = null) {
|
|
4057
|
+
return this.getConnection(connection);
|
|
4058
|
+
}
|
|
4059
|
+
getConnection(name = null) {
|
|
4060
|
+
name = name || "default";
|
|
4061
|
+
if (this.manager[name] === void 0) {
|
|
4062
|
+
const queryBuilder = new query_builder_default(this.connections[name], this.constructor.getConnectorFactory());
|
|
4063
|
+
this.manager[name] = queryBuilder;
|
|
4064
|
+
}
|
|
4065
|
+
return this.manager[name];
|
|
4066
|
+
}
|
|
4067
|
+
addConnection(config, name = "default") {
|
|
4068
|
+
this.connections[name] = {
|
|
4069
|
+
...config,
|
|
4070
|
+
connection: {
|
|
4071
|
+
...config.connection,
|
|
4072
|
+
dateStrings: true,
|
|
4073
|
+
typeCast: function(field, next) {
|
|
4074
|
+
if (field.type === "JSON") {
|
|
4075
|
+
return field.string("utf8");
|
|
4076
|
+
}
|
|
4077
|
+
return next();
|
|
4078
|
+
}
|
|
4079
|
+
}
|
|
4080
|
+
};
|
|
4081
|
+
}
|
|
4082
|
+
beginTransaction(connection = null) {
|
|
4083
|
+
return this.connection(connection).transaction();
|
|
4084
|
+
}
|
|
4085
|
+
transaction(callback, connection = null) {
|
|
4086
|
+
return this.connection(connection).transaction(callback);
|
|
4087
|
+
}
|
|
4088
|
+
table(name, connection = null) {
|
|
4089
|
+
return this.connection(connection).table(name);
|
|
4090
|
+
}
|
|
4091
|
+
schema(connection = null) {
|
|
4092
|
+
return this.connection(connection).schema;
|
|
4093
|
+
}
|
|
4094
|
+
async destroyAll() {
|
|
4095
|
+
await Promise.all(Object.values(this.manager).map((connection) => {
|
|
4096
|
+
return connection?.destroy();
|
|
4097
|
+
}));
|
|
4098
|
+
}
|
|
4099
|
+
createModel(name, options = {}) {
|
|
4100
|
+
let BaseModel2 = Model;
|
|
4101
|
+
if ("plugins" in options) {
|
|
4102
|
+
BaseModel2 = compose(BaseModel2, ...options.plugins);
|
|
4103
|
+
}
|
|
4104
|
+
this.models = {
|
|
4105
|
+
...this.models,
|
|
4106
|
+
[name]: class extends BaseModel2 {
|
|
4107
|
+
table = options?.table ?? null;
|
|
4108
|
+
connection = options?.connection ?? null;
|
|
4109
|
+
timestamps = options?.timestamps ?? true;
|
|
4110
|
+
primaryKey = options?.primaryKey ?? "id";
|
|
4111
|
+
keyType = options?.keyType ?? "int";
|
|
4112
|
+
incrementing = options?.incrementing ?? true;
|
|
4113
|
+
with = options?.with ?? [];
|
|
4114
|
+
casts = options?.casts ?? {};
|
|
4115
|
+
static CREATED_AT = options?.CREATED_AT ?? "created_at";
|
|
4116
|
+
static UPDATED_AT = options?.UPDATED_AT ?? "updated_at";
|
|
4117
|
+
static DELETED_AT = options?.DELETED_AT ?? "deleted_at";
|
|
4118
|
+
}
|
|
4119
|
+
};
|
|
4120
|
+
if ("attributes" in options) {
|
|
4121
|
+
for (const attribute in options.attributes) {
|
|
4122
|
+
if (options.attributes[attribute] instanceof attribute_default === false) {
|
|
4123
|
+
throw new Error('Attribute must be an instance of "Attribute"');
|
|
4124
|
+
}
|
|
4125
|
+
this.models[name].prototype[getAttrMethod(attribute)] = () => options.attributes[attribute];
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
if ("relations" in options) {
|
|
4129
|
+
for (const relation in options.relations) {
|
|
4130
|
+
this.models[name].prototype[getRelationMethod(relation)] = function() {
|
|
4131
|
+
return options.relations[relation](this);
|
|
4132
|
+
};
|
|
4133
|
+
}
|
|
4134
|
+
}
|
|
4135
|
+
if ("scopes" in options) {
|
|
4136
|
+
for (const scope in options.scopes) {
|
|
4137
|
+
this.models[name].prototype[getScopeMethod(scope)] = options.scopes[scope];
|
|
4138
|
+
}
|
|
4139
|
+
}
|
|
4140
|
+
this.models[name].setConnectionResolver(this);
|
|
4141
|
+
return this.models[name];
|
|
4142
|
+
}
|
|
4143
|
+
};
|
|
4144
|
+
var arquebus_default = arquebus;
|
|
4145
|
+
|
|
4146
|
+
// bin/utils.js
|
|
4147
|
+
import * as color2 from "colorette";
|
|
4148
|
+
import escalade from "escalade/sync";
|
|
4149
|
+
import path2 from "path";
|
|
4150
|
+
import resolveFrom from "resolve-from";
|
|
4151
|
+
var join = path2.join;
|
|
4152
|
+
async function getMigrationPaths(cwd, migrator, defaultPath, path3) {
|
|
4153
|
+
if (path3) {
|
|
4154
|
+
return [join(cwd, path3)];
|
|
4155
|
+
}
|
|
4156
|
+
return [
|
|
4157
|
+
...migrator.getPaths(),
|
|
4158
|
+
join(cwd, defaultPath)
|
|
4159
|
+
];
|
|
4160
|
+
}
|
|
4161
|
+
|
|
4162
|
+
// src/migrate.js
|
|
4163
|
+
async function prepareDatabase(migrator) {
|
|
4164
|
+
const exists = await migrator.repositoryExists();
|
|
4165
|
+
if (!exists) {
|
|
4166
|
+
console.log("Preparing database.");
|
|
4167
|
+
console.log("Creating migration table...");
|
|
4168
|
+
await migrator.repository.createRepository();
|
|
4169
|
+
console.log("Migration table created successfully.");
|
|
4170
|
+
}
|
|
4171
|
+
}
|
|
4172
|
+
async function setupConnection(config) {
|
|
4173
|
+
const table = config?.migration?.table || "migrations";
|
|
4174
|
+
arquebus_default.addConnection(config, "default");
|
|
4175
|
+
Object.entries(config.connections || {}).forEach(([name, connection]) => {
|
|
4176
|
+
arquebus_default.addConnection(connection, name);
|
|
4177
|
+
});
|
|
4178
|
+
const repository = new migration_repository_default(arquebus_default, table);
|
|
4179
|
+
const migrator = new migrator_default(repository, arquebus_default);
|
|
4180
|
+
return { arquebus: arquebus_default, migrator };
|
|
4181
|
+
}
|
|
4182
|
+
async function migrateRun(config, options = {}, destroyAll = false) {
|
|
4183
|
+
const { arquebus: arquebus2, migrator } = await setupConnection(config);
|
|
4184
|
+
await prepareDatabase(migrator);
|
|
4185
|
+
const paths = await getMigrationPaths(process.cwd(), migrator, config?.migrations?.path, options.path);
|
|
4186
|
+
await migrator.setOutput(true).run(paths, {
|
|
4187
|
+
step: options.step,
|
|
4188
|
+
pretend: options.pretend
|
|
4189
|
+
});
|
|
4190
|
+
if (destroyAll) {
|
|
4191
|
+
await arquebus2.destroyAll();
|
|
4192
|
+
}
|
|
4193
|
+
}
|
|
4194
|
+
async function migrateRollback(config, options = {}, destroyAll = false) {
|
|
4195
|
+
const { arquebus: arquebus2, migrator } = await setupConnection(config);
|
|
4196
|
+
const paths = await getMigrationPaths(process.cwd(), migrator, config?.migrations?.path, options.path);
|
|
4197
|
+
await migrator.setOutput(true).rollback(paths, {
|
|
4198
|
+
step: options.step || 0,
|
|
4199
|
+
pretend: options.pretend,
|
|
4200
|
+
batch: options.batch || 0
|
|
4201
|
+
});
|
|
4202
|
+
if (destroyAll) {
|
|
4203
|
+
await arquebus2.destroyAll();
|
|
4204
|
+
}
|
|
4205
|
+
}
|
|
4206
|
+
async function migrateStatus(config, options = {}, destroyAll = false) {
|
|
4207
|
+
const { arquebus: arquebus2, migrator } = await setupConnection(config);
|
|
4208
|
+
async function getAllMigrationFiles() {
|
|
4209
|
+
return await migrator.getMigrationFiles(await getMigrationPaths(process.cwd(), migrator, config?.migrations?.path, options.path));
|
|
4210
|
+
}
|
|
4211
|
+
async function getStatusFor(ran2, batches2) {
|
|
4212
|
+
const files = await getAllMigrationFiles();
|
|
4213
|
+
return Object.values(files).map(function(migration) {
|
|
4214
|
+
const migrationName = migrator.getMigrationName(migration);
|
|
4215
|
+
const status = {
|
|
4216
|
+
name: migrationName,
|
|
4217
|
+
ran: ran2.includes(migrationName),
|
|
4218
|
+
batch: ran2.includes(migrationName) ? batches2[migrationName] : null
|
|
4219
|
+
};
|
|
4220
|
+
return status;
|
|
4221
|
+
});
|
|
4222
|
+
}
|
|
4223
|
+
const exists = await migrator.repositoryExists();
|
|
4224
|
+
if (!exists) {
|
|
4225
|
+
throw new Error("Migration table does not exist.");
|
|
4226
|
+
}
|
|
4227
|
+
const ran = await migrator.repository.getRan();
|
|
4228
|
+
const batches = await migrator.getRepository().getMigrationBatches();
|
|
4229
|
+
const migrations = await getStatusFor(ran, batches);
|
|
4230
|
+
if (destroyAll) {
|
|
4231
|
+
await arquebus2.destroyAll();
|
|
4232
|
+
}
|
|
4233
|
+
return migrations;
|
|
4234
|
+
}
|
|
4235
|
+
|
|
4236
|
+
// src/concerns/has-unique-ids.js
|
|
4237
|
+
var HasUniqueIds = (Model2) => {
|
|
4238
|
+
return class extends Model2 {
|
|
4239
|
+
useUniqueIds = true;
|
|
4240
|
+
uniqueIds() {
|
|
4241
|
+
return [this.getKeyName()];
|
|
4242
|
+
}
|
|
4243
|
+
getKeyType() {
|
|
4244
|
+
if (this.uniqueIds().includes(this.getKeyName())) {
|
|
4245
|
+
return "string";
|
|
4246
|
+
}
|
|
4247
|
+
return this.keyType;
|
|
4248
|
+
}
|
|
4249
|
+
getIncrementing() {
|
|
4250
|
+
if (this.uniqueIds().includes(this.getKeyName())) {
|
|
4251
|
+
return false;
|
|
4252
|
+
}
|
|
4253
|
+
return this.incrementing;
|
|
4254
|
+
}
|
|
4255
|
+
};
|
|
4256
|
+
};
|
|
4257
|
+
var has_unique_ids_default = HasUniqueIds;
|
|
4258
|
+
|
|
4259
|
+
// src/migrations/migration.js
|
|
4260
|
+
var Migration = class {
|
|
4261
|
+
connection;
|
|
4262
|
+
withinTransaction = true;
|
|
4263
|
+
getConnection() {
|
|
4264
|
+
return this.connection;
|
|
4265
|
+
}
|
|
4266
|
+
};
|
|
4267
|
+
var migration_default = Migration;
|
|
4268
|
+
|
|
4269
|
+
// src/pivot.js
|
|
4270
|
+
var pivot_default = Pivot;
|
|
4271
|
+
|
|
4272
|
+
// src/soft-deleting-scope.js
|
|
4273
|
+
var hasJoins = (statements) => {
|
|
4274
|
+
for (const statement of statements) {
|
|
4275
|
+
if (statement?.grouping === "join") {
|
|
4276
|
+
return true;
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
return false;
|
|
4280
|
+
};
|
|
4281
|
+
var SoftDeletingScope = class extends scope_default {
|
|
4282
|
+
extensions = ["Restore", "RestoreOrCreate", "CreateOrRestore", "WithTrashed", "WithoutTrashed", "OnlyTrashed"];
|
|
4283
|
+
apply(builder, model) {
|
|
4284
|
+
builder.whereNull(model.getQualifiedDeletedAtColumn());
|
|
4285
|
+
}
|
|
4286
|
+
extend(builder) {
|
|
4287
|
+
for (const extension of this.extensions) {
|
|
4288
|
+
this[`add${extension}`](builder);
|
|
4289
|
+
}
|
|
4290
|
+
builder.onDelete(async (builder2) => {
|
|
4291
|
+
const column = this.getDeletedAtColumn(builder2);
|
|
4292
|
+
return await builder2.update({
|
|
4293
|
+
[column]: builder2.getModel().freshTimestampString()
|
|
4294
|
+
});
|
|
4295
|
+
});
|
|
4296
|
+
}
|
|
4297
|
+
getDeletedAtColumn(builder) {
|
|
4298
|
+
if (hasJoins(builder.getQuery()._statements)) {
|
|
4299
|
+
return builder.getModel().getQualifiedDeletedAtColumn();
|
|
4300
|
+
}
|
|
4301
|
+
return builder.getModel().getDeletedAtColumn();
|
|
4302
|
+
}
|
|
4303
|
+
addRestore(builder) {
|
|
4304
|
+
builder.macro("restore", (builder2) => {
|
|
4305
|
+
builder2.withTrashed();
|
|
4306
|
+
return builder2.update({
|
|
4307
|
+
[builder2.getModel().getDeletedAtColumn()]: null
|
|
4308
|
+
});
|
|
4309
|
+
});
|
|
4310
|
+
}
|
|
4311
|
+
addRestoreOrCreate(builder) {
|
|
4312
|
+
builder.macro("restoreOrCreate", async (builder2, attributes = {}, values = {}) => {
|
|
4313
|
+
builder2.withTrashed();
|
|
4314
|
+
return tap(await builder2.firstOrCreate(attributes, values), async (instance) => {
|
|
4315
|
+
await instance.restore();
|
|
4316
|
+
});
|
|
4317
|
+
});
|
|
4318
|
+
}
|
|
4319
|
+
addCreateOrRestore(builder) {
|
|
4320
|
+
builder.macro("createOrRestore", async (builder2, attributes = {}, values = {}) => {
|
|
4321
|
+
builder2.withTrashed();
|
|
4322
|
+
return tap(await builder2.createOrFirst(attributes, values), async (instance) => {
|
|
4323
|
+
await instance.restore();
|
|
4324
|
+
});
|
|
4325
|
+
});
|
|
4326
|
+
}
|
|
4327
|
+
addWithTrashed(builder) {
|
|
4328
|
+
builder.macro("withTrashed", (builder2, withTrashed = true) => {
|
|
4329
|
+
if (!withTrashed) {
|
|
4330
|
+
return builder2.withoutTrashed();
|
|
4331
|
+
}
|
|
4332
|
+
return builder2.withoutGlobalScope(this);
|
|
4333
|
+
});
|
|
4334
|
+
}
|
|
4335
|
+
addWithoutTrashed(builder) {
|
|
4336
|
+
builder.macro("withoutTrashed", (builder2) => {
|
|
4337
|
+
const model = builder2.getModel();
|
|
4338
|
+
builder2.withoutGlobalScope(this).whereNull(model.getQualifiedDeletedAtColumn());
|
|
4339
|
+
return builder2;
|
|
4340
|
+
});
|
|
4341
|
+
}
|
|
4342
|
+
addOnlyTrashed(builder) {
|
|
4343
|
+
builder.macro("onlyTrashed", (builder2) => {
|
|
4344
|
+
const model = builder2.getModel();
|
|
4345
|
+
builder2.withoutGlobalScope(this).whereNotNull(model.getQualifiedDeletedAtColumn());
|
|
4346
|
+
return builder2;
|
|
4347
|
+
});
|
|
4348
|
+
}
|
|
4349
|
+
};
|
|
4350
|
+
var soft_deleting_scope_default = SoftDeletingScope;
|
|
4351
|
+
|
|
4352
|
+
// src/soft-deletes.js
|
|
4353
|
+
import { isNullish } from "radashi";
|
|
4354
|
+
var softDeletes = (Model2) => {
|
|
4355
|
+
return class extends Model2 {
|
|
4356
|
+
forceDeleting = false;
|
|
4357
|
+
static bootSoftDeletes() {
|
|
4358
|
+
this.addGlobalScope(new soft_deleting_scope_default());
|
|
4359
|
+
}
|
|
4360
|
+
initialize() {
|
|
4361
|
+
super.initialize();
|
|
4362
|
+
this.constructor.bootSoftDeletes();
|
|
4363
|
+
this.addPluginInitializer("initializeSoftDeletes");
|
|
4364
|
+
}
|
|
4365
|
+
initializeSoftDeletes() {
|
|
4366
|
+
if (this.casts[this.getDeletedAtColumn()] === void 0) {
|
|
4367
|
+
this.casts[this.getDeletedAtColumn()] = "datetime";
|
|
4368
|
+
}
|
|
4369
|
+
}
|
|
4370
|
+
async forceDelete() {
|
|
4371
|
+
if (this.execHooks("forceDeleting") === false) {
|
|
4372
|
+
return false;
|
|
4373
|
+
}
|
|
4374
|
+
this.forceDeleting = true;
|
|
4375
|
+
return tap(await this.delete(), (deleted) => {
|
|
4376
|
+
this.forceDeleting = false;
|
|
4377
|
+
if (deleted) {
|
|
4378
|
+
this.execHooks("forceDeleted", false);
|
|
4379
|
+
}
|
|
4380
|
+
});
|
|
4381
|
+
}
|
|
4382
|
+
forceDeleteQuietly() {
|
|
4383
|
+
return this.withoutEvents(() => this.forceDelete());
|
|
4384
|
+
}
|
|
4385
|
+
async performDeleteOnModel(options = {}) {
|
|
4386
|
+
if (this.forceDeleting) {
|
|
4387
|
+
return tap(await this.setKeysForSaveQuery(this.newModelQuery()).forceDelete(), () => {
|
|
4388
|
+
this.exists = false;
|
|
4389
|
+
});
|
|
4390
|
+
}
|
|
4391
|
+
return await this.runSoftDelete(options);
|
|
4392
|
+
}
|
|
4393
|
+
async runSoftDelete(options = {}) {
|
|
4394
|
+
const query = this.setKeysForSaveQuery(this.newModelQuery());
|
|
4395
|
+
const time = this.freshTimestamp();
|
|
4396
|
+
const columns = {
|
|
4397
|
+
[this.getDeletedAtColumn()]: this.fromDateTime(time)
|
|
4398
|
+
};
|
|
4399
|
+
this[this.getDeletedAtColumn()] = time;
|
|
4400
|
+
if (this.usesTimestamps() && this.getUpdatedAtColumn()) {
|
|
4401
|
+
this[this.getUpdatedAtColumn()] = time;
|
|
4402
|
+
columns[this.getUpdatedAtColumn()] = this.fromDateTime(time);
|
|
4403
|
+
}
|
|
4404
|
+
await query.update(columns);
|
|
4405
|
+
this.syncOriginalAttributes(Object.keys(columns));
|
|
4406
|
+
this.execHooks("trashed", options);
|
|
4407
|
+
}
|
|
4408
|
+
async restore(options = {}) {
|
|
4409
|
+
if (this.execHooks("restoring", options) === false) {
|
|
4410
|
+
return false;
|
|
4411
|
+
}
|
|
4412
|
+
this[this.getDeletedAtColumn()] = null;
|
|
4413
|
+
this.exists = true;
|
|
4414
|
+
const result = await this.save();
|
|
4415
|
+
this.execHooks("restored", options);
|
|
4416
|
+
return result;
|
|
4417
|
+
}
|
|
4418
|
+
restoreQuietly() {
|
|
4419
|
+
return this.withoutEvents(() => this.restore());
|
|
4420
|
+
}
|
|
4421
|
+
trashed() {
|
|
4422
|
+
return !isNullish(this[this.getDeletedAtColumn()]);
|
|
4423
|
+
}
|
|
4424
|
+
static softDeleted(callback) {
|
|
4425
|
+
this.addHook("trashed", callback);
|
|
4426
|
+
}
|
|
4427
|
+
static restoring(callback) {
|
|
4428
|
+
this.addHook("restoring", callback);
|
|
4429
|
+
}
|
|
4430
|
+
static restored(callback) {
|
|
4431
|
+
this.addHook("restored", callback);
|
|
4432
|
+
}
|
|
4433
|
+
static forceDeleting(callback) {
|
|
4434
|
+
this.addHook("forceDeleting", callback);
|
|
4435
|
+
}
|
|
4436
|
+
static forceDeleted(callback) {
|
|
4437
|
+
this.addHook("forceDeleted", callback);
|
|
4438
|
+
}
|
|
4439
|
+
isForceDeleting() {
|
|
4440
|
+
return this.forceDeleting;
|
|
4441
|
+
}
|
|
4442
|
+
getDeletedAtColumn() {
|
|
4443
|
+
return this.constructor.DELETED_AT || "deleted_at";
|
|
4444
|
+
}
|
|
4445
|
+
getQualifiedDeletedAtColumn() {
|
|
4446
|
+
return this.qualifyColumn(this.getDeletedAtColumn());
|
|
4447
|
+
}
|
|
4448
|
+
};
|
|
4449
|
+
};
|
|
4450
|
+
var soft_deletes_default = softDeletes;
|
|
4451
|
+
|
|
4452
|
+
// src/index.js
|
|
4453
|
+
var make = (model, data, options = {}) => {
|
|
4454
|
+
const { paginated } = options;
|
|
4455
|
+
if (paginated) {
|
|
4456
|
+
return new paginator_default(
|
|
4457
|
+
data.data.map((item) => model.make(item)),
|
|
4458
|
+
data.total,
|
|
4459
|
+
data.per_page,
|
|
4460
|
+
data.current_page
|
|
4461
|
+
);
|
|
4462
|
+
}
|
|
4463
|
+
if (Array.isArray(data)) {
|
|
4464
|
+
return new collection_default(data.map((item) => model.make(item)));
|
|
4465
|
+
}
|
|
4466
|
+
return model.make(data);
|
|
4467
|
+
};
|
|
4468
|
+
var makeCollection = (model, data) => new collection_default(data.map((item) => model.make(item)));
|
|
4469
|
+
var makePaginator = (model, data) => new paginator_default(
|
|
4470
|
+
data.data.map((item) => model.make(item)),
|
|
4471
|
+
data.total,
|
|
4472
|
+
data.per_page,
|
|
4473
|
+
data.current_page
|
|
4474
|
+
);
|
|
4475
|
+
export {
|
|
4476
|
+
attribute_default as Attribute,
|
|
4477
|
+
builder_default as Builder,
|
|
4478
|
+
casts_attributes_default as CastsAttributes,
|
|
4479
|
+
collection_default as Collection,
|
|
4480
|
+
has_unique_ids_default as HasUniqueIds,
|
|
4481
|
+
InvalidArgumentError,
|
|
4482
|
+
migration_default as Migration,
|
|
4483
|
+
model_default as Model,
|
|
4484
|
+
ModelNotFoundError2 as ModelNotFoundError,
|
|
4485
|
+
paginator_default as Paginator,
|
|
4486
|
+
pivot_default as Pivot,
|
|
4487
|
+
query_builder_default as QueryBuilder,
|
|
4488
|
+
RelationNotFoundError,
|
|
4489
|
+
scope_default as Scope,
|
|
4490
|
+
soft_deletes_default as SoftDeletes,
|
|
4491
|
+
arquebus_default as arquebus,
|
|
4492
|
+
compose,
|
|
4493
|
+
flattenDeep,
|
|
4494
|
+
getAttrMethod,
|
|
4495
|
+
getAttrName,
|
|
4496
|
+
getGetterMethod,
|
|
4497
|
+
getRelationMethod,
|
|
4498
|
+
getRelationName,
|
|
4499
|
+
getScopeMethod,
|
|
4500
|
+
getScopeName,
|
|
4501
|
+
getSetterMethod,
|
|
4502
|
+
kebabCase,
|
|
4503
|
+
make,
|
|
4504
|
+
makeCollection,
|
|
4505
|
+
makePaginator,
|
|
4506
|
+
migrateRollback,
|
|
4507
|
+
migrateRun,
|
|
4508
|
+
migrateStatus,
|
|
4509
|
+
now,
|
|
4510
|
+
snakeCase,
|
|
4511
|
+
tap
|
|
4512
|
+
};
|
|
4513
|
+
//# sourceMappingURL=index.js.map
|