@routevn/creator-model 1.12.1 → 1.12.2

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.
Files changed (3) hide show
  1. package/README.md +34 -0
  2. package/package.json +1 -1
  3. package/src/model.js +106 -1
package/README.md CHANGED
@@ -173,6 +173,40 @@ Computed definitions may use a simple `expr` or literal `value`, or ordered
173
173
  operator grammar, result types, concrete `variables.*`/`runtime.*` paths,
174
174
  declared variable references, and an acyclic computed dependency graph.
175
175
 
176
+ Computed definitions may also store examples. Example inputs mirror the
177
+ evaluation context, while calculated results remain derived and are not
178
+ persisted:
179
+
180
+ ```js
181
+ {
182
+ computed: {
183
+ expr: {
184
+ mul: [
185
+ {
186
+ div: [
187
+ { var: "variables.hp" },
188
+ { var: "variables.maxHp" },
189
+ ],
190
+ },
191
+ 100,
192
+ ],
193
+ },
194
+ examples: [
195
+ {
196
+ id: "example-low-health",
197
+ name: "Low health",
198
+ input: {
199
+ variables: {
200
+ hp: 40,
201
+ maxHp: 80,
202
+ },
203
+ },
204
+ },
205
+ ],
206
+ },
207
+ }
208
+ ```
209
+
176
210
  ## File Structure
177
211
 
178
212
  ```text
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routevn/creator-model",
3
- "version": "1.12.1",
3
+ "version": "1.12.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/model.js CHANGED
@@ -3789,6 +3789,99 @@ const validateComputedResultConfig = ({
3789
3789
  return VALID_RESULT;
3790
3790
  };
3791
3791
 
3792
+ const validateComputedExamples = ({ examples, path, errorFactory }) => {
3793
+ if (!Array.isArray(examples)) {
3794
+ return invalidFromErrorFactory(errorFactory, `${path} must be an array`);
3795
+ }
3796
+
3797
+ const exampleIds = new Set();
3798
+ for (const [index, example] of examples.entries()) {
3799
+ const examplePath = `${path}[${index}]`;
3800
+ {
3801
+ const result = validateAllowedKeys({
3802
+ value: example,
3803
+ allowedKeys: ["id", "name", "input"],
3804
+ path: examplePath,
3805
+ errorFactory,
3806
+ });
3807
+ if (result?.valid === false) {
3808
+ return result;
3809
+ }
3810
+ }
3811
+
3812
+ if (!isNonEmptyString(example.id)) {
3813
+ return invalidFromErrorFactory(
3814
+ errorFactory,
3815
+ `${examplePath}.id must be a non-empty string`,
3816
+ );
3817
+ }
3818
+ if (exampleIds.has(example.id)) {
3819
+ return invalidFromErrorFactory(
3820
+ errorFactory,
3821
+ `${examplePath}.id must be unique within examples`,
3822
+ );
3823
+ }
3824
+ exampleIds.add(example.id);
3825
+
3826
+ if (Object.hasOwn(example, "name") && !isNonEmptyString(example.name)) {
3827
+ return invalidFromErrorFactory(
3828
+ errorFactory,
3829
+ `${examplePath}.name must be a non-empty string`,
3830
+ );
3831
+ }
3832
+
3833
+ if (!Object.hasOwn(example, "input")) {
3834
+ return invalidFromErrorFactory(
3835
+ errorFactory,
3836
+ `${examplePath}.input is required`,
3837
+ );
3838
+ }
3839
+ if (
3840
+ !isPlainObject(example.input) ||
3841
+ ![Object.prototype, null].includes(Object.getPrototypeOf(example.input))
3842
+ ) {
3843
+ return invalidFromErrorFactory(
3844
+ errorFactory,
3845
+ `${examplePath}.input must be an object`,
3846
+ );
3847
+ }
3848
+ {
3849
+ const result = validateAllowedKeys({
3850
+ value: example.input,
3851
+ allowedKeys: ["variables", "runtime"],
3852
+ path: `${examplePath}.input`,
3853
+ errorFactory,
3854
+ });
3855
+ if (result?.valid === false) {
3856
+ return result;
3857
+ }
3858
+ }
3859
+
3860
+ for (const namespace of ["variables", "runtime"]) {
3861
+ if (!Object.hasOwn(example.input, namespace)) {
3862
+ continue;
3863
+ }
3864
+ const namespacePath = `${examplePath}.input.${namespace}`;
3865
+ if (!isPlainObject(example.input[namespace])) {
3866
+ return invalidFromErrorFactory(
3867
+ errorFactory,
3868
+ `${namespacePath} must be an object`,
3869
+ );
3870
+ }
3871
+ const result = validateComputedDataValue({
3872
+ value: example.input[namespace],
3873
+ path: namespacePath,
3874
+ errorFactory,
3875
+ });
3876
+ if (result?.valid === false) {
3877
+ return result;
3878
+ }
3879
+ }
3880
+ }
3881
+
3882
+ return VALID_RESULT;
3883
+ };
3884
+
3792
3885
  const validateVariableComputedConfig = ({
3793
3886
  computed,
3794
3887
  variableType,
@@ -3801,11 +3894,22 @@ const validateVariableComputedConfig = ({
3801
3894
  return invalidFromErrorFactory(errorFactory, `${path} must be an object`);
3802
3895
  }
3803
3896
 
3897
+ if (Object.hasOwn(computed, "examples")) {
3898
+ const result = validateComputedExamples({
3899
+ examples: computed.examples,
3900
+ path: `${path}.examples`,
3901
+ errorFactory,
3902
+ });
3903
+ if (result?.valid === false) {
3904
+ return result;
3905
+ }
3906
+ }
3907
+
3804
3908
  if (Object.hasOwn(computed, "branches")) {
3805
3909
  {
3806
3910
  const result = validateAllowedKeys({
3807
3911
  value: computed,
3808
- allowedKeys: ["branches", "default"],
3912
+ allowedKeys: ["branches", "default", "examples"],
3809
3913
  path,
3810
3914
  errorFactory,
3811
3915
  });
@@ -3881,6 +3985,7 @@ const validateVariableComputedConfig = ({
3881
3985
  errorFactory,
3882
3986
  variables,
3883
3987
  dependencies,
3988
+ allowedKeys: ["expr", "value", "examples"],
3884
3989
  });
3885
3990
  };
3886
3991