tinacms 1.3.3 → 1.4.1

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.
@@ -1,6 +1,7 @@
1
1
  /// <reference types="react" />
2
- export declare const TinaAdmin: ({ preview, config, schemaJson, }: {
2
+ export declare const TinaAdmin: ({ preview, Playground, config, schemaJson, }: {
3
3
  schemaJson?: any;
4
4
  preview?: (props: object) => JSX.Element;
5
+ Playground?: (props: object) => JSX.Element;
5
6
  config: object;
6
7
  }) => JSX.Element;
@@ -1,6 +1,3 @@
1
- /**
2
-
3
- */
4
1
  /// <reference types="react" />
5
2
  declare const CollectionCreatePage: () => JSX.Element;
6
3
  export default CollectionCreatePage;
@@ -1,17 +1,5 @@
1
- /**
2
-
3
- */
4
1
  import { Form } from '@tinacms/toolkit';
5
2
  import type { FormOptions, TinaCMS } from '@tinacms/toolkit';
6
- export declare const transformDocumentIntoMutationRequestPayload: (document: {
7
- [key: string]: unknown;
8
- _collection: string;
9
- __typename?: string;
10
- _template: string;
11
- }, instructions: {
12
- includeCollection?: boolean;
13
- includeTemplate?: boolean;
14
- }) => any;
15
3
  export declare const generateFormCreators: (cms: TinaCMS, showInSidebar?: boolean, global?: boolean | {
16
4
  icon?: any;
17
5
  layout: 'fullscreen' | 'popup';
package/dist/index.es.js CHANGED
@@ -4,7 +4,7 @@ export * from "@tinacms/toolkit";
4
4
  export { MdxFieldPluginExtendible } from "@tinacms/toolkit";
5
5
  import { getIntrospectionQuery, buildClientSchema, print, parse, buildSchema } from "graphql";
6
6
  import gql$1 from "graphql-tag";
7
- import { TinaSchema, addNamespaceToSchema, parseURL, resolveForm, validateSchema } from "@tinacms/schema-tools";
7
+ import { TinaSchema, addNamespaceToSchema, parseURL, resolveForm, normalizePath, validateSchema } from "@tinacms/schema-tools";
8
8
  export { NAMER, resolveForm } from "@tinacms/schema-tools";
9
9
  import React, { useState, useCallback, useEffect, Fragment, useMemo } from "react";
10
10
  import * as yup from "yup";
@@ -58,12 +58,18 @@ const IndexStatusResponse = z.object({
58
58
  ]).optional(),
59
59
  timestamp: z.number().optional()
60
60
  });
61
- async function asyncPoll(fn, pollInterval = 5 * 1e3, pollTimeout = 30 * 1e3) {
61
+ function asyncPoll(fn, pollInterval = 5 * 1e3, pollTimeout = 30 * 1e3) {
62
62
  const endTime = new Date().getTime() + pollTimeout;
63
+ let stop = false;
64
+ const cancel = () => {
65
+ stop = true;
66
+ };
63
67
  const checkCondition = (resolve, reject) => {
64
68
  Promise.resolve(fn()).then((result) => {
65
69
  const now = new Date().getTime();
66
- if (result.done) {
70
+ if (stop) {
71
+ reject(new Error("AsyncPoller: cancelled"));
72
+ } else if (result.done) {
67
73
  resolve(result.data);
68
74
  } else if (now < endTime) {
69
75
  setTimeout(checkCondition, pollInterval, resolve, reject);
@@ -74,7 +80,7 @@ async function asyncPoll(fn, pollInterval = 5 * 1e3, pollTimeout = 30 * 1e3) {
74
80
  reject(err);
75
81
  });
76
82
  };
77
- return new Promise(checkCondition);
83
+ return [new Promise(checkCondition), cancel];
78
84
  }
79
85
  class Client {
80
86
  constructor({ tokenStorage = "MEMORY", ...options }) {
@@ -126,6 +132,7 @@ mutation addPendingDocumentMutation(
126
132
  });
127
133
  return parse(data.getOptimizedQuery);
128
134
  };
135
+ this.tinaGraphQLVersion = options.tinaGraphQLVersion;
129
136
  this.onLogin = (_d = (_c = (_b = (_a = options.schema) == null ? void 0 : _a.config) == null ? void 0 : _b.admin) == null ? void 0 : _c.auth) == null ? void 0 : _d.onLogin;
130
137
  this.onLogout = (_h = (_g = (_f = (_e = options.schema) == null ? void 0 : _e.config) == null ? void 0 : _f.admin) == null ? void 0 : _g.auth) == null ? void 0 : _h.onLogout;
131
138
  if ((_l = (_k = (_j = (_i = options.schema) == null ? void 0 : _i.config) == null ? void 0 : _j.admin) == null ? void 0 : _k.auth) == null ? void 0 : _l.logout) {
@@ -210,7 +217,7 @@ mutation addPendingDocumentMutation(
210
217
  this.frontendUrl = ((_b = this.options.tinaioConfig) == null ? void 0 : _b.frontendUrlOverride) || "https://app.tina.io";
211
218
  this.identityApiUrl = ((_c = this.options.tinaioConfig) == null ? void 0 : _c.identityApiUrlOverride) || "https://identity.tinajs.io";
212
219
  this.contentApiBase = ((_d = this.options.tinaioConfig) == null ? void 0 : _d.contentApiUrlOverride) || `https://content.tinajs.io`;
213
- this.contentApiUrl = this.options.customContentApiUrl || `${this.contentApiBase}/content/${this.options.clientId}/github/${encodedBranch}`;
220
+ this.contentApiUrl = this.options.customContentApiUrl || `${this.contentApiBase}/${this.tinaGraphQLVersion}/content/${this.options.clientId}/github/${encodedBranch}`;
214
221
  }
215
222
  async request(query, { variables }) {
216
223
  const res = await fetch(this.contentApiUrl, {
@@ -230,6 +237,13 @@ mutation addPendingDocumentMutation(
230
237
  if (resBody.message) {
231
238
  errorMessage = `${errorMessage}, Response: ${resBody.message}`;
232
239
  }
240
+ errorMessage = `${errorMessage}, Please check that the following information is correct:
241
+ clientId: ${this.options.clientId}
242
+ branch: ${this.branch}.`;
243
+ if (this.branch !== "main") {
244
+ errorMessage = `${errorMessage}
245
+ Note: This error can occur if the branch does not exist on GitHub or on Tina Cloud`;
246
+ }
233
247
  throw new Error(errorMessage);
234
248
  }
235
249
  const json = await res.json();
@@ -375,15 +389,15 @@ mutation addPendingDocumentMutation(
375
389
  return null;
376
390
  }
377
391
  }
378
- async waitForIndexStatus({ ref }) {
392
+ waitForIndexStatus({ ref }) {
379
393
  try {
380
- const result = await asyncPoll(async () => {
394
+ const [prom, cancel] = asyncPoll(async () => {
381
395
  try {
382
- const result2 = await this.getIndexStatus({ ref });
383
- if (!(result2.status === "inprogress" || result2.status === "unknown")) {
396
+ const result = await this.getIndexStatus({ ref });
397
+ if (!(result.status === "inprogress" || result.status === "unknown")) {
384
398
  return Promise.resolve({
385
399
  done: true,
386
- data: result2
400
+ data: result
387
401
  });
388
402
  } else {
389
403
  return Promise.resolve({
@@ -394,7 +408,7 @@ mutation addPendingDocumentMutation(
394
408
  return Promise.reject(err);
395
409
  }
396
410
  }, 5e3, 9e5);
397
- return result;
411
+ return [prom, cancel];
398
412
  } catch (error) {
399
413
  if (error.message === "AsyncPoller: reached timeout") {
400
414
  console.warn(error);
@@ -462,6 +476,7 @@ class LocalClient extends Client {
462
476
  ...props,
463
477
  clientId: "",
464
478
  branch: "",
479
+ tinaGraphQLVersion: "",
465
480
  customContentApiUrl: props && props.customContentApiUrl ? props.customContentApiUrl : DEFAULT_LOCAL_TINA_GQL_SERVER_URL
466
481
  };
467
482
  super(clientProps);
@@ -533,14 +548,16 @@ const createClient = ({
533
548
  branch,
534
549
  tinaioConfig,
535
550
  schema,
536
- apiUrl
551
+ apiUrl,
552
+ tinaGraphQLVersion
537
553
  }) => {
538
554
  return isLocalClient ? new LocalClient({ customContentApiUrl: apiUrl, schema }) : new Client({
539
555
  clientId: clientId || "",
540
556
  branch: branch || "main",
541
557
  tokenStorage: "LOCAL_STORAGE",
542
558
  tinaioConfig,
543
- schema
559
+ schema,
560
+ tinaGraphQLVersion
544
561
  });
545
562
  };
546
563
  function assertShape(value, yupSchema, errorMessage) {
@@ -2302,7 +2319,8 @@ const TinaCMSProvider2 = ({
2302
2319
  cmsCallback: props.cmsCallback,
2303
2320
  mediaStore: props.mediaStore,
2304
2321
  apiUrl: apiURL,
2305
- schema: { ...schema, config: { ...schema.config, ...props } }
2322
+ schema: { ...schema, config: { ...schema.config, ...props } },
2323
+ tinaGraphQLVersion: props.tinaGraphQLVersion
2306
2324
  }, /* @__PURE__ */ React.createElement("style", null, styles), /* @__PURE__ */ React.createElement(ErrorBoundary, null, props.children)));
2307
2325
  };
2308
2326
  const Loader = (props) => {
@@ -3607,42 +3625,6 @@ const RenameModal = ({
3607
3625
  function HiChevronRight(props) {
3608
3626
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 20 20", "fill": "currentColor" }, "child": [{ "tag": "path", "attr": { "fillRule": "evenodd", "d": "M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z", "clipRule": "evenodd" } }] })(props);
3609
3627
  }
3610
- const transformDocumentIntoMutationRequestPayload = (document, instructions) => {
3611
- const { _collection, __typename, _template, ...rest } = document;
3612
- const params = transformParams(rest);
3613
- const paramsWithTemplate = instructions.includeTemplate ? { [_template]: params } : params;
3614
- return instructions.includeCollection ? { [_collection]: paramsWithTemplate } : paramsWithTemplate;
3615
- };
3616
- const transformParams = (data) => {
3617
- if (["string", "number", "boolean"].includes(typeof data)) {
3618
- return data;
3619
- }
3620
- if (Array.isArray(data)) {
3621
- return data.map((item) => transformParams(item));
3622
- }
3623
- try {
3624
- assertShape(data, (yup2) => yup2.object({ _template: yup2.string().required() }));
3625
- const { _template, __typename, ...rest } = data;
3626
- const nested = transformParams(rest);
3627
- return { [_template]: nested };
3628
- } catch (e) {
3629
- if (e.message === "Failed to assertShape - _template is a required field") {
3630
- if (!data) {
3631
- return [];
3632
- }
3633
- const accum = {};
3634
- Object.entries(data).map(([keyName, value]) => {
3635
- accum[keyName] = transformParams(value);
3636
- });
3637
- return accum;
3638
- } else {
3639
- if (!data) {
3640
- return [];
3641
- }
3642
- throw e;
3643
- }
3644
- }
3645
- };
3646
3628
  function FaLock(props) {
3647
3629
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 448 512" }, "child": [{ "tag": "path", "attr": { "d": "M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zm-104 0H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z" } }] })(props);
3648
3630
  }
@@ -3652,15 +3634,11 @@ function FaUnlock(props) {
3652
3634
  const createDocument = async (cms, collection, template, mutationInfo, values) => {
3653
3635
  const api = new TinaAdminApi(cms);
3654
3636
  const { filename, ...leftover } = values;
3655
- const { includeCollection, includeTemplate } = mutationInfo;
3656
3637
  const relativePath = `${filename}.${collection.format}`;
3657
- const params = transformDocumentIntoMutationRequestPayload({
3638
+ const params = api.schema.transformPayload(collection.name, {
3658
3639
  _collection: collection.name,
3659
3640
  ...template && { _template: template.name },
3660
3641
  ...leftover
3661
- }, {
3662
- includeCollection,
3663
- includeTemplate
3664
3642
  });
3665
3643
  if (await api.isAuthenticated()) {
3666
3644
  await api.createDocument(collection.name, relativePath, params);
@@ -3765,6 +3743,7 @@ const RenderForm$1 = ({ cms, collection, templateName, mutationInfo }) => {
3765
3743
  description: /* @__PURE__ */ React.createElement("span", null, "A unique filename for the content.", /* @__PURE__ */ React.createElement("br", null), "Examples: ", /* @__PURE__ */ React.createElement("code", null, "My_Document"), ", ", /* @__PURE__ */ React.createElement("code", null, "My_Document.en"), ",", " ", /* @__PURE__ */ React.createElement("code", null, "sub-folder/My_Document")),
3766
3744
  placeholder: `My_Document`,
3767
3745
  validate: (value, allValues, meta) => {
3746
+ var _a3, _b3;
3768
3747
  if (!value) {
3769
3748
  if (meta.dirty) {
3770
3749
  return "Required";
@@ -3775,6 +3754,16 @@ const RenderForm$1 = ({ cms, collection, templateName, mutationInfo }) => {
3775
3754
  if (value && !isValid) {
3776
3755
  return "Must begin with a-z, A-Z, 0-9, or _ and contain only a-z, A-Z, 0-9, -, _, ., or /.";
3777
3756
  }
3757
+ if (((_a3 = schemaCollection.match) == null ? void 0 : _a3.exclude) || ((_b3 = schemaCollection.match) == null ? void 0 : _b3.include)) {
3758
+ const filePath = `${normalizePath(schemaCollection.path)}/${value}.${schemaCollection.format || "md"}`;
3759
+ const match = schema.matchFiles({
3760
+ files: [filePath],
3761
+ collection: schemaCollection
3762
+ });
3763
+ if (match.length === 0) {
3764
+ return `The filename "${value}" is not allowed for this collection.`;
3765
+ }
3766
+ }
3778
3767
  }
3779
3768
  }
3780
3769
  ],
@@ -3864,11 +3853,7 @@ const GetDocument = ({
3864
3853
  };
3865
3854
  const updateDocument = async (cms, relativePath, collection, mutationInfo, values) => {
3866
3855
  const api = new TinaAdminApi(cms);
3867
- const { includeCollection, includeTemplate } = mutationInfo;
3868
- const params = transformDocumentIntoMutationRequestPayload(values, {
3869
- includeCollection,
3870
- includeTemplate
3871
- });
3856
+ const params = api.schema.transformPayload(collection.name, values);
3872
3857
  if (await api.isAuthenticated()) {
3873
3858
  await api.updateDocument(collection.name, relativePath, params);
3874
3859
  } else {
@@ -4081,6 +4066,7 @@ const CheckSchema = ({
4081
4066
  };
4082
4067
  const TinaAdmin = ({
4083
4068
  preview,
4069
+ Playground,
4084
4070
  config,
4085
4071
  schemaJson
4086
4072
  }) => {
@@ -4113,6 +4099,9 @@ const TinaAdmin = ({
4113
4099
  config,
4114
4100
  preview
4115
4101
  })
4102
+ }), /* @__PURE__ */ React.createElement(Route, {
4103
+ path: "graphql",
4104
+ element: /* @__PURE__ */ React.createElement(PlainLayout, null, /* @__PURE__ */ React.createElement(Playground, null))
4116
4105
  }), /* @__PURE__ */ React.createElement(Route, {
4117
4106
  path: "collections/:collectionName/new",
4118
4107
  element: /* @__PURE__ */ React.createElement(DefaultWrapper, {
@@ -4174,6 +4163,21 @@ const DefaultWrapper = ({
4174
4163
  className: "flex-1 relative"
4175
4164
  }, children)));
4176
4165
  };
4166
+ const PlainLayout = ({ children }) => {
4167
+ return /* @__PURE__ */ React.createElement("div", {
4168
+ style: {
4169
+ position: "fixed",
4170
+ top: 0,
4171
+ left: 0,
4172
+ width: "100%",
4173
+ height: "100%",
4174
+ overflow: "auto",
4175
+ background: "#F6F6F9",
4176
+ fontFamily: "'Inter', sans-serif",
4177
+ zIndex: 9999
4178
+ }
4179
+ }, children);
4180
+ };
4177
4181
  class RouteMappingPlugin {
4178
4182
  constructor(mapper) {
4179
4183
  this.__type = "tina-admin";
package/dist/index.js CHANGED
@@ -73,12 +73,18 @@
73
73
  ]).optional(),
74
74
  timestamp: zod.z.number().optional()
75
75
  });
76
- async function asyncPoll(fn, pollInterval = 5 * 1e3, pollTimeout = 30 * 1e3) {
76
+ function asyncPoll(fn, pollInterval = 5 * 1e3, pollTimeout = 30 * 1e3) {
77
77
  const endTime = new Date().getTime() + pollTimeout;
78
+ let stop = false;
79
+ const cancel = () => {
80
+ stop = true;
81
+ };
78
82
  const checkCondition = (resolve, reject) => {
79
83
  Promise.resolve(fn()).then((result) => {
80
84
  const now = new Date().getTime();
81
- if (result.done) {
85
+ if (stop) {
86
+ reject(new Error("AsyncPoller: cancelled"));
87
+ } else if (result.done) {
82
88
  resolve(result.data);
83
89
  } else if (now < endTime) {
84
90
  setTimeout(checkCondition, pollInterval, resolve, reject);
@@ -89,7 +95,7 @@
89
95
  reject(err);
90
96
  });
91
97
  };
92
- return new Promise(checkCondition);
98
+ return [new Promise(checkCondition), cancel];
93
99
  }
94
100
  class Client {
95
101
  constructor({ tokenStorage = "MEMORY", ...options }) {
@@ -141,6 +147,7 @@ mutation addPendingDocumentMutation(
141
147
  });
142
148
  return graphql.parse(data.getOptimizedQuery);
143
149
  };
150
+ this.tinaGraphQLVersion = options.tinaGraphQLVersion;
144
151
  this.onLogin = (_d = (_c = (_b = (_a = options.schema) == null ? void 0 : _a.config) == null ? void 0 : _b.admin) == null ? void 0 : _c.auth) == null ? void 0 : _d.onLogin;
145
152
  this.onLogout = (_h = (_g = (_f = (_e = options.schema) == null ? void 0 : _e.config) == null ? void 0 : _f.admin) == null ? void 0 : _g.auth) == null ? void 0 : _h.onLogout;
146
153
  if ((_l = (_k = (_j = (_i = options.schema) == null ? void 0 : _i.config) == null ? void 0 : _j.admin) == null ? void 0 : _k.auth) == null ? void 0 : _l.logout) {
@@ -225,7 +232,7 @@ mutation addPendingDocumentMutation(
225
232
  this.frontendUrl = ((_b = this.options.tinaioConfig) == null ? void 0 : _b.frontendUrlOverride) || "https://app.tina.io";
226
233
  this.identityApiUrl = ((_c = this.options.tinaioConfig) == null ? void 0 : _c.identityApiUrlOverride) || "https://identity.tinajs.io";
227
234
  this.contentApiBase = ((_d = this.options.tinaioConfig) == null ? void 0 : _d.contentApiUrlOverride) || `https://content.tinajs.io`;
228
- this.contentApiUrl = this.options.customContentApiUrl || `${this.contentApiBase}/content/${this.options.clientId}/github/${encodedBranch}`;
235
+ this.contentApiUrl = this.options.customContentApiUrl || `${this.contentApiBase}/${this.tinaGraphQLVersion}/content/${this.options.clientId}/github/${encodedBranch}`;
229
236
  }
230
237
  async request(query, { variables }) {
231
238
  const res = await fetch(this.contentApiUrl, {
@@ -245,6 +252,13 @@ mutation addPendingDocumentMutation(
245
252
  if (resBody.message) {
246
253
  errorMessage = `${errorMessage}, Response: ${resBody.message}`;
247
254
  }
255
+ errorMessage = `${errorMessage}, Please check that the following information is correct:
256
+ clientId: ${this.options.clientId}
257
+ branch: ${this.branch}.`;
258
+ if (this.branch !== "main") {
259
+ errorMessage = `${errorMessage}
260
+ Note: This error can occur if the branch does not exist on GitHub or on Tina Cloud`;
261
+ }
248
262
  throw new Error(errorMessage);
249
263
  }
250
264
  const json = await res.json();
@@ -390,15 +404,15 @@ mutation addPendingDocumentMutation(
390
404
  return null;
391
405
  }
392
406
  }
393
- async waitForIndexStatus({ ref }) {
407
+ waitForIndexStatus({ ref }) {
394
408
  try {
395
- const result = await asyncPoll(async () => {
409
+ const [prom, cancel] = asyncPoll(async () => {
396
410
  try {
397
- const result2 = await this.getIndexStatus({ ref });
398
- if (!(result2.status === "inprogress" || result2.status === "unknown")) {
411
+ const result = await this.getIndexStatus({ ref });
412
+ if (!(result.status === "inprogress" || result.status === "unknown")) {
399
413
  return Promise.resolve({
400
414
  done: true,
401
- data: result2
415
+ data: result
402
416
  });
403
417
  } else {
404
418
  return Promise.resolve({
@@ -409,7 +423,7 @@ mutation addPendingDocumentMutation(
409
423
  return Promise.reject(err);
410
424
  }
411
425
  }, 5e3, 9e5);
412
- return result;
426
+ return [prom, cancel];
413
427
  } catch (error) {
414
428
  if (error.message === "AsyncPoller: reached timeout") {
415
429
  console.warn(error);
@@ -477,6 +491,7 @@ mutation addPendingDocumentMutation(
477
491
  ...props,
478
492
  clientId: "",
479
493
  branch: "",
494
+ tinaGraphQLVersion: "",
480
495
  customContentApiUrl: props && props.customContentApiUrl ? props.customContentApiUrl : DEFAULT_LOCAL_TINA_GQL_SERVER_URL
481
496
  };
482
497
  super(clientProps);
@@ -548,14 +563,16 @@ mutation addPendingDocumentMutation(
548
563
  branch,
549
564
  tinaioConfig,
550
565
  schema,
551
- apiUrl
566
+ apiUrl,
567
+ tinaGraphQLVersion
552
568
  }) => {
553
569
  return isLocalClient ? new LocalClient({ customContentApiUrl: apiUrl, schema }) : new Client({
554
570
  clientId: clientId || "",
555
571
  branch: branch || "main",
556
572
  tokenStorage: "LOCAL_STORAGE",
557
573
  tinaioConfig,
558
- schema
574
+ schema,
575
+ tinaGraphQLVersion
559
576
  });
560
577
  };
561
578
  function assertShape(value, yupSchema, errorMessage) {
@@ -2317,7 +2334,8 @@ mutation addPendingDocumentMutation(
2317
2334
  cmsCallback: props.cmsCallback,
2318
2335
  mediaStore: props.mediaStore,
2319
2336
  apiUrl: apiURL,
2320
- schema: { ...schema, config: { ...schema.config, ...props } }
2337
+ schema: { ...schema, config: { ...schema.config, ...props } },
2338
+ tinaGraphQLVersion: props.tinaGraphQLVersion
2321
2339
  }, /* @__PURE__ */ React__default["default"].createElement("style", null, styles), /* @__PURE__ */ React__default["default"].createElement(ErrorBoundary, null, props.children)));
2322
2340
  };
2323
2341
  const Loader = (props) => {
@@ -3622,42 +3640,6 @@ This will work when developing locally but NOT when deployed to production.
3622
3640
  function HiChevronRight(props) {
3623
3641
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 20 20", "fill": "currentColor" }, "child": [{ "tag": "path", "attr": { "fillRule": "evenodd", "d": "M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z", "clipRule": "evenodd" } }] })(props);
3624
3642
  }
3625
- const transformDocumentIntoMutationRequestPayload = (document, instructions) => {
3626
- const { _collection, __typename, _template, ...rest } = document;
3627
- const params = transformParams(rest);
3628
- const paramsWithTemplate = instructions.includeTemplate ? { [_template]: params } : params;
3629
- return instructions.includeCollection ? { [_collection]: paramsWithTemplate } : paramsWithTemplate;
3630
- };
3631
- const transformParams = (data) => {
3632
- if (["string", "number", "boolean"].includes(typeof data)) {
3633
- return data;
3634
- }
3635
- if (Array.isArray(data)) {
3636
- return data.map((item) => transformParams(item));
3637
- }
3638
- try {
3639
- assertShape(data, (yup2) => yup2.object({ _template: yup2.string().required() }));
3640
- const { _template, __typename, ...rest } = data;
3641
- const nested = transformParams(rest);
3642
- return { [_template]: nested };
3643
- } catch (e) {
3644
- if (e.message === "Failed to assertShape - _template is a required field") {
3645
- if (!data) {
3646
- return [];
3647
- }
3648
- const accum = {};
3649
- Object.entries(data).map(([keyName, value]) => {
3650
- accum[keyName] = transformParams(value);
3651
- });
3652
- return accum;
3653
- } else {
3654
- if (!data) {
3655
- return [];
3656
- }
3657
- throw e;
3658
- }
3659
- }
3660
- };
3661
3643
  function FaLock(props) {
3662
3644
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 448 512" }, "child": [{ "tag": "path", "attr": { "d": "M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zm-104 0H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z" } }] })(props);
3663
3645
  }
@@ -3667,15 +3649,11 @@ This will work when developing locally but NOT when deployed to production.
3667
3649
  const createDocument = async (cms, collection, template, mutationInfo, values) => {
3668
3650
  const api = new TinaAdminApi(cms);
3669
3651
  const { filename, ...leftover } = values;
3670
- const { includeCollection, includeTemplate } = mutationInfo;
3671
3652
  const relativePath = `${filename}.${collection.format}`;
3672
- const params = transformDocumentIntoMutationRequestPayload({
3653
+ const params = api.schema.transformPayload(collection.name, {
3673
3654
  _collection: collection.name,
3674
3655
  ...template && { _template: template.name },
3675
3656
  ...leftover
3676
- }, {
3677
- includeCollection,
3678
- includeTemplate
3679
3657
  });
3680
3658
  if (await api.isAuthenticated()) {
3681
3659
  await api.createDocument(collection.name, relativePath, params);
@@ -3780,6 +3758,7 @@ This will work when developing locally but NOT when deployed to production.
3780
3758
  description: /* @__PURE__ */ React__default["default"].createElement("span", null, "A unique filename for the content.", /* @__PURE__ */ React__default["default"].createElement("br", null), "Examples: ", /* @__PURE__ */ React__default["default"].createElement("code", null, "My_Document"), ", ", /* @__PURE__ */ React__default["default"].createElement("code", null, "My_Document.en"), ",", " ", /* @__PURE__ */ React__default["default"].createElement("code", null, "sub-folder/My_Document")),
3781
3759
  placeholder: `My_Document`,
3782
3760
  validate: (value, allValues, meta) => {
3761
+ var _a3, _b3;
3783
3762
  if (!value) {
3784
3763
  if (meta.dirty) {
3785
3764
  return "Required";
@@ -3790,6 +3769,16 @@ This will work when developing locally but NOT when deployed to production.
3790
3769
  if (value && !isValid) {
3791
3770
  return "Must begin with a-z, A-Z, 0-9, or _ and contain only a-z, A-Z, 0-9, -, _, ., or /.";
3792
3771
  }
3772
+ if (((_a3 = schemaCollection.match) == null ? void 0 : _a3.exclude) || ((_b3 = schemaCollection.match) == null ? void 0 : _b3.include)) {
3773
+ const filePath = `${schemaTools.normalizePath(schemaCollection.path)}/${value}.${schemaCollection.format || "md"}`;
3774
+ const match = schema.matchFiles({
3775
+ files: [filePath],
3776
+ collection: schemaCollection
3777
+ });
3778
+ if (match.length === 0) {
3779
+ return `The filename "${value}" is not allowed for this collection.`;
3780
+ }
3781
+ }
3793
3782
  }
3794
3783
  }
3795
3784
  ],
@@ -3879,11 +3868,7 @@ This will work when developing locally but NOT when deployed to production.
3879
3868
  };
3880
3869
  const updateDocument = async (cms, relativePath, collection, mutationInfo, values) => {
3881
3870
  const api = new TinaAdminApi(cms);
3882
- const { includeCollection, includeTemplate } = mutationInfo;
3883
- const params = transformDocumentIntoMutationRequestPayload(values, {
3884
- includeCollection,
3885
- includeTemplate
3886
- });
3871
+ const params = api.schema.transformPayload(collection.name, values);
3887
3872
  if (await api.isAuthenticated()) {
3888
3873
  await api.updateDocument(collection.name, relativePath, params);
3889
3874
  } else {
@@ -4096,6 +4081,7 @@ This will work when developing locally but NOT when deployed to production.
4096
4081
  };
4097
4082
  const TinaAdmin = ({
4098
4083
  preview,
4084
+ Playground,
4099
4085
  config,
4100
4086
  schemaJson
4101
4087
  }) => {
@@ -4128,6 +4114,9 @@ This will work when developing locally but NOT when deployed to production.
4128
4114
  config,
4129
4115
  preview
4130
4116
  })
4117
+ }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
4118
+ path: "graphql",
4119
+ element: /* @__PURE__ */ React__default["default"].createElement(PlainLayout, null, /* @__PURE__ */ React__default["default"].createElement(Playground, null))
4131
4120
  }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
4132
4121
  path: "collections/:collectionName/new",
4133
4122
  element: /* @__PURE__ */ React__default["default"].createElement(DefaultWrapper, {
@@ -4189,6 +4178,21 @@ This will work when developing locally but NOT when deployed to production.
4189
4178
  className: "flex-1 relative"
4190
4179
  }, children)));
4191
4180
  };
4181
+ const PlainLayout = ({ children }) => {
4182
+ return /* @__PURE__ */ React__default["default"].createElement("div", {
4183
+ style: {
4184
+ position: "fixed",
4185
+ top: 0,
4186
+ left: 0,
4187
+ width: "100%",
4188
+ height: "100%",
4189
+ overflow: "auto",
4190
+ background: "#F6F6F9",
4191
+ fontFamily: "'Inter', sans-serif",
4192
+ zIndex: 9999
4193
+ }
4194
+ }, children);
4195
+ };
4192
4196
  class RouteMappingPlugin {
4193
4197
  constructor(mapper) {
4194
4198
  this.__type = "tina-admin";
@@ -16,6 +16,7 @@ interface ServerOptions {
16
16
  schema?: Schema;
17
17
  clientId: string;
18
18
  branch: string;
19
+ tinaGraphQLVersion: string;
19
20
  customContentApiUrl?: string;
20
21
  getTokenFn?: () => Promise<TokenObject>;
21
22
  tinaioConfig?: TinaIOConfig;
@@ -104,7 +105,7 @@ pollInterval?: number,
104
105
  *
105
106
  * Default 30 seconds.
106
107
  */
107
- pollTimeout?: number): Promise<T>;
108
+ pollTimeout?: number): ((() => void) | Promise<T>)[];
108
109
  export declare class Client {
109
110
  onLogin?: OnLoginFunc;
110
111
  onLogout?: () => Promise<void>;
@@ -117,6 +118,7 @@ export declare class Client {
117
118
  clientId: string;
118
119
  contentApiBase: string;
119
120
  query: string;
121
+ tinaGraphQLVersion: string;
120
122
  setToken: (_token: TokenObject) => void;
121
123
  private getToken;
122
124
  private token;
@@ -200,7 +202,9 @@ export declare class Client {
200
202
  }>;
201
203
  waitForIndexStatus({ ref }: {
202
204
  ref: string;
203
- }): Promise<any>;
205
+ }): (Promise<any> | (() => void))[] | {
206
+ status: string;
207
+ };
204
208
  getIndexStatus({ ref }: {
205
209
  ref: string;
206
210
  }): Promise<{
@@ -226,7 +230,7 @@ export declare class LocalClient extends Client {
226
230
  constructor(props?: {
227
231
  customContentApiUrl?: string;
228
232
  schema?: Schema;
229
- } & Omit<ServerOptions, 'clientId' | 'branch'>);
233
+ } & Omit<ServerOptions, 'clientId' | 'branch' | 'tinaGraphQLVersion'>);
230
234
  get isLocalMode(): boolean;
231
235
  logout(): Promise<void>;
232
236
  authenticate(): Promise<{
@@ -51,5 +51,7 @@ declare type QueryProviderProps = {
51
51
  /** The `data` from getStaticProps */
52
52
  data?: never;
53
53
  };
54
- export declare type TinaCMSProviderDefaultProps = QueryProviderProps & APIProviderProps & BaseProviderProps & Config;
54
+ export declare type TinaCMSProviderDefaultProps = QueryProviderProps & APIProviderProps & BaseProviderProps & Config & {
55
+ tinaGraphQLVersion: string;
56
+ };
55
57
  export {};
@@ -14,7 +14,8 @@ export interface CreateClientProps {
14
14
  branch?: string;
15
15
  schema?: Schema;
16
16
  apiUrl?: string;
17
+ tinaGraphQLVersion: string;
17
18
  }
18
- export declare const createClient: ({ clientId, isLocalClient, branch, tinaioConfig, schema, apiUrl, }: CreateClientProps) => Client;
19
+ export declare const createClient: ({ clientId, isLocalClient, branch, tinaioConfig, schema, apiUrl, tinaGraphQLVersion, }: CreateClientProps) => Client;
19
20
  export declare function assertShape<T extends unknown>(value: unknown, yupSchema: (args: typeof yup) => yup.AnySchema, errorMessage?: string): asserts value is T;
20
21
  export declare function safeAssertShape<T extends unknown>(value: unknown, yupSchema: (args: typeof yup) => yup.AnySchema): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tinacms",
3
- "version": "1.3.3",
3
+ "version": "1.4.1",
4
4
  "main": "dist/index.js",
5
5
  "module": "./dist/index.es.js",
6
6
  "exports": {
@@ -56,9 +56,9 @@
56
56
  "@headlessui/react": "^1.5.0",
57
57
  "@heroicons/react": "^1.0.4",
58
58
  "@react-hook/window-size": "^3.0.7",
59
- "@tinacms/schema-tools": "1.3.4",
59
+ "@tinacms/schema-tools": "1.4.1",
60
60
  "@tinacms/sharedctx": "1.0.1",
61
- "@tinacms/toolkit": "1.5.2",
61
+ "@tinacms/toolkit": "1.6.1",
62
62
  "crypto-js": "^4.0.0",
63
63
  "encoding": "0.1.13",
64
64
  "fetch-ponyfill": "^7.1.0",
@@ -78,7 +78,7 @@
78
78
  "@testing-library/react": "^12.0.0",
79
79
  "@testing-library/react-hooks": "^7.0.2",
80
80
  "@testing-library/user-event": "^12.7.0",
81
- "@tinacms/scripts": "1.0.4",
81
+ "@tinacms/scripts": "1.1.0",
82
82
  "@types/jest": "^27.0.1",
83
83
  "@types/lodash": "^4.14.169",
84
84
  "@types/node": "^14.0.13",