Skip to content

Commit

Permalink
Update @graphql-ts/schema, rename schema export to graphql and mo…
Browse files Browse the repository at this point in the history
…ve it to main entrypoint (keystonejs#6393)

* Update @graphql-ts/schema

* Update prisma utils
  • Loading branch information
emmatown authored and Nikitoring committed Sep 14, 2021
1 parent f41af7c commit 4278fd4
Show file tree
Hide file tree
Showing 48 changed files with 1,248 additions and 1,237 deletions.
5 changes: 5 additions & 0 deletions .changeset/happy-chairs-juggle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@keystone-next/keystone': major
---

Updated `@graphql-ts/schema` to `0.3.0` and moved the `schema` export to `@keystone-next/keystone` entrypoint and renamed it to `graphql`. `bindSchemaAPIToContext` on the `graphql` export has also been renamed to `bindGraphQLSchemaAPIToContext`.
9 changes: 4 additions & 5 deletions docs/pages/docs/apis/fields.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -562,18 +562,17 @@ Options:
- `graphQLReturnFragment` (default: `''` ): The sub-fields that should be fetched by the Admin UI when displaying this field.

```typescript
import { config, createSchema, list } from '@keystone-next/keystone';
import { config, createSchema, list, graphql } from '@keystone-next/keystone';
import { virtual } from '@keystone-next/keystone/fields';
import { schema } from '@keystone-next/keystone/types';

export default config({
lists: createSchema({
ListName: list({
fields: {
fieldName: virtual({
field: schema.field({
type: schema.String,
args: { something: schema.arg({ type: schema.Int }) },
field: graphql.field({
type: graphql.String,
args: { something: graphql.arg({ type: graphql.Int }) },
resolve(item, args, context, info) {

}
Expand Down
34 changes: 17 additions & 17 deletions docs/pages/docs/guides/custom-fields.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
FieldTypeFunc,
CommonFieldConfig,
fieldType,
schema,
graphql,
orderDirectionEnum,
filters,
FieldDefaultValue,
Expand Down Expand Up @@ -58,12 +58,12 @@ export const myInt =
})({
...config,
input: {
where: { arg: schema.arg({ type: filters[meta.provider].Int.optional }), resolve: filters.resolveCommon },
create: { arg: schema.arg({ type: schema.Int }) },
update: { arg: schema.arg({ type: schema.Int }) },
orderBy: { arg: schema.arg({ type: orderDirectionEnum }) },
where: { arg: graphql.arg({ type: filters[meta.provider].Int.optional }), resolve: filters.resolveCommon },
create: { arg: graphql.arg({ type: graphql.Int }) },
update: { arg: graphql.arg({ type: graphql.Int }) },
orderBy: { arg: graphql.arg({ type: orderDirectionEnum }) },
},
output: schema.field({ type: schema.Int }),
output: graphql.field({ type: graphql.Int }),
views: require.resolve('./view.tsx'),
__legacy: {
isRequired,
Expand All @@ -83,21 +83,21 @@ The `input` object defines the GraphQL inputs for the field type.

```ts
input: {
where: { arg: schema.arg({ type: filters[meta.provider].Int.optional }), resolve: filters.resolveCommon },
create: { arg: schema.arg({ type: schema.Int }) },
update: { arg: schema.arg({ type: schema.Int }) },
orderBy: { arg: schema.arg({ type: orderDirectionEnum }) },
where: { arg: graphql.arg({ type: filters[meta.provider].Int.optional }), resolve: filters.resolveCommon },
create: { arg: graphql.arg({ type: graphql.Int }) },
update: { arg: graphql.arg({ type: graphql.Int }) },
orderBy: { arg: graphql.arg({ type: orderDirectionEnum }) },
},
```

You can also provide resolvers to transform the value coming from GraphQL into the value that is passed to Prisma.

```ts
input: {
where: { arg: schema.arg({ type: filters[meta.provider].Int.optional }), resolve: filters.resolveCommon },
create: { arg: schema.arg({ type: schema.Int }), resolve: (val, context) => val },
update: { arg: schema.arg({ type: schema.Int }), resolve: (val, context) => val },
orderBy: { arg: schema.arg({ type: orderDirectionEnum }), resolve: (val, context) => val },
where: { arg: graphql.arg({ type: filters[meta.provider].Int.optional }), resolve: filters.resolveCommon },
create: { arg: graphql.arg({ type: graphql.Int }), resolve: (val, context) => val },
update: { arg: graphql.arg({ type: graphql.Int }), resolve: (val, context) => val },
orderBy: { arg: graphql.arg({ type: orderDirectionEnum }), resolve: (val, context) => val },
},
```

Expand All @@ -106,14 +106,14 @@ input: {
The output field defines what can be fetched from the field:

```ts
output: schema.field({ type: schema.Int })
output: graphql.field({ type: graphql.Int })
```

A resolver can also be provided:

```ts
output: schema.field({
type: schema.Int,
output: graphql.field({
type: graphql.Int,
resolve({ value, item }, args, context, info) {
return value;
}
Expand Down
59 changes: 29 additions & 30 deletions docs/pages/docs/guides/virtual-fields.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,16 @@ In this guide we'll introduce the syntax for adding virtual fields, and show how
We'll start with a list called `Example` and create a virtual field called `hello`.

```typescript
import { config, createSchema, list } from '@keystone-next/keystone';
import { config, createSchema, list, graphql } from '@keystone-next/keystone';
import { virtual } from '@keystone-next/keystone/fields';
import { schema } from '@keystone-next/keystone/types';

export default config({
lists: createSchema({
Example: list({
fields: {
hello: virtual({
field: schema.field({
type: schema.String,
field: graphql.field({
type: graphql.String,
resolve() {
return "Hello, world!";
},
Expand Down Expand Up @@ -57,18 +56,18 @@ which gives the response:
The value of `hello` is generated from the `resolve` function, which returns the string `"Hello, world!"`.
## The schema API
## The `graphql` API
The `virtual` field is configured using functions from the `schema` API in the `@keystone-next/keystone/types` package.
The `virtual` field is configured using functions from the `graphql` export from `@keystone-next/keystone`.
This API provides the interface required to create type-safe extensions to the Keystone GraphQL schema.
The schema API is based on the [`@graphql-ts/schema`](https://github.com/Thinkmill/graphql-ts) package.
The `graphql` API is based on the [`@graphql-ts/schema`](https://github.com/Thinkmill/graphql-ts) package.
The `virtual` field accepts a configuration option called `field`, which is a `schema.field()` object.
The `virtual` field accepts a configuration option called `field`, which is a `graphql.field()` object.
In our example we passed in two required options to `schema.field()`.
The option `type: schema.String` specifies the GraphQL type of our virtual field, and `resolve() { ... }` defines the [GraphQL resolver](https://graphql.org/learn/execution/#root-fields-resolvers) to be executed when this field is queried.
In our example we passed in two required options to `graphql.field()`.
The option `type: graphql.String` specifies the GraphQL type of our virtual field, and `resolve() { ... }` defines the [GraphQL resolver](https://graphql.org/learn/execution/#root-fields-resolvers) to be executed when this field is queried.
The `schema` API provides support for the built in GraphQL scalar types `Int`, `Float`, `String`, `Boolean`, and `ID`, as well as the Keystone custom scalars `Upload` and `JSON`.
The `graphql` API provides support for the built in GraphQL scalar types `Int`, `Float`, `String`, `Boolean`, and `ID`, as well as the Keystone custom scalars `Upload` and `JSON`.
## Resolver arguments
Expand All @@ -92,8 +91,8 @@ export default config({
content: text(),
author: relationship({ ref: 'Author', many: false }),
authorName: virtual({
type: schema.String,
field: schema.field({
type: graphql.String,
field: graphql.field({
async resolve(item, args, context) {
const { author } = await context.lists.Post.findOne({
where: { id: item.id.toString() },
Expand Down Expand Up @@ -130,11 +129,11 @@ export default config({
fields: {
content: text(),
excerpt: virtual({
field: schema.field({
type: schema.String,
field: graphql.field({
type: graphql.String,
args: {
length: schema.arg({
type: schema.nonNull(schema.Int),
length: graphql.arg({
type: graphql.nonNull(graphql.Int),
defaultValue: 200
}),
},
Expand Down Expand Up @@ -188,7 +187,7 @@ Had we not specified `defaultValue` in our field, the `graphQLReturnFragment` ar
The examples above returned a scalar `String` value. Virtual fields can also be configured to return a GraphQL object.
In our blog example we might want to provide some statistics on each blog post, such as the number of words, sentences, and paragraphs in the post.
We can set up a GraphQL type called `PostCounts` to represent this data using the `schema.object()` function.
We can set up a GraphQL type called `PostCounts` to represent this data using the `graphql.object()` function.
```typescript
export default config({
Expand All @@ -197,17 +196,17 @@ export default config({
fields: {
content: text(),
counts: virtual({
field: schema.field({
type: schema.object<{
field: graphql.field({
type: graphql.object<{
words: number;
sentences: number;
paragraphs: number;
}>()({
name: 'PostCounts',
fields: {
words: schema.field({ type: schema.Int }),
sentences: schema.field({ type: schema.Int }),
paragraphs: schema.field({ type: schema.Int }),
words: graphql.field({ type: graphql.Int }),
sentences: graphql.field({ type: graphql.Int }),
paragraphs: graphql.field({ type: graphql.Int }),
},
}),
resolve(item: any) {
Expand Down Expand Up @@ -235,18 +234,18 @@ This fragment tells the Keystone Admin UI which values to show in the item page
#### Self-referencing objects
!> This information is specifically for TypeScript users of the `schema.object()` function with a self-referential GraphQL type.
!> This information is specifically for TypeScript users of the `graphql.object()` function with a self-referential GraphQL type.
GraphQL types will often contain references to themselves and to make TypeScript allow that, you need have an explicit type annotation of `schema.ObjectType<RootVal>` along with making `fields` a function that returns the object.
GraphQL types will often contain references to themselves and to make TypeScript allow that, you need have an explicit type annotation of `graphql.ObjectType<RootVal>` along with making `fields` a function that returns the object.
```ts
type PersonRootVal = { name: string; friends: PersonRootVal[] };
const Person: schema.ObjectType<PersonRootVal> = schema.object<PersonRootVal>()({
const Person: graphql.ObjectType<PersonRootVal> = graphql.object<PersonRootVal>()({
name: "Person",
fields: () => ({
name: schema.field({ type: schema.String }),
friends: schema.field({ type: schema.list(Person) }),
name: graphql.field({ type: graphql.String }),
friends: graphql.field({ type: graphql.list(Person) }),
}),
});
```
Expand All @@ -256,7 +255,7 @@ const Person: schema.ObjectType<PersonRootVal> = schema.object<PersonRootVal>()(
Rather than returning a custom GraphQL object, we might want to have a virtual field which returns one of the GraphQL types generated by Keystone itself.
For example, for each `Author` we might want to return their `latestPost` as a `Post` object.
To achieve this, rather than passing in `schema.field({ ... })` as the `field` option, we pass in a function `lists => schema.field({ ... })`.
To achieve this, rather than passing in `graphql.field({ ... })` as the `field` option, we pass in a function `lists => graphql.field({ ... })`.
The argument `lists` contains the type information for all of the Keystone lists.
In our case, we want the output type of the `Post` list, so we specify `type: lists.Post.types.output`.
Expand All @@ -277,7 +276,7 @@ export const lists = createSchema({
posts: relationship({ ref: 'Post.author', many: true }),
latestPost: virtual({
field: lists =>
schema.field({
graphql.field({
type: lists.Post.types.output,
async resolve(item, args, context) {
const { posts } = await context.lists.Author.findOne({
Expand Down
10 changes: 5 additions & 5 deletions examples-staging/basic/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '@keystone-next/keystone/fields';
import { document } from '@keystone-next/fields-document';
// import { cloudinaryImage } from '@keystone-next/cloudinary';
import { KeystoneListsAPI, schema } from '@keystone-next/keystone/types';
import { KeystoneListsAPI, graphql } from '@keystone-next/keystone/types';
import { componentBlocks } from './admin/fieldViews/Content';
import { KeystoneListsTypeInfo } from '.keystone/types';

Expand Down Expand Up @@ -84,8 +84,8 @@ export const lists = createSchema({
}),
posts: relationship({ ref: 'Post.author', many: true }),
randomNumber: virtual({
field: schema.field({
type: schema.Float,
field: graphql.field({
type: graphql.Float,
resolve() {
return randomNumber();
},
Expand All @@ -100,8 +100,8 @@ export const lists = createSchema({
},
fields: {
label: virtual({
field: schema.field({
type: schema.String,
field: graphql.field({
type: graphql.String,
resolve(item) {
return `${item.type} - ${item.value}`;
},
Expand Down
6 changes: 3 additions & 3 deletions examples-staging/ecommerce/schemas/Order.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { integer, text, relationship, virtual } from '@keystone-next/keystone/fields';
import { list } from '@keystone-next/keystone';
import { schema } from '@keystone-next/keystone/types';
import { graphql } from '@keystone-next/keystone/types';
import { isSignedIn, rules } from '../access';
import formatMoney from '../lib/formatMoney';

Expand All @@ -13,8 +13,8 @@ export const Order = list({
},
fields: {
label: virtual({
field: schema.field({
type: schema.String,
field: graphql.field({
type: graphql.String,
resolve(item) {
return `${formatMoney((item as any).total)}`;
},
Expand Down
14 changes: 7 additions & 7 deletions examples/custom-field/stars-field/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
FieldTypeFunc,
CommonFieldConfig,
orderDirectionEnum,
schema,
graphql,
filters,
} from '@keystone-next/keystone/types';

Expand Down Expand Up @@ -57,11 +57,11 @@ export const stars =
// all of these inputs are optional if they don't make sense for a particular field type
input: {
where: {
arg: schema.arg({ type: filters[meta.provider].Int.optional }),
arg: graphql.arg({ type: filters[meta.provider].Int.optional }),
resolve: filters.resolveCommon,
},
create: {
arg: schema.arg({ type: schema.Int }),
arg: graphql.arg({ type: graphql.Int }),
// this field type doesn't need to do anything special
// but field types can specify resolvers for inputs like they can for their output GraphQL field
// this function can be omitted, it is here purely to show how you could change it
Expand All @@ -82,12 +82,12 @@ export const stars =
return val;
},
},
update: { arg: schema.arg({ type: schema.Int }) },
orderBy: { arg: schema.arg({ type: orderDirectionEnum }) },
update: { arg: graphql.arg({ type: graphql.Int }) },
orderBy: { arg: graphql.arg({ type: orderDirectionEnum }) },
},
// this
output: schema.field({
type: schema.Int,
output: graphql.field({
type: graphql.Int,
// like the input resolvers, providing the resolver is unnecessary if you're just returning the value
// it is shown here to show what you could do
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand Down
Loading

0 comments on commit 4278fd4

Please sign in to comment.