@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 CHANGED
@@ -788,13 +788,8 @@ interface FieldSnapshot {
788
788
  * plain, storable data (snapshots) and vice-versa. It uses a `FieldRegistry`
789
789
  * to resolve class constructors and a `PolicySerializer` to handle the state
790
790
  * of any attached policies.
791
- *
792
- * @todo Implement a `patch(field, snapshot)` method.
793
- * Unlike `hydrate`, which creates a new
794
- * instance, `patch` should update the state of an *existing* field instance
795
- * without breaking external references to it.
796
791
  */
797
- declare class FieldSerializer {
792
+ declare class FieldHydrator {
798
793
  private readonly fieldRegistry;
799
794
  private readonly policySerializer;
800
795
  /**
@@ -803,13 +798,6 @@ declare class FieldSerializer {
803
798
  * @param {PolicySerializer} policySerializer - A serializer dedicated to handling Policy instances.
804
799
  */
805
800
  constructor(fieldRegistry: FieldRegistry, policySerializer: PolicySerializer);
806
- /**
807
- * Creates a serializable snapshot of a Field instance.
808
- * The snapshot includes the field's type, name, current value, and the state of all its policies.
809
- * @param {Field<any>} field - The Field instance to serialize.
810
- * @returns {FieldSnapshot} A plain object ready for JSON serialization.
811
- */
812
- snapshot(field: Field<any>): FieldSnapshot;
813
801
  /**
814
802
  * Restores a Field instance from its snapshot representation.
815
803
  * It uses the `__type` property to find the correct constructor and hydrates
@@ -819,6 +807,30 @@ declare class FieldSerializer {
819
807
  * @throws If the snapshot is invalid, missing a `__type`, or if the type is not registered.
820
808
  */
821
809
  hydrate(snapshot: FieldSnapshot): Field<any>;
810
+ /**
811
+ * Updates an existing Field instance with data from a snapshot.
812
+ *
813
+ * This method modifies the field in-place, preserving the object reference.
814
+ * It updates the field's value and completely replaces its current policies
815
+ * with the ones defined in the snapshot.
816
+ *
817
+ * @param {Field<any>} field - The existing Field instance to update.
818
+ * @param {FieldSnapshot} snapshot - The snapshot containing the new state.
819
+ */
820
+ patch(field: Field<any>, snapshot: FieldSnapshot): void;
821
+ private hydratePolicies;
822
+ }
823
+
824
+ declare class FieldSnapshotter {
825
+ readonly policySerializer: PolicySerializer;
826
+ constructor(policySerializer: PolicySerializer);
827
+ /**
828
+ * Creates a serializable snapshot of a Field instance.
829
+ * The snapshot includes the field's type, name, current value, and the state of all its policies.
830
+ * @param {Field<any>} field - The Field instance to serialize.
831
+ * @returns {FieldSnapshot} A plain object ready for JSON serialization.
832
+ */
833
+ snapshot(field: Field<any>): FieldSnapshot;
822
834
  }
823
835
 
824
836
  /**
@@ -830,25 +842,53 @@ interface FieldsSnapshot {
830
842
  }
831
843
 
832
844
  /**
833
- * Orchestrates the serialization and deserialization of `Fields` container instances.
834
- *
835
- * This class acts as a high-level composer, responsible for converting an entire `Fields` object
836
- * into a storable snapshot and back.
837
- * It delegates the actual serialization of each `Field` and `Policy` to their respective serializers.
838
- *
839
- * @todo Implement a `patch(fields, snapshot)` method. It should perform a non-destructive
840
- * update, creating new fields, removing missing ones, and patching existing ones
841
- * in place, preserving the container instance itself.
845
+ * Deserialization of `Fields` container instances.
846
+ * Responsible for converting snapshot of `Fields` object into a `Fields` instance.
842
847
  */
843
- declare class FieldsSerializer<TFields extends Fields> {
848
+ declare class FieldsHydrator<TFields extends Fields> {
844
849
  private readonly fieldsFactory;
845
- private readonly fieldSerializer;
850
+ private readonly fieldHydrator;
846
851
  /**
847
852
  * Creates an instance of FieldsSerializer.
848
853
  * @param {FieldsFactory} fieldsFactory - A registry that maps string type names to Field constructors.
849
- * @param {FieldSerializer} fieldSerializer - A serializer of field instances.
854
+ * @param {FieldHydrator} fieldHydrator - A hydrator of field instances.
855
+ */
856
+ constructor(fieldsFactory: FieldsFactory<TFields>, fieldHydrator: FieldHydrator);
857
+ /**
858
+ * Restores a `Fields` container instance from its snapshot representation.
859
+ *
860
+ * It iterates through the field snapshots and hydrates them individually, adding them to the new container.
861
+ * @param {FieldsSnapshot} snapshot - The plain object snapshot to deserialize.
862
+ * @returns {Fields} A new `DefaultFields` instance populated with the restored fields.
863
+ */
864
+ hydrate(snapshot: FieldsSnapshot): TFields;
865
+ /**
866
+ * Synchronizes an existing `Fields` container with a snapshot.
867
+ *
868
+ * This method performs a "smart update":
869
+ * 1. **Removes** fields from the container that are missing in the snapshot.
870
+ * 2. **Patches** existing fields in-place using {@link FieldHydrator.patch}, preserving object references.
871
+ * 3. **Creates** (hydrates) and adds new fields that exist in the snapshot but not in the container.
872
+ *
873
+ * @param {Fields} fields - The target `Fields` container to update.
874
+ * @param {FieldsSnapshot} snapshot - The source snapshot containing the desired state.
875
+ */
876
+ patch(fields: TFields, snapshot: FieldsSnapshot): void;
877
+ }
878
+
879
+ /**
880
+ * The serialization of `Fields` container instances.
881
+ *
882
+ * This class responsible for converting an entire `Fields` object
883
+ * into a storable snapshot.
884
+ */
885
+ declare class FieldsSnapshotter {
886
+ private readonly fieldSnapshotter;
887
+ /**
888
+ * Creates an instance of FieldsSnapshotter.
889
+ * @param {FieldSnapshotter} fieldSnapshotter - A serializer of field instances.
850
890
  */
851
- constructor(fieldsFactory: FieldsFactory<TFields>, fieldSerializer: FieldSerializer);
891
+ constructor(fieldSnapshotter: FieldSnapshotter);
852
892
  /**
853
893
  * Creates a serializable snapshot of a `Fields` container.
854
894
  *
@@ -858,14 +898,6 @@ declare class FieldsSerializer<TFields extends Fields> {
858
898
  * @returns {FieldsSnapshot} A plain object ready for JSON serialization.
859
899
  */
860
900
  snapshot(fields: Fields): FieldsSnapshot;
861
- /**
862
- * Restores a `Fields` container instance from its snapshot representation.
863
- *
864
- * It iterates through the field snapshots and hydrates them individually, adding them to the new container.
865
- * @param {FieldsSnapshot} snapshot - The plain object snapshot to deserialize.
866
- * @returns {Fields} A new `DefaultFields` instance populated with the restored fields.
867
- */
868
- hydrate(snapshot: FieldsSnapshot): TFields;
869
901
  }
870
902
 
871
903
  /**
@@ -883,36 +915,90 @@ interface FieldTreeSnapshot {
883
915
  }
884
916
 
885
917
  /**
886
- * Orchestrates the recursive serialization and deserialization of `FieldTree` instances.
918
+ * Orchestrates the recursive deserialization of `FieldTree` instances.
887
919
  *
888
920
  * This class handles the conversion of an entire `FieldTree` object graph into a
889
921
  * plain, storable snapshot and vice-versa. It delegates the processing of `Fields`
890
- * leaf nodes to a dedicated `FieldsSerializer`.
922
+ * leaf nodes to a dedicated `FieldsHydrator`.
891
923
  * @todo Refactoring: The current implementation uses `if/else` logic in `snapshot` and `hydrate`
892
924
  * to process different node types. A more extensible approach would be to use a
893
925
  * registry of dedicated handlers for each node type.
894
926
  * This would allow new node types to be supported without
895
927
  * modifying this class, adhering to the Open/Closed Principle.
896
- *
897
- * @todo Implement a `patch(tree, snapshot)` method for recursive, non-destructive
898
- * updates. This method should traverse the existing tree and the snapshot,
899
- * patching nodes in place to maintain object references.
900
928
  */
901
- declare class FieldTreeSerializer<TFields extends Fields> {
902
- private readonly fieldTreeNodeFactory;
903
- private readonly fieldsSerializer;
904
- constructor(fieldTreeNodeFactory: FieldTreeFactory<TFields>, fieldsSerializer: FieldsSerializer<TFields>);
905
- /**
906
- * Creates a serializable snapshot of the entire tree and its contained fields.
907
- * @returns A plain JavaScript object representing the complete state managed by this tree.
908
- */
909
- snapshot(tree: FieldTree<TFields>): FieldTreeSnapshot;
929
+ declare class FieldTreeHydrator<TFields extends Fields> {
930
+ _factory: FieldTreeFactory<TFields>;
931
+ _fieldsHydrator: FieldsHydrator<TFields>;
932
+ get factory(): FieldTreeFactory<TFields>;
933
+ get fieldsHydrator(): FieldsHydrator<TFields>;
934
+ constructor(fieldTreeNodeFactory: FieldTreeFactory<TFields>, fieldsHydrator: FieldsHydrator<TFields>);
910
935
  /**
911
936
  * Restores the state of the tree from a snapshot.
912
937
  * It intelligently creates missing nodes based on `__type` metadata and delegates hydration to child nodes.
913
938
  * @param snapshot The snapshot object to load.
914
939
  */
915
940
  hydrate(snapshot: FieldTreeSnapshot): FieldTree<TFields>;
941
+ /**
942
+ * Synchronizes an existing `FieldTree` branch with a snapshot.
943
+ *
944
+ * This method performs a recursive update to match the tree state with the provided snapshot:
945
+ * 1. **Removes** child nodes that are present in the tree but missing in the snapshot.
946
+ * 2. **Creates** new nodes that are present in the snapshot but missing in the tree.
947
+ * 3. **Replaces** nodes if their type has changed (e.g., replacing a `Fields` leaf with a `FieldTree` branch).
948
+ * 4. **Patches** existing matching nodes in-place (recursively).
949
+ *
950
+ * @param {FieldTree} tree - The target tree instance to update.
951
+ * @param {FieldTreeSnapshot} snapshot - The source snapshot containing the desired state.
952
+ */
953
+ patch(tree: FieldTree<TFields>, snapshot: FieldTreeSnapshot): void;
954
+ /**
955
+ * Helper method to instantiate and add a new node to the tree based on the snapshot type.
956
+ *
957
+ * It determines whether to create a nested `FieldTree` or a `Fields` container
958
+ * by inspecting the `__type` property of the snapshot, hydrates it, and attaches it to the parent tree.
959
+ *
960
+ * @param {FieldTree} tree - The parent tree instance where the new node will be added.
961
+ * @param {string} key - The name (key) for the new node.
962
+ * @param {FieldsSnapshot | FieldTreeSnapshot} snapshot - The source snapshot data.
963
+ * @throws If the snapshot contains an unsupported or unknown `__type`.
964
+ */
965
+ private addNodeFromSnapshot;
966
+ }
967
+
968
+ /**
969
+ */
970
+ declare class FieldTreeSnapshotter {
971
+ readonly fieldsSnapshotter: FieldsSnapshotter;
972
+ constructor(fieldsSnapshotter: FieldsSnapshotter);
973
+ /**
974
+ * Creates a serializable snapshot of the entire tree and its contained fields.
975
+ * @returns A plain JavaScript object representing the complete state managed by this tree.
976
+ */
977
+ snapshot(tree: CoreFieldTree): FieldTreeSnapshot;
978
+ }
979
+
980
+ /**
981
+ * A plain object representation of a DataStore's state, used for serialization.
982
+ *
983
+ * It captures both the detached 'flat' variables (used for stack frames/local scopes)
984
+ * and the hierarchical 'tree' structure (used for global/persistent data).
985
+ */
986
+ interface DataStoreSnapshot {
987
+ /**
988
+ * The type identifier for the store (e.g., 'dataStore').
989
+ * Used for type guards and polymorphic deserialization.
990
+ */
991
+ __type: string;
992
+ /**
993
+ * Snapshot of the independent, root-level variables (CoreFields).
994
+ * Present only if the store contained detached variables.
995
+ */
996
+ variables?: FieldsSnapshot;
997
+ /**
998
+ * Snapshot of the nested data hierarchy (CoreFieldTree).
999
+ * Present only if the store managed a complex tree structure.
1000
+ */
1001
+ tree?: FieldTreeSnapshot;
916
1002
  }
917
1003
 
918
1004
  interface StoreCreateFieldOptions {
@@ -925,6 +1011,8 @@ interface StoreCreateFieldOptions {
925
1011
  * both type-safe and dynamic methods for manipulating data.
926
1012
  */
927
1013
  interface Store extends DataStorage {
1014
+ /**
1015
+ */
928
1016
  readonly typeName: string;
929
1017
  /**
930
1018
  * Retrieves the raw value of a Field at a specific path.
@@ -1073,14 +1161,15 @@ interface DataStoreFieldResolver {
1073
1161
  }
1074
1162
 
1075
1163
  declare class DataStore implements Store {
1076
- private readonly tree;
1077
1164
  static readonly typeName = "dataStore";
1078
1165
  readonly typeName = "dataStore";
1079
1166
  private readonly resolvers;
1080
- private readonly rootFieldsName;
1081
- private _rootFields;
1082
- private get rootFields();
1083
- constructor(tree: CoreFieldTree);
1167
+ private _variables;
1168
+ private _tree;
1169
+ private readonly _factory;
1170
+ private get variables();
1171
+ private get tree();
1172
+ constructor(treeOrFactory: CoreFieldTree | FieldTreeFactory<CoreFields>, variables?: CoreFields);
1084
1173
  registerResolver(resolver: DataStoreFieldResolver): void;
1085
1174
  clearResolvers(): void;
1086
1175
  getValue<T>(path: PathType): T;
@@ -1101,8 +1190,6 @@ declare class DataStore implements Store {
1101
1190
  getFields(path: PathType): CoreFields;
1102
1191
  getTree(path: PathType): CoreFieldTree;
1103
1192
  remove(path: PathType): void;
1104
- private isPathToRootFields;
1105
- private getDestinationFields;
1106
1193
  /**
1107
1194
  * Creates a new, independent instance of the Store with a fresh, empty data state (FieldsTree).
1108
1195
  *
@@ -1120,6 +1207,88 @@ declare class DataStore implements Store {
1120
1207
  create(path: PathType, value: unknown): void;
1121
1208
  upset(path: PathType, value: unknown): void;
1122
1209
  delete(path: PathType): void;
1210
+ /**
1211
+ * @internal Used for serialization
1212
+ */
1213
+ getInternalVariables(): CoreFields | undefined;
1214
+ /**
1215
+ * @internal Used for serialization
1216
+ */
1217
+ getInternalTree(): CoreFieldTree | undefined;
1218
+ /**
1219
+ * @internal Used for serialization
1220
+ */
1221
+ getOrCreateInternalVariables(): CoreFields;
1222
+ /**
1223
+ * @internal Used for serialization
1224
+ */
1225
+ getOrCreateInternalTree(): CoreFieldTree;
1226
+ /**
1227
+ * @private
1228
+ */
1229
+ private isPathToVariables;
1230
+ /**
1231
+ * @private
1232
+ */
1233
+ private getDestinationFields;
1234
+ }
1235
+
1236
+ /**
1237
+ *
1238
+ */
1239
+ declare class DataStoreHydrator {
1240
+ private readonly fieldsFieldTreeHydrator;
1241
+ /**
1242
+ * Creates an instance of DataStoreSerializer.
1243
+ * @param {FieldTreeHydrator} fieldsFieldTreeHydrator - The serializer used for the underlying tree and fields.
1244
+ */
1245
+ constructor(fieldsFieldTreeHydrator: FieldTreeHydrator<CoreFields>);
1246
+ /**
1247
+ * Reconstructs a DataStore instance from a snapshot.
1248
+ *
1249
+ * If the snapshot contains a tree, the store is initialized with it.
1250
+ * If not, the store is initialized with the factory (lazy mode), and the
1251
+ * detached variables are injected if present.
1252
+ *
1253
+ * @param {DataStoreSnapshot} snapshot - The snapshot to hydrate.
1254
+ * @returns {DataStore} A new, fully restored DataStore instance.
1255
+ */
1256
+ hydrate(snapshot: DataStoreSnapshot): DataStore;
1257
+ /**
1258
+ * Synchronizes a DataStore instance with a snapshot.
1259
+ *
1260
+ * This method ensures the DataStore's internal state matches the snapshot by:
1261
+ * 1. **Destroying** internal containers (variables/tree) if they are missing in the snapshot.
1262
+ * 2. **Patching** (updating/creating) contents if they exist in the snapshot.
1263
+ *
1264
+ * This allows for a granular update where only specific parts of the store (e.g., only variables)
1265
+ * are modified if the snapshot contains partial data, or a full reset if parts are missing.
1266
+ *
1267
+ * @param {DataStore} store - The target DataStore to update.
1268
+ * @param {DataStoreSnapshot} snapshot - The source snapshot.
1269
+ */
1270
+ patch(store: DataStore, snapshot: DataStoreSnapshot): void;
1271
+ }
1272
+
1273
+ /**
1274
+ */
1275
+ declare class DataStoreSnapshotter {
1276
+ private readonly treeSnapshotter;
1277
+ /**
1278
+ * Creates an instance of DataStoreSnapshotter.
1279
+ * @param {FieldTreeSnapshotter} treeSnapshotter - The serializer used for the underlying tree and fields.
1280
+ */
1281
+ constructor(treeSnapshotter: FieldTreeSnapshotter);
1282
+ /**
1283
+ * Captures the current state of a DataStore into a serializable snapshot.
1284
+ *
1285
+ * It checks for the existence of internal variables and the internal tree,
1286
+ * serializing them only if they have been initialized (lazy serialization).
1287
+ *
1288
+ * @param {DataStore} store - The store instance to serialize.
1289
+ * @returns {DataStoreSnapshot} The snapshot object.
1290
+ */
1291
+ snapshot(store: DataStore): DataStoreSnapshot;
1123
1292
  }
1124
1293
 
1125
1294
  /**
@@ -1180,20 +1349,20 @@ declare function createCoreTreeNodeFactory(fieldRegistry: FieldRegistry): CoreTr
1180
1349
  * This function composes all necessary serializers (FieldTree, Fields, Field) for a complete setup.
1181
1350
  * @param {CoreTreeNodeFactory} fieldTreeNodeFactory - The factory used to create new tree nodes during deserialization.
1182
1351
  * @param policySerializer
1183
- * @returns {FieldTreeSerializer<CoreFields>} A top-level serializer for the entire field tree.
1352
+ * @returns {FieldTreeHydrator<CoreFields>} A top-level serializer for the entire field tree.
1184
1353
  */
1185
- declare function createCoreTreeSerializer(fieldTreeNodeFactory: CoreTreeNodeFactory, policySerializer?: PolicySerializer): FieldTreeSerializer<CoreFields>;
1354
+ declare function createCoreTreeSerializer(fieldTreeNodeFactory: CoreTreeNodeFactory, policySerializer?: PolicySerializer): FieldTreeHydrator<CoreFields>;
1186
1355
  interface CoreFieldSystemConfig {
1187
1356
  registry?: FieldRegistry;
1188
1357
  policySerializer?: PolicySerializer;
1189
1358
  }
1190
1359
  /**
1191
1360
  * Creates a complete core setup for the field system.
1192
- * @returns {{factory: CoreTreeNodeFactory, serializer: FieldTreeSerializer<CoreFields>}}
1361
+ * @returns {{factory: CoreTreeNodeFactory, serializer: FieldTreeHydrator<CoreFields>}}
1193
1362
  */
1194
1363
  declare function createCoreFieldSystem(config?: CoreFieldSystemConfig): {
1195
1364
  factory: CoreTreeNodeFactory;
1196
- serializer: FieldTreeSerializer<CoreFields>;
1365
+ serializer: FieldTreeHydrator<CoreFields>;
1197
1366
  };
1198
1367
 
1199
- export { type BooleanField, ClampMaxPolicy, ClampMaxPolicySerializerHandler, ClampMinPolicy, ClampMinPolicySerializerHandler, ClampPolicy, ClampPolicySerializerHandler, CoreBooleanField, type CoreBooleanFieldOptions, CoreField, type CoreFieldSystemConfig, CoreFieldTree, CoreFields, CoreFieldsFactory, CoreNumericField, type CoreNumericFieldOptions, CoreStringField, type CoreStringFieldOptions, CoreTreeNodeFactory, DataStore, type Field, type FieldOptions, FieldRegistry, FieldSerializer, type FieldSnapshot, FieldTree, type FieldTreeFactory, FieldTreeSerializer, type FieldTreeSnapshot, Fields, type FieldsFactory, FieldsSerializer, type FieldsSnapshot, type NumericField, Policies, type Policy, PolicySerializer, type PolicySerializerHandler, type Store, type StoreCreateFieldOptions, type StringField, type TreeNode, clampMaxPolicy, clampMinPolicy, clampPolicy, createCoreFieldRegistry, createCoreFieldSystem, createCorePolicySerializer, createCoreTreeNodeFactory, createCoreTreeSerializer, createTypedMethodsMixin, isDataStore, isFieldTree, isFields };
1368
+ export { type BooleanField, ClampMaxPolicy, ClampMaxPolicySerializerHandler, ClampMinPolicy, ClampMinPolicySerializerHandler, ClampPolicy, ClampPolicySerializerHandler, CoreBooleanField, type CoreBooleanFieldOptions, CoreField, type CoreFieldSystemConfig, CoreFieldTree, CoreFields, CoreFieldsFactory, CoreNumericField, type CoreNumericFieldOptions, CoreStringField, type CoreStringFieldOptions, CoreTreeNodeFactory, DataStore, DataStoreHydrator, type DataStoreSnapshot, DataStoreSnapshotter, type Field, FieldHydrator, type FieldOptions, FieldRegistry, type FieldSnapshot, FieldSnapshotter, FieldTree, type FieldTreeFactory, FieldTreeHydrator, type FieldTreeSnapshot, FieldTreeSnapshotter, Fields, type FieldsFactory, FieldsHydrator, type FieldsSnapshot, FieldsSnapshotter, type NumericField, Policies, type Policy, PolicySerializer, type PolicySerializerHandler, type Store, type StoreCreateFieldOptions, type StringField, type TreeNode, clampMaxPolicy, clampMinPolicy, clampPolicy, createCoreFieldRegistry, createCoreFieldSystem, createCorePolicySerializer, createCoreTreeNodeFactory, createCoreTreeSerializer, createTypedMethodsMixin, isDataStore, isFieldTree, isFields };