tinacms 0.59.1 → 0.60.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # tinacms
2
2
 
3
+ ## 0.60.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 75974d0a4: Updates the tina cloud client to do id_token & access_token refreshes when needed
8
+
9
+ ### Patch Changes
10
+
11
+ - 88c209b45: Throw when Tina Cloud responds with non 200 code
12
+ - dcdf1ecf0: Updates `react-router` to `v6` for `TinaAdmin`
13
+ - 47d126029: Fix support of objects in a list for MDX templates
14
+ - Updated dependencies [bc4699d2b]
15
+ - @tinacms/toolkit@0.56.2
16
+
3
17
  ## 0.59.1
4
18
 
5
19
  ### Patch Changes
@@ -11,9 +11,9 @@ See the License for the specific language governing permissions and
11
11
  limitations under the License.
12
12
  */
13
13
  import { TokenObject } from '../auth/authenticate';
14
+ import { BranchData, EventBus } from '@tinacms/toolkit';
14
15
  import { DocumentNode, GraphQLSchema } from 'graphql';
15
16
  import gql from 'graphql-tag';
16
- import { EventBus, BranchData } from '@tinacms/toolkit';
17
17
  export declare type TinaIOConfig = {
18
18
  frontendUrlOverride?: string;
19
19
  identityApiUrlOverride?: string;
@@ -23,7 +23,7 @@ interface ServerOptions {
23
23
  clientId: string;
24
24
  branch: string;
25
25
  customContentApiUrl?: string;
26
- getTokenFn?: () => TokenObject;
26
+ getTokenFn?: () => Promise<TokenObject>;
27
27
  tinaioConfig?: TinaIOConfig;
28
28
  tokenStorage?: 'MEMORY' | 'LOCAL_STORAGE' | 'CUSTOM';
29
29
  }
@@ -51,6 +51,8 @@ export declare class Client {
51
51
  request<ReturnType>(query: ((gqlTag: typeof gql) => DocumentNode) | string, { variables }: {
52
52
  variables: object;
53
53
  }): Promise<ReturnType>;
54
+ parseJwt(token: any): any;
55
+ getRefreshedToken(tokens: string): Promise<TokenObject>;
54
56
  isAuthorized(): Promise<boolean>;
55
57
  isAuthenticated(): Promise<boolean>;
56
58
  authenticate(): Promise<TokenObject>;
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, StyleReset, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, useCMS, useBranchData, FormMetaPlugin, Form, GlobalFormPlugin, FullscreenFormBuilder } from "@tinacms/toolkit";
33
+ export * from "@tinacms/toolkit";
32
34
  import { TypeInfo, visit, visitWithTypeInfo, getNamedType, GraphQLObjectType, isLeafType, GraphQLUnionType, isScalarType, getIntrospectionQuery, buildClientSchema, print } from "graphql";
33
35
  import set from "lodash.set";
34
36
  import gql$1 from "graphql-tag";
35
- import { EventBus, StyleReset, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, useCMS, useBranchData, FormMetaPlugin, Form, GlobalFormPlugin, FullscreenFormBuilder } from "@tinacms/toolkit";
36
- export * from "@tinacms/toolkit";
37
37
  import React, { useState, useCallback, useEffect, Fragment } from "react";
38
38
  import styled from "styled-components";
39
39
  import * as yup from "yup";
40
40
  import { setEditing, useEditState } from "@tinacms/sharedctx";
41
41
  import { getIn, setIn } from "final-form";
42
- import { NavLink, useLocation, useParams, Link, useHistory, BrowserRouter, Switch, Route } from "react-router-dom";
42
+ import { NavLink, useLocation, useParams, Link, useNavigate, BrowserRouter, Routes, Route } from "react-router-dom";
43
43
  import { Menu, Transition } from "@headlessui/react";
44
44
  function popupWindow(url, title, window2, w, h) {
45
45
  const y = window2.top.outerHeight / 2 + window2.top.screenY - h / 2;
@@ -424,10 +424,10 @@ mutation addPendingDocumentMutation(
424
424
  this.clientId = options.clientId;
425
425
  switch (tokenStorage) {
426
426
  case "LOCAL_STORAGE":
427
- this.getToken = function() {
427
+ this.getToken = async function() {
428
428
  const tokens = localStorage.getItem(AUTH_TOKEN_KEY) || null;
429
429
  if (tokens) {
430
- return JSON.parse(tokens);
430
+ return await this.getRefreshedToken(tokens);
431
431
  } else {
432
432
  return {
433
433
  access_token: null,
@@ -441,9 +441,9 @@ mutation addPendingDocumentMutation(
441
441
  };
442
442
  break;
443
443
  case "MEMORY":
444
- this.getToken = () => {
444
+ this.getToken = async () => {
445
445
  if (this.token) {
446
- return JSON.parse(this.token);
446
+ return await this.getRefreshedToken(this.token);
447
447
  } else {
448
448
  return {
449
449
  access_token: null,
@@ -482,13 +482,16 @@ mutation addPendingDocumentMutation(
482
482
  method: "POST",
483
483
  headers: {
484
484
  "Content-Type": "application/json",
485
- Authorization: "Bearer " + this.getToken().id_token
485
+ Authorization: "Bearer " + (await this.getToken()).id_token
486
486
  },
487
487
  body: JSON.stringify({
488
488
  query: typeof query === "function" ? print(query(gql$1)) : query,
489
489
  variables
490
490
  })
491
491
  });
492
+ if (res.status !== 200) {
493
+ throw new Error(`Unable to complete request, ${res.statusText}`);
494
+ }
492
495
  const json = await res.json();
493
496
  if (json.errors) {
494
497
  throw new Error(`Unable to fetch, errors:
@@ -496,6 +499,47 @@ mutation addPendingDocumentMutation(
496
499
  }
497
500
  return json.data;
498
501
  }
502
+ parseJwt(token) {
503
+ const base64Url = token.split(".")[1];
504
+ const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
505
+ const jsonPayload = decodeURIComponent(atob(base64).split("").map(function(c) {
506
+ return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
507
+ }).join(""));
508
+ return JSON.parse(jsonPayload);
509
+ }
510
+ async getRefreshedToken(tokens) {
511
+ const { access_token, id_token, refresh_token } = JSON.parse(tokens);
512
+ const { exp, iss, client_id } = this.parseJwt(access_token);
513
+ if (Date.now() / 1e3 >= exp) {
514
+ const refreshResponse = await fetch(iss, {
515
+ method: "POST",
516
+ headers: {
517
+ "Content-Type": "application/x-amz-json-1.1",
518
+ "x-amz-target": "AWSCognitoIdentityProviderService.InitiateAuth"
519
+ },
520
+ body: JSON.stringify({
521
+ ClientId: client_id,
522
+ AuthFlow: "REFRESH_TOKEN_AUTH",
523
+ AuthParameters: {
524
+ REFRESH_TOKEN: refresh_token,
525
+ DEVICE_KEY: null
526
+ }
527
+ })
528
+ });
529
+ if (refreshResponse.status !== 200) {
530
+ throw new Error("Unable to refresh auth tokens");
531
+ }
532
+ const responseJson = await refreshResponse.json();
533
+ const newToken = {
534
+ access_token: responseJson.AuthenticationResult.AccessToken,
535
+ id_token: responseJson.AuthenticationResult.IdToken,
536
+ refresh_token
537
+ };
538
+ this.setToken(newToken);
539
+ return Promise.resolve(newToken);
540
+ }
541
+ return Promise.resolve({ access_token, id_token, refresh_token });
542
+ }
499
543
  async isAuthorized() {
500
544
  return this.isAuthenticated();
501
545
  }
@@ -511,7 +555,7 @@ mutation addPendingDocumentMutation(
511
555
  const headers = (init == null ? void 0 : init.headers) || {};
512
556
  return await fetch(input, __spreadProps(__spreadValues({}, init), {
513
557
  headers: new Headers(__spreadValues({
514
- Authorization: "Bearer " + this.getToken().id_token
558
+ Authorization: "Bearer " + (await this.getToken()).id_token
515
559
  }, headers))
516
560
  }));
517
561
  }
@@ -995,25 +1039,30 @@ function useGraphqlForms({
995
1039
  setPendingReset(queryName);
996
1040
  },
997
1041
  onSubmit: async (payload2) => {
998
- const params = transformDocumentIntoMutationRequestPayload(payload2, result.form.mutationInfo);
999
- const variables2 = { params };
1000
- const mutationString = result.form.mutationInfo.string;
1001
- if (onSubmit) {
1002
- onSubmit({
1003
- queryString: mutationString,
1004
- mutationString,
1005
- variables: variables2
1006
- });
1007
- } else {
1008
- try {
1009
- await cms.api.tina.request(mutationString, {
1042
+ try {
1043
+ const params = transformDocumentIntoMutationRequestPayload(payload2, result.form.mutationInfo);
1044
+ const variables2 = { params };
1045
+ const mutationString = result.form.mutationInfo.string;
1046
+ if (onSubmit) {
1047
+ onSubmit({
1048
+ queryString: mutationString,
1049
+ mutationString,
1010
1050
  variables: variables2
1011
1051
  });
1012
- cms.alerts.success("Document saved!");
1013
- } catch (e) {
1014
- cms.alerts.error("There was a problem saving your document");
1015
- console.error(e);
1052
+ } else {
1053
+ try {
1054
+ await cms.api.tina.request(mutationString, {
1055
+ variables: variables2
1056
+ });
1057
+ cms.alerts.success("Document saved!");
1058
+ } catch (e) {
1059
+ cms.alerts.error("There was a problem saving your document");
1060
+ console.error(e);
1061
+ }
1016
1062
  }
1063
+ } catch (e) {
1064
+ console.error(e);
1065
+ cms.alerts.error("There was a problem saving your document");
1017
1066
  }
1018
1067
  }
1019
1068
  };
@@ -1125,6 +1174,9 @@ const transformParams = (data) => {
1125
1174
  return { [_template]: nested };
1126
1175
  } catch (e) {
1127
1176
  if (e.message === "Failed to assertShape - _template is a required field") {
1177
+ if (!data) {
1178
+ return [];
1179
+ }
1128
1180
  const accum = {};
1129
1181
  Object.entries(data).map(([keyName, value]) => {
1130
1182
  accum[keyName] = transformParams(value);
@@ -1687,8 +1739,9 @@ const Sidebar = ({ cms }) => {
1687
1739
  return /* @__PURE__ */ React.createElement("li", {
1688
1740
  key: `${collection.name}-link`
1689
1741
  }, /* @__PURE__ */ React.createElement(NavLink, {
1690
- className: `text-lg tracking-wide hover:text-blue-600 flex items-center opacity-90 hover:opacity-100`,
1691
- activeClassName: "text-blue-600",
1742
+ className: ({ isActive }) => {
1743
+ return `text-lg tracking-wide ${isActive ? "text-blue-600" : ""} hover:text-blue-600 flex items-center opacity-90 hover:opacity-100`;
1744
+ },
1692
1745
  to: `/admin/collections/${collection.name}`
1693
1746
  }, /* @__PURE__ */ React.createElement(ImFilesEmpty, {
1694
1747
  className: "mr-2 h-6 opacity-80 w-auto"
@@ -2017,7 +2070,7 @@ const createDocument = async (cms, collection, template, mutationInfo, values) =
2017
2070
  };
2018
2071
  const CollectionCreatePage = () => {
2019
2072
  const { collectionName, templateName } = useParams();
2020
- const history = useHistory();
2073
+ const navigate = useNavigate();
2021
2074
  return /* @__PURE__ */ React.createElement(GetCMS, null, (cms) => /* @__PURE__ */ React.createElement(GetDocumentFields, {
2022
2075
  cms,
2023
2076
  collectionName,
@@ -2038,7 +2091,7 @@ const CollectionCreatePage = () => {
2038
2091
  ],
2039
2092
  onSubmit: async (values) => {
2040
2093
  await createDocument(cms, collection, template, mutationInfo, values);
2041
- history.push(`/admin/collections/${collection.name}`);
2094
+ navigate(`/admin/collections/${collection.name}`);
2042
2095
  }
2043
2096
  });
2044
2097
  const formLabel = template ? `${collection.label} - Create New ${template.label}` : `${collection.label} - Create New`;
@@ -2105,7 +2158,7 @@ const updateDocument = async (cms, relativePath, collection, mutationInfo, value
2105
2158
  };
2106
2159
  const CollectionUpdatePage = () => {
2107
2160
  const { collectionName, filename } = useParams();
2108
- const history = useHistory();
2161
+ const navigate = useNavigate();
2109
2162
  return /* @__PURE__ */ React.createElement(GetCMS, null, (cms) => /* @__PURE__ */ React.createElement(GetDocumentFields, {
2110
2163
  cms,
2111
2164
  collectionName
@@ -2123,7 +2176,7 @@ const CollectionUpdatePage = () => {
2123
2176
  initialValues: document2.values,
2124
2177
  onSubmit: async (values) => {
2125
2178
  await updateDocument(cms, relativePath, collection, mutationInfo, values);
2126
- history.push(`/admin/collections/${collection.name}`);
2179
+ navigate(`/collections/${collection.name}`);
2127
2180
  }
2128
2181
  });
2129
2182
  return /* @__PURE__ */ React.createElement("div", {
@@ -2154,10 +2207,10 @@ const useEmbedTailwind = () => {
2154
2207
  const TinaAdmin = () => {
2155
2208
  useEmbedTailwind();
2156
2209
  const isSSR = typeof window === "undefined";
2210
+ const { edit } = useEditState();
2157
2211
  if (isSSR) {
2158
2212
  return null;
2159
2213
  }
2160
- const { edit } = useEditState();
2161
2214
  if (!edit) {
2162
2215
  return /* @__PURE__ */ React.createElement(Layout, null, /* @__PURE__ */ React.createElement(LoginPage, null));
2163
2216
  }
@@ -2170,22 +2223,27 @@ const TinaAdmin = () => {
2170
2223
  cms
2171
2224
  }), /* @__PURE__ */ React.createElement("div", {
2172
2225
  className: "flex-1"
2173
- }, /* @__PURE__ */ React.createElement(Switch, null, /* @__PURE__ */ React.createElement(Route, {
2174
- path: `/admin/collections/:collectionName/new`
2175
- }, /* @__PURE__ */ React.createElement(CollectionCreatePage, null)), /* @__PURE__ */ React.createElement(Route, {
2176
- path: `/admin/collections/:collectionName/:templateName/new`
2177
- }, /* @__PURE__ */ React.createElement(CollectionCreatePage, null)), /* @__PURE__ */ React.createElement(Route, {
2178
- path: `/admin/collections/:collectionName/:filename`
2179
- }, /* @__PURE__ */ React.createElement(CollectionUpdatePage, null)), /* @__PURE__ */ React.createElement(Route, {
2180
- path: `/admin/collections/:collectionName`
2181
- }, /* @__PURE__ */ React.createElement(CollectionListPage, null)), /* @__PURE__ */ React.createElement(Route, {
2182
- path: `/admin`
2183
- }, /* @__PURE__ */ React.createElement(DashboardPage, null)))))));
2226
+ }, /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, {
2227
+ path: "/admin/collections/:collectionName/new",
2228
+ element: /* @__PURE__ */ React.createElement(CollectionCreatePage, null)
2229
+ }), /* @__PURE__ */ React.createElement(Route, {
2230
+ path: "/admin/collections/:collectionName/:templateName/new",
2231
+ element: /* @__PURE__ */ React.createElement(CollectionCreatePage, null)
2232
+ }), /* @__PURE__ */ React.createElement(Route, {
2233
+ path: "/admin/collections/:collectionName/:filename",
2234
+ element: /* @__PURE__ */ React.createElement(CollectionUpdatePage, null)
2235
+ }), /* @__PURE__ */ React.createElement(Route, {
2236
+ path: "/admin/collections/:collectionName",
2237
+ element: /* @__PURE__ */ React.createElement(CollectionListPage, null)
2238
+ }), /* @__PURE__ */ React.createElement(Route, {
2239
+ path: "/admin",
2240
+ element: /* @__PURE__ */ React.createElement(DashboardPage, null)
2241
+ }))))));
2184
2242
  } else {
2185
- return /* @__PURE__ */ React.createElement(Layout, null, /* @__PURE__ */ React.createElement(BrowserRouter, null, /* @__PURE__ */ React.createElement(Switch, null, /* @__PURE__ */ React.createElement(Route, {
2186
- path: [`/admin/logout`, `/admin/exit`, `/admin/exit-admin`]
2243
+ return /* @__PURE__ */ React.createElement(Layout, null, /* @__PURE__ */ React.createElement(BrowserRouter, null, /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, {
2244
+ path: "/admin/logout"
2187
2245
  }, /* @__PURE__ */ React.createElement(LogoutPage, null)), /* @__PURE__ */ React.createElement(Route, {
2188
- path: `/admin`
2246
+ path: "/admin"
2189
2247
  }, () => {
2190
2248
  window.location.href = "/";
2191
2249
  }))));
package/dist/index.js CHANGED
@@ -30,8 +30,8 @@ var __objRest = (source, exclude) => {
30
30
  return target;
31
31
  };
32
32
  (function(global, factory) {
33
- typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("graphql"), require("lodash.set"), require("graphql-tag"), require("@tinacms/toolkit"), require("react"), require("styled-components"), require("yup"), require("@tinacms/sharedctx"), require("final-form"), require("react-router-dom"), require("@headlessui/react")) : typeof define === "function" && define.amd ? define(["exports", "graphql", "lodash.set", "graphql-tag", "@tinacms/toolkit", "react", "styled-components", "yup", "@tinacms/sharedctx", "final-form", "react-router-dom", "@headlessui/react"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.tinacms = {}, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP));
34
- })(this, function(exports2, graphql, set, gql$1, toolkit, React, styled, yup, sharedctx, finalForm, reactRouterDom, react) {
33
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("@tinacms/toolkit"), require("graphql"), require("lodash.set"), require("graphql-tag"), require("react"), require("styled-components"), require("yup"), require("@tinacms/sharedctx"), require("final-form"), require("react-router-dom"), require("@headlessui/react")) : typeof define === "function" && define.amd ? define(["exports", "@tinacms/toolkit", "graphql", "lodash.set", "graphql-tag", "react", "styled-components", "yup", "@tinacms/sharedctx", "final-form", "react-router-dom", "@headlessui/react"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.tinacms = {}, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP));
34
+ })(this, function(exports2, toolkit, graphql, set, gql$1, React, styled, yup, sharedctx, finalForm, reactRouterDom, react) {
35
35
  "use strict";
36
36
  function _interopDefaultLegacy(e) {
37
37
  return e && typeof e === "object" && "default" in e ? e : { "default": e };
@@ -444,10 +444,10 @@ mutation addPendingDocumentMutation(
444
444
  this.clientId = options.clientId;
445
445
  switch (tokenStorage) {
446
446
  case "LOCAL_STORAGE":
447
- this.getToken = function() {
447
+ this.getToken = async function() {
448
448
  const tokens = localStorage.getItem(AUTH_TOKEN_KEY) || null;
449
449
  if (tokens) {
450
- return JSON.parse(tokens);
450
+ return await this.getRefreshedToken(tokens);
451
451
  } else {
452
452
  return {
453
453
  access_token: null,
@@ -461,9 +461,9 @@ mutation addPendingDocumentMutation(
461
461
  };
462
462
  break;
463
463
  case "MEMORY":
464
- this.getToken = () => {
464
+ this.getToken = async () => {
465
465
  if (this.token) {
466
- return JSON.parse(this.token);
466
+ return await this.getRefreshedToken(this.token);
467
467
  } else {
468
468
  return {
469
469
  access_token: null,
@@ -502,13 +502,16 @@ mutation addPendingDocumentMutation(
502
502
  method: "POST",
503
503
  headers: {
504
504
  "Content-Type": "application/json",
505
- Authorization: "Bearer " + this.getToken().id_token
505
+ Authorization: "Bearer " + (await this.getToken()).id_token
506
506
  },
507
507
  body: JSON.stringify({
508
508
  query: typeof query === "function" ? graphql.print(query(gql__default["default"])) : query,
509
509
  variables
510
510
  })
511
511
  });
512
+ if (res.status !== 200) {
513
+ throw new Error(`Unable to complete request, ${res.statusText}`);
514
+ }
512
515
  const json = await res.json();
513
516
  if (json.errors) {
514
517
  throw new Error(`Unable to fetch, errors:
@@ -516,6 +519,47 @@ mutation addPendingDocumentMutation(
516
519
  }
517
520
  return json.data;
518
521
  }
522
+ parseJwt(token) {
523
+ const base64Url = token.split(".")[1];
524
+ const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
525
+ const jsonPayload = decodeURIComponent(atob(base64).split("").map(function(c) {
526
+ return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
527
+ }).join(""));
528
+ return JSON.parse(jsonPayload);
529
+ }
530
+ async getRefreshedToken(tokens) {
531
+ const { access_token, id_token, refresh_token } = JSON.parse(tokens);
532
+ const { exp, iss, client_id } = this.parseJwt(access_token);
533
+ if (Date.now() / 1e3 >= exp) {
534
+ const refreshResponse = await fetch(iss, {
535
+ method: "POST",
536
+ headers: {
537
+ "Content-Type": "application/x-amz-json-1.1",
538
+ "x-amz-target": "AWSCognitoIdentityProviderService.InitiateAuth"
539
+ },
540
+ body: JSON.stringify({
541
+ ClientId: client_id,
542
+ AuthFlow: "REFRESH_TOKEN_AUTH",
543
+ AuthParameters: {
544
+ REFRESH_TOKEN: refresh_token,
545
+ DEVICE_KEY: null
546
+ }
547
+ })
548
+ });
549
+ if (refreshResponse.status !== 200) {
550
+ throw new Error("Unable to refresh auth tokens");
551
+ }
552
+ const responseJson = await refreshResponse.json();
553
+ const newToken = {
554
+ access_token: responseJson.AuthenticationResult.AccessToken,
555
+ id_token: responseJson.AuthenticationResult.IdToken,
556
+ refresh_token
557
+ };
558
+ this.setToken(newToken);
559
+ return Promise.resolve(newToken);
560
+ }
561
+ return Promise.resolve({ access_token, id_token, refresh_token });
562
+ }
519
563
  async isAuthorized() {
520
564
  return this.isAuthenticated();
521
565
  }
@@ -531,7 +575,7 @@ mutation addPendingDocumentMutation(
531
575
  const headers = (init == null ? void 0 : init.headers) || {};
532
576
  return await fetch(input, __spreadProps(__spreadValues({}, init), {
533
577
  headers: new Headers(__spreadValues({
534
- Authorization: "Bearer " + this.getToken().id_token
578
+ Authorization: "Bearer " + (await this.getToken()).id_token
535
579
  }, headers))
536
580
  }));
537
581
  }
@@ -1015,25 +1059,30 @@ mutation addPendingDocumentMutation(
1015
1059
  setPendingReset(queryName);
1016
1060
  },
1017
1061
  onSubmit: async (payload2) => {
1018
- const params = transformDocumentIntoMutationRequestPayload(payload2, result.form.mutationInfo);
1019
- const variables2 = { params };
1020
- const mutationString = result.form.mutationInfo.string;
1021
- if (onSubmit) {
1022
- onSubmit({
1023
- queryString: mutationString,
1024
- mutationString,
1025
- variables: variables2
1026
- });
1027
- } else {
1028
- try {
1029
- await cms.api.tina.request(mutationString, {
1062
+ try {
1063
+ const params = transformDocumentIntoMutationRequestPayload(payload2, result.form.mutationInfo);
1064
+ const variables2 = { params };
1065
+ const mutationString = result.form.mutationInfo.string;
1066
+ if (onSubmit) {
1067
+ onSubmit({
1068
+ queryString: mutationString,
1069
+ mutationString,
1030
1070
  variables: variables2
1031
1071
  });
1032
- cms.alerts.success("Document saved!");
1033
- } catch (e) {
1034
- cms.alerts.error("There was a problem saving your document");
1035
- console.error(e);
1072
+ } else {
1073
+ try {
1074
+ await cms.api.tina.request(mutationString, {
1075
+ variables: variables2
1076
+ });
1077
+ cms.alerts.success("Document saved!");
1078
+ } catch (e) {
1079
+ cms.alerts.error("There was a problem saving your document");
1080
+ console.error(e);
1081
+ }
1036
1082
  }
1083
+ } catch (e) {
1084
+ console.error(e);
1085
+ cms.alerts.error("There was a problem saving your document");
1037
1086
  }
1038
1087
  }
1039
1088
  };
@@ -1145,6 +1194,9 @@ mutation addPendingDocumentMutation(
1145
1194
  return { [_template]: nested };
1146
1195
  } catch (e) {
1147
1196
  if (e.message === "Failed to assertShape - _template is a required field") {
1197
+ if (!data) {
1198
+ return [];
1199
+ }
1148
1200
  const accum = {};
1149
1201
  Object.entries(data).map(([keyName, value]) => {
1150
1202
  accum[keyName] = transformParams(value);
@@ -1707,8 +1759,9 @@ This will work when developing locally but NOT when deployed to production.
1707
1759
  return /* @__PURE__ */ React__default["default"].createElement("li", {
1708
1760
  key: `${collection.name}-link`
1709
1761
  }, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.NavLink, {
1710
- className: `text-lg tracking-wide hover:text-blue-600 flex items-center opacity-90 hover:opacity-100`,
1711
- activeClassName: "text-blue-600",
1762
+ className: ({ isActive }) => {
1763
+ return `text-lg tracking-wide ${isActive ? "text-blue-600" : ""} hover:text-blue-600 flex items-center opacity-90 hover:opacity-100`;
1764
+ },
1712
1765
  to: `/admin/collections/${collection.name}`
1713
1766
  }, /* @__PURE__ */ React__default["default"].createElement(ImFilesEmpty, {
1714
1767
  className: "mr-2 h-6 opacity-80 w-auto"
@@ -2037,7 +2090,7 @@ This will work when developing locally but NOT when deployed to production.
2037
2090
  };
2038
2091
  const CollectionCreatePage = () => {
2039
2092
  const { collectionName, templateName } = reactRouterDom.useParams();
2040
- const history = reactRouterDom.useHistory();
2093
+ const navigate = reactRouterDom.useNavigate();
2041
2094
  return /* @__PURE__ */ React__default["default"].createElement(GetCMS, null, (cms) => /* @__PURE__ */ React__default["default"].createElement(GetDocumentFields, {
2042
2095
  cms,
2043
2096
  collectionName,
@@ -2058,7 +2111,7 @@ This will work when developing locally but NOT when deployed to production.
2058
2111
  ],
2059
2112
  onSubmit: async (values) => {
2060
2113
  await createDocument(cms, collection, template, mutationInfo, values);
2061
- history.push(`/admin/collections/${collection.name}`);
2114
+ navigate(`/admin/collections/${collection.name}`);
2062
2115
  }
2063
2116
  });
2064
2117
  const formLabel = template ? `${collection.label} - Create New ${template.label}` : `${collection.label} - Create New`;
@@ -2125,7 +2178,7 @@ This will work when developing locally but NOT when deployed to production.
2125
2178
  };
2126
2179
  const CollectionUpdatePage = () => {
2127
2180
  const { collectionName, filename } = reactRouterDom.useParams();
2128
- const history = reactRouterDom.useHistory();
2181
+ const navigate = reactRouterDom.useNavigate();
2129
2182
  return /* @__PURE__ */ React__default["default"].createElement(GetCMS, null, (cms) => /* @__PURE__ */ React__default["default"].createElement(GetDocumentFields, {
2130
2183
  cms,
2131
2184
  collectionName
@@ -2143,7 +2196,7 @@ This will work when developing locally but NOT when deployed to production.
2143
2196
  initialValues: document2.values,
2144
2197
  onSubmit: async (values) => {
2145
2198
  await updateDocument(cms, relativePath, collection, mutationInfo, values);
2146
- history.push(`/admin/collections/${collection.name}`);
2199
+ navigate(`/collections/${collection.name}`);
2147
2200
  }
2148
2201
  });
2149
2202
  return /* @__PURE__ */ React__default["default"].createElement("div", {
@@ -2174,10 +2227,10 @@ This will work when developing locally but NOT when deployed to production.
2174
2227
  const TinaAdmin = () => {
2175
2228
  useEmbedTailwind();
2176
2229
  const isSSR = typeof window === "undefined";
2230
+ const { edit } = sharedctx.useEditState();
2177
2231
  if (isSSR) {
2178
2232
  return null;
2179
2233
  }
2180
- const { edit } = sharedctx.useEditState();
2181
2234
  if (!edit) {
2182
2235
  return /* @__PURE__ */ React__default["default"].createElement(Layout, null, /* @__PURE__ */ React__default["default"].createElement(LoginPage, null));
2183
2236
  }
@@ -2190,22 +2243,27 @@ This will work when developing locally but NOT when deployed to production.
2190
2243
  cms
2191
2244
  }), /* @__PURE__ */ React__default["default"].createElement("div", {
2192
2245
  className: "flex-1"
2193
- }, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Switch, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
2194
- path: `/admin/collections/:collectionName/new`
2195
- }, /* @__PURE__ */ React__default["default"].createElement(CollectionCreatePage, null)), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
2196
- path: `/admin/collections/:collectionName/:templateName/new`
2197
- }, /* @__PURE__ */ React__default["default"].createElement(CollectionCreatePage, null)), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
2198
- path: `/admin/collections/:collectionName/:filename`
2199
- }, /* @__PURE__ */ React__default["default"].createElement(CollectionUpdatePage, null)), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
2200
- path: `/admin/collections/:collectionName`
2201
- }, /* @__PURE__ */ React__default["default"].createElement(CollectionListPage, null)), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
2202
- path: `/admin`
2203
- }, /* @__PURE__ */ React__default["default"].createElement(DashboardPage, null)))))));
2246
+ }, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Routes, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
2247
+ path: "/admin/collections/:collectionName/new",
2248
+ element: /* @__PURE__ */ React__default["default"].createElement(CollectionCreatePage, null)
2249
+ }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
2250
+ path: "/admin/collections/:collectionName/:templateName/new",
2251
+ element: /* @__PURE__ */ React__default["default"].createElement(CollectionCreatePage, null)
2252
+ }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
2253
+ path: "/admin/collections/:collectionName/:filename",
2254
+ element: /* @__PURE__ */ React__default["default"].createElement(CollectionUpdatePage, null)
2255
+ }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
2256
+ path: "/admin/collections/:collectionName",
2257
+ element: /* @__PURE__ */ React__default["default"].createElement(CollectionListPage, null)
2258
+ }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
2259
+ path: "/admin",
2260
+ element: /* @__PURE__ */ React__default["default"].createElement(DashboardPage, null)
2261
+ }))))));
2204
2262
  } else {
2205
- return /* @__PURE__ */ React__default["default"].createElement(Layout, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.BrowserRouter, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Switch, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
2206
- path: [`/admin/logout`, `/admin/exit`, `/admin/exit-admin`]
2263
+ return /* @__PURE__ */ React__default["default"].createElement(Layout, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.BrowserRouter, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Routes, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
2264
+ path: "/admin/logout"
2207
2265
  }, /* @__PURE__ */ React__default["default"].createElement(LogoutPage, null)), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
2208
- path: `/admin`
2266
+ path: "/admin"
2209
2267
  }, () => {
2210
2268
  window.location.href = "/";
2211
2269
  }))));