@mikro-orm/core 7.0.4-dev.8 → 7.0.4
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/EntityManager.d.ts +884 -583
- package/EntityManager.js +1922 -1895
- package/MikroORM.d.ts +103 -74
- package/MikroORM.js +178 -179
- package/README.md +1 -1
- package/cache/CacheAdapter.d.ts +36 -36
- package/cache/FileCacheAdapter.d.ts +30 -24
- package/cache/FileCacheAdapter.js +80 -78
- package/cache/GeneratedCacheAdapter.d.ts +18 -20
- package/cache/GeneratedCacheAdapter.js +30 -30
- package/cache/MemoryCacheAdapter.d.ts +18 -20
- package/cache/MemoryCacheAdapter.js +35 -36
- package/cache/NullCacheAdapter.d.ts +16 -16
- package/cache/NullCacheAdapter.js +24 -24
- package/connections/Connection.d.ts +95 -84
- package/connections/Connection.js +165 -168
- package/drivers/DatabaseDriver.d.ts +186 -80
- package/drivers/DatabaseDriver.js +450 -443
- package/drivers/IDatabaseDriver.d.ts +440 -301
- package/entity/BaseEntity.d.ts +120 -83
- package/entity/BaseEntity.js +43 -43
- package/entity/Collection.d.ts +212 -179
- package/entity/Collection.js +727 -721
- package/entity/EntityAssigner.d.ts +88 -77
- package/entity/EntityAssigner.js +231 -230
- package/entity/EntityFactory.d.ts +66 -54
- package/entity/EntityFactory.js +425 -383
- package/entity/EntityHelper.d.ts +34 -22
- package/entity/EntityHelper.js +280 -267
- package/entity/EntityIdentifier.d.ts +4 -4
- package/entity/EntityIdentifier.js +10 -10
- package/entity/EntityLoader.d.ts +98 -72
- package/entity/EntityLoader.js +753 -723
- package/entity/EntityRepository.d.ts +316 -201
- package/entity/EntityRepository.js +213 -213
- package/entity/PolymorphicRef.d.ts +5 -5
- package/entity/PolymorphicRef.js +10 -10
- package/entity/Reference.d.ts +126 -82
- package/entity/Reference.js +278 -274
- package/entity/WrappedEntity.d.ts +115 -72
- package/entity/WrappedEntity.js +168 -166
- package/entity/defineEntity.d.ts +1315 -636
- package/entity/defineEntity.js +527 -518
- package/entity/utils.d.ts +13 -3
- package/entity/utils.js +71 -73
- package/entity/validators.js +43 -43
- package/entity/wrap.js +8 -8
- package/enums.d.ts +258 -253
- package/enums.js +251 -252
- package/errors.d.ts +114 -72
- package/errors.js +350 -253
- package/events/EventManager.d.ts +26 -14
- package/events/EventManager.js +79 -77
- package/events/EventSubscriber.d.ts +29 -29
- package/events/TransactionEventBroadcaster.d.ts +15 -8
- package/events/TransactionEventBroadcaster.js +14 -14
- package/exceptions.d.ts +23 -40
- package/exceptions.js +35 -52
- package/hydration/Hydrator.d.ts +42 -17
- package/hydration/Hydrator.js +43 -43
- package/hydration/ObjectHydrator.d.ts +50 -17
- package/hydration/ObjectHydrator.js +481 -416
- package/index.d.ts +116 -2
- package/index.js +10 -1
- package/logging/DefaultLogger.d.ts +34 -32
- package/logging/DefaultLogger.js +86 -86
- package/logging/Logger.d.ts +41 -41
- package/logging/SimpleLogger.d.ts +13 -11
- package/logging/SimpleLogger.js +22 -22
- package/logging/colors.d.ts +6 -6
- package/logging/colors.js +11 -10
- package/logging/inspect.js +7 -7
- package/metadata/EntitySchema.d.ts +211 -127
- package/metadata/EntitySchema.js +397 -398
- package/metadata/MetadataDiscovery.d.ts +114 -114
- package/metadata/MetadataDiscovery.js +1951 -1863
- package/metadata/MetadataProvider.d.ts +24 -21
- package/metadata/MetadataProvider.js +82 -84
- package/metadata/MetadataStorage.d.ts +38 -32
- package/metadata/MetadataStorage.js +118 -118
- package/metadata/MetadataValidator.d.ts +39 -39
- package/metadata/MetadataValidator.js +381 -338
- package/metadata/discover-entities.d.ts +5 -2
- package/metadata/discover-entities.js +35 -27
- package/metadata/types.d.ts +615 -531
- package/naming-strategy/AbstractNamingStrategy.d.ts +54 -39
- package/naming-strategy/AbstractNamingStrategy.js +90 -85
- package/naming-strategy/EntityCaseNamingStrategy.d.ts +6 -6
- package/naming-strategy/EntityCaseNamingStrategy.js +22 -22
- package/naming-strategy/MongoNamingStrategy.d.ts +6 -6
- package/naming-strategy/MongoNamingStrategy.js +18 -18
- package/naming-strategy/NamingStrategy.d.ts +109 -99
- package/naming-strategy/UnderscoreNamingStrategy.d.ts +7 -7
- package/naming-strategy/UnderscoreNamingStrategy.js +21 -21
- package/not-supported.js +7 -4
- package/package.json +1 -1
- package/platforms/ExceptionConverter.d.ts +1 -1
- package/platforms/ExceptionConverter.js +4 -4
- package/platforms/Platform.d.ts +310 -299
- package/platforms/Platform.js +663 -636
- package/serialization/EntitySerializer.d.ts +49 -26
- package/serialization/EntitySerializer.js +224 -218
- package/serialization/EntityTransformer.d.ts +10 -6
- package/serialization/EntityTransformer.js +219 -217
- package/serialization/SerializationContext.d.ts +27 -23
- package/serialization/SerializationContext.js +105 -105
- package/types/ArrayType.d.ts +8 -8
- package/types/ArrayType.js +33 -33
- package/types/BigIntType.d.ts +17 -10
- package/types/BigIntType.js +37 -37
- package/types/BlobType.d.ts +3 -3
- package/types/BlobType.js +13 -13
- package/types/BooleanType.d.ts +4 -4
- package/types/BooleanType.js +12 -12
- package/types/CharacterType.d.ts +2 -2
- package/types/CharacterType.js +6 -6
- package/types/DateTimeType.d.ts +5 -5
- package/types/DateTimeType.js +15 -15
- package/types/DateType.d.ts +5 -5
- package/types/DateType.js +15 -15
- package/types/DecimalType.d.ts +7 -7
- package/types/DecimalType.js +26 -26
- package/types/DoubleType.d.ts +3 -3
- package/types/DoubleType.js +12 -12
- package/types/EnumArrayType.d.ts +5 -5
- package/types/EnumArrayType.js +24 -24
- package/types/EnumType.d.ts +3 -3
- package/types/EnumType.js +11 -11
- package/types/FloatType.d.ts +3 -3
- package/types/FloatType.js +9 -9
- package/types/IntegerType.d.ts +3 -3
- package/types/IntegerType.js +9 -9
- package/types/IntervalType.d.ts +4 -4
- package/types/IntervalType.js +12 -12
- package/types/JsonType.d.ts +8 -8
- package/types/JsonType.js +32 -32
- package/types/MediumIntType.d.ts +1 -1
- package/types/MediumIntType.js +3 -3
- package/types/SmallIntType.d.ts +3 -3
- package/types/SmallIntType.js +9 -9
- package/types/StringType.d.ts +4 -4
- package/types/StringType.js +12 -12
- package/types/TextType.d.ts +3 -3
- package/types/TextType.js +9 -9
- package/types/TimeType.d.ts +5 -5
- package/types/TimeType.js +17 -17
- package/types/TinyIntType.d.ts +3 -3
- package/types/TinyIntType.js +10 -10
- package/types/Type.d.ts +83 -79
- package/types/Type.js +82 -82
- package/types/Uint8ArrayType.d.ts +4 -4
- package/types/Uint8ArrayType.js +21 -21
- package/types/UnknownType.d.ts +4 -4
- package/types/UnknownType.js +12 -12
- package/types/UuidType.d.ts +5 -5
- package/types/UuidType.js +19 -19
- package/types/index.d.ts +75 -49
- package/types/index.js +52 -26
- package/typings.d.ts +1250 -737
- package/typings.js +244 -231
- package/unit-of-work/ChangeSet.d.ts +26 -26
- package/unit-of-work/ChangeSet.js +56 -56
- package/unit-of-work/ChangeSetComputer.d.ts +12 -12
- package/unit-of-work/ChangeSetComputer.js +178 -170
- package/unit-of-work/ChangeSetPersister.d.ts +63 -44
- package/unit-of-work/ChangeSetPersister.js +442 -421
- package/unit-of-work/CommitOrderCalculator.d.ts +40 -40
- package/unit-of-work/CommitOrderCalculator.js +89 -88
- package/unit-of-work/IdentityMap.d.ts +31 -31
- package/unit-of-work/IdentityMap.js +105 -105
- package/unit-of-work/UnitOfWork.d.ts +181 -141
- package/unit-of-work/UnitOfWork.js +1200 -1183
- package/utils/AbstractMigrator.d.ts +111 -91
- package/utils/AbstractMigrator.js +275 -275
- package/utils/AbstractSchemaGenerator.d.ts +43 -34
- package/utils/AbstractSchemaGenerator.js +121 -122
- package/utils/AsyncContext.d.ts +3 -3
- package/utils/AsyncContext.js +34 -35
- package/utils/Configuration.d.ts +852 -808
- package/utils/Configuration.js +359 -344
- package/utils/Cursor.d.ts +40 -22
- package/utils/Cursor.js +135 -127
- package/utils/DataloaderUtils.d.ts +58 -43
- package/utils/DataloaderUtils.js +203 -198
- package/utils/EntityComparator.d.ts +98 -81
- package/utils/EntityComparator.js +828 -728
- package/utils/NullHighlighter.d.ts +1 -1
- package/utils/NullHighlighter.js +3 -3
- package/utils/QueryHelper.d.ts +79 -51
- package/utils/QueryHelper.js +372 -361
- package/utils/RawQueryFragment.d.ts +50 -34
- package/utils/RawQueryFragment.js +107 -105
- package/utils/RequestContext.d.ts +32 -32
- package/utils/RequestContext.js +52 -53
- package/utils/TransactionContext.d.ts +16 -16
- package/utils/TransactionContext.js +27 -27
- package/utils/TransactionManager.d.ts +58 -58
- package/utils/TransactionManager.js +199 -197
- package/utils/Utils.d.ts +204 -145
- package/utils/Utils.js +812 -810
- package/utils/clone.js +104 -113
- package/utils/env-vars.js +90 -88
- package/utils/fs-utils.d.ts +15 -15
- package/utils/fs-utils.js +180 -181
- package/utils/upsert-utils.d.ts +20 -5
- package/utils/upsert-utils.js +114 -116
package/utils/Utils.js
CHANGED
|
@@ -3,846 +3,848 @@ import { GroupOperator, PlainObject, QueryOperator, ReferenceKind } from '../enu
|
|
|
3
3
|
import { helper } from '../entity/wrap.js';
|
|
4
4
|
import { Raw } from './RawQueryFragment.js';
|
|
5
5
|
function compareConstructors(a, b) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
if (a.constructor === b.constructor) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
if (!a.constructor) {
|
|
10
|
+
return b.constructor === Object;
|
|
11
|
+
}
|
|
12
|
+
if (!b.constructor) {
|
|
13
|
+
return a.constructor === Object;
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
16
|
}
|
|
17
17
|
/** Deeply compares two objects for equality, handling dates, regexes, and raw fragments. */
|
|
18
18
|
export function compareObjects(a, b) {
|
|
19
|
-
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
if (!a || !b || typeof a !== 'object' || typeof b !== 'object' || !compareConstructors(a, b)) {
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
if (a.__raw && b.__raw) {
|
|
26
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
27
|
-
return a.sql === b.sql && compareArrays(a.params, b.params);
|
|
28
|
-
}
|
|
29
|
-
if (a instanceof Date && b instanceof Date) {
|
|
30
|
-
const timeA = a.getTime();
|
|
31
|
-
const timeB = b.getTime();
|
|
32
|
-
if (isNaN(timeA) || isNaN(timeB)) {
|
|
33
|
-
throw new Error('Comparing invalid dates is not supported');
|
|
34
|
-
}
|
|
35
|
-
return timeA === timeB;
|
|
36
|
-
}
|
|
37
|
-
/* v8 ignore next */
|
|
38
|
-
if ((typeof a === 'function' && typeof b === 'function') ||
|
|
39
|
-
(a instanceof RegExp && b instanceof RegExp) ||
|
|
40
|
-
(a instanceof String && b instanceof String) ||
|
|
41
|
-
(a instanceof Number && b instanceof Number)) {
|
|
42
|
-
return a.toString() === b.toString();
|
|
43
|
-
}
|
|
44
|
-
const keys = Object.keys(a);
|
|
45
|
-
const length = keys.length;
|
|
46
|
-
if (length !== Object.keys(b).length) {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
for (let i = length; i-- !== 0;) {
|
|
50
|
-
if (!Object.hasOwn(b, keys[i])) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
for (let i = length; i-- !== 0;) {
|
|
55
|
-
const key = keys[i];
|
|
56
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
57
|
-
if (!equals(a[key], b[key])) {
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
19
|
+
if (a === b || (a == null && b == null)) {
|
|
61
20
|
return true;
|
|
21
|
+
}
|
|
22
|
+
if (!a || !b || typeof a !== 'object' || typeof b !== 'object' || !compareConstructors(a, b)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
if (a.__raw && b.__raw) {
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
27
|
+
return a.sql === b.sql && compareArrays(a.params, b.params);
|
|
28
|
+
}
|
|
29
|
+
if (a instanceof Date && b instanceof Date) {
|
|
30
|
+
const timeA = a.getTime();
|
|
31
|
+
const timeB = b.getTime();
|
|
32
|
+
if (isNaN(timeA) || isNaN(timeB)) {
|
|
33
|
+
throw new Error('Comparing invalid dates is not supported');
|
|
34
|
+
}
|
|
35
|
+
return timeA === timeB;
|
|
36
|
+
}
|
|
37
|
+
/* v8 ignore next */
|
|
38
|
+
if (
|
|
39
|
+
(typeof a === 'function' && typeof b === 'function') ||
|
|
40
|
+
(a instanceof RegExp && b instanceof RegExp) ||
|
|
41
|
+
(a instanceof String && b instanceof String) ||
|
|
42
|
+
(a instanceof Number && b instanceof Number)
|
|
43
|
+
) {
|
|
44
|
+
return a.toString() === b.toString();
|
|
45
|
+
}
|
|
46
|
+
const keys = Object.keys(a);
|
|
47
|
+
const length = keys.length;
|
|
48
|
+
if (length !== Object.keys(b).length) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
for (let i = length; i-- !== 0; ) {
|
|
52
|
+
if (!Object.hasOwn(b, keys[i])) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
for (let i = length; i-- !== 0; ) {
|
|
57
|
+
const key = keys[i];
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
59
|
+
if (!equals(a[key], b[key])) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
62
64
|
}
|
|
63
65
|
/** Compares two arrays element-by-element for deep equality. */
|
|
64
66
|
export function compareArrays(a, b) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
const length = a.length;
|
|
68
|
+
if (length !== b.length) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
for (let i = length; i-- !== 0; ) {
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
73
|
+
if (!equals(a[i], b[i])) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
76
78
|
}
|
|
77
79
|
/** Compares two boolean values, treating numeric 0/1 as false/true. */
|
|
78
80
|
export function compareBooleans(a, b) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
a = typeof a === 'number' ? Boolean(a) : a;
|
|
82
|
+
b = typeof b === 'number' ? Boolean(b) : b;
|
|
83
|
+
return a === b;
|
|
82
84
|
}
|
|
83
85
|
/** Compares two byte arrays element-by-element. */
|
|
84
86
|
export function compareBuffers(a, b) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
87
|
+
const length = a.length;
|
|
88
|
+
if (length !== b.length) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
for (let i = length; i-- !== 0; ) {
|
|
92
|
+
if (a[i] !== b[i]) {
|
|
93
|
+
return false;
|
|
93
94
|
}
|
|
94
|
-
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
95
97
|
}
|
|
96
98
|
/**
|
|
97
99
|
* Checks if arguments are deeply (but not strictly) equal.
|
|
98
100
|
*/
|
|
99
101
|
export function equals(a, b) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
+
if (a === b) {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
if (a && b && typeof a === 'object' && typeof b === 'object') {
|
|
106
|
+
if (Array.isArray(a)) {
|
|
107
|
+
return compareArrays(a, b);
|
|
102
108
|
}
|
|
103
|
-
if (a && b
|
|
104
|
-
|
|
105
|
-
return compareArrays(a, b);
|
|
106
|
-
}
|
|
107
|
-
if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
|
|
108
|
-
return compareBuffers(a, b);
|
|
109
|
-
}
|
|
110
|
-
return compareObjects(a, b);
|
|
109
|
+
if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
|
|
110
|
+
return compareBuffers(a, b);
|
|
111
111
|
}
|
|
112
|
-
return
|
|
112
|
+
return compareObjects(a, b);
|
|
113
|
+
}
|
|
114
|
+
return Number.isNaN(a) && Number.isNaN(b);
|
|
113
115
|
}
|
|
114
116
|
const equalsFn = equals;
|
|
115
117
|
/** Parses a JSON string safely, returning the original value if parsing fails. */
|
|
116
118
|
export function parseJsonSafe(value) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return value;
|
|
119
|
+
if (typeof value === 'string') {
|
|
120
|
+
/* v8 ignore next */
|
|
121
|
+
try {
|
|
122
|
+
return JSON.parse(value);
|
|
123
|
+
} catch {
|
|
124
|
+
// ignore and return the value, as sometimes we get the parsed value,
|
|
125
|
+
// e.g. when it is a string value in JSON column
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return value;
|
|
128
129
|
}
|
|
129
130
|
/** Collection of general-purpose utility methods used throughout the ORM. */
|
|
130
131
|
export class Utils {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Checks if arguments are deeply (but not strictly) equal.
|
|
188
|
-
*/
|
|
189
|
-
static equals(a, b) {
|
|
190
|
-
return equalsFn(a, b);
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Gets array without duplicates.
|
|
194
|
-
*/
|
|
195
|
-
static unique(items) {
|
|
196
|
-
if (items.length < 2) {
|
|
197
|
-
return items;
|
|
198
|
-
}
|
|
199
|
-
return [...new Set(items)];
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Merges all sources into the target recursively.
|
|
203
|
-
*/
|
|
204
|
-
static merge(target, ...sources) {
|
|
205
|
-
return Utils._merge(target, sources, false);
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* Merges all sources into the target recursively. Ignores `undefined` values.
|
|
209
|
-
*/
|
|
210
|
-
static mergeConfig(target, ...sources) {
|
|
211
|
-
return Utils._merge(target, sources, true);
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Merges all sources into the target recursively.
|
|
215
|
-
*/
|
|
216
|
-
static _merge(target, sources, ignoreUndefined) {
|
|
217
|
-
if (!sources.length) {
|
|
218
|
-
return target;
|
|
219
|
-
}
|
|
220
|
-
const source = sources.shift();
|
|
221
|
-
if (Utils.isObject(target) && Utils.isPlainObject(source)) {
|
|
222
|
-
for (const [key, value] of Object.entries(source)) {
|
|
223
|
-
if (ignoreUndefined && typeof value === 'undefined') {
|
|
224
|
-
continue;
|
|
225
|
-
}
|
|
226
|
-
if (Utils.isPlainObject(value)) {
|
|
227
|
-
if (!Utils.isObject(target[key])) {
|
|
228
|
-
target[key] = Utils.copy(value);
|
|
229
|
-
continue;
|
|
230
|
-
}
|
|
231
|
-
/* v8 ignore next */
|
|
232
|
-
if (!(key in target)) {
|
|
233
|
-
Object.assign(target, { [key]: {} });
|
|
234
|
-
}
|
|
235
|
-
Utils._merge(target[key], [value], ignoreUndefined);
|
|
236
|
-
}
|
|
237
|
-
else {
|
|
238
|
-
Object.assign(target, { [key]: value });
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
return Utils._merge(target, sources, ignoreUndefined);
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Creates deep copy of given object.
|
|
246
|
-
*/
|
|
247
|
-
static copy(entity, respectCustomCloneMethod = true) {
|
|
248
|
-
return clone(entity, respectCustomCloneMethod);
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Normalize the argument to always be an array.
|
|
252
|
-
*/
|
|
253
|
-
static asArray(data, strict = false) {
|
|
254
|
-
if (typeof data === 'undefined' && !strict) {
|
|
255
|
-
return [];
|
|
256
|
-
}
|
|
257
|
-
if (this.isIterable(data)) {
|
|
258
|
-
return Array.from(data);
|
|
259
|
-
}
|
|
260
|
-
return [data];
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Checks if the value is iterable, but considers strings and buffers as not iterable.
|
|
264
|
-
*/
|
|
265
|
-
static isIterable(value) {
|
|
266
|
-
if (value == null || typeof value === 'string' || ArrayBuffer.isView(value)) {
|
|
267
|
-
return false;
|
|
268
|
-
}
|
|
269
|
-
return typeof Object(value)[Symbol.iterator] === 'function';
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Renames object key, keeps order of properties.
|
|
273
|
-
*/
|
|
274
|
-
static renameKey(payload, from, to) {
|
|
275
|
-
if (Utils.isObject(payload) && from in payload && !(to in payload)) {
|
|
276
|
-
for (const key of Object.keys(payload)) {
|
|
277
|
-
const value = payload[key];
|
|
278
|
-
delete payload[key];
|
|
279
|
-
payload[from === key ? to : key] = value;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Returns array of functions argument names. Uses basic regex for source code analysis, might not work with advanced syntax.
|
|
285
|
-
*/
|
|
286
|
-
static getConstructorParams(func) {
|
|
287
|
-
const source = func.toString();
|
|
288
|
-
const i = source.indexOf('constructor');
|
|
289
|
-
if (i === -1) {
|
|
290
|
-
return undefined;
|
|
291
|
-
}
|
|
292
|
-
const start = source.indexOf('(', i);
|
|
293
|
-
if (start === -1) {
|
|
294
|
-
return undefined;
|
|
295
|
-
}
|
|
296
|
-
let depth = 0;
|
|
297
|
-
let end = start;
|
|
298
|
-
for (; end < source.length; end++) {
|
|
299
|
-
if (source[end] === '(') {
|
|
300
|
-
depth++;
|
|
301
|
-
}
|
|
302
|
-
if (source[end] === ')') {
|
|
303
|
-
depth--;
|
|
304
|
-
}
|
|
305
|
-
if (depth === 0) {
|
|
306
|
-
break;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
const raw = source.slice(start + 1, end);
|
|
310
|
-
return raw
|
|
311
|
-
.split(',')
|
|
312
|
-
.map(s => s.trim().replace(/=.*$/, '').trim())
|
|
313
|
-
.filter(Boolean)
|
|
314
|
-
.map(raw => (raw.startsWith('{') && raw.endsWith('}') ? '' : raw));
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* Checks whether the argument looks like primary key (string, number or ObjectId).
|
|
318
|
-
*/
|
|
319
|
-
static isPrimaryKey(key, allowComposite = false) {
|
|
320
|
-
if (['string', 'number', 'bigint'].includes(typeof key)) {
|
|
321
|
-
return true;
|
|
322
|
-
}
|
|
323
|
-
if (allowComposite && Array.isArray(key) && key.every(v => Utils.isPrimaryKey(v, true))) {
|
|
324
|
-
return true;
|
|
325
|
-
}
|
|
326
|
-
if (Utils.isObject(key)) {
|
|
327
|
-
if (key.constructor?.name === 'ObjectId') {
|
|
328
|
-
return true;
|
|
329
|
-
}
|
|
330
|
-
if (!Utils.isPlainObject(key) && !Utils.isEntity(key, true)) {
|
|
331
|
-
return true;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
return false;
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* Extracts primary key from `data`. Accepts objects or primary keys directly.
|
|
338
|
-
*/
|
|
339
|
-
static extractPK(data, meta, strict = false) {
|
|
340
|
-
if (Utils.isPrimaryKey(data)) {
|
|
341
|
-
return data;
|
|
342
|
-
}
|
|
343
|
-
if (Utils.isEntity(data, true)) {
|
|
344
|
-
const wrapped = helper(data);
|
|
345
|
-
if (wrapped.__meta.compositePK) {
|
|
346
|
-
return wrapped.getPrimaryKeys();
|
|
347
|
-
}
|
|
348
|
-
return wrapped.getPrimaryKey();
|
|
349
|
-
}
|
|
350
|
-
if (strict && meta && Utils.getObjectKeysSize(data) !== meta.primaryKeys.length) {
|
|
351
|
-
return null;
|
|
352
|
-
}
|
|
353
|
-
if (Utils.isPlainObject(data) && meta) {
|
|
354
|
-
if (meta.compositePK) {
|
|
355
|
-
return this.getCompositeKeyValue(data, meta);
|
|
356
|
-
}
|
|
357
|
-
return data[meta.primaryKeys[0]] ?? data[meta.serializedPrimaryKey] ?? null;
|
|
358
|
-
}
|
|
359
|
-
return null;
|
|
360
|
-
}
|
|
361
|
-
static getCompositeKeyValue(data, meta, convertCustomTypes = false, platform) {
|
|
362
|
-
return meta.primaryKeys.map((pk, idx) => {
|
|
363
|
-
const value = Array.isArray(data) ? data[idx] : data[pk];
|
|
364
|
-
const prop = meta.properties[pk];
|
|
365
|
-
if (prop.targetMeta && Utils.isPlainObject(value)) {
|
|
366
|
-
return this.getCompositeKeyValue(value, prop.targetMeta);
|
|
367
|
-
}
|
|
368
|
-
if (prop.customType && platform && convertCustomTypes) {
|
|
369
|
-
const method = typeof convertCustomTypes === 'string' ? convertCustomTypes : 'convertToJSValue';
|
|
370
|
-
return prop.customType[method](value, platform);
|
|
371
|
-
}
|
|
372
|
-
return value;
|
|
373
|
-
});
|
|
374
|
-
}
|
|
375
|
-
static getCompositeKeyHash(data, meta, convertCustomTypes = false, platform, flat = false) {
|
|
376
|
-
let pks = this.getCompositeKeyValue(data, meta, convertCustomTypes, platform);
|
|
377
|
-
if (flat) {
|
|
378
|
-
pks = Utils.flatten(pks);
|
|
379
|
-
}
|
|
380
|
-
return Utils.getPrimaryKeyHash(pks);
|
|
381
|
-
}
|
|
382
|
-
static getPrimaryKeyHash(pks) {
|
|
383
|
-
return pks
|
|
384
|
-
.map(pk => {
|
|
385
|
-
if (Buffer.isBuffer(pk)) {
|
|
386
|
-
return pk.toString('hex');
|
|
387
|
-
}
|
|
388
|
-
if (pk instanceof Date) {
|
|
389
|
-
return pk.toISOString();
|
|
390
|
-
}
|
|
391
|
-
return pk;
|
|
392
|
-
})
|
|
393
|
-
.join(this.PK_SEPARATOR);
|
|
394
|
-
}
|
|
395
|
-
static splitPrimaryKeys(key) {
|
|
396
|
-
return key.split(this.PK_SEPARATOR);
|
|
397
|
-
}
|
|
398
|
-
static getPrimaryKeyValues(entity, meta, allowScalar = false, convertCustomTypes = false) {
|
|
399
|
-
/* v8 ignore next */
|
|
400
|
-
if (entity == null) {
|
|
401
|
-
return entity;
|
|
402
|
-
}
|
|
403
|
-
function toArray(val) {
|
|
404
|
-
if (Utils.isPlainObject(val)) {
|
|
405
|
-
return Object.values(val).flatMap(v => toArray(v));
|
|
406
|
-
}
|
|
407
|
-
return val;
|
|
408
|
-
}
|
|
409
|
-
let pk;
|
|
410
|
-
if (Utils.isEntity(entity, true)) {
|
|
411
|
-
pk = helper(entity).getPrimaryKey(convertCustomTypes);
|
|
412
|
-
}
|
|
413
|
-
else {
|
|
414
|
-
pk = meta.primaryKeys.reduce((o, pk) => {
|
|
415
|
-
const targetMeta = meta.properties[pk].targetMeta;
|
|
416
|
-
if (targetMeta && Utils.isPlainObject(entity[pk])) {
|
|
417
|
-
o[pk] = Utils.getPrimaryKeyValues(entity[pk], targetMeta, allowScalar, convertCustomTypes);
|
|
418
|
-
}
|
|
419
|
-
else {
|
|
420
|
-
o[pk] = entity[pk];
|
|
421
|
-
}
|
|
422
|
-
return o;
|
|
423
|
-
}, {});
|
|
424
|
-
}
|
|
425
|
-
if (meta.primaryKeys.length > 1) {
|
|
426
|
-
return toArray(pk);
|
|
427
|
-
}
|
|
428
|
-
if (allowScalar) {
|
|
429
|
-
if (Utils.isPlainObject(pk)) {
|
|
430
|
-
return pk[meta.primaryKeys[0]];
|
|
431
|
-
}
|
|
432
|
-
return pk;
|
|
433
|
-
}
|
|
434
|
-
return [pk];
|
|
435
|
-
}
|
|
436
|
-
static getPrimaryKeyCond(entity, primaryKeys) {
|
|
437
|
-
const cond = primaryKeys.reduce((o, pk) => {
|
|
438
|
-
o[pk] = Utils.extractPK(entity[pk]);
|
|
439
|
-
return o;
|
|
440
|
-
}, {});
|
|
441
|
-
if (Object.values(cond).some(v => v === null)) {
|
|
442
|
-
return null;
|
|
443
|
-
}
|
|
444
|
-
return cond;
|
|
445
|
-
}
|
|
446
|
-
/**
|
|
447
|
-
* Maps nested FKs from `[1, 2, 3]` to `[1, [2, 3]]`.
|
|
448
|
-
*/
|
|
449
|
-
static mapFlatCompositePrimaryKey(fk, prop, fieldNames = prop.fieldNames, idx = 0) {
|
|
450
|
-
if (!prop.targetMeta) {
|
|
451
|
-
return fk[idx++];
|
|
452
|
-
}
|
|
453
|
-
const parts = [];
|
|
454
|
-
for (const pk of prop.targetMeta.getPrimaryProps()) {
|
|
455
|
-
parts.push(this.mapFlatCompositePrimaryKey(fk, pk, fieldNames, idx));
|
|
456
|
-
idx += pk.fieldNames.length;
|
|
457
|
-
}
|
|
458
|
-
if (parts.length < 2) {
|
|
459
|
-
return parts[0];
|
|
460
|
-
}
|
|
461
|
-
return parts;
|
|
462
|
-
}
|
|
463
|
-
static getPrimaryKeyCondFromArray(pks, meta) {
|
|
464
|
-
return meta.getPrimaryProps().reduce((o, pk, idx) => {
|
|
465
|
-
if (Array.isArray(pks[idx]) && pk.targetMeta) {
|
|
466
|
-
o[pk.name] = pks[idx];
|
|
467
|
-
}
|
|
468
|
-
else {
|
|
469
|
-
o[pk.name] = Utils.extractPK(pks[idx], meta);
|
|
470
|
-
}
|
|
471
|
-
return o;
|
|
472
|
-
}, {});
|
|
473
|
-
}
|
|
474
|
-
static getOrderedPrimaryKeys(id, meta, platform, convertCustomTypes = false, allowScalar = false) {
|
|
475
|
-
const data = (Utils.isPrimaryKey(id) ? { [meta.primaryKeys[0]]: id } : id);
|
|
476
|
-
const pks = meta.primaryKeys.map((pk, idx) => {
|
|
477
|
-
const prop = meta.properties[pk];
|
|
478
|
-
// `data` can be a composite PK in form of array of PKs, or a DTO
|
|
479
|
-
let value = Array.isArray(data) ? data[idx] : (data[pk] ?? data);
|
|
480
|
-
if (convertCustomTypes && platform && prop.customType && !prop.targetMeta) {
|
|
481
|
-
value = prop.customType.convertToJSValue(value, platform);
|
|
482
|
-
}
|
|
483
|
-
if (prop.kind !== ReferenceKind.SCALAR && prop.targetMeta) {
|
|
484
|
-
const value2 = this.getOrderedPrimaryKeys(value, prop.targetMeta, platform, convertCustomTypes, allowScalar);
|
|
485
|
-
value = value2.length > 1 ? value2 : value2[0];
|
|
486
|
-
}
|
|
487
|
-
return value;
|
|
488
|
-
});
|
|
489
|
-
if (allowScalar && pks.length === 1) {
|
|
490
|
-
return pks[0];
|
|
491
|
-
}
|
|
492
|
-
// we need to flatten the PKs as composite PKs can be build from another composite PKs
|
|
493
|
-
// and this method is used to get the PK hash in identity map, that expects flat array
|
|
494
|
-
return Utils.flatten(pks);
|
|
495
|
-
}
|
|
496
|
-
/**
|
|
497
|
-
* Checks whether given object is an entity instance.
|
|
498
|
-
*/
|
|
499
|
-
static isEntity(data, allowReference = false) {
|
|
500
|
-
if (!Utils.isObject(data)) {
|
|
501
|
-
return false;
|
|
502
|
-
}
|
|
503
|
-
if (allowReference && !!data.__reference) {
|
|
504
|
-
return true;
|
|
505
|
-
}
|
|
506
|
-
return !!data.__entity;
|
|
507
|
-
}
|
|
508
|
-
/**
|
|
509
|
-
* Checks whether given object is a scalar reference.
|
|
510
|
-
*/
|
|
511
|
-
static isScalarReference(data, allowReference = false) {
|
|
512
|
-
return typeof data === 'object' && data?.__scalarReference;
|
|
513
|
-
}
|
|
514
|
-
/**
|
|
515
|
-
* Checks whether the argument is empty (array without items, object without keys or falsy value).
|
|
516
|
-
*/
|
|
517
|
-
static isEmpty(data) {
|
|
518
|
-
if (Array.isArray(data)) {
|
|
519
|
-
return data.length === 0;
|
|
520
|
-
}
|
|
521
|
-
if (Utils.isObject(data)) {
|
|
522
|
-
return !Utils.hasObjectKeys(data);
|
|
523
|
-
}
|
|
524
|
-
return !data;
|
|
525
|
-
}
|
|
526
|
-
/**
|
|
527
|
-
* Gets string name of given class.
|
|
528
|
-
*/
|
|
529
|
-
static className(classOrName) {
|
|
530
|
-
if (typeof classOrName === 'string') {
|
|
531
|
-
return classOrName;
|
|
532
|
-
}
|
|
533
|
-
return classOrName.name;
|
|
534
|
-
}
|
|
535
|
-
static extractChildElements(items, prefix, allSymbol) {
|
|
536
|
-
return items
|
|
537
|
-
.filter(field => field === allSymbol || field.startsWith(`${prefix}.`))
|
|
538
|
-
.map(field => (field === allSymbol ? allSymbol : field.substring(prefix.length + 1)));
|
|
539
|
-
}
|
|
540
|
-
/**
|
|
541
|
-
* Tries to detect TypeScript support.
|
|
542
|
-
*/
|
|
543
|
-
static detectTypeScriptSupport() {
|
|
544
|
-
/* v8 ignore next */
|
|
545
|
-
const process = globalThis.process ?? {};
|
|
546
|
-
/* v8 ignore next */
|
|
547
|
-
return (process.argv?.[0]?.endsWith('ts-node') || // running via ts-node directly
|
|
548
|
-
!!process.env?.MIKRO_ORM_CLI_ALWAYS_ALLOW_TS || // forced explicitly or enabled via `registerTypeScriptSupport()`
|
|
549
|
-
!!process.env?.TS_JEST || // check if ts-jest is used
|
|
550
|
-
!!process.env?.VITEST || // check if vitest is used
|
|
551
|
-
!!process.versions?.bun || // check if bun is used
|
|
552
|
-
process.argv?.slice(1).some(arg => /\.([mc]?ts|tsx)$/.exec(arg)) || // executing `.ts` file
|
|
553
|
-
process.execArgv?.some(arg => {
|
|
554
|
-
return (arg.includes('ts-node') || // check for ts-node loader
|
|
555
|
-
arg.includes('@swc-node/register') || // check for swc-node/register loader
|
|
556
|
-
arg.includes('node_modules/tsx/')); // check for tsx loader
|
|
557
|
-
}));
|
|
558
|
-
}
|
|
559
|
-
/**
|
|
560
|
-
* Gets the type of the argument.
|
|
561
|
-
*/
|
|
562
|
-
static getObjectType(value) {
|
|
563
|
-
const simple = typeof value;
|
|
564
|
-
if (['string', 'number', 'boolean', 'bigint'].includes(simple)) {
|
|
565
|
-
return simple;
|
|
566
|
-
}
|
|
567
|
-
const objectType = Object.prototype.toString.call(value);
|
|
568
|
-
const type = /^\[object (.+)]$/.exec(objectType)[1];
|
|
569
|
-
if (type === 'Uint8Array') {
|
|
570
|
-
return 'Buffer';
|
|
571
|
-
}
|
|
572
|
-
return type;
|
|
573
|
-
}
|
|
574
|
-
/**
|
|
575
|
-
* Checks whether the value is POJO (e.g. `{ foo: 'bar' }`, and not instance of `Foo`)
|
|
576
|
-
*/
|
|
577
|
-
static isPlainObject(value) {
|
|
578
|
-
return ((value !== null &&
|
|
579
|
-
typeof value === 'object' &&
|
|
580
|
-
typeof value.constructor === 'function' &&
|
|
581
|
-
(Object.hasOwn(value.constructor.prototype, 'isPrototypeOf') ||
|
|
582
|
-
Object.getPrototypeOf(value.constructor.prototype) === null)) ||
|
|
583
|
-
(value && Object.getPrototypeOf(value) === null) ||
|
|
584
|
-
value instanceof PlainObject);
|
|
585
|
-
}
|
|
586
|
-
/**
|
|
587
|
-
* Executes the `cb` promise serially on every element of the `items` array and returns array of resolved values.
|
|
588
|
-
*/
|
|
589
|
-
static async runSerial(items, cb) {
|
|
590
|
-
const ret = [];
|
|
591
|
-
for (const item of items) {
|
|
592
|
-
ret.push(await cb(item));
|
|
593
|
-
}
|
|
594
|
-
return ret;
|
|
595
|
-
}
|
|
596
|
-
static isCollection(item) {
|
|
597
|
-
return item?.__collection;
|
|
598
|
-
}
|
|
599
|
-
// FNV-1a 64-bit
|
|
600
|
-
static hash(data, length) {
|
|
601
|
-
let h1 = 0xcbf29ce484222325n;
|
|
602
|
-
for (let i = 0; i < data.length; i++) {
|
|
603
|
-
h1 ^= BigInt(data.charCodeAt(i));
|
|
604
|
-
h1 = (h1 * 0x100000001b3n) & 0xffffffffffffffffn;
|
|
605
|
-
}
|
|
606
|
-
const hash = h1.toString(16).padStart(16, '0');
|
|
607
|
-
if (length) {
|
|
608
|
-
return hash.substring(0, length);
|
|
609
|
-
}
|
|
610
|
-
return hash;
|
|
611
|
-
}
|
|
612
|
-
static runIfNotEmpty(clause, data) {
|
|
613
|
-
if (!Utils.isEmpty(data)) {
|
|
614
|
-
clause();
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
static defaultValue(prop, option, defaultValue) {
|
|
618
|
-
prop[option] = option in prop ? prop[option] : defaultValue;
|
|
619
|
-
}
|
|
620
|
-
static findDuplicates(items) {
|
|
621
|
-
return items.reduce((acc, v, i, arr) => {
|
|
622
|
-
return arr.indexOf(v) !== i && !acc.includes(v) ? acc.concat(v) : acc;
|
|
623
|
-
}, []);
|
|
624
|
-
}
|
|
625
|
-
static removeDuplicates(items) {
|
|
626
|
-
const ret = [];
|
|
627
|
-
const contains = (arr, val) => !!arr.find(v => equals(val, v));
|
|
628
|
-
for (const item of items) {
|
|
629
|
-
if (!contains(ret, item)) {
|
|
630
|
-
ret.push(item);
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
return ret;
|
|
634
|
-
}
|
|
635
|
-
static randomInt(min, max) {
|
|
636
|
-
return Math.round(Math.random() * (max - min)) + min;
|
|
637
|
-
}
|
|
638
|
-
/**
|
|
639
|
-
* Extracts all possible values of a TS enum. Works with both string and numeric enums.
|
|
640
|
-
*/
|
|
641
|
-
static extractEnumValues(target) {
|
|
642
|
-
const keys = Object.keys(target);
|
|
643
|
-
const values = Object.values(target);
|
|
644
|
-
const numeric = !!values.find(v => typeof v === 'number');
|
|
645
|
-
const constEnum = values.length % 2 === 0 && // const enum will have even number of items
|
|
646
|
-
values.slice(0, values.length / 2).every(v => typeof v === 'string') && // first half are strings
|
|
647
|
-
values.slice(values.length / 2).every(v => typeof v === 'number') && // second half are numbers
|
|
648
|
-
this.equals(keys, values
|
|
649
|
-
.slice(values.length / 2)
|
|
650
|
-
.concat(values.slice(0, values.length / 2))
|
|
651
|
-
.map(v => '' + v)); // and when swapped, it will match the keys
|
|
652
|
-
if (numeric || constEnum) {
|
|
653
|
-
return values.filter(val => !keys.includes(val));
|
|
654
|
-
}
|
|
655
|
-
return values;
|
|
132
|
+
static PK_SEPARATOR = '~~~';
|
|
133
|
+
static #ORM_VERSION = '7.0.4';
|
|
134
|
+
/**
|
|
135
|
+
* Checks if the argument is instance of `Object`. Returns false for arrays.
|
|
136
|
+
*/
|
|
137
|
+
static isObject(o) {
|
|
138
|
+
return !!o && typeof o === 'object' && !Array.isArray(o);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Removes `undefined` properties (recursively) so they are not saved as nulls
|
|
142
|
+
*/
|
|
143
|
+
static dropUndefinedProperties(o, value, visited = new Set()) {
|
|
144
|
+
if (Array.isArray(o)) {
|
|
145
|
+
for (const item of o) {
|
|
146
|
+
Utils.dropUndefinedProperties(item, value, visited);
|
|
147
|
+
}
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (!Utils.isPlainObject(o) || visited.has(o)) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
visited.add(o);
|
|
154
|
+
for (const key of Object.keys(o)) {
|
|
155
|
+
if (o[key] === value) {
|
|
156
|
+
delete o[key];
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
Utils.dropUndefinedProperties(o[key], value, visited);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Returns the number of properties on `obj`. This is 20x faster than Object.keys(obj).length.
|
|
164
|
+
* @see https://github.com/deepkit/deepkit-framework/blob/master/packages/core/src/core.ts
|
|
165
|
+
*/
|
|
166
|
+
static getObjectKeysSize(object) {
|
|
167
|
+
let size = 0;
|
|
168
|
+
for (const key in object) {
|
|
169
|
+
if (Object.hasOwn(object, key)) {
|
|
170
|
+
size++;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return size;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Returns true if `obj` has at least one property. This is 20x faster than Object.keys(obj).length.
|
|
177
|
+
* @see https://github.com/deepkit/deepkit-framework/blob/master/packages/core/src/core.ts
|
|
178
|
+
*/
|
|
179
|
+
static hasObjectKeys(object) {
|
|
180
|
+
for (const key in object) {
|
|
181
|
+
if (Object.hasOwn(object, key)) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
656
184
|
}
|
|
657
|
-
|
|
658
|
-
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Checks if arguments are deeply (but not strictly) equal.
|
|
189
|
+
*/
|
|
190
|
+
static equals(a, b) {
|
|
191
|
+
return equalsFn(a, b);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Gets array without duplicates.
|
|
195
|
+
*/
|
|
196
|
+
static unique(items) {
|
|
197
|
+
if (items.length < 2) {
|
|
198
|
+
return items;
|
|
199
|
+
}
|
|
200
|
+
return [...new Set(items)];
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Merges all sources into the target recursively.
|
|
204
|
+
*/
|
|
205
|
+
static merge(target, ...sources) {
|
|
206
|
+
return Utils._merge(target, sources, false);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Merges all sources into the target recursively. Ignores `undefined` values.
|
|
210
|
+
*/
|
|
211
|
+
static mergeConfig(target, ...sources) {
|
|
212
|
+
return Utils._merge(target, sources, true);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Merges all sources into the target recursively.
|
|
216
|
+
*/
|
|
217
|
+
static _merge(target, sources, ignoreUndefined) {
|
|
218
|
+
if (!sources.length) {
|
|
219
|
+
return target;
|
|
220
|
+
}
|
|
221
|
+
const source = sources.shift();
|
|
222
|
+
if (Utils.isObject(target) && Utils.isPlainObject(source)) {
|
|
223
|
+
for (const [key, value] of Object.entries(source)) {
|
|
224
|
+
if (ignoreUndefined && typeof value === 'undefined') {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
if (Utils.isPlainObject(value)) {
|
|
228
|
+
if (!Utils.isObject(target[key])) {
|
|
229
|
+
target[key] = Utils.copy(value);
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
/* v8 ignore next */
|
|
233
|
+
if (!(key in target)) {
|
|
234
|
+
Object.assign(target, { [key]: {} });
|
|
235
|
+
}
|
|
236
|
+
Utils._merge(target[key], [value], ignoreUndefined);
|
|
237
|
+
} else {
|
|
238
|
+
Object.assign(target, { [key]: value });
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return Utils._merge(target, sources, ignoreUndefined);
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Creates deep copy of given object.
|
|
246
|
+
*/
|
|
247
|
+
static copy(entity, respectCustomCloneMethod = true) {
|
|
248
|
+
return clone(entity, respectCustomCloneMethod);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Normalize the argument to always be an array.
|
|
252
|
+
*/
|
|
253
|
+
static asArray(data, strict = false) {
|
|
254
|
+
if (typeof data === 'undefined' && !strict) {
|
|
255
|
+
return [];
|
|
256
|
+
}
|
|
257
|
+
if (this.isIterable(data)) {
|
|
258
|
+
return Array.from(data);
|
|
259
|
+
}
|
|
260
|
+
return [data];
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Checks if the value is iterable, but considers strings and buffers as not iterable.
|
|
264
|
+
*/
|
|
265
|
+
static isIterable(value) {
|
|
266
|
+
if (value == null || typeof value === 'string' || ArrayBuffer.isView(value)) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
return typeof Object(value)[Symbol.iterator] === 'function';
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Renames object key, keeps order of properties.
|
|
273
|
+
*/
|
|
274
|
+
static renameKey(payload, from, to) {
|
|
275
|
+
if (Utils.isObject(payload) && from in payload && !(to in payload)) {
|
|
276
|
+
for (const key of Object.keys(payload)) {
|
|
277
|
+
const value = payload[key];
|
|
278
|
+
delete payload[key];
|
|
279
|
+
payload[from === key ? to : key] = value;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Returns array of functions argument names. Uses basic regex for source code analysis, might not work with advanced syntax.
|
|
285
|
+
*/
|
|
286
|
+
static getConstructorParams(func) {
|
|
287
|
+
const source = func.toString();
|
|
288
|
+
const i = source.indexOf('constructor');
|
|
289
|
+
if (i === -1) {
|
|
290
|
+
return undefined;
|
|
291
|
+
}
|
|
292
|
+
const start = source.indexOf('(', i);
|
|
293
|
+
if (start === -1) {
|
|
294
|
+
return undefined;
|
|
295
|
+
}
|
|
296
|
+
let depth = 0;
|
|
297
|
+
let end = start;
|
|
298
|
+
for (; end < source.length; end++) {
|
|
299
|
+
if (source[end] === '(') {
|
|
300
|
+
depth++;
|
|
301
|
+
}
|
|
302
|
+
if (source[end] === ')') {
|
|
303
|
+
depth--;
|
|
304
|
+
}
|
|
305
|
+
if (depth === 0) {
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
const raw = source.slice(start + 1, end);
|
|
310
|
+
return raw
|
|
311
|
+
.split(',')
|
|
312
|
+
.map(s => s.trim().replace(/=.*$/, '').trim())
|
|
313
|
+
.filter(Boolean)
|
|
314
|
+
.map(raw => (raw.startsWith('{') && raw.endsWith('}') ? '' : raw));
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Checks whether the argument looks like primary key (string, number or ObjectId).
|
|
318
|
+
*/
|
|
319
|
+
static isPrimaryKey(key, allowComposite = false) {
|
|
320
|
+
if (['string', 'number', 'bigint'].includes(typeof key)) {
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
323
|
+
if (allowComposite && Array.isArray(key) && key.every(v => Utils.isPrimaryKey(v, true))) {
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
if (Utils.isObject(key)) {
|
|
327
|
+
if (key.constructor?.name === 'ObjectId') {
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
if (!Utils.isPlainObject(key) && !Utils.isEntity(key, true)) {
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
659
333
|
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Extracts primary key from `data`. Accepts objects or primary keys directly.
|
|
338
|
+
*/
|
|
339
|
+
static extractPK(data, meta, strict = false) {
|
|
340
|
+
if (Utils.isPrimaryKey(data)) {
|
|
341
|
+
return data;
|
|
342
|
+
}
|
|
343
|
+
if (Utils.isEntity(data, true)) {
|
|
344
|
+
const wrapped = helper(data);
|
|
345
|
+
if (wrapped.__meta.compositePK) {
|
|
346
|
+
return wrapped.getPrimaryKeys();
|
|
347
|
+
}
|
|
348
|
+
return wrapped.getPrimaryKey();
|
|
349
|
+
}
|
|
350
|
+
if (strict && meta && Utils.getObjectKeysSize(data) !== meta.primaryKeys.length) {
|
|
351
|
+
return null;
|
|
352
|
+
}
|
|
353
|
+
if (Utils.isPlainObject(data) && meta) {
|
|
354
|
+
if (meta.compositePK) {
|
|
355
|
+
return this.getCompositeKeyValue(data, meta);
|
|
356
|
+
}
|
|
357
|
+
return data[meta.primaryKeys[0]] ?? data[meta.serializedPrimaryKey] ?? null;
|
|
358
|
+
}
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
static getCompositeKeyValue(data, meta, convertCustomTypes = false, platform) {
|
|
362
|
+
return meta.primaryKeys.map((pk, idx) => {
|
|
363
|
+
const value = Array.isArray(data) ? data[idx] : data[pk];
|
|
364
|
+
const prop = meta.properties[pk];
|
|
365
|
+
if (prop.targetMeta && Utils.isPlainObject(value)) {
|
|
366
|
+
return this.getCompositeKeyValue(value, prop.targetMeta);
|
|
367
|
+
}
|
|
368
|
+
if (prop.customType && platform && convertCustomTypes) {
|
|
369
|
+
const method = typeof convertCustomTypes === 'string' ? convertCustomTypes : 'convertToJSValue';
|
|
370
|
+
return prop.customType[method](value, platform);
|
|
371
|
+
}
|
|
372
|
+
return value;
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
static getCompositeKeyHash(data, meta, convertCustomTypes = false, platform, flat = false) {
|
|
376
|
+
let pks = this.getCompositeKeyValue(data, meta, convertCustomTypes, platform);
|
|
377
|
+
if (flat) {
|
|
378
|
+
pks = Utils.flatten(pks);
|
|
379
|
+
}
|
|
380
|
+
return Utils.getPrimaryKeyHash(pks);
|
|
381
|
+
}
|
|
382
|
+
static getPrimaryKeyHash(pks) {
|
|
383
|
+
return pks
|
|
384
|
+
.map(pk => {
|
|
385
|
+
if (Buffer.isBuffer(pk)) {
|
|
386
|
+
return pk.toString('hex');
|
|
387
|
+
}
|
|
388
|
+
if (pk instanceof Date) {
|
|
389
|
+
return pk.toISOString();
|
|
390
|
+
}
|
|
391
|
+
return pk;
|
|
392
|
+
})
|
|
393
|
+
.join(this.PK_SEPARATOR);
|
|
394
|
+
}
|
|
395
|
+
static splitPrimaryKeys(key) {
|
|
396
|
+
return key.split(this.PK_SEPARATOR);
|
|
397
|
+
}
|
|
398
|
+
static getPrimaryKeyValues(entity, meta, allowScalar = false, convertCustomTypes = false) {
|
|
399
|
+
/* v8 ignore next */
|
|
400
|
+
if (entity == null) {
|
|
401
|
+
return entity;
|
|
402
|
+
}
|
|
403
|
+
function toArray(val) {
|
|
404
|
+
if (Utils.isPlainObject(val)) {
|
|
405
|
+
return Object.values(val).flatMap(v => toArray(v));
|
|
406
|
+
}
|
|
407
|
+
return val;
|
|
408
|
+
}
|
|
409
|
+
let pk;
|
|
410
|
+
if (Utils.isEntity(entity, true)) {
|
|
411
|
+
pk = helper(entity).getPrimaryKey(convertCustomTypes);
|
|
412
|
+
} else {
|
|
413
|
+
pk = meta.primaryKeys.reduce((o, pk) => {
|
|
414
|
+
const targetMeta = meta.properties[pk].targetMeta;
|
|
415
|
+
if (targetMeta && Utils.isPlainObject(entity[pk])) {
|
|
416
|
+
o[pk] = Utils.getPrimaryKeyValues(entity[pk], targetMeta, allowScalar, convertCustomTypes);
|
|
417
|
+
} else {
|
|
418
|
+
o[pk] = entity[pk];
|
|
419
|
+
}
|
|
420
|
+
return o;
|
|
421
|
+
}, {});
|
|
422
|
+
}
|
|
423
|
+
if (meta.primaryKeys.length > 1) {
|
|
424
|
+
return toArray(pk);
|
|
425
|
+
}
|
|
426
|
+
if (allowScalar) {
|
|
427
|
+
if (Utils.isPlainObject(pk)) {
|
|
428
|
+
return pk[meta.primaryKeys[0]];
|
|
429
|
+
}
|
|
430
|
+
return pk;
|
|
431
|
+
}
|
|
432
|
+
return [pk];
|
|
433
|
+
}
|
|
434
|
+
static getPrimaryKeyCond(entity, primaryKeys) {
|
|
435
|
+
const cond = primaryKeys.reduce((o, pk) => {
|
|
436
|
+
o[pk] = Utils.extractPK(entity[pk]);
|
|
437
|
+
return o;
|
|
438
|
+
}, {});
|
|
439
|
+
if (Object.values(cond).some(v => v === null)) {
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
return cond;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Maps nested FKs from `[1, 2, 3]` to `[1, [2, 3]]`.
|
|
446
|
+
*/
|
|
447
|
+
static mapFlatCompositePrimaryKey(fk, prop, fieldNames = prop.fieldNames, idx = 0) {
|
|
448
|
+
if (!prop.targetMeta) {
|
|
449
|
+
return fk[idx++];
|
|
450
|
+
}
|
|
451
|
+
const parts = [];
|
|
452
|
+
for (const pk of prop.targetMeta.getPrimaryProps()) {
|
|
453
|
+
parts.push(this.mapFlatCompositePrimaryKey(fk, pk, fieldNames, idx));
|
|
454
|
+
idx += pk.fieldNames.length;
|
|
455
|
+
}
|
|
456
|
+
if (parts.length < 2) {
|
|
457
|
+
return parts[0];
|
|
458
|
+
}
|
|
459
|
+
return parts;
|
|
460
|
+
}
|
|
461
|
+
static getPrimaryKeyCondFromArray(pks, meta) {
|
|
462
|
+
return meta.getPrimaryProps().reduce((o, pk, idx) => {
|
|
463
|
+
if (Array.isArray(pks[idx]) && pk.targetMeta) {
|
|
464
|
+
o[pk.name] = pks[idx];
|
|
465
|
+
} else {
|
|
466
|
+
o[pk.name] = Utils.extractPK(pks[idx], meta);
|
|
467
|
+
}
|
|
468
|
+
return o;
|
|
469
|
+
}, {});
|
|
470
|
+
}
|
|
471
|
+
static getOrderedPrimaryKeys(id, meta, platform, convertCustomTypes = false, allowScalar = false) {
|
|
472
|
+
const data = Utils.isPrimaryKey(id) ? { [meta.primaryKeys[0]]: id } : id;
|
|
473
|
+
const pks = meta.primaryKeys.map((pk, idx) => {
|
|
474
|
+
const prop = meta.properties[pk];
|
|
475
|
+
// `data` can be a composite PK in form of array of PKs, or a DTO
|
|
476
|
+
let value = Array.isArray(data) ? data[idx] : (data[pk] ?? data);
|
|
477
|
+
if (convertCustomTypes && platform && prop.customType && !prop.targetMeta) {
|
|
478
|
+
value = prop.customType.convertToJSValue(value, platform);
|
|
479
|
+
}
|
|
480
|
+
if (prop.kind !== ReferenceKind.SCALAR && prop.targetMeta) {
|
|
481
|
+
const value2 = this.getOrderedPrimaryKeys(value, prop.targetMeta, platform, convertCustomTypes, allowScalar);
|
|
482
|
+
value = value2.length > 1 ? value2 : value2[0];
|
|
483
|
+
}
|
|
484
|
+
return value;
|
|
485
|
+
});
|
|
486
|
+
if (allowScalar && pks.length === 1) {
|
|
487
|
+
return pks[0];
|
|
488
|
+
}
|
|
489
|
+
// we need to flatten the PKs as composite PKs can be build from another composite PKs
|
|
490
|
+
// and this method is used to get the PK hash in identity map, that expects flat array
|
|
491
|
+
return Utils.flatten(pks);
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Checks whether given object is an entity instance.
|
|
495
|
+
*/
|
|
496
|
+
static isEntity(data, allowReference = false) {
|
|
497
|
+
if (!Utils.isObject(data)) {
|
|
498
|
+
return false;
|
|
499
|
+
}
|
|
500
|
+
if (allowReference && !!data.__reference) {
|
|
501
|
+
return true;
|
|
502
|
+
}
|
|
503
|
+
return !!data.__entity;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Checks whether given object is a scalar reference.
|
|
507
|
+
*/
|
|
508
|
+
static isScalarReference(data, allowReference = false) {
|
|
509
|
+
return typeof data === 'object' && data?.__scalarReference;
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Checks whether the argument is empty (array without items, object without keys or falsy value).
|
|
513
|
+
*/
|
|
514
|
+
static isEmpty(data) {
|
|
515
|
+
if (Array.isArray(data)) {
|
|
516
|
+
return data.length === 0;
|
|
517
|
+
}
|
|
518
|
+
if (Utils.isObject(data)) {
|
|
519
|
+
return !Utils.hasObjectKeys(data);
|
|
520
|
+
}
|
|
521
|
+
return !data;
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Gets string name of given class.
|
|
525
|
+
*/
|
|
526
|
+
static className(classOrName) {
|
|
527
|
+
if (typeof classOrName === 'string') {
|
|
528
|
+
return classOrName;
|
|
529
|
+
}
|
|
530
|
+
return classOrName.name;
|
|
531
|
+
}
|
|
532
|
+
static extractChildElements(items, prefix, allSymbol) {
|
|
533
|
+
return items
|
|
534
|
+
.filter(field => field === allSymbol || field.startsWith(`${prefix}.`))
|
|
535
|
+
.map(field => (field === allSymbol ? allSymbol : field.substring(prefix.length + 1)));
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Tries to detect TypeScript support.
|
|
539
|
+
*/
|
|
540
|
+
static detectTypeScriptSupport() {
|
|
541
|
+
/* v8 ignore next */
|
|
542
|
+
const process = globalThis.process ?? {};
|
|
543
|
+
/* v8 ignore next */
|
|
544
|
+
return (
|
|
545
|
+
process.argv?.[0]?.endsWith('ts-node') || // running via ts-node directly
|
|
546
|
+
!!process.env?.MIKRO_ORM_CLI_ALWAYS_ALLOW_TS || // forced explicitly or enabled via `registerTypeScriptSupport()`
|
|
547
|
+
!!process.env?.TS_JEST || // check if ts-jest is used
|
|
548
|
+
!!process.env?.VITEST || // check if vitest is used
|
|
549
|
+
!!process.versions?.bun || // check if bun is used
|
|
550
|
+
process.argv?.slice(1).some(arg => /\.([mc]?ts|tsx)$/.exec(arg)) || // executing `.ts` file
|
|
551
|
+
process.execArgv?.some(arg => {
|
|
552
|
+
return (
|
|
553
|
+
arg.includes('ts-node') || // check for ts-node loader
|
|
554
|
+
arg.includes('@swc-node/register') || // check for swc-node/register loader
|
|
555
|
+
arg.includes('node_modules/tsx/') || // check for tsx loader
|
|
556
|
+
arg.includes('@oxc-node/core') // check for oxc-node loader
|
|
557
|
+
);
|
|
558
|
+
})
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Gets the type of the argument.
|
|
563
|
+
*/
|
|
564
|
+
static getObjectType(value) {
|
|
565
|
+
const simple = typeof value;
|
|
566
|
+
if (['string', 'number', 'boolean', 'bigint'].includes(simple)) {
|
|
567
|
+
return simple;
|
|
568
|
+
}
|
|
569
|
+
const objectType = Object.prototype.toString.call(value);
|
|
570
|
+
const type = /^\[object (.+)]$/.exec(objectType)[1];
|
|
571
|
+
if (type === 'Uint8Array') {
|
|
572
|
+
return 'Buffer';
|
|
573
|
+
}
|
|
574
|
+
return type;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Checks whether the value is POJO (e.g. `{ foo: 'bar' }`, and not instance of `Foo`)
|
|
578
|
+
*/
|
|
579
|
+
static isPlainObject(value) {
|
|
580
|
+
return (
|
|
581
|
+
(value !== null &&
|
|
582
|
+
typeof value === 'object' &&
|
|
583
|
+
typeof value.constructor === 'function' &&
|
|
584
|
+
(Object.hasOwn(value.constructor.prototype, 'isPrototypeOf') ||
|
|
585
|
+
Object.getPrototypeOf(value.constructor.prototype) === null)) ||
|
|
586
|
+
(value && Object.getPrototypeOf(value) === null) ||
|
|
587
|
+
value instanceof PlainObject
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Executes the `cb` promise serially on every element of the `items` array and returns array of resolved values.
|
|
592
|
+
*/
|
|
593
|
+
static async runSerial(items, cb) {
|
|
594
|
+
const ret = [];
|
|
595
|
+
for (const item of items) {
|
|
596
|
+
ret.push(await cb(item));
|
|
597
|
+
}
|
|
598
|
+
return ret;
|
|
599
|
+
}
|
|
600
|
+
static isCollection(item) {
|
|
601
|
+
return item?.__collection;
|
|
602
|
+
}
|
|
603
|
+
// FNV-1a 64-bit
|
|
604
|
+
static hash(data, length) {
|
|
605
|
+
let h1 = 0xcbf29ce484222325n;
|
|
606
|
+
for (let i = 0; i < data.length; i++) {
|
|
607
|
+
h1 ^= BigInt(data.charCodeAt(i));
|
|
608
|
+
h1 = (h1 * 0x100000001b3n) & 0xffffffffffffffffn;
|
|
609
|
+
}
|
|
610
|
+
const hash = h1.toString(16).padStart(16, '0');
|
|
611
|
+
if (length) {
|
|
612
|
+
return hash.substring(0, length);
|
|
613
|
+
}
|
|
614
|
+
return hash;
|
|
615
|
+
}
|
|
616
|
+
static runIfNotEmpty(clause, data) {
|
|
617
|
+
if (!Utils.isEmpty(data)) {
|
|
618
|
+
clause();
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
static defaultValue(prop, option, defaultValue) {
|
|
622
|
+
prop[option] = option in prop ? prop[option] : defaultValue;
|
|
623
|
+
}
|
|
624
|
+
static findDuplicates(items) {
|
|
625
|
+
return items.reduce((acc, v, i, arr) => {
|
|
626
|
+
return arr.indexOf(v) !== i && !acc.includes(v) ? acc.concat(v) : acc;
|
|
627
|
+
}, []);
|
|
628
|
+
}
|
|
629
|
+
static removeDuplicates(items) {
|
|
630
|
+
const ret = [];
|
|
631
|
+
const contains = (arr, val) => !!arr.find(v => equals(val, v));
|
|
632
|
+
for (const item of items) {
|
|
633
|
+
if (!contains(ret, item)) {
|
|
634
|
+
ret.push(item);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return ret;
|
|
638
|
+
}
|
|
639
|
+
static randomInt(min, max) {
|
|
640
|
+
return Math.round(Math.random() * (max - min)) + min;
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Extracts all possible values of a TS enum. Works with both string and numeric enums.
|
|
644
|
+
*/
|
|
645
|
+
static extractEnumValues(target) {
|
|
646
|
+
const keys = Object.keys(target);
|
|
647
|
+
const values = Object.values(target);
|
|
648
|
+
const numeric = !!values.find(v => typeof v === 'number');
|
|
649
|
+
const constEnum =
|
|
650
|
+
values.length % 2 === 0 && // const enum will have even number of items
|
|
651
|
+
values.slice(0, values.length / 2).every(v => typeof v === 'string') && // first half are strings
|
|
652
|
+
values.slice(values.length / 2).every(v => typeof v === 'number') && // second half are numbers
|
|
653
|
+
this.equals(
|
|
654
|
+
keys,
|
|
655
|
+
values
|
|
656
|
+
.slice(values.length / 2)
|
|
657
|
+
.concat(values.slice(0, values.length / 2))
|
|
658
|
+
.map(v => '' + v),
|
|
659
|
+
); // and when swapped, it will match the keys
|
|
660
|
+
if (numeric || constEnum) {
|
|
661
|
+
return values.filter(val => !keys.includes(val));
|
|
662
|
+
}
|
|
663
|
+
return values;
|
|
664
|
+
}
|
|
665
|
+
static flatten(arrays, deep) {
|
|
666
|
+
return arrays.flatMap(v => (deep && Array.isArray(v) ? this.flatten(v, true) : v));
|
|
667
|
+
}
|
|
668
|
+
static isOperator(key, includeGroupOperators = true) {
|
|
669
|
+
if (!includeGroupOperators) {
|
|
670
|
+
return key in QueryOperator;
|
|
671
|
+
}
|
|
672
|
+
return key in GroupOperator || key in QueryOperator;
|
|
673
|
+
}
|
|
674
|
+
static hasNestedKey(object, key) {
|
|
675
|
+
if (!object) {
|
|
676
|
+
return false;
|
|
677
|
+
}
|
|
678
|
+
if (Array.isArray(object)) {
|
|
679
|
+
return object.some(o => this.hasNestedKey(o, key));
|
|
680
|
+
}
|
|
681
|
+
if (typeof object === 'object') {
|
|
682
|
+
return Object.entries(object).some(([k, v]) => k === key || this.hasNestedKey(v, key));
|
|
665
683
|
}
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
684
|
+
return false;
|
|
685
|
+
}
|
|
686
|
+
static getORMVersion() {
|
|
687
|
+
return this.#ORM_VERSION;
|
|
688
|
+
}
|
|
689
|
+
static createFunction(context, code, compiledFunctions, key) {
|
|
690
|
+
if (key && compiledFunctions?.[key]) {
|
|
691
|
+
return compiledFunctions[key](...context.values());
|
|
692
|
+
}
|
|
693
|
+
try {
|
|
694
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
695
|
+
return new Function(...context.keys(), `'use strict';\n` + code)(...context.values());
|
|
696
|
+
/* v8 ignore next */
|
|
697
|
+
} catch (e) {
|
|
698
|
+
// eslint-disable-next-line no-console
|
|
699
|
+
console.error(code);
|
|
700
|
+
throw e;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
static callCompiledFunction(fn, ...args) {
|
|
704
|
+
try {
|
|
705
|
+
return fn(...args);
|
|
706
|
+
} catch (e) {
|
|
707
|
+
/* v8 ignore next */
|
|
708
|
+
if ([SyntaxError, TypeError, EvalError, ReferenceError].some(t => e instanceof t)) {
|
|
709
|
+
const position = e.stack.match(/<anonymous>:(\d+):(\d+)/);
|
|
710
|
+
let code = fn.toString();
|
|
711
|
+
if (position) {
|
|
712
|
+
const lines = code.split('\n').map((line, idx) => {
|
|
713
|
+
if (idx === +position[1] - 5) {
|
|
714
|
+
return '> ' + line;
|
|
715
|
+
}
|
|
716
|
+
return ' ' + line;
|
|
717
|
+
});
|
|
718
|
+
lines.splice(+position[1] - 4, 0, ' '.repeat(+position[2]) + '^');
|
|
719
|
+
code = lines.join('\n');
|
|
720
|
+
}
|
|
721
|
+
// eslint-disable-next-line no-console
|
|
722
|
+
console.error(`JIT runtime error: ${e.message}\n\n${code}`);
|
|
723
|
+
}
|
|
724
|
+
throw e;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
static unwrapProperty(entity, meta, prop, payload = false) {
|
|
728
|
+
let p = prop;
|
|
729
|
+
const path = [];
|
|
730
|
+
if (!prop.object && !prop.array && !prop.embedded) {
|
|
731
|
+
return entity[prop.name] != null ? [[entity[prop.name], []]] : [];
|
|
732
|
+
}
|
|
733
|
+
while (p.embedded) {
|
|
734
|
+
const child = meta.properties[p.embedded[0]];
|
|
735
|
+
if (payload && !child.object && !child.array) {
|
|
736
|
+
break;
|
|
737
|
+
}
|
|
738
|
+
path.shift();
|
|
739
|
+
path.unshift(p.embedded[0], p.embedded[1]);
|
|
740
|
+
p = child;
|
|
741
|
+
}
|
|
742
|
+
const ret = [];
|
|
743
|
+
const follow = (t, idx = 0, i = []) => {
|
|
744
|
+
const k = path[idx];
|
|
745
|
+
if (Array.isArray(t)) {
|
|
746
|
+
for (const t1 of t) {
|
|
747
|
+
const ii = t.indexOf(t1);
|
|
748
|
+
follow(t1, idx, [...i, ii]);
|
|
749
|
+
}
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
if (t == null) {
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
const target = t[k];
|
|
756
|
+
if (path[++idx]) {
|
|
757
|
+
follow(target, idx, i);
|
|
758
|
+
} else if (target != null) {
|
|
759
|
+
ret.push([target, i]);
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
follow(entity);
|
|
763
|
+
return ret;
|
|
764
|
+
}
|
|
765
|
+
static setPayloadProperty(entity, meta, prop, value, idx) {
|
|
766
|
+
if (!prop.object && !prop.array && !prop.embedded) {
|
|
767
|
+
entity[prop.name] = value;
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
let target = entity;
|
|
771
|
+
let p = prop;
|
|
772
|
+
const path = [];
|
|
773
|
+
while (p.embedded) {
|
|
774
|
+
path.shift();
|
|
775
|
+
path.unshift(p.embedded[0], p.embedded[1]);
|
|
776
|
+
const prev = p;
|
|
777
|
+
p = meta.properties[p.embedded[0]];
|
|
778
|
+
if (!p.object) {
|
|
779
|
+
path.shift();
|
|
780
|
+
path[0] = prev.name;
|
|
781
|
+
break;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
let j = 0;
|
|
785
|
+
for (const k of path) {
|
|
786
|
+
const i = path.indexOf(k);
|
|
787
|
+
if (i === path.length - 1) {
|
|
788
|
+
if (Array.isArray(target)) {
|
|
789
|
+
target[idx[j++]][k] = value;
|
|
790
|
+
} else {
|
|
791
|
+
target[k] = value;
|
|
792
|
+
}
|
|
793
|
+
} else {
|
|
794
|
+
if (Array.isArray(target)) {
|
|
795
|
+
target = target[idx[j++]][k];
|
|
796
|
+
} else {
|
|
797
|
+
target = target[k];
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
static async tryImport({ module, warning }) {
|
|
803
|
+
try {
|
|
804
|
+
return await import(module);
|
|
805
|
+
} catch (err) {
|
|
806
|
+
if (warning && err.code === 'ERR_MODULE_NOT_FOUND') {
|
|
807
|
+
// eslint-disable-next-line no-console
|
|
808
|
+
console.warn(warning);
|
|
809
|
+
}
|
|
810
|
+
return undefined;
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
static xor(a, b) {
|
|
814
|
+
return (a || b) && !(a && b);
|
|
815
|
+
}
|
|
816
|
+
static keys(obj) {
|
|
817
|
+
return Object.keys(obj);
|
|
818
|
+
}
|
|
819
|
+
static values(obj) {
|
|
820
|
+
return Object.values(obj);
|
|
821
|
+
}
|
|
822
|
+
static entries(obj) {
|
|
823
|
+
return Object.entries(obj);
|
|
824
|
+
}
|
|
825
|
+
static primaryKeyToObject(meta, primaryKey, visible) {
|
|
826
|
+
const pks =
|
|
827
|
+
meta.compositePK && Utils.isPlainObject(primaryKey) ? Object.values(primaryKey) : Utils.asArray(primaryKey);
|
|
828
|
+
const pkProps = meta.getPrimaryProps();
|
|
829
|
+
return meta.primaryKeys.reduce((o, pk, idx) => {
|
|
830
|
+
const pkProp = pkProps[idx];
|
|
831
|
+
if (visible && !visible.includes(pkProp.name)) {
|
|
832
|
+
return o;
|
|
833
|
+
}
|
|
834
|
+
if (Utils.isPlainObject(pks[idx]) && pkProp.targetMeta) {
|
|
835
|
+
o[pk] = Utils.getOrderedPrimaryKeys(pks[idx], pkProp.targetMeta);
|
|
836
|
+
return o;
|
|
837
|
+
}
|
|
838
|
+
o[pk] = pks[idx];
|
|
839
|
+
return o;
|
|
840
|
+
}, {});
|
|
841
|
+
}
|
|
842
|
+
static getObjectQueryKeys(obj) {
|
|
843
|
+
return Reflect.ownKeys(obj).filter(key => {
|
|
844
|
+
if (!Object.prototype.propertyIsEnumerable.call(obj, key)) {
|
|
676
845
|
return false;
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
static createFunction(context, code, compiledFunctions, key) {
|
|
682
|
-
if (key && compiledFunctions?.[key]) {
|
|
683
|
-
return compiledFunctions[key](...context.values());
|
|
684
|
-
}
|
|
685
|
-
try {
|
|
686
|
-
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
687
|
-
return new Function(...context.keys(), `'use strict';\n` + code)(...context.values());
|
|
688
|
-
/* v8 ignore next */
|
|
689
|
-
}
|
|
690
|
-
catch (e) {
|
|
691
|
-
// eslint-disable-next-line no-console
|
|
692
|
-
console.error(code);
|
|
693
|
-
throw e;
|
|
694
|
-
}
|
|
695
|
-
}
|
|
696
|
-
static callCompiledFunction(fn, ...args) {
|
|
697
|
-
try {
|
|
698
|
-
return fn(...args);
|
|
699
|
-
}
|
|
700
|
-
catch (e) {
|
|
701
|
-
/* v8 ignore next */
|
|
702
|
-
if ([SyntaxError, TypeError, EvalError, ReferenceError].some(t => e instanceof t)) {
|
|
703
|
-
const position = e.stack.match(/<anonymous>:(\d+):(\d+)/);
|
|
704
|
-
let code = fn.toString();
|
|
705
|
-
if (position) {
|
|
706
|
-
const lines = code.split('\n').map((line, idx) => {
|
|
707
|
-
if (idx === +position[1] - 5) {
|
|
708
|
-
return '> ' + line;
|
|
709
|
-
}
|
|
710
|
-
return ' ' + line;
|
|
711
|
-
});
|
|
712
|
-
lines.splice(+position[1] - 4, 0, ' '.repeat(+position[2]) + '^');
|
|
713
|
-
code = lines.join('\n');
|
|
714
|
-
}
|
|
715
|
-
// eslint-disable-next-line no-console
|
|
716
|
-
console.error(`JIT runtime error: ${e.message}\n\n${code}`);
|
|
717
|
-
}
|
|
718
|
-
throw e;
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
static unwrapProperty(entity, meta, prop, payload = false) {
|
|
722
|
-
let p = prop;
|
|
723
|
-
const path = [];
|
|
724
|
-
if (!prop.object && !prop.array && !prop.embedded) {
|
|
725
|
-
return entity[prop.name] != null ? [[entity[prop.name], []]] : [];
|
|
726
|
-
}
|
|
727
|
-
while (p.embedded) {
|
|
728
|
-
const child = meta.properties[p.embedded[0]];
|
|
729
|
-
if (payload && !child.object && !child.array) {
|
|
730
|
-
break;
|
|
731
|
-
}
|
|
732
|
-
path.shift();
|
|
733
|
-
path.unshift(p.embedded[0], p.embedded[1]);
|
|
734
|
-
p = child;
|
|
735
|
-
}
|
|
736
|
-
const ret = [];
|
|
737
|
-
const follow = (t, idx = 0, i = []) => {
|
|
738
|
-
const k = path[idx];
|
|
739
|
-
if (Array.isArray(t)) {
|
|
740
|
-
for (const t1 of t) {
|
|
741
|
-
const ii = t.indexOf(t1);
|
|
742
|
-
follow(t1, idx, [...i, ii]);
|
|
743
|
-
}
|
|
744
|
-
return;
|
|
745
|
-
}
|
|
746
|
-
if (t == null) {
|
|
747
|
-
return;
|
|
748
|
-
}
|
|
749
|
-
const target = t[k];
|
|
750
|
-
if (path[++idx]) {
|
|
751
|
-
follow(target, idx, i);
|
|
752
|
-
}
|
|
753
|
-
else if (target != null) {
|
|
754
|
-
ret.push([target, i]);
|
|
755
|
-
}
|
|
756
|
-
};
|
|
757
|
-
follow(entity);
|
|
758
|
-
return ret;
|
|
759
|
-
}
|
|
760
|
-
static setPayloadProperty(entity, meta, prop, value, idx) {
|
|
761
|
-
if (!prop.object && !prop.array && !prop.embedded) {
|
|
762
|
-
entity[prop.name] = value;
|
|
763
|
-
return;
|
|
764
|
-
}
|
|
765
|
-
let target = entity;
|
|
766
|
-
let p = prop;
|
|
767
|
-
const path = [];
|
|
768
|
-
while (p.embedded) {
|
|
769
|
-
path.shift();
|
|
770
|
-
path.unshift(p.embedded[0], p.embedded[1]);
|
|
771
|
-
const prev = p;
|
|
772
|
-
p = meta.properties[p.embedded[0]];
|
|
773
|
-
if (!p.object) {
|
|
774
|
-
path.shift();
|
|
775
|
-
path[0] = prev.name;
|
|
776
|
-
break;
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
let j = 0;
|
|
780
|
-
for (const k of path) {
|
|
781
|
-
const i = path.indexOf(k);
|
|
782
|
-
if (i === path.length - 1) {
|
|
783
|
-
if (Array.isArray(target)) {
|
|
784
|
-
target[idx[j++]][k] = value;
|
|
785
|
-
}
|
|
786
|
-
else {
|
|
787
|
-
target[k] = value;
|
|
788
|
-
}
|
|
789
|
-
}
|
|
790
|
-
else {
|
|
791
|
-
if (Array.isArray(target)) {
|
|
792
|
-
target = target[idx[j++]][k];
|
|
793
|
-
}
|
|
794
|
-
else {
|
|
795
|
-
target = target[k];
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
static async tryImport({ module, warning, }) {
|
|
801
|
-
try {
|
|
802
|
-
return await import(module);
|
|
803
|
-
}
|
|
804
|
-
catch (err) {
|
|
805
|
-
if (warning && err.code === 'ERR_MODULE_NOT_FOUND') {
|
|
806
|
-
// eslint-disable-next-line no-console
|
|
807
|
-
console.warn(warning);
|
|
808
|
-
}
|
|
809
|
-
return undefined;
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
static xor(a, b) {
|
|
813
|
-
return (a || b) && !(a && b);
|
|
814
|
-
}
|
|
815
|
-
static keys(obj) {
|
|
816
|
-
return Object.keys(obj);
|
|
817
|
-
}
|
|
818
|
-
static values(obj) {
|
|
819
|
-
return Object.values(obj);
|
|
820
|
-
}
|
|
821
|
-
static entries(obj) {
|
|
822
|
-
return Object.entries(obj);
|
|
823
|
-
}
|
|
824
|
-
static primaryKeyToObject(meta, primaryKey, visible) {
|
|
825
|
-
const pks = meta.compositePK && Utils.isPlainObject(primaryKey) ? Object.values(primaryKey) : Utils.asArray(primaryKey);
|
|
826
|
-
const pkProps = meta.getPrimaryProps();
|
|
827
|
-
return meta.primaryKeys.reduce((o, pk, idx) => {
|
|
828
|
-
const pkProp = pkProps[idx];
|
|
829
|
-
if (visible && !visible.includes(pkProp.name)) {
|
|
830
|
-
return o;
|
|
831
|
-
}
|
|
832
|
-
if (Utils.isPlainObject(pks[idx]) && pkProp.targetMeta) {
|
|
833
|
-
o[pk] = Utils.getOrderedPrimaryKeys(pks[idx], pkProp.targetMeta);
|
|
834
|
-
return o;
|
|
835
|
-
}
|
|
836
|
-
o[pk] = pks[idx];
|
|
837
|
-
return o;
|
|
838
|
-
}, {});
|
|
839
|
-
}
|
|
840
|
-
static getObjectQueryKeys(obj) {
|
|
841
|
-
return Reflect.ownKeys(obj).filter(key => {
|
|
842
|
-
if (!Object.prototype.propertyIsEnumerable.call(obj, key)) {
|
|
843
|
-
return false;
|
|
844
|
-
}
|
|
845
|
-
return typeof key === 'string' || Raw.isKnownFragmentSymbol(key);
|
|
846
|
-
});
|
|
847
|
-
}
|
|
846
|
+
}
|
|
847
|
+
return typeof key === 'string' || Raw.isKnownFragmentSymbol(key);
|
|
848
|
+
});
|
|
849
|
+
}
|
|
848
850
|
}
|