@twin.org/entity 0.0.2-next.9 → 0.0.3-next.1

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 (60) hide show
  1. package/dist/es/decorators/entityDecorator.js +19 -0
  2. package/dist/es/decorators/entityDecorator.js.map +1 -0
  3. package/dist/es/decorators/propertyDecorator.js +31 -0
  4. package/dist/es/decorators/propertyDecorator.js.map +1 -0
  5. package/dist/es/factories/entitySchemaFactory.js +9 -0
  6. package/dist/es/factories/entitySchemaFactory.js.map +1 -0
  7. package/dist/es/index.js +22 -0
  8. package/dist/es/index.js.map +1 -0
  9. package/dist/es/models/IComparator.js +2 -0
  10. package/dist/es/models/IComparator.js.map +1 -0
  11. package/dist/es/models/IComparatorGroup.js +2 -0
  12. package/dist/es/models/IComparatorGroup.js.map +1 -0
  13. package/dist/es/models/IEntitySchema.js +2 -0
  14. package/dist/es/models/IEntitySchema.js.map +1 -0
  15. package/dist/es/models/IEntitySchemaOptions.js +4 -0
  16. package/dist/es/models/IEntitySchemaOptions.js.map +1 -0
  17. package/dist/es/models/IEntitySchemaProperty.js +2 -0
  18. package/dist/es/models/IEntitySchemaProperty.js.map +1 -0
  19. package/dist/es/models/IEntitySort.js +2 -0
  20. package/dist/es/models/IEntitySort.js.map +1 -0
  21. package/dist/es/models/comparisonOperator.js +52 -0
  22. package/dist/es/models/comparisonOperator.js.map +1 -0
  23. package/dist/es/models/entityCondition.js +2 -0
  24. package/dist/es/models/entityCondition.js.map +1 -0
  25. package/dist/es/models/entitySchemaPropertyFormat.js +77 -0
  26. package/dist/es/models/entitySchemaPropertyFormat.js.map +1 -0
  27. package/dist/es/models/entitySchemaPropertyType.js +33 -0
  28. package/dist/es/models/entitySchemaPropertyType.js.map +1 -0
  29. package/dist/es/models/logicalOperator.js +17 -0
  30. package/dist/es/models/logicalOperator.js.map +1 -0
  31. package/dist/es/models/sortDirection.js +17 -0
  32. package/dist/es/models/sortDirection.js.map +1 -0
  33. package/dist/es/utils/decoratorHelper.js +29 -0
  34. package/dist/es/utils/decoratorHelper.js.map +1 -0
  35. package/dist/es/utils/entityConditions.js +175 -0
  36. package/dist/es/utils/entityConditions.js.map +1 -0
  37. package/dist/es/utils/entitySchemaHelper.js +143 -0
  38. package/dist/es/utils/entitySchemaHelper.js.map +1 -0
  39. package/dist/es/utils/entitySorter.js +72 -0
  40. package/dist/es/utils/entitySorter.js.map +1 -0
  41. package/dist/types/decorators/entityDecorator.d.ts +1 -1
  42. package/dist/types/decorators/propertyDecorator.d.ts +1 -1
  43. package/dist/types/factories/entitySchemaFactory.d.ts +1 -1
  44. package/dist/types/index.d.ts +19 -19
  45. package/dist/types/models/IComparator.d.ts +1 -1
  46. package/dist/types/models/IComparatorGroup.d.ts +2 -2
  47. package/dist/types/models/IEntitySchema.d.ts +2 -2
  48. package/dist/types/models/IEntitySchemaProperty.d.ts +3 -3
  49. package/dist/types/models/IEntitySort.d.ts +2 -2
  50. package/dist/types/models/entityCondition.d.ts +2 -2
  51. package/dist/types/utils/decoratorHelper.d.ts +1 -1
  52. package/dist/types/utils/entityConditions.d.ts +2 -2
  53. package/dist/types/utils/entitySchemaHelper.d.ts +8 -4
  54. package/dist/types/utils/entitySorter.d.ts +3 -3
  55. package/docs/changelog.md +262 -0
  56. package/docs/reference/classes/EntitySchemaHelper.md +12 -4
  57. package/docs/reference/interfaces/IEntitySchema.md +1 -1
  58. package/package.json +19 -10
  59. package/dist/cjs/index.cjs +0 -673
  60. package/dist/esm/index.mjs +0 -660
@@ -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;