@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,231 @@
1
+ "use strict";
2
+ const require_runtime = require("../_virtual/_rolldown/runtime.js");
3
+ const require_lib_types = require("./types.js");
4
+ const require_lib_model = require("./model.js");
5
+ const require_lib_model_builder = require("./model-builder.js");
6
+ //#region src/lib/model-definition.ts
7
+ var require_model_definition = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
8
+ const assert = require("assert");
9
+ const util = require("util");
10
+ const EventEmitter = require("events").EventEmitter;
11
+ const traverse = require("neotraverse/legacy");
12
+ const ModelBaseClass = require_lib_model;
13
+ const ModelBuilder = require_lib_model_builder;
14
+ /**
15
+ * Model definition
16
+ */
17
+ module.exports = ModelDefinition;
18
+ /**
19
+ * Constructor for ModelDefinition
20
+ * @param {ModelBuilder} modelBuilder A model builder instance
21
+ * @param {String|Object} name The model name or the schema object
22
+ * @param {Object} properties The model properties, optional
23
+ * @param {Object} settings The model settings, optional
24
+ * @returns {ModelDefinition}
25
+ * @constructor
26
+ *
27
+ */
28
+ function ModelDefinition(modelBuilder, name, properties, settings) {
29
+ if (!(this instanceof ModelDefinition)) return new ModelDefinition(modelBuilder, name, properties, settings);
30
+ this.modelBuilder = modelBuilder || ModelBuilder.defaultInstance;
31
+ assert(name, "name is missing");
32
+ if (arguments.length === 2 && typeof name === "object") {
33
+ const schema = name;
34
+ this.name = schema.name;
35
+ this.rawProperties = schema.properties || {};
36
+ this.settings = schema.settings || {};
37
+ } else {
38
+ assert(typeof name === "string", "name must be a string");
39
+ this.name = name;
40
+ this.rawProperties = properties || {};
41
+ this.settings = settings || {};
42
+ }
43
+ this.relations = [];
44
+ this.properties = null;
45
+ this.build();
46
+ }
47
+ util.inherits(ModelDefinition, EventEmitter);
48
+ require_lib_types(ModelDefinition);
49
+ /**
50
+ * Return table name for specified `modelName`
51
+ * @param {String} connectorType The connector type, such as 'oracle' or 'mongodb'
52
+ */
53
+ ModelDefinition.prototype.tableName = function(connectorType) {
54
+ const settings = this.settings;
55
+ if (settings[connectorType]) return settings[connectorType].table || settings[connectorType].tableName || this.name;
56
+ else return this.name;
57
+ };
58
+ /**
59
+ * Return column name for specified modelName and propertyName
60
+ * @param {String} connectorType The connector type, such as 'oracle' or 'mongodb'
61
+ * @param propertyName The property name
62
+ * @returns {String} columnName
63
+ */
64
+ ModelDefinition.prototype.columnName = function(connectorType, propertyName) {
65
+ if (!propertyName) return propertyName;
66
+ this.build();
67
+ const property = this.properties[propertyName];
68
+ if (property && property[connectorType]) return property[connectorType].column || property[connectorType].columnName || propertyName;
69
+ else return propertyName;
70
+ };
71
+ /**
72
+ * Return column metadata for specified modelName and propertyName
73
+ * @param {String} connectorType The connector type, such as 'oracle' or 'mongodb'
74
+ * @param propertyName The property name
75
+ * @returns {Object} column metadata
76
+ */
77
+ ModelDefinition.prototype.columnMetadata = function(connectorType, propertyName) {
78
+ if (!propertyName) return propertyName;
79
+ this.build();
80
+ const property = this.properties[propertyName];
81
+ if (property && property[connectorType]) return property[connectorType];
82
+ else return null;
83
+ };
84
+ /**
85
+ * Return column names for specified modelName
86
+ * @param {String} connectorType The connector type, such as 'oracle' or 'mongodb'
87
+ * @returns {String[]} column names
88
+ */
89
+ ModelDefinition.prototype.columnNames = function(connectorType) {
90
+ this.build();
91
+ const props = this.properties;
92
+ const cols = [];
93
+ for (const p in props) if (props[p][connectorType]) cols.push(props[p][connectorType].column || props[p][connectorType].columnName || p);
94
+ else cols.push(p);
95
+ return cols;
96
+ };
97
+ /**
98
+ * Find the ID properties sorted by the index
99
+ * @returns {Object[]} property name/index for IDs
100
+ */
101
+ ModelDefinition.prototype.ids = function() {
102
+ if (this._ids) return this._ids;
103
+ const ids = [];
104
+ this.build();
105
+ const props = this.properties;
106
+ for (const key in props) {
107
+ let id = props[key].id;
108
+ if (!id) continue;
109
+ if (typeof id !== "number") id = 1;
110
+ ids.push({
111
+ name: key,
112
+ id,
113
+ property: props[key]
114
+ });
115
+ }
116
+ ids.sort(function(a, b) {
117
+ return a.id - b.id;
118
+ });
119
+ this._ids = ids;
120
+ return ids;
121
+ };
122
+ /**
123
+ * Find the ID column name
124
+ * @param {String} modelName The model name
125
+ * @returns {String} columnName for ID
126
+ */
127
+ ModelDefinition.prototype.idColumnName = function(connectorType) {
128
+ return this.columnName(connectorType, this.idName());
129
+ };
130
+ /**
131
+ * Find the ID property name
132
+ * @returns {String} property name for ID
133
+ */
134
+ ModelDefinition.prototype.idName = function() {
135
+ const id = this.ids()[0];
136
+ if (this.properties.id && this.properties.id.id) return "id";
137
+ else return id && id.name;
138
+ };
139
+ /**
140
+ * Find the ID property names sorted by the index
141
+ * @returns {String[]} property names for IDs
142
+ */
143
+ ModelDefinition.prototype.idNames = function() {
144
+ return this.ids().map(function(id) {
145
+ return id.name;
146
+ });
147
+ };
148
+ /**
149
+ *
150
+ * @returns {{}}
151
+ */
152
+ ModelDefinition.prototype.indexes = function() {
153
+ this.build();
154
+ const indexes = {};
155
+ if (this.settings.indexes) for (const i in this.settings.indexes) indexes[i] = this.settings.indexes[i];
156
+ for (const p in this.properties) if (this.properties[p].index) indexes[p + "_index"] = this.properties[p].index;
157
+ return indexes;
158
+ };
159
+ /**
160
+ * Build a model definition
161
+ * @param {Boolean} force Forcing rebuild
162
+ */
163
+ ModelDefinition.prototype.build = function(forceRebuild) {
164
+ if (forceRebuild) {
165
+ this.properties = null;
166
+ this.relations = [];
167
+ this._ids = null;
168
+ this.json = null;
169
+ }
170
+ if (this.properties) return this.properties;
171
+ this.properties = {};
172
+ for (const p in this.rawProperties) {
173
+ const prop = this.rawProperties[p];
174
+ const type = this.modelBuilder.resolveType(prop);
175
+ if (typeof type === "string") this.relations.push({
176
+ source: this.name,
177
+ target: type,
178
+ type: Array.isArray(prop) ? "hasMany" : "belongsTo",
179
+ as: p
180
+ });
181
+ else {
182
+ const typeDef = { type };
183
+ if (typeof prop === "object" && prop !== null) {
184
+ for (const a in prop) if (a !== "type") typeDef[a] = prop[a];
185
+ }
186
+ this.properties[p] = typeDef;
187
+ }
188
+ }
189
+ return this.properties;
190
+ };
191
+ /**
192
+ * Define a property
193
+ * @param {String} propertyName The property name
194
+ * @param {Object} propertyDefinition The property definition
195
+ */
196
+ ModelDefinition.prototype.defineProperty = function(propertyName, propertyDefinition) {
197
+ this.rawProperties[propertyName] = propertyDefinition;
198
+ this.build(true);
199
+ };
200
+ function isModelClass(cls) {
201
+ if (!cls) return false;
202
+ return cls.prototype instanceof ModelBaseClass;
203
+ }
204
+ ModelDefinition.prototype.toJSON = function(forceRebuild) {
205
+ if (forceRebuild) this.json = null;
206
+ if (this.json) return this.json;
207
+ const json = {
208
+ name: this.name,
209
+ properties: {},
210
+ settings: this.settings
211
+ };
212
+ this.build(forceRebuild);
213
+ const mapper = function(val) {
214
+ if (val === void 0 || val === null) return val;
215
+ if ("function" === typeof val.toJSON) return val.toJSON();
216
+ if ("function" === typeof val) {
217
+ if (isModelClass(val)) if (val.settings && val.settings.anonymous) return val.definition && val.definition.toJSON().properties;
218
+ else return val.modelName;
219
+ return val.name;
220
+ } else return val;
221
+ };
222
+ for (const p in this.properties) json.properties[p] = traverse(this.properties[p]).map(mapper);
223
+ this.json = json;
224
+ return json;
225
+ };
226
+ ModelDefinition.prototype.hasPK = function() {
227
+ return this.ids().length > 0;
228
+ };
229
+ }));
230
+ //#endregion
231
+ module.exports = require_model_definition();
@@ -0,0 +1,368 @@
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.js");
2
+ const require_lib_globalize = require("./globalize.js");
3
+ const require_lib_geo = require("./geo.js");
4
+ const require_lib_utils = require("./utils.js");
5
+ require("./model.js");
6
+ //#region src/lib/model-utils.ts
7
+ var require_model_utils = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
8
+ module.exports = ModelUtils;
9
+ /*!
10
+ * Module dependencies
11
+ */
12
+ const g = require_lib_globalize();
13
+ const geo = require_lib_geo;
14
+ const { fieldsToArray, sanitizeQuery: sanitizeQueryOrData, isPlainObject, isClass, toRegExp } = require_lib_utils;
15
+ /**
16
+ * A mixin to contain utility methods for DataAccessObject
17
+ */
18
+ function ModelUtils() {}
19
+ /**
20
+ * Verify if allowExtendedOperators is enabled
21
+ * @options {Object} [options] Optional options to use.
22
+ * @property {Boolean} allowExtendedOperators.
23
+ * @returns {Boolean} Returns `true` if allowExtendedOperators is enabled, else `false`.
24
+ */
25
+ ModelUtils._allowExtendedOperators = function(options) {
26
+ const flag = this._getSetting("allowExtendedOperators", options);
27
+ if (flag != null) return !!flag;
28
+ return false;
29
+ };
30
+ /**
31
+ * Get settings via hierarchical determination
32
+ * - method level options
33
+ * - model level settings
34
+ * - data source level settings
35
+ *
36
+ * @param {String} key The setting key
37
+ */
38
+ ModelUtils._getSetting = function(key, options) {
39
+ let val = options && options[key];
40
+ if (val !== void 0) return val;
41
+ const m = this.definition;
42
+ if (m && m.settings) {
43
+ val = m.settings[key];
44
+ if (val !== void 0) return m.settings[key];
45
+ }
46
+ const ds = this.getDataSource();
47
+ if (ds && ds.settings) return ds.settings[key];
48
+ };
49
+ const operators = {
50
+ eq: "=",
51
+ gt: ">",
52
+ gte: ">=",
53
+ lt: "<",
54
+ lte: "<=",
55
+ between: "BETWEEN",
56
+ inq: "IN",
57
+ nin: "NOT IN",
58
+ neq: "!=",
59
+ like: "LIKE",
60
+ nlike: "NOT LIKE",
61
+ ilike: "ILIKE",
62
+ nilike: "NOT ILIKE",
63
+ regexp: "REGEXP"
64
+ };
65
+ ModelUtils._normalize = function(filter, options) {
66
+ if (!filter) return;
67
+ let err = null;
68
+ if (typeof filter !== "object" || Array.isArray(filter)) {
69
+ err = new Error(g.f("The query filter %j is not an {{object}}", filter));
70
+ err.statusCode = 400;
71
+ throw err;
72
+ }
73
+ if (filter.limit || filter.skip || filter.offset) {
74
+ const limit = Number(filter.limit || 100);
75
+ const offset = Number(filter.skip || filter.offset || 0);
76
+ if (isNaN(limit) || limit <= 0 || Math.ceil(limit) !== limit) {
77
+ err = new Error(g.f("The {{limit}} parameter %j is not valid", filter.limit));
78
+ err.statusCode = 400;
79
+ throw err;
80
+ }
81
+ if (isNaN(offset) || offset < 0 || Math.ceil(offset) !== offset) {
82
+ err = new Error(g.f("The {{offset/skip}} parameter %j is not valid", filter.skip || filter.offset));
83
+ err.statusCode = 400;
84
+ throw err;
85
+ }
86
+ filter.limit = limit;
87
+ filter.offset = offset;
88
+ filter.skip = offset;
89
+ }
90
+ if (filter.order) {
91
+ let order = filter.order;
92
+ if (!Array.isArray(order)) order = [order];
93
+ const fields = [];
94
+ for (let i = 0, m = order.length; i < m; i++) if (typeof order[i] === "string") {
95
+ const tokens = order[i].split(/(?:\s*,\s*)+/);
96
+ for (let t = 0, n = tokens.length; t < n; t++) {
97
+ let token = tokens[t];
98
+ if (token.length === 0) continue;
99
+ const parts = token.split(/\s+/);
100
+ if (parts.length >= 2) {
101
+ const dir = parts[1].toUpperCase();
102
+ if (dir === "ASC" || dir === "DESC") token = parts[0] + " " + dir;
103
+ else {
104
+ err = new Error(g.f("The {{order}} %j has invalid direction", token));
105
+ err.statusCode = 400;
106
+ throw err;
107
+ }
108
+ }
109
+ fields.push(token);
110
+ }
111
+ } else {
112
+ err = new Error(g.f("The order %j is not valid", order[i]));
113
+ err.statusCode = 400;
114
+ throw err;
115
+ }
116
+ if (fields.length === 1 && typeof filter.order === "string") filter.order = fields[0];
117
+ else filter.order = fields;
118
+ }
119
+ if (filter.fields) filter.fields = fieldsToArray(filter.fields, Object.keys(this.definition.properties), this.settings.strict);
120
+ filter = this._sanitizeQuery(filter, options);
121
+ this._coerce(filter.where, options);
122
+ return filter;
123
+ };
124
+ function DateType(arg) {
125
+ const d = new Date(arg);
126
+ if (isNaN(d.getTime())) throw new Error(g.f("Invalid date: %s", arg));
127
+ return d;
128
+ }
129
+ function BooleanType(arg) {
130
+ if (typeof arg === "string") switch (arg) {
131
+ case "true":
132
+ case "1": return true;
133
+ case "false":
134
+ case "0": return false;
135
+ }
136
+ if (arg == null) return null;
137
+ return Boolean(arg);
138
+ }
139
+ function NumberType(val) {
140
+ const num = Number(val);
141
+ return !isNaN(num) ? num : val;
142
+ }
143
+ function coerceArray(val) {
144
+ if (Array.isArray(val)) return val;
145
+ if (!isPlainObject(val)) throw new Error(g.f("Value is not an {{array}} or {{object}} with sequential numeric indices"));
146
+ const props = Object.keys(val);
147
+ if (props.length === 0) throw new Error(g.f("Value is an empty {{object}}"));
148
+ const arrayVal = Array.from({ length: props.length });
149
+ for (let i = 0; i < arrayVal.length; ++i) {
150
+ if (!val.hasOwnProperty(i)) throw new Error(g.f("Value is not an {{array}} or {{object}} with sequential numeric indices"));
151
+ arrayVal[i] = val[i];
152
+ }
153
+ return arrayVal;
154
+ }
155
+ function _normalizeAsArray(result) {
156
+ if (typeof result === "string") result = [result];
157
+ if (Array.isArray(result)) return result;
158
+ else {
159
+ const keys = [];
160
+ for (const k in result) if (result[k]) keys.push(k);
161
+ return keys;
162
+ }
163
+ }
164
+ /**
165
+ * Get an array of hidden property names
166
+ */
167
+ ModelUtils._getHiddenProperties = function() {
168
+ const settings = this.definition.settings || {};
169
+ return _normalizeAsArray(settings.hiddenProperties || settings.hidden || []);
170
+ };
171
+ /**
172
+ * Get an array of protected property names
173
+ */
174
+ ModelUtils._getProtectedProperties = function() {
175
+ const settings = this.definition.settings || {};
176
+ return _normalizeAsArray(settings.protectedProperties || settings.protected || []);
177
+ };
178
+ /**
179
+ * Get the maximum depth of a query object
180
+ */
181
+ ModelUtils._getMaxDepthOfQuery = function(options, defaultValue) {
182
+ options = options || {};
183
+ let maxDepth = this._getSetting("maxDepthOfQuery", options);
184
+ if (maxDepth == null) maxDepth = defaultValue || 32;
185
+ return +maxDepth;
186
+ };
187
+ /**
188
+ * Get the maximum depth of a data object
189
+ */
190
+ ModelUtils._getMaxDepthOfData = function(options, defaultValue) {
191
+ options = options || {};
192
+ let maxDepth = this._getSetting("maxDepthOfData", options);
193
+ if (maxDepth == null) maxDepth = defaultValue || 64;
194
+ return +maxDepth;
195
+ };
196
+ /**
197
+ * Get the prohibitHiddenPropertiesInQuery flag
198
+ */
199
+ ModelUtils._getProhibitHiddenPropertiesInQuery = function(options, defaultValue) {
200
+ const flag = this._getSetting("prohibitHiddenPropertiesInQuery", options);
201
+ if (flag == null) return !!defaultValue;
202
+ return !!flag;
203
+ };
204
+ /**
205
+ * Sanitize the query object
206
+ */
207
+ ModelUtils._sanitizeQuery = function(query, options) {
208
+ options = options || {};
209
+ const normalizeUndefinedInQuery = this._getSetting("normalizeUndefinedInQuery", options);
210
+ const prohibitHiddenPropertiesInQuery = this._getProhibitHiddenPropertiesInQuery(options);
211
+ const maxDepthOfQuery = this._getMaxDepthOfQuery(options);
212
+ let prohibitedKeys = [];
213
+ if (prohibitHiddenPropertiesInQuery) {
214
+ prohibitedKeys = this._getHiddenProperties();
215
+ if (options.prohibitProtectedPropertiesInQuery) prohibitedKeys = prohibitedKeys.concat(this._getProtectedProperties());
216
+ }
217
+ return sanitizeQueryOrData(query, Object.assign({
218
+ maxDepth: maxDepthOfQuery,
219
+ prohibitedKeys,
220
+ normalizeUndefinedInQuery
221
+ }, options));
222
+ };
223
+ /**
224
+ * Sanitize the data object
225
+ */
226
+ ModelUtils._sanitizeData = function(data, options) {
227
+ options = options || {};
228
+ return sanitizeQueryOrData(data, Object.assign({ maxDepth: this._getMaxDepthOfData(options) }, options));
229
+ };
230
+ ModelUtils._coerce = function(where, options, modelDef) {
231
+ const self = this;
232
+ if (where == null) return where;
233
+ options = options || {};
234
+ let err;
235
+ if (typeof where !== "object" || Array.isArray(where)) {
236
+ err = new Error(g.f("The where clause %j is not an {{object}}", where));
237
+ err.statusCode = 400;
238
+ throw err;
239
+ }
240
+ let props;
241
+ if (modelDef && modelDef.properties) props = modelDef.properties;
242
+ else props = self.definition.properties;
243
+ for (const p in where) {
244
+ if (p === "and" || p === "or" || p === "nor") {
245
+ let clauses = where[p];
246
+ try {
247
+ clauses = coerceArray(clauses);
248
+ } catch (e) {
249
+ err = new Error(g.f("The %s operator has invalid clauses %j: %s", p, clauses, e.message));
250
+ err.statusCode = 400;
251
+ throw err;
252
+ }
253
+ for (let k = 0; k < clauses.length; k++) self._coerce(clauses[k], options);
254
+ where[p] = clauses;
255
+ continue;
256
+ }
257
+ let DataType = props[p] && props[p].type;
258
+ if (!DataType) continue;
259
+ if ((Array.isArray(DataType) || DataType === Array) && !isNestedModel(DataType)) DataType = DataType[0];
260
+ if (DataType === Date) DataType = DateType;
261
+ else if (DataType === Boolean) DataType = BooleanType;
262
+ else if (DataType === Number) DataType = NumberType;
263
+ if (!DataType) continue;
264
+ if (DataType === geo.GeoPoint) continue;
265
+ let val = where[p];
266
+ if (val === null || val === void 0) continue;
267
+ let operator = null;
268
+ const exp = val;
269
+ if (val.constructor === Object) {
270
+ for (const op in operators) if (op in val) {
271
+ val = val[op];
272
+ operator = op;
273
+ switch (operator) {
274
+ case "inq":
275
+ case "nin":
276
+ case "between":
277
+ try {
278
+ val = coerceArray(val);
279
+ } catch (e) {
280
+ err = new Error(g.f("The %s property has invalid clause %j: %s", p, where[p], e));
281
+ err.statusCode = 400;
282
+ throw err;
283
+ }
284
+ if (operator === "between" && val.length !== 2) {
285
+ err = new Error(g.f("The %s property has invalid clause %j: Expected precisely 2 values, received %d", p, where[p], val.length));
286
+ err.statusCode = 400;
287
+ throw err;
288
+ }
289
+ break;
290
+ case "like":
291
+ case "nlike":
292
+ case "ilike":
293
+ case "nilike":
294
+ if (!(typeof val === "string" || val instanceof RegExp)) {
295
+ err = new Error(g.f("The %s property has invalid clause %j: Expected a string or RegExp", p, where[p]));
296
+ err.statusCode = 400;
297
+ throw err;
298
+ }
299
+ break;
300
+ case "regexp":
301
+ val = toRegExp(val);
302
+ if (val instanceof Error) {
303
+ val.statusCode = 400;
304
+ throw val;
305
+ }
306
+ break;
307
+ }
308
+ break;
309
+ }
310
+ }
311
+ try {
312
+ val = coerceArray(val);
313
+ } catch {}
314
+ const allowExtendedOperators = self._allowExtendedOperators(options);
315
+ if (Array.isArray(val) && !isNestedModel(DataType)) {
316
+ for (let i = 0; i < val.length; i++) if (val[i] !== null && val[i] !== void 0) {
317
+ if (!(val[i] instanceof RegExp)) val[i] = isClass(DataType) ? new DataType(val[i]) : DataType(val[i]);
318
+ }
319
+ } else if (val != null) if (operator === null && val instanceof RegExp) operator = "regexp";
320
+ else if (operator === "regexp" && val instanceof RegExp) {} else if ((operator === "like" || operator === "nlike" || operator === "ilike" || operator === "nilike") && val instanceof RegExp) {} else if (allowExtendedOperators && typeof val === "object") {} else {
321
+ if (!allowExtendedOperators) {
322
+ const extendedOperators = Object.keys(val).filter(function(k) {
323
+ return k[0] === "$";
324
+ });
325
+ if (extendedOperators.length) {
326
+ const msg = g.f("Operators \"" + extendedOperators.join(", ") + "\" are not allowed in query");
327
+ const err = new Error(msg);
328
+ err.code = "OPERATOR_NOT_ALLOWED_IN_QUERY";
329
+ err.statusCode = 400;
330
+ err.details = {
331
+ operators: extendedOperators,
332
+ where
333
+ };
334
+ throw err;
335
+ }
336
+ }
337
+ if (isNestedModel(DataType)) {
338
+ if (Array.isArray(DataType) && Array.isArray(val)) {
339
+ if (val === null || val === void 0) continue;
340
+ for (const it of val) self._coerce(it, options, DataType[0].definition);
341
+ } else self._coerce(val, options, DataType.definition);
342
+ continue;
343
+ } else val = isClass(DataType) ? new DataType(val) : DataType(val);
344
+ }
345
+ if (operator && operator !== "eq") {
346
+ const value = {};
347
+ value[operator] = val;
348
+ if (exp.options) value.options = exp.options;
349
+ val = value;
350
+ }
351
+ where[p] = val;
352
+ }
353
+ return where;
354
+ };
355
+ /**
356
+ * A utility function which checks for nested property definitions
357
+ *
358
+ * @param {*} propType Property type metadata
359
+ *
360
+ */
361
+ function isNestedModel(propType) {
362
+ if (!propType) return false;
363
+ if (Array.isArray(propType)) return isNestedModel(propType[0]);
364
+ return propType.hasOwnProperty("definition") && propType.definition.hasOwnProperty("properties");
365
+ }
366
+ }));
367
+ //#endregion
368
+ module.exports = require_model_utils();