1- import type { CacheHint } from '@apollo/cache-control-types'
1+ import { type CacheHint } from '@apollo/cache-control-types'
22import { GraphQLString , isInputObjectType } from 'graphql'
33import { type getGqlNames , QueryMode } from '../../types'
44import {
@@ -12,11 +12,21 @@ import {
1212 type KeystoneConfig ,
1313 type MaybePromise ,
1414 type NextFieldType ,
15+ type FieldTypeFunc ,
1516} from '../../types'
1617import { graphql } from '../..'
17- import type { FieldHooks , ResolvedListHooks , ResolvedFieldHooks } from '../../types/config/hooks'
18- import type { FilterOrderArgs } from '../../types/config/fields'
19- import type { MaybeItemFunction , MaybeSessionFunction } from '../../types/config/lists'
18+ import {
19+ type FieldHooks ,
20+ type ResolvedListHooks ,
21+ type ResolvedFieldHooks
22+ } from '../../types/config/hooks'
23+ import {
24+ type FilterOrderArgs
25+ } from '../../types/config/fields'
26+ import {
27+ type MaybeItemFunction ,
28+ type MaybeSessionFunction
29+ } from '../../types/config/lists'
2030import {
2131 type ResolvedFieldAccessControl ,
2232 type ResolvedListAccessControl ,
@@ -133,16 +143,19 @@ function throwIfNotAFilter (x: unknown, listKey: string, fieldKey: string) {
133143 )
134144}
135145
136- function getIsEnabled ( listKey : string , listConfig : KeystoneConfig [ 'lists' ] [ string ] ) {
146+ type ListConfigType = KeystoneConfig [ 'lists' ] [ string ]
147+ type FieldConfigType = ReturnType < FieldTypeFunc < any > >
148+ type PartiallyInitialisedList1 = { graphql : { isEnabled : IsEnabled } }
149+ type PartiallyInitialisedList2 = Omit < InitialisedList , 'lists' | 'resolvedDbFields' >
150+
151+ function getIsEnabled ( listKey : string , listConfig : ListConfigType ) {
137152 const omit = listConfig . graphql ?. omit ?? false
138153 const {
139154 defaultIsFilterable = true ,
140155 defaultIsOrderable = true
141156 } = listConfig
142157
143- // We explicity check for boolean/function values here to ensure the dev hasn't made a mistake
144- // when defining these values. We avoid duck-typing here as this is security related
145- // and we want to make it hard to write incorrect code.
158+ // TODO: check types in initConfig
146159 throwIfNotAFilter ( defaultIsFilterable , listKey , 'defaultIsFilterable' )
147160 throwIfNotAFilter ( defaultIsOrderable , listKey , 'defaultIsOrderable' )
148161
@@ -170,6 +183,39 @@ function getIsEnabled (listKey: string, listConfig: KeystoneConfig['lists'][stri
170183 }
171184}
172185
186+ function getIsEnabledField ( f : FieldConfigType , listKey : string , listConfig : PartiallyInitialisedList1 ) {
187+ const omit = f . graphql ?. omit ?? false
188+ const {
189+ isFilterable = listConfig . graphql . isEnabled . filter ,
190+ isOrderable = listConfig . graphql . isEnabled . orderBy ,
191+ } = f
192+
193+ // TODO: check types in initConfig
194+ throwIfNotAFilter ( isFilterable , listKey , 'isFilterable' )
195+ throwIfNotAFilter ( isOrderable , listKey , 'isOrderable' )
196+
197+ if ( typeof omit === 'boolean' ) {
198+ const notOmit = ! omit
199+ return {
200+ type : notOmit ,
201+ read : notOmit ,
202+ create : notOmit ,
203+ update : notOmit ,
204+ filter : notOmit ? isFilterable : false ,
205+ orderBy : notOmit ? isOrderable : false ,
206+ }
207+ }
208+
209+ return {
210+ type : true ,
211+ read : ! omit . read ,
212+ create : ! omit . create ,
213+ update : ! omit . update ,
214+ filter : ! omit . read ? isFilterable : false , // prevent filtering if read is false
215+ orderBy : ! omit . read ? isOrderable : false , // prevent ordering if read is false
216+ }
217+ }
218+
173219function defaultOperationHook ( ) { }
174220function defaultListHooksResolveInput ( { resolvedData } : { resolvedData : any } ) {
175221 return resolvedData
@@ -264,14 +310,12 @@ function parseFieldHooks (
264310 }
265311}
266312
267- type PartiallyInitialisedList = Omit < InitialisedList , 'lists' | 'resolvedDbFields' >
268-
269313function getListsWithInitialisedFields (
270314 { storage : configStorage , lists : listsConfig , db : { provider } } : KeystoneConfig ,
271315 listGraphqlTypes : Record < string , ListGraphQLTypes > ,
272- intermediateLists : Record < string , { graphql : { isEnabled : IsEnabled } } >
316+ intermediateLists : Record < string , PartiallyInitialisedList1 >
273317) {
274- const result : Record < string , PartiallyInitialisedList > = { }
318+ const result : Record < string , PartiallyInitialisedList2 > = { }
275319
276320 for ( const [ listKey , list ] of Object . entries ( listsConfig ) ) {
277321 const intermediateList = intermediateLists [ listKey ]
@@ -308,16 +352,7 @@ function getListsWithInitialisedFields (
308352 getStorage : storage => configStorage ?. [ storage ] ,
309353 } )
310354
311- // We explicity check for boolean values here to ensure the dev hasn't made a mistake
312- // when defining these values. We avoid duck-typing here as this is security related
313- // and we want to make it hard to write incorrect code.
314- throwIfNotAFilter ( f . isFilterable , listKey , 'isFilterable' )
315- throwIfNotAFilter ( f . isOrderable , listKey , 'isOrderable' )
316-
317- const omit = f . graphql ?. omit ?? false
318- const read = typeof omit === 'boolean' ? ! omit : ! omit . read
319- const create = typeof omit === 'boolean' ? ! omit : ! omit . create
320- const update = typeof omit === 'boolean' ? ! omit : ! omit . update
355+ const isEnabledField = getIsEnabledField ( f , listKey , intermediateList )
321356 const fieldModes = {
322357 create : f . ui ?. createView ?. fieldMode ?? list . ui ?. createView ?. defaultFieldMode ?? 'edit' ,
323358 item : f . ui ?. itemView ?. fieldMode ?? list . ui ?. itemView ?. defaultFieldMode ?? 'edit' ,
@@ -330,15 +365,7 @@ function getListsWithInitialisedFields (
330365 hooks : parseFieldHooks ( f . hooks ?? { } ) ,
331366 graphql : {
332367 cacheHint : f . graphql ?. cacheHint ,
333- isEnabled : {
334- read,
335- create,
336- update,
337- // Filter and orderBy can be defaulted at the list level, otherwise they
338- // default to `false` if no value was set at the list level.
339- filter : read && ( f . isFilterable ?? intermediateList . graphql . isEnabled . filter ) ,
340- orderBy : read && ( f . isOrderable ?? intermediateList . graphql . isEnabled . orderBy ) ,
341- } ,
368+ isEnabled : isEnabledField ,
342369 isNonNull : {
343370 read : f . graphql ?. isNonNull ?. read ?? false ,
344371 create : f . graphql ?. isNonNull ?. create ?? false ,
@@ -350,20 +377,20 @@ function getListsWithInitialisedFields (
350377 description : f . ui ?. description ?? null ,
351378 views : f . ui ?. views ?? null ,
352379 createView : {
353- fieldMode : create ? fieldModes . create : 'hidden' ,
380+ fieldMode : isEnabledField . create ? fieldModes . create : 'hidden' ,
354381 } ,
355382
356383 itemView : {
357384 fieldPosition : f . ui ?. itemView ?. fieldPosition ?? 'form' ,
358- fieldMode : update
385+ fieldMode : isEnabledField . update
359386 ? fieldModes . item
360- : read && fieldModes . item !== 'hidden'
361- ? 'read'
362- : 'hidden' ,
387+ : isEnabledField . read && fieldModes . item !== 'hidden'
388+ ? 'read'
389+ : 'hidden' ,
363390 } ,
364391
365392 listView : {
366- fieldMode : read ? fieldModes . list : 'hidden' ,
393+ fieldMode : isEnabledField . read ? fieldModes . list : 'hidden' ,
367394 } ,
368395 } ,
369396
0 commit comments