charon-conversation-editor 0.0.20 → 0.0.29

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/assets/index.css CHANGED
@@ -628,6 +628,7 @@ svg.react-flow__connectionline {
628
628
  flex-direction: row;
629
629
  position: relative;
630
630
 
631
+ --ext-node-select-color: var(--app-color-primary, blue);
631
632
  --ext-panel-background-color: var(--app-white-background, white);
632
633
  --ext-node-edge-color: hsl(from var(--app-color-gray, gray) h s calc(l * 1.2));
633
634
  --ext-node-border-color: hsl(from var(--app-color-gray, gray) h s calc(l * 1.2));
@@ -1082,6 +1083,7 @@ svg.react-flow__connectionline {
1082
1083
  line-height: 1.5;
1083
1084
  }
1084
1085
 
1086
+ .ext-ce-schema-validation-container .ext-ce-schema-name,
1085
1087
  .ext-ce-schema-validation-container .ext-ce-error-message code {
1086
1088
  background-color: #edf2f7;
1087
1089
  padding: 2px 6px;
@@ -1092,7 +1094,7 @@ svg.react-flow__connectionline {
1092
1094
  }
1093
1095
 
1094
1096
 
1095
- .ext-ce-schema-validation-container .ext-ce-copy-button {
1097
+ .ext-ce-schema-validation-container .ext-ce-migrate-button {
1096
1098
  background-color: var(--ext-panel-background-color);
1097
1099
  border: 1px solid var(--app-color-gray);
1098
1100
  outline: none;
@@ -1106,6 +1108,6 @@ svg.react-flow__connectionline {
1106
1108
  text-align: left;
1107
1109
  }
1108
1110
 
1109
- .ext-ce-schema-validation-container .ext-ce-copy-button:hover {
1111
+ .ext-ce-schema-validation-container .ext-ce-migrate-button:hover {
1110
1112
  background-color: var(--app-light-gray-background);
1111
1113
  }
package/index.js CHANGED
@@ -7157,7 +7157,7 @@ function requireReactDomClient_production() {
7157
7157
  function commitHostUpdate(finishedWork, newProps, oldProps) {
7158
7158
  try {
7159
7159
  var domElement = finishedWork.stateNode;
7160
- updateProperties(domElement, finishedWork.type, oldProps, newProps);
7160
+ updateProperties2(domElement, finishedWork.type, oldProps, newProps);
7161
7161
  domElement[internalPropsKey] = newProps;
7162
7162
  } catch (error) {
7163
7163
  captureCommitPhaseError(finishedWork, finishedWork.return, error);
@@ -10741,7 +10741,7 @@ function requireReactDomClient_production() {
10741
10741
  for (defaultValue in props)
10742
10742
  props.hasOwnProperty(defaultValue) && (hasSrc = props[defaultValue], null != hasSrc && setProp(domElement, tag, defaultValue, hasSrc, props, null));
10743
10743
  }
10744
- function updateProperties(domElement, tag, lastProps, nextProps) {
10744
+ function updateProperties2(domElement, tag, lastProps, nextProps) {
10745
10745
  switch (tag) {
10746
10746
  case "div":
10747
10747
  case "span":
@@ -21179,11 +21179,25 @@ function ResizeControl({ nodeId, position, variant = ResizeControlVariant.Handle
21179
21179
  }, children: children2 });
21180
21180
  }
21181
21181
  reactExports.memo(ResizeControl);
21182
+ function isValueControl(value) {
21183
+ return !!value && typeof value === "object" && // probe few properties and functions
21184
+ typeof value.type === "string" && typeof value.changeStatus === "string" && typeof value.setValue === "function" && typeof value.makeWriteable === "function";
21185
+ }
21186
+ function isRootDocumentControl(value) {
21187
+ return !!value && value.type === "document" && "schema" in value && (!value.schemaProperty || Object.is(value.schemaProperty, value.schema.getIdProperty()));
21188
+ }
21189
+ function getRootDocumentControl(value) {
21190
+ const rootOrNull = isValueControl(value) ? value.root : null;
21191
+ if (!isRootDocumentControl(rootOrNull)) {
21192
+ throw new Error("Unable to find root node for the specified control.");
21193
+ }
21194
+ return rootOrNull;
21195
+ }
21182
21196
  function isDocumentCollectionControl(value) {
21183
21197
  return value && value.type === "document-collection";
21184
21198
  }
21185
21199
  function isDocumentControl(value) {
21186
- return value && value.type === "document";
21200
+ return !!value && value.type === "document";
21187
21201
  }
21188
21202
  var DataType = /* @__PURE__ */ ((DataType2) => {
21189
21203
  DataType2[DataType2["Text"] = 0] = "Text";
@@ -21347,9 +21361,7 @@ function bindInstanceMethods(instance) {
21347
21361
  const noChanges = [];
21348
21362
  class ConversationState {
21349
21363
  constructor(conversationTreeControl) {
21350
- __publicField(this, "originalIdToControlMap");
21351
21364
  this.conversationTreeControl = conversationTreeControl;
21352
- this.originalIdToControlMap = /* @__PURE__ */ new Map();
21353
21365
  bindInstanceMethods(this);
21354
21366
  }
21355
21367
  getConversationNodeChanges(nodes) {
@@ -21363,8 +21375,8 @@ class ConversationState {
21363
21375
  const existingNode = nodesById.get(dialogFlowNodeId);
21364
21376
  const specification = new URLSearchParams(String(Specification || ""));
21365
21377
  const position = getPosition(specification);
21366
- nodesById.delete(dialogFlowNodeId);
21367
21378
  if (existingNode && Object.is(existingNode.data.valueControl, dialogNodeControl)) {
21379
+ nodesById.delete(existingNode.id);
21368
21380
  if (position && !arePositionsEquals(position, existingNode.position)) {
21369
21381
  changes.push({
21370
21382
  id: existingNode.id,
@@ -21395,8 +21407,8 @@ class ConversationState {
21395
21407
  const existingRootNode = nodesById.get(rootFlowNodeId);
21396
21408
  const rootNodeSpecification = new URLSearchParams(String(((_a = this.conversationTreeControl.controls.Specification) == null ? void 0 : _a.value) || ""));
21397
21409
  const rootPosition = getPosition(rootNodeSpecification);
21398
- nodesById.delete(rootFlowNodeId);
21399
21410
  if (existingRootNode && Object.is(existingRootNode.data.valueControl, this.conversationTreeControl)) {
21411
+ nodesById.delete(existingRootNode.id);
21400
21412
  if (rootPosition && !arePositionsEquals(rootPosition, existingRootNode.position)) {
21401
21413
  changes.push({
21402
21414
  id: existingRootNode.id,
@@ -21493,14 +21505,13 @@ class ConversationState {
21493
21505
  const nodesControl = this.conversationTreeControl.controls.Nodes;
21494
21506
  const newDialogNodeId = generateDialogNodeIdPlaceholder();
21495
21507
  const specification = setPosition("", position);
21496
- const newDialogNodeControl = nodesControl.append({
21508
+ nodesControl.append({
21497
21509
  Id: newDialogNodeId,
21498
21510
  Text: "<EMPTY>",
21499
21511
  NextNode: null,
21500
21512
  Responses: [],
21501
21513
  Specification: specification.toString()
21502
21514
  }, opts);
21503
- this.originalIdToControlMap.set(newDialogNodeId, new WeakRef(newDialogNodeControl));
21504
21515
  const { id: sourceDialogNodeId } = parseHandleOrFlowNodeId(source);
21505
21516
  const { id: sourceDialogNodeOrResponseId, type: handleType } = parseHandleOrFlowNodeId(sourceHandleId);
21506
21517
  switch (handleType) {
@@ -21519,7 +21530,7 @@ class ConversationState {
21519
21530
  const nodesControl = this.conversationTreeControl.controls.Nodes;
21520
21531
  const specification = setPosition((initialData == null ? void 0 : initialData.Specification) ?? "", position);
21521
21532
  const newDialogNodeId = initialData.Id || generateDialogNodeIdPlaceholder();
21522
- const newDialogNodeControl = nodesControl.append({
21533
+ nodesControl.append({
21523
21534
  ...initialData,
21524
21535
  Id: newDialogNodeId,
21525
21536
  Text: initialData.Text ?? "<EMPTY>",
@@ -21527,9 +21538,6 @@ class ConversationState {
21527
21538
  Responses: (initialData.Responses ?? []).map(mapResponse),
21528
21539
  Specification: specification.toString()
21529
21540
  }, opts);
21530
- if (typeof newDialogNodeId === "string" && newDialogNodeId.startsWith("_ID_")) {
21531
- this.originalIdToControlMap.set(newDialogNodeId, new WeakRef(newDialogNodeControl));
21532
- }
21533
21541
  function mapResponse(responseData) {
21534
21542
  return {
21535
21543
  ...responseData,
@@ -21540,36 +21548,36 @@ class ConversationState {
21540
21548
  };
21541
21549
  }
21542
21550
  }
21543
- setDialogNextNode(dialogNodeId, targetDialogNodeId, comparisonTargetDialogNodeId, opts) {
21551
+ setDialogNextNode(dialogNodeId, targetDialogNodeId, changeTargetFromId, opts) {
21544
21552
  var _a;
21545
21553
  const dialogNodeControl = this.findDialogNode(dialogNodeId);
21546
21554
  if (!dialogNodeControl) {
21547
21555
  return;
21548
21556
  }
21549
21557
  const nextNodeControl = dialogNodeControl.controls.NextNode;
21550
- if (comparisonTargetDialogNodeId !== void 0 && ((_a = nextNodeControl.value) == null ? void 0 : _a.Id) != comparisonTargetDialogNodeId) {
21558
+ if (changeTargetFromId !== void 0 && ((_a = nextNodeControl.value) == null ? void 0 : _a.Id) != changeTargetFromId) {
21551
21559
  return;
21552
21560
  }
21553
21561
  const nextNodeReference = this.getNextNodeReference(targetDialogNodeId);
21554
21562
  nextNodeControl.setValue(nextNodeReference, opts);
21555
21563
  }
21556
- setDialogResponseNextNode(dialogNodeId, dialogResponseId, targetDialogNodeId, comparisonTargetDialogNodeId, opts) {
21564
+ setDialogResponseNextNode(dialogNodeId, dialogResponseId, targetDialogNodeId, changeTargetFromId, opts) {
21557
21565
  var _a;
21558
21566
  const dialogResponseControl = this.findDialogResponse(dialogNodeId, dialogResponseId);
21559
21567
  if (!dialogResponseControl) {
21560
21568
  return;
21561
21569
  }
21562
21570
  const nextNodeControl = dialogResponseControl.controls.NextNode;
21563
- if (comparisonTargetDialogNodeId !== void 0 && ((_a = nextNodeControl.value) == null ? void 0 : _a.Id) != comparisonTargetDialogNodeId) {
21571
+ if (changeTargetFromId !== void 0 && ((_a = nextNodeControl.value) == null ? void 0 : _a.Id) != changeTargetFromId) {
21564
21572
  return;
21565
21573
  }
21566
21574
  const nextNodeReference = this.getNextNodeReference(targetDialogNodeId);
21567
21575
  nextNodeControl.setValue(nextNodeReference, opts);
21568
21576
  }
21569
- setRootNode(targetDialogNodeId, comparisonTargetDialogNodeId, opts) {
21577
+ setRootNode(targetDialogNodeId, changeTargetFromId, opts) {
21570
21578
  var _a;
21571
21579
  const rootNodeControl = this.conversationTreeControl.controls.RootNode;
21572
- if (comparisonTargetDialogNodeId !== void 0 && ((_a = rootNodeControl.value) == null ? void 0 : _a.Id) != comparisonTargetDialogNodeId) {
21580
+ if (changeTargetFromId !== void 0 && ((_a = rootNodeControl.value) == null ? void 0 : _a.Id) != changeTargetFromId) {
21573
21581
  return;
21574
21582
  }
21575
21583
  const nextNodeReference = this.getNextNodeReference(targetDialogNodeId);
@@ -21608,16 +21616,14 @@ class ConversationState {
21608
21616
  }
21609
21617
  const newDialogResponseId = generateDialogNodeResponseIdPlaceholder();
21610
21618
  const responsesControl = dialogNodeControl.controls.Responses;
21611
- const newDialogResponseControl = responsesControl.append({
21619
+ responsesControl.append({
21612
21620
  Id: newDialogResponseId,
21613
21621
  Text: text,
21614
21622
  NextNode: null,
21615
21623
  Specification: ""
21616
21624
  }, opts);
21617
- this.originalIdToControlMap.set(newDialogResponseId, new WeakRef(newDialogResponseControl));
21618
21625
  }
21619
21626
  removeDialogResponse(dialogNodeId, dialogResponseId, opts) {
21620
- dialogResponseId = this.actualizeId(dialogResponseId);
21621
21627
  const dialogNodeControl = this.findDialogNode(dialogNodeId);
21622
21628
  if (!dialogNodeControl) {
21623
21629
  return;
@@ -21632,7 +21638,6 @@ class ConversationState {
21632
21638
  }
21633
21639
  removeDialogNode(dialogNodeId, opts) {
21634
21640
  var _a;
21635
- dialogNodeId = this.actualizeId(dialogNodeId);
21636
21641
  const nodesControl = this.conversationTreeControl.controls.Nodes;
21637
21642
  const dialogNodeIndex = nodesControl.value.findIndex((node) => node.Id == dialogNodeId);
21638
21643
  if (dialogNodeIndex < 0) {
@@ -21660,7 +21665,6 @@ class ConversationState {
21660
21665
  return true;
21661
21666
  }
21662
21667
  findDialogNode(dialogNodeId) {
21663
- dialogNodeId = this.actualizeId(dialogNodeId);
21664
21668
  if (!dialogNodeId) {
21665
21669
  return;
21666
21670
  }
@@ -21672,8 +21676,6 @@ class ConversationState {
21672
21676
  return nodesControl.controls[dialogNodeIndex];
21673
21677
  }
21674
21678
  findDialogResponse(dialogNodeId, dialogResponseId) {
21675
- dialogNodeId = this.actualizeId(dialogNodeId);
21676
- dialogResponseId = this.actualizeId(dialogResponseId);
21677
21679
  if (!dialogNodeId || !dialogResponseId) {
21678
21680
  return;
21679
21681
  }
@@ -21689,17 +21691,6 @@ class ConversationState {
21689
21691
  }
21690
21692
  }
21691
21693
  }
21692
- actualizeId(dialogNodeOrResponseId) {
21693
- var _a;
21694
- if (!dialogNodeOrResponseId) {
21695
- return null;
21696
- }
21697
- const control = (_a = this.originalIdToControlMap.get(dialogNodeOrResponseId)) == null ? void 0 : _a.deref();
21698
- if (control) {
21699
- return getDocumentIdAsString(control);
21700
- }
21701
- return dialogNodeOrResponseId;
21702
- }
21703
21694
  getEdgeChange(edges, source, target, sourceHandle) {
21704
21695
  const newEdge = this.createEdge(source, target, sourceHandle, void 0);
21705
21696
  const existingEdge = edges.get(newEdge.id);
@@ -22996,6 +22987,30 @@ function of() {
22996
22987
  var scheduler2 = popScheduler(args);
22997
22988
  return from(args, scheduler2);
22998
22989
  }
22990
+ var EmptyError = createErrorClass(function(_super) {
22991
+ return function EmptyErrorImpl() {
22992
+ _super(this);
22993
+ this.name = "EmptyError";
22994
+ this.message = "no elements in sequence";
22995
+ };
22996
+ });
22997
+ function firstValueFrom(source, config2) {
22998
+ return new Promise(function(resolve, reject) {
22999
+ var subscriber = new SafeSubscriber({
23000
+ next: function(value) {
23001
+ resolve(value);
23002
+ subscriber.unsubscribe();
23003
+ },
23004
+ error: reject,
23005
+ complete: function() {
23006
+ {
23007
+ reject(new EmptyError());
23008
+ }
23009
+ }
23010
+ });
23011
+ source.subscribe(subscriber);
23012
+ });
23013
+ }
22999
23014
  class UndoRedoState {
23000
23015
  /**
23001
23016
  * Creates a new UndoRedoState instance for managing ValueControl history
@@ -23375,6 +23390,18 @@ class DevSchema {
23375
23390
  getHashCode() {
23376
23391
  return 0;
23377
23392
  }
23393
+ toDocument() {
23394
+ return {
23395
+ Id: this.id,
23396
+ Name: this.name,
23397
+ DisplayName: this.displayName,
23398
+ Type: this.type,
23399
+ Description: this.description,
23400
+ IdGenerator: this.idGenerator,
23401
+ Specification: this.specification,
23402
+ Properties: this.properties.map((property) => property.toDocument())
23403
+ };
23404
+ }
23378
23405
  toString() {
23379
23406
  return this.name;
23380
23407
  }
@@ -23907,6 +23934,22 @@ class DevSchemaProperty {
23907
23934
  getHashCode() {
23908
23935
  return 0;
23909
23936
  }
23937
+ toDocument() {
23938
+ return {
23939
+ Id: this.id,
23940
+ SharedProperty: this.sharedProperty ? { Id: this.sharedProperty.id } : null,
23941
+ Name: this.name,
23942
+ DisplayName: this.displayName,
23943
+ Description: this.description,
23944
+ DataType: this.dataType,
23945
+ DefaultValue: this.defaultValue,
23946
+ Uniqueness: this.uniqueness,
23947
+ Requirement: this.requirement,
23948
+ ReferenceType: this.referenceType ? { Id: this.referenceType.id, DisplayName: this.referenceType.displayName } : null,
23949
+ Size: this.size,
23950
+ Specification: this.specification
23951
+ };
23952
+ }
23910
23953
  toString() {
23911
23954
  return this.name;
23912
23955
  }
@@ -34462,11 +34505,35 @@ function validateProperty(schema, modelPath, propertyName, expectedTypes, errors
34462
34505
  });
34463
34506
  }
34464
34507
  }
34465
- const ConversationSchema = {
34508
+ var ImportMode = /* @__PURE__ */ ((ImportMode2) => {
34509
+ ImportMode2[ImportMode2["createAndUpdate"] = 0] = "createAndUpdate";
34510
+ ImportMode2[ImportMode2["create"] = 1] = "create";
34511
+ ImportMode2[ImportMode2["update"] = 2] = "update";
34512
+ ImportMode2[ImportMode2["safeUpdate"] = 3] = "safeUpdate";
34513
+ ImportMode2[ImportMode2["replace"] = 4] = "replace";
34514
+ ImportMode2[ImportMode2["delete"] = 5] = "delete";
34515
+ return ImportMode2;
34516
+ })(ImportMode || {});
34517
+ var ValidationOption = /* @__PURE__ */ ((ValidationOption2) => {
34518
+ ValidationOption2[ValidationOption2["repair"] = 0] = "repair";
34519
+ ValidationOption2[ValidationOption2["checkTranslations"] = 1] = "checkTranslations";
34520
+ ValidationOption2[ValidationOption2["deduplicateIds"] = 2] = "deduplicateIds";
34521
+ ValidationOption2[ValidationOption2["repairRequiredWithDefaults"] = 3] = "repairRequiredWithDefaults";
34522
+ ValidationOption2[ValidationOption2["resolveConflictingUnions"] = 4] = "resolveConflictingUnions";
34523
+ ValidationOption2[ValidationOption2["eraseInvalidValues"] = 5] = "eraseInvalidValues";
34524
+ ValidationOption2[ValidationOption2["checkRequirements"] = 6] = "checkRequirements";
34525
+ ValidationOption2[ValidationOption2["checkFormat"] = 7] = "checkFormat";
34526
+ ValidationOption2[ValidationOption2["checkUniqueness"] = 8] = "checkUniqueness";
34527
+ ValidationOption2[ValidationOption2["checkReferences"] = 9] = "checkReferences";
34528
+ ValidationOption2[ValidationOption2["checkSpecification"] = 10] = "checkSpecification";
34529
+ ValidationOption2[ValidationOption2["checkConstraints"] = 11] = "checkConstraints";
34530
+ return ValidationOption2;
34531
+ })(ValidationOption || {});
34532
+ const conversationSchema = {
34466
34533
  "Collections": {
34467
34534
  "Schema": [
34468
34535
  {
34469
- "Id": "68efe4c7c1e4b04cc8f8d232",
34536
+ "Id": "_ID_DialogResponse_8d232",
34470
34537
  "Name": "DialogResponse",
34471
34538
  "DisplayName": "Dialog Response",
34472
34539
  "Type": 1,
@@ -34475,7 +34542,7 @@ const ConversationSchema = {
34475
34542
  "Specification": "displayTextTemplate=%7BText%7D",
34476
34543
  "Properties": [
34477
34544
  {
34478
- "Id": "68efe4c7c1e4b04cc8f8d22f",
34545
+ "Id": "_ID_68efe4c7c1e4b04cc8f8d22f",
34479
34546
  "SharedProperty": null,
34480
34547
  "Name": "Id",
34481
34548
  "DisplayName": "Id",
@@ -34489,7 +34556,7 @@ const ConversationSchema = {
34489
34556
  "Specification": "display=hidden"
34490
34557
  },
34491
34558
  {
34492
- "Id": "68efe4c7c1e4b04cc8f8d230",
34559
+ "Id": "_ID_68efe4c7c1e4b04cc8f8d230",
34493
34560
  "SharedProperty": null,
34494
34561
  "Name": "Text",
34495
34562
  "DisplayName": "Text",
@@ -34503,7 +34570,7 @@ const ConversationSchema = {
34503
34570
  "Specification": "editor=localized-text-multiline"
34504
34571
  },
34505
34572
  {
34506
- "Id": "68efe4edc1e4b04cc8f8d240",
34573
+ "Id": "_ID_68efe4edc1e4b04cc8f8d240",
34507
34574
  "SharedProperty": null,
34508
34575
  "Name": "NextNode",
34509
34576
  "DisplayName": "Next Node",
@@ -34513,14 +34580,14 @@ const ConversationSchema = {
34513
34580
  "Uniqueness": 0,
34514
34581
  "Requirement": 0,
34515
34582
  "ReferenceType": {
34516
- "Id": "68efe4cbc1e4b04cc8f8d239",
34583
+ "Id": "_ID_DialogNode_8d239",
34517
34584
  "DisplayName": "Dialog Node"
34518
34585
  },
34519
34586
  "Size": 0,
34520
34587
  "Specification": ""
34521
34588
  },
34522
34589
  {
34523
- "Id": "68efe4c7c1e4b04cc8f8d231",
34590
+ "Id": "_ID_68efe4c7c1e4b04cc8f8d231",
34524
34591
  "SharedProperty": null,
34525
34592
  "Name": "Specification",
34526
34593
  "DisplayName": "Specification",
@@ -34536,7 +34603,7 @@ const ConversationSchema = {
34536
34603
  ]
34537
34604
  },
34538
34605
  {
34539
- "Id": "68efe4cbc1e4b04cc8f8d239",
34606
+ "Id": "_ID_DialogNode_8d239",
34540
34607
  "Name": "DialogNode",
34541
34608
  "DisplayName": "Dialog Node",
34542
34609
  "Type": 1,
@@ -34545,7 +34612,7 @@ const ConversationSchema = {
34545
34612
  "Specification": "displayTextTemplate=%7BText%7D",
34546
34613
  "Properties": [
34547
34614
  {
34548
- "Id": "68efe4cbc1e4b04cc8f8d234",
34615
+ "Id": "_ID_68efe4cbc1e4b04cc8f8d234",
34549
34616
  "SharedProperty": null,
34550
34617
  "Name": "Id",
34551
34618
  "DisplayName": "Id",
@@ -34559,7 +34626,7 @@ const ConversationSchema = {
34559
34626
  "Specification": "display=hidden"
34560
34627
  },
34561
34628
  {
34562
- "Id": "68efe4cbc1e4b04cc8f8d235",
34629
+ "Id": "_ID_68efe4cbc1e4b04cc8f8d235",
34563
34630
  "SharedProperty": null,
34564
34631
  "Name": "Text",
34565
34632
  "DisplayName": "Text",
@@ -34573,7 +34640,7 @@ const ConversationSchema = {
34573
34640
  "Specification": "editor=localized-text-multiline"
34574
34641
  },
34575
34642
  {
34576
- "Id": "68efe4cbc1e4b04cc8f8d236",
34643
+ "Id": "_ID_68efe4cbc1e4b04cc8f8d236",
34577
34644
  "SharedProperty": null,
34578
34645
  "Name": "NextNode",
34579
34646
  "DisplayName": "Next Node",
@@ -34583,14 +34650,14 @@ const ConversationSchema = {
34583
34650
  "Uniqueness": 0,
34584
34651
  "Requirement": 0,
34585
34652
  "ReferenceType": {
34586
- "Id": "68efe4cbc1e4b04cc8f8d239",
34653
+ "Id": "_ID_DialogNode_8d239",
34587
34654
  "DisplayName": "Dialog Node"
34588
34655
  },
34589
34656
  "Size": 0,
34590
34657
  "Specification": ""
34591
34658
  },
34592
34659
  {
34593
- "Id": "68efe4cbc1e4b04cc8f8d237",
34660
+ "Id": "_ID_68efe4cbc1e4b04cc8f8d237",
34594
34661
  "SharedProperty": null,
34595
34662
  "Name": "Responses",
34596
34663
  "DisplayName": "Responses",
@@ -34600,14 +34667,14 @@ const ConversationSchema = {
34600
34667
  "Uniqueness": 0,
34601
34668
  "Requirement": 2,
34602
34669
  "ReferenceType": {
34603
- "Id": "68efe4c7c1e4b04cc8f8d232",
34670
+ "Id": "_ID_DialogResponse_8d232",
34604
34671
  "DisplayName": "Dialog Response"
34605
34672
  },
34606
34673
  "Size": 0,
34607
34674
  "Specification": ""
34608
34675
  },
34609
34676
  {
34610
- "Id": "68efe4cbc1e4b04cc8f8d238",
34677
+ "Id": "_ID_68efe4cbc1e4b04cc8f8d238",
34611
34678
  "SharedProperty": null,
34612
34679
  "Name": "Specification",
34613
34680
  "DisplayName": "Specification",
@@ -34623,7 +34690,7 @@ const ConversationSchema = {
34623
34690
  ]
34624
34691
  },
34625
34692
  {
34626
- "Id": "68efe4d3c1e4b04cc8f8d23e",
34693
+ "Id": "_ID_ConversationTree_8d23e",
34627
34694
  "Name": "ConversationTree",
34628
34695
  "DisplayName": "Conversation",
34629
34696
  "Type": 0,
@@ -34632,7 +34699,7 @@ const ConversationSchema = {
34632
34699
  "Specification": "editor=ext-conversation-editor&displayTextTemplate=%7BId%7D&icon=emoji%2Fspeech_balloon",
34633
34700
  "Properties": [
34634
34701
  {
34635
- "Id": "68efe4d3c1e4b04cc8f8d23b",
34702
+ "Id": "_ID_68efe4d3c1e4b04cc8f8d23b",
34636
34703
  "SharedProperty": null,
34637
34704
  "Name": "Id",
34638
34705
  "DisplayName": "Id",
@@ -34646,7 +34713,7 @@ const ConversationSchema = {
34646
34713
  "Specification": ""
34647
34714
  },
34648
34715
  {
34649
- "Id": "68efe527c1e4b04cc8f8d243",
34716
+ "Id": "_ID_68efe527c1e4b04cc8f8d243",
34650
34717
  "SharedProperty": null,
34651
34718
  "Name": "RootNode",
34652
34719
  "DisplayName": "Root Node",
@@ -34656,14 +34723,14 @@ const ConversationSchema = {
34656
34723
  "Uniqueness": 0,
34657
34724
  "Requirement": 2,
34658
34725
  "ReferenceType": {
34659
- "Id": "68efe4cbc1e4b04cc8f8d239",
34726
+ "Id": "_ID_DialogNode_8d239",
34660
34727
  "DisplayName": "Dialog Node"
34661
34728
  },
34662
34729
  "Size": 0,
34663
34730
  "Specification": ""
34664
34731
  },
34665
34732
  {
34666
- "Id": "68efe4d3c1e4b04cc8f8d23d",
34733
+ "Id": "_ID_68efe4d3c1e4b04cc8f8d23d",
34667
34734
  "SharedProperty": null,
34668
34735
  "Name": "Nodes",
34669
34736
  "DisplayName": "Nodes",
@@ -34673,14 +34740,14 @@ const ConversationSchema = {
34673
34740
  "Uniqueness": 0,
34674
34741
  "Requirement": 2,
34675
34742
  "ReferenceType": {
34676
- "Id": "68efe4cbc1e4b04cc8f8d239",
34743
+ "Id": "_ID_DialogNode_8d239",
34677
34744
  "DisplayName": "Dialog Node"
34678
34745
  },
34679
34746
  "Size": 0,
34680
34747
  "Specification": ""
34681
34748
  },
34682
34749
  {
34683
- "Id": "68efe4d3c1e4b04cc8f8d23c",
34750
+ "Id": "_ID_68efe4d3c1e4b04cc8f8d23c",
34684
34751
  "SharedProperty": null,
34685
34752
  "Name": "Specification",
34686
34753
  "DisplayName": "Specification",
@@ -34698,19 +34765,135 @@ const ConversationSchema = {
34698
34765
  ]
34699
34766
  }
34700
34767
  };
34768
+ const ConversationSchema = conversationSchema;
34769
+ async function migrateSchema(schema, dataSource) {
34770
+ var _a, _b, _c;
34771
+ const nodesProperty = schema.findSchemaProperty("Nodes");
34772
+ const dialogNodeSchema = nodesProperty && nodesProperty.dataType === DataType.DocumentCollection ? nodesProperty.getReferencedSchema() : null;
34773
+ const responsesProperty = dialogNodeSchema == null ? void 0 : dialogNodeSchema.findSchemaProperty("Responses");
34774
+ const responseSchema = responsesProperty && responsesProperty.dataType === DataType.DocumentCollection ? responsesProperty.getReferencedSchema() : null;
34775
+ const schemaQuery = from(dataSource.query([schema.id, dialogNodeSchema == null ? void 0 : dialogNodeSchema.id, responseSchema == null ? void 0 : responseSchema.id].filter((id2) => Boolean(id2)).map((uniqueSchemaPropertyValue) => ({ schemaNameOrId: "Schema", uniqueSchemaPropertyNameOrId: "Id", uniqueSchemaPropertyValue }))));
34776
+ const existingSchemaDocuments = await firstValueFrom(schemaQuery);
34777
+ const expectedConversationTreeSchemaDocument = ConversationSchema.Collections.Schema.find((schemaDocument) => schemaDocument.Name === "ConversationTree");
34778
+ const expectedDialogNodeSchemaDocument = ConversationSchema.Collections.Schema.find((schemaDocument) => schemaDocument.Name === "DialogNode");
34779
+ const expectedDialogResponseSchemaDocument = ConversationSchema.Collections.Schema.find((schemaDocument) => schemaDocument.Name === "DialogResponse");
34780
+ const conversationTreeSchemaDocument = deepClone(((_a = existingSchemaDocuments.find((result) => {
34781
+ var _a2;
34782
+ return String((_a2 = result.document) == null ? void 0 : _a2.Id) === schema.id;
34783
+ })) == null ? void 0 : _a.document) ?? expectedConversationTreeSchemaDocument);
34784
+ const dialogNodeSchemaDocument = deepClone(((_b = existingSchemaDocuments.find((result) => {
34785
+ var _a2;
34786
+ return String((_a2 = result.document) == null ? void 0 : _a2.Id) === (dialogNodeSchema == null ? void 0 : dialogNodeSchema.id);
34787
+ })) == null ? void 0 : _b.document) ?? expectedDialogNodeSchemaDocument);
34788
+ const dialogResponseSchemaDocument = deepClone(((_c = existingSchemaDocuments.find((result) => {
34789
+ var _a2;
34790
+ return String((_a2 = result.document) == null ? void 0 : _a2.Id) === (responseSchema == null ? void 0 : responseSchema.id);
34791
+ })) == null ? void 0 : _c.document) ?? expectedDialogResponseSchemaDocument);
34792
+ updateProperties(conversationTreeSchemaDocument, expectedConversationTreeSchemaDocument);
34793
+ updateProperties(dialogNodeSchemaDocument, expectedDialogNodeSchemaDocument);
34794
+ updateProperties(dialogResponseSchemaDocument, expectedDialogResponseSchemaDocument);
34795
+ updateRefrenceType(conversationTreeSchemaDocument, "RootNode", dialogNodeSchemaDocument);
34796
+ updateRefrenceType(conversationTreeSchemaDocument, "Nodes", dialogNodeSchemaDocument);
34797
+ updateRefrenceType(dialogNodeSchemaDocument, "NextNode", dialogNodeSchemaDocument);
34798
+ updateRefrenceType(dialogNodeSchemaDocument, "Responses", dialogResponseSchemaDocument);
34799
+ updateRefrenceType(dialogResponseSchemaDocument, "NextNode", dialogNodeSchemaDocument);
34800
+ const importDocuments = {
34801
+ Collections: {
34802
+ Schema: [
34803
+ conversationTreeSchemaDocument,
34804
+ dialogNodeSchemaDocument,
34805
+ dialogResponseSchemaDocument
34806
+ ]
34807
+ }
34808
+ };
34809
+ const importQuery = from(
34810
+ dataSource.import(
34811
+ // type of documents to import = Schema
34812
+ ["Schema"],
34813
+ // languages = all
34814
+ [],
34815
+ // documents
34816
+ importDocuments,
34817
+ // import mode
34818
+ ImportMode.createAndUpdate,
34819
+ // validation options = default for creation/updating
34820
+ [
34821
+ ValidationOption.repair,
34822
+ ValidationOption.repairRequiredWithDefaults,
34823
+ ValidationOption.checkRequirements,
34824
+ ValidationOption.checkFormat,
34825
+ ValidationOption.checkReferences,
34826
+ ValidationOption.checkUniqueness,
34827
+ ValidationOption.checkSpecification,
34828
+ ValidationOption.checkConstraints
34829
+ ],
34830
+ // dry run = no
34831
+ void 0
34832
+ )
34833
+ );
34834
+ await firstValueFrom(importQuery);
34835
+ }
34836
+ function deepClone(value) {
34837
+ return JSON.parse(JSON.stringify(value));
34838
+ }
34839
+ function updateProperties(schemaDocument, expectedSchemaDocument) {
34840
+ const properties = schemaDocument.Properties ?? [];
34841
+ const expectedProperties = expectedSchemaDocument.Properties ?? [];
34842
+ for (const expectedProperty of expectedProperties) {
34843
+ const existingProperty = properties.find((propertyDocument) => String(propertyDocument.Name) === String(expectedProperty.Name));
34844
+ if (existingProperty && existingProperty.Name === "Id") {
34845
+ continue;
34846
+ } else if (existingProperty) {
34847
+ updateProperty(existingProperty, expectedProperty);
34848
+ } else {
34849
+ properties.push(deepClone(expectedProperty));
34850
+ }
34851
+ }
34852
+ schemaDocument.Properties = properties;
34853
+ }
34854
+ function updateProperty(schemaPropertyDocument, expectedSchemaPropertyDocument) {
34855
+ for (const propertyName in expectedSchemaPropertyDocument) {
34856
+ if (!Object.prototype.hasOwnProperty.call(expectedSchemaPropertyDocument, propertyName)) continue;
34857
+ const propertyValue = expectedSchemaPropertyDocument[propertyName];
34858
+ schemaPropertyDocument[propertyName] = propertyValue;
34859
+ }
34860
+ }
34861
+ function updateRefrenceType(schemaDocument, propertyName, referencedSchema) {
34862
+ var _a;
34863
+ const properties = schemaDocument.Properties ?? [];
34864
+ const property = properties.find((propertyDocument) => String(propertyDocument.Name) === propertyName);
34865
+ if (!property) {
34866
+ return;
34867
+ }
34868
+ if (![DataType.Document, DataType.DocumentCollection, DataType.Reference, DataType.ReferenceCollection].includes(property.DataType)) {
34869
+ return;
34870
+ }
34871
+ const schemaReference = { Id: String(referencedSchema.Id), DisplayName: String(referencedSchema.DisplayName) };
34872
+ if (((_a = property.ReferenceType) == null ? void 0 : _a.Id) === schemaReference.Id) {
34873
+ return;
34874
+ }
34875
+ property.ReferenceType = schemaReference;
34876
+ }
34701
34877
  function SchemaValidationResult({ documentControl }) {
34702
34878
  const errors = validateSchema(documentControl.schema);
34703
34879
  const validationResult = { isValid: !errors.length, errors };
34704
- const copySchemaHandler = reactExports.useCallback(() => {
34705
- const textToCopy = JSON.stringify(ConversationSchema);
34706
- navigator.clipboard.writeText(textToCopy).catch((error) => {
34707
- console.error("Failed to copy text to clipboard: ", error);
34708
- });
34709
- }, []);
34880
+ const [migrationError, setMigrationError] = reactExports.useState("");
34881
+ const services = getRootDocumentControl(documentControl).services;
34882
+ const dataService = services.dataService;
34883
+ const [migrateIsPending, setMigrateIsPending] = reactExports.useState(false);
34884
+ const migrateSchemaHandler = reactExports.useCallback(() => {
34885
+ setMigrateIsPending(true);
34886
+ setMigrationError("");
34887
+ migrateSchema(documentControl.schema, dataService).catch((error) => setMigrationError(String(error))).catch((error) => console.error(error)).then(() => window.location.reload()).finally(() => setMigrateIsPending(false));
34888
+ }, [dataService, documentControl]);
34710
34889
  return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ext-ce-schema-validation-container", children: [
34711
34890
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ext-ce-validation-header", children: [
34712
34891
  /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { children: "Schema Validation" }),
34713
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "This editor requires a specific document schema to function properly. You can correct the errors listed below or import the entire schema directly." }),
34892
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
34893
+ "This editor requires a specific document schema to function properly. You can correct the errors listed below or",
34894
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "migrate" }),
34895
+ " the schema to the required format."
34896
+ ] }),
34714
34897
  validationResult.isValid ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ext-ce-validation-status valid", children: [
34715
34898
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ext-ce-status-icon", children: "✓" }),
34716
34899
  "Schema is valid"
@@ -34727,35 +34910,20 @@ function SchemaValidationResult({ documentControl }) {
34727
34910
  validationResult.errors.map((error, index2) => /* @__PURE__ */ jsxRuntimeExports.jsx(ValidationErrorItem, { error }, index2))
34728
34911
  ] }),
34729
34912
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ext-ce-schema-import", children: [
34730
- /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { children: "Importing Schema" }),
34731
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "You can create a proper data schema for the dialog editor by importing it:" }),
34732
- /* @__PURE__ */ jsxRuntimeExports.jsxs("ol", { children: [
34733
- /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
34734
- "Go to ",
34735
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Dashboard" }),
34736
- " → ",
34737
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Import Documents" })
34738
- ] }),
34739
- /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
34740
- "Option: Create and Update ",
34741
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Next" })
34742
- ] }),
34743
- /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
34744
- "Option: Clipboard → ",
34745
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Next" })
34746
- ] }),
34747
- /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
34748
- "Click the ",
34749
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ext-ce-copy-button", onClick: copySchemaHandler, children: "Copy Schema" }),
34750
- " and paste into the input field → ",
34751
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Next" })
34752
- ] }),
34753
- /* @__PURE__ */ jsxRuntimeExports.jsxs("li", { children: [
34754
- "Checkbox All → ",
34755
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Import" })
34756
- ] })
34757
- ] })
34758
- ] })
34913
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { children: "Schema Migration" }),
34914
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { children: [
34915
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Migrate" }),
34916
+ " the ",
34917
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ext-ce-schema-name", children: documentControl.schema.displayName }),
34918
+ " schema to the required structure. This action will attempt to fix structural issues while preserving existing data."
34919
+ ] }),
34920
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "ext-ce-migrate-button", onClick: migrateSchemaHandler, disabled: migrateIsPending, children: "Migrate Schema" })
34921
+ ] }),
34922
+ migrationError && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ext-ce-validation-error-item", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ext-ce-error-message", children: [
34923
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Schema Migration Error:" }),
34924
+ " ",
34925
+ migrationError
34926
+ ] }) })
34759
34927
  ] }) });
34760
34928
  }
34761
34929
  function ValidationErrorItem({ error }) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://raw.githubusercontent.com/gamedevware/charon-extensions/refs/heads/main/package.json.schema.json",
3
3
  "name": "charon-conversation-editor",
4
- "version": "0.0.20",
4
+ "version": "0.0.29",
5
5
  "description": "",
6
6
  "keywords": [
7
7
  "charon",
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "dependencies": {
40
40
  "@xyflow/react": "^12.8.6",
41
- "charon-extensions": "2.314.388",
41
+ "charon-extensions": "2.317.395",
42
42
  "dagre": "^0.8.5",
43
43
  "react": "^19.2.0",
44
44
  "react-dom": "^19.2.0",
@@ -61,4 +61,4 @@
61
61
  "typescript-eslint": "^8.24.1",
62
62
  "vite": "^6.2.0"
63
63
  }
64
- }
64
+ }