@axi-engine/fields 0.3.7 → 0.3.9
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 +172 -17
- package/dist/index.d.ts +172 -17
- package/dist/index.js +69 -25
- package/dist/index.mjs +69 -25
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _axi_engine_utils from '@axi-engine/utils';
|
|
2
|
-
import { Subscribable,
|
|
2
|
+
import { Subscribable, Registry, Constructor, Emitter, PathType, DataStorage } from '@axi-engine/utils';
|
|
3
3
|
|
|
4
4
|
interface Policy<T> {
|
|
5
5
|
readonly id: string;
|
|
@@ -75,39 +75,141 @@ declare class Policies<T> {
|
|
|
75
75
|
apply(val: T): T;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Configuration options for creating a new Field instance.
|
|
80
|
+
* @template T The type of the value stored in the field.
|
|
81
|
+
*/
|
|
78
82
|
interface FieldOptions<T> {
|
|
83
|
+
/**
|
|
84
|
+
* An optional array of policies to apply to this field.
|
|
85
|
+
* Policies can enforce validation rules, transform values, or handle constraints.
|
|
86
|
+
*/
|
|
79
87
|
policies?: Policy<T>[];
|
|
80
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Represents a reactive data holder for a specific value type.
|
|
91
|
+
*
|
|
92
|
+
* A Field wraps a raw value, providing features like change observation (`onChange`),
|
|
93
|
+
* policy enforcement (validation/transformation), and metadata management (`name`, `typeName`).
|
|
94
|
+
*
|
|
95
|
+
* @template T The type of the value stored in the field.
|
|
96
|
+
*/
|
|
81
97
|
interface Field<T> {
|
|
98
|
+
/**
|
|
99
|
+
* A unique string identifier for the field type (e.g., 'numeric', 'boolean').
|
|
100
|
+
* Used for serialization and type guards.
|
|
101
|
+
*/
|
|
82
102
|
readonly typeName: string;
|
|
103
|
+
/**
|
|
104
|
+
* The name or key of this field within its parent container.
|
|
105
|
+
*/
|
|
83
106
|
readonly name: string;
|
|
107
|
+
/**
|
|
108
|
+
* The current value of the field.
|
|
109
|
+
* Assigning a new value triggers policies and emits the `onChange` event
|
|
110
|
+
* if the value is different from the current one.
|
|
111
|
+
*/
|
|
84
112
|
value: T;
|
|
113
|
+
/**
|
|
114
|
+
* The collection of policies applied to this field.
|
|
115
|
+
*/
|
|
85
116
|
policies: Policies<T>;
|
|
117
|
+
/**
|
|
118
|
+
* Updates the field's value without triggering the `onChange` event.
|
|
119
|
+
* Useful for internal synchronization or restoring state where side effects are undesirable.
|
|
120
|
+
* @param val The new value to set.
|
|
121
|
+
*/
|
|
86
122
|
setValueSilently(val: T): void;
|
|
123
|
+
/**
|
|
124
|
+
* Performs an atomic-like update using a callback function.
|
|
125
|
+
* The callback receives the current value and should return the new value.
|
|
126
|
+
* @param updateFn A function that transforms the current value into a new one.
|
|
127
|
+
*/
|
|
87
128
|
batchUpdate(updateFn: (currentValue: T) => T): void;
|
|
129
|
+
/**
|
|
130
|
+
* An observable stream that emits an event whenever the value changes.
|
|
131
|
+
* The payload contains the new value and the old value.
|
|
132
|
+
*/
|
|
88
133
|
onChange: Subscribable<[newValue: T, oldValue: T]>;
|
|
134
|
+
/**
|
|
135
|
+
* Cleans up the field, removing all listeners and releasing resources.
|
|
136
|
+
* Should be called when the field is no longer needed.
|
|
137
|
+
*/
|
|
89
138
|
destroy(): void;
|
|
90
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* A specialized Field for handling numeric values.
|
|
142
|
+
* Provides capabilities for range clamping (min/max) and arithmetic operations.
|
|
143
|
+
*/
|
|
91
144
|
interface NumericField extends Field<number> {
|
|
145
|
+
/** The minimum allowed value for this field, or undefined if no lower bound exists. */
|
|
92
146
|
readonly min: number | undefined;
|
|
147
|
+
/** The maximum allowed value for this field, or undefined if no upper bound exists. */
|
|
93
148
|
readonly max: number | undefined;
|
|
149
|
+
/**
|
|
150
|
+
* Checks if the current value is equal to or less than the minimum limit.
|
|
151
|
+
*/
|
|
94
152
|
isMin(): boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Checks if the current value is equal to or greater than the maximum limit.
|
|
155
|
+
*/
|
|
95
156
|
isMax(): boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Increments the current value by the specified amount.
|
|
159
|
+
* @param val The amount to add.
|
|
160
|
+
*/
|
|
96
161
|
inc(val: number): void;
|
|
162
|
+
/**
|
|
163
|
+
* Decrements the current value by the specified amount.
|
|
164
|
+
* @param val The amount to subtract.
|
|
165
|
+
*/
|
|
97
166
|
dec(val: number): void;
|
|
98
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* A specialized Field for handling boolean values.
|
|
170
|
+
* Provides toggle functionality.
|
|
171
|
+
*/
|
|
99
172
|
interface BooleanField extends Field<boolean> {
|
|
173
|
+
/**
|
|
174
|
+
* Inverts the current boolean value (true -> false, false -> true).
|
|
175
|
+
* @returns {boolean} The new value after toggling.
|
|
176
|
+
*/
|
|
100
177
|
toggle(): boolean;
|
|
101
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* A specialized Field for handling string values.
|
|
181
|
+
* Provides chainable methods for common string manipulations.
|
|
182
|
+
*/
|
|
102
183
|
interface StringField extends Field<string> {
|
|
184
|
+
/**
|
|
185
|
+
* Appends a string or number to the end of the current value.
|
|
186
|
+
* @param str The value to append.
|
|
187
|
+
* @returns {this} The field instance for chaining.
|
|
188
|
+
*/
|
|
103
189
|
append(str: string | number): this;
|
|
190
|
+
/**
|
|
191
|
+
* Prepends a string or number to the beginning of the current value.
|
|
192
|
+
* @param str The value to prepend.
|
|
193
|
+
* @returns {this} The field instance for chaining.
|
|
194
|
+
*/
|
|
104
195
|
prepend(str: string | number): this;
|
|
196
|
+
/**
|
|
197
|
+
* Removes whitespace from both ends of the current string value.
|
|
198
|
+
* @returns {this} The field instance for chaining.
|
|
199
|
+
*/
|
|
105
200
|
trim(): this;
|
|
201
|
+
/**
|
|
202
|
+
* Checks if the current string is empty (length is 0).
|
|
203
|
+
* @returns {boolean} `true` if the string is empty, otherwise `false`.
|
|
204
|
+
*/
|
|
106
205
|
isEmpty(): boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Sets the value to an empty string.
|
|
208
|
+
*/
|
|
107
209
|
clear(): void;
|
|
108
210
|
}
|
|
109
211
|
|
|
110
|
-
declare class FieldRegistry extends
|
|
212
|
+
declare class FieldRegistry extends Registry<string, Constructor<Field<any>>> {
|
|
111
213
|
}
|
|
112
214
|
|
|
113
215
|
/**
|
|
@@ -144,6 +246,9 @@ declare class Fields {
|
|
|
144
246
|
}]>;
|
|
145
247
|
/**
|
|
146
248
|
* Gets the read-only map of all `Field` instances in this container.
|
|
249
|
+
*
|
|
250
|
+
* @internal
|
|
251
|
+
*
|
|
147
252
|
* @returns {Map<string, Field<any>>} The collection of fields.
|
|
148
253
|
*/
|
|
149
254
|
get fields(): Map<string, Field<any>>;
|
|
@@ -379,9 +484,24 @@ declare class FieldTree<TFields extends Fields> {
|
|
|
379
484
|
names: string[];
|
|
380
485
|
}]>;
|
|
381
486
|
/**
|
|
382
|
-
*
|
|
487
|
+
* Provides direct access to the internal node storage.
|
|
488
|
+
*
|
|
489
|
+
* @remarks
|
|
490
|
+
* This is primarily intended for **serialization**, debugging, or low-level iteration.
|
|
491
|
+
* Avoid modifying this map directly to maintain internal consistency; use {@link addNode} or {@link removeNode} instead.
|
|
492
|
+
* @internal
|
|
383
493
|
*/
|
|
384
494
|
get nodes(): Map<string, TreeNode<TFields>>;
|
|
495
|
+
/**
|
|
496
|
+
* Exposes the internal factory instance used by this tree.
|
|
497
|
+
*
|
|
498
|
+
* @remarks
|
|
499
|
+
* Direct usage of this getter is generally unnecessary.
|
|
500
|
+
* Prefer using {@link createDetachedTree} or {@link createDetachedFields} to create isolated instances.
|
|
501
|
+
*
|
|
502
|
+
* @returns {FieldTreeFactory} The factory instance.
|
|
503
|
+
*/
|
|
504
|
+
get factory(): FieldTreeFactory<TFields>;
|
|
385
505
|
/**
|
|
386
506
|
* Creates an instance of FieldTree.
|
|
387
507
|
* @param {FieldTreeFactory} factory - A factory responsible for creating new nodes within the tree.
|
|
@@ -488,6 +608,19 @@ declare class FieldTree<TFields extends Fields> {
|
|
|
488
608
|
* This method should be called when a node is no longer needed.
|
|
489
609
|
*/
|
|
490
610
|
destroy(): void;
|
|
611
|
+
/**
|
|
612
|
+
* Creates a new, detached FieldTree instance using the same factory as this tree.
|
|
613
|
+
* This new tree has no parent and is completely isolated.
|
|
614
|
+
*
|
|
615
|
+
* @returns A new instance of the same tree type.
|
|
616
|
+
*/
|
|
617
|
+
createDetachedTree(): FieldTree<TFields>;
|
|
618
|
+
/**
|
|
619
|
+
* Creates a new, detached Fields container using the same factory.
|
|
620
|
+
*
|
|
621
|
+
* @returns
|
|
622
|
+
*/
|
|
623
|
+
createDetachedFields(): TFields;
|
|
491
624
|
/**
|
|
492
625
|
* @private
|
|
493
626
|
* Navigates the tree to the parent of a target node.
|
|
@@ -583,9 +716,8 @@ interface PolicySerializerHandler<T extends Policy<any>, S extends object> {
|
|
|
583
716
|
hydrate(snapshotData: S): T;
|
|
584
717
|
}
|
|
585
718
|
declare class PolicySerializer {
|
|
586
|
-
|
|
587
|
-
register(policyId: string, handler: PolicySerializerHandler<any, any>):
|
|
588
|
-
clearHandlers(): void;
|
|
719
|
+
handlers: Registry<string, PolicySerializerHandler<any, any>>;
|
|
720
|
+
register(policyId: string, handler: PolicySerializerHandler<any, any>): void;
|
|
589
721
|
/**
|
|
590
722
|
* Creates a serializable snapshot of a policy instance.
|
|
591
723
|
* The snapshot includes the policy's state and a `__type` identifier.
|
|
@@ -648,6 +780,7 @@ interface FieldSnapshot {
|
|
|
648
780
|
value: any;
|
|
649
781
|
policies?: object[];
|
|
650
782
|
}
|
|
783
|
+
|
|
651
784
|
/**
|
|
652
785
|
* Orchestrates the serialization and deserialization of Field instances.
|
|
653
786
|
*
|
|
@@ -695,6 +828,7 @@ interface FieldsSnapshot {
|
|
|
695
828
|
__type: string;
|
|
696
829
|
[fieldName: string]: FieldSnapshot | string;
|
|
697
830
|
}
|
|
831
|
+
|
|
698
832
|
/**
|
|
699
833
|
* Orchestrates the serialization and deserialization of `Fields` container instances.
|
|
700
834
|
*
|
|
@@ -747,6 +881,7 @@ interface FieldTreeSnapshot {
|
|
|
747
881
|
__type: string;
|
|
748
882
|
[fieldName: string]: FieldsSnapshot | FieldTreeSnapshot | string;
|
|
749
883
|
}
|
|
884
|
+
|
|
750
885
|
/**
|
|
751
886
|
* Orchestrates the recursive serialization and deserialization of `FieldTree` instances.
|
|
752
887
|
*
|
|
@@ -790,6 +925,7 @@ interface StoreCreateFieldOptions {
|
|
|
790
925
|
* both type-safe and dynamic methods for manipulating data.
|
|
791
926
|
*/
|
|
792
927
|
interface Store extends DataStorage {
|
|
928
|
+
readonly typeName: string;
|
|
793
929
|
/**
|
|
794
930
|
* Retrieves the raw value of a Field at a specific path.
|
|
795
931
|
* @template T The expected type of the value.
|
|
@@ -910,6 +1046,16 @@ interface Store extends DataStorage {
|
|
|
910
1046
|
* @param path The path to the node to remove.
|
|
911
1047
|
*/
|
|
912
1048
|
remove(path: PathType): void;
|
|
1049
|
+
/**
|
|
1050
|
+
* Creates a new, independent instance of the Store.
|
|
1051
|
+
*
|
|
1052
|
+
* The returned store must operate on a completely separate data structure,
|
|
1053
|
+
* ensuring that operations on the new instance do not affect the current one (and vice versa).
|
|
1054
|
+
* Typically used for creating local execution scopes, stack frames, or sandbox environments.
|
|
1055
|
+
*
|
|
1056
|
+
* @returns {Store} A new, isolated Store instance.
|
|
1057
|
+
*/
|
|
1058
|
+
createIsolated(): Store;
|
|
913
1059
|
}
|
|
914
1060
|
|
|
915
1061
|
interface DataStoreFieldResolver {
|
|
@@ -928,6 +1074,8 @@ interface DataStoreFieldResolver {
|
|
|
928
1074
|
|
|
929
1075
|
declare class DataStore implements Store {
|
|
930
1076
|
private readonly tree;
|
|
1077
|
+
static readonly typeName = "dataStore";
|
|
1078
|
+
readonly typeName = "dataStore";
|
|
931
1079
|
private readonly resolvers;
|
|
932
1080
|
private readonly rootFieldsName;
|
|
933
1081
|
private _rootFields;
|
|
@@ -955,8 +1103,18 @@ declare class DataStore implements Store {
|
|
|
955
1103
|
remove(path: PathType): void;
|
|
956
1104
|
private isPathToRootFields;
|
|
957
1105
|
private getDestinationFields;
|
|
1106
|
+
/**
|
|
1107
|
+
* Creates a new, independent instance of the Store with a fresh, empty data state (FieldsTree).
|
|
1108
|
+
*
|
|
1109
|
+
* The new instance retains the same capabilities (e.g., factory configuration)
|
|
1110
|
+
* as the current one but is completely detached from the existing data hierarchy.
|
|
1111
|
+
* This is useful for creating local scopes, stack frames, or temporary data contexts.
|
|
1112
|
+
*
|
|
1113
|
+
* @returns {DataStore} A new, isolated DataStore instance.
|
|
1114
|
+
*/
|
|
1115
|
+
createIsolated(): DataStore;
|
|
1116
|
+
/** code below -> implementation of the DataStore from utils */
|
|
958
1117
|
has(path: PathType): boolean;
|
|
959
|
-
/** implementation of the DataStore from utils */
|
|
960
1118
|
get(path: PathType): unknown;
|
|
961
1119
|
set(path: PathType, value: unknown): void;
|
|
962
1120
|
create(path: PathType, value: unknown): void;
|
|
@@ -981,18 +1139,15 @@ declare function isFields(value: unknown): value is Fields;
|
|
|
981
1139
|
*/
|
|
982
1140
|
declare function isFieldTree(value: unknown): value is FieldTree<any>;
|
|
983
1141
|
/**
|
|
984
|
-
* Type guard that checks if
|
|
985
|
-
*
|
|
986
|
-
* It performs a structural check (duck typing) by verifying the presence of methods
|
|
987
|
-
* that are unique to the `Store` interface and are not part of the simpler `DataSource`
|
|
988
|
-
* or `DataStorage` contracts, such as `createFields` and `createTree`.
|
|
1142
|
+
* Type guard that checks if a value is an instance of the `DataStore` class.
|
|
1143
|
+
* It verifies this by checking the static `typeName` property on the instance.
|
|
989
1144
|
*
|
|
990
1145
|
* @param value The `unknown` value to check.
|
|
991
|
-
* @returns {boolean} `true` if the value is a `
|
|
1146
|
+
* @returns {boolean} `true` if the value is a `DataStore` instance, otherwise `false`.
|
|
992
1147
|
*
|
|
993
1148
|
* @example
|
|
994
|
-
* function processData(source:
|
|
995
|
-
* if (
|
|
1149
|
+
* function processData(source: DataStore) {
|
|
1150
|
+
* if (isDataStore(source)) {
|
|
996
1151
|
* // Inside this block, TypeScript now knows `source` is a full `Store`.
|
|
997
1152
|
* // We can safely call Store-specific methods like `createFields`.
|
|
998
1153
|
* source.createFields('new.data.group');
|
|
@@ -1002,7 +1157,7 @@ declare function isFieldTree(value: unknown): value is FieldTree<any>;
|
|
|
1002
1157
|
* }
|
|
1003
1158
|
* }
|
|
1004
1159
|
*/
|
|
1005
|
-
declare function
|
|
1160
|
+
declare function isDataStore(value: unknown): value is DataStore;
|
|
1006
1161
|
|
|
1007
1162
|
/**
|
|
1008
1163
|
* Creates and configures a FieldRegistry with all the core field types.
|
|
@@ -1041,4 +1196,4 @@ declare function createCoreFieldSystem(config?: CoreFieldSystemConfig): {
|
|
|
1041
1196
|
serializer: FieldTreeSerializer<CoreFields>;
|
|
1042
1197
|
};
|
|
1043
1198
|
|
|
1044
|
-
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, isFieldTree, isFields
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _axi_engine_utils from '@axi-engine/utils';
|
|
2
|
-
import { Subscribable,
|
|
2
|
+
import { Subscribable, Registry, Constructor, Emitter, PathType, DataStorage } from '@axi-engine/utils';
|
|
3
3
|
|
|
4
4
|
interface Policy<T> {
|
|
5
5
|
readonly id: string;
|
|
@@ -75,39 +75,141 @@ declare class Policies<T> {
|
|
|
75
75
|
apply(val: T): T;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Configuration options for creating a new Field instance.
|
|
80
|
+
* @template T The type of the value stored in the field.
|
|
81
|
+
*/
|
|
78
82
|
interface FieldOptions<T> {
|
|
83
|
+
/**
|
|
84
|
+
* An optional array of policies to apply to this field.
|
|
85
|
+
* Policies can enforce validation rules, transform values, or handle constraints.
|
|
86
|
+
*/
|
|
79
87
|
policies?: Policy<T>[];
|
|
80
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Represents a reactive data holder for a specific value type.
|
|
91
|
+
*
|
|
92
|
+
* A Field wraps a raw value, providing features like change observation (`onChange`),
|
|
93
|
+
* policy enforcement (validation/transformation), and metadata management (`name`, `typeName`).
|
|
94
|
+
*
|
|
95
|
+
* @template T The type of the value stored in the field.
|
|
96
|
+
*/
|
|
81
97
|
interface Field<T> {
|
|
98
|
+
/**
|
|
99
|
+
* A unique string identifier for the field type (e.g., 'numeric', 'boolean').
|
|
100
|
+
* Used for serialization and type guards.
|
|
101
|
+
*/
|
|
82
102
|
readonly typeName: string;
|
|
103
|
+
/**
|
|
104
|
+
* The name or key of this field within its parent container.
|
|
105
|
+
*/
|
|
83
106
|
readonly name: string;
|
|
107
|
+
/**
|
|
108
|
+
* The current value of the field.
|
|
109
|
+
* Assigning a new value triggers policies and emits the `onChange` event
|
|
110
|
+
* if the value is different from the current one.
|
|
111
|
+
*/
|
|
84
112
|
value: T;
|
|
113
|
+
/**
|
|
114
|
+
* The collection of policies applied to this field.
|
|
115
|
+
*/
|
|
85
116
|
policies: Policies<T>;
|
|
117
|
+
/**
|
|
118
|
+
* Updates the field's value without triggering the `onChange` event.
|
|
119
|
+
* Useful for internal synchronization or restoring state where side effects are undesirable.
|
|
120
|
+
* @param val The new value to set.
|
|
121
|
+
*/
|
|
86
122
|
setValueSilently(val: T): void;
|
|
123
|
+
/**
|
|
124
|
+
* Performs an atomic-like update using a callback function.
|
|
125
|
+
* The callback receives the current value and should return the new value.
|
|
126
|
+
* @param updateFn A function that transforms the current value into a new one.
|
|
127
|
+
*/
|
|
87
128
|
batchUpdate(updateFn: (currentValue: T) => T): void;
|
|
129
|
+
/**
|
|
130
|
+
* An observable stream that emits an event whenever the value changes.
|
|
131
|
+
* The payload contains the new value and the old value.
|
|
132
|
+
*/
|
|
88
133
|
onChange: Subscribable<[newValue: T, oldValue: T]>;
|
|
134
|
+
/**
|
|
135
|
+
* Cleans up the field, removing all listeners and releasing resources.
|
|
136
|
+
* Should be called when the field is no longer needed.
|
|
137
|
+
*/
|
|
89
138
|
destroy(): void;
|
|
90
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* A specialized Field for handling numeric values.
|
|
142
|
+
* Provides capabilities for range clamping (min/max) and arithmetic operations.
|
|
143
|
+
*/
|
|
91
144
|
interface NumericField extends Field<number> {
|
|
145
|
+
/** The minimum allowed value for this field, or undefined if no lower bound exists. */
|
|
92
146
|
readonly min: number | undefined;
|
|
147
|
+
/** The maximum allowed value for this field, or undefined if no upper bound exists. */
|
|
93
148
|
readonly max: number | undefined;
|
|
149
|
+
/**
|
|
150
|
+
* Checks if the current value is equal to or less than the minimum limit.
|
|
151
|
+
*/
|
|
94
152
|
isMin(): boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Checks if the current value is equal to or greater than the maximum limit.
|
|
155
|
+
*/
|
|
95
156
|
isMax(): boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Increments the current value by the specified amount.
|
|
159
|
+
* @param val The amount to add.
|
|
160
|
+
*/
|
|
96
161
|
inc(val: number): void;
|
|
162
|
+
/**
|
|
163
|
+
* Decrements the current value by the specified amount.
|
|
164
|
+
* @param val The amount to subtract.
|
|
165
|
+
*/
|
|
97
166
|
dec(val: number): void;
|
|
98
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* A specialized Field for handling boolean values.
|
|
170
|
+
* Provides toggle functionality.
|
|
171
|
+
*/
|
|
99
172
|
interface BooleanField extends Field<boolean> {
|
|
173
|
+
/**
|
|
174
|
+
* Inverts the current boolean value (true -> false, false -> true).
|
|
175
|
+
* @returns {boolean} The new value after toggling.
|
|
176
|
+
*/
|
|
100
177
|
toggle(): boolean;
|
|
101
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* A specialized Field for handling string values.
|
|
181
|
+
* Provides chainable methods for common string manipulations.
|
|
182
|
+
*/
|
|
102
183
|
interface StringField extends Field<string> {
|
|
184
|
+
/**
|
|
185
|
+
* Appends a string or number to the end of the current value.
|
|
186
|
+
* @param str The value to append.
|
|
187
|
+
* @returns {this} The field instance for chaining.
|
|
188
|
+
*/
|
|
103
189
|
append(str: string | number): this;
|
|
190
|
+
/**
|
|
191
|
+
* Prepends a string or number to the beginning of the current value.
|
|
192
|
+
* @param str The value to prepend.
|
|
193
|
+
* @returns {this} The field instance for chaining.
|
|
194
|
+
*/
|
|
104
195
|
prepend(str: string | number): this;
|
|
196
|
+
/**
|
|
197
|
+
* Removes whitespace from both ends of the current string value.
|
|
198
|
+
* @returns {this} The field instance for chaining.
|
|
199
|
+
*/
|
|
105
200
|
trim(): this;
|
|
201
|
+
/**
|
|
202
|
+
* Checks if the current string is empty (length is 0).
|
|
203
|
+
* @returns {boolean} `true` if the string is empty, otherwise `false`.
|
|
204
|
+
*/
|
|
106
205
|
isEmpty(): boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Sets the value to an empty string.
|
|
208
|
+
*/
|
|
107
209
|
clear(): void;
|
|
108
210
|
}
|
|
109
211
|
|
|
110
|
-
declare class FieldRegistry extends
|
|
212
|
+
declare class FieldRegistry extends Registry<string, Constructor<Field<any>>> {
|
|
111
213
|
}
|
|
112
214
|
|
|
113
215
|
/**
|
|
@@ -144,6 +246,9 @@ declare class Fields {
|
|
|
144
246
|
}]>;
|
|
145
247
|
/**
|
|
146
248
|
* Gets the read-only map of all `Field` instances in this container.
|
|
249
|
+
*
|
|
250
|
+
* @internal
|
|
251
|
+
*
|
|
147
252
|
* @returns {Map<string, Field<any>>} The collection of fields.
|
|
148
253
|
*/
|
|
149
254
|
get fields(): Map<string, Field<any>>;
|
|
@@ -379,9 +484,24 @@ declare class FieldTree<TFields extends Fields> {
|
|
|
379
484
|
names: string[];
|
|
380
485
|
}]>;
|
|
381
486
|
/**
|
|
382
|
-
*
|
|
487
|
+
* Provides direct access to the internal node storage.
|
|
488
|
+
*
|
|
489
|
+
* @remarks
|
|
490
|
+
* This is primarily intended for **serialization**, debugging, or low-level iteration.
|
|
491
|
+
* Avoid modifying this map directly to maintain internal consistency; use {@link addNode} or {@link removeNode} instead.
|
|
492
|
+
* @internal
|
|
383
493
|
*/
|
|
384
494
|
get nodes(): Map<string, TreeNode<TFields>>;
|
|
495
|
+
/**
|
|
496
|
+
* Exposes the internal factory instance used by this tree.
|
|
497
|
+
*
|
|
498
|
+
* @remarks
|
|
499
|
+
* Direct usage of this getter is generally unnecessary.
|
|
500
|
+
* Prefer using {@link createDetachedTree} or {@link createDetachedFields} to create isolated instances.
|
|
501
|
+
*
|
|
502
|
+
* @returns {FieldTreeFactory} The factory instance.
|
|
503
|
+
*/
|
|
504
|
+
get factory(): FieldTreeFactory<TFields>;
|
|
385
505
|
/**
|
|
386
506
|
* Creates an instance of FieldTree.
|
|
387
507
|
* @param {FieldTreeFactory} factory - A factory responsible for creating new nodes within the tree.
|
|
@@ -488,6 +608,19 @@ declare class FieldTree<TFields extends Fields> {
|
|
|
488
608
|
* This method should be called when a node is no longer needed.
|
|
489
609
|
*/
|
|
490
610
|
destroy(): void;
|
|
611
|
+
/**
|
|
612
|
+
* Creates a new, detached FieldTree instance using the same factory as this tree.
|
|
613
|
+
* This new tree has no parent and is completely isolated.
|
|
614
|
+
*
|
|
615
|
+
* @returns A new instance of the same tree type.
|
|
616
|
+
*/
|
|
617
|
+
createDetachedTree(): FieldTree<TFields>;
|
|
618
|
+
/**
|
|
619
|
+
* Creates a new, detached Fields container using the same factory.
|
|
620
|
+
*
|
|
621
|
+
* @returns
|
|
622
|
+
*/
|
|
623
|
+
createDetachedFields(): TFields;
|
|
491
624
|
/**
|
|
492
625
|
* @private
|
|
493
626
|
* Navigates the tree to the parent of a target node.
|
|
@@ -583,9 +716,8 @@ interface PolicySerializerHandler<T extends Policy<any>, S extends object> {
|
|
|
583
716
|
hydrate(snapshotData: S): T;
|
|
584
717
|
}
|
|
585
718
|
declare class PolicySerializer {
|
|
586
|
-
|
|
587
|
-
register(policyId: string, handler: PolicySerializerHandler<any, any>):
|
|
588
|
-
clearHandlers(): void;
|
|
719
|
+
handlers: Registry<string, PolicySerializerHandler<any, any>>;
|
|
720
|
+
register(policyId: string, handler: PolicySerializerHandler<any, any>): void;
|
|
589
721
|
/**
|
|
590
722
|
* Creates a serializable snapshot of a policy instance.
|
|
591
723
|
* The snapshot includes the policy's state and a `__type` identifier.
|
|
@@ -648,6 +780,7 @@ interface FieldSnapshot {
|
|
|
648
780
|
value: any;
|
|
649
781
|
policies?: object[];
|
|
650
782
|
}
|
|
783
|
+
|
|
651
784
|
/**
|
|
652
785
|
* Orchestrates the serialization and deserialization of Field instances.
|
|
653
786
|
*
|
|
@@ -695,6 +828,7 @@ interface FieldsSnapshot {
|
|
|
695
828
|
__type: string;
|
|
696
829
|
[fieldName: string]: FieldSnapshot | string;
|
|
697
830
|
}
|
|
831
|
+
|
|
698
832
|
/**
|
|
699
833
|
* Orchestrates the serialization and deserialization of `Fields` container instances.
|
|
700
834
|
*
|
|
@@ -747,6 +881,7 @@ interface FieldTreeSnapshot {
|
|
|
747
881
|
__type: string;
|
|
748
882
|
[fieldName: string]: FieldsSnapshot | FieldTreeSnapshot | string;
|
|
749
883
|
}
|
|
884
|
+
|
|
750
885
|
/**
|
|
751
886
|
* Orchestrates the recursive serialization and deserialization of `FieldTree` instances.
|
|
752
887
|
*
|
|
@@ -790,6 +925,7 @@ interface StoreCreateFieldOptions {
|
|
|
790
925
|
* both type-safe and dynamic methods for manipulating data.
|
|
791
926
|
*/
|
|
792
927
|
interface Store extends DataStorage {
|
|
928
|
+
readonly typeName: string;
|
|
793
929
|
/**
|
|
794
930
|
* Retrieves the raw value of a Field at a specific path.
|
|
795
931
|
* @template T The expected type of the value.
|
|
@@ -910,6 +1046,16 @@ interface Store extends DataStorage {
|
|
|
910
1046
|
* @param path The path to the node to remove.
|
|
911
1047
|
*/
|
|
912
1048
|
remove(path: PathType): void;
|
|
1049
|
+
/**
|
|
1050
|
+
* Creates a new, independent instance of the Store.
|
|
1051
|
+
*
|
|
1052
|
+
* The returned store must operate on a completely separate data structure,
|
|
1053
|
+
* ensuring that operations on the new instance do not affect the current one (and vice versa).
|
|
1054
|
+
* Typically used for creating local execution scopes, stack frames, or sandbox environments.
|
|
1055
|
+
*
|
|
1056
|
+
* @returns {Store} A new, isolated Store instance.
|
|
1057
|
+
*/
|
|
1058
|
+
createIsolated(): Store;
|
|
913
1059
|
}
|
|
914
1060
|
|
|
915
1061
|
interface DataStoreFieldResolver {
|
|
@@ -928,6 +1074,8 @@ interface DataStoreFieldResolver {
|
|
|
928
1074
|
|
|
929
1075
|
declare class DataStore implements Store {
|
|
930
1076
|
private readonly tree;
|
|
1077
|
+
static readonly typeName = "dataStore";
|
|
1078
|
+
readonly typeName = "dataStore";
|
|
931
1079
|
private readonly resolvers;
|
|
932
1080
|
private readonly rootFieldsName;
|
|
933
1081
|
private _rootFields;
|
|
@@ -955,8 +1103,18 @@ declare class DataStore implements Store {
|
|
|
955
1103
|
remove(path: PathType): void;
|
|
956
1104
|
private isPathToRootFields;
|
|
957
1105
|
private getDestinationFields;
|
|
1106
|
+
/**
|
|
1107
|
+
* Creates a new, independent instance of the Store with a fresh, empty data state (FieldsTree).
|
|
1108
|
+
*
|
|
1109
|
+
* The new instance retains the same capabilities (e.g., factory configuration)
|
|
1110
|
+
* as the current one but is completely detached from the existing data hierarchy.
|
|
1111
|
+
* This is useful for creating local scopes, stack frames, or temporary data contexts.
|
|
1112
|
+
*
|
|
1113
|
+
* @returns {DataStore} A new, isolated DataStore instance.
|
|
1114
|
+
*/
|
|
1115
|
+
createIsolated(): DataStore;
|
|
1116
|
+
/** code below -> implementation of the DataStore from utils */
|
|
958
1117
|
has(path: PathType): boolean;
|
|
959
|
-
/** implementation of the DataStore from utils */
|
|
960
1118
|
get(path: PathType): unknown;
|
|
961
1119
|
set(path: PathType, value: unknown): void;
|
|
962
1120
|
create(path: PathType, value: unknown): void;
|
|
@@ -981,18 +1139,15 @@ declare function isFields(value: unknown): value is Fields;
|
|
|
981
1139
|
*/
|
|
982
1140
|
declare function isFieldTree(value: unknown): value is FieldTree<any>;
|
|
983
1141
|
/**
|
|
984
|
-
* Type guard that checks if
|
|
985
|
-
*
|
|
986
|
-
* It performs a structural check (duck typing) by verifying the presence of methods
|
|
987
|
-
* that are unique to the `Store` interface and are not part of the simpler `DataSource`
|
|
988
|
-
* or `DataStorage` contracts, such as `createFields` and `createTree`.
|
|
1142
|
+
* Type guard that checks if a value is an instance of the `DataStore` class.
|
|
1143
|
+
* It verifies this by checking the static `typeName` property on the instance.
|
|
989
1144
|
*
|
|
990
1145
|
* @param value The `unknown` value to check.
|
|
991
|
-
* @returns {boolean} `true` if the value is a `
|
|
1146
|
+
* @returns {boolean} `true` if the value is a `DataStore` instance, otherwise `false`.
|
|
992
1147
|
*
|
|
993
1148
|
* @example
|
|
994
|
-
* function processData(source:
|
|
995
|
-
* if (
|
|
1149
|
+
* function processData(source: DataStore) {
|
|
1150
|
+
* if (isDataStore(source)) {
|
|
996
1151
|
* // Inside this block, TypeScript now knows `source` is a full `Store`.
|
|
997
1152
|
* // We can safely call Store-specific methods like `createFields`.
|
|
998
1153
|
* source.createFields('new.data.group');
|
|
@@ -1002,7 +1157,7 @@ declare function isFieldTree(value: unknown): value is FieldTree<any>;
|
|
|
1002
1157
|
* }
|
|
1003
1158
|
* }
|
|
1004
1159
|
*/
|
|
1005
|
-
declare function
|
|
1160
|
+
declare function isDataStore(value: unknown): value is DataStore;
|
|
1006
1161
|
|
|
1007
1162
|
/**
|
|
1008
1163
|
* Creates and configures a FieldRegistry with all the core field types.
|
|
@@ -1041,4 +1196,4 @@ declare function createCoreFieldSystem(config?: CoreFieldSystemConfig): {
|
|
|
1041
1196
|
serializer: FieldTreeSerializer<CoreFields>;
|
|
1042
1197
|
};
|
|
1043
1198
|
|
|
1044
|
-
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, isFieldTree, isFields
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -52,9 +52,9 @@ __export(index_exports, {
|
|
|
52
52
|
createCoreTreeNodeFactory: () => createCoreTreeNodeFactory,
|
|
53
53
|
createCoreTreeSerializer: () => createCoreTreeSerializer,
|
|
54
54
|
createTypedMethodsMixin: () => createTypedMethodsMixin,
|
|
55
|
+
isDataStore: () => isDataStore,
|
|
55
56
|
isFieldTree: () => isFieldTree,
|
|
56
|
-
isFields: () => isFields
|
|
57
|
-
isStore: () => isStore
|
|
57
|
+
isFields: () => isFields
|
|
58
58
|
});
|
|
59
59
|
module.exports = __toCommonJS(index_exports);
|
|
60
60
|
|
|
@@ -351,7 +351,7 @@ var CoreNumericField = class _CoreNumericField extends CoreField {
|
|
|
351
351
|
|
|
352
352
|
// src/field-registry.ts
|
|
353
353
|
var import_utils3 = require("@axi-engine/utils");
|
|
354
|
-
var FieldRegistry = class extends import_utils3.
|
|
354
|
+
var FieldRegistry = class extends import_utils3.Registry {
|
|
355
355
|
};
|
|
356
356
|
|
|
357
357
|
// src/fields.ts
|
|
@@ -378,6 +378,9 @@ var Fields = class _Fields {
|
|
|
378
378
|
onRemove = new import_utils4.Emitter();
|
|
379
379
|
/**
|
|
380
380
|
* Gets the read-only map of all `Field` instances in this container.
|
|
381
|
+
*
|
|
382
|
+
* @internal
|
|
383
|
+
*
|
|
381
384
|
* @returns {Map<string, Field<any>>} The collection of fields.
|
|
382
385
|
*/
|
|
383
386
|
get fields() {
|
|
@@ -425,7 +428,7 @@ var Fields = class _Fields {
|
|
|
425
428
|
* @returns {T} The newly created `Field` instance.
|
|
426
429
|
*/
|
|
427
430
|
create(typeName, name, initialValue, options) {
|
|
428
|
-
const Ctor = this._fieldRegistry.
|
|
431
|
+
const Ctor = this._fieldRegistry.getOrThrow(typeName);
|
|
429
432
|
const field = new Ctor(name, initialValue, options);
|
|
430
433
|
this.add(field);
|
|
431
434
|
return field;
|
|
@@ -524,11 +527,28 @@ var FieldTree = class _FieldTree {
|
|
|
524
527
|
*/
|
|
525
528
|
onRemove = new import_utils5.Emitter();
|
|
526
529
|
/**
|
|
527
|
-
*
|
|
530
|
+
* Provides direct access to the internal node storage.
|
|
531
|
+
*
|
|
532
|
+
* @remarks
|
|
533
|
+
* This is primarily intended for **serialization**, debugging, or low-level iteration.
|
|
534
|
+
* Avoid modifying this map directly to maintain internal consistency; use {@link addNode} or {@link removeNode} instead.
|
|
535
|
+
* @internal
|
|
528
536
|
*/
|
|
529
537
|
get nodes() {
|
|
530
538
|
return this._nodes;
|
|
531
539
|
}
|
|
540
|
+
/**
|
|
541
|
+
* Exposes the internal factory instance used by this tree.
|
|
542
|
+
*
|
|
543
|
+
* @remarks
|
|
544
|
+
* Direct usage of this getter is generally unnecessary.
|
|
545
|
+
* Prefer using {@link createDetachedTree} or {@link createDetachedFields} to create isolated instances.
|
|
546
|
+
*
|
|
547
|
+
* @returns {FieldTreeFactory} The factory instance.
|
|
548
|
+
*/
|
|
549
|
+
get factory() {
|
|
550
|
+
return this._factory;
|
|
551
|
+
}
|
|
532
552
|
/**
|
|
533
553
|
* Creates an instance of FieldTree.
|
|
534
554
|
* @param {FieldTreeFactory} factory - A factory responsible for creating new nodes within the tree.
|
|
@@ -700,6 +720,23 @@ var FieldTree = class _FieldTree {
|
|
|
700
720
|
this.onAdd.clear();
|
|
701
721
|
this.onRemove.clear();
|
|
702
722
|
}
|
|
723
|
+
/**
|
|
724
|
+
* Creates a new, detached FieldTree instance using the same factory as this tree.
|
|
725
|
+
* This new tree has no parent and is completely isolated.
|
|
726
|
+
*
|
|
727
|
+
* @returns A new instance of the same tree type.
|
|
728
|
+
*/
|
|
729
|
+
createDetachedTree() {
|
|
730
|
+
return this._factory.tree();
|
|
731
|
+
}
|
|
732
|
+
/**
|
|
733
|
+
* Creates a new, detached Fields container using the same factory.
|
|
734
|
+
*
|
|
735
|
+
* @returns
|
|
736
|
+
*/
|
|
737
|
+
createDetachedFields() {
|
|
738
|
+
return this._factory.fields();
|
|
739
|
+
}
|
|
703
740
|
/**
|
|
704
741
|
* @private
|
|
705
742
|
* Navigates the tree to the parent of a target node.
|
|
@@ -820,14 +857,9 @@ var ClampMinPolicySerializerHandler = class {
|
|
|
820
857
|
// src/serializer/policy-serializer.ts
|
|
821
858
|
var import_utils6 = require("@axi-engine/utils");
|
|
822
859
|
var PolicySerializer = class {
|
|
823
|
-
handlers =
|
|
860
|
+
handlers = new import_utils6.Registry();
|
|
824
861
|
register(policyId, handler) {
|
|
825
|
-
|
|
826
|
-
this.handlers.set(policyId, handler);
|
|
827
|
-
return this;
|
|
828
|
-
}
|
|
829
|
-
clearHandlers() {
|
|
830
|
-
this.handlers.clear();
|
|
862
|
+
this.handlers.register(policyId, handler);
|
|
831
863
|
}
|
|
832
864
|
/**
|
|
833
865
|
* Creates a serializable snapshot of a policy instance.
|
|
@@ -837,8 +869,7 @@ var PolicySerializer = class {
|
|
|
837
869
|
* @throws If no handler is registered for the policy's ID.
|
|
838
870
|
*/
|
|
839
871
|
snapshot(policy) {
|
|
840
|
-
const handler = this.handlers.
|
|
841
|
-
(0, import_utils6.throwIfEmpty)(handler, `No serializer handler registered for policy ID: '${policy.id}'`);
|
|
872
|
+
const handler = this.handlers.getOrThrow(policy.id);
|
|
842
873
|
const data = handler.snapshot(policy);
|
|
843
874
|
return {
|
|
844
875
|
__type: policy.id,
|
|
@@ -854,8 +885,7 @@ var PolicySerializer = class {
|
|
|
854
885
|
hydrate(snapshot) {
|
|
855
886
|
const typeId = snapshot?.__type;
|
|
856
887
|
(0, import_utils6.throwIfEmpty)(typeId, 'Invalid policy snapshot: missing "__type" identifier.');
|
|
857
|
-
const handler = this.handlers.
|
|
858
|
-
(0, import_utils6.throwIfEmpty)(handler, `No serializer handler registered for policy ID: '${typeId}'`);
|
|
888
|
+
const handler = this.handlers.getOrThrow(typeId);
|
|
859
889
|
const { __type, ...data } = snapshot;
|
|
860
890
|
return handler.hydrate(data);
|
|
861
891
|
}
|
|
@@ -903,7 +933,7 @@ var FieldSerializer = class {
|
|
|
903
933
|
hydrate(snapshot) {
|
|
904
934
|
const fieldType = snapshot.__type;
|
|
905
935
|
(0, import_utils7.throwIfEmpty)(fieldType, 'Invalid field snapshot: missing "__type" identifier.');
|
|
906
|
-
const Ctor = this.fieldRegistry.
|
|
936
|
+
const Ctor = this.fieldRegistry.getOrThrow(fieldType);
|
|
907
937
|
let policies;
|
|
908
938
|
if (!(0, import_utils7.isNullOrUndefined)(snapshot.policies)) {
|
|
909
939
|
policies = [];
|
|
@@ -1030,13 +1060,15 @@ var StringFieldResolver = class {
|
|
|
1030
1060
|
};
|
|
1031
1061
|
|
|
1032
1062
|
// src/data-store.ts
|
|
1033
|
-
var DataStore = class {
|
|
1063
|
+
var DataStore = class _DataStore {
|
|
1034
1064
|
constructor(tree) {
|
|
1035
1065
|
this.tree = tree;
|
|
1036
1066
|
this.registerResolver(new NumericFieldResolver());
|
|
1037
1067
|
this.registerResolver(new BooleanFieldResolver());
|
|
1038
1068
|
this.registerResolver(new StringFieldResolver());
|
|
1039
1069
|
}
|
|
1070
|
+
static typeName = "dataStore";
|
|
1071
|
+
typeName = _DataStore.typeName;
|
|
1040
1072
|
resolvers = [];
|
|
1041
1073
|
rootFieldsName = "__root_fields";
|
|
1042
1074
|
_rootFields;
|
|
@@ -1160,6 +1192,19 @@ var DataStore = class {
|
|
|
1160
1192
|
const leafName = pathArr.pop();
|
|
1161
1193
|
return { fields: this.tree.getOrCreateFields(path), leafName };
|
|
1162
1194
|
}
|
|
1195
|
+
/**
|
|
1196
|
+
* Creates a new, independent instance of the Store with a fresh, empty data state (FieldsTree).
|
|
1197
|
+
*
|
|
1198
|
+
* The new instance retains the same capabilities (e.g., factory configuration)
|
|
1199
|
+
* as the current one but is completely detached from the existing data hierarchy.
|
|
1200
|
+
* This is useful for creating local scopes, stack frames, or temporary data contexts.
|
|
1201
|
+
*
|
|
1202
|
+
* @returns {DataStore} A new, isolated DataStore instance.
|
|
1203
|
+
*/
|
|
1204
|
+
createIsolated() {
|
|
1205
|
+
return new _DataStore(this.tree.createDetachedTree());
|
|
1206
|
+
}
|
|
1207
|
+
/** code below -> implementation of the DataStore from utils */
|
|
1163
1208
|
has(path) {
|
|
1164
1209
|
const pathArr = (0, import_utils10.ensurePathArray)(path);
|
|
1165
1210
|
if (this.isPathToRootFields(pathArr)) {
|
|
@@ -1167,7 +1212,6 @@ var DataStore = class {
|
|
|
1167
1212
|
}
|
|
1168
1213
|
return this.tree.hasPath(pathArr);
|
|
1169
1214
|
}
|
|
1170
|
-
/** implementation of the DataStore from utils */
|
|
1171
1215
|
get(path) {
|
|
1172
1216
|
return this.getField(path).value;
|
|
1173
1217
|
}
|
|
@@ -1188,13 +1232,13 @@ var DataStore = class {
|
|
|
1188
1232
|
// src/guards.ts
|
|
1189
1233
|
var import_utils11 = require("@axi-engine/utils");
|
|
1190
1234
|
function isFields(value) {
|
|
1191
|
-
return value
|
|
1235
|
+
return !(0, import_utils11.isNullOrUndefined)(value) && value.typeName === Fields.typeName;
|
|
1192
1236
|
}
|
|
1193
1237
|
function isFieldTree(value) {
|
|
1194
|
-
return value
|
|
1238
|
+
return !(0, import_utils11.isNullOrUndefined)(value) && value.typeName === FieldTree.typeName;
|
|
1195
1239
|
}
|
|
1196
|
-
function
|
|
1197
|
-
return !(0, import_utils11.isNullOrUndefined)(value) &&
|
|
1240
|
+
function isDataStore(value) {
|
|
1241
|
+
return !(0, import_utils11.isNullOrUndefined)(value) && value.typeName === DataStore.typeName;
|
|
1198
1242
|
}
|
|
1199
1243
|
|
|
1200
1244
|
// src/setup.ts
|
|
@@ -1265,7 +1309,7 @@ function createCoreFieldSystem(config) {
|
|
|
1265
1309
|
createCoreTreeNodeFactory,
|
|
1266
1310
|
createCoreTreeSerializer,
|
|
1267
1311
|
createTypedMethodsMixin,
|
|
1312
|
+
isDataStore,
|
|
1268
1313
|
isFieldTree,
|
|
1269
|
-
isFields
|
|
1270
|
-
isStore
|
|
1314
|
+
isFields
|
|
1271
1315
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -290,8 +290,8 @@ var CoreNumericField = class _CoreNumericField extends CoreField {
|
|
|
290
290
|
};
|
|
291
291
|
|
|
292
292
|
// src/field-registry.ts
|
|
293
|
-
import {
|
|
294
|
-
var FieldRegistry = class extends
|
|
293
|
+
import { Registry } from "@axi-engine/utils";
|
|
294
|
+
var FieldRegistry = class extends Registry {
|
|
295
295
|
};
|
|
296
296
|
|
|
297
297
|
// src/fields.ts
|
|
@@ -318,6 +318,9 @@ var Fields = class _Fields {
|
|
|
318
318
|
onRemove = new Emitter2();
|
|
319
319
|
/**
|
|
320
320
|
* Gets the read-only map of all `Field` instances in this container.
|
|
321
|
+
*
|
|
322
|
+
* @internal
|
|
323
|
+
*
|
|
321
324
|
* @returns {Map<string, Field<any>>} The collection of fields.
|
|
322
325
|
*/
|
|
323
326
|
get fields() {
|
|
@@ -365,7 +368,7 @@ var Fields = class _Fields {
|
|
|
365
368
|
* @returns {T} The newly created `Field` instance.
|
|
366
369
|
*/
|
|
367
370
|
create(typeName, name, initialValue, options) {
|
|
368
|
-
const Ctor = this._fieldRegistry.
|
|
371
|
+
const Ctor = this._fieldRegistry.getOrThrow(typeName);
|
|
369
372
|
const field = new Ctor(name, initialValue, options);
|
|
370
373
|
this.add(field);
|
|
371
374
|
return field;
|
|
@@ -464,11 +467,28 @@ var FieldTree = class _FieldTree {
|
|
|
464
467
|
*/
|
|
465
468
|
onRemove = new Emitter3();
|
|
466
469
|
/**
|
|
467
|
-
*
|
|
470
|
+
* Provides direct access to the internal node storage.
|
|
471
|
+
*
|
|
472
|
+
* @remarks
|
|
473
|
+
* This is primarily intended for **serialization**, debugging, or low-level iteration.
|
|
474
|
+
* Avoid modifying this map directly to maintain internal consistency; use {@link addNode} or {@link removeNode} instead.
|
|
475
|
+
* @internal
|
|
468
476
|
*/
|
|
469
477
|
get nodes() {
|
|
470
478
|
return this._nodes;
|
|
471
479
|
}
|
|
480
|
+
/**
|
|
481
|
+
* Exposes the internal factory instance used by this tree.
|
|
482
|
+
*
|
|
483
|
+
* @remarks
|
|
484
|
+
* Direct usage of this getter is generally unnecessary.
|
|
485
|
+
* Prefer using {@link createDetachedTree} or {@link createDetachedFields} to create isolated instances.
|
|
486
|
+
*
|
|
487
|
+
* @returns {FieldTreeFactory} The factory instance.
|
|
488
|
+
*/
|
|
489
|
+
get factory() {
|
|
490
|
+
return this._factory;
|
|
491
|
+
}
|
|
472
492
|
/**
|
|
473
493
|
* Creates an instance of FieldTree.
|
|
474
494
|
* @param {FieldTreeFactory} factory - A factory responsible for creating new nodes within the tree.
|
|
@@ -640,6 +660,23 @@ var FieldTree = class _FieldTree {
|
|
|
640
660
|
this.onAdd.clear();
|
|
641
661
|
this.onRemove.clear();
|
|
642
662
|
}
|
|
663
|
+
/**
|
|
664
|
+
* Creates a new, detached FieldTree instance using the same factory as this tree.
|
|
665
|
+
* This new tree has no parent and is completely isolated.
|
|
666
|
+
*
|
|
667
|
+
* @returns A new instance of the same tree type.
|
|
668
|
+
*/
|
|
669
|
+
createDetachedTree() {
|
|
670
|
+
return this._factory.tree();
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Creates a new, detached Fields container using the same factory.
|
|
674
|
+
*
|
|
675
|
+
* @returns
|
|
676
|
+
*/
|
|
677
|
+
createDetachedFields() {
|
|
678
|
+
return this._factory.fields();
|
|
679
|
+
}
|
|
643
680
|
/**
|
|
644
681
|
* @private
|
|
645
682
|
* Navigates the tree to the parent of a target node.
|
|
@@ -758,16 +795,11 @@ var ClampMinPolicySerializerHandler = class {
|
|
|
758
795
|
};
|
|
759
796
|
|
|
760
797
|
// src/serializer/policy-serializer.ts
|
|
761
|
-
import {
|
|
798
|
+
import { Registry as Registry2, throwIfEmpty as throwIfEmpty2 } from "@axi-engine/utils";
|
|
762
799
|
var PolicySerializer = class {
|
|
763
|
-
handlers =
|
|
800
|
+
handlers = new Registry2();
|
|
764
801
|
register(policyId, handler) {
|
|
765
|
-
|
|
766
|
-
this.handlers.set(policyId, handler);
|
|
767
|
-
return this;
|
|
768
|
-
}
|
|
769
|
-
clearHandlers() {
|
|
770
|
-
this.handlers.clear();
|
|
802
|
+
this.handlers.register(policyId, handler);
|
|
771
803
|
}
|
|
772
804
|
/**
|
|
773
805
|
* Creates a serializable snapshot of a policy instance.
|
|
@@ -777,8 +809,7 @@ var PolicySerializer = class {
|
|
|
777
809
|
* @throws If no handler is registered for the policy's ID.
|
|
778
810
|
*/
|
|
779
811
|
snapshot(policy) {
|
|
780
|
-
const handler = this.handlers.
|
|
781
|
-
throwIfEmpty2(handler, `No serializer handler registered for policy ID: '${policy.id}'`);
|
|
812
|
+
const handler = this.handlers.getOrThrow(policy.id);
|
|
782
813
|
const data = handler.snapshot(policy);
|
|
783
814
|
return {
|
|
784
815
|
__type: policy.id,
|
|
@@ -794,8 +825,7 @@ var PolicySerializer = class {
|
|
|
794
825
|
hydrate(snapshot) {
|
|
795
826
|
const typeId = snapshot?.__type;
|
|
796
827
|
throwIfEmpty2(typeId, 'Invalid policy snapshot: missing "__type" identifier.');
|
|
797
|
-
const handler = this.handlers.
|
|
798
|
-
throwIfEmpty2(handler, `No serializer handler registered for policy ID: '${typeId}'`);
|
|
828
|
+
const handler = this.handlers.getOrThrow(typeId);
|
|
799
829
|
const { __type, ...data } = snapshot;
|
|
800
830
|
return handler.hydrate(data);
|
|
801
831
|
}
|
|
@@ -843,7 +873,7 @@ var FieldSerializer = class {
|
|
|
843
873
|
hydrate(snapshot) {
|
|
844
874
|
const fieldType = snapshot.__type;
|
|
845
875
|
throwIfEmpty3(fieldType, 'Invalid field snapshot: missing "__type" identifier.');
|
|
846
|
-
const Ctor = this.fieldRegistry.
|
|
876
|
+
const Ctor = this.fieldRegistry.getOrThrow(fieldType);
|
|
847
877
|
let policies;
|
|
848
878
|
if (!isNullOrUndefined2(snapshot.policies)) {
|
|
849
879
|
policies = [];
|
|
@@ -970,13 +1000,15 @@ var StringFieldResolver = class {
|
|
|
970
1000
|
};
|
|
971
1001
|
|
|
972
1002
|
// src/data-store.ts
|
|
973
|
-
var DataStore = class {
|
|
1003
|
+
var DataStore = class _DataStore {
|
|
974
1004
|
constructor(tree) {
|
|
975
1005
|
this.tree = tree;
|
|
976
1006
|
this.registerResolver(new NumericFieldResolver());
|
|
977
1007
|
this.registerResolver(new BooleanFieldResolver());
|
|
978
1008
|
this.registerResolver(new StringFieldResolver());
|
|
979
1009
|
}
|
|
1010
|
+
static typeName = "dataStore";
|
|
1011
|
+
typeName = _DataStore.typeName;
|
|
980
1012
|
resolvers = [];
|
|
981
1013
|
rootFieldsName = "__root_fields";
|
|
982
1014
|
_rootFields;
|
|
@@ -1100,6 +1132,19 @@ var DataStore = class {
|
|
|
1100
1132
|
const leafName = pathArr.pop();
|
|
1101
1133
|
return { fields: this.tree.getOrCreateFields(path), leafName };
|
|
1102
1134
|
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Creates a new, independent instance of the Store with a fresh, empty data state (FieldsTree).
|
|
1137
|
+
*
|
|
1138
|
+
* The new instance retains the same capabilities (e.g., factory configuration)
|
|
1139
|
+
* as the current one but is completely detached from the existing data hierarchy.
|
|
1140
|
+
* This is useful for creating local scopes, stack frames, or temporary data contexts.
|
|
1141
|
+
*
|
|
1142
|
+
* @returns {DataStore} A new, isolated DataStore instance.
|
|
1143
|
+
*/
|
|
1144
|
+
createIsolated() {
|
|
1145
|
+
return new _DataStore(this.tree.createDetachedTree());
|
|
1146
|
+
}
|
|
1147
|
+
/** code below -> implementation of the DataStore from utils */
|
|
1103
1148
|
has(path) {
|
|
1104
1149
|
const pathArr = ensurePathArray2(path);
|
|
1105
1150
|
if (this.isPathToRootFields(pathArr)) {
|
|
@@ -1107,7 +1152,6 @@ var DataStore = class {
|
|
|
1107
1152
|
}
|
|
1108
1153
|
return this.tree.hasPath(pathArr);
|
|
1109
1154
|
}
|
|
1110
|
-
/** implementation of the DataStore from utils */
|
|
1111
1155
|
get(path) {
|
|
1112
1156
|
return this.getField(path).value;
|
|
1113
1157
|
}
|
|
@@ -1128,13 +1172,13 @@ var DataStore = class {
|
|
|
1128
1172
|
// src/guards.ts
|
|
1129
1173
|
import { isNullOrUndefined as isNullOrUndefined3 } from "@axi-engine/utils";
|
|
1130
1174
|
function isFields(value) {
|
|
1131
|
-
return value
|
|
1175
|
+
return !isNullOrUndefined3(value) && value.typeName === Fields.typeName;
|
|
1132
1176
|
}
|
|
1133
1177
|
function isFieldTree(value) {
|
|
1134
|
-
return value
|
|
1178
|
+
return !isNullOrUndefined3(value) && value.typeName === FieldTree.typeName;
|
|
1135
1179
|
}
|
|
1136
|
-
function
|
|
1137
|
-
return !isNullOrUndefined3(value) &&
|
|
1180
|
+
function isDataStore(value) {
|
|
1181
|
+
return !isNullOrUndefined3(value) && value.typeName === DataStore.typeName;
|
|
1138
1182
|
}
|
|
1139
1183
|
|
|
1140
1184
|
// src/setup.ts
|
|
@@ -1204,7 +1248,7 @@ export {
|
|
|
1204
1248
|
createCoreTreeNodeFactory,
|
|
1205
1249
|
createCoreTreeSerializer,
|
|
1206
1250
|
createTypedMethodsMixin,
|
|
1251
|
+
isDataStore,
|
|
1207
1252
|
isFieldTree,
|
|
1208
|
-
isFields
|
|
1209
|
-
isStore
|
|
1253
|
+
isFields
|
|
1210
1254
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axi-engine/fields",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
4
4
|
"description": "A compact, reactive state management library based on a tree of observable fields.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"dequal": "^2.0.3"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@axi-engine/utils": "^0.2.
|
|
39
|
+
"@axi-engine/utils": "^0.2.6"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@axi-engine/utils": "^0.2.
|
|
42
|
+
"@axi-engine/utils": "^0.2.6"
|
|
43
43
|
}
|
|
44
44
|
}
|