lkb-fields-document 1.0.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.
Files changed (112) hide show
  1. package/component-blocks/dist/lkb-fields-document-component-blocks.cjs.d.ts +2 -0
  2. package/component-blocks/dist/lkb-fields-document-component-blocks.cjs.js +306 -0
  3. package/component-blocks/dist/lkb-fields-document-component-blocks.esm.js +300 -0
  4. package/component-blocks/dist/lkb-fields-document-component-blocks.node.cjs.js +306 -0
  5. package/component-blocks/dist/lkb-fields-document-component-blocks.node.esm.js +300 -0
  6. package/component-blocks/package.json +4 -0
  7. package/dist/Cell-0ac0ac66.node.cjs.js +21 -0
  8. package/dist/Cell-242f7404.esm.js +17 -0
  9. package/dist/Cell-3103f73d.node.esm.js +17 -0
  10. package/dist/Cell-bfb56d74.cjs.js +21 -0
  11. package/dist/Field-0e0f75ed.node.cjs.js +1628 -0
  12. package/dist/Field-28177061.cjs.js +1628 -0
  13. package/dist/Field-35b79e6b.node.esm.js +1619 -0
  14. package/dist/Field-92d13205.esm.js +1619 -0
  15. package/dist/api-2f524611.esm.js +502 -0
  16. package/dist/api-73636987.cjs.js +506 -0
  17. package/dist/api-8e2b20b8.node.cjs.js +506 -0
  18. package/dist/api-c32e360e.node.esm.js +502 -0
  19. package/dist/callout-ui-2aded278.cjs.js +131 -0
  20. package/dist/callout-ui-3e5ca544.node.esm.js +126 -0
  21. package/dist/callout-ui-8b5f2376.esm.js +126 -0
  22. package/dist/callout-ui-ad50f301.node.cjs.js +131 -0
  23. package/dist/declarations/src/component-blocks.d.ts +4 -0
  24. package/dist/declarations/src/component-blocks.d.ts.map +1 -0
  25. package/dist/declarations/src/document-editor/component-blocks/api.d.ts +120 -0
  26. package/dist/declarations/src/document-editor/component-blocks/api.d.ts.map +1 -0
  27. package/dist/declarations/src/document-editor/component-blocks/types.d.ts +241 -0
  28. package/dist/declarations/src/document-editor/component-blocks/types.d.ts.map +1 -0
  29. package/dist/declarations/src/document-editor/toolset/relationship/relationship-shared.d.ts +10 -0
  30. package/dist/declarations/src/document-editor/toolset/relationship/relationship-shared.d.ts.map +1 -0
  31. package/dist/declarations/src/index.d.ts +7 -0
  32. package/dist/declarations/src/index.d.ts.map +1 -0
  33. package/dist/declarations/src/my-component-blocks/index.d.ts +46 -0
  34. package/dist/declarations/src/my-component-blocks/index.d.ts.map +1 -0
  35. package/dist/declarations/src/structure/Cell.d.ts +5 -0
  36. package/dist/declarations/src/structure/Cell.d.ts.map +1 -0
  37. package/dist/declarations/src/structure/Field.d.ts +5 -0
  38. package/dist/declarations/src/structure/Field.d.ts.map +1 -0
  39. package/dist/declarations/src/structure/controller.d.ts +10 -0
  40. package/dist/declarations/src/structure/controller.d.ts.map +1 -0
  41. package/dist/declarations/src/structure/structure.d.ts +4 -0
  42. package/dist/declarations/src/structure/structure.d.ts.map +1 -0
  43. package/dist/declarations/src/structure-views.d.ts +5 -0
  44. package/dist/declarations/src/structure-views.d.ts.map +1 -0
  45. package/dist/declarations/src/types/DocumentFeatures.d.ts +33 -0
  46. package/dist/declarations/src/types/DocumentFeatures.d.ts.map +1 -0
  47. package/dist/declarations/src/types/DocumentFieldConfig.d.ts +18 -0
  48. package/dist/declarations/src/types/DocumentFieldConfig.d.ts.map +1 -0
  49. package/dist/declarations/src/types/FormattingConfig.d.ts +28 -0
  50. package/dist/declarations/src/types/FormattingConfig.d.ts.map +1 -0
  51. package/dist/declarations/src/types/RelationshipsConfig.d.ts +9 -0
  52. package/dist/declarations/src/types/RelationshipsConfig.d.ts.map +1 -0
  53. package/dist/declarations/src/types/StructureFieldConfig.d.ts +10 -0
  54. package/dist/declarations/src/types/StructureFieldConfig.d.ts.map +1 -0
  55. package/dist/declarations/src/validation/structure-validation.d.ts +218 -0
  56. package/dist/declarations/src/validation/structure-validation.d.ts.map +1 -0
  57. package/dist/declarations/src/views/Cell.d.ts +5 -0
  58. package/dist/declarations/src/views/Cell.d.ts.map +1 -0
  59. package/dist/declarations/src/views/Field.d.ts +5 -0
  60. package/dist/declarations/src/views/Field.d.ts.map +1 -0
  61. package/dist/declarations/src/views/controller.d.ts +15 -0
  62. package/dist/declarations/src/views/controller.d.ts.map +1 -0
  63. package/dist/declarations/src/views/document.d.ts +4 -0
  64. package/dist/declarations/src/views/document.d.ts.map +1 -0
  65. package/dist/declarations/src/views.d.ts +7 -0
  66. package/dist/declarations/src/views.d.ts.map +1 -0
  67. package/dist/editor-shared-a6e340e6.node.esm.js +1993 -0
  68. package/dist/editor-shared-a997ae98.node.cjs.js +2007 -0
  69. package/dist/editor-shared-cc1293ed.cjs.js +2007 -0
  70. package/dist/editor-shared-da518ba3.esm.js +1993 -0
  71. package/dist/form-from-preview-2042b9ef.cjs.js +512 -0
  72. package/dist/form-from-preview-5df6e492.node.esm.js +508 -0
  73. package/dist/form-from-preview-9e501058.node.cjs.js +512 -0
  74. package/dist/form-from-preview-b3a66f37.esm.js +508 -0
  75. package/dist/index-06c36775.cjs.js +14 -0
  76. package/dist/index-586adb8f.node.esm.js +11 -0
  77. package/dist/index-67d52357.esm.js +11 -0
  78. package/dist/index-c3223fdc.node.cjs.js +14 -0
  79. package/dist/layouts-6412fa2a.esm.js +189 -0
  80. package/dist/layouts-a4a3cf0b.node.cjs.js +196 -0
  81. package/dist/layouts-ba9a558b.cjs.js +196 -0
  82. package/dist/layouts-e653b908.node.esm.js +189 -0
  83. package/dist/lkb-fields-document.cjs.d.ts +2 -0
  84. package/dist/lkb-fields-document.cjs.js +1167 -0
  85. package/dist/lkb-fields-document.esm.js +1162 -0
  86. package/dist/lkb-fields-document.node.cjs.js +1167 -0
  87. package/dist/lkb-fields-document.node.esm.js +1162 -0
  88. package/dist/shared-0533009e.cjs.js +594 -0
  89. package/dist/shared-4684cc24.node.cjs.js +594 -0
  90. package/dist/shared-5e864055.node.esm.js +579 -0
  91. package/dist/shared-aaba5901.esm.js +579 -0
  92. package/dist/toolbar-state-3359e2f3.cjs.js +994 -0
  93. package/dist/toolbar-state-945823b8.node.esm.js +971 -0
  94. package/dist/toolbar-state-9611743f.node.cjs.js +994 -0
  95. package/dist/toolbar-state-bc8fe661.esm.js +971 -0
  96. package/dist/utils-06bcddc4.node.cjs.js +747 -0
  97. package/dist/utils-200ff260.node.esm.js +722 -0
  98. package/dist/utils-6409f730.cjs.js +747 -0
  99. package/dist/utils-bc6a0b82.esm.js +722 -0
  100. package/package.json +118 -0
  101. package/structure-views/dist/lkb-fields-document-structure-views.cjs.d.ts +2 -0
  102. package/structure-views/dist/lkb-fields-document-structure-views.cjs.js +138 -0
  103. package/structure-views/dist/lkb-fields-document-structure-views.esm.js +131 -0
  104. package/structure-views/dist/lkb-fields-document-structure-views.node.cjs.js +138 -0
  105. package/structure-views/dist/lkb-fields-document-structure-views.node.esm.js +131 -0
  106. package/structure-views/package.json +4 -0
  107. package/views/dist/lkb-fields-document-views.cjs.d.ts +2 -0
  108. package/views/dist/lkb-fields-document-views.cjs.js +114 -0
  109. package/views/dist/lkb-fields-document-views.esm.js +95 -0
  110. package/views/dist/lkb-fields-document-views.node.cjs.js +114 -0
  111. package/views/dist/lkb-fields-document-views.node.esm.js +95 -0
  112. package/views/package.json +4 -0
