tinacms 0.66.9 → 0.66.10

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/dist/index.es.js CHANGED
@@ -32,12 +32,13 @@ var __objRest = (source, exclude) => {
32
32
  import { useCMS, useBranchData, FormMetaPlugin, Form, GlobalFormPlugin, EventBus, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, Nav, LocalWarning, FormStatus, FormBuilder } from "@tinacms/toolkit";
33
33
  export * from "@tinacms/toolkit";
34
34
  import * as G from "graphql";
35
- import { TypeInfo, visit, visitWithTypeInfo, getNamedType, GraphQLObjectType, isLeafType, GraphQLUnionType, isScalarType, getIntrospectionQuery, buildClientSchema, print, parse } from "graphql";
35
+ import { TypeInfo, visit, visitWithTypeInfo, getNamedType, GraphQLObjectType, isLeafType, GraphQLUnionType, isScalarType as isScalarType$1, getIntrospectionQuery, buildClientSchema, print, parse } from "graphql";
36
36
  import set from "lodash.set";
37
37
  import React, { useState, useCallback, useEffect, Fragment, useMemo } from "react";
38
38
  import { getIn, setIn } from "final-form";
39
- import * as yup from "yup";
39
+ import { resolveForm, TinaSchema, addNamespaceToSchema } from "@tinacms/schema-tools";
40
40
  import gql$1 from "graphql-tag";
41
+ import * as yup from "yup";
41
42
  import styled from "styled-components";
42
43
  import { setEditing, TinaDataContext, useEditState } from "@tinacms/sharedctx";
43
44
  import UrlPattern from "url-pattern";
@@ -287,7 +288,7 @@ const buildSelectionsFields = (fields, callback) => {
287
288
  const result = callback(fields);
288
289
  if (!result.continue) {
289
290
  if (fields.every((field) => {
290
- return !isScalarType(getNamedType(field.type));
291
+ return !isScalarType$1(getNamedType(field.type));
291
292
  })) {
292
293
  return [
293
294
  {
@@ -300,7 +301,7 @@ const buildSelectionsFields = (fields, callback) => {
300
301
  ];
301
302
  }
302
303
  return buildSelectionsFields(result.filteredFields.filter((field) => {
303
- if (isScalarType(getNamedType(field.type))) {
304
+ if (isScalarType$1(getNamedType(field.type))) {
304
305
  return true;
305
306
  }
306
307
  return false;
@@ -380,13 +381,15 @@ const createClient = ({
380
381
  clientId,
381
382
  isLocalClient = true,
382
383
  branch,
383
- tinaioConfig
384
+ tinaioConfig,
385
+ schema
384
386
  }) => {
385
- return isLocalClient ? new LocalClient() : new Client({
387
+ return isLocalClient ? new LocalClient({ schema }) : new Client({
386
388
  clientId: clientId || "",
387
389
  branch: branch || "main",
388
390
  tokenStorage: "LOCAL_STORAGE",
389
- tinaioConfig
391
+ tinaioConfig,
392
+ schema
390
393
  });
391
394
  };
392
395
  function assertShape(value, yupSchema, errorMessage) {
@@ -515,11 +518,10 @@ function useGraphqlForms({
515
518
  values: yup2.object().required(),
516
519
  form: yup2.object().required()
517
520
  }), `Unable to build form shape for fields at ${queryName}`);
518
- const formConfig = {
521
+ let formConfig = {};
522
+ const formCommon = {
519
523
  id: queryName,
520
- label: result.form.label,
521
524
  initialValues: result.values,
522
- fields: result.form.fields,
523
525
  reset: () => {
524
526
  setPendingReset(queryName);
525
527
  },
@@ -551,6 +553,29 @@ function useGraphqlForms({
551
553
  }
552
554
  }
553
555
  };
556
+ if (cms.api.tina.schema) {
557
+ const enrichedSchema = cms.api.tina.schema;
558
+ const collection = enrichedSchema.getCollection(result._internalSys.collection.name);
559
+ const template = enrichedSchema.getTemplateForData({
560
+ collection,
561
+ data: result.values
562
+ });
563
+ const formInfo = resolveForm({
564
+ collection,
565
+ basename: collection.name,
566
+ schema: enrichedSchema,
567
+ template
568
+ });
569
+ formConfig = __spreadValues({
570
+ label: formInfo.label,
571
+ fields: formInfo.fields
572
+ }, formCommon);
573
+ } else {
574
+ formConfig = __spreadValues({
575
+ label: result.form.label,
576
+ fields: result.form.fields
577
+ }, formCommon);
578
+ }
554
579
  const { createForm, createGlobalForm } = generateFormCreators(cms);
555
580
  const SKIPPED = "SKIPPED";
556
581
  let form;
@@ -722,100 +747,7 @@ const generateFormCreatorsUnstable = (cms, showInSidebar) => {
722
747
  };
723
748
  return { createForm, createGlobalForm };
724
749
  };
725
- const isNodeField = (type) => {
726
- if (G.isUnionType(type)) {
727
- return type.getTypes().every((type2) => {
728
- return type2.getInterfaces().find((intfc) => intfc.name === "Node");
729
- });
730
- } else if (G.isObjectType(type)) {
731
- return !!type.getInterfaces().find((intfc) => intfc.name === "Node");
732
- } else if (G.isInterfaceType(type)) {
733
- if (type.name === "Node") {
734
- return true;
735
- }
736
- } else {
737
- return false;
738
- }
739
- };
740
- const isConnectionField = (type) => {
741
- if (G.isObjectType(type)) {
742
- return !!type.getInterfaces().find((intfc) => intfc.name === "Connection");
743
- } else {
744
- throw new Error(`Expected GraphQLObjectType for isConnectionField check`);
745
- }
746
- };
747
- const getObjectField = (object, selectionNode) => {
748
- return object.getFields()[selectionNode.name.value];
749
- };
750
- const getSelectedUnionType = (unionType, selectionNode) => {
751
- return unionType.getTypes().find((type) => type.name === selectionNode.typeCondition.name.value);
752
- };
753
- function isListType(type) {
754
- if (G.isListType(type)) {
755
- return true;
756
- } else if (G.isNonNullType(type)) {
757
- if (G.isListType(type.ofType)) {
758
- return true;
759
- }
760
- }
761
- return false;
762
- }
763
- function ensureNodeField(field) {
764
- if (!isNodeField(field)) {
765
- throw new Error(`Expected field to implement Node interface`);
766
- }
767
- }
768
- function ensureUnionType(type) {
769
- if (!G.isUnionType(type)) {
770
- throw new Error(`Expected type to be GraphQLUnionType`);
771
- }
772
- }
773
- function ensureObjectType(type) {
774
- if (!G.isObjectType(type)) {
775
- console.log(type);
776
- throw new Error(`Expected type to be GraphQLObjectType`);
777
- }
778
- }
779
- function ensureOperationDefinition(type) {
780
- if (type.kind !== "OperationDefinition") {
781
- throw new Error(`Expected top-level definition to be an OperationDefinition node, ensure your query has been optimized before calling formify`);
782
- }
783
- }
784
- function getNameAndAlias(fieldNode, list, isNode) {
785
- return {
786
- name: fieldNode.name.value,
787
- alias: fieldNode.alias ? fieldNode.alias.value : fieldNode.name.value,
788
- list: !!list,
789
- isNode: !!isNode
790
- };
791
- }
792
- const node = G.parse(`
793
- query Sample {
794
- _internalSys: sys {
795
- path
796
- collection {
797
- name
798
- }
799
- }
800
- form
801
- values
802
- }`);
803
- const metaFields = node.definitions[0].selectionSet.selections;
804
- const getRelativeBlueprint = (path) => {
805
- let indexOfLastNode = 0;
806
- path.forEach((item, i) => {
807
- if (item.isNode) {
808
- if (i === path.length - 1)
809
- ;
810
- else {
811
- indexOfLastNode = i;
812
- }
813
- }
814
- });
815
- const documentBlueprintPath = path.slice(0, indexOfLastNode + 1);
816
- return getBlueprintNamePath({ path: documentBlueprintPath });
817
- };
818
- const getIn2 = (state, path) => {
750
+ const getValueForBlueprint = (state, path) => {
819
751
  const pathArray = path.split(".");
820
752
  let latest = state;
821
753
  pathArray.every((item, index) => {
@@ -825,7 +757,7 @@ const getIn2 = (state, path) => {
825
757
  const next = [];
826
758
  if (Array.isArray(latest)) {
827
759
  latest.forEach((latest2, index2) => {
828
- const res = getIn2(latest2, restOfItems.join("."));
760
+ const res = getValueForBlueprint(latest2, restOfItems.join("."));
829
761
  next.push(res);
830
762
  });
831
763
  } else {
@@ -892,9 +824,8 @@ const buildForm = (doc, cms, formify2, showInSidebar = false, onSubmit) => {
892
824
  if (skipped)
893
825
  return;
894
826
  const id = doc._internalSys.path;
895
- const formConfig = __spreadProps(__spreadValues({
896
- id
897
- }, doc.form), {
827
+ const formCommon = {
828
+ id,
898
829
  label: doc.form.label,
899
830
  initialValues: doc.values,
900
831
  onSubmit: async (payload) => {
@@ -924,7 +855,31 @@ const buildForm = (doc, cms, formify2, showInSidebar = false, onSubmit) => {
924
855
  cms.alerts.error("There was a problem saving your document");
925
856
  }
926
857
  }
927
- });
858
+ };
859
+ let formConfig = {};
860
+ if (cms.api.tina.schema) {
861
+ const enrichedSchema = cms.api.tina.schema;
862
+ const collection = enrichedSchema.getCollection(doc._internalSys.collection.name);
863
+ const template = enrichedSchema.getTemplateForData({
864
+ collection,
865
+ data: doc.values
866
+ });
867
+ const formInfo = resolveForm({
868
+ collection,
869
+ basename: collection.name,
870
+ schema: enrichedSchema,
871
+ template
872
+ });
873
+ formConfig = __spreadValues({
874
+ label: formInfo.label,
875
+ fields: formInfo.fields
876
+ }, formCommon);
877
+ } else {
878
+ formConfig = __spreadValues({
879
+ label: doc.form.label,
880
+ fields: doc.form.fields
881
+ }, formCommon);
882
+ }
928
883
  if (formify2) {
929
884
  form = formify2({
930
885
  formConfig,
@@ -970,19 +925,6 @@ const sequential = async (items, callback) => {
970
925
  }
971
926
  return accum;
972
927
  };
973
- const getBlueprintId = (path) => {
974
- const namePath = [];
975
- const aliasPath = [];
976
- path.forEach((p) => {
977
- namePath.push(p.name);
978
- aliasPath.push(p.alias);
979
- if (p.list) {
980
- namePath.push("[]");
981
- aliasPath.push("[]");
982
- }
983
- });
984
- return namePath.join(".");
985
- };
986
928
  const getFormNodesStartingWith = (string, state) => {
987
929
  return state.formNodes.filter((subFormNode) => {
988
930
  return subFormNode.documentBlueprintId.startsWith(string);
@@ -998,44 +940,6 @@ const getFormNodesForField = (fieldBlueprint, formNode, event, state) => {
998
940
  const existing = getIn(state.data, pathToChange);
999
941
  return { pathToChange, formNodes, eventLocation, existing };
1000
942
  };
1001
- const matchLocation = (eventLocation, formNode) => {
1002
- return eventLocation.every((item, index) => item === formNode.location[index]);
1003
- };
1004
- const bumpLocation = (location) => {
1005
- return location.map((item, index) => {
1006
- if (index === location.length - 1) {
1007
- return item + 1;
1008
- }
1009
- return item;
1010
- });
1011
- };
1012
- const maybeLowerLocation = (location, at) => {
1013
- return location.map((item, index) => {
1014
- if (index === location.length - 1) {
1015
- return item < at ? item : item - 1;
1016
- }
1017
- return item;
1018
- });
1019
- };
1020
- const matchesAt = (location, at) => {
1021
- let matches = false;
1022
- location.map((item, index) => {
1023
- if (index === location.length - 1) {
1024
- if (item === at) {
1025
- matches = true;
1026
- }
1027
- }
1028
- });
1029
- return matches;
1030
- };
1031
- const swapLocation = (location, mapping) => {
1032
- return location.map((item, index) => {
1033
- if (index === location.length - 1) {
1034
- return mapping[item];
1035
- }
1036
- return item;
1037
- });
1038
- };
1039
943
  const getBlueprintAliasPath = (blueprint) => {
1040
944
  const namePath = [];
1041
945
  const aliasPath = [];
@@ -1051,22 +955,56 @@ const getBlueprintAliasPath = (blueprint) => {
1051
955
  };
1052
956
  const getBlueprintFieldsForEvent = (blueprint, event) => {
1053
957
  return blueprint.fields.filter((fbp) => {
1054
- return getBlueprintNamePath(fbp) === getEventPath(event, blueprint);
958
+ if (getBlueprintNamePath(fbp) === getEventPath(event, blueprint)) {
959
+ return true;
960
+ }
961
+ }).filter((fbp) => {
962
+ return filterFieldBlueprintsByParentTypename(fbp, event.field.data.tinaField.parentTypename);
963
+ });
964
+ };
965
+ const filterFieldBlueprintsByParentTypename = (fbp, typename) => {
966
+ let lastDisambiguator;
967
+ fbp.path.forEach((path) => {
968
+ if (path.parentTypename) {
969
+ lastDisambiguator = path.parentTypename;
970
+ }
1055
971
  });
972
+ if (lastDisambiguator) {
973
+ return typename === lastDisambiguator;
974
+ } else {
975
+ return true;
976
+ }
1056
977
  };
1057
- const getBlueprintNamePath = (blueprint) => {
978
+ const getBlueprintNamePath = (blueprint, disambiguator) => {
1058
979
  const namePath = [];
1059
- const aliasPath = [];
1060
980
  blueprint.path.forEach((p) => {
981
+ if (disambiguator) {
982
+ if (p.parentTypename) {
983
+ namePath.push(p.parentTypename);
984
+ }
985
+ }
1061
986
  namePath.push(p.name);
1062
- aliasPath.push(p.alias);
1063
987
  if (p.list) {
1064
988
  namePath.push("[]");
1065
- aliasPath.push("[]");
1066
989
  }
1067
990
  });
1068
991
  return namePath.join(".");
1069
992
  };
993
+ const getEventPath = (event, blueprint) => {
994
+ const stringArray = event.field.name.split(".");
995
+ const eventPath = stringArray.map((item) => {
996
+ if (isNaN(Number(item))) {
997
+ return item;
998
+ }
999
+ return `[]`;
1000
+ }).join(".");
1001
+ const items = [blueprint.id, DATA_NODE_NAME$1, eventPath];
1002
+ const isList = event.field.data.tinaField.list;
1003
+ if (isList && !eventPath.endsWith("[]")) {
1004
+ items.push(`[]`);
1005
+ }
1006
+ return items.join(".");
1007
+ };
1070
1008
  const stripIndices = (string) => {
1071
1009
  const accum = [];
1072
1010
  const stringArray = string.split(".");
@@ -1088,20 +1026,21 @@ const replaceRealNum = (string) => {
1088
1026
  return "[]";
1089
1027
  }).join(".");
1090
1028
  };
1029
+ const getMatchName = ({ field, prefix, blueprint }) => {
1030
+ const fieldName = field.list ? `${field.name}.[]` : field.name;
1031
+ const blueprintName = getBlueprintNamePath(blueprint);
1032
+ const extra = [];
1033
+ if (prefix) {
1034
+ extra.push(prefix);
1035
+ }
1036
+ const matchName = [blueprintName, DATA_NODE_NAME$1, ...extra, fieldName].join(".");
1037
+ return { matchName, fieldName };
1038
+ };
1091
1039
  const getFormNodesFromEvent = (state, event) => {
1092
1040
  const formNodes = state.formNodes.filter((formNode) => formNode.documentFormId === event.formId);
1093
1041
  return formNodes;
1094
1042
  };
1095
1043
  const DATA_NODE_NAME$1 = "data";
1096
- const getEventPath = (event, blueprint) => {
1097
- const eventPath = replaceRealNum(event.field.name);
1098
- const items = [blueprint.id, DATA_NODE_NAME$1, eventPath];
1099
- const isList = event.field.data.tinaField.list;
1100
- if (isList && !eventPath.endsWith("[]")) {
1101
- items.push("[]");
1102
- }
1103
- return items.join(".");
1104
- };
1105
1044
  const printEvent = (event) => {
1106
1045
  var _a, _b;
1107
1046
  return {
@@ -1170,17 +1109,43 @@ const getMoveMapping = (existing, from, to) => {
1170
1109
  }
1171
1110
  return newOrderObject;
1172
1111
  };
1173
- const getPathsToChange = (event, state) => {
1174
- const pathsToChange = [];
1175
- const formNodes = getFormNodesFromEvent(state, event);
1176
- formNodes.forEach((formNode) => {
1177
- const blueprint = getFormNodeBlueprint(formNode, state);
1178
- getBlueprintFieldsForEvent(blueprint, event).forEach((fieldBlueprint) => {
1179
- const pathToChange = getPathToChange(fieldBlueprint, formNode, event);
1180
- pathsToChange.push({ pathToChange, formNode });
1181
- });
1112
+ const matchLocation = (eventLocation, formNode) => {
1113
+ return eventLocation.every((item, index) => item === formNode.location[index]);
1114
+ };
1115
+ const bumpLocation = (location) => {
1116
+ return location.map((item, index) => {
1117
+ if (index === location.length - 1) {
1118
+ return item + 1;
1119
+ }
1120
+ return item;
1121
+ });
1122
+ };
1123
+ const maybeLowerLocation = (location, at) => {
1124
+ return location.map((item, index) => {
1125
+ if (index === location.length - 1) {
1126
+ return item < at ? item : item - 1;
1127
+ }
1128
+ return item;
1129
+ });
1130
+ };
1131
+ const matchesAt = (location, at) => {
1132
+ let matches = false;
1133
+ location.map((item, index) => {
1134
+ if (index === location.length - 1) {
1135
+ if (item === at) {
1136
+ matches = true;
1137
+ }
1138
+ }
1139
+ });
1140
+ return matches;
1141
+ };
1142
+ const swapLocation = (location, mapping) => {
1143
+ return location.map((item, index) => {
1144
+ if (index === location.length - 1) {
1145
+ return mapping[item];
1146
+ }
1147
+ return item;
1182
1148
  });
1183
- return pathsToChange;
1184
1149
  };
1185
1150
  const getSubFields = (changeSet) => {
1186
1151
  var _a;
@@ -1191,6 +1156,133 @@ const getSubFields = (changeSet) => {
1191
1156
  }
1192
1157
  return { fields, __typename };
1193
1158
  };
1159
+ const isFormifiableDocument = (t) => {
1160
+ const type = G.getNamedType(t);
1161
+ if (G.isUnionType(type)) {
1162
+ return type.getTypes().every((type2) => {
1163
+ return type2.getInterfaces().find((intfc) => intfc.name === "Node");
1164
+ });
1165
+ } else if (G.isObjectType(type)) {
1166
+ return !!type.getInterfaces().find((intfc) => intfc.name === "Node");
1167
+ } else {
1168
+ return false;
1169
+ }
1170
+ };
1171
+ const isScalarType = (t) => {
1172
+ const namedType = G.getNamedType(t);
1173
+ return G.isScalarType(namedType);
1174
+ };
1175
+ const isConnectionField = (t) => {
1176
+ const type = G.getNamedType(t);
1177
+ if (G.isObjectType(type)) {
1178
+ return !!type.getInterfaces().find((intfc) => intfc.name === "Connection");
1179
+ } else {
1180
+ throw new Error(`Expected GraphQLObjectType for isConnectionField check`);
1181
+ }
1182
+ };
1183
+ const getObjectField = (object, selectionNode) => {
1184
+ const namedType = G.getNamedType(object);
1185
+ ensureObjectOrInterfaceType(namedType);
1186
+ return namedType.getFields()[selectionNode.name.value];
1187
+ };
1188
+ const getSelectedUnionType = (unionType, selectionNode) => {
1189
+ const namedType = G.getNamedType(unionType);
1190
+ if (!G.isUnionType(namedType)) {
1191
+ return;
1192
+ }
1193
+ const types = namedType.getTypes();
1194
+ const typeCondition = selectionNode.typeCondition.name.value;
1195
+ let intfc;
1196
+ types.forEach((type) => {
1197
+ intfc = type.getInterfaces().find((intfc2) => intfc2.name === typeCondition);
1198
+ });
1199
+ if (intfc) {
1200
+ return intfc;
1201
+ }
1202
+ return namedType.getTypes().find((type) => type.name === typeCondition);
1203
+ };
1204
+ function isListType(type) {
1205
+ if (G.isListType(type)) {
1206
+ return true;
1207
+ } else if (G.isNonNullType(type)) {
1208
+ if (G.isListType(type.ofType)) {
1209
+ return true;
1210
+ }
1211
+ }
1212
+ return false;
1213
+ }
1214
+ function ensureObjectOrInterfaceType(type) {
1215
+ if (G.isInterfaceType(type) || G.isObjectType(type))
1216
+ ;
1217
+ else {
1218
+ console.log("Expected type to be GraphQLObjectType or GraphQLInterfaceType", type);
1219
+ throw new Error(`Expected type to be GraphQLObjectType or GraphQLInterfaceType`);
1220
+ }
1221
+ }
1222
+ function ensureOperationDefinition(type) {
1223
+ if (type.kind !== "OperationDefinition") {
1224
+ throw new Error(`Expected top-level definition to be an OperationDefinition node, ensure your query has been optimized before calling formify`);
1225
+ }
1226
+ }
1227
+ function buildPath({
1228
+ fieldNode,
1229
+ type,
1230
+ parentTypename,
1231
+ path
1232
+ }) {
1233
+ const p = path || [];
1234
+ const list = isListType(type);
1235
+ const isNode = isFormifiableDocument(type);
1236
+ return [
1237
+ ...p,
1238
+ {
1239
+ name: fieldNode.name.value,
1240
+ alias: fieldNode.alias ? fieldNode.alias.value : fieldNode.name.value,
1241
+ parentTypename,
1242
+ list: !!list,
1243
+ isNode: !!isNode
1244
+ }
1245
+ ];
1246
+ }
1247
+ const node = G.parse(`
1248
+ query Sample {
1249
+ _internalSys: sys {
1250
+ path
1251
+ collection {
1252
+ name
1253
+ }
1254
+ }
1255
+ form
1256
+ values
1257
+ }`);
1258
+ const metaFields = node.definitions[0].selectionSet.selections;
1259
+ const getRelativeBlueprint = (path) => {
1260
+ let indexOfLastNode = 0;
1261
+ path.forEach((item, i) => {
1262
+ if (item.isNode) {
1263
+ if (i === path.length - 1)
1264
+ ;
1265
+ else {
1266
+ indexOfLastNode = i;
1267
+ }
1268
+ }
1269
+ });
1270
+ const documentBlueprintPath = path.slice(0, indexOfLastNode + 1);
1271
+ return getBlueprintNamePath({ path: documentBlueprintPath });
1272
+ };
1273
+ const getBlueprintId = (path) => {
1274
+ const namePath = [];
1275
+ const aliasPath = [];
1276
+ path.forEach((p) => {
1277
+ namePath.push(p.name);
1278
+ aliasPath.push(p.alias);
1279
+ if (p.list) {
1280
+ namePath.push("[]");
1281
+ aliasPath.push("[]");
1282
+ }
1283
+ });
1284
+ return namePath.join(".");
1285
+ };
1194
1286
  const NOOP = "This is either an error or is not yet supported";
1195
1287
  const UNEXPECTED = "Formify encountered an unexpected error, please contact support";
1196
1288
  const EDGES_NODE_NAME = "edges";
@@ -1223,11 +1315,10 @@ const formify = async ({
1223
1315
  const optimizedQuery = await getOptimizedQuery(documentNodeWithName);
1224
1316
  const typeInfo = new G.TypeInfo(schema);
1225
1317
  const formifyConnection = ({
1226
- namedFieldType,
1318
+ parentType,
1227
1319
  selectionNode,
1228
1320
  path
1229
1321
  }) => {
1230
- ensureObjectType(namedFieldType);
1231
1322
  return __spreadProps(__spreadValues({}, selectionNode), {
1232
1323
  selectionSet: {
1233
1324
  kind: "SelectionSet",
@@ -1235,13 +1326,12 @@ const formify = async ({
1235
1326
  switch (selectionNode2.kind) {
1236
1327
  case "Field":
1237
1328
  if (selectionNode2.name.value === EDGES_NODE_NAME) {
1238
- const edgeField = namedFieldType.getFields()[EDGES_NODE_NAME];
1239
- const edgeType = G.getNamedType(edgeField.type);
1240
- ensureObjectType(edgeType);
1241
- const path2 = [
1242
- ...path,
1243
- getNameAndAlias(selectionNode2, true, false)
1244
- ];
1329
+ const edgeField = getObjectField(parentType, selectionNode2);
1330
+ const edgesPath = buildPath({
1331
+ fieldNode: selectionNode2,
1332
+ type: edgeField.type,
1333
+ path
1334
+ });
1245
1335
  return __spreadProps(__spreadValues({}, selectionNode2), {
1246
1336
  selectionSet: {
1247
1337
  kind: "SelectionSet",
@@ -1249,15 +1339,15 @@ const formify = async ({
1249
1339
  switch (subSelectionNode.kind) {
1250
1340
  case "Field":
1251
1341
  if (subSelectionNode.name.value === NODE_NAME) {
1252
- const nodeField = edgeType.getFields()[NODE_NAME];
1253
- const path3 = [
1254
- ...path2,
1255
- getNameAndAlias(subSelectionNode, false, true)
1256
- ];
1257
- return formifyNode({
1258
- fieldOrInlineFragmentNode: subSelectionNode,
1342
+ const nodeField = getObjectField(edgeField.type, subSelectionNode);
1343
+ return formifyFieldNodeDocument({
1344
+ fieldNode: subSelectionNode,
1259
1345
  type: nodeField.type,
1260
- path: path3,
1346
+ path: buildPath({
1347
+ fieldNode: subSelectionNode,
1348
+ type: nodeField.type,
1349
+ path: edgesPath
1350
+ }),
1261
1351
  showInSidebar: false
1262
1352
  });
1263
1353
  } else {
@@ -1278,28 +1368,48 @@ const formify = async ({
1278
1368
  }
1279
1369
  });
1280
1370
  };
1281
- function formifyNode({
1282
- fieldOrInlineFragmentNode,
1371
+ function formifyInlineFragmentDocument({
1372
+ inlineFragmentNode,
1373
+ type,
1374
+ path,
1375
+ showInSidebar = false
1376
+ }) {
1377
+ return formifyDocument({
1378
+ selection: inlineFragmentNode,
1379
+ type,
1380
+ path,
1381
+ showInSidebar
1382
+ });
1383
+ }
1384
+ function formifyFieldNodeDocument({
1385
+ fieldNode,
1386
+ type,
1387
+ path,
1388
+ showInSidebar = false
1389
+ }) {
1390
+ return formifyDocument({ selection: fieldNode, type, path, showInSidebar });
1391
+ }
1392
+ function formifyDocument({
1393
+ selection,
1283
1394
  type,
1284
1395
  path,
1285
1396
  showInSidebar = false
1286
1397
  }) {
1287
1398
  let extraFields = [];
1288
- const namedType = G.getNamedType(type);
1289
1399
  let hasDataJSONField = false;
1290
1400
  let hasValuesField = false;
1291
1401
  let shouldFormify = false;
1292
- fieldOrInlineFragmentNode.selectionSet.selections.forEach((selection) => {
1293
- if (selection.kind === "Field") {
1294
- if (selection.name.value === "dataJSON") {
1402
+ selection.selectionSet.selections.forEach((selection2) => {
1403
+ if (selection2.kind === "Field") {
1404
+ if (selection2.name.value === "dataJSON") {
1295
1405
  shouldFormify = true;
1296
1406
  hasDataJSONField = true;
1297
1407
  }
1298
- if (selection.name.value === "values") {
1408
+ if (selection2.name.value === "values") {
1299
1409
  shouldFormify = true;
1300
1410
  hasValuesField = true;
1301
1411
  }
1302
- if (selection.name.value === "data") {
1412
+ if (selection2.name.value === "data") {
1303
1413
  shouldFormify = true;
1304
1414
  }
1305
1415
  }
@@ -1308,7 +1418,7 @@ const formify = async ({
1308
1418
  blueprints.push({
1309
1419
  id: getBlueprintId(path),
1310
1420
  path,
1311
- selection: fieldOrInlineFragmentNode,
1421
+ selection,
1312
1422
  fields: [],
1313
1423
  showInSidebar,
1314
1424
  hasDataJSONField,
@@ -1316,71 +1426,58 @@ const formify = async ({
1316
1426
  });
1317
1427
  extraFields = metaFields;
1318
1428
  }
1319
- const formifiedNode = __spreadProps(__spreadValues({}, fieldOrInlineFragmentNode), {
1429
+ return __spreadProps(__spreadValues({}, selection), {
1320
1430
  selectionSet: {
1321
1431
  kind: "SelectionSet",
1322
1432
  selections: [
1323
- ...fieldOrInlineFragmentNode.selectionSet.selections.map((selectionNode) => {
1433
+ ...selection.selectionSet.selections.map((selectionNode) => {
1324
1434
  switch (selectionNode.kind) {
1325
- case "InlineFragment":
1435
+ case "InlineFragment": {
1436
+ const namedType = G.getNamedType(type);
1326
1437
  if (G.isInterfaceType(namedType)) {
1327
- const subType2 = schema.getImplementations(namedType).objects.find((item) => item.name === selectionNode.typeCondition.name.value);
1328
- return formifyNode({
1329
- fieldOrInlineFragmentNode: selectionNode,
1330
- type: subType2,
1438
+ const subType = schema.getImplementations(namedType).objects.find((item) => item.name === selectionNode.typeCondition.name.value);
1439
+ return formifyInlineFragmentDocument({
1440
+ inlineFragmentNode: selectionNode,
1441
+ type: subType,
1331
1442
  path,
1332
- showInSidebar: false
1443
+ showInSidebar: true
1333
1444
  });
1334
1445
  }
1335
- ensureUnionType(namedType);
1336
- const subType = getSelectedUnionType(namedType, selectionNode);
1337
- return formifyNode({
1338
- fieldOrInlineFragmentNode: selectionNode,
1339
- type: subType,
1340
- path,
1341
- showInSidebar
1446
+ return formifyInlineFragmentNode({
1447
+ inlineFragmentNode: selectionNode,
1448
+ parentType: type,
1449
+ path
1342
1450
  });
1343
- case "Field":
1451
+ }
1452
+ case "Field": {
1344
1453
  if (selectionNode.name.value === DATA_NODE_NAME) {
1345
- const path2 = [
1346
- ...path,
1347
- getNameAndAlias(selectionNode, false, false)
1348
- ];
1349
- if (G.isObjectType(namedType)) {
1350
- const field = getObjectField(namedType, selectionNode);
1351
- const namedSubType = G.getNamedType(field.type);
1352
- ensureObjectType(namedSubType);
1353
- return __spreadProps(__spreadValues({}, selectionNode), {
1354
- selectionSet: {
1355
- kind: "SelectionSet",
1356
- selections: [
1357
- ...selectionNode.selectionSet.selections.map((subSelectionNode) => {
1358
- switch (subSelectionNode.kind) {
1359
- case "Field":
1360
- const subSelectionField = getObjectField(namedSubType, subSelectionNode);
1361
- if (!subSelectionField) {
1362
- return subSelectionNode;
1363
- }
1364
- const subSelectionType = G.getNamedType(subSelectionField.type);
1365
- return formifyField({
1366
- fieldNode: subSelectionNode,
1367
- parentType: field.type,
1368
- path: [
1369
- ...path2,
1370
- getNameAndAlias(subSelectionNode, isListType(subSelectionField.type), isNodeField(subSelectionType))
1371
- ]
1372
- });
1373
- default:
1374
- throw new FormifyError("UNEXPECTED", `selection ${subSelectionNode.kind}`);
1375
- }
1376
- })
1377
- ]
1378
- }
1379
- });
1380
- }
1381
- throw new FormifyError("UNEXPECTED");
1454
+ const field = getObjectField(type, selectionNode);
1455
+ return __spreadProps(__spreadValues({}, selectionNode), {
1456
+ selectionSet: {
1457
+ kind: "SelectionSet",
1458
+ selections: [
1459
+ ...selectionNode.selectionSet.selections.map((subSelectionNode) => {
1460
+ switch (subSelectionNode.kind) {
1461
+ case "Field":
1462
+ return formifyFieldNode({
1463
+ fieldNode: subSelectionNode,
1464
+ parentType: field.type,
1465
+ path: buildPath({
1466
+ fieldNode: selectionNode,
1467
+ type: field.type,
1468
+ path
1469
+ })
1470
+ });
1471
+ default:
1472
+ throw new FormifyError("UNEXPECTED", `selection ${subSelectionNode.kind}`);
1473
+ }
1474
+ })
1475
+ ]
1476
+ }
1477
+ });
1382
1478
  }
1383
1479
  return selectionNode;
1480
+ }
1384
1481
  default:
1385
1482
  throw new FormifyError("UNEXPECTED");
1386
1483
  }
@@ -1389,32 +1486,35 @@ const formify = async ({
1389
1486
  ]
1390
1487
  }
1391
1488
  });
1392
- return formifiedNode;
1393
1489
  }
1394
- const formifyField = ({
1490
+ const formifyFieldNode = ({
1395
1491
  fieldNode,
1396
1492
  parentType,
1397
1493
  path
1398
1494
  }) => {
1399
- const namedParentType = G.getNamedType(parentType);
1400
- ensureObjectType(namedParentType);
1401
- const field = getObjectField(namedParentType, fieldNode);
1495
+ if (fieldNode.name.value === "__typename") {
1496
+ return fieldNode;
1497
+ }
1498
+ const field = getObjectField(parentType, fieldNode);
1402
1499
  if (!field) {
1403
- if (fieldNode.name.value === "__typename") {
1404
- return fieldNode;
1405
- } else {
1406
- throw new FormifyError("UNEXPECTED", `field with no associated type ${fieldNode.name.value}`);
1407
- }
1500
+ return fieldNode;
1408
1501
  }
1409
- const namedType = G.getNamedType(field.type);
1410
- const fieldBlueprint = {
1411
- id: getBlueprintId([...path]),
1412
- documentBlueprintId: getRelativeBlueprint(path),
1413
- path: [...path]
1414
- };
1415
1502
  const blueprint = blueprints.find((blueprint2) => blueprint2.id === getRelativeBlueprint(path));
1416
- blueprint.fields.push(fieldBlueprint);
1417
- if (G.isScalarType(namedType)) {
1503
+ if (!blueprint) {
1504
+ return fieldNode;
1505
+ }
1506
+ const fieldPath = buildPath({
1507
+ fieldNode,
1508
+ type: field.type,
1509
+ parentTypename: G.getNamedType(parentType).name,
1510
+ path
1511
+ });
1512
+ blueprint.fields.push({
1513
+ id: getBlueprintId(fieldPath),
1514
+ documentBlueprintId: blueprint.id,
1515
+ path: fieldPath
1516
+ });
1517
+ if (isScalarType(field.type)) {
1418
1518
  return fieldNode;
1419
1519
  }
1420
1520
  return __spreadProps(__spreadValues({}, fieldNode), {
@@ -1423,121 +1523,20 @@ const formify = async ({
1423
1523
  selections: [
1424
1524
  ...fieldNode.selectionSet.selections.map((selectionNode) => {
1425
1525
  switch (selectionNode.kind) {
1426
- case "Field":
1427
- if (selectionNode.name.value === "__typename") {
1428
- return selectionNode;
1429
- }
1430
- ensureObjectType(namedType);
1431
- const subField = getObjectField(namedType, selectionNode);
1432
- if (!subField) {
1433
- return fieldNode;
1434
- }
1435
- if (G.isScalarType(G.getNamedType(subField.type))) {
1436
- const newPath2 = [
1437
- ...path,
1438
- getNameAndAlias(selectionNode, isListType(subField.type), false)
1439
- ];
1440
- const fieldBlueprint3 = {
1441
- id: getBlueprintId(newPath2),
1442
- documentBlueprintId: getRelativeBlueprint(newPath2),
1443
- path: newPath2
1444
- };
1445
- const blueprint3 = blueprints.find((blueprint4) => blueprint4.id === getRelativeBlueprint(path));
1446
- blueprint3.fields.push(fieldBlueprint3);
1447
- return selectionNode;
1448
- }
1449
- const subFieldType = subField.type;
1450
- const namedSubFieldType = G.getNamedType(subFieldType);
1451
- const newPath = [
1452
- ...path,
1453
- getNameAndAlias(selectionNode, isListType(subFieldType), isNodeField(namedSubFieldType))
1454
- ];
1455
- const fieldBlueprint2 = {
1456
- id: getBlueprintId(newPath),
1457
- documentBlueprintId: getRelativeBlueprint(newPath),
1458
- path: newPath
1459
- };
1460
- const blueprint2 = blueprints.find((blueprint3) => blueprint3.id === getRelativeBlueprint(path));
1461
- blueprint2.fields.push(fieldBlueprint2);
1462
- return __spreadProps(__spreadValues({}, selectionNode), {
1463
- selectionSet: {
1464
- kind: "SelectionSet",
1465
- selections: selectionNode.selectionSet.selections.map((subSelectionNode) => {
1466
- switch (subSelectionNode.kind) {
1467
- case "Field":
1468
- if (subSelectionNode.name.value === "__typename") {
1469
- return subSelectionNode;
1470
- }
1471
- ensureObjectType(namedSubFieldType);
1472
- const subField1 = getObjectField(namedSubFieldType, subSelectionNode);
1473
- const subType1 = subField1.type;
1474
- const namedSubType2 = G.getNamedType(subType1);
1475
- return formifyField({
1476
- fieldNode: subSelectionNode,
1477
- parentType: subFieldType,
1478
- path: [
1479
- ...path,
1480
- getNameAndAlias(subSelectionNode, isListType(subType1), isNodeField(namedSubType2))
1481
- ]
1482
- });
1483
- case "InlineFragment":
1484
- const subNamedType = G.getNamedType(subField.type);
1485
- ensureNodeField(subNamedType);
1486
- ensureUnionType(subNamedType);
1487
- const subType2 = getSelectedUnionType(subNamedType, subSelectionNode);
1488
- const newPath2 = [
1489
- ...path,
1490
- getNameAndAlias(selectionNode, isListType(subField.type), true)
1491
- ];
1492
- return formifyNode({
1493
- fieldOrInlineFragmentNode: subSelectionNode,
1494
- type: subType2,
1495
- path: newPath2,
1496
- showInSidebar: false
1497
- });
1498
- default:
1499
- throw new FormifyError("UNEXPECTED", `selection ${subSelectionNode.kind}`);
1500
- }
1501
- })
1502
- }
1526
+ case "Field": {
1527
+ return formifyFieldNode({
1528
+ fieldNode: selectionNode,
1529
+ parentType: field.type,
1530
+ path: fieldPath
1503
1531
  });
1504
- case "InlineFragment":
1505
- ensureUnionType(namedType);
1506
- if (isNodeField(namedType)) {
1507
- const parentType2 = getSelectedUnionType(namedType, selectionNode);
1508
- return formifyNode({
1509
- fieldOrInlineFragmentNode: selectionNode,
1510
- type: parentType2,
1511
- path,
1512
- showInSidebar: false
1513
- });
1514
- }
1515
- const subType = getSelectedUnionType(namedType, selectionNode);
1516
- const namedSubType = G.getNamedType(subType);
1517
- return __spreadProps(__spreadValues({}, selectionNode), {
1518
- selectionSet: {
1519
- kind: "SelectionSet",
1520
- selections: selectionNode.selectionSet.selections.map((subSelectionNode) => {
1521
- switch (subSelectionNode.kind) {
1522
- case "Field":
1523
- ensureObjectType(namedSubType);
1524
- const subField2 = getObjectField(namedSubType, subSelectionNode);
1525
- const subType2 = subField2.type;
1526
- const namedSubType2 = G.getNamedType(subType2);
1527
- return formifyField({
1528
- fieldNode: subSelectionNode,
1529
- parentType: subType,
1530
- path: [
1531
- ...path,
1532
- getNameAndAlias(subSelectionNode, isListType(subType2), isNodeField(namedSubType2))
1533
- ]
1534
- });
1535
- default:
1536
- throw new FormifyError("UNEXPECTED", `selection ${subSelectionNode.kind}`);
1537
- }
1538
- })
1539
- }
1532
+ }
1533
+ case "InlineFragment": {
1534
+ return formifyInlineFragmentNode({
1535
+ inlineFragmentNode: selectionNode,
1536
+ parentType: field.type,
1537
+ path: fieldPath
1540
1538
  });
1539
+ }
1541
1540
  default:
1542
1541
  throw new FormifyError("UNEXPECTED", `selection ${selectionNode.kind}`);
1543
1542
  }
@@ -1546,43 +1545,77 @@ const formify = async ({
1546
1545
  }
1547
1546
  });
1548
1547
  };
1548
+ const formifyInlineFragmentNode = ({
1549
+ inlineFragmentNode,
1550
+ parentType,
1551
+ path
1552
+ }) => {
1553
+ const type = getSelectedUnionType(parentType, inlineFragmentNode);
1554
+ if (!type) {
1555
+ return inlineFragmentNode;
1556
+ }
1557
+ if (isFormifiableDocument(type)) {
1558
+ return formifyInlineFragmentDocument({
1559
+ inlineFragmentNode,
1560
+ type,
1561
+ path,
1562
+ showInSidebar: false
1563
+ });
1564
+ }
1565
+ return __spreadProps(__spreadValues({}, inlineFragmentNode), {
1566
+ selectionSet: {
1567
+ kind: "SelectionSet",
1568
+ selections: inlineFragmentNode.selectionSet.selections.map((selectionNode) => {
1569
+ switch (selectionNode.kind) {
1570
+ case "Field":
1571
+ return formifyFieldNode({
1572
+ fieldNode: selectionNode,
1573
+ parentType: type,
1574
+ path
1575
+ });
1576
+ default:
1577
+ throw new FormifyError("UNEXPECTED", `selection ${selectionNode.kind}`);
1578
+ }
1579
+ })
1580
+ }
1581
+ });
1582
+ };
1549
1583
  const formifiedQuery = {
1550
1584
  kind: "Document",
1551
1585
  definitions: optimizedQuery.definitions.map((definition) => {
1552
1586
  typeInfo.enter(definition);
1553
1587
  ensureOperationDefinition(definition);
1554
- const type = typeInfo.getType();
1555
- const namedType = G.getNamedType(type);
1556
- ensureObjectType(namedType);
1588
+ const parentType = typeInfo.getType();
1557
1589
  return __spreadProps(__spreadValues({}, definition), {
1558
1590
  selectionSet: {
1559
1591
  kind: "SelectionSet",
1560
1592
  selections: definition.selectionSet.selections.map((selectionNode) => {
1561
1593
  switch (selectionNode.kind) {
1562
1594
  case "Field":
1563
- const parentType = type;
1564
- const namedParentType = G.getNamedType(parentType);
1565
- ensureObjectType(namedParentType);
1566
- const field = getObjectField(namedParentType, selectionNode);
1567
- const namedFieldType = G.getNamedType(field.type);
1568
- if (isNodeField(namedFieldType)) {
1569
- return formifyNode({
1570
- fieldOrInlineFragmentNode: selectionNode,
1595
+ const field = getObjectField(parentType, selectionNode);
1596
+ const path = buildPath({
1597
+ fieldNode: selectionNode,
1598
+ type: field.type
1599
+ });
1600
+ if (isFormifiableDocument(field.type)) {
1601
+ return formifyFieldNodeDocument({
1602
+ fieldNode: selectionNode,
1571
1603
  type: field.type,
1572
- path: [getNameAndAlias(selectionNode, false, true)],
1604
+ path,
1573
1605
  showInSidebar: true
1574
1606
  });
1575
- } else if (isConnectionField(namedFieldType)) {
1607
+ } else if (isConnectionField(field.type)) {
1576
1608
  return formifyConnection({
1577
- namedFieldType,
1609
+ parentType: field.type,
1578
1610
  selectionNode,
1579
- path: [getNameAndAlias(selectionNode, false, false)]
1611
+ path
1580
1612
  });
1581
1613
  }
1582
1614
  if (selectionNode.name.value === COLLECTION_FIELD_NAME || selectionNode.name.value === COLLECTIONS_FIELD_NAME) {
1583
- const path = [
1584
- getNameAndAlias(selectionNode, false, false)
1585
- ];
1615
+ const path2 = buildPath({
1616
+ fieldNode: selectionNode,
1617
+ type: field.type
1618
+ });
1586
1619
  return __spreadProps(__spreadValues({}, selectionNode), {
1587
1620
  selectionSet: {
1588
1621
  kind: "SelectionSet",
@@ -1590,16 +1623,15 @@ const formify = async ({
1590
1623
  switch (subSelectionNode.kind) {
1591
1624
  case "Field":
1592
1625
  if (subSelectionNode.name.value === COLLECTIONS_DOCUMENTS_NAME) {
1593
- ensureObjectType(namedFieldType);
1594
- const n = namedFieldType.getFields()[COLLECTIONS_DOCUMENTS_NAME];
1595
- const docType = G.getNamedType(n.type);
1626
+ const subField = getObjectField(field.type, subSelectionNode);
1596
1627
  return formifyConnection({
1597
- namedFieldType: docType,
1628
+ parentType: subField.type,
1598
1629
  selectionNode: subSelectionNode,
1599
- path: [
1600
- ...path,
1601
- getNameAndAlias(subSelectionNode, isListType(docType), isNodeField(docType))
1602
- ]
1630
+ path: buildPath({
1631
+ fieldNode: subSelectionNode,
1632
+ type: subField.type,
1633
+ path: path2
1634
+ })
1603
1635
  });
1604
1636
  }
1605
1637
  return subSelectionNode;
@@ -1639,9 +1671,27 @@ class FormifyError extends Error {
1639
1671
  this.name = "FormifyError";
1640
1672
  }
1641
1673
  }
1674
+ const defaultState = {
1675
+ status: "idle",
1676
+ schema: void 0,
1677
+ query: null,
1678
+ queryString: null,
1679
+ data: {},
1680
+ changeSets: [],
1681
+ count: 0,
1682
+ blueprints: [],
1683
+ formNodes: [],
1684
+ documentForms: []
1685
+ };
1642
1686
  function reducer(state, action) {
1643
1687
  var _a, _b, _c, _d;
1644
1688
  switch (action.type) {
1689
+ case "start":
1690
+ return __spreadProps(__spreadValues(__spreadValues({}, state), defaultState), {
1691
+ query: action.value.query ? G.parse(action.value.query) : null,
1692
+ queryString: action.value.query,
1693
+ status: "initialized"
1694
+ });
1645
1695
  case "addDocumentBlueprints":
1646
1696
  return __spreadProps(__spreadValues({}, state), {
1647
1697
  status: "formified",
@@ -1696,16 +1746,21 @@ function reducer(state, action) {
1696
1746
  }
1697
1747
  if (event.mutationType.type === "change") {
1698
1748
  if (!action.value.form) {
1699
- getPathsToChange(event, state).forEach(({ formNode: formNode2, pathToChange }) => {
1749
+ getBlueprintFieldsForEvent(blueprint, event).forEach((fieldBlueprint) => {
1750
+ const { pathToChange } = getFormNodesForField(fieldBlueprint, formNode, event, state);
1700
1751
  changeSets.push(__spreadValues({
1701
1752
  path: pathToChange
1702
- }, buildChangeSet(event, formNode2)));
1753
+ }, buildChangeSet(event, formNode)));
1703
1754
  });
1704
1755
  }
1705
1756
  } else if (event.mutationType.type === "referenceChange") {
1706
1757
  getBlueprintFieldsForEvent(blueprint, event).forEach((fieldBlueprint) => {
1707
- const { pathToChange, formNodes, eventLocation } = getFormNodesForField(fieldBlueprint, formNode, event, state);
1708
- if (action.value.form) {
1758
+ const {
1759
+ pathToChange,
1760
+ formNodes: subFormNodes,
1761
+ eventLocation
1762
+ } = getFormNodesForField(fieldBlueprint, formNode, event, state);
1763
+ if (action.value.form && state.blueprints.find((blueprint2) => blueprint2.id === fieldBlueprint.id)) {
1709
1764
  const newFormNode = {
1710
1765
  documentBlueprintId: fieldBlueprint.id,
1711
1766
  documentFormId: action.value.form.id,
@@ -1716,8 +1771,15 @@ function reducer(state, action) {
1716
1771
  path: pathToChange
1717
1772
  }, buildChangeSet(event, newFormNode)));
1718
1773
  }
1719
- formNodes.forEach((subFormNode) => {
1774
+ subFormNodes.forEach((subFormNode) => {
1720
1775
  if (matchLocation(eventLocation, subFormNode)) {
1776
+ if (!action.value.form) {
1777
+ changeSets.push(__spreadProps(__spreadValues({
1778
+ path: pathToChange
1779
+ }, buildChangeSet(event, subFormNode)), {
1780
+ value: null
1781
+ }));
1782
+ }
1721
1783
  formNodesToReplace.push(subFormNode);
1722
1784
  }
1723
1785
  });
@@ -1870,7 +1932,7 @@ const useFormify = ({
1870
1932
  }) => {
1871
1933
  const formIds = React.useRef([]);
1872
1934
  const [state, dispatch] = React.useReducer(reducer, {
1873
- status: "initialized",
1935
+ status: "idle",
1874
1936
  schema: void 0,
1875
1937
  query: query ? G.parse(query) : null,
1876
1938
  queryString: query,
@@ -1881,6 +1943,17 @@ const useFormify = ({
1881
1943
  formNodes: [],
1882
1944
  documentForms: []
1883
1945
  });
1946
+ React.useEffect(() => {
1947
+ if (query) {
1948
+ dispatch({ type: "start", value: { query } });
1949
+ formIds.current.forEach((formId) => {
1950
+ const form = cms.forms.find(formId);
1951
+ if (form) {
1952
+ cms.plugins.remove(form);
1953
+ }
1954
+ });
1955
+ }
1956
+ }, [query, JSON.stringify(variables)]);
1884
1957
  React.useEffect(() => {
1885
1958
  if (state.status === "initialized") {
1886
1959
  cms.api.tina.request(query, { variables }).then((res) => {
@@ -1912,7 +1985,7 @@ const useFormify = ({
1912
1985
  variables
1913
1986
  });
1914
1987
  state.blueprints.map((blueprint) => {
1915
- const responseAtBlueprint = getIn2(result, getBlueprintAliasPath(blueprint));
1988
+ const responseAtBlueprint = getValueForBlueprint(result, getBlueprintAliasPath(blueprint));
1916
1989
  const location = [];
1917
1990
  const findFormNodes = (res, location2) => {
1918
1991
  if (Array.isArray(res)) {
@@ -1961,6 +2034,9 @@ const useFormify = ({
1961
2034
  React.useEffect(() => {
1962
2035
  if (state.status === "ready") {
1963
2036
  cms.events.subscribe(`forms:reset`, (event) => {
2037
+ if (eventList) {
2038
+ eventList.push(printEvent(event));
2039
+ }
1964
2040
  dispatch({ type: "formOnReset", value: { event } });
1965
2041
  });
1966
2042
  cms.events.subscribe(`forms:fields:onChange`, async (event) => {
@@ -1982,6 +2058,9 @@ const useFormify = ({
1982
2058
  values
1983
2059
  _internalSys: sys {
1984
2060
  path
2061
+ collection {
2062
+ name
2063
+ }
1985
2064
  }
1986
2065
  }
1987
2066
  }
@@ -2012,7 +2091,8 @@ const useFormify = ({
2012
2091
  const form = cms.forms.find(changeSet.formId);
2013
2092
  resolveSubFields({
2014
2093
  formNode: changeSet.formNode,
2015
- form
2094
+ form,
2095
+ loc: []
2016
2096
  }).then((res) => {
2017
2097
  dispatch({
2018
2098
  type: "setIn",
@@ -2121,22 +2201,15 @@ const useFormify = ({
2121
2201
  const data = {};
2122
2202
  await sequential(form.fields, async (field) => {
2123
2203
  const value = form.values[field.name];
2124
- const fieldName = field.list ? `${field.name}.[]` : field.name;
2125
2204
  const blueprint = getFormNodeBlueprint(formNode, state);
2126
- const blueprintName = getBlueprintNamePath(blueprint);
2127
- const extra = [];
2128
- if (prefix) {
2129
- extra.push(prefix);
2130
- }
2131
- const matchName = [
2132
- blueprintName,
2133
- DATA_NODE_NAME,
2134
- ...extra,
2135
- fieldName
2136
- ].join(".");
2205
+ const { matchName, fieldName } = getMatchName({
2206
+ field,
2207
+ prefix,
2208
+ blueprint
2209
+ });
2137
2210
  const fieldBlueprints = blueprint.fields.filter((fieldBlueprint) => {
2138
2211
  return matchName === getBlueprintNamePath(fieldBlueprint);
2139
- });
2212
+ }).filter((fbp) => filterFieldBlueprintsByParentTypename(fbp, field.parentTypename));
2140
2213
  switch (field.type) {
2141
2214
  case "object":
2142
2215
  if (field.templates) {
@@ -2150,18 +2223,17 @@ const useFormify = ({
2150
2223
  if (!Array.isArray(value)) {
2151
2224
  throw new Error(`Expected value for object list field to be an array`);
2152
2225
  }
2153
- const d = [];
2154
- await sequential(value, async (item, index) => {
2226
+ data[keyName] = await sequential(value, async (item, index) => {
2155
2227
  const template = field.templates[item._template];
2156
- const d2 = await resolveSubFields({
2228
+ return __spreadProps(__spreadValues({}, await resolveSubFields({
2157
2229
  formNode,
2158
2230
  form: { fields: template.fields, values: item },
2159
- prefix: [prefix, fieldName].join("."),
2231
+ prefix: prefix ? [prefix, fieldName].join(".") : fieldName,
2160
2232
  loc: [...loc, index]
2233
+ })), {
2234
+ __typename: field.typeMap[item._template]
2161
2235
  });
2162
- d.push(d2);
2163
2236
  });
2164
- data[keyName] = d;
2165
2237
  });
2166
2238
  } else {
2167
2239
  throw new Error("blocks without list true is not yet supported");
@@ -2177,18 +2249,14 @@ const useFormify = ({
2177
2249
  if (!Array.isArray(value)) {
2178
2250
  throw new Error(`Expected value for object list field to be an array`);
2179
2251
  }
2180
- const d = [];
2181
- await sequential(value, async (item, index) => {
2182
- const d2 = await resolveSubFields({
2252
+ data[keyName] = await sequential(value, async (item, index) => {
2253
+ return resolveSubFields({
2183
2254
  formNode,
2184
2255
  form: { fields: field.fields, values: item },
2185
2256
  prefix: [prefix, fieldName].join("."),
2186
2257
  loc: [...loc, index]
2187
2258
  });
2188
- d.push(d2);
2189
- return true;
2190
2259
  });
2191
- data[keyName] = d;
2192
2260
  return true;
2193
2261
  });
2194
2262
  } else {
@@ -2198,13 +2266,12 @@ const useFormify = ({
2198
2266
  data[keyName] = null;
2199
2267
  return true;
2200
2268
  }
2201
- const d = await resolveSubFields({
2269
+ data[keyName] = await resolveSubFields({
2202
2270
  formNode,
2203
2271
  form: { fields: field.fields, values: value },
2204
2272
  prefix: [prefix, fieldName].join("."),
2205
2273
  loc
2206
2274
  });
2207
- data[keyName] = d;
2208
2275
  return true;
2209
2276
  });
2210
2277
  }
@@ -2225,6 +2292,9 @@ const useFormify = ({
2225
2292
  values
2226
2293
  _internalSys: sys {
2227
2294
  path
2295
+ collection {
2296
+ name
2297
+ }
2228
2298
  }
2229
2299
  }
2230
2300
  }
@@ -2259,12 +2329,13 @@ const useFormify = ({
2259
2329
  }
2260
2330
  }
2261
2331
  `, { variables: { id: value } });
2262
- const d = await resolveSubFields({
2263
- formNode: subDocumentFormNode,
2264
- form: form2,
2265
- loc: location
2332
+ data[keyName] = __spreadProps(__spreadValues({}, res.node), {
2333
+ data: await resolveSubFields({
2334
+ formNode: subDocumentFormNode,
2335
+ form: form2,
2336
+ loc: location
2337
+ })
2266
2338
  });
2267
- data[keyName] = __spreadProps(__spreadValues({}, res.node), { data: d });
2268
2339
  });
2269
2340
  break;
2270
2341
  default:
@@ -2332,13 +2403,13 @@ mutation addPendingDocumentMutation(
2332
2403
  return result;
2333
2404
  };
2334
2405
  this.getSchema = async () => {
2335
- if (!this.schema) {
2406
+ if (!this.gqlSchema) {
2336
2407
  const data = await this.request(getIntrospectionQuery(), {
2337
2408
  variables: {}
2338
2409
  });
2339
- this.schema = buildClientSchema(data);
2410
+ this.gqlSchema = buildClientSchema(data);
2340
2411
  }
2341
- return this.schema;
2412
+ return this.gqlSchema;
2342
2413
  };
2343
2414
  this.getOptimizedQuery = async (documentNode) => {
2344
2415
  const data = await this.request(`query GetOptimizedQuery($queryString: String!) {
@@ -2348,6 +2419,13 @@ mutation addPendingDocumentMutation(
2348
2419
  });
2349
2420
  return parse(data.getOptimizedQuery);
2350
2421
  };
2422
+ if (options.schema) {
2423
+ const enrichedSchema = new TinaSchema(__spreadValues({
2424
+ version: { fullVersion: "", major: "", minor: "", patch: "" },
2425
+ meta: { flags: [] }
2426
+ }, addNamespaceToSchema(options.schema, [])));
2427
+ this.schema = enrichedSchema;
2428
+ }
2351
2429
  this.options = options;
2352
2430
  this.setBranch(options.branch);
2353
2431
  this.events.subscribe("branch:change", ({ branchName }) => {
@@ -2557,11 +2635,11 @@ mutation addPendingDocumentMutation(
2557
2635
  const DEFAULT_LOCAL_TINA_GQL_SERVER_URL = "http://localhost:4001/graphql";
2558
2636
  class LocalClient extends Client {
2559
2637
  constructor(props) {
2560
- const clientProps = {
2638
+ const clientProps = __spreadProps(__spreadValues({}, props), {
2561
2639
  clientId: "",
2562
2640
  branch: "",
2563
2641
  customContentApiUrl: props && props.customContentApiUrl ? props.customContentApiUrl : DEFAULT_LOCAL_TINA_GQL_SERVER_URL
2564
- };
2642
+ });
2565
2643
  super(clientProps);
2566
2644
  }
2567
2645
  async isAuthorized() {
@@ -3136,11 +3214,13 @@ const TinaCMSProvider2 = (_c) => {
3136
3214
  var _d = _c, {
3137
3215
  query,
3138
3216
  documentCreatorCallback,
3139
- formifyCallback
3217
+ formifyCallback,
3218
+ schema
3140
3219
  } = _d, props = __objRest(_d, [
3141
3220
  "query",
3142
3221
  "documentCreatorCallback",
3143
- "formifyCallback"
3222
+ "formifyCallback",
3223
+ "schema"
3144
3224
  ]);
3145
3225
  const validOldSetup = new Boolean(props == null ? void 0 : props.isLocalClient) || new Boolean(props == null ? void 0 : props.clientId) && new Boolean(props == null ? void 0 : props.branch);
3146
3226
  if (!props.apiURL && !validOldSetup) {
@@ -3157,7 +3237,8 @@ const TinaCMSProvider2 = (_c) => {
3157
3237
  tinaioConfig: props.tinaioConfig,
3158
3238
  isLocalClient,
3159
3239
  cmsCallback: props.cmsCallback,
3160
- mediaStore: props.mediaStore
3240
+ mediaStore: props.mediaStore,
3241
+ schema
3161
3242
  }, /* @__PURE__ */ React.createElement("style", null, styles), /* @__PURE__ */ React.createElement(ErrorBoundary, null, /* @__PURE__ */ React.createElement(DocumentCreator, {
3162
3243
  documentCreatorCallback
3163
3244
  }), /* @__PURE__ */ React.createElement(TinaDataProvider, {
@@ -3885,7 +3966,7 @@ const handleNavigate = (navigate, cms, collection, document) => {
3885
3966
  window.location.href = routeOverride;
3886
3967
  return null;
3887
3968
  } else {
3888
- navigate(document.sys.filename);
3969
+ navigate(document.sys.breadcrumbs.join("/"));
3889
3970
  }
3890
3971
  };
3891
3972
  const CollectionListPage = () => {
@@ -3918,8 +3999,9 @@ const CollectionListPage = () => {
3918
3999
  }, /* @__PURE__ */ React.createElement("tbody", {
3919
4000
  className: "divide-y divide-gray-150"
3920
4001
  }, documents.map((document) => {
4002
+ const subfolders = document.node.sys.breadcrumbs.slice(0, -1).join("/");
3921
4003
  return /* @__PURE__ */ React.createElement("tr", {
3922
- key: `document-${document.node.sys.filename}`,
4004
+ key: `document-${document.node.sys.relativePath}`,
3923
4005
  className: ""
3924
4006
  }, /* @__PURE__ */ React.createElement("td", {
3925
4007
  className: "px-6 py-2 whitespace-nowrap"
@@ -3934,7 +4016,9 @@ const CollectionListPage = () => {
3934
4016
  className: "block text-xs text-gray-400 mb-1 uppercase"
3935
4017
  }, "Filename"), /* @__PURE__ */ React.createElement("span", {
3936
4018
  className: "h-5 leading-5 block whitespace-nowrap"
3937
- }, document.node.sys.filename)))), /* @__PURE__ */ React.createElement("td", {
4019
+ }, subfolders && /* @__PURE__ */ React.createElement("span", {
4020
+ className: "text-xs text-gray-400"
4021
+ }, `${subfolders}/`), /* @__PURE__ */ React.createElement("span", null, document.node.sys.filename))))), /* @__PURE__ */ React.createElement("td", {
3938
4022
  className: "px-6 py-4 whitespace-nowrap"
3939
4023
  }, /* @__PURE__ */ React.createElement("span", {
3940
4024
  className: "block text-xs text-gray-400 mb-1 uppercase"
@@ -4058,6 +4142,22 @@ const RenderForm$1 = ({ cms, collection, template, fields, mutationInfo }) => {
4058
4142
  var _a, _b;
4059
4143
  const navigate = useNavigate();
4060
4144
  const [formIsPristine, setFormIsPristine] = useState(true);
4145
+ const schema = cms.api.tina.schema;
4146
+ let schemaFields = fields;
4147
+ if (schema) {
4148
+ const schemaCollection = schema.getCollection(collection.name);
4149
+ const template2 = schema.getTemplateForData({
4150
+ collection: schemaCollection,
4151
+ data: {}
4152
+ });
4153
+ const formInfo = resolveForm({
4154
+ collection: schemaCollection,
4155
+ basename: schemaCollection.name,
4156
+ schema,
4157
+ template: template2
4158
+ });
4159
+ schemaFields = formInfo.fields;
4160
+ }
4061
4161
  const form = useMemo(() => {
4062
4162
  return new Form({
4063
4163
  id: "create-form",
@@ -4067,7 +4167,7 @@ const RenderForm$1 = ({ cms, collection, template, fields, mutationInfo }) => {
4067
4167
  name: "filename",
4068
4168
  label: "Filename",
4069
4169
  component: "text",
4070
- description: `A unique filename for the content. Example: My_Document`,
4170
+ description: /* @__PURE__ */ React.createElement("span", null, "A unique filename for the content.", /* @__PURE__ */ React.createElement("br", null), "Examples: ", /* @__PURE__ */ React.createElement("code", null, "My_Document"), ", ", /* @__PURE__ */ React.createElement("code", null, "My_Document.en"), ",", " ", /* @__PURE__ */ React.createElement("code", null, "sub-folder/My_Document")),
4071
4171
  placeholder: `My_Document`,
4072
4172
  validate: (value, allValues, meta) => {
4073
4173
  if (!value) {
@@ -4076,13 +4176,13 @@ const RenderForm$1 = ({ cms, collection, template, fields, mutationInfo }) => {
4076
4176
  }
4077
4177
  return true;
4078
4178
  }
4079
- const isValid = /^[_a-zA-Z][.,-,_a-zA-Z0-9]*$/.test(value);
4179
+ const isValid = /^[_a-zA-Z][\.\-_\/a-zA-Z0-9]*$/.test(value);
4080
4180
  if (value && !isValid) {
4081
- return "Must begin with a-z, A-Z, or _ and contain only a-z, A-Z, 0-9, -, ., or _";
4181
+ return "Must begin with a-z, A-Z, or _ and contain only a-z, A-Z, 0-9, -, _, ., or /.";
4082
4182
  }
4083
4183
  }
4084
4184
  },
4085
- ...fields
4185
+ ...schemaFields
4086
4186
  ],
4087
4187
  onSubmit: async (values) => {
4088
4188
  try {
@@ -4175,7 +4275,8 @@ const updateDocument = async (cms, relativePath, collection, mutationInfo, value
4175
4275
  }
4176
4276
  };
4177
4277
  const CollectionUpdatePage = () => {
4178
- const { collectionName, filename } = useParams();
4278
+ const _a = useParams(), { collectionName } = _a, rest = __objRest(_a, ["collectionName"]);
4279
+ const { "*": filename } = rest;
4179
4280
  return /* @__PURE__ */ React.createElement(GetCMS, null, (cms) => /* @__PURE__ */ React.createElement(GetDocumentFields, {
4180
4281
  cms,
4181
4282
  collectionName
@@ -4204,13 +4305,28 @@ const RenderForm = ({
4204
4305
  mutationInfo
4205
4306
  }) => {
4206
4307
  var _a, _b;
4207
- useNavigate();
4208
4308
  const [formIsPristine, setFormIsPristine] = useState(true);
4309
+ const schema = cms.api.tina.schema;
4310
+ let schemaFields = document.form.fields;
4311
+ if (schema) {
4312
+ const schemaCollection = schema.getCollection(collection.name);
4313
+ const template = schema.getTemplateForData({
4314
+ collection: schemaCollection,
4315
+ data: document.value
4316
+ });
4317
+ const formInfo = resolveForm({
4318
+ collection: schemaCollection,
4319
+ basename: schemaCollection.name,
4320
+ schema,
4321
+ template
4322
+ });
4323
+ schemaFields = formInfo.fields;
4324
+ }
4209
4325
  const form = useMemo(() => {
4210
4326
  return new Form({
4211
4327
  id: "update-form",
4212
4328
  label: "form",
4213
- fields: document.form.fields,
4329
+ fields: schemaFields,
4214
4330
  initialValues: document.values,
4215
4331
  onSubmit: async (values) => {
4216
4332
  try {
@@ -4294,7 +4410,7 @@ const TinaAdmin = () => {
4294
4410
  path: "collections/:collectionName/:templateName/new",
4295
4411
  element: /* @__PURE__ */ React.createElement(CollectionCreatePage, null)
4296
4412
  }), /* @__PURE__ */ React.createElement(Route, {
4297
- path: "collections/:collectionName/:filename",
4413
+ path: "collections/:collectionName/*",
4298
4414
  element: /* @__PURE__ */ React.createElement(CollectionUpdatePage, null)
4299
4415
  }), /* @__PURE__ */ React.createElement(Route, {
4300
4416
  path: "collections/:collectionName",