@axi-engine/fields 0.2.2 → 0.3.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/dist/index.mjs CHANGED
@@ -117,13 +117,38 @@ var Policies = class {
117
117
  }
118
118
  };
119
119
 
120
- // src/field-definitions/default-field.ts
120
+ // src/mixins/mixin-factory.ts
121
+ function createTypedMethodsMixin(typeName, baseMethodName) {
122
+ const methodNames = {
123
+ create: `create${baseMethodName}`,
124
+ upset: `upset${baseMethodName}`,
125
+ get: `get${baseMethodName}`
126
+ };
127
+ return function(Base) {
128
+ return class FieldsWith extends Base {
129
+ // createBoolean, createMySignal, etc.
130
+ [methodNames.create](name, initialValue, options) {
131
+ return this.create(typeName, name, initialValue, options);
132
+ }
133
+ // upsetBoolean, upsetMySignal, etc.
134
+ [methodNames.upset](name, value, options) {
135
+ return this.upset(typeName, name, value, options);
136
+ }
137
+ // getBoolean, getMySignal, etc.
138
+ [methodNames.get](name) {
139
+ return this.get(name);
140
+ }
141
+ };
142
+ };
143
+ }
144
+
145
+ // src/field-definitions/core-field.ts
121
146
  import { Emitter } from "@axi-engine/utils";
122
147
  import { dequal } from "dequal";
