@twin.org/entity-storage-models 0.0.3-next.16 → 0.0.3-next.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/helpers/{entityHelper.js → entityStorageHelper.js} +18 -10
- package/dist/es/helpers/entityStorageHelper.js.map +1 -0
- package/dist/es/index.js +1 -1
- package/dist/es/index.js.map +1 -1
- package/dist/types/helpers/{entityHelper.d.ts → entityStorageHelper.d.ts} +9 -4
- package/dist/types/index.d.ts +1 -1
- package/docs/changelog.md +7 -0
- package/docs/reference/classes/{EntityHelper.md → EntityStorageHelper.md} +17 -6
- package/docs/reference/index.md +1 -1
- package/package.json +3 -3
- package/dist/es/helpers/entityHelper.js.map +0 -1
|
@@ -5,26 +5,34 @@ import { ComparisonOperator, EntitySchemaHelper } from "@twin.org/entity";
|
|
|
5
5
|
/**
|
|
6
6
|
* Helper class for performing schema migrations between two connectors.
|
|
7
7
|
*/
|
|
8
|
-
export class
|
|
8
|
+
export class EntityStorageHelper {
|
|
9
9
|
/**
|
|
10
10
|
* Runtime name for the class.
|
|
11
11
|
*/
|
|
12
|
-
static CLASS_NAME = "
|
|
12
|
+
static CLASS_NAME = "EntityStorageHelper";
|
|
13
13
|
/**
|
|
14
14
|
* Prepare the entity by handling undefined and null values and validating it against the schema.
|
|
15
15
|
* @param entity The entity to handle undefined and null values for.
|
|
16
16
|
* @param schema The schema to validate the entity against.
|
|
17
17
|
* @param additionalProperties Optional list of additional properties to set on the entity.
|
|
18
|
+
* @param options Options controlling how null/undefined optional properties are stored.
|
|
19
|
+
* @param options.nullBehavior "omit" strips null/undefined optional properties before writing
|
|
20
|
+
* (NoSQL — avoids index-key type errors). "nullify" converts undefined to null (SQL — the default).
|
|
18
21
|
* @returns The entity with undefined and null values handled.
|
|
19
22
|
*/
|
|
20
|
-
static prepareEntity(entity, schema, additionalProperties) {
|
|
23
|
+
static prepareEntity(entity, schema, additionalProperties, options) {
|
|
21
24
|
const entityForValidation = ObjectHelper.clone(entity);
|
|
22
25
|
EntitySchemaHelper.validateEntity(entityForValidation, schema);
|
|
23
26
|
if (Is.arrayValue(schema.properties)) {
|
|
24
27
|
for (const property of schema.properties) {
|
|
25
28
|
if (property.optional ?? false) {
|
|
26
29
|
const propValue = entityForValidation[property.property];
|
|
27
|
-
if (
|
|
30
|
+
if (options?.nullBehavior === "omit") {
|
|
31
|
+
if (propValue === undefined || propValue === null) {
|
|
32
|
+
ObjectHelper.propertyDelete(entityForValidation, property.property);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else if (propValue === undefined) {
|
|
28
36
|
ObjectHelper.propertySet(entityForValidation, property.property, null);
|
|
29
37
|
}
|
|
30
38
|
}
|
|
@@ -53,8 +61,8 @@ export class EntityHelper {
|
|
|
53
61
|
return nonNullEntity;
|
|
54
62
|
}
|
|
55
63
|
/**
|
|
56
|
-
* Deep-clone condition tree and
|
|
57
|
-
* so in-memory evaluation matches stored-
|
|
64
|
+
* Deep-clone condition tree and normalise null/undefined to undefined on Equals/NotEquals leaves
|
|
65
|
+
* so in-memory evaluation matches stored-absent semantics (optional absent props are omitted/undefined).
|
|
58
66
|
* @param condition The user-supplied condition (not mutated).
|
|
59
67
|
* @returns A clone safe to pass to check.
|
|
60
68
|
*/
|
|
@@ -62,16 +70,16 @@ export class EntityHelper {
|
|
|
62
70
|
if ("conditions" in condition) {
|
|
63
71
|
return {
|
|
64
72
|
...condition,
|
|
65
|
-
conditions: condition.conditions.map(c =>
|
|
73
|
+
conditions: condition.conditions.map(c => EntityStorageHelper.normalizeConditionValues(c))
|
|
66
74
|
};
|
|
67
75
|
}
|
|
68
76
|
const leaf = condition;
|
|
69
77
|
if ((leaf.comparison === ComparisonOperator.Equals ||
|
|
70
78
|
leaf.comparison === ComparisonOperator.NotEquals) &&
|
|
71
|
-
leaf.value === undefined) {
|
|
72
|
-
return { ...leaf, value:
|
|
79
|
+
(leaf.value === undefined || leaf.value === null)) {
|
|
80
|
+
return { ...leaf, value: undefined };
|
|
73
81
|
}
|
|
74
82
|
return { ...leaf };
|
|
75
83
|
}
|
|
76
84
|
}
|
|
77
|
-
//# sourceMappingURL=
|
|
85
|
+
//# sourceMappingURL=entityStorageHelper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entityStorageHelper.js","sourceRoot":"","sources":["../../../src/helpers/entityStorageHelper.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Is, ObjectHelper } from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntitySchemaHelper,\n\ttype IEntitySchema\n} from \"@twin.org/entity\";\nimport { nameof } from \"@twin.org/nameof\";\n\n/**\n * Helper class for performing schema migrations between two connectors.\n */\nexport class EntityStorageHelper {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<EntityStorageHelper>();\n\n\t/**\n\t * Prepare the entity by handling undefined and null values and validating it against the schema.\n\t * @param entity The entity to handle undefined and null values for.\n\t * @param schema The schema to validate the entity against.\n\t * @param additionalProperties Optional list of additional properties to set on the entity.\n\t * @param options Options controlling how null/undefined optional properties are stored.\n\t * @param options.nullBehavior \"omit\" strips null/undefined optional properties before writing\n\t * (NoSQL — avoids index-key type errors). \"nullify\" converts undefined to null (SQL — the default).\n\t * @returns The entity with undefined and null values handled.\n\t */\n\tpublic static prepareEntity<T>(\n\t\tentity: T,\n\t\tschema: IEntitySchema<T>,\n\t\tadditionalProperties?: { property: string; value: unknown }[],\n\t\toptions?: { nullBehavior?: \"omit\" | \"nullify\" }\n\t): T {\n\t\tconst entityForValidation = ObjectHelper.clone(entity);\n\t\tEntitySchemaHelper.validateEntity(entityForValidation, schema);\n\n\t\tif (Is.arrayValue(schema.properties)) {\n\t\t\tfor (const property of schema.properties) {\n\t\t\t\tif (property.optional ?? false) {\n\t\t\t\t\tconst propValue = entityForValidation[property.property];\n\t\t\t\t\tif (options?.nullBehavior === \"omit\") {\n\t\t\t\t\t\tif (propValue === undefined || propValue === null) {\n\t\t\t\t\t\t\tObjectHelper.propertyDelete(entityForValidation, property.property as string);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (propValue === undefined) {\n\t\t\t\t\t\tObjectHelper.propertySet(entityForValidation, property.property as string, null);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (Is.arrayValue(additionalProperties)) {\n\t\t\tfor (const additionalProperty of additionalProperties) {\n\t\t\t\tObjectHelper.propertySet(\n\t\t\t\t\tentityForValidation,\n\t\t\t\t\tadditionalProperty.property,\n\t\t\t\t\tadditionalProperty.value\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn entityForValidation;\n\t}\n\n\t/**\n\t * Un-prepare the entity by removing null values.\n\t * @param entity The entity to handle undefined and null values for.\n\t * @param removeProperties Optional list of properties to remove from the entity.\n\t * @returns The entity with undefined and null values handled.\n\t */\n\tpublic static unPrepareEntity<T>(entity: Partial<T> | undefined, removeProperties?: string[]): T {\n\t\tconst nonNullEntity = ObjectHelper.removeEmptyProperties(entity, { removeNull: true });\n\n\t\tif (Is.arrayValue(removeProperties)) {\n\t\t\tfor (const property of removeProperties) {\n\t\t\t\tObjectHelper.propertyDelete(nonNullEntity, property);\n\t\t\t}\n\t\t}\n\n\t\treturn nonNullEntity as T;\n\t}\n\n\t/**\n\t * Deep-clone condition tree and normalise null/undefined to undefined on Equals/NotEquals leaves\n\t * so in-memory evaluation matches stored-absent semantics (optional absent props are omitted/undefined).\n\t * @param condition The user-supplied condition (not mutated).\n\t * @returns A clone safe to pass to check.\n\t */\n\tpublic static normalizeConditionValues<T>(condition: EntityCondition<T>): EntityCondition<T> {\n\t\tif (\"conditions\" in condition) {\n\t\t\treturn {\n\t\t\t\t...condition,\n\t\t\t\tconditions: condition.conditions.map(c => EntityStorageHelper.normalizeConditionValues(c))\n\t\t\t};\n\t\t}\n\n\t\tconst leaf = condition;\n\t\tif (\n\t\t\t(leaf.comparison === ComparisonOperator.Equals ||\n\t\t\t\tleaf.comparison === ComparisonOperator.NotEquals) &&\n\t\t\t(leaf.value === undefined || leaf.value === null)\n\t\t) {\n\t\t\treturn { ...leaf, value: undefined };\n\t\t}\n\t\treturn { ...leaf };\n\t}\n}\n"]}
|
package/dist/es/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright 2024 IOTA Stiftung.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
3
|
export * from "./factories/entityStorageConnectorFactory.js";
|
|
4
|
-
export * from "./helpers/
|
|
4
|
+
export * from "./helpers/entityStorageHelper.js";
|
|
5
5
|
export * from "./helpers/migrationHelper.js";
|
|
6
6
|
export * from "./models/api/IEntityStorageCountRequest.js";
|
|
7
7
|
export * from "./models/api/IEntityStorageCountResponse.js";
|
package/dist/es/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,8CAA8C,CAAC;AAC7D,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,cAAc,8CAA8C,CAAC;AAC7D,cAAc,kCAAkC,CAAC;AACjD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4CAA4C,CAAC;AAC3D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,0CAA0C,CAAC;AACzD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,kDAAkD,CAAC;AACjE,cAAc,6CAA6C,CAAC;AAC5D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,0CAA0C,CAAC;AACzD,cAAc,qCAAqC,CAAC;AACpD,cAAc,qCAAqC,CAAC;AACpD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,+BAA+B,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nexport * from \"./factories/entityStorageConnectorFactory.js\";\nexport * from \"./helpers/entityStorageHelper.js\";\nexport * from \"./helpers/migrationHelper.js\";\nexport * from \"./models/api/IEntityStorageCountRequest.js\";\nexport * from \"./models/api/IEntityStorageCountResponse.js\";\nexport * from \"./models/api/IEntityStorageEmptyRequest.js\";\nexport * from \"./models/api/IEntityStorageGetRequest.js\";\nexport * from \"./models/api/IEntityStorageGetResponse.js\";\nexport * from \"./models/api/IEntityStorageListRequest.js\";\nexport * from \"./models/api/IEntityStorageListResponse.js\";\nexport * from \"./models/api/IEntityStorageRemoveBatchRequest.js\";\nexport * from \"./models/api/IEntityStorageRemoveRequest.js\";\nexport * from \"./models/api/IEntityStorageSetBatchRequest.js\";\nexport * from \"./models/api/IEntityStorageSetRequest.js\";\nexport * from \"./models/IEntityStorageComponent.js\";\nexport * from \"./models/IEntityStorageConnector.js\";\nexport * from \"./models/IEntityStorageMigrationConnector.js\";\nexport * from \"./models/IMigrationOptions.js\";\n"]}
|
|
@@ -2,7 +2,7 @@ import { type EntityCondition, type IEntitySchema } from "@twin.org/entity";
|
|
|
2
2
|
/**
|
|
3
3
|
* Helper class for performing schema migrations between two connectors.
|
|
4
4
|
*/
|
|
5
|
-
export declare class
|
|
5
|
+
export declare class EntityStorageHelper {
|
|
6
6
|
/**
|
|
7
7
|
* Runtime name for the class.
|
|
8
8
|
*/
|
|
@@ -12,12 +12,17 @@ export declare class EntityHelper {
|
|
|
12
12
|
* @param entity The entity to handle undefined and null values for.
|
|
13
13
|
* @param schema The schema to validate the entity against.
|
|
14
14
|
* @param additionalProperties Optional list of additional properties to set on the entity.
|
|
15
|
+
* @param options Options controlling how null/undefined optional properties are stored.
|
|
16
|
+
* @param options.nullBehavior "omit" strips null/undefined optional properties before writing
|
|
17
|
+
* (NoSQL — avoids index-key type errors). "nullify" converts undefined to null (SQL — the default).
|
|
15
18
|
* @returns The entity with undefined and null values handled.
|
|
16
19
|
*/
|
|
17
20
|
static prepareEntity<T>(entity: T, schema: IEntitySchema<T>, additionalProperties?: {
|
|
18
21
|
property: string;
|
|
19
22
|
value: unknown;
|
|
20
|
-
}[]
|
|
23
|
+
}[], options?: {
|
|
24
|
+
nullBehavior?: "omit" | "nullify";
|
|
25
|
+
}): T;
|
|
21
26
|
/**
|
|
22
27
|
* Un-prepare the entity by removing null values.
|
|
23
28
|
* @param entity The entity to handle undefined and null values for.
|
|
@@ -26,8 +31,8 @@ export declare class EntityHelper {
|
|
|
26
31
|
*/
|
|
27
32
|
static unPrepareEntity<T>(entity: Partial<T> | undefined, removeProperties?: string[]): T;
|
|
28
33
|
/**
|
|
29
|
-
* Deep-clone condition tree and
|
|
30
|
-
* so in-memory evaluation matches stored-
|
|
34
|
+
* Deep-clone condition tree and normalise null/undefined to undefined on Equals/NotEquals leaves
|
|
35
|
+
* so in-memory evaluation matches stored-absent semantics (optional absent props are omitted/undefined).
|
|
31
36
|
* @param condition The user-supplied condition (not mutated).
|
|
32
37
|
* @returns A clone safe to pass to check.
|
|
33
38
|
*/
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from "./factories/entityStorageConnectorFactory.js";
|
|
2
|
-
export * from "./helpers/
|
|
2
|
+
export * from "./helpers/entityStorageHelper.js";
|
|
3
3
|
export * from "./helpers/migrationHelper.js";
|
|
4
4
|
export * from "./models/api/IEntityStorageCountRequest.js";
|
|
5
5
|
export * from "./models/api/IEntityStorageCountResponse.js";
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.3-next.17](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-models-v0.0.3-next.16...entity-storage-models-v0.0.3-next.17) (2026-06-01)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* null secondary indexes ([#103](https://github.com/iotaledger/twin-entity-storage/issues/103)) ([5e44f11](https://github.com/iotaledger/twin-entity-storage/commit/5e44f11bb5af5bf2c27d6f1d56aba5851116ff89))
|
|
9
|
+
|
|
3
10
|
## [0.0.3-next.16](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-models-v0.0.3-next.15...entity-storage-models-v0.0.3-next.16) (2026-05-20)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Class:
|
|
1
|
+
# Class: EntityStorageHelper
|
|
2
2
|
|
|
3
3
|
Helper class for performing schema migrations between two connectors.
|
|
4
4
|
|
|
@@ -6,11 +6,11 @@ Helper class for performing schema migrations between two connectors.
|
|
|
6
6
|
|
|
7
7
|
### Constructor
|
|
8
8
|
|
|
9
|
-
> **new
|
|
9
|
+
> **new EntityStorageHelper**(): `EntityStorageHelper`
|
|
10
10
|
|
|
11
11
|
#### Returns
|
|
12
12
|
|
|
13
|
-
`
|
|
13
|
+
`EntityStorageHelper`
|
|
14
14
|
|
|
15
15
|
## Properties
|
|
16
16
|
|
|
@@ -24,7 +24,7 @@ Runtime name for the class.
|
|
|
24
24
|
|
|
25
25
|
### prepareEntity() {#prepareentity}
|
|
26
26
|
|
|
27
|
-
> `static` **prepareEntity**\<`T`\>(`entity`, `schema`, `additionalProperties?`): `T`
|
|
27
|
+
> `static` **prepareEntity**\<`T`\>(`entity`, `schema`, `additionalProperties?`, `options?`): `T`
|
|
28
28
|
|
|
29
29
|
Prepare the entity by handling undefined and null values and validating it against the schema.
|
|
30
30
|
|
|
@@ -54,6 +54,17 @@ The schema to validate the entity against.
|
|
|
54
54
|
|
|
55
55
|
Optional list of additional properties to set on the entity.
|
|
56
56
|
|
|
57
|
+
##### options?
|
|
58
|
+
|
|
59
|
+
Options controlling how null/undefined optional properties are stored.
|
|
60
|
+
|
|
61
|
+
###### nullBehavior?
|
|
62
|
+
|
|
63
|
+
`"omit"` \| `"nullify"`
|
|
64
|
+
|
|
65
|
+
"omit" strips null/undefined optional properties before writing
|
|
66
|
+
(NoSQL — avoids index-key type errors). "nullify" converts undefined to null (SQL — the default).
|
|
67
|
+
|
|
57
68
|
#### Returns
|
|
58
69
|
|
|
59
70
|
`T`
|
|
@@ -100,8 +111,8 @@ The entity with undefined and null values handled.
|
|
|
100
111
|
|
|
101
112
|
> `static` **normalizeConditionValues**\<`T`\>(`condition`): `EntityCondition`\<`T`\>
|
|
102
113
|
|
|
103
|
-
Deep-clone condition tree and
|
|
104
|
-
so in-memory evaluation matches stored-
|
|
114
|
+
Deep-clone condition tree and normalise null/undefined to undefined on Equals/NotEquals leaves
|
|
115
|
+
so in-memory evaluation matches stored-absent semantics (optional absent props are omitted/undefined).
|
|
105
116
|
|
|
106
117
|
#### Type Parameters
|
|
107
118
|
|
package/docs/reference/index.md
CHANGED
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/entity-storage-models",
|
|
3
|
-
"version": "0.0.3-next.
|
|
3
|
+
"version": "0.0.3-next.17",
|
|
4
4
|
"description": "Shared models for storage contracts, requests, responses and connector capabilities.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/iotaledger/entity-storage.git",
|
|
7
|
+
"url": "git+https://github.com/iotaledger/twin-entity-storage.git",
|
|
8
8
|
"directory": "packages/entity-storage-models"
|
|
9
9
|
},
|
|
10
10
|
"author": "martyn.janes@iota.org",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"schemas"
|
|
52
52
|
],
|
|
53
53
|
"bugs": {
|
|
54
|
-
"url": "git+https://github.com/iotaledger/entity-storage/issues"
|
|
54
|
+
"url": "git+https://github.com/iotaledger/twin-entity-storage/issues"
|
|
55
55
|
},
|
|
56
56
|
"homepage": "https://twindev.org"
|
|
57
57
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"entityHelper.js","sourceRoot":"","sources":["../../../src/helpers/entityHelper.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EACN,kBAAkB,EAElB,kBAAkB,EAElB,MAAM,kBAAkB,CAAC;AAG1B;;GAEG;AACH,MAAM,OAAO,YAAY;IACxB;;OAEG;IACI,MAAM,CAAU,UAAU,kBAAkC;IAEnE;;;;;;OAMG;IACI,MAAM,CAAC,aAAa,CAC1B,MAAS,EACT,MAAwB,EACxB,oBAA6D;QAE7D,MAAM,mBAAmB,GAAG,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACvD,kBAAkB,CAAC,cAAc,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;QAE/D,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;YACtC,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;gBAC1C,IAAI,QAAQ,CAAC,QAAQ,IAAI,KAAK,EAAE,CAAC;oBAChC,MAAM,SAAS,GAAG,mBAAmB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBACzD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;wBAC7B,YAAY,CAAC,WAAW,CAAC,mBAAmB,EAAE,QAAQ,CAAC,QAAkB,EAAE,IAAI,CAAC,CAAC;oBAClF,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;QAED,IAAI,EAAE,CAAC,UAAU,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACzC,KAAK,MAAM,kBAAkB,IAAI,oBAAoB,EAAE,CAAC;gBACvD,YAAY,CAAC,WAAW,CACvB,mBAAmB,EACnB,kBAAkB,CAAC,QAAQ,EAC3B,kBAAkB,CAAC,KAAK,CACxB,CAAC;YACH,CAAC;QACF,CAAC;QAED,OAAO,mBAAmB,CAAC;IAC5B,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,eAAe,CAAI,MAA8B,EAAE,gBAA2B;QAC3F,MAAM,aAAa,GAAG,YAAY,CAAC,qBAAqB,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;QAEvF,IAAI,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACrC,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;gBACzC,YAAY,CAAC,cAAc,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;YACtD,CAAC;QACF,CAAC;QAED,OAAO,aAAkB,CAAC;IAC3B,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,wBAAwB,CAAI,SAA6B;QACtE,IAAI,YAAY,IAAI,SAAS,EAAE,CAAC;YAC/B,OAAO;gBACN,GAAG,SAAS;gBACZ,UAAU,EAAE,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC;aACnF,CAAC;QACH,CAAC;QAED,MAAM,IAAI,GAAG,SAAS,CAAC;QACvB,IACC,CAAC,IAAI,CAAC,UAAU,KAAK,kBAAkB,CAAC,MAAM;YAC7C,IAAI,CAAC,UAAU,KAAK,kBAAkB,CAAC,SAAS,CAAC;YAClD,IAAI,CAAC,KAAK,KAAK,SAAS,EACvB,CAAC;YACF,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACjC,CAAC;QACD,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;IACpB,CAAC","sourcesContent":["// Copyright 2026 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Is, ObjectHelper } from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntitySchemaHelper,\n\ttype IEntitySchema\n} from \"@twin.org/entity\";\nimport { nameof } from \"@twin.org/nameof\";\n\n/**\n * Helper class for performing schema migrations between two connectors.\n */\nexport class EntityHelper {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<EntityHelper>();\n\n\t/**\n\t * Prepare the entity by handling undefined and null values and validating it against the schema.\n\t * @param entity The entity to handle undefined and null values for.\n\t * @param schema The schema to validate the entity against.\n\t * @param additionalProperties Optional list of additional properties to set on the entity.\n\t * @returns The entity with undefined and null values handled.\n\t */\n\tpublic static prepareEntity<T>(\n\t\tentity: T,\n\t\tschema: IEntitySchema<T>,\n\t\tadditionalProperties?: { property: string; value: unknown }[]\n\t): T {\n\t\tconst entityForValidation = ObjectHelper.clone(entity);\n\t\tEntitySchemaHelper.validateEntity(entityForValidation, schema);\n\n\t\tif (Is.arrayValue(schema.properties)) {\n\t\t\tfor (const property of schema.properties) {\n\t\t\t\tif (property.optional ?? false) {\n\t\t\t\t\tconst propValue = entityForValidation[property.property];\n\t\t\t\t\tif (propValue === undefined) {\n\t\t\t\t\t\tObjectHelper.propertySet(entityForValidation, property.property as string, null);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (Is.arrayValue(additionalProperties)) {\n\t\t\tfor (const additionalProperty of additionalProperties) {\n\t\t\t\tObjectHelper.propertySet(\n\t\t\t\t\tentityForValidation,\n\t\t\t\t\tadditionalProperty.property,\n\t\t\t\t\tadditionalProperty.value\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn entityForValidation;\n\t}\n\n\t/**\n\t * Un-prepare the entity by removing null values.\n\t * @param entity The entity to handle undefined and null values for.\n\t * @param removeProperties Optional list of properties to remove from the entity.\n\t * @returns The entity with undefined and null values handled.\n\t */\n\tpublic static unPrepareEntity<T>(entity: Partial<T> | undefined, removeProperties?: string[]): T {\n\t\tconst nonNullEntity = ObjectHelper.removeEmptyProperties(entity, { removeNull: true });\n\n\t\tif (Is.arrayValue(removeProperties)) {\n\t\t\tfor (const property of removeProperties) {\n\t\t\t\tObjectHelper.propertyDelete(nonNullEntity, property);\n\t\t\t}\n\t\t}\n\n\t\treturn nonNullEntity as T;\n\t}\n\n\t/**\n\t * Deep-clone condition tree and map `undefined` to `null` on Equals/NotEquals leaves\n\t * so in-memory evaluation matches stored-null semantics (optional absent props are stored as null).\n\t * @param condition The user-supplied condition (not mutated).\n\t * @returns A clone safe to pass to check.\n\t */\n\tpublic static normalizeConditionValues<T>(condition: EntityCondition<T>): EntityCondition<T> {\n\t\tif (\"conditions\" in condition) {\n\t\t\treturn {\n\t\t\t\t...condition,\n\t\t\t\tconditions: condition.conditions.map(c => EntityHelper.normalizeConditionValues(c))\n\t\t\t};\n\t\t}\n\n\t\tconst leaf = condition;\n\t\tif (\n\t\t\t(leaf.comparison === ComparisonOperator.Equals ||\n\t\t\t\tleaf.comparison === ComparisonOperator.NotEquals) &&\n\t\t\tleaf.value === undefined\n\t\t) {\n\t\t\treturn { ...leaf, value: null };\n\t\t}\n\t\treturn { ...leaf };\n\t}\n}\n"]}
|