Skip to content

Latest commit

 

History

History
 
 

virtual-field

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Feature Example - virtual field

This project demonstrates how to add virtual fields to a Keystone list It builds on the Blog starter project.

Instructions

To run this project, clone the Keystone repository locally, run yarn at the root of the repository then navigate to this directory and run:

yarn dev

This will start the Admin UI at localhost:3000. You can use the Admin UI to create items in your database.

You can also access a GraphQL Playground at localhost:3000/api/graphql, which allows you to directly run GraphQL queries and mutations.

Features

This project demonstrates how to use virtual fields. It uses the graphql export from @keystone-6/core to define the GraphQL schema used by the virtual fields.

isPublished

The isPublished field shows how to use the virtual field to return some derived data.

isPublished: virtual({
  field: graphql.field({
    type: graphql.Boolean,
    resolve(item: any) {
      return item.status === 'published';
    },
  }),
}),

counts

The counts field shows how to return a GraphQL object rather than a scalar from a virtual field.

counts: virtual({
  field: graphql.field({
    type: graphql.object<{ content: string }>()({
      name: 'PostCounts',
      fields: {
        words: graphql.field({
          type: graphql.Int,
          resolve({ content }) {
            return content.split(' ').length;
          },
        }),
        sentences: graphql.field({
          type: graphql.Int,
          resolve({ content }) {
            return content.split('.').length;
          },
        }),
        paragraphs: graphql.field({
          type: graphql.Int,
          resolve({ content }) {
            return content.split('\n\n').length;
          },
        }),
      },
    }),
    resolve(item: any) {
      return { content: item.content || '' };
    },
  }),
  ui: { query: '{ words sentences paragraphs }' },
}),

excerpt

The excerpt field shows how to add GraphQL arguments to a virtual field.

excerpt: virtual({
  field: graphql.field({
    type: graphql.String,
    args: {
      length: graphql.arg({ type: graphql.nonNull(graphql.Int), defaultValue: 200 }),
    },
    resolve(item, { length }) {
      if (!item.content) {
        return null;
      }
      return (item.content as string).slice(0, length - 3) + '...';
    },
  }),
}),

relatedPosts

The relatedPosts field shows how to use the GraphQL types defined by a Keystone list.

relatedPosts: virtual({
  field: lists =>
    graphql.field({
      type: graphql.list(graphql.nonNull(lists.Post.types.output)),
      resolve(item, args, context) {
        // this could have some logic to get posts that are actually related to this one somehow
        // this is a just a naive "get the three latest posts that aren't this one"
        return context.db.Post.findMany({
          take: 3,
          where: { id_not: item.id, status: 'published' },
          orderBy: [{ publishDate: 'desc' }],
        });
      },
    }),
  ui: { query: '{ title }' },
}),

Try it out in CodeSandbox 🧪

You can play with this example online in a web browser using the free codesandbox.io service. To launch this example, open the URL https://githubbox.com/keystonejs/keystone/tree/main/examples/virtual-field. You can also fork this sandbox to make your own changes.