@routevn/creator-model 1.12.0 → 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.
- package/README.md +38 -0
- package/package.json +1 -1
- package/src/model.js +203 -46
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
|
|
@@ -294,6 +328,10 @@ Current animation update tween properties support either:
|
|
|
294
328
|
- `keyframes`
|
|
295
329
|
- `auto: { duration, easing }`
|
|
296
330
|
|
|
331
|
+
Transition animation `mask` accepts one mask object or a non-empty ordered
|
|
332
|
+
array. Each mask may define a non-negative safe-integer `delay` in
|
|
333
|
+
milliseconds.
|
|
334
|
+
|
|
297
335
|
## Current Scope
|
|
298
336
|
|
|
299
337
|
Currently implemented command types:
|
package/package.json
CHANGED
package/src/model.js
CHANGED
|
@@ -1930,6 +1930,7 @@ const validateMaskDefinition = ({ mask, path, errorFactory }) => {
|
|
|
1930
1930
|
"softness",
|
|
1931
1931
|
"invert",
|
|
1932
1932
|
"sample",
|
|
1933
|
+
"delay",
|
|
1933
1934
|
"progress",
|
|
1934
1935
|
"progressDuration",
|
|
1935
1936
|
"progressEasing",
|
|
@@ -2108,6 +2109,16 @@ const validateMaskDefinition = ({ mask, path, errorFactory }) => {
|
|
|
2108
2109
|
);
|
|
2109
2110
|
}
|
|
2110
2111
|
|
|
2112
|
+
if (
|
|
2113
|
+
mask.delay !== undefined &&
|
|
2114
|
+
(!Number.isSafeInteger(mask.delay) || mask.delay < 0)
|
|
2115
|
+
) {
|
|
2116
|
+
return invalidFromErrorFactory(
|
|
2117
|
+
errorFactory,
|
|
2118
|
+
`${path}.delay must be a non-negative safe integer when provided`,
|
|
2119
|
+
);
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2111
2122
|
if (mask.progress !== undefined) {
|
|
2112
2123
|
{
|
|
2113
2124
|
const result = validateTweenProperty({
|
|
@@ -2171,6 +2182,30 @@ const validateMaskDefinition = ({ mask, path, errorFactory }) => {
|
|
|
2171
2182
|
}
|
|
2172
2183
|
};
|
|
2173
2184
|
|
|
2185
|
+
const validateAnimationMasks = ({ mask, path, errorFactory }) => {
|
|
2186
|
+
if (!Array.isArray(mask)) {
|
|
2187
|
+
return validateMaskDefinition({ mask, path, errorFactory });
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2190
|
+
if (mask.length === 0) {
|
|
2191
|
+
return invalidFromErrorFactory(
|
|
2192
|
+
errorFactory,
|
|
2193
|
+
`${path} must be a non-empty array when provided`,
|
|
2194
|
+
);
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
for (const [index, maskDefinition] of mask.entries()) {
|
|
2198
|
+
const result = validateMaskDefinition({
|
|
2199
|
+
mask: maskDefinition,
|
|
2200
|
+
path: `${path}[${index}]`,
|
|
2201
|
+
errorFactory,
|
|
2202
|
+
});
|
|
2203
|
+
if (result?.valid === false) {
|
|
2204
|
+
return result;
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
};
|
|
2208
|
+
|
|
2174
2209
|
const validateAnimationDefinition = ({ animation, path, errorFactory }) => {
|
|
2175
2210
|
{
|
|
2176
2211
|
const result = validateAllowedKeys({
|
|
@@ -2276,7 +2311,7 @@ const validateAnimationDefinition = ({ animation, path, errorFactory }) => {
|
|
|
2276
2311
|
|
|
2277
2312
|
if (animation.mask !== undefined) {
|
|
2278
2313
|
{
|
|
2279
|
-
const result =
|
|
2314
|
+
const result = validateAnimationMasks({
|
|
2280
2315
|
mask: animation.mask,
|
|
2281
2316
|
path: `${path}.mask`,
|
|
2282
2317
|
errorFactory,
|
|
@@ -3754,6 +3789,99 @@ const validateComputedResultConfig = ({
|
|
|
3754
3789
|
return VALID_RESULT;
|
|
3755
3790
|
};
|
|
3756
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
|
+
|
|
3757
3885
|
const validateVariableComputedConfig = ({
|
|
3758
3886
|
computed,
|
|
3759
3887
|
variableType,
|
|
@@ -3766,11 +3894,22 @@ const validateVariableComputedConfig = ({
|
|
|
3766
3894
|
return invalidFromErrorFactory(errorFactory, `${path} must be an object`);
|
|
3767
3895
|
}
|
|
3768
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
|
+
|
|
3769
3908
|
if (Object.hasOwn(computed, "branches")) {
|
|
3770
3909
|
{
|
|
3771
3910
|
const result = validateAllowedKeys({
|
|
3772
3911
|
value: computed,
|
|
3773
|
-
allowedKeys: ["branches", "default"],
|
|
3912
|
+
allowedKeys: ["branches", "default", "examples"],
|
|
3774
3913
|
path,
|
|
3775
3914
|
errorFactory,
|
|
3776
3915
|
});
|
|
@@ -3846,6 +3985,7 @@ const validateVariableComputedConfig = ({
|
|
|
3846
3985
|
errorFactory,
|
|
3847
3986
|
variables,
|
|
3848
3987
|
dependencies,
|
|
3988
|
+
allowedKeys: ["expr", "value", "examples"],
|
|
3849
3989
|
});
|
|
3850
3990
|
};
|
|
3851
3991
|
|
|
@@ -8119,43 +8259,41 @@ const validateAnimationMaskImageReferences = ({
|
|
|
8119
8259
|
details = {},
|
|
8120
8260
|
errorFactory = createPreconditionValidationError,
|
|
8121
8261
|
}) => {
|
|
8122
|
-
if (
|
|
8123
|
-
!isPlainObject(animation) ||
|
|
8124
|
-
animation.type !== "transition" ||
|
|
8125
|
-
!isPlainObject(animation.mask)
|
|
8126
|
-
) {
|
|
8262
|
+
if (!isPlainObject(animation) || animation.type !== "transition") {
|
|
8127
8263
|
return VALID_RESULT;
|
|
8128
8264
|
}
|
|
8129
8265
|
|
|
8130
|
-
const
|
|
8266
|
+
const maskDefinitions = Array.isArray(animation.mask)
|
|
8267
|
+
? animation.mask.map((mask, index) => ({
|
|
8268
|
+
mask,
|
|
8269
|
+
path: `${path}.mask[${index}]`,
|
|
8270
|
+
fieldPrefix: `mask[${index}].`,
|
|
8271
|
+
}))
|
|
8272
|
+
: isPlainObject(animation.mask)
|
|
8273
|
+
? [
|
|
8274
|
+
{
|
|
8275
|
+
mask: animation.mask,
|
|
8276
|
+
path: `${path}.mask`,
|
|
8277
|
+
fieldPrefix: "",
|
|
8278
|
+
},
|
|
8279
|
+
]
|
|
8280
|
+
: [];
|
|
8131
8281
|
|
|
8132
|
-
|
|
8133
|
-
const
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
path: `${path}.mask.imageId`,
|
|
8137
|
-
details: {
|
|
8138
|
-
...details,
|
|
8139
|
-
field: "imageId",
|
|
8140
|
-
imageId: mask.imageId,
|
|
8141
|
-
},
|
|
8142
|
-
errorFactory,
|
|
8143
|
-
});
|
|
8144
|
-
if (!result.valid) {
|
|
8145
|
-
return result;
|
|
8282
|
+
for (const maskDefinition of maskDefinitions) {
|
|
8283
|
+
const { mask, path: maskPath, fieldPrefix } = maskDefinition;
|
|
8284
|
+
if (!isPlainObject(mask)) {
|
|
8285
|
+
continue;
|
|
8146
8286
|
}
|
|
8147
|
-
}
|
|
8148
8287
|
|
|
8149
|
-
|
|
8150
|
-
for (const [index, imageId] of mask.imageIds.entries()) {
|
|
8288
|
+
if (mask.imageId !== undefined) {
|
|
8151
8289
|
const result = validateImageReference({
|
|
8152
8290
|
state,
|
|
8153
|
-
imageId,
|
|
8154
|
-
path: `${
|
|
8291
|
+
imageId: mask.imageId,
|
|
8292
|
+
path: `${maskPath}.imageId`,
|
|
8155
8293
|
details: {
|
|
8156
8294
|
...details,
|
|
8157
|
-
field:
|
|
8158
|
-
imageId,
|
|
8295
|
+
field: `${fieldPrefix}imageId`,
|
|
8296
|
+
imageId: mask.imageId,
|
|
8159
8297
|
},
|
|
8160
8298
|
errorFactory,
|
|
8161
8299
|
});
|
|
@@ -8163,27 +8301,46 @@ const validateAnimationMaskImageReferences = ({
|
|
|
8163
8301
|
return result;
|
|
8164
8302
|
}
|
|
8165
8303
|
}
|
|
8166
|
-
}
|
|
8167
8304
|
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
|
|
8305
|
+
if (Array.isArray(mask.imageIds)) {
|
|
8306
|
+
for (const [index, imageId] of mask.imageIds.entries()) {
|
|
8307
|
+
const result = validateImageReference({
|
|
8308
|
+
state,
|
|
8309
|
+
imageId,
|
|
8310
|
+
path: `${maskPath}.imageIds[${index}]`,
|
|
8311
|
+
details: {
|
|
8312
|
+
...details,
|
|
8313
|
+
field: `${fieldPrefix}imageIds[${index}]`,
|
|
8314
|
+
imageId,
|
|
8315
|
+
},
|
|
8316
|
+
errorFactory,
|
|
8317
|
+
});
|
|
8318
|
+
if (!result.valid) {
|
|
8319
|
+
return result;
|
|
8320
|
+
}
|
|
8172
8321
|
}
|
|
8322
|
+
}
|
|
8173
8323
|
|
|
8174
|
-
|
|
8175
|
-
|
|
8176
|
-
|
|
8177
|
-
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
8324
|
+
if (Array.isArray(mask.items)) {
|
|
8325
|
+
for (const [index, item] of mask.items.entries()) {
|
|
8326
|
+
if (item?.imageId === undefined) {
|
|
8327
|
+
continue;
|
|
8328
|
+
}
|
|
8329
|
+
|
|
8330
|
+
const result = validateImageReference({
|
|
8331
|
+
state,
|
|
8181
8332
|
imageId: item.imageId,
|
|
8182
|
-
|
|
8183
|
-
|
|
8184
|
-
|
|
8185
|
-
|
|
8186
|
-
|
|
8333
|
+
path: `${maskPath}.items[${index}].imageId`,
|
|
8334
|
+
details: {
|
|
8335
|
+
...details,
|
|
8336
|
+
field: `${fieldPrefix}items[${index}].imageId`,
|
|
8337
|
+
imageId: item.imageId,
|
|
8338
|
+
},
|
|
8339
|
+
errorFactory,
|
|
8340
|
+
});
|
|
8341
|
+
if (!result.valid) {
|
|
8342
|
+
return result;
|
|
8343
|
+
}
|
|
8187
8344
|
}
|
|
8188
8345
|
}
|
|
8189
8346
|
}
|