123
- var DefaultField = class _DefaultField {
148
+ var CoreField = class _CoreField {
124
149
  /** A type keyword of the field */
125
150
  static typeName = "default";
126
- typeName = _DefaultField.typeName;
151
+ typeName = _CoreField.typeName;
127
152
  /** A unique identifier for the field. */
128
153
  _name;
129
154
  _value;
@@ -184,10 +209,10 @@ var DefaultField = class _DefaultField {
184
209
  }
185
210
  };
186
211
 
187
- // src/field-definitions/default-boolean-field.ts
188
- var DefaultBooleanField = class _DefaultBooleanField extends DefaultField {
212
+ // src/field-definitions/core-boolean-field.ts
213
+ var CoreBooleanField = class _CoreBooleanField extends CoreField {
189
214
  static typeName = "boolean";
190
- typeName = _DefaultBooleanField.typeName;
215
+ typeName = _CoreBooleanField.typeName;
191
216
  constructor(name, initialVal, options) {
192
217
  super(name, initialVal, options);
193
218
  }
@@ -197,10 +222,10 @@ var DefaultBooleanField = class _DefaultBooleanField extends DefaultField {
197
222
  }
198
223
  };
199
224
 
200
- // src/field-definitions/default-string-field.ts
201
- var DefaultStringField = class _DefaultStringField extends DefaultField {
225
+ // src/field-definitions/core-string-field.ts
226
+ var CoreStringField = class _CoreStringField extends CoreField {
202
227
  static typeName = "string";
203
- typeName = _DefaultStringField.typeName;
228
+ typeName = _CoreStringField.typeName;
204
229
  constructor(name, initialVal, options) {
205
230
  super(name, initialVal, options);
206
231
  }
@@ -224,11 +249,11 @@ var DefaultStringField = class _DefaultStringField extends DefaultField {
224
249
  }
225
250
  };
226
251
 
227
- // src/field-definitions/default-numeric-field.ts
252
+ // src/field-definitions/core-numeric-field.ts
228
253
  import { isNullOrUndefined } from "@axi-engine/utils";
229
- var DefaultNumericField = class _DefaultNumericField extends DefaultField {
254
+ var CoreNumericField = class _CoreNumericField extends CoreField {
230
255
  static typeName = "numeric";
231
- typeName = _DefaultNumericField.typeName;
256
+ typeName = _CoreNumericField.typeName;
232
257
  get min() {
233
258
  const policy = this.policies.get(ClampPolicy.id) ?? this.policies.get(ClampMinPolicy.id);
234
259
  return policy?.min;
@@ -408,9 +433,9 @@ var Fields = class _Fields {
408
433
  }
409
434
  /**
410
435
  * Retrieves a field by its name.
411
- * @template T - The expected `Field` type to be returned.
436
+ * @template TField - The expected `Field` type to be returned.
412
437
  * @param {string} name - The name of the field to retrieve.
413
- * @returns {T} The `Field` instance.
438
+ * @returns {TField} The `Field` instance.
414
439
  * @throws If the field does not exist.
415
440
  */
416
441
  get(name) {
@@ -450,70 +475,6 @@ var Fields = class _Fields {
450
475
  }
451
476
  };
452
477
 
453
- // src/mixins/with-boolean-fields.mixin.ts
454
- function WithBooleanFields(Base) {
455
- return class FieldsWithBoolean extends Base {
456
- createBoolean(name, initialValue, options) {
457
- return this.create(DefaultBooleanField.typeName, name, initialValue, options);
458
- }
459
- upsetBoolean(name, value, options) {
460
- return this.upset(DefaultBooleanField.typeName, name, value, options);
461
- }
462
- getBoolean(name) {
463
- return this.get(name);
464
- }
465
- };
466
- }
467
-
468
- // src/mixins/with-string-fields.mixin.ts
469
- function WithStringFields(Base) {
470
- return class FieldsWithString extends Base {
471
- createString(name, initialValue, options) {
472
- return this.create(DefaultStringField.typeName, name, initialValue, options);
473
- }
474
- upsetString(name, value, options) {
475
- return this.upset(DefaultStringField.typeName, name, value, options);
476
- }
477
- getString(name) {
478
- return this.get(name);
479
- }
480
- };
481
- }
482
-
483
- // src/mixins/with-numeric-fields.mixin.ts
484
- function WithNumericFields(Base) {
485
- return class FieldsWithNumeric extends Base {
486
- createNumeric(name, initialValue, options) {
487
- return this.create(DefaultNumericField.typeName, name, initialValue, options);
488
- }
489
- upsetNumeric(name, value, options) {
490
- return this.upset(DefaultNumericField.typeName, name, value, options);
491
- }
492
- getNumeric(name) {
493
- return this.get(name);
494
- }
495
- };
496
- }
497
-
498
- // src/mixins/with-default-generic-fields.mixin.ts
499
- function WithDefaultGenericFields(Base) {
500
- return class FieldsWithDefaultGeneric extends Base {
501
- createGeneric(name, initialValue, options) {
502
- return this.create(DefaultField.typeName, name, initialValue, options);
503
- }
504
- upsetGeneric(name, value, options) {
505
- return this.upset(DefaultField.typeName, name, value, options);
506
- }
507
- getGeneric(name) {
508
- return this.get(name);
509
- }
510
- };
511
- }
512
-
513
- // src/default-fields.ts
514
- var DefaultFields = class extends WithBooleanFields(WithStringFields(WithNumericFields(WithDefaultGenericFields(Fields)))) {
515
- };
516
-
517
478
  // src/field-tree.ts
518
479
  import { Emitter as Emitter3, ensurePathArray, ensurePathString, throwIf as throwIf3, throwIfEmpty as throwIfEmpty2 } from "@axi-engine/utils";
519
480
  var FieldTree = class _FieldTree {
@@ -554,7 +515,7 @@ var FieldTree = class _FieldTree {
554
515
  }
555
516
  /**
556
517
  * Creates an instance of FieldTree.
557
- * @param {TreeNodeFactory} factory - A factory responsible for creating new nodes within the tree.
518
+ * @param {FieldTreeFactory} factory - A factory responsible for creating new nodes within the tree.
558
519
  */
559
520
  constructor(factory) {
560
521
  this._factory = factory;
@@ -693,6 +654,16 @@ var FieldTree = class _FieldTree {
693
654
  const traversedPath = this.traversePath(path, true);
694
655
  return traversedPath.branch.has(traversedPath.leafName) ? traversedPath.branch.getFields(traversedPath.leafName) : traversedPath.branch.createFields(traversedPath.leafName);
695
656
  }
657
+ /**
658
+ * Finds the parent node for a given path.
659
+ * @param path The path to the target node.
660
+ * @returns The parent node (either a FieldTree or Fields).
661
+ * @throws An error if the path is invalid or any intermediate node is not a FieldTree.
662
+ */
663
+ findParentNode(path) {
664
+ const info = this.traversePath(path);
665
+ return info.branch;
666
+ }
696
667
  /**
697
668
  * Removes all child nodes from this tree branch.
698
669
  * This method ensures that `destroy()` is called on each child node, allowing for
@@ -744,21 +715,59 @@ var FieldTree = class _FieldTree {
744
715
  }
745
716
  };
746
717
 
747
- // src/field-tree-node-factory.ts
748
- var DefaultFieldsFactory = class {
718
+ // src/mixins/with-boolean-fields.mixin.ts
719
+ var WithBooleanFields = createTypedMethodsMixin(CoreBooleanField.typeName, "Boolean");
720
+
721
+ // src/mixins/with-string-fields.mixin.ts
722
+ var WithStringFields = createTypedMethodsMixin(CoreBooleanField.typeName, "String");
723
+
724
+ // src/mixins/with-numeric-fields.mixin.ts
725
+ var WithNumericFields = createTypedMethodsMixin(CoreBooleanField.typeName, "Numeric");
726
+
727
+ // src/mixins/with-default-generic-fields.mixin.ts
728
+ function WithDefaultGenericFields(Base) {
729
+ return class FieldsWithDefaultGeneric extends Base {
730
+ createGeneric(name, initialValue, options) {
731
+ return this.create(CoreField.typeName, name, initialValue, options);
732
+ }
733
+ upsetGeneric(name, value, options) {
734
+ return this.upset(CoreField.typeName, name, value, options);
735
+ }
736
+ getGeneric(name) {
737
+ return this.get(name);
738
+ }
739
+ };
740
+ }
741
+
742
+ // src/core-fields.ts
743
+ var CoreFields = class extends WithBooleanFields(WithStringFields(WithNumericFields(WithDefaultGenericFields(Fields)))) {
744
+ };
745
+
746
+ // src/core-fields-factory.ts
747
+ var CoreFieldsFactory = class {
748
+ _fieldRegistry;
749
+ get fieldRegistry() {
750
+ return this._fieldRegistry;
751
+ }
749
752
  constructor(fieldRegistry) {
750
- this.fieldRegistry = fieldRegistry;
753
+ this._fieldRegistry = fieldRegistry;
751
754
  }
752
755
  fields() {
753
- return new DefaultFields(this.fieldRegistry);
756
+ return new CoreFields(this._fieldRegistry);
754
757
  }
755
758
  };
756
- var DefaultTreeNodeFactory = class extends DefaultFieldsFactory {
759
+
760
+ // src/core-field-tree.ts
761
+ var CoreFieldTree = class extends FieldTree {
762
+ };
763
+
764
+ // src/core-field-tree-factory.ts
765
+ var CoreTreeNodeFactory = class extends CoreFieldsFactory {
757
766
  constructor(fieldRegistry) {
758
767
  super(fieldRegistry);
759
768
  }
760
769
  tree() {
761
- return new FieldTree(this);
770
+ return new CoreFieldTree(this);
762
771
  }
763
772
  };
764
773
 
@@ -979,6 +988,196 @@ var FieldTreeSerializer = class {
979
988
  return tree;
980
989
  }
981
990
  };
991
+
992
+ // src/data-store-field-resolver.ts
993
+ import { isBoolean, isNumber, isString as isString2 } from "@axi-engine/utils";
994
+ var NumericFieldResolver = class {
995
+ typeName = CoreNumericField.typeName;
996
+ supports(value) {
997
+ return isNumber(value);
998
+ }
999
+ };
1000
+ var BooleanFieldResolver = class {
1001
+ typeName = CoreBooleanField.typeName;
1002
+ supports(value) {
1003
+ return isBoolean(value);
1004
+ }
1005
+ };
1006
+ var StringFieldResolver = class {
1007
+ typeName = CoreStringField.typeName;
1008
+ supports(value) {
1009
+ return isString2(value);
1010
+ }
1011
+ };
1012
+
1013
+ // src/data-store.ts
1014
+ import { ensurePathArray as ensurePathArray2, ensurePathString as ensurePathString2, throwIfEmpty as throwIfEmpty5 } from "@axi-engine/utils";
1015
+ var DataStore = class {
1016
+ constructor(tree) {
1017
+ this.tree = tree;
1018
+ this.registerResolver(new NumericFieldResolver());
1019
+ this.registerResolver(new BooleanFieldResolver());
1020
+ this.registerResolver(new StringFieldResolver());
1021
+ }
1022
+ resolvers = [];
1023
+ rootFieldsName = "__root_fields";
1024
+ _rootFields;
1025
+ get rootFields() {
1026
+ if (!this._rootFields) {
1027
+ this._rootFields = this.tree.getOrCreateFields(this.rootFieldsName);
1028
+ }
1029
+ return this._rootFields;
1030
+ }
1031
+ registerResolver(resolver) {
1032
+ this.resolvers.unshift(resolver);
1033
+ }
1034
+ clearResolvers() {
1035
+ this.resolvers.length = 0;
1036
+ }
1037
+ getValue(path) {
1038
+ return this.getField(path).value;
1039
+ }
1040
+ setValue(path, val) {
1041
+ const field = this.getField(path);
1042
+ field.value = val;
1043
+ return field.value;
1044
+ }
1045
+ createValue(path, val, options) {
1046
+ const dest = this.getDestinationFields(path);
1047
+ if (options?.fieldType) {
1048
+ return dest.fields.create(options.fieldType, dest.leafName, val, options).value;
1049
+ }
1050
+ for (let resolver of this.resolvers) {
1051
+ if (resolver.supports(val)) {
1052
+ return dest.fields.create(resolver.typeName, dest.leafName, val, options).value;
1053
+ }
1054
+ }
1055
+ return dest.fields.createGeneric(dest.leafName, val, options).value;
1056
+ }
1057
+ upsetValue(path, val, options) {
1058
+ const dest = this.getDestinationFields(path);
1059
+ if (options?.fieldType) {
1060
+ return dest.fields.upset(options.fieldType, dest.leafName, val, options).value;
1061
+ }
1062
+ for (let resolver of this.resolvers) {
1063
+ if (resolver.supports(val)) {
1064
+ return dest.fields.upset(resolver.typeName, dest.leafName, val, options).value;
1065
+ }
1066
+ }
1067
+ return dest.fields.upsetGeneric(dest.leafName, val, options).value;
1068
+ }
1069
+ createBoolean(path, initialValue, options) {
1070
+ const dest = this.getDestinationFields(path);
1071
+ return dest.fields.createBoolean(dest.leafName, initialValue, options);
1072
+ }
1073
+ createNumeric(path, initialValue, options) {
1074
+ const dest = this.getDestinationFields(path);
1075
+ return dest.fields.createNumeric(dest.leafName, initialValue, options);
1076
+ }
1077
+ createString(path, initialValue, options) {
1078
+ const dest = this.getDestinationFields(path);
1079
+ return dest.fields.createString(dest.leafName, initialValue, options);
1080
+ }
1081
+ createGeneric(path, initialValue, options) {
1082
+ const dest = this.getDestinationFields(path);
1083
+ return dest.fields.createGeneric(dest.leafName, initialValue, options);
1084
+ }
1085
+ getBoolean(path) {
1086
+ return this.getField(path);
1087
+ }
1088
+ getNumeric(path) {
1089
+ return this.getField(path);
1090
+ }
1091
+ getString(path) {
1092
+ return this.getField(path);
1093
+ }
1094
+ getGeneric(path) {
1095
+ return this.getField(path);
1096
+ }
1097
+ getField(path) {
1098
+ const pathArr = ensurePathArray2(path);
1099
+ throwIfEmpty5(pathArr, `Wrong path or path is empty: ${ensurePathString2(path)}, should contain at least one path segment`);
1100
+ if (this.isPathToRootFields(pathArr)) {
1101
+ return this.rootFields.get(pathArr[0]);
1102
+ }
1103
+ const fieldName = pathArr.pop();
1104
+ const fields = this.tree.getFields(pathArr);
1105
+ return fields.get(fieldName);
1106
+ }
1107
+ createFields(path) {
1108
+ return this.tree.createFields(path, true);
1109
+ }
1110
+ createTree(path) {
1111
+ return this.tree.createFieldTree(path, true);
1112
+ }
1113
+ getFields(path) {
1114
+ return this.tree.getFields(path);
1115
+ }
1116
+ getTree(path) {
1117
+ return this.tree.getFieldTree(path);
1118
+ }
1119
+ remove(path) {
1120
+ const pathArr = ensurePathArray2(path);
1121
+ throwIfEmpty5(pathArr, `Wrong path or path is empty: ${ensurePathString2(path)}, should contain at least one path segment`);
1122
+ if (this.isPathToRootFields(pathArr)) {
1123
+ this.rootFields.remove(pathArr);
1124
+ return;
1125
+ }
1126
+ const node = this.tree.findParentNode(pathArr);
1127
+ const leafName = pathArr[pathArr.length - 1];
1128
+ if (node instanceof CoreFields) {
1129
+ node.remove(leafName);
1130
+ } else if (node instanceof CoreFieldTree) {
1131
+ node.removeNode(leafName);
1132
+ }
1133
+ }
1134
+ isPathToRootFields(path) {
1135
+ return ensurePathArray2(path).length === 1;
1136
+ }
1137
+ getDestinationFields(path) {
1138
+ const pathArr = ensurePathArray2(path);
1139
+ if (this.isPathToRootFields(pathArr)) {
1140
+ return { fields: this.rootFields, leafName: pathArr[0] };
1141
+ }
1142
+ const leafName = pathArr.pop();
1143
+ return { fields: this.tree.getOrCreateFields(path), leafName };
1144
+ }
1145
+ };
1146
+
1147
+ // src/setup.ts
1148
+ function createCoreFieldRegistry() {
1149
+ const fieldRegistry = new FieldRegistry();
1150
+ fieldRegistry.register(CoreField.typeName, CoreField);
1151
+ fieldRegistry.register(CoreNumericField.typeName, CoreNumericField);
1152
+ fieldRegistry.register(CoreStringField.typeName, CoreStringField);
1153
+ fieldRegistry.register(CoreBooleanField.typeName, CoreBooleanField);
1154
+ return fieldRegistry;
1155
+ }
1156
+ function createCorePolicySerializer() {
1157
+ const policySerializer = new PolicySerializer();
1158
+ policySerializer.register(ClampPolicy.id, new ClampPolicySerializerHandler());
1159
+ policySerializer.register(ClampMinPolicy.id, new ClampMinPolicySerializerHandler());
1160
+ policySerializer.register(ClampMaxPolicy.id, new ClampMaxPolicySerializerHandler());
1161
+ return policySerializer;
1162
+ }
1163
+ function createCoreTreeNodeFactory(fieldRegistry) {
1164
+ return new CoreTreeNodeFactory(fieldRegistry);
1165
+ }
1166
+ function createCoreTreeSerializer(fieldTreeNodeFactory, policySerializer) {
1167
+ return new FieldTreeSerializer(
1168
+ fieldTreeNodeFactory,
1169
+ new FieldsSerializer(
1170
+ fieldTreeNodeFactory,
1171
+ new FieldSerializer(fieldTreeNodeFactory.fieldRegistry, policySerializer ?? createCorePolicySerializer())
1172
+ )
1173
+ );
1174
+ }
1175
+ function createCoreFieldSystem(config) {
1176
+ const registry = config?.registry ?? createCoreFieldRegistry();
1177
+ const factory = createCoreTreeNodeFactory(registry);
1178
+ const serializer = createCoreTreeSerializer(factory, config?.policySerializer);
1179
+ return { factory, serializer };
1180
+ }
982
1181
  export {
983
1182
  ClampMaxPolicy,
984
1183
  ClampMaxPolicySerializerHandler,
@@ -986,13 +1185,15 @@ export {
986
1185
  ClampMinPolicySerializerHandler,
987
1186
  ClampPolicy,
988
1187
  ClampPolicySerializerHandler,
989
- DefaultBooleanField,
990
- DefaultField,
991
- DefaultFields,
992
- DefaultFieldsFactory,
993
- DefaultNumericField,
994
- DefaultStringField,
995
- DefaultTreeNodeFactory,
1188
+ CoreBooleanField,
1189
+ CoreField,
1190
+ CoreFieldTree,
1191
+ CoreFields,
1192
+ CoreFieldsFactory,
1193
+ CoreNumericField,
1194
+ CoreStringField,
1195
+ CoreTreeNodeFactory,
1196
+ DataStore,
996
1197
  FieldRegistry,
997
1198
  FieldSerializer,
998
1199
  FieldTree,
@@ -1003,5 +1204,11 @@ export {
1003
1204
  PolicySerializer,
1004
1205
  clampMaxPolicy,
1005
1206
  clampMinPolicy,
1006
- clampPolicy
1207
+ clampPolicy,
1208
+ createCoreFieldRegistry,
1209
+ createCoreFieldSystem,
1210
+ createCorePolicySerializer,
1211
+ createCoreTreeNodeFactory,
1212
+ createCoreTreeSerializer,
1213
+ createTypedMethodsMixin
1007
1214
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axi-engine/fields",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "keywords": [