tinacms 1.2.2 → 1.3.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/dist/index.es.js CHANGED
@@ -1,2115 +1,43 @@
1
1
  import { z } from "zod";
2
- import { useCMS, Form, GlobalFormPlugin, EventBus, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, TinaMediaStore, DummyMediaStore, Nav, BranchBanner, LocalWarning, BillingWarning, Select, Input, ReactDateTimeWithStyles, textFieldClasses, Toggle, OverflowMenu, CursorPaginator, PopupModal, BaseTextField, wrapFieldsWithMeta, FormStatus, FormBuilder } from "@tinacms/toolkit";
2
+ import { EventBus, Modal, ModalPopup, ModalHeader, ModalBody, ModalActions, Button, LoadingDots, useLocalStorage, TinaCMS, BranchSwitcherPlugin, BranchDataProvider, TinaProvider, TinaMediaStore, DummyMediaStore, useCMS, Nav, BranchBanner, LocalWarning, BillingWarning, Select, Input, ReactDateTimeWithStyles, textFieldClasses, Toggle, OverflowMenu, CursorPaginator, PopupModal, BaseTextField, Form, wrapFieldsWithMeta, FormStatus, FormBuilder } from "@tinacms/toolkit";
3
3
  export * from "@tinacms/toolkit";
4
4
  export { MdxFieldPluginExtendible } from "@tinacms/toolkit";
