@@ -20,11 +20,8 @@ import DataloaderPlugin, {
20
20
import { DateResolver , JSONResolver } from 'graphql-scalars'
21
21
import { GraphQLParams } from 'graphql-yoga'
22
22
import listPlugin from './pothos-list'
23
- export type {
24
- GetContext ,
25
- InitialContext ,
26
- StellateOptions ,
27
- } from './utils/yoga-helpers'
23
+ import { Datasource } from './datasources'
24
+ import { NotFoundError } from './errors'
28
25
29
26
const builder = new SchemaBuilder < {
30
27
Context : { request : Request ; params : GraphQLParams } & Record < string , unknown >
@@ -69,60 +66,6 @@ builder.mutationType({
69
66
builder . addScalarType ( 'JSON' , JSONResolver , { } )
70
67
builder . addScalarType ( 'Date' , DateResolver , { } )
71
68
72
- type Builder = Omit <
73
- typeof builder ,
74
- | 'addScalarType'
75
- | 'loadableInterface'
76
- | 'loadableUnion'
77
- | 'objectType'
78
- | 'loadableInterfaceRef'
79
- | 'loadableObjectRef'
80
- | 'nodeInterfaceRef'
81
- | 'inputRef'
82
- | 'objectRef'
83
- | 'scalarType'
84
- | 'interfaceField'
85
- | 'listObject'
86
- | 'node'
87
- | 'options'
88
- | 'pageInfoRef'
89
- | 'subscriptionType'
90
- | 'queryFields'
91
- | 'queryType'
92
- | 'mutationType'
93
- | 'mutationFields'
94
- | 'connectionObject'
95
- | 'edgeObject'
96
- | 'configStore'
97
- | 'defaultFieldNullability'
98
- | 'defaultInputFieldRequiredness'
99
- | 'globalConnectionField'
100
- | 'globalConnectionFields'
101
- | 'args'
102
- | 'loadableNode'
103
- | 'loadableNodeRef'
104
- | 'interfaceFields'
105
- | 'subscriptionFields'
106
- | 'subscriptionField'
107
- | 'relayMutationField'
108
- | 'enumType'
109
- | 'inputType'
110
- | 'interfaceRef'
111
- | 'interfaceType'
112
- | 'loadableObject'
113
- | 'mutationField'
114
- | 'mutationFields'
115
- | 'objectField'
116
- | 'objectFields'
117
- | 'queryField'
118
- | 'unionType'
119
- >
120
- const reducedBuilder : Builder = builder
121
-
122
- export { reducedBuilder as builder }
123
- export { decodeGlobalID , encodeGlobalID } from '@pothos/plugin-relay'
124
- export * from './errors'
125
-
126
69
type BuilderTypes = typeof builder extends PothosSchemaTypes . SchemaBuilder <
127
70
infer T
128
71
>
@@ -172,7 +115,8 @@ export function node<
172
115
name : string
173
116
key ?: keyof T
174
117
description ?: string
175
- load : (
118
+ datasource ?: Datasource < T >
119
+ load ?: (
176
120
ids : Array < string | Key > ,
177
121
ctx : Record < string , unknown > ,
178
122
) => Promise < Array < T | Error > >
@@ -204,6 +148,12 @@ export function node<
204
148
string | number
205
149
> [ 'interfaces' ]
206
150
} ) {
151
+ if ( ! opts . datasource && ! opts . load ) {
152
+ throw new Error (
153
+ "A node has to define either 'datasource' or 'load', to be able to load data." ,
154
+ )
155
+ }
156
+
207
157
const node = builder . loadableNode ( opts . name , {
208
158
description : opts . description ,
209
159
isTypeOf : opts . isTypeOf ,
@@ -237,10 +187,40 @@ export function node<
237
187
return id
238
188
}
239
189
} )
240
- const results = await opts . load ( translatedIds , ctx )
241
- return results . map ( ( result ) =>
242
- result instanceof Error ? result : { ...result , __typename : opts . name } ,
243
- )
190
+
191
+ if ( opts . datasource ) {
192
+ if ( opts . datasource . getMany ) {
193
+ const results = await opts . datasource . getMany ( translatedIds , ctx )
194
+ return translatedIds . map ( ( id ) => {
195
+ const found = results . find (
196
+ ( result ) => result [ ( opts . key || 'id' ) as keyof T ] === id ,
197
+ )
198
+ if ( ! found ) {
199
+ return new NotFoundError ( 'Could not find node.' )
200
+ }
201
+ return found
202
+ } )
203
+ } else {
204
+ const results = await Promise . allSettled (
205
+ translatedIds . map ( ( id ) => opts . datasource ! . getOne ( id , ctx ) ) ,
206
+ )
207
+ return results . map ( ( result ) =>
208
+ result . status === 'rejected'
209
+ ? new NotFoundError ( result . reason )
210
+ : { ...result . value , __typename : opts . name } ,
211
+ )
212
+ }
213
+ } else if ( opts . load ) {
214
+ const results = await opts . load ( translatedIds , ctx )
215
+ return results . map ( ( result ) =>
216
+ result instanceof Error
217
+ ? result
218
+ : { ...result , __typename : opts . name } ,
219
+ )
220
+ } else {
221
+ // Should never happen due to the check when we intialize the node
222
+ return [ ]
223
+ }
244
224
} ,
245
225
} )
246
226
@@ -496,3 +476,63 @@ export const unionType = (
496
476
const { name, ...options } = opts
497
477
return builder . unionType ( name , options )
498
478
}
479
+
480
+ type Builder = Omit <
481
+ typeof builder ,
482
+ | 'addScalarType'
483
+ | 'loadableInterface'
484
+ | 'loadableUnion'
485
+ | 'objectType'
486
+ | 'loadableInterfaceRef'
487
+ | 'loadableObjectRef'
488
+ | 'nodeInterfaceRef'
489
+ | 'inputRef'
490
+ | 'objectRef'
491
+ | 'scalarType'
492
+ | 'interfaceField'
493
+ | 'listObject'
494
+ | 'node'
495
+ | 'options'
496
+ | 'pageInfoRef'
497
+ | 'subscriptionType'
498
+ | 'queryFields'
499
+ | 'queryType'
500
+ | 'mutationType'
501
+ | 'mutationFields'
502
+ | 'connectionObject'
503
+ | 'edgeObject'
504
+ | 'configStore'
505
+ | 'defaultFieldNullability'
506
+ | 'defaultInputFieldRequiredness'
507
+ | 'globalConnectionField'
508
+ | 'globalConnectionFields'
509
+ | 'args'
510
+ | 'loadableNode'
511
+ | 'loadableNodeRef'
512
+ | 'interfaceFields'
513
+ | 'subscriptionFields'
514
+ | 'subscriptionField'
515
+ | 'relayMutationField'
516
+ | 'enumType'
517
+ | 'inputType'
518
+ | 'interfaceRef'
519
+ | 'interfaceType'
520
+ | 'loadableObject'
521
+ | 'mutationField'
522
+ | 'mutationFields'
523
+ | 'objectField'
524
+ | 'objectFields'
525
+ | 'queryField'
526
+ | 'unionType'
527
+ >
528
+ const reducedBuilder : Builder = builder
529
+
530
+ export { reducedBuilder as builder }
531
+ export { decodeGlobalID , encodeGlobalID } from '@pothos/plugin-relay'
532
+ export * from './errors'
533
+ export { Datasource } from './datasources'
534
+ export type {
535
+ GetContext ,
536
+ InitialContext ,
537
+ StellateOptions ,
538
+ } from './utils/yoga-helpers'
0 commit comments