@vsaas/loopback-datasource-juggler 10.0.0

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.
Files changed (63) hide show
  1. package/LICENSE +25 -0
  2. package/NOTICE +23 -0
  3. package/README.md +74 -0
  4. package/dist/_virtual/_rolldown/runtime.js +4 -0
  5. package/dist/index.js +26 -0
  6. package/dist/lib/browser.depd.js +13 -0
  7. package/dist/lib/case-utils.js +21 -0
  8. package/dist/lib/connectors/kv-memory.js +158 -0
  9. package/dist/lib/connectors/memory.js +810 -0
  10. package/dist/lib/connectors/transient.js +126 -0
  11. package/dist/lib/dao.js +2445 -0
  12. package/dist/lib/datasource.js +2215 -0
  13. package/dist/lib/date-string.js +87 -0
  14. package/dist/lib/geo.js +244 -0
  15. package/dist/lib/globalize.js +33 -0
  16. package/dist/lib/hooks.js +79 -0
  17. package/dist/lib/id-utils.js +66 -0
  18. package/dist/lib/include.js +795 -0
  19. package/dist/lib/include_utils.js +104 -0
  20. package/dist/lib/introspection.js +37 -0
  21. package/dist/lib/jutil.js +65 -0
  22. package/dist/lib/kvao/delete-all.js +57 -0
  23. package/dist/lib/kvao/delete.js +43 -0
  24. package/dist/lib/kvao/expire.js +35 -0
  25. package/dist/lib/kvao/get.js +34 -0
  26. package/dist/lib/kvao/index.js +28 -0
  27. package/dist/lib/kvao/iterate-keys.js +38 -0
  28. package/dist/lib/kvao/keys.js +55 -0
  29. package/dist/lib/kvao/set.js +39 -0
  30. package/dist/lib/kvao/ttl.js +35 -0
  31. package/dist/lib/list.js +101 -0
  32. package/dist/lib/mixins.js +58 -0
  33. package/dist/lib/model-builder.js +608 -0
  34. package/dist/lib/model-definition.js +231 -0
  35. package/dist/lib/model-utils.js +368 -0
  36. package/dist/lib/model.js +586 -0
  37. package/dist/lib/observer.js +235 -0
  38. package/dist/lib/relation-definition.js +2604 -0
  39. package/dist/lib/relations.js +587 -0
  40. package/dist/lib/scope.js +392 -0
  41. package/dist/lib/transaction.js +183 -0
  42. package/dist/lib/types.js +58 -0
  43. package/dist/lib/utils.js +625 -0
  44. package/dist/lib/validations.js +742 -0
  45. package/dist/package.js +93 -0
  46. package/package.json +85 -0
  47. package/types/common.d.ts +28 -0
  48. package/types/connector.d.ts +52 -0
  49. package/types/datasource.d.ts +324 -0
  50. package/types/date-string.d.ts +21 -0
  51. package/types/inclusion-mixin.d.ts +44 -0
  52. package/types/index.d.ts +36 -0
  53. package/types/kv-model.d.ts +201 -0
  54. package/types/model.d.ts +368 -0
  55. package/types/observer-mixin.d.ts +174 -0
  56. package/types/persisted-model.d.ts +505 -0
  57. package/types/query.d.ts +108 -0
  58. package/types/relation-mixin.d.ts +577 -0
  59. package/types/relation.d.ts +301 -0
  60. package/types/scope.d.ts +92 -0
  61. package/types/transaction-mixin.d.ts +47 -0
  62. package/types/types.d.ts +65 -0
  63. package/types/validation-mixin.d.ts +287 -0
