@routevn/creator-model 1.1.11 → 1.1.12
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 +20 -0
- package/package.json +5 -2
- package/src/model.js +16 -15
package/README.md
CHANGED
|
@@ -5,6 +5,9 @@ Shared RouteVN domain model package.
|
|
|
5
5
|
Repo rules and contribution expectations are in
|
|
6
6
|
[GUIDELINES.md](./GUIDELINES.md).
|
|
7
7
|
|
|
8
|
+
Schema compatibility maintenance rules are in
|
|
9
|
+
[docs/schema-compatibility.md](./docs/schema-compatibility.md).
|
|
10
|
+
|
|
8
11
|
This repo is intended to be the single source of truth for:
|
|
9
12
|
|
|
10
13
|
- state validation
|
|
@@ -79,6 +82,9 @@ Design rules:
|
|
|
79
82
|
- pure functions whenever possible
|
|
80
83
|
- command payload shape is validated separately from state-aware preconditions
|
|
81
84
|
- `SCHEMA_VERSION` is the source of truth for persisted command schema versioning
|
|
85
|
+
- `SCHEMA_VERSION` must stay aligned with the minor version from `package.json`
|
|
86
|
+
- patch releases must not change persisted schema compatibility
|
|
87
|
+
- `bun run test:compat` is the required compatibility gate for model changes
|
|
82
88
|
- `processCommand()` is the authoritative state transition
|
|
83
89
|
- model state should contain project-owned runtime data only
|
|
84
90
|
- app-owned metadata like project id, name, and description should stay out of
|
|
@@ -190,6 +196,20 @@ YAML Puty specs use [tests/support/putyApi.js](./tests/support/putyApi.js) as a
|
|
|
190
196
|
small adapter so the declarative `throws:` assertions can stay concise while the
|
|
191
197
|
real public API returns `{ valid: ... }` result objects.
|
|
192
198
|
|
|
199
|
+
Compatibility fixtures live under `tests/compat/schema-<n>/`.
|
|
200
|
+
|
|
201
|
+
- `payloads/` fixtures are frozen command payload shapes for that schema version
|
|
202
|
+
- `states/` fixtures are frozen persisted-state snapshots for that schema version
|
|
203
|
+
- `streams/` fixtures are frozen command sequences for that schema version
|
|
204
|
+
- current tests must continue to validate/replay every archived compatibility
|
|
205
|
+
fixture from the same or older schema versions
|
|
206
|
+
- current schema payload coverage must include `minimal.yaml` and `full.yaml` for
|
|
207
|
+
every public command type
|
|
208
|
+
|
|
209
|
+
See also:
|
|
210
|
+
|
|
211
|
+
- [docs/schema-compatibility.md](./docs/schema-compatibility.md)
|
|
212
|
+
|
|
193
213
|
## Current Scope
|
|
194
214
|
|
|
195
215
|
Currently implemented command types:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@routevn/creator-model",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.12",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -27,10 +27,13 @@
|
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
29
|
"test": "bunx vitest run",
|
|
30
|
+
"test:compat": "bunx vitest run tests/compatibility-fixtures.test.js",
|
|
30
31
|
"test:watch": "bunx vitest",
|
|
31
|
-
"bench": "bun scripts/benchmark-process-command.js"
|
|
32
|
+
"bench": "bun scripts/benchmark-process-command.js",
|
|
33
|
+
"generate:compat-fixtures": "node scripts/generate-compat-fixtures.js"
|
|
32
34
|
},
|
|
33
35
|
"devDependencies": {
|
|
36
|
+
"js-yaml": "^4.1.0",
|
|
34
37
|
"puty": "0.1.2",
|
|
35
38
|
"vitest": "^3.2.1"
|
|
36
39
|
}
|
package/src/model.js
CHANGED
|
@@ -145,7 +145,7 @@ const LAYOUT_ELEMENT_BASE_TYPES = [
|
|
|
145
145
|
"container-ref-confirm-dialog-ok",
|
|
146
146
|
"container-ref-confirm-dialog-cancel",
|
|
147
147
|
];
|
|
148
|
-
export const SCHEMA_VERSION =
|
|
148
|
+
export const SCHEMA_VERSION = 1;
|
|
149
149
|
const LAYOUT_CONTAINER_ELEMENT_TYPES = [
|
|
150
150
|
"folder",
|
|
151
151
|
"container",
|
|
@@ -1357,30 +1357,21 @@ const validateMaskDefinition = ({ mask, path, errorFactory }) => {
|
|
|
1357
1357
|
}
|
|
1358
1358
|
}
|
|
1359
1359
|
|
|
1360
|
-
if (
|
|
1361
|
-
item.texture !== undefined &&
|
|
1362
|
-
!isNonEmptyString(item.texture)
|
|
1363
|
-
) {
|
|
1360
|
+
if (item.texture !== undefined && !isNonEmptyString(item.texture)) {
|
|
1364
1361
|
return invalidFromErrorFactory(
|
|
1365
1362
|
errorFactory,
|
|
1366
1363
|
`${itemPath}.texture must be a non-empty string when provided`,
|
|
1367
1364
|
);
|
|
1368
1365
|
}
|
|
1369
1366
|
|
|
1370
|
-
if (
|
|
1371
|
-
item.imageId !== undefined &&
|
|
1372
|
-
!isNonEmptyString(item.imageId)
|
|
1373
|
-
) {
|
|
1367
|
+
if (item.imageId !== undefined && !isNonEmptyString(item.imageId)) {
|
|
1374
1368
|
return invalidFromErrorFactory(
|
|
1375
1369
|
errorFactory,
|
|
1376
1370
|
`${itemPath}.imageId must be a non-empty string when provided`,
|
|
1377
1371
|
);
|
|
1378
1372
|
}
|
|
1379
1373
|
|
|
1380
|
-
if (
|
|
1381
|
-
!isNonEmptyString(item.texture) &&
|
|
1382
|
-
!isNonEmptyString(item.imageId)
|
|
1383
|
-
) {
|
|
1374
|
+
if (!isNonEmptyString(item.texture) && !isNonEmptyString(item.imageId)) {
|
|
1384
1375
|
return invalidFromErrorFactory(
|
|
1385
1376
|
errorFactory,
|
|
1386
1377
|
`${itemPath} must define texture or imageId`,
|
|
@@ -1987,7 +1978,15 @@ const validateVariableItems = ({ items, path, errorFactory }) => {
|
|
|
1987
1978
|
allowedKeys:
|
|
1988
1979
|
variableType === "folder"
|
|
1989
1980
|
? ["id", "type", "name", "description"]
|
|
1990
|
-
: [
|
|
1981
|
+
: [
|
|
1982
|
+
"id",
|
|
1983
|
+
"type",
|
|
1984
|
+
"name",
|
|
1985
|
+
"description",
|
|
1986
|
+
"scope",
|
|
1987
|
+
"default",
|
|
1988
|
+
"value",
|
|
1989
|
+
],
|
|
1991
1990
|
path: itemPath,
|
|
1992
1991
|
errorFactory,
|
|
1993
1992
|
});
|
|
@@ -4502,7 +4501,9 @@ export const assertInvariants = ({ state }) => {
|
|
|
4502
4501
|
}
|
|
4503
4502
|
}
|
|
4504
4503
|
|
|
4505
|
-
for (const [animationId, animation] of Object.entries(
|
|
4504
|
+
for (const [animationId, animation] of Object.entries(
|
|
4505
|
+
state.animations.items,
|
|
4506
|
+
)) {
|
|
4506
4507
|
if (animation.type !== "animation") {
|
|
4507
4508
|
continue;
|
|
4508
4509
|
}
|