@@ -0,0 +1,1162 @@
1
+ import { g } from 'lkb-core';
2
+ import { fieldType } from 'lkb-core/types';
3
+ import { GraphQLError } from 'graphql';
4
+ import { a as assertNever, g as getInitialPropsValue } from './utils-200ff260.node.esm.js';
5
+ import { Editor, Text } from 'slate';
6
+ import { c as createDocumentEditor } from './editor-shared-a6e340e6.node.esm.js';
7
+ import { z } from 'zod';
8
+ import { i as isValidURL } from './index-586adb8f.node.esm.js';
9
+ import 'slate-history';
10
+ import '@emotion/weak-memoize';
11
+ import './shared-5e864055.node.esm.js';
12
+ import 'mdast-util-from-markdown';
13
+ import 'mdast-util-gfm-autolink-literal/from-markdown';
14
+ import 'micromark-extension-gfm-autolink-literal';
15
+ import 'mdast-util-gfm-strikethrough/from-markdown';
16
+ import 'micromark-extension-gfm-strikethrough';
17
+ import '@braintree/sanitize-url';
18
+
19
+ function assertValidComponentSchema(schema, lists, mode) {
20
+ assertValidComponentSchemaInner(schema, [], [], new Set(), lists, mode);
21
+ }
22
+
23
+ // recursive things can exist but they have to either be:
24
+ // - inside the non-default portion of a conditional field
25
+ // - inside an array field
26
+ // when we hit the non-default portion of a conditional field or an array field
27
+ // checking inside of it essentially means pretend it's a new thing
28
+ function assertValidComponentSchemaInner(schema, schemaAncestors, propPath, seenProps, lists, mode) {
29
+ if (schema.kind === 'form') {
30
+ if (mode === 'structure' && !schema.graphql) {
31
+ throw new Error(`There is a form field without a configured GraphQL schema at "${propPath.join('.')}", fields used in the structure field must have a GraphQL schema.`);
32
+ }
33
+ return;
34
+ }
35
+ if (schema.kind === 'child') {
36
+ if (mode === 'structure') {
37
+ throw new Error(`There is a child field at "${propPath.join('.')}" but child fields are not allowed in structure fields.`);
38
+ }
39
+ return;
40
+ }
41
+ if (schema.kind === 'relationship') {
42
+ if (lists.has(schema.listKey)) {
43
+ return;
44
+ }
45
+ throw new Error(`The relationship field at "${propPath.join('.')}" has the listKey "${schema.listKey}" but no list named "${schema.listKey}" exists.`);
46
+ }
47
+ const ancestor = schemaAncestors.indexOf(schema);
48
+ if (ancestor !== -1) {
49
+ throw new Error(`The field "${propPath.join('.')}" is the same as it's ancestor. Use an array or conditional field for recursive structures.`);
50
+ }
51
+ if (seenProps.has(schema)) {
52
+ return;
53
+ }
54
+ propPath.push(schema.kind);
55
+ try {
56
+ seenProps.add(schema);
57
+ if (schema.kind === 'array') {
58
+ assertValidComponentSchemaInner(schema.element, [], propPath, seenProps, lists, mode);
59
+ return;
60
+ }
61
+ if (schema.kind === 'object') {
62
+ schemaAncestors.push(schema);
63
+ for (const [key, innerProp] of Object.entries(schema.fields)) {
64
+ propPath.push(key);
65
+ if (schema.fields[key] !== innerProp) {
66
+ throw new Error(`Fields on an object field must not change over time but the field at "${propPath.join('.')}" changes between accesses`);
67
+ }
68
+ assertValidComponentSchemaInner(innerProp, schemaAncestors, propPath, seenProps, lists, mode);
69
+ propPath.pop();
70
+ }
71
+ schemaAncestors.pop();
72
+ return;
73
+ }
74
+ if (schema.kind === 'conditional') {
75
+ schemaAncestors.push(schema);
76
+ const stringifiedDefaultDiscriminant = schema.discriminant.defaultValue.toString();
77
+ for (const [key, innerProp] of Object.entries(schema.values)) {
78
+ propPath.push(key);
79
+ if (schema.values[key] !== innerProp) {
80
+ throw new Error(`Fields on a conditional field must not change over time but the field at "${propPath.join('.')}" changes between accesses`);
81
+ }
82
+ assertValidComponentSchemaInner(innerProp, key === stringifiedDefaultDiscriminant ? schemaAncestors : [], propPath, seenProps, lists, mode);
83
+ propPath.pop();
84
+ }
85
+ schemaAncestors.pop();
86
+ return;
87
+ }
88
+ } finally {
89
+ propPath.pop();
90
+ }
91
+ assertNever(schema);
92
+ }
93
+
94
+ const labelFieldAlias = '____document_field_relationship_item_label';
95
+ const idFieldAlias = '____document_field_relationship_item_id';
96
+ function addRelationshipData(nodes, context, relationships, componentBlocks) {
97
+ return Promise.all(nodes === null || nodes === void 0 ? void 0 : nodes.map(async node => {
98
+ if (node.type === 'relationship') {
99
+ const relationship = relationships[node.relationship];
100
+ if (!relationship) return node;
101
+ return {
102
+ ...node,
103
+ data: await fetchDataForOne(context, {
104
+ ...relationship,
105
+ many: false
106
+ }, node.data)
107
+ };
108
+ }
109
+ if (node.type === 'component-block') {
110
+ const componentBlock = componentBlocks[node.component];
111
+ if (componentBlock) {
112
+ const [props, children] = await Promise.all([addRelationshipDataToComponentProps({
113
+ kind: 'object',
114
+ fields: componentBlock.schema
115
+ }, node.props, (relationship, data) => fetchRelationshipData(context, relationship, data)), addRelationshipData(node.children, context, relationships, componentBlocks)]);
116
+ return {
117
+ ...node,
118
+ props,
119
+ children
120
+ };
121
+ }
122
+ }
123
+ if ('children' in node && Array.isArray(node.children)) {
124
+ return {
125
+ ...node,
126
+ children: await addRelationshipData(node.children, context, relationships, componentBlocks)
127
+ };
128
+ }
129
+ return node;
130
+ }));
131
+ }
132
+ async function fetchRelationshipData(context, relationship, data) {
133
+ var _relationship$labelFi;
134
+ if (!relationship.many) return fetchDataForOne(context, relationship, data);
135
+ const ids = Array.isArray(data) ? data.filter(item => item.id != null).map(x => x.id) : [];
136
+ if (!ids.length) return [];
137
+ const list = context.__internal.lists[relationship.listKey];
138
+ const {
139
+ listQueryName
140
+ } = list.graphql.names;
141
+ const labelField = (_relationship$labelFi = relationship.labelField) !== null && _relationship$labelFi !== void 0 ? _relationship$labelFi : list.ui.labelField;
142
+ const value = await context.graphql.run({
143
+ query: `query($ids: [ID!]!) {items:${listQueryName}(where: { id: { in: $ids } }) {${idFieldAlias}:id ${labelFieldAlias}:${labelField}\n${relationship.selection || ''}}}`,
144
+ variables: {
145
+ ids
146
+ }
147
+ });
148
+ return Array.isArray(value.items) ? value.items.map(({
149
+ [labelFieldAlias]: label,
150
+ [idFieldAlias]: id,
151
+ ...data
152
+ }) => {
153
+ return {
154
+ id,
155
+ label,
156
+ data
157
+ };
158
+ }) : [];
159
+ }
160
+ async function fetchDataForOne(context, relationship, data) {
161
+ var _relationship$labelFi2;
162
+ // Single related item
163
+ const id = data === null || data === void 0 ? void 0 : data.id;
164
+ if (id == null) return null;
165
+
166
+ // An exception here indicates something wrong with either the system or the
167
+ // configuration (e.g. a bad selection field). These will surface as system
168
+ // errors from the GraphQL field resolver.
169
+ const list = context.__internal.lists[relationship.listKey];
170
+ const {
171
+ itemQueryName
172
+ } = list.graphql.names;
173
+ const labelField = (_relationship$labelFi2 = relationship.labelField) !== null && _relationship$labelFi2 !== void 0 ? _relationship$labelFi2 : list.ui.labelField;
174
+ const value = await context.graphql.run({
175
+ query: `query($id: ID!) {item:${itemQueryName}(where: { id: $id }) {${labelFieldAlias}:${labelField}\n${relationship.selection || ''}}}`,
176
+ variables: {
177
+ id
178
+ }
179
+ });
180
+ if (value.item === null) return {
181
+ id,
182
+ data: undefined,
183
+ label: undefined
184
+ };
185
+ return {
186
+ id,
187
+ label: value.item[labelFieldAlias],
188
+ data: (() => {
189
+ const {
190
+ [labelFieldAlias]: _ignore,
191
+ ...otherData
192
+ } = value.item;
193
+ return otherData;
194
+ })()
195
+ };
196
+ }
197
+ async function addRelationshipDataToComponentProps(schema, value, fetchData) {
198
+ switch (schema.kind) {
199
+ case 'child':
200
+ return value;
201
+ case 'form':
202
+ return value;
203
+ case 'relationship':
204
+ return fetchData(schema, value);
205
+ case 'object':
206
+ {
207
+ return Object.fromEntries(await Promise.all(Object.keys(schema.fields).map(async key => [key,
208
+ // if val[key] === undefined, we know a new field was added to the schema
209
+ // but there is old data in the database that doesn't have the new field
210
+ // we're intentionally not just magically adding it because we may want to
211
+ // have a more optimised strategy of hydrating relationships so we don't
212
+ // want to add something unrelated that requires the current "traverse everything" strategy
213
+ value[key] === undefined ? undefined : await addRelationshipDataToComponentProps(schema.fields[key], value[key], fetchData)])));
214
+ }
215
+ case 'conditional':
216
+ {
217
+ return {
218
+ discriminant: value.discriminant,
219
+ value: await addRelationshipDataToComponentProps(schema.values[value.discriminant], value.value, fetchData)
220
+ };
221
+ }
222
+ case 'array':
223
+ {
224
+ return await Promise.all(value.map(async innerVal => addRelationshipDataToComponentProps(schema.element, innerVal, fetchData)));
225
+ }
226
+ }
227
+ assertNever(schema);
228
+ }
229
+
230
+ // leaf types
231
+ const zMarkValue = z.union([z.literal(true), z.undefined()]);
232
+ const zText = z.object({
233
+ type: z.never().optional(),
234
+ text: z.string(),
235
+ bold: zMarkValue,
236
+ italic: zMarkValue,
237
+ underline: zMarkValue,
238
+ strikethrough: zMarkValue,
239
+ code: zMarkValue,
240
+ superscript: zMarkValue,
241
+ subscript: zMarkValue,
242
+ keyboard: zMarkValue,
243
+ insertMenu: zMarkValue
244
+ }).strict();
245
+ const zTextAlign = z.union([z.undefined(), z.literal('center'), z.literal('end')]);
246
+
247
+ // recursive types
248
+ const zLink = z.object({
249
+ type: z.literal('link'),
250
+ href: z.string().refinement(isValidURL, val => ({
251
+ code: 'custom',
252
+ message: `Invalid URL: ${val}`
253
+ }))
254
+ }).strict();
255
+ const zHeading = z.object({
256
+ type: z.literal('heading'),
257
+ textAlign: zTextAlign,
258
+ level: z.union([z.literal(1), z.literal(2), z.literal(3), z.literal(4), z.literal(5), z.literal(6)])
259
+ }).strict();
260
+ const zParagraph = z.object({
261
+ type: z.literal('paragraph'),
262
+ textAlign: zTextAlign
263
+ }).strict();
264
+ const zBasicElement = type => z.object({
265
+ type: z.literal(type)
266
+ }).strict();
267
+ const zBasicElements = [zBasicElement('blockquote'), zBasicElement('layout-area'), zBasicElement('code'), zBasicElement('divider'), zBasicElement('list-item'), zBasicElement('list-item-content'), zBasicElement('ordered-list'), zBasicElement('unordered-list')];
268
+ const zLayout = z.object({
269
+ type: z.literal('layout'),
270
+ layout: z.array(z.number())
271
+ }).strict();
272
+ const zRelationshipData = z.object({
273
+ id: z.string(),
274
+ label: z.string().optional(),
275
+ data: z.record(z.string(), z.any()).optional()
276
+ }).strict();
277
+ const zRelationship = z.object({
278
+ type: z.literal('relationship'),
279
+ relationship: z.string(),
280
+ data: z.union([zRelationshipData, z.null()])
281
+ }).strict();
282
+ const zComponentBlock = z.object({
283
+ type: z.literal('component-block'),
284
+ component: z.string(),
285
+ props: z.record(z.string(), z.any())
286
+ }).strict();
287
+ const zComponentProp = type => z.object({
288
+ type: z.literal(type),
289
+ propPath: z.array(z.union([z.string(), z.number()])).optional()
290
+ }).strict();
291
+ const zComponentProps = [zComponentProp('component-block-prop'), zComponentProp('component-inline-prop')];
292
+ const zBlock = z.discriminatedUnion('type', [zComponentBlock.extend({
293
+ children: z.lazy(() => zChildren)
294
+ }), ...zComponentProps.map(prop => prop.extend({
295
+ children: z.lazy(() => zChildren)
296
+ })), ...zBasicElements.map(prop => prop.extend({
297
+ children: z.lazy(() => zChildren)
298
+ })), zHeading.extend({
299
+ children: z.lazy(() => zChildren)
300
+ }), zLayout.extend({
301
+ children: z.lazy(() => zChildren)
302
+ }), zParagraph.extend({
303
+ children: z.lazy(() => zChildren)
304
+ })]);
305
+ const zInline = z.discriminatedUnion('type', [zText, zLink.extend({
306
+ children: z.lazy(() => zChildren)
307
+ }), zRelationship.extend({
308
+ children: z.lazy(() => zChildren)
309
+ })]);
310
+ const zChildren = z.array(z.union([zBlock, zInline]));
311
+ const zDocument = z.array(zBlock);
312
+
313
+ // exports
314
+
315
+ function isRelationshipData(value) {
316
+ return zRelationshipData.safeParse(value).success;
317
+ }
318
+ function validateDocumentStructure(value) {
319
+ const result = zDocument.safeParse(value);
320
+ if (!result.success) {
321
+ throw new Error(`Invalid document structure: ${result.error.message}`);
322
+ }
323
+ }
324
+
325
+ class PropValidationError extends Error {
326
+ constructor(message, path) {
327
+ super(`${message} at ${path.join('.')}`);
328
+ this.path = path;
329
+ }
330
+ }
331
+ function validateComponentBlockProps(schema, value, relationships, path) {
332
+ if (schema.kind === 'form') {
333
+ value = value === undefined ? schema.defaultValue : value;
334
+ if (schema.validate(value)) {
335
+ return value;
336
+ }
337
+ throw new PropValidationError(`Invalid form prop value: ${JSON.stringify(value)}`, path);
338
+ }
339
+ if (schema.kind === 'child') {
340
+ return null;
341
+ }
342
+ if (schema.kind === 'relationship') {
343
+ if (schema.many) {
344
+ if (Array.isArray(value) && value.every(isRelationshipData)) {
345
+ // yes, ts understands this completely correctly, i'm as suprised as you are
346
+ return value.map(x => ({
347
+ id: x.id
348
+ }));
349
+ } else {
350
+ throw new PropValidationError(`Invalid relationship value: ${JSON.stringify(value)}`, path);
351
+ }
352
+ }
353
+ if (value === null || isRelationshipData(value)) {
354
+ return value === null ? null : {
355
+ id: value.id
356
+ };
357
+ } else {
358
+ throw new PropValidationError(`Invalid relationship value: ${JSON.stringify(value)}`, path);
359
+ }
360
+ }
361
+ if (schema.kind === 'conditional') {
362
+ if (typeof value !== 'object' || value === null) {
363
+ throw new PropValidationError(`Conditional value must be an object but is ${typeof value}`, path);
364
+ }
365
+ for (const key of Object.keys(value)) {
366
+ if (key !== 'discriminant' && key !== 'value') {
367
+ throw new PropValidationError(`Conditional value only allows keys named "discriminant" and "value", not "${key}"`, path);
368
+ }
369
+ }
370
+ const discriminant = value.discriminant;
371
+ const val = value.value;
372
+ // for some reason mongo or mongoose or something is saving undefined as null
373
+ // so we're doing this so that we avoid setting undefined on objects
374
+ const obj = {};
375
+ const discriminantVal = validateComponentBlockProps(schema.discriminant, discriminant, relationships, path.concat('discriminant'));
376
+ if (discriminantVal !== undefined) {
377
+ obj.discriminant = discriminantVal;
378
+ }
379
+ const conditionalFieldValue = validateComponentBlockProps(schema.values[discriminant], val, relationships, path.concat('value'));
380
+ if (conditionalFieldValue !== undefined) {
381
+ obj.value = conditionalFieldValue;
382
+ }
383
+ return obj;
384
+ }
385
+ if (schema.kind === 'object') {
386
+ if (typeof value !== 'object' || value === null) {
387
+ throw new PropValidationError(`Object value must be an object but is ${typeof value}`, path);
388
+ }
389
+ const val = {};
390
+ for (const key of Object.keys(schema.fields)) {
391
+ const propVal = validateComponentBlockProps(schema.fields[key], value[key], relationships, path.concat(key));
392
+ // for some reason mongo or mongoose or something is saving undefined as null
393
+ // so we're doing this so that we avoid setting undefined on objects
394
+ if (propVal !== undefined) {
395
+ val[key] = propVal;
396
+ }
397
+ }
398
+ return val;
399
+ }
400
+ if (schema.kind === 'array') {
401
+ if (!Array.isArray(value)) {
402
+ throw new PropValidationError(`Array field value must be an array but is ${typeof value}`, path);
403
+ }
404
+ return value.map((innerVal, i) => {
405
+ return validateComponentBlockProps(schema.element, innerVal, relationships, path.concat(i));
406
+ });
407
+ }
408
+ assertNever(schema);
409
+ }
410
+ function isText(node) {
411
+ return Text.isText(node);
412
+ }
413
+
414
+ // note that the errors thrown from here will only be exposed
415
+ // as internal server error from the graphql api in prod
416
+ // this is fine because these cases are pretty much all about
417
+ // malicious content being inserted, not valid content
418
+ function getValidatedNodeWithNormalizedComponentFormProps(node, componentBlocks, relationships) {
419
+ if (isText(node)) return node;
420
+ if (node.type === 'component-block') {
421
+ if (Object.prototype.hasOwnProperty.call(componentBlocks, node.component)) {
422
+ const componentBlock = componentBlocks[node.component];
423
+ node = {
424
+ ...node,
425
+ props: validateComponentBlockProps({
426
+ kind: 'object',
427
+ fields: componentBlock.schema
428
+ }, node.props, relationships, [])
429
+ };
430
+ }
431
+ }
432
+ if (node.type === 'relationship') {
433
+ var _node$data;
434
+ node = {
435
+ type: 'relationship',
436
+ data: ((_node$data = node.data) === null || _node$data === void 0 ? void 0 : _node$data.id) !== undefined ? {
437
+ id: node.data.id,
438
+ data: undefined,
439
+ label: undefined
440
+ } : null,
441
+ relationship: node.relationship,
442
+ children: node.children
443
+ };
444
+ }
445
+ return {
446
+ ...node,
447
+ children: node.children.map(x => getValidatedNodeWithNormalizedComponentFormProps(x, componentBlocks, relationships))
448
+ };
449
+ }
450
+ function validateAndNormalizeDocument(value, documentFeatures, componentBlocks, relationships) {
451
+ validateDocumentStructure(value);
452
+ const children = value.map(x => getValidatedNodeWithNormalizedComponentFormProps(x, componentBlocks, relationships));
453
+ const editor = createDocumentEditor(documentFeatures, componentBlocks, relationships);
454
+ editor.children = children;
455
+ Editor.normalize(editor, {
456
+ force: true
457
+ });
458
+ return editor.children;
459
+ }
460
+
461
+ function normaliseDocumentFeatures(config) {
462
+ var _config$formatting;
463
+ const {
464
+ alignment,
465
+ blockTypes,
466
+ headingLevels,
467
+ inlineMarks,
468
+ listTypes,
469
+ softBreaks
470
+ } = typeof config.formatting === 'boolean' ? {
471
+ alignment: config.formatting,
472
+ blockTypes: config.formatting,
473
+ headingLevels: config.formatting,
474
+ inlineMarks: config.formatting,
475
+ listTypes: config.formatting,
476
+ softBreaks: config.formatting
477
+ } : (_config$formatting = config.formatting) !== null && _config$formatting !== void 0 ? _config$formatting : {};
478
+ const documentFeatures = {
479
+ formatting: {
480
+ alignment: {
481
+ center: typeof alignment === 'boolean' ? alignment : !!(alignment !== null && alignment !== void 0 && alignment.center),
482
+ end: typeof alignment === 'boolean' ? alignment : !!(alignment !== null && alignment !== void 0 && alignment.end)
483
+ },
484
+ blockTypes: {
485
+ blockquote: typeof blockTypes === 'boolean' ? blockTypes : !!(blockTypes !== null && blockTypes !== void 0 && blockTypes.blockquote),
486
+ code: typeof blockTypes === 'boolean' ? blockTypes : !!(blockTypes !== null && blockTypes !== void 0 && blockTypes.code)
487
+ },
488
+ headingLevels: typeof headingLevels === 'boolean' ? [1, 2, 3, 4, 5, 6].filter(_ => headingLevels) : [...new Set(headingLevels)].sort(),
489
+ inlineMarks: {
490
+ bold: typeof inlineMarks === 'boolean' ? inlineMarks : !!(inlineMarks !== null && inlineMarks !== void 0 && inlineMarks.bold),
491
+ code: typeof inlineMarks === 'boolean' ? inlineMarks : !!(inlineMarks !== null && inlineMarks !== void 0 && inlineMarks.code),
492
+ italic: typeof inlineMarks === 'boolean' ? inlineMarks : !!(inlineMarks !== null && inlineMarks !== void 0 && inlineMarks.italic),
493
+ strikethrough: typeof inlineMarks === 'boolean' ? inlineMarks : !!(inlineMarks !== null && inlineMarks !== void 0 && inlineMarks.strikethrough),
494
+ underline: typeof inlineMarks === 'boolean' ? inlineMarks : !!(inlineMarks !== null && inlineMarks !== void 0 && inlineMarks.underline),
495
+ keyboard: typeof inlineMarks === 'boolean' ? inlineMarks : !!(inlineMarks !== null && inlineMarks !== void 0 && inlineMarks.keyboard),
496
+ subscript: typeof inlineMarks === 'boolean' ? inlineMarks : !!(inlineMarks !== null && inlineMarks !== void 0 && inlineMarks.subscript),
497
+ superscript: typeof inlineMarks === 'boolean' ? inlineMarks : !!(inlineMarks !== null && inlineMarks !== void 0 && inlineMarks.superscript)
498
+ },
499
+ listTypes: {
500
+ ordered: typeof listTypes === 'boolean' ? listTypes : !!(listTypes !== null && listTypes !== void 0 && listTypes.ordered),
501
+ unordered: typeof listTypes === 'boolean' ? listTypes : !!(listTypes !== null && listTypes !== void 0 && listTypes.unordered)
502
+ },
503
+ softBreaks: typeof softBreaks === 'boolean' ? softBreaks : !!softBreaks
504
+ },
505
+ links: !!config.links,
506
+ layouts: [...new Set((config.layouts || []).map(x => JSON.stringify(x)))].map(x => JSON.parse(x)),
507
+ dividers: !!config.dividers
508
+ };
509
+ return documentFeatures;
510
+ }
511
+
512
+ function normaliseRelationships(configRelationships, meta) {
513
+ if (!configRelationships) return {};
514
+ const relationships = {};
515
+ for (const [key, relationship] of Object.entries(configRelationships)) {
516
+ var _relationship$labelFi, _relationship$selecti;
517
+ if (meta.lists[relationship.listKey] === undefined) {
518
+ throw new Error(`An inline relationship ${relationship.label} (${key}) in the field at ${meta.listKey}.${meta.fieldKey} has listKey set to "${relationship.listKey}" but no list named "${relationship.listKey}" exists.`);
519
+ }
520
+ relationships[key] = {
521
+ ...relationship,
522
+ labelField: (_relationship$labelFi = relationship.labelField) !== null && _relationship$labelFi !== void 0 ? _relationship$labelFi : null,
523
+ selection: (_relationship$selecti = relationship.selection) !== null && _relationship$selecti !== void 0 ? _relationship$selecti : null
524
+ };
525
+ }
526
+ return relationships;
527
+ }
528
+
529
+ function document({
530
+ componentBlocks = {},
531
+ dividers,
532
+ formatting,
533
+ layouts,
534
+ relationships: configRelationships,
535
+ links,
536
+ ...config
537
+ } = {}) {
538
+ return meta => {
539
+ var _config$db, _config$db2;
540
+ const documentFeatures = normaliseDocumentFeatures({
541
+ dividers,
542
+ formatting,
543
+ layouts,
544
+ links
545
+ });
546
+ const relationships = normaliseRelationships(configRelationships, meta);
547
+ const inputResolver = data => {
548
+ if (data === null) throw new GraphQLError('Input error: Document fields cannot be set to null');
549
+ if (data === undefined) return data;
550
+ return validateAndNormalizeDocument(data, documentFeatures, componentBlocks, relationships);
551
+ };
552
+ if (config.isIndexed === 'unique') {
553
+ throw Error("isIndexed: 'unique' is not a supported option for field type document");
554
+ }
555
+ const lists = new Set(Object.keys(meta.lists));
556
+ for (const [name, block] of Object.entries(componentBlocks)) {
557
+ try {
558
+ assertValidComponentSchema({
559
+ kind: 'object',
560
+ fields: block.schema
561
+ }, lists, 'document');
562
+ } catch (err) {
563
+ throw new Error(`Component block ${name} in ${meta.listKey}.${meta.fieldKey}: ${err.message}`);
564
+ }
565
+ }
566
+ const defaultValue = [{
567
+ type: 'paragraph',
568
+ children: [{
569
+ text: ''
570
+ }]
571
+ }];
572
+ return fieldType({
573
+ kind: 'scalar',
574
+ scalar: 'Json',
575
+ mode: 'required',
576
+ default: meta.provider === 'sqlite' ? undefined : {
577
+ kind: 'literal',
578
+ // TODO: waiting on https://github.com/prisma/prisma/issues/26571
579
+ // input.create manages defaultValues anyway
580
+ value: JSON.stringify(defaultValue !== null && defaultValue !== void 0 ? defaultValue : null)
581
+ },
582
+ map: (_config$db = config.db) === null || _config$db === void 0 ? void 0 : _config$db.map,
583
+ extendPrismaSchema: (_config$db2 = config.db) === null || _config$db2 === void 0 ? void 0 : _config$db2.extendPrismaSchema
584
+ })({
585
+ ...config,
586
+ input: {
587
+ create: {
588
+ arg: g.arg({
589
+ type: g.JSON
590
+ }),
591
+ resolve(val) {
592
+ if (val === undefined) {
593
+ val = defaultValue;
594
+ }
595
+ return inputResolver(val);
596
+ }
597
+ },
598
+ update: {
599
+ arg: g.arg({
600
+ type: g.JSON
601
+ }),
602
+ resolve: inputResolver
603
+ }
604
+ },
605
+ output: g.field({
606
+ type: g.object()({
607
+ name: `${meta.listKey}_${meta.fieldKey}_Document`,
608
+ fields: {
609
+ document: g.field({
610
+ args: {
611
+ hydrateRelationships: g.arg({
612
+ type: g.nonNull(g.Boolean),
613
+ defaultValue: false
614
+ })
615
+ },
616
+ type: g.nonNull(g.JSON),
617
+ resolve({
618
+ document
619
+ }, {
620
+ hydrateRelationships
621
+ }, context) {
622
+ return hydrateRelationships ? addRelationshipData(document, context, relationships, componentBlocks) : document;
623
+ }
624
+ })
625
+ }
626
+ }),
627
+ resolve({
628
+ value
629
+ }) {
630
+ if (value === null) return null;
631
+ return {
632
+ document: value
633
+ };
634
+ }
635
+ }),
636
+ views: 'lkb-fields-document/views',
637
+ getAdminMeta() {
638
+ return {
639
+ relationships,
640
+ documentFeatures,
641
+ componentBlocksPassedOnServer: Object.keys(componentBlocks)
642
+ };
643
+ }
644
+ });
645
+ };
646
+ }
647
+
648
+ function getGraphQLInputType(name, schema, operation, cache, meta) {
649
+ if (!cache.has(schema)) {
650
+ const res = getGraphQLInputTypeInner(name, schema, operation, cache, meta);
651
+ cache.set(schema, res);
652
+ }
653
+ return cache.get(schema);
654
+ }
655
+ function getGraphQLInputTypeInner(name, schema, operation, cache, meta) {
656
+ if (schema.kind === 'form') {
657
+ if (!schema.graphql) {
658
+ throw new Error(`Field at ${name} is missing a graphql field`);
659
+ }
660
+ return schema.graphql.input;
661
+ }
662
+ if (schema.kind === 'object') {
663
+ const input = g.inputObject({
664
+ name: `${name}${operation[0].toUpperCase()}${operation.slice(1)}Input`,
665
+ fields: () => Object.fromEntries(Object.entries(schema.fields).map(([key, val]) => {
666
+ const type = getGraphQLInputType(`${name}${key[0].toUpperCase()}${key.slice(1)}`, val, operation, cache, meta);
667
+ return [key, g.arg({
668
+ type
669
+ })];
670
+ }))
671
+ });
672
+ return input;
673
+ }
674
+ if (schema.kind === 'array') {
675
+ const innerType = getGraphQLInputType(name, schema.element, operation, cache, meta);
676
+ return g.list(innerType);
677
+ }
678
+ if (schema.kind === 'conditional') {
679
+ const input = g.inputObject({
680
+ name: `${name}${operation[0].toUpperCase()}${operation.slice(1)}Input`,
681
+ fields: () => Object.fromEntries(Object.entries(schema.values).map(([key, val]) => {
682
+ const type = getGraphQLInputType(`${name}${key[0].toUpperCase()}${key.slice(1)}`, val, operation, cache, meta);
683
+ return [key, g.arg({
684
+ type
685
+ })];
686
+ }))
687
+ });
688
+ return input;
689
+ }
690
+ if (schema.kind === 'relationship') {
691
+ const inputType = meta.lists[schema.listKey].types.relateTo[schema.many ? 'many' : 'one'][operation];
692
+ // there are cases where this won't exist
693
+ // for example if gql omit is enabled on the related field
694
+ if (inputType === undefined) {
695
+ throw new Error('');
696
+ }
697
+ return inputType;
698
+ }
699
+ if (schema.kind === 'child') {
700
+ throw new Error(`Child fields are not supported in the structure field, found one at ${name}`);
701
+ }
702
+ assertNever(schema);
703
+ }
704
+ async function getValueForUpdate(schema, value, prevValue, context, path) {
705
+ if (value === undefined) return prevValue;
706
+ if (prevValue === undefined) {
707
+ prevValue = getInitialPropsValue(schema);
708
+ }
709
+ if (schema.kind === 'form') {
710
+ if (schema.validate(value)) return value;
711
+ throw new Error(`The value of the form field at '${path.join('.')}' is invalid`);
712
+ }
713
+ if (value === null) {
714
+ throw new Error(`${schema.kind[0].toUpperCase() + schema.kind.slice(1)} fields cannot be set to null but the field at '${path.join('.')}' is null`);
715
+ }
716
+ if (schema.kind === 'object') {
717
+ return Object.fromEntries(await Promise.all(Object.entries(schema.fields).map(async ([key, val]) => {
718
+ return [key, await getValueForUpdate(val, value[key], prevValue[key], context, path.concat(key))];
719
+ })));
720
+ }
721
+ if (schema.kind === 'array') {
722
+ return Promise.all(value.map((val, i) => getValueForUpdate(schema.element, val, prevValue[i], context, path.concat(i))));
723
+ }
724
+ if (schema.kind === 'relationship') {
725
+ if (schema.many) {
726
+ const val = value;
727
+ return resolveRelateToManyForUpdateInput(val, context, schema.listKey, prevValue);
728
+ } else {
729
+ const val = value;
730
+ return resolveRelateToOneForUpdateInput(val, context, schema.listKey);
731
+ }
732
+ }
733
+ if (schema.kind === 'conditional') {
734
+ const conditionalValueKeys = Object.keys(value);
735
+ if (conditionalValueKeys.length !== 1) {
736
+ throw new Error(`Conditional field inputs must set exactly one of the fields but the field at ${path.join('.')} has ${conditionalValueKeys.length} fields set`);
737
+ }
738
+ const key = conditionalValueKeys[0];
739
+ let discriminant = key;
740
+ if ((key === 'true' || key === 'false') && !schema.discriminant.validate(key)) {
741
+ discriminant = key === 'true';
742
+ }
743
+ return {
744
+ discriminant,
745
+ value: await getValueForUpdate(schema.values[key], value[key], prevValue.discriminant === discriminant ? prevValue.value : getInitialPropsValue(schema), context, path.concat('value'))
746
+ };
747
+ }
748
+ if (schema.kind === 'child') {
749
+ throw new Error(`Child fields are not supported in the structure field, found one at ${path.join('.')}`);
750
+ }
751
+ assertNever(schema);
752
+ }
753
+ async function getValueForCreate(schema, value, context, path) {
754
+ // If value is undefined, get the specified defaultValue
755
+ if (value === undefined) return getInitialPropsValue(schema);
756
+ if (schema.kind === 'form') {
757
+ if (schema.validate(value)) return value;
758
+ throw new Error(`The value of the form field at '${path.join('.')}' is invalid`);
759
+ }
760
+ if (value === null) {
761
+ throw new Error(`${schema.kind[0].toUpperCase() + schema.kind.slice(1)} fields cannot be set to null but the field at '${path.join('.')}' is null`);
762
+ }
763
+ if (schema.kind === 'array') {
764
+ return Promise.all(value.map((val, i) => getValueForCreate(schema.element, val, context, path.concat(i))));
765
+ }
766
+ if (schema.kind === 'object') {
767
+ return Object.fromEntries(await Promise.all(Object.entries(schema.fields).map(async ([key, val]) => {
768
+ return [key, await getValueForCreate(val, value[key], context, path.concat(key))];
769
+ })));
770
+ }
771
+ if (schema.kind === 'relationship') {
772
+ if (schema.many) {
773
+ const val = value;
774
+ return resolveRelateToManyForCreateInput(val, context, schema.listKey);
775
+ } else {
776
+ const val = value;
777
+ return resolveRelateToOneForCreateInput(val, context, schema.listKey);
778
+ }
779
+ }
780
+ if (schema.kind === 'conditional') {
781
+ if (value === null) throw new Error();
782
+ const conditionalValueKeys = Object.keys(value);
783
+ if (conditionalValueKeys.length !== 1) throw new Error();
784
+ const key = conditionalValueKeys[0];
785
+ let discriminant = key;
786
+ if ((key === 'true' || key === 'false') && !schema.discriminant.validate(key)) {
787
+ discriminant = key === 'true';
788
+ }
789
+ return {
790
+ discriminant,
791
+ value: await getValueForCreate(schema.values[key], value[key], context, path.concat('value'))
792
+ };
793
+ }
794
+ if (schema.kind === 'child') {
795
+ throw new Error(`Child fields are not supported in the structure field, found one at ${path.join('.')}`);
796
+ }
797
+ assertNever(schema);
798
+ }
799
+ /** MANY */
800
+
801
+ class RelationshipErrors extends Error {
802
+ constructor(errors) {
803
+ super('Multiple relationship errors');
804
+ this.errors = errors;
805
+ }
806
+ }
807
+ function getResolvedUniqueWheres(uniqueInputs, context, foreignListKey, operation) {
808
+ return uniqueInputs.map(uniqueInput => checkUniqueItemExists(uniqueInput, foreignListKey, context, operation));
809
+ }
810
+
811
+ // these aren't here out of thinking this is better syntax(i do not think it is),
812
+ // it's just because TS won't infer the arg is X bit
813
+ const isFulfilled = arg => arg.status === 'fulfilled';
814
+ const isRejected = arg => arg.status === 'rejected';
815
+ async function resolveRelateToManyForCreateInput(value, context, foreignListKey, tag) {
816
+ if (!Array.isArray(value.connect) && !Array.isArray(value.create)) {
817
+ throw new Error(`You must provide "connect" or "create" in to-many relationship inputs for "create" operations.`);
818
+ }
819
+
820
+ // Perform queries for the connections
821
+ const connects = Promise.allSettled(getResolvedUniqueWheres(value.connect || [], context, foreignListKey, 'connect'));
822
+
823
+ // Perform nested mutations for the creations
824
+ const creates = Promise.allSettled((value.create || []).map(x => resolveCreateMutation(x, context, foreignListKey)));
825
+ const [connectResult, createResult] = await Promise.all([connects, creates]);
826
+
827
+ // Collect all the errors
828
+ const errors = [...connectResult, ...createResult].filter(isRejected);
829
+ if (errors.length) {
830
+ // readd tag
831
+ throw new RelationshipErrors(errors.map(x => ({
832
+ error: x.reason,
833
+ tag: tag || ''
834
+ })));
835
+ }
836
+
837
+ // Perform queries for the connections
838
+ return [...connectResult, ...createResult].filter(isFulfilled).map(x => x.value);
839
+ }
840
+ async function resolveRelateToManyForUpdateInput(value, context, foreignListKey, prevVal) {
841
+ if (!Array.isArray(value.connect) && !Array.isArray(value.create) && !Array.isArray(value.disconnect) && !Array.isArray(value.set)) {
842
+ throw new Error(`You must provide at least one of "set", "connect", "create" or "disconnect" in to-many relationship inputs for "update" operations.`);
843
+ }
844
+ if (value.set && value.disconnect) {
845
+ throw new Error(`The "set" and "disconnect" fields cannot both be provided to to-many relationship inputs for "update" operations.`);
846
+ }
847
+
848
+ // Perform queries for the connections
849
+ const connects = Promise.allSettled(getResolvedUniqueWheres(value.connect || [], context, foreignListKey, 'connect'));
850
+ const disconnects = Promise.allSettled(getResolvedUniqueWheres(value.disconnect || [], context, foreignListKey, 'disconnect'));
851
+ const sets = Promise.allSettled(getResolvedUniqueWheres(value.set || [], context, foreignListKey, 'set'));
852
+
853
+ // Perform nested mutations for the creations
854
+ const creates = Promise.allSettled((value.create || []).map(x => resolveCreateMutation(x, context, foreignListKey)));
855
+ const [connectResult, createResult, disconnectResult, setResult] = await Promise.all([connects, creates, disconnects, sets]);
856
+
857
+ // Collect all the errors
858
+ const errors = [...connectResult, ...createResult, ...disconnectResult, ...setResult].filter(isRejected);
859
+ if (errors.length) throw new RelationshipErrors(errors.map(x => ({
860
+ error: x.reason,
861
+ tag: ''
862
+ })));
863
+ let values = prevVal;
864
+ if (value.set) {
865
+ values = setResult.filter(isFulfilled).map(x => x.value);
866
+ }
867
+ const idsToDisconnect = new Set(disconnectResult.filter(isFulfilled).map(x => x.value.id));
868
+ values = values.filter(x => !idsToDisconnect.has(x.id));
869
+ values.push(...connectResult.filter(isFulfilled).map(x => x.value));
870
+ values.push(...createResult.filter(isFulfilled).map(x => x.value));
871
+ return values;
872
+ }
873
+
874
+ /** ONE */
875
+
876
+ function missingItem(operation, uniqueWhere) {
877
+ throw new Error(`You cannot ${operation} the item '${JSON.stringify(uniqueWhere)}' - it may not exist`);
878
+ }
879
+ async function checkUniqueItemExists(uniqueInput, listKey, context, operation) {
880
+ // Check whether the item exists (from this users POV).
881
+ const item = await context.db[listKey].findOne({
882
+ where: uniqueInput
883
+ });
884
+ if (item === null) throw missingItem(operation, uniqueInput);
885
+ return {
886
+ id: item.id.toString()
887
+ };
888
+ }
889
+ async function handleCreateAndUpdate(value, context, foreignListKey) {
890
+ if (value.connect) return checkUniqueItemExists(value.connect, foreignListKey, context, 'connect');
891
+ return resolveCreateMutation(value, context, foreignListKey);
892
+ }
893
+ async function resolveCreateMutation(value, context, foreignListKey) {
894
+ const mutationType = context.graphql.schema.getMutationType();
895
+ const {
896
+ id
897
+ } = await mutationType.getFields()[context.__internal.lists[foreignListKey].graphql.names.createMutationName].resolve({}, {
898
+ data: value.create
899
+ }, context,
900
+ // we happen to know this isn't used
901
+ // no one else should rely on that though
902
+ // it could change in the future
903
+ {});
904
+ return {
905
+ id: id.toString()
906
+ };
907
+ }
908
+ function resolveRelateToOneForCreateInput(value, context, foreignListKey) {
909
+ const numOfKeys = Object.keys(value).length;
910
+ if (numOfKeys !== 1) throw new Error(`You must provide "connect" or "create" in to-one relationship inputs for "create" operations.`);
911
+ return handleCreateAndUpdate(value, context, foreignListKey);
912
+ }
913
+ function resolveRelateToOneForUpdateInput(value, context, foreignListKey) {
914
+ if (Object.keys(value).length !== 1) throw new Error(`You must provide one of "connect", "create" or "disconnect" in to-one relationship inputs for "update" operations.`);
915
+ if (value.connect || value.create) return handleCreateAndUpdate(value, context, foreignListKey);
916
+ if (value.disconnect) return null;
917
+ }
918
+
919
+ function wrapGraphQLFieldInResolver(inputField, getVal) {
920
+ return g.field({
921
+ type: inputField.type,
922
+ args: inputField.args,
923
+ deprecationReason: inputField.deprecationReason,
924
+ description: inputField.description,
925
+ extensions: inputField.extensions,
926
+ resolve(value, args, context, info) {
927
+ const val = getVal(value);
928
+ if (!inputField.resolve) {
929
+ return val;
930
+ }
931
+ return inputField.resolve({
932
+ value: val
933
+ }, args, context, info);
934
+ }
935
+ });
936
+ }
937
+ function getOutputGraphQLField(name, schema, interfaceImplementations, cache, meta) {
938
+ if (!cache.has(schema)) {
939
+ const res = getOutputGraphQLFieldInner(name, schema, interfaceImplementations, cache, meta);
940
+ cache.set(schema, res);
941
+ }
942
+ return cache.get(schema);
943
+ }
944
+ function getOutputGraphQLFieldInner(name, schema, interfaceImplementations, cache, meta) {
945
+ if (schema.kind === 'form') {
946
+ if (!schema.graphql) {
947
+ throw new Error(`Field at ${name} is missing a graphql field`);
948
+ }
949
+ return wrapGraphQLFieldInResolver(schema.graphql.output, x => x.value);
950
+ }
951
+ if (schema.kind === 'object') {
952
+ return g.field({
953
+ type: g.object()({
954
+ name,
955
+ fields: () => Object.fromEntries(Object.entries(schema.fields).map(([key, val]) => {
956
+ const field = getOutputGraphQLField(`${name}${key[0].toUpperCase()}${key.slice(1)}`, val, interfaceImplementations, cache, meta);
957
+ return [key, wrapGraphQLFieldInResolver(field, source => source[key])];
958
+ }))
959
+ }),
960
+ resolve({
961
+ value
962
+ }) {
963
+ return value;
964
+ }
965
+ });
966
+ }
967
+ if (schema.kind === 'array') {
968
+ const innerField = getOutputGraphQLField(name, schema.element, interfaceImplementations, cache, meta);
969
+ const resolve = innerField.resolve;
970
+ return g.field({
971
+ type: g.list(innerField.type),
972
+ args: innerField.args,
973
+ deprecationReason: innerField.deprecationReason,
974
+ description: innerField.description,
975
+ extensions: innerField.extensions,
976
+ resolve({
977
+ value
978
+ }, args, context, info) {
979
+ if (!resolve) {
980
+ return value;
981
+ }
982
+ return value.map(val => resolve({
983
+ value: val
984
+ }, args, context, info));
985
+ }
986
+ });
987
+ }
988
+ if (schema.kind === 'conditional') {
989
+ let discriminantField;
990
+ const getDiscriminantField = () => {
991
+ if (!discriminantField) {
992
+ discriminantField = getOutputGraphQLField(name + 'Discriminant', schema.discriminant, interfaceImplementations, cache, meta);
993
+ }
994
+ return discriminantField;
995
+ };
996
+ const interfaceType = g.interface()({
997
+ name,
998
+ resolveType: value => {
999
+ const stringifiedDiscriminant = value.discriminant.toString();
1000
+ return name + stringifiedDiscriminant[0].toUpperCase() + stringifiedDiscriminant.slice(1);
1001
+ },
1002
+ fields: () => ({
1003
+ discriminant: getDiscriminantField()
1004
+ })
1005
+ });
1006
+ interfaceImplementations.push(...Object.entries(schema.values).map(([key, val]) => {
1007
+ const innerName = name + key[0].toUpperCase() + key.slice(1);
1008
+ return g.object()({
1009
+ name: innerName,
1010
+ interfaces: [interfaceType],
1011
+ fields: () => ({
1012
+ discriminant: wrapGraphQLFieldInResolver(getDiscriminantField(), x => x.discriminant),
1013
+ value: getOutputGraphQLField(`${innerName}Value`, val, interfaceImplementations, cache, meta)
1014
+ })
1015
+ });
1016
+ }));
1017
+ return g.field({
1018
+ type: interfaceType,
1019
+ resolve({
1020
+ value
1021
+ }) {
1022
+ return value;
1023
+ }
1024
+ });
1025
+ }
1026
+ if (schema.kind === 'relationship') {
1027
+ const listOutputType = meta.lists[schema.listKey].types.output;
1028
+ return g.field({
1029
+ type: schema.many ? g.list(listOutputType) : listOutputType,
1030
+ resolve({
1031
+ value
1032
+ }, args, context) {
1033
+ if (Array.isArray(value)) {
1034
+ return context.db[schema.listKey].findMany({
1035
+ where: {
1036
+ id: {
1037
+ in: value.map(x => x.id)
1038
+ }
1039
+ }
1040
+ });
1041
+ }
1042
+ if ((value === null || value === void 0 ? void 0 : value.id) == null) {
1043
+ return null;
1044
+ }
1045
+ return context.db[schema.listKey].findOne({
1046
+ where: {
1047
+ id: value.id
1048
+ }
1049
+ });
1050
+ }
1051
+ });
1052
+ }
1053
+ if (schema.kind === 'child') {
1054
+ throw new Error('Child fields are not supported in the structure field');
1055
+ }
1056
+ assertNever(schema);
1057
+ }
1058
+
1059
+ function structure({
1060
+ schema,
1061
+ ...config
1062
+ }) {
1063
+ return meta => {
1064
+ var _config$hooks, _config$hooks2, _config$db, _config$hooks3, _config$hooks4;
1065
+ if (config.isIndexed === 'unique') {
1066
+ throw Error("isIndexed: 'unique' is not a supported option for field type structure");
1067
+ }
1068
+ const lists = new Set(Object.keys(meta.lists));
1069
+ try {
1070
+ assertValidComponentSchema(schema, lists, 'structure');
1071
+ } catch (err) {
1072
+ throw new Error(`${meta.listKey}.${meta.fieldKey}: ${err.message}`);
1073
+ }
1074
+ const defaultValue = getInitialPropsValue(schema);
1075
+ const unreferencedConcreteInterfaceImplementations = [];
1076
+ const name = meta.listKey + meta.fieldKey[0].toUpperCase() + meta.fieldKey.slice(1);
1077
+ const innerUpdate = typeof ((_config$hooks = config.hooks) === null || _config$hooks === void 0 ? void 0 : _config$hooks.resolveInput) === 'function' ? config.hooks.resolveInput : (_config$hooks2 = config.hooks) === null || _config$hooks2 === void 0 || (_config$hooks2 = _config$hooks2.resolveInput) === null || _config$hooks2 === void 0 ? void 0 : _config$hooks2.update;
1078
+ return fieldType({
1079
+ kind: 'scalar',
1080
+ scalar: 'Json',
1081
+ default: meta.provider === 'sqlite' ? undefined : {
1082
+ kind: 'literal',
1083
+ // TODO: waiting on https://github.com/prisma/prisma/issues/26571
1084
+ // input.create manages defaultValues anyway
1085
+ value: JSON.stringify(defaultValue !== null && defaultValue !== void 0 ? defaultValue : null)
1086
+ },
1087
+ map: (_config$db = config.db) === null || _config$db === void 0 ? void 0 : _config$db.map,
1088
+ mode: 'required'
1089
+ })({
1090
+ ...config,
1091
+ hooks: {
1092
+ ...config.hooks,
1093
+ resolveInput: {
1094
+ create: typeof ((_config$hooks3 = config.hooks) === null || _config$hooks3 === void 0 ? void 0 : _config$hooks3.resolveInput) === 'function' ? config.hooks.resolveInput : (_config$hooks4 = config.hooks) === null || _config$hooks4 === void 0 || (_config$hooks4 = _config$hooks4.resolveInput) === null || _config$hooks4 === void 0 ? void 0 : _config$hooks4.create,
1095
+ update: async args => {
1096
+ let val = args.resolvedData[meta.fieldKey];
1097
+ let prevVal = args.item[meta.fieldKey];
1098
+ val = await getValueForUpdate(schema, val, prevVal, args.context, []);
1099
+ return innerUpdate ? innerUpdate({
1100
+ ...args,
1101
+ resolvedData: {
1102
+ ...args.resolvedData,
1103
+ [meta.fieldKey]: val
1104
+ }
1105
+ }) : val;
1106
+ }
1107
+ }
1108
+ },
1109
+ input: {
1110
+ create: {
1111
+ arg: g.arg({
1112
+ type: getGraphQLInputType(name, schema, 'create', new Map(), meta)
1113
+ }),
1114
+ async resolve(val, context) {
1115
+ return await getValueForCreate(schema, val, context, []);
1116
+ }
1117
+ },
1118
+ update: {
1119
+ arg: g.arg({
1120
+ type: getGraphQLInputType(name, schema, 'update', new Map(), meta)
1121
+ }),
1122
+ resolve(val) {
1123
+ return val;
1124
+ }
1125
+ }
1126
+ },
1127
+ output: g.field({
1128
+ type: g.object()({
1129
+ name: `${name}Output`,
1130
+ fields: {
1131
+ structure: getOutputGraphQLField(name, schema, unreferencedConcreteInterfaceImplementations, new Map(), meta),
1132
+ json: g.field({
1133
+ type: g.JSON,
1134
+ args: {
1135
+ hydrateRelationships: g.arg({
1136
+ type: g.nonNull(g.Boolean),
1137
+ defaultValue: false
1138
+ })
1139
+ },
1140
+ resolve({
1141
+ value
1142
+ }, args, context) {
1143
+ if (!args.hydrateRelationships) return value;
1144
+ return addRelationshipDataToComponentProps(schema, value, (schema, value) => {
1145
+ return fetchRelationshipData(context, schema, value);
1146
+ });
1147
+ }
1148
+ })
1149
+ }
1150
+ }),
1151
+ resolve(source) {
1152
+ return source;
1153
+ }
1154
+ }),
1155
+ views: 'lkb-fields-document/structure-views',
1156
+ getAdminMeta: () => ({}),
1157
+ unreferencedConcreteInterfaceImplementations
1158
+ });
1159
+ };
1160
+ }
1161
+
1162
+ export { document, structure };