@@ -0,0 +1,586 @@
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.js");
2
+ const require_lib_globalize = require("./globalize.js");
3
+ const require_lib_jutil = require("./jutil.js");
4
+ const require_lib_utils = require("./utils.js");
5
+ const require_lib_list = require("./list.js");
6
+ const require_lib_model_utils = require("./model-utils.js");
7
+ const require_lib_observer = require("./observer.js");
8
+ const require_lib_hooks = require("./hooks.js");
9
+ const require_lib_validations = require("./validations.js");
10
+ const require_lib_id_utils = require("./id-utils.js");
11
+ //#region src/lib/model.ts
12
+ var require_model = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
13
+ /*!
14
+ * Module exports class Model
15
+ */
16
+ module.exports = ModelBaseClass;
17
+ /*!
18
+ * Module dependencies
19
+ */
20
+ const g = require_lib_globalize();
21
+ const util = require("util");
22
+ const jutil = require_lib_jutil;
23
+ const List = require_lib_list;
24
+ const DataAccessUtils = require_lib_model_utils;
25
+ const Observer = require_lib_observer;
26
+ const Hookable = require_lib_hooks;
27
+ const validations = require_lib_validations;
28
+ const utils = require_lib_utils;
29
+ const fieldsToArray = utils.fieldsToArray;
30
+ const { uuidV1, uuidV4, nanoid } = require_lib_id_utils;
31
+ const BASE_TYPES = {
32
+ String: true,
33
+ Boolean: true,
34
+ Number: true,
35
+ Date: true,
36
+ Text: true,
37
+ ObjectID: true
38
+ };
39
+ /**
40
+ * Model class: base class for all persistent objects.
41
+ *
42
+ * `ModelBaseClass` mixes `Validatable` and `Hookable` classes methods
43
+ *
44
+ * @class
45
+ * @param {Object} data Initial object data
46
+ * @param {Object} options An object to control the instantiation
47
+ * @returns {ModelBaseClass} an instance of the ModelBaseClass
48
+ */
49
+ function ModelBaseClass(data, options) {
50
+ options = options || {};
51
+ if (!("applySetters" in options)) options.applySetters = true;
52
+ if (!("applyDefaultValues" in options)) options.applyDefaultValues = true;
53
+ this._initProperties(data, options);
54
+ }
55
+ /**
56
+ * Initialize the model instance with a list of properties
57
+ * @param {Object} data The data object
58
+ * @param {Object} options An object to control the instantiation
59
+ * @property {Boolean} applySetters Controls if the setters will be applied
60
+ * @property {Boolean} applyDefaultValues Default attributes and values will be applied
61
+ * @property {Boolean} strict Set the instance level strict mode
62
+ * @property {Boolean} persisted Whether the instance has been persisted
63
+ * @private
64
+ */
65
+ ModelBaseClass.prototype._initProperties = function(data, options) {
66
+ const self = this;
67
+ const ctor = this.constructor;
68
+ if (typeof data !== "undefined" && data !== null && data.constructor && typeof data.constructor !== "function") throw new Error(g.f("Property name \"{{constructor}}\" is not allowed in %s data", ctor.modelName));
69
+ if (data instanceof ctor) data = data.toObject(false);
70
+ const properties = Object.assign({}, ctor.definition.properties);
71
+ data = data || {};
72
+ if (typeof ctor.applyProperties === "function") ctor.applyProperties(data);
73
+ options = options || {};
74
+ const applySetters = options.applySetters;
75
+ const applyDefaultValues = options.applyDefaultValues;
76
+ let strict = options.strict;
77
+ if (strict === void 0) strict = ctor.definition.settings.strict;
78
+ else if (strict === "throw") g.warn("Warning: Model %s, {{strict mode: `throw`}} has been removed, please use {{`strict: true`}} instead, which returns{{`Validation Error`}} for unknown properties,", ctor.modelName);
79
+ const persistUndefinedAsNull = ctor.definition.settings.persistUndefinedAsNull;
80
+ if (ctor.hideInternalProperties) {
81
+ Object.defineProperties(this, {
82
+ __cachedRelations: {
83
+ writable: true,
84
+ enumerable: false,
85
+ configurable: true,
86
+ value: {}
87
+ },
88
+ __data: {
89
+ writable: true,
90
+ enumerable: false,
91
+ configurable: true,
92
+ value: {}
93
+ },
94
+ __dataSource: {
95
+ writable: true,
96
+ enumerable: false,
97
+ configurable: true,
98
+ value: options.dataSource
99
+ },
100
+ __strict: {
101
+ writable: true,
102
+ enumerable: false,
103
+ configurable: true,
104
+ value: strict
105
+ },
106
+ __persisted: {
107
+ writable: true,
108
+ enumerable: false,
109
+ configurable: true,
110
+ value: false
111
+ }
112
+ });
113
+ if (strict) Object.defineProperty(this, "__unknownProperties", {
114
+ writable: true,
115
+ enumerable: false,
116
+ configrable: true,
117
+ value: []
118
+ });
119
+ } else {
120
+ this.__cachedRelations = {};
121
+ this.__data = {};
122
+ this.__dataSource = options.dataSource;
123
+ this.__strict = strict;
124
+ this.__persisted = false;
125
+ if (strict) this.__unknownProperties = [];
126
+ }
127
+ if (options.persisted !== void 0) this.__persisted = options.persisted === true;
128
+ if (data.__cachedRelations) this.__cachedRelations = data.__cachedRelations;
129
+ let keys = Object.keys(data);
130
+ if (Array.isArray(options.fields)) keys = keys.filter(function(k) {
131
+ return options.fields.indexOf(k) != -1;
132
+ });
133
+ let size = keys.length;
134
+ let p, propVal;
135
+ for (let k = 0; k < size; k++) {
136
+ p = keys[k];
137
+ propVal = data[p];
138
+ if (typeof propVal === "function") continue;
139
+ if (propVal === void 0 && persistUndefinedAsNull) propVal = null;
140
+ if (properties[p]) if (applySetters || properties[p].id) self[p] = propVal;
141
+ else self.__data[p] = propVal;
142
+ else if (ctor.relations[p]) {
143
+ const relationType = ctor.relations[p].type;
144
+ let modelTo;
145
+ if (!properties[p]) {
146
+ modelTo = ctor.relations[p].modelTo || ModelBaseClass;
147
+ const multiple = ctor.relations[p].multiple;
148
+ properties[p] = {
149
+ name: multiple ? "Array" : modelTo.modelName,
150
+ type: multiple ? [modelTo] : modelTo
151
+ };
152
+ }
153
+ if (relationType === "belongsTo" && propVal != null) {
154
+ self.__data[ctor.relations[p].keyFrom] = propVal[ctor.relations[p].keyTo];
155
+ if (ctor.relations[p].options.embedsProperties) {
156
+ const fields = fieldsToArray(ctor.relations[p].properties, modelTo.definition.properties, modelTo.settings.strict);
157
+ if (!~fields.indexOf(ctor.relations[p].keyTo)) fields.push(ctor.relations[p].keyTo);
158
+ self.__data[p] = new modelTo(propVal, {
159
+ fields,
160
+ applySetters: false,
161
+ persisted: options.persisted
162
+ });
163
+ }
164
+ }
165
+ self.__cachedRelations[p] = propVal;
166
+ } else if (strict === false || self.__cachedRelations[p]) {
167
+ self[p] = self.__data[p] = propVal !== void 0 ? propVal : self.__cachedRelations[p];
168
+ if (/\./.test(p)) throw new Error(g.f("Property names containing dot(s) are not supported. Model: %s, dynamic property: %s", this.constructor.modelName, p));
169
+ } else if (strict !== "filter") this.__unknownProperties.push(p);
170
+ }
171
+ keys = Object.keys(properties);
172
+ if (Array.isArray(options.fields)) keys = keys.filter(function(k) {
173
+ return options.fields.indexOf(k) != -1;
174
+ });
175
+ size = keys.length;
176
+ for (let k = 0; k < size; k++) {
177
+ p = keys[k];
178
+ propVal = self.__data[p];
179
+ const type = properties[p].type;
180
+ if (applyDefaultValues && propVal === void 0 && appliesDefaultsOnWrites(properties[p])) {
181
+ let def = properties[p]["default"];
182
+ if (def !== void 0) {
183
+ if (typeof def === "function") if (def === Date) def = /* @__PURE__ */ new Date();
184
+ else def = def();
185
+ else if (type.name === "Date" && def === "$now") def = /* @__PURE__ */ new Date();
186
+ self.__data[p] = propVal = def;
187
+ }
188
+ }
189
+ if (ignoresMatchedDefault(properties[p]) && properties[p].default === propVal) delete self.__data[p];
190
+ if (applyDefaultValues && propVal === void 0) {
191
+ const defn = properties[p].defaultFn;
192
+ switch (defn) {
193
+ case void 0: break;
194
+ case "guid":
195
+ case "uuid":
196
+ propVal = uuidV1();
197
+ break;
198
+ case "uuidv4":
199
+ propVal = uuidV4();
200
+ break;
201
+ case "now":
202
+ propVal = /* @__PURE__ */ new Date();
203
+ break;
204
+ case "shortid":
205
+ case "nanoid":
206
+ propVal = nanoid(9);
207
+ break;
208
+ default: g.warn("Unknown default value provider %s", defn);
209
+ }
210
+ if (propVal !== void 0) self.__data[p] = propVal;
211
+ }
212
+ if (propVal === void 0 && persistUndefinedAsNull) self.__data[p] = propVal = null;
213
+ if (!BASE_TYPES[type.name]) {
214
+ if (typeof self.__data[p] !== "object" && self.__data[p]) try {
215
+ self.__data[p] = JSON.parse(self.__data[p] + "");
216
+ } catch {
217
+ self.__data[p] = String(self.__data[p]);
218
+ }
219
+ if (type.prototype instanceof ModelBaseClass) {
220
+ if (!(self.__data[p] instanceof type) && typeof self.__data[p] === "object" && self.__data[p] !== null) {
221
+ self.__data[p] = new type(self.__data[p]);
222
+ utils.applyParentProperty(self.__data[p], this);
223
+ }
224
+ } else if (type.name === "Array" || Array.isArray(type)) {
225
+ if (!(self.__data[p] instanceof List) && self.__data[p] !== void 0 && self.__data[p] !== null) self.__data[p] = List(self.__data[p], type, self);
226
+ }
227
+ }
228
+ }
229
+ this.trigger("initialize");
230
+ };
231
+ function ignoresMatchedDefault(property) {
232
+ if (property && property.persistDefaultValues === false) return true;
233
+ }
234
+ function appliesDefaultsOnWrites(property) {
235
+ if (property && "applyDefaultOnWrites" in property) return property.applyDefaultOnWrites;
236
+ return true;
237
+ }
238
+ /**
239
+ * Define a property on the model.
240
+ * @param {String} prop Property name
241
+ * @param {Object} params Various property configuration
242
+ */
243
+ ModelBaseClass.defineProperty = function(prop, params) {
244
+ if (this.dataSource) this.dataSource.defineProperty(this.modelName, prop, params);
245
+ else this.modelBuilder.defineProperty(this.modelName, prop, params);
246
+ };
247
+ /**
248
+ * Get model property type.
249
+ * @param {String} propName Property name
250
+ * @returns {String} Name of property type
251
+ */
252
+ ModelBaseClass.getPropertyType = function(propName) {
253
+ const prop = this.definition.properties[propName];
254
+ if (!prop) return null;
255
+ if (!prop.type) throw new Error(g.f("Type not defined for property %s.%s", this.modelName, propName));
256
+ return prop.type.name;
257
+ };
258
+ /**
259
+ * Get model property type.
260
+ * @param {String} propName Property name
261
+ * @returns {String} Name of property type
262
+ */
263
+ ModelBaseClass.prototype.getPropertyType = function(propName) {
264
+ return this.constructor.getPropertyType(propName);
265
+ };
266
+ /**
267
+ * Return string representation of class
268
+ * This overrides the default `toString()` method
269
+ */
270
+ ModelBaseClass.toString = function() {
271
+ return "[Model " + this.modelName + "]";
272
+ };
273
+ /**
274
+ * Convert model instance to a plain JSON object.
275
+ * Returns a canonical object representation (no getters and setters).
276
+ *
277
+ * @param {Boolean} onlySchema Restrict properties to dataSource only. Default is false. If true, the function returns only properties defined in the schema; Otherwise it returns all enumerable properties.
278
+ * @param {Boolean} removeHidden Boolean flag as part of the transformation. If true, then hidden properties should not be brought out.
279
+ * @param {Boolean} removeProtected Boolean flag as part of the transformation. If true, then protected properties should not be brought out.
280
+ * @returns {Object} returns Plain JSON object
281
+ */
282
+ ModelBaseClass.prototype.toObject = function(onlySchema, removeHidden, removeProtected) {
283
+ if (typeof onlySchema === "object" && onlySchema != null) {
284
+ const options = onlySchema;
285
+ onlySchema = options.onlySchema;
286
+ removeHidden = options.removeHidden;
287
+ removeProtected = options.removeProtected;
288
+ }
289
+ if (onlySchema === void 0) onlySchema = true;
290
+ const data = {};
291
+ const self = this;
292
+ const Model = this.constructor;
293
+ if (Model === Object) return self;
294
+ const schemaLess = this.__strict === false || !onlySchema;
295
+ const persistUndefinedAsNull = Model.definition.settings.persistUndefinedAsNull;
296
+ const props = Model.definition.properties;
297
+ let keys = Object.keys(props);
298
+ let propertyName, val;
299
+ for (let i = 0; i < keys.length; i++) {
300
+ propertyName = keys[i];
301
+ val = self[propertyName];
302
+ if (typeof val === "function") continue;
303
+ if (removeHidden && Model.isHiddenProperty(propertyName)) continue;
304
+ if (removeProtected && Model.isProtectedProperty(propertyName)) continue;
305
+ if (val instanceof List) data[propertyName] = val.toObject(!schemaLess, removeHidden, true);
306
+ else if (val !== void 0 && val !== null && val.toObject) data[propertyName] = val.toObject(!schemaLess, removeHidden, true);
307
+ else {
308
+ if (val === void 0 && persistUndefinedAsNull) val = null;
309
+ data[propertyName] = val;
310
+ }
311
+ }
312
+ if (schemaLess) {
313
+ keys = Object.keys(self);
314
+ let size = keys.length;
315
+ for (let i = 0; i < size; i++) {
316
+ propertyName = keys[i];
317
+ if (props[propertyName]) continue;
318
+ if (propertyName.indexOf("__") === 0) continue;
319
+ if (removeHidden && Model.isHiddenProperty(propertyName)) continue;
320
+ if (removeProtected && Model.isProtectedProperty(propertyName)) continue;
321
+ if (data[propertyName] !== void 0) continue;
322
+ val = self[propertyName];
323
+ if (val !== void 0) {
324
+ if (typeof val === "function") continue;
325
+ if (val !== null && val.toObject) data[propertyName] = val.toObject(!schemaLess, removeHidden, true);
326
+ else data[propertyName] = val;
327
+ } else if (persistUndefinedAsNull) data[propertyName] = null;
328
+ }
329
+ keys = Object.keys(self.__data);
330
+ size = keys.length;
331
+ for (let i = 0; i < size; i++) {
332
+ propertyName = keys[i];
333
+ if (propertyName.indexOf("__") === 0) continue;
334
+ if (data[propertyName] === void 0) {
335
+ if (removeHidden && Model.isHiddenProperty(propertyName)) continue;
336
+ if (removeProtected && Model.isProtectedProperty(propertyName)) continue;
337
+ const ownVal = self[propertyName];
338
+ val = ownVal !== void 0 && typeof ownVal !== "function" ? ownVal : self.__data[propertyName];
339
+ if (typeof val === "function") continue;
340
+ if (val !== void 0 && val !== null && val.toObject) data[propertyName] = val.toObject(!schemaLess, removeHidden, true);
341
+ else if (val === void 0 && persistUndefinedAsNull) data[propertyName] = null;
342
+ else data[propertyName] = val;
343
+ }
344
+ }
345
+ }
346
+ return data;
347
+ };
348
+ /**
349
+ * Convert an array of strings into an object as the map
350
+ * @param {string[]} arr An array of strings
351
+ */
352
+ function asObjectMap(arr) {
353
+ const obj = {};
354
+ if (Array.isArray(arr)) {
355
+ for (let i = 0; i < arr.length; i++) obj[arr[i]] = true;
356
+ return obj;
357
+ }
358
+ return arr || obj;
359
+ }
360
+ /**
361
+ * Checks if property is protected.
362
+ * @param {String} propertyName Property name
363
+ * @returns {Boolean} true or false if protected or not.
364
+ */
365
+ ModelBaseClass.isProtectedProperty = function(propertyName) {
366
+ const settings = this.definition && this.definition.settings || {};
367
+ settings.protectedProperties = asObjectMap(settings.protectedProperties || settings.protected);
368
+ return settings.protectedProperties[propertyName];
369
+ };
370
+ /**
371
+ * Checks if property is hidden.
372
+ * @param {String} propertyName Property name
373
+ * @returns {Boolean} true or false if hidden or not.
374
+ */
375
+ ModelBaseClass.isHiddenProperty = function(propertyName) {
376
+ const settings = this.definition && this.definition.settings || {};
377
+ settings.hiddenProperties = asObjectMap(settings.hiddenProperties || settings.hidden);
378
+ return settings.hiddenProperties[propertyName];
379
+ };
380
+ ModelBaseClass.prototype.toJSON = function() {
381
+ return this.toObject(false, true, false);
382
+ };
383
+ ModelBaseClass.prototype.fromObject = function(obj) {
384
+ for (const key in obj) this[key] = obj[key];
385
+ };
386
+ /**
387
+ * Reset dirty attributes.
388
+ * This method does not perform any database operations; it just resets the object to its
389
+ * initial state.
390
+ */
391
+ ModelBaseClass.prototype.reset = function() {
392
+ const obj = this;
393
+ for (const k in obj) if (k !== "id" && !obj.constructor.dataSource.definitions[obj.constructor.modelName].properties[k]) delete obj[k];
394
+ };
395
+ const versionParts = process.versions && process.versions.node ? process.versions.node.split(/\./g).map(function(v) {
396
+ return +v;
397
+ }) : [
398
+ 1,
399
+ 0,
400
+ 0
401
+ ];
402
+ const INSPECT_SUPPORTS_OBJECT_RETVAL = versionParts[0] > 0 || versionParts[1] > 11 || versionParts[0] === 11 && versionParts[1] >= 14;
403
+ ModelBaseClass.prototype.inspect = function(depth) {
404
+ if (INSPECT_SUPPORTS_OBJECT_RETVAL) return this.__data;
405
+ return util.inspect(this.__data, {
406
+ showHidden: false,
407
+ depth,
408
+ colors: false
409
+ });
410
+ };
411
+ if (util.inspect.custom) ModelBaseClass.prototype[util.inspect.custom] = ModelBaseClass.prototype.inspect;
412
+ /**
413
+ *
414
+ * @param {String} anotherClass could be string or class. Name of the class or the class itself
415
+ * @param {Object} options An object to control the instantiation
416
+ * @returns {ModelClass}
417
+ */
418
+ ModelBaseClass.mixin = function(anotherClass, options) {
419
+ if (typeof anotherClass === "string") this.modelBuilder.mixins.applyMixin(this, anotherClass, options);
420
+ else {
421
+ if (anotherClass.prototype instanceof ModelBaseClass) {
422
+ const props = anotherClass.definition.properties;
423
+ for (const i in props) {
424
+ if (this.definition.properties[i]) continue;
425
+ this.defineProperty(i, props[i]);
426
+ }
427
+ }
428
+ return jutil.mixin(this, anotherClass, options);
429
+ }
430
+ };
431
+ ModelBaseClass.prototype.getDataSource = function() {
432
+ return this.__dataSource || this.constructor.dataSource;
433
+ };
434
+ ModelBaseClass.getDataSource = function() {
435
+ return this.dataSource;
436
+ };
437
+ ModelBaseClass.prototype.setStrict = function(strict) {
438
+ this.__strict = strict;
439
+ };
440
+ /**
441
+ *
442
+ * `getMergePolicy()` provides model merge policies to apply when extending
443
+ * a child model from a base model. Such a policy drives the way parent/child model
444
+ * properties/settings are merged/mixed-in together.
445
+ *
446
+ * Below is presented the expected merge behaviour for each option.
447
+ * NOTE: This applies to top-level settings properties
448
+ *
449
+ *
450
+ * - Any
451
+ * - `{replace: true}` (default): child replaces the value from parent
452
+ * - assignin `null` on child setting deletes the inherited setting
453
+ *
454
+ * - Arrays:
455
+ * - `{replace: false}`: unique elements of parent and child cumulate
456
+ * - `{rank: true}` adds the model inheritance rank to array
457
+ * elements of type Object {} as internal property `__rank`
458
+ *
459
+ * - Object {}:
460
+ * - `{replace: false}`: deep merges parent and child objects
461
+ * - `{patch: true}`: child replaces inner properties from parent
462
+ *
463
+ *
464
+ * The recommended built-in merge policy is as follows. It is returned by getMergePolicy()
465
+ * when calling the method with option `{configureModelMerge: true}`.
466
+ *
467
+ * ```
468
+ * {
469
+ * description: {replace: true}, // string or array
470
+ * options: {patch: true}, // object
471
+ * hidden: {replace: false}, // array
472
+ * protected: {replace: false}, // array
473
+ * indexes: {patch: true}, // object
474
+ * methods: {patch: true}, // object
475
+ * mixins: {patch: true}, // object
476
+ * relations: {patch: true}, // object
477
+ * scope: {replace: true}, // object
478
+ * scopes: {patch: true}, // object
479
+ * acls: {rank: true}, // array
480
+ * // this setting controls which child model property's value allows deleting
481
+ * // a base model's property
482
+ * __delete: null,
483
+ * // this setting controls the default merge behaviour for settings not defined
484
+ * // in the mergePolicy specification
485
+ * __default: {replace: true},
486
+ * }
487
+ * ```
488
+ *
489
+ * The legacy built-in merge policy is as follows, it is retuned by `getMergePolicy()`
490
+ * when avoiding option `configureModelMerge`.
491
+ * NOTE: it also provides the ACLs ranking in addition to the legacy behaviour, as well
492
+ * as fixes for settings 'description' and 'relations': matching relations from child
493
+ * replace relations from parents.
494
+ *
495
+ * ```
496
+ * {
497
+ * description: {replace: true}, // string or array
498
+ * properties: {patch: true}, // object
499
+ * hidden: {replace: false}, // array
500
+ * protected: {replace: false}, // array
501
+ * relations: {acls: true}, // object
502
+ * acls: {rank: true}, // array
503
+ * }
504
+ * ```
505
+ *
506
+ *
507
+ * `getMergePolicy()` can be customized using model's setting `configureModelMerge` as follows:
508
+ *
509
+ * ``` json
510
+ * {
511
+ * // ..
512
+ * options: {
513
+ * configureModelMerge: {
514
+ * // merge options
515
+ * }
516
+ * }
517
+ * // ..
518
+ * }
519
+ * ```
520
+ *
521
+ * NOTE: mergePolicy parameter can also defined at JSON model definition root
522
+ *
523
+ * `getMergePolicy()` method can also be extended programmatically as follows:
524
+ *
525
+ * ``` js
526
+ * myModel.getMergePolicy = function(options) {
527
+ * const origin = myModel.base.getMergePolicy(options);
528
+ * return Object.assign({}, origin, {
529
+ * // new/overriding options
530
+ * });
531
+ * };
532
+ * ```
533
+ *
534
+ * @param {Object} options option `configureModelMerge` can be used to alter the
535
+ * returned merge policy:
536
+ * - `configureModelMerge: true` will have the method return the recommended merge policy.
537
+ * - `configureModelMerge: {..}` will actually have the method return the provided object.
538
+ * - not providing this options will have the method return a merge policy emulating the
539
+ * the model merge behaviour up to datasource-juggler v3.6.1, as well as the ACLs ranking.
540
+ * @returns {Object} mergePolicy The model merge policy to apply when using the
541
+ * current model as base class for a child model
542
+ */
543
+ ModelBaseClass.getMergePolicy = function(options) {
544
+ let mergePolicy = {
545
+ description: { replace: true },
546
+ properties: { patch: true },
547
+ hidden: { replace: false },
548
+ protected: { replace: false },
549
+ relations: { patch: true },
550
+ acls: { rank: true }
551
+ };
552
+ const config = (options || {}).configureModelMerge;
553
+ if (config === true) mergePolicy = {
554
+ description: { replace: true },
555
+ options: { patch: true },
556
+ hidden: { replace: false },
557
+ protected: { replace: false },
558
+ indexes: { patch: true },
559
+ methods: { patch: true },
560
+ mixins: { patch: true },
561
+ relations: { patch: true },
562
+ scope: { replace: true },
563
+ scopes: { patch: true },
564
+ acls: { rank: true },
565
+ __delete: null,
566
+ __default: { replace: true }
567
+ };
568
+ if (config && typeof config === "object" && !Array.isArray(config)) mergePolicy = config;
569
+ return mergePolicy;
570
+ };
571
+ /**
572
+ * Gets properties defined with 'updateOnly' flag set to true from the model. This flag is also set to true
573
+ * internally for the id property, if this property is generated and IdInjection is true.
574
+ * @returns {updateOnlyProps} List of properties with updateOnly set to true.
575
+ */
576
+ ModelBaseClass.getUpdateOnlyProperties = function() {
577
+ const props = this.definition.properties;
578
+ return Object.keys(props).filter((key) => props[key].updateOnly);
579
+ };
580
+ jutil.mixin(ModelBaseClass, DataAccessUtils);
581
+ jutil.mixin(ModelBaseClass, Observer);
582
+ jutil.mixin(ModelBaseClass, Hookable);
583
+ jutil.mixin(ModelBaseClass, validations.Validatable);
584
+ }));
585
+ //#endregion
586
+ module.exports = require_model();