@axi-engine/fields 0.3.9 → 0.3.11
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/index.d.mts +230 -61
- package/dist/index.d.ts +230 -61
- package/dist/index.js +400 -128
- package/dist/index.mjs +386 -119
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -35,12 +35,17 @@ __export(index_exports, {
|
|
|
35
35
|
CoreStringField: () => CoreStringField,
|
|
36
36
|
CoreTreeNodeFactory: () => CoreTreeNodeFactory,
|
|
37
37
|
DataStore: () => DataStore,
|
|
38
|
+
DataStoreHydrator: () => DataStoreHydrator,
|
|
39
|
+
DataStoreSnapshotter: () => DataStoreSnapshotter,
|
|
40
|
+
FieldHydrator: () => FieldHydrator,
|
|
38
41
|
FieldRegistry: () => FieldRegistry,
|
|
39
|
-
|
|
42
|
+
FieldSnapshotter: () => FieldSnapshotter,
|
|
40
43
|
FieldTree: () => FieldTree,
|
|
41
|
-
|
|
44
|
+
FieldTreeHydrator: () => FieldTreeHydrator,
|
|
45
|
+
FieldTreeSnapshotter: () => FieldTreeSnapshotter,
|
|
42
46
|
Fields: () => Fields,
|
|
43
|
-
|
|
47
|
+
FieldsHydrator: () => FieldsHydrator,
|
|
48
|
+
FieldsSnapshotter: () => FieldsSnapshotter,
|
|
44
49
|
Policies: () => Policies,
|
|
45
50
|
PolicySerializer: () => PolicySerializer,
|
|
46
51
|
clampMaxPolicy: () => clampMaxPolicy,
|
|
@@ -468,6 +473,9 @@ var Fields = class _Fields {
|
|
|
468
473
|
*/
|
|
469
474
|
remove(names) {
|
|
470
475
|
const namesToRemove = Array.isArray(names) ? names : [names];
|
|
476
|
+
if (!namesToRemove.length) {
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
471
479
|
const reallyRemoved = namesToRemove.filter((name) => {
|
|
472
480
|
const field = this._fields.get(name);
|
|
473
481
|
if (!field) {
|
|
@@ -824,7 +832,7 @@ var CoreTreeNodeFactory = class extends CoreFieldsFactory {
|
|
|
824
832
|
}
|
|
825
833
|
};
|
|
826
834
|
|
|
827
|
-
// src/
|
|
835
|
+
// src/serializers/policies/clamp-policy-serializer-handler.ts
|
|
828
836
|
var ClampPolicySerializerHandler = class {
|
|
829
837
|
snapshot(policy) {
|
|
830
838
|
return { min: policy.min, max: policy.max };
|
|
@@ -834,7 +842,7 @@ var ClampPolicySerializerHandler = class {
|
|
|
834
842
|
}
|
|
835
843
|
};
|
|
836
844
|
|
|
837
|
-
// src/
|
|
845
|
+
// src/serializers/policies/clamp-max-policy-serializer-handler.ts
|
|
838
846
|
var ClampMaxPolicySerializerHandler = class {
|
|
839
847
|
snapshot(policy) {
|
|
840
848
|
return { max: policy.max };
|
|
@@ -844,7 +852,7 @@ var ClampMaxPolicySerializerHandler = class {
|
|
|
844
852
|
}
|
|
845
853
|
};
|
|
846
854
|
|
|
847
|
-
// src/
|
|
855
|
+
// src/serializers/policies/clamp-min-policy-serializer-handler.ts
|
|
848
856
|
var ClampMinPolicySerializerHandler = class {
|
|
849
857
|
snapshot(policy) {
|
|
850
858
|
return { min: policy.min };
|
|
@@ -854,7 +862,7 @@ var ClampMinPolicySerializerHandler = class {
|
|
|
854
862
|
}
|
|
855
863
|
};
|
|
856
864
|
|
|
857
|
-
// src/
|
|
865
|
+
// src/serializers/policy-serializer.ts
|
|
858
866
|
var import_utils6 = require("@axi-engine/utils");
|
|
859
867
|
var PolicySerializer = class {
|
|
860
868
|
handlers = new import_utils6.Registry();
|
|
@@ -891,9 +899,9 @@ var PolicySerializer = class {
|
|
|
891
899
|
}
|
|
892
900
|
};
|
|
893
901
|
|
|
894
|
-
// src/
|
|
902
|
+
// src/serializers/field-hydrator.ts
|
|
895
903
|
var import_utils7 = require("@axi-engine/utils");
|
|
896
|
-
var
|
|
904
|
+
var FieldHydrator = class {
|
|
897
905
|
/**
|
|
898
906
|
* Creates an instance of FieldSerializer.
|
|
899
907
|
* @param {FieldRegistry} fieldRegistry - A registry that maps string type names to Field constructors.
|
|
@@ -903,6 +911,47 @@ var FieldSerializer = class {
|
|
|
903
911
|
this.fieldRegistry = fieldRegistry;
|
|
904
912
|
this.policySerializer = policySerializer;
|
|
905
913
|
}
|
|
914
|
+
/**
|
|
915
|
+
* Restores a Field instance from its snapshot representation.
|
|
916
|
+
* It uses the `__type` property to find the correct constructor and hydrates
|
|
917
|
+
* the field with its value and all its policies.
|
|
918
|
+
* @param {FieldSnapshot} snapshot - The plain object snapshot to deserialize.
|
|
919
|
+
* @returns {Field<any>} A new, fully functional Field instance.
|
|
920
|
+
* @throws If the snapshot is invalid, missing a `__type`, or if the type is not registered.
|
|
921
|
+
*/
|
|
922
|
+
hydrate(snapshot) {
|
|
923
|
+
const fieldType = snapshot.__type;
|
|
924
|
+
(0, import_utils7.throwIfEmpty)(fieldType, 'Invalid field snapshot: missing "__type" identifier.');
|
|
925
|
+
const Ctor = this.fieldRegistry.getOrThrow(fieldType);
|
|
926
|
+
let policies = this.hydratePolicies(snapshot);
|
|
927
|
+
return new Ctor(snapshot.name, snapshot.value, { policies });
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* Updates an existing Field instance with data from a snapshot.
|
|
931
|
+
*
|
|
932
|
+
* This method modifies the field in-place, preserving the object reference.
|
|
933
|
+
* It updates the field's value and completely replaces its current policies
|
|
934
|
+
* with the ones defined in the snapshot.
|
|
935
|
+
*
|
|
936
|
+
* @param {Field<any>} field - The existing Field instance to update.
|
|
937
|
+
* @param {FieldSnapshot} snapshot - The snapshot containing the new state.
|
|
938
|
+
*/
|
|
939
|
+
patch(field, snapshot) {
|
|
940
|
+
field.policies.clear();
|
|
941
|
+
const policies = this.hydratePolicies(snapshot);
|
|
942
|
+
policies?.forEach((p) => field.policies.add(p));
|
|
943
|
+
field.value = snapshot.value;
|
|
944
|
+
}
|
|
945
|
+
hydratePolicies(snapshot) {
|
|
946
|
+
return (0, import_utils7.isNullOrUndefined)(snapshot.policies) ? void 0 : snapshot.policies.map((p) => this.policySerializer.hydrate(p));
|
|
947
|
+
}
|
|
948
|
+
};
|
|
949
|
+
|
|
950
|
+
// src/serializers/field-snapshotter.ts
|
|
951
|
+
var FieldSnapshotter = class {
|
|
952
|
+
constructor(policySerializer) {
|
|
953
|
+
this.policySerializer = policySerializer;
|
|
954
|
+
}
|
|
906
955
|
/**
|
|
907
956
|
* Creates a serializable snapshot of a Field instance.
|
|
908
957
|
* The snapshot includes the field's type, name, current value, and the state of all its policies.
|
|
@@ -916,58 +965,22 @@ var FieldSerializer = class {
|
|
|
916
965
|
value: field.value
|
|
917
966
|
};
|
|
918
967
|
if (!field.policies.isEmpty()) {
|
|
919
|
-
|
|
920
|
-
field.policies.items.forEach((policy) => serializedPolicies.push(this.policySerializer.snapshot(policy)));
|
|
921
|
-
snapshot.policies = serializedPolicies;
|
|
968
|
+
snapshot.policies = Array.from(field.policies.items.values()).map((policy) => this.policySerializer.snapshot(policy));
|
|
922
969
|
}
|
|
923
970
|
return snapshot;
|
|
924
971
|
}
|
|
925
|
-
/**
|
|
926
|
-
* Restores a Field instance from its snapshot representation.
|
|
927
|
-
* It uses the `__type` property to find the correct constructor and hydrates
|
|
928
|
-
* the field with its value and all its policies.
|
|
929
|
-
* @param {FieldSnapshot} snapshot - The plain object snapshot to deserialize.
|
|
930
|
-
* @returns {Field<any>} A new, fully functional Field instance.
|
|
931
|
-
* @throws If the snapshot is invalid, missing a `__type`, or if the type is not registered.
|
|
932
|
-
*/
|
|
933
|
-
hydrate(snapshot) {
|
|
934
|
-
const fieldType = snapshot.__type;
|
|
935
|
-
(0, import_utils7.throwIfEmpty)(fieldType, 'Invalid field snapshot: missing "__type" identifier.');
|
|
936
|
-
const Ctor = this.fieldRegistry.getOrThrow(fieldType);
|
|
937
|
-
let policies;
|
|
938
|
-
if (!(0, import_utils7.isNullOrUndefined)(snapshot.policies)) {
|
|
939
|
-
policies = [];
|
|
940
|
-
snapshot.policies.forEach((p) => policies.push(this.policySerializer.hydrate(p)));
|
|
941
|
-
}
|
|
942
|
-
return new Ctor(snapshot.name, snapshot.value, { policies });
|
|
943
|
-
}
|
|
944
972
|
};
|
|
945
973
|
|
|
946
|
-
// src/
|
|
947
|
-
var
|
|
974
|
+
// src/serializers/fields-hydrator.ts
|
|
975
|
+
var FieldsHydrator = class {
|
|
948
976
|
/**
|
|
949
977
|
* Creates an instance of FieldsSerializer.
|
|
950
978
|
* @param {FieldsFactory} fieldsFactory - A registry that maps string type names to Field constructors.
|
|
951
|
-
* @param {
|
|
979
|
+
* @param {FieldHydrator} fieldHydrator - A hydrator of field instances.
|
|
952
980
|
*/
|
|
953
|
-
constructor(fieldsFactory,
|
|
981
|
+
constructor(fieldsFactory, fieldHydrator) {
|
|
954
982
|
this.fieldsFactory = fieldsFactory;
|
|
955
|
-
this.
|
|
956
|
-
}
|
|
957
|
-
/**
|
|
958
|
-
* Creates a serializable snapshot of a `Fields` container.
|
|
959
|
-
*
|
|
960
|
-
* The snapshot includes a `__type` identifier (currently hardcoded) and an array of snapshots
|
|
961
|
-
* for each `Field` within the container.
|
|
962
|
-
* @param {Fields} fields - The `Fields` instance to serialize.
|
|
963
|
-
* @returns {FieldsSnapshot} A plain object ready for JSON serialization.
|
|
964
|
-
*/
|
|
965
|
-
snapshot(fields) {
|
|
966
|
-
const res = {
|
|
967
|
-
__type: fields.typeName
|
|
968
|
-
};
|
|
969
|
-
fields.fields.forEach((field) => res[field.name] = this.fieldSerializer.snapshot(field));
|
|
970
|
-
return res;
|
|
983
|
+
this.fieldHydrator = fieldHydrator;
|
|
971
984
|
}
|
|
972
985
|
/**
|
|
973
986
|
* Restores a `Fields` container instance from its snapshot representation.
|
|
@@ -981,37 +994,81 @@ var FieldsSerializer = class {
|
|
|
981
994
|
const fields = this.fieldsFactory.fields();
|
|
982
995
|
for (const fieldName in fieldsData) {
|
|
983
996
|
const fieldSnapshot = fieldsData[fieldName];
|
|
984
|
-
const restoredField = this.
|
|
997
|
+
const restoredField = this.fieldHydrator.hydrate(fieldSnapshot);
|
|
985
998
|
fields.add(restoredField);
|
|
986
999
|
}
|
|
987
1000
|
return fields;
|
|
988
1001
|
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Synchronizes an existing `Fields` container with a snapshot.
|
|
1004
|
+
*
|
|
1005
|
+
* This method performs a "smart update":
|
|
1006
|
+
* 1. **Removes** fields from the container that are missing in the snapshot.
|
|
1007
|
+
* 2. **Patches** existing fields in-place using {@link FieldHydrator.patch}, preserving object references.
|
|
1008
|
+
* 3. **Creates** (hydrates) and adds new fields that exist in the snapshot but not in the container.
|
|
1009
|
+
*
|
|
1010
|
+
* @param {Fields} fields - The target `Fields` container to update.
|
|
1011
|
+
* @param {FieldsSnapshot} snapshot - The source snapshot containing the desired state.
|
|
1012
|
+
*/
|
|
1013
|
+
patch(fields, snapshot) {
|
|
1014
|
+
const { __type, ...fieldsData } = snapshot;
|
|
1015
|
+
const snapshotKeys = new Set(Object.keys(fieldsData));
|
|
1016
|
+
const fieldsToRemove = Array.from(fields.fields.values()).filter((f) => !snapshotKeys.has(f.name)).map((f) => f.name);
|
|
1017
|
+
fields.remove(fieldsToRemove);
|
|
1018
|
+
for (const fieldName in fieldsData) {
|
|
1019
|
+
const fieldSnapshot = fieldsData[fieldName];
|
|
1020
|
+
if (fields.has(fieldName)) {
|
|
1021
|
+
const existingField = fields.get(fieldName);
|
|
1022
|
+
this.fieldHydrator.patch(existingField, fieldSnapshot);
|
|
1023
|
+
} else {
|
|
1024
|
+
const newField = this.fieldHydrator.hydrate(fieldSnapshot);
|
|
1025
|
+
fields.add(newField);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
989
1029
|
};
|
|
990
1030
|
|
|
991
|
-
// src/
|
|
992
|
-
var
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1031
|
+
// src/serializers/fields-snapshotter.ts
|
|
1032
|
+
var FieldsSnapshotter = class {
|
|
1033
|
+
/**
|
|
1034
|
+
* Creates an instance of FieldsSnapshotter.
|
|
1035
|
+
* @param {FieldSnapshotter} fieldSnapshotter - A serializer of field instances.
|
|
1036
|
+
*/
|
|
1037
|
+
constructor(fieldSnapshotter) {
|
|
1038
|
+
this.fieldSnapshotter = fieldSnapshotter;
|
|
997
1039
|
}
|
|
998
1040
|
/**
|
|
999
|
-
* Creates a serializable snapshot of
|
|
1000
|
-
*
|
|
1041
|
+
* Creates a serializable snapshot of a `Fields` container.
|
|
1042
|
+
*
|
|
1043
|
+
* The snapshot includes a `__type` identifier (currently hardcoded) and an array of snapshots
|
|
1044
|
+
* for each `Field` within the container.
|
|
1045
|
+
* @param {Fields} fields - The `Fields` instance to serialize.
|
|
1046
|
+
* @returns {FieldsSnapshot} A plain object ready for JSON serialization.
|
|
1001
1047
|
*/
|
|
1002
|
-
snapshot(
|
|
1048
|
+
snapshot(fields) {
|
|
1003
1049
|
const res = {
|
|
1004
|
-
__type:
|
|
1050
|
+
__type: fields.typeName
|
|
1005
1051
|
};
|
|
1006
|
-
|
|
1007
|
-
if (node.typeName === tree.typeName) {
|
|
1008
|
-
res[key] = this.snapshot(node);
|
|
1009
|
-
} else if (node.typeName === Fields.typeName) {
|
|
1010
|
-
res[key] = this.fieldsSerializer.snapshot(node);
|
|
1011
|
-
}
|
|
1012
|
-
});
|
|
1052
|
+
fields.fields.forEach((field) => res[field.name] = this.fieldSnapshotter.snapshot(field));
|
|
1013
1053
|
return res;
|
|
1014
1054
|
}
|
|
1055
|
+
};
|
|
1056
|
+
|
|
1057
|
+
// src/serializers/field-tree-hydrator.ts
|
|
1058
|
+
var import_utils8 = require("@axi-engine/utils");
|
|
1059
|
+
var FieldTreeHydrator = class {
|
|
1060
|
+
_factory;
|
|
1061
|
+
_fieldsHydrator;
|
|
1062
|
+
get factory() {
|
|
1063
|
+
return this._factory;
|
|
1064
|
+
}
|
|
1065
|
+
get fieldsHydrator() {
|
|
1066
|
+
return this._fieldsHydrator;
|
|
1067
|
+
}
|
|
1068
|
+
constructor(fieldTreeNodeFactory, fieldsHydrator) {
|
|
1069
|
+
this._factory = fieldTreeNodeFactory;
|
|
1070
|
+
this._fieldsHydrator = fieldsHydrator;
|
|
1071
|
+
}
|
|
1015
1072
|
/**
|
|
1016
1073
|
* Restores the state of the tree from a snapshot.
|
|
1017
1074
|
* It intelligently creates missing nodes based on `__type` metadata and delegates hydration to child nodes.
|
|
@@ -1019,24 +1076,103 @@ var FieldTreeSerializer = class {
|
|
|
1019
1076
|
*/
|
|
1020
1077
|
hydrate(snapshot) {
|
|
1021
1078
|
const { __type, ...nodes } = snapshot;
|
|
1022
|
-
const tree = this.
|
|
1079
|
+
const tree = this._factory.tree();
|
|
1023
1080
|
for (const key in nodes) {
|
|
1024
1081
|
const nodeData = nodes[key];
|
|
1025
1082
|
if ((0, import_utils8.isString)(nodeData)) {
|
|
1026
1083
|
continue;
|
|
1027
1084
|
}
|
|
1028
|
-
|
|
1029
|
-
tree.addNode(key, this.hydrate(nodeData));
|
|
1030
|
-
} else if (nodeData.__type === Fields.typeName) {
|
|
1031
|
-
tree.addNode(key, this.fieldsSerializer.hydrate(nodeData));
|
|
1032
|
-
}
|
|
1085
|
+
this.addNodeFromSnapshot(tree, key, nodeData);
|
|
1033
1086
|
}
|
|
1034
1087
|
return tree;
|
|
1035
1088
|
}
|
|
1089
|
+
/**
|
|
1090
|
+
* Synchronizes an existing `FieldTree` branch with a snapshot.
|
|
1091
|
+
*
|
|
1092
|
+
* This method performs a recursive update to match the tree state with the provided snapshot:
|
|
1093
|
+
* 1. **Removes** child nodes that are present in the tree but missing in the snapshot.
|
|
1094
|
+
* 2. **Creates** new nodes that are present in the snapshot but missing in the tree.
|
|
1095
|
+
* 3. **Replaces** nodes if their type has changed (e.g., replacing a `Fields` leaf with a `FieldTree` branch).
|
|
1096
|
+
* 4. **Patches** existing matching nodes in-place (recursively).
|
|
1097
|
+
*
|
|
1098
|
+
* @param {FieldTree} tree - The target tree instance to update.
|
|
1099
|
+
* @param {FieldTreeSnapshot} snapshot - The source snapshot containing the desired state.
|
|
1100
|
+
*/
|
|
1101
|
+
patch(tree, snapshot) {
|
|
1102
|
+
const { __type, ...nodes } = snapshot;
|
|
1103
|
+
const snapshotKeys = new Set(Object.keys(nodes));
|
|
1104
|
+
const nodesToRemove = Array.from(tree.nodes.keys()).filter((key) => !snapshotKeys.has(key));
|
|
1105
|
+
tree.removeNode(nodesToRemove);
|
|
1106
|
+
for (const key in nodes) {
|
|
1107
|
+
const nodeData = nodes[key];
|
|
1108
|
+
if ((0, import_utils8.isString)(nodeData)) {
|
|
1109
|
+
continue;
|
|
1110
|
+
}
|
|
1111
|
+
if (!tree.has(key)) {
|
|
1112
|
+
this.addNodeFromSnapshot(tree, key, nodeData);
|
|
1113
|
+
} else {
|
|
1114
|
+
const treeNode = tree.getNode(key);
|
|
1115
|
+
if (treeNode.typeName !== nodeData.__type) {
|
|
1116
|
+
tree.removeNode(key);
|
|
1117
|
+
this.addNodeFromSnapshot(tree, key, nodeData);
|
|
1118
|
+
} else {
|
|
1119
|
+
if (nodeData.__type === FieldTree.typeName) {
|
|
1120
|
+
this.patch(treeNode, nodeData);
|
|
1121
|
+
} else if (nodeData.__type === Fields.typeName) {
|
|
1122
|
+
this.fieldsHydrator.patch(treeNode, nodeData);
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
/**
|
|
1129
|
+
* Helper method to instantiate and add a new node to the tree based on the snapshot type.
|
|
1130
|
+
*
|
|
1131
|
+
* It determines whether to create a nested `FieldTree` or a `Fields` container
|
|
1132
|
+
* by inspecting the `__type` property of the snapshot, hydrates it, and attaches it to the parent tree.
|
|
1133
|
+
*
|
|
1134
|
+
* @param {FieldTree} tree - The parent tree instance where the new node will be added.
|
|
1135
|
+
* @param {string} key - The name (key) for the new node.
|
|
1136
|
+
* @param {FieldsSnapshot | FieldTreeSnapshot} snapshot - The source snapshot data.
|
|
1137
|
+
* @throws If the snapshot contains an unsupported or unknown `__type`.
|
|
1138
|
+
*/
|
|
1139
|
+
addNodeFromSnapshot(tree, key, snapshot) {
|
|
1140
|
+
if (snapshot.__type === FieldTree.typeName) {
|
|
1141
|
+
tree.addNode(key, this.hydrate(snapshot));
|
|
1142
|
+
} else if (snapshot.__type === Fields.typeName) {
|
|
1143
|
+
tree.addNode(key, this.fieldsHydrator.hydrate(snapshot));
|
|
1144
|
+
} else {
|
|
1145
|
+
(0, import_utils8.throwError)(`Can't hydrate node with unsupported type: ${snapshot.__type}`);
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
};
|
|
1149
|
+
|
|
1150
|
+
// src/serializers/field-tree-snapshotter.ts
|
|
1151
|
+
var FieldTreeSnapshotter = class {
|
|
1152
|
+
constructor(fieldsSnapshotter) {
|
|
1153
|
+
this.fieldsSnapshotter = fieldsSnapshotter;
|
|
1154
|
+
}
|
|
1155
|
+
/**
|
|
1156
|
+
* Creates a serializable snapshot of the entire tree and its contained fields.
|
|
1157
|
+
* @returns A plain JavaScript object representing the complete state managed by this tree.
|
|
1158
|
+
*/
|
|
1159
|
+
snapshot(tree) {
|
|
1160
|
+
const res = {
|
|
1161
|
+
__type: tree.typeName
|
|
1162
|
+
};
|
|
1163
|
+
tree.nodes.forEach((node, key) => {
|
|
1164
|
+
if (node.typeName === tree.typeName) {
|
|
1165
|
+
res[key] = this.snapshot(node);
|
|
1166
|
+
} else if (node.typeName === Fields.typeName) {
|
|
1167
|
+
res[key] = this.fieldsSnapshotter.snapshot(node);
|
|
1168
|
+
}
|
|
1169
|
+
});
|
|
1170
|
+
return res;
|
|
1171
|
+
}
|
|
1036
1172
|
};
|
|
1037
1173
|
|
|
1038
1174
|
// src/data-store.ts
|
|
1039
|
-
var
|
|
1175
|
+
var import_utils11 = require("@axi-engine/utils");
|
|
1040
1176
|
|
|
1041
1177
|
// src/data-store-field-resolver.ts
|
|
1042
1178
|
var import_utils9 = require("@axi-engine/utils");
|
|
@@ -1059,24 +1195,51 @@ var StringFieldResolver = class {
|
|
|
1059
1195
|
}
|
|
1060
1196
|
};
|
|
1061
1197
|
|
|
1198
|
+
// src/guards.ts
|
|
1199
|
+
var import_utils10 = require("@axi-engine/utils");
|
|
1200
|
+
function isFields(value) {
|
|
1201
|
+
return !(0, import_utils10.isNullOrUndefined)(value) && value.typeName === Fields.typeName;
|
|
1202
|
+
}
|
|
1203
|
+
function isFieldTree(value) {
|
|
1204
|
+
return !(0, import_utils10.isNullOrUndefined)(value) && value.typeName === FieldTree.typeName;
|
|
1205
|
+
}
|
|
1206
|
+
function isDataStore(value) {
|
|
1207
|
+
return !(0, import_utils10.isNullOrUndefined)(value) && value.typeName === DataStore.typeName;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1062
1210
|
// src/data-store.ts
|
|
1063
1211
|
var DataStore = class _DataStore {
|
|
1064
|
-
constructor(tree) {
|
|
1065
|
-
this.tree = tree;
|
|
1066
|
-
this.registerResolver(new NumericFieldResolver());
|
|
1067
|
-
this.registerResolver(new BooleanFieldResolver());
|
|
1068
|
-
this.registerResolver(new StringFieldResolver());
|
|
1069
|
-
}
|
|
1070
1212
|
static typeName = "dataStore";
|
|
1071
1213
|
typeName = _DataStore.typeName;
|
|
1072
1214
|
resolvers = [];
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1215
|
+
_variables;
|
|
1216
|
+
_tree;
|
|
1217
|
+
_factory;
|
|
1218
|
+
get variables() {
|
|
1219
|
+
if (!this._variables) {
|
|
1220
|
+
this._variables = this._factory.fields();
|
|
1078
1221
|
}
|
|
1079
|
-
return this.
|
|
1222
|
+
return this._variables;
|
|
1223
|
+
}
|
|
1224
|
+
get tree() {
|
|
1225
|
+
if (!this._tree) {
|
|
1226
|
+
this._tree = this._factory.tree();
|
|
1227
|
+
}
|
|
1228
|
+
return this._tree;
|
|
1229
|
+
}
|
|
1230
|
+
constructor(treeOrFactory, variables) {
|
|
1231
|
+
if (!isFieldTree(treeOrFactory)) {
|
|
1232
|
+
this._factory = treeOrFactory;
|
|
1233
|
+
} else {
|
|
1234
|
+
this._tree = treeOrFactory;
|
|
1235
|
+
this._factory = this._tree.factory;
|
|
1236
|
+
}
|
|
1237
|
+
if (variables) {
|
|
1238
|
+
this._variables = variables;
|
|
1239
|
+
}
|
|
1240
|
+
this.registerResolver(new NumericFieldResolver());
|
|
1241
|
+
this.registerResolver(new BooleanFieldResolver());
|
|
1242
|
+
this.registerResolver(new StringFieldResolver());
|
|
1080
1243
|
}
|
|
1081
1244
|
registerResolver(resolver) {
|
|
1082
1245
|
this.resolvers.unshift(resolver);
|
|
@@ -1145,10 +1308,10 @@ var DataStore = class _DataStore {
|
|
|
1145
1308
|
return this.getField(path);
|
|
1146
1309
|
}
|
|
1147
1310
|
getField(path) {
|
|
1148
|
-
const pathArr = (0,
|
|
1149
|
-
(0,
|
|
1150
|
-
if (this.
|
|
1151
|
-
return this.
|
|
1311
|
+
const pathArr = (0, import_utils11.ensurePathArray)(path);
|
|
1312
|
+
(0, import_utils11.throwIfEmpty)(pathArr, `Wrong path or path is empty: ${(0, import_utils11.ensurePathString)(path)}, should contain at least one path segment`);
|
|
1313
|
+
if (this.isPathToVariables(pathArr)) {
|
|
1314
|
+
return this.variables.get(pathArr[0]);
|
|
1152
1315
|
}
|
|
1153
1316
|
const fieldName = pathArr.pop();
|
|
1154
1317
|
const fields = this.tree.getFields(pathArr);
|
|
@@ -1167,10 +1330,10 @@ var DataStore = class _DataStore {
|
|
|
1167
1330
|
return this.tree.getFieldTree(path);
|
|
1168
1331
|
}
|
|
1169
1332
|
remove(path) {
|
|
1170
|
-
const pathArr = (0,
|
|
1171
|
-
(0,
|
|
1172
|
-
if (this.
|
|
1173
|
-
this.
|
|
1333
|
+
const pathArr = (0, import_utils11.ensurePathArray)(path);
|
|
1334
|
+
(0, import_utils11.throwIfEmpty)(pathArr, `Wrong path or path is empty: ${(0, import_utils11.ensurePathString)(path)}, should contain at least one path segment`);
|
|
1335
|
+
if (this.isPathToVariables(pathArr)) {
|
|
1336
|
+
this.variables.remove(pathArr);
|
|
1174
1337
|
return;
|
|
1175
1338
|
}
|
|
1176
1339
|
const node = this.tree.findParentNode(pathArr);
|
|
@@ -1181,17 +1344,6 @@ var DataStore = class _DataStore {
|
|
|
1181
1344
|
node.removeNode(leafName);
|
|
1182
1345
|
}
|
|
1183
1346
|
}
|
|
1184
|
-
isPathToRootFields(path) {
|
|
1185
|
-
return (0, import_utils10.ensurePathArray)(path).length === 1;
|
|
1186
|
-
}
|
|
1187
|
-
getDestinationFields(path) {
|
|
1188
|
-
const pathArr = (0, import_utils10.ensurePathArray)(path);
|
|
1189
|
-
if (this.isPathToRootFields(pathArr)) {
|
|
1190
|
-
return { fields: this.rootFields, leafName: pathArr[0] };
|
|
1191
|
-
}
|
|
1192
|
-
const leafName = pathArr.pop();
|
|
1193
|
-
return { fields: this.tree.getOrCreateFields(path), leafName };
|
|
1194
|
-
}
|
|
1195
1347
|
/**
|
|
1196
1348
|
* Creates a new, independent instance of the Store with a fresh, empty data state (FieldsTree).
|
|
1197
1349
|
*
|
|
@@ -1202,13 +1354,13 @@ var DataStore = class _DataStore {
|
|
|
1202
1354
|
* @returns {DataStore} A new, isolated DataStore instance.
|
|
1203
1355
|
*/
|
|
1204
1356
|
createIsolated() {
|
|
1205
|
-
return new _DataStore(this.
|
|
1357
|
+
return new _DataStore(this._factory);
|
|
1206
1358
|
}
|
|
1207
1359
|
/** code below -> implementation of the DataStore from utils */
|
|
1208
1360
|
has(path) {
|
|
1209
|
-
const pathArr = (0,
|
|
1210
|
-
if (this.
|
|
1211
|
-
return this.
|
|
1361
|
+
const pathArr = (0, import_utils11.ensurePathArray)(path);
|
|
1362
|
+
if (this.isPathToVariables(pathArr)) {
|
|
1363
|
+
return this.variables.has(pathArr[0]);
|
|
1212
1364
|
}
|
|
1213
1365
|
return this.tree.hasPath(pathArr);
|
|
1214
1366
|
}
|
|
@@ -1227,19 +1379,134 @@ var DataStore = class _DataStore {
|
|
|
1227
1379
|
delete(path) {
|
|
1228
1380
|
this.remove(path);
|
|
1229
1381
|
}
|
|
1382
|
+
/**
|
|
1383
|
+
* @internal Used for serialization
|
|
1384
|
+
*/
|
|
1385
|
+
getInternalVariables() {
|
|
1386
|
+
return this._variables;
|
|
1387
|
+
}
|
|
1388
|
+
/**
|
|
1389
|
+
* @internal Used for serialization
|
|
1390
|
+
*/
|
|
1391
|
+
getInternalTree() {
|
|
1392
|
+
return this._tree;
|
|
1393
|
+
}
|
|
1394
|
+
/**
|
|
1395
|
+
* @internal Used for serialization
|
|
1396
|
+
*/
|
|
1397
|
+
getOrCreateInternalVariables() {
|
|
1398
|
+
return this.variables;
|
|
1399
|
+
}
|
|
1400
|
+
/**
|
|
1401
|
+
* @internal Used for serialization
|
|
1402
|
+
*/
|
|
1403
|
+
getOrCreateInternalTree() {
|
|
1404
|
+
return this.tree;
|
|
1405
|
+
}
|
|
1406
|
+
/**
|
|
1407
|
+
* @private
|
|
1408
|
+
*/
|
|
1409
|
+
isPathToVariables(path) {
|
|
1410
|
+
return (0, import_utils11.ensurePathArray)(path).length === 1;
|
|
1411
|
+
}
|
|
1412
|
+
/**
|
|
1413
|
+
* @private
|
|
1414
|
+
*/
|
|
1415
|
+
getDestinationFields(path) {
|
|
1416
|
+
const pathArr = (0, import_utils11.ensurePathArray)(path);
|
|
1417
|
+
if (this.isPathToVariables(pathArr)) {
|
|
1418
|
+
return { fields: this.variables, leafName: pathArr[0] };
|
|
1419
|
+
}
|
|
1420
|
+
const leafName = pathArr.pop();
|
|
1421
|
+
return { fields: this.tree.getOrCreateFields(path), leafName };
|
|
1422
|
+
}
|
|
1230
1423
|
};
|
|
1231
1424
|
|
|
1232
|
-
// src/
|
|
1233
|
-
var
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1425
|
+
// src/serializers/data-store-hydrator.ts
|
|
1426
|
+
var import_utils12 = require("@axi-engine/utils");
|
|
1427
|
+
var DataStoreHydrator = class {
|
|
1428
|
+
/**
|
|
1429
|
+
* Creates an instance of DataStoreSerializer.
|
|
1430
|
+
* @param {FieldTreeHydrator} fieldsFieldTreeHydrator - The serializer used for the underlying tree and fields.
|
|
1431
|
+
*/
|
|
1432
|
+
constructor(fieldsFieldTreeHydrator) {
|
|
1433
|
+
this.fieldsFieldTreeHydrator = fieldsFieldTreeHydrator;
|
|
1434
|
+
}
|
|
1435
|
+
/**
|
|
1436
|
+
* Reconstructs a DataStore instance from a snapshot.
|
|
1437
|
+
*
|
|
1438
|
+
* If the snapshot contains a tree, the store is initialized with it.
|
|
1439
|
+
* If not, the store is initialized with the factory (lazy mode), and the
|
|
1440
|
+
* detached variables are injected if present.
|
|
1441
|
+
*
|
|
1442
|
+
* @param {DataStoreSnapshot} snapshot - The snapshot to hydrate.
|
|
1443
|
+
* @returns {DataStore} A new, fully restored DataStore instance.
|
|
1444
|
+
*/
|
|
1445
|
+
hydrate(snapshot) {
|
|
1446
|
+
const tree = (0, import_utils12.isNullOrUndefined)(snapshot.tree) ? void 0 : this.fieldsFieldTreeHydrator.hydrate(snapshot.tree);
|
|
1447
|
+
const variables = (0, import_utils12.isNullOrUndefined)(snapshot.variables) ? void 0 : this.fieldsFieldTreeHydrator.fieldsHydrator.hydrate(snapshot.variables);
|
|
1448
|
+
return new DataStore(tree ? tree : this.fieldsFieldTreeHydrator.factory, variables);
|
|
1449
|
+
}
|
|
1450
|
+
/**
|
|
1451
|
+
* Synchronizes a DataStore instance with a snapshot.
|
|
1452
|
+
*
|
|
1453
|
+
* This method ensures the DataStore's internal state matches the snapshot by:
|
|
1454
|
+
* 1. **Destroying** internal containers (variables/tree) if they are missing in the snapshot.
|
|
1455
|
+
* 2. **Patching** (updating/creating) contents if they exist in the snapshot.
|
|
1456
|
+
*
|
|
1457
|
+
* This allows for a granular update where only specific parts of the store (e.g., only variables)
|
|
1458
|
+
* are modified if the snapshot contains partial data, or a full reset if parts are missing.
|
|
1459
|
+
*
|
|
1460
|
+
* @param {DataStore} store - The target DataStore to update.
|
|
1461
|
+
* @param {DataStoreSnapshot} snapshot - The source snapshot.
|
|
1462
|
+
*/
|
|
1463
|
+
patch(store, snapshot) {
|
|
1464
|
+
if (!snapshot.variables) {
|
|
1465
|
+
store.getInternalVariables()?.destroy();
|
|
1466
|
+
} else {
|
|
1467
|
+
this.fieldsFieldTreeHydrator.fieldsHydrator.patch(store.getOrCreateInternalVariables(), snapshot.variables);
|
|
1468
|
+
}
|
|
1469
|
+
if (!snapshot.tree) {
|
|
1470
|
+
store.getInternalTree()?.destroy();
|
|
1471
|
+
} else {
|
|
1472
|
+
this.fieldsFieldTreeHydrator.patch(store.getOrCreateInternalTree(), snapshot.tree);
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1476
|
+
|
|
1477
|
+
// src/serializers/data-store-snapshotter.ts
|
|
1478
|
+
var DataStoreSnapshotter = class {
|
|
1479
|
+
/**
|
|
1480
|
+
* Creates an instance of DataStoreSnapshotter.
|
|
1481
|
+
* @param {FieldTreeSnapshotter} treeSnapshotter - The serializer used for the underlying tree and fields.
|
|
1482
|
+
*/
|
|
1483
|
+
constructor(treeSnapshotter) {
|
|
1484
|
+
this.treeSnapshotter = treeSnapshotter;
|
|
1485
|
+
}
|
|
1486
|
+
/**
|
|
1487
|
+
* Captures the current state of a DataStore into a serializable snapshot.
|
|
1488
|
+
*
|
|
1489
|
+
* It checks for the existence of internal variables and the internal tree,
|
|
1490
|
+
* serializing them only if they have been initialized (lazy serialization).
|
|
1491
|
+
*
|
|
1492
|
+
* @param {DataStore} store - The store instance to serialize.
|
|
1493
|
+
* @returns {DataStoreSnapshot} The snapshot object.
|
|
1494
|
+
*/
|
|
1495
|
+
snapshot(store) {
|
|
1496
|
+
let snapshot = {
|
|
1497
|
+
__type: store.typeName
|
|
1498
|
+
};
|
|
1499
|
+
const variables = store.getInternalVariables();
|
|
1500
|
+
if (variables) {
|
|
1501
|
+
snapshot.variables = this.treeSnapshotter.fieldsSnapshotter.snapshot(variables);
|
|
1502
|
+
}
|
|
1503
|
+
const tree = store.getInternalTree();
|
|
1504
|
+
if (tree) {
|
|
1505
|
+
snapshot.tree = this.treeSnapshotter.snapshot(tree);
|
|
1506
|
+
}
|
|
1507
|
+
return snapshot;
|
|
1508
|
+
}
|
|
1509
|
+
};
|
|
1243
1510
|
|
|
1244
1511
|
// src/setup.ts
|
|
1245
1512
|
function createCoreFieldRegistry() {
|
|
@@ -1261,11 +1528,11 @@ function createCoreTreeNodeFactory(fieldRegistry) {
|
|
|
1261
1528
|
return new CoreTreeNodeFactory(fieldRegistry);
|
|
1262
1529
|
}
|
|
1263
1530
|
function createCoreTreeSerializer(fieldTreeNodeFactory, policySerializer) {
|
|
1264
|
-
return new
|
|
1531
|
+
return new FieldTreeHydrator(
|
|
1265
1532
|
fieldTreeNodeFactory,
|
|
1266
|
-
new
|
|
1533
|
+
new FieldsHydrator(
|
|
1267
1534
|
fieldTreeNodeFactory,
|
|
1268
|
-
new
|
|
1535
|
+
new FieldHydrator(fieldTreeNodeFactory.fieldRegistry, policySerializer ?? createCorePolicySerializer())
|
|
1269
1536
|
)
|
|
1270
1537
|
);
|
|
1271
1538
|
}
|
|
@@ -1292,12 +1559,17 @@ function createCoreFieldSystem(config) {
|
|
|
1292
1559
|
CoreStringField,
|
|
1293
1560
|
CoreTreeNodeFactory,
|
|
1294
1561
|
DataStore,
|
|
1562
|
+
DataStoreHydrator,
|
|
1563
|
+
DataStoreSnapshotter,
|
|
1564
|
+
FieldHydrator,
|
|
1295
1565
|
FieldRegistry,
|
|
1296
|
-
|
|
1566
|
+
FieldSnapshotter,
|
|
1297
1567
|
FieldTree,
|
|
1298
|
-
|
|
1568
|
+
FieldTreeHydrator,
|
|
1569
|
+
FieldTreeSnapshotter,
|
|
1299
1570
|
Fields,
|
|
1300
|
-
|
|
1571
|
+
FieldsHydrator,
|
|
1572
|
+
FieldsSnapshotter,
|
|
1301
1573
|
Policies,
|
|
1302
1574
|
PolicySerializer,
|
|
1303
1575
|
clampMaxPolicy,
|