@axi-engine/fields 0.1.5 → 0.2.0
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/README.md +13 -7
- package/dist/index.d.mts +648 -212
- package/dist/index.d.ts +648 -212
- package/dist/index.js +707 -382
- package/dist/index.mjs +688 -373
- package/package.json +3 -6
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import { PathType } from '@axi-engine/utils';
|
|
1
|
+
import * as _axi_engine_utils from '@axi-engine/utils';
|
|
2
|
+
import { Subscribable, Constructor, Emitter, PathType } from '@axi-engine/utils';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
fieldTree = "FieldTree",
|
|
7
|
-
fields = "Fields"
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
interface FieldPolicy<T> {
|
|
4
|
+
interface Policy<T> {
|
|
11
5
|
readonly id: string;
|
|
12
6
|
apply: (val: T) => T;
|
|
13
7
|
destroy?: () => void;
|
|
14
8
|
}
|
|
15
|
-
|
|
9
|
+
|
|
10
|
+
declare class ClampPolicy implements Policy<number> {
|
|
16
11
|
min: number;
|
|
17
12
|
max: number;
|
|
18
13
|
static readonly id = "clamp";
|
|
@@ -21,15 +16,9 @@ declare class ClampPolicy implements FieldPolicy<number> {
|
|
|
21
16
|
apply(val: number): number;
|
|
22
17
|
updateBounds(min: number, max: number): void;
|
|
23
18
|
}
|
|
24
|
-
declare
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
readonly id = "clampMin";
|
|
28
|
-
constructor(min: number);
|
|
29
|
-
apply(val: number): number;
|
|
30
|
-
updateBounds(min: number): void;
|
|
31
|
-
}
|
|
32
|
-
declare class ClampMaxPolicy implements FieldPolicy<number> {
|
|
19
|
+
declare function clampPolicy(min: number, max: number): ClampPolicy;
|
|
20
|
+
|
|
21
|
+
declare class ClampMaxPolicy implements Policy<number> {
|
|
33
22
|
max: number;
|
|
34
23
|
static readonly id = "clampMax";
|
|
35
24
|
readonly id = "clampMax";
|
|
@@ -37,48 +26,21 @@ declare class ClampMaxPolicy implements FieldPolicy<number> {
|
|
|
37
26
|
apply(val: number): number;
|
|
38
27
|
updateBounds(max: number): void;
|
|
39
28
|
}
|
|
40
|
-
declare function clampPolicy(min: number, max: number): ClampPolicy;
|
|
41
|
-
declare function clampMinPolicy(min: number): ClampMinPolicy;
|
|
42
29
|
declare function clampMaxPolicy(max: number): ClampMaxPolicy;
|
|
43
30
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
31
|
+
declare class ClampMinPolicy implements Policy<number> {
|
|
32
|
+
min: number;
|
|
33
|
+
static readonly id = "clampMin";
|
|
34
|
+
readonly id = "clampMin";
|
|
35
|
+
constructor(min: number);
|
|
36
|
+
apply(val: number): number;
|
|
37
|
+
updateBounds(min: number): void;
|
|
38
|
+
}
|
|
39
|
+
declare function clampMinPolicy(min: number): ClampMinPolicy;
|
|
40
|
+
|
|
41
|
+
declare class Policies<T> {
|
|
52
42
|
private readonly policies;
|
|
53
|
-
|
|
54
|
-
/** A unique identifier for the field. */
|
|
55
|
-
name: string;
|
|
56
|
-
/**
|
|
57
|
-
* Creates an instance of a Field.
|
|
58
|
-
* @param name A unique identifier for the field.
|
|
59
|
-
* @param initialVal The initial value of the field.
|
|
60
|
-
* @param options Optional configuration for the field.
|
|
61
|
-
* @param options.policies An array of policies to apply to the field's value on every `set` operation.
|
|
62
|
-
*/
|
|
63
|
-
constructor(name: string, initialVal: T, options?: {
|
|
64
|
-
policies?: FieldPolicy<T>[];
|
|
65
|
-
});
|
|
66
|
-
/**
|
|
67
|
-
* Gets the current raw value of the field.
|
|
68
|
-
* For reactive updates, it's recommended to use the `.signal` property instead.
|
|
69
|
-
*/
|
|
70
|
-
get val(): T;
|
|
71
|
-
/**
|
|
72
|
-
* Provides readonly access to the underlying Preact Signal.
|
|
73
|
-
* Subscribe to this signal to react to value changes.
|
|
74
|
-
*/
|
|
75
|
-
get signal(): ReadonlySignal<T>;
|
|
76
|
-
/**
|
|
77
|
-
* Sets a new value for the field.
|
|
78
|
-
* The provided value will be processed by all registered policies before the underlying signal is updated.
|
|
79
|
-
* @param val The new value to set.
|
|
80
|
-
*/
|
|
81
|
-
set(val: T): void;
|
|
43
|
+
get items(): Map<string, Policy<T>>;
|
|
82
44
|
/**
|
|
83
45
|
* Retrieves a specific policy instance by its ID.
|
|
84
46
|
* Useful for accessing a policy's internal state or methods.
|
|
@@ -86,30 +48,106 @@ declare class Field<T> {
|
|
|
86
48
|
* @param id The unique ID of the policy to retrieve.
|
|
87
49
|
* @returns The policy instance, or `undefined` if not found.
|
|
88
50
|
*/
|
|
89
|
-
|
|
51
|
+
get<P extends Policy<T>>(id: string): P | undefined;
|
|
90
52
|
/**
|
|
91
53
|
* Adds a new policy to the field or replaces an existing one with the same ID.
|
|
92
54
|
* The new policy will be applied on the next `set()` operation.
|
|
93
55
|
* If a policy with the same ID already exists, its `destroy` method will be called before it is replaced.
|
|
94
56
|
* @param policy The policy instance to add.
|
|
95
57
|
*/
|
|
96
|
-
|
|
58
|
+
add(policy: Policy<T>): this;
|
|
97
59
|
/**
|
|
98
60
|
* Removes a policy from the field by its ID and call `destroy` method.
|
|
99
61
|
* @param policyId The unique ID of the policy to remove.
|
|
100
62
|
* @returns `true` if the policy was found and removed, otherwise `false`.
|
|
101
63
|
*/
|
|
102
|
-
|
|
64
|
+
remove(policyId: string): boolean;
|
|
65
|
+
isEmpty(): boolean;
|
|
103
66
|
/**
|
|
104
67
|
* Removes all policies from the field.
|
|
105
68
|
* After this, `set()` will no longer apply any transformations to the value until new policies are added.
|
|
106
69
|
*/
|
|
107
|
-
|
|
70
|
+
clear(): void;
|
|
108
71
|
/**
|
|
109
72
|
* Forces the current value to be re-processed by all policies.
|
|
110
73
|
* Useful if a policy's logic has changed and you need to re-evaluate the current state.
|
|
111
74
|
*/
|
|
112
|
-
|
|
75
|
+
apply(val: T): T;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface FieldOptions<T> {
|
|
79
|
+
policies?: Policy<T>[];
|
|
80
|
+
}
|
|
81
|
+
interface Field<T> {
|
|
82
|
+
readonly typeName: string;
|
|
83
|
+
readonly name: string;
|
|
84
|
+
value: T;
|
|
85
|
+
policies: Policies<T>;
|
|
86
|
+
setValueSilently(val: T): void;
|
|
87
|
+
batchUpdate(updateFn: (currentValue: T) => T): void;
|
|
88
|
+
onChange: Subscribable<[newValue: T, oldValue: T]>;
|
|
89
|
+
destroy(): void;
|
|
90
|
+
}
|
|
91
|
+
interface NumericField extends Field<number> {
|
|
92
|
+
readonly min: number | undefined;
|
|
93
|
+
readonly max: number | undefined;
|
|
94
|
+
isMin(): boolean;
|
|
95
|
+
isMax(): boolean;
|
|
96
|
+
inc(val: number): void;
|
|
97
|
+
dec(val: number): void;
|
|
98
|
+
}
|
|
99
|
+
interface BooleanField extends Field<boolean> {
|
|
100
|
+
toggle(): boolean;
|
|
101
|
+
}
|
|
102
|
+
interface StringField extends Field<string> {
|
|
103
|
+
append(str: string | number): this;
|
|
104
|
+
prepend(str: string | number): this;
|
|
105
|
+
trim(): this;
|
|
106
|
+
isEmpty(): boolean;
|
|
107
|
+
clear(): void;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* A state container that wraps a value.
|
|
112
|
+
* It allows applying a pipeline of transformation or validation "policies" before any new value is set.
|
|
113
|
+
*
|
|
114
|
+
* @template T The type of the value this field holds.
|
|
115
|
+
*
|
|
116
|
+
*/
|
|
117
|
+
declare class DefaultField<T> implements Field<T> {
|
|
118
|
+
/** A type keyword of the field */
|
|
119
|
+
static readonly typeName: string;
|
|
120
|
+
readonly typeName: string;
|
|
121
|
+
/** A unique identifier for the field. */
|
|
122
|
+
private readonly _name;
|
|
123
|
+
private _value;
|
|
124
|
+
private readonly _onChange;
|
|
125
|
+
readonly onChange: Subscribable<[newValue: T, oldvalue: T]>;
|
|
126
|
+
readonly policies: Policies<T>;
|
|
127
|
+
get name(): string;
|
|
128
|
+
/**
|
|
129
|
+
* Gets the current raw value of the field.
|
|
130
|
+
* For reactive updates, it's recommended to use the `.signal` property instead.
|
|
131
|
+
*/
|
|
132
|
+
get value(): T;
|
|
133
|
+
/**
|
|
134
|
+
* Sets a new value for the field.
|
|
135
|
+
* The provided value will be processed by all registered policies before the underlying signal is updated.
|
|
136
|
+
* @param val The new value to set.
|
|
137
|
+
*/
|
|
138
|
+
set value(val: T);
|
|
139
|
+
/**
|
|
140
|
+
* Creates an instance of a Field.
|
|
141
|
+
* @param name A unique identifier for the field.
|
|
142
|
+
* @param initialVal The initial value of the field.
|
|
143
|
+
* @param options Optional configuration for the field.
|
|
144
|
+
* @param options.policies An array of policies to apply to the field's value on every `set` operation.
|
|
145
|
+
* @param options.isEqual An function for compare old and new value, by default uses the strictEquals from `utils`
|
|
146
|
+
*
|
|
147
|
+
*/
|
|
148
|
+
constructor(name: string, initialVal: T, options?: FieldOptions<T>);
|
|
149
|
+
setValueSilently(val: T): void;
|
|
150
|
+
batchUpdate(updateFn: (currentValue: T) => T): void;
|
|
113
151
|
/**
|
|
114
152
|
* Cleans up resources used by the field and its policies.
|
|
115
153
|
* This should be called when the field is no longer needed to prevent memory leaks from reactive policies.
|
|
@@ -117,240 +155,638 @@ declare class Field<T> {
|
|
|
117
155
|
destroy(): void;
|
|
118
156
|
}
|
|
119
157
|
|
|
120
|
-
interface
|
|
158
|
+
interface DefaultBooleanFieldOptions extends FieldOptions<boolean> {
|
|
159
|
+
}
|
|
160
|
+
declare class DefaultBooleanField extends DefaultField<boolean> implements BooleanField {
|
|
161
|
+
static readonly typeName: string;
|
|
162
|
+
readonly typeName: string;
|
|
163
|
+
constructor(name: string, initialVal: boolean, options?: DefaultBooleanFieldOptions);
|
|
164
|
+
toggle(): boolean;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
interface DefaultStringFieldOptions extends FieldOptions<string> {
|
|
168
|
+
}
|
|
169
|
+
declare class DefaultStringField extends DefaultField<string> implements StringField {
|
|
170
|
+
static readonly typeName: string;
|
|
171
|
+
readonly typeName: string;
|
|
172
|
+
constructor(name: string, initialVal: string, options?: DefaultStringFieldOptions);
|
|
173
|
+
append(str: string | number): this;
|
|
174
|
+
prepend(str: string | number): this;
|
|
175
|
+
trim(): this;
|
|
176
|
+
isEmpty(): boolean;
|
|
177
|
+
clear(): void;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
interface DefaultNumericFieldOptions extends FieldOptions<number> {
|
|
121
181
|
min?: number;
|
|
122
182
|
max?: number;
|
|
123
|
-
policies?: FieldPolicy<number>[];
|
|
124
183
|
}
|
|
125
|
-
declare class
|
|
184
|
+
declare class DefaultNumericField extends DefaultField<number> implements NumericField {
|
|
185
|
+
static readonly typeName: string;
|
|
186
|
+
readonly typeName: string;
|
|
126
187
|
get min(): number | undefined;
|
|
127
188
|
get max(): number | undefined;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
189
|
+
constructor(name: string, initialVal: number, options?: DefaultNumericFieldOptions);
|
|
190
|
+
isMin(): boolean;
|
|
191
|
+
isMax(): boolean;
|
|
131
192
|
inc(amount?: number): void;
|
|
132
193
|
dec(amount?: number): void;
|
|
133
194
|
}
|
|
134
195
|
|
|
135
196
|
/**
|
|
136
|
-
*
|
|
197
|
+
* A generic registry for mapping string identifiers to class constructors.
|
|
137
198
|
*
|
|
138
|
-
* This
|
|
139
|
-
*
|
|
199
|
+
* This utility is fundamental for building extensible systems like dependency injection containers,
|
|
200
|
+
* factories, and serialization engines where types need to be dynamically resolved.
|
|
201
|
+
*
|
|
202
|
+
* @template T - A base type that all registered constructors must produce an instance of.
|
|
203
|
+
*/
|
|
204
|
+
declare class ConstructorRegistry<T> {
|
|
205
|
+
private readonly items;
|
|
206
|
+
/**
|
|
207
|
+
* Registers a constructor with a unique string identifier.
|
|
208
|
+
*
|
|
209
|
+
* @param typeId - The unique identifier for the constructor (e.g., a static `typeName` property from a class).
|
|
210
|
+
* @param ctor - The class constructor to register.
|
|
211
|
+
* @returns The registry instance for chainable calls.
|
|
212
|
+
* @throws If a constructor with the same `typeId` is already registered.
|
|
213
|
+
*/
|
|
214
|
+
register(typeId: string, ctor: Constructor<T>): this;
|
|
215
|
+
/**
|
|
216
|
+
* Retrieves a constructor by its identifier.
|
|
217
|
+
*
|
|
218
|
+
* @param typeId - The identifier of the constructor to retrieve.
|
|
219
|
+
* @returns The found class constructor.
|
|
220
|
+
* @throws If no constructor is found for the given `typeId`.
|
|
221
|
+
*/
|
|
222
|
+
get(typeId: string): Constructor<T>;
|
|
223
|
+
/**
|
|
224
|
+
* Checks if a constructor for a given identifier is registered.
|
|
225
|
+
* @param typeId - The identifier to check.
|
|
226
|
+
* @returns `true` if a constructor is registered, otherwise `false`.
|
|
227
|
+
*/
|
|
228
|
+
has(typeId: string): boolean;
|
|
229
|
+
/**
|
|
230
|
+
* Clears all registered constructors from the registry.
|
|
231
|
+
*/
|
|
232
|
+
clear(): void;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
declare class FieldRegistry extends ConstructorRegistry<Field<any>> {
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* A container for a collection of named `Field` instances.
|
|
140
240
|
*
|
|
141
|
-
*
|
|
241
|
+
* This class acts as a "leaf" node in the `FieldTree` hierarchy, managing a flat
|
|
242
|
+
* key-value store of reactive data points. It uses a `FieldRegistry` to dynamically
|
|
243
|
+
* create `Field` instances of different types.
|
|
142
244
|
*/
|
|
143
|
-
declare
|
|
144
|
-
|
|
145
|
-
readonly
|
|
245
|
+
declare class Fields {
|
|
246
|
+
static readonly typeName = "fields";
|
|
247
|
+
readonly typeName = "fields";
|
|
248
|
+
readonly _fields: Map<string, Field<any>>;
|
|
249
|
+
readonly _fieldRegistry: FieldRegistry;
|
|
250
|
+
/**
|
|
251
|
+
* An event emitter that fires when a new field is added to the collection.
|
|
252
|
+
* @event
|
|
253
|
+
* @param {object} event - The event payload.
|
|
254
|
+
* @param {string} event.name - The name of the added field.
|
|
255
|
+
* @param {Field<any>} event.field - The `Field` instance that was added.
|
|
256
|
+
*/
|
|
257
|
+
onAdd: Emitter<[event: {
|
|
258
|
+
name: string;
|
|
259
|
+
field: Field<any>;
|
|
260
|
+
}]>;
|
|
261
|
+
/**
|
|
262
|
+
* An event emitter that fires after one or more fields have been removed.
|
|
263
|
+
* @event
|
|
264
|
+
* @param {object} event - The event payload.
|
|
265
|
+
* @param {string[]} event.names - An array of names of the fields that were successfully removed.
|
|
266
|
+
*/
|
|
267
|
+
onRemove: Emitter<[event: {
|
|
268
|
+
names: string[];
|
|
269
|
+
}]>;
|
|
270
|
+
/**
|
|
271
|
+
* Gets the read-only map of all `Field` instances in this container.
|
|
272
|
+
* @returns {Map<string, Field<any>>} The collection of fields.
|
|
273
|
+
*/
|
|
274
|
+
get fields(): Map<string, Field<any>>;
|
|
146
275
|
/**
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
* Avoid to change any data in the map manually.
|
|
276
|
+
* Creates an instance of Fields.
|
|
277
|
+
* @param {FieldRegistry} fieldRegistry - The registry used to create new `Field` instances.
|
|
150
278
|
*/
|
|
151
|
-
|
|
279
|
+
constructor(fieldRegistry: FieldRegistry);
|
|
152
280
|
/**
|
|
153
281
|
* Checks if a field with the given name exists in the collection.
|
|
154
|
-
* @param name The name of the field to check.
|
|
155
|
-
* @returns `true` if the field exists, otherwise `false`.
|
|
282
|
+
* @param {string} name The name of the field to check.
|
|
283
|
+
* @returns {boolean} `true` if the field exists, otherwise `false`.
|
|
156
284
|
*/
|
|
157
285
|
has(name: string): boolean;
|
|
158
286
|
/**
|
|
159
|
-
*
|
|
160
|
-
* @
|
|
161
|
-
* @param
|
|
162
|
-
* @returns The
|
|
287
|
+
* Adds a pre-existing `Field` instance to the collection and fires the `onAdd` event.
|
|
288
|
+
* @template T - The specific `Field` type being added.
|
|
289
|
+
* @param {Field<any>} field - The `Field` instance to add.
|
|
290
|
+
* @returns {T} The added `Field` instance, cast to type `T`.
|
|
291
|
+
* @throws If a field with the same name already exists.
|
|
163
292
|
*/
|
|
164
|
-
|
|
293
|
+
add<T extends Field<any>>(field: Field<any>): T;
|
|
165
294
|
/**
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
* @
|
|
169
|
-
* @
|
|
295
|
+
* Creates a new `Field` instance of a specified type, adds it to the collection, and returns it.
|
|
296
|
+
* This is the primary factory method for creating fields within this container.
|
|
297
|
+
* @template T - The expected `Field` type to be returned.
|
|
298
|
+
* @param {string} typeName - The registered type name of the field to create (e.g., 'numeric', 'boolean').
|
|
299
|
+
* @param {string} name - The unique name for the new field.
|
|
300
|
+
* @param {*} initialValue - The initial value for the new field.
|
|
301
|
+
* @param {*} [options] - Optional configuration passed to the field's constructor.
|
|
302
|
+
* @returns {T} The newly created `Field` instance.
|
|
170
303
|
*/
|
|
171
|
-
|
|
304
|
+
create<T extends Field<any>>(typeName: string, name: string, initialValue: any, options?: any): T;
|
|
172
305
|
/**
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* @param
|
|
176
|
-
* @
|
|
306
|
+
* Updates an existing field's value or creates a new one if it doesn't exist.
|
|
307
|
+
* @template T - The expected `Field` type.
|
|
308
|
+
* @param {string} typeName - The type name to use if a new field needs to be created.
|
|
309
|
+
* @param {string} name - The name of the field to update or create.
|
|
310
|
+
* @param {*} value - The new value to set.
|
|
311
|
+
* @param {*} [options] - Optional configuration, used only if a new field is created.
|
|
312
|
+
* @returns {T} The existing or newly created `Field` instance.
|
|
177
313
|
*/
|
|
178
|
-
|
|
314
|
+
upset<T extends Field<any>>(typeName: string, name: string, value: any, options?: any): T;
|
|
179
315
|
/**
|
|
180
|
-
*
|
|
181
|
-
* @
|
|
182
|
-
* @param
|
|
183
|
-
* @returns The
|
|
316
|
+
* Retrieves a field by its name.
|
|
317
|
+
* @template T - The expected `Field` type to be returned.
|
|
318
|
+
* @param {string} name - The name of the field to retrieve.
|
|
319
|
+
* @returns {T} The `Field` instance.
|
|
320
|
+
* @throws If the field does not exist.
|
|
184
321
|
*/
|
|
185
|
-
|
|
322
|
+
get<T extends Field<any>>(name: string): T;
|
|
186
323
|
/**
|
|
187
324
|
* Removes one or more fields from the collection.
|
|
188
325
|
* This method ensures that the `destroy` method of each removed field is called to clean up its resources.
|
|
189
|
-
* @param names A single name or an array of names to remove.
|
|
326
|
+
* @param {string| string[]} names A single name or an array of names to remove.
|
|
190
327
|
*/
|
|
191
328
|
remove(names: string | string[]): void;
|
|
192
329
|
/**
|
|
193
330
|
* Removes all fields from the collection, ensuring each is properly destroyed.
|
|
194
331
|
*/
|
|
195
332
|
clear(): void;
|
|
196
|
-
/**
|
|
197
|
-
* Creates a serializable snapshot of the current state of all fields.
|
|
198
|
-
* @returns A plain JavaScript object representing the values of all fields.
|
|
199
|
-
*/
|
|
200
|
-
snapshot(): Record<string, any>;
|
|
201
|
-
/**
|
|
202
|
-
* Restores the state of the fields from a snapshot.
|
|
203
|
-
* It uses the `upset` logic to create or update fields based on the snapshot data.
|
|
204
|
-
* @param snapshot The snapshot object to load.
|
|
205
|
-
*/
|
|
206
|
-
hydrate(snapshot: any): void;
|
|
207
333
|
}
|
|
208
334
|
|
|
209
|
-
declare
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
335
|
+
declare const DefaultFields_base: {
|
|
336
|
+
new (...args: any[]): {
|
|
337
|
+
createBoolean(name: string, initialValue: boolean, options?: DefaultBooleanFieldOptions): DefaultBooleanField;
|
|
338
|
+
upsetBoolean(name: string, value: boolean, options?: DefaultBooleanFieldOptions): DefaultBooleanField;
|
|
339
|
+
getBoolean(name: string): DefaultBooleanField;
|
|
340
|
+
readonly typeName: "fields";
|
|
341
|
+
readonly _fields: Map<string, Field<any>>;
|
|
342
|
+
readonly _fieldRegistry: FieldRegistry;
|
|
343
|
+
onAdd: _axi_engine_utils.Emitter<[event: {
|
|
344
|
+
name: string;
|
|
345
|
+
field: Field<any>;
|
|
346
|
+
}]>;
|
|
347
|
+
onRemove: _axi_engine_utils.Emitter<[event: {
|
|
348
|
+
names: string[];
|
|
349
|
+
}]>;
|
|
350
|
+
get fields(): Map<string, Field<any>>;
|
|
351
|
+
has(name: string): boolean;
|
|
352
|
+
add<T extends Field<any>>(field: Field<any>): T;
|
|
353
|
+
create<T extends Field<any>>(typeName: string, name: string, initialValue: any, options?: any): T;
|
|
354
|
+
upset<T extends Field<any>>(typeName: string, name: string, value: any, options?: any): T;
|
|
355
|
+
get<T extends Field<any>>(name: string): T;
|
|
356
|
+
remove(names: string | string[]): void;
|
|
357
|
+
clear(): void;
|
|
358
|
+
};
|
|
359
|
+
} & {
|
|
360
|
+
new (...args: any[]): {
|
|
361
|
+
createString(name: string, initialValue: string, options?: DefaultStringFieldOptions): DefaultStringField;
|
|
362
|
+
upsetString(name: string, value: string, options?: DefaultStringFieldOptions): DefaultStringField;
|
|
363
|
+
getString(name: string): DefaultStringField;
|
|
364
|
+
readonly typeName: "fields";
|
|
365
|
+
readonly _fields: Map<string, Field<any>>;
|
|
366
|
+
readonly _fieldRegistry: FieldRegistry;
|
|
367
|
+
onAdd: _axi_engine_utils.Emitter<[event: {
|
|
368
|
+
name: string;
|
|
369
|
+
field: Field<any>;
|
|
370
|
+
}]>;
|
|
371
|
+
onRemove: _axi_engine_utils.Emitter<[event: {
|
|
372
|
+
names: string[];
|
|
373
|
+
}]>;
|
|
374
|
+
get fields(): Map<string, Field<any>>;
|
|
375
|
+
has(name: string): boolean;
|
|
376
|
+
add<T extends Field<any>>(field: Field<any>): T;
|
|
377
|
+
create<T extends Field<any>>(typeName: string, name: string, initialValue: any, options?: any): T;
|
|
378
|
+
upset<T extends Field<any>>(typeName: string, name: string, value: any, options?: any): T;
|
|
379
|
+
get<T extends Field<any>>(name: string): T;
|
|
380
|
+
remove(names: string | string[]): void;
|
|
381
|
+
clear(): void;
|
|
382
|
+
};
|
|
383
|
+
} & {
|
|
384
|
+
new (...args: any[]): {
|
|
385
|
+
createNumeric(name: string, initialValue: number, options?: DefaultNumericFieldOptions): DefaultNumericField;
|
|
386
|
+
upsetNumeric(name: string, value: number, options?: DefaultNumericFieldOptions): DefaultNumericField;
|
|
387
|
+
getNumeric(name: string): DefaultNumericField;
|
|
388
|
+
readonly typeName: "fields";
|
|
389
|
+
readonly _fields: Map<string, Field<any>>;
|
|
390
|
+
readonly _fieldRegistry: FieldRegistry;
|
|
391
|
+
onAdd: _axi_engine_utils.Emitter<[event: {
|
|
392
|
+
name: string;
|
|
393
|
+
field: Field<any>;
|
|
394
|
+
}]>;
|
|
395
|
+
onRemove: _axi_engine_utils.Emitter<[event: {
|
|
396
|
+
names: string[];
|
|
397
|
+
}]>;
|
|
398
|
+
get fields(): Map<string, Field<any>>;
|
|
399
|
+
has(name: string): boolean;
|
|
400
|
+
add<T extends Field<any>>(field: Field<any>): T;
|
|
401
|
+
create<T extends Field<any>>(typeName: string, name: string, initialValue: any, options?: any): T;
|
|
402
|
+
upset<T extends Field<any>>(typeName: string, name: string, value: any, options?: any): T;
|
|
403
|
+
get<T extends Field<any>>(name: string): T;
|
|
404
|
+
remove(names: string | string[]): void;
|
|
405
|
+
clear(): void;
|
|
406
|
+
};
|
|
407
|
+
} & {
|
|
408
|
+
new (...args: any[]): {
|
|
409
|
+
createDefault<T>(name: string, initialValue: T, options?: FieldOptions<T> | undefined): DefaultField<T>;
|
|
410
|
+
upsetDefault<T>(name: string, value: T, options?: FieldOptions<T> | undefined): DefaultField<T>;
|
|
411
|
+
readonly typeName: "fields";
|
|
412
|
+
readonly _fields: Map<string, Field<any>>;
|
|
413
|
+
readonly _fieldRegistry: FieldRegistry;
|
|
414
|
+
onAdd: _axi_engine_utils.Emitter<[event: {
|
|
415
|
+
name: string;
|
|
416
|
+
field: Field<any>;
|
|
417
|
+
}]>;
|
|
418
|
+
onRemove: _axi_engine_utils.Emitter<[event: {
|
|
419
|
+
names: string[];
|
|
420
|
+
}]>;
|
|
421
|
+
get fields(): Map<string, Field<any>>;
|
|
422
|
+
has(name: string): boolean;
|
|
423
|
+
add<T extends Field<any>>(field: Field<any>): T;
|
|
424
|
+
create<T extends Field<any>>(typeName: string, name: string, initialValue: any, options?: any): T;
|
|
425
|
+
upset<T extends Field<any>>(typeName: string, name: string, value: any, options?: any): T;
|
|
426
|
+
get<T extends Field<any>>(name: string): T;
|
|
427
|
+
remove(names: string | string[]): void;
|
|
428
|
+
clear(): void;
|
|
429
|
+
};
|
|
430
|
+
} & typeof Fields;
|
|
431
|
+
declare class DefaultFields extends DefaultFields_base {
|
|
216
432
|
}
|
|
217
433
|
|
|
218
|
-
|
|
434
|
+
/**
|
|
435
|
+
* Defines the contract for a factory that creates nodes for a FieldTree.
|
|
436
|
+
* This allows for custom implementations of Fields and FieldTree to be used.
|
|
437
|
+
*/
|
|
438
|
+
interface TreeNodeFactory {
|
|
439
|
+
fields<T extends Fields>(): T;
|
|
440
|
+
tree<T extends FieldTree>(): T;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* The default factory implementation that creates standard DefaultFields and FieldTree instances.
|
|
444
|
+
*/
|
|
445
|
+
declare class DefaultTreeNodeFactory implements TreeNodeFactory {
|
|
446
|
+
private readonly fieldRegistry;
|
|
447
|
+
constructor(fieldRegistry: FieldRegistry);
|
|
448
|
+
fields: () => any;
|
|
449
|
+
tree: () => any;
|
|
219
450
|
}
|
|
220
451
|
|
|
221
452
|
/** A type alias for any container that can be a child node in a FieldTree */
|
|
222
|
-
type
|
|
223
|
-
/** Describes the payload for events emitted when a container is created or removed from a FieldTree. */
|
|
224
|
-
type FieldTreeContainerEvent = {
|
|
225
|
-
type: 'created' | 'removed';
|
|
226
|
-
name: string;
|
|
227
|
-
path: [];
|
|
228
|
-
node: TreeOrFieldsContainer;
|
|
229
|
-
};
|
|
453
|
+
type TreeOrFieldsNode = FieldTree | Fields;
|
|
230
454
|
/**
|
|
231
|
-
* Represents the global
|
|
232
|
-
*
|
|
455
|
+
* Represents a hierarchical data structure for managing the global state of the system.
|
|
456
|
+
*
|
|
457
|
+
* This class acts as the single source of truth for long-term data that exists
|
|
233
458
|
* across different scenes and scripts, such as player stats, inventory,
|
|
234
|
-
* and overall game progress.
|
|
235
|
-
*
|
|
236
|
-
* independent of any single script's / minigames execution lifecycle.
|
|
459
|
+
* and overall game progress. It uses a path-based system for accessing and
|
|
460
|
+
* manipulating nested data, similar to a file system.
|
|
237
461
|
*
|
|
238
|
-
* @todo
|
|
239
|
-
* -
|
|
462
|
+
* @todo
|
|
463
|
+
* - Add node removal functionality.
|
|
464
|
+
* - Implement an event system for node creation/removal.
|
|
240
465
|
*/
|
|
241
466
|
declare class FieldTree {
|
|
242
|
-
|
|
243
|
-
readonly
|
|
467
|
+
static readonly typeName = "fieldTree";
|
|
468
|
+
readonly typeName = "fieldTree";
|
|
469
|
+
/** @private The internal map storing child nodes (branches or leaves). */
|
|
470
|
+
private readonly _nodes;
|
|
471
|
+
/** @private The factory used to create new child nodes. */
|
|
472
|
+
private readonly _factory;
|
|
244
473
|
/**
|
|
245
|
-
*
|
|
246
|
-
* Use this with `effect` to react to structural changes in the tree (e.g., adding a new `Fields` container).
|
|
474
|
+
* Gets the collection of direct child nodes of this tree branch.
|
|
247
475
|
*/
|
|
248
|
-
get
|
|
249
|
-
constructor();
|
|
476
|
+
get nodes(): Map<string, TreeOrFieldsNode>;
|
|
250
477
|
/**
|
|
251
|
-
*
|
|
252
|
-
* @
|
|
478
|
+
* Creates an instance of FieldTree.
|
|
479
|
+
* @param {TreeNodeFactory} factory - A factory responsible for creating new nodes within the tree.
|
|
253
480
|
*/
|
|
254
|
-
|
|
481
|
+
constructor(factory: TreeNodeFactory);
|
|
255
482
|
/**
|
|
256
|
-
*
|
|
257
|
-
* @param name The name of the child node.
|
|
258
|
-
* @returns
|
|
259
|
-
* @throws If the node does not exist or is not a `FieldTree`.
|
|
483
|
+
* Checks if a direct child node with the given name exists.
|
|
484
|
+
* @param {string} name - The name of the direct child node.
|
|
485
|
+
* @returns {boolean} `true` if the node exists, otherwise `false`.
|
|
260
486
|
*/
|
|
261
|
-
|
|
487
|
+
has(name: string): boolean;
|
|
262
488
|
/**
|
|
263
|
-
*
|
|
264
|
-
* @param
|
|
265
|
-
* @returns
|
|
266
|
-
* @throws If the node does not exist or is not a `Fields` container.
|
|
489
|
+
* Checks if a node exists at a given path, traversing the tree.
|
|
490
|
+
* @param {PathType} path - The path to check (e.g., 'player/stats' or ['player', 'stats']).
|
|
491
|
+
* @returns {boolean} `true` if the entire path resolves to a node, otherwise `false`.
|
|
267
492
|
*/
|
|
268
|
-
|
|
493
|
+
hasPath(path: PathType): boolean;
|
|
269
494
|
/**
|
|
270
|
-
*
|
|
271
|
-
* @param name The name
|
|
272
|
-
* @
|
|
273
|
-
* @
|
|
495
|
+
* Adds a pre-existing node as a direct child of this tree branch.
|
|
496
|
+
* @param {string} name - The name to assign to the new child node.
|
|
497
|
+
* @param {TreeOrFieldsNode} node - The node instance to add.
|
|
498
|
+
* @returns {TreeOrFieldsNode} The added node.
|
|
499
|
+
* @throws If a node with the same name already exists.
|
|
274
500
|
*/
|
|
275
|
-
|
|
501
|
+
addNode(name: string, node: TreeOrFieldsNode): TreeOrFieldsNode;
|
|
276
502
|
/**
|
|
277
|
-
* Retrieves a child node
|
|
278
|
-
* @param name The name of the child node.
|
|
279
|
-
* @returns The retrieved node
|
|
503
|
+
* Retrieves a direct child node by its name.
|
|
504
|
+
* @param {string} name - The name of the child node.
|
|
505
|
+
* @returns {TreeOrFieldsNode} The retrieved node.
|
|
280
506
|
* @throws If a node with the given name cannot be found.
|
|
281
507
|
*/
|
|
282
|
-
getNode(name: string):
|
|
508
|
+
getNode(name: string): TreeOrFieldsNode;
|
|
283
509
|
/**
|
|
284
|
-
* Creates
|
|
285
|
-
* @param
|
|
286
|
-
* @
|
|
510
|
+
* Creates a new `FieldTree` (branch) node at the specified path.
|
|
511
|
+
* @param {PathType} path - The path where the new `FieldTree` should be created.
|
|
512
|
+
* @param {boolean} [createPath=false] - If `true`, any missing parent branches in the path will be created automatically.
|
|
513
|
+
* @returns {FieldTree} The newly created `FieldTree` instance.
|
|
514
|
+
* @throws If the path is invalid or a node already exists at the target location.
|
|
287
515
|
*/
|
|
288
|
-
createFieldTree(
|
|
516
|
+
createFieldTree<T extends FieldTree>(path: PathType, createPath?: boolean): T;
|
|
289
517
|
/**
|
|
290
|
-
* Creates
|
|
291
|
-
* @param
|
|
292
|
-
* @
|
|
518
|
+
* Creates a new `Fields` (leaf) container at the specified path.
|
|
519
|
+
* @param {PathType} path - The path where the new `Fields` container should be created.
|
|
520
|
+
* @param {boolean} [createPath=false] - If `true`, any missing parent branches in the path will be created automatically.
|
|
521
|
+
* @returns {Fields} The newly created `Fields` instance.
|
|
522
|
+
* @throws If the path is invalid or a node already exists at the target location.
|
|
293
523
|
*/
|
|
294
|
-
createFields(
|
|
524
|
+
createFields<T extends Fields>(path: PathType, createPath?: boolean): T;
|
|
295
525
|
/**
|
|
296
|
-
*
|
|
297
|
-
* @param
|
|
298
|
-
* @returns The
|
|
526
|
+
* Retrieves a `FieldTree` (branch) node from a specified path.
|
|
527
|
+
* @param {PathType} path - The path to the `FieldTree` node.
|
|
528
|
+
* @returns {FieldTree} The `FieldTree` instance at the specified path.
|
|
529
|
+
* @throws If the path is invalid or the node at the path is not a `FieldTree`.
|
|
299
530
|
*/
|
|
300
|
-
|
|
531
|
+
getFieldTree(path: PathType): FieldTree;
|
|
301
532
|
/**
|
|
302
|
-
*
|
|
303
|
-
* @param path The path to the `Fields` container
|
|
304
|
-
* @returns The `Fields`
|
|
305
|
-
* @throws If the path is
|
|
533
|
+
* Retrieves a `Fields` (leaf) container from a specified path.
|
|
534
|
+
* @param {PathType} path - The path to the `Fields` container.
|
|
535
|
+
* @returns {Fields} The `Fields` instance at the specified path.
|
|
536
|
+
* @throws If the path is invalid or the node at the path is not a `Fields` container.
|
|
306
537
|
*/
|
|
307
|
-
|
|
538
|
+
getFields(path: PathType): Fields;
|
|
308
539
|
/**
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
* @
|
|
312
|
-
* @param initialValue The initial value for the new field.
|
|
313
|
-
* @returns The newly created `Field` instance.
|
|
540
|
+
* Retrieves a `FieldTree` at the specified path. If it or any part of the path doesn't exist, it will be created.
|
|
541
|
+
* @param {PathType} path - The path to the `FieldTree` node.
|
|
542
|
+
* @returns {FieldTree} The existing or newly created `FieldTree` instance.
|
|
314
543
|
*/
|
|
315
|
-
|
|
544
|
+
getOrCreateFieldTree(path: PathType): FieldTree;
|
|
316
545
|
/**
|
|
317
|
-
*
|
|
318
|
-
* @param path The
|
|
319
|
-
* @
|
|
320
|
-
* @returns The newly created `NumberField` instance.
|
|
546
|
+
* Retrieves a `Fields` container at the specified path. If it or any part of the path doesn't exist, it will be created.
|
|
547
|
+
* @param {PathType} path - The path to the `Fields` container.
|
|
548
|
+
* @returns {Fields} The existing or newly created `Fields` instance.
|
|
321
549
|
*/
|
|
322
|
-
|
|
550
|
+
getOrCreateFields(path: PathType): Fields;
|
|
323
551
|
/**
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
552
|
+
* @private
|
|
553
|
+
* Navigates the tree to the parent of a target node.
|
|
554
|
+
* This is the core traversal logic for all path-based operations.
|
|
555
|
+
* @param {PathType} path - The full path to the target node.
|
|
556
|
+
* @param {boolean} [createPath=false] - If `true`, creates missing `FieldTree` branches along the path.
|
|
557
|
+
* @returns {{branch: FieldTree, leafName: string}} An object containing the final branch (parent node) and the name of the leaf (target node).
|
|
558
|
+
* @throws If the path is empty, invalid, or contains a `Fields` container as an intermediate segment.
|
|
559
|
+
*/
|
|
560
|
+
private traversePath;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Defines the contract for a handler that can serialize and deserialize a specific type of Policy.
|
|
565
|
+
* @template T - The specific Policy class this handler manages.
|
|
566
|
+
* @template S - The shape of the plain object this handler produces/consumes.
|
|
567
|
+
*/
|
|
568
|
+
interface PolicySerializerHandler<T extends Policy<any>, S extends object> {
|
|
569
|
+
/**
|
|
570
|
+
* Converts a Policy instance into a serializable plain object.
|
|
571
|
+
* @param policy The Policy instance to serialize.
|
|
572
|
+
* @returns A plain object representing the policy's state.
|
|
327
573
|
*/
|
|
328
|
-
|
|
574
|
+
snapshot(policy: T): S;
|
|
329
575
|
/**
|
|
330
|
-
*
|
|
331
|
-
* @param
|
|
332
|
-
* @returns
|
|
576
|
+
* Creates a new Policy instance from a plain object.
|
|
577
|
+
* @param snapshotData The plain object containing the policy's state.
|
|
578
|
+
* @returns A new instance of the Policy.
|
|
333
579
|
*/
|
|
334
|
-
|
|
580
|
+
hydrate(snapshotData: S): T;
|
|
581
|
+
}
|
|
582
|
+
declare class PolicySerializer {
|
|
583
|
+
private readonly handlers;
|
|
584
|
+
register(policyId: string, handler: PolicySerializerHandler<any, any>): this;
|
|
585
|
+
clearHandlers(): void;
|
|
586
|
+
/**
|
|
587
|
+
* Creates a serializable snapshot of a policy instance.
|
|
588
|
+
* The snapshot includes the policy's state and a `__type` identifier.
|
|
589
|
+
* @param policy The policy instance to snapshot.
|
|
590
|
+
* @returns A plain object ready for JSON serialization.
|
|
591
|
+
* @throws If no handler is registered for the policy's ID.
|
|
592
|
+
*/
|
|
593
|
+
snapshot(policy: Policy<any>): object;
|
|
594
|
+
/**
|
|
595
|
+
* Restores a policy instance from its snapshot representation.
|
|
596
|
+
* @param snapshot The plain object snapshot, which must contain a `__type` property.
|
|
597
|
+
* @returns A new, fully functional policy instance.
|
|
598
|
+
* @throws If the snapshot is invalid or no handler is registered for its `__type`.
|
|
599
|
+
*/
|
|
600
|
+
hydrate(snapshot: any): Policy<any>;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
declare class ClampPolicySerializerHandler implements PolicySerializerHandler<ClampPolicy, {
|
|
604
|
+
min: number;
|
|
605
|
+
max: number;
|
|
606
|
+
}> {
|
|
607
|
+
snapshot(policy: ClampPolicy): {
|
|
608
|
+
min: number;
|
|
609
|
+
max: number;
|
|
610
|
+
};
|
|
611
|
+
hydrate(data: {
|
|
612
|
+
min: number;
|
|
613
|
+
max: number;
|
|
614
|
+
}): ClampPolicy;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
declare class ClampMaxPolicySerializerHandler implements PolicySerializerHandler<ClampMaxPolicy, {
|
|
618
|
+
max: number;
|
|
619
|
+
}> {
|
|
620
|
+
snapshot(policy: ClampMaxPolicy): {
|
|
621
|
+
max: number;
|
|
622
|
+
};
|
|
623
|
+
hydrate(data: {
|
|
624
|
+
max: number;
|
|
625
|
+
}): ClampMaxPolicy;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
declare class ClampMinPolicySerializerHandler implements PolicySerializerHandler<ClampMinPolicy, {
|
|
629
|
+
min: number;
|
|
630
|
+
}> {
|
|
631
|
+
snapshot(policy: ClampMinPolicy): {
|
|
632
|
+
min: number;
|
|
633
|
+
};
|
|
634
|
+
hydrate(data: {
|
|
635
|
+
min: number;
|
|
636
|
+
}): ClampMinPolicy;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* A plain object representation of a Field's state for serialization.
|
|
641
|
+
*/
|
|
642
|
+
interface FieldSnapshot {
|
|
643
|
+
__type: string;
|
|
644
|
+
name: string;
|
|
645
|
+
value: any;
|
|
646
|
+
policies?: object[];
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Orchestrates the serialization and deserialization of Field instances.
|
|
650
|
+
*
|
|
651
|
+
* This class acts as a central point for converting complex Field objects into
|
|
652
|
+
* plain, storable data (snapshots) and vice-versa. It uses a `FieldRegistry`
|
|
653
|
+
* to resolve class constructors and a `PolicySerializer` to handle the state
|
|
654
|
+
* of any attached policies.
|
|
655
|
+
*
|
|
656
|
+
* @todo Implement a `patch(field, snapshot)` method.
|
|
657
|
+
* Unlike `hydrate`, which creates a new
|
|
658
|
+
* instance, `patch` should update the state of an *existing* field instance
|
|
659
|
+
* without breaking external references to it.
|
|
660
|
+
*/
|
|
661
|
+
declare class FieldSerializer {
|
|
662
|
+
private readonly fieldRegistry;
|
|
663
|
+
private readonly policySerializer;
|
|
664
|
+
/**
|
|
665
|
+
* Creates an instance of FieldSerializer.
|
|
666
|
+
* @param {FieldRegistry} fieldRegistry - A registry that maps string type names to Field constructors.
|
|
667
|
+
* @param {PolicySerializer} policySerializer - A serializer dedicated to handling Policy instances.
|
|
668
|
+
*/
|
|
669
|
+
constructor(fieldRegistry: FieldRegistry, policySerializer: PolicySerializer);
|
|
670
|
+
/**
|
|
671
|
+
* Creates a serializable snapshot of a Field instance.
|
|
672
|
+
* The snapshot includes the field's type, name, current value, and the state of all its policies.
|
|
673
|
+
* @param {Field<any>} field - The Field instance to serialize.
|
|
674
|
+
* @returns {FieldSnapshot} A plain object ready for JSON serialization.
|
|
675
|
+
*/
|
|
676
|
+
snapshot(field: Field<any>): FieldSnapshot;
|
|
677
|
+
/**
|
|
678
|
+
* Restores a Field instance from its snapshot representation.
|
|
679
|
+
* It uses the `__type` property to find the correct constructor and hydrates
|
|
680
|
+
* the field with its value and all its policies.
|
|
681
|
+
* @param {FieldSnapshot} snapshot - The plain object snapshot to deserialize.
|
|
682
|
+
* @returns {Field<any>} A new, fully functional Field instance.
|
|
683
|
+
* @throws If the snapshot is invalid, missing a `__type`, or if the type is not registered.
|
|
684
|
+
*/
|
|
685
|
+
hydrate(snapshot: FieldSnapshot): Field<any>;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* A plain object representation of a Fields container's state for serialization.
|
|
690
|
+
*/
|
|
691
|
+
interface FieldsSnapshot {
|
|
692
|
+
__type: string;
|
|
693
|
+
[fieldName: string]: FieldSnapshot | string;
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Orchestrates the serialization and deserialization of `Fields` container instances.
|
|
697
|
+
*
|
|
698
|
+
* This class acts as a high-level composer, responsible for converting an entire `Fields` object
|
|
699
|
+
* into a storable snapshot and back.
|
|
700
|
+
* It delegates the actual serialization of each `Field` and `Policy` to their respective serializers.
|
|
701
|
+
*
|
|
702
|
+
* @todo This implementation is coupled to creating `DefaultFields` instances during hydration.
|
|
703
|
+
* To make the system fully extensible, this class should be refactored to use a
|
|
704
|
+
* `FieldsRegistry` (a `ConstructorRegistry<Fields>`). This would allow it to
|
|
705
|
+
* hydrate any custom `Fields` class (e.g., `ReactiveFields`) based on the `__type`
|
|
706
|
+
* property in the snapshot, mirroring the pattern used by `FieldSerializer`.
|
|
707
|
+
*
|
|
708
|
+
* @todo Implement a `patch(fields, snapshot)` method. It should perform a non-destructive
|
|
709
|
+
* update, creating new fields, removing missing ones, and patching existing ones
|
|
710
|
+
* in place, preserving the container instance itself.
|
|
711
|
+
*/
|
|
712
|
+
declare class FieldsSerializer {
|
|
713
|
+
private readonly fieldRegistry;
|
|
714
|
+
private readonly policySerializer;
|
|
715
|
+
/**
|
|
716
|
+
* An internal instance of FieldSerializer to handle individual fields.
|
|
717
|
+
* @private
|
|
718
|
+
*/
|
|
719
|
+
private readonly fieldSerializer;
|
|
720
|
+
/**
|
|
721
|
+
* Creates an instance of FieldsSerializer.
|
|
722
|
+
* @param {FieldRegistry} fieldRegistry - A registry that maps string type names to Field constructors.
|
|
723
|
+
* @param {PolicySerializer} policySerializer - A serializer dedicated to handling Policy instances.
|
|
724
|
+
*/
|
|
725
|
+
constructor(fieldRegistry: FieldRegistry, policySerializer: PolicySerializer);
|
|
726
|
+
/**
|
|
727
|
+
* Creates a serializable snapshot of a `Fields` container.
|
|
728
|
+
*
|
|
729
|
+
* The snapshot includes a `__type` identifier (currently hardcoded) and an array of snapshots
|
|
730
|
+
* for each `Field` within the container.
|
|
731
|
+
* @param {Fields} fields - The `Fields` instance to serialize.
|
|
732
|
+
* @returns {FieldsSnapshot} A plain object ready for JSON serialization.
|
|
733
|
+
*/
|
|
734
|
+
snapshot(fields: Fields): FieldsSnapshot;
|
|
735
|
+
/**
|
|
736
|
+
* Restores a `Fields` container instance from its snapshot representation.
|
|
737
|
+
*
|
|
738
|
+
* **Limitation:** This method is currently hardcoded to always create an instance of `DefaultFields`.
|
|
739
|
+
* It iterates through the field snapshots and hydrates them individually, adding them to the new container.
|
|
740
|
+
* @param {FieldsSnapshot} snapshot - The plain object snapshot to deserialize.
|
|
741
|
+
* @returns {DefaultFields} A new `DefaultFields` instance populated with the restored fields.
|
|
742
|
+
*/
|
|
743
|
+
hydrate(snapshot: FieldsSnapshot): DefaultFields;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* Represents the serializable state of a `FieldTree` container.
|
|
748
|
+
*
|
|
749
|
+
* This type describes a plain object that has:
|
|
750
|
+
* 1. A required `__type` property to identify the tree's class.
|
|
751
|
+
* 2. An arbitrary number of other properties, where each key is the `name`
|
|
752
|
+
* of a child node, and the value is the snapshot of that child node.
|
|
753
|
+
* The `| string` is included to ensure compatibility with the `__type` property.
|
|
754
|
+
*/
|
|
755
|
+
interface FieldTreeSnapshot {
|
|
756
|
+
__type: string;
|
|
757
|
+
[fieldName: string]: FieldsSnapshot | FieldTreeSnapshot | string;
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Orchestrates the recursive serialization and deserialization of `FieldTree` instances.
|
|
761
|
+
*
|
|
762
|
+
* This class handles the conversion of an entire `FieldTree` object graph into a
|
|
763
|
+
* plain, storable snapshot and vice-versa. It delegates the processing of `Fields`
|
|
764
|
+
* leaf nodes to a dedicated `FieldsSerializer`.
|
|
765
|
+
* @todo Refactoring: The current implementation uses `if/else` logic in `snapshot` and `hydrate`
|
|
766
|
+
* to process different node types. A more extensible approach would be to use a
|
|
767
|
+
* registry of dedicated handlers for each node type.
|
|
768
|
+
* This would allow new node types to be supported without
|
|
769
|
+
* modifying this class, adhering to the Open/Closed Principle.
|
|
770
|
+
*
|
|
771
|
+
* @todo Implement a `patch(tree, snapshot)` method for recursive, non-destructive
|
|
772
|
+
* updates. This method should traverse the existing tree and the snapshot,
|
|
773
|
+
* patching nodes in place to maintain object references.
|
|
774
|
+
*/
|
|
775
|
+
declare class FieldTreeSerializer {
|
|
776
|
+
private readonly fieldTreeNodeFactory;
|
|
777
|
+
private readonly fieldsSerializer;
|
|
778
|
+
constructor(fieldTreeNodeFactory: TreeNodeFactory, fieldsSerializer: FieldsSerializer);
|
|
335
779
|
/**
|
|
336
780
|
* Creates a serializable snapshot of the entire tree and its contained fields.
|
|
337
781
|
* @returns A plain JavaScript object representing the complete state managed by this tree.
|
|
338
782
|
*/
|
|
339
|
-
snapshot():
|
|
783
|
+
snapshot(tree: FieldTree): FieldTreeSnapshot;
|
|
340
784
|
/**
|
|
341
785
|
* Restores the state of the tree from a snapshot.
|
|
342
786
|
* It intelligently creates missing nodes based on `__type` metadata and delegates hydration to child nodes.
|
|
343
787
|
* @param snapshot The snapshot object to load.
|
|
344
788
|
*/
|
|
345
|
-
hydrate(snapshot:
|
|
346
|
-
/**
|
|
347
|
-
* @private
|
|
348
|
-
* Generic internal method for creating and adding a new node to the tree.
|
|
349
|
-
* @param name The name of the node to create.
|
|
350
|
-
* @param ctor The constructor for the node type (e.g., `FieldTree` or `Fields`).
|
|
351
|
-
* @returns The newly created node instance.
|
|
352
|
-
*/
|
|
353
|
-
private createNode;
|
|
789
|
+
hydrate(snapshot: FieldTreeSnapshot): FieldTree;
|
|
354
790
|
}
|
|
355
791
|
|
|
356
|
-
export {
|
|
792
|
+
export { type BooleanField, ClampMaxPolicy, ClampMaxPolicySerializerHandler, ClampMinPolicy, ClampMinPolicySerializerHandler, ClampPolicy, ClampPolicySerializerHandler, DefaultBooleanField, type DefaultBooleanFieldOptions, DefaultField, DefaultFields, DefaultNumericField, type DefaultNumericFieldOptions, DefaultStringField, type DefaultStringFieldOptions, DefaultTreeNodeFactory, type Field, type FieldOptions, FieldRegistry, FieldSerializer, type FieldSnapshot, FieldTree, FieldTreeSerializer, type FieldTreeSnapshot, Fields, FieldsSerializer, type FieldsSnapshot, type NumericField, Policies, type Policy, PolicySerializer, type PolicySerializerHandler, type StringField, type TreeNodeFactory, type TreeOrFieldsNode, clampMaxPolicy, clampMinPolicy, clampPolicy };
|