rzc96
rzc96

Reputation: 1

How exactly do fixtures work with `createItems` in Keystone JS?

I've been running around trying to create some base fixture for the base repository on given models but I can't seem to find how. I'm fairly new to node, even more to Keystone. Most repos or tutorials give you the base skeleton for the createItems function but not much overall.

So how are these base fixtures created, I do have my list for User in a User.ts file:

export default {
  User: list({
    fields: {
      firstName: text({ validation: { isRequired: true } }),
      lastName: text({ validation: { isRequired: true } }),
      phoneNumber: text({ validation: { isRequired: true } }),
      email: text({
        validation: { isRequired: true },
        isIndexed: 'unique',
        isFilterable: true,
      }),
      password: password({ validation: { isRequired: true } }),
      dataPoints: relationship({ ref: 'DataPoint.author', many: true }),
      organization: relationship({ ref: 'Organization.users' }),
    },
  })
};

But where can I manage to write up and "execute" a createItems for a User?

Database is Postgresql if that gives any insight.

Upvotes: 0

Views: 279

Answers (1)

Molomby
Molomby

Reputation: 6559

Keystone has a number of ways to programatically access the lists and fields you've configured. They effectively let you manipulate your data at different "layers" in the Keystone stack – either via GraphQL (remotely or from Node), the data Keystone uses internally or reaching right down to the Prisma database connection. We've tried to keep these interfaces as consistent as possible but, ultimately, they work in different ways and you'll find you use them for different purposes.

The docs site covers a lot of detail but there's a real lack of introductory content that brings the high-level picture together. Let me give it a crack...

GraphQL API

I don't know how familiar you are with GraphQL but it's basically a typed HTTP API. You can connect to it programmatically using standard HTTP tools or specially built GraphQL clients like Apollo Client.

From the docs:

By default Keystone serves your GraphQL endpoint at /api/graphql. Keystone also includes GraphQL Playground, an in-browser GraphQL IDE, giving you a great way to explore the API Keystone creates for your app.

When using Keystone's default settings in dev, both the GraphQL Playground and the GraphQL API itself will be available at http://localhost:3000/api/graphql. This will likely be the case if you're running one of the example projects or developing your own Keystone app locally.

Keystone Docs – GraphQL API: Using the API

Usually you'd use the GraphQL API from your frontend app or website code, running in a browser. If you're just playing around with it in dev though, definitely check out the GraphQL Playground that ships with Keystone. It shows you all the types and fields available which is indispensable when writing queries (click the SCHEMA and DOCS tabs that open from the right).

Here's a createUsers query running there, with the relevant docs open:

Calling createUsers mutation from the GraphQL Playground

Query API

So the GraphQL API is great for remote calls – talking to Keystone from another app or the browser – but you'll often want to query your lists from within the app itself. This happens when you're building out hooks, custom queries and mutation, virtual field resolver, etc. In these situations it's a bit inefficient (and clunky) to call out over HTTP. For this we have the Query API:

The Query API provides a programmatic API for running CRUD operations against your GraphQL API. For each list in your system the following API is available at context.query.<listName>. [...] The arguments to these functions closely correspond to their equivalent GraphQL APIs, making it easy to switch between the programmatic API and the GraphQL API.

Keystone Docs – Query API

Think of it as a native JS interface to the GraphQL API. The query in the image above, written using the Query API would look like this:

// Note the `query` argument is a GraphQL snippet so you can resolve relationships here
const users = await context.query.User.createMany({
  data: [
    {
      firstName: 'Jane',
      lastName: 'Fredrickson',
      email: '[email protected]',
      phoneNumber: '+61420202029',
      password: 'notverysecure'
    }
  ],
  query: 'id'
});

When talking to lists in this way, things like hooks, defaults, validation rules, etc. are still run. Plus, since this API exists within the context object (ie. it exists within the context of another operation), access control is still applied.

Database API

You can think of the Database API as the layer below the Query API. From the docs:

The database API provides a programmatic API for running CRUD operations against the internal GraphQL resolvers in your system. Importantly, this API bypasses the GraphQL Server itself, instead invoking the resolver functions directly. The return values of this API are internal item objects, which are suitable to be returned from GraphQL resolvers.

Keystone Docs – Database API

Usage looks pretty similar too:

// The user objects returned here include raw values for all fields
const users = await context.db.User.createMany({
  data: [
    {
      firstName: 'Jane',
      lastName: 'Fredrickson',
      email: '[email protected]',
      phoneNumber: '+61420202029',
      password: 'notverysecure'
    }
  ]
});

You probably won't often use it very often but it's needed for a few specific use cases. For Example, if you want to build a custom mutation that returns a native item from a list, you'll need to use the Database API so you can get the item before it's things like relationship resolution have run.

Like the Query API, operations that use the Database API will also triggers hooks, defaults, validation rules, etc. and be subject to access control based on the request being made.

Prisma Client

This is the bottom of the stack as far as Keystone is concerned - the underlying database driver used internally by Keystone to resolve all operations. It's available at context.prisma and, for usage, you can refer to the Prisma docs.

Operations performed against this API effectively don't "pass through" Keystone at all so things like hooks, access control, field defaults, etc. (all the "rich" functionality Keystone gives you) are not applied. This can be good or bad, depending on your use case.

Upvotes: 1

Related Questions