@tinacms/app 0.0.21 → 0.0.23
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/appFiles/package.json +19 -0
- package/appFiles/src/App.tsx +63 -0
- package/appFiles/src/assets/react.svg +1 -0
- package/appFiles/src/index.css +3 -0
- package/appFiles/src/lib/formify/index.ts +314 -0
- package/appFiles/src/lib/machines/document-machine.ts +348 -0
- package/appFiles/src/lib/machines/query-machine.ts +630 -0
- package/appFiles/src/lib/machines/util.ts +205 -0
- package/appFiles/src/main.tsx +24 -0
- package/appFiles/src/preview.tsx +108 -0
- package/appFiles/src/vite-env.d.ts +14 -0
- package/dist/index.js +129 -96
- package/package.json +21 -25
- package/dist/assets/out.es.js +0 -111383
- package/dist/assets/style.css +0 -651
- package/dist/assets/webfontloader.js +0 -620
- package/dist/index.dev.html +0 -26
- package/dist/index.html +0 -13
- package/dist/prebuild.d.ts +0 -1
- package/dist/prebuild.js +0 -302
|
@@ -0,0 +1,630 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Copyright 2021 Forestry.io Holdings, Inc.
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
Unless required by applicable law or agreed to in writing, software
|
|
8
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
9
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
10
|
+
See the License for the specific language governing permissions and
|
|
11
|
+
limitations under the License.
|
|
12
|
+
*/
|
|
13
|
+
import { assign, ContextFrom, createMachine, spawn } from 'xstate'
|
|
14
|
+
import {
|
|
15
|
+
Form,
|
|
16
|
+
TinaCMS,
|
|
17
|
+
NAMER,
|
|
18
|
+
Template,
|
|
19
|
+
TinaFieldEnriched,
|
|
20
|
+
TinaCollection,
|
|
21
|
+
TinaSchema,
|
|
22
|
+
GlobalFormPlugin,
|
|
23
|
+
Client,
|
|
24
|
+
} from 'tinacms'
|
|
25
|
+
import * as G from 'graphql'
|
|
26
|
+
import { formify } from '../formify'
|
|
27
|
+
import { documentMachine, FieldType, FormValues } from './document-machine'
|
|
28
|
+
import type { ActorRefFrom } from 'xstate'
|
|
29
|
+
import { Blueprint2 } from '../formify'
|
|
30
|
+
|
|
31
|
+
export type DataType = Record<string, unknown>
|
|
32
|
+
type DocumentInfo = {
|
|
33
|
+
ref: ActorRefFrom<typeof documentMachine>
|
|
34
|
+
}
|
|
35
|
+
type DocumentMap = {
|
|
36
|
+
[documentId: string]: DocumentInfo & {
|
|
37
|
+
/** We don't support nested forms or forms for list queries */
|
|
38
|
+
skipFormRegister: boolean
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type ContextType = {
|
|
43
|
+
id: null | string
|
|
44
|
+
data: null | DataType
|
|
45
|
+
cms: TinaCMS
|
|
46
|
+
selectedDocument: string | null
|
|
47
|
+
iframe: null | HTMLIFrameElement
|
|
48
|
+
formifyCallback: (args: any) => Form
|
|
49
|
+
documentMap: DocumentMap
|
|
50
|
+
blueprints: Blueprint2[]
|
|
51
|
+
}
|
|
52
|
+
export const initialContext: Omit<ContextType, 'cms' | 'formifyCallback'> = {
|
|
53
|
+
id: null,
|
|
54
|
+
data: null,
|
|
55
|
+
selectedDocument: null,
|
|
56
|
+
blueprints: [],
|
|
57
|
+
documentMap: {},
|
|
58
|
+
iframe: null,
|
|
59
|
+
}
|
|
60
|
+
export const queryMachine =
|
|
61
|
+
/** @xstate-layout N4IgpgJg5mDOIC5QAoC2BDAxgCwJYDswBKAOgFcAnAGxNwirAGIBlAUQBUB9AVQCUAZRKAAOAe1i4ALrlH4hIAB6IAjAAYALCXXqAnACZVAVmUAOAGxmAzMp1mANCACeidXpMkdnnSZvLDh1X11AF9ghzQsPEJSSho6BhYOTgBJADkABW4uPkEkEDEJaVl5JQQAdh0SMtVqvTqassN1M0MHZwRLdWUPLx8dPwCg0PCMHAJicmpaeiY2LgARZOZ0-gBBAE0eAXkCqRk5PNKyvRJVM-OL8+U2xD0mns8+gcC9ELCQCLHoybiZxm50vNVuxWFtciJxHtiodECZKqoLOpVMpjiYTGUyp0bghlGYyg9vL5-C83iNIuNSMJcMIwFRxtMEqt5vNOABFbisXjrHaQooHUBHPSWEiGSw6VSWUWYvRWHTYsro07nSzIpE+CrDD6jKITKk0umEBmzbgAIXmAHkAMLcACyrFS7GYPMK+xKiGOwtF4sllmlsuxOlcIquJlUJm04pMms+Osp1Np9PiTGSADFeKs7ZwbebuA7WPNnVD+YpEKKzCKFWG0dZkSZWk5YRKlWdDMc8f5SVryd89QnDQQ9ug6QAvAhQRgQWRgWj4ABuogA1tOYxSSL2DdOB9Ih7hR-goAgCPPMOg+QBtVQAXULfLdOLU+Neej8yksNdM9faCs0l3FrleorRtqq7rom+CDiOY6MGAFAUKIFBrlQp4AGbwagJArj28YbjOEG7mOh5zqIJ7nleN6ujC941CQT4vm+agftiZg6Piv4aHU6iAe8mG6th9IAO7oHs+6MBa1p2g6nC8KwTLcnkuy3pRygPjRrh0e+dbYspujNmcf4cU0QHdrx+r0jS+AQFBk79kRS4YcBWGmYa5mWfuhHHqe+wXte8m8hRAoqKYmiSn4Mr0bWn4qJYipeJ4gSto0zRGV8Jl9tOLlQTBcEIcISGSKhFDoTxcZOelYAWQRR7EZ5sjeeR0IBVRj5qcY4WMQ2OIIicbH-pxnbFWufGGhQYDoBAjj-ICwKgjk9XFqUlh4iQnS+kiOgJU09gdfo5YXCqyhqiiOjJbGg2lSQI1jRN0nZgAaqC7KcnJEIug1JYdEtK1lGtG3NNi6LuBc6gmHUophmUJ0gUN06XeNiT8KwloLFatr2uwc13sphgijYooJcpdRmCYWnKeWsXiutGKbZDjlpRdo1wymySsPwLKWgAEqsqQAOKsBjlGLfiX0-VTf0dcoMruIYoTvPgogQHA8gDbERr841ynuDK63WHclyWNihgGASTzEvoNMTLEavvcDumXBcB0Btj5PxaLZh6ObJV00mVulE02Nu7oROSs+XR6P9626a2MqNIZ3EOalOFbrgO57lAPuIH+VQ+M+0UaZF5SGLt5xR+2sdkilns4YJwlp75r3zRn3inDovoaAq6LSiTb4kCYb4qvoBh4sdcfGZXZnla5tcvUWmO+t0am99WDGaeL1juAqraGCDRg2O7I8V2ddOw+00+KY1GJaQY7jO5TiVmB7h84Vl8Hpzic9aM+i+98v+dlGoBIU1+vffep1QKEFfqKJidxdKmDDBGBEHtX6vFtnbM4DsOpCgAeTXowDQhAA */
|
|
62
|
+
createMachine(
|
|
63
|
+
{
|
|
64
|
+
tsTypes: {} as import('./query-machine.typegen').Typegen0,
|
|
65
|
+
schema: {
|
|
66
|
+
context: {} as ContextType,
|
|
67
|
+
services: {} as {
|
|
68
|
+
initializer: {
|
|
69
|
+
data: {
|
|
70
|
+
data: DataType
|
|
71
|
+
blueprints: Blueprint2[]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
setter: {
|
|
75
|
+
data: { data: DataType }
|
|
76
|
+
}
|
|
77
|
+
subDocumentResolver: {
|
|
78
|
+
data: {
|
|
79
|
+
id: string
|
|
80
|
+
location: string
|
|
81
|
+
}[]
|
|
82
|
+
}
|
|
83
|
+
onChangeCallback: {
|
|
84
|
+
data: undefined
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
events: {} as
|
|
88
|
+
| {
|
|
89
|
+
type: 'IFRAME_MOUNTED'
|
|
90
|
+
value: HTMLIFrameElement
|
|
91
|
+
}
|
|
92
|
+
| {
|
|
93
|
+
type: 'SELECT_DOCUMENT'
|
|
94
|
+
value: string
|
|
95
|
+
}
|
|
96
|
+
| {
|
|
97
|
+
type: 'DOCUMENT_READY'
|
|
98
|
+
value: string
|
|
99
|
+
}
|
|
100
|
+
| {
|
|
101
|
+
type: 'NAVIGATE'
|
|
102
|
+
}
|
|
103
|
+
| {
|
|
104
|
+
type: 'ADD_QUERY'
|
|
105
|
+
value: {
|
|
106
|
+
id: string
|
|
107
|
+
type: 'open' | 'close'
|
|
108
|
+
query: string
|
|
109
|
+
data: object
|
|
110
|
+
variables: object
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
| {
|
|
114
|
+
type: 'REMOVE_QUERY'
|
|
115
|
+
value: string
|
|
116
|
+
}
|
|
117
|
+
| {
|
|
118
|
+
type: 'SUBDOCUMENTS'
|
|
119
|
+
value: { id: string; location: string }[]
|
|
120
|
+
}
|
|
121
|
+
| {
|
|
122
|
+
type: 'FIELD_CHANGE'
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
id: '(machine)',
|
|
126
|
+
type: 'parallel',
|
|
127
|
+
states: {
|
|
128
|
+
pipeline: {
|
|
129
|
+
initial: 'idle',
|
|
130
|
+
states: {
|
|
131
|
+
idle: {
|
|
132
|
+
entry: 'clear',
|
|
133
|
+
on: {
|
|
134
|
+
ADD_QUERY: {
|
|
135
|
+
target: 'initializing',
|
|
136
|
+
},
|
|
137
|
+
SUBDOCUMENTS: {
|
|
138
|
+
target: 'pending',
|
|
139
|
+
},
|
|
140
|
+
IFRAME_MOUNTED: {
|
|
141
|
+
actions: 'setIframe',
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
initializing: {
|
|
146
|
+
invoke: {
|
|
147
|
+
src: 'initializer',
|
|
148
|
+
onDone: [
|
|
149
|
+
{
|
|
150
|
+
actions: 'storeInitialValues',
|
|
151
|
+
target: 'pending',
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
onError: [
|
|
155
|
+
{
|
|
156
|
+
actions: 'handleError',
|
|
157
|
+
target: 'error',
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
waiting: {
|
|
163
|
+
on: {
|
|
164
|
+
DOCUMENT_READY: {
|
|
165
|
+
target: 'pending',
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
pending: {
|
|
170
|
+
invoke: {
|
|
171
|
+
src: 'setter',
|
|
172
|
+
onDone: [
|
|
173
|
+
{
|
|
174
|
+
target: 'ready',
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
onError: [
|
|
178
|
+
{
|
|
179
|
+
actions: 'handleMissingDocument',
|
|
180
|
+
target: 'waiting',
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
ready: {
|
|
186
|
+
entry: 'resolveData',
|
|
187
|
+
invoke: {
|
|
188
|
+
src: 'onChangeCallback',
|
|
189
|
+
},
|
|
190
|
+
on: {
|
|
191
|
+
NAVIGATE: {
|
|
192
|
+
target: 'idle',
|
|
193
|
+
},
|
|
194
|
+
REMOVE_QUERY: {
|
|
195
|
+
target: 'idle',
|
|
196
|
+
},
|
|
197
|
+
SELECT_DOCUMENT: {
|
|
198
|
+
actions: 'selectDocument',
|
|
199
|
+
},
|
|
200
|
+
FIELD_CHANGE: {
|
|
201
|
+
target: 'pending',
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
error: {},
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
actions: {
|
|
212
|
+
handleError: (_context, event) => console.error(event.data),
|
|
213
|
+
handleMissingDocument: assign((context, event) => {
|
|
214
|
+
count = count + 1
|
|
215
|
+
if (count > 50) {
|
|
216
|
+
throw new Error('infinite loop')
|
|
217
|
+
}
|
|
218
|
+
if (event.data instanceof QueryError) {
|
|
219
|
+
if (context.documentMap[event.data.id]) {
|
|
220
|
+
// Already exists
|
|
221
|
+
return context
|
|
222
|
+
}
|
|
223
|
+
if (!event.data.id) {
|
|
224
|
+
return context
|
|
225
|
+
}
|
|
226
|
+
const doc = {
|
|
227
|
+
ref: spawn(
|
|
228
|
+
documentMachine.withContext({
|
|
229
|
+
id: event.data.id,
|
|
230
|
+
cms: context.cms,
|
|
231
|
+
formifyCallback: context.formifyCallback,
|
|
232
|
+
form: null,
|
|
233
|
+
data: null,
|
|
234
|
+
})
|
|
235
|
+
),
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
...context,
|
|
240
|
+
documentMap: {
|
|
241
|
+
...context.documentMap,
|
|
242
|
+
[event.data.id]: {
|
|
243
|
+
...doc,
|
|
244
|
+
skipFormRegister: event.data.skipFormRegister,
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
}
|
|
248
|
+
} else {
|
|
249
|
+
console.error(event.data)
|
|
250
|
+
return context
|
|
251
|
+
}
|
|
252
|
+
}),
|
|
253
|
+
clear: assign((context) => {
|
|
254
|
+
context.cms.forms.all().forEach((form) => {
|
|
255
|
+
context.cms.forms.remove(form.id)
|
|
256
|
+
})
|
|
257
|
+
return {
|
|
258
|
+
...initialContext,
|
|
259
|
+
formifyCallback: context.formifyCallback,
|
|
260
|
+
cms: context.cms,
|
|
261
|
+
// documentMap: context.documentMap, // to preserve docs across pages
|
|
262
|
+
iframe: context.iframe,
|
|
263
|
+
}
|
|
264
|
+
}),
|
|
265
|
+
storeInitialValues: assign((context, event) => {
|
|
266
|
+
return {
|
|
267
|
+
...context,
|
|
268
|
+
...event.data,
|
|
269
|
+
}
|
|
270
|
+
}),
|
|
271
|
+
selectDocument: assign((context, event) => {
|
|
272
|
+
return {
|
|
273
|
+
...context,
|
|
274
|
+
selectedDocument: event.value,
|
|
275
|
+
}
|
|
276
|
+
}),
|
|
277
|
+
setIframe: assign((context, event) => {
|
|
278
|
+
return {
|
|
279
|
+
...context,
|
|
280
|
+
iframe: event.value,
|
|
281
|
+
}
|
|
282
|
+
}),
|
|
283
|
+
resolveData: assign((context, event) => {
|
|
284
|
+
if (context.iframe) {
|
|
285
|
+
context.iframe?.contentWindow?.postMessage({
|
|
286
|
+
type: 'updateData',
|
|
287
|
+
id: context.id,
|
|
288
|
+
data: event.data.data,
|
|
289
|
+
})
|
|
290
|
+
}
|
|
291
|
+
return {
|
|
292
|
+
...context,
|
|
293
|
+
data: event.data.data,
|
|
294
|
+
}
|
|
295
|
+
}),
|
|
296
|
+
},
|
|
297
|
+
services: {
|
|
298
|
+
setter: async (context) => {
|
|
299
|
+
const walk = (obj: unknown, path: string[] = []) => {
|
|
300
|
+
const accum: Record<string, unknown> = {}
|
|
301
|
+
if (isScalar(obj)) {
|
|
302
|
+
return obj
|
|
303
|
+
}
|
|
304
|
+
Object.entries(obj as object).map(([key, value]) => {
|
|
305
|
+
if (Array.isArray(value)) {
|
|
306
|
+
accum[key] = value.map((item) => walk(item, [...path, key]))
|
|
307
|
+
} else {
|
|
308
|
+
const blueprint = context.blueprints.find(
|
|
309
|
+
(bp) => bp.path?.join('.') === [...path, key].join('.')
|
|
310
|
+
)
|
|
311
|
+
if (blueprint) {
|
|
312
|
+
accum[key] = setData(value, blueprint, context)
|
|
313
|
+
} else {
|
|
314
|
+
accum[key] = walk(value, [...path, key])
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
})
|
|
318
|
+
return accum
|
|
319
|
+
}
|
|
320
|
+
const accum = walk(context.data)
|
|
321
|
+
return { data: accum }
|
|
322
|
+
},
|
|
323
|
+
initializer: async (context, event) => {
|
|
324
|
+
const tina = context.cms.api.tina as Client
|
|
325
|
+
const schema = await tina.getSchema()
|
|
326
|
+
const documentNode = G.parse(event.value.query)
|
|
327
|
+
const optimizedQuery = await tina.getOptimizedQuery(documentNode)
|
|
328
|
+
if (!optimizedQuery) {
|
|
329
|
+
throw new Error(`Unable to optimize query`)
|
|
330
|
+
}
|
|
331
|
+
const { blueprints, formifiedQuery } = await formify({
|
|
332
|
+
schema,
|
|
333
|
+
optimizedDocumentNode: optimizedQuery,
|
|
334
|
+
})
|
|
335
|
+
const data = (await context.cms.api.tina.request(
|
|
336
|
+
G.print(formifiedQuery),
|
|
337
|
+
{
|
|
338
|
+
variables: event.value.variables,
|
|
339
|
+
}
|
|
340
|
+
)) as DataType
|
|
341
|
+
return {
|
|
342
|
+
data,
|
|
343
|
+
blueprints,
|
|
344
|
+
id: event.value.id,
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
onChangeCallback: (context) => (callback, _onReceive) => {
|
|
348
|
+
const schema = context.cms.api.tina.schema as TinaSchema
|
|
349
|
+
Object.values(context.documentMap).forEach((documentMachine) => {
|
|
350
|
+
if (documentMachine.skipFormRegister) {
|
|
351
|
+
return
|
|
352
|
+
}
|
|
353
|
+
const documentContext = documentMachine.ref.getSnapshot()?.context
|
|
354
|
+
const collectionName =
|
|
355
|
+
documentContext?.data?._internalSys.collection.name
|
|
356
|
+
|
|
357
|
+
const collection = schema.getCollection(
|
|
358
|
+
collectionName || ''
|
|
359
|
+
) as TinaCollection
|
|
360
|
+
if (documentContext?.form) {
|
|
361
|
+
if (collection.ui?.global) {
|
|
362
|
+
context.cms.plugins.add(
|
|
363
|
+
new GlobalFormPlugin(documentContext.form)
|
|
364
|
+
)
|
|
365
|
+
} else {
|
|
366
|
+
context.cms.forms.add(documentContext.form)
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
})
|
|
370
|
+
if (context.cms) {
|
|
371
|
+
context.cms.events.subscribe(`forms:fields:onChange`, () => {
|
|
372
|
+
callback({ type: 'FIELD_CHANGE' })
|
|
373
|
+
})
|
|
374
|
+
context.cms.events.subscribe(`forms:reset`, () => {
|
|
375
|
+
callback({ type: 'FIELD_CHANGE' })
|
|
376
|
+
})
|
|
377
|
+
}
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
}
|
|
381
|
+
)
|
|
382
|
+
class QueryError extends Error {
|
|
383
|
+
public id: string
|
|
384
|
+
public skipFormRegister: boolean
|
|
385
|
+
constructor(message: string, id: string, skipFormRegister: boolean) {
|
|
386
|
+
super(message) // (1)
|
|
387
|
+
this.name = 'QueryError' // (2)
|
|
388
|
+
this.id = id
|
|
389
|
+
this.skipFormRegister = skipFormRegister
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
let count = 0
|
|
393
|
+
|
|
394
|
+
// https://github.com/oleics/node-is-scalar/blob/master/index.js
|
|
395
|
+
const withSymbol = typeof Symbol !== 'undefined'
|
|
396
|
+
function isScalar(value: unknown) {
|
|
397
|
+
const type = typeof value
|
|
398
|
+
if (type === 'string') return true
|
|
399
|
+
if (type === 'number') return true
|
|
400
|
+
if (type === 'boolean') return true
|
|
401
|
+
if (withSymbol === true && type === 'symbol') return true
|
|
402
|
+
|
|
403
|
+
if (value == null) return true
|
|
404
|
+
if (withSymbol === true && value instanceof Symbol) return true
|
|
405
|
+
if (value instanceof String) return true
|
|
406
|
+
if (value instanceof Number) return true
|
|
407
|
+
if (value instanceof Boolean) return true
|
|
408
|
+
|
|
409
|
+
return false
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const setData = (
|
|
413
|
+
data: { [key: string]: unknown },
|
|
414
|
+
blueprint: Blueprint2,
|
|
415
|
+
context: ContextFrom<typeof queryMachine>
|
|
416
|
+
) => {
|
|
417
|
+
if (data?._internalSys) {
|
|
418
|
+
const id = data._internalSys?.path
|
|
419
|
+
const doc = context.documentMap[id]
|
|
420
|
+
const docContext = doc?.ref?.getSnapshot()?.context
|
|
421
|
+
const form = docContext?.form
|
|
422
|
+
if (!form) {
|
|
423
|
+
const skipFormRegiester = (blueprint.path?.length || 0) > 2
|
|
424
|
+
throw new QueryError(
|
|
425
|
+
`Unable to resolve form for initial document`,
|
|
426
|
+
id,
|
|
427
|
+
skipFormRegiester
|
|
428
|
+
)
|
|
429
|
+
}
|
|
430
|
+
const _internalSys = docContext.data?._internalSys
|
|
431
|
+
if (!_internalSys) {
|
|
432
|
+
throw new Error(`No system information found for document ${id}`)
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const fields = form.fields
|
|
436
|
+
const result = resolveForm({
|
|
437
|
+
id,
|
|
438
|
+
fields,
|
|
439
|
+
sys: _internalSys,
|
|
440
|
+
values: form.values,
|
|
441
|
+
fieldsToInclude: blueprint.fields,
|
|
442
|
+
context,
|
|
443
|
+
})
|
|
444
|
+
return { ...docContext.data, ...result }
|
|
445
|
+
} else {
|
|
446
|
+
// this isn't a node
|
|
447
|
+
}
|
|
448
|
+
return data
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const resolveForm = ({
|
|
452
|
+
id,
|
|
453
|
+
fields,
|
|
454
|
+
sys,
|
|
455
|
+
values,
|
|
456
|
+
fieldsToInclude,
|
|
457
|
+
context,
|
|
458
|
+
}: {
|
|
459
|
+
id: string
|
|
460
|
+
fields: FieldType[]
|
|
461
|
+
sys: Record<string, unknown>
|
|
462
|
+
values: FormValues | undefined
|
|
463
|
+
fieldsToInclude: Blueprint2['fields']
|
|
464
|
+
context: ContextFrom<typeof queryMachine>
|
|
465
|
+
}) => {
|
|
466
|
+
const accum: Record<string, unknown> = {}
|
|
467
|
+
if (!values) {
|
|
468
|
+
return accum
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
fieldsToInclude?.forEach((fieldToInclude) => {
|
|
472
|
+
const field = fields.find((field) => fieldToInclude.name === field.name)
|
|
473
|
+
if (!field) {
|
|
474
|
+
if (fieldToInclude.name === 'id') {
|
|
475
|
+
accum[fieldToInclude.alias] = id
|
|
476
|
+
} else if (fieldToInclude.name === '_sys') {
|
|
477
|
+
if (fieldToInclude.alias !== '_internalSys') {
|
|
478
|
+
const sysAccum: Record<string, unknown> = {}
|
|
479
|
+
// TODO: loop through these and actually use their alias values
|
|
480
|
+
fieldToInclude.fields?.forEach((field) => {
|
|
481
|
+
sysAccum[field.alias] = sys[field.name]
|
|
482
|
+
})
|
|
483
|
+
accum[fieldToInclude.alias] = sysAccum
|
|
484
|
+
}
|
|
485
|
+
} else if (fieldToInclude.name === '__typename') {
|
|
486
|
+
// field namespaces are one level deeper than what we need, so grab the first
|
|
487
|
+
// one and remove the last string on the namespace
|
|
488
|
+
accum[fieldToInclude.alias] = NAMER.dataTypeName(
|
|
489
|
+
fields[0].namespace.slice(0, fields[0].namespace.length - 1)
|
|
490
|
+
)
|
|
491
|
+
} else if (fieldToInclude.name === '_values') {
|
|
492
|
+
if (fieldToInclude.alias !== '_internalValues') {
|
|
493
|
+
accum[fieldToInclude.alias] = values
|
|
494
|
+
}
|
|
495
|
+
} else {
|
|
496
|
+
}
|
|
497
|
+
} else {
|
|
498
|
+
const result = resolveField({
|
|
499
|
+
id,
|
|
500
|
+
field,
|
|
501
|
+
sys,
|
|
502
|
+
value: values[field.name],
|
|
503
|
+
fieldsToInclude: fieldsToInclude.find(({ name }) => name === field.name)
|
|
504
|
+
?.fields,
|
|
505
|
+
context,
|
|
506
|
+
})
|
|
507
|
+
if (result) {
|
|
508
|
+
accum[fieldToInclude.alias] = result
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
})
|
|
512
|
+
|
|
513
|
+
return accum
|
|
514
|
+
}
|
|
515
|
+
const resolveField = ({
|
|
516
|
+
id,
|
|
517
|
+
field,
|
|
518
|
+
sys,
|
|
519
|
+
value,
|
|
520
|
+
fieldsToInclude,
|
|
521
|
+
context,
|
|
522
|
+
}: {
|
|
523
|
+
id: string
|
|
524
|
+
field: TinaFieldEnriched
|
|
525
|
+
sys: Record<string, unknown>
|
|
526
|
+
value: unknown
|
|
527
|
+
fieldsToInclude: Blueprint2['fields']
|
|
528
|
+
context: ContextFrom<typeof queryMachine>
|
|
529
|
+
}) => {
|
|
530
|
+
switch (field.type) {
|
|
531
|
+
case 'reference':
|
|
532
|
+
if (!value) {
|
|
533
|
+
return
|
|
534
|
+
}
|
|
535
|
+
if (typeof value === 'string') {
|
|
536
|
+
const doc = context.documentMap[value]
|
|
537
|
+
const docContext = doc?.ref?.getSnapshot()?.context
|
|
538
|
+
const form = docContext?.form
|
|
539
|
+
if (!form) {
|
|
540
|
+
throw new QueryError(
|
|
541
|
+
`Unable to resolve form for document`,
|
|
542
|
+
value,
|
|
543
|
+
true
|
|
544
|
+
)
|
|
545
|
+
}
|
|
546
|
+
const _internalSys = docContext.data?._internalSys
|
|
547
|
+
if (!_internalSys) {
|
|
548
|
+
throw new Error(`No system information found for document ${id}`)
|
|
549
|
+
}
|
|
550
|
+
return resolveForm({
|
|
551
|
+
id: value,
|
|
552
|
+
fields: form.fields,
|
|
553
|
+
sys: _internalSys,
|
|
554
|
+
values: form.values,
|
|
555
|
+
fieldsToInclude,
|
|
556
|
+
context,
|
|
557
|
+
})
|
|
558
|
+
}
|
|
559
|
+
throw new Error(`Unexpected value for type "reference"`)
|
|
560
|
+
case 'object':
|
|
561
|
+
if (field.fields) {
|
|
562
|
+
if (typeof field.fields === 'string') {
|
|
563
|
+
throw new Error('Global templates not supported')
|
|
564
|
+
}
|
|
565
|
+
field.fields
|
|
566
|
+
if (field.list) {
|
|
567
|
+
if (Array.isArray(value)) {
|
|
568
|
+
return value.map((item) => {
|
|
569
|
+
if (typeof field.fields === 'string') {
|
|
570
|
+
throw new Error('Global templates not supported')
|
|
571
|
+
}
|
|
572
|
+
return resolveForm({
|
|
573
|
+
id,
|
|
574
|
+
fields: field.fields,
|
|
575
|
+
sys,
|
|
576
|
+
values: item,
|
|
577
|
+
fieldsToInclude,
|
|
578
|
+
context,
|
|
579
|
+
})
|
|
580
|
+
})
|
|
581
|
+
}
|
|
582
|
+
} else {
|
|
583
|
+
return resolveForm({
|
|
584
|
+
id,
|
|
585
|
+
fields: field.fields,
|
|
586
|
+
sys,
|
|
587
|
+
values: value,
|
|
588
|
+
fieldsToInclude,
|
|
589
|
+
context,
|
|
590
|
+
})
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
if (field.templates) {
|
|
594
|
+
if (field.list) {
|
|
595
|
+
if (!value) {
|
|
596
|
+
return
|
|
597
|
+
}
|
|
598
|
+
if (!Array.isArray(value)) {
|
|
599
|
+
return
|
|
600
|
+
}
|
|
601
|
+
return value.map((item) => {
|
|
602
|
+
let t: Template<true>
|
|
603
|
+
Object.entries(field.templates).forEach(([name, template]) => {
|
|
604
|
+
if (name === item._template) {
|
|
605
|
+
if (typeof template === 'string') {
|
|
606
|
+
throw new Error('Global templates not supported')
|
|
607
|
+
}
|
|
608
|
+
t = template
|
|
609
|
+
}
|
|
610
|
+
})
|
|
611
|
+
return {
|
|
612
|
+
_template: item._template,
|
|
613
|
+
...resolveForm({
|
|
614
|
+
id,
|
|
615
|
+
fields: t.fields,
|
|
616
|
+
sys,
|
|
617
|
+
values: item,
|
|
618
|
+
fieldsToInclude,
|
|
619
|
+
context,
|
|
620
|
+
}),
|
|
621
|
+
}
|
|
622
|
+
})
|
|
623
|
+
} else {
|
|
624
|
+
// not supported yet
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
default:
|
|
628
|
+
return value
|
|
629
|
+
}
|
|
630
|
+
}
|