5
- import * as G from "graphql";
6
- import { TypeInfo, visit, visitWithTypeInfo, getNamedType, GraphQLObjectType, isLeafType, GraphQLUnionType, isScalarType as isScalarType$1, getIntrospectionQuery, buildClientSchema, print, parse, buildSchema } from "graphql";
7
- import set from "lodash.set";
8
- import React, { useState, useCallback, useEffect, Fragment, useMemo } from "react";
9
- import { getIn, setIn } from "final-form";
10
- import { resolveForm, TinaSchema, addNamespaceToSchema, parseURL, validateSchema } from "@tinacms/schema-tools";
11
- export { NAMER, resolveForm } from "@tinacms/schema-tools";
12
- import * as yup from "yup";
13
- import gql$1 from "graphql-tag";
14
- import { setEditing, TinaDataContext, EditContext, useEditState } from "@tinacms/sharedctx";
15
- import { diff } from "@graphql-inspector/core";
16
- import { NavLink, useSearchParams, useNavigate, useParams, useLocation, Link, HashRouter, Routes, Route } from "react-router-dom";
17
- import { Transition, Menu } from "@headlessui/react";
18
- import { useWindowWidth } from "@react-hook/window-size";
19
- function popupWindow(url, title, window2, w, h) {
20
- const y = window2.top.outerHeight / 2 + window2.top.screenY - h / 2;
21
- const x = window2.top.outerWidth / 2 + window2.top.screenX - w / 2;
22
- return window2.open(url, title, "toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=no, width=" + w + ", height=" + h + ", top=" + y + ", left=" + x);
23
- }
24
- const TINA_LOGIN_EVENT = "tinaCloudLogin";
25
- const AUTH_TOKEN_KEY = "tinacms-auth";
26
- const authenticate = (clientId, frontendUrl) => {
27
- return new Promise((resolve) => {
28
- let authTab;
29
- window.addEventListener("message", function(e) {
30
- if (e.data.source === TINA_LOGIN_EVENT) {
31
- if (authTab) {
32
- authTab.close();
33
- }
34
- resolve({
35
- id_token: e.data.id_token,
36
- access_token: e.data.access_token,
37
- refresh_token: e.data.refresh_token
38
- });
39
- }
40
- });
41
- const origin = `${window.location.protocol}//${window.location.host}`;
42
- authTab = popupWindow(`${frontendUrl}/signin?clientId=${clientId}&origin=${origin}`, "_blank", window, 1e3, 700);
43
- });
44
- };
45
- const formify$1 = (query, schema) => {
46
- const typeInfo = new TypeInfo(schema);
47
- const pathsToPopulate = [];
48
- const visitor = {
49
- leave(node2, key, parent, path, ancestors) {
50
- const type = typeInfo.getType();
51
- if (type) {
52
- const namedType = getNamedType(type);
53
- if (namedType instanceof GraphQLObjectType) {
54
- const hasNodeInterface = !!namedType.getInterfaces().find((i) => i.name === "Node");
55
- if (hasNodeInterface) {
56
- if (typeof path[path.length - 1] === "number") {
57
- assertIsObjectType(namedType);
58
- const valuesNode = namedType.getFields().values;
59
- const namedValuesNode = getNamedType(valuesNode.type);
60
- const pathForValues = [...path];
61
- pathForValues.push("selectionSet");
62
- pathForValues.push("selections");
63
- const valuesAst = buildValuesForType(namedValuesNode);
64
- pathForValues.push(100);
65
- const formNode = namedType.getFields().form;
66
- const namedFormNode = getNamedType(formNode.type);
67
- const pathForForm = [...path];
68
- pathForForm.push("selectionSet");
69
- pathForForm.push("selections");
70
- const formAst = buildFormForType(namedFormNode);
71
- pathForForm.push(101);
72
- const sysNode = namedType.getFields().sys;
73
- const namedSysNode = getNamedType(sysNode.type);
74
- const pathForSys = [...path];
75
- pathForSys.push("selectionSet");
76
- pathForSys.push("selections");
77
- const sysAst = buildSysForType(namedSysNode);
78
- pathForSys.push(102);
79
- pathsToPopulate.push({
80
- path: path.map((p) => p.toString()).join("-"),
81
- paths: [
82
- {
83
- path: pathForValues.map((p) => p.toString()),
84
- ast: valuesAst
85
- },
86
- {
87
- path: pathForForm.map((p) => p.toString()),
88
- ast: formAst
89
- },
90
- {
91
- path: pathForSys.map((p) => p.toString()),
92
- ast: sysAst
93
- }
94
- ]
95
- });
96
- }
97
- }
98
- }
99
- }
100
- }
101
- };
102
- visit(query, visitWithTypeInfo(typeInfo, visitor));
103
- const topLevelPaths = pathsToPopulate.filter((p, i) => {
104
- const otherPaths = pathsToPopulate.filter((_, index) => index !== i);
105
- const isChildOfOtherPaths = otherPaths.some((op) => {
106
- if (p.path.startsWith(op.path)) {
107
- return true;
108
- } else {
109
- return false;
110
- }
111
- });
112
- if (isChildOfOtherPaths) {
113
- return false;
114
- } else {
115
- return true;
116
- }
117
- });
118
- topLevelPaths.map((p) => {
119
- p.paths.map((pathNode) => {
120
- set(query, pathNode.path, pathNode.ast);
121
- });
122
- });
123
- return query;
124
- };
125
- const buildSysForType = (type) => {
126
- assertIsObjectType(type);
127
- return {
128
- kind: "Field",
129
- alias: {
130
- kind: "Name",
131
- value: "_internalSys"
132
- },
133
- name: {
134
- kind: "Name",
135
- value: "sys"
136
- },
137
- selectionSet: {
138
- kind: "SelectionSet",
139
- selections: buildSelectionsFields(Object.values(type.getFields()), (fields) => {
140
- return {
141
- continue: true,
142
- filteredFields: fields.filter((field) => field.name !== "documents")
143
- };
144
- })
145
- }
146
- };
147
- };
148
- const buildValuesForType = (type) => {
149
- try {
150
- assertIsUnionType(type);
151
- return {
152
- kind: "Field",
153
- name: {
154
- kind: "Name",
155
- value: "values"
156
- },
157
- selectionSet: {
158
- kind: "SelectionSet",
159
- selections: buildSelectionInlineFragments(type.getTypes())
160
- }
161
- };
162
- } catch (e) {
163
- return {
164
- kind: "Field",
165
- name: {
166
- kind: "Name",
167
- value: "values"
168
- }
169
- };
170
- }
171
- };
172
- const buildFormForType = (type) => {
173
- try {
174
- assertIsUnionType(type);
175
- return {
176
- kind: "Field",
177
- name: {
178
- kind: "Name",
179
- value: "form"
180
- },
181
- selectionSet: {
182
- kind: "SelectionSet",
183
- selections: buildSelectionInlineFragments(type.getTypes())
184
- }
185
- };
186
- } catch (e) {
187
- return {
188
- kind: "Field",
189
- name: {
190
- kind: "Name",
191
- value: "form"
192
- }
193
- };
194
- }
195
- };
196
- const buildSelectionInlineFragments = (types, callback) => {
197
- return types.map((type) => {
198
- return {
199
- kind: "InlineFragment",
200
- typeCondition: {
201
- kind: "NamedType",
202
- name: {
203
- kind: "Name",
204
- value: type.name
205
- }
206
- },
207
- selectionSet: {
208
- kind: "SelectionSet",
209
- selections: [
210
- ...Object.values(type.getFields()).map((field) => {
211
- const namedType = getNamedType(field.type);
212
- if (isLeafType(namedType)) {
213
- return {
214
- kind: "Field",
215
- name: {
216
- kind: "Name",
217
- value: field.name
218
- }
219
- };
220
- } else if (namedType instanceof GraphQLUnionType) {
221
- return {
222
- kind: "Field",
223
- name: {
224
- kind: "Name",
225
- value: field.name
226
- },
227
- selectionSet: {
228
- kind: "SelectionSet",
229
- selections: [
230
- ...buildSelectionInlineFragments(namedType.getTypes(), callback)
231
- ]
232
- }
233
- };
234
- } else if (namedType instanceof GraphQLObjectType) {
235
- return {
236
- kind: "Field",
237
- name: {
238
- kind: "Name",
239
- value: field.name
240
- },
241
- selectionSet: {
242
- kind: "SelectionSet",
243
- selections: [
244
- ...buildSelectionsFields(Object.values(namedType.getFields()), callback)
245
- ]
246
- }
247
- };
248
- } else {
249
- throw new Error(`Unexpected GraphQL type for field ${namedType.name}`);
250
- }
251
- })
252
- ]
253
- }
254
- };
255
- });
256
- };
257
- const buildSelectionsFields = (fields, callback) => {
258
- let filteredFields = fields;
259
- if (callback) {
260
- const result = callback(fields);
261
- if (!result.continue) {
262
- if (fields.every((field) => {
263
- return !isScalarType$1(getNamedType(field.type));
264
- })) {
265
- return [
266
- {
267
- kind: "Field",
268
- name: {
269
- kind: "Name",
270
- value: "__typename"
271
- }
272
- }
273
- ];
274
- }
275
- return buildSelectionsFields(result.filteredFields.filter((field) => {
276
- if (isScalarType$1(getNamedType(field.type))) {
277
- return true;
278
- }
279
- return false;
280
- }));
281
- } else {
282
- filteredFields = result.filteredFields;
283
- }
284
- }
285
- return filteredFields.map((field) => {
286
- const namedType = getNamedType(field.type);
287
- if (isLeafType(namedType)) {
288
- return {
289
- kind: "Field",
290
- name: {
291
- kind: "Name",
292
- value: field.name
293
- }
294
- };
295
- } else if (namedType instanceof GraphQLUnionType) {
296
- return {
297
- kind: "Field",
298
- name: {
299
- kind: "Name",
300
- value: field.name
301
- },
302
- selectionSet: {
303
- kind: "SelectionSet",
304
- selections: [
305
- ...buildSelectionInlineFragments(namedType.getTypes(), callback)
306
- ]
307
- }
308
- };
309
- } else if (namedType instanceof GraphQLObjectType) {
310
- return {
311
- kind: "Field",
312
- name: {
313
- kind: "Name",
314
- value: field.name
315
- },
316
- selectionSet: {
317
- kind: "SelectionSet",
318
- selections: [
319
- ...buildSelectionsFields(Object.values(namedType.getFields()), callback)
320
- ]
321
- }
322
- };
323
- } else {
324
- return {
325
- kind: "Field",
326
- name: {
327
- kind: "Name",
328
- value: field.name
329
- },
330
- selectionSet: {
331
- kind: "SelectionSet",
332
- selections: []
333
- }
334
- };
335
- }
336
- });
337
- };
338
- function assertIsObjectType(type) {
339
- if (type instanceof GraphQLObjectType)
340
- ;
341
- else {
342
- throw new Error(`Expected an instance of GraphQLObjectType for type ${type.name}`);
343
- }
344
- }
345
- function assertIsUnionType(type) {
346
- if (type instanceof GraphQLUnionType)
347
- ;
348
- else {
349
- throw new Error(`Expected an instance of GraphQLUnionType for type ${type.name}`);
350
- }
351
- }
352
- const createClient = ({
353
- clientId,
354
- isLocalClient = true,
355
- branch,
356
- tinaioConfig,
357
- schema,
358
- apiUrl
359
- }) => {
360
- return isLocalClient ? new LocalClient({ customContentApiUrl: apiUrl, schema }) : new Client({
361
- clientId: clientId || "",
362
- branch: branch || "main",
363
- tokenStorage: "LOCAL_STORAGE",
364
- tinaioConfig,
365
- schema
366
- });
367
- };
368
- function assertShape(value, yupSchema, errorMessage) {
369
- const shape = yupSchema(yup);
370
- try {
371
- shape.validateSync(value);
372
- } catch (e) {
373
- const message = errorMessage || `Failed to assertShape - ${e.message}`;
374
- throw new Error(message);
375
- }
376
- }
377
- function safeAssertShape(value, yupSchema) {
378
- try {
379
- assertShape(value, yupSchema);
380
- return true;
381
- } catch (e) {
382
- return false;
383
- }
384
- }
385
- function useGraphqlForms({
386
- variables,
387
- onSubmit,
388
- query,
389
- formify: formify2,
390
- eventList
391
- }) {
392
- const cms = useCMS();
393
- const state = useFormify({
394
- query,
395
- cms,
396
- variables,
397
- formify: formify2,
398
- eventList,
399
- onSubmit
400
- });
401
- if (!query) {
402
- return [state.data, false];
403
- }
404
- return [state.data, state.status !== "done"];
405
- }
406
- const transformDocumentIntoMutationRequestPayload = (document, instructions) => {
407
- const { _collection, __typename, _template, ...rest } = document;
408
- const params = transformParams(rest);
409
- const paramsWithTemplate = instructions.includeTemplate ? { [_template]: params } : params;
410
- return instructions.includeCollection ? { [_collection]: paramsWithTemplate } : paramsWithTemplate;
411
- };
412
- const transformParams = (data) => {
413
- if (["string", "number", "boolean"].includes(typeof data)) {
414
- return data;
415
- }
416
- if (Array.isArray(data)) {
417
- return data.map((item) => transformParams(item));
418
- }
419
- try {
420
- assertShape(data, (yup2) => yup2.object({ _template: yup2.string().required() }));
421
- const { _template, __typename, ...rest } = data;
422
- const nested = transformParams(rest);
423
- return { [_template]: nested };
424
- } catch (e) {
425
- if (e.message === "Failed to assertShape - _template is a required field") {
426
- if (!data) {
427
- return [];
428
- }
429
- const accum = {};
430
- Object.entries(data).map(([keyName, value]) => {
431
- accum[keyName] = transformParams(value);
432
- });
433
- return accum;
434
- } else {
435
- if (!data) {
436
- return [];
437
- }
438
- throw e;
439
- }
440
- }
441
- };
442
- const generateFormCreators = (cms, showInSidebar, global) => {
443
- const createForm = (formConfig) => {
444
- const form = new Form(formConfig);
445
- if (showInSidebar) {
446
- if (global) {
447
- const options = typeof global === "boolean" ? [null, "fullscreen"] : [global.icon, global.layout];
448
- cms.plugins.add(new GlobalFormPlugin(form, ...options));
449
- } else {
450
- cms.forms.add(form);
451
- }
452
- }
453
- return form;
454
- };
455
- const createGlobalForm = (formConfig, options) => {
456
- const form = new Form(formConfig);
457
- if (showInSidebar) {
458
- cms.plugins.add(new GlobalFormPlugin(form, options == null ? void 0 : options.icon, options == null ? void 0 : options.layout));
459
- }
460
- return form;
461
- };
462
- return { createForm, createGlobalForm };
463
- };
464
- const getValueForBlueprint = (state, path) => {
465
- const pathArray = path.split(".");
466
- let latest = state;
467
- pathArray.every((item, index) => {
468
- if (item === "[]") {
469
- const restOfItems = pathArray.slice(index + 1);
470
- if (latest) {
471
- const next = [];
472
- if (Array.isArray(latest)) {
473
- latest.forEach((latest2, index2) => {
474
- const res = getValueForBlueprint(latest2, restOfItems.join("."));
475
- next.push(res);
476
- });
477
- } else {
478
- throw new Error(`Expected value to be an array for "[]" item`);
479
- }
480
- if (next.length > 0) {
481
- latest = next;
482
- } else {
483
- latest = void 0;
484
- }
485
- }
486
- return false;
487
- } else {
488
- if (latest) {
489
- latest = latest[item];
490
- } else {
491
- latest = void 0;
492
- }
493
- }
494
- return true;
495
- });
496
- return latest;
497
- };
498
- const getFieldNameOrAlias = (fieldBlueprint) => {
499
- return fieldBlueprint.path[fieldBlueprint.path.length - 1].alias;
500
- };
501
- const spliceLocation = (string, location) => {
502
- const accum = [];
503
- let counter = 0;
504
- string.split(".").forEach((item) => {
505
- if (item === "[]") {
506
- accum.push(location[counter]);
507
- counter++;
508
- } else {
509
- accum.push(item);
510
- }
511
- });
512
- return accum.join(".");
513
- };
514
- const getPathToChange = (documentBlueprint, formNode, event) => {
515
- const fieldName = event.field.name;
516
- const location = [...formNode.location, ...stripIndices(fieldName)];
517
- const accum = [];
518
- let counter = 0;
519
- documentBlueprint.path.forEach((item) => {
520
- accum.push(item.alias);
521
- if (item.list) {
522
- if (location[counter] !== void 0) {
523
- accum.push(location[counter]);
524
- counter++;
525
- }
526
- }
527
- });
528
- return accum.join(".");
529
- };
530
- const buildForm = (doc, cms, formify2, showInSidebar = false, onSubmit) => {
531
- var _a;
532
- const id = doc._internalSys.path;
533
- const enrichedSchema = cms.api.tina.schema;
534
- const collection = enrichedSchema.getCollection(doc._internalSys.collection.name);
535
- const { createForm, createGlobalForm } = generateFormCreators(cms, showInSidebar, (_a = collection.ui) == null ? void 0 : _a.global);
536
- const SKIPPED = "SKIPPED";
537
- let form;
538
- let skipped;
539
- const skip = () => {
540
- skipped = SKIPPED;
541
- };
542
- if (skipped)
543
- return;
544
- const template = enrichedSchema.getTemplateForData({
545
- collection,
546
- data: doc._values
547
- });
548
- const formCommon = {
549
- id,
550
- label: id,
551
- initialValues: doc._values,
552
- onSubmit: async (payload) => {
553
- try {
554
- const params = transformDocumentIntoMutationRequestPayload(payload, {
555
- includeCollection: false,
556
- includeTemplate: !!collection.templates
557
- });
558
- const variables = { params };
559
- const mutationString = `#graphql
560
- mutation UpdateDocument($collection: String!, $relativePath: String!, $params: DocumentUpdateMutation!) {
561
- updateDocument(collection: $collection, relativePath: $relativePath, params: $params) {
562
- __typename
563
- }
564
- }
565
- `;
566
- if (onSubmit) {
567
- onSubmit({
568
- queryString: mutationString,
569
- mutationString,
570
- variables: {
571
- collection: doc._internalSys.collection.name,
572
- relativePath: doc._internalSys.relativePath,
573
- params: { [doc._internalSys.collection.name]: variables }
574
- }
575
- });
576
- } else {
577
- try {
578
- await cms.api.tina.request(mutationString, {
579
- variables: {
580
- collection: doc._internalSys.collection.name,
581
- relativePath: doc._internalSys.relativePath,
582
- params: {
583
- [doc._internalSys.collection.name]: variables.params
584
- }
585
- }
586
- });
587
- cms.alerts.success("Document saved!");
588
- } catch (e) {
589
- cms.alerts.error("There was a problem saving your document.");
590
- console.error(e);
591
- }
592
- }
593
- } catch (e) {
594
- console.error(e);
595
- cms.alerts.error("There was a problem saving your document.");
596
- }
597
- }
598
- };
599
- let formConfig = {};
600
- const formInfo = resolveForm({
601
- collection,
602
- basename: collection.name,
603
- schema: enrichedSchema,
604
- template
605
- });
606
- formConfig = {
607
- label: formInfo.label,
608
- fields: formInfo.fields,
609
- ...formCommon
610
- };
611
- if (formify2) {
612
- form = formify2({
613
- formConfig,
614
- createForm,
615
- createGlobalForm,
616
- skip
617
- }, cms);
618
- } else {
619
- form = createForm(formConfig);
620
- }
621
- if (!(form instanceof Form)) {
622
- if (skipped === SKIPPED) {
623
- return;
624
- }
625
- throw new Error("formify must return a form or skip()");
626
- }
627
- return form;
628
- };
629
- const formNodeId = (formNode) => {
630
- return spliceLocation(formNode.documentBlueprintId, formNode.location) + formNode.documentFormId;
631
- };
632
- const formNodePath = (formNode) => {
633
- return spliceLocation(formNode.documentBlueprintId, formNode.location);
634
- };
635
- const formNodeNotIn = (formNode, formNodes) => {
636
- return !formNodes.find((fn) => formNodeId(fn) === formNodeId(formNode));
637
- };
638
- const sequential = async (items, callback) => {
639
- const accum = [];
640
- if (!items) {
641
- return [];
642
- }
643
- const reducePromises = async (previous, endpoint) => {
644
- const prev = await previous;
645
- if (prev) {
646
- accum.push(prev);
647
- }
648
- return callback(endpoint, accum.length);
649
- };
650
- const result = await items.reduce(reducePromises, Promise.resolve());
651
- if (result) {
652
- accum.push(result);
653
- }
654
- return accum;
655
- };
656
- const getFormNodesStartingWith = (string, state) => {
657
- return state.formNodes.filter((subFormNode) => {
658
- return subFormNode.documentBlueprintId.startsWith(string);
659
- });
660
- };
661
- const getFormNodesForField = (fieldBlueprint, formNode, event, state) => {
662
- const pathToChange = getPathToChange(fieldBlueprint, formNode, event);
663
- const formNodes = getFormNodesStartingWith(fieldBlueprint.id, state);
664
- const eventLocation = [
665
- ...formNode.location,
666
- ...stripIndices(event.field.name)
667
- ];
668
- const existing = getIn(state.data, pathToChange);
669
- return { pathToChange, formNodes, eventLocation, existing };
670
- };
671
- const getBlueprintAliasPath = (blueprint) => {
672
- const namePath = [];
673
- const aliasPath = [];
674
- blueprint.path.forEach((p) => {
675
- namePath.push(p.name);
676
- aliasPath.push(p.alias);
677
- if (p.list) {
678
- namePath.push("[]");
679
- aliasPath.push("[]");
680
- }
681
- });
682
- return aliasPath.join(".");
683
- };
684
- const getBlueprintFieldsForEvent = (blueprint, event) => {
685
- return blueprint.fields.filter((fbp) => {
686
- if (getBlueprintNamePath(fbp) === getEventPath(event, blueprint)) {
687
- return true;
688
- }
689
- }).filter((fbp) => {
690
- return filterFieldBlueprintsByParentTypename(fbp, event.field.data.tinaField.parentTypename);
691
- });
692
- };
693
- const filterFieldBlueprintsByParentTypename = (fbp, typename) => {
694
- let lastDisambiguator;
695
- fbp.path.forEach((path) => {
696
- if (path.parentTypename) {
697
- lastDisambiguator = path.parentTypename;
698
- }
699
- });
700
- if (lastDisambiguator) {
701
- return typename === lastDisambiguator;
702
- } else {
703
- return true;
704
- }
705
- };
706
- const getBlueprintNamePath = (blueprint, disambiguator) => {
707
- const namePath = [];
708
- blueprint.path.forEach((p) => {
709
- if (disambiguator) {
710
- if (p.parentTypename) {
711
- namePath.push(p.parentTypename);
712
- }
713
- }
714
- namePath.push(p.name);
715
- if (p.list) {
716
- namePath.push("[]");
717
- }
718
- });
719
- return namePath.join(".");
720
- };
721
- const getEventPath = (event, blueprint) => {
722
- const stringArray = event.field.name.split(".");
723
- const eventPath = stringArray.map((item) => {
724
- if (isNaN(Number(item))) {
725
- return item;
726
- }
727
- return `[]`;
728
- }).join(".");
729
- const items = [blueprint.id, eventPath];
730
- const isList = event.field.data.tinaField.list;
731
- if (isList && !eventPath.endsWith("[]")) {
732
- items.push(`[]`);
733
- }
734
- return items.join(".");
735
- };
736
- const stripIndices = (string) => {
737
- const accum = [];
738
- const stringArray = string.split(".");
739
- stringArray.forEach((item) => {
740
- if (isNaN(item))
741
- ;
742
- else {
743
- accum.push(Number(item));
744
- }
745
- });
746
- return accum;
747
- };
748
- const replaceRealNum = (string) => {
749
- const stringArray = string.split(".");
750
- return stringArray.map((item) => {
751
- if (isNaN(item)) {
752
- return item;
753
- }
754
- return "[]";
755
- }).join(".");
756
- };
757
- const getMatchName = ({ field, prefix, blueprint }) => {
758
- const fieldName = field.list ? `${field.name}.[]` : field.name;
759
- const blueprintName = getBlueprintNamePath(blueprint);
760
- const extra = [];
761
- if (prefix) {
762
- extra.push(prefix);
763
- }
764
- const matchName = [blueprintName, ...extra, fieldName].join(".");
765
- return { matchName, fieldName };
766
- };
767
- const getFormNodesFromEvent = (state, event) => {
768
- const formNodes = state.formNodes.filter((formNode) => formNode.documentFormId === event.formId);
769
- return formNodes;
770
- };
771
- const printEvent = (event) => {
772
- var _a, _b;
773
- return {
774
- type: event.type,
775
- value: event.value,
776
- previousValue: event.previousValue,
777
- mutationType: event.mutationType,
778
- formId: event.formId,
779
- field: {
780
- data: (_a = event.field) == null ? void 0 : _a.data,
781
- name: (_b = event.field) == null ? void 0 : _b.name
782
- }
783
- };
784
- };
785
- const getFormNodeBlueprint = (formNode, state) => {
786
- return state.blueprints.find((d) => d.id === formNode.documentBlueprintId);
787
- };
788
- const getMoveMapping = (existing, from, to) => {
789
- const newOrderObject = {};
790
- if (from < to) {
791
- existing.map((_, i) => {
792
- if (i === from) {
793
- newOrderObject[i] = to;
794
- return;
795
- }
796
- if (i > from) {
797
- if (i < to) {
798
- newOrderObject[i] = i - 1;
799
- return;
800
- } else {
801
- if (i === to) {
802
- newOrderObject[i] = i - 1;
803
- return;
804
- }
805
- newOrderObject[i] = i;
806
- return;
807
- }
808
- } else {
809
- newOrderObject[i] = i;
810
- return;
811
- }
812
- });
813
- } else {
814
- existing.map((_, i) => {
815
- if (i === from) {
816
- newOrderObject[i] = to;
817
- return;
818
- }
819
- if (i > to) {
820
- if (i < from) {
821
- newOrderObject[i] = i + 1;
822
- return;
823
- } else {
824
- newOrderObject[i] = i;
825
- return;
826
- }
827
- } else {
828
- if (i === to) {
829
- newOrderObject[i] = i + 1;
830
- return;
831
- }
832
- newOrderObject[i] = i;
833
- return;
834
- }
835
- });
836
- }
837
- return newOrderObject;
838
- };
839
- const matchLocation = (eventLocation, formNode) => {
840
- return eventLocation.every((item, index) => item === formNode.location[index]);
841
- };
842
- const bumpLocation = (location) => {
843
- return location.map((item, index) => {
844
- if (index === location.length - 1) {
845
- return item + 1;
846
- }
847
- return item;
848
- });
849
- };
850
- const maybeLowerLocation = (location, at) => {
851
- return location.map((item, index) => {
852
- if (index === location.length - 1) {
853
- return item < at ? item : item - 1;
854
- }
855
- return item;
856
- });
857
- };
858
- const matchesAt = (location, at) => {
859
- let matches = false;
860
- location.map((item, index) => {
861
- if (index === location.length - 1) {
862
- if (item === at) {
863
- matches = true;
864
- }
865
- }
866
- });
867
- return matches;
868
- };
869
- const swapLocation = (location, mapping) => {
870
- return location.map((item, index) => {
871
- if (index === location.length - 1) {
872
- return mapping[item];
873
- }
874
- return item;
875
- });
876
- };
877
- const getSubFields = (changeSet) => {
878
- var _a;
879
- const fields = changeSet.fieldDefinition.fields ? changeSet.fieldDefinition.fields : changeSet.fieldDefinition.templates[changeSet.value[0]._template].fields;
880
- let __typename;
881
- if ((_a = changeSet.fieldDefinition) == null ? void 0 : _a.templates) {
882
- __typename = changeSet.fieldDefinition.typeMap[changeSet.value[0]._template];
883
- }
884
- return { fields, __typename };
885
- };
886
- const isFormifiableDocument = (t) => {
887
- const type = G.getNamedType(t);
888
- if (G.isUnionType(type)) {
889
- return type.getTypes().every((type2) => {
890
- return type2.getInterfaces().find((intfc) => intfc.name === "Node");
891
- });
892
- } else if (G.isObjectType(type)) {
893
- return !!type.getInterfaces().find((intfc) => intfc.name === "Node");
894
- } else {
895
- return false;
896
- }
897
- };
898
- const isScalarType = (t) => {
899
- const namedType = G.getNamedType(t);
900
- return G.isScalarType(namedType);
901
- };
902
- const isConnectionField = (t) => {
903
- const type = G.getNamedType(t);
904
- if (G.isObjectType(type)) {
905
- return !!type.getInterfaces().find((intfc) => intfc.name === "Connection");
906
- } else {
907
- throw new Error(`Expected GraphQLObjectType for isConnectionField check`);
908
- }
909
- };
910
- const getObjectField = (object, selectionNode) => {
911
- const namedType = G.getNamedType(object);
912
- ensureObjectOrInterfaceType(namedType);
913
- return namedType.getFields()[selectionNode.name.value];
914
- };
915
- const getSelectedUnionType = (unionType, selectionNode) => {
916
- const namedType = G.getNamedType(unionType);
917
- if (!G.isUnionType(namedType)) {
918
- return;
919
- }
920
- const types = namedType.getTypes();
921
- const typeCondition = selectionNode.typeCondition.name.value;
922
- let intfc;
923
- types.forEach((type) => {
924
- intfc = type.getInterfaces().find((intfc2) => intfc2.name === typeCondition);
925
- });
926
- if (intfc) {
927
- return intfc;
928
- }
929
- return namedType.getTypes().find((type) => type.name === typeCondition);
930
- };
931
- function isListType(type) {
932
- if (G.isListType(type)) {
933
- return true;
934
- } else if (G.isNonNullType(type)) {
935
- if (G.isListType(type.ofType)) {
936
- return true;
937
- }
938
- }
939
- return false;
940
- }
941
- function ensureObjectOrInterfaceType(type) {
942
- if (G.isInterfaceType(type) || G.isObjectType(type))
943
- ;
944
- else {
945
- console.log("Expected type to be GraphQLObjectType or GraphQLInterfaceType", type);
946
- throw new Error(`Expected type to be GraphQLObjectType or GraphQLInterfaceType`);
947
- }
948
- }
949
- function ensureOperationDefinition(type) {
950
- if (type.kind !== "OperationDefinition") {
951
- throw new Error(`Expected top-level definition to be an OperationDefinition node, ensure your query has been optimized before calling formify`);
952
- }
953
- }
954
- function buildPath({
955
- fieldNode,
956
- type,
957
- parentTypename,
958
- path
959
- }) {
960
- const p = path || [];
961
- const list = isListType(type);
962
- const isNode = isFormifiableDocument(type);
963
- return [
964
- ...p,
965
- {
966
- name: fieldNode.name.value,
967
- alias: fieldNode.alias ? fieldNode.alias.value : fieldNode.name.value,
968
- parentTypename,
969
- list: !!list,
970
- isNode: !!isNode
971
- }
972
- ];
973
- }
974
- const node = G.parse(`
975
- query Sample {
976
- ...on Document {
977
- _internalSys: _sys {
978
- path
979
- relativePath
980
- collection {
981
- name
982
- }
983
- }
984
- _values
985
- }
986
- }`);
987
- const metaFields = node.definitions[0].selectionSet.selections;
988
- const getRelativeBlueprint = (path) => {
989
- let indexOfLastNode = 0;
990
- path.forEach((item, i) => {
991
- if (item.isNode) {
992
- if (i === path.length - 1)
993
- ;
994
- else {
995
- indexOfLastNode = i;
996
- }
997
- }
998
- });
999
- const documentBlueprintPath = path.slice(0, indexOfLastNode + 1);
1000
- return getBlueprintNamePath({ path: documentBlueprintPath });
1001
- };
1002
- const isSysField = (fieldNode) => {
1003
- if (fieldNode.name.value === "__typename") {
1004
- return true;
1005
- }
1006
- if (fieldNode.name.value === "_sys") {
1007
- return true;
1008
- }
1009
- if (fieldNode.name.value === "_values") {
1010
- return true;
1011
- }
1012
- if (fieldNode.name.value === "id") {
1013
- return true;
1014
- }
1015
- return false;
1016
- };
1017
- const getBlueprintId = (path) => {
1018
- const namePath = [];
1019
- const aliasPath = [];
1020
- path.forEach((p) => {
1021
- namePath.push(p.name);
1022
- aliasPath.push(p.alias);
1023
- if (p.list) {
1024
- namePath.push("[]");
1025
- aliasPath.push("[]");
1026
- }
1027
- });
1028
- return namePath.join(".");
1029
- };
1030
- const NOOP = "This is either an error or is not yet supported";
1031
- const UNEXPECTED = "Formify encountered an unexpected error, please contact support";
1032
- const EDGES_NODE_NAME = "edges";
1033
- const NODE_NAME = "node";
1034
- const COLLECTION_FIELD_NAME = "collection";
1035
- const COLLECTIONS_FIELD_NAME = "collections";
1036
- const COLLECTIONS_DOCUMENTS_NAME = "documents";
1037
- const formify = async ({
1038
- schema,
1039
- query,
1040
- getOptimizedQuery
1041
- }) => {
1042
- const blueprints = [];
1043
- const documentNode = G.parse(query);
1044
- const visitor = {
1045
- OperationDefinition: (node2) => {
1046
- if (!node2.name) {
1047
- return {
1048
- ...node2,
1049
- name: {
1050
- kind: "Name",
1051
- value: `QueryOperation`
1052
- }
1053
- };
1054
- }
1055
- return node2;
1056
- }
1057
- };
1058
- const documentNodeWithName = G.visit(documentNode, visitor);
1059
- const optimizedQuery = await getOptimizedQuery(documentNodeWithName);
1060
- const typeInfo = new G.TypeInfo(schema);
1061
- const formifyConnection = ({
1062
- parentType,
1063
- selectionNode,
1064
- path
1065
- }) => {
1066
- return {
1067
- ...selectionNode,
1068
- selectionSet: {
1069
- kind: "SelectionSet",
1070
- selections: selectionNode.selectionSet.selections.map((selectionNode2) => {
1071
- switch (selectionNode2.kind) {
1072
- case "Field":
1073
- if (selectionNode2.name.value === EDGES_NODE_NAME) {
1074
- const edgeField = getObjectField(parentType, selectionNode2);
1075
- const edgesPath = buildPath({
1076
- fieldNode: selectionNode2,
1077
- type: edgeField.type,
1078
- path
1079
- });
1080
- return {
1081
- ...selectionNode2,
1082
- selectionSet: {
1083
- kind: "SelectionSet",
1084
- selections: selectionNode2.selectionSet.selections.map((subSelectionNode) => {
1085
- switch (subSelectionNode.kind) {
1086
- case "Field":
1087
- if (subSelectionNode.name.value === NODE_NAME) {
1088
- const nodeField = getObjectField(edgeField.type, subSelectionNode);
1089
- return formifyFieldNodeDocument({
1090
- fieldNode: subSelectionNode,
1091
- type: nodeField.type,
1092
- path: buildPath({
1093
- fieldNode: subSelectionNode,
1094
- type: nodeField.type,
1095
- path: edgesPath
1096
- }),
1097
- showInSidebar: false
1098
- });
1099
- } else {
1100
- return subSelectionNode;
1101
- }
1102
- default:
1103
- throw new FormifyError("NOOP");
1104
- }
1105
- })
1106
- }
1107
- };
1108
- }
1109
- return selectionNode2;
1110
- default:
1111
- throw new FormifyError("UNEXPECTED");
1112
- }
1113
- })
1114
- }
1115
- };
1116
- };
1117
- function formifyInlineFragmentDocument({
1118
- inlineFragmentNode,
1119
- type,
1120
- path,
1121
- showInSidebar = false
1122
- }) {
1123
- return formifyDocument({
1124
- selection: inlineFragmentNode,
1125
- type,
1126
- path,
1127
- showInSidebar
1128
- });
1129
- }
1130
- function formifyFieldNodeDocument({
1131
- fieldNode,
1132
- type,
1133
- path,
1134
- showInSidebar = false
1135
- }) {
1136
- return formifyDocument({ selection: fieldNode, type, path, showInSidebar });
1137
- }
1138
- function formifyDocument({
1139
- selection,
1140
- type,
1141
- path,
1142
- showInSidebar = false
1143
- }) {
1144
- let extraFields = [];
1145
- const hasDataJSONField = false;
1146
- let hasValuesField = false;
1147
- let shouldFormify = false;
1148
- selection.selectionSet.selections.forEach((selection2) => {
1149
- if (selection2.kind === "Field") {
1150
- shouldFormify = true;
1151
- if (selection2.name.value === "_values") {
1152
- hasValuesField = true;
1153
- }
1154
- }
1155
- });
1156
- if (shouldFormify) {
1157
- blueprints.push({
1158
- id: getBlueprintId(path),
1159
- path,
1160
- selection,
1161
- fields: [],
1162
- showInSidebar,
1163
- hasDataJSONField,
1164
- hasValuesField
1165
- });
1166
- extraFields = metaFields;
1167
- }
1168
- return {
1169
- ...selection,
1170
- selectionSet: {
1171
- kind: "SelectionSet",
1172
- selections: [
1173
- ...selection.selectionSet.selections.map((selectionNode) => {
1174
- switch (selectionNode.kind) {
1175
- case "InlineFragment": {
1176
- const namedType = G.getNamedType(type);
1177
- if (G.isInterfaceType(namedType)) {
1178
- const subType = schema.getImplementations(namedType).objects.find((item) => item.name === selectionNode.typeCondition.name.value);
1179
- return formifyInlineFragmentDocument({
1180
- inlineFragmentNode: selectionNode,
1181
- type: subType,
1182
- path,
1183
- showInSidebar: true
1184
- });
1185
- }
1186
- return formifyInlineFragmentNode({
1187
- inlineFragmentNode: selectionNode,
1188
- parentType: type,
1189
- path,
1190
- showInSidebar: true
1191
- });
1192
- }
1193
- case "Field": {
1194
- return formifyFieldNode({
1195
- fieldNode: selectionNode,
1196
- parentType: type,
1197
- path
1198
- });
1199
- }
1200
- default:
1201
- throw new FormifyError("UNEXPECTED");
1202
- }
1203
- }),
1204
- ...extraFields
1205
- ]
1206
- }
1207
- };
1208
- }
1209
- const formifyFieldNode = ({
1210
- fieldNode,
1211
- parentType,
1212
- path
1213
- }) => {
1214
- if (fieldNode.name.value === "__typename") {
1215
- return fieldNode;
1216
- }
1217
- const field = getObjectField(parentType, fieldNode);
1218
- if (!field) {
1219
- return fieldNode;
1220
- }
1221
- const fieldPath = buildPath({
1222
- fieldNode,
1223
- type: field.type,
1224
- parentTypename: G.getNamedType(parentType).name,
1225
- path
1226
- });
1227
- const blueprint = blueprints.find((blueprint2) => blueprint2.id === getRelativeBlueprint(fieldPath));
1228
- if (!blueprint) {
1229
- return fieldNode;
1230
- }
1231
- if (isSysField(fieldNode)) {
1232
- return fieldNode;
1233
- }
1234
- blueprint.fields.push({
1235
- id: getBlueprintId(fieldPath),
1236
- documentBlueprintId: blueprint.id,
1237
- path: fieldPath
1238
- });
1239
- if (isScalarType(field.type)) {
1240
- return fieldNode;
1241
- }
1242
- return {
1243
- ...fieldNode,
1244
- selectionSet: {
1245
- kind: "SelectionSet",
1246
- selections: [
1247
- ...fieldNode.selectionSet.selections.map((selectionNode) => {
1248
- switch (selectionNode.kind) {
1249
- case "Field": {
1250
- return formifyFieldNode({
1251
- fieldNode: selectionNode,
1252
- parentType: field.type,
1253
- path: fieldPath
1254
- });
1255
- }
1256
- case "InlineFragment": {
1257
- return formifyInlineFragmentNode({
1258
- inlineFragmentNode: selectionNode,
1259
- parentType: field.type,
1260
- path: fieldPath,
1261
- showInSidebar: false
1262
- });
1263
- }
1264
- default:
1265
- throw new FormifyError("UNEXPECTED", `selection ${selectionNode.kind}`);
1266
- }
1267
- })
1268
- ]
1269
- }
1270
- };
1271
- };
1272
- const formifyInlineFragmentNode = ({
1273
- inlineFragmentNode,
1274
- parentType,
1275
- path,
1276
- showInSidebar
1277
- }) => {
1278
- const type = getSelectedUnionType(parentType, inlineFragmentNode);
1279
- if (!type) {
1280
- return inlineFragmentNode;
1281
- }
1282
- if (isFormifiableDocument(type)) {
1283
- return formifyInlineFragmentDocument({
1284
- inlineFragmentNode,
1285
- type,
1286
- path,
1287
- showInSidebar
1288
- });
1289
- }
1290
- return {
1291
- ...inlineFragmentNode,
1292
- selectionSet: {
1293
- kind: "SelectionSet",
1294
- selections: inlineFragmentNode.selectionSet.selections.map((selectionNode) => {
1295
- switch (selectionNode.kind) {
1296
- case "Field":
1297
- return formifyFieldNode({
1298
- fieldNode: selectionNode,
1299
- parentType: type,
1300
- path
1301
- });
1302
- default:
1303
- throw new FormifyError("UNEXPECTED", `selection ${selectionNode.kind}`);
1304
- }
1305
- })
1306
- }
1307
- };
1308
- };
1309
- const formifiedQuery = {
1310
- kind: "Document",
1311
- definitions: optimizedQuery.definitions.map((definition) => {
1312
- typeInfo.enter(definition);
1313
- ensureOperationDefinition(definition);
1314
- const parentType = typeInfo.getType();
1315
- return {
1316
- ...definition,
1317
- selectionSet: {
1318
- kind: "SelectionSet",
1319
- selections: definition.selectionSet.selections.map((selectionNode) => {
1320
- switch (selectionNode.kind) {
1321
- case "Field":
1322
- const field = getObjectField(parentType, selectionNode);
1323
- const path = buildPath({
1324
- fieldNode: selectionNode,
1325
- type: field.type
1326
- });
1327
- if (isFormifiableDocument(field.type)) {
1328
- return formifyFieldNodeDocument({
1329
- fieldNode: selectionNode,
1330
- type: field.type,
1331
- path,
1332
- showInSidebar: true
1333
- });
1334
- } else if (isConnectionField(field.type)) {
1335
- return formifyConnection({
1336
- parentType: field.type,
1337
- selectionNode,
1338
- path
1339
- });
1340
- }
1341
- if (selectionNode.name.value === COLLECTION_FIELD_NAME || selectionNode.name.value === COLLECTIONS_FIELD_NAME) {
1342
- const path2 = buildPath({
1343
- fieldNode: selectionNode,
1344
- type: field.type
1345
- });
1346
- return {
1347
- ...selectionNode,
1348
- selectionSet: {
1349
- kind: "SelectionSet",
1350
- selections: selectionNode.selectionSet.selections.map((subSelectionNode) => {
1351
- switch (subSelectionNode.kind) {
1352
- case "Field":
1353
- if (subSelectionNode.name.value === COLLECTIONS_DOCUMENTS_NAME) {
1354
- const subField = getObjectField(field.type, subSelectionNode);
1355
- return formifyConnection({
1356
- parentType: subField.type,
1357
- selectionNode: subSelectionNode,
1358
- path: buildPath({
1359
- fieldNode: subSelectionNode,
1360
- type: subField.type,
1361
- path: path2
1362
- })
1363
- });
1364
- }
1365
- return subSelectionNode;
1366
- default:
1367
- throw new FormifyError("NOOP");
1368
- }
1369
- })
1370
- }
1371
- };
1372
- }
1373
- throw new FormifyError("NOOP");
1374
- default:
1375
- throw new FormifyError("UNEXPECTED");
1376
- }
1377
- })
1378
- }
1379
- };
1380
- })
1381
- };
1382
- return { formifiedQuery, blueprints };
1383
- };
1384
- class FormifyError extends Error {
1385
- constructor(code, details) {
1386
- let message;
1387
- switch (code) {
1388
- case "NOOP":
1389
- message = NOOP;
1390
- break;
1391
- case "UNEXPECTED":
1392
- message = UNEXPECTED;
1393
- break;
1394
- default:
1395
- message = "";
1396
- break;
1397
- }
1398
- super(`${message} ${details || ""}`);
1399
- this.name = "FormifyError";
1400
- }
1401
- }
1402
- const defaultState = {
1403
- status: "idle",
1404
- schema: void 0,
1405
- query: null,
1406
- queryString: null,
1407
- data: {},
1408
- changeSets: [],
1409
- count: 0,
1410
- blueprints: [],
1411
- formNodes: [],
1412
- documentForms: []
1413
- };
1414
- function reducer(state, action) {
1415
- var _a, _b, _c, _d;
1416
- switch (action.type) {
1417
- case "start":
1418
- return {
1419
- ...state,
1420
- ...defaultState,
1421
- query: action.value.query ? G.parse(action.value.query) : null,
1422
- queryString: action.value.query,
1423
- status: "initialized"
1424
- };
1425
- case "addDocumentBlueprints":
1426
- return {
1427
- ...state,
1428
- status: "formified",
1429
- blueprints: action.value.blueprints,
1430
- query: action.value.formifiedQuery
1431
- };
1432
- case "addOrReplaceDocumentFormNode": {
1433
- const existingDocumentForms = state.documentForms.filter((documentForm) => {
1434
- var _a2, _b2;
1435
- return documentForm.id !== ((_b2 = (_a2 = action.value) == null ? void 0 : _a2.documentForm) == null ? void 0 : _b2.id);
1436
- });
1437
- const existingDocumentFormNodes = state.formNodes.filter((formNode) => {
1438
- return formNodeId(formNode) !== formNodeId(action.value.formNode);
1439
- });
1440
- const newDocumentForms = [];
1441
- if ((_a = action.value) == null ? void 0 : _a.documentForm) {
1442
- newDocumentForms.push((_b = action.value) == null ? void 0 : _b.documentForm);
1443
- }
1444
- return {
1445
- ...state,
1446
- formNodes: [...existingDocumentFormNodes, action.value.formNode],
1447
- documentForms: [...existingDocumentForms, ...newDocumentForms]
1448
- };
1449
- }
1450
- case "onFieldChange": {
1451
- const event = action.value.event;
1452
- const changeSets = [];
1453
- const formNodesToReplace = [];
1454
- const formNodesToRemove = [];
1455
- const newFormNodes = [];
1456
- const form = state.documentForms.find((documentForm) => documentForm.id === event.formId);
1457
- getFormNodesFromEvent(state, event).forEach((formNode) => {
1458
- const blueprint = getFormNodeBlueprint(formNode, state);
1459
- if (blueprint.hasValuesField) {
1460
- changeSets.push({
1461
- path: [formNodePath(formNode), "values"].join("."),
1462
- ...buildChangeSet(event, formNode),
1463
- value: form.values,
1464
- mutationType: {
1465
- type: "global"
1466
- }
1467
- });
1468
- }
1469
- if (blueprint.hasDataJSONField) {
1470
- changeSets.push({
1471
- path: [formNodePath(formNode), "dataJSON"].join("."),
1472
- ...buildChangeSet(event, formNode),
1473
- value: form.values,
1474
- mutationType: {
1475
- type: "global"
1476
- }
1477
- });
1478
- }
1479
- if (event.mutationType.type === "change") {
1480
- if (!action.value.form) {
1481
- getBlueprintFieldsForEvent(blueprint, event).forEach((fieldBlueprint) => {
1482
- const { pathToChange } = getFormNodesForField(fieldBlueprint, formNode, event, state);
1483
- changeSets.push({
1484
- path: pathToChange,
1485
- ...buildChangeSet(event, formNode)
1486
- });
1487
- });
1488
- }
1489
- } else if (event.mutationType.type === "referenceChange") {
1490
- getBlueprintFieldsForEvent(blueprint, event).forEach((fieldBlueprint) => {
1491
- const {
1492
- pathToChange,
1493
- formNodes: subFormNodes,
1494
- eventLocation
1495
- } = getFormNodesForField(fieldBlueprint, formNode, event, state);
1496
- if (action.value.form && state.blueprints.find((blueprint2) => blueprint2.id === fieldBlueprint.id)) {
1497
- const newFormNode = {
1498
- documentBlueprintId: fieldBlueprint.id,
1499
- documentFormId: action.value.form.id,
1500
- location: eventLocation
1501
- };
1502
- newFormNodes.push(newFormNode);
1503
- changeSets.push({
1504
- path: pathToChange,
1505
- ...buildChangeSet(event, newFormNode)
1506
- });
1507
- }
1508
- subFormNodes.forEach((subFormNode) => {
1509
- if (matchLocation(eventLocation, subFormNode)) {
1510
- if (!action.value.form) {
1511
- changeSets.push({
1512
- path: pathToChange,
1513
- ...buildChangeSet(event, subFormNode),
1514
- value: null
1515
- });
1516
- }
1517
- formNodesToReplace.push(subFormNode);
1518
- }
1519
- });
1520
- });
1521
- } else {
1522
- getBlueprintFieldsForEvent(blueprint, event).forEach((fieldBlueprint) => {
1523
- const { pathToChange, formNodes, existing, eventLocation } = getFormNodesForField(fieldBlueprint, formNode, event, state);
1524
- if (event.mutationType.type === "insert") {
1525
- formNodes.forEach((subFormNode) => {
1526
- if (matchLocation(eventLocation, subFormNode)) {
1527
- newFormNodes.push({
1528
- ...subFormNode,
1529
- location: bumpLocation(subFormNode.location)
1530
- });
1531
- formNodesToReplace.push(subFormNode);
1532
- }
1533
- });
1534
- changeSets.push({
1535
- path: pathToChange,
1536
- ...buildChangeSet(event, formNode)
1537
- });
1538
- }
1539
- if (event.mutationType.type === "remove") {
1540
- const { at } = event.mutationType;
1541
- formNodes.forEach((subFormNode) => {
1542
- if (matchLocation(eventLocation, subFormNode)) {
1543
- if (matchesAt(subFormNode.location, at)) {
1544
- formNodesToRemove.push(subFormNode);
1545
- } else {
1546
- newFormNodes.push({
1547
- ...subFormNode,
1548
- location: maybeLowerLocation(subFormNode.location, at)
1549
- });
1550
- formNodesToReplace.push(subFormNode);
1551
- }
1552
- }
1553
- });
1554
- const next = existing.filter((_, index) => index !== at);
1555
- changeSets.push({
1556
- path: pathToChange,
1557
- ...buildChangeSet(event, formNode),
1558
- value: next
1559
- });
1560
- }
1561
- if (event.mutationType.type === "move") {
1562
- const next = [];
1563
- const { from, to } = event.mutationType;
1564
- const newOrderObject = getMoveMapping(existing, from, to);
1565
- formNodes.forEach((subFormNode) => {
1566
- if (matchLocation(eventLocation, subFormNode)) {
1567
- newFormNodes.push({
1568
- ...subFormNode,
1569
- location: swapLocation(subFormNode.location, newOrderObject)
1570
- });
1571
- formNodesToReplace.push(subFormNode);
1572
- }
1573
- });
1574
- Object.values(newOrderObject).forEach((orderIndex, index) => {
1575
- next[orderIndex] = existing[index];
1576
- });
1577
- changeSets.push({
1578
- path: pathToChange,
1579
- ...buildChangeSet(event, formNode),
1580
- value: next
1581
- });
1582
- }
1583
- });
1584
- }
1585
- });
1586
- const existingDocumentForms = state.documentForms.filter((documentForm) => {
1587
- var _a2;
1588
- return documentForm.id !== ((_a2 = action.value.form) == null ? void 0 : _a2.id);
1589
- });
1590
- const newDocumentForms = [];
1591
- if ((_c = action.value) == null ? void 0 : _c.form) {
1592
- newDocumentForms.push((_d = action.value) == null ? void 0 : _d.form);
1593
- }
1594
- return {
1595
- ...state,
1596
- changeSets,
1597
- formNodes: [
1598
- ...state.formNodes.filter((formNode) => formNodeNotIn(formNode, formNodesToReplace)).filter((formNode) => formNodeNotIn(formNode, formNodesToRemove)),
1599
- ...newFormNodes
1600
- ],
1601
- documentForms: [...existingDocumentForms, ...newDocumentForms]
1602
- };
1603
- }
1604
- case "formOnReset": {
1605
- const { event } = action.value;
1606
- const changeSets = [];
1607
- const form = state.documentForms.find((documentForm) => documentForm.id === event.formId);
1608
- state.formNodes.filter((fn) => fn.documentFormId === (form == null ? void 0 : form.id)).forEach((formNode) => {
1609
- const blueprint = getFormNodeBlueprint(formNode, state);
1610
- if (blueprint.hasValuesField) {
1611
- changeSets.push({
1612
- path: [formNodePath(formNode), "_values"].join("."),
1613
- ...buildChangeSet(event, formNode)
1614
- });
1615
- }
1616
- changeSets.push({
1617
- path: [formNodePath(formNode)].join("."),
1618
- ...buildChangeSet(event, formNode)
1619
- });
1620
- });
1621
- return { ...state, changeSets };
1622
- }
1623
- case "ready":
1624
- return { ...state, status: "ready" };
1625
- case "done":
1626
- return { ...state, status: "done" };
1627
- case "setData":
1628
- return { ...state, data: action.value };
1629
- case "setIn": {
1630
- let newData;
1631
- if (action.value.displaceIndex) {
1632
- const existing = getIn(state.data, action.value.path) || [];
1633
- newData = setIn(state.data, action.value.path, [
1634
- action.value.value,
1635
- ...existing
1636
- ]);
1637
- } else {
1638
- newData = setIn(state.data, action.value.path, action.value.value);
1639
- }
1640
- const changeSets = state.changeSets.filter((cs) => cs.path !== action.value.path);
1641
- return {
1642
- ...state,
1643
- data: newData,
1644
- changeSets
1645
- };
1646
- }
1647
- default:
1648
- return state;
1649
- }
1650
- }
1651
- const buildChangeSet = (event, formNode) => {
1652
- var _a, _b, _c;
1653
- return {
1654
- fieldDefinition: (_b = (_a = event.field) == null ? void 0 : _a.data) == null ? void 0 : _b.tinaField,
1655
- name: (_c = event.field) == null ? void 0 : _c.name,
1656
- formId: event.formId,
1657
- mutationType: event.mutationType,
1658
- value: event.value,
1659
- formNode
1660
- };
1661
- };
1662
- const useFormify = ({
1663
- query,
1664
- cms,
1665
- variables,
1666
- onSubmit,
1667
- formify: formifyFunc,
1668
- eventList
1669
- }) => {
1670
- const formIds = React.useRef([]);
1671
- const [state, dispatch] = React.useReducer(reducer, {
1672
- status: "idle",
1673
- schema: void 0,
1674
- query: query ? G.parse(query) : null,
1675
- queryString: query,
1676
- data: {},
1677
- changeSets: [],
1678
- count: 0,
1679
- blueprints: [],
1680
- formNodes: [],
1681
- documentForms: []
1682
- });
1683
- React.useEffect(() => {
1684
- if (query) {
1685
- dispatch({ type: "start", value: { query } });
1686
- formIds.current.forEach((formId) => {
1687
- const form = cms.forms.find(formId);
1688
- if (form) {
1689
- cms.plugins.remove(form);
1690
- }
1691
- });
1692
- }
1693
- }, [query, JSON.stringify(variables)]);
1694
- React.useEffect(() => {
1695
- if (state.status === "initialized") {
1696
- cms.api.tina.request(query, { variables }).then((res) => {
1697
- delete res.paths;
1698
- dispatch({ type: "setData", value: res });
1699
- });
1700
- }
1701
- }, [state.status]);
1702
- React.useEffect(() => {
1703
- const run = async () => {
1704
- const schema = await cms.api.tina.getSchema();
1705
- const result = await formify({
1706
- schema,
1707
- query,
1708
- getOptimizedQuery: cms.api.tina.getOptimizedQuery
1709
- });
1710
- dispatch({
1711
- type: "addDocumentBlueprints",
1712
- value: result
1713
- });
1714
- };
1715
- if (state.status === "initialized") {
1716
- run();
1717
- }
1718
- }, [state.status]);
1719
- React.useEffect(() => {
1720
- const run = async () => {
1721
- const result = await cms.api.tina.request(G.print(state.query), {
1722
- variables
1723
- });
1724
- state.blueprints.map((blueprint) => {
1725
- const responseAtBlueprint = getValueForBlueprint(result, getBlueprintAliasPath(blueprint));
1726
- const location = [];
1727
- const findFormNodes = (res, location2) => {
1728
- if (Array.isArray(res)) {
1729
- res.forEach((item, index) => {
1730
- if (Array.isArray(item)) {
1731
- findFormNodes(item, [...location2, index]);
1732
- } else {
1733
- if (item) {
1734
- const form = buildForm(item, cms, formifyFunc, blueprint.showInSidebar, onSubmit);
1735
- const formNode = buildFormNode(blueprint, form, [
1736
- ...location2,
1737
- index
1738
- ]);
1739
- dispatch({
1740
- type: "addOrReplaceDocumentFormNode",
1741
- value: {
1742
- formNode,
1743
- documentForm: form
1744
- }
1745
- });
1746
- }
1747
- }
1748
- });
1749
- } else {
1750
- if (res) {
1751
- const form = buildForm(res, cms, formifyFunc, blueprint.showInSidebar, onSubmit);
1752
- const formNode = buildFormNode(blueprint, form, location2);
1753
- dispatch({
1754
- type: "addOrReplaceDocumentFormNode",
1755
- value: {
1756
- formNode,
1757
- documentForm: form
1758
- }
1759
- });
1760
- }
1761
- }
1762
- };
1763
- findFormNodes(responseAtBlueprint, location);
1764
- });
1765
- dispatch({ type: "ready" });
1766
- };
1767
- if (state.status === "formified") {
1768
- run();
1769
- }
1770
- }, [state.status]);
1771
- React.useEffect(() => {
1772
- if (state.status === "ready") {
1773
- cms.events.subscribe(`forms:reset`, (event) => {
1774
- if (eventList) {
1775
- eventList.push(printEvent(event));
1776
- }
1777
- dispatch({ type: "formOnReset", value: { event } });
1778
- });
1779
- cms.events.subscribe(`forms:fields:onChange`, async (event) => {
1780
- if (eventList) {
1781
- eventList.push(printEvent(event));
1782
- }
1783
- if (event.field.data.tinaField.type === "reference") {
1784
- let form;
1785
- if (event.value && typeof event.value === "string") {
1786
- const existingForm = cms.forms.find(event.value);
1787
- if (existingForm) {
1788
- form = existingForm;
1789
- } else {
1790
- const formInfo = await cms.api.tina.request(`#graphql
1791
- query Node($id: String!) {
1792
- node(id: $id) {
1793
- ...on Document {
1794
- _values
1795
- _internalSys: _sys {
1796
- path
1797
- relativePath
1798
- collection {
1799
- name
1800
- }
1801
- }
1802
- }
1803
- }
1804
- }
1805
- `, { variables: { id: event.value } });
1806
- form = buildForm(formInfo.node, cms, formifyFunc, false, onSubmit);
1807
- }
1808
- }
1809
- dispatch({
1810
- type: "onFieldChange",
1811
- value: {
1812
- event: {
1813
- ...event,
1814
- mutationType: { type: "referenceChange" }
1815
- },
1816
- form
1817
- }
1818
- });
1819
- } else {
1820
- dispatch({ type: "onFieldChange", value: { event } });
5
+ import { getIntrospectionQuery, buildClientSchema, print, parse, buildSchema } from "graphql";
6
+ import gql$1 from "graphql-tag";
7
+ import { TinaSchema, addNamespaceToSchema, parseURL, resolveForm, validateSchema } from "@tinacms/schema-tools";
8
+ export { NAMER, resolveForm } from "@tinacms/schema-tools";
9
+ import React, { useState, useCallback, useEffect, Fragment, useMemo } from "react";
10
+ import * as yup from "yup";
11
+ import { setEditing, useEditState } from "@tinacms/sharedctx";
12
+ import { diff } from "@graphql-inspector/core";
13
+ import { NavLink, useSearchParams, useNavigate, useParams, useLocation, Link, HashRouter, Routes, Route } from "react-router-dom";
14
+ import { Transition, Menu } from "@headlessui/react";
15
+ import { useWindowWidth } from "@react-hook/window-size";
16
+ function popupWindow(url, title, window2, w, h) {
17
+ const y = window2.top.outerHeight / 2 + window2.top.screenY - h / 2;
18
+ const x = window2.top.outerWidth / 2 + window2.top.screenX - w / 2;
19
+ return window2.open(url, title, "toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=no, width=" + w + ", height=" + h + ", top=" + y + ", left=" + x);
20
+ }
21
+ const TINA_LOGIN_EVENT = "tinaCloudLogin";
22
+ const AUTH_TOKEN_KEY = "tinacms-auth";
23
+ const authenticate = (clientId, frontendUrl) => {
24
+ return new Promise((resolve) => {
25
+ let authTab;
26
+ window.addEventListener("message", function(e) {
27
+ if (e.data.source === TINA_LOGIN_EVENT) {
28
+ if (authTab) {
29
+ authTab.close();
1821
30
  }
1822
- });
1823
- dispatch({ type: "done" });
1824
- }
1825
- }, [state.status]);
1826
- React.useEffect(() => {
1827
- state.changeSets.forEach((changeSet) => {
1828
- if (changeSet.mutationType.type === "reset") {
1829
- const form = cms.forms.find(changeSet.formId);
1830
- resolveSubFields({
1831
- formNode: changeSet.formNode,
1832
- form,
1833
- loc: []
1834
- }).then((res) => {
1835
- dispatch({
1836
- type: "setIn",
1837
- value: {
1838
- value: res,
1839
- path: changeSet.path
1840
- }
1841
- });
31
+ resolve({
32
+ id_token: e.data.id_token,
33
+ access_token: e.data.access_token,
34
+ refresh_token: e.data.refresh_token
1842
35
  });
1843
- return;
1844
- } else if (changeSet.mutationType.type === "insert") {
1845
- if (changeSet.fieldDefinition.type === "object") {
1846
- const fieldName = changeSet.fieldDefinition.list ? `${changeSet.name}.[]` : changeSet.name;
1847
- const { fields, __typename } = getSubFields(changeSet);
1848
- resolveSubFields({
1849
- formNode: changeSet.formNode,
1850
- prefix: replaceRealNum(fieldName),
1851
- loc: [...stripIndices(changeSet.path), 0],
1852
- form: {
1853
- fields,
1854
- values: changeSet.value[0]
1855
- }
1856
- }).then((res) => {
1857
- const extra = {};
1858
- if (__typename) {
1859
- extra["__typename"] = __typename;
1860
- }
1861
- dispatch({
1862
- type: "setIn",
1863
- value: {
1864
- displaceIndex: true,
1865
- ...changeSet,
1866
- value: {
1867
- ...res,
1868
- ...extra
1869
- }
1870
- }
1871
- });
1872
- });
1873
- } else {
1874
- dispatch({
1875
- type: "setIn",
1876
- value: {
1877
- displaceIndex: true,
1878
- ...changeSet,
1879
- value: changeSet.value[0]
1880
- }
1881
- });
1882
- }
1883
- } else {
1884
- if (changeSet.mutationType.type === "referenceChange") {
1885
- const { formNode } = changeSet;
1886
- const blueprint = getFormNodeBlueprint(formNode, state);
1887
- if (!changeSet.value) {
1888
- dispatch({
1889
- type: "setIn",
1890
- value: {
1891
- ...changeSet,
1892
- value: null
1893
- }
1894
- });
1895
- } else {
1896
- cms.api.tina.request(`
1897
- query Node($id: String!) {
1898
- node(id: $id) {
1899
- ${G.print(blueprint.selection)}
1900
- }
1901
- }
1902
- `, { variables: { id: changeSet.value } }).then(async (res) => {
1903
- const form = state.documentForms.find((documentForm) => documentForm.id === formNode.documentFormId);
1904
- const data = await resolveSubFields({
1905
- formNode,
1906
- form,
1907
- loc: formNode.location
1908
- });
1909
- dispatch({
1910
- type: "setIn",
1911
- value: {
1912
- ...changeSet,
1913
- value: {
1914
- ...res.node,
1915
- ...data
1916
- }
1917
- }
1918
- });
1919
- }).catch((e) => {
1920
- cms.alerts.error(`Unexpected error fetching reference.`);
1921
- console.log(e);
1922
- });
1923
- }
1924
- } else {
1925
- dispatch({ type: "setIn", value: changeSet });
1926
- }
1927
- }
1928
- });
1929
- }, [JSON.stringify(state.changeSets)]);
1930
- React.useEffect(() => {
1931
- formIds.current = state.documentForms.map((df) => df.id);
1932
- }, [state.documentForms.length]);
1933
- React.useEffect(() => {
1934
- return () => {
1935
- formIds.current.forEach((formId) => {
1936
- const form = cms.forms.find(formId);
1937
- if (form) {
1938
- cms.plugins.remove(form);
1939
- }
1940
- });
1941
- };
1942
- }, []);
1943
- const resolveSubFields = React.useCallback(async (args) => {
1944
- const { form, formNode, prefix, loc } = args;
1945
- const data = {};
1946
- await sequential(form.fields, async (field) => {
1947
- const value = form.values[field.name];
1948
- const blueprint = getFormNodeBlueprint(formNode, state);
1949
- const { matchName, fieldName } = getMatchName({
1950
- field,
1951
- prefix,
1952
- blueprint
1953
- });
1954
- const fieldBlueprints = blueprint.fields.filter((fieldBlueprint) => {
1955
- return matchName === getBlueprintNamePath(fieldBlueprint);
1956
- }).filter((fbp) => filterFieldBlueprintsByParentTypename(fbp, field.parentTypename));
1957
- switch (field.type) {
1958
- case "object":
1959
- if (field.templates) {
1960
- if (field.list) {
1961
- await sequential(fieldBlueprints, async (fieldBlueprint) => {
1962
- const keyName = getFieldNameOrAlias(fieldBlueprint);
1963
- if (!value) {
1964
- data[keyName] = null;
1965
- return true;
1966
- }
1967
- if (!Array.isArray(value)) {
1968
- throw new Error(`Expected value for object list field to be an array`);
1969
- }
1970
- data[keyName] = await sequential(value, async (item, index) => {
1971
- const template = field.templates[item._template];
1972
- return {
1973
- ...await resolveSubFields({
1974
- formNode,
1975
- form: { fields: template.fields, values: item },
1976
- prefix: prefix ? [prefix, fieldName].join(".") : fieldName,
1977
- loc: [...loc, index]
1978
- }),
1979
- __typename: field.typeMap[item._template]
1980
- };
1981
- });
1982
- });
1983
- } else {
1984
- throw new Error("blocks without list true is not yet supported");
1985
- }
1986
- } else {
1987
- if (field.list) {
1988
- await sequential(fieldBlueprints, async (fieldBlueprint) => {
1989
- const keyName = getFieldNameOrAlias(fieldBlueprint);
1990
- if (!value) {
1991
- data[keyName] = null;
1992
- return true;
1993
- }
1994
- if (!Array.isArray(value)) {
1995
- throw new Error(`Expected value for object list field to be an array`);
1996
- }
1997
- data[keyName] = await sequential(value, async (item, index) => {
1998
- return resolveSubFields({
1999
- formNode,
2000
- form: { fields: field.fields, values: item },
2001
- prefix: [prefix, fieldName].join("."),
2002
- loc: [...loc, index]
2003
- });
2004
- });
2005
- return true;
2006
- });
2007
- } else {
2008
- await sequential(fieldBlueprints, async (fieldBlueprint) => {
2009
- const keyName = getFieldNameOrAlias(fieldBlueprint);
2010
- if (!value) {
2011
- data[keyName] = null;
2012
- return true;
2013
- }
2014
- data[keyName] = await resolveSubFields({
2015
- formNode,
2016
- form: { fields: field.fields, values: value },
2017
- prefix: [prefix, fieldName].join("."),
2018
- loc
2019
- });
2020
- return true;
2021
- });
2022
- }
2023
- }
2024
- break;
2025
- case "reference":
2026
- let form2;
2027
- if (typeof value === "string") {
2028
- const existingForm = cms.forms.find(value);
2029
- if (existingForm) {
2030
- form2 = existingForm;
2031
- } else {
2032
- const formInfo = await cms.api.tina.request(`#graphql
2033
- query Node($id: String!) {
2034
- node(id: $id) {
2035
- ...on Document {
2036
- _values
2037
- _internalSys: _sys {
2038
- path
2039
- relativePath
2040
- collection {
2041
- name
2042
- }
2043
- }
2044
- }
2045
- }
2046
- }
2047
- `, { variables: { id: value } });
2048
- form2 = buildForm(formInfo.node, cms, formifyFunc, false, onSubmit);
2049
- }
2050
- }
2051
- await sequential(fieldBlueprints, async (fieldBlueprint) => {
2052
- const keyName = getFieldNameOrAlias(fieldBlueprint);
2053
- if (!value) {
2054
- data[keyName] = null;
2055
- return true;
2056
- }
2057
- const documentBlueprint = state.blueprints.find((dp) => getBlueprintNamePath(dp) === matchName);
2058
- const location = [...formNode.location];
2059
- if (loc) {
2060
- loc.forEach((item) => location.push(item));
2061
- }
2062
- const subDocumentFormNode = buildFormNode(documentBlueprint, form2, location);
2063
- dispatch({
2064
- type: "addOrReplaceDocumentFormNode",
2065
- value: {
2066
- formNode: subDocumentFormNode,
2067
- documentForm: form2
2068
- }
2069
- });
2070
- const res = await cms.api.tina.request(`
2071
- query Node($id: String!) {
2072
- node(id: $id) {
2073
- ${G.print(documentBlueprint.selection)}
2074
- }
2075
- }
2076
- `, { variables: { id: value } });
2077
- data[keyName] = {
2078
- ...res.node,
2079
- ...await resolveSubFields({
2080
- formNode: subDocumentFormNode,
2081
- form: form2,
2082
- loc: location
2083
- })
2084
- };
2085
- });
2086
- break;
2087
- default:
2088
- fieldBlueprints.forEach((fieldBlueprint) => {
2089
- const keyName = getFieldNameOrAlias(fieldBlueprint);
2090
- if (!value) {
2091
- data[keyName] = null;
2092
- } else {
2093
- data[keyName] = value;
2094
- }
2095
- });
2096
- break;
2097
36
  }
2098
- return true;
2099
37
  });
2100
- return data;
2101
- }, [cms, JSON.stringify(state), dispatch]);
2102
- return {
2103
- ...state,
2104
- queryString: G.print(state.query)
2105
- };
2106
- };
2107
- const buildFormNode = (documentBlueprint, form, location) => {
2108
- return {
2109
- documentBlueprintId: documentBlueprint.id,
2110
- documentFormId: form.id,
2111
- location
2112
- };
38
+ const origin = `${window.location.protocol}//${window.location.host}`;
39
+ authTab = popupWindow(`${frontendUrl}/signin?clientId=${clientId}&origin=${origin}`, "_blank", window, 1e3, 700);
40
+ });
2113
41
  };
2114
42
  const captureBranchName = /^refs\/heads\/(.*)/;
2115
43
  const parseRefForBranchName = (ref) => {
@@ -2284,24 +212,6 @@ mutation addPendingDocumentMutation(
2284
212
  this.contentApiBase = ((_d = this.options.tinaioConfig) == null ? void 0 : _d.contentApiUrlOverride) || `https://content.tinajs.io`;
2285
213
  this.contentApiUrl = this.options.customContentApiUrl || `${this.contentApiBase}/content/${this.options.clientId}/github/${encodedBranch}`;
2286
214
  }
2287
- async requestWithForm(query, {
2288
- variables,
2289
- useUnstableFormify
2290
- }) {
2291
- const schema = await this.getSchema();
2292
- let formifiedQuery;
2293
- if (useUnstableFormify) {
2294
- const res = await formify({
2295
- schema,
2296
- query: print(query(gql$1)),
2297
- getOptimizedQuery: this.getOptimizedQuery
2298
- });
2299
- formifiedQuery = res.formifiedQuery;
2300
- } else {
2301
- formifiedQuery = formify$1(query(gql$1), schema);
2302
- }
2303
- return this.request(print(formifiedQuery), { variables });
2304
- }
2305
215
  async request(query, { variables }) {
2306
216
  const res = await fetch(this.contentApiUrl, {
2307
217
  method: "POST",
@@ -2595,6 +505,7 @@ const AsyncButton = ({ name, primary, action }) => {
2595
505
  }
2596
506
  }, [action, setSubmitting]);
2597
507
  return /* @__PURE__ */ React.createElement(Button, {
508
+ "data-test": name.replace(/\s/g, "-").toLowerCase(),
2598
509
  variant: primary ? "primary" : "secondary",
2599
510
  onClick,
2600
511
  busy: submitting,
@@ -2616,6 +527,39 @@ const useTinaAuthRedirect = () => {
2616
527
  localStorage[TINA_AUTH_CONFIG] = JSON.stringify(config);
2617
528
  }, []);
2618
529
  };
530
+ const createClient = ({
531
+ clientId,
532
+ isLocalClient = true,
533
+ branch,
534
+ tinaioConfig,
535
+ schema,
536
+ apiUrl
537
+ }) => {
538
+ return isLocalClient ? new LocalClient({ customContentApiUrl: apiUrl, schema }) : new Client({
539
+ clientId: clientId || "",
540
+ branch: branch || "main",
541
+ tokenStorage: "LOCAL_STORAGE",
542
+ tinaioConfig,
543
+ schema
544
+ });
545
+ };
546
+ function assertShape(value, yupSchema, errorMessage) {
547
+ const shape = yupSchema(yup);
548
+ try {
549
+ shape.validateSync(value);
550
+ } catch (e) {
551
+ const message = errorMessage || `Failed to assertShape - ${e.message}`;
552
+ throw new Error(message);
553
+ }
554
+ }
555
+ function safeAssertShape(value, yupSchema) {
556
+ try {
557
+ assertShape(value, yupSchema);
558
+ return true;
559
+ } catch (e) {
560
+ return false;
561
+ }
562
+ }
2619
563
  class TinaAdminApi {
2620
564
  constructor(cms) {
2621
565
  this.api = cms.api.tina;
@@ -3370,6 +1314,15 @@ var styles = `.tina-tailwind {
3370
1314
  margin-left: auto;
3371
1315
  margin-right: auto;
3372
1316
  }
1317
+ .tina-tailwind .mb-6 {
1318
+ margin-bottom: 24px;
1319
+ }
1320
+ .tina-tailwind .mr-1 {
1321
+ margin-right: 4px;
1322
+ }
1323
+ .tina-tailwind .mb-8 {
1324
+ margin-bottom: 32px;
1325
+ }
3373
1326
  .tina-tailwind .-ml-px {
3374
1327
  margin-left: -1px;
3375
1328
  }
@@ -3403,18 +1356,12 @@ var styles = `.tina-tailwind {
3403
1356
  .tina-tailwind .mr-1\\.5 {
3404
1357
  margin-right: 6px;
3405
1358
  }
3406
- .tina-tailwind .mr-1 {
3407
- margin-right: 4px;
3408
- }
3409
1359
  .tina-tailwind .block {
3410
1360
  display: block;
3411
1361
  }
3412
1362
  .tina-tailwind .inline-block {
3413
1363
  display: inline-block;
3414
1364
  }
3415
- .tina-tailwind .inline {
3416
- display: inline;
3417
- }
3418
1365
  .tina-tailwind .flex {
3419
1366
  display: flex;
3420
1367
  }
@@ -3457,6 +1404,12 @@ var styles = `.tina-tailwind {
3457
1404
  .tina-tailwind .w-10 {
3458
1405
  width: 40px;
3459
1406
  }
1407
+ .tina-tailwind .w-12 {
1408
+ width: 48px;
1409
+ }
1410
+ .tina-tailwind .w-7 {
1411
+ width: 28px;
1412
+ }
3460
1413
  .tina-tailwind .w-auto {
3461
1414
  width: auto;
3462
1415
  }
@@ -3652,6 +1605,10 @@ var styles = `.tina-tailwind {
3652
1605
  --tw-bg-opacity: 1;
3653
1606
  background-color: rgb(255 255 255 / var(--tw-bg-opacity));
3654
1607
  }
1608
+ .tina-tailwind .bg-gray-100 {
1609
+ --tw-bg-opacity: 1;
1610
+ background-color: rgb(237 236 243 / var(--tw-bg-opacity));
1611
+ }
3655
1612
  .tina-tailwind .bg-gray-50 {
3656
1613
  --tw-bg-opacity: 1;
3657
1614
  background-color: rgb(246 246 249 / var(--tw-bg-opacity));
@@ -3694,6 +1651,9 @@ var styles = `.tina-tailwind {
3694
1651
  .tina-tailwind .to-black {
3695
1652
  --tw-gradient-to: #000;
3696
1653
  }
1654
+ .tina-tailwind .fill-current {
1655
+ fill: currentColor;
1656
+ }
3697
1657
  .tina-tailwind .px-4 {
3698
1658
  padding-left: 16px;
3699
1659
  padding-right: 16px;
@@ -3788,14 +1748,18 @@ var styles = `.tina-tailwind {
3788
1748
  font-size: 16px;
3789
1749
  line-height: 1.5;
3790
1750
  }
3791
- .tina-tailwind .text-sm {
3792
- font-size: 14px;
3793
- line-height: 1.43;
1751
+ .tina-tailwind .text-4xl {
1752
+ font-size: 36px;
1753
+ line-height: 1.1;
3794
1754
  }
3795
1755
  .tina-tailwind .text-xl {
3796
1756
  font-size: 20px;
3797
1757
  line-height: 1.4;
3798
1758
  }
1759
+ .tina-tailwind .text-sm {
1760
+ font-size: 14px;
1761
+ line-height: 1.43;
1762
+ }
3799
1763
  .tina-tailwind .text-md {
3800
1764
  font-size: 16px;
3801
1765
  line-height: 1.5;
@@ -3836,6 +1800,14 @@ var styles = `.tina-tailwind {
3836
1800
  --tw-text-opacity: 1;
3837
1801
  color: rgb(67 62 82 / var(--tw-text-opacity));
3838
1802
  }
1803
+ .tina-tailwind .text-red-500 {
1804
+ --tw-text-opacity: 1;
1805
+ color: rgb(239 68 68 / var(--tw-text-opacity));
1806
+ }
1807
+ .tina-tailwind .text-red-400 {
1808
+ --tw-text-opacity: 1;
1809
+ color: rgb(248 113 113 / var(--tw-text-opacity));
1810
+ }
3839
1811
  .tina-tailwind .text-blue-600 {
3840
1812
  --tw-text-opacity: 1;
3841
1813
  color: rgb(5 116 228 / var(--tw-text-opacity));
@@ -3871,13 +1843,12 @@ var styles = `.tina-tailwind {
3871
1843
  --tw-text-opacity: 1;
3872
1844
  color: rgb(37 35 54 / var(--tw-text-opacity));
3873
1845
  }
3874
- .tina-tailwind .text-red-500 {
3875
- --tw-text-opacity: 1;
3876
- color: rgb(239 68 68 / var(--tw-text-opacity));
3877
- }
3878
1846
  .tina-tailwind .underline {
3879
1847
  text-decoration-line: underline;
3880
1848
  }
1849
+ .tina-tailwind .opacity-70 {
1850
+ opacity: .7;
1851
+ }
3881
1852
  .tina-tailwind .opacity-100 {
3882
1853
  opacity: 1;
3883
1854
  }
@@ -3896,9 +1867,6 @@ var styles = `.tina-tailwind {
3896
1867
  .tina-tailwind .opacity-50 {
3897
1868
  opacity: .5;
3898
1869
  }
3899
- .tina-tailwind .opacity-70 {
3900
- opacity: .7;
3901
- }
3902
1870
  .tina-tailwind .shadow-lg {
3903
1871
  --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
3904
1872
  --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
@@ -4223,42 +2191,6 @@ const useDocumentCreatorPlugin = (args) => {
4223
2191
  };
4224
2192
  }, [plugin]);
4225
2193
  };
4226
- function useTina({
4227
- query,
4228
- variables,
4229
- data
4230
- }) {
4231
- React.useEffect(() => {
4232
- console.warn(`
4233
- "useTina" from 'tinacms/dist/edit-state' is now deprecated
4234
- * Use "import { useTina } from 'tinacms/dist/react" instead.
4235
- * See https://tina.io/blog/upgrading-to-iframe/ for full migration details
4236
- `);
4237
- }, []);
4238
- const {
4239
- setRequest,
4240
- state,
4241
- isDummyContainer,
4242
- isLoading: contextLoading
4243
- } = React.useContext(TinaDataContext);
4244
- const [waitForContextRerender, setWaitForContextRerender] = useState(!isDummyContainer);
4245
- const isLoading = contextLoading || waitForContextRerender;
4246
- React.useEffect(() => {
4247
- setRequest({ query, variables });
4248
- }, [JSON.stringify(variables), query]);
4249
- useEffect(() => {
4250
- if (!isDummyContainer) {
4251
- setTimeout(() => setWaitForContextRerender(false), 0);
4252
- }
4253
- return () => {
4254
- setRequest(void 0);
4255
- };
4256
- }, [isDummyContainer]);
4257
- return {
4258
- data: isDummyContainer || isLoading ? data : state.payload,
4259
- isLoading
4260
- };
4261
- }
4262
2194
  const errorButtonStyles = {
4263
2195
  background: "#eb6337",
4264
2196
  padding: "12px 18px",
@@ -4346,12 +2278,6 @@ const TinaCMSProvider2 = ({
4346
2278
  ...props
4347
2279
  }) => {
4348
2280
  var _a, _b, _c, _d, _e;
4349
- React.useEffect(() => {
4350
- console.warn(`
4351
- * Tina no longer requires wrapping your site in the TinaProvider
4352
- * See https://tina.io/blog/upgrading-to-iframe/ for full migration details
4353
- `);
4354
- }, []);
4355
2281
  if (props == null ? void 0 : props.apiURL) {
4356
2282
  console.warn("The apiURL prop is deprecated. Please see https://tina.io/blog/tina-v-0.68.14 for information on how to upgrade to the new API");
4357
2283
  }
@@ -4377,84 +2303,7 @@ const TinaCMSProvider2 = ({
4377
2303
  mediaStore: props.mediaStore,
4378
2304
  apiUrl: apiURL,
4379
2305
  schema: { ...schema, config: { ...schema.config, ...props } }
4380
- }, /* @__PURE__ */ React.createElement("style", null, styles), /* @__PURE__ */ React.createElement(ErrorBoundary, null, /* @__PURE__ */ React.createElement(DocumentCreator, {
4381
- documentCreatorCallback
4382
- }), /* @__PURE__ */ React.createElement(TinaDataProvider, {
4383
- formifyCallback
4384
- }, typeof props.children == "function" ? /* @__PURE__ */ React.createElement(TinaQuery, {
4385
- ...props,
4386
- variables: props.variables,
4387
- data: props.data,
4388
- query,
4389
- formifyCallback,
4390
- children: props.children
4391
- }) : props.children))));
4392
- };
4393
- const DocumentCreator = ({
4394
- documentCreatorCallback
4395
- }) => {
4396
- useDocumentCreatorPlugin(documentCreatorCallback);
4397
- return null;
4398
- };
4399
- const TinaQuery = (props) => {
4400
- return /* @__PURE__ */ React.createElement(TinaQueryInner, {
4401
- key: `rootQuery-${props.query}`,
4402
- ...props
4403
- });
4404
- };
4405
- const TinaQueryInner = ({ children, ...props }) => {
4406
- const { data: liveData, isLoading } = useTina({
4407
- query: props.query,
4408
- variables: props.variables,
4409
- data: props.data
4410
- });
4411
- return /* @__PURE__ */ React.createElement(React.Fragment, null, children(isLoading || !props.query ? props : { ...props, data: liveData }));
4412
- };
4413
- const TinaDataProvider = ({
4414
- children,
4415
- formifyCallback
4416
- }) => {
4417
- const [request, setRequest] = useState();
4418
- const [state, setState] = React.useState({
4419
- payload: void 0,
4420
- isLoading: true
4421
- });
4422
- return /* @__PURE__ */ React.createElement(TinaDataContext.Provider, {
4423
- value: {
4424
- setRequest,
4425
- isLoading: state.isLoading,
4426
- state: { payload: state.payload }
4427
- }
4428
- }, /* @__PURE__ */ React.createElement(FormRegistrar, {
4429
- key: request == null ? void 0 : request.query,
4430
- request,
4431
- formifyCallback,
4432
- onPayloadStateChange: setState
4433
- }), children);
4434
- };
4435
- const FormRegistrar = ({
4436
- request,
4437
- formifyCallback,
4438
- onPayloadStateChange
4439
- }) => {
4440
- const cms = useCMS();
4441
- const { setFormsRegistering } = React.useContext(EditContext);
4442
- const [payload, isLoading] = useGraphqlForms({
4443
- query: request == null ? void 0 : request.query,
4444
- variables: request == null ? void 0 : request.variables,
4445
- formify: (args) => {
4446
- if (formifyCallback) {
4447
- return formifyCallback(args, cms);
4448
- } else {
4449
- return args.createForm(args.formConfig);
4450
- }
4451
- }
4452
- });
4453
- React.useEffect(() => {
4454
- onPayloadStateChange({ payload, isLoading });
4455
- setFormsRegistering && setFormsRegistering(isLoading);
4456
- }, [JSON.stringify(payload), isLoading]);
4457
- return isLoading ? /* @__PURE__ */ React.createElement(Loader, null, /* @__PURE__ */ React.createElement(React.Fragment, null)) : null;
2306
+ }, /* @__PURE__ */ React.createElement("style", null, styles), /* @__PURE__ */ React.createElement(ErrorBoundary, null, props.children)));
4458
2307
  };
4459
2308
  const Loader = (props) => {
4460
2309
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
@@ -4648,10 +2497,10 @@ var __rest = globalThis && globalThis.__rest || function(s, e) {
4648
2497
  return t;
4649
2498
  };
4650
2499
  function Tree2Element(tree) {
4651
- return tree && tree.map(function(node2, i) {
4652
- return React.createElement(node2.tag, __assign({
2500
+ return tree && tree.map(function(node, i) {
2501
+ return React.createElement(node.tag, __assign({
4653
2502
  key: i
4654
- }, node2.attr), Tree2Element(node2.child));
2503
+ }, node.attr), Tree2Element(node.child));
4655
2504
  });
4656
2505
  }
4657
2506
  function GenIcon(data) {
@@ -4701,6 +2550,9 @@ function IoMdClose(props) {
4701
2550
  function BiEdit(props) {
4702
2551
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "m7 17.013 4.413-.015 9.632-9.54c.378-.378.586-.88.586-1.414s-.208-1.036-.586-1.414l-1.586-1.586c-.756-.756-2.075-.752-2.825-.003L7 12.583v4.43zM18.045 4.458l1.589 1.583-1.597 1.582-1.586-1.585 1.594-1.58zM9 13.417l6.03-5.973 1.586 1.586-6.029 5.971L9 15.006v-1.589z" } }, { "tag": "path", "attr": { "d": "M5 21h14c1.103 0 2-.897 2-2v-8.668l-2 2V19H8.158c-.026 0-.053.01-.079.01-.033 0-.066-.009-.1-.01H5V5h6.847l2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2z" } }] })(props);
4703
2552
  }
2553
+ function BiError(props) {
2554
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M11.001 10h2v5h-2zM11 16h2v2h-2z" } }, { "tag": "path", "attr": { "d": "M13.768 4.2C13.42 3.545 12.742 3.138 12 3.138s-1.42.407-1.768 1.063L2.894 18.064a1.986 1.986 0 0 0 .054 1.968A1.984 1.984 0 0 0 4.661 21h14.678c.708 0 1.349-.362 1.714-.968a1.989 1.989 0 0 0 .054-1.968L13.768 4.2zM4.661 19 12 5.137 19.344 19H4.661z" } }] })(props);
2555
+ }
4704
2556
  function BiLogIn(props) {
4705
2557
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "m13 16 5-4-5-4v3H4v2h9z" } }, { "tag": "path", "attr": { "d": "M20 3h-9c-1.103 0-2 .897-2 2v4h2V5h9v14h-9v-4H9v4c0 1.103.897 2 2 2h9c1.103 0 2-.897 2-2V5c0-1.103-.897-2-2-2z" } }] })(props);
4706
2558
  }
@@ -4719,6 +2571,9 @@ function BiRename(props) {
4719
2571
  function BiSearch(props) {
4720
2572
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M10 18a7.952 7.952 0 0 0 4.897-1.688l4.396 4.396 1.414-1.414-4.396-4.396A7.952 7.952 0 0 0 18 10c0-4.411-3.589-8-8-8s-8 3.589-8 8 3.589 8 8 8zm0-14c3.309 0 6 2.691 6 6s-2.691 6-6 6-6-2.691-6-6 2.691-6 6-6z" } }] })(props);
4721
2573
  }
2574
+ function BiSync(props) {
2575
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "m13 7.101.01.001a4.978 4.978 0 0 1 2.526 1.362 5.005 5.005 0 0 1 1.363 2.528 5.061 5.061 0 0 1-.001 2.016 4.976 4.976 0 0 1-1.363 2.527l1.414 1.414a7.014 7.014 0 0 0 1.908-3.54 6.98 6.98 0 0 0 0-2.819 6.957 6.957 0 0 0-1.907-3.539 6.97 6.97 0 0 0-2.223-1.5 6.921 6.921 0 0 0-1.315-.408c-.137-.028-.275-.043-.412-.063V2L9 6l4 4V7.101zm-7.45 7.623c.174.412.392.812.646 1.19.249.37.537.718.854 1.034a7.036 7.036 0 0 0 2.224 1.501c.425.18.868.317 1.315.408.167.034.338.056.508.078v2.944l4-4-4-4v3.03c-.035-.006-.072-.003-.107-.011a4.978 4.978 0 0 1-2.526-1.362 4.994 4.994 0 0 1 .001-7.071L7.051 7.05a7.01 7.01 0 0 0-1.5 2.224A6.974 6.974 0 0 0 5 12a6.997 6.997 0 0 0 .55 2.724z" } }] })(props);
2576
+ }
4722
2577
  function BiTrash(props) {
4723
2578
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M5 20a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8h2V6h-4V4a2 2 0 0 0-2-2H9a2 2 0 0 0-2 2v2H3v2h2zM9 4h6v2H9zM8 8h9v12H7V8z" } }, { "tag": "path", "attr": { "d": "M9 10h2v8H9zm4 0h2v8h-2z" } }] })(props);
4724
2579
  }
@@ -5130,6 +2985,25 @@ const LoadingPage = () => /* @__PURE__ */ React.createElement(React.Fragment, nu
5130
2985
  fontWeight: "normal"
5131
2986
  }
5132
2987
  }, "Please wait, Tina is loading data..."))));
2988
+ const FullscreenError = ({
2989
+ title = "Error",
2990
+ errorMessage = "It looks like something went wrong."
2991
+ }) => {
2992
+ return /* @__PURE__ */ React.createElement("div", {
2993
+ className: "flex flex-col justify-center items-center h-screen bg-gray-100"
2994
+ }, /* @__PURE__ */ React.createElement("div", {
2995
+ className: "text-red-500 text-4xl mb-6 flex items-center"
2996
+ }, /* @__PURE__ */ React.createElement(BiError, {
2997
+ className: "w-12 h-auto fill-current text-red-400 opacity-70 mr-1"
2998
+ }), " ", title), /* @__PURE__ */ React.createElement("p", {
2999
+ className: "text-gray-700 text-xl mb-8"
3000
+ }, errorMessage), /* @__PURE__ */ React.createElement(Button, {
3001
+ variant: "danger",
3002
+ onClick: () => window.location.reload()
3003
+ }, /* @__PURE__ */ React.createElement(BiSync, {
3004
+ className: "w-7 h-auto fill-current opacity-70 mr-1"
3005
+ }), " Reload"));
3006
+ };
5133
3007
  const useGetCollection = (cms, collectionName, includeDocuments = true, after = "", sortKey, filterArgs) => {
5134
3008
  const api = new TinaAdminApi(cms);
5135
3009
  const schema = cms.api.tina.schema;
@@ -5173,7 +3047,7 @@ const GetCollection = ({
5173
3047
  }) => {
5174
3048
  const { collection, loading, error, reFetchCollection, collectionExtra } = useGetCollection(cms, collectionName, includeDocuments, startCursor || "", sortKey, filterArgs) || {};
5175
3049
  if (error) {
5176
- return null;
3050
+ return /* @__PURE__ */ React.createElement(FullscreenError, null);
5177
3051
  }
5178
3052
  if (loading) {
5179
3053
  return /* @__PURE__ */ React.createElement(LoadingPage, null);
@@ -5275,7 +3149,7 @@ const CollectionListPage = () => {
5275
3149
  }));
5276
3150
  }, [collectionName]);
5277
3151
  return /* @__PURE__ */ React.createElement(GetCMS, null, (cms) => {
5278
- return /* @__PURE__ */ React.createElement(GetCollection, {
3152
+ return /* @__PURE__ */ React.createElement(PageWrapper, null, /* @__PURE__ */ React.createElement(GetCollection, {
5279
3153
  cms,
5280
3154
  collectionName,
5281
3155
  includeDocuments: true,
@@ -5309,7 +3183,7 @@ const CollectionListPage = () => {
5309
3183
  const collectionDefinition = cms.api.tina.schema.getCollection(collection.name);
5310
3184
  const allowCreate = (_e = (_d = (_c = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _c.allowedActions) == null ? void 0 : _d.create) != null ? _e : true;
5311
3185
  const allowDelete = (_h = (_g = (_f = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _f.allowedActions) == null ? void 0 : _g.delete) != null ? _h : true;
5312
- return /* @__PURE__ */ React.createElement(PageWrapper, null, /* @__PURE__ */ React.createElement(React.Fragment, null, deleteModalOpen && /* @__PURE__ */ React.createElement(DeleteModal, {
3186
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, deleteModalOpen && /* @__PURE__ */ React.createElement(DeleteModal, {
5313
3187
  filename: vars.relativePath,
5314
3188
  deleteFunc: async () => {
5315
3189
  try {
@@ -5418,7 +3292,7 @@ const CollectionListPage = () => {
5418
3292
  value: ""
5419
3293
  },
5420
3294
  ...filterFields.map((x) => ({
5421
- label: x.label || x.name,
3295
+ label: typeof x.label === "string" && x.label || x.name,
5422
3296
  value: x.name
5423
3297
  }))
5424
3298
  ],
@@ -5673,8 +3547,8 @@ const CollectionListPage = () => {
5673
3547
  setEndCursor(prev);
5674
3548
  }
5675
3549
  }
5676
- }))))));
5677
- });
3550
+ })))));
3551
+ }));
5678
3552
  });
5679
3553
  };
5680
3554
  const NoDocumentsPlaceholder = () => {
@@ -5733,6 +3607,42 @@ const RenameModal = ({
5733
3607
  function HiChevronRight(props) {
5734
3608
  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);
5735
3609
  }
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
+ };
5736
3646
  function FaLock(props) {
5737
3647
  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);
5738
3648
  }
@@ -5814,7 +3724,7 @@ const RenderForm$1 = ({ cms, collection, templateName, mutationInfo }) => {
5814
3724
  schema,
5815
3725
  template
5816
3726
  });
5817
- let slugFunction = (_b = (_a = template == null ? void 0 : template.ui) == null ? void 0 : _a.filename) == null ? void 0 : _b.slugify;
3727
+ let slugFunction = (_b = (_a = schemaCollection.ui) == null ? void 0 : _a.filename) == null ? void 0 : _b.slugify;
5818
3728
  if (!slugFunction) {
5819
3729
  const titleField = (_c = template == null ? void 0 : template.fields.find((x) => x.required && x.type === "string" && x.isTitle)) == null ? void 0 : _c.name;
5820
3730
  if (titleField) {
@@ -5847,11 +3757,11 @@ const RenderForm$1 = ({ cms, collection, templateName, mutationInfo }) => {
5847
3757
  component: slugFunction ? wrapFieldsWithMeta(({ field, input, meta }) => {
5848
3758
  var _a3, _b3;
5849
3759
  return /* @__PURE__ */ React.createElement(FilenameInput, {
5850
- readonly: (_b3 = (_a3 = template == null ? void 0 : template.ui) == null ? void 0 : _a3.filename) == null ? void 0 : _b3.readonly,
3760
+ readonly: (_b3 = (_a3 = schemaCollection == null ? void 0 : schemaCollection.ui) == null ? void 0 : _a3.filename) == null ? void 0 : _b3.readonly,
5851
3761
  ...input
5852
3762
  });
5853
3763
  }) : "text",
5854
- disabled: (_b2 = (_a2 = template == null ? void 0 : template.ui) == null ? void 0 : _a2.filename) == null ? void 0 : _b2.readonly,
3764
+ disabled: (_b2 = (_a2 = schemaCollection == null ? void 0 : schemaCollection.ui) == null ? void 0 : _a2.filename) == null ? void 0 : _b2.readonly,
5855
3765
  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")),
5856
3766
  placeholder: `My_Document`,
5857
3767
  validate: (value, allValues, meta) => {
@@ -5945,7 +3855,7 @@ const GetDocument = ({
5945
3855
  }) => {
5946
3856
  const { document, loading, error } = useGetDocument(cms, collectionName, relativePath);
5947
3857
  if (error) {
5948
- return null;
3858
+ return /* @__PURE__ */ React.createElement(FullscreenError, null);
5949
3859
  }
5950
3860
  if (loading) {
5951
3861
  return /* @__PURE__ */ React.createElement(LoadingPage, null);
@@ -5981,7 +3891,7 @@ const CollectionUpdatePage = () => {
5981
3891
  includeCollection: true,
5982
3892
  includeTemplate: !!collection.templates
5983
3893
  };
5984
- return /* @__PURE__ */ React.createElement(GetDocument, {
3894
+ return /* @__PURE__ */ React.createElement(PageWrapper, null, /* @__PURE__ */ React.createElement(GetDocument, {
5985
3895
  cms,
5986
3896
  collectionName: collection.name,
5987
3897
  relativePath
@@ -5992,7 +3902,7 @@ const CollectionUpdatePage = () => {
5992
3902
  relativePath,
5993
3903
  collection,
5994
3904
  mutationInfo
5995
- }));
3905
+ })));
5996
3906
  }));
5997
3907
  };
5998
3908
  const RenderForm = ({
@@ -6038,7 +3948,7 @@ const RenderForm = ({
6038
3948
  const windowWidth = useWindowWidth();
6039
3949
  const renderNavToggle = windowWidth < navBreakpoint + 1;
6040
3950
  const headerPadding = renderNavToggle ? "px-20" : "px-6";
6041
- return /* @__PURE__ */ React.createElement(PageWrapper, null, /* @__PURE__ */ React.createElement(React.Fragment, null, ((_b = (_a = cms == null ? void 0 : cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.isLocalMode) ? /* @__PURE__ */ React.createElement(LocalWarning, null) : /* @__PURE__ */ React.createElement(BillingWarning, null), /* @__PURE__ */ React.createElement("div", {
3951
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, ((_b = (_a = cms == null ? void 0 : cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.isLocalMode) ? /* @__PURE__ */ React.createElement(LocalWarning, null) : /* @__PURE__ */ React.createElement(BillingWarning, null), /* @__PURE__ */ React.createElement("div", {
6042
3952
  className: `py-4 border-b border-gray-200 bg-white ${headerPadding}`
6043
3953
  }, /* @__PURE__ */ React.createElement("div", {
6044
3954
  className: "max-w-form mx-auto"
@@ -6058,7 +3968,7 @@ const RenderForm = ({
6058
3968
  }))), /* @__PURE__ */ React.createElement(FormBuilder, {
6059
3969
  form,
6060
3970
  onPristineChange: setFormIsPristine
6061
- })));
3971
+ }));
6062
3972
  };
6063
3973
  const ScreenPage = () => {
6064
3974
  const { screenName } = useParams();
@@ -6287,4 +4197,4 @@ const defineStaticConfig = (config) => {
6287
4197
  return config;
6288
4198
  };
6289
4199
  const defineConfig = defineStaticConfig;
6290
- export { AuthWallInner, Client, DEFAULT_LOCAL_TINA_GQL_SERVER_URL, LocalClient, RouteMappingPlugin, TinaAdmin, TinaAdminApi, TinaCMSProvider2, TinaCloudAuthWall, TinaCloudProvider, TinaDataProvider, assertShape, asyncPoll, createClient, TinaCMSProvider2 as default, defineConfig, defineLegacyConfig, defineSchema, defineStaticConfig, getStaticPropsForTina, gql, safeAssertShape, staticRequest, useDocumentCreatorPlugin, useGraphqlForms, useTinaAuthRedirect };
4200
+ export { AuthWallInner, Client, DEFAULT_LOCAL_TINA_GQL_SERVER_URL, LocalClient, RouteMappingPlugin, TinaAdmin, TinaAdminApi, TinaCMSProvider2, TinaCloudAuthWall, TinaCloudProvider, assertShape, asyncPoll, createClient, TinaCMSProvider2 as default, defineConfig, defineLegacyConfig, defineSchema, defineStaticConfig, getStaticPropsForTina, gql, safeAssertShape, staticRequest, useDocumentCreatorPlugin, useTinaAuthRedirect };