Fields API
We recently improved this API. If you were using it prior to October 5th 2021, read this guide for details on how to upgrade.
The fields
option of a list configuration defines the names, types, and configuration of the fields in the list.
This configuration option takes an object with field names as keys, and configured field types as values.
This document covers the different field types which are available and the configuration options they accept. To see how to access fields in the GraphQL API please see the GraphQL API docs.
import { config, list } from '@keystone-next/keystone';import {// Scalar typescheckbox,integer,json,float,password,select,text,timestamp,// Relationship typerelationship,// Virtual typevirtual,// File typesfile,image,} from '@keystone-next/keystone/fields';// Complex typesimport { document } from '@keystone-next/fields-document';import { cloudinaryImage } from '@keystone-next/cloudinary';export default config({lists: {ListName: list({fields: {fieldName: text({ /* ... */ }),/* ... */},}),/* ... */},/* ... */});
Common configuration
All field types accept a common set of configuration options. All options are optional.
Options:
isFilterable
(default:true
): Iffalse
, the GraphQL API and admin UI will not support filtering by this field. Iftrue
(default), the GraphQL API and Admin UI will support filtering by this field. If a function is provided, it will be evaluated dynamically each time this field is used as a filter in a GraphQL operation. If the function returnsfalse
, the operation will return an error indicating that filtering on this field is not allowed.isOrderable
(default:true
): Iffalse
, the GraphQL API and admin UI will not support ordering by this field. Iftrue
(default), the GraphQL API and Admin UI will support ordering by this field. If a function is provided, it will be evaluated dynamically each time this field is used as an ordering field in a GraphQL operation. If the function returnsfalse
, the operation will return an error indicating this ordering by this field is not allowed.access
: Defines the Access Control rules for the field. See the Access Control API for full details on the available access control options.hooks
: Thehooks
option defines hook functions for the field. Hooks allow you to execute code at different stages of the mutation lifecycle. See the Hooks API for full details on the available hook options.label
: The label displayed for this field in the Admin UI. Defaults to a human readable version of the field name.ui
: Controls how the field is displayed in the Admin UI.views
: A resolved path to a module containing code to replace or extend the default Admin UI components for this field. See the Custom Field Views guide for details on how to use this option.createView.fieldMode
(default:'edit'
): Controls the create view page of the Admin UI. Can be one of['edit', 'hidden']
, or an async function with an argument{ session, context }
that returns one of['edit', 'hidden']
. Defaults to the list'sui.createView.defaultFieldMode
config if defined. See the Schema API for details.itemView.fieldMode
(default:'edit'
): Controls the item view page of the Admin UI. Can be one of['edit', 'read', 'hidden']
, or an async function with an argument{ session, context, item }
that returns one of['edit', 'read', 'hidden']
. Defaults to the list'sui.itemView.defaultFieldMode
config if defined. See the Schema API for details.listView.fieldMode
(default:'read'
): Controls the list view page of the Admin UI. Can be one of['read', 'hidden']
, or an async function with an argument{ session, context }
that returns one of['read', 'hidden']
. Defaults to the list'sui.listView.defaultFieldMode
config if defined. See the Schema API for details.
graphql
: Configures certain aspects of the GraphQL API.cacheHint
(default:undefined
): Allows you to specific the dynamic cache control hints used for queries to this this list.omit
(default: 'undefined'): Controls whether this field appears in the autogenerated types of the GraphQL API This option accepts eithertrue
, or an array of the valuesread
,create
, orupdate
. If you specifytrue
then the field will be excluded from all input and output types in the GraphQL API. If you provide an array ofread
,create
, orupdate
the field will be omitted from the corresponding input and output types in the GraphQL API.
export default config({lists: {ListName: list({fields: {fieldName: text({isFilterable: ({ context, session, fieldKey, listKey }) => true,isOrderable: ({ context, session, fieldKey, listKey }) => true,access: { /* ... */ },hooks: { /* ... */ },label: '...',ui: {views: require.resolve('path/to/viewsModule.tsx'),createView: {fieldMode: ({ session, context }) => 'edit',},itemView: {fieldMode: ({ session, context, item }) => 'read',},listView: {fieldMode: ({ session, context }) => 'read',},},graphql: {cacheHint: { maxAge: 60, scope: CacheScope.Private },omit: ['read', 'create', 'update'],}}),/* ... */},}),/* ... */},/* ... */});
Scalar types
checkbox
A checkbox
field represents a boolean (true
/false
) value.
Options:
defaultValue
(default:false
): This value will be used for the field when creating items if no explicit value is set.graphql.read.isNonNull
(default:false
): If you have no read access control and you don't intend to add any in the future, you can set this to true and the output field will be non-nullable. This is only allowed when you have no read access control because otherwise, when access is denied,null
will be returned which will cause an error since the field is non-nullable and the error will propagate up until a nullable field is found which means the entire item will be unreadable and when doing anitems
query, all the items will be unreadable.graphql.create.isNonNull
(default:false
): If you have no create access control and you want to explicitly show that this is field is non-nullable in the create input you can set this to true and the create field will be non-nullable and have a default value at the GraphQL level. This is only allowed when you have no create access control because otherwise, the item will always fail access control if a user doesn't have access to create the particular field regardless of whether or not they specify the field in the create.
import { config, list } from '@keystone-next/keystone';import { checkbox } from '@keystone-next/keystone/fields';export default config({lists: {ListName: list({fields: {fieldName: checkbox({defaultValue: true,graphql: {read: {isNonNull: true},create: {isNonNull: true},}}),/* ... */},}),/* ... */},/* ... */});
integer
An integer
field represents a 32 bit signed integer value.
Options:
defaultValue
(default:undefined
): Can be either an integer value or{ kind: 'autoincrement' }
. This value will be used for the field when creating items if no explicit value is set.db.isNullable
(default:validation.isRequired ? false : true
): Iffalse
then this field will be made non-nullable in the database and it will never be possible to set asnull
.validation.isRequired
(default:false
): Iftrue
then this field can never be set tonull
. It validate this when creating and updating an item through the GraphQL API or the Admin UI. It will also defaultdb.isNullable
to false.validation.min
(default:-2147483647
): This describes the minimum number allowed. If you attempt to submit a number under this, you will get a validation error.validation.max
(default:2147483647
): This describes the maximum number allowed. If you attempt to submit a number over this, you will get a validation error.- If you want to specify a range within which the numbers must fall, specify both a minimum and a maximum value.
isIndexed
(default:false
)- If
true
then this field will be indexed by the database. - If
'unique'
then all values of this field must be unique.
- If
graphql.read.isNonNull
(default:false
): If you have no read access control and you don't intend to add any in the future, you can set this to true and the output field will be non-nullable. This is only allowed when you have no read access control because otherwise, when access is denied,null
will be returned which will cause an error since the field is non-nullable and the error will propagate up until a nullable field is found which means the entire item will be unreadable and when doing anitems
query, all the items will be unreadable.graphql.create.isNonNull
(default:false
): If you have no create access control and you want to explicitly show that this is field is non-nullable in the create input you can set this to true and the create field will be non-nullable and have a default value at the GraphQL level. This is only allowed when you have no create access control because otherwise, the item will always fail access control if a user doesn't have access to create the particular field regardless of whether or not they specify the field in the create.
import { config, list } from '@keystone-next/keystone';import { integer } from '@keystone-next/keystone/fields';export default config({lists: {ListName: list({fields: {fieldName: integer({defaultValue: 0,validation: {isRequired: true,},isIndexed: 'unique',}),/* ... */},}),/* ... */},/* ... */});
json
A json
field represents a JSON blob.
Currently the json
field is non-orderable and non-filterable.
defaultValue
(default:null
): Can be set to any JSON value. This value will be used for the field when creating items if no explicit value is set.
import { config, list } from '@keystone-next/keystone';import { json } from '@keystone-next/keystone/fields';export default config({lists: {ListName: list({fields: {fieldName: json({defaultValue: { something: true },}),/* ... */},}),/* ... */},/* ... */});
float
A float
field represents a floating point value.
Options:
defaultValue
(default:undefined
): Can be a finite float value. This value will be used for the field when creating items if no explicit value is set.db.isNullable
(default:validation.isRequired ? false : true
): Iffalse
then this field will be made non-nullable in the database and it will never be possible to set asnull
.validation.isRequired
(default:false
): Iftrue
then this field can never be set tonull
. It validate this when creating and updating an item through the GraphQL API or the Admin UI. It will also defaultdb.isNullable
to false.validation.min
(default:undefined
): This describes the minimum number allowed. If you attempt to submit a number under this, you will get a validation error.validation.max
(default:undefined
): This describes the maximum number allowed. If you attempt to submit a number over this, you will get a validation error.isIndexed
(default:false
)- If
true
then this field will be indexed by the database. - If
'unique'
then all values of this field must be unique.
- If
graphql.read.isNonNull
(default:false
): If you have no read access control and you don't intend to add any in the future, you can set this to true and the output field will be non-nullable. This is only allowed when you have no read access control because otherwise, when access is denied,null
will be returned which will cause an error since the field is non-nullable and the error will propagate up until a nullable field is found which means the entire item will be unreadable and when doing anitems
query, all the items will be unreadable.graphql.create.isNonNull
(default:false
): If you have no create access control and you want to explicitly show that this is field is non-nullable in the create input you can set this to true and the create field will be non-nullable and have a default value at the GraphQL level. This is only allowed when you have no create access control because otherwise, the item will always fail access control if a user doesn't have access to create the particular field regardless of whether or not they specify the field in the create.
import { config, list } from '@keystone-next/keystone';import { float } from '@keystone-next/keystone/fields';export default config({lists: {ListName: list({fields: {fieldName: float({defaultValue: 3.14159,validation: {isRequired: true,},isIndexed: 'unique',}),/* ... */},}),/* ... */},/* ... */});
decimal
A decimal
field represents a decimal value.
Options:
defaultValue
(default:undefined
): Can be a decimal value written as a string This value will be used for the field when creating items if no explicit value is set.precision
(default:18
): Maximum number of digits that are present in the number.scale
(default:4
): Maximum number of decimal places.db.isNullable
(default:validation.isRequired ? false : true
): Iffalse
then this field will be made non-nullable in the database and it will never be possible to set asnull
.validation.isRequired
(default:false
): Iftrue
then this field can never be set tonull
. It validate this when creating and updating an item through the GraphQL API or the Admin UI. It will also defaultdb.isNullable
to false.validation.min
(default:undefined
): This describes the minimum number allowed. If you attempt to submit a number under this, you will get a validation error.validation.max
(default:undefined
): This describes the maximum number allowed. If you attempt to submit a number over this, you will get a validation error.- If you want to specify a range within which the numbers must fall, specify both a minimum and a maximum value.
isIndexed
(default:false
)- If
true
then this field will be indexed by the database. - If
'unique'
then all values of this field must be unique.
- If
graphql.read.isNonNull
(default:false
): If you have no read access control and you don't intend to add any in the future, you can set this to true and the output field will be non-nullable. This is only allowed when you have no read access control because otherwise, when access is denied,null
will be returned which will cause an error since the field is non-nullable and the error will propagate up until a nullable field is found which means the entire item will be unreadable and when doing anitems
query, all the items will be unreadable.graphql.create.isNonNull
(default:false
): If you have no create access control and you want to explicitly show that this is field is non-nullable in the create input you can set this to true and the create field will be non-nullable and have a default value at the GraphQL level. This is only allowed when you have no create access control because otherwise, the item will always fail access control if a user doesn't have access to create the particular field regardless of whether or not they specify the field in the create.
import { config, list } from '@keystone-next/keystone';import { decimal } from '@keystone-next/keystone/fields';export default config({lists: {ListName: list({fields: {fieldName: decimal({defaultValue: '3.142',precision: 12,scale: 3,validation: {isRequired: true,max: '10000',min: '2',},isIndexed: 'unique',}),/* ... */},}),/* ... */},/* ... */});
password
A password
field represents an encrypted password value.
Options:
db.isNullable
(default:validation.isRequired ? false : true
): Iffalse
then this field will be made non-nullable in the database and it will never be possible to set asnull
.validation.isRequired
(default:false
): Iftrue
then this field can never be set tonull
. It validate this when creating and updating an item through the GraphQL API or the Admin UI. It will also defaultdb.isNullable
to false.validation.length.min
(default:8
): This describes the minimum length allowed. If you attempt to submit a string shorter than this, you will get a validation error.validation.length.max
(default:undefined
): This describes the maximum length allowed. If you attempt to submit a string longer than this, you will get a validation error.validation.match
(default:undefined
): This describes a pattern that values for this field must matchvalidation.match.regex
: The regular expressionvalidation.match.explanation
(default:${fieldLabel} must match ${validation.match.regex}
): A message shown in the Admin when a value doesn't match the regex and returned as a validation error from the GraphQL API
validation.rejectCommon
(default:false
): Rejects passwords from a list of commonly used passwords.bcrypt
(default:require('bcryptjs')
): A module which implements the same interface as thebcryptjs
package, such as the nativebcrypt
package. This module will be used for all encryption routines in thepassword
field.
import { config, list } from '@keystone-next/keystone';import { password } from '@keystone-next/keystone/fields';export default config({lists: {ListName: list({fields: {fieldName: password({validation: {length: { min: 10, max: 1000 },isRequired: true,rejectCommon: true,},bcrypt: require('bcrypt'),}),/* ... */},}),/* ... */},/* ... */});
select
A select
field represents the selection of one of fixed set of values.
Values can be either strings, integers, or enum values, as determined by the type
option.
This will determine their GraphQL data type, as well as their database storage type except for enum
on SQLite
where the GraphQL type will be an enum but it will be represented as a string in the database.
Options:
type
(default:'string'
): Sets the type of the values of this field. Must be one of['string', 'enum', 'integer']
.options
: An array of{ label, value }
.label
is a string to be displayed in the Admin UI.value
is either astring
(for{ type: 'string' }
or{ type: 'enum' }
), or anumber
(for{ type: 'integer' }
). Thevalue
will be used in the GraphQL API and stored in the database.defaultValue
(default:undefined
): This value will be used for the field when creating items if no explicit value is set.db.isNullable
(default:validation.isRequired ? false : true
): Iffalse
then this field will be made non-nullable in the database and it will never be possible to set asnull
.validation.isRequired
(default:false
): Iftrue
then this field can never be set tonull
. It validate this when creating and updating an item through the GraphQL API or the Admin UI. It will also defaultdb.isNullable
to false.isIndexed
(default:false
)- If
true
then this field will be indexed by the database. - If
'unique'
then all values of this field must be unique.
- If
ui.displayMode
(default:'select'
): Configures the display mode of the field in the Admin UI. Can be one of['select', 'segmented-control']
.graphql.read.isNonNull
(default:false
): If you have no read access control and you don't intend to add any in the future, you can set this to true and the output field will be non-nullable. This is only allowed when you have no read access control because otherwise, when access is denied,null
will be returned which will cause an error since the field is non-nullable and the error will propagate up until a nullable field is found which means the entire item will be unreadable and when doing anitems
query, all the items will be unreadable.graphql.create.isNonNull
(default:false
): If you have no create access control and you want to explicitly show that this is field is non-nullable in the create input you can set this to true and the create field will be non-nullable and have a default value at the GraphQL level. This is only allowed when you have no create access control because otherwise, the item will always fail access control if a user doesn't have access to create the particular field regardless of whether or not they specify the field in the create.
import { config, list } from '@keystone-next/keystone';import { select } from '@keystone-next/keystone/fields';export default config({lists: {ListName: list({fields: {fieldName: select({type: 'enum',options: [{ label: '...', value: '...' },/* ... */],defaultValue: '...',validation: { isRequired: true, },isIndexed: 'unique',ui: { displayMode: 'select' },}),/* ... */},}),/* ... */},/* ... */});
text
A text
field represents a string value.
Options:
db.isNullable
(default:false
): Iftrue
then this field will be made nullable in the database and it will be possible to set asnull
.defaultValue
(default:db.isNullable === true ? undefined : ''
): This value will be used for the field when creating items if no explicit value is set.validation.isRequired
(default:false
): Iftrue
then this field can never be set tonull
or an empty string. Unlikedb.isNullable
, this will require that a value with at least 1 character is provided in the Admin UI. It will also validate this when creating and updating an item through the GraphQL API but it will not enforce it at the database level.validation.length.min
(default:0
): This describes the minimum number allowed. If you attempt to submit a string shorter than this, you will get a validation error.validation.length.max
(default:undefined
): This describes the maximum length allowed. If you attempt to submit a string longer than this, you will get a validation error.validation.match
(default:undefined
): This describes a pattern that values for this field must matchvalidation.match.regex
: The regular expressionvalidation.match.explanation
(default:${fieldLabel} must match ${validation.match.regex}
): A message shown in the Admin when a value doesn't match the regex and returned as a validation error from the GraphQL API
isIndexed
(default:false
)- If
true
then this field will be indexed by the database. - If
'unique'
then all values of this field must be unique.
- If
ui
(default:{ displayMode: 'input' }
): Configures the display mode of the field in the Admin UI. Can be one of['input', 'textarea']
.graphql.read.isNonNull
(default:false
): If you have no read access control and you don't intend to add any in the future, you can set this to true and the output field will be non-nullable. This is only allowed when you have no read access control because otherwise, when access is denied,null
will be returned which will cause an error since the field is non-nullable and the error will propagate up until a nullable field is found which means the entire item will be unreadable and when doing anitems
query, all the items will be unreadable.graphql.create.isNonNull
(default:false
): If you have no create access control and you want to explicitly show that this is field is non-nullable in the create input you can set this to true and the create field will be non-nullable and have a default value at the GraphQL level. This is only allowed when you have no create access control because otherwise, the item will always fail access control if a user doesn't have access to create the particular field regardless of whether or not they specify the field in the create.
import { config, list } from '@keystone-next/keystone';import { text } from '@keystone-next/keystone/fields';export default config({lists: {ListName: list({fields: {fieldName: text({defaultValue: '...',validation: { isRequired: true },isIndexed: 'unique',ui: { displayMode: 'textarea' },}),/* ... */},}),/* ... */},/* ... */});
timestamp
A timestamp
field represents a date time value in ISO8601 format.
Options:
defaultValue
(default:undefined
): Can be either a string value with a date time string in ISO8601 format or{ kind: 'now' }
. This value will be used for the field when creating items if no explicit value is set.db.isNullable
(default:validation.isRequired ? false : true
): Iffalse
then this field will be made non-nullable in the database and it will never be possible to set asnull
.validation.isRequired
(default:false
): Iftrue
then this field can never be set tonull
. It validate this when creating and updating an item through the GraphQL API or the Admin UI. It will also defaultdb.isNullable
to false.db.updatedAt
(default:false
) Iftrue
then this field will add the@updatedAt
attribute to this field in the Prisma schema. This will update this field to the current time whenever an item is created/updated with the GraphQL API or any other usage of the Prisma Client if this field is not explicitly set in the request. Note this happens at the Prisma Client level, not at the database so if you update an item in your database directly, fields withdb.updatedAt: true
will not automatically update.isIndexed
(default:false
)- If
true
then this field will be indexed by the database. - If
'unique'
then all values of this field must be unique.
- If
graphql.read.isNonNull
(default:false
): If you have no read access control and you don't intend to add any in the future, you can set this to true and the output field will be non-nullable. This is only allowed when you have no read access control because otherwise, when access is denied,null
will be returned which will cause an error since the field is non-nullable and the error will propagate up until a nullable field is found which means the entire item will be unreadable and when doing anitems
query, all the items will be unreadable.graphql.create.isNonNull
(default:false
): If you have no create access control and you want to explicitly show that this is field is non-nullable in the create input you can set this to true and the create field will be non-nullable and have a default value at the GraphQL level. This is only allowed when you have no create access control because otherwise, the item will always fail access control if a user doesn't have access to create the particular field regardless of whether or not they specify the field in the create.
import { config, list } from '@keystone-next/keystone';import { timestamp } from '@keystone-next/keystone/fields';export default config({lists: {ListName: list({fields: {fieldName: timestamp({defaultValue: '1970-01-01T00:00:00.000Z',validation: { isRequired: true },isIndexed: 'unique',}),/* ... */},}),/* ... */},/* ... */});
Relationship type
relationship
A relationship
field represents a relationship between two lists.
Read our relationships guide for details on Keystone’s relationship model and how to configure them in your project.
ref
(required): A string of the form<listKey>
or<listKey>.<fieldKey>
.many
(default:false
): Configures the cardinality of the relationship.ui
(default:{ hideCreate: false, displayMode: 'select' }
): Configures the display mode of the field in the Admin UI.hideCreate
(default:false
). Iftrue
, the "Create related item" button is not shown in the item view.displayMode
(default:'select'
): Controls the mode used to display the field in the item view. The mode'select'
displays related items in a select component, while'cards'
displays the related items in a card layout. Each display mode supports further configuration.
ui.displayMode === 'select'
options:labelField
: The field path from the related list to use for item labels in the select. Defaults to thelabelField
configured on the related list.
ui.displayMode === 'cards'
options:cardFields
: A list of field paths from the related list to render in the card component. Defaults to'id'
and thelabelField
configured on the related list.linkToItem
(defaultfalse
): Iftrue
, the default card component will render as a link to navigate to the related item.removeMode
(default:'disconnect'
): Controls whether theRemove
button is present in the card. If'disconnect'
, the button will be present. If'none'
, the button will not be present.inlineCreate
(default:null
): If notnull
, an object of the form{ fields: [...] }
, wherefields
is a list of field paths from the related list should be provided. An inlineCreate
button will be included in the cards allowing a new related item to be created based on the configured field paths.inlineEdit
(default:null
): If notnull
, an object of the form{ fields: [...] }
, wherefields
is a list of field paths from the related list should be provided. AnEdit
button will be included in each card, allowing the configured fields to be edited for each related item.inlineConnect
(default:false
): Iftrue
, an inlineLink existing item
button will be present, allowing existing items of the related list to be connected in this field.
ui.displayMode === 'count'
only supportsmany
relationships
import { config, list } from '@keystone-next/keystone';import { relationship } from '@keystone-next/keystone/fields';export default config({lists: {ListName: list({fields: {fieldName: relationship({ref: '...',many: false,ui: {hideCreate: false,// Display mode: 'select'displayMode: 'select',labelField: 'name',// Display mode: 'cards'displayMode: 'cards',cardFields: [...],linkToItem: true,removeMode: 'disconnect',inlineCreate: { fields: [...] },inlineEdit: { fields: [...] },inlineConnect: true,// Display mode: 'count'// requires many: true abovedisplayMode: 'count',},}),/* ... */},}),/* ... */},/* ... */});
Virtual type
virtual
A virtual
field represents a value which is computed at read time, rather than stored in the database.
See the virtual fields guide for details on how to use virtual fields.
Options:
field
(required): The GraphQL field that defines the type, resolver and arguments.ui.query
(default:''
): Defines what the Admin UI should fetch from this field, it's interpolated into a query like this:
This is only needed when you your field returns a GraphQL type other than a scalar(String and etc.) or an enum or you need to provide arguments to the field.query {item(where: { id: "..." }) {field${ui.query}}}
import { config, createSchema, list } from '@keystone-next/keystone';import { graphql } from '@keystone-next/keystone/types';import { virtual } from '@keystone-next/keystone/fields';export default config({lists: {ListName: list({fields: {fieldName: virtual({field: graphql.field({type: graphql.String,args: { something: graphql.arg({ type: graphql.Int }) },resolve(item, args, context, info) {}})}),/* ... */},}),/* ... */},/* ... */});
File types
File types allow you to upload different types of files to your Keystone system.
file
A file
field represents a file of any type.
See config.files
for details on how to configure your Keystone system with support for the file
field type.
import { config, list } from '@keystone-next/keystone';import { file } from '@keystone-next/keystone/fields';export default config({lists: {ListName: list({fields: {repo: file(),/* ... */},}),/* ... */},/* ... */});
image
An image
field represents an image file, i.e. .jpg
, .png
, .webp
, or .gif
.
See config.images
for details on how to configure your Keystone system with support for the image
field type.
import { config, list } from '@keystone-next/keystone';import { image } from '@keystone-next/keystone/fields';export default config({lists: {ListName: list({fields: {avatar: image(),/* ... */},}),/* ... */},/* ... */});
Complex types
document
(coming soon)
Options:
relationships
componentBlocks
formatting
links
dividers
layouts
import { config, list } from '@keystone-next/keystone';import { document } from '@keystone-next/fields-document';export default config({lists: {ListName: list({fields: {fieldName: document({relationships: { /* ... */ },componentBlocks: {block: { /* ... */ },/* ... */},formatting: { /* ... */ },links: true,dividers: true,layouts: [/* ... */],}),/* ... */},}),/* ... */},/* ... */});
cloudinaryImage
(coming soon)
cloudinary
: Configuration for the connected Cloudinary account.cloudName
apiKey
apiSecret
folder
import { config, list } from '@keystone-next/keystone';import { cloudinaryImage } from '@keystone-next/cloudinary';export default config({lists: {ListName: list({fields: {fieldName: cloudinaryImage({cloudinary: {cloudName: process.env.CLOUDINARY_CLOUD_NAME,apiKey: process.env.CLOUDINARY_API_KEY,apiSecret: process.env.CLOUDINARY_API_SECRET,folder: process.env.CLOUDINARY_API_FOLDER,},}),/* ... */},}),/* ... */},/* ... */});