@payloadcms/graphql 3.28.0-internal.b3cf0a3 → 3.28.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.
@@ -0,0 +1,828 @@
1
+ import { GraphQLBoolean, GraphQLEnumType, GraphQLFloat, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLString, GraphQLUnionType } from 'graphql';
2
+ import { DateTimeResolver, EmailAddressResolver } from 'graphql-scalars';
3
+ import { combineQueries, createDataloaderCacheKey, MissingEditorProp, toWords } from 'payload';
4
+ import { tabHasName } from 'payload/shared';
5
+ import { GraphQLJSON } from '../packages/graphql-type-json/index.js';
6
+ import { combineParentName } from '../utilities/combineParentName.js';
7
+ import { formatName } from '../utilities/formatName.js';
8
+ import { formatOptions } from '../utilities/formatOptions.js';
9
+ import { buildObjectType } from './buildObjectType.js';
10
+ import { isFieldNullable } from './isFieldNullable.js';
11
+ import { withNullableType } from './withNullableType.js';
12
+ function formattedNameResolver({ field, ...rest }) {
13
+ if ('name' in field) {
14
+ if (formatName(field.name) !== field.name) {
15
+ return {
16
+ ...rest,
17
+ resolve: (parent)=>parent[field.name]
18
+ };
19
+ }
20
+ }
21
+ return rest;
22
+ }
23
+ export const fieldToSchemaMap = {
24
+ array: ({ config, field, forceNullable, graphqlResult, objectTypeConfig, parentIsLocalized, parentName })=>{
25
+ const interfaceName = field?.interfaceName || combineParentName(parentName, toWords(field.name, true));
26
+ if (!graphqlResult.types.arrayTypes[interfaceName]) {
27
+ const objectType = buildObjectType({
28
+ name: interfaceName,
29
+ config,
30
+ fields: field.fields,
31
+ forceNullable: isFieldNullable({
32
+ field,
33
+ forceNullable,
34
+ parentIsLocalized
35
+ }),
36
+ graphqlResult,
37
+ parentIsLocalized: field.localized || parentIsLocalized,
38
+ parentName: interfaceName
39
+ });
40
+ if (Object.keys(objectType.getFields()).length) {
41
+ graphqlResult.types.arrayTypes[interfaceName] = objectType;
42
+ }
43
+ }
44
+ if (!graphqlResult.types.arrayTypes[interfaceName]) {
45
+ return objectTypeConfig;
46
+ }
47
+ const arrayType = new GraphQLList(new GraphQLNonNull(graphqlResult.types.arrayTypes[interfaceName]));
48
+ return {
49
+ ...objectTypeConfig,
50
+ [formatName(field.name)]: formattedNameResolver({
51
+ type: withNullableType({
52
+ type: arrayType,
53
+ field,
54
+ parentIsLocalized
55
+ }),
56
+ field
57
+ })
58
+ };
59
+ },
60
+ blocks: ({ config, field, forceNullable, graphqlResult, objectTypeConfig, parentIsLocalized, parentName })=>{
61
+ const blockTypes = (field.blockReferences ?? field.blocks).reduce((acc, _block)=>{
62
+ const blockSlug = typeof _block === 'string' ? _block : _block.slug;
63
+ if (!graphqlResult.types.blockTypes[blockSlug]) {
64
+ // TODO: iterate over blocks mapped to block slug in v4, or pass through payload.blocks
65
+ const block = typeof _block === 'string' ? config.blocks.find((b)=>b.slug === _block) : _block;
66
+ const interfaceName = block?.interfaceName || block?.graphQL?.singularName || toWords(block.slug, true);
67
+ const objectType = buildObjectType({
68
+ name: interfaceName,
69
+ config,
70
+ fields: [
71
+ ...block.fields,
72
+ {
73
+ name: 'blockType',
74
+ type: 'text'
75
+ }
76
+ ],
77
+ forceNullable,
78
+ graphqlResult,
79
+ parentIsLocalized,
80
+ parentName: interfaceName
81
+ });
82
+ if (Object.keys(objectType.getFields()).length) {
83
+ graphqlResult.types.blockTypes[block.slug] = objectType;
84
+ }
85
+ }
86
+ if (graphqlResult.types.blockTypes[blockSlug]) {
87
+ acc.push(graphqlResult.types.blockTypes[blockSlug]);
88
+ }
89
+ return acc;
90
+ }, []);
91
+ if (blockTypes.length === 0) {
92
+ return objectTypeConfig;
93
+ }
94
+ const fullName = combineParentName(parentName, toWords(field.name, true));
95
+ const type = new GraphQLList(new GraphQLNonNull(new GraphQLUnionType({
96
+ name: fullName,
97
+ resolveType: (data)=>graphqlResult.types.blockTypes[data.blockType].name,
98
+ types: blockTypes
99
+ })));
100
+ return {
101
+ ...objectTypeConfig,
102
+ [formatName(field.name)]: formattedNameResolver({
103
+ type: withNullableType({
104
+ type,
105
+ field,
106
+ parentIsLocalized
107
+ }),
108
+ field
109
+ })
110
+ };
111
+ },
112
+ checkbox: ({ field, forceNullable, objectTypeConfig, parentIsLocalized })=>({
113
+ ...objectTypeConfig,
114
+ [formatName(field.name)]: formattedNameResolver({
115
+ type: withNullableType({
116
+ type: GraphQLBoolean,
117
+ field,
118
+ forceNullable,
119
+ parentIsLocalized
120
+ }),
121
+ field
122
+ })
123
+ }),
124
+ code: ({ field, forceNullable, objectTypeConfig, parentIsLocalized })=>({
125
+ ...objectTypeConfig,
126
+ [formatName(field.name)]: formattedNameResolver({
127
+ type: withNullableType({
128
+ type: GraphQLString,
129
+ field,
130
+ forceNullable,
131
+ parentIsLocalized
132
+ }),
133
+ field
134
+ })
135
+ }),
136
+ collapsible: ({ config, field, forceNullable, graphqlResult, newlyCreatedBlockType, objectTypeConfig, parentIsLocalized, parentName })=>field.fields.reduce((objectTypeConfigWithCollapsibleFields, subField)=>{
137
+ const addSubField = fieldToSchemaMap[subField.type];
138
+ if (addSubField) {
139
+ return addSubField({
140
+ config,
141
+ field: subField,
142
+ forceNullable,
143
+ graphqlResult,
144
+ newlyCreatedBlockType,
145
+ objectTypeConfig: objectTypeConfigWithCollapsibleFields,
146
+ parentIsLocalized,
147
+ parentName
148
+ });
149
+ }
150
+ return objectTypeConfigWithCollapsibleFields;
151
+ }, objectTypeConfig),
152
+ date: ({ field, forceNullable, objectTypeConfig, parentIsLocalized })=>({
153
+ ...objectTypeConfig,
154
+ [formatName(field.name)]: formattedNameResolver({
155
+ type: withNullableType({
156
+ type: DateTimeResolver,
157
+ field,
158
+ forceNullable,
159
+ parentIsLocalized
160
+ }),
161
+ field
162
+ })
163
+ }),
164
+ email: ({ field, forceNullable, objectTypeConfig, parentIsLocalized })=>({
165
+ ...objectTypeConfig,
166
+ [formatName(field.name)]: formattedNameResolver({
167
+ type: withNullableType({
168
+ type: EmailAddressResolver,
169
+ field,
170
+ forceNullable,
171
+ parentIsLocalized
172
+ }),
173
+ field
174
+ })
175
+ }),
176
+ group: ({ config, field, forceNullable, graphqlResult, objectTypeConfig, parentIsLocalized, parentName })=>{
177
+ const interfaceName = field?.interfaceName || combineParentName(parentName, toWords(field.name, true));
178
+ if (!graphqlResult.types.groupTypes[interfaceName]) {
179
+ const objectType = buildObjectType({
180
+ name: interfaceName,
181
+ config,
182
+ fields: field.fields,
183
+ forceNullable: isFieldNullable({
184
+ field,
185
+ forceNullable,
186
+ parentIsLocalized
187
+ }),
188
+ graphqlResult,
189
+ parentIsLocalized: field.localized || parentIsLocalized,
190
+ parentName: interfaceName
191
+ });
192
+ if (Object.keys(objectType.getFields()).length) {
193
+ graphqlResult.types.groupTypes[interfaceName] = objectType;
194
+ }
195
+ }
196
+ if (!graphqlResult.types.groupTypes[interfaceName]) {
197
+ return objectTypeConfig;
198
+ }
199
+ return {
200
+ ...objectTypeConfig,
201
+ [formatName(field.name)]: {
202
+ type: graphqlResult.types.groupTypes[interfaceName],
203
+ resolve: (parent, args, context)=>{
204
+ return {
205
+ ...parent[field.name],
206
+ _id: parent._id ?? parent.id
207
+ };
208
+ }
209
+ }
210
+ };
211
+ },
212
+ join: ({ field, graphqlResult, objectTypeConfig, parentName })=>{
213
+ const joinName = combineParentName(parentName, toWords(field.name, true));
214
+ const joinType = {
215
+ type: new GraphQLObjectType({
216
+ name: joinName,
217
+ fields: {
218
+ docs: {
219
+ type: Array.isArray(field.collection) ? GraphQLJSON : new GraphQLList(graphqlResult.collections[field.collection].graphQL.type)
220
+ },
221
+ hasNextPage: {
222
+ type: GraphQLBoolean
223
+ }
224
+ }
225
+ }),
226
+ args: {
227
+ limit: {
228
+ type: GraphQLInt
229
+ },
230
+ page: {
231
+ type: GraphQLInt
232
+ },
233
+ sort: {
234
+ type: GraphQLString
235
+ },
236
+ where: {
237
+ type: Array.isArray(field.collection) ? GraphQLJSON : graphqlResult.collections[field.collection].graphQL.whereInputType
238
+ }
239
+ },
240
+ extensions: {
241
+ complexity: typeof field?.graphQL?.complexity === 'number' ? field.graphQL.complexity : 10
242
+ },
243
+ async resolve (parent, args, context) {
244
+ const { collection } = field;
245
+ const { limit, page, sort, where } = args;
246
+ const { req } = context;
247
+ const fullWhere = combineQueries(where, {
248
+ [field.on]: {
249
+ equals: parent._id ?? parent.id
250
+ }
251
+ });
252
+ if (Array.isArray(collection)) {
253
+ throw new Error('GraphQL with array of join.field.collection is not implemented');
254
+ }
255
+ return await req.payload.find({
256
+ collection,
257
+ depth: 0,
258
+ fallbackLocale: req.fallbackLocale,
259
+ limit,
260
+ locale: req.locale,
261
+ overrideAccess: false,
262
+ page,
263
+ req,
264
+ sort,
265
+ where: fullWhere
266
+ });
267
+ }
268
+ };
269
+ return {
270
+ ...objectTypeConfig,
271
+ [formatName(field.name)]: joinType
272
+ };
273
+ },
274
+ json: ({ field, forceNullable, objectTypeConfig, parentIsLocalized })=>({
275
+ ...objectTypeConfig,
276
+ [formatName(field.name)]: formattedNameResolver({
277
+ type: withNullableType({
278
+ type: GraphQLJSON,
279
+ field,
280
+ forceNullable,
281
+ parentIsLocalized
282
+ }),
283
+ field
284
+ })
285
+ }),
286
+ number: ({ field, forceNullable, objectTypeConfig, parentIsLocalized })=>{
287
+ const type = field?.name === 'id' ? GraphQLInt : GraphQLFloat;
288
+ return {
289
+ ...objectTypeConfig,
290
+ [formatName(field.name)]: formattedNameResolver({
291
+ type: withNullableType({
292
+ type: field?.hasMany === true ? new GraphQLList(type) : type,
293
+ field,
294
+ forceNullable,
295
+ parentIsLocalized
296
+ }),
297
+ field
298
+ })
299
+ };
300
+ },
301
+ point: ({ field, forceNullable, objectTypeConfig, parentIsLocalized })=>({
302
+ ...objectTypeConfig,
303
+ [formatName(field.name)]: formattedNameResolver({
304
+ type: withNullableType({
305
+ type: new GraphQLList(new GraphQLNonNull(GraphQLFloat)),
306
+ field,
307
+ forceNullable,
308
+ parentIsLocalized
309
+ }),
310
+ field
311
+ })
312
+ }),
313
+ radio: ({ field, forceNullable, objectTypeConfig, parentIsLocalized, parentName })=>({
314
+ ...objectTypeConfig,
315
+ [formatName(field.name)]: formattedNameResolver({
316
+ type: withNullableType({
317
+ type: new GraphQLEnumType({
318
+ name: combineParentName(parentName, field.name),
319
+ values: formatOptions(field)
320
+ }),
321
+ field,
322
+ forceNullable,
323
+ parentIsLocalized
324
+ }),
325
+ field
326
+ })
327
+ }),
328
+ relationship: ({ config, field, forceNullable, graphqlResult, newlyCreatedBlockType, objectTypeConfig, parentIsLocalized, parentName })=>{
329
+ const { relationTo } = field;
330
+ const isRelatedToManyCollections = Array.isArray(relationTo);
331
+ const hasManyValues = field.hasMany;
332
+ const relationshipName = combineParentName(parentName, toWords(field.name, true));
333
+ let type;
334
+ let relationToType = null;
335
+ const graphQLCollections = config.collections.filter((collectionConfig)=>collectionConfig.graphQL !== false);
336
+ if (Array.isArray(relationTo)) {
337
+ relationToType = new GraphQLEnumType({
338
+ name: `${relationshipName}_RelationTo`,
339
+ values: relationTo.filter((relation)=>graphQLCollections.some((collection)=>collection.slug === relation)).reduce((relations, relation)=>({
340
+ ...relations,
341
+ [formatName(relation)]: {
342
+ value: relation
343
+ }
344
+ }), {})
345
+ });
346
+ // Only pass collections that are GraphQL enabled
347
+ const types = relationTo.filter((relation)=>graphQLCollections.some((collection)=>collection.slug === relation)).map((relation)=>graphqlResult.collections[relation]?.graphQL.type);
348
+ type = new GraphQLObjectType({
349
+ name: `${relationshipName}_Relationship`,
350
+ fields: {
351
+ relationTo: {
352
+ type: relationToType
353
+ },
354
+ value: {
355
+ type: new GraphQLUnionType({
356
+ name: relationshipName,
357
+ resolveType (data) {
358
+ return graphqlResult.collections[data.collection].graphQL.type.name;
359
+ },
360
+ types
361
+ })
362
+ }
363
+ }
364
+ });
365
+ } else {
366
+ ;
367
+ ({ type } = graphqlResult.collections[relationTo].graphQL);
368
+ }
369
+ // If the relationshipType is undefined at this point,
370
+ // it can be assumed that this blockType can have a relationship
371
+ // to itself. Therefore, we set the relationshipType equal to the blockType
372
+ // that is currently being created.
373
+ type = type || newlyCreatedBlockType;
374
+ const relationshipArgs = {};
375
+ const relationsUseDrafts = (Array.isArray(relationTo) ? relationTo : [
376
+ relationTo
377
+ ]).filter((relation)=>graphQLCollections.some((collection)=>collection.slug === relation)).some((relation)=>graphqlResult.collections[relation].config.versions?.drafts);
378
+ if (relationsUseDrafts) {
379
+ relationshipArgs.draft = {
380
+ type: GraphQLBoolean
381
+ };
382
+ }
383
+ if (config.localization) {
384
+ relationshipArgs.locale = {
385
+ type: graphqlResult.types.localeInputType
386
+ };
387
+ relationshipArgs.fallbackLocale = {
388
+ type: graphqlResult.types.fallbackLocaleInputType
389
+ };
390
+ }
391
+ const relationship = {
392
+ type: withNullableType({
393
+ type: hasManyValues ? new GraphQLList(new GraphQLNonNull(type)) : type,
394
+ field,
395
+ forceNullable,
396
+ parentIsLocalized
397
+ }),
398
+ args: relationshipArgs,
399
+ extensions: {
400
+ complexity: typeof field?.graphQL?.complexity === 'number' ? field.graphQL.complexity : 10
401
+ },
402
+ async resolve (parent, args, context) {
403
+ const value = parent[field.name];
404
+ const locale = args.locale || context.req.locale;
405
+ const fallbackLocale = args.fallbackLocale || context.req.fallbackLocale;
406
+ let relatedCollectionSlug = field.relationTo;
407
+ const draft = Boolean(args.draft ?? context.req.query?.draft);
408
+ if (hasManyValues) {
409
+ const results = [];
410
+ const resultPromises = [];
411
+ const createPopulationPromise = async (relatedDoc, i)=>{
412
+ let id = relatedDoc;
413
+ let collectionSlug = field.relationTo;
414
+ const isValidGraphQLCollection = isRelatedToManyCollections ? graphQLCollections.some((collection)=>collectionSlug.includes(collection.slug)) : graphQLCollections.some((collection)=>collectionSlug === collection.slug);
415
+ if (isValidGraphQLCollection) {
416
+ if (isRelatedToManyCollections) {
417
+ collectionSlug = relatedDoc.relationTo;
418
+ id = relatedDoc.value;
419
+ }
420
+ const result = await context.req.payloadDataLoader.load(createDataloaderCacheKey({
421
+ collectionSlug: collectionSlug,
422
+ currentDepth: 0,
423
+ depth: 0,
424
+ docID: id,
425
+ draft,
426
+ fallbackLocale,
427
+ locale,
428
+ overrideAccess: false,
429
+ showHiddenFields: false,
430
+ transactionID: context.req.transactionID
431
+ }));
432
+ if (result) {
433
+ if (isRelatedToManyCollections) {
434
+ results[i] = {
435
+ relationTo: collectionSlug,
436
+ value: {
437
+ ...result,
438
+ collection: collectionSlug
439
+ }
440
+ };
441
+ } else {
442
+ results[i] = result;
443
+ }
444
+ }
445
+ }
446
+ };
447
+ if (value) {
448
+ value.forEach((relatedDoc, i)=>{
449
+ resultPromises.push(createPopulationPromise(relatedDoc, i));
450
+ });
451
+ }
452
+ await Promise.all(resultPromises);
453
+ return results;
454
+ }
455
+ let id = value;
456
+ if (isRelatedToManyCollections && value) {
457
+ id = value.value;
458
+ relatedCollectionSlug = value.relationTo;
459
+ }
460
+ if (id) {
461
+ if (graphQLCollections.some((collection)=>collection.slug === relatedCollectionSlug)) {
462
+ const relatedDocument = await context.req.payloadDataLoader.load(createDataloaderCacheKey({
463
+ collectionSlug: relatedCollectionSlug,
464
+ currentDepth: 0,
465
+ depth: 0,
466
+ docID: id,
467
+ draft,
468
+ fallbackLocale,
469
+ locale,
470
+ overrideAccess: false,
471
+ showHiddenFields: false,
472
+ transactionID: context.req.transactionID
473
+ }));
474
+ if (relatedDocument) {
475
+ if (isRelatedToManyCollections) {
476
+ return {
477
+ relationTo: relatedCollectionSlug,
478
+ value: {
479
+ ...relatedDocument,
480
+ collection: relatedCollectionSlug
481
+ }
482
+ };
483
+ }
484
+ return relatedDocument;
485
+ }
486
+ }
487
+ return null;
488
+ }
489
+ return null;
490
+ }
491
+ };
492
+ return {
493
+ ...objectTypeConfig,
494
+ [formatName(field.name)]: relationship
495
+ };
496
+ },
497
+ richText: ({ config, field, forceNullable, objectTypeConfig, parentIsLocalized })=>({
498
+ ...objectTypeConfig,
499
+ [formatName(field.name)]: {
500
+ type: withNullableType({
501
+ type: GraphQLJSON,
502
+ field,
503
+ forceNullable,
504
+ parentIsLocalized
505
+ }),
506
+ args: {
507
+ depth: {
508
+ type: GraphQLInt
509
+ }
510
+ },
511
+ async resolve (parent, args, context) {
512
+ let depth = config.defaultDepth;
513
+ if (typeof args.depth !== 'undefined') {
514
+ depth = args.depth;
515
+ }
516
+ if (!field?.editor) {
517
+ throw new MissingEditorProp(field) // while we allow disabling editor functionality, you should not have any richText fields defined if you do not have an editor
518
+ ;
519
+ }
520
+ if (typeof field?.editor === 'function') {
521
+ throw new Error('Attempted to access unsanitized rich text editor.');
522
+ }
523
+ const editor = field?.editor;
524
+ // RichText fields have their own depth argument in GraphQL.
525
+ // This is why the populationPromise (which populates richtext fields like uploads and relationships)
526
+ // is run here again, with the provided depth.
527
+ // In the graphql find.ts resolver, the depth is then hard-coded to 0.
528
+ // Effectively, this means that the populationPromise for GraphQL is only run here, and not in the find.ts resolver / normal population promise.
529
+ if (editor?.graphQLPopulationPromises) {
530
+ const fieldPromises = [];
531
+ const populationPromises = [];
532
+ const populateDepth = field?.maxDepth !== undefined && field?.maxDepth < depth ? field?.maxDepth : depth;
533
+ editor?.graphQLPopulationPromises({
534
+ context,
535
+ depth: populateDepth,
536
+ draft: args.draft,
537
+ field,
538
+ fieldPromises,
539
+ findMany: false,
540
+ flattenLocales: false,
541
+ overrideAccess: false,
542
+ parentIsLocalized,
543
+ populationPromises,
544
+ req: context.req,
545
+ showHiddenFields: false,
546
+ siblingDoc: parent
547
+ });
548
+ await Promise.all(fieldPromises);
549
+ await Promise.all(populationPromises);
550
+ }
551
+ return parent[field.name];
552
+ }
553
+ }
554
+ }),
555
+ row: ({ field, objectTypeConfig, ...rest })=>field.fields.reduce((objectTypeConfigWithRowFields, subField)=>{
556
+ const addSubField = fieldToSchemaMap[subField.type];
557
+ if (addSubField) {
558
+ return addSubField({
559
+ field: subField,
560
+ objectTypeConfig: objectTypeConfigWithRowFields,
561
+ ...rest
562
+ });
563
+ }
564
+ return objectTypeConfigWithRowFields;
565
+ }, objectTypeConfig),
566
+ select: ({ field, forceNullable, objectTypeConfig, parentIsLocalized, parentName })=>{
567
+ const fullName = combineParentName(parentName, field.name);
568
+ let type = new GraphQLEnumType({
569
+ name: fullName,
570
+ values: formatOptions(field)
571
+ });
572
+ type = field.hasMany ? new GraphQLList(new GraphQLNonNull(type)) : type;
573
+ type = withNullableType({
574
+ type,
575
+ field,
576
+ forceNullable,
577
+ parentIsLocalized
578
+ });
579
+ return {
580
+ ...objectTypeConfig,
581
+ [formatName(field.name)]: formattedNameResolver({
582
+ type,
583
+ field
584
+ })
585
+ };
586
+ },
587
+ tabs: ({ config, field, forceNullable, graphqlResult, newlyCreatedBlockType, objectTypeConfig, parentIsLocalized, parentName })=>field.tabs.reduce((tabSchema, tab)=>{
588
+ if (tabHasName(tab)) {
589
+ const interfaceName = tab?.interfaceName || combineParentName(parentName, toWords(tab.name, true));
590
+ if (!graphqlResult.types.groupTypes[interfaceName]) {
591
+ const objectType = buildObjectType({
592
+ name: interfaceName,
593
+ config,
594
+ fields: tab.fields,
595
+ forceNullable,
596
+ graphqlResult,
597
+ parentIsLocalized: tab.localized || parentIsLocalized,
598
+ parentName: interfaceName
599
+ });
600
+ if (Object.keys(objectType.getFields()).length) {
601
+ graphqlResult.types.groupTypes[interfaceName] = objectType;
602
+ }
603
+ }
604
+ if (!graphqlResult.types.groupTypes[interfaceName]) {
605
+ return tabSchema;
606
+ }
607
+ return {
608
+ ...tabSchema,
609
+ [tab.name]: {
610
+ type: graphqlResult.types.groupTypes[interfaceName],
611
+ resolve (parent, args, context) {
612
+ return {
613
+ ...parent[tab.name],
614
+ _id: parent._id ?? parent.id
615
+ };
616
+ }
617
+ }
618
+ };
619
+ }
620
+ return {
621
+ ...tabSchema,
622
+ ...tab.fields.reduce((subFieldSchema, subField)=>{
623
+ const addSubField = fieldToSchemaMap[subField.type];
624
+ if (addSubField) {
625
+ return addSubField({
626
+ config,
627
+ field: subField,
628
+ forceNullable,
629
+ graphqlResult,
630
+ newlyCreatedBlockType,
631
+ objectTypeConfig: subFieldSchema,
632
+ parentIsLocalized,
633
+ parentName
634
+ });
635
+ }
636
+ return subFieldSchema;
637
+ }, tabSchema)
638
+ };
639
+ }, objectTypeConfig),
640
+ text: ({ field, forceNullable, objectTypeConfig, parentIsLocalized })=>({
641
+ ...objectTypeConfig,
642
+ [formatName(field.name)]: formattedNameResolver({
643
+ type: withNullableType({
644
+ type: field.hasMany === true ? new GraphQLList(GraphQLString) : GraphQLString,
645
+ field,
646
+ forceNullable,
647
+ parentIsLocalized
648
+ }),
649
+ field
650
+ })
651
+ }),
652
+ textarea: ({ field, forceNullable, objectTypeConfig, parentIsLocalized })=>({
653
+ ...objectTypeConfig,
654
+ [formatName(field.name)]: formattedNameResolver({
655
+ type: withNullableType({
656
+ type: GraphQLString,
657
+ field,
658
+ forceNullable,
659
+ parentIsLocalized
660
+ }),
661
+ field
662
+ })
663
+ }),
664
+ upload: ({ config, field, forceNullable, graphqlResult, newlyCreatedBlockType, objectTypeConfig, parentIsLocalized, parentName })=>{
665
+ const { relationTo } = field;
666
+ const isRelatedToManyCollections = Array.isArray(relationTo);
667
+ const hasManyValues = field.hasMany;
668
+ const relationshipName = combineParentName(parentName, toWords(field.name, true));
669
+ let type;
670
+ let relationToType = null;
671
+ if (Array.isArray(relationTo)) {
672
+ relationToType = new GraphQLEnumType({
673
+ name: `${relationshipName}_RelationTo`,
674
+ values: relationTo.reduce((relations, relation)=>({
675
+ ...relations,
676
+ [formatName(relation)]: {
677
+ value: relation
678
+ }
679
+ }), {})
680
+ });
681
+ const types = relationTo.map((relation)=>graphqlResult.collections[relation].graphQL.type);
682
+ type = new GraphQLObjectType({
683
+ name: `${relationshipName}_Relationship`,
684
+ fields: {
685
+ relationTo: {
686
+ type: relationToType
687
+ },
688
+ value: {
689
+ type: new GraphQLUnionType({
690
+ name: relationshipName,
691
+ resolveType (data) {
692
+ return graphqlResult.collections[data.collection].graphQL.type.name;
693
+ },
694
+ types
695
+ })
696
+ }
697
+ }
698
+ });
699
+ } else {
700
+ ;
701
+ ({ type } = graphqlResult.collections[relationTo].graphQL);
702
+ }
703
+ // If the relationshipType is undefined at this point,
704
+ // it can be assumed that this blockType can have a relationship
705
+ // to itself. Therefore, we set the relationshipType equal to the blockType
706
+ // that is currently being created.
707
+ type = type || newlyCreatedBlockType;
708
+ const relationshipArgs = {};
709
+ const relationsUseDrafts = (Array.isArray(relationTo) ? relationTo : [
710
+ relationTo
711
+ ]).some((relation)=>graphqlResult.collections[relation].config.versions?.drafts);
712
+ if (relationsUseDrafts) {
713
+ relationshipArgs.draft = {
714
+ type: GraphQLBoolean
715
+ };
716
+ }
717
+ if (config.localization) {
718
+ relationshipArgs.locale = {
719
+ type: graphqlResult.types.localeInputType
720
+ };
721
+ relationshipArgs.fallbackLocale = {
722
+ type: graphqlResult.types.fallbackLocaleInputType
723
+ };
724
+ }
725
+ const relationship = {
726
+ type: withNullableType({
727
+ type: hasManyValues ? new GraphQLList(new GraphQLNonNull(type)) : type,
728
+ field,
729
+ forceNullable,
730
+ parentIsLocalized
731
+ }),
732
+ args: relationshipArgs,
733
+ extensions: {
734
+ complexity: typeof field?.graphQL?.complexity === 'number' ? field.graphQL.complexity : 10
735
+ },
736
+ async resolve (parent, args, context) {
737
+ const value = parent[field.name];
738
+ const locale = args.locale || context.req.locale;
739
+ const fallbackLocale = args.fallbackLocale || context.req.fallbackLocale;
740
+ let relatedCollectionSlug = field.relationTo;
741
+ const draft = Boolean(args.draft ?? context.req.query?.draft);
742
+ if (hasManyValues) {
743
+ const results = [];
744
+ const resultPromises = [];
745
+ const createPopulationPromise = async (relatedDoc, i)=>{
746
+ let id = relatedDoc;
747
+ let collectionSlug = field.relationTo;
748
+ if (isRelatedToManyCollections) {
749
+ collectionSlug = relatedDoc.relationTo;
750
+ id = relatedDoc.value;
751
+ }
752
+ const result = await context.req.payloadDataLoader.load(createDataloaderCacheKey({
753
+ collectionSlug,
754
+ currentDepth: 0,
755
+ depth: 0,
756
+ docID: id,
757
+ draft,
758
+ fallbackLocale,
759
+ locale,
760
+ overrideAccess: false,
761
+ showHiddenFields: false,
762
+ transactionID: context.req.transactionID
763
+ }));
764
+ if (result) {
765
+ if (isRelatedToManyCollections) {
766
+ results[i] = {
767
+ relationTo: collectionSlug,
768
+ value: {
769
+ ...result,
770
+ collection: collectionSlug
771
+ }
772
+ };
773
+ } else {
774
+ results[i] = result;
775
+ }
776
+ }
777
+ };
778
+ if (value) {
779
+ value.forEach((relatedDoc, i)=>{
780
+ resultPromises.push(createPopulationPromise(relatedDoc, i));
781
+ });
782
+ }
783
+ await Promise.all(resultPromises);
784
+ return results;
785
+ }
786
+ let id = value;
787
+ if (isRelatedToManyCollections && value) {
788
+ id = value.value;
789
+ relatedCollectionSlug = value.relationTo;
790
+ }
791
+ if (id) {
792
+ const relatedDocument = await context.req.payloadDataLoader.load(createDataloaderCacheKey({
793
+ collectionSlug: relatedCollectionSlug,
794
+ currentDepth: 0,
795
+ depth: 0,
796
+ docID: id,
797
+ draft,
798
+ fallbackLocale,
799
+ locale,
800
+ overrideAccess: false,
801
+ showHiddenFields: false,
802
+ transactionID: context.req.transactionID
803
+ }));
804
+ if (relatedDocument) {
805
+ if (isRelatedToManyCollections) {
806
+ return {
807
+ relationTo: relatedCollectionSlug,
808
+ value: {
809
+ ...relatedDocument,
810
+ collection: relatedCollectionSlug
811
+ }
812
+ };
813
+ }
814
+ return relatedDocument;
815
+ }
816
+ return null;
817
+ }
818
+ return null;
819
+ }
820
+ };
821
+ return {
822
+ ...objectTypeConfig,
823
+ [formatName(field.name)]: relationship
824
+ };
825
+ }
826
+ };
827
+
828
+ //# sourceMappingURL=fieldToSchemaMap.js.map