@tinacms/app 0.0.0-00f6525-20241015065741
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +984 -0
- package/LICENSE +176 -0
- package/index.html +69 -0
- package/package.json +28 -0
- package/src/App.tsx +79 -0
- package/src/Playground.tsx +163 -0
- package/src/dummy-client.ts +1 -0
- package/src/fields/rich-text/index.tsx +6 -0
- package/src/fields/rich-text/monaco/error-message.tsx +118 -0
- package/src/fields/rich-text/monaco/index.tsx +236 -0
- package/src/fields/rich-text/monaco/use-debounce.ts +25 -0
- package/src/global.css +120 -0
- package/src/index.css +384 -0
- package/src/lib/build-form.ts +49 -0
- package/src/lib/errors.tsx +24 -0
- package/src/lib/expand-query.ts +268 -0
- package/src/lib/graphql-reducer.ts +987 -0
- package/src/lib/types.ts +51 -0
- package/src/lib/util.ts +134 -0
- package/src/main.tsx +12 -0
- package/src/preflight.css +233 -0
- package/src/preview.tsx +27 -0
- package/src/vite-env.d.ts +8 -0
- package/tsconfig.json +32 -0
- package/tsconfig.node.json +10 -0
package/src/index.css
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
@import 'global.css';
|
|
2
|
+
@import 'preflight.css';
|
|
3
|
+
@tailwind base;
|
|
4
|
+
@tailwind components;
|
|
5
|
+
@tailwind utilities;
|
|
6
|
+
|
|
7
|
+
/* Tailwind reset clobbers some playground styles */
|
|
8
|
+
.graphiql-execute-button {
|
|
9
|
+
@apply bg-blue-600 !important;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.icon-parent svg {
|
|
13
|
+
fill: currentColor;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
body {
|
|
17
|
+
margin: 0;
|
|
18
|
+
padding: 0;
|
|
19
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
|
20
|
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
|
21
|
+
sans-serif;
|
|
22
|
+
-webkit-font-smoothing: antialiased;
|
|
23
|
+
-moz-osx-font-smoothing: grayscale;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
code {
|
|
27
|
+
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
|
28
|
+
monospace;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
div.graphiql-explorer-root > div:last-child {
|
|
32
|
+
display: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.graphiql-container {
|
|
36
|
+
height: 100vh !important;
|
|
37
|
+
width: 100vw !important;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* if the last block has margin-bottom it makes the text box larger but some of it isn't clickable */
|
|
41
|
+
.tina-prose [data-slate-editor='true'] {
|
|
42
|
+
padding-bottom: 0.5em;
|
|
43
|
+
/* Outline is placed on the parent element for styling consistency with other elements */
|
|
44
|
+
outline: none;
|
|
45
|
+
}
|
|
46
|
+
/* prose adds backticks, which look like they should be editable */
|
|
47
|
+
.tina-prose [data-slate-editor='true'] .slate-code::before {
|
|
48
|
+
content: '';
|
|
49
|
+
}
|
|
50
|
+
.tina-prose [data-slate-editor='true'] .slate-code::after {
|
|
51
|
+
content: '';
|
|
52
|
+
}
|
|
53
|
+
.tina-prose [data-slate-editor='true'] .slate-code_block {
|
|
54
|
+
margin: 0;
|
|
55
|
+
}
|
|
56
|
+
/* code lines as part of a block don't need the same background formatting */
|
|
57
|
+
.tina-prose [data-slate-editor='true'] .slate-code_block .slate-code {
|
|
58
|
+
background: none;
|
|
59
|
+
}
|
|
60
|
+
/* prose makes the first p in a block slightly larger */
|
|
61
|
+
.tina-prose [data-slate-editor='true'] p:first-of-type {
|
|
62
|
+
font-size: 1em;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* experimental floating toolbar doesn't need a large text area */
|
|
66
|
+
.with-toolbar [data-slate-editor='true'] {
|
|
67
|
+
min-height: 72px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@keyframes color-popup-keyframes {
|
|
71
|
+
0% {
|
|
72
|
+
transform: translate3d(-50%, 0, 0) scale3d(0.5, 0.5, 1);
|
|
73
|
+
}
|
|
74
|
+
100% {
|
|
75
|
+
transform: translate3d(-50%, 8px, 0) scale3d(1, 1, 1);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@keyframes color-popup-open-top-keyframes {
|
|
80
|
+
0% {
|
|
81
|
+
transform: translate3d(-50%, -100%, 0) scale3d(0.5, 0.5, 1);
|
|
82
|
+
}
|
|
83
|
+
100% {
|
|
84
|
+
transform: translate3d(-50%, calc(-100% - 8px), 0) scale3d(1, 1, 1);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@keyframes loading-dots-scale-up-and-down {
|
|
89
|
+
0% {
|
|
90
|
+
transform: scale(0.1);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
50% {
|
|
94
|
+
transform: scale(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
90% {
|
|
98
|
+
transform: scale(0.1);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
100% {
|
|
102
|
+
transform: scale(0.1);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.color-picker-clip-path::before,
|
|
107
|
+
.color-picker-clip-path::after {
|
|
108
|
+
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.color-picker-on-top-clip-path::before,
|
|
112
|
+
.color-picker-on-top-clip-path::after {
|
|
113
|
+
clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.tina-date-field .rdt {
|
|
117
|
+
position: relative;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.tina-date-field .rdtPicker {
|
|
121
|
+
display: none;
|
|
122
|
+
position: absolute;
|
|
123
|
+
width: 100%;
|
|
124
|
+
max-width: 350px;
|
|
125
|
+
padding: 4px;
|
|
126
|
+
margin-top: 4px;
|
|
127
|
+
z-index: 99999 !important;
|
|
128
|
+
background: var(--tina-color-grey-0);
|
|
129
|
+
border-radius: var(--tina-radius-small);
|
|
130
|
+
box-shadow: var(--tina-shadow-big);
|
|
131
|
+
border: 1px solid var(--tina-color-grey-2);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.tina-date-field .rdtOpen .rdtPicker {
|
|
135
|
+
display: block;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.tina-date-field .rdtStatic .rdtPicker {
|
|
139
|
+
box-shadow: none;
|
|
140
|
+
position: static;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.tina-date-field .rdtPicker .rdtTimeToggle {
|
|
144
|
+
text-align: center;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.tina-date-field .rdtPicker table {
|
|
148
|
+
width: 100%;
|
|
149
|
+
margin: 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.tina-date-field .rdtPicker td,
|
|
153
|
+
.rdtPicker th {
|
|
154
|
+
text-align: center;
|
|
155
|
+
height: 28px;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.tina-date-field .rdtPicker td {
|
|
159
|
+
cursor: pointer;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.tina-date-field .rdtPicker td.rdtDay:hover,
|
|
163
|
+
.tina-date-field .rdtPicker td.rdtHour:hover,
|
|
164
|
+
.tina-date-field .rdtPicker td.rdtMinute:hover,
|
|
165
|
+
.tina-date-field .rdtPicker td.rdtSecond:hover,
|
|
166
|
+
.tina-date-field .rdtPicker .rdtTimeToggle:hover {
|
|
167
|
+
background: var(--tina-color-grey-2);
|
|
168
|
+
color: var(--tina-color-primary);
|
|
169
|
+
border-radius: var(--tina-radius-small);
|
|
170
|
+
cursor: pointer;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.tina-date-field .rdtPicker td.rdtDay:hover:active,
|
|
174
|
+
.tina-date-field .rdtPicker td.rdtHour:hover:active,
|
|
175
|
+
.tina-date-field .rdtPicker td.rdtMinute:hover:active,
|
|
176
|
+
.tina-date-field .rdtPicker td.rdtSecond:hover:active,
|
|
177
|
+
.tina-date-field .rdtPicker .rdtTimeToggle:hover:active {
|
|
178
|
+
background: var(--tina-color-primary);
|
|
179
|
+
color: var(--tina-color-grey-0);
|
|
180
|
+
border-radius: var(--tina-radius-small);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.tina-date-field .rdtPicker td.rdtOld,
|
|
184
|
+
.rdtPicker td.rdtNew {
|
|
185
|
+
color: var(--tina-color-grey-6);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.tina-date-field .rdtPicker td.rdtToday {
|
|
189
|
+
position: relative;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.tina-date-field .rdtPicker td.rdtToday:before {
|
|
193
|
+
content: '';
|
|
194
|
+
display: inline-block;
|
|
195
|
+
border-left: 7px solid transparent;
|
|
196
|
+
border-bottom: 7px solid var(--tina-color-primary);
|
|
197
|
+
border-radius: 20px;
|
|
198
|
+
border-top-color: rgba(0, 0, 0, 0.2);
|
|
199
|
+
position: absolute;
|
|
200
|
+
bottom: 4px;
|
|
201
|
+
right: 4px;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.tina-date-field .rdtPicker td.rdtActive,
|
|
205
|
+
.rdtPicker td.rdtActive:hover {
|
|
206
|
+
background-color: var(--tina-color-primary);
|
|
207
|
+
color: var(--tina-color-grey-0);
|
|
208
|
+
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.tina-date-field .rdtPicker td.rdtActive.rdtToday:before {
|
|
212
|
+
border-bottom-color: var(--tina-color-grey-0);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.tina-date-field .rdtPicker td.rdtDisabled,
|
|
216
|
+
.rdtPicker td.rdtDisabled:hover {
|
|
217
|
+
background: none;
|
|
218
|
+
color: var(--tina-color-grey-6);
|
|
219
|
+
cursor: not-allowed;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.tina-date-field .rdtPicker td span.rdtOld {
|
|
223
|
+
color: var(--tina-color-grey-6);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.tina-date-field .rdtPicker td span.rdtDisabled,
|
|
227
|
+
.rdtPicker td span.rdtDisabled:hover {
|
|
228
|
+
background: none;
|
|
229
|
+
color: var(--tina-color-grey-6);
|
|
230
|
+
cursor: not-allowed;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.tina-date-field .rdtPicker th {
|
|
234
|
+
border-bottom: 1px solid var(--tina-color-grey-1);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.tina-date-field .rdtPicker .dow {
|
|
238
|
+
width: 14.2857%;
|
|
239
|
+
border-bottom: none;
|
|
240
|
+
cursor: default;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.tina-date-field .rdtPicker th.rdtSwitch {
|
|
244
|
+
width: 100px;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.tina-date-field .rdtPicker th.rdtNext,
|
|
248
|
+
.rdtPicker th.rdtPrev {
|
|
249
|
+
font-size: 21px;
|
|
250
|
+
vertical-align: top;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.tina-date-field .rdtPrev span,
|
|
254
|
+
.rdtNext span {
|
|
255
|
+
display: block;
|
|
256
|
+
-webkit-touch-callout: none;
|
|
257
|
+
/* iOS Safari */
|
|
258
|
+
-webkit-user-select: none;
|
|
259
|
+
/* Chrome/Safari/Opera */
|
|
260
|
+
-khtml-user-select: none;
|
|
261
|
+
/* Konqueror */
|
|
262
|
+
-moz-user-select: none;
|
|
263
|
+
/* Firefox */
|
|
264
|
+
-ms-user-select: none;
|
|
265
|
+
/* Internet Explorer/Edge */
|
|
266
|
+
user-select: none;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.tina-date-field .rdtPicker th.rdtDisabled,
|
|
270
|
+
.rdtPicker th.rdtDisabled:hover {
|
|
271
|
+
background: none;
|
|
272
|
+
color: var(--tina-color-grey-6);
|
|
273
|
+
cursor: not-allowed;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.tina-date-field .rdtPicker thead tr:first-child th {
|
|
277
|
+
cursor: pointer;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.tina-date-field .rdtPicker thead tr:first-child th:hover {
|
|
281
|
+
background: var(--tina-color-grey-2);
|
|
282
|
+
color: var(--tina-color-primary);
|
|
283
|
+
border-radius: var(--tina-radius-small);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.tina-date-field .rdtPicker tfoot {
|
|
287
|
+
border-top: 1px solid var(--tina-color-grey-1);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.tina-date-field .rdtPicker button {
|
|
291
|
+
border: none;
|
|
292
|
+
background: none;
|
|
293
|
+
cursor: pointer;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.tina-date-field .rdtPicker button:hover {
|
|
297
|
+
background: var(--tina-color-grey-2);
|
|
298
|
+
color: var(--tina-color-primary);
|
|
299
|
+
border-radius: var(--tina-radius-small);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.tina-date-field .rdtPicker thead button {
|
|
303
|
+
width: 100%;
|
|
304
|
+
height: 100%;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.tina-date-field td.rdtMonth,
|
|
308
|
+
td.rdtYear {
|
|
309
|
+
height: 50px;
|
|
310
|
+
width: 25%;
|
|
311
|
+
cursor: pointer;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.tina-date-field td.rdtMonth:hover,
|
|
315
|
+
td.rdtYear:hover {
|
|
316
|
+
background: var(--tina-color-grey-2);
|
|
317
|
+
color: var(--tina-color-primary);
|
|
318
|
+
border-radius: var(--tina-radius-small);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.tina-date-field .rdtCounters {
|
|
322
|
+
display: inline-block;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.tina-date-field .rdtCounters > div {
|
|
326
|
+
float: left;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.tina-date-field .rdtCounter {
|
|
330
|
+
height: 100px;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.tina-date-field .rdtCounter {
|
|
334
|
+
width: 40px;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.tina-date-field .rdtCounterSeparator {
|
|
338
|
+
line-height: 100px;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.tina-date-field .rdtCounter .rdtBtn {
|
|
342
|
+
height: 40%;
|
|
343
|
+
line-height: 40px;
|
|
344
|
+
cursor: pointer;
|
|
345
|
+
display: block;
|
|
346
|
+
-webkit-touch-callout: none;
|
|
347
|
+
/* iOS Safari */
|
|
348
|
+
-webkit-user-select: none;
|
|
349
|
+
/* Chrome/Safari/Opera */
|
|
350
|
+
-khtml-user-select: none;
|
|
351
|
+
/* Konqueror */
|
|
352
|
+
-moz-user-select: none;
|
|
353
|
+
/* Firefox */
|
|
354
|
+
-ms-user-select: none;
|
|
355
|
+
/* Internet Explorer/Edge */
|
|
356
|
+
user-select: none;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.tina-date-field .rdtCounter .rdtBtn:hover {
|
|
360
|
+
background: var(--tina-color-grey-2);
|
|
361
|
+
color: var(--tina-color-primary);
|
|
362
|
+
border-radius: var(--tina-radius-small);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.tina-date-field .rdtCounter .rdtCount {
|
|
366
|
+
height: 20%;
|
|
367
|
+
font-size: 1.2em;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.tina-date-field .rdtMilli {
|
|
371
|
+
vertical-align: middle;
|
|
372
|
+
padding-left: 8px;
|
|
373
|
+
width: 48px;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.tina-date-field .rdtMilli input {
|
|
377
|
+
width: 100%;
|
|
378
|
+
font-size: 1.2em;
|
|
379
|
+
margin-top: 37px;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.tina-date-field .rdtTime td {
|
|
383
|
+
cursor: default;
|
|
384
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Field, Form, FormOptions, TinaCMS, TinaField } from 'tinacms'
|
|
2
|
+
|
|
3
|
+
export type FieldType = Field & TinaField
|
|
4
|
+
export type FormValues = Record<string, unknown>
|
|
5
|
+
export type FormType = Form<FormValues, FieldType>
|
|
6
|
+
|
|
7
|
+
type FormCreator = (formConfig: FormOptions<any>) => Form
|
|
8
|
+
interface GlobalFormOptions {
|
|
9
|
+
icon?: any
|
|
10
|
+
layout: 'fullscreen' | 'popup'
|
|
11
|
+
}
|
|
12
|
+
type GlobalFormCreator = (
|
|
13
|
+
formConfig: FormOptions<any>,
|
|
14
|
+
options?: GlobalFormOptions
|
|
15
|
+
) => Form
|
|
16
|
+
interface GlobalFormOptions {
|
|
17
|
+
icon?: any
|
|
18
|
+
layout: 'fullscreen' | 'popup'
|
|
19
|
+
}
|
|
20
|
+
export interface FormifyArgs {
|
|
21
|
+
formConfig: FormOptions<any>
|
|
22
|
+
createForm: FormCreator
|
|
23
|
+
createGlobalForm: FormCreator
|
|
24
|
+
skip?: () => void
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type FormifyCallback = (args: FormifyArgs, cms: TinaCMS) => Form | void
|
|
28
|
+
export type onSubmitArgs = {
|
|
29
|
+
/**
|
|
30
|
+
* @deprecated queryString is actually a mutation string, use `mutationString` instead
|
|
31
|
+
*/
|
|
32
|
+
queryString: string
|
|
33
|
+
mutationString: string
|
|
34
|
+
variables: object
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const createForm = (formConfig: FormOptions<any, any>) => {
|
|
38
|
+
return new Form(formConfig)
|
|
39
|
+
}
|
|
40
|
+
export const createGlobalForm: GlobalFormCreator = (
|
|
41
|
+
formConfig,
|
|
42
|
+
options?: { icon?: any; layout: 'fullscreen' | 'popup' }
|
|
43
|
+
) => {
|
|
44
|
+
const form = new Form({
|
|
45
|
+
...formConfig,
|
|
46
|
+
global: { global: true, ...options },
|
|
47
|
+
})
|
|
48
|
+
return form
|
|
49
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { TinaCMS } from 'tinacms'
|
|
3
|
+
|
|
4
|
+
const ErrorModalContent = (props: { title: string; errors: string[] }) => {
|
|
5
|
+
const { title, errors } = props
|
|
6
|
+
return (
|
|
7
|
+
<>
|
|
8
|
+
<div>{title}</div>
|
|
9
|
+
<ul>
|
|
10
|
+
{errors.map((error, i) => (
|
|
11
|
+
<li key={i}>{error}</li>
|
|
12
|
+
))}
|
|
13
|
+
</ul>
|
|
14
|
+
</>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const showErrorModal = (
|
|
19
|
+
title: string,
|
|
20
|
+
errors: string[],
|
|
21
|
+
cms: TinaCMS
|
|
22
|
+
) => {
|
|
23
|
+
cms.alerts.error(() => <ErrorModalContent title={title} errors={errors} />)
|
|
24
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import * as G from 'graphql'
|
|
2
|
+
|
|
3
|
+
export const expandQuery = ({
|
|
4
|
+
schema,
|
|
5
|
+
documentNode,
|
|
6
|
+
}: {
|
|
7
|
+
schema: G.GraphQLSchema
|
|
8
|
+
documentNode: G.DocumentNode
|
|
9
|
+
}): G.DocumentNode => {
|
|
10
|
+
const documentNodeWithTypenames = addTypenameToDocument(documentNode)
|
|
11
|
+
return addMetaFieldsToQuery(documentNodeWithTypenames, new G.TypeInfo(schema))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const addTypenameToDocument = (doc: G.DocumentNode) => {
|
|
15
|
+
function isField(selection: G.SelectionNode): selection is G.FieldNode {
|
|
16
|
+
return selection.kind === 'Field'
|
|
17
|
+
}
|
|
18
|
+
return G.visit(doc, {
|
|
19
|
+
SelectionSet: {
|
|
20
|
+
enter(node, _key, parent) {
|
|
21
|
+
// Don't add __typename to OperationDefinitions.
|
|
22
|
+
if (
|
|
23
|
+
parent &&
|
|
24
|
+
(parent as G.OperationDefinitionNode).kind ===
|
|
25
|
+
G.Kind.OPERATION_DEFINITION
|
|
26
|
+
) {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// No changes if no selections.
|
|
31
|
+
const { selections } = node
|
|
32
|
+
if (!selections) {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// If selections already have a __typename, or are part of an
|
|
37
|
+
// introspection query, do nothing.
|
|
38
|
+
const skip = selections.some((selection) => {
|
|
39
|
+
return (
|
|
40
|
+
isField(selection) &&
|
|
41
|
+
(selection.name.value === '__typename' ||
|
|
42
|
+
selection.name.value.lastIndexOf('__', 0) === 0)
|
|
43
|
+
)
|
|
44
|
+
})
|
|
45
|
+
if (skip) {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// If this SelectionSet is @export-ed as an input variable, it should
|
|
50
|
+
// not have a __typename field (see issue #4691).
|
|
51
|
+
const field = parent as G.FieldNode
|
|
52
|
+
if (
|
|
53
|
+
isField(field) &&
|
|
54
|
+
field.directives &&
|
|
55
|
+
field.directives.some((d) => d.name.value === 'export')
|
|
56
|
+
) {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Create and return a new SelectionSet with a __typename Field.
|
|
61
|
+
return {
|
|
62
|
+
...node,
|
|
63
|
+
selections: [...selections, TYPENAME_FIELD],
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const CONTENT_SOURCE_FIELD: G.FieldNode = {
|
|
71
|
+
kind: G.Kind.FIELD,
|
|
72
|
+
name: {
|
|
73
|
+
kind: G.Kind.NAME,
|
|
74
|
+
value: '_content_source',
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
const METADATA_FIELD: G.FieldNode = {
|
|
78
|
+
kind: G.Kind.FIELD,
|
|
79
|
+
name: {
|
|
80
|
+
kind: G.Kind.NAME,
|
|
81
|
+
value: '_tina_metadata',
|
|
82
|
+
},
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const TYPENAME_FIELD: G.FieldNode = {
|
|
86
|
+
kind: G.Kind.FIELD,
|
|
87
|
+
name: {
|
|
88
|
+
kind: G.Kind.NAME,
|
|
89
|
+
value: '__typename',
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const addMetadataField = (
|
|
94
|
+
node: G.FieldNode | G.InlineFragmentNode | G.FragmentDefinitionNode
|
|
95
|
+
): G.ASTNode => {
|
|
96
|
+
return {
|
|
97
|
+
...node,
|
|
98
|
+
selectionSet: {
|
|
99
|
+
...(node.selectionSet || {
|
|
100
|
+
kind: 'SelectionSet',
|
|
101
|
+
selections: [],
|
|
102
|
+
}),
|
|
103
|
+
selections:
|
|
104
|
+
[
|
|
105
|
+
...(node.selectionSet?.selections || []),
|
|
106
|
+
METADATA_FIELD,
|
|
107
|
+
CONTENT_SOURCE_FIELD,
|
|
108
|
+
] || [],
|
|
109
|
+
},
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const addMetaFieldsToQuery = (
|
|
114
|
+
documentNode: G.DocumentNode,
|
|
115
|
+
typeInfo: G.TypeInfo
|
|
116
|
+
) => {
|
|
117
|
+
const addMetaFields: G.VisitFn<G.ASTNode, G.FieldNode> = (
|
|
118
|
+
node: G.FieldNode
|
|
119
|
+
): G.ASTNode => {
|
|
120
|
+
return {
|
|
121
|
+
...node,
|
|
122
|
+
selectionSet: {
|
|
123
|
+
...(node.selectionSet || {
|
|
124
|
+
kind: 'SelectionSet',
|
|
125
|
+
selections: [],
|
|
126
|
+
}),
|
|
127
|
+
selections:
|
|
128
|
+
[...(node.selectionSet?.selections || []), ...metaFields] || [],
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const formifyVisitor: G.Visitor<G.ASTKindToNode, G.ASTNode> = {
|
|
134
|
+
FragmentDefinition: {
|
|
135
|
+
enter: (node, key, parent, path, ancestors) => {
|
|
136
|
+
typeInfo.enter(node)
|
|
137
|
+
const type = typeInfo.getType()
|
|
138
|
+
if (type) {
|
|
139
|
+
const namedType = G.getNamedType(type)
|
|
140
|
+
if (G.isObjectType(namedType)) {
|
|
141
|
+
if (namedType.getFields()['_tina_metadata']) {
|
|
142
|
+
return addMetadataField(node)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return node
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
InlineFragment: {
|
|
150
|
+
enter: (node, key, parent, path, ancestors) => {
|
|
151
|
+
typeInfo.enter(node)
|
|
152
|
+
const type = typeInfo.getType()
|
|
153
|
+
if (type) {
|
|
154
|
+
const namedType = G.getNamedType(type)
|
|
155
|
+
if (G.isObjectType(namedType)) {
|
|
156
|
+
if (namedType.getFields()['_tina_metadata']) {
|
|
157
|
+
return addMetadataField(node)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return node
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
Field: {
|
|
165
|
+
enter: (node, key, parent, path, ancestors) => {
|
|
166
|
+
typeInfo.enter(node)
|
|
167
|
+
const type = typeInfo.getType()
|
|
168
|
+
if (type) {
|
|
169
|
+
if (isNodeType(type)) {
|
|
170
|
+
return addMetaFields(node, key, parent, path, ancestors)
|
|
171
|
+
}
|
|
172
|
+
const namedType = G.getNamedType(type)
|
|
173
|
+
if (G.isObjectType(namedType)) {
|
|
174
|
+
if (namedType.getFields()['_tina_metadata']) {
|
|
175
|
+
return addMetadataField(node)
|
|
176
|
+
}
|
|
177
|
+
return node
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return node
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
}
|
|
184
|
+
return G.visit(documentNode, G.visitWithTypeInfo(typeInfo, formifyVisitor))
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* This is a dummy query which we pull apart and spread
|
|
188
|
+
* back into the the selectionSet for all "Node" fields
|
|
189
|
+
*/
|
|
190
|
+
const node = G.parse(`
|
|
191
|
+
query Sample {
|
|
192
|
+
...on Document {
|
|
193
|
+
_internalValues: _values
|
|
194
|
+
_internalSys: _sys {
|
|
195
|
+
breadcrumbs
|
|
196
|
+
basename
|
|
197
|
+
filename
|
|
198
|
+
path
|
|
199
|
+
extension
|
|
200
|
+
relativePath
|
|
201
|
+
title
|
|
202
|
+
template
|
|
203
|
+
collection {
|
|
204
|
+
name
|
|
205
|
+
slug
|
|
206
|
+
label
|
|
207
|
+
path
|
|
208
|
+
format
|
|
209
|
+
matches
|
|
210
|
+
templates
|
|
211
|
+
fields
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}`)
|
|
216
|
+
const metaFields: G.SelectionNode[] =
|
|
217
|
+
// @ts-ignore
|
|
218
|
+
node.definitions[0].selectionSet.selections
|
|
219
|
+
|
|
220
|
+
export const isNodeType = (type: G.GraphQLOutputType) => {
|
|
221
|
+
const namedType = G.getNamedType(type)
|
|
222
|
+
if (G.isInterfaceType(namedType)) {
|
|
223
|
+
if (namedType.name === 'Node') {
|
|
224
|
+
return true
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (G.isUnionType(namedType)) {
|
|
228
|
+
const types = namedType.getTypes()
|
|
229
|
+
if (
|
|
230
|
+
types.every((type) => {
|
|
231
|
+
return type.getInterfaces().some((intfc) => intfc.name === 'Node')
|
|
232
|
+
})
|
|
233
|
+
) {
|
|
234
|
+
return true
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (G.isObjectType(namedType)) {
|
|
238
|
+
if (namedType.getInterfaces().some((intfc) => intfc.name === 'Node')) {
|
|
239
|
+
return true
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export const isConnectionType = (type: G.GraphQLOutputType) => {
|
|
245
|
+
const namedType = G.getNamedType(type)
|
|
246
|
+
if (G.isInterfaceType(namedType)) {
|
|
247
|
+
if (namedType.name === 'Connection') {
|
|
248
|
+
return true
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (G.isUnionType(namedType)) {
|
|
252
|
+
const types = namedType.getTypes()
|
|
253
|
+
if (
|
|
254
|
+
types.every((type) => {
|
|
255
|
+
return type.getInterfaces().some((intfc) => intfc.name === 'Connection')
|
|
256
|
+
})
|
|
257
|
+
) {
|
|
258
|
+
return true
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (G.isObjectType(namedType)) {
|
|
262
|
+
if (
|
|
263
|
+
namedType.getInterfaces().some((intfc) => intfc.name === 'Connection')
|
|
264
|
+
) {
|
|
265
|
+
return true
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|