tinacms 0.66.8 → 0.66.9

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
@@ -29,17 +29,17 @@ var __objRest = (source, exclude) => {
29
29
  }
30
30
  return target;
31
31
  };
32
- import { EventBus, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, useCMS, useBranchData, FormMetaPlugin, Form, GlobalFormPlugin, Nav, LocalWarning, FormStatus, FormBuilder } from "@tinacms/toolkit";
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
35
  import { TypeInfo, visit, visitWithTypeInfo, getNamedType, GraphQLObjectType, isLeafType, GraphQLUnionType, isScalarType, 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
+ import { getIn, setIn } from "final-form";
39
+ import * as yup from "yup";
38
40
  import gql$1 from "graphql-tag";
39
41
  import styled from "styled-components";
40
- import * as yup from "yup";
41
42
  import { setEditing, TinaDataContext, useEditState } from "@tinacms/sharedctx";
42
- import { getIn, setIn } from "final-form";
43
43
  import UrlPattern from "url-pattern";
44
44
  import { NavLink, useNavigate, useParams, Link, HashRouter, Routes, Route } from "react-router-dom";
45
45
  import { Menu, Transition } from "@headlessui/react";
@@ -376,1306 +376,2486 @@ function assertIsUnionType(type) {
376
376
  throw new Error(`Expected an instance of GraphQLUnionType for type ${type.name}`);
377
377
  }
378
378
  }
379
- const isNodeField = (type) => {
380
- if (G.isUnionType(type)) {
381
- return type.getTypes().every((type2) => {
382
- return type2.getInterfaces().find((intfc) => intfc.name === "Node");
383
- });
384
- } else if (G.isObjectType(type)) {
385
- return !!type.getInterfaces().find((intfc) => intfc.name === "Node");
386
- } else if (G.isInterfaceType(type)) {
387
- if (type.name === "Node") {
388
- return true;
389
- }
390
- } else {
391
- throw new Error(`Expected GraphQLObjectType or GraphQLUnionType for isNodeField check`);
392
- }
393
- };
394
- const isConnectionField = (type) => {
395
- if (G.isObjectType(type)) {
396
- return !!type.getInterfaces().find((intfc) => intfc.name === "Connection");
397
- } else {
398
- throw new Error(`Expected GraphQLObjectType for isCollectionField check`);
399
- }
400
- };
401
- const getObjectField = (object, selectionNode) => {
402
- return object.getFields()[selectionNode.name.value];
403
- };
404
- const getSelectedUnionType = (unionType, selectionNode) => {
405
- return unionType.getTypes().find((type) => type.name === selectionNode.typeCondition.name.value);
379
+ const createClient = ({
380
+ clientId,
381
+ isLocalClient = true,
382
+ branch,
383
+ tinaioConfig
384
+ }) => {
385
+ return isLocalClient ? new LocalClient() : new Client({
386
+ clientId: clientId || "",
387
+ branch: branch || "main",
388
+ tokenStorage: "LOCAL_STORAGE",
389
+ tinaioConfig
390
+ });
406
391
  };
407
- function ensureNodeField(field) {
408
- if (!isNodeField(field)) {
409
- throw new Error(`Expected field to implement Node interface`);
410
- }
411
- }
412
- function ensureUnionType(type) {
413
- if (!G.isUnionType(type)) {
414
- throw new Error(`Expected type to be GraphQLUnionType`);
415
- }
416
- }
417
- function ensureObjectType(type) {
418
- if (!G.isObjectType(type)) {
419
- console.log(type);
420
- throw new Error(`Expected type to be GraphQLObjectType`);
421
- }
422
- }
423
- function ensureOperationDefinition(type) {
424
- if (type.kind !== "OperationDefinition") {
425
- throw new Error(`Expected top-level definition to be an OperationDefinition node, ensure your query has been optimized before calling formify`);
392
+ function assertShape(value, yupSchema, errorMessage) {
393
+ const shape = yupSchema(yup);
394
+ try {
395
+ shape.validateSync(value);
396
+ } catch (e) {
397
+ const message = errorMessage || `Failed to assertShape - ${e.message}`;
398
+ throw new Error(message);
426
399
  }
427
400
  }
428
- function getNameAndAlias(fieldNode, list) {
429
- return {
430
- name: fieldNode.name.value,
431
- alias: fieldNode.alias ? fieldNode.alias.value : fieldNode.name.value,
432
- list: !!list
433
- };
434
- }
435
- const node = G.parse(`
436
- query Sample {
437
- _internalSys: sys {
438
- path
439
- collection {
440
- name
441
- }
442
- }
443
- form
444
- values
445
- }`);
446
- const metaFields = node.definitions[0].selectionSet.selections;
447
- const NOOP = "This is either an error or is not yet supported";
448
- const UNEXPECTED = "Formify encountered an unexpected error, please contact support";
449
- const DATA_NODE_NAME = "data";
450
- const EDGES_NODE_NAME = "edges";
451
- const NODE_NAME = "node";
452
- const COLLECTION_FIELD_NAME = "getCollection";
453
- const COLLECTIONS_FIELD_NAME = "getCollections";
454
- const COLLECTIONS_DOCUMENTS_NAME = "documents";
455
- class FormifyError extends Error {
456
- constructor(code, details) {
457
- let message;
458
- switch (code) {
459
- case "NOOP":
460
- message = NOOP;
461
- break;
462
- case "UNEXPECTED":
463
- message = UNEXPECTED;
464
- break;
465
- default:
466
- message = "";
467
- break;
468
- }
469
- super(`${message} ${details || ""}`);
470
- this.name = "FormifyError";
401
+ function safeAssertShape(value, yupSchema) {
402
+ try {
403
+ assertShape(value, yupSchema);
404
+ return true;
405
+ } catch (e) {
406
+ return false;
471
407
  }
472
408
  }
473
- const formify = async ({
474
- schema,
409
+ function useGraphqlFormsUnstable({
410
+ variables,
411
+ onSubmit,
475
412
  query,
476
- getOptimizedQuery
477
- }) => {
478
- const nodes = [];
479
- const documentNode = G.parse(query);
480
- const visitor2 = {
481
- OperationDefinition: (node2) => {
482
- if (!node2.name) {
483
- return __spreadProps(__spreadValues({}, node2), {
484
- name: {
485
- kind: "Name",
486
- value: `QueryOperation`
487
- }
488
- });
413
+ formify: formify2,
414
+ eventList
415
+ }) {
416
+ const cms = useCMS();
417
+ React.useEffect(() => {
418
+ console.log("NOTE: using unstable formify");
419
+ }, []);
420
+ const state = useFormify({
421
+ query,
422
+ cms,
423
+ variables,
424
+ formify: formify2,
425
+ eventList,
426
+ onSubmit
427
+ });
428
+ return [state.data, state.status !== "done"];
429
+ }
430
+ function useGraphqlForms({
431
+ variables,
432
+ onSubmit,
433
+ formify: formify2 = null,
434
+ query
435
+ }) {
436
+ const cms = useCMS();
437
+ const [formValues, setFormValues] = React.useState({});
438
+ const [data, setData] = React.useState(null);
439
+ const [initialData, setInitialData] = React.useState({});
440
+ const [pendingReset, setPendingReset] = React.useState(null);
441
+ const [isLoading, setIsLoading] = React.useState(true);
442
+ const [newUpdate, setNewUpdate] = React.useState(null);
443
+ const { currentBranch } = useBranchData();
444
+ const updateData = async () => {
445
+ var _a;
446
+ if (newUpdate) {
447
+ const newValue = getIn(formValues, newUpdate.get);
448
+ const activeForm = getIn(data, [newUpdate.queryName, "form"].join("."));
449
+ if (!activeForm) {
450
+ throw new Error(`Unable to find form for query ${newUpdate.queryName}`);
489
451
  }
490
- return node2;
491
- }
492
- };
493
- const documentNodeWithName = visit(documentNode, visitor2);
494
- const optimizedQuery = await getOptimizedQuery(documentNodeWithName);
495
- const typeInfo = new G.TypeInfo(schema);
496
- const formifyConnection = ({
497
- namedFieldType,
498
- selectionNode,
499
- path
500
- }) => {
501
- ensureObjectType(namedFieldType);
502
- return __spreadProps(__spreadValues({}, selectionNode), {
503
- selectionSet: {
504
- kind: "SelectionSet",
505
- selections: selectionNode.selectionSet.selections.map((selectionNode2) => {
506
- switch (selectionNode2.kind) {
507
- case "Field":
508
- if (selectionNode2.name.value === EDGES_NODE_NAME) {
509
- const edgeField = namedFieldType.getFields()[EDGES_NODE_NAME];
510
- const edgeType = G.getNamedType(edgeField.type);
511
- ensureObjectType(edgeType);
512
- return __spreadProps(__spreadValues({}, selectionNode2), {
513
- selectionSet: {
514
- kind: "SelectionSet",
515
- selections: selectionNode2.selectionSet.selections.map((subSelectionNode) => {
516
- switch (subSelectionNode.kind) {
517
- case "Field":
518
- if (subSelectionNode.name.value === NODE_NAME) {
519
- const nodeField = edgeType.getFields()[NODE_NAME];
520
- return formifyNode({
521
- fieldOrInlineFragmentNode: subSelectionNode,
522
- parentType: nodeField.type,
523
- path: [
524
- ...path,
525
- getNameAndAlias(selectionNode2),
526
- getNameAndAlias(subSelectionNode, true)
527
- ]
528
- });
529
- } else {
530
- return subSelectionNode;
531
- }
532
- default:
533
- throw new FormifyError("NOOP");
534
- }
535
- })
536
- }
537
- });
538
- }
539
- return selectionNode2;
540
- default:
541
- throw new FormifyError("UNEXPECTED");
542
- }
543
- })
452
+ if (activeForm == null ? void 0 : activeForm.paths) {
453
+ const asyncUpdate = (_a = activeForm.paths) == null ? void 0 : _a.find((p) => p.dataPath.join(".") === newUpdate.setReference);
454
+ if (asyncUpdate) {
455
+ const res = await cms.api.tina.request(asyncUpdate.queryString, {
456
+ variables: { id: newValue }
457
+ });
458
+ const newData2 = setIn(data, newUpdate.set, res.node);
459
+ const newDataAndNewJSONData2 = setIn(newData2, newUpdate.set.replace("data", "dataJSON"), newValue);
460
+ setData(newDataAndNewJSONData2);
461
+ setNewUpdate(null);
462
+ return;
463
+ }
544
464
  }
545
- });
465
+ if (newUpdate.lookup) {
466
+ const field = getFieldUpdate(newUpdate, activeForm, formValues);
467
+ if (field && field.typeMap) {
468
+ newValue.forEach((item) => {
469
+ if (!item.__typename) {
470
+ item["__typename"] = field.typeMap[item._template];
471
+ }
472
+ });
473
+ }
474
+ }
475
+ const newData = setIn(data, newUpdate.set, newValue);
476
+ const newDataAndNewJSONData = setIn(newData, newUpdate.set.replace("data", "dataJSON"), newValue);
477
+ setData(newDataAndNewJSONData);
478
+ setNewUpdate(null);
479
+ }
546
480
  };
547
- function formifyNode({
548
- fieldOrInlineFragmentNode,
549
- parentType,
550
- path
551
- }) {
552
- let extraFields = [];
553
- const namedParentType = G.getNamedType(parentType);
554
- const formifiedNode = __spreadProps(__spreadValues({}, fieldOrInlineFragmentNode), {
555
- selectionSet: {
556
- kind: "SelectionSet",
557
- selections: [
558
- ...fieldOrInlineFragmentNode.selectionSet.selections.map((selectionNode) => {
559
- switch (selectionNode.kind) {
560
- case "InlineFragment":
561
- if (G.isInterfaceType(namedParentType)) {
562
- const type2 = schema.getImplementations(namedParentType).objects[selectionNode.typeCondition.name.value];
563
- return formifyNode({
564
- fieldOrInlineFragmentNode: selectionNode,
565
- parentType: type2,
566
- path
567
- });
568
- }
569
- ensureUnionType(namedParentType);
570
- const type = getSelectedUnionType(namedParentType, selectionNode);
571
- return formifyNode({
572
- fieldOrInlineFragmentNode: selectionNode,
573
- parentType: type,
574
- path
575
- });
576
- case "Field":
577
- if (selectionNode.name.value === DATA_NODE_NAME) {
578
- extraFields = metaFields;
579
- if (G.isObjectType(namedParentType)) {
580
- const field = getObjectField(namedParentType, selectionNode);
581
- const namedType = G.getNamedType(field.type);
582
- ensureObjectType(namedType);
583
- return __spreadProps(__spreadValues({}, selectionNode), {
584
- selectionSet: {
585
- kind: "SelectionSet",
586
- selections: [
587
- ...selectionNode.selectionSet.selections.map((subSelectionNode) => {
588
- switch (subSelectionNode.kind) {
589
- case "Field":
590
- const subSelectionField = getObjectField(namedType, subSelectionNode);
591
- if (!subSelectionField) {
592
- return subSelectionNode;
593
- }
594
- return formifyField({
595
- fieldNode: subSelectionNode,
596
- parentType: field.type,
597
- path: [
598
- ...path,
599
- getNameAndAlias(subSelectionNode, G.isListType(subSelectionField.type))
600
- ]
601
- });
602
- default:
603
- throw new FormifyError("UNEXPECTED", `selection ${subSelectionNode.kind}`);
604
- }
605
- })
606
- ]
607
- }
608
- });
609
- }
610
- return selectionNode;
611
- }
612
- return selectionNode;
613
- default:
614
- throw new FormifyError("UNEXPECTED");
615
- }
616
- }),
617
- ...extraFields
618
- ]
619
- }
620
- });
621
- return formifiedNode;
622
- }
623
- const formifyField = ({
624
- fieldNode,
625
- parentType,
626
- path
627
- }) => {
628
- const namedParentType = G.getNamedType(parentType);
629
- ensureObjectType(namedParentType);
630
- const field = getObjectField(namedParentType, fieldNode);
631
- if (!field) {
632
- if (fieldNode.name.value === "__typename") {
633
- return fieldNode;
634
- } else {
635
- throw new FormifyError("UNEXPECTED", `field with no associated type ${fieldNode.name.value}`);
636
- }
637
- }
638
- const namedType = G.getNamedType(field.type);
639
- if (G.isScalarType(namedType)) {
640
- return fieldNode;
481
+ React.useEffect(() => {
482
+ updateData();
483
+ }, [JSON.stringify(formValues)]);
484
+ React.useEffect(() => {
485
+ if (pendingReset) {
486
+ setData(__spreadProps(__spreadValues({}, data), { [pendingReset]: initialData[pendingReset] }));
487
+ setPendingReset(null);
641
488
  }
642
- return __spreadProps(__spreadValues({}, fieldNode), {
643
- selectionSet: {
644
- kind: "SelectionSet",
645
- selections: [
646
- ...fieldNode.selectionSet.selections.map((selectionNode) => {
647
- switch (selectionNode.kind) {
648
- case "Field":
649
- if (selectionNode.name.value === "__typename") {
650
- return selectionNode;
651
- }
652
- ensureObjectType(namedType);
653
- const field2 = getObjectField(namedType, selectionNode);
654
- if (!field2) {
655
- return fieldNode;
656
- }
657
- if (G.isScalarType(G.getNamedType(field2.type))) {
658
- return selectionNode;
659
- }
660
- return __spreadProps(__spreadValues({}, selectionNode), {
661
- selectionSet: {
662
- kind: "SelectionSet",
663
- selections: selectionNode.selectionSet.selections.map((selectionNode2) => {
664
- switch (selectionNode2.kind) {
665
- case "Field":
666
- if (selectionNode2.name.value === "__typename") {
667
- return selectionNode2;
668
- }
669
- return formifyField({
670
- fieldNode: selectionNode2,
671
- parentType: field2.type,
672
- path
673
- });
674
- case "InlineFragment":
675
- const namedType2 = G.getNamedType(field2.type);
676
- ensureNodeField(namedType2);
677
- return formifyNode({
678
- fieldOrInlineFragmentNode: selectionNode2,
679
- parentType: field2.type,
680
- path
681
- });
682
- default:
683
- throw new FormifyError("UNEXPECTED", `selection ${selectionNode2.kind}`);
684
- }
685
- })
686
- }
687
- });
688
- case "InlineFragment":
689
- ensureUnionType(namedType);
690
- if (isNodeField(namedType)) {
691
- const parentType2 = getSelectedUnionType(namedType, selectionNode);
692
- return formifyNode({
693
- fieldOrInlineFragmentNode: selectionNode,
694
- parentType: parentType2,
695
- path
696
- });
697
- }
698
- return __spreadProps(__spreadValues({}, selectionNode), {
699
- selectionSet: {
700
- kind: "SelectionSet",
701
- selections: selectionNode.selectionSet.selections.map((subSelectionNode) => {
702
- switch (subSelectionNode.kind) {
703
- case "Field":
704
- const parentType2 = getSelectedUnionType(namedType, selectionNode);
705
- return formifyField({
706
- fieldNode: subSelectionNode,
707
- parentType: parentType2,
708
- path
709
- });
710
- default:
711
- throw new FormifyError("UNEXPECTED", `selection ${subSelectionNode.kind}`);
712
- }
713
- })
714
- }
715
- });
716
- default:
717
- throw new FormifyError("UNEXPECTED", `selection ${selectionNode.kind}`);
718
- }
719
- })
720
- ]
721
- }
722
- });
723
- };
724
- const formifiedQuery = {
725
- kind: "Document",
726
- definitions: optimizedQuery.definitions.map((definition) => {
727
- typeInfo.enter(definition);
728
- ensureOperationDefinition(definition);
729
- const type = typeInfo.getType();
730
- const namedType = G.getNamedType(type);
731
- ensureObjectType(namedType);
732
- return __spreadProps(__spreadValues({}, definition), {
733
- selectionSet: {
734
- kind: "SelectionSet",
735
- selections: definition.selectionSet.selections.map((selectionNode) => {
736
- switch (selectionNode.kind) {
737
- case "Field":
738
- const parentType = type;
739
- const namedParentType = G.getNamedType(parentType);
740
- ensureObjectType(namedParentType);
741
- const field = getObjectField(namedParentType, selectionNode);
742
- const namedFieldType = G.getNamedType(field.type);
743
- if (isNodeField(namedFieldType)) {
744
- return formifyNode({
745
- fieldOrInlineFragmentNode: selectionNode,
746
- parentType: field.type,
747
- path: [getNameAndAlias(selectionNode)]
748
- });
749
- } else if (isConnectionField(namedFieldType)) {
750
- return formifyConnection({
751
- namedFieldType,
752
- selectionNode,
753
- path: [getNameAndAlias(selectionNode)]
754
- });
755
- }
756
- if (selectionNode.name.value === COLLECTION_FIELD_NAME || selectionNode.name.value === COLLECTIONS_FIELD_NAME) {
757
- return __spreadProps(__spreadValues({}, selectionNode), {
758
- selectionSet: {
759
- kind: "SelectionSet",
760
- selections: selectionNode.selectionSet.selections.map((selectionNode2) => {
761
- switch (selectionNode2.kind) {
762
- case "Field":
763
- if (selectionNode2.name.value === COLLECTIONS_DOCUMENTS_NAME) {
764
- ensureObjectType(namedFieldType);
765
- const n = namedFieldType.getFields()[COLLECTIONS_DOCUMENTS_NAME];
766
- const docType = G.getNamedType(n.type);
767
- return formifyConnection({
768
- namedFieldType: docType,
769
- selectionNode: selectionNode2,
770
- path: [getNameAndAlias(selectionNode2)]
771
- });
772
- }
773
- return selectionNode2;
774
- default:
775
- throw new FormifyError("NOOP");
776
- }
777
- })
778
- }
779
- });
780
- }
781
- throw new FormifyError("NOOP");
782
- default:
783
- throw new FormifyError("UNEXPECTED");
784
- }
785
- })
786
- }
787
- });
788
- })
789
- };
790
- nodes.map((node2) => {
791
- const namePath = [];
792
- const aliasPath = [];
793
- node2.path.forEach((p) => {
794
- namePath.push(p.name);
795
- aliasPath.push(p.alias);
796
- if (p.list) {
797
- namePath.push("NUM");
798
- aliasPath.push("NUM");
799
- }
800
- });
801
- JSON.stringify({
802
- namePath: namePath.join("."),
803
- aliasPath: aliasPath.join(".")
804
- }, null, 2);
805
- });
806
- return { formifiedQuery, nodes };
807
- };
808
- const captureBranchName = /^refs\/heads\/(.*)/;
809
- const parseRefForBranchName = (ref) => {
810
- const matches = ref.match(captureBranchName);
811
- return matches[1];
812
- };
813
- class Client {
814
- constructor(_a) {
815
- var _b = _a, { tokenStorage = "MEMORY" } = _b, options = __objRest(_b, ["tokenStorage"]);
816
- this.events = new EventBus();
817
- this.addPendingContent = async (props) => {
818
- const mutation = `#graphql
819
- mutation addPendingDocumentMutation(
820
- $relativePath: String!
821
- $collection: String!
822
- $template: String
823
- ) {
824
- addPendingDocument(
825
- relativePath: $relativePath
826
- template: $template
827
- collection: $collection
828
- ) {
829
- ... on Document {
830
- sys {
831
- relativePath
832
- path
833
- breadcrumbs
834
- collection {
835
- slug
836
- }
837
- }
489
+ }, [pendingReset]);
490
+ React.useEffect(() => {
491
+ if (!query) {
492
+ setIsLoading(false);
493
+ return;
838
494
  }
839
- }
840
- }`;
841
- const result = await this.request(mutation, {
842
- variables: props
843
- });
844
- return result;
845
- };
846
- this.getSchema = async () => {
847
- if (!this.schema) {
848
- const data = await this.request(getIntrospectionQuery(), {
849
- variables: {}
850
- });
851
- this.schema = buildClientSchema(data);
852
- }
853
- return this.schema;
854
- };
855
- this.getOptimizedQuery = async (documentNode) => {
856
- const data = await this.request(`query GetOptimizedQuery($queryString: String!) {
857
- getOptimizedQuery(queryString: $queryString)
858
- }`, {
859
- variables: { queryString: print(documentNode) }
860
- });
861
- return parse(data.getOptimizedQuery);
862
- };
863
- this.options = options;
864
- this.setBranch(options.branch);
865
- this.events.subscribe("branch:change", ({ branchName }) => {
866
- this.setBranch(branchName);
867
- });
868
- this.clientId = options.clientId;
869
- switch (tokenStorage) {
870
- case "LOCAL_STORAGE":
871
- this.getToken = async function() {
872
- const tokens = localStorage.getItem(AUTH_TOKEN_KEY) || null;
873
- if (tokens) {
874
- return await this.getRefreshedToken(tokens);
875
- } else {
876
- return {
877
- access_token: null,
878
- id_token: null,
879
- refresh_token: null
880
- };
495
+ const formIds = [];
496
+ setIsLoading(true);
497
+ cms.api.tina.requestWithForm((gql2) => gql2(query), {
498
+ variables,
499
+ useUnstableFormify: cms.flags.get("use-unstable-formify")
500
+ }).then((payload) => {
501
+ cms.plugins.remove(new FormMetaPlugin({ name: "tina-admin-link" }));
502
+ setData(payload);
503
+ setInitialData(payload);
504
+ setIsLoading(false);
505
+ Object.entries(payload).map(([queryName, result]) => {
506
+ formIds.push(queryName);
507
+ const canBeFormified = safeAssertShape(result, (yup2) => yup2.object({
508
+ values: yup2.object().required(),
509
+ form: yup2.object().required()
510
+ }));
511
+ if (!canBeFormified) {
512
+ return;
513
+ }
514
+ assertShape(result, (yup2) => yup2.object({
515
+ values: yup2.object().required(),
516
+ form: yup2.object().required()
517
+ }), `Unable to build form shape for fields at ${queryName}`);
518
+ const formConfig = {
519
+ id: queryName,
520
+ label: result.form.label,
521
+ initialValues: result.values,
522
+ fields: result.form.fields,
523
+ reset: () => {
524
+ setPendingReset(queryName);
525
+ },
526
+ onSubmit: async (payload2) => {
527
+ try {
528
+ const params = transformDocumentIntoMutationRequestPayload(payload2, result.form.mutationInfo);
529
+ const variables2 = { params };
530
+ const mutationString = result.form.mutationInfo.string;
531
+ if (onSubmit) {
532
+ onSubmit({
533
+ queryString: mutationString,
534
+ mutationString,
535
+ variables: variables2
536
+ });
537
+ } else {
538
+ try {
539
+ await cms.api.tina.request(mutationString, {
540
+ variables: variables2
541
+ });
542
+ cms.alerts.success("Document saved!");
543
+ } catch (e) {
544
+ cms.alerts.error("There was a problem saving your document");
545
+ console.error(e);
546
+ }
547
+ }
548
+ } catch (e) {
549
+ console.error(e);
550
+ cms.alerts.error("There was a problem saving your document");
551
+ }
881
552
  }
882
553
  };
883
- this.setToken = function(token) {
884
- localStorage.setItem(AUTH_TOKEN_KEY, JSON.stringify(token, null, 2));
554
+ const { createForm, createGlobalForm } = generateFormCreators(cms);
555
+ const SKIPPED = "SKIPPED";
556
+ let form;
557
+ let skipped;
558
+ const skip = () => {
559
+ skipped = SKIPPED;
885
560
  };
886
- break;
887
- case "MEMORY":
888
- this.getToken = async () => {
889
- if (this.token) {
890
- return await this.getRefreshedToken(this.token);
561
+ if (skipped)
562
+ return;
563
+ if (formify2) {
564
+ form = formify2({ formConfig, createForm, createGlobalForm, skip }, cms);
565
+ } else {
566
+ form = createForm(formConfig);
567
+ }
568
+ if (!(form instanceof Form)) {
569
+ if (skipped === SKIPPED) {
570
+ return;
571
+ }
572
+ throw new Error("formify must return a form or skip()");
573
+ }
574
+ const { change } = form.finalForm;
575
+ form.finalForm.change = (name, value) => {
576
+ let referenceName = "";
577
+ if (typeof name === "string") {
578
+ referenceName = name.split(".").filter((item) => isNaN(Number(item))).join(".");
891
579
  } else {
892
- return {
893
- access_token: null,
894
- id_token: null,
895
- refresh_token: null
896
- };
580
+ throw new Error(`Expected name to be of type string for FinalForm change callback`);
897
581
  }
582
+ setNewUpdate({
583
+ queryName,
584
+ get: [queryName, "values", name].join("."),
585
+ set: [queryName, "data", name].join("."),
586
+ setReference: [queryName, "data", referenceName].join(".")
587
+ });
588
+ return change(name, value);
898
589
  };
899
- this.setToken = (token) => {
900
- this.token = JSON.stringify(token, null, 2);
590
+ const _a = form.finalForm.mutators, { insert, move, remove } = _a, rest = __objRest(_a, ["insert", "move", "remove"]);
591
+ const prepareNewUpdate = (name, lookup) => {
592
+ const extra = {};
593
+ if (lookup) {
594
+ extra["lookup"] = lookup;
595
+ }
596
+ const referenceName = name.split(".").filter((item) => isNaN(Number(item))).join(".");
597
+ setNewUpdate(__spreadValues({
598
+ queryName,
599
+ get: [queryName, "values", name].join("."),
600
+ set: [queryName, "data", name].join("."),
601
+ setReference: [queryName, "data", referenceName].join(".")
602
+ }, extra));
901
603
  };
902
- break;
903
- case "CUSTOM":
904
- if (!options.getTokenFn) {
905
- throw new Error("When CUSTOM token storage is selected, a getTokenFn must be provided");
604
+ form.finalForm.mutators = __spreadValues({
605
+ insert: (...args) => {
606
+ const fieldName = args[0];
607
+ prepareNewUpdate(fieldName, fieldName);
608
+ insert(...args);
609
+ },
610
+ move: (...args) => {
611
+ const fieldName = args[0];
612
+ prepareNewUpdate(fieldName, fieldName);
613
+ move(...args);
614
+ },
615
+ remove: (...args) => {
616
+ const fieldName = args[0];
617
+ prepareNewUpdate(fieldName, fieldName);
618
+ remove(...args);
619
+ }
620
+ }, rest);
621
+ form.subscribe(({ values }) => {
622
+ setFormValues(__spreadProps(__spreadValues({}, formValues), { [queryName]: { values } }));
623
+ }, { values: true });
624
+ });
625
+ }).catch((e) => {
626
+ cms.alerts.error("There was a problem setting up forms for your query");
627
+ console.error("There was a problem setting up forms for your query");
628
+ console.error(e);
629
+ setIsLoading(false);
630
+ });
631
+ return () => {
632
+ formIds.forEach((name) => {
633
+ const formPlugin = cms.forms.find(name);
634
+ if (formPlugin) {
635
+ cms.forms.remove(formPlugin);
906
636
  }
907
- this.getToken = options.getTokenFn;
908
- break;
909
- }
910
- }
911
- get isLocalMode() {
912
- return this.contentApiUrl.includes("localhost");
637
+ });
638
+ };
639
+ }, [query, JSON.stringify(variables), currentBranch]);
640
+ return [data, isLoading];
641
+ }
642
+ const transformDocumentIntoMutationRequestPayload = (document, instructions) => {
643
+ const _a = document, { _collection, __typename, _template } = _a, rest = __objRest(_a, ["_collection", "__typename", "_template"]);
644
+ const params = transformParams(rest);
645
+ const paramsWithTemplate = instructions.includeTemplate ? { [_template]: params } : params;
646
+ return instructions.includeCollection ? { [_collection]: paramsWithTemplate } : paramsWithTemplate;
647
+ };
648
+ const transformParams = (data) => {
649
+ if (["string", "number", "boolean"].includes(typeof data)) {
650
+ return data;
913
651
  }
914
- setBranch(branchName) {
915
- var _a, _b, _c;
916
- const encodedBranch = encodeURIComponent(branchName);
917
- this.frontendUrl = ((_a = this.options.tinaioConfig) == null ? void 0 : _a.frontendUrlOverride) || "https://app.tina.io";
918
- this.identityApiUrl = ((_b = this.options.tinaioConfig) == null ? void 0 : _b.identityApiUrlOverride) || "https://identity.tinajs.io";
919
- this.contentApiBase = ((_c = this.options.tinaioConfig) == null ? void 0 : _c.contentApiUrlOverride) || `https://content.tinajs.io`;
920
- this.contentApiUrl = this.options.customContentApiUrl || `${this.contentApiBase}/content/${this.options.clientId}/github/${encodedBranch}`;
652
+ if (Array.isArray(data)) {
653
+ return data.map((item) => transformParams(item));
921
654
  }
922
- async requestWithForm(query, {
923
- variables,
924
- useUnstableFormify
925
- }) {
926
- const schema = await this.getSchema();
927
- let formifiedQuery;
928
- if (useUnstableFormify) {
929
- const res = await formify({
930
- schema,
931
- query: print(query(gql$1)),
932
- getOptimizedQuery: this.getOptimizedQuery
655
+ try {
656
+ assertShape(data, (yup2) => yup2.object({ _template: yup2.string().required() }));
657
+ const _a = data, { _template, __typename } = _a, rest = __objRest(_a, ["_template", "__typename"]);
658
+ const nested = transformParams(rest);
659
+ return { [_template]: nested };
660
+ } catch (e) {
661
+ if (e.message === "Failed to assertShape - _template is a required field") {
662
+ if (!data) {
663
+ return [];
664
+ }
665
+ const accum = {};
666
+ Object.entries(data).map(([keyName, value]) => {
667
+ accum[keyName] = transformParams(value);
933
668
  });
934
- formifiedQuery = res.formifiedQuery;
669
+ return accum;
935
670
  } else {
936
- formifiedQuery = formify$1(query(gql$1), schema);
671
+ if (!data) {
672
+ return [];
673
+ }
674
+ throw e;
937
675
  }
938
- return this.request(print(formifiedQuery), { variables });
939
676
  }
940
- async request(query, { variables }) {
941
- const res = await fetch(this.contentApiUrl, {
942
- method: "POST",
943
- headers: {
944
- "Content-Type": "application/json",
945
- Authorization: "Bearer " + (await this.getToken()).id_token
946
- },
947
- body: JSON.stringify({
948
- query: typeof query === "function" ? print(query(gql$1)) : query,
949
- variables
950
- })
951
- });
952
- if (res.status !== 200) {
953
- throw new Error(`Unable to complete request, ${res.statusText}`);
677
+ };
678
+ const getFieldUpdate = (newUpdate, activeForm, formValues) => {
679
+ const items = newUpdate.lookup.split(".");
680
+ let currentFields = activeForm.fields;
681
+ items.map((item, index) => {
682
+ const lookupName = items.slice(0, index + 1).join(".");
683
+ const value = getIn(formValues, [newUpdate.queryName, "values", lookupName].join("."));
684
+ if (isNaN(Number(item))) {
685
+ if (Array.isArray(currentFields)) {
686
+ currentFields = currentFields.find((field) => field.name === item);
687
+ }
688
+ } else {
689
+ const template = currentFields.templates ? currentFields.templates[value._template] : currentFields;
690
+ currentFields = template.fields;
954
691
  }
955
- const json = await res.json();
956
- if (json.errors) {
957
- throw new Error(`Unable to fetch, errors:
958
- ${json.errors.map((error) => error.message).join("\n")}`);
692
+ });
693
+ return currentFields;
694
+ };
695
+ const generateFormCreators = (cms) => {
696
+ const createForm = (formConfig) => {
697
+ const form = new Form(formConfig);
698
+ cms.forms.add(form);
699
+ return form;
700
+ };
701
+ const createGlobalForm = (formConfig, options) => {
702
+ const form = new Form(formConfig);
703
+ cms.plugins.add(new GlobalFormPlugin(form, options == null ? void 0 : options.icon, options == null ? void 0 : options.layout));
704
+ return form;
705
+ };
706
+ return { createForm, createGlobalForm };
707
+ };
708
+ const generateFormCreatorsUnstable = (cms, showInSidebar) => {
709
+ const createForm = (formConfig) => {
710
+ const form = new Form(formConfig);
711
+ if (showInSidebar) {
712
+ cms.forms.add(form);
713
+ }
714
+ return form;
715
+ };
716
+ const createGlobalForm = (formConfig, options) => {
717
+ const form = new Form(formConfig);
718
+ if (showInSidebar) {
719
+ cms.plugins.add(new GlobalFormPlugin(form, options == null ? void 0 : options.icon, options == null ? void 0 : options.layout));
720
+ }
721
+ return form;
722
+ };
723
+ return { createForm, createGlobalForm };
724
+ };
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;
959
735
  }
960
- return json.data;
736
+ } else {
737
+ return false;
961
738
  }
962
- parseJwt(token) {
963
- const base64Url = token.split(".")[1];
964
- const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
965
- const jsonPayload = decodeURIComponent(atob(base64).split("").map(function(c) {
966
- return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
967
- }).join(""));
968
- return JSON.parse(jsonPayload);
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`);
969
745
  }
970
- async getRefreshedToken(tokens) {
971
- const { access_token, id_token, refresh_token } = JSON.parse(tokens);
972
- const { exp, iss, client_id } = this.parseJwt(access_token);
973
- if (Date.now() / 1e3 >= exp - 120) {
974
- const refreshResponse = await fetch(iss, {
975
- method: "POST",
976
- headers: {
977
- "Content-Type": "application/x-amz-json-1.1",
978
- "x-amz-target": "AWSCognitoIdentityProviderService.InitiateAuth"
979
- },
980
- body: JSON.stringify({
981
- ClientId: client_id,
982
- AuthFlow: "REFRESH_TOKEN_AUTH",
983
- AuthParameters: {
984
- REFRESH_TOKEN: refresh_token,
985
- DEVICE_KEY: null
986
- }
987
- })
988
- });
989
- if (refreshResponse.status !== 200) {
990
- throw new Error("Unable to refresh auth tokens");
991
- }
992
- const responseJson = await refreshResponse.json();
993
- const newToken = {
994
- access_token: responseJson.AuthenticationResult.AccessToken,
995
- id_token: responseJson.AuthenticationResult.IdToken,
996
- refresh_token
997
- };
998
- this.setToken(newToken);
999
- return Promise.resolve(newToken);
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;
1000
759
  }
1001
- return Promise.resolve({ access_token, id_token, refresh_token });
1002
760
  }
1003
- async isAuthorized() {
1004
- return this.isAuthenticated();
761
+ return false;
762
+ }
763
+ function ensureNodeField(field) {
764
+ if (!isNodeField(field)) {
765
+ throw new Error(`Expected field to implement Node interface`);
1005
766
  }
1006
- async isAuthenticated() {
1007
- return !!await this.getUser();
767
+ }
768
+ function ensureUnionType(type) {
769
+ if (!G.isUnionType(type)) {
770
+ throw new Error(`Expected type to be GraphQLUnionType`);
1008
771
  }
1009
- async authenticate() {
1010
- const token = await authenticate(this.clientId, this.frontendUrl);
1011
- this.setToken(token);
1012
- return token;
772
+ }
773
+ function ensureObjectType(type) {
774
+ if (!G.isObjectType(type)) {
775
+ console.log(type);
776
+ throw new Error(`Expected type to be GraphQLObjectType`);
1013
777
  }
1014
- async fetchWithToken(input, init) {
1015
- const headers = (init == null ? void 0 : init.headers) || {};
1016
- return await fetch(input, __spreadProps(__spreadValues({}, init), {
1017
- headers: new Headers(__spreadValues({
1018
- Authorization: "Bearer " + (await this.getToken()).id_token
1019
- }, headers))
1020
- }));
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`);
1021
782
  }
1022
- async getUser() {
1023
- if (!this.clientId) {
1024
- return null;
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
+ }
1025
813
  }
1026
- const url = `${this.identityApiUrl}/v2/apps/${this.clientId}/currentUser`;
1027
- try {
1028
- const res = await this.fetchWithToken(url, {
1029
- method: "GET"
1030
- });
1031
- const val = await res.json();
1032
- if (!res.status.toString().startsWith("2")) {
1033
- console.error(val.error);
1034
- return null;
814
+ });
815
+ const documentBlueprintPath = path.slice(0, indexOfLastNode + 1);
816
+ return getBlueprintNamePath({ path: documentBlueprintPath });
817
+ };
818
+ const getIn2 = (state, path) => {
819
+ const pathArray = path.split(".");
820
+ let latest = state;
821
+ pathArray.every((item, index) => {
822
+ if (item === "[]") {
823
+ const restOfItems = pathArray.slice(index + 1);
824
+ if (latest) {
825
+ const next = [];
826
+ if (Array.isArray(latest)) {
827
+ latest.forEach((latest2, index2) => {
828
+ const res = getIn2(latest2, restOfItems.join("."));
829
+ next.push(res);
830
+ });
831
+ } else {
832
+ throw new Error(`Expected value to be an array for "[]" item`);
833
+ }
834
+ if (next.length > 0) {
835
+ latest = next;
836
+ } else {
837
+ latest = void 0;
838
+ }
839
+ }
840
+ return false;
841
+ } else {
842
+ if (latest) {
843
+ latest = latest[item];
844
+ } else {
845
+ latest = void 0;
1035
846
  }
1036
- return val;
1037
- } catch (e) {
1038
- console.error(e);
1039
- return null;
1040
847
  }
1041
- }
1042
- async listBranches() {
1043
- const url = `${this.contentApiBase}/github/${this.clientId}/list_branches`;
1044
- const res = await this.fetchWithToken(url, {
1045
- method: "GET"
1046
- });
1047
- return res.json();
1048
- }
1049
- async createBranch({ baseBranch, branchName }) {
1050
- const url = `${this.contentApiBase}/github/${this.clientId}/create_branch`;
1051
- try {
1052
- const res = await this.fetchWithToken(url, {
1053
- method: "POST",
1054
- body: JSON.stringify({
1055
- baseBranch,
1056
- branchName
1057
- }),
1058
- headers: {
1059
- "Content-Type": "application/json"
848
+ return true;
849
+ });
850
+ return latest;
851
+ };
852
+ const getFieldNameOrAlias = (fieldBlueprint) => {
853
+ return fieldBlueprint.path[fieldBlueprint.path.length - 1].alias;
854
+ };
855
+ const spliceLocation = (string, location) => {
856
+ const accum = [];
857
+ let counter = 0;
858
+ string.split(".").forEach((item) => {
859
+ if (item === "[]") {
860
+ accum.push(location[counter]);
861
+ counter++;
862
+ } else {
863
+ accum.push(item);
864
+ }
865
+ });
866
+ return accum.join(".");
867
+ };
868
+ const getPathToChange = (documentBlueprint, formNode, event) => {
869
+ const fieldName = event.field.name;
870
+ const location = [...formNode.location, ...stripIndices(fieldName)];
871
+ const accum = [];
872
+ let counter = 0;
873
+ documentBlueprint.path.forEach((item) => {
874
+ accum.push(item.alias);
875
+ if (item.list) {
876
+ if (location[counter] !== void 0) {
877
+ accum.push(location[counter]);
878
+ counter++;
879
+ }
880
+ }
881
+ });
882
+ return accum.join(".");
883
+ };
884
+ const buildForm = (doc, cms, formify2, showInSidebar = false, onSubmit) => {
885
+ const { createForm, createGlobalForm } = generateFormCreatorsUnstable(cms, showInSidebar);
886
+ const SKIPPED = "SKIPPED";
887
+ let form;
888
+ let skipped;
889
+ const skip = () => {
890
+ skipped = SKIPPED;
891
+ };
892
+ if (skipped)
893
+ return;
894
+ const id = doc._internalSys.path;
895
+ const formConfig = __spreadProps(__spreadValues({
896
+ id
897
+ }, doc.form), {
898
+ label: doc.form.label,
899
+ initialValues: doc.values,
900
+ onSubmit: async (payload) => {
901
+ try {
902
+ const params = transformDocumentIntoMutationRequestPayload(payload, doc.form.mutationInfo);
903
+ const variables = { params };
904
+ const mutationString = doc.form.mutationInfo.string;
905
+ if (onSubmit) {
906
+ onSubmit({
907
+ queryString: mutationString,
908
+ mutationString,
909
+ variables
910
+ });
911
+ } else {
912
+ try {
913
+ await cms.api.tina.request(mutationString, {
914
+ variables
915
+ });
916
+ cms.alerts.success("Document saved!");
917
+ } catch (e) {
918
+ cms.alerts.error("There was a problem saving your document");
919
+ console.error(e);
920
+ }
1060
921
  }
1061
- });
1062
- return await res.json().then((r) => parseRefForBranchName(r.data.ref));
1063
- } catch (error) {
1064
- console.error("There was an error creating a new branch.", error);
1065
- return null;
922
+ } catch (e) {
923
+ console.error(e);
924
+ cms.alerts.error("There was a problem saving your document");
925
+ }
1066
926
  }
927
+ });
928
+ if (formify2) {
929
+ form = formify2({
930
+ formConfig,
931
+ createForm,
932
+ createGlobalForm,
933
+ skip
934
+ }, cms);
935
+ } else {
936
+ form = createForm(formConfig);
1067
937
  }
1068
- }
1069
- const DEFAULT_LOCAL_TINA_GQL_SERVER_URL = "http://localhost:4001/graphql";
1070
- class LocalClient extends Client {
1071
- constructor(props) {
1072
- const clientProps = {
1073
- clientId: "",
1074
- branch: "",
1075
- customContentApiUrl: props && props.customContentApiUrl ? props.customContentApiUrl : DEFAULT_LOCAL_TINA_GQL_SERVER_URL
1076
- };
1077
- super(clientProps);
938
+ if (!(form instanceof Form)) {
939
+ if (skipped === SKIPPED) {
940
+ return;
941
+ }
942
+ throw new Error("formify must return a form or skip()");
1078
943
  }
1079
- async isAuthorized() {
1080
- return true;
944
+ return form;
945
+ };
946
+ const formNodeId = (formNode) => {
947
+ return spliceLocation(formNode.documentBlueprintId, formNode.location) + formNode.documentFormId;
948
+ };
949
+ const formNodePath = (formNode) => {
950
+ return spliceLocation(formNode.documentBlueprintId, formNode.location);
951
+ };
952
+ const formNodeNotIn = (formNode, formNodes) => {
953
+ return !formNodes.find((fn) => formNodeId(fn) === formNodeId(formNode));
954
+ };
955
+ const sequential = async (items, callback) => {
956
+ const accum = [];
957
+ if (!items) {
958
+ return [];
1081
959
  }
1082
- async isAuthenticated() {
1083
- return true;
960
+ const reducePromises = async (previous, endpoint) => {
961
+ const prev = await previous;
962
+ if (prev) {
963
+ accum.push(prev);
964
+ }
965
+ return callback(endpoint, accum.length);
966
+ };
967
+ const result = await items.reduce(reducePromises, Promise.resolve());
968
+ if (result) {
969
+ accum.push(result);
1084
970
  }
1085
- }
1086
- function ModalBuilder(modalProps) {
1087
- return /* @__PURE__ */ React.createElement(Modal, null, /* @__PURE__ */ React.createElement(ModalPopup, null, /* @__PURE__ */ React.createElement(ModalHeader, null, modalProps.title), /* @__PURE__ */ React.createElement(ModalBody, {
1088
- padded: true
1089
- }, /* @__PURE__ */ React.createElement("p", null, modalProps.message), modalProps.error && /* @__PURE__ */ React.createElement(ErrorLabel, null, modalProps.error)), /* @__PURE__ */ React.createElement(ModalActions, null, modalProps.actions.map((action) => /* @__PURE__ */ React.createElement(AsyncButton, __spreadValues({
1090
- key: action.name
1091
- }, action))))));
1092
- }
1093
- const ErrorLabel = styled.p`
1094
- color: var(--tina-color-error) !important;
1095
- `;
1096
- const AsyncButton = ({ name, primary, action }) => {
1097
- const [submitting, setSubmitting] = useState(false);
1098
- const onClick = useCallback(async () => {
1099
- setSubmitting(true);
1100
- try {
1101
- await action();
1102
- setSubmitting(false);
1103
- } catch (e) {
1104
- setSubmitting(false);
1105
- throw e;
971
+ return accum;
972
+ };
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("[]");
1106
982
  }
1107
- }, [action, setSubmitting]);
1108
- return /* @__PURE__ */ React.createElement(Button, {
1109
- variant: primary ? "primary" : "secondary",
1110
- onClick,
1111
- busy: submitting,
1112
- disabled: submitting
1113
- }, submitting && /* @__PURE__ */ React.createElement(LoadingDots, null), !submitting && name);
983
+ });
984
+ return namePath.join(".");
985
+ };
986
+ const getFormNodesStartingWith = (string, state) => {
987
+ return state.formNodes.filter((subFormNode) => {
988
+ return subFormNode.documentBlueprintId.startsWith(string);
989
+ });
990
+ };
991
+ const getFormNodesForField = (fieldBlueprint, formNode, event, state) => {
992
+ const pathToChange = getPathToChange(fieldBlueprint, formNode, event);
993
+ const formNodes = getFormNodesStartingWith(fieldBlueprint.id, state);
994
+ const eventLocation = [
995
+ ...formNode.location,
996
+ ...stripIndices(event.field.name)
997
+ ];
998
+ const existing = getIn(state.data, pathToChange);
999
+ return { pathToChange, formNodes, eventLocation, existing };
1000
+ };
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
+ });
1114
1038
  };
1115
- const TINA_AUTH_CONFIG = "tina_auth_config";
1116
- const useTinaAuthRedirect = () => {
1117
- useEffect(() => {
1118
- const urlParams = new URLSearchParams(window.location.search);
1119
- const config = {
1120
- code: urlParams.get("code") || "",
1121
- scope: urlParams.get("scope") || "email",
1122
- state: urlParams.get("state")
1123
- };
1124
- if (!config.code) {
1125
- return;
1039
+ const getBlueprintAliasPath = (blueprint) => {
1040
+ const namePath = [];
1041
+ const aliasPath = [];
1042
+ blueprint.path.forEach((p) => {
1043
+ namePath.push(p.name);
1044
+ aliasPath.push(p.alias);
1045
+ if (p.list) {
1046
+ namePath.push("[]");
1047
+ aliasPath.push("[]");
1126
1048
  }
1127
- localStorage[TINA_AUTH_CONFIG] = JSON.stringify(config);
1128
- }, []);
1049
+ });
1050
+ return aliasPath.join(".");
1129
1051
  };
1130
- const createClient = ({
1131
- clientId,
1132
- isLocalClient = true,
1133
- branch,
1134
- tinaioConfig
1135
- }) => {
1136
- return isLocalClient ? new LocalClient() : new Client({
1137
- clientId: clientId || "",
1138
- branch: branch || "main",
1139
- tokenStorage: "LOCAL_STORAGE",
1140
- tinaioConfig
1052
+ const getBlueprintFieldsForEvent = (blueprint, event) => {
1053
+ return blueprint.fields.filter((fbp) => {
1054
+ return getBlueprintNamePath(fbp) === getEventPath(event, blueprint);
1141
1055
  });
1142
1056
  };
1143
- function assertShape(value, yupSchema, errorMessage) {
1144
- const shape = yupSchema(yup);
1145
- try {
1146
- shape.validateSync(value);
1147
- } catch (e) {
1148
- const message = errorMessage || `Failed to assertShape - ${e.message}`;
1149
- throw new Error(message);
1150
- }
1151
- }
1152
- function safeAssertShape(value, yupSchema) {
1153
- try {
1154
- assertShape(value, yupSchema);
1155
- return true;
1156
- } catch (e) {
1157
- return false;
1158
- }
1159
- }
1160
- class TinaAdminApi {
1161
- constructor(cms) {
1162
- this.api = cms.api.tina;
1163
- }
1164
- async isAuthenticated() {
1165
- return await this.api.isAuthenticated();
1166
- }
1167
- async fetchCollections() {
1168
- const response = await this.api.request(`#graphql
1169
- query{
1170
- getCollections {
1171
- label,
1172
- name
1173
- }
1174
- }`, { variables: {} });
1175
- return response;
1057
+ const getBlueprintNamePath = (blueprint) => {
1058
+ const namePath = [];
1059
+ const aliasPath = [];
1060
+ blueprint.path.forEach((p) => {
1061
+ namePath.push(p.name);
1062
+ aliasPath.push(p.alias);
1063
+ if (p.list) {
1064
+ namePath.push("[]");
1065
+ aliasPath.push("[]");
1066
+ }
1067
+ });
1068
+ return namePath.join(".");
1069
+ };
1070
+ const stripIndices = (string) => {
1071
+ const accum = [];
1072
+ const stringArray = string.split(".");
1073
+ stringArray.forEach((item) => {
1074
+ if (isNaN(item))
1075
+ ;
1076
+ else {
1077
+ accum.push(Number(item));
1078
+ }
1079
+ });
1080
+ return accum;
1081
+ };
1082
+ const replaceRealNum = (string) => {
1083
+ const stringArray = string.split(".");
1084
+ return stringArray.map((item) => {
1085
+ if (isNaN(item)) {
1086
+ return item;
1087
+ }
1088
+ return "[]";
1089
+ }).join(".");
1090
+ };
1091
+ const getFormNodesFromEvent = (state, event) => {
1092
+ const formNodes = state.formNodes.filter((formNode) => formNode.documentFormId === event.formId);
1093
+ return formNodes;
1094
+ };
1095
+ 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("[]");
1176
1102
  }
1177
- async fetchCollection(collectionName, includeDocuments) {
1178
- const response = await this.api.request(`#graphql
1179
- query($collection: String!, $includeDocuments: Boolean!){
1180
- getCollection(collection: $collection){
1181
- name
1182
- label
1183
- format
1184
- templates
1185
- documents @include(if: $includeDocuments) {
1186
- totalCount
1187
- edges {
1188
- node {
1189
- ... on Document {
1190
- sys {
1191
- template
1192
- breadcrumbs
1193
- path
1194
- basename
1195
- relativePath
1196
- filename
1197
- extension
1198
- }
1199
- }
1200
- }
1201
- }
1103
+ return items.join(".");
1104
+ };
1105
+ const printEvent = (event) => {
1106
+ var _a, _b;
1107
+ return {
1108
+ type: event.type,
1109
+ value: event.value,
1110
+ previousValue: event.previousValue,
1111
+ mutationType: event.mutationType,
1112
+ formId: event.formId,
1113
+ field: {
1114
+ data: (_a = event.field) == null ? void 0 : _a.data,
1115
+ name: (_b = event.field) == null ? void 0 : _b.name
1116
+ }
1117
+ };
1118
+ };
1119
+ const getFormNodeBlueprint = (formNode, state) => {
1120
+ return state.blueprints.find((d) => d.id === formNode.documentBlueprintId);
1121
+ };
1122
+ const getMoveMapping = (existing, from, to) => {
1123
+ const newOrderObject = {};
1124
+ if (from < to) {
1125
+ existing.map((_, i) => {
1126
+ if (i === from) {
1127
+ newOrderObject[i] = to;
1128
+ return;
1129
+ }
1130
+ if (i > from) {
1131
+ if (i < to) {
1132
+ newOrderObject[i] = i - 1;
1133
+ return;
1134
+ } else {
1135
+ if (i === to) {
1136
+ newOrderObject[i] = i - 1;
1137
+ return;
1202
1138
  }
1139
+ newOrderObject[i] = i;
1140
+ return;
1203
1141
  }
1204
- }`, { variables: { collection: collectionName, includeDocuments } });
1205
- return response;
1206
- }
1207
- async fetchDocument(collectionName, relativePath) {
1208
- const response = await this.api.request(`#graphql
1209
- query($collection: String!, $relativePath: String!) {
1210
- getDocument(collection:$collection, relativePath:$relativePath) {
1211
- ... on Document {
1212
- form
1213
- values
1214
- }
1142
+ } else {
1143
+ newOrderObject[i] = i;
1144
+ return;
1145
+ }
1146
+ });
1147
+ } else {
1148
+ existing.map((_, i) => {
1149
+ if (i === from) {
1150
+ newOrderObject[i] = to;
1151
+ return;
1152
+ }
1153
+ if (i > to) {
1154
+ if (i < from) {
1155
+ newOrderObject[i] = i + 1;
1156
+ return;
1157
+ } else {
1158
+ newOrderObject[i] = i;
1159
+ return;
1215
1160
  }
1216
- }`, { variables: { collection: collectionName, relativePath } });
1217
- return response;
1218
- }
1219
- async fetchDocumentFields() {
1220
- const response = await this.api.request(`#graphql
1221
- query {
1222
- getDocumentFields
1223
- }`, { variables: {} });
1224
- return response;
1225
- }
1226
- async createDocument(collectionName, relativePath, params) {
1227
- const response = await this.api.request(`#graphql
1228
- mutation($collection: String!, $relativePath: String!, $params: DocumentMutation!) {
1229
- createDocument(
1230
- collection: $collection,
1231
- relativePath: $relativePath,
1232
- params: $params
1233
- ){__typename}
1234
- }`, {
1235
- variables: {
1236
- collection: collectionName,
1237
- relativePath,
1238
- params
1161
+ } else {
1162
+ if (i === to) {
1163
+ newOrderObject[i] = i + 1;
1164
+ return;
1165
+ }
1166
+ newOrderObject[i] = i;
1167
+ return;
1239
1168
  }
1240
1169
  });
1241
- return response;
1242
1170
  }
1243
- async updateDocument(collectionName, relativePath, params) {
1244
- const response = await this.api.request(`#graphql
1245
- mutation($collection: String!, $relativePath: String!, $params: DocumentMutation!) {
1246
- updateDocument(
1247
- collection: $collection,
1248
- relativePath: $relativePath,
1249
- params: $params
1250
- ){__typename}
1251
- }`, {
1252
- variables: {
1253
- collection: collectionName,
1254
- relativePath,
1255
- params
1256
- }
1171
+ return newOrderObject;
1172
+ };
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 });
1257
1181
  });
1258
- return response;
1182
+ });
1183
+ return pathsToChange;
1184
+ };
1185
+ const getSubFields = (changeSet) => {
1186
+ var _a;
1187
+ const fields = changeSet.fieldDefinition.fields ? changeSet.fieldDefinition.fields : changeSet.fieldDefinition.templates[changeSet.value[0]._template].fields;
1188
+ let __typename;
1189
+ if ((_a = changeSet.fieldDefinition) == null ? void 0 : _a.templates) {
1190
+ __typename = changeSet.fieldDefinition.typeMap[changeSet.value[0]._template];
1259
1191
  }
1260
- }
1261
- function sleep(ms) {
1262
- return new Promise((resolve) => setTimeout(resolve, ms));
1263
- }
1264
- const AuthWallInner = ({
1265
- children,
1266
- cms,
1267
- loginScreen,
1268
- getModalActions
1192
+ return { fields, __typename };
1193
+ };
1194
+ const NOOP = "This is either an error or is not yet supported";
1195
+ const UNEXPECTED = "Formify encountered an unexpected error, please contact support";
1196
+ const EDGES_NODE_NAME = "edges";
1197
+ const NODE_NAME = "node";
1198
+ const COLLECTION_FIELD_NAME = "getCollection";
1199
+ const COLLECTIONS_FIELD_NAME = "getCollections";
1200
+ const COLLECTIONS_DOCUMENTS_NAME = "documents";
1201
+ const DATA_NODE_NAME = "data";
1202
+ const formify = async ({
1203
+ schema,
1204
+ query,
1205
+ getOptimizedQuery
1269
1206
  }) => {
1270
- const client = cms.api.tina;
1271
- const [activeModal, setActiveModal] = useState(null);
1272
- const [showChildren, setShowChildren] = useState(false);
1273
- React.useEffect(() => {
1274
- client.isAuthenticated().then((isAuthenticated) => {
1275
- if (isAuthenticated) {
1276
- setShowChildren(true);
1277
- cms.enable();
1278
- } else {
1279
- sleep(500).then(() => {
1280
- setActiveModal("authenticate");
1207
+ const blueprints = [];
1208
+ const documentNode = G.parse(query);
1209
+ const visitor = {
1210
+ OperationDefinition: (node2) => {
1211
+ if (!node2.name) {
1212
+ return __spreadProps(__spreadValues({}, node2), {
1213
+ name: {
1214
+ kind: "Name",
1215
+ value: `QueryOperation`
1216
+ }
1281
1217
  });
1282
1218
  }
1219
+ return node2;
1220
+ }
1221
+ };
1222
+ const documentNodeWithName = G.visit(documentNode, visitor);
1223
+ const optimizedQuery = await getOptimizedQuery(documentNodeWithName);
1224
+ const typeInfo = new G.TypeInfo(schema);
1225
+ const formifyConnection = ({
1226
+ namedFieldType,
1227
+ selectionNode,
1228
+ path
1229
+ }) => {
1230
+ ensureObjectType(namedFieldType);
1231
+ return __spreadProps(__spreadValues({}, selectionNode), {
1232
+ selectionSet: {
1233
+ kind: "SelectionSet",
1234
+ selections: selectionNode.selectionSet.selections.map((selectionNode2) => {
1235
+ switch (selectionNode2.kind) {
1236
+ case "Field":
1237
+ 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
+ ];
1245
+ return __spreadProps(__spreadValues({}, selectionNode2), {
1246
+ selectionSet: {
1247
+ kind: "SelectionSet",
1248
+ selections: selectionNode2.selectionSet.selections.map((subSelectionNode) => {
1249
+ switch (subSelectionNode.kind) {
1250
+ case "Field":
1251
+ 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,
1259
+ type: nodeField.type,
1260
+ path: path3,
1261
+ showInSidebar: false
1262
+ });
1263
+ } else {
1264
+ return subSelectionNode;
1265
+ }
1266
+ default:
1267
+ throw new FormifyError("NOOP");
1268
+ }
1269
+ })
1270
+ }
1271
+ });
1272
+ }
1273
+ return selectionNode2;
1274
+ default:
1275
+ throw new FormifyError("UNEXPECTED");
1276
+ }
1277
+ })
1278
+ }
1283
1279
  });
1284
- }, []);
1285
- const onAuthSuccess = async () => {
1286
- if (await client.isAuthenticated()) {
1287
- setShowChildren(true);
1288
- setActiveModal(null);
1289
- } else {
1290
- throw new Error("No access to repo");
1291
- }
1292
1280
  };
1293
- const otherModalActions = getModalActions ? getModalActions({
1294
- closeModal: () => {
1295
- setActiveModal(null);
1281
+ function formifyNode({
1282
+ fieldOrInlineFragmentNode,
1283
+ type,
1284
+ path,
1285
+ showInSidebar = false
1286
+ }) {
1287
+ let extraFields = [];
1288
+ const namedType = G.getNamedType(type);
1289
+ let hasDataJSONField = false;
1290
+ let hasValuesField = false;
1291
+ let shouldFormify = false;
1292
+ fieldOrInlineFragmentNode.selectionSet.selections.forEach((selection) => {
1293
+ if (selection.kind === "Field") {
1294
+ if (selection.name.value === "dataJSON") {
1295
+ shouldFormify = true;
1296
+ hasDataJSONField = true;
1297
+ }
1298
+ if (selection.name.value === "values") {
1299
+ shouldFormify = true;
1300
+ hasValuesField = true;
1301
+ }
1302
+ if (selection.name.value === "data") {
1303
+ shouldFormify = true;
1304
+ }
1305
+ }
1306
+ });
1307
+ if (shouldFormify) {
1308
+ blueprints.push({
1309
+ id: getBlueprintId(path),
1310
+ path,
1311
+ selection: fieldOrInlineFragmentNode,
1312
+ fields: [],
1313
+ showInSidebar,
1314
+ hasDataJSONField,
1315
+ hasValuesField
1316
+ });
1317
+ extraFields = metaFields;
1296
1318
  }
1297
- }) : [];
1298
- return /* @__PURE__ */ React.createElement(React.Fragment, null, activeModal === "authenticate" && /* @__PURE__ */ React.createElement(ModalBuilder, {
1299
- title: "Tina Cloud Authorization",
1300
- message: "To save edits, Tina Cloud authorization is required. On save, changes will get commited using your account.",
1301
- close,
1302
- actions: [
1303
- ...otherModalActions,
1304
- {
1305
- action: async () => {
1306
- setEditing(false);
1307
- window.location.reload();
1308
- },
1309
- name: "Close",
1310
- primary: false
1311
- },
1312
- {
1313
- name: "Continue to Tina Cloud",
1314
- action: async () => {
1315
- await client.authenticate();
1316
- onAuthSuccess();
1317
- },
1318
- primary: true
1319
+ const formifiedNode = __spreadProps(__spreadValues({}, fieldOrInlineFragmentNode), {
1320
+ selectionSet: {
1321
+ kind: "SelectionSet",
1322
+ selections: [
1323
+ ...fieldOrInlineFragmentNode.selectionSet.selections.map((selectionNode) => {
1324
+ switch (selectionNode.kind) {
1325
+ case "InlineFragment":
1326
+ 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,
1331
+ path,
1332
+ showInSidebar: false
1333
+ });
1334
+ }
1335
+ ensureUnionType(namedType);
1336
+ const subType = getSelectedUnionType(namedType, selectionNode);
1337
+ return formifyNode({
1338
+ fieldOrInlineFragmentNode: selectionNode,
1339
+ type: subType,
1340
+ path,
1341
+ showInSidebar
1342
+ });
1343
+ case "Field":
1344
+ 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");
1382
+ }
1383
+ return selectionNode;
1384
+ default:
1385
+ throw new FormifyError("UNEXPECTED");
1386
+ }
1387
+ }),
1388
+ ...extraFields
1389
+ ]
1319
1390
  }
1320
- ]
1321
- }), showChildren ? children : loginScreen ? loginScreen : null);
1322
- };
1323
- const TinaCloudProvider = (props) => {
1324
- const baseBranch = props.branch || "main";
1325
- const [currentBranch, setCurrentBranch] = useLocalStorage("tinacms-current-branch", baseBranch);
1326
- useTinaAuthRedirect();
1327
- const cms = React.useMemo(() => props.cms || new TinaCMS({
1328
- enabled: true,
1329
- sidebar: true
1330
- }), [props.cms]);
1331
- if (!cms.api.tina) {
1332
- cms.registerApi("tina", createClient(props));
1333
- }
1334
- if (!cms.api.admin) {
1335
- cms.registerApi("admin", new TinaAdminApi(cms));
1391
+ });
1392
+ return formifiedNode;
1336
1393
  }
1337
- const setupMedia = async () => {
1338
- var _a;
1339
- if (props.mediaStore) {
1340
- if ((_a = props.mediaStore.prototype) == null ? void 0 : _a.persist) {
1341
- cms.media.store = new props.mediaStore(cms.api.tina);
1394
+ const formifyField = ({
1395
+ fieldNode,
1396
+ parentType,
1397
+ path
1398
+ }) => {
1399
+ const namedParentType = G.getNamedType(parentType);
1400
+ ensureObjectType(namedParentType);
1401
+ const field = getObjectField(namedParentType, fieldNode);
1402
+ if (!field) {
1403
+ if (fieldNode.name.value === "__typename") {
1404
+ return fieldNode;
1342
1405
  } else {
1343
- const MediaClass = await props.mediaStore();
1344
- cms.media.store = new MediaClass(cms.api.tina);
1406
+ throw new FormifyError("UNEXPECTED", `field with no associated type ${fieldNode.name.value}`);
1345
1407
  }
1346
1408
  }
1409
+ const namedType = G.getNamedType(field.type);
1410
+ const fieldBlueprint = {
1411
+ id: getBlueprintId([...path]),
1412
+ documentBlueprintId: getRelativeBlueprint(path),
1413
+ path: [...path]
1414
+ };
1415
+ const blueprint = blueprints.find((blueprint2) => blueprint2.id === getRelativeBlueprint(path));
1416
+ blueprint.fields.push(fieldBlueprint);
1417
+ if (G.isScalarType(namedType)) {
1418
+ return fieldNode;
1419
+ }
1420
+ return __spreadProps(__spreadValues({}, fieldNode), {
1421
+ selectionSet: {
1422
+ kind: "SelectionSet",
1423
+ selections: [
1424
+ ...fieldNode.selectionSet.selections.map((selectionNode) => {
1425
+ 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
+ }
1503
+ });
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
+ }
1540
+ });
1541
+ default:
1542
+ throw new FormifyError("UNEXPECTED", `selection ${selectionNode.kind}`);
1543
+ }
1544
+ })
1545
+ ]
1546
+ }
1547
+ });
1548
+ };
1549
+ const formifiedQuery = {
1550
+ kind: "Document",
1551
+ definitions: optimizedQuery.definitions.map((definition) => {
1552
+ typeInfo.enter(definition);
1553
+ ensureOperationDefinition(definition);
1554
+ const type = typeInfo.getType();
1555
+ const namedType = G.getNamedType(type);
1556
+ ensureObjectType(namedType);
1557
+ return __spreadProps(__spreadValues({}, definition), {
1558
+ selectionSet: {
1559
+ kind: "SelectionSet",
1560
+ selections: definition.selectionSet.selections.map((selectionNode) => {
1561
+ switch (selectionNode.kind) {
1562
+ 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,
1571
+ type: field.type,
1572
+ path: [getNameAndAlias(selectionNode, false, true)],
1573
+ showInSidebar: true
1574
+ });
1575
+ } else if (isConnectionField(namedFieldType)) {
1576
+ return formifyConnection({
1577
+ namedFieldType,
1578
+ selectionNode,
1579
+ path: [getNameAndAlias(selectionNode, false, false)]
1580
+ });
1581
+ }
1582
+ if (selectionNode.name.value === COLLECTION_FIELD_NAME || selectionNode.name.value === COLLECTIONS_FIELD_NAME) {
1583
+ const path = [
1584
+ getNameAndAlias(selectionNode, false, false)
1585
+ ];
1586
+ return __spreadProps(__spreadValues({}, selectionNode), {
1587
+ selectionSet: {
1588
+ kind: "SelectionSet",
1589
+ selections: selectionNode.selectionSet.selections.map((subSelectionNode) => {
1590
+ switch (subSelectionNode.kind) {
1591
+ case "Field":
1592
+ 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);
1596
+ return formifyConnection({
1597
+ namedFieldType: docType,
1598
+ selectionNode: subSelectionNode,
1599
+ path: [
1600
+ ...path,
1601
+ getNameAndAlias(subSelectionNode, isListType(docType), isNodeField(docType))
1602
+ ]
1603
+ });
1604
+ }
1605
+ return subSelectionNode;
1606
+ default:
1607
+ throw new FormifyError("NOOP");
1608
+ }
1609
+ })
1610
+ }
1611
+ });
1612
+ }
1613
+ throw new FormifyError("NOOP");
1614
+ default:
1615
+ throw new FormifyError("UNEXPECTED");
1616
+ }
1617
+ })
1618
+ }
1619
+ });
1620
+ })
1347
1621
  };
1348
- const handleListBranches = async () => {
1349
- const { owner, repo } = props;
1350
- const branches = await cms.api.tina.listBranches({ owner, repo });
1351
- if (!Array.isArray(branches)) {
1352
- return [];
1622
+ return { formifiedQuery, blueprints };
1623
+ };
1624
+ class FormifyError extends Error {
1625
+ constructor(code, details) {
1626
+ let message;
1627
+ switch (code) {
1628
+ case "NOOP":
1629
+ message = NOOP;
1630
+ break;
1631
+ case "UNEXPECTED":
1632
+ message = UNEXPECTED;
1633
+ break;
1634
+ default:
1635
+ message = "";
1636
+ break;
1353
1637
  }
1354
- return branches;
1355
- };
1356
- const handleCreateBranch = async (data) => {
1357
- const newBranch = await cms.api.tina.createBranch(data);
1358
- return newBranch;
1359
- };
1360
- setupMedia();
1361
- const [branchingEnabled, setBranchingEnabled] = React.useState(() => cms.flags.get("branch-switcher"));
1362
- React.useEffect(() => {
1363
- cms.events.subscribe("flag:set", ({ key, value }) => {
1364
- if (key === "branch-switcher") {
1365
- setBranchingEnabled(value);
1366
- }
1367
- });
1368
- }, [cms.events]);
1369
- React.useEffect(() => {
1370
- let branchSwitcher;
1371
- if (branchingEnabled) {
1372
- branchSwitcher = new BranchSwitcherPlugin({
1373
- listBranches: handleListBranches,
1374
- createBranch: handleCreateBranch
1638
+ super(`${message} ${details || ""}`);
1639
+ this.name = "FormifyError";
1640
+ }
1641
+ }
1642
+ function reducer(state, action) {
1643
+ var _a, _b, _c, _d;
1644
+ switch (action.type) {
1645
+ case "addDocumentBlueprints":
1646
+ return __spreadProps(__spreadValues({}, state), {
1647
+ status: "formified",
1648
+ blueprints: action.value.blueprints,
1649
+ query: action.value.formifiedQuery
1375
1650
  });
1376
- cms.plugins.add(branchSwitcher);
1377
- }
1378
- return () => {
1379
- if (branchingEnabled && branchSwitcher) {
1380
- cms.plugins.remove(branchSwitcher);
1651
+ case "addOrReplaceDocumentFormNode": {
1652
+ const existingDocumentForms = state.documentForms.filter((documentForm) => {
1653
+ var _a2, _b2;
1654
+ return documentForm.id !== ((_b2 = (_a2 = action.value) == null ? void 0 : _a2.documentForm) == null ? void 0 : _b2.id);
1655
+ });
1656
+ const existingDocumentFormNodes = state.formNodes.filter((formNode) => {
1657
+ return formNodeId(formNode) !== formNodeId(action.value.formNode);
1658
+ });
1659
+ const newDocumentForms = [];
1660
+ if ((_a = action.value) == null ? void 0 : _a.documentForm) {
1661
+ newDocumentForms.push((_b = action.value) == null ? void 0 : _b.documentForm);
1381
1662
  }
1382
- };
1383
- }, [branchingEnabled, props.branch]);
1384
- React.useEffect(() => {
1385
- if (props.cmsCallback) {
1386
- props.cmsCallback(cms);
1387
- }
1388
- }, []);
1389
- return /* @__PURE__ */ React.createElement(BranchDataProvider, {
1390
- currentBranch,
1391
- setCurrentBranch: (b) => {
1392
- setCurrentBranch(b);
1663
+ return __spreadProps(__spreadValues({}, state), {
1664
+ formNodes: [...existingDocumentFormNodes, action.value.formNode],
1665
+ documentForms: [...existingDocumentForms, ...newDocumentForms]
1666
+ });
1393
1667
  }
1394
- }, /* @__PURE__ */ React.createElement(TinaProvider, {
1395
- cms
1396
- }, /* @__PURE__ */ React.createElement(AuthWallInner, __spreadProps(__spreadValues({}, props), {
1397
- cms
1398
- }))));
1399
- };
1400
- const TinaCloudAuthWall = TinaCloudProvider;
1401
- function useGraphqlForms({
1402
- variables,
1403
- onSubmit,
1404
- formify: formify2 = null,
1405
- query
1406
- }) {
1407
- const cms = useCMS();
1408
- const [formValues, setFormValues] = React.useState({});
1409
- const [data, setData] = React.useState(null);
1410
- const [initialData, setInitialData] = React.useState({});
1411
- const [pendingReset, setPendingReset] = React.useState(null);
1412
- const [isLoading, setIsLoading] = React.useState(true);
1413
- const [newUpdate, setNewUpdate] = React.useState(null);
1414
- const { currentBranch } = useBranchData();
1415
- const updateData = async () => {
1416
- var _a;
1417
- if (newUpdate) {
1418
- const newValue = getIn(formValues, newUpdate.get);
1419
- const activeForm = getIn(data, [newUpdate.queryName, "form"].join("."));
1420
- if (!activeForm) {
1421
- throw new Error(`Unable to find form for query ${newUpdate.queryName}`);
1422
- }
1423
- if (activeForm == null ? void 0 : activeForm.paths) {
1424
- const asyncUpdate = (_a = activeForm.paths) == null ? void 0 : _a.find((p) => p.dataPath.join(".") === newUpdate.setReference);
1425
- if (asyncUpdate) {
1426
- const res = await cms.api.tina.request(asyncUpdate.queryString, {
1427
- variables: { id: newValue }
1428
- });
1429
- const newData2 = setIn(data, newUpdate.set, res.node);
1430
- const newDataAndNewJSONData2 = setIn(newData2, newUpdate.set.replace("data", "dataJSON"), newValue);
1431
- setData(newDataAndNewJSONData2);
1432
- setNewUpdate(null);
1433
- return;
1668
+ case "onFieldChange": {
1669
+ const event = action.value.event;
1670
+ const changeSets = [];
1671
+ const formNodesToReplace = [];
1672
+ const formNodesToRemove = [];
1673
+ const newFormNodes = [];
1674
+ const form = state.documentForms.find((documentForm) => documentForm.id === event.formId);
1675
+ getFormNodesFromEvent(state, event).forEach((formNode) => {
1676
+ const blueprint = getFormNodeBlueprint(formNode, state);
1677
+ if (blueprint.hasValuesField) {
1678
+ changeSets.push(__spreadProps(__spreadValues({
1679
+ path: [formNodePath(formNode), "values"].join(".")
1680
+ }, buildChangeSet(event, formNode)), {
1681
+ value: form.values,
1682
+ mutationType: {
1683
+ type: "global"
1684
+ }
1685
+ }));
1434
1686
  }
1435
- }
1436
- if (newUpdate.lookup) {
1437
- const field = getFieldUpdate(newUpdate, activeForm, formValues);
1438
- if (field && field.typeMap) {
1439
- newValue.forEach((item) => {
1440
- if (!item.__typename) {
1441
- item["__typename"] = field.typeMap[item._template];
1687
+ if (blueprint.hasDataJSONField) {
1688
+ changeSets.push(__spreadProps(__spreadValues({
1689
+ path: [formNodePath(formNode), "dataJSON"].join(".")
1690
+ }, buildChangeSet(event, formNode)), {
1691
+ value: form.values,
1692
+ mutationType: {
1693
+ type: "global"
1694
+ }
1695
+ }));
1696
+ }
1697
+ if (event.mutationType.type === "change") {
1698
+ if (!action.value.form) {
1699
+ getPathsToChange(event, state).forEach(({ formNode: formNode2, pathToChange }) => {
1700
+ changeSets.push(__spreadValues({
1701
+ path: pathToChange
1702
+ }, buildChangeSet(event, formNode2)));
1703
+ });
1704
+ }
1705
+ } else if (event.mutationType.type === "referenceChange") {
1706
+ getBlueprintFieldsForEvent(blueprint, event).forEach((fieldBlueprint) => {
1707
+ const { pathToChange, formNodes, eventLocation } = getFormNodesForField(fieldBlueprint, formNode, event, state);
1708
+ if (action.value.form) {
1709
+ const newFormNode = {
1710
+ documentBlueprintId: fieldBlueprint.id,
1711
+ documentFormId: action.value.form.id,
1712
+ location: eventLocation
1713
+ };
1714
+ newFormNodes.push(newFormNode);
1715
+ changeSets.push(__spreadValues({
1716
+ path: pathToChange
1717
+ }, buildChangeSet(event, newFormNode)));
1718
+ }
1719
+ formNodes.forEach((subFormNode) => {
1720
+ if (matchLocation(eventLocation, subFormNode)) {
1721
+ formNodesToReplace.push(subFormNode);
1722
+ }
1723
+ });
1724
+ });
1725
+ } else {
1726
+ getBlueprintFieldsForEvent(blueprint, event).forEach((fieldBlueprint) => {
1727
+ const { pathToChange, formNodes, existing, eventLocation } = getFormNodesForField(fieldBlueprint, formNode, event, state);
1728
+ if (event.mutationType.type === "insert") {
1729
+ formNodes.forEach((subFormNode) => {
1730
+ if (matchLocation(eventLocation, subFormNode)) {
1731
+ newFormNodes.push(__spreadProps(__spreadValues({}, subFormNode), {
1732
+ location: bumpLocation(subFormNode.location)
1733
+ }));
1734
+ formNodesToReplace.push(subFormNode);
1735
+ }
1736
+ });
1737
+ changeSets.push(__spreadValues({
1738
+ path: pathToChange
1739
+ }, buildChangeSet(event, formNode)));
1740
+ }
1741
+ if (event.mutationType.type === "remove") {
1742
+ const { at } = event.mutationType;
1743
+ formNodes.forEach((subFormNode) => {
1744
+ if (matchLocation(eventLocation, subFormNode)) {
1745
+ if (matchesAt(subFormNode.location, at)) {
1746
+ formNodesToRemove.push(subFormNode);
1747
+ } else {
1748
+ newFormNodes.push(__spreadProps(__spreadValues({}, subFormNode), {
1749
+ location: maybeLowerLocation(subFormNode.location, at)
1750
+ }));
1751
+ formNodesToReplace.push(subFormNode);
1752
+ }
1753
+ }
1754
+ });
1755
+ const next = existing.filter((_, index) => index !== at);
1756
+ changeSets.push(__spreadProps(__spreadValues({
1757
+ path: pathToChange
1758
+ }, buildChangeSet(event, formNode)), {
1759
+ value: next
1760
+ }));
1761
+ }
1762
+ if (event.mutationType.type === "move") {
1763
+ const next = [];
1764
+ const { from, to } = event.mutationType;
1765
+ const newOrderObject = getMoveMapping(existing, from, to);
1766
+ formNodes.forEach((subFormNode) => {
1767
+ if (matchLocation(eventLocation, subFormNode)) {
1768
+ newFormNodes.push(__spreadProps(__spreadValues({}, subFormNode), {
1769
+ location: swapLocation(subFormNode.location, newOrderObject)
1770
+ }));
1771
+ formNodesToReplace.push(subFormNode);
1772
+ }
1773
+ });
1774
+ Object.values(newOrderObject).forEach((orderIndex, index) => {
1775
+ next[orderIndex] = existing[index];
1776
+ });
1777
+ changeSets.push(__spreadProps(__spreadValues({
1778
+ path: pathToChange
1779
+ }, buildChangeSet(event, formNode)), {
1780
+ value: next
1781
+ }));
1442
1782
  }
1443
1783
  });
1444
1784
  }
1785
+ });
1786
+ const existingDocumentForms = state.documentForms.filter((documentForm) => {
1787
+ var _a2;
1788
+ return documentForm.id !== ((_a2 = action.value.form) == null ? void 0 : _a2.id);
1789
+ });
1790
+ const newDocumentForms = [];
1791
+ if ((_c = action.value) == null ? void 0 : _c.form) {
1792
+ newDocumentForms.push((_d = action.value) == null ? void 0 : _d.form);
1445
1793
  }
1446
- const newData = setIn(data, newUpdate.set, newValue);
1447
- const newDataAndNewJSONData = setIn(newData, newUpdate.set.replace("data", "dataJSON"), newValue);
1448
- setData(newDataAndNewJSONData);
1449
- setNewUpdate(null);
1794
+ return __spreadProps(__spreadValues({}, state), {
1795
+ changeSets,
1796
+ formNodes: [
1797
+ ...state.formNodes.filter((formNode) => formNodeNotIn(formNode, formNodesToReplace)).filter((formNode) => formNodeNotIn(formNode, formNodesToRemove)),
1798
+ ...newFormNodes
1799
+ ],
1800
+ documentForms: [...existingDocumentForms, ...newDocumentForms]
1801
+ });
1802
+ }
1803
+ case "formOnReset": {
1804
+ const { event } = action.value;
1805
+ const changeSets = [];
1806
+ const form = state.documentForms.find((documentForm) => documentForm.id === event.formId);
1807
+ state.formNodes.filter((fn) => fn.documentFormId === (form == null ? void 0 : form.id)).forEach((formNode) => {
1808
+ const blueprint = getFormNodeBlueprint(formNode, state);
1809
+ if (blueprint.hasValuesField) {
1810
+ changeSets.push(__spreadValues({
1811
+ path: [formNodePath(formNode), "values"].join(".")
1812
+ }, buildChangeSet(event, formNode)));
1813
+ }
1814
+ if (blueprint.hasDataJSONField) {
1815
+ changeSets.push(__spreadValues({
1816
+ path: [formNodePath(formNode), "dataJSON"].join(".")
1817
+ }, buildChangeSet(event, formNode)));
1818
+ }
1819
+ changeSets.push(__spreadValues({
1820
+ path: [formNodePath(formNode), "data"].join(".")
1821
+ }, buildChangeSet(event, formNode)));
1822
+ });
1823
+ return __spreadProps(__spreadValues({}, state), { changeSets });
1824
+ }
1825
+ case "ready":
1826
+ return __spreadProps(__spreadValues({}, state), { status: "ready" });
1827
+ case "done":
1828
+ return __spreadProps(__spreadValues({}, state), { status: "done" });
1829
+ case "setData":
1830
+ return __spreadProps(__spreadValues({}, state), { data: action.value });
1831
+ case "setIn": {
1832
+ let newData;
1833
+ if (action.value.displaceIndex) {
1834
+ const existing = getIn(state.data, action.value.path) || [];
1835
+ newData = setIn(state.data, action.value.path, [
1836
+ action.value.value,
1837
+ ...existing
1838
+ ]);
1839
+ } else {
1840
+ newData = setIn(state.data, action.value.path, action.value.value);
1841
+ }
1842
+ const changeSets = state.changeSets.filter((cs) => cs.path !== action.value.path);
1843
+ return __spreadProps(__spreadValues({}, state), {
1844
+ data: newData,
1845
+ changeSets
1846
+ });
1450
1847
  }
1848
+ default:
1849
+ return state;
1850
+ }
1851
+ }
1852
+ const buildChangeSet = (event, formNode) => {
1853
+ var _a, _b, _c;
1854
+ return {
1855
+ fieldDefinition: (_b = (_a = event.field) == null ? void 0 : _a.data) == null ? void 0 : _b.tinaField,
1856
+ name: (_c = event.field) == null ? void 0 : _c.name,
1857
+ formId: event.formId,
1858
+ mutationType: event.mutationType,
1859
+ value: event.value,
1860
+ formNode
1451
1861
  };
1862
+ };
1863
+ const useFormify = ({
1864
+ query,
1865
+ cms,
1866
+ variables,
1867
+ onSubmit,
1868
+ formify: formifyFunc,
1869
+ eventList
1870
+ }) => {
1871
+ const formIds = React.useRef([]);
1872
+ const [state, dispatch] = React.useReducer(reducer, {
1873
+ status: "initialized",
1874
+ schema: void 0,
1875
+ query: query ? G.parse(query) : null,
1876
+ queryString: query,
1877
+ data: {},
1878
+ changeSets: [],
1879
+ count: 0,
1880
+ blueprints: [],
1881
+ formNodes: [],
1882
+ documentForms: []
1883
+ });
1452
1884
  React.useEffect(() => {
1453
- updateData();
1454
- }, [JSON.stringify(formValues)]);
1455
- React.useEffect(() => {
1456
- if (pendingReset) {
1457
- setData(__spreadProps(__spreadValues({}, data), { [pendingReset]: initialData[pendingReset] }));
1458
- setPendingReset(null);
1885
+ if (state.status === "initialized") {
1886
+ cms.api.tina.request(query, { variables }).then((res) => {
1887
+ delete res.paths;
1888
+ dispatch({ type: "setData", value: res });
1889
+ });
1459
1890
  }
1460
- }, [pendingReset]);
1891
+ }, [state.status]);
1461
1892
  React.useEffect(() => {
1462
- if (!query) {
1463
- setIsLoading(false);
1464
- return;
1893
+ const run = async () => {
1894
+ const schema = await cms.api.tina.getSchema();
1895
+ const result = await formify({
1896
+ schema,
1897
+ query,
1898
+ getOptimizedQuery: cms.api.tina.getOptimizedQuery
1899
+ });
1900
+ dispatch({
1901
+ type: "addDocumentBlueprints",
1902
+ value: result
1903
+ });
1904
+ };
1905
+ if (state.status === "initialized") {
1906
+ run();
1465
1907
  }
1466
- const formIds = [];
1467
- setIsLoading(true);
1468
- cms.api.tina.requestWithForm((gql2) => gql2(query), {
1469
- variables,
1470
- useUnstableFormify: cms.flags.get("use-unstable-formify")
1471
- }).then((payload) => {
1472
- cms.plugins.remove(new FormMetaPlugin({ name: "tina-admin-link" }));
1473
- setData(payload);
1474
- setInitialData(payload);
1475
- setIsLoading(false);
1476
- Object.entries(payload).map(([queryName, result]) => {
1477
- formIds.push(queryName);
1478
- const canBeFormified = safeAssertShape(result, (yup2) => yup2.object({
1479
- values: yup2.object().required(),
1480
- form: yup2.object().required()
1481
- }));
1482
- if (!canBeFormified) {
1483
- return;
1484
- }
1485
- assertShape(result, (yup2) => yup2.object({
1486
- values: yup2.object().required(),
1487
- form: yup2.object().required()
1488
- }), `Unable to build form shape for fields at ${queryName}`);
1489
- const formConfig = {
1490
- id: queryName,
1491
- label: result.form.label,
1492
- initialValues: result.values,
1493
- fields: result.form.fields,
1494
- reset: () => {
1495
- setPendingReset(queryName);
1496
- },
1497
- onSubmit: async (payload2) => {
1498
- try {
1499
- const params = transformDocumentIntoMutationRequestPayload(payload2, result.form.mutationInfo);
1500
- const variables2 = { params };
1501
- const mutationString = result.form.mutationInfo.string;
1502
- if (onSubmit) {
1503
- onSubmit({
1504
- queryString: mutationString,
1505
- mutationString,
1506
- variables: variables2
1507
- });
1908
+ }, [state.status]);
1909
+ React.useEffect(() => {
1910
+ const run = async () => {
1911
+ const result = await cms.api.tina.request(G.print(state.query), {
1912
+ variables
1913
+ });
1914
+ state.blueprints.map((blueprint) => {
1915
+ const responseAtBlueprint = getIn2(result, getBlueprintAliasPath(blueprint));
1916
+ const location = [];
1917
+ const findFormNodes = (res, location2) => {
1918
+ if (Array.isArray(res)) {
1919
+ res.forEach((item, index) => {
1920
+ if (Array.isArray(item)) {
1921
+ findFormNodes(item, [...location2, index]);
1508
1922
  } else {
1509
- try {
1510
- await cms.api.tina.request(mutationString, {
1511
- variables: variables2
1923
+ if (item) {
1924
+ const form = buildForm(item, cms, formifyFunc, blueprint.showInSidebar, onSubmit);
1925
+ const formNode = buildFormNode(blueprint, form, [
1926
+ ...location2,
1927
+ index
1928
+ ]);
1929
+ dispatch({
1930
+ type: "addOrReplaceDocumentFormNode",
1931
+ value: {
1932
+ formNode,
1933
+ documentForm: form
1934
+ }
1512
1935
  });
1513
- cms.alerts.success("Document saved!");
1514
- } catch (e) {
1515
- cms.alerts.error("There was a problem saving your document");
1516
- console.error(e);
1517
1936
  }
1518
1937
  }
1519
- } catch (e) {
1520
- console.error(e);
1521
- cms.alerts.error("There was a problem saving your document");
1522
- }
1938
+ });
1939
+ } else {
1940
+ if (res) {
1941
+ const form = buildForm(res, cms, formifyFunc, blueprint.showInSidebar, onSubmit);
1942
+ const formNode = buildFormNode(blueprint, form, location2);
1943
+ dispatch({
1944
+ type: "addOrReplaceDocumentFormNode",
1945
+ value: {
1946
+ formNode,
1947
+ documentForm: form
1948
+ }
1949
+ });
1950
+ }
1951
+ }
1952
+ };
1953
+ findFormNodes(responseAtBlueprint, location);
1954
+ });
1955
+ dispatch({ type: "ready" });
1956
+ };
1957
+ if (state.status === "formified") {
1958
+ run();
1959
+ }
1960
+ }, [state.status]);
1961
+ React.useEffect(() => {
1962
+ if (state.status === "ready") {
1963
+ cms.events.subscribe(`forms:reset`, (event) => {
1964
+ dispatch({ type: "formOnReset", value: { event } });
1965
+ });
1966
+ cms.events.subscribe(`forms:fields:onChange`, async (event) => {
1967
+ if (eventList) {
1968
+ eventList.push(printEvent(event));
1969
+ }
1970
+ if (event.field.data.tinaField.type === "reference") {
1971
+ let form;
1972
+ if (event.value && typeof event.value === "string") {
1973
+ const existingForm = cms.forms.find(event.value);
1974
+ if (existingForm) {
1975
+ form = existingForm;
1976
+ } else {
1977
+ const formInfo = await cms.api.tina.request(`#graphql
1978
+ query Node($id: String!) {
1979
+ node(id: $id) {
1980
+ ...on Document {
1981
+ form
1982
+ values
1983
+ _internalSys: sys {
1984
+ path
1985
+ }
1986
+ }
1987
+ }
1988
+ }
1989
+ `, { variables: { id: event.value } });
1990
+ form = buildForm(formInfo.node, cms, formifyFunc, false, onSubmit);
1991
+ }
1992
+ }
1993
+ dispatch({
1994
+ type: "onFieldChange",
1995
+ value: {
1996
+ event: __spreadProps(__spreadValues({}, event), {
1997
+ mutationType: { type: "referenceChange" }
1998
+ }),
1999
+ form
2000
+ }
2001
+ });
2002
+ } else {
2003
+ dispatch({ type: "onFieldChange", value: { event } });
2004
+ }
2005
+ });
2006
+ dispatch({ type: "done" });
2007
+ }
2008
+ }, [state.status]);
2009
+ React.useEffect(() => {
2010
+ state.changeSets.forEach((changeSet) => {
2011
+ if (changeSet.mutationType.type === "reset") {
2012
+ const form = cms.forms.find(changeSet.formId);
2013
+ resolveSubFields({
2014
+ formNode: changeSet.formNode,
2015
+ form
2016
+ }).then((res) => {
2017
+ dispatch({
2018
+ type: "setIn",
2019
+ value: {
2020
+ value: res,
2021
+ path: changeSet.path
2022
+ }
2023
+ });
2024
+ });
2025
+ return;
2026
+ } else if (changeSet.mutationType.type === "insert") {
2027
+ if (changeSet.fieldDefinition.type === "object") {
2028
+ const fieldName = changeSet.fieldDefinition.list ? `${changeSet.name}.[]` : changeSet.name;
2029
+ const { fields, __typename } = getSubFields(changeSet);
2030
+ resolveSubFields({
2031
+ formNode: changeSet.formNode,
2032
+ prefix: replaceRealNum(fieldName),
2033
+ loc: [...stripIndices(changeSet.path), 0],
2034
+ form: {
2035
+ fields,
2036
+ values: changeSet.value[0]
2037
+ }
2038
+ }).then((res) => {
2039
+ const extra = {};
2040
+ if (__typename) {
2041
+ extra["__typename"] = __typename;
2042
+ }
2043
+ dispatch({
2044
+ type: "setIn",
2045
+ value: __spreadProps(__spreadValues({
2046
+ displaceIndex: true
2047
+ }, changeSet), {
2048
+ value: __spreadValues(__spreadValues({}, res), extra)
2049
+ })
2050
+ });
2051
+ });
2052
+ } else {
2053
+ dispatch({
2054
+ type: "setIn",
2055
+ value: __spreadProps(__spreadValues({
2056
+ displaceIndex: true
2057
+ }, changeSet), {
2058
+ value: changeSet.value[0]
2059
+ })
2060
+ });
2061
+ }
2062
+ } else {
2063
+ if (changeSet.mutationType.type === "referenceChange") {
2064
+ const { formNode } = changeSet;
2065
+ const blueprint = getFormNodeBlueprint(formNode, state);
2066
+ if (!changeSet.value) {
2067
+ dispatch({
2068
+ type: "setIn",
2069
+ value: __spreadProps(__spreadValues({}, changeSet), {
2070
+ value: null
2071
+ })
2072
+ });
2073
+ } else {
2074
+ cms.api.tina.request(`
2075
+ query Node($id: String!) {
2076
+ node(id: $id) {
2077
+ ${G.print(blueprint.selection)}
2078
+ }
2079
+ }
2080
+ `, { variables: { id: changeSet.value } }).then(async (res) => {
2081
+ const form = state.documentForms.find((documentForm) => documentForm.id === formNode.documentFormId);
2082
+ const data = await resolveSubFields({
2083
+ formNode,
2084
+ form,
2085
+ loc: formNode.location
2086
+ });
2087
+ dispatch({
2088
+ type: "setIn",
2089
+ value: __spreadProps(__spreadValues({}, changeSet), {
2090
+ value: __spreadProps(__spreadValues({}, res.node), {
2091
+ data
2092
+ })
2093
+ })
2094
+ });
2095
+ }).catch((e) => {
2096
+ cms.alerts.error(`Unexpected error fetching reference`);
2097
+ console.log(e);
2098
+ });
1523
2099
  }
1524
- };
1525
- const { createForm, createGlobalForm } = generateFormCreators(cms);
1526
- const SKIPPED = "SKIPPED";
1527
- let form;
1528
- let skipped;
1529
- const skip = () => {
1530
- skipped = SKIPPED;
1531
- };
1532
- if (skipped)
1533
- return;
1534
- if (formify2) {
1535
- form = formify2({ formConfig, createForm, createGlobalForm, skip }, cms);
1536
2100
  } else {
1537
- form = createForm(formConfig);
2101
+ dispatch({ type: "setIn", value: changeSet });
1538
2102
  }
1539
- if (!(form instanceof Form)) {
1540
- if (skipped === SKIPPED) {
1541
- return;
1542
- }
1543
- throw new Error("formify must return a form or skip()");
2103
+ }
2104
+ });
2105
+ }, [state.changeSets.length]);
2106
+ React.useEffect(() => {
2107
+ formIds.current = state.documentForms.map((df) => df.id);
2108
+ }, [state.documentForms.length]);
2109
+ React.useEffect(() => {
2110
+ return () => {
2111
+ formIds.current.forEach((formId) => {
2112
+ const form = cms.forms.find(formId);
2113
+ if (form) {
2114
+ cms.plugins.remove(form);
1544
2115
  }
1545
- const { change } = form.finalForm;
1546
- form.finalForm.change = (name, value) => {
1547
- let referenceName = "";
1548
- if (typeof name === "string") {
1549
- referenceName = name.split(".").filter((item) => isNaN(Number(item))).join(".");
2116
+ });
2117
+ };
2118
+ }, []);
2119
+ const resolveSubFields = React.useCallback(async (args) => {
2120
+ const { form, formNode, prefix, loc } = args;
2121
+ const data = {};
2122
+ await sequential(form.fields, async (field) => {
2123
+ const value = form.values[field.name];
2124
+ const fieldName = field.list ? `${field.name}.[]` : field.name;
2125
+ 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(".");
2137
+ const fieldBlueprints = blueprint.fields.filter((fieldBlueprint) => {
2138
+ return matchName === getBlueprintNamePath(fieldBlueprint);
2139
+ });
2140
+ switch (field.type) {
2141
+ case "object":
2142
+ if (field.templates) {
2143
+ if (field.list) {
2144
+ await sequential(fieldBlueprints, async (fieldBlueprint) => {
2145
+ const keyName = getFieldNameOrAlias(fieldBlueprint);
2146
+ if (!value) {
2147
+ data[keyName] = null;
2148
+ return true;
2149
+ }
2150
+ if (!Array.isArray(value)) {
2151
+ throw new Error(`Expected value for object list field to be an array`);
2152
+ }
2153
+ const d = [];
2154
+ await sequential(value, async (item, index) => {
2155
+ const template = field.templates[item._template];
2156
+ const d2 = await resolveSubFields({
2157
+ formNode,
2158
+ form: { fields: template.fields, values: item },
2159
+ prefix: [prefix, fieldName].join("."),
2160
+ loc: [...loc, index]
2161
+ });
2162
+ d.push(d2);
2163
+ });
2164
+ data[keyName] = d;
2165
+ });
2166
+ } else {
2167
+ throw new Error("blocks without list true is not yet supported");
2168
+ }
1550
2169
  } else {
1551
- throw new Error(`Expected name to be of type string for FinalForm change callback`);
2170
+ if (field.list) {
2171
+ await sequential(fieldBlueprints, async (fieldBlueprint) => {
2172
+ const keyName = getFieldNameOrAlias(fieldBlueprint);
2173
+ if (!value) {
2174
+ data[keyName] = null;
2175
+ return true;
2176
+ }
2177
+ if (!Array.isArray(value)) {
2178
+ throw new Error(`Expected value for object list field to be an array`);
2179
+ }
2180
+ const d = [];
2181
+ await sequential(value, async (item, index) => {
2182
+ const d2 = await resolveSubFields({
2183
+ formNode,
2184
+ form: { fields: field.fields, values: item },
2185
+ prefix: [prefix, fieldName].join("."),
2186
+ loc: [...loc, index]
2187
+ });
2188
+ d.push(d2);
2189
+ return true;
2190
+ });
2191
+ data[keyName] = d;
2192
+ return true;
2193
+ });
2194
+ } else {
2195
+ await sequential(fieldBlueprints, async (fieldBlueprint) => {
2196
+ const keyName = getFieldNameOrAlias(fieldBlueprint);
2197
+ if (!value) {
2198
+ data[keyName] = null;
2199
+ return true;
2200
+ }
2201
+ const d = await resolveSubFields({
2202
+ formNode,
2203
+ form: { fields: field.fields, values: value },
2204
+ prefix: [prefix, fieldName].join("."),
2205
+ loc
2206
+ });
2207
+ data[keyName] = d;
2208
+ return true;
2209
+ });
2210
+ }
1552
2211
  }
1553
- setNewUpdate({
1554
- queryName,
1555
- get: [queryName, "values", name].join("."),
1556
- set: [queryName, "data", name].join("."),
1557
- setReference: [queryName, "data", referenceName].join(".")
2212
+ break;
2213
+ case "reference":
2214
+ let form2;
2215
+ if (typeof value === "string") {
2216
+ const existingForm = cms.forms.find(value);
2217
+ if (existingForm) {
2218
+ form2 = existingForm;
2219
+ } else {
2220
+ const formInfo = await cms.api.tina.request(`#graphql
2221
+ query Node($id: String!) {
2222
+ node(id: $id) {
2223
+ ...on Document {
2224
+ form
2225
+ values
2226
+ _internalSys: sys {
2227
+ path
2228
+ }
2229
+ }
2230
+ }
2231
+ }
2232
+ `, { variables: { id: value } });
2233
+ form2 = buildForm(formInfo.node, cms, formifyFunc, false, onSubmit);
2234
+ }
2235
+ }
2236
+ await sequential(fieldBlueprints, async (fieldBlueprint) => {
2237
+ const keyName = getFieldNameOrAlias(fieldBlueprint);
2238
+ if (!value) {
2239
+ data[keyName] = null;
2240
+ return true;
2241
+ }
2242
+ const documentBlueprint = state.blueprints.find((dp) => getBlueprintNamePath(dp) === matchName);
2243
+ const location = [...formNode.location];
2244
+ if (loc) {
2245
+ loc.forEach((item) => location.push(item));
2246
+ }
2247
+ const subDocumentFormNode = buildFormNode(documentBlueprint, form2, location);
2248
+ dispatch({
2249
+ type: "addOrReplaceDocumentFormNode",
2250
+ value: {
2251
+ formNode: subDocumentFormNode,
2252
+ documentForm: form2
2253
+ }
2254
+ });
2255
+ const res = await cms.api.tina.request(`
2256
+ query Node($id: String!) {
2257
+ node(id: $id) {
2258
+ ${G.print(documentBlueprint.selection)}
2259
+ }
2260
+ }
2261
+ `, { variables: { id: value } });
2262
+ const d = await resolveSubFields({
2263
+ formNode: subDocumentFormNode,
2264
+ form: form2,
2265
+ loc: location
2266
+ });
2267
+ data[keyName] = __spreadProps(__spreadValues({}, res.node), { data: d });
1558
2268
  });
1559
- return change(name, value);
2269
+ break;
2270
+ default:
2271
+ fieldBlueprints.forEach((fieldBlueprint) => {
2272
+ const keyName = getFieldNameOrAlias(fieldBlueprint);
2273
+ if (!value) {
2274
+ data[keyName] = null;
2275
+ } else {
2276
+ data[keyName] = value;
2277
+ }
2278
+ });
2279
+ break;
2280
+ }
2281
+ return true;
2282
+ });
2283
+ return data;
2284
+ }, [cms, JSON.stringify(state), dispatch]);
2285
+ return __spreadProps(__spreadValues({}, state), {
2286
+ queryString: G.print(state.query)
2287
+ });
2288
+ };
2289
+ const buildFormNode = (documentBlueprint, form, location) => {
2290
+ return {
2291
+ documentBlueprintId: documentBlueprint.id,
2292
+ documentFormId: form.id,
2293
+ location
2294
+ };
2295
+ };
2296
+ const captureBranchName = /^refs\/heads\/(.*)/;
2297
+ const parseRefForBranchName = (ref) => {
2298
+ const matches = ref.match(captureBranchName);
2299
+ return matches[1];
2300
+ };
2301
+ class Client {
2302
+ constructor(_a) {
2303
+ var _b = _a, { tokenStorage = "MEMORY" } = _b, options = __objRest(_b, ["tokenStorage"]);
2304
+ this.events = new EventBus();
2305
+ this.addPendingContent = async (props) => {
2306
+ const mutation = `#graphql
2307
+ mutation addPendingDocumentMutation(
2308
+ $relativePath: String!
2309
+ $collection: String!
2310
+ $template: String
2311
+ ) {
2312
+ addPendingDocument(
2313
+ relativePath: $relativePath
2314
+ template: $template
2315
+ collection: $collection
2316
+ ) {
2317
+ ... on Document {
2318
+ sys {
2319
+ relativePath
2320
+ path
2321
+ breadcrumbs
2322
+ collection {
2323
+ slug
2324
+ }
2325
+ }
2326
+ }
2327
+ }
2328
+ }`;
2329
+ const result = await this.request(mutation, {
2330
+ variables: props
2331
+ });
2332
+ return result;
2333
+ };
2334
+ this.getSchema = async () => {
2335
+ if (!this.schema) {
2336
+ const data = await this.request(getIntrospectionQuery(), {
2337
+ variables: {}
2338
+ });
2339
+ this.schema = buildClientSchema(data);
2340
+ }
2341
+ return this.schema;
2342
+ };
2343
+ this.getOptimizedQuery = async (documentNode) => {
2344
+ const data = await this.request(`query GetOptimizedQuery($queryString: String!) {
2345
+ getOptimizedQuery(queryString: $queryString)
2346
+ }`, {
2347
+ variables: { queryString: print(documentNode) }
2348
+ });
2349
+ return parse(data.getOptimizedQuery);
2350
+ };
2351
+ this.options = options;
2352
+ this.setBranch(options.branch);
2353
+ this.events.subscribe("branch:change", ({ branchName }) => {
2354
+ this.setBranch(branchName);
2355
+ });
2356
+ this.clientId = options.clientId;
2357
+ switch (tokenStorage) {
2358
+ case "LOCAL_STORAGE":
2359
+ this.getToken = async function() {
2360
+ const tokens = localStorage.getItem(AUTH_TOKEN_KEY) || null;
2361
+ if (tokens) {
2362
+ return await this.getRefreshedToken(tokens);
2363
+ } else {
2364
+ return {
2365
+ access_token: null,
2366
+ id_token: null,
2367
+ refresh_token: null
2368
+ };
2369
+ }
1560
2370
  };
1561
- const _a = form.finalForm.mutators, { insert, move, remove } = _a, rest = __objRest(_a, ["insert", "move", "remove"]);
1562
- const prepareNewUpdate = (name, lookup) => {
1563
- const extra = {};
1564
- if (lookup) {
1565
- extra["lookup"] = lookup;
2371
+ this.setToken = function(token) {
2372
+ localStorage.setItem(AUTH_TOKEN_KEY, JSON.stringify(token, null, 2));
2373
+ };
2374
+ break;
2375
+ case "MEMORY":
2376
+ this.getToken = async () => {
2377
+ if (this.token) {
2378
+ return await this.getRefreshedToken(this.token);
2379
+ } else {
2380
+ return {
2381
+ access_token: null,
2382
+ id_token: null,
2383
+ refresh_token: null
2384
+ };
1566
2385
  }
1567
- const referenceName = name.split(".").filter((item) => isNaN(Number(item))).join(".");
1568
- setNewUpdate(__spreadValues({
1569
- queryName,
1570
- get: [queryName, "values", name].join("."),
1571
- set: [queryName, "data", name].join("."),
1572
- setReference: [queryName, "data", referenceName].join(".")
1573
- }, extra));
1574
2386
  };
1575
- form.finalForm.mutators = __spreadValues({
1576
- insert: (...args) => {
1577
- const fieldName = args[0];
1578
- prepareNewUpdate(fieldName, fieldName);
1579
- insert(...args);
1580
- },
1581
- move: (...args) => {
1582
- const fieldName = args[0];
1583
- prepareNewUpdate(fieldName, fieldName);
1584
- move(...args);
1585
- },
1586
- remove: (...args) => {
1587
- const fieldName = args[0];
1588
- prepareNewUpdate(fieldName, fieldName);
1589
- remove(...args);
2387
+ this.setToken = (token) => {
2388
+ this.token = JSON.stringify(token, null, 2);
2389
+ };
2390
+ break;
2391
+ case "CUSTOM":
2392
+ if (!options.getTokenFn) {
2393
+ throw new Error("When CUSTOM token storage is selected, a getTokenFn must be provided");
2394
+ }
2395
+ this.getToken = options.getTokenFn;
2396
+ break;
2397
+ }
2398
+ }
2399
+ get isLocalMode() {
2400
+ return this.contentApiUrl.includes("localhost");
2401
+ }
2402
+ setBranch(branchName) {
2403
+ var _a, _b, _c;
2404
+ const encodedBranch = encodeURIComponent(branchName);
2405
+ this.frontendUrl = ((_a = this.options.tinaioConfig) == null ? void 0 : _a.frontendUrlOverride) || "https://app.tina.io";
2406
+ this.identityApiUrl = ((_b = this.options.tinaioConfig) == null ? void 0 : _b.identityApiUrlOverride) || "https://identity.tinajs.io";
2407
+ this.contentApiBase = ((_c = this.options.tinaioConfig) == null ? void 0 : _c.contentApiUrlOverride) || `https://content.tinajs.io`;
2408
+ this.contentApiUrl = this.options.customContentApiUrl || `${this.contentApiBase}/content/${this.options.clientId}/github/${encodedBranch}`;
2409
+ }
2410
+ async requestWithForm(query, {
2411
+ variables,
2412
+ useUnstableFormify
2413
+ }) {
2414
+ const schema = await this.getSchema();
2415
+ let formifiedQuery;
2416
+ if (useUnstableFormify) {
2417
+ const res = await formify({
2418
+ schema,
2419
+ query: print(query(gql$1)),
2420
+ getOptimizedQuery: this.getOptimizedQuery
2421
+ });
2422
+ formifiedQuery = res.formifiedQuery;
2423
+ } else {
2424
+ formifiedQuery = formify$1(query(gql$1), schema);
2425
+ }
2426
+ return this.request(print(formifiedQuery), { variables });
2427
+ }
2428
+ async request(query, { variables }) {
2429
+ const res = await fetch(this.contentApiUrl, {
2430
+ method: "POST",
2431
+ headers: {
2432
+ "Content-Type": "application/json",
2433
+ Authorization: "Bearer " + (await this.getToken()).id_token
2434
+ },
2435
+ body: JSON.stringify({
2436
+ query: typeof query === "function" ? print(query(gql$1)) : query,
2437
+ variables
2438
+ })
2439
+ });
2440
+ if (res.status !== 200) {
2441
+ throw new Error(`Unable to complete request, ${res.statusText}`);
2442
+ }
2443
+ const json = await res.json();
2444
+ if (json.errors) {
2445
+ throw new Error(`Unable to fetch, errors:
2446
+ ${json.errors.map((error) => error.message).join("\n")}`);
2447
+ }
2448
+ return json.data;
2449
+ }
2450
+ parseJwt(token) {
2451
+ const base64Url = token.split(".")[1];
2452
+ const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
2453
+ const jsonPayload = decodeURIComponent(atob(base64).split("").map(function(c) {
2454
+ return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
2455
+ }).join(""));
2456
+ return JSON.parse(jsonPayload);
2457
+ }
2458
+ async getRefreshedToken(tokens) {
2459
+ const { access_token, id_token, refresh_token } = JSON.parse(tokens);
2460
+ const { exp, iss, client_id } = this.parseJwt(access_token);
2461
+ if (Date.now() / 1e3 >= exp - 120) {
2462
+ const refreshResponse = await fetch(iss, {
2463
+ method: "POST",
2464
+ headers: {
2465
+ "Content-Type": "application/x-amz-json-1.1",
2466
+ "x-amz-target": "AWSCognitoIdentityProviderService.InitiateAuth"
2467
+ },
2468
+ body: JSON.stringify({
2469
+ ClientId: client_id,
2470
+ AuthFlow: "REFRESH_TOKEN_AUTH",
2471
+ AuthParameters: {
2472
+ REFRESH_TOKEN: refresh_token,
2473
+ DEVICE_KEY: null
1590
2474
  }
1591
- }, rest);
1592
- form.subscribe(({ values }) => {
1593
- setFormValues(__spreadProps(__spreadValues({}, formValues), { [queryName]: { values } }));
1594
- }, { values: true });
2475
+ })
1595
2476
  });
1596
- }).catch((e) => {
1597
- cms.alerts.error("There was a problem setting up forms for your query");
1598
- console.error("There was a problem setting up forms for your query");
2477
+ if (refreshResponse.status !== 200) {
2478
+ throw new Error("Unable to refresh auth tokens");
2479
+ }
2480
+ const responseJson = await refreshResponse.json();
2481
+ const newToken = {
2482
+ access_token: responseJson.AuthenticationResult.AccessToken,
2483
+ id_token: responseJson.AuthenticationResult.IdToken,
2484
+ refresh_token
2485
+ };
2486
+ this.setToken(newToken);
2487
+ return Promise.resolve(newToken);
2488
+ }
2489
+ return Promise.resolve({ access_token, id_token, refresh_token });
2490
+ }
2491
+ async isAuthorized() {
2492
+ return this.isAuthenticated();
2493
+ }
2494
+ async isAuthenticated() {
2495
+ return !!await this.getUser();
2496
+ }
2497
+ async authenticate() {
2498
+ const token = await authenticate(this.clientId, this.frontendUrl);
2499
+ this.setToken(token);
2500
+ return token;
2501
+ }
2502
+ async fetchWithToken(input, init) {
2503
+ const headers = (init == null ? void 0 : init.headers) || {};
2504
+ return await fetch(input, __spreadProps(__spreadValues({}, init), {
2505
+ headers: new Headers(__spreadValues({
2506
+ Authorization: "Bearer " + (await this.getToken()).id_token
2507
+ }, headers))
2508
+ }));
2509
+ }
2510
+ async getUser() {
2511
+ if (!this.clientId) {
2512
+ return null;
2513
+ }
2514
+ const url = `${this.identityApiUrl}/v2/apps/${this.clientId}/currentUser`;
2515
+ try {
2516
+ const res = await this.fetchWithToken(url, {
2517
+ method: "GET"
2518
+ });
2519
+ const val = await res.json();
2520
+ if (!res.status.toString().startsWith("2")) {
2521
+ console.error(val.error);
2522
+ return null;
2523
+ }
2524
+ return val;
2525
+ } catch (e) {
1599
2526
  console.error(e);
1600
- setIsLoading(false);
2527
+ return null;
2528
+ }
2529
+ }
2530
+ async listBranches() {
2531
+ const url = `${this.contentApiBase}/github/${this.clientId}/list_branches`;
2532
+ const res = await this.fetchWithToken(url, {
2533
+ method: "GET"
1601
2534
  });
1602
- return () => {
1603
- formIds.forEach((name) => {
1604
- const formPlugin = cms.forms.find(name);
1605
- if (formPlugin) {
1606
- cms.forms.remove(formPlugin);
2535
+ return res.json();
2536
+ }
2537
+ async createBranch({ baseBranch, branchName }) {
2538
+ const url = `${this.contentApiBase}/github/${this.clientId}/create_branch`;
2539
+ try {
2540
+ const res = await this.fetchWithToken(url, {
2541
+ method: "POST",
2542
+ body: JSON.stringify({
2543
+ baseBranch,
2544
+ branchName
2545
+ }),
2546
+ headers: {
2547
+ "Content-Type": "application/json"
1607
2548
  }
1608
2549
  });
2550
+ return await res.json().then((r) => parseRefForBranchName(r.data.ref));
2551
+ } catch (error) {
2552
+ console.error("There was an error creating a new branch.", error);
2553
+ return null;
2554
+ }
2555
+ }
2556
+ }
2557
+ const DEFAULT_LOCAL_TINA_GQL_SERVER_URL = "http://localhost:4001/graphql";
2558
+ class LocalClient extends Client {
2559
+ constructor(props) {
2560
+ const clientProps = {
2561
+ clientId: "",
2562
+ branch: "",
2563
+ customContentApiUrl: props && props.customContentApiUrl ? props.customContentApiUrl : DEFAULT_LOCAL_TINA_GQL_SERVER_URL
1609
2564
  };
1610
- }, [query, JSON.stringify(variables), currentBranch]);
1611
- return [data, isLoading];
2565
+ super(clientProps);
2566
+ }
2567
+ async isAuthorized() {
2568
+ return true;
2569
+ }
2570
+ async isAuthenticated() {
2571
+ return true;
2572
+ }
1612
2573
  }
1613
- const transformDocumentIntoMutationRequestPayload = (document, instructions) => {
1614
- const _a = document, { _collection, __typename, _template } = _a, rest = __objRest(_a, ["_collection", "__typename", "_template"]);
1615
- const params = transformParams(rest);
1616
- const paramsWithTemplate = instructions.includeTemplate ? { [_template]: params } : params;
1617
- return instructions.includeCollection ? { [_collection]: paramsWithTemplate } : paramsWithTemplate;
2574
+ function ModalBuilder(modalProps) {
2575
+ return /* @__PURE__ */ React.createElement(Modal, null, /* @__PURE__ */ React.createElement(ModalPopup, null, /* @__PURE__ */ React.createElement(ModalHeader, null, modalProps.title), /* @__PURE__ */ React.createElement(ModalBody, {
2576
+ padded: true
2577
+ }, /* @__PURE__ */ React.createElement("p", null, modalProps.message), modalProps.error && /* @__PURE__ */ React.createElement(ErrorLabel, null, modalProps.error)), /* @__PURE__ */ React.createElement(ModalActions, null, modalProps.actions.map((action) => /* @__PURE__ */ React.createElement(AsyncButton, __spreadValues({
2578
+ key: action.name
2579
+ }, action))))));
2580
+ }
2581
+ const ErrorLabel = styled.p`
2582
+ color: var(--tina-color-error) !important;
2583
+ `;
2584
+ const AsyncButton = ({ name, primary, action }) => {
2585
+ const [submitting, setSubmitting] = useState(false);
2586
+ const onClick = useCallback(async () => {
2587
+ setSubmitting(true);
2588
+ try {
2589
+ await action();
2590
+ setSubmitting(false);
2591
+ } catch (e) {
2592
+ setSubmitting(false);
2593
+ throw e;
2594
+ }
2595
+ }, [action, setSubmitting]);
2596
+ return /* @__PURE__ */ React.createElement(Button, {
2597
+ variant: primary ? "primary" : "secondary",
2598
+ onClick,
2599
+ busy: submitting,
2600
+ disabled: submitting
2601
+ }, submitting && /* @__PURE__ */ React.createElement(LoadingDots, null), !submitting && name);
1618
2602
  };
1619
- const transformParams = (data) => {
1620
- if (["string", "number", "boolean"].includes(typeof data)) {
1621
- return data;
2603
+ const TINA_AUTH_CONFIG = "tina_auth_config";
2604
+ const useTinaAuthRedirect = () => {
2605
+ useEffect(() => {
2606
+ const urlParams = new URLSearchParams(window.location.search);
2607
+ const config = {
2608
+ code: urlParams.get("code") || "",
2609
+ scope: urlParams.get("scope") || "email",
2610
+ state: urlParams.get("state")
2611
+ };
2612
+ if (!config.code) {
2613
+ return;
2614
+ }
2615
+ localStorage[TINA_AUTH_CONFIG] = JSON.stringify(config);
2616
+ }, []);
2617
+ };
2618
+ class TinaAdminApi {
2619
+ constructor(cms) {
2620
+ this.api = cms.api.tina;
2621
+ }
2622
+ async isAuthenticated() {
2623
+ return await this.api.isAuthenticated();
2624
+ }
2625
+ async fetchCollections() {
2626
+ const response = await this.api.request(`#graphql
2627
+ query{
2628
+ getCollections {
2629
+ label,
2630
+ name
2631
+ }
2632
+ }`, { variables: {} });
2633
+ return response;
2634
+ }
2635
+ async fetchCollection(collectionName, includeDocuments) {
2636
+ const response = await this.api.request(`#graphql
2637
+ query($collection: String!, $includeDocuments: Boolean!){
2638
+ getCollection(collection: $collection){
2639
+ name
2640
+ label
2641
+ format
2642
+ templates
2643
+ documents @include(if: $includeDocuments) {
2644
+ totalCount
2645
+ edges {
2646
+ node {
2647
+ ... on Document {
2648
+ sys {
2649
+ template
2650
+ breadcrumbs
2651
+ path
2652
+ basename
2653
+ relativePath
2654
+ filename
2655
+ extension
2656
+ }
2657
+ }
2658
+ }
2659
+ }
2660
+ }
2661
+ }
2662
+ }`, { variables: { collection: collectionName, includeDocuments } });
2663
+ return response;
2664
+ }
2665
+ async fetchDocument(collectionName, relativePath) {
2666
+ const response = await this.api.request(`#graphql
2667
+ query($collection: String!, $relativePath: String!) {
2668
+ getDocument(collection:$collection, relativePath:$relativePath) {
2669
+ ... on Document {
2670
+ form
2671
+ values
2672
+ }
2673
+ }
2674
+ }`, { variables: { collection: collectionName, relativePath } });
2675
+ return response;
1622
2676
  }
1623
- if (Array.isArray(data)) {
1624
- return data.map((item) => transformParams(item));
2677
+ async fetchDocumentFields() {
2678
+ const response = await this.api.request(`#graphql
2679
+ query {
2680
+ getDocumentFields
2681
+ }`, { variables: {} });
2682
+ return response;
1625
2683
  }
1626
- try {
1627
- assertShape(data, (yup2) => yup2.object({ _template: yup2.string().required() }));
1628
- const _a = data, { _template, __typename } = _a, rest = __objRest(_a, ["_template", "__typename"]);
1629
- const nested = transformParams(rest);
1630
- return { [_template]: nested };
1631
- } catch (e) {
1632
- if (e.message === "Failed to assertShape - _template is a required field") {
1633
- if (!data) {
1634
- return [];
2684
+ async createDocument(collectionName, relativePath, params) {
2685
+ const response = await this.api.request(`#graphql
2686
+ mutation($collection: String!, $relativePath: String!, $params: DocumentMutation!) {
2687
+ createDocument(
2688
+ collection: $collection,
2689
+ relativePath: $relativePath,
2690
+ params: $params
2691
+ ){__typename}
2692
+ }`, {
2693
+ variables: {
2694
+ collection: collectionName,
2695
+ relativePath,
2696
+ params
1635
2697
  }
1636
- const accum = {};
1637
- Object.entries(data).map(([keyName, value]) => {
1638
- accum[keyName] = transformParams(value);
1639
- });
1640
- return accum;
1641
- } else {
1642
- if (!data) {
1643
- return [];
2698
+ });
2699
+ return response;
2700
+ }
2701
+ async updateDocument(collectionName, relativePath, params) {
2702
+ const response = await this.api.request(`#graphql
2703
+ mutation($collection: String!, $relativePath: String!, $params: DocumentMutation!) {
2704
+ updateDocument(
2705
+ collection: $collection,
2706
+ relativePath: $relativePath,
2707
+ params: $params
2708
+ ){__typename}
2709
+ }`, {
2710
+ variables: {
2711
+ collection: collectionName,
2712
+ relativePath,
2713
+ params
1644
2714
  }
1645
- throw e;
1646
- }
2715
+ });
2716
+ return response;
1647
2717
  }
1648
- };
1649
- const getFieldUpdate = (newUpdate, activeForm, formValues) => {
1650
- const items = newUpdate.lookup.split(".");
1651
- let currentFields = activeForm.fields;
1652
- items.map((item, index) => {
1653
- const lookupName = items.slice(0, index + 1).join(".");
1654
- const value = getIn(formValues, [newUpdate.queryName, "values", lookupName].join("."));
1655
- if (isNaN(Number(item))) {
1656
- if (Array.isArray(currentFields)) {
1657
- currentFields = currentFields.find((field) => field.name === item);
2718
+ }
2719
+ function sleep(ms) {
2720
+ return new Promise((resolve) => setTimeout(resolve, ms));
2721
+ }
2722
+ const AuthWallInner = ({
2723
+ children,
2724
+ cms,
2725
+ loginScreen,
2726
+ getModalActions
2727
+ }) => {
2728
+ const client = cms.api.tina;
2729
+ const [activeModal, setActiveModal] = useState(null);
2730
+ const [showChildren, setShowChildren] = useState(false);
2731
+ React.useEffect(() => {
2732
+ client.isAuthenticated().then((isAuthenticated) => {
2733
+ if (isAuthenticated) {
2734
+ setShowChildren(true);
2735
+ cms.enable();
2736
+ } else {
2737
+ sleep(500).then(() => {
2738
+ setActiveModal("authenticate");
2739
+ });
1658
2740
  }
2741
+ });
2742
+ }, []);
2743
+ const onAuthSuccess = async () => {
2744
+ if (await client.isAuthenticated()) {
2745
+ setShowChildren(true);
2746
+ setActiveModal(null);
1659
2747
  } else {
1660
- const template = currentFields.templates ? currentFields.templates[value._template] : currentFields;
1661
- currentFields = template.fields;
2748
+ throw new Error("No access to repo");
1662
2749
  }
1663
- });
1664
- return currentFields;
2750
+ };
2751
+ const otherModalActions = getModalActions ? getModalActions({
2752
+ closeModal: () => {
2753
+ setActiveModal(null);
2754
+ }
2755
+ }) : [];
2756
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, activeModal === "authenticate" && /* @__PURE__ */ React.createElement(ModalBuilder, {
2757
+ title: "Tina Cloud Authorization",
2758
+ message: "To save edits, Tina Cloud authorization is required. On save, changes will get commited using your account.",
2759
+ close,
2760
+ actions: [
2761
+ ...otherModalActions,
2762
+ {
2763
+ action: async () => {
2764
+ setEditing(false);
2765
+ window.location.reload();
2766
+ },
2767
+ name: "Close",
2768
+ primary: false
2769
+ },
2770
+ {
2771
+ name: "Continue to Tina Cloud",
2772
+ action: async () => {
2773
+ await client.authenticate();
2774
+ onAuthSuccess();
2775
+ },
2776
+ primary: true
2777
+ }
2778
+ ]
2779
+ }), showChildren ? children : loginScreen ? loginScreen : null);
1665
2780
  };
1666
- const generateFormCreators = (cms) => {
1667
- const createForm = (formConfig) => {
1668
- const form = new Form(formConfig);
1669
- cms.forms.add(form);
1670
- return form;
2781
+ const TinaCloudProvider = (props) => {
2782
+ const baseBranch = props.branch || "main";
2783
+ const [currentBranch, setCurrentBranch] = useLocalStorage("tinacms-current-branch", baseBranch);
2784
+ useTinaAuthRedirect();
2785
+ const cms = React.useMemo(() => props.cms || new TinaCMS({
2786
+ enabled: true,
2787
+ sidebar: true
2788
+ }), [props.cms]);
2789
+ if (!cms.api.tina) {
2790
+ cms.registerApi("tina", createClient(props));
2791
+ }
2792
+ if (!cms.api.admin) {
2793
+ cms.registerApi("admin", new TinaAdminApi(cms));
2794
+ }
2795
+ const setupMedia = async () => {
2796
+ var _a;
2797
+ if (props.mediaStore) {
2798
+ if ((_a = props.mediaStore.prototype) == null ? void 0 : _a.persist) {
2799
+ cms.media.store = new props.mediaStore(cms.api.tina);
2800
+ } else {
2801
+ const MediaClass = await props.mediaStore();
2802
+ cms.media.store = new MediaClass(cms.api.tina);
2803
+ }
2804
+ }
1671
2805
  };
1672
- const createGlobalForm = (formConfig, options) => {
1673
- const form = new Form(formConfig);
1674
- cms.plugins.add(new GlobalFormPlugin(form, options == null ? void 0 : options.icon, options == null ? void 0 : options.layout));
1675
- return form;
2806
+ const handleListBranches = async () => {
2807
+ const { owner, repo } = props;
2808
+ const branches = await cms.api.tina.listBranches({ owner, repo });
2809
+ if (!Array.isArray(branches)) {
2810
+ return [];
2811
+ }
2812
+ return branches;
1676
2813
  };
1677
- return { createForm, createGlobalForm };
2814
+ const handleCreateBranch = async (data) => {
2815
+ const newBranch = await cms.api.tina.createBranch(data);
2816
+ return newBranch;
2817
+ };
2818
+ setupMedia();
2819
+ const [branchingEnabled, setBranchingEnabled] = React.useState(() => cms.flags.get("branch-switcher"));
2820
+ React.useEffect(() => {
2821
+ cms.events.subscribe("flag:set", ({ key, value }) => {
2822
+ if (key === "branch-switcher") {
2823
+ setBranchingEnabled(value);
2824
+ }
2825
+ });
2826
+ }, [cms.events]);
2827
+ React.useEffect(() => {
2828
+ let branchSwitcher;
2829
+ if (branchingEnabled) {
2830
+ branchSwitcher = new BranchSwitcherPlugin({
2831
+ listBranches: handleListBranches,
2832
+ createBranch: handleCreateBranch
2833
+ });
2834
+ cms.plugins.add(branchSwitcher);
2835
+ }
2836
+ return () => {
2837
+ if (branchingEnabled && branchSwitcher) {
2838
+ cms.plugins.remove(branchSwitcher);
2839
+ }
2840
+ };
2841
+ }, [branchingEnabled, props.branch]);
2842
+ React.useEffect(() => {
2843
+ if (props.cmsCallback) {
2844
+ props.cmsCallback(cms);
2845
+ }
2846
+ }, []);
2847
+ return /* @__PURE__ */ React.createElement(BranchDataProvider, {
2848
+ currentBranch,
2849
+ setCurrentBranch: (b) => {
2850
+ setCurrentBranch(b);
2851
+ }
2852
+ }, /* @__PURE__ */ React.createElement(TinaProvider, {
2853
+ cms
2854
+ }, /* @__PURE__ */ React.createElement(AuthWallInner, __spreadProps(__spreadValues({}, props), {
2855
+ cms
2856
+ }))));
1678
2857
  };
2858
+ const TinaCloudAuthWall = TinaCloudProvider;
1679
2859
  class ContentCreatorPlugin {
1680
2860
  constructor(options) {
1681
2861
  this.__type = "content-creator";
@@ -2019,13 +3199,25 @@ const TinaDataProvider = ({
2019
3199
  payload: void 0,
2020
3200
  isLoading: true
2021
3201
  });
3202
+ const cms = useCMS();
3203
+ const useUnstableFormify = React.useMemo(() => {
3204
+ if (cms == null ? void 0 : cms.flags.get("use-unstable-formify")) {
3205
+ return true;
3206
+ }
3207
+ return false;
3208
+ }, [cms == null ? void 0 : cms.flags]);
2022
3209
  return /* @__PURE__ */ React.createElement(TinaDataContext.Provider, {
2023
3210
  value: {
2024
3211
  setRequest,
2025
3212
  isLoading: state.isLoading,
2026
3213
  state: { payload: state.payload }
2027
3214
  }
2028
- }, /* @__PURE__ */ React.createElement(FormRegistrar, {
3215
+ }, useUnstableFormify ? /* @__PURE__ */ React.createElement(FormRegistrarUnstable, {
3216
+ key: request == null ? void 0 : request.query,
3217
+ request,
3218
+ formifyCallback,
3219
+ onPayloadStateChange: setState
3220
+ }) : /* @__PURE__ */ React.createElement(FormRegistrar, {
2029
3221
  key: request == null ? void 0 : request.query,
2030
3222
  request,
2031
3223
  formifyCallback,
@@ -2054,6 +3246,35 @@ const FormRegistrar = ({
2054
3246
  }, [JSON.stringify(payload), isLoading]);
2055
3247
  return isLoading ? /* @__PURE__ */ React.createElement(Loader, null, /* @__PURE__ */ React.createElement(React.Fragment, null)) : null;
2056
3248
  };
3249
+ const FormRegistrarUnstable = (props) => {
3250
+ var _a;
3251
+ if (!((_a = props.request) == null ? void 0 : _a.query)) {
3252
+ return null;
3253
+ }
3254
+ return /* @__PURE__ */ React.createElement(FormRegistrarUnstableInner, __spreadValues({}, props));
3255
+ };
3256
+ const FormRegistrarUnstableInner = ({
3257
+ request,
3258
+ formifyCallback,
3259
+ onPayloadStateChange
3260
+ }) => {
3261
+ const cms = useCMS();
3262
+ const [payload, isLoading] = useGraphqlFormsUnstable({
3263
+ query: request == null ? void 0 : request.query,
3264
+ variables: request == null ? void 0 : request.variables,
3265
+ formify: (args) => {
3266
+ if (formifyCallback) {
3267
+ return formifyCallback(args, cms);
3268
+ } else {
3269
+ return args.createForm(args.formConfig);
3270
+ }
3271
+ }
3272
+ });
3273
+ React.useEffect(() => {
3274
+ onPayloadStateChange({ payload, isLoading });
3275
+ }, [JSON.stringify(payload), isLoading]);
3276
+ return isLoading ? /* @__PURE__ */ React.createElement(Loader, null, /* @__PURE__ */ React.createElement(React.Fragment, null)) : null;
3277
+ };
2057
3278
  const Loader = (props) => {
2058
3279
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
2059
3280
  style: {
@@ -2855,9 +4076,9 @@ const RenderForm$1 = ({ cms, collection, template, fields, mutationInfo }) => {
2855
4076
  }
2856
4077
  return true;
2857
4078
  }
2858
- const isValid = /^[_a-zA-Z][-,_a-zA-Z0-9]*$/.test(value);
4079
+ const isValid = /^[_a-zA-Z][.,-,_a-zA-Z0-9]*$/.test(value);
2859
4080
  if (value && !isValid) {
2860
- return "Must begin with a-z, A-Z, or _ and contain only a-z, A-Z, 0-9, - or _";
4081
+ return "Must begin with a-z, A-Z, or _ and contain only a-z, A-Z, 0-9, -, ., or _";
2861
4082
  }
2862
4083
  }
2863
4084
  },
@@ -3109,4 +4330,4 @@ const defineSchema = (config) => {
3109
4330
  const defineConfig = (config) => {
3110
4331
  return config;
3111
4332
  };
3112
- export { AuthWallInner, Client, DEFAULT_LOCAL_TINA_GQL_SERVER_URL, LocalClient, RouteMappingPlugin, TinaAdmin, TinaAdminApi, TinaCMSProvider2, TinaCloudAuthWall, TinaCloudProvider, TinaDataProvider, assertShape, createClient, TinaCMSProvider2 as default, defineConfig, defineSchema, getStaticPropsForTina, gql, safeAssertShape, staticRequest, useDocumentCreatorPlugin, useGraphqlForms, useTinaAuthRedirect };
4333
+ export { AuthWallInner, Client, DEFAULT_LOCAL_TINA_GQL_SERVER_URL, LocalClient, RouteMappingPlugin, TinaAdmin, TinaAdminApi, TinaCMSProvider2, TinaCloudAuthWall, TinaCloudProvider, TinaDataProvider, assertShape, createClient, TinaCMSProvider2 as default, defineConfig, defineSchema, getStaticPropsForTina, gql, safeAssertShape, staticRequest, useDocumentCreatorPlugin, useGraphqlForms, useGraphqlFormsUnstable, useTinaAuthRedirect };