@routevn/creator-model 1.5.0 → 1.5.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 +1 -0
  2. package/package.json +1 -1
  3. package/src/model.js +226 -3
package/README.md CHANGED
@@ -293,6 +293,7 @@ Currently implemented command types:
293
293
  - `layout.update`
294
294
  - `layout.delete`
295
295
  - `layout.move`
296
+ - `layout.schema.upgrade`
296
297
  - `character.sprite.create`
297
298
  - `character.sprite.update`
298
299
  - `character.sprite.delete`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routevn/creator-model",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/model.js CHANGED
@@ -40,7 +40,12 @@ const LINE_UPDATE_ACTIONS_PRESERVE_PATHS = ["dialogue.content"];
40
40
  const LINE_UPDATE_ACTIONS_PRESERVE_PATHS_SET = new Set(
41
41
  LINE_UPDATE_ACTIONS_PRESERVE_PATHS,
42
42
  );
43
+ const CURRENT_LAYOUT_SCHEMA_VERSION = 2;
43
44
  const isPositiveFiniteNumber = (value) => isFiniteNumber(value) && value > 0;
45
+ const normalizeLayoutSchemaVersion = (value) =>
46
+ Number.isInteger(value) && value >= 1 ? value : 1;
47
+ const isSupportedLayoutSchemaVersion = (value) =>
48
+ value === CURRENT_LAYOUT_SCHEMA_VERSION;
44
49
  const createEmptyCollectionState = () => ({
45
50
  items: {},
46
51
  tree: [],
@@ -2205,7 +2210,7 @@ const validateAnimationItems = ({ items, path, errorFactory }) => {
2205
2210
  }
2206
2211
 
2207
2212
  {
2208
- const result = validatePreviewObject({
2213
+ const result = validateAnimationPreviewObject({
2209
2214
  value: item.preview,
2210
2215
  path: `${itemPath}.preview`,
2211
2216
  errorFactory,
@@ -4901,6 +4906,102 @@ const validatePreviewObject = ({ value, path, errorFactory }) => {
4901
4906
  return VALID_RESULT;
4902
4907
  };
4903
4908
 
4909
+ const validateAnimationPreviewSlot = ({
4910
+ value,
4911
+ path,
4912
+ allowTransform = false,
4913
+ errorFactory,
4914
+ }) => {
4915
+ if (value === undefined) {
4916
+ return VALID_RESULT;
4917
+ }
4918
+
4919
+ if (!isPlainObject(value)) {
4920
+ return invalidFromErrorFactory(
4921
+ errorFactory,
4922
+ `${path} must be an object when provided`,
4923
+ );
4924
+ }
4925
+
4926
+ {
4927
+ const result = validateAllowedKeys({
4928
+ value,
4929
+ allowedKeys: allowTransform ? ["imageId", "transformId"] : ["imageId"],
4930
+ path,
4931
+ errorFactory,
4932
+ });
4933
+ if (result?.valid === false) {
4934
+ return result;
4935
+ }
4936
+ }
4937
+
4938
+ if (value.imageId !== undefined && !isNonEmptyString(value.imageId)) {
4939
+ return invalidFromErrorFactory(
4940
+ errorFactory,
4941
+ `${path}.imageId must be a non-empty string when provided`,
4942
+ );
4943
+ }
4944
+
4945
+ if (value.transformId !== undefined && !isNonEmptyString(value.transformId)) {
4946
+ return invalidFromErrorFactory(
4947
+ errorFactory,
4948
+ `${path}.transformId must be a non-empty string when provided`,
4949
+ );
4950
+ }
4951
+
4952
+ return VALID_RESULT;
4953
+ };
4954
+
4955
+ const validateAnimationPreviewObject = ({ value, path, errorFactory }) => {
4956
+ if (value === undefined) {
4957
+ return VALID_RESULT;
4958
+ }
4959
+
4960
+ if (!isPlainObject(value)) {
4961
+ return invalidFromErrorFactory(
4962
+ errorFactory,
4963
+ `${path} must be an object when provided`,
4964
+ );
4965
+ }
4966
+
4967
+ {
4968
+ const result = validateAllowedKeys({
4969
+ value,
4970
+ allowedKeys: ["background", "target", "outgoing", "incoming"],
4971
+ path,
4972
+ errorFactory,
4973
+ });
4974
+ if (result?.valid === false) {
4975
+ return result;
4976
+ }
4977
+ }
4978
+
4979
+ {
4980
+ const result = validateAnimationPreviewSlot({
4981
+ value: value.background,
4982
+ path: `${path}.background`,
4983
+ errorFactory,
4984
+ });
4985
+ if (result?.valid === false) {
4986
+ return result;
4987
+ }
4988
+ }
4989
+
4990
+ for (const key of ["target", "outgoing", "incoming"]) {
4991
+ const result = validateAnimationPreviewSlot({
4992
+ value: value[key],
4993
+ path: `${path}.${key}`,
4994
+ allowTransform: true,
4995
+ errorFactory,
4996
+ });
4997
+ if (result?.valid === false) {
4998
+ return result;
4999
+ }
5000
+ }
5001
+
5002
+ return VALID_RESULT;
5003
+ };
5004
+
4904
5005
  const validateTransformPreviewSlot = ({ value, path, errorFactory }) => {
4905
5006
  if (value === undefined) {
4906
5007
  return VALID_RESULT;
@@ -4997,6 +5098,7 @@ const validateLayoutItems = ({ items, path, errorFactory }) => {
4997
5098
  "description",
4998
5099
  "tagIds",
4999
5100
  "layoutType",
5101
+ "layoutSchemaVersion",
5000
5102
  "isFragment",
5001
5103
  "thumbnailFileId",
5002
5104
  "preview",
@@ -5079,6 +5181,16 @@ const validateLayoutItems = ({ items, path, errorFactory }) => {
5079
5181
  );
5080
5182
  }
5081
5183
 
5184
+ if (
5185
+ item.layoutSchemaVersion !== undefined &&
5186
+ !isSupportedLayoutSchemaVersion(item.layoutSchemaVersion)
5187
+ ) {
5188
+ return invalidFromErrorFactory(
5189
+ errorFactory,
5190
+ `${itemPath}.layoutSchemaVersion must be ${CURRENT_LAYOUT_SCHEMA_VERSION} when provided`,
5191
+ );
5192
+ }
5193
+
5082
5194
  if (
5083
5195
  item.isFragment !== undefined &&
5084
5196
  typeof item.isFragment !== "boolean"
@@ -9148,7 +9260,7 @@ const validateAnimationCreateData = ({ data, errorFactory }) => {
9148
9260
  }
9149
9261
 
9150
9262
  {
9151
- const result = validatePreviewObject({
9263
+ const result = validateAnimationPreviewObject({
9152
9264
  value: data.preview,
9153
9265
  path: "payload.data.preview",
9154
9266
  errorFactory,
@@ -9234,7 +9346,7 @@ const validateAnimationUpdateData = ({ data, errorFactory }) => {
9234
9346
  }
9235
9347
 
9236
9348
  {
9237
- const result = validatePreviewObject({
9349
+ const result = validateAnimationPreviewObject({
9238
9350
  value: data.preview,
9239
9351
  path: "payload.data.preview",
9240
9352
  errorFactory,
@@ -10520,6 +10632,7 @@ const validateLayoutCreateData = ({ data, errorFactory }) => {
10520
10632
  "description",
10521
10633
  "tagIds",
10522
10634
  "layoutType",
10635
+ "layoutSchemaVersion",
10523
10636
  "isFragment",
10524
10637
  "thumbnailFileId",
10525
10638
  "preview",
@@ -10587,6 +10700,16 @@ const validateLayoutCreateData = ({ data, errorFactory }) => {
10587
10700
  );
10588
10701
  }
10589
10702
 
10703
+ if (
10704
+ data.layoutSchemaVersion !== undefined &&
10705
+ !isSupportedLayoutSchemaVersion(data.layoutSchemaVersion)
10706
+ ) {
10707
+ return invalidFromErrorFactory(
10708
+ errorFactory,
10709
+ `payload.data.layoutSchemaVersion must be ${CURRENT_LAYOUT_SCHEMA_VERSION} when provided`,
10710
+ );
10711
+ }
10712
+
10590
10713
  if (data.isFragment !== undefined && typeof data.isFragment !== "boolean") {
10591
10714
  return invalidFromErrorFactory(
10592
10715
  errorFactory,
@@ -11393,6 +11516,32 @@ const createEmptyNestedCollection = () => ({
11393
11516
  tree: [],
11394
11517
  });
11395
11518
 
11519
+ const isDirectedLayoutContainer = (item) =>
11520
+ item?.direction === "horizontal" || item?.direction === "vertical";
11521
+
11522
+ const upgradeLayoutTreeOrder = ({ nodes, items, parentItem } = {}) => {
11523
+ const sourceNodes = Array.isArray(nodes) ? nodes : [];
11524
+ const orderedNodes = isDirectedLayoutContainer(parentItem)
11525
+ ? sourceNodes
11526
+ : [...sourceNodes].reverse();
11527
+
11528
+ return orderedNodes.map((node) => {
11529
+ const nextNode = {
11530
+ ...node,
11531
+ };
11532
+
11533
+ if (Array.isArray(node?.children) && node.children.length > 0) {
11534
+ nextNode.children = upgradeLayoutTreeOrder({
11535
+ nodes: node.children,
11536
+ items,
11537
+ parentItem: items?.[node.id],
11538
+ });
11539
+ }
11540
+
11541
+ return nextNode;
11542
+ });
11543
+ };
11544
+
11396
11545
  const findSectionLocation = ({ state, sectionId }) => {
11397
11546
  for (const [sceneId, scene] of Object.entries(state.scenes.items)) {
11398
11547
  if (scene?.type !== "scene") {
@@ -16866,6 +17015,11 @@ const COMMAND_DEFINITIONS = [
16866
17015
  }
16867
17016
  : {}),
16868
17017
  layoutType: payload.data.layoutType,
17018
+ ...(payload.data.layoutSchemaVersion !== undefined
17019
+ ? {
17020
+ layoutSchemaVersion: payload.data.layoutSchemaVersion,
17021
+ }
17022
+ : {}),
16869
17023
  isFragment: payload.data.isFragment,
16870
17024
  ...(payload.data.thumbnailFileId !== undefined
16871
17025
  ? {
@@ -16954,6 +17108,75 @@ const COMMAND_DEFINITIONS = [
16954
17108
  }
16955
17109
  },
16956
17110
  }),
17111
+ {
17112
+ type: "layout.schema.upgrade",
17113
+ validatePayload: ({ payload }) => {
17114
+ {
17115
+ const result = validateExactKeys({
17116
+ value: payload,
17117
+ expectedKeys: ["layoutIds", "targetSchemaVersion"],
17118
+ path: "payload",
17119
+ errorFactory: createPayloadValidationError,
17120
+ });
17121
+ if (result?.valid === false) {
17122
+ return result;
17123
+ }
17124
+ }
17125
+
17126
+ {
17127
+ const result = validateRequiredUniqueIdArray({
17128
+ value: payload.layoutIds,
17129
+ path: "payload.layoutIds",
17130
+ errorFactory: createPayloadValidationError,
17131
+ });
17132
+ if (result?.valid === false) {
17133
+ return result;
17134
+ }
17135
+ }
17136
+
17137
+ if (payload.targetSchemaVersion !== CURRENT_LAYOUT_SCHEMA_VERSION) {
17138
+ return invalidPayload(
17139
+ `payload.targetSchemaVersion must be ${CURRENT_LAYOUT_SCHEMA_VERSION}`,
17140
+ );
17141
+ }
17142
+
17143
+ return VALID_RESULT;
17144
+ },
17145
+ validateAgainstState: ({ state, payload }) => {
17146
+ for (const layoutId of payload.layoutIds) {
17147
+ const layout = state.layouts.items[layoutId];
17148
+ if (!isPlainObject(layout) || layout.type !== "layout") {
17149
+ return invalidPrecondition(
17150
+ "payload.layoutIds must reference existing layouts",
17151
+ {
17152
+ layoutId,
17153
+ },
17154
+ );
17155
+ }
17156
+ }
17157
+
17158
+ return VALID_RESULT;
17159
+ },
17160
+ reduce: ({ state, payload }) => {
17161
+ for (const layoutId of payload.layoutIds) {
17162
+ const layout = state.layouts.items[layoutId];
17163
+ if (
17164
+ normalizeLayoutSchemaVersion(layout.layoutSchemaVersion) >=
17165
+ payload.targetSchemaVersion
17166
+ ) {
17167
+ continue;
17168
+ }
17169
+
17170
+ layout.elements.tree = upgradeLayoutTreeOrder({
17171
+ nodes: layout.elements.tree,
17172
+ items: layout.elements.items,
17173
+ });
17174
+ layout.layoutSchemaVersion = payload.targetSchemaVersion;
17175
+ }
17176
+
17177
+ return state;
17178
+ },
17179
+ },
16957
17180
  ...createFolderedCollectionCommandDefinitions({
16958
17181
  familyName: "control",
16959
17182
  collectionKey: "controls",