@twin.org/entity 0.0.2-next.9 → 0.0.3-next.2
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/dist/es/decorators/entityDecorator.js +19 -0
- package/dist/es/decorators/entityDecorator.js.map +1 -0
- package/dist/es/decorators/propertyDecorator.js +31 -0
- package/dist/es/decorators/propertyDecorator.js.map +1 -0
- package/dist/es/factories/entitySchemaFactory.js +9 -0
- package/dist/es/factories/entitySchemaFactory.js.map +1 -0
- package/dist/es/index.js +22 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/models/IComparator.js +2 -0
- package/dist/es/models/IComparator.js.map +1 -0
- package/dist/es/models/IComparatorGroup.js +2 -0
- package/dist/es/models/IComparatorGroup.js.map +1 -0
- package/dist/es/models/IEntitySchema.js +2 -0
- package/dist/es/models/IEntitySchema.js.map +1 -0
- package/dist/es/models/IEntitySchemaOptions.js +4 -0
- package/dist/es/models/IEntitySchemaOptions.js.map +1 -0
- package/dist/es/models/IEntitySchemaProperty.js +2 -0
- package/dist/es/models/IEntitySchemaProperty.js.map +1 -0
- package/dist/es/models/IEntitySort.js +2 -0
- package/dist/es/models/IEntitySort.js.map +1 -0
- package/dist/es/models/comparisonOperator.js +52 -0
- package/dist/es/models/comparisonOperator.js.map +1 -0
- package/dist/es/models/entityCondition.js +2 -0
- package/dist/es/models/entityCondition.js.map +1 -0
- package/dist/es/models/entitySchemaPropertyFormat.js +77 -0
- package/dist/es/models/entitySchemaPropertyFormat.js.map +1 -0
- package/dist/es/models/entitySchemaPropertyType.js +33 -0
- package/dist/es/models/entitySchemaPropertyType.js.map +1 -0
- package/dist/es/models/logicalOperator.js +17 -0
- package/dist/es/models/logicalOperator.js.map +1 -0
- package/dist/es/models/sortDirection.js +17 -0
- package/dist/es/models/sortDirection.js.map +1 -0
- package/dist/es/utils/decoratorHelper.js +29 -0
- package/dist/es/utils/decoratorHelper.js.map +1 -0
- package/dist/es/utils/entityConditions.js +175 -0
- package/dist/es/utils/entityConditions.js.map +1 -0
- package/dist/es/utils/entitySchemaHelper.js +143 -0
- package/dist/es/utils/entitySchemaHelper.js.map +1 -0
- package/dist/es/utils/entitySorter.js +72 -0
- package/dist/es/utils/entitySorter.js.map +1 -0
- package/dist/types/decorators/entityDecorator.d.ts +1 -1
- package/dist/types/decorators/propertyDecorator.d.ts +1 -1
- package/dist/types/factories/entitySchemaFactory.d.ts +1 -1
- package/dist/types/index.d.ts +19 -19
- package/dist/types/models/IComparator.d.ts +1 -1
- package/dist/types/models/IComparatorGroup.d.ts +2 -2
- package/dist/types/models/IEntitySchema.d.ts +2 -2
- package/dist/types/models/IEntitySchemaProperty.d.ts +3 -3
- package/dist/types/models/IEntitySort.d.ts +2 -2
- package/dist/types/models/entityCondition.d.ts +2 -2
- package/dist/types/utils/decoratorHelper.d.ts +1 -1
- package/dist/types/utils/entityConditions.d.ts +2 -2
- package/dist/types/utils/entitySchemaHelper.d.ts +8 -4
- package/dist/types/utils/entitySorter.d.ts +3 -3
- package/docs/changelog.md +281 -0
- package/docs/reference/classes/EntitySchemaHelper.md +12 -4
- package/docs/reference/interfaces/IEntitySchema.md +1 -1
- package/package.json +19 -10
- package/dist/cjs/index.cjs +0 -673
- package/dist/esm/index.mjs +0 -660
package/dist/cjs/index.cjs
DELETED
|
@@ -1,673 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
require('reflect-metadata');
|
|
4
|
-
var core = require('@twin.org/core');
|
|
5
|
-
|
|
6
|
-
// Copyright 2024 IOTA Stiftung.
|
|
7
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
8
|
-
const META_DATA_KEY = "EntitySchemaMetadata";
|
|
9
|
-
/**
|
|
10
|
-
* Class to help with decorators.
|
|
11
|
-
*/
|
|
12
|
-
class DecoratorHelper {
|
|
13
|
-
/**
|
|
14
|
-
* Get the schema from the reflection metadata.
|
|
15
|
-
* @param target The object to get the schema data from.
|
|
16
|
-
* @returns The schema from the metadata if it can be found.
|
|
17
|
-
*/
|
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
-
static getSchema(target) {
|
|
20
|
-
return (Reflect.getMetadata(META_DATA_KEY, typeof target === "object" ? target : target.prototype) ??
|
|
21
|
-
{});
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Set the schema from the reflection metadata.
|
|
25
|
-
* @param target The object to get the schema data from.
|
|
26
|
-
* @param entitySchema The schema to set.
|
|
27
|
-
*/
|
|
28
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
-
static setSchema(target, entitySchema) {
|
|
30
|
-
Reflect.defineMetadata(META_DATA_KEY, entitySchema, typeof target === "object" ? target : target.prototype);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Copyright 2024 IOTA Stiftung.
|
|
35
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
36
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
37
|
-
/**
|
|
38
|
-
* Decorator to produce schema data for entity.
|
|
39
|
-
* @param options The options for the entity.
|
|
40
|
-
* @returns The class decorator.
|
|
41
|
-
*/
|
|
42
|
-
function entity(options) {
|
|
43
|
-
return (target) => {
|
|
44
|
-
const entitySchema = DecoratorHelper.getSchema(target);
|
|
45
|
-
entitySchema.type = target.name;
|
|
46
|
-
entitySchema.options = options;
|
|
47
|
-
DecoratorHelper.setSchema(target, entitySchema);
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Copyright 2024 IOTA Stiftung.
|
|
52
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
53
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
54
|
-
/**
|
|
55
|
-
* Decorator to produce schema property data for entities.
|
|
56
|
-
* @param options The options for the property.
|
|
57
|
-
* @returns The property decorator.
|
|
58
|
-
*/
|
|
59
|
-
function property(options) {
|
|
60
|
-
return (target, propertyKey) => {
|
|
61
|
-
const entitySchema = DecoratorHelper.getSchema(target);
|
|
62
|
-
entitySchema.properties ??= [];
|
|
63
|
-
const idx = entitySchema.properties.findIndex(p => p.property === propertyKey);
|
|
64
|
-
if (idx !== -1) {
|
|
65
|
-
entitySchema.properties[idx] = {
|
|
66
|
-
...options,
|
|
67
|
-
property: propertyKey
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
entitySchema.properties.push({
|
|
72
|
-
...options,
|
|
73
|
-
property: propertyKey
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
DecoratorHelper.setSchema(target, entitySchema);
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Copyright 2024 IOTA Stiftung.
|
|
81
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
82
|
-
/**
|
|
83
|
-
* Factory for creating entity schemas.
|
|
84
|
-
*/
|
|
85
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
86
|
-
const EntitySchemaFactory = core.Factory.createFactory("entity-schema");
|
|
87
|
-
|
|
88
|
-
// Copyright 2024 IOTA Stiftung.
|
|
89
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
90
|
-
/**
|
|
91
|
-
* The types of comparisons.
|
|
92
|
-
*/
|
|
93
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
94
|
-
const ComparisonOperator = {
|
|
95
|
-
/**
|
|
96
|
-
* Equals.
|
|
97
|
-
*/
|
|
98
|
-
Equals: "equals",
|
|
99
|
-
/**
|
|
100
|
-
* Not Equals.
|
|
101
|
-
*/
|
|
102
|
-
NotEquals: "not-equals",
|
|
103
|
-
/**
|
|
104
|
-
* Greater Than.
|
|
105
|
-
*/
|
|
106
|
-
GreaterThan: "greater-than",
|
|
107
|
-
/**
|
|
108
|
-
* Greater Than Or Equal.
|
|
109
|
-
*/
|
|
110
|
-
GreaterThanOrEqual: "greater-than-or-equal",
|
|
111
|
-
/**
|
|
112
|
-
* Less Than.
|
|
113
|
-
*/
|
|
114
|
-
LessThan: "less-than",
|
|
115
|
-
/**
|
|
116
|
-
* Less Than Or Equal.
|
|
117
|
-
*/
|
|
118
|
-
LessThanOrEqual: "less-than-or-equal",
|
|
119
|
-
/**
|
|
120
|
-
* Includes.
|
|
121
|
-
* A string in a substring.
|
|
122
|
-
* A set contains an element.
|
|
123
|
-
* A list contains an element.
|
|
124
|
-
*/
|
|
125
|
-
Includes: "includes",
|
|
126
|
-
/**
|
|
127
|
-
* Not Includes.
|
|
128
|
-
* A string not in a substring.
|
|
129
|
-
* A set does not contain an element.
|
|
130
|
-
* A list does not contain an element.
|
|
131
|
-
*/
|
|
132
|
-
NotIncludes: "not-includes",
|
|
133
|
-
/**
|
|
134
|
-
* In.
|
|
135
|
-
* A element is in a set.
|
|
136
|
-
*/
|
|
137
|
-
In: "in"
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
// Copyright 2024 IOTA Stiftung.
|
|
141
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
142
|
-
/**
|
|
143
|
-
* Definition of the entity property format.
|
|
144
|
-
*/
|
|
145
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
146
|
-
const EntitySchemaPropertyFormat = {
|
|
147
|
-
/**
|
|
148
|
-
* UUID.
|
|
149
|
-
*/
|
|
150
|
-
Uuid: "uuid",
|
|
151
|
-
/**
|
|
152
|
-
* URI.
|
|
153
|
-
*/
|
|
154
|
-
Uri: "uri",
|
|
155
|
-
/**
|
|
156
|
-
* email.
|
|
157
|
-
*/
|
|
158
|
-
Email: "email",
|
|
159
|
-
/**
|
|
160
|
-
* int8.
|
|
161
|
-
*/
|
|
162
|
-
Int8: "int8",
|
|
163
|
-
/**
|
|
164
|
-
* uint8.
|
|
165
|
-
*/
|
|
166
|
-
Uint8: "uint8",
|
|
167
|
-
/**
|
|
168
|
-
* int16.
|
|
169
|
-
*/
|
|
170
|
-
Int16: "int16",
|
|
171
|
-
/**
|
|
172
|
-
* uint16.
|
|
173
|
-
*/
|
|
174
|
-
Uint16: "uint16",
|
|
175
|
-
/**
|
|
176
|
-
* int32.
|
|
177
|
-
*/
|
|
178
|
-
Int32: "int32",
|
|
179
|
-
/**
|
|
180
|
-
* uint32.
|
|
181
|
-
*/
|
|
182
|
-
Uint32: "uint32",
|
|
183
|
-
/**
|
|
184
|
-
* float.
|
|
185
|
-
*/
|
|
186
|
-
Float: "float",
|
|
187
|
-
/**
|
|
188
|
-
* double.
|
|
189
|
-
*/
|
|
190
|
-
Double: "double",
|
|
191
|
-
/**
|
|
192
|
-
* int64.
|
|
193
|
-
*/
|
|
194
|
-
Int64: "int64",
|
|
195
|
-
/**
|
|
196
|
-
* uint64.
|
|
197
|
-
*/
|
|
198
|
-
Uint64: "uint64",
|
|
199
|
-
/**
|
|
200
|
-
* date.
|
|
201
|
-
*/
|
|
202
|
-
Date: "date",
|
|
203
|
-
/**
|
|
204
|
-
* time.
|
|
205
|
-
*/
|
|
206
|
-
Time: "time",
|
|
207
|
-
/**
|
|
208
|
-
* date-time.
|
|
209
|
-
*/
|
|
210
|
-
DateTime: "date-time",
|
|
211
|
-
/**
|
|
212
|
-
* JSON.
|
|
213
|
-
*/
|
|
214
|
-
Json: "json"
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
// Copyright 2024 IOTA Stiftung.
|
|
218
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
219
|
-
/**
|
|
220
|
-
* Definition of the entity property types.
|
|
221
|
-
*/
|
|
222
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
223
|
-
const EntitySchemaPropertyType = {
|
|
224
|
-
/**
|
|
225
|
-
* String.
|
|
226
|
-
*/
|
|
227
|
-
String: "string",
|
|
228
|
-
/**
|
|
229
|
-
* Number.
|
|
230
|
-
*/
|
|
231
|
-
Number: "number",
|
|
232
|
-
/**
|
|
233
|
-
* Integer.
|
|
234
|
-
*/
|
|
235
|
-
Integer: "integer",
|
|
236
|
-
/**
|
|
237
|
-
* Boolean.
|
|
238
|
-
*/
|
|
239
|
-
Boolean: "boolean",
|
|
240
|
-
/**
|
|
241
|
-
* Array.
|
|
242
|
-
*/
|
|
243
|
-
Array: "array",
|
|
244
|
-
/**
|
|
245
|
-
* Object.
|
|
246
|
-
*/
|
|
247
|
-
Object: "object"
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
// Copyright 2024 IOTA Stiftung.
|
|
251
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
252
|
-
/**
|
|
253
|
-
* The logical operators for condition combining.
|
|
254
|
-
*/
|
|
255
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
256
|
-
const LogicalOperator = {
|
|
257
|
-
/**
|
|
258
|
-
* Logical operator AND.
|
|
259
|
-
*/
|
|
260
|
-
And: "and",
|
|
261
|
-
/**
|
|
262
|
-
* Logical operator OR.
|
|
263
|
-
*/
|
|
264
|
-
Or: "or"
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
// Copyright 2024 IOTA Stiftung.
|
|
268
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
269
|
-
/**
|
|
270
|
-
* The sort directions.
|
|
271
|
-
*/
|
|
272
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
273
|
-
const SortDirection = {
|
|
274
|
-
/**
|
|
275
|
-
* Ascending.
|
|
276
|
-
*/
|
|
277
|
-
Ascending: "asc",
|
|
278
|
-
/**
|
|
279
|
-
* Descending.
|
|
280
|
-
*/
|
|
281
|
-
Descending: "desc"
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
// Copyright 2024 IOTA Stiftung.
|
|
285
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
286
|
-
/**
|
|
287
|
-
* Class to perform condition checks.
|
|
288
|
-
*/
|
|
289
|
-
class EntityConditions {
|
|
290
|
-
/**
|
|
291
|
-
* See if the entity matches the conditions.
|
|
292
|
-
* @param entity The entity to test.
|
|
293
|
-
* @param condition The conditions to test.
|
|
294
|
-
* @returns True if the entity matches.
|
|
295
|
-
*/
|
|
296
|
-
static check(entity, condition) {
|
|
297
|
-
// If no conditions are defined then it's a match
|
|
298
|
-
if (core.Is.undefined(condition)) {
|
|
299
|
-
return true;
|
|
300
|
-
}
|
|
301
|
-
if ("conditions" in condition) {
|
|
302
|
-
// It's a group of comparisons, so check the individual items and combine with the logical operator
|
|
303
|
-
const results = condition.conditions.map(c => this.check(entity, c));
|
|
304
|
-
if ((condition.logicalOperator ?? LogicalOperator.And) === LogicalOperator.And) {
|
|
305
|
-
return results.every(Boolean);
|
|
306
|
-
}
|
|
307
|
-
return results.some(Boolean);
|
|
308
|
-
}
|
|
309
|
-
if (condition.property.includes(".")) {
|
|
310
|
-
// It's a child property comparison, so evaluate the child property
|
|
311
|
-
// and then compare it to the conditions
|
|
312
|
-
const path = condition.property.split(".");
|
|
313
|
-
const child = core.ObjectHelper.propertyGet(entity, path[0]);
|
|
314
|
-
// If the child is an array then check each item
|
|
315
|
-
if (core.Is.array(child)) {
|
|
316
|
-
for (const c of child) {
|
|
317
|
-
const check = EntityConditions.check(c, {
|
|
318
|
-
...condition,
|
|
319
|
-
property: path.slice(1).join(".")
|
|
320
|
-
});
|
|
321
|
-
if (check) {
|
|
322
|
-
return true;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
return false;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
// It's a single value so just check the condition
|
|
329
|
-
return EntityConditions.compare(entity, condition);
|
|
330
|
-
}
|
|
331
|
-
/**
|
|
332
|
-
* See if the entity matches the conditions.
|
|
333
|
-
* @param entity The entity to test.
|
|
334
|
-
* @param comparator The condition to test.
|
|
335
|
-
* @returns True if the entity matches.
|
|
336
|
-
*/
|
|
337
|
-
static compare(entity, comparator) {
|
|
338
|
-
const val = core.ObjectHelper.propertyGet(entity, comparator.property);
|
|
339
|
-
const conditionValue = comparator.value;
|
|
340
|
-
if (core.Is.undefined(conditionValue)) {
|
|
341
|
-
const valUndefined = core.Is.undefined(val);
|
|
342
|
-
if (valUndefined && comparator.comparison === ComparisonOperator.Equals) {
|
|
343
|
-
return true;
|
|
344
|
-
}
|
|
345
|
-
else if (!valUndefined && comparator.comparison === ComparisonOperator.NotEquals) {
|
|
346
|
-
return true;
|
|
347
|
-
}
|
|
348
|
-
return false;
|
|
349
|
-
}
|
|
350
|
-
else if (core.Is.string(val)) {
|
|
351
|
-
if (core.Is.string(conditionValue)) {
|
|
352
|
-
if (!((comparator.comparison === ComparisonOperator.Equals && val === conditionValue) ||
|
|
353
|
-
(comparator.comparison === ComparisonOperator.NotEquals && val !== conditionValue) ||
|
|
354
|
-
(comparator.comparison === ComparisonOperator.GreaterThan && val > conditionValue) ||
|
|
355
|
-
(comparator.comparison === ComparisonOperator.LessThan && val < conditionValue) ||
|
|
356
|
-
(comparator.comparison === ComparisonOperator.GreaterThanOrEqual &&
|
|
357
|
-
val >= conditionValue) ||
|
|
358
|
-
(comparator.comparison === ComparisonOperator.LessThanOrEqual &&
|
|
359
|
-
val <= conditionValue) ||
|
|
360
|
-
(comparator.comparison === ComparisonOperator.Includes &&
|
|
361
|
-
val.includes(conditionValue)) ||
|
|
362
|
-
(comparator.comparison === ComparisonOperator.NotIncludes &&
|
|
363
|
-
!val.includes(conditionValue)))) {
|
|
364
|
-
return false;
|
|
365
|
-
}
|
|
366
|
-
return true;
|
|
367
|
-
}
|
|
368
|
-
else if (core.Is.array(conditionValue)) {
|
|
369
|
-
if (!(comparator.comparison === ComparisonOperator.In && conditionValue.includes(val))) {
|
|
370
|
-
return false;
|
|
371
|
-
}
|
|
372
|
-
return true;
|
|
373
|
-
}
|
|
374
|
-
return false;
|
|
375
|
-
}
|
|
376
|
-
else if (core.Is.number(val)) {
|
|
377
|
-
if (core.Is.number(conditionValue)) {
|
|
378
|
-
if (!((comparator.comparison === ComparisonOperator.Equals && val === conditionValue) ||
|
|
379
|
-
(comparator.comparison === ComparisonOperator.NotEquals && val !== conditionValue) ||
|
|
380
|
-
(comparator.comparison === ComparisonOperator.GreaterThan && val > conditionValue) ||
|
|
381
|
-
(comparator.comparison === ComparisonOperator.LessThan && val < conditionValue) ||
|
|
382
|
-
(comparator.comparison === ComparisonOperator.GreaterThanOrEqual &&
|
|
383
|
-
val >= conditionValue) ||
|
|
384
|
-
(comparator.comparison === ComparisonOperator.LessThanOrEqual && val <= conditionValue))) {
|
|
385
|
-
return false;
|
|
386
|
-
}
|
|
387
|
-
return true;
|
|
388
|
-
}
|
|
389
|
-
else if (core.Is.array(conditionValue)) {
|
|
390
|
-
if (!(comparator.comparison === ComparisonOperator.In && conditionValue.includes(val))) {
|
|
391
|
-
return false;
|
|
392
|
-
}
|
|
393
|
-
return true;
|
|
394
|
-
}
|
|
395
|
-
return false;
|
|
396
|
-
}
|
|
397
|
-
else if (core.Is.boolean(val)) {
|
|
398
|
-
if (core.Is.boolean(conditionValue)) {
|
|
399
|
-
if (!((comparator.comparison === ComparisonOperator.Equals && val === conditionValue) ||
|
|
400
|
-
(comparator.comparison === ComparisonOperator.NotEquals && val !== conditionValue))) {
|
|
401
|
-
return false;
|
|
402
|
-
}
|
|
403
|
-
return true;
|
|
404
|
-
}
|
|
405
|
-
return false;
|
|
406
|
-
}
|
|
407
|
-
else if (core.Is.array(val)) {
|
|
408
|
-
if (core.Is.array(conditionValue)) {
|
|
409
|
-
if (comparator.comparison === ComparisonOperator.Equals ||
|
|
410
|
-
comparator.comparison === ComparisonOperator.NotEquals) {
|
|
411
|
-
const matches = core.ArrayHelper.matches(val, conditionValue);
|
|
412
|
-
if (!((comparator.comparison === ComparisonOperator.Equals && matches) ||
|
|
413
|
-
(comparator.comparison === ComparisonOperator.NotEquals && !matches))) {
|
|
414
|
-
return false;
|
|
415
|
-
}
|
|
416
|
-
return true;
|
|
417
|
-
}
|
|
418
|
-
return false;
|
|
419
|
-
}
|
|
420
|
-
else if (core.Is.number(conditionValue) || core.Is.string(conditionValue)) {
|
|
421
|
-
if (comparator.comparison === ComparisonOperator.Includes ||
|
|
422
|
-
comparator.comparison === ComparisonOperator.NotIncludes ||
|
|
423
|
-
comparator.comparison === ComparisonOperator.In) {
|
|
424
|
-
const includes = val.includes(conditionValue);
|
|
425
|
-
if (!((comparator.comparison === ComparisonOperator.Includes && includes) ||
|
|
426
|
-
(comparator.comparison === ComparisonOperator.NotIncludes && !includes) ||
|
|
427
|
-
(comparator.comparison === ComparisonOperator.In && includes))) {
|
|
428
|
-
return false;
|
|
429
|
-
}
|
|
430
|
-
return true;
|
|
431
|
-
}
|
|
432
|
-
return false;
|
|
433
|
-
}
|
|
434
|
-
else if (core.Is.object(conditionValue)) {
|
|
435
|
-
if (comparator.comparison === ComparisonOperator.Includes) {
|
|
436
|
-
for (const v of val) {
|
|
437
|
-
if (core.ObjectHelper.equal(v, conditionValue)) {
|
|
438
|
-
return true;
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
else if (comparator.comparison === ComparisonOperator.NotIncludes) {
|
|
443
|
-
for (const v of val) {
|
|
444
|
-
if (!core.ObjectHelper.equal(v, conditionValue)) {
|
|
445
|
-
return true;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
return false;
|
|
451
|
-
}
|
|
452
|
-
return false;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
// Copyright 2024 IOTA Stiftung.
|
|
457
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
458
|
-
/**
|
|
459
|
-
* Class to help with entity schema operations.
|
|
460
|
-
*/
|
|
461
|
-
class EntitySchemaHelper {
|
|
462
|
-
/**
|
|
463
|
-
* Runtime name for the class.
|
|
464
|
-
* @internal
|
|
465
|
-
*/
|
|
466
|
-
static _CLASS_NAME = "EntitySchemaHelper";
|
|
467
|
-
/**
|
|
468
|
-
* Get the schema for the specified object.
|
|
469
|
-
* @param target The object to get the schema data for.
|
|
470
|
-
* @returns The schema for the object if it can be found.
|
|
471
|
-
*/
|
|
472
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
473
|
-
static getSchema(target) {
|
|
474
|
-
return DecoratorHelper.getSchema(target);
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* Get the primary key from the entity schema.
|
|
478
|
-
* @param entitySchema The entity schema to find the primary key from.
|
|
479
|
-
* @returns The key if only one was found.
|
|
480
|
-
* @throws If no primary key was found, or more than one.
|
|
481
|
-
*/
|
|
482
|
-
static getPrimaryKey(entitySchema) {
|
|
483
|
-
core.Guards.object(EntitySchemaHelper._CLASS_NAME, "entitySchema", entitySchema);
|
|
484
|
-
const primaryKeys = (entitySchema.properties ?? [])?.filter(p => p.isPrimary);
|
|
485
|
-
if (primaryKeys.length === 0) {
|
|
486
|
-
throw new core.GeneralError(EntitySchemaHelper._CLASS_NAME, "noIsPrimary");
|
|
487
|
-
}
|
|
488
|
-
if (primaryKeys.length > 1) {
|
|
489
|
-
throw new core.GeneralError(EntitySchemaHelper._CLASS_NAME, "multipleIsPrimary");
|
|
490
|
-
}
|
|
491
|
-
return primaryKeys[0];
|
|
492
|
-
}
|
|
493
|
-
/**
|
|
494
|
-
* Get the sort properties from the schema.
|
|
495
|
-
* @param entitySchema The entity schema to find the primary key from.
|
|
496
|
-
* @returns The sort keys from the schema or undefined if there are none.
|
|
497
|
-
*/
|
|
498
|
-
static getSortProperties(entitySchema) {
|
|
499
|
-
core.Guards.object(EntitySchemaHelper._CLASS_NAME, "entitySchema", entitySchema);
|
|
500
|
-
const sortFields = (entitySchema.properties ?? []).filter(p => !core.Is.undefined(p.sortDirection));
|
|
501
|
-
return sortFields.length > 0
|
|
502
|
-
? sortFields.map(p => ({
|
|
503
|
-
property: p.property,
|
|
504
|
-
type: p.type,
|
|
505
|
-
sortDirection: p.sortDirection
|
|
506
|
-
}))
|
|
507
|
-
: undefined;
|
|
508
|
-
}
|
|
509
|
-
/**
|
|
510
|
-
* Build sort properties from the schema and override if necessary.
|
|
511
|
-
* @param entitySchema The entity schema to retrieve the default sort keys.
|
|
512
|
-
* @param overrideSortKeys The override sort keys.
|
|
513
|
-
* @returns The finalised sort keys.
|
|
514
|
-
*/
|
|
515
|
-
static buildSortProperties(entitySchema, overrideSortKeys) {
|
|
516
|
-
core.Guards.object(EntitySchemaHelper._CLASS_NAME, "entitySchema", entitySchema);
|
|
517
|
-
let finalSortKeys;
|
|
518
|
-
if (core.Is.arrayValue(overrideSortKeys)) {
|
|
519
|
-
finalSortKeys = [];
|
|
520
|
-
for (const sortKey of overrideSortKeys) {
|
|
521
|
-
const property = (entitySchema.properties ?? []).find(p => p.property === sortKey.property);
|
|
522
|
-
if (property) {
|
|
523
|
-
finalSortKeys.push({
|
|
524
|
-
property: sortKey.property,
|
|
525
|
-
sortDirection: sortKey.sortDirection,
|
|
526
|
-
type: property.type
|
|
527
|
-
});
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
else {
|
|
532
|
-
finalSortKeys = EntitySchemaHelper.getSortProperties(entitySchema);
|
|
533
|
-
}
|
|
534
|
-
return finalSortKeys;
|
|
535
|
-
}
|
|
536
|
-
/**
|
|
537
|
-
* Validate the entity against the schema.
|
|
538
|
-
* @param entity The entity to validate.
|
|
539
|
-
* @param entitySchema The schema to validate against.
|
|
540
|
-
* @throws If the entity is invalid.
|
|
541
|
-
*/
|
|
542
|
-
static validateEntity(entity, entitySchema) {
|
|
543
|
-
core.Guards.object(EntitySchemaHelper._CLASS_NAME, "entity", entity);
|
|
544
|
-
core.Guards.object(EntitySchemaHelper._CLASS_NAME, "entitySchema", entitySchema);
|
|
545
|
-
const properties = entitySchema.properties ?? [];
|
|
546
|
-
if (properties.length === 0 && core.Is.objectValue(entity)) {
|
|
547
|
-
throw new core.GeneralError(EntitySchemaHelper._CLASS_NAME, "invalidEntityProperties");
|
|
548
|
-
}
|
|
549
|
-
const allKeys = Object.keys(entity);
|
|
550
|
-
for (const prop of properties) {
|
|
551
|
-
const idx = allKeys.indexOf(prop.property);
|
|
552
|
-
if (idx !== -1) {
|
|
553
|
-
allKeys.splice(idx, 1);
|
|
554
|
-
}
|
|
555
|
-
const value = entity[prop.property];
|
|
556
|
-
if (core.Is.empty(value)) {
|
|
557
|
-
// If the value is empty but the property is not optional, then it's invalid
|
|
558
|
-
if (!prop.optional) {
|
|
559
|
-
throw new core.GeneralError(EntitySchemaHelper._CLASS_NAME, "invalidOptional", {
|
|
560
|
-
property: prop.property,
|
|
561
|
-
type: prop.type
|
|
562
|
-
});
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
else if (prop.type === "integer" && core.Is.integer(value)) ;
|
|
566
|
-
else if (prop.type === "object" &&
|
|
567
|
-
(core.Is.object(value) ||
|
|
568
|
-
core.Is.array(value) ||
|
|
569
|
-
core.Is.string(value) ||
|
|
570
|
-
core.Is.number(value) ||
|
|
571
|
-
core.Is.boolean(value) ||
|
|
572
|
-
core.Is.null(value))) ;
|
|
573
|
-
else if (prop.type === "array" && core.Is.array(value)) ;
|
|
574
|
-
else if (prop.type !== typeof value) {
|
|
575
|
-
// The schema type does not match the value type
|
|
576
|
-
throw new core.GeneralError(EntitySchemaHelper._CLASS_NAME, "invalidEntityProperty", {
|
|
577
|
-
value,
|
|
578
|
-
property: prop.property,
|
|
579
|
-
type: prop.type
|
|
580
|
-
});
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
if (allKeys.length > 0) {
|
|
584
|
-
// There are keys in the entity that are not in the schema
|
|
585
|
-
throw new core.GeneralError(EntitySchemaHelper._CLASS_NAME, "invalidEntityKeys", {
|
|
586
|
-
keys: allKeys.join(", ")
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
// Copyright 2024 IOTA Stiftung.
|
|
593
|
-
// SPDX-License-Identifier: Apache-2.0.
|
|
594
|
-
/**
|
|
595
|
-
* Class to perform sort operations on entities.
|
|
596
|
-
*/
|
|
597
|
-
class EntitySorter {
|
|
598
|
-
/**
|
|
599
|
-
* Sort a list of entities using multiple keys and direction.
|
|
600
|
-
* @param entities The list of entities.
|
|
601
|
-
* @param entitySorters The sort keys to use.
|
|
602
|
-
* @returns The sorted list.
|
|
603
|
-
*/
|
|
604
|
-
static sort(entities, entitySorters) {
|
|
605
|
-
if (!core.Is.arrayValue(entities) || core.Is.empty(entitySorters)) {
|
|
606
|
-
return entities;
|
|
607
|
-
}
|
|
608
|
-
return entities.sort((a, b) => {
|
|
609
|
-
for (const entitySorter of entitySorters) {
|
|
610
|
-
const compareResult = EntitySorter.compare(a, b, entitySorter.property, entitySorter.type, entitySorter.sortDirection);
|
|
611
|
-
if (compareResult !== 0) {
|
|
612
|
-
return compareResult;
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
return 0;
|
|
616
|
-
});
|
|
617
|
-
}
|
|
618
|
-
/**
|
|
619
|
-
* Compare two properties.
|
|
620
|
-
* @param entity1 The first entity.
|
|
621
|
-
* @param entity2 The second entity.
|
|
622
|
-
* @param prop The property to compare.
|
|
623
|
-
* @param type The type of the property.
|
|
624
|
-
* @param direction The direction of the sort.
|
|
625
|
-
* @returns The result of the comparison.
|
|
626
|
-
*/
|
|
627
|
-
static compare(entity1, entity2, prop, type, direction = SortDirection.Ascending) {
|
|
628
|
-
let res = 0;
|
|
629
|
-
const hasProp1 = !core.Is.empty(entity1[prop]);
|
|
630
|
-
const hasProp2 = !core.Is.empty(entity2[prop]);
|
|
631
|
-
if (hasProp1 && hasProp2) {
|
|
632
|
-
if (type === "number" || type === "integer") {
|
|
633
|
-
res = entity1[prop] - entity2[prop];
|
|
634
|
-
}
|
|
635
|
-
else if (type === "boolean") {
|
|
636
|
-
const b1 = entity1[prop];
|
|
637
|
-
const b2 = entity2[prop];
|
|
638
|
-
if (b1 === b2) {
|
|
639
|
-
res = 0;
|
|
640
|
-
}
|
|
641
|
-
else if (b1) {
|
|
642
|
-
res = -1;
|
|
643
|
-
}
|
|
644
|
-
else {
|
|
645
|
-
res = 1;
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
else if (type === "string") {
|
|
649
|
-
res = entity1[prop].localeCompare(entity2[prop]);
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
else if (hasProp1) {
|
|
653
|
-
res = -1;
|
|
654
|
-
}
|
|
655
|
-
else {
|
|
656
|
-
res = 1;
|
|
657
|
-
}
|
|
658
|
-
return direction === SortDirection.Ascending ? res : res * -1;
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
exports.ComparisonOperator = ComparisonOperator;
|
|
663
|
-
exports.DecoratorHelper = DecoratorHelper;
|
|
664
|
-
exports.EntityConditions = EntityConditions;
|
|
665
|
-
exports.EntitySchemaFactory = EntitySchemaFactory;
|
|
666
|
-
exports.EntitySchemaHelper = EntitySchemaHelper;
|
|
667
|
-
exports.EntitySchemaPropertyFormat = EntitySchemaPropertyFormat;
|
|
668
|
-
exports.EntitySchemaPropertyType = EntitySchemaPropertyType;
|
|
669
|
-
exports.EntitySorter = EntitySorter;
|
|
670
|
-
exports.LogicalOperator = LogicalOperator;
|
|
671
|
-
exports.SortDirection = SortDirection;
|
|
672
|
-
exports.entity = entity;
|
|
673
|
-
exports.property = property;
|