pinia-orm-edge 1.7.3-28257628.bbb8bab
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 +96 -0
- package/dist/casts.cjs +124 -0
- package/dist/casts.d.cts +66 -0
- package/dist/casts.d.mts +66 -0
- package/dist/casts.d.ts +66 -0
- package/dist/casts.mjs +118 -0
- package/dist/decorators.cjs +219 -0
- package/dist/decorators.d.cts +107 -0
- package/dist/decorators.d.mts +107 -0
- package/dist/decorators.d.ts +107 -0
- package/dist/decorators.mjs +198 -0
- package/dist/helpers.cjs +69 -0
- package/dist/helpers.d.cts +54 -0
- package/dist/helpers.d.mts +54 -0
- package/dist/helpers.d.ts +54 -0
- package/dist/helpers.mjs +61 -0
- package/dist/index.cjs +3592 -0
- package/dist/index.d.cts +49 -0
- package/dist/index.d.mts +49 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.mjs +3561 -0
- package/dist/nanoid/async.cjs +42 -0
- package/dist/nanoid/async.d.cts +29 -0
- package/dist/nanoid/async.d.mts +29 -0
- package/dist/nanoid/async.d.ts +29 -0
- package/dist/nanoid/async.mjs +39 -0
- package/dist/nanoid/index.cjs +42 -0
- package/dist/nanoid/index.d.cts +24 -0
- package/dist/nanoid/index.d.mts +24 -0
- package/dist/nanoid/index.d.ts +24 -0
- package/dist/nanoid/index.mjs +39 -0
- package/dist/nanoid/non-secure.cjs +42 -0
- package/dist/nanoid/non-secure.d.cts +24 -0
- package/dist/nanoid/non-secure.d.mts +24 -0
- package/dist/nanoid/non-secure.d.ts +24 -0
- package/dist/nanoid/non-secure.mjs +39 -0
- package/dist/shared/pinia-orm.1bd7d299.mjs +153 -0
- package/dist/shared/pinia-orm.4ff2e12f.mjs +66 -0
- package/dist/shared/pinia-orm.876a7cdc.d.cts +1981 -0
- package/dist/shared/pinia-orm.876a7cdc.d.mts +1981 -0
- package/dist/shared/pinia-orm.876a7cdc.d.ts +1981 -0
- package/dist/shared/pinia-orm.a62c4fc4.cjs +167 -0
- package/dist/shared/pinia-orm.a7e3e0f3.cjs +68 -0
- package/dist/uuid/v1.cjs +41 -0
- package/dist/uuid/v1.d.cts +25 -0
- package/dist/uuid/v1.d.mts +25 -0
- package/dist/uuid/v1.d.ts +25 -0
- package/dist/uuid/v1.mjs +38 -0
- package/dist/uuid/v4.cjs +41 -0
- package/dist/uuid/v4.d.cts +25 -0
- package/dist/uuid/v4.d.mts +25 -0
- package/dist/uuid/v4.d.ts +25 -0
- package/dist/uuid/v4.mjs +38 -0
- package/package.json +126 -0
package/dist/index.cjs
ADDED
@@ -0,0 +1,3592 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const Utils = require('./shared/pinia-orm.a62c4fc4.cjs');
|
4
|
+
const pinia = require('pinia');
|
5
|
+
const normalizr = require('@pinia-orm/normalizr');
|
6
|
+
const CastAttribute = require('./shared/pinia-orm.a7e3e0f3.cjs');
|
7
|
+
|
8
|
+
var __defProp$k = Object.defineProperty;
|
9
|
+
var __defNormalProp$k = (obj, key, value) => key in obj ? __defProp$k(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
10
|
+
var __publicField$k = (obj, key, value) => {
|
11
|
+
__defNormalProp$k(obj, typeof key !== "symbol" ? key + "" : key, value);
|
12
|
+
return value;
|
13
|
+
};
|
14
|
+
class Attribute {
|
15
|
+
/**
|
16
|
+
* Create a new Attribute instance.
|
17
|
+
*/
|
18
|
+
constructor(model) {
|
19
|
+
/**
|
20
|
+
* The model instance.
|
21
|
+
*/
|
22
|
+
__publicField$k(this, "model");
|
23
|
+
/**
|
24
|
+
* The field name
|
25
|
+
*/
|
26
|
+
__publicField$k(this, "key");
|
27
|
+
this.model = model;
|
28
|
+
this.key = "";
|
29
|
+
}
|
30
|
+
/**
|
31
|
+
* Set the key name of the field
|
32
|
+
*/
|
33
|
+
setKey(key) {
|
34
|
+
this.key = key;
|
35
|
+
return this;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
var __defProp$j = Object.defineProperty;
|
40
|
+
var __defNormalProp$j = (obj, key, value) => key in obj ? __defProp$j(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
41
|
+
var __publicField$j = (obj, key, value) => {
|
42
|
+
__defNormalProp$j(obj, typeof key !== "symbol" ? key + "" : key, value);
|
43
|
+
return value;
|
44
|
+
};
|
45
|
+
class Relation extends Attribute {
|
46
|
+
/**
|
47
|
+
* Create a new relation instance.
|
48
|
+
*/
|
49
|
+
constructor(parent, related) {
|
50
|
+
super(parent);
|
51
|
+
/**
|
52
|
+
* The parent model.
|
53
|
+
*/
|
54
|
+
__publicField$j(this, "parent");
|
55
|
+
/**
|
56
|
+
* The related model.
|
57
|
+
*/
|
58
|
+
__publicField$j(this, "related");
|
59
|
+
/**
|
60
|
+
* The delete mode
|
61
|
+
*/
|
62
|
+
__publicField$j(this, "onDeleteMode");
|
63
|
+
this.parent = parent;
|
64
|
+
this.related = related;
|
65
|
+
}
|
66
|
+
/**
|
67
|
+
* Get the related model of the relation.
|
68
|
+
*/
|
69
|
+
getRelated() {
|
70
|
+
return this.related;
|
71
|
+
}
|
72
|
+
/**
|
73
|
+
* Get all of the primary keys for an array of models.
|
74
|
+
*/
|
75
|
+
getKeys(models, key) {
|
76
|
+
return models.map((model) => model[key]);
|
77
|
+
}
|
78
|
+
/**
|
79
|
+
* Specify how this model should behave on delete
|
80
|
+
*/
|
81
|
+
onDelete(mode) {
|
82
|
+
this.onDeleteMode = mode;
|
83
|
+
return this;
|
84
|
+
}
|
85
|
+
/**
|
86
|
+
* Run a dictionary map over the items.
|
87
|
+
*/
|
88
|
+
mapToDictionary(models, callback) {
|
89
|
+
return models.reduce((dictionary, model) => {
|
90
|
+
const [key, value] = callback(model);
|
91
|
+
if (!dictionary[key]) {
|
92
|
+
dictionary[key] = [];
|
93
|
+
}
|
94
|
+
dictionary[key].push(value);
|
95
|
+
return dictionary;
|
96
|
+
}, {});
|
97
|
+
}
|
98
|
+
/**
|
99
|
+
* Call a function for a current key match
|
100
|
+
*/
|
101
|
+
compositeKeyMapper(foreignKey, localKey, call) {
|
102
|
+
if (Utils.isArray(foreignKey) && Utils.isArray(localKey)) {
|
103
|
+
foreignKey.forEach((key, index) => {
|
104
|
+
call(key, localKey[index]);
|
105
|
+
});
|
106
|
+
} else if (!Utils.isArray(localKey) && !Utils.isArray(foreignKey)) {
|
107
|
+
call(foreignKey, localKey);
|
108
|
+
} else {
|
109
|
+
Utils.throwError([
|
110
|
+
"This relation cant be resolve. Either child or parent doesnt have different key types (composite)",
|
111
|
+
JSON.stringify(foreignKey),
|
112
|
+
JSON.stringify(localKey)
|
113
|
+
]);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
/**
|
117
|
+
* Get the index key defined by the primary key or keys (composite)
|
118
|
+
*/
|
119
|
+
getKey(key) {
|
120
|
+
return Utils.isArray(key) ? `[${key.join(",")}]` : key;
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
var __defProp$i = Object.defineProperty;
|
125
|
+
var __defNormalProp$i = (obj, key, value) => key in obj ? __defProp$i(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
126
|
+
var __publicField$i = (obj, key, value) => {
|
127
|
+
__defNormalProp$i(obj, typeof key !== "symbol" ? key + "" : key, value);
|
128
|
+
return value;
|
129
|
+
};
|
130
|
+
class MorphTo extends Relation {
|
131
|
+
/**
|
132
|
+
* Create a new morph-to relation instance.
|
133
|
+
*/
|
134
|
+
constructor(parent, relatedModels, morphId, morphType, ownerKey) {
|
135
|
+
super(parent, parent);
|
136
|
+
/**
|
137
|
+
* The related models.
|
138
|
+
*/
|
139
|
+
__publicField$i(this, "relatedModels");
|
140
|
+
/**
|
141
|
+
* The related model dictionary.
|
142
|
+
*/
|
143
|
+
__publicField$i(this, "relatedTypes");
|
144
|
+
/**
|
145
|
+
* The field name that contains id of the parent model.
|
146
|
+
*/
|
147
|
+
__publicField$i(this, "morphId");
|
148
|
+
/**
|
149
|
+
* The field name that contains type of the parent model.
|
150
|
+
*/
|
151
|
+
__publicField$i(this, "morphType");
|
152
|
+
/**
|
153
|
+
* The associated key of the child model.
|
154
|
+
*/
|
155
|
+
__publicField$i(this, "ownerKey");
|
156
|
+
this.relatedModels = relatedModels;
|
157
|
+
this.relatedTypes = this.createRelatedTypes(relatedModels);
|
158
|
+
this.morphId = morphId;
|
159
|
+
this.morphType = morphType;
|
160
|
+
this.ownerKey = ownerKey;
|
161
|
+
}
|
162
|
+
/**
|
163
|
+
* Create a dictionary of relations keyed by their entity.
|
164
|
+
*/
|
165
|
+
createRelatedTypes(models) {
|
166
|
+
return models.reduce((types, model) => {
|
167
|
+
types[model.$entity()] = model;
|
168
|
+
return types;
|
169
|
+
}, {});
|
170
|
+
}
|
171
|
+
/**
|
172
|
+
* Get the type field name.
|
173
|
+
*/
|
174
|
+
getType() {
|
175
|
+
return this.morphType;
|
176
|
+
}
|
177
|
+
/**
|
178
|
+
* Get all related models for the relationship.
|
179
|
+
*/
|
180
|
+
getRelateds() {
|
181
|
+
return this.relatedModels;
|
182
|
+
}
|
183
|
+
/**
|
184
|
+
* Define the normalizr schema for the relation.
|
185
|
+
*/
|
186
|
+
define(schema) {
|
187
|
+
return schema.union(this.relatedModels, (value, parent, _key) => {
|
188
|
+
const type = parent[this.morphType];
|
189
|
+
const model = this.relatedTypes[type];
|
190
|
+
const key = this.ownerKey || model.$getKeyName();
|
191
|
+
parent[this.morphId] = value[key];
|
192
|
+
return type;
|
193
|
+
});
|
194
|
+
}
|
195
|
+
/**
|
196
|
+
* Attach the relational key to the given record. Since morph-to relationship
|
197
|
+
* doesn't have any foreign key, it would do nothing.
|
198
|
+
*/
|
199
|
+
attach(_record, _child) {
|
200
|
+
}
|
201
|
+
/**
|
202
|
+
* Add eager constraints. Since we do not know the related model ahead of time,
|
203
|
+
* we cannot add any eager constraints.
|
204
|
+
*/
|
205
|
+
addEagerConstraints(_query, _models) {
|
206
|
+
}
|
207
|
+
/**
|
208
|
+
* Find and attach related children to their respective parents.
|
209
|
+
*/
|
210
|
+
match(relation, models, query) {
|
211
|
+
const dictionary = this.buildDictionary(query, models);
|
212
|
+
models.forEach((model) => {
|
213
|
+
const type = model[this.morphType];
|
214
|
+
const id = model[this.morphId];
|
215
|
+
const related = dictionary[type]?.[id] ?? null;
|
216
|
+
model.$setRelation(relation, related);
|
217
|
+
});
|
218
|
+
}
|
219
|
+
/**
|
220
|
+
* Make a related model.
|
221
|
+
*/
|
222
|
+
make(element, type) {
|
223
|
+
if (!element || !type) {
|
224
|
+
return null;
|
225
|
+
}
|
226
|
+
return this.relatedTypes[type].$newInstance(element);
|
227
|
+
}
|
228
|
+
/**
|
229
|
+
* Build model dictionary keyed by the owner key for each entity.
|
230
|
+
*/
|
231
|
+
buildDictionary(query, models) {
|
232
|
+
const keys = this.getKeysByEntity(models);
|
233
|
+
const dictionary = {};
|
234
|
+
for (const entity in keys) {
|
235
|
+
const model = this.relatedTypes[entity];
|
236
|
+
Utils.assert(!!model, [
|
237
|
+
`Trying to load "morph to" relation of \`${entity}\``,
|
238
|
+
"but the model could not be found."
|
239
|
+
]);
|
240
|
+
const ownerKey = this.ownerKey || model.$getKeyName();
|
241
|
+
const results = query.newQueryWithConstraints(entity).whereIn(ownerKey, keys[entity]).get(false);
|
242
|
+
dictionary[entity] = results.reduce(
|
243
|
+
(dic, result) => {
|
244
|
+
dic[result[ownerKey]] = result;
|
245
|
+
return dic;
|
246
|
+
},
|
247
|
+
{}
|
248
|
+
);
|
249
|
+
}
|
250
|
+
return dictionary;
|
251
|
+
}
|
252
|
+
/**
|
253
|
+
* Get the relation's primary keys grouped by its entity.
|
254
|
+
*/
|
255
|
+
getKeysByEntity(models) {
|
256
|
+
return models.reduce((keys, model) => {
|
257
|
+
const type = model[this.morphType];
|
258
|
+
const id = model[this.morphId];
|
259
|
+
if (id !== null && this.relatedTypes[type] !== void 0) {
|
260
|
+
if (!keys[type]) {
|
261
|
+
keys[type] = [];
|
262
|
+
}
|
263
|
+
keys[type].push(id);
|
264
|
+
}
|
265
|
+
return keys;
|
266
|
+
}, {});
|
267
|
+
}
|
268
|
+
}
|
269
|
+
|
270
|
+
var __defProp$h = Object.defineProperty;
|
271
|
+
var __defNormalProp$h = (obj, key, value) => key in obj ? __defProp$h(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
272
|
+
var __publicField$h = (obj, key, value) => {
|
273
|
+
__defNormalProp$h(obj, typeof key !== "symbol" ? key + "" : key, value);
|
274
|
+
return value;
|
275
|
+
};
|
276
|
+
class Type extends Attribute {
|
277
|
+
/**
|
278
|
+
* Create a new Type attribute instance.
|
279
|
+
*/
|
280
|
+
constructor(model, value = null) {
|
281
|
+
super(model);
|
282
|
+
/**
|
283
|
+
* The default value for the attribute.
|
284
|
+
*/
|
285
|
+
__publicField$h(this, "value");
|
286
|
+
/**
|
287
|
+
* Whether the attribute accepts `null` value or not.
|
288
|
+
*/
|
289
|
+
__publicField$h(this, "isNullable", true);
|
290
|
+
this.value = typeof value === "function" ? value() : value;
|
291
|
+
}
|
292
|
+
/**
|
293
|
+
* Set the nullable option to false.
|
294
|
+
*/
|
295
|
+
notNullable() {
|
296
|
+
this.isNullable = false;
|
297
|
+
return this;
|
298
|
+
}
|
299
|
+
makeReturn(type, value) {
|
300
|
+
if (value === void 0) {
|
301
|
+
return this.value;
|
302
|
+
}
|
303
|
+
if (value === null) {
|
304
|
+
if (!this.isNullable) {
|
305
|
+
this.throwWarning(["is set as non nullable!"]);
|
306
|
+
}
|
307
|
+
return value;
|
308
|
+
}
|
309
|
+
if (typeof value !== type) {
|
310
|
+
this.throwWarning([value, "is not a", type]);
|
311
|
+
}
|
312
|
+
return value;
|
313
|
+
}
|
314
|
+
/**
|
315
|
+
* Throw warning for wrong type
|
316
|
+
*/
|
317
|
+
throwWarning(message) {
|
318
|
+
console.warn(["[Pinia ORM]"].concat([`Field ${this.model.$entity()}:${this.key} - `, ...message]).join(" "));
|
319
|
+
}
|
320
|
+
}
|
321
|
+
|
322
|
+
var __defProp$g = Object.defineProperty;
|
323
|
+
var __defNormalProp$g = (obj, key, value) => key in obj ? __defProp$g(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
324
|
+
var __publicField$g = (obj, key, value) => {
|
325
|
+
__defNormalProp$g(obj, typeof key !== "symbol" ? key + "" : key, value);
|
326
|
+
return value;
|
327
|
+
};
|
328
|
+
class Uid extends Type {
|
329
|
+
constructor(model, options = {}) {
|
330
|
+
super(model);
|
331
|
+
__publicField$g(this, "options");
|
332
|
+
// This alphabet uses `A-Za-z0-9_-` symbols.
|
333
|
+
// The order of characters is optimized for better gzip and brotli compression.
|
334
|
+
// References to the same file (works both for gzip and brotli):
|
335
|
+
// `'use`, `andom`, and `rict'`
|
336
|
+
// References to the brotli default dictionary:
|
337
|
+
// `-26T`, `1983`, `40px`, `75px`, `bush`, `jack`, `mind`, `very`, and `wolf`
|
338
|
+
__publicField$g(this, "alphabet", "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict");
|
339
|
+
__publicField$g(this, "size", 21);
|
340
|
+
this.options = typeof options === "number" ? { size: options } : options;
|
341
|
+
this.alphabet = this.options.alphabet ?? this.alphabet;
|
342
|
+
this.size = this.options.size ?? this.size;
|
343
|
+
}
|
344
|
+
/**
|
345
|
+
* Make the value for the attribute.
|
346
|
+
*/
|
347
|
+
make(value) {
|
348
|
+
const uidCast = this.model.$casts()[this.model.$getKeyName()];
|
349
|
+
if (uidCast) {
|
350
|
+
return value ?? uidCast.withParameters(this.options).newRawInstance(this.model.$fields()).set(value);
|
351
|
+
}
|
352
|
+
return value ?? Utils.generateId(this.size, this.alphabet);
|
353
|
+
}
|
354
|
+
}
|
355
|
+
|
356
|
+
var __defProp$f = Object.defineProperty;
|
357
|
+
var __defNormalProp$f = (obj, key, value) => key in obj ? __defProp$f(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
358
|
+
var __publicField$f = (obj, key, value) => {
|
359
|
+
__defNormalProp$f(obj, typeof key !== "symbol" ? key + "" : key, value);
|
360
|
+
return value;
|
361
|
+
};
|
362
|
+
class Schema {
|
363
|
+
/**
|
364
|
+
* Create a new Schema instance.
|
365
|
+
*/
|
366
|
+
constructor(model) {
|
367
|
+
/**
|
368
|
+
* The list of generated schemas.
|
369
|
+
*/
|
370
|
+
__publicField$f(this, "schemas", {});
|
371
|
+
/**
|
372
|
+
* The model instance.
|
373
|
+
*/
|
374
|
+
__publicField$f(this, "model");
|
375
|
+
this.model = model;
|
376
|
+
}
|
377
|
+
/**
|
378
|
+
* Create a single schema.
|
379
|
+
*/
|
380
|
+
one(model, parent) {
|
381
|
+
model = model || this.model;
|
382
|
+
parent = parent || this.model;
|
383
|
+
const entity = `${model.$entity()}${parent.$entity()}`;
|
384
|
+
if (this.schemas[entity]) {
|
385
|
+
return this.schemas[entity];
|
386
|
+
}
|
387
|
+
const schema = this.newEntity(model, parent);
|
388
|
+
this.schemas[entity] = schema;
|
389
|
+
const definition = this.definition(model);
|
390
|
+
schema.define(definition);
|
391
|
+
return schema;
|
392
|
+
}
|
393
|
+
/**
|
394
|
+
* Create an array schema for the given model.
|
395
|
+
*/
|
396
|
+
many(model, parent) {
|
397
|
+
return new normalizr.schema.Array(this.one(model, parent));
|
398
|
+
}
|
399
|
+
/**
|
400
|
+
* Create an union schema for the given models.
|
401
|
+
*/
|
402
|
+
union(models, callback) {
|
403
|
+
const schemas = models.reduce((schemas2, model) => {
|
404
|
+
schemas2[model.$entity()] = this.one(model);
|
405
|
+
return schemas2;
|
406
|
+
}, {});
|
407
|
+
return new normalizr.schema.Union(schemas, callback);
|
408
|
+
}
|
409
|
+
/**
|
410
|
+
* Create a new normalizr entity.
|
411
|
+
*/
|
412
|
+
newEntity(model, parent) {
|
413
|
+
const entity = model.$entity();
|
414
|
+
const idAttribute = this.idAttribute(model, parent);
|
415
|
+
return new normalizr.schema.Entity(entity, {}, { idAttribute });
|
416
|
+
}
|
417
|
+
/**
|
418
|
+
* The `id` attribute option for the normalizr entity.
|
419
|
+
*
|
420
|
+
* Generates any missing primary keys declared by a Uid attribute. Missing
|
421
|
+
* primary keys where the designated attributes do not exist will
|
422
|
+
* throw an error.
|
423
|
+
*
|
424
|
+
* Note that this will only generate uids for primary key attributes since it
|
425
|
+
* is required to generate the "index id" while the other attributes are not.
|
426
|
+
*
|
427
|
+
* It's especially important when attempting to "update" records since we'll
|
428
|
+
* want to retain the missing attributes in-place to prevent them being
|
429
|
+
* overridden by newly generated uid values.
|
430
|
+
*
|
431
|
+
* If uid primary keys are omitted, when invoking the "update" method, it will
|
432
|
+
* fail because the uid values will never exist in the store.
|
433
|
+
*
|
434
|
+
* While it would be nice to throw an error in such a case, instead of
|
435
|
+
* silently failing an update, we don't have a way to detect whether users
|
436
|
+
* are trying to "update" records or "inserting" new records at this stage.
|
437
|
+
* Something to consider for future revisions.
|
438
|
+
*/
|
439
|
+
idAttribute(model, parent) {
|
440
|
+
const uidFields = this.getUidPrimaryKeyPairs(model);
|
441
|
+
return (record, parentRecord, key) => {
|
442
|
+
if (key !== null) {
|
443
|
+
parent.$fields()[key]?.attach(parentRecord, record);
|
444
|
+
}
|
445
|
+
for (const key2 in uidFields) {
|
446
|
+
if (Utils.isNullish(record[key2])) {
|
447
|
+
record[key2] = uidFields[key2].setKey(key2).make(record[key2]);
|
448
|
+
}
|
449
|
+
}
|
450
|
+
if (["BelongsTo", "HasOne", "MorphOne", "MorphTo"].includes(parent.$fields()[key]?.constructor.name ?? "") && Utils.isArray(parentRecord[key])) {
|
451
|
+
Utils.throwError(['You are passing a list to "', `${parent.$entity()}.${key}`, `" which is a one to one Relation(${parent.$fields()[key]?.constructor.name}):`, JSON.stringify(parentRecord[key])]);
|
452
|
+
}
|
453
|
+
const id = model.$getIndexId(record);
|
454
|
+
return id;
|
455
|
+
};
|
456
|
+
}
|
457
|
+
/**
|
458
|
+
* Get all primary keys defined by the Uid attribute for the given model.
|
459
|
+
*/
|
460
|
+
getUidPrimaryKeyPairs(model) {
|
461
|
+
const fields = model.$fields();
|
462
|
+
const key = model.$getKeyName();
|
463
|
+
const keys = Utils.isArray(key) ? key : [key];
|
464
|
+
const attributes = {};
|
465
|
+
keys.forEach((k) => {
|
466
|
+
const attr = fields[k];
|
467
|
+
if (attr instanceof Uid) {
|
468
|
+
attributes[k] = attr;
|
469
|
+
}
|
470
|
+
});
|
471
|
+
return attributes;
|
472
|
+
}
|
473
|
+
/**
|
474
|
+
* Create a definition for the given model.
|
475
|
+
*/
|
476
|
+
definition(model) {
|
477
|
+
const fields = model.$fields();
|
478
|
+
const definition = {};
|
479
|
+
for (const key in fields) {
|
480
|
+
const field = fields[key];
|
481
|
+
if (field instanceof Relation) {
|
482
|
+
definition[key] = field.define(this);
|
483
|
+
}
|
484
|
+
}
|
485
|
+
return definition;
|
486
|
+
}
|
487
|
+
}
|
488
|
+
|
489
|
+
var __defProp$e = Object.defineProperty;
|
490
|
+
var __defNormalProp$e = (obj, key, value) => key in obj ? __defProp$e(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
491
|
+
var __publicField$e = (obj, key, value) => {
|
492
|
+
__defNormalProp$e(obj, typeof key !== "symbol" ? key + "" : key, value);
|
493
|
+
return value;
|
494
|
+
};
|
495
|
+
class Interpreter {
|
496
|
+
/**
|
497
|
+
* Create a new Interpreter instance.
|
498
|
+
*/
|
499
|
+
constructor(model) {
|
500
|
+
/**
|
501
|
+
* The model object.
|
502
|
+
*/
|
503
|
+
__publicField$e(this, "model");
|
504
|
+
this.model = model;
|
505
|
+
}
|
506
|
+
process(data) {
|
507
|
+
const normalizedData = this.normalize(data);
|
508
|
+
return [data, normalizedData];
|
509
|
+
}
|
510
|
+
/**
|
511
|
+
* Normalize the given data.
|
512
|
+
*/
|
513
|
+
normalize(data) {
|
514
|
+
const schema = Utils.isArray(data) ? [this.getSchema()] : this.getSchema();
|
515
|
+
return normalizr.normalize(data, schema).entities;
|
516
|
+
}
|
517
|
+
/**
|
518
|
+
* Get the schema from the database.
|
519
|
+
*/
|
520
|
+
getSchema() {
|
521
|
+
return new Schema(this.model).one();
|
522
|
+
}
|
523
|
+
}
|
524
|
+
|
525
|
+
function useStoreActions(query) {
|
526
|
+
return {
|
527
|
+
save(records, triggerQueryAction = true) {
|
528
|
+
Object.assign(this.data, records);
|
529
|
+
if (triggerQueryAction && query) {
|
530
|
+
query.newQuery(this.$id).save(Object.values(records));
|
531
|
+
}
|
532
|
+
},
|
533
|
+
insert(records, triggerQueryAction = true) {
|
534
|
+
Object.assign(this.data, records);
|
535
|
+
if (triggerQueryAction && query) {
|
536
|
+
query.newQuery(this.$id).insert(Object.values(records));
|
537
|
+
}
|
538
|
+
},
|
539
|
+
update(records, triggerQueryAction = true) {
|
540
|
+
Object.assign(this.data, records);
|
541
|
+
if (triggerQueryAction && query) {
|
542
|
+
query.newQuery(this.$id).update(Object.values(records));
|
543
|
+
}
|
544
|
+
},
|
545
|
+
fresh(records, triggerQueryAction = true) {
|
546
|
+
this.data = records;
|
547
|
+
if (triggerQueryAction && query) {
|
548
|
+
query.newQuery(this.$id).fresh(Object.values(records));
|
549
|
+
}
|
550
|
+
},
|
551
|
+
destroy(ids, triggerQueryAction = true) {
|
552
|
+
if (triggerQueryAction && query) {
|
553
|
+
query.newQuery(this.$id).newQuery(this.$id).destroy(ids);
|
554
|
+
} else {
|
555
|
+
ids.forEach((id) => delete this.data[id]);
|
556
|
+
}
|
557
|
+
},
|
558
|
+
/**
|
559
|
+
* Commit `delete` change to the store.
|
560
|
+
*/
|
561
|
+
delete(ids, triggerQueryAction = true) {
|
562
|
+
if (triggerQueryAction && query) {
|
563
|
+
query.whereId(ids).delete();
|
564
|
+
} else {
|
565
|
+
ids.forEach((id) => delete this.data[id]);
|
566
|
+
}
|
567
|
+
},
|
568
|
+
flush(_records, triggerQueryAction = true) {
|
569
|
+
this.data = {};
|
570
|
+
if (triggerQueryAction && query) {
|
571
|
+
query.newQuery(this.$id).flush();
|
572
|
+
}
|
573
|
+
}
|
574
|
+
};
|
575
|
+
}
|
576
|
+
|
577
|
+
function useDataStore(id, options, query) {
|
578
|
+
return pinia.defineStore(id, {
|
579
|
+
state: () => ({ data: {} }),
|
580
|
+
actions: useStoreActions(query),
|
581
|
+
...options
|
582
|
+
});
|
583
|
+
}
|
584
|
+
|
585
|
+
var __defProp$d = Object.defineProperty;
|
586
|
+
var __defNormalProp$d = (obj, key, value) => key in obj ? __defProp$d(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
587
|
+
var __publicField$d = (obj, key, value) => {
|
588
|
+
__defNormalProp$d(obj, typeof key !== "symbol" ? key + "" : key, value);
|
589
|
+
return value;
|
590
|
+
};
|
591
|
+
class BelongsToMany extends Relation {
|
592
|
+
/**
|
593
|
+
* Create a new belongs to instance.
|
594
|
+
*/
|
595
|
+
constructor(parent, related, pivot, foreignPivotKey, relatedPivotKey, parentKey, relatedKey) {
|
596
|
+
super(parent, related);
|
597
|
+
/**
|
598
|
+
* The pivot model.
|
599
|
+
*/
|
600
|
+
__publicField$d(this, "pivot");
|
601
|
+
/**
|
602
|
+
* The foreign key of the parent model.
|
603
|
+
*/
|
604
|
+
__publicField$d(this, "foreignPivotKey");
|
605
|
+
/**
|
606
|
+
* The associated key of the relation.
|
607
|
+
*/
|
608
|
+
__publicField$d(this, "relatedPivotKey");
|
609
|
+
/**
|
610
|
+
* The key name of the parent model.
|
611
|
+
*/
|
612
|
+
__publicField$d(this, "parentKey");
|
613
|
+
/**
|
614
|
+
* The key name of the related model.
|
615
|
+
*/
|
616
|
+
__publicField$d(this, "relatedKey");
|
617
|
+
/**
|
618
|
+
* The key name of the pivot data.
|
619
|
+
*/
|
620
|
+
__publicField$d(this, "pivotKey", "pivot");
|
621
|
+
this.pivot = pivot;
|
622
|
+
this.foreignPivotKey = foreignPivotKey;
|
623
|
+
this.relatedPivotKey = relatedPivotKey;
|
624
|
+
this.parentKey = parentKey;
|
625
|
+
this.relatedKey = relatedKey;
|
626
|
+
}
|
627
|
+
/**
|
628
|
+
* Get all related models for the relationship.
|
629
|
+
*/
|
630
|
+
getRelateds() {
|
631
|
+
return [this.related, this.pivot];
|
632
|
+
}
|
633
|
+
/**
|
634
|
+
* Define the normalizr schema for the relationship.
|
635
|
+
*/
|
636
|
+
define(schema) {
|
637
|
+
return schema.many(this.related, this.parent);
|
638
|
+
}
|
639
|
+
/**
|
640
|
+
* Attach the parent type and id to the given relation.
|
641
|
+
*/
|
642
|
+
attach(record, child) {
|
643
|
+
const pivot = child.pivot ?? {};
|
644
|
+
pivot[this.foreignPivotKey] = record[this.parentKey];
|
645
|
+
pivot[this.relatedPivotKey] = child[this.relatedKey];
|
646
|
+
child[`pivot_${this.pivot.$entity()}`] = pivot;
|
647
|
+
}
|
648
|
+
/**
|
649
|
+
* Convert given value to the appropriate value for the attribute.
|
650
|
+
*/
|
651
|
+
make(elements) {
|
652
|
+
return elements ? elements.map((element) => this.related.$newInstance(element)) : [];
|
653
|
+
}
|
654
|
+
/**
|
655
|
+
* Match the eagerly loaded results to their parents.
|
656
|
+
*/
|
657
|
+
match(relation, models, query) {
|
658
|
+
const relatedModels = query.get(false);
|
659
|
+
const pivotModels = query.newQuery(this.pivot.$entity()).whereIn(this.relatedPivotKey, this.getKeys(relatedModels, this.relatedKey)).whereIn(this.foreignPivotKey, this.getKeys(models, this.parentKey)).groupBy(this.foreignPivotKey, this.relatedPivotKey).get();
|
660
|
+
models.forEach((parentModel) => {
|
661
|
+
const relationResults = [];
|
662
|
+
relatedModels.forEach((relatedModel) => {
|
663
|
+
const pivot = pivotModels[`[${parentModel[this.parentKey]},${relatedModel[this.relatedKey]}]`]?.[0] ?? null;
|
664
|
+
const relatedModelCopy = relatedModel.$newInstance(relatedModel.$toJson());
|
665
|
+
relatedModelCopy.$setRelation("pivot", pivot);
|
666
|
+
if (pivot) {
|
667
|
+
relationResults.push(relatedModelCopy);
|
668
|
+
}
|
669
|
+
});
|
670
|
+
parentModel.$setRelation(relation, relationResults);
|
671
|
+
});
|
672
|
+
}
|
673
|
+
/**
|
674
|
+
* Set the constraints for the related relation.
|
675
|
+
*/
|
676
|
+
addEagerConstraints(_query, _collection) {
|
677
|
+
}
|
678
|
+
}
|
679
|
+
|
680
|
+
var __defProp$c = Object.defineProperty;
|
681
|
+
var __defNormalProp$c = (obj, key, value) => key in obj ? __defProp$c(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
682
|
+
var __publicField$c = (obj, key, value) => {
|
683
|
+
__defNormalProp$c(obj, typeof key !== "symbol" ? key + "" : key, value);
|
684
|
+
return value;
|
685
|
+
};
|
686
|
+
class Query {
|
687
|
+
/**
|
688
|
+
* Create a new query instance.
|
689
|
+
*/
|
690
|
+
constructor(database, model, cache, hydratedData, pinia) {
|
691
|
+
/**
|
692
|
+
* The database instance.
|
693
|
+
*/
|
694
|
+
__publicField$c(this, "database");
|
695
|
+
/**
|
696
|
+
* The model object.
|
697
|
+
*/
|
698
|
+
__publicField$c(this, "model");
|
699
|
+
/**
|
700
|
+
* The where constraints for the query.
|
701
|
+
*/
|
702
|
+
__publicField$c(this, "wheres", []);
|
703
|
+
/**
|
704
|
+
* The orderings for the query.
|
705
|
+
*/
|
706
|
+
__publicField$c(this, "orders", []);
|
707
|
+
/**
|
708
|
+
* The orderings for the query.
|
709
|
+
*/
|
710
|
+
__publicField$c(this, "groups", []);
|
711
|
+
/**
|
712
|
+
* The maximum number of records to return.
|
713
|
+
*/
|
714
|
+
__publicField$c(this, "take", null);
|
715
|
+
/**
|
716
|
+
* The number of records to skip.
|
717
|
+
*/
|
718
|
+
__publicField$c(this, "skip", 0);
|
719
|
+
/**
|
720
|
+
* Fields that should be visible.
|
721
|
+
*/
|
722
|
+
__publicField$c(this, "visible", ["*"]);
|
723
|
+
/**
|
724
|
+
* Fields that should be hidden.
|
725
|
+
*/
|
726
|
+
__publicField$c(this, "hidden", []);
|
727
|
+
/**
|
728
|
+
* The cache object.
|
729
|
+
*/
|
730
|
+
__publicField$c(this, "cache");
|
731
|
+
/**
|
732
|
+
* The relationships that should be eager loaded.
|
733
|
+
*/
|
734
|
+
__publicField$c(this, "eagerLoad", {});
|
735
|
+
/**
|
736
|
+
* The pinia store.
|
737
|
+
*/
|
738
|
+
__publicField$c(this, "pinia");
|
739
|
+
__publicField$c(this, "fromCache", false);
|
740
|
+
__publicField$c(this, "cacheConfig", {});
|
741
|
+
__publicField$c(this, "getNewHydrated", false);
|
742
|
+
/**
|
743
|
+
* Hydrated models. They are stored to prevent rerendering of child components.
|
744
|
+
*/
|
745
|
+
__publicField$c(this, "hydratedDataCache");
|
746
|
+
this.database = database;
|
747
|
+
this.model = model;
|
748
|
+
this.pinia = pinia;
|
749
|
+
this.cache = cache;
|
750
|
+
this.hydratedDataCache = hydratedData;
|
751
|
+
this.getNewHydrated = false;
|
752
|
+
}
|
753
|
+
/**
|
754
|
+
* Create a new query instance for the given model.
|
755
|
+
*/
|
756
|
+
newQuery(model) {
|
757
|
+
this.getNewHydrated = true;
|
758
|
+
return new Query(this.database, this.database.getModel(model), this.cache, this.hydratedDataCache, this.pinia);
|
759
|
+
}
|
760
|
+
/**
|
761
|
+
* Create a new query instance with constraints for the given model.
|
762
|
+
*/
|
763
|
+
newQueryWithConstraints(model) {
|
764
|
+
const newQuery = new Query(this.database, this.database.getModel(model), this.cache, this.hydratedDataCache, this.pinia);
|
765
|
+
newQuery.eagerLoad = { ...this.eagerLoad };
|
766
|
+
newQuery.wheres = [...this.wheres];
|
767
|
+
newQuery.orders = [...this.orders];
|
768
|
+
newQuery.take = this.take;
|
769
|
+
newQuery.skip = this.skip;
|
770
|
+
newQuery.fromCache = this.fromCache;
|
771
|
+
newQuery.cacheConfig = this.cacheConfig;
|
772
|
+
return newQuery;
|
773
|
+
}
|
774
|
+
/**
|
775
|
+
* Create a new query instance from the given relation.
|
776
|
+
*/
|
777
|
+
newQueryForRelation(relation) {
|
778
|
+
return new Query(this.database, relation.getRelated(), this.cache, /* @__PURE__ */ new Map(), this.pinia);
|
779
|
+
}
|
780
|
+
/**
|
781
|
+
* Create a new interpreter instance.
|
782
|
+
*/
|
783
|
+
newInterpreter() {
|
784
|
+
return new Interpreter(this.model);
|
785
|
+
}
|
786
|
+
/**
|
787
|
+
* Commit a store action and get the data
|
788
|
+
*/
|
789
|
+
commit(name, payload) {
|
790
|
+
const store = useDataStore(this.model.$storeName(), this.model.$piniaOptions(), this)(this.pinia);
|
791
|
+
if (undefined) {
|
792
|
+
undefined.accept(pinia.acceptHMRUpdate(store, undefined));
|
793
|
+
}
|
794
|
+
if (name && typeof store[name] === "function") {
|
795
|
+
store[name](payload, false);
|
796
|
+
}
|
797
|
+
if (this.cache && ["get", "all", "insert", "flush", "delete", "update", "destroy"].includes(name)) {
|
798
|
+
this.cache.clear();
|
799
|
+
}
|
800
|
+
return store.$state.data;
|
801
|
+
}
|
802
|
+
/**
|
803
|
+
* Make meta field visible
|
804
|
+
*/
|
805
|
+
withMeta() {
|
806
|
+
return this.makeVisible(["_meta"]);
|
807
|
+
}
|
808
|
+
/**
|
809
|
+
* Make hidden fields visible
|
810
|
+
*/
|
811
|
+
makeVisible(fields) {
|
812
|
+
this.visible = fields;
|
813
|
+
this.getNewHydrated = true;
|
814
|
+
return this;
|
815
|
+
}
|
816
|
+
/**
|
817
|
+
* Make visible fields hidden
|
818
|
+
*/
|
819
|
+
makeHidden(fields) {
|
820
|
+
this.hidden = fields;
|
821
|
+
this.getNewHydrated = true;
|
822
|
+
return this;
|
823
|
+
}
|
824
|
+
/**
|
825
|
+
* Add a basic where clause to the query.
|
826
|
+
*/
|
827
|
+
where(field, value) {
|
828
|
+
this.wheres.push({ field, value, boolean: "and" });
|
829
|
+
return this;
|
830
|
+
}
|
831
|
+
/**
|
832
|
+
* Add a "where in" clause to the query.
|
833
|
+
*/
|
834
|
+
whereIn(field, values) {
|
835
|
+
if (values instanceof Set) {
|
836
|
+
values = Array.from(values);
|
837
|
+
}
|
838
|
+
this.wheres.push({ field, value: values, boolean: "and" });
|
839
|
+
return this;
|
840
|
+
}
|
841
|
+
/**
|
842
|
+
* Add a where clause on the primary key to the query.
|
843
|
+
*/
|
844
|
+
whereId(ids) {
|
845
|
+
return this.where(this.model.$getKeyName(), ids);
|
846
|
+
}
|
847
|
+
/**
|
848
|
+
* Add an "or where" clause to the query.
|
849
|
+
*/
|
850
|
+
orWhere(field, value) {
|
851
|
+
this.wheres.push({ field, value, boolean: "or" });
|
852
|
+
return this;
|
853
|
+
}
|
854
|
+
/**
|
855
|
+
* Add a "where has" clause to the query.
|
856
|
+
*/
|
857
|
+
whereHas(relation, callback = () => {
|
858
|
+
}, operator, count) {
|
859
|
+
return this.where(this.getFieldWhereForRelations(relation, callback, operator, count));
|
860
|
+
}
|
861
|
+
/**
|
862
|
+
* Add an "or where has" clause to the query.
|
863
|
+
*/
|
864
|
+
orWhereHas(relation, callback = () => {
|
865
|
+
}, operator, count) {
|
866
|
+
return this.orWhere(this.getFieldWhereForRelations(relation, callback, operator, count));
|
867
|
+
}
|
868
|
+
/**
|
869
|
+
* Add a "has" clause to the query.
|
870
|
+
*/
|
871
|
+
has(relation, operator, count) {
|
872
|
+
return this.where(this.getFieldWhereForRelations(relation, () => {
|
873
|
+
}, operator, count));
|
874
|
+
}
|
875
|
+
/**
|
876
|
+
* Add an "or has" clause to the query.
|
877
|
+
*/
|
878
|
+
orHas(relation, operator, count) {
|
879
|
+
return this.orWhere(this.getFieldWhereForRelations(relation, () => {
|
880
|
+
}, operator, count));
|
881
|
+
}
|
882
|
+
/**
|
883
|
+
* Add a "doesn't have" clause to the query.
|
884
|
+
*/
|
885
|
+
doesntHave(relation) {
|
886
|
+
return this.where(this.getFieldWhereForRelations(relation, () => {
|
887
|
+
}, "=", 0));
|
888
|
+
}
|
889
|
+
/**
|
890
|
+
* Add a "doesn't have" clause to the query.
|
891
|
+
*/
|
892
|
+
orDoesntHave(relation) {
|
893
|
+
return this.orWhere(this.getFieldWhereForRelations(relation, () => {
|
894
|
+
}, "=", 0));
|
895
|
+
}
|
896
|
+
/**
|
897
|
+
* Add a "where doesn't have" clause to the query.
|
898
|
+
*/
|
899
|
+
whereDoesntHave(relation, callback = () => {
|
900
|
+
}) {
|
901
|
+
return this.where(this.getFieldWhereForRelations(relation, callback, "=", 0));
|
902
|
+
}
|
903
|
+
/**
|
904
|
+
* Add an "or where doesn't have" clause to the query.
|
905
|
+
*/
|
906
|
+
orWhereDoesntHave(relation, callback = () => {
|
907
|
+
}) {
|
908
|
+
return this.orWhere(this.getFieldWhereForRelations(relation, callback, "=", 0));
|
909
|
+
}
|
910
|
+
/**
|
911
|
+
* Add a "group by" clause to the query.
|
912
|
+
*/
|
913
|
+
groupBy(...fields) {
|
914
|
+
fields.forEach((field) => {
|
915
|
+
this.groups.push({ field });
|
916
|
+
});
|
917
|
+
return this;
|
918
|
+
}
|
919
|
+
/**
|
920
|
+
* Add an "order by" clause to the query.
|
921
|
+
*/
|
922
|
+
orderBy(field, direction = "asc") {
|
923
|
+
this.orders.push({ field, direction });
|
924
|
+
return this;
|
925
|
+
}
|
926
|
+
/**
|
927
|
+
* Set the "limit" value of the query.
|
928
|
+
*/
|
929
|
+
limit(value) {
|
930
|
+
this.take = value;
|
931
|
+
return this;
|
932
|
+
}
|
933
|
+
/**
|
934
|
+
* Set the "offset" value of the query.
|
935
|
+
*/
|
936
|
+
offset(value) {
|
937
|
+
this.skip = value;
|
938
|
+
return this;
|
939
|
+
}
|
940
|
+
/**
|
941
|
+
* Set the relationships that should be eager loaded.
|
942
|
+
*/
|
943
|
+
with(name, callback = () => {
|
944
|
+
}) {
|
945
|
+
this.getNewHydrated = true;
|
946
|
+
this.eagerLoad[name] = callback;
|
947
|
+
return this;
|
948
|
+
}
|
949
|
+
/**
|
950
|
+
* Set to eager load all top-level relationships. Constraint is set for all relationships.
|
951
|
+
*/
|
952
|
+
withAll(callback = () => {
|
953
|
+
}) {
|
954
|
+
let fields = this.model.$fields();
|
955
|
+
const typeModels = Object.values(this.model.$types());
|
956
|
+
typeModels.forEach((typeModel) => {
|
957
|
+
fields = { ...fields, ...typeModel.fields() };
|
958
|
+
});
|
959
|
+
for (const name in fields) {
|
960
|
+
fields[name] instanceof Relation && this.with(name, callback);
|
961
|
+
}
|
962
|
+
return this;
|
963
|
+
}
|
964
|
+
/**
|
965
|
+
* Set to eager load all relationships recursively.
|
966
|
+
*/
|
967
|
+
withAllRecursive(depth = 3) {
|
968
|
+
return this.withAll((query) => {
|
969
|
+
depth > 0 && query.withAllRecursive(depth - 1);
|
970
|
+
});
|
971
|
+
}
|
972
|
+
/**
|
973
|
+
* Define to use the cache for a query
|
974
|
+
*/
|
975
|
+
useCache(key, params) {
|
976
|
+
this.fromCache = true;
|
977
|
+
this.cacheConfig = {
|
978
|
+
key,
|
979
|
+
params
|
980
|
+
};
|
981
|
+
return this;
|
982
|
+
}
|
983
|
+
/**
|
984
|
+
* Get where closure for relations
|
985
|
+
*/
|
986
|
+
getFieldWhereForRelations(relation, callback = () => {
|
987
|
+
}, operator, count) {
|
988
|
+
const modelIdsByRelation = this.newQuery(this.model.$entity()).with(relation, callback).get(false).filter((model) => Utils.compareWithOperator(
|
989
|
+
Utils.isArray(model[relation]) ? model[relation].length : model[relation] === null ? 0 : 1,
|
990
|
+
typeof operator === "number" ? operator : count ?? 1,
|
991
|
+
typeof operator === "number" || count === void 0 ? ">=" : operator
|
992
|
+
)).map((model) => model.$getIndexId());
|
993
|
+
return (model) => modelIdsByRelation.includes(model.$getIndexId());
|
994
|
+
}
|
995
|
+
/**
|
996
|
+
* Get all models by id from the store. The difference with the `get` is that this
|
997
|
+
* method will not process any query chain.
|
998
|
+
*/
|
999
|
+
storeFind(ids = []) {
|
1000
|
+
const data = this.commit("all");
|
1001
|
+
const collection = [];
|
1002
|
+
const deduplicatedIds = new Set(ids);
|
1003
|
+
if (deduplicatedIds.size > 0) {
|
1004
|
+
deduplicatedIds.forEach((id) => {
|
1005
|
+
if (data[id]) {
|
1006
|
+
collection.push(this.hydrate(data[id], { visible: this.visible, hidden: this.hidden, operation: "get" }));
|
1007
|
+
}
|
1008
|
+
});
|
1009
|
+
} else {
|
1010
|
+
Object.values(data).forEach((value) => collection.push(this.hydrate(value, { visible: this.visible, hidden: this.hidden, operation: "get" })));
|
1011
|
+
}
|
1012
|
+
return collection;
|
1013
|
+
}
|
1014
|
+
/**
|
1015
|
+
* Get all models from the store. The difference with the `get` is that this
|
1016
|
+
* method will not process any query chain. It'll always retrieve all models.
|
1017
|
+
*/
|
1018
|
+
all() {
|
1019
|
+
return this.storeFind();
|
1020
|
+
}
|
1021
|
+
get(triggerHook = true) {
|
1022
|
+
if (!this.fromCache || !this.cache) {
|
1023
|
+
return this.internalGet(triggerHook);
|
1024
|
+
}
|
1025
|
+
const key = this.cacheConfig.key ? this.cacheConfig.key + JSON.stringify(this.cacheConfig.params) : Utils.generateKey(this.model.$entity(), {
|
1026
|
+
where: this.wheres,
|
1027
|
+
groups: this.groups,
|
1028
|
+
orders: this.orders,
|
1029
|
+
eagerLoads: this.eagerLoad,
|
1030
|
+
skip: this.skip,
|
1031
|
+
take: this.take,
|
1032
|
+
hidden: this.hidden,
|
1033
|
+
visible: this.visible
|
1034
|
+
});
|
1035
|
+
const result = this.cache.get(key);
|
1036
|
+
if (result) {
|
1037
|
+
return result;
|
1038
|
+
}
|
1039
|
+
const queryResult = this.internalGet(triggerHook);
|
1040
|
+
this.cache.set(key, queryResult);
|
1041
|
+
return queryResult;
|
1042
|
+
}
|
1043
|
+
internalGet(triggerHook) {
|
1044
|
+
if (this.model.$entity() !== this.model.$baseEntity()) {
|
1045
|
+
this.where(this.model.$typeKey(), this.model.$fields()[this.model.$typeKey()].make());
|
1046
|
+
}
|
1047
|
+
const models = this.select();
|
1048
|
+
if (!Utils.isEmpty(models)) {
|
1049
|
+
this.eagerLoadRelations(models);
|
1050
|
+
}
|
1051
|
+
if (triggerHook) {
|
1052
|
+
models.forEach((model) => model.$self().retrieved(model));
|
1053
|
+
}
|
1054
|
+
if (this.groups.length > 0) {
|
1055
|
+
return this.filterGroup(models);
|
1056
|
+
}
|
1057
|
+
return models;
|
1058
|
+
}
|
1059
|
+
/**
|
1060
|
+
* Execute the query and get the first result.
|
1061
|
+
*/
|
1062
|
+
first() {
|
1063
|
+
return this.limit(1).get()[0] ?? null;
|
1064
|
+
}
|
1065
|
+
find(ids) {
|
1066
|
+
return this.whereId(ids)[Utils.isArray(ids) ? "get" : "first"]();
|
1067
|
+
}
|
1068
|
+
/**
|
1069
|
+
* Retrieve models by processing all filters set to the query chain.
|
1070
|
+
*/
|
1071
|
+
select() {
|
1072
|
+
let ids = [];
|
1073
|
+
const originalWheres = this.wheres;
|
1074
|
+
const whereIdsIndex = this.wheres.findIndex((where) => where.field === this.model.$getKeyName());
|
1075
|
+
if (whereIdsIndex > -1) {
|
1076
|
+
const whereIds = this.wheres[whereIdsIndex].value;
|
1077
|
+
ids = ((Utils.isFunction(whereIds) ? [] : Utils.isArray(whereIds) ? whereIds : [whereIds]) || []).map(String) || [];
|
1078
|
+
if (ids.length > 0) {
|
1079
|
+
this.wheres = [...this.wheres.slice(0, whereIdsIndex), ...this.wheres.slice(whereIdsIndex + 1)];
|
1080
|
+
}
|
1081
|
+
}
|
1082
|
+
let models = this.storeFind(ids);
|
1083
|
+
models = this.filterWhere(models);
|
1084
|
+
models = this.filterOrder(models);
|
1085
|
+
models = this.filterLimit(models);
|
1086
|
+
this.wheres = originalWheres;
|
1087
|
+
return models;
|
1088
|
+
}
|
1089
|
+
/**
|
1090
|
+
* Filter the given collection by the registered where clause.
|
1091
|
+
*/
|
1092
|
+
filterWhere(models) {
|
1093
|
+
if (Utils.isEmpty(this.wheres)) {
|
1094
|
+
return models;
|
1095
|
+
}
|
1096
|
+
const comparator = this.getWhereComparator();
|
1097
|
+
return models.filter((model) => comparator(model));
|
1098
|
+
}
|
1099
|
+
/**
|
1100
|
+
* Get comparator for the where clause.
|
1101
|
+
*/
|
1102
|
+
getWhereComparator() {
|
1103
|
+
const { and, or } = Utils.groupBy(this.wheres, (where) => where.boolean);
|
1104
|
+
return (model) => {
|
1105
|
+
const results = [];
|
1106
|
+
and && results.push(and.every((w) => this.whereComparator(model, w)));
|
1107
|
+
or && results.push(or.some((w) => this.whereComparator(model, w)));
|
1108
|
+
return results.includes(true);
|
1109
|
+
};
|
1110
|
+
}
|
1111
|
+
/**
|
1112
|
+
* The function to compare where clause to the given model.
|
1113
|
+
*/
|
1114
|
+
whereComparator(model, where) {
|
1115
|
+
if (Utils.isFunction(where.field)) {
|
1116
|
+
return where.field(model);
|
1117
|
+
}
|
1118
|
+
if (Utils.isArray(where.value)) {
|
1119
|
+
return where.value.includes(model[where.field]);
|
1120
|
+
}
|
1121
|
+
if (Utils.isFunction(where.value)) {
|
1122
|
+
return where.value(model[where.field]);
|
1123
|
+
}
|
1124
|
+
return model[where.field] === where.value;
|
1125
|
+
}
|
1126
|
+
/**
|
1127
|
+
* Filter the given collection by the registered order conditions.
|
1128
|
+
*/
|
1129
|
+
filterOrder(models) {
|
1130
|
+
if (this.orders.length === 0) {
|
1131
|
+
return models;
|
1132
|
+
}
|
1133
|
+
const fields = this.orders.map((order) => order.field);
|
1134
|
+
const directions = this.orders.map((order) => order.direction);
|
1135
|
+
return Utils.orderBy(models, fields, directions);
|
1136
|
+
}
|
1137
|
+
/**
|
1138
|
+
* Filter the given collection by the registered group conditions.
|
1139
|
+
*/
|
1140
|
+
filterGroup(models) {
|
1141
|
+
const grouped = {};
|
1142
|
+
const fields = this.groups.map((group) => group.field);
|
1143
|
+
models.forEach((model) => {
|
1144
|
+
const key = fields.length === 1 ? model[fields[0]] : `[${fields.map((field) => model[field]).toString()}]`;
|
1145
|
+
grouped[key] = (grouped[key] || []).concat(model);
|
1146
|
+
});
|
1147
|
+
return grouped;
|
1148
|
+
}
|
1149
|
+
/**
|
1150
|
+
* Filter the given collection by the registered limit and offset values.
|
1151
|
+
*/
|
1152
|
+
filterLimit(models) {
|
1153
|
+
return this.take !== null ? models.slice(this.skip, this.skip + this.take) : models.slice(this.skip);
|
1154
|
+
}
|
1155
|
+
/**
|
1156
|
+
* Eager load relations on the model.
|
1157
|
+
*/
|
1158
|
+
load(models) {
|
1159
|
+
this.eagerLoadRelations(models);
|
1160
|
+
}
|
1161
|
+
/**
|
1162
|
+
* Eager load the relationships for the models.
|
1163
|
+
*/
|
1164
|
+
eagerLoadRelations(models) {
|
1165
|
+
for (const name in this.eagerLoad) {
|
1166
|
+
this.eagerLoadRelation(models, name, this.eagerLoad[name]);
|
1167
|
+
}
|
1168
|
+
}
|
1169
|
+
/**
|
1170
|
+
* Eagerly load the relationship on a set of models.
|
1171
|
+
*/
|
1172
|
+
eagerLoadRelation(models, name, constraints) {
|
1173
|
+
const relation = this.getRelation(name);
|
1174
|
+
const query = this.newQueryForRelation(relation);
|
1175
|
+
relation.addEagerConstraints(query, models);
|
1176
|
+
constraints(query);
|
1177
|
+
relation.match(name, models, query);
|
1178
|
+
}
|
1179
|
+
/**
|
1180
|
+
* Get the relation instance for the given relation name.
|
1181
|
+
*/
|
1182
|
+
getRelation(name) {
|
1183
|
+
return this.model.$getRelation(name);
|
1184
|
+
}
|
1185
|
+
revive(schema) {
|
1186
|
+
return Utils.isArray(schema) ? this.reviveMany(schema) : this.reviveOne(schema);
|
1187
|
+
}
|
1188
|
+
/**
|
1189
|
+
* Revive single model from the given schema.
|
1190
|
+
*/
|
1191
|
+
reviveOne(schema) {
|
1192
|
+
this.getNewHydrated = false;
|
1193
|
+
const id = this.model.$getIndexId(schema);
|
1194
|
+
const item = this.commit("get")[id] ?? null;
|
1195
|
+
if (!item) {
|
1196
|
+
return null;
|
1197
|
+
}
|
1198
|
+
const model = this.hydrate(item, { visible: this.visible, hidden: this.hidden, operation: "get" });
|
1199
|
+
this.reviveRelations(model, schema);
|
1200
|
+
return model;
|
1201
|
+
}
|
1202
|
+
/**
|
1203
|
+
* Revive multiple models from the given schema.
|
1204
|
+
*/
|
1205
|
+
reviveMany(schema) {
|
1206
|
+
return schema.reduce((collection, item) => {
|
1207
|
+
const model = this.reviveOne(item);
|
1208
|
+
model && collection.push(model);
|
1209
|
+
return collection;
|
1210
|
+
}, []);
|
1211
|
+
}
|
1212
|
+
/**
|
1213
|
+
* Revive relations for the given schema and entity.
|
1214
|
+
*/
|
1215
|
+
reviveRelations(model, schema) {
|
1216
|
+
const fields = this.model.$fields();
|
1217
|
+
for (const key in schema) {
|
1218
|
+
const attr = fields[key];
|
1219
|
+
if (!(attr instanceof Relation)) {
|
1220
|
+
continue;
|
1221
|
+
}
|
1222
|
+
const relatedSchema = schema[key];
|
1223
|
+
if (!relatedSchema) {
|
1224
|
+
return;
|
1225
|
+
}
|
1226
|
+
if (attr instanceof MorphTo) {
|
1227
|
+
const relatedType = model[attr.getType()];
|
1228
|
+
model[key] = this.newQuery(relatedType).reviveOne(relatedSchema);
|
1229
|
+
continue;
|
1230
|
+
}
|
1231
|
+
model[key] = Utils.isArray(relatedSchema) ? this.newQueryForRelation(attr).reviveMany(relatedSchema) : this.newQueryForRelation(attr).reviveOne(relatedSchema);
|
1232
|
+
}
|
1233
|
+
}
|
1234
|
+
/**
|
1235
|
+
* Create and persist model with default values.
|
1236
|
+
*/
|
1237
|
+
new(persist = true) {
|
1238
|
+
let model = this.hydrate({}, { operation: persist ? "set" : "get" });
|
1239
|
+
const isCreating = model.$self().creating(model);
|
1240
|
+
const isSaving = model.$self().saving(model);
|
1241
|
+
if (isCreating === false || isSaving === false) {
|
1242
|
+
return null;
|
1243
|
+
}
|
1244
|
+
if (model.$isDirty()) {
|
1245
|
+
model = this.hydrate(model.$getAttributes(), { operation: persist ? "set" : "get" });
|
1246
|
+
}
|
1247
|
+
if (persist) {
|
1248
|
+
this.hydratedDataCache.set(this.model.$entity() + model.$getKey(void 0, true), this.hydrate(model.$getAttributes(), { operation: "get" }));
|
1249
|
+
model.$self().created(model);
|
1250
|
+
model.$self().saved(model);
|
1251
|
+
this.commit("insert", this.compile(model));
|
1252
|
+
}
|
1253
|
+
return model;
|
1254
|
+
}
|
1255
|
+
save(records) {
|
1256
|
+
let processedData = this.newInterpreter().process(records);
|
1257
|
+
const modelTypes = this.model.$types();
|
1258
|
+
const isChildEntity = this.model.$baseEntity() !== this.model.$entity();
|
1259
|
+
if (Object.values(modelTypes).length > 0 || isChildEntity) {
|
1260
|
+
const modelTypesKeys = Object.keys(modelTypes);
|
1261
|
+
const recordsByTypes = {};
|
1262
|
+
records = Utils.isArray(records) ? records : [records];
|
1263
|
+
records.forEach((record) => {
|
1264
|
+
const recordType = modelTypesKeys.includes(`${record[this.model.$typeKey()]}`) || isChildEntity ? record[this.model.$typeKey()] ?? this.model.$fields()[this.model.$typeKey()].value : modelTypesKeys[0];
|
1265
|
+
if (!recordsByTypes[recordType]) {
|
1266
|
+
recordsByTypes[recordType] = [];
|
1267
|
+
}
|
1268
|
+
recordsByTypes[recordType].push(record);
|
1269
|
+
});
|
1270
|
+
for (const entry in recordsByTypes) {
|
1271
|
+
const typeModel = modelTypes[entry];
|
1272
|
+
if (typeModel.entity === this.model.$entity()) {
|
1273
|
+
processedData = this.newInterpreter().process(recordsByTypes[entry]);
|
1274
|
+
} else {
|
1275
|
+
this.newQueryWithConstraints(typeModel.entity).save(recordsByTypes[entry]);
|
1276
|
+
}
|
1277
|
+
}
|
1278
|
+
}
|
1279
|
+
const [data, entities] = processedData;
|
1280
|
+
for (const entity in entities) {
|
1281
|
+
const query = this.newQuery(entity);
|
1282
|
+
const elements = entities[entity];
|
1283
|
+
query.saveElements(elements);
|
1284
|
+
}
|
1285
|
+
return this.revive(data);
|
1286
|
+
}
|
1287
|
+
/**
|
1288
|
+
* Save the given elements to the store.
|
1289
|
+
*/
|
1290
|
+
saveElements(elements) {
|
1291
|
+
const newData = {};
|
1292
|
+
const currentData = this.commit("all");
|
1293
|
+
const afterSavingHooks = [];
|
1294
|
+
for (const id in elements) {
|
1295
|
+
const record = elements[id];
|
1296
|
+
const existing = currentData[id];
|
1297
|
+
let model = existing ? this.hydrate({ ...existing, ...record }, { operation: "set", action: "update" }) : this.hydrate(record, { operation: "set", action: "save" });
|
1298
|
+
const isSaving = model.$self().saving(model, record);
|
1299
|
+
const isUpdatingOrCreating = existing ? model.$self().updating(model, record) : model.$self().creating(model, record);
|
1300
|
+
if (isSaving === false || isUpdatingOrCreating === false) {
|
1301
|
+
continue;
|
1302
|
+
}
|
1303
|
+
if (model.$isDirty()) {
|
1304
|
+
model = this.hydrate(model.$getAttributes(), { operation: "set", action: existing ? "update" : "save" });
|
1305
|
+
}
|
1306
|
+
afterSavingHooks.push(() => model.$self().saved(model, record));
|
1307
|
+
afterSavingHooks.push(() => existing ? model.$self().updated(model, record) : model.$self().created(model, record));
|
1308
|
+
newData[id] = model.$getAttributes();
|
1309
|
+
if (Object.values(model.$types()).length > 0 && !newData[id][model.$typeKey()]) {
|
1310
|
+
newData[id][model.$typeKey()] = record[model.$typeKey()];
|
1311
|
+
}
|
1312
|
+
}
|
1313
|
+
if (Object.keys(newData).length > 0) {
|
1314
|
+
this.commit("save", newData);
|
1315
|
+
afterSavingHooks.forEach((hook) => hook());
|
1316
|
+
}
|
1317
|
+
}
|
1318
|
+
insert(records) {
|
1319
|
+
const models = this.hydrate(records, { operation: "set", action: "insert" });
|
1320
|
+
this.commit("insert", this.compile(models));
|
1321
|
+
return models;
|
1322
|
+
}
|
1323
|
+
fresh(records) {
|
1324
|
+
this.hydratedDataCache.clear();
|
1325
|
+
const models = this.hydrate(records, { action: "update" });
|
1326
|
+
this.commit("fresh", this.compile(models));
|
1327
|
+
return models;
|
1328
|
+
}
|
1329
|
+
/**
|
1330
|
+
* Update the reocrd matching the query chain.
|
1331
|
+
*/
|
1332
|
+
update(record) {
|
1333
|
+
const models = this.get(false);
|
1334
|
+
if (Utils.isEmpty(models)) {
|
1335
|
+
return [];
|
1336
|
+
}
|
1337
|
+
const newModels = models.map((model) => {
|
1338
|
+
const newModel = this.hydrate({ ...model.$getAttributes(), ...record }, { action: "update", operation: "set" });
|
1339
|
+
if (model.$self().updating(model, record) === false) {
|
1340
|
+
return model;
|
1341
|
+
}
|
1342
|
+
newModel.$self().updated(newModel);
|
1343
|
+
return newModel;
|
1344
|
+
});
|
1345
|
+
this.commit("update", this.compile(newModels));
|
1346
|
+
return newModels;
|
1347
|
+
}
|
1348
|
+
destroy(ids) {
|
1349
|
+
return Utils.isArray(ids) ? this.destroyMany(ids) : this.destroyOne(ids);
|
1350
|
+
}
|
1351
|
+
destroyOne(id) {
|
1352
|
+
const model = this.find(id);
|
1353
|
+
if (!model) {
|
1354
|
+
return null;
|
1355
|
+
}
|
1356
|
+
const [afterHooks, removeIds] = this.dispatchDeleteHooks(model);
|
1357
|
+
if (!removeIds.includes(model.$getIndexId())) {
|
1358
|
+
this.commit("destroy", [model.$getIndexId()]);
|
1359
|
+
afterHooks.forEach((hook) => hook());
|
1360
|
+
}
|
1361
|
+
return model;
|
1362
|
+
}
|
1363
|
+
destroyMany(ids) {
|
1364
|
+
const models = this.find(ids);
|
1365
|
+
if (Utils.isEmpty(models)) {
|
1366
|
+
return [];
|
1367
|
+
}
|
1368
|
+
const [afterHooks, removeIds] = this.dispatchDeleteHooks(models);
|
1369
|
+
const checkedIds = this.getIndexIdsFromCollection(models).filter((id) => !removeIds.includes(id));
|
1370
|
+
this.commit("destroy", checkedIds);
|
1371
|
+
afterHooks.forEach((hook) => hook());
|
1372
|
+
return models;
|
1373
|
+
}
|
1374
|
+
/**
|
1375
|
+
* Delete records resolved by the query chain.
|
1376
|
+
*/
|
1377
|
+
delete() {
|
1378
|
+
const models = this.get(false);
|
1379
|
+
if (Utils.isEmpty(models)) {
|
1380
|
+
return [];
|
1381
|
+
}
|
1382
|
+
const [afterHooks, removeIds] = this.dispatchDeleteHooks(models);
|
1383
|
+
const ids = this.getIndexIdsFromCollection(models).filter((id) => !removeIds.includes(id));
|
1384
|
+
this.commit("delete", ids);
|
1385
|
+
afterHooks.forEach((hook) => hook());
|
1386
|
+
return models;
|
1387
|
+
}
|
1388
|
+
/**
|
1389
|
+
* Delete all records in the store.
|
1390
|
+
*/
|
1391
|
+
flush() {
|
1392
|
+
this.commit("flush");
|
1393
|
+
this.hydratedDataCache.clear();
|
1394
|
+
return this.get(false);
|
1395
|
+
}
|
1396
|
+
checkAndDeleteRelations(model) {
|
1397
|
+
const fields = model.$fields();
|
1398
|
+
for (const name in fields) {
|
1399
|
+
const relation = fields[name];
|
1400
|
+
if (fields[name] instanceof Relation && relation.onDeleteMode && model[name]) {
|
1401
|
+
const models = Utils.isArray(model[name]) ? model[name] : [model[name]];
|
1402
|
+
const relationIds = models.map((relation2) => {
|
1403
|
+
return relation2.$getKey(void 0, true);
|
1404
|
+
});
|
1405
|
+
const record = {};
|
1406
|
+
if (relation instanceof BelongsToMany) {
|
1407
|
+
this.newQuery(relation.pivot.$entity()).where(relation.foreignPivotKey, model[model.$getLocalKey()]).delete();
|
1408
|
+
continue;
|
1409
|
+
}
|
1410
|
+
switch (relation.onDeleteMode) {
|
1411
|
+
case "cascade": {
|
1412
|
+
this.newQueryForRelation(relation).destroy(relationIds);
|
1413
|
+
break;
|
1414
|
+
}
|
1415
|
+
case "set null": {
|
1416
|
+
if (relation.foreignKey) {
|
1417
|
+
record[relation.foreignKey] = null;
|
1418
|
+
}
|
1419
|
+
if (relation.morphId) {
|
1420
|
+
record[relation.morphId] = null;
|
1421
|
+
record[relation.morphType] = null;
|
1422
|
+
}
|
1423
|
+
this.newQueryForRelation(relation).whereId(relationIds).update(record);
|
1424
|
+
break;
|
1425
|
+
}
|
1426
|
+
}
|
1427
|
+
}
|
1428
|
+
}
|
1429
|
+
}
|
1430
|
+
dispatchDeleteHooks(models) {
|
1431
|
+
const afterHooks = [];
|
1432
|
+
const notDeletableIds = [];
|
1433
|
+
models = Utils.isArray(models) ? models : [models];
|
1434
|
+
this.withAll().load(models);
|
1435
|
+
models.forEach((currentModel) => {
|
1436
|
+
const isDeleting = currentModel.$self().deleting(currentModel);
|
1437
|
+
if (isDeleting === false) {
|
1438
|
+
notDeletableIds.push(currentModel.$getIndexId());
|
1439
|
+
} else {
|
1440
|
+
this.hydratedDataCache.delete(this.model.$entity() + currentModel.$getIndexId());
|
1441
|
+
afterHooks.push(() => currentModel.$self().deleted(currentModel));
|
1442
|
+
this.checkAndDeleteRelations(currentModel);
|
1443
|
+
}
|
1444
|
+
});
|
1445
|
+
return [afterHooks, notDeletableIds];
|
1446
|
+
}
|
1447
|
+
/**
|
1448
|
+
* Get an array of index ids from the given collection.
|
1449
|
+
*/
|
1450
|
+
getIndexIdsFromCollection(models) {
|
1451
|
+
return models.map((model) => model.$getIndexId());
|
1452
|
+
}
|
1453
|
+
hydrate(records, options) {
|
1454
|
+
return Utils.isArray(records) ? records.map((record) => this.hydrate(record, options)) : this.getHydratedModel(records, { relations: false, ...options || {} });
|
1455
|
+
}
|
1456
|
+
/**
|
1457
|
+
* Convert given models into an indexed object that is ready to be saved to
|
1458
|
+
* the store.
|
1459
|
+
*/
|
1460
|
+
compile(models) {
|
1461
|
+
const collection = Utils.isArray(models) ? models : [models];
|
1462
|
+
return collection.reduce((records, model) => {
|
1463
|
+
records[model.$getIndexId()] = model.$getAttributes();
|
1464
|
+
return records;
|
1465
|
+
}, {});
|
1466
|
+
}
|
1467
|
+
/**
|
1468
|
+
* Save already existing models and return them if they exist to prevent
|
1469
|
+
* an update event trigger in vue if the object is used.
|
1470
|
+
*/
|
1471
|
+
getHydratedModel(record, options) {
|
1472
|
+
const id = this.model.$getKey(record, true);
|
1473
|
+
const savedHydratedModel = id && this.hydratedDataCache.get(this.model.$entity() + id);
|
1474
|
+
if (!this.getNewHydrated && options?.operation !== "set" && savedHydratedModel) {
|
1475
|
+
return savedHydratedModel;
|
1476
|
+
}
|
1477
|
+
const modelByType = this.model.$types()[record[this.model.$typeKey()]];
|
1478
|
+
const getNewInsance = (newOptions) => (modelByType ? modelByType.newRawInstance() : this.model).$newInstance(record, { relations: false, ...options || {}, ...newOptions });
|
1479
|
+
const hydratedModel = getNewInsance();
|
1480
|
+
if (id && !this.getNewHydrated && options?.operation !== "set") {
|
1481
|
+
this.hydratedDataCache.set(this.model.$entity() + id, hydratedModel);
|
1482
|
+
}
|
1483
|
+
if (id && options?.action === "update") {
|
1484
|
+
this.hydratedDataCache.set(this.model.$entity() + id, getNewInsance({ operation: "get" }));
|
1485
|
+
}
|
1486
|
+
return hydratedModel;
|
1487
|
+
}
|
1488
|
+
}
|
1489
|
+
|
1490
|
+
var __defProp$b = Object.defineProperty;
|
1491
|
+
var __defNormalProp$b = (obj, key, value) => key in obj ? __defProp$b(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
1492
|
+
var __publicField$b = (obj, key, value) => {
|
1493
|
+
__defNormalProp$b(obj, typeof key !== "symbol" ? key + "" : key, value);
|
1494
|
+
return value;
|
1495
|
+
};
|
1496
|
+
var __accessCheck = (obj, member, msg) => {
|
1497
|
+
if (!member.has(obj))
|
1498
|
+
throw TypeError("Cannot " + msg);
|
1499
|
+
};
|
1500
|
+
var __privateGet = (obj, member, getter) => {
|
1501
|
+
__accessCheck(obj, member, "read from private field");
|
1502
|
+
return getter ? getter.call(obj) : member.get(obj);
|
1503
|
+
};
|
1504
|
+
var __privateAdd = (obj, member, value) => {
|
1505
|
+
if (member.has(obj))
|
1506
|
+
throw TypeError("Cannot add the same private member more than once");
|
1507
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
1508
|
+
};
|
1509
|
+
var _a, _map;
|
1510
|
+
class WeakCache {
|
1511
|
+
constructor() {
|
1512
|
+
// @ts-expect-error dont know
|
1513
|
+
__publicField$b(this, _a);
|
1514
|
+
__privateAdd(this, _map, /* @__PURE__ */ new Map());
|
1515
|
+
}
|
1516
|
+
has(key) {
|
1517
|
+
return !!(__privateGet(this, _map).has(key) && __privateGet(this, _map).get(key)?.deref());
|
1518
|
+
}
|
1519
|
+
get(key) {
|
1520
|
+
const weakRef = __privateGet(this, _map).get(key);
|
1521
|
+
if (!weakRef) {
|
1522
|
+
return void 0;
|
1523
|
+
}
|
1524
|
+
const value = weakRef.deref();
|
1525
|
+
if (value) {
|
1526
|
+
return value;
|
1527
|
+
}
|
1528
|
+
__privateGet(this, _map).delete(key);
|
1529
|
+
return void 0;
|
1530
|
+
}
|
1531
|
+
set(key, value) {
|
1532
|
+
__privateGet(this, _map).set(key, new WeakRef(value));
|
1533
|
+
return this;
|
1534
|
+
}
|
1535
|
+
get size() {
|
1536
|
+
return __privateGet(this, _map).size;
|
1537
|
+
}
|
1538
|
+
clear() {
|
1539
|
+
__privateGet(this, _map).clear();
|
1540
|
+
}
|
1541
|
+
delete(key) {
|
1542
|
+
__privateGet(this, _map).delete(key);
|
1543
|
+
return false;
|
1544
|
+
}
|
1545
|
+
forEach(cb) {
|
1546
|
+
for (const [key, value] of this) {
|
1547
|
+
cb(value, key, this);
|
1548
|
+
}
|
1549
|
+
}
|
1550
|
+
*[(_a = Symbol.toStringTag, Symbol.iterator)]() {
|
1551
|
+
for (const [key, weakRef] of __privateGet(this, _map)) {
|
1552
|
+
const ref = weakRef.deref();
|
1553
|
+
if (!ref) {
|
1554
|
+
__privateGet(this, _map).delete(key);
|
1555
|
+
continue;
|
1556
|
+
}
|
1557
|
+
yield [key, ref];
|
1558
|
+
}
|
1559
|
+
}
|
1560
|
+
*entries() {
|
1561
|
+
for (const [key, value] of this) {
|
1562
|
+
yield [key, value];
|
1563
|
+
}
|
1564
|
+
}
|
1565
|
+
*keys() {
|
1566
|
+
for (const [key] of this) {
|
1567
|
+
yield key;
|
1568
|
+
}
|
1569
|
+
}
|
1570
|
+
*values() {
|
1571
|
+
for (const [, value] of this) {
|
1572
|
+
yield value;
|
1573
|
+
}
|
1574
|
+
}
|
1575
|
+
}
|
1576
|
+
_map = new WeakMap();
|
1577
|
+
|
1578
|
+
const cache$1 = new WeakCache();
|
1579
|
+
|
1580
|
+
const cache = /* @__PURE__ */ new Map();
|
1581
|
+
|
1582
|
+
const CONFIG_DEFAULTS = {
|
1583
|
+
model: {
|
1584
|
+
namespace: "",
|
1585
|
+
withMeta: false,
|
1586
|
+
hidden: ["_meta"],
|
1587
|
+
visible: ["*"]
|
1588
|
+
},
|
1589
|
+
cache: {
|
1590
|
+
shared: true,
|
1591
|
+
provider: WeakCache
|
1592
|
+
}
|
1593
|
+
};
|
1594
|
+
const config = { ...CONFIG_DEFAULTS };
|
1595
|
+
|
1596
|
+
var __defProp$a = Object.defineProperty;
|
1597
|
+
var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
1598
|
+
var __publicField$a = (obj, key, value) => {
|
1599
|
+
__defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
|
1600
|
+
return value;
|
1601
|
+
};
|
1602
|
+
class Repository {
|
1603
|
+
/**
|
1604
|
+
* Create a new Repository instance.
|
1605
|
+
*/
|
1606
|
+
constructor(database, pinia) {
|
1607
|
+
/**
|
1608
|
+
* The database instance.
|
1609
|
+
*/
|
1610
|
+
__publicField$a(this, "database");
|
1611
|
+
/**
|
1612
|
+
* The model instance.
|
1613
|
+
*/
|
1614
|
+
__publicField$a(this, "model");
|
1615
|
+
/**
|
1616
|
+
* The pinia instance
|
1617
|
+
*/
|
1618
|
+
__publicField$a(this, "pinia");
|
1619
|
+
/**
|
1620
|
+
* The cache instance
|
1621
|
+
*/
|
1622
|
+
__publicField$a(this, "queryCache");
|
1623
|
+
/**
|
1624
|
+
* Hydrated models. They are stored to prevent rerendering of child components.
|
1625
|
+
*/
|
1626
|
+
__publicField$a(this, "hydratedDataCache");
|
1627
|
+
/**
|
1628
|
+
* The model object to be used for the custom repository.
|
1629
|
+
*/
|
1630
|
+
__publicField$a(this, "use");
|
1631
|
+
/**
|
1632
|
+
* Global config
|
1633
|
+
*/
|
1634
|
+
__publicField$a(this, "config");
|
1635
|
+
this.config = config;
|
1636
|
+
this.database = database;
|
1637
|
+
this.pinia = pinia;
|
1638
|
+
this.hydratedDataCache = cache;
|
1639
|
+
}
|
1640
|
+
/**
|
1641
|
+
* Set the model
|
1642
|
+
*/
|
1643
|
+
static setModel(model) {
|
1644
|
+
this.useModel = model;
|
1645
|
+
return this;
|
1646
|
+
}
|
1647
|
+
/**
|
1648
|
+
* Set the global config
|
1649
|
+
*/
|
1650
|
+
setConfig(config) {
|
1651
|
+
this.config = config;
|
1652
|
+
}
|
1653
|
+
/**
|
1654
|
+
* Initialize the repository by setting the model instance.
|
1655
|
+
*/
|
1656
|
+
initialize(model) {
|
1657
|
+
if (this.config.cache && this.config.cache !== true) {
|
1658
|
+
this.queryCache = this.config.cache.shared ? cache$1 : new this.config.cache.provider();
|
1659
|
+
}
|
1660
|
+
if (model) {
|
1661
|
+
this.model = model.newRawInstance();
|
1662
|
+
return this;
|
1663
|
+
}
|
1664
|
+
if (this.use || this.$self().useModel) {
|
1665
|
+
this.use = this.use ?? this.$self().useModel;
|
1666
|
+
this.model = this.use.newRawInstance();
|
1667
|
+
return this;
|
1668
|
+
}
|
1669
|
+
return this;
|
1670
|
+
}
|
1671
|
+
/**
|
1672
|
+
* Get the constructor for this model.
|
1673
|
+
*/
|
1674
|
+
$self() {
|
1675
|
+
return this.constructor;
|
1676
|
+
}
|
1677
|
+
/**
|
1678
|
+
* Get the model instance. If the model is not registered to the repository,
|
1679
|
+
* it will throw an error. It happens when users use a custom repository
|
1680
|
+
* without setting `use` property.
|
1681
|
+
*/
|
1682
|
+
getModel() {
|
1683
|
+
Utils.assert(!!this.model, [
|
1684
|
+
"The model is not registered. Please define the model to be used at",
|
1685
|
+
"`use` property of the repository class."
|
1686
|
+
]);
|
1687
|
+
return this.model;
|
1688
|
+
}
|
1689
|
+
/**
|
1690
|
+
* Returns the pinia store used with this model
|
1691
|
+
*/
|
1692
|
+
piniaStore() {
|
1693
|
+
return useDataStore(this.model.$storeName(), this.model.$piniaOptions(), this.query())(this.pinia);
|
1694
|
+
}
|
1695
|
+
repo(modelOrRepository) {
|
1696
|
+
return useRepo(modelOrRepository);
|
1697
|
+
}
|
1698
|
+
/**
|
1699
|
+
* Create a new Query instance.
|
1700
|
+
*/
|
1701
|
+
query() {
|
1702
|
+
return new Query(this.database, this.getModel(), this.queryCache, this.hydratedDataCache, this.pinia);
|
1703
|
+
}
|
1704
|
+
/**
|
1705
|
+
* Create a new Query instance.
|
1706
|
+
*/
|
1707
|
+
cache() {
|
1708
|
+
return this.queryCache;
|
1709
|
+
}
|
1710
|
+
/**
|
1711
|
+
* Add a basic where clause to the query.
|
1712
|
+
*/
|
1713
|
+
where(field, value) {
|
1714
|
+
return this.query().where(field, value);
|
1715
|
+
}
|
1716
|
+
/**
|
1717
|
+
* Add an "or where" clause to the query.
|
1718
|
+
*/
|
1719
|
+
orWhere(field, value) {
|
1720
|
+
return this.query().orWhere(field, value);
|
1721
|
+
}
|
1722
|
+
/**
|
1723
|
+
* Add a "where has" clause to the query.
|
1724
|
+
*/
|
1725
|
+
whereHas(relation, callback = () => {
|
1726
|
+
}, operator, count) {
|
1727
|
+
return this.query().whereHas(relation, callback, operator, count);
|
1728
|
+
}
|
1729
|
+
/**
|
1730
|
+
* Add an "or where has" clause to the query.
|
1731
|
+
*/
|
1732
|
+
orWhereHas(relation, callback = () => {
|
1733
|
+
}, operator, count) {
|
1734
|
+
return this.query().orWhereHas(relation, callback, operator, count);
|
1735
|
+
}
|
1736
|
+
/**
|
1737
|
+
* Add a "has" clause to the query.
|
1738
|
+
*/
|
1739
|
+
has(relation, operator, count) {
|
1740
|
+
return this.query().has(relation, operator, count);
|
1741
|
+
}
|
1742
|
+
/**
|
1743
|
+
* Add an "or has" clause to the query.
|
1744
|
+
*/
|
1745
|
+
orHas(relation, operator, count) {
|
1746
|
+
return this.query().orHas(relation, operator, count);
|
1747
|
+
}
|
1748
|
+
/**
|
1749
|
+
* Add a "doesn't have" clause to the query.
|
1750
|
+
*/
|
1751
|
+
doesntHave(relation) {
|
1752
|
+
return this.query().doesntHave(relation);
|
1753
|
+
}
|
1754
|
+
/**
|
1755
|
+
* Add a "doesn't have" clause to the query.
|
1756
|
+
*/
|
1757
|
+
orDoesntHave(relation) {
|
1758
|
+
return this.query().orDoesntHave(relation);
|
1759
|
+
}
|
1760
|
+
/**
|
1761
|
+
* Add a "where doesn't have" clause to the query.
|
1762
|
+
*/
|
1763
|
+
whereDoesntHave(relation, callback = () => {
|
1764
|
+
}) {
|
1765
|
+
return this.query().whereDoesntHave(relation, callback);
|
1766
|
+
}
|
1767
|
+
/**
|
1768
|
+
* Add an "or where doesn't have" clause to the query.
|
1769
|
+
*/
|
1770
|
+
orWhereDoesntHave(relation, callback = () => {
|
1771
|
+
}) {
|
1772
|
+
return this.query().orWhereDoesntHave(relation, callback);
|
1773
|
+
}
|
1774
|
+
/**
|
1775
|
+
* Make meta field visible
|
1776
|
+
*/
|
1777
|
+
withMeta() {
|
1778
|
+
return this.query().withMeta();
|
1779
|
+
}
|
1780
|
+
/**
|
1781
|
+
* Make hidden fields visible
|
1782
|
+
*/
|
1783
|
+
makeVisible(fields) {
|
1784
|
+
return this.query().makeVisible(fields);
|
1785
|
+
}
|
1786
|
+
/**
|
1787
|
+
* Make visible fields hidden
|
1788
|
+
*/
|
1789
|
+
makeHidden(fields) {
|
1790
|
+
return this.query().makeHidden(fields);
|
1791
|
+
}
|
1792
|
+
/**
|
1793
|
+
* Add a "group by" clause to the query.
|
1794
|
+
*/
|
1795
|
+
groupBy(...fields) {
|
1796
|
+
return this.query().groupBy(...fields);
|
1797
|
+
}
|
1798
|
+
/**
|
1799
|
+
* Add an "order by" clause to the query.
|
1800
|
+
*/
|
1801
|
+
orderBy(field, direction) {
|
1802
|
+
return this.query().orderBy(field, direction);
|
1803
|
+
}
|
1804
|
+
/**
|
1805
|
+
* Set the "limit" value of the query.
|
1806
|
+
*/
|
1807
|
+
limit(value) {
|
1808
|
+
return this.query().limit(value);
|
1809
|
+
}
|
1810
|
+
/**
|
1811
|
+
* Set the "offset" value of the query.
|
1812
|
+
*/
|
1813
|
+
offset(value) {
|
1814
|
+
return this.query().offset(value);
|
1815
|
+
}
|
1816
|
+
/**
|
1817
|
+
* Set the relationships that should be eager loaded.
|
1818
|
+
*/
|
1819
|
+
with(name, callback) {
|
1820
|
+
return this.query().with(name, callback);
|
1821
|
+
}
|
1822
|
+
/**
|
1823
|
+
* Set to eager load all top-level relationships. Constraint is set for all relationships.
|
1824
|
+
*/
|
1825
|
+
withAll(callback) {
|
1826
|
+
return this.query().withAll(callback);
|
1827
|
+
}
|
1828
|
+
/**
|
1829
|
+
* Set to eager load all top-level relationships. Constraint is set for all relationships.
|
1830
|
+
*/
|
1831
|
+
withAllRecursive(depth) {
|
1832
|
+
return this.query().withAllRecursive(depth);
|
1833
|
+
}
|
1834
|
+
/**
|
1835
|
+
* Define to use the cache for a query
|
1836
|
+
*/
|
1837
|
+
useCache(key, params) {
|
1838
|
+
return this.query().useCache(key, params);
|
1839
|
+
}
|
1840
|
+
/**
|
1841
|
+
* Get all models from the store.
|
1842
|
+
*/
|
1843
|
+
all() {
|
1844
|
+
return this.query().get();
|
1845
|
+
}
|
1846
|
+
find(ids) {
|
1847
|
+
return this.query().find(ids);
|
1848
|
+
}
|
1849
|
+
revive(schema) {
|
1850
|
+
return this.query().revive(schema);
|
1851
|
+
}
|
1852
|
+
make(records) {
|
1853
|
+
if (Utils.isArray(records)) {
|
1854
|
+
return records.map((record) => this.getModel().$newInstance(record, {
|
1855
|
+
relations: true
|
1856
|
+
}));
|
1857
|
+
}
|
1858
|
+
return this.getModel().$newInstance(records, {
|
1859
|
+
relations: true
|
1860
|
+
});
|
1861
|
+
}
|
1862
|
+
save(records) {
|
1863
|
+
return this.query().save(records);
|
1864
|
+
}
|
1865
|
+
/**
|
1866
|
+
* Create and persist model with default values.
|
1867
|
+
*/
|
1868
|
+
new(persist = true) {
|
1869
|
+
return this.query().new(persist);
|
1870
|
+
}
|
1871
|
+
insert(records) {
|
1872
|
+
return this.query().insert(records);
|
1873
|
+
}
|
1874
|
+
fresh(records) {
|
1875
|
+
return this.query().fresh(records);
|
1876
|
+
}
|
1877
|
+
destroy(ids) {
|
1878
|
+
return this.query().destroy(ids);
|
1879
|
+
}
|
1880
|
+
/**
|
1881
|
+
* Delete all records in the store.
|
1882
|
+
*/
|
1883
|
+
flush() {
|
1884
|
+
return this.query().flush();
|
1885
|
+
}
|
1886
|
+
}
|
1887
|
+
/**
|
1888
|
+
* A special flag to indicate if this is the repository class or not. It's
|
1889
|
+
* used when retrieving repository instance from `store.$repo()` method to
|
1890
|
+
* determine whether the passed in class is either a repository or a model.
|
1891
|
+
*/
|
1892
|
+
__publicField$a(Repository, "_isRepository", true);
|
1893
|
+
/**
|
1894
|
+
* The model object to be used for the custom repository.
|
1895
|
+
*/
|
1896
|
+
__publicField$a(Repository, "useModel");
|
1897
|
+
|
1898
|
+
var __defProp$9 = Object.defineProperty;
|
1899
|
+
var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
1900
|
+
var __publicField$9 = (obj, key, value) => {
|
1901
|
+
__defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
|
1902
|
+
return value;
|
1903
|
+
};
|
1904
|
+
class Database {
|
1905
|
+
constructor() {
|
1906
|
+
/**
|
1907
|
+
* The list of registered models.
|
1908
|
+
*/
|
1909
|
+
__publicField$9(this, "models", {});
|
1910
|
+
}
|
1911
|
+
/**
|
1912
|
+
* Register the given model.
|
1913
|
+
*/
|
1914
|
+
register(model) {
|
1915
|
+
const entity = model.$entity();
|
1916
|
+
if (!this.models[entity]) {
|
1917
|
+
this.models[entity] = model;
|
1918
|
+
this.registerRelatedModels(model);
|
1919
|
+
}
|
1920
|
+
}
|
1921
|
+
/**
|
1922
|
+
* Register all related models.
|
1923
|
+
*/
|
1924
|
+
registerRelatedModels(model) {
|
1925
|
+
const fields = model.$fields();
|
1926
|
+
for (const name in fields) {
|
1927
|
+
const attr = fields[name];
|
1928
|
+
if (attr instanceof Relation) {
|
1929
|
+
attr.getRelateds().forEach((m) => {
|
1930
|
+
this.register(m);
|
1931
|
+
});
|
1932
|
+
}
|
1933
|
+
}
|
1934
|
+
}
|
1935
|
+
/**
|
1936
|
+
* Get a model by the specified entity name.
|
1937
|
+
*/
|
1938
|
+
getModel(name) {
|
1939
|
+
return this.models[name];
|
1940
|
+
}
|
1941
|
+
}
|
1942
|
+
|
1943
|
+
const definePiniaOrmPlugin = (plugin) => plugin;
|
1944
|
+
const plugins = [];
|
1945
|
+
function registerPlugins(repository) {
|
1946
|
+
let config$1 = config;
|
1947
|
+
plugins.forEach((plugin) => {
|
1948
|
+
const pluginConfig = plugin({ config: config$1, repository, model: repository.getModel() });
|
1949
|
+
config$1 = { ...config$1, ...pluginConfig.config };
|
1950
|
+
});
|
1951
|
+
repository.setConfig(config$1);
|
1952
|
+
return repository;
|
1953
|
+
}
|
1954
|
+
|
1955
|
+
function useRepo(ModelOrRepository, pinia) {
|
1956
|
+
const database = new Database();
|
1957
|
+
const repository = ModelOrRepository._isRepository ? new ModelOrRepository(database, pinia).initialize() : new Repository(database, pinia).initialize(ModelOrRepository);
|
1958
|
+
try {
|
1959
|
+
const typeModels = Object.values(repository.getModel().$types());
|
1960
|
+
if (typeModels.length > 0) {
|
1961
|
+
typeModels.forEach((typeModel) => repository.database.register(typeModel.newRawInstance()));
|
1962
|
+
} else {
|
1963
|
+
repository.database.register(repository.getModel());
|
1964
|
+
}
|
1965
|
+
} catch (e) {
|
1966
|
+
}
|
1967
|
+
return registerPlugins(repository);
|
1968
|
+
}
|
1969
|
+
|
1970
|
+
function mapRepos(modelsOrRepositories) {
|
1971
|
+
const repositories = {};
|
1972
|
+
for (const name in modelsOrRepositories) {
|
1973
|
+
repositories[name] = function() {
|
1974
|
+
return useRepo(modelsOrRepositories[name]);
|
1975
|
+
};
|
1976
|
+
}
|
1977
|
+
return repositories;
|
1978
|
+
}
|
1979
|
+
|
1980
|
+
function createORM(options) {
|
1981
|
+
config.model = { ...CONFIG_DEFAULTS.model, ...options?.model };
|
1982
|
+
config.cache = options?.cache === false ? false : { ...CONFIG_DEFAULTS.cache, ...options?.cache !== true && options?.cache };
|
1983
|
+
const orm = {
|
1984
|
+
use(plugin) {
|
1985
|
+
plugins.push(plugin);
|
1986
|
+
return this;
|
1987
|
+
}
|
1988
|
+
};
|
1989
|
+
return () => orm;
|
1990
|
+
}
|
1991
|
+
|
1992
|
+
class Attr extends Type {
|
1993
|
+
/**
|
1994
|
+
* Make the value for the attribute.
|
1995
|
+
*/
|
1996
|
+
make(value) {
|
1997
|
+
return value === void 0 ? this.value : value;
|
1998
|
+
}
|
1999
|
+
}
|
2000
|
+
|
2001
|
+
let String$1 = class String extends Type {
|
2002
|
+
/**
|
2003
|
+
* Create a new String attribute instance.
|
2004
|
+
*/
|
2005
|
+
constructor(model, value) {
|
2006
|
+
super(model, value);
|
2007
|
+
}
|
2008
|
+
/**
|
2009
|
+
* Make the value for the attribute.
|
2010
|
+
*/
|
2011
|
+
make(value) {
|
2012
|
+
return this.makeReturn("string", value);
|
2013
|
+
}
|
2014
|
+
};
|
2015
|
+
|
2016
|
+
class Number extends Type {
|
2017
|
+
/**
|
2018
|
+
* Create a new Number attribute instance.
|
2019
|
+
*/
|
2020
|
+
constructor(model, value) {
|
2021
|
+
super(model, value);
|
2022
|
+
}
|
2023
|
+
/**
|
2024
|
+
* Make the value for the attribute.
|
2025
|
+
*/
|
2026
|
+
make(value) {
|
2027
|
+
return this.makeReturn("number", value);
|
2028
|
+
}
|
2029
|
+
}
|
2030
|
+
|
2031
|
+
class Boolean extends Type {
|
2032
|
+
/**
|
2033
|
+
* Create a new Boolean attribute instance.
|
2034
|
+
*/
|
2035
|
+
constructor(model, value) {
|
2036
|
+
super(model, value);
|
2037
|
+
}
|
2038
|
+
/**
|
2039
|
+
* Make the value for the attribute.
|
2040
|
+
*/
|
2041
|
+
make(value) {
|
2042
|
+
return this.makeReturn("boolean", value);
|
2043
|
+
}
|
2044
|
+
}
|
2045
|
+
|
2046
|
+
var __defProp$8 = Object.defineProperty;
|
2047
|
+
var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
2048
|
+
var __publicField$8 = (obj, key, value) => {
|
2049
|
+
__defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
|
2050
|
+
return value;
|
2051
|
+
};
|
2052
|
+
class HasOne extends Relation {
|
2053
|
+
/**
|
2054
|
+
* Create a new has-one relation instance.
|
2055
|
+
*/
|
2056
|
+
constructor(parent, related, foreignKey, localKey) {
|
2057
|
+
super(parent, related);
|
2058
|
+
/**
|
2059
|
+
* The foreign key of the parent model.
|
2060
|
+
*/
|
2061
|
+
__publicField$8(this, "foreignKey");
|
2062
|
+
/**
|
2063
|
+
* The local key of the parent model.
|
2064
|
+
*/
|
2065
|
+
__publicField$8(this, "localKey");
|
2066
|
+
this.foreignKey = foreignKey;
|
2067
|
+
this.localKey = localKey;
|
2068
|
+
}
|
2069
|
+
/**
|
2070
|
+
* Get all related models for the relationship.
|
2071
|
+
*/
|
2072
|
+
getRelateds() {
|
2073
|
+
return [this.related];
|
2074
|
+
}
|
2075
|
+
/**
|
2076
|
+
* Define the normalizr schema for the relation.
|
2077
|
+
*/
|
2078
|
+
define(schema) {
|
2079
|
+
return schema.one(this.related, this.parent);
|
2080
|
+
}
|
2081
|
+
/**
|
2082
|
+
* Attach the relational key to the given relation.
|
2083
|
+
*/
|
2084
|
+
attach(record, child) {
|
2085
|
+
this.compositeKeyMapper(
|
2086
|
+
this.foreignKey,
|
2087
|
+
this.localKey,
|
2088
|
+
(foreignKey, localKey) => {
|
2089
|
+
child[foreignKey] = record[localKey];
|
2090
|
+
}
|
2091
|
+
);
|
2092
|
+
}
|
2093
|
+
/**
|
2094
|
+
* Set the constraints for an eager load of the relation.
|
2095
|
+
*/
|
2096
|
+
addEagerConstraints(query, models) {
|
2097
|
+
this.compositeKeyMapper(
|
2098
|
+
this.foreignKey,
|
2099
|
+
this.localKey,
|
2100
|
+
(foreignKey, localKey) => query.whereIn(foreignKey, this.getKeys(models, localKey))
|
2101
|
+
);
|
2102
|
+
}
|
2103
|
+
/**
|
2104
|
+
* Match the eagerly loaded results to their parents.
|
2105
|
+
*/
|
2106
|
+
match(relation, models, query) {
|
2107
|
+
const dictionary = this.buildDictionary(query.get(false));
|
2108
|
+
models.forEach((model) => {
|
2109
|
+
const key = model[this.getKey(this.localKey)];
|
2110
|
+
dictionary[key] ? model.$setRelation(relation, dictionary[key][0]) : model.$setRelation(relation, null);
|
2111
|
+
});
|
2112
|
+
}
|
2113
|
+
/**
|
2114
|
+
* Build model dictionary keyed by the relation's foreign key.
|
2115
|
+
*/
|
2116
|
+
buildDictionary(results) {
|
2117
|
+
return this.mapToDictionary(results, (result) => {
|
2118
|
+
return [result[this.getKey(this.foreignKey)], result];
|
2119
|
+
});
|
2120
|
+
}
|
2121
|
+
/**
|
2122
|
+
* Make a related model.
|
2123
|
+
*/
|
2124
|
+
make(element) {
|
2125
|
+
return element ? this.related.$newInstance(element) : null;
|
2126
|
+
}
|
2127
|
+
}
|
2128
|
+
|
2129
|
+
var __defProp$7 = Object.defineProperty;
|
2130
|
+
var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
2131
|
+
var __publicField$7 = (obj, key, value) => {
|
2132
|
+
__defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
|
2133
|
+
return value;
|
2134
|
+
};
|
2135
|
+
class BelongsTo extends Relation {
|
2136
|
+
/**
|
2137
|
+
* Create a new belongs-to relation instance.
|
2138
|
+
*/
|
2139
|
+
constructor(parent, child, foreignKey, ownerKey) {
|
2140
|
+
super(parent, child);
|
2141
|
+
/**
|
2142
|
+
* The child model instance of the relation.
|
2143
|
+
*/
|
2144
|
+
__publicField$7(this, "child");
|
2145
|
+
/**
|
2146
|
+
* The foreign key of the parent model.
|
2147
|
+
*/
|
2148
|
+
__publicField$7(this, "foreignKey");
|
2149
|
+
/**
|
2150
|
+
* The associated key on the parent model.
|
2151
|
+
*/
|
2152
|
+
__publicField$7(this, "ownerKey");
|
2153
|
+
this.foreignKey = foreignKey;
|
2154
|
+
this.ownerKey = ownerKey;
|
2155
|
+
this.child = child;
|
2156
|
+
}
|
2157
|
+
/**
|
2158
|
+
* Get all related models for the relationship.
|
2159
|
+
*/
|
2160
|
+
getRelateds() {
|
2161
|
+
return [this.child];
|
2162
|
+
}
|
2163
|
+
/**
|
2164
|
+
* Define the normalizr schema for the relation.
|
2165
|
+
*/
|
2166
|
+
define(schema) {
|
2167
|
+
return schema.one(this.child, this.parent);
|
2168
|
+
}
|
2169
|
+
/**
|
2170
|
+
* Attach the relational key to the given relation.
|
2171
|
+
*/
|
2172
|
+
attach(record, child) {
|
2173
|
+
this.compositeKeyMapper(
|
2174
|
+
this.foreignKey,
|
2175
|
+
this.ownerKey,
|
2176
|
+
(foreignKey, ownerKey) => {
|
2177
|
+
record[foreignKey] = child[ownerKey];
|
2178
|
+
}
|
2179
|
+
);
|
2180
|
+
}
|
2181
|
+
/**
|
2182
|
+
* Set the constraints for an eager load of the relation.
|
2183
|
+
*/
|
2184
|
+
addEagerConstraints(query, models) {
|
2185
|
+
this.compositeKeyMapper(
|
2186
|
+
this.foreignKey,
|
2187
|
+
this.ownerKey,
|
2188
|
+
(foreignKey, ownerKey) => query.whereIn(ownerKey, this.getEagerModelKeys(models, foreignKey))
|
2189
|
+
);
|
2190
|
+
}
|
2191
|
+
/**
|
2192
|
+
* Gather the keys from a collection of related models.
|
2193
|
+
*/
|
2194
|
+
getEagerModelKeys(models, foreignKey) {
|
2195
|
+
return models.reduce((keys, model) => {
|
2196
|
+
if (model[foreignKey] !== null) {
|
2197
|
+
keys.push(model[foreignKey]);
|
2198
|
+
}
|
2199
|
+
return keys;
|
2200
|
+
}, []);
|
2201
|
+
}
|
2202
|
+
/**
|
2203
|
+
* Match the eagerly loaded results to their respective parents.
|
2204
|
+
*/
|
2205
|
+
match(relation, models, query) {
|
2206
|
+
const dictionary = this.buildDictionary(query.get(false));
|
2207
|
+
models.forEach((model) => {
|
2208
|
+
const key = model[this.getKey(this.foreignKey)];
|
2209
|
+
dictionary[key] ? model.$setRelation(relation, dictionary[key]) : model.$setRelation(relation, null);
|
2210
|
+
});
|
2211
|
+
}
|
2212
|
+
/**
|
2213
|
+
* Build model dictionary keyed by relation's parent key.
|
2214
|
+
*/
|
2215
|
+
buildDictionary(models) {
|
2216
|
+
return models.reduce((dictionary, model) => {
|
2217
|
+
dictionary[model[this.getKey(this.ownerKey)]] = model;
|
2218
|
+
return dictionary;
|
2219
|
+
}, {});
|
2220
|
+
}
|
2221
|
+
/**
|
2222
|
+
* Make a related model.
|
2223
|
+
*/
|
2224
|
+
make(element) {
|
2225
|
+
return element ? this.child.$newInstance(element) : null;
|
2226
|
+
}
|
2227
|
+
}
|
2228
|
+
|
2229
|
+
var __defProp$6 = Object.defineProperty;
|
2230
|
+
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
2231
|
+
var __publicField$6 = (obj, key, value) => {
|
2232
|
+
__defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
|
2233
|
+
return value;
|
2234
|
+
};
|
2235
|
+
class HasMany extends Relation {
|
2236
|
+
/**
|
2237
|
+
* Create a new has-many relation instance.
|
2238
|
+
*/
|
2239
|
+
constructor(parent, related, foreignKey, localKey) {
|
2240
|
+
super(parent, related);
|
2241
|
+
/**
|
2242
|
+
* The foreign key of the parent model.
|
2243
|
+
*/
|
2244
|
+
__publicField$6(this, "foreignKey");
|
2245
|
+
/**
|
2246
|
+
* The local key of the parent model.
|
2247
|
+
*/
|
2248
|
+
__publicField$6(this, "localKey");
|
2249
|
+
this.foreignKey = foreignKey;
|
2250
|
+
this.localKey = localKey;
|
2251
|
+
}
|
2252
|
+
/**
|
2253
|
+
* Get all related models for the relationship.
|
2254
|
+
*/
|
2255
|
+
getRelateds() {
|
2256
|
+
return [this.related];
|
2257
|
+
}
|
2258
|
+
/**
|
2259
|
+
* Define the normalizr schema for the relation.
|
2260
|
+
*/
|
2261
|
+
define(schema) {
|
2262
|
+
return schema.many(this.related, this.parent);
|
2263
|
+
}
|
2264
|
+
/**
|
2265
|
+
* Attach the relational key to the given relation.
|
2266
|
+
*/
|
2267
|
+
attach(record, child) {
|
2268
|
+
this.compositeKeyMapper(
|
2269
|
+
this.foreignKey,
|
2270
|
+
this.localKey,
|
2271
|
+
(foreignKey, localKey) => {
|
2272
|
+
child[foreignKey] = record[localKey];
|
2273
|
+
}
|
2274
|
+
);
|
2275
|
+
}
|
2276
|
+
/**
|
2277
|
+
* Set the constraints for an eager load of the relation.
|
2278
|
+
*/
|
2279
|
+
addEagerConstraints(query, models) {
|
2280
|
+
this.compositeKeyMapper(
|
2281
|
+
this.foreignKey,
|
2282
|
+
this.localKey,
|
2283
|
+
(foreignKey, localKey) => query.whereIn(foreignKey, this.getKeys(models, localKey))
|
2284
|
+
);
|
2285
|
+
}
|
2286
|
+
/**
|
2287
|
+
* Match the eagerly loaded results to their parents.
|
2288
|
+
*/
|
2289
|
+
match(relation, models, query) {
|
2290
|
+
const dictionary = this.buildDictionary(query.get(false));
|
2291
|
+
models.forEach((model) => {
|
2292
|
+
const key = model[this.getKey(this.localKey)];
|
2293
|
+
dictionary[key] ? model.$setRelation(relation, dictionary[key]) : model.$setRelation(relation, []);
|
2294
|
+
});
|
2295
|
+
}
|
2296
|
+
/**
|
2297
|
+
* Build model dictionary keyed by the relation's foreign key.
|
2298
|
+
*/
|
2299
|
+
buildDictionary(results) {
|
2300
|
+
return this.mapToDictionary(results, (result) => {
|
2301
|
+
const key = this.getKey(this.foreignKey);
|
2302
|
+
return [result[key], result];
|
2303
|
+
});
|
2304
|
+
}
|
2305
|
+
/**
|
2306
|
+
* Make related models.
|
2307
|
+
*/
|
2308
|
+
make(elements) {
|
2309
|
+
return elements ? elements.map((element) => this.related.$newInstance(element)) : [];
|
2310
|
+
}
|
2311
|
+
}
|
2312
|
+
|
2313
|
+
var __defProp$5 = Object.defineProperty;
|
2314
|
+
var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
2315
|
+
var __publicField$5 = (obj, key, value) => {
|
2316
|
+
__defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
|
2317
|
+
return value;
|
2318
|
+
};
|
2319
|
+
class HasManyBy extends Relation {
|
2320
|
+
/**
|
2321
|
+
* Create a new has-many-by relation instance.
|
2322
|
+
*/
|
2323
|
+
constructor(parent, child, foreignKey, ownerKey) {
|
2324
|
+
super(parent, child);
|
2325
|
+
/**
|
2326
|
+
* The child model instance of the relation.
|
2327
|
+
*/
|
2328
|
+
__publicField$5(this, "child");
|
2329
|
+
/**
|
2330
|
+
* The foreign key of the parent model.
|
2331
|
+
*/
|
2332
|
+
__publicField$5(this, "foreignKey");
|
2333
|
+
/**
|
2334
|
+
* The owner key of the parent model.
|
2335
|
+
*/
|
2336
|
+
__publicField$5(this, "ownerKey");
|
2337
|
+
this.foreignKey = foreignKey;
|
2338
|
+
this.ownerKey = ownerKey;
|
2339
|
+
this.child = child;
|
2340
|
+
}
|
2341
|
+
/**
|
2342
|
+
* Get all related models for the relationship.
|
2343
|
+
*/
|
2344
|
+
getRelateds() {
|
2345
|
+
return [this.child];
|
2346
|
+
}
|
2347
|
+
/**
|
2348
|
+
* Define the normalizr schema for the relation.
|
2349
|
+
*/
|
2350
|
+
define(schema) {
|
2351
|
+
return schema.many(this.child, this.parent);
|
2352
|
+
}
|
2353
|
+
/**
|
2354
|
+
* Attach the relational key to the given relation.
|
2355
|
+
*/
|
2356
|
+
attach(record, child) {
|
2357
|
+
if (child[this.ownerKey] === void 0) {
|
2358
|
+
return;
|
2359
|
+
}
|
2360
|
+
if (!record[this.foreignKey]) {
|
2361
|
+
record[this.foreignKey] = [];
|
2362
|
+
}
|
2363
|
+
this.attachIfMissing(record[this.foreignKey], child[this.ownerKey]);
|
2364
|
+
}
|
2365
|
+
/**
|
2366
|
+
* Push owner key to foregin key array if owner key doesn't exist in foreign
|
2367
|
+
* key array.
|
2368
|
+
*/
|
2369
|
+
attachIfMissing(foreignKey, ownerKey) {
|
2370
|
+
if (!foreignKey.includes(ownerKey)) {
|
2371
|
+
foreignKey.push(ownerKey);
|
2372
|
+
}
|
2373
|
+
}
|
2374
|
+
/**
|
2375
|
+
* Set the constraints for an eager load of the relation.
|
2376
|
+
*/
|
2377
|
+
addEagerConstraints(query, models) {
|
2378
|
+
query.whereIn(this.ownerKey, this.getEagerModelKeys(models));
|
2379
|
+
}
|
2380
|
+
/**
|
2381
|
+
* Gather the keys from a collection of related models.
|
2382
|
+
*/
|
2383
|
+
getEagerModelKeys(models) {
|
2384
|
+
return models.reduce((keys, model) => {
|
2385
|
+
return [...keys, ...model[this.foreignKey]];
|
2386
|
+
}, []);
|
2387
|
+
}
|
2388
|
+
/**
|
2389
|
+
* Match the eagerly loaded results to their parents.
|
2390
|
+
*/
|
2391
|
+
match(relation, models, query) {
|
2392
|
+
const dictionary = this.buildDictionary(query.get(false));
|
2393
|
+
models.forEach((model) => {
|
2394
|
+
const relatedModels = this.getRelatedModels(
|
2395
|
+
dictionary,
|
2396
|
+
model[this.foreignKey]
|
2397
|
+
);
|
2398
|
+
model.$setRelation(relation, relatedModels);
|
2399
|
+
});
|
2400
|
+
}
|
2401
|
+
/**
|
2402
|
+
* Build model dictionary keyed by the relation's foreign key.
|
2403
|
+
*/
|
2404
|
+
buildDictionary(models) {
|
2405
|
+
return models.reduce((dictionary, model) => {
|
2406
|
+
dictionary[model[this.ownerKey]] = model;
|
2407
|
+
return dictionary;
|
2408
|
+
}, {});
|
2409
|
+
}
|
2410
|
+
/**
|
2411
|
+
* Get all related models from the given dictionary.
|
2412
|
+
*/
|
2413
|
+
getRelatedModels(dictionary, keys) {
|
2414
|
+
return keys.reduce((items, key) => {
|
2415
|
+
const item = dictionary[key];
|
2416
|
+
item && items.push(item);
|
2417
|
+
return items;
|
2418
|
+
}, []);
|
2419
|
+
}
|
2420
|
+
/**
|
2421
|
+
* Make related models.
|
2422
|
+
*/
|
2423
|
+
make(elements) {
|
2424
|
+
return elements ? elements.map((element) => this.child.$newInstance(element)) : [];
|
2425
|
+
}
|
2426
|
+
}
|
2427
|
+
|
2428
|
+
var __defProp$4 = Object.defineProperty;
|
2429
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
2430
|
+
var __publicField$4 = (obj, key, value) => {
|
2431
|
+
__defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
2432
|
+
return value;
|
2433
|
+
};
|
2434
|
+
class MorphOne extends Relation {
|
2435
|
+
/**
|
2436
|
+
* Create a new morph-one relation instance.
|
2437
|
+
*/
|
2438
|
+
constructor(parent, related, morphId, morphType, localKey) {
|
2439
|
+
super(parent, related);
|
2440
|
+
/**
|
2441
|
+
* The field name that contains id of the parent model.
|
2442
|
+
*/
|
2443
|
+
__publicField$4(this, "morphId");
|
2444
|
+
/**
|
2445
|
+
* The field name that contains type of the parent model.
|
2446
|
+
*/
|
2447
|
+
__publicField$4(this, "morphType");
|
2448
|
+
/**
|
2449
|
+
* The local key of the model.
|
2450
|
+
*/
|
2451
|
+
__publicField$4(this, "localKey");
|
2452
|
+
this.morphId = morphId;
|
2453
|
+
this.morphType = morphType;
|
2454
|
+
this.localKey = localKey;
|
2455
|
+
}
|
2456
|
+
/**
|
2457
|
+
* Get all related models for the relationship.
|
2458
|
+
*/
|
2459
|
+
getRelateds() {
|
2460
|
+
return [this.related];
|
2461
|
+
}
|
2462
|
+
/**
|
2463
|
+
* Define the normalizr schema for the relation.
|
2464
|
+
*/
|
2465
|
+
define(schema) {
|
2466
|
+
return schema.one(this.related, this.parent);
|
2467
|
+
}
|
2468
|
+
/**
|
2469
|
+
* Attach the parent type and id to the given relation.
|
2470
|
+
*/
|
2471
|
+
attach(record, child) {
|
2472
|
+
child[this.morphId] = record[this.localKey];
|
2473
|
+
child[this.morphType] = this.parent.$entity();
|
2474
|
+
}
|
2475
|
+
/**
|
2476
|
+
* Set the constraints for an eager load of the relation.
|
2477
|
+
*/
|
2478
|
+
addEagerConstraints(query, models) {
|
2479
|
+
query.where(this.morphType, this.parent.$entity()).whereIn(this.morphId, this.getKeys(models, this.localKey));
|
2480
|
+
}
|
2481
|
+
/**
|
2482
|
+
* Match the eagerly loaded results to their parents.
|
2483
|
+
*/
|
2484
|
+
match(relation, models, query) {
|
2485
|
+
const dictionary = this.buildDictionary(query.get(false));
|
2486
|
+
models.forEach((model) => {
|
2487
|
+
const key = model[this.localKey];
|
2488
|
+
dictionary[key] ? model.$setRelation(relation, dictionary[key]) : model.$setRelation(relation, null);
|
2489
|
+
});
|
2490
|
+
}
|
2491
|
+
/**
|
2492
|
+
* Build model dictionary keyed by the relation's foreign key.
|
2493
|
+
*/
|
2494
|
+
buildDictionary(models) {
|
2495
|
+
return models.reduce((dictionary, model) => {
|
2496
|
+
dictionary[model[this.morphId]] = model;
|
2497
|
+
return dictionary;
|
2498
|
+
}, {});
|
2499
|
+
}
|
2500
|
+
/**
|
2501
|
+
* Make a related model.
|
2502
|
+
*/
|
2503
|
+
make(element) {
|
2504
|
+
return element ? this.related.$newInstance(element) : null;
|
2505
|
+
}
|
2506
|
+
}
|
2507
|
+
|
2508
|
+
var __defProp$3 = Object.defineProperty;
|
2509
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
2510
|
+
var __publicField$3 = (obj, key, value) => {
|
2511
|
+
__defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
2512
|
+
return value;
|
2513
|
+
};
|
2514
|
+
class MorphMany extends Relation {
|
2515
|
+
/**
|
2516
|
+
* Create a new morph-many relation instance.
|
2517
|
+
*/
|
2518
|
+
constructor(parent, related, morphId, morphType, localKey) {
|
2519
|
+
super(parent, related);
|
2520
|
+
/**
|
2521
|
+
* The field name that contains id of the parent model.
|
2522
|
+
*/
|
2523
|
+
__publicField$3(this, "morphId");
|
2524
|
+
/**
|
2525
|
+
* The field name that contains type of the parent model.
|
2526
|
+
*/
|
2527
|
+
__publicField$3(this, "morphType");
|
2528
|
+
/**
|
2529
|
+
* The local key of the model.
|
2530
|
+
*/
|
2531
|
+
__publicField$3(this, "localKey");
|
2532
|
+
this.morphId = morphId;
|
2533
|
+
this.morphType = morphType;
|
2534
|
+
this.localKey = localKey;
|
2535
|
+
}
|
2536
|
+
/**
|
2537
|
+
* Get all related models for the relationship.
|
2538
|
+
*/
|
2539
|
+
getRelateds() {
|
2540
|
+
return [this.related];
|
2541
|
+
}
|
2542
|
+
/**
|
2543
|
+
* Define the normalizr schema for the relation.
|
2544
|
+
*/
|
2545
|
+
define(schema) {
|
2546
|
+
return schema.many(this.related, this.parent);
|
2547
|
+
}
|
2548
|
+
/**
|
2549
|
+
* Attach the parent type and id to the given relation.
|
2550
|
+
*/
|
2551
|
+
attach(record, child) {
|
2552
|
+
child[this.morphId] = record[this.localKey];
|
2553
|
+
child[this.morphType] = this.parent.$entity();
|
2554
|
+
}
|
2555
|
+
/**
|
2556
|
+
* Set the constraints for an eager load of the relation.
|
2557
|
+
*/
|
2558
|
+
addEagerConstraints(query, models) {
|
2559
|
+
query.where(this.morphType, this.parent.$entity());
|
2560
|
+
query.whereIn(this.morphId, this.getKeys(models, this.localKey));
|
2561
|
+
}
|
2562
|
+
/**
|
2563
|
+
* Match the eagerly loaded results to their parents.
|
2564
|
+
*/
|
2565
|
+
match(relation, models, query) {
|
2566
|
+
const dictionary = this.buildDictionary(query.get(false));
|
2567
|
+
models.forEach((model) => {
|
2568
|
+
const key = model[this.localKey];
|
2569
|
+
dictionary[key] ? model.$setRelation(relation, dictionary[key]) : model.$setRelation(relation, []);
|
2570
|
+
});
|
2571
|
+
}
|
2572
|
+
/**
|
2573
|
+
* Build model dictionary keyed by the relation's foreign key.
|
2574
|
+
*/
|
2575
|
+
buildDictionary(results) {
|
2576
|
+
return this.mapToDictionary(results, (result) => {
|
2577
|
+
return [result[this.morphId], result];
|
2578
|
+
});
|
2579
|
+
}
|
2580
|
+
/**
|
2581
|
+
* Make related models.
|
2582
|
+
*/
|
2583
|
+
make(elements) {
|
2584
|
+
return elements ? elements.map((element) => this.related.$newInstance(element)) : [];
|
2585
|
+
}
|
2586
|
+
}
|
2587
|
+
|
2588
|
+
var __defProp$2 = Object.defineProperty;
|
2589
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
2590
|
+
var __publicField$2 = (obj, key, value) => {
|
2591
|
+
__defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
2592
|
+
return value;
|
2593
|
+
};
|
2594
|
+
class HasManyThrough extends Relation {
|
2595
|
+
/**
|
2596
|
+
* Create a new has-many-through relation instance.
|
2597
|
+
*/
|
2598
|
+
constructor(parent, related, through, firstKey, secondKey, localKey, secondLocalKey) {
|
2599
|
+
super(parent, related);
|
2600
|
+
/**
|
2601
|
+
* The "through" parent model.
|
2602
|
+
*/
|
2603
|
+
__publicField$2(this, "through");
|
2604
|
+
/**
|
2605
|
+
* The near key on the relationship.
|
2606
|
+
*/
|
2607
|
+
__publicField$2(this, "firstKey");
|
2608
|
+
/**
|
2609
|
+
* The far key on the relationship.
|
2610
|
+
*/
|
2611
|
+
__publicField$2(this, "secondKey");
|
2612
|
+
/**
|
2613
|
+
* The local key on the relationship.
|
2614
|
+
*/
|
2615
|
+
__publicField$2(this, "localKey");
|
2616
|
+
/**
|
2617
|
+
* The local key on the intermediary model.
|
2618
|
+
*/
|
2619
|
+
__publicField$2(this, "secondLocalKey");
|
2620
|
+
this.through = through;
|
2621
|
+
this.firstKey = firstKey;
|
2622
|
+
this.secondKey = secondKey;
|
2623
|
+
this.localKey = localKey;
|
2624
|
+
this.secondLocalKey = secondLocalKey;
|
2625
|
+
}
|
2626
|
+
/**
|
2627
|
+
* Get all related models for the relationship.
|
2628
|
+
*/
|
2629
|
+
getRelateds() {
|
2630
|
+
return [this.related, this.through];
|
2631
|
+
}
|
2632
|
+
/**
|
2633
|
+
* Define the normalizr schema for the relation.
|
2634
|
+
*/
|
2635
|
+
define(schema) {
|
2636
|
+
return schema.many(this.related, this.parent);
|
2637
|
+
}
|
2638
|
+
/**
|
2639
|
+
* Attach the relational key to the given data. Since has many through
|
2640
|
+
* relationship doesn't have any foreign key, it would do nothing.
|
2641
|
+
*/
|
2642
|
+
attach(_record, _child) {
|
2643
|
+
}
|
2644
|
+
/**
|
2645
|
+
* Only register missing through relation
|
2646
|
+
*/
|
2647
|
+
addEagerConstraints(_query, _models) {
|
2648
|
+
}
|
2649
|
+
/**
|
2650
|
+
* Match the eagerly loaded results to their parents.
|
2651
|
+
*/
|
2652
|
+
match(relation, models, query) {
|
2653
|
+
const throughModels = query.newQuery(this.through.$entity()).where(this.firstKey, this.getKeys(models, this.localKey)).get(false);
|
2654
|
+
const relatedModels = query.where(this.secondKey, this.getKeys(throughModels, this.secondLocalKey)).groupBy(this.secondKey).get(false);
|
2655
|
+
const dictionary = this.buildDictionary(throughModels, relatedModels);
|
2656
|
+
models.forEach((model) => {
|
2657
|
+
const key = model[this.localKey];
|
2658
|
+
dictionary[key] ? model.$setRelation(relation, dictionary[key][0]) : model.$setRelation(relation, []);
|
2659
|
+
});
|
2660
|
+
}
|
2661
|
+
/**
|
2662
|
+
* Build model dictionary keyed by the relation's foreign key.
|
2663
|
+
*/
|
2664
|
+
buildDictionary(throughResults, results) {
|
2665
|
+
return this.mapToDictionary(throughResults, (throughResult) => {
|
2666
|
+
return [throughResult[this.firstKey], results[throughResult[this.secondLocalKey]]];
|
2667
|
+
});
|
2668
|
+
}
|
2669
|
+
/**
|
2670
|
+
* Make related models.
|
2671
|
+
*/
|
2672
|
+
make(elements) {
|
2673
|
+
return elements ? elements.map((element) => this.related.$newInstance(element)) : [];
|
2674
|
+
}
|
2675
|
+
}
|
2676
|
+
|
2677
|
+
var __defProp$1 = Object.defineProperty;
|
2678
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
2679
|
+
var __publicField$1 = (obj, key, value) => {
|
2680
|
+
__defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
2681
|
+
return value;
|
2682
|
+
};
|
2683
|
+
class MorphToMany extends Relation {
|
2684
|
+
/**
|
2685
|
+
* Create a new morph to many to instance.
|
2686
|
+
*/
|
2687
|
+
constructor(parent, related, pivot, relatedId, morphId, morphType, parentKey, relatedKey) {
|
2688
|
+
super(parent, related);
|
2689
|
+
/**
|
2690
|
+
* The pivot model.
|
2691
|
+
*/
|
2692
|
+
__publicField$1(this, "pivot");
|
2693
|
+
/**
|
2694
|
+
* The field name that contains id of the parent model.
|
2695
|
+
*/
|
2696
|
+
__publicField$1(this, "morphId");
|
2697
|
+
/**
|
2698
|
+
* The field name that contains type of the parent model.
|
2699
|
+
*/
|
2700
|
+
__publicField$1(this, "morphType");
|
2701
|
+
/**
|
2702
|
+
* The associated key of the relation.
|
2703
|
+
*/
|
2704
|
+
__publicField$1(this, "relatedId");
|
2705
|
+
/**
|
2706
|
+
* The key name of the parent model.
|
2707
|
+
*/
|
2708
|
+
__publicField$1(this, "parentKey");
|
2709
|
+
/**
|
2710
|
+
* The key name of the related model.
|
2711
|
+
*/
|
2712
|
+
__publicField$1(this, "relatedKey");
|
2713
|
+
/**
|
2714
|
+
* The key name of the pivot data.
|
2715
|
+
*/
|
2716
|
+
__publicField$1(this, "pivotKey", "pivot");
|
2717
|
+
this.pivot = pivot;
|
2718
|
+
this.morphId = morphId;
|
2719
|
+
this.morphType = morphType;
|
2720
|
+
this.relatedId = relatedId;
|
2721
|
+
this.parentKey = parentKey;
|
2722
|
+
this.relatedKey = relatedKey;
|
2723
|
+
}
|
2724
|
+
/**
|
2725
|
+
* Get all related models for the relationship.
|
2726
|
+
*/
|
2727
|
+
getRelateds() {
|
2728
|
+
return [this.related, this.pivot];
|
2729
|
+
}
|
2730
|
+
/**
|
2731
|
+
* Define the normalizr schema for the relationship.
|
2732
|
+
*/
|
2733
|
+
define(schema) {
|
2734
|
+
return schema.many(this.related, this.parent);
|
2735
|
+
}
|
2736
|
+
/**
|
2737
|
+
* Attach the parent type and id to the given relation.
|
2738
|
+
*/
|
2739
|
+
attach(record, child) {
|
2740
|
+
const pivot = child.pivot ?? {};
|
2741
|
+
pivot[this.morphId] = record[this.parentKey];
|
2742
|
+
pivot[this.morphType] = this.parent.$entity();
|
2743
|
+
pivot[this.relatedId] = child[this.relatedKey];
|
2744
|
+
child[`pivot_${this.pivot.$entity()}`] = pivot;
|
2745
|
+
}
|
2746
|
+
/**
|
2747
|
+
* Convert given value to the appropriate value for the attribute.
|
2748
|
+
*/
|
2749
|
+
make(elements) {
|
2750
|
+
return elements ? elements.map((element) => this.related.$newInstance(element)) : [];
|
2751
|
+
}
|
2752
|
+
/**
|
2753
|
+
* Match the eagerly loaded results to their parents.
|
2754
|
+
*/
|
2755
|
+
match(relation, models, query) {
|
2756
|
+
const relatedModels = query.get(false);
|
2757
|
+
const pivotModels = query.newQuery(this.pivot.$entity()).whereIn(this.relatedId, this.getKeys(relatedModels, this.relatedKey)).whereIn(this.morphId, this.getKeys(models, this.parentKey)).groupBy(this.morphId, this.relatedId, this.morphType).get();
|
2758
|
+
models.forEach((parentModel) => {
|
2759
|
+
const relationResults = [];
|
2760
|
+
relatedModels.forEach((relatedModel) => {
|
2761
|
+
const pivot = pivotModels[`[${parentModel[this.parentKey]},${relatedModel[this.relatedKey]},${this.parent.$entity()}]`]?.[0] ?? null;
|
2762
|
+
const relatedModelCopy = relatedModel.$newInstance(relatedModel.$toJson());
|
2763
|
+
relatedModelCopy.$setRelation("pivot", pivot);
|
2764
|
+
if (pivot) {
|
2765
|
+
relationResults.push(relatedModelCopy);
|
2766
|
+
}
|
2767
|
+
});
|
2768
|
+
parentModel.$setRelation(relation, relationResults);
|
2769
|
+
});
|
2770
|
+
}
|
2771
|
+
/**
|
2772
|
+
* Set the constraints for the related relation.
|
2773
|
+
*/
|
2774
|
+
addEagerConstraints(_query, _collection) {
|
2775
|
+
}
|
2776
|
+
}
|
2777
|
+
|
2778
|
+
var __defProp = Object.defineProperty;
|
2779
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
2780
|
+
var __publicField = (obj, key, value) => {
|
2781
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
2782
|
+
return value;
|
2783
|
+
};
|
2784
|
+
class Model {
|
2785
|
+
/**
|
2786
|
+
* Create a new model instance.
|
2787
|
+
*/
|
2788
|
+
constructor(attributes, options = { operation: "set" }) {
|
2789
|
+
this.$boot();
|
2790
|
+
const fill = options.fill ?? true;
|
2791
|
+
fill && this.$fill(attributes, options);
|
2792
|
+
}
|
2793
|
+
/**
|
2794
|
+
* Create a new model fields definition.
|
2795
|
+
*/
|
2796
|
+
static fields() {
|
2797
|
+
return {};
|
2798
|
+
}
|
2799
|
+
/**
|
2800
|
+
* Build the schema by evaluating fields and registry.
|
2801
|
+
*/
|
2802
|
+
static initializeSchema() {
|
2803
|
+
this.schemas[this.entity] = {};
|
2804
|
+
this.fieldsOnDelete[this.entity] = this.fieldsOnDelete[this.entity] ?? {};
|
2805
|
+
const registry = {
|
2806
|
+
...this.fields(),
|
2807
|
+
...this.registries[this.entity]
|
2808
|
+
};
|
2809
|
+
for (const key in registry) {
|
2810
|
+
const attribute = registry[key];
|
2811
|
+
this.schemas[this.entity][key] = typeof attribute === "function" ? attribute() : attribute;
|
2812
|
+
if (this.fieldsOnDelete[this.entity][key]) {
|
2813
|
+
this.schemas[this.entity][key] = this.schemas[this.entity][key].onDelete(this.fieldsOnDelete[this.entity][key]);
|
2814
|
+
}
|
2815
|
+
}
|
2816
|
+
}
|
2817
|
+
/**
|
2818
|
+
* Set the attribute to the registry.
|
2819
|
+
*/
|
2820
|
+
static setRegistry(key, attribute) {
|
2821
|
+
if (!this.registries[this.entity]) {
|
2822
|
+
this.registries[this.entity] = {};
|
2823
|
+
}
|
2824
|
+
this.registries[this.entity][key] = attribute;
|
2825
|
+
return this;
|
2826
|
+
}
|
2827
|
+
/**
|
2828
|
+
* Set delete behaviour for relation field
|
2829
|
+
*/
|
2830
|
+
static setFieldDeleteMode(key, mode) {
|
2831
|
+
this.fieldsOnDelete[this.entity] = this.fieldsOnDelete[this.entity] ?? {};
|
2832
|
+
this.fieldsOnDelete[this.entity][key] = mode;
|
2833
|
+
return this;
|
2834
|
+
}
|
2835
|
+
/**
|
2836
|
+
* Set an mutator for a field
|
2837
|
+
*/
|
2838
|
+
static setMutator(key, mutator) {
|
2839
|
+
this.fieldMutators[key] = mutator;
|
2840
|
+
return this;
|
2841
|
+
}
|
2842
|
+
/**
|
2843
|
+
* Set a cast for a field
|
2844
|
+
*/
|
2845
|
+
static setCast(key, to) {
|
2846
|
+
this.fieldCasts[key] = to;
|
2847
|
+
return this;
|
2848
|
+
}
|
2849
|
+
/**
|
2850
|
+
* Set a field to hidden
|
2851
|
+
*/
|
2852
|
+
static setHidden(key) {
|
2853
|
+
this.hidden.push(key);
|
2854
|
+
return this;
|
2855
|
+
}
|
2856
|
+
/**
|
2857
|
+
* Clear the list of booted models so they can be re-booted.
|
2858
|
+
*/
|
2859
|
+
static clearBootedModels() {
|
2860
|
+
this.booted = {};
|
2861
|
+
this.original = {};
|
2862
|
+
this.schemas = {};
|
2863
|
+
this.fieldMutators = {};
|
2864
|
+
this.fieldCasts = {};
|
2865
|
+
this.hidden = [];
|
2866
|
+
this.visible = [];
|
2867
|
+
}
|
2868
|
+
/**
|
2869
|
+
* Clear registries.
|
2870
|
+
*/
|
2871
|
+
static clearRegistries() {
|
2872
|
+
this.registries = {};
|
2873
|
+
}
|
2874
|
+
/**
|
2875
|
+
* Create a new model instance without field values being populated.
|
2876
|
+
*
|
2877
|
+
* This method is mainly for the internal use when registering models to the
|
2878
|
+
* database. Since all pre-registered models are for referencing its model
|
2879
|
+
* setting during the various process, but the fields are not required.
|
2880
|
+
*
|
2881
|
+
* Use this method when you want create a new model instance for:
|
2882
|
+
* - Registering model to a component (eg. Repository, Query, etc.)
|
2883
|
+
* - Registering model to attributes (String, Has Many, etc.)
|
2884
|
+
*/
|
2885
|
+
static newRawInstance() {
|
2886
|
+
return new this(void 0, { fill: false });
|
2887
|
+
}
|
2888
|
+
/**
|
2889
|
+
* Create a new Attr attribute instance.
|
2890
|
+
*/
|
2891
|
+
static attr(value) {
|
2892
|
+
return new Attr(this.newRawInstance(), value);
|
2893
|
+
}
|
2894
|
+
/**
|
2895
|
+
* Create a new String attribute instance.
|
2896
|
+
*/
|
2897
|
+
static string(value) {
|
2898
|
+
return new String$1(this.newRawInstance(), value);
|
2899
|
+
}
|
2900
|
+
/**
|
2901
|
+
* Create a new Number attribute instance.
|
2902
|
+
*/
|
2903
|
+
static number(value) {
|
2904
|
+
return new Number(this.newRawInstance(), value);
|
2905
|
+
}
|
2906
|
+
/**
|
2907
|
+
* Create a new Boolean attribute instance.
|
2908
|
+
*/
|
2909
|
+
static boolean(value) {
|
2910
|
+
return new Boolean(this.newRawInstance(), value);
|
2911
|
+
}
|
2912
|
+
/**
|
2913
|
+
* Create a new Uid attribute instance.
|
2914
|
+
*/
|
2915
|
+
static uid(options) {
|
2916
|
+
return new Uid(this.newRawInstance(), options);
|
2917
|
+
}
|
2918
|
+
/**
|
2919
|
+
* Create a new HasOne relation instance.
|
2920
|
+
*/
|
2921
|
+
static hasOne(related, foreignKey, localKey) {
|
2922
|
+
const model = this.newRawInstance();
|
2923
|
+
localKey = localKey ?? model.$getKeyName();
|
2924
|
+
return new HasOne(model, related.newRawInstance(), foreignKey, localKey);
|
2925
|
+
}
|
2926
|
+
/**
|
2927
|
+
* Create a new BelongsTo relation instance.
|
2928
|
+
*/
|
2929
|
+
static belongsTo(related, foreignKey, ownerKey) {
|
2930
|
+
const instance = related.newRawInstance();
|
2931
|
+
ownerKey = ownerKey ?? instance.$getKeyName();
|
2932
|
+
return new BelongsTo(this.newRawInstance(), instance, foreignKey, ownerKey);
|
2933
|
+
}
|
2934
|
+
/**
|
2935
|
+
* Create a new HasMany relation instance.
|
2936
|
+
*/
|
2937
|
+
static belongsToMany(related, pivot, foreignPivotKey, relatedPivotKey, parentKey, relatedKey) {
|
2938
|
+
const instance = related.newRawInstance();
|
2939
|
+
const model = this.newRawInstance();
|
2940
|
+
const pivotInstance = pivot.newRawInstance();
|
2941
|
+
parentKey = parentKey ?? model.$getLocalKey();
|
2942
|
+
relatedKey = relatedKey ?? instance.$getLocalKey();
|
2943
|
+
this.schemas[related.entity][`pivot_${pivotInstance.$entity()}`] = new HasOne(instance, pivotInstance, relatedPivotKey, relatedKey);
|
2944
|
+
return new BelongsToMany(
|
2945
|
+
model,
|
2946
|
+
instance,
|
2947
|
+
pivotInstance,
|
2948
|
+
foreignPivotKey,
|
2949
|
+
relatedPivotKey,
|
2950
|
+
parentKey,
|
2951
|
+
relatedKey
|
2952
|
+
);
|
2953
|
+
}
|
2954
|
+
/**
|
2955
|
+
* Create a new MorphToMany relation instance.
|
2956
|
+
*/
|
2957
|
+
static morphToMany(related, pivot, relatedId, id, type, parentKey, relatedKey) {
|
2958
|
+
const instance = related.newRawInstance();
|
2959
|
+
const model = this.newRawInstance();
|
2960
|
+
const pivotInstance = pivot.newRawInstance();
|
2961
|
+
parentKey = parentKey ?? model.$getLocalKey();
|
2962
|
+
relatedKey = relatedKey ?? instance.$getLocalKey();
|
2963
|
+
this.schemas[related.entity][`pivot_${pivotInstance.$entity()}`] = new MorphOne(instance, pivotInstance, relatedId, model.$entity(), relatedKey);
|
2964
|
+
return new MorphToMany(
|
2965
|
+
model,
|
2966
|
+
instance,
|
2967
|
+
pivotInstance,
|
2968
|
+
relatedId,
|
2969
|
+
id,
|
2970
|
+
type,
|
2971
|
+
parentKey,
|
2972
|
+
relatedKey
|
2973
|
+
);
|
2974
|
+
}
|
2975
|
+
/**
|
2976
|
+
* Create a new HasMany relation instance.
|
2977
|
+
*/
|
2978
|
+
static hasMany(related, foreignKey, localKey) {
|
2979
|
+
const model = this.newRawInstance();
|
2980
|
+
localKey = localKey ?? model.$getKeyName();
|
2981
|
+
return new HasMany(model, related.newRawInstance(), foreignKey, localKey);
|
2982
|
+
}
|
2983
|
+
/**
|
2984
|
+
* Create a new HasManyBy relation instance.
|
2985
|
+
*/
|
2986
|
+
static hasManyBy(related, foreignKey, ownerKey) {
|
2987
|
+
const instance = related.newRawInstance();
|
2988
|
+
ownerKey = ownerKey ?? instance.$getLocalKey();
|
2989
|
+
return new HasManyBy(this.newRawInstance(), instance, foreignKey, ownerKey);
|
2990
|
+
}
|
2991
|
+
/**
|
2992
|
+
* Create a new HasMany relation instance.
|
2993
|
+
*/
|
2994
|
+
static hasManyThrough(related, through, firstKey, secondKey, localKey, secondLocalKey) {
|
2995
|
+
const model = this.newRawInstance();
|
2996
|
+
const throughModel = through.newRawInstance();
|
2997
|
+
localKey = localKey ?? model.$getLocalKey();
|
2998
|
+
secondLocalKey = secondLocalKey ?? throughModel.$getLocalKey();
|
2999
|
+
return new HasManyThrough(model, related.newRawInstance(), throughModel, firstKey, secondKey, localKey, secondLocalKey);
|
3000
|
+
}
|
3001
|
+
/**
|
3002
|
+
* Create a new MorphOne relation instance.
|
3003
|
+
*/
|
3004
|
+
static morphOne(related, id, type, localKey) {
|
3005
|
+
const model = this.newRawInstance();
|
3006
|
+
localKey = localKey ?? model.$getLocalKey();
|
3007
|
+
return new MorphOne(model, related.newRawInstance(), id, type, localKey);
|
3008
|
+
}
|
3009
|
+
/**
|
3010
|
+
* Create a new MorphTo relation instance.
|
3011
|
+
*/
|
3012
|
+
static morphTo(related, id, type, ownerKey = "") {
|
3013
|
+
const instance = this.newRawInstance();
|
3014
|
+
const relatedModels = related.map((model) => model.newRawInstance());
|
3015
|
+
return new MorphTo(instance, relatedModels, id, type, ownerKey);
|
3016
|
+
}
|
3017
|
+
/**
|
3018
|
+
* Create a new MorphMany relation instance.
|
3019
|
+
*/
|
3020
|
+
static morphMany(related, id, type, localKey) {
|
3021
|
+
const model = this.newRawInstance();
|
3022
|
+
localKey = localKey ?? model.$getLocalKey();
|
3023
|
+
return new MorphMany(model, related.newRawInstance(), id, type, localKey);
|
3024
|
+
}
|
3025
|
+
/**
|
3026
|
+
* Mutators to mutate matching fields when instantiating the model.
|
3027
|
+
*/
|
3028
|
+
static mutators() {
|
3029
|
+
return {};
|
3030
|
+
}
|
3031
|
+
/**
|
3032
|
+
* Casts to cast matching fields when instantiating the model.
|
3033
|
+
*/
|
3034
|
+
static casts() {
|
3035
|
+
return {};
|
3036
|
+
}
|
3037
|
+
/**
|
3038
|
+
* Types mapping used to dispatch entities based on their discriminator field
|
3039
|
+
*/
|
3040
|
+
static types() {
|
3041
|
+
return {};
|
3042
|
+
}
|
3043
|
+
/**
|
3044
|
+
* Get the constructor for this model.
|
3045
|
+
*/
|
3046
|
+
$self() {
|
3047
|
+
return this.constructor;
|
3048
|
+
}
|
3049
|
+
/**
|
3050
|
+
* Get the entity for this model.
|
3051
|
+
*/
|
3052
|
+
$entity() {
|
3053
|
+
return this.$self().entity;
|
3054
|
+
}
|
3055
|
+
/**
|
3056
|
+
* Get the model config.
|
3057
|
+
*/
|
3058
|
+
$config() {
|
3059
|
+
return this.$self().config;
|
3060
|
+
}
|
3061
|
+
/**
|
3062
|
+
* Get the namespace.
|
3063
|
+
*/
|
3064
|
+
$namespace() {
|
3065
|
+
return this.$self().namespace ?? config.model.namespace;
|
3066
|
+
}
|
3067
|
+
/**
|
3068
|
+
* Get the store name.
|
3069
|
+
*/
|
3070
|
+
$storeName() {
|
3071
|
+
return (this.$namespace() ? this.$namespace() + "/" : "") + this.$baseEntity();
|
3072
|
+
}
|
3073
|
+
/**
|
3074
|
+
* Get the base entity for this model.
|
3075
|
+
*/
|
3076
|
+
$baseEntity() {
|
3077
|
+
return this.$self().baseEntity ?? this.$entity();
|
3078
|
+
}
|
3079
|
+
/**
|
3080
|
+
* Get the type key for this model.
|
3081
|
+
*/
|
3082
|
+
$typeKey() {
|
3083
|
+
return this.$self().typeKey;
|
3084
|
+
}
|
3085
|
+
/**
|
3086
|
+
* Get the types for this model.
|
3087
|
+
*/
|
3088
|
+
$types() {
|
3089
|
+
return this.$self().types();
|
3090
|
+
}
|
3091
|
+
/**
|
3092
|
+
* Get the pinia options for this model.
|
3093
|
+
*/
|
3094
|
+
$piniaOptions() {
|
3095
|
+
return this.$self().piniaOptions;
|
3096
|
+
}
|
3097
|
+
/**
|
3098
|
+
* Get the primary key for this model.
|
3099
|
+
*/
|
3100
|
+
$primaryKey() {
|
3101
|
+
return this.$self().primaryKey;
|
3102
|
+
}
|
3103
|
+
/**
|
3104
|
+
* Get the model fields for this model.
|
3105
|
+
*/
|
3106
|
+
$fields() {
|
3107
|
+
return this.$self().schemas[this.$entity()];
|
3108
|
+
}
|
3109
|
+
/**
|
3110
|
+
* Get the model hidden fields
|
3111
|
+
*/
|
3112
|
+
$hidden() {
|
3113
|
+
return this.$self().hidden;
|
3114
|
+
}
|
3115
|
+
/**
|
3116
|
+
* Get the model visible fields
|
3117
|
+
*/
|
3118
|
+
$visible() {
|
3119
|
+
return this.$self().visible;
|
3120
|
+
}
|
3121
|
+
/**
|
3122
|
+
* Create a new instance of this model. This method provides a convenient way
|
3123
|
+
* to re-generate a fresh instance of this model. It's particularly useful
|
3124
|
+
* during hydration through Query operations.
|
3125
|
+
*/
|
3126
|
+
$newInstance(attributes, options) {
|
3127
|
+
const Self = this.$self();
|
3128
|
+
return new Self(attributes, options);
|
3129
|
+
}
|
3130
|
+
/**
|
3131
|
+
* Bootstrap this model.
|
3132
|
+
*/
|
3133
|
+
$boot() {
|
3134
|
+
if (!this.$self().booted[this.$entity()]) {
|
3135
|
+
this.$self().booted[this.$entity()] = true;
|
3136
|
+
this.$initializeSchema();
|
3137
|
+
}
|
3138
|
+
}
|
3139
|
+
/**
|
3140
|
+
* Build the schema by evaluating fields and registry.
|
3141
|
+
*/
|
3142
|
+
$initializeSchema() {
|
3143
|
+
this.$self().initializeSchema();
|
3144
|
+
}
|
3145
|
+
$casts() {
|
3146
|
+
return {
|
3147
|
+
...this.$getCasts(),
|
3148
|
+
...this.$self().fieldCasts
|
3149
|
+
};
|
3150
|
+
}
|
3151
|
+
/**
|
3152
|
+
* Fill this model by the given attributes. Missing fields will be populated
|
3153
|
+
* by the attributes default value.
|
3154
|
+
*/
|
3155
|
+
$fill(attributes = {}, options = {}) {
|
3156
|
+
const operation = options.operation ?? "get";
|
3157
|
+
const modelConfig = {
|
3158
|
+
...config.model,
|
3159
|
+
...this.$config()
|
3160
|
+
};
|
3161
|
+
modelConfig.withMeta && (this.$self().schemas[this.$entity()][this.$self().metaKey] = this.$self().attr({}));
|
3162
|
+
const fields = this.$fields();
|
3163
|
+
const fillRelation = options.relations ?? true;
|
3164
|
+
const mutators = {
|
3165
|
+
...this.$getMutators(),
|
3166
|
+
...this.$self().fieldMutators
|
3167
|
+
};
|
3168
|
+
for (const key in fields) {
|
3169
|
+
if (operation === "get" && !this.isFieldVisible(key, this.$hidden(), this.$visible(), options)) {
|
3170
|
+
continue;
|
3171
|
+
}
|
3172
|
+
const attr = fields[key];
|
3173
|
+
let value = attributes[key];
|
3174
|
+
if (attr instanceof Relation && !fillRelation) {
|
3175
|
+
continue;
|
3176
|
+
}
|
3177
|
+
const mutator = mutators?.[key];
|
3178
|
+
const cast = this.$casts()[key]?.newRawInstance(fields);
|
3179
|
+
if (mutator && operation === "get") {
|
3180
|
+
value = typeof mutator === "function" ? mutator(value) : typeof mutator.get === "function" ? mutator.get(value) : value;
|
3181
|
+
}
|
3182
|
+
if (cast && operation === "get") {
|
3183
|
+
value = cast.get(value);
|
3184
|
+
}
|
3185
|
+
let keyValue = this.$fillField(key, attr, value);
|
3186
|
+
if (mutator && typeof mutator !== "function" && operation === "set" && mutator.set) {
|
3187
|
+
keyValue = mutator.set(keyValue);
|
3188
|
+
}
|
3189
|
+
if (cast && operation === "set") {
|
3190
|
+
keyValue = cast.set(keyValue);
|
3191
|
+
}
|
3192
|
+
this[key] = this[key] ?? keyValue;
|
3193
|
+
}
|
3194
|
+
operation === "set" && (this.$self().original[this.$getKey(this, true)] = this.$getAttributes());
|
3195
|
+
modelConfig.withMeta && operation === "set" && this.$fillMeta(options.action);
|
3196
|
+
return this;
|
3197
|
+
}
|
3198
|
+
$fillMeta(action = "save") {
|
3199
|
+
const timestamp = Math.floor(Date.now() / 1e3);
|
3200
|
+
if (action === "save") {
|
3201
|
+
this[this.$self().metaKey] = {
|
3202
|
+
createdAt: timestamp,
|
3203
|
+
updatedAt: timestamp
|
3204
|
+
};
|
3205
|
+
}
|
3206
|
+
if (action === "update") {
|
3207
|
+
this[this.$self().metaKey].updatedAt = timestamp;
|
3208
|
+
}
|
3209
|
+
}
|
3210
|
+
/**
|
3211
|
+
* Fill the given attribute with a given value specified by the given key.
|
3212
|
+
*/
|
3213
|
+
$fillField(key, attr, value) {
|
3214
|
+
if (value !== void 0) {
|
3215
|
+
return attr instanceof MorphTo ? attr.setKey(key).make(value, this[attr.getType()]) : attr.setKey(key).make(value);
|
3216
|
+
}
|
3217
|
+
if (this[key] === void 0) {
|
3218
|
+
return attr.setKey(key).make();
|
3219
|
+
}
|
3220
|
+
}
|
3221
|
+
isFieldVisible(key, modelHidden, modelVisible, options) {
|
3222
|
+
const hidden = modelHidden.length > 0 ? modelHidden : config.model.hidden;
|
3223
|
+
const visible = [...modelVisible.length > 0 ? modelVisible : config.model.visible, String(this.$primaryKey())];
|
3224
|
+
const optionsVisible = options.visible ?? [];
|
3225
|
+
const optionsHidden = options.hidden ?? [];
|
3226
|
+
if ((hidden.includes("*") || hidden.includes(key)) && !optionsVisible.includes(key) || optionsHidden.includes(key)) {
|
3227
|
+
return false;
|
3228
|
+
}
|
3229
|
+
return (visible.includes("*") || visible.includes(key)) && !optionsHidden.includes(key) || optionsVisible.includes(key);
|
3230
|
+
}
|
3231
|
+
/**
|
3232
|
+
* Get the primary key field name.
|
3233
|
+
*/
|
3234
|
+
$getKeyName() {
|
3235
|
+
return this.$primaryKey();
|
3236
|
+
}
|
3237
|
+
/**
|
3238
|
+
* Get primary key value for the model. If the model has the composite key,
|
3239
|
+
* it will return an array of ids.
|
3240
|
+
*/
|
3241
|
+
$getKey(record, concatCompositeKey = false) {
|
3242
|
+
record = record ?? this;
|
3243
|
+
if (this.$hasCompositeKey()) {
|
3244
|
+
const compositeKey = this.$getCompositeKey(record);
|
3245
|
+
return concatCompositeKey ? "[" + compositeKey?.join(",") + "]" : compositeKey;
|
3246
|
+
}
|
3247
|
+
const id = record[this.$getKeyName()];
|
3248
|
+
return Utils.isNullish(id) ? null : id;
|
3249
|
+
}
|
3250
|
+
/**
|
3251
|
+
* Check whether the model has composite key.
|
3252
|
+
*/
|
3253
|
+
$hasCompositeKey() {
|
3254
|
+
return Utils.isArray(this.$getKeyName());
|
3255
|
+
}
|
3256
|
+
/**
|
3257
|
+
* Get the composite key values for the given model as an array of ids.
|
3258
|
+
*/
|
3259
|
+
$getCompositeKey(record) {
|
3260
|
+
let ids = [];
|
3261
|
+
this.$getKeyName().every((key) => {
|
3262
|
+
const id = record[key];
|
3263
|
+
if (Utils.isNullish(id)) {
|
3264
|
+
ids = null;
|
3265
|
+
return false;
|
3266
|
+
}
|
3267
|
+
ids.push(id);
|
3268
|
+
return true;
|
3269
|
+
});
|
3270
|
+
return ids === null ? null : ids;
|
3271
|
+
}
|
3272
|
+
/**
|
3273
|
+
* Get the index id of this model or for a given record.
|
3274
|
+
*/
|
3275
|
+
$getIndexId(record) {
|
3276
|
+
const target = record ?? this;
|
3277
|
+
const id = this.$getKey(target);
|
3278
|
+
Utils.assert(id !== null, [
|
3279
|
+
"The record is missing the primary key. If you want to persist record",
|
3280
|
+
"without the primary key, please define the primary key field with the",
|
3281
|
+
"`uid` attribute."
|
3282
|
+
]);
|
3283
|
+
return this.$stringifyId(id);
|
3284
|
+
}
|
3285
|
+
/**
|
3286
|
+
* Stringify the given id.
|
3287
|
+
*/
|
3288
|
+
$stringifyId(id) {
|
3289
|
+
return Utils.isArray(id) ? JSON.stringify(id) : String(id);
|
3290
|
+
}
|
3291
|
+
/**
|
3292
|
+
* Get the local key name for the model.
|
3293
|
+
*/
|
3294
|
+
$getLocalKey() {
|
3295
|
+
Utils.assert(!this.$hasCompositeKey(), [
|
3296
|
+
"Please provide the local key for the relationship. The model with the",
|
3297
|
+
"composite key can't infer its local key."
|
3298
|
+
]);
|
3299
|
+
return this.$getKeyName();
|
3300
|
+
}
|
3301
|
+
/**
|
3302
|
+
* Get the relation instance for the given relation name.
|
3303
|
+
*/
|
3304
|
+
$getRelation(name) {
|
3305
|
+
let relation = this.$fields()[name];
|
3306
|
+
const typeModels = Object.values(this.$types());
|
3307
|
+
typeModels.forEach((typeModel) => {
|
3308
|
+
if (relation === void 0) {
|
3309
|
+
relation = typeModel.fields()[name];
|
3310
|
+
}
|
3311
|
+
});
|
3312
|
+
Utils.assert(relation instanceof Relation, [
|
3313
|
+
`Relationship [${name}] on model [${this.$entity()}] not found.`
|
3314
|
+
]);
|
3315
|
+
return relation;
|
3316
|
+
}
|
3317
|
+
/**
|
3318
|
+
* Set the given relationship on the model.
|
3319
|
+
*/
|
3320
|
+
$setRelation(relation, model) {
|
3321
|
+
if (relation.includes("pivot")) {
|
3322
|
+
this.pivot = model;
|
3323
|
+
return this;
|
3324
|
+
}
|
3325
|
+
if (this.$fields()[relation]) {
|
3326
|
+
this[relation] = model;
|
3327
|
+
}
|
3328
|
+
return this;
|
3329
|
+
}
|
3330
|
+
/**
|
3331
|
+
* Get the mutators of the model
|
3332
|
+
*/
|
3333
|
+
$getMutators() {
|
3334
|
+
return this.$self().mutators();
|
3335
|
+
}
|
3336
|
+
/**
|
3337
|
+
* Get the casts of the model
|
3338
|
+
*/
|
3339
|
+
$getCasts() {
|
3340
|
+
return this.$self().casts();
|
3341
|
+
}
|
3342
|
+
/**
|
3343
|
+
* Get the original values of the model instance
|
3344
|
+
*/
|
3345
|
+
$getOriginal() {
|
3346
|
+
return this.$self().original[this.$getKey(this, true)];
|
3347
|
+
}
|
3348
|
+
/**
|
3349
|
+
* Return the model instance with its original state
|
3350
|
+
*/
|
3351
|
+
$refresh() {
|
3352
|
+
if (this.$isDirty()) {
|
3353
|
+
Object.entries(this.$getOriginal()).forEach((entry) => {
|
3354
|
+
this[entry[0]] = entry[1];
|
3355
|
+
});
|
3356
|
+
}
|
3357
|
+
return this;
|
3358
|
+
}
|
3359
|
+
/**
|
3360
|
+
* Checks if attributes were changed
|
3361
|
+
*/
|
3362
|
+
$isDirty($attribute) {
|
3363
|
+
const original = this.$getOriginal();
|
3364
|
+
if ($attribute) {
|
3365
|
+
if (!Object.keys(original).includes($attribute)) {
|
3366
|
+
Utils.throwError(['The property"', $attribute, '"does not exit in the model "', this.$entity(), '"']);
|
3367
|
+
}
|
3368
|
+
return !Utils.equals(this[$attribute], original[$attribute]);
|
3369
|
+
}
|
3370
|
+
return !Utils.equals(original, this.$getAttributes());
|
3371
|
+
}
|
3372
|
+
/**
|
3373
|
+
* Get the serialized model attributes.
|
3374
|
+
*/
|
3375
|
+
$getAttributes() {
|
3376
|
+
return this.$toJson(this, { relations: false });
|
3377
|
+
}
|
3378
|
+
/**
|
3379
|
+
* Serialize this model, or the given model, as POJO.
|
3380
|
+
*/
|
3381
|
+
$toJson(model, options = {}) {
|
3382
|
+
model = model ?? this;
|
3383
|
+
const fields = model.$fields();
|
3384
|
+
const withRelation = options.relations ?? true;
|
3385
|
+
const record = {};
|
3386
|
+
for (const key in fields) {
|
3387
|
+
const attr = fields[key];
|
3388
|
+
const value = model[key];
|
3389
|
+
if (!(attr instanceof Relation)) {
|
3390
|
+
record[key] = this.serializeValue(value);
|
3391
|
+
continue;
|
3392
|
+
}
|
3393
|
+
if (withRelation) {
|
3394
|
+
record[key] = this.serializeRelation(value);
|
3395
|
+
}
|
3396
|
+
}
|
3397
|
+
return record;
|
3398
|
+
}
|
3399
|
+
/**
|
3400
|
+
* Serialize the given value.
|
3401
|
+
*/
|
3402
|
+
serializeValue(value) {
|
3403
|
+
if (value === null) {
|
3404
|
+
return null;
|
3405
|
+
}
|
3406
|
+
if (Utils.isArray(value)) {
|
3407
|
+
return this.serializeArray(value);
|
3408
|
+
}
|
3409
|
+
if (typeof value === "object") {
|
3410
|
+
if (value instanceof Date && !isNaN(value.getTime()) && typeof value.toISOString === "function") {
|
3411
|
+
return value.toISOString();
|
3412
|
+
} else {
|
3413
|
+
return this.serializeObject(value);
|
3414
|
+
}
|
3415
|
+
}
|
3416
|
+
return value;
|
3417
|
+
}
|
3418
|
+
/**
|
3419
|
+
* Serialize the given array to JSON.
|
3420
|
+
*/
|
3421
|
+
serializeArray(value) {
|
3422
|
+
return value.map((v) => this.serializeValue(v));
|
3423
|
+
}
|
3424
|
+
/**
|
3425
|
+
* Serialize the given object to JSON.
|
3426
|
+
*/
|
3427
|
+
serializeObject(value) {
|
3428
|
+
const obj = {};
|
3429
|
+
for (const key in value) {
|
3430
|
+
obj[key] = this.serializeValue(value[key]);
|
3431
|
+
}
|
3432
|
+
return obj;
|
3433
|
+
}
|
3434
|
+
serializeRelation(relation) {
|
3435
|
+
if (relation === void 0) {
|
3436
|
+
return void 0;
|
3437
|
+
}
|
3438
|
+
if (relation === null) {
|
3439
|
+
return null;
|
3440
|
+
}
|
3441
|
+
return Utils.isArray(relation) ? relation.map((model) => model.$toJson()) : relation.$toJson();
|
3442
|
+
}
|
3443
|
+
}
|
3444
|
+
/**
|
3445
|
+
* The name of the model.
|
3446
|
+
*/
|
3447
|
+
__publicField(Model, "entity");
|
3448
|
+
/**
|
3449
|
+
* The reference to the base entity name if the class extends a base entity.
|
3450
|
+
*/
|
3451
|
+
__publicField(Model, "baseEntity");
|
3452
|
+
/**
|
3453
|
+
* Define a namespace if you have multiple equal entity names.
|
3454
|
+
* Resulting in "{namespace}/{entity}"
|
3455
|
+
*/
|
3456
|
+
__publicField(Model, "namespace");
|
3457
|
+
/**
|
3458
|
+
* The primary key for the model.
|
3459
|
+
*/
|
3460
|
+
__publicField(Model, "primaryKey", "id");
|
3461
|
+
/**
|
3462
|
+
* The meta key for the model.
|
3463
|
+
*/
|
3464
|
+
__publicField(Model, "metaKey", "_meta");
|
3465
|
+
/**
|
3466
|
+
* Hidden properties
|
3467
|
+
*/
|
3468
|
+
__publicField(Model, "hidden", ["_meta"]);
|
3469
|
+
/**
|
3470
|
+
* Visible properties
|
3471
|
+
*/
|
3472
|
+
__publicField(Model, "visible", []);
|
3473
|
+
/**
|
3474
|
+
* The global install options
|
3475
|
+
*/
|
3476
|
+
__publicField(Model, "config");
|
3477
|
+
/**
|
3478
|
+
* The type key for the model.
|
3479
|
+
*/
|
3480
|
+
__publicField(Model, "typeKey", "type");
|
3481
|
+
/**
|
3482
|
+
* Behaviour for relational fields on delete.
|
3483
|
+
*/
|
3484
|
+
__publicField(Model, "fieldsOnDelete", {});
|
3485
|
+
/**
|
3486
|
+
* Original model data.
|
3487
|
+
*/
|
3488
|
+
__publicField(Model, "original", {});
|
3489
|
+
/**
|
3490
|
+
* The schema for the model. It contains the result of the `fields`
|
3491
|
+
* method or the attributes defined by decorators.
|
3492
|
+
*/
|
3493
|
+
__publicField(Model, "schemas", {});
|
3494
|
+
/**
|
3495
|
+
* The registry for the model. It contains predefined model schema generated
|
3496
|
+
* by the property decorators and gets evaluated, and stored, on the `schema`
|
3497
|
+
* property when registering models to the database.
|
3498
|
+
*/
|
3499
|
+
__publicField(Model, "registries", {});
|
3500
|
+
/**
|
3501
|
+
* The pinia options for the model. It can contain options which will passed
|
3502
|
+
* to the 'defineStore' function of pinia.
|
3503
|
+
*/
|
3504
|
+
__publicField(Model, "piniaOptions", {});
|
3505
|
+
/**
|
3506
|
+
* The mutators for the model.
|
3507
|
+
*/
|
3508
|
+
__publicField(Model, "fieldMutators", {});
|
3509
|
+
/**
|
3510
|
+
* The casts for the model.
|
3511
|
+
*/
|
3512
|
+
__publicField(Model, "fieldCasts", {});
|
3513
|
+
/**
|
3514
|
+
* The array of booted models.
|
3515
|
+
*/
|
3516
|
+
__publicField(Model, "booted", {});
|
3517
|
+
/**
|
3518
|
+
* Lifecycle hook for before saving
|
3519
|
+
*/
|
3520
|
+
__publicField(Model, "saving", () => {
|
3521
|
+
});
|
3522
|
+
/**
|
3523
|
+
* Lifecycle hook for before updating
|
3524
|
+
*/
|
3525
|
+
__publicField(Model, "updating", () => {
|
3526
|
+
});
|
3527
|
+
/**
|
3528
|
+
* Lifecycle hook for before creating
|
3529
|
+
*/
|
3530
|
+
__publicField(Model, "creating", () => {
|
3531
|
+
});
|
3532
|
+
/**
|
3533
|
+
* Lifecycle hook for before deleting
|
3534
|
+
*/
|
3535
|
+
__publicField(Model, "deleting", () => {
|
3536
|
+
});
|
3537
|
+
/**
|
3538
|
+
* Lifecycle hook for after getting data
|
3539
|
+
*/
|
3540
|
+
__publicField(Model, "retrieved", () => {
|
3541
|
+
});
|
3542
|
+
/**
|
3543
|
+
* Lifecycle hook for after saved
|
3544
|
+
*/
|
3545
|
+
__publicField(Model, "saved", () => {
|
3546
|
+
});
|
3547
|
+
/**
|
3548
|
+
* Lifecycle hook for after updated
|
3549
|
+
*/
|
3550
|
+
__publicField(Model, "updated", () => {
|
3551
|
+
});
|
3552
|
+
/**
|
3553
|
+
* Lifecycle hook for after created
|
3554
|
+
*/
|
3555
|
+
__publicField(Model, "created", () => {
|
3556
|
+
});
|
3557
|
+
/**
|
3558
|
+
* Lifecycle hook for after deleted
|
3559
|
+
*/
|
3560
|
+
__publicField(Model, "deleted", () => {
|
3561
|
+
});
|
3562
|
+
|
3563
|
+
exports.CastAttribute = CastAttribute.CastAttribute;
|
3564
|
+
exports.Attribute = Attribute;
|
3565
|
+
exports.BelongsTo = BelongsTo;
|
3566
|
+
exports.BelongsToMany = BelongsToMany;
|
3567
|
+
exports.CONFIG_DEFAULTS = CONFIG_DEFAULTS;
|
3568
|
+
exports.Database = Database;
|
3569
|
+
exports.HasMany = HasMany;
|
3570
|
+
exports.HasManyBy = HasManyBy;
|
3571
|
+
exports.HasManyThrough = HasManyThrough;
|
3572
|
+
exports.HasOne = HasOne;
|
3573
|
+
exports.Interpreter = Interpreter;
|
3574
|
+
exports.Model = Model;
|
3575
|
+
exports.MorphMany = MorphMany;
|
3576
|
+
exports.MorphOne = MorphOne;
|
3577
|
+
exports.MorphTo = MorphTo;
|
3578
|
+
exports.MorphToMany = MorphToMany;
|
3579
|
+
exports.Query = Query;
|
3580
|
+
exports.Relation = Relation;
|
3581
|
+
exports.Repository = Repository;
|
3582
|
+
exports.Schema = Schema;
|
3583
|
+
exports.Type = Type;
|
3584
|
+
exports.config = config;
|
3585
|
+
exports.createORM = createORM;
|
3586
|
+
exports.definePiniaOrmPlugin = definePiniaOrmPlugin;
|
3587
|
+
exports.mapRepos = mapRepos;
|
3588
|
+
exports.plugins = plugins;
|
3589
|
+
exports.registerPlugins = registerPlugins;
|
3590
|
+
exports.useDataStore = useDataStore;
|
3591
|
+
exports.useRepo = useRepo;
|
3592
|
+
exports.useStoreActions = useStoreActions;
|