Skip to content

Commit

Permalink
Add graphql.schemaPath configuration (#8773)
Browse files Browse the repository at this point in the history
Co-authored-by: Marek Rybczynski <[email protected]>
Co-authored-by: Daniel Cousens <[email protected]>
  • Loading branch information
3 people authored Aug 21, 2023
1 parent d028587 commit 32f7a6a
Show file tree
Hide file tree
Showing 10 changed files with 261 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .changeset/add-graphql-schema-path.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@keystone-6/core': minor
---

Adds `config.graphql.schemaPath`
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
**/.next
**/__generated__
**/dist
**/schema.graphql
**/*.graphql
*.vscode
.changeset/**/*
.keystone/tests
Expand Down
1 change: 1 addition & 0 deletions docs/pages/docs/config/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ Options:
- `false` - Add `ApolloServerPluginLandingPageDisabled` to the Apollo Server plugins
- `'apollo'` - Do not add any plugins to the Apollo config, this will use [Apollo Sandbox](https://www.apollographql.com/docs/apollo-server/testing/build-run-queries/#apollo-sandbox)
- `apolloConfig` (default: `undefined`): Allows you to pass [extra options](https://www.apollographql.com/docs/apollo-server/api/apollo-server/#constructor) into the `ApolloServer` constructor.
- `schemaPath` (default: `schema.graphql`): The path of the generated GraphQL API schema.

```typescript
export default config({
Expand Down
4 changes: 4 additions & 0 deletions examples/custom-output-paths/keystone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export default config({
},
lists,

graphql: {
schemaPath: 'my-graphql.graphql',
},

// when working in a monorepo environment you may want to output the types elsewhere
// you can use .types.path to configure where that is
types: {
Expand Down
232 changes: 232 additions & 0 deletions examples/custom-output-paths/my-graphql.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
# This file is automatically generated by Keystone, do not modify it manually.
# Modify your Keystone config when you want to change this.

type Post {
id: ID!
title: String
content: String
publishDate: DateTime
}

scalar DateTime @specifiedBy(url: "https://datatracker.ietf.org/doc/html/rfc3339#section-5.6")

input PostWhereUniqueInput {
id: ID
}

input PostWhereInput {
AND: [PostWhereInput!]
OR: [PostWhereInput!]
NOT: [PostWhereInput!]
id: IDFilter
title: StringFilter
content: StringFilter
publishDate: DateTimeNullableFilter
}

input IDFilter {
equals: ID
in: [ID!]
notIn: [ID!]
lt: ID
lte: ID
gt: ID
gte: ID
not: IDFilter
}

input StringFilter {
equals: String
in: [String!]
notIn: [String!]
lt: String
lte: String
gt: String
gte: String
contains: String
startsWith: String
endsWith: String
not: NestedStringFilter
}

input NestedStringFilter {
equals: String
in: [String!]
notIn: [String!]
lt: String
lte: String
gt: String
gte: String
contains: String
startsWith: String
endsWith: String
not: NestedStringFilter
}

input DateTimeNullableFilter {
equals: DateTime
in: [DateTime!]
notIn: [DateTime!]
lt: DateTime
lte: DateTime
gt: DateTime
gte: DateTime
not: DateTimeNullableFilter
}

input PostOrderByInput {
id: OrderDirection
title: OrderDirection
content: OrderDirection
publishDate: OrderDirection
}

enum OrderDirection {
asc
desc
}

input PostUpdateInput {
title: String
content: String
publishDate: DateTime
}

input PostUpdateArgs {
where: PostWhereUniqueInput!
data: PostUpdateInput!
}

input PostCreateInput {
title: String
content: String
publishDate: DateTime
}

"""
The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
"""
scalar JSON @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf")

type Mutation {
createPost(data: PostCreateInput!): Post
createPosts(data: [PostCreateInput!]!): [Post]
updatePost(where: PostWhereUniqueInput!, data: PostUpdateInput!): Post
updatePosts(data: [PostUpdateArgs!]!): [Post]
deletePost(where: PostWhereUniqueInput!): Post
deletePosts(where: [PostWhereUniqueInput!]!): [Post]
}

type Query {
posts(where: PostWhereInput! = {}, orderBy: [PostOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: PostWhereUniqueInput): [Post!]
post(where: PostWhereUniqueInput!): Post
postsCount(where: PostWhereInput! = {}): Int
keystone: KeystoneMeta!
}

type KeystoneMeta {
adminMeta: KeystoneAdminMeta!
}

type KeystoneAdminMeta {
lists: [KeystoneAdminUIListMeta!]!
list(key: String!): KeystoneAdminUIListMeta
}

type KeystoneAdminUIListMeta {
key: String!
itemQueryName: String!
listQueryName: String!
hideCreate: Boolean!
hideDelete: Boolean!
path: String!
label: String!
singular: String!
plural: String!
description: String
initialColumns: [String!]!
pageSize: Int!
labelField: String!
fields: [KeystoneAdminUIFieldMeta!]!
groups: [KeystoneAdminUIFieldGroupMeta!]!
initialSort: KeystoneAdminUISort
isHidden: Boolean!
isSingleton: Boolean!
}

type KeystoneAdminUIFieldMeta {
path: String!
label: String!
description: String
isOrderable: Boolean!
isFilterable: Boolean!
isNonNull: [KeystoneAdminUIFieldMetaIsNonNull!]
fieldMeta: JSON
viewsIndex: Int!
customViewsIndex: Int
createView: KeystoneAdminUIFieldMetaCreateView!
listView: KeystoneAdminUIFieldMetaListView!
itemView(id: ID): KeystoneAdminUIFieldMetaItemView
search: QueryMode
}

enum KeystoneAdminUIFieldMetaIsNonNull {
read
create
update
}

type KeystoneAdminUIFieldMetaCreateView {
fieldMode: KeystoneAdminUIFieldMetaCreateViewFieldMode!
}

enum KeystoneAdminUIFieldMetaCreateViewFieldMode {
edit
hidden
}

type KeystoneAdminUIFieldMetaListView {
fieldMode: KeystoneAdminUIFieldMetaListViewFieldMode!
}

enum KeystoneAdminUIFieldMetaListViewFieldMode {
read
hidden
}

type KeystoneAdminUIFieldMetaItemView {
fieldMode: KeystoneAdminUIFieldMetaItemViewFieldMode
fieldPosition: KeystoneAdminUIFieldMetaItemViewFieldPosition
}

enum KeystoneAdminUIFieldMetaItemViewFieldMode {
edit
read
hidden
}

enum KeystoneAdminUIFieldMetaItemViewFieldPosition {
form
sidebar
}

enum QueryMode {
default
insensitive
}

type KeystoneAdminUIFieldGroupMeta {
label: String!
description: String
fields: [KeystoneAdminUIFieldMeta!]!
}

type KeystoneAdminUISort {
field: String!
direction: KeystoneAdminUISortDirection!
}

enum KeystoneAdminUISortDirection {
ASC
DESC
}
6 changes: 5 additions & 1 deletion packages/core/src/artifacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ export function getSystemPaths(cwd: string, config: KeystoneConfig) {
? `./${posixify(path.relative(path.dirname(builtTypesPath), prismaClientPath))}`
: '@prisma/client';

const builtGraphqlPath = config.graphql?.schemaPath
? path.join(cwd, config.graphql.schemaPath)
: path.join(cwd, 'schema.graphql');

return {
config: getBuiltKeystoneConfigurationPath(cwd),
admin: path.join(cwd, '.keystone/admin'),
Expand All @@ -110,7 +114,7 @@ export function getSystemPaths(cwd: string, config: KeystoneConfig) {
schema: {
types: builtTypesPath,
prisma: path.join(cwd, 'schema.prisma'),
graphql: path.join(cwd, 'schema.graphql'),
graphql: builtGraphqlPath,
},
};
}
Expand Down
6 changes: 6 additions & 0 deletions packages/core/src/types/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,12 @@ export type GraphQLConfig<TypeInfo extends BaseKeystoneTypeInfo = BaseKeystoneTy
* @default process.env.NODE_ENV !== 'production'
*/
debug?: boolean;

/**
* The path to GraphQL schema
* @default 'schema.graphql'
*/
schemaPath?: string;
};

// config.extendGraphqlSchema
Expand Down
14 changes: 1 addition & 13 deletions tests/cli-tests/artifacts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
customPrismaKeystoneConfig,
symlinkKeystoneDeps,
testdir,
customGraphqlPathKeystoneConfig,
} from './utils';

describe.each(['postinstall', ['build', '--frozen'], ['prisma', 'migrate', 'status']])(
Expand Down Expand Up @@ -44,19 +45,6 @@ describe('postinstall', () => {
expect(files).toEqual(await getFiles(`${__dirname}/fixtures/basic-project`, schemasMatch));
expect(recording()).toMatchInlineSnapshot(`"? Generated GraphQL and Prisma schemas"`);
});
test('customising primsa schema through extendPrisma works', async () => {
const tmp = await testdir({
...symlinkKeystoneDeps,
'keystone.js': customPrismaKeystoneConfig,
});
const recording = recordConsole();
await runCommand(tmp, ['postinstall', '--fix']);
const files = await getFiles(tmp, ['schema.prisma']);
expect(files).toEqual(
await getFiles(`${__dirname}/fixtures/custom-prisma-project`, ['schema.prisma'])
);
expect(recording()).toMatchInlineSnapshot(`"? Generated GraphQL and Prisma schemas"`);
});
test("does not prompt, error or modify the schemas if they're already up to date", async () => {
const tmp = await testdir({
...symlinkKeystoneDeps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ type Mutation {
}

type Query {
todos(where: TodoWhereInput! = {}, orderBy: [TodoOrderByInput!]! = [], take: Int, skip: Int! = 0): [Todo!]
todos(where: TodoWhereInput! = {}, orderBy: [TodoOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: TodoWhereUniqueInput): [Todo!]
todo(where: TodoWhereUniqueInput!): Todo
todosCount(where: TodoWhereInput! = {}): Int
keystone: KeystoneMeta!
Expand Down
5 changes: 5 additions & 0 deletions tests/cli-tests/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ export const customPrismaKeystoneConfig = fs.readFileSync(
'utf8'
);

export const customGraphqlPathKeystoneConfig = fs.readFileSync(
`${__dirname}/fixtures/custom-graphql-path/keystone.ts`,
'utf8'
);

export function recordConsole() {
let oldConsole = { ...console };
const contents: string[] = [];
Expand Down

0 comments on commit 32f7a6a

Please sign in to comment.