Skip to content

Commit

Permalink
add config.graphql.schemaPath
Browse files Browse the repository at this point in the history
  • Loading branch information
marekryb authored and dcousens committed Aug 21, 2023
1 parent 992c60a commit f64d0fc
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 2 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`
1 change: 1 addition & 0 deletions docs/pages/docs/config/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,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
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 graphqlSchemaPath = 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: graphqlSchemaPath,
},
};
}
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;
};

export type FilesConfig = {
Expand Down
13 changes: 13 additions & 0 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']])('%s', command => {
Expand Down Expand Up @@ -96,4 +97,16 @@ describe('postinstall', () => {
expect(await getFiles(tmp, ['node_modules/.keystone/**/*'])).toMatchSnapshot();
expect(recording()).toMatchInlineSnapshot(`"? GraphQL and Prisma schemas are up to date"`);
});
test('customising graphQL schema through schemaPath works', async () => {
const tmp = await testdir({
...symlinkKeystoneDeps,
'keystone.js': customGraphqlPathKeystoneConfig,
});
const recording = recordConsole();
await runCommand(tmp, ['postinstall', '--fix']);
const schemas = ['schema.prisma', 'different_schema.graphql'];
const files = await getFiles(tmp, schemas);
expect(files).toEqual(await getFiles(`${__dirname}/fixtures/custom-graphql-path`, schemas));
expect(recording()).toMatchInlineSnapshot(`"? Generated GraphQL and Prisma schemas"`);
});
});
209 changes: 209 additions & 0 deletions tests/cli-tests/fixtures/custom-graphql-path/different_schema.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
# This file is automatically generated by Keystone, do not modify it manually.
# Modify your Keystone config when you want to change this.

type Todo {
id: ID!
title: String
}

input TodoWhereUniqueInput {
id: ID
}

input TodoWhereInput {
AND: [TodoWhereInput!]
OR: [TodoWhereInput!]
NOT: [TodoWhereInput!]
id: IDFilter
title: StringFilter
}

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 TodoOrderByInput {
id: OrderDirection
title: OrderDirection
}

enum OrderDirection {
asc
desc
}

input TodoUpdateInput {
title: String
}

input TodoUpdateArgs {
where: TodoWhereUniqueInput!
data: TodoUpdateInput!
}

input TodoCreateInput {
title: String
}

"""
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 {
createTodo(data: TodoCreateInput!): Todo
createTodos(data: [TodoCreateInput!]!): [Todo]
updateTodo(where: TodoWhereUniqueInput!, data: TodoUpdateInput!): Todo
updateTodos(data: [TodoUpdateArgs!]!): [Todo]
deleteTodo(where: TodoWhereUniqueInput!): Todo
deleteTodos(where: [TodoWhereUniqueInput!]!): [Todo]
}

type Query {
todos(where: TodoWhereInput! = {}, orderBy: [TodoOrderByInput!]! = [], take: Int, skip: Int! = 0, cursor: TodoWhereUniqueInput): [Todo!]
todo(where: TodoWhereUniqueInput!): Todo
todosCount(where: TodoWhereInput! = {}): 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
}
22 changes: 22 additions & 0 deletions tests/cli-tests/fixtures/custom-graphql-path/keystone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { list, config } from '@keystone-6/core';
import { allowAll } from '@keystone-6/core/access';
import { text } from '@keystone-6/core/fields';

export default config({
db: {
provider: 'sqlite',
url: 'file:./app.db',
},
ui: { isDisabled: true },
lists: {
Todo: list({
access: allowAll,
fields: {
title: text(),
},
}),
},
graphql: {
schemaPath: 'different_schema.graphql',
},
});
17 changes: 17 additions & 0 deletions tests/cli-tests/fixtures/custom-graphql-path/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// This file is automatically generated by Keystone, do not modify it manually.
// Modify your Keystone config when you want to change this.

datasource sqlite {
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
provider = "sqlite"
}

generator client {
provider = "prisma-client-js"
}

model Todo {
id String @id @default(cuid())
title String @default("")
}
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 f64d0fc

Please sign in to comment.