Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add introspection support to Apollo Server Config #6391

Merged
merged 4 commits into from
Aug 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/great-cougars-argue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@keystone-next/website': patch
'@keystone-next/example-playground': patch
'@keystone-next/keystone': patch
---

Adds support for `introspection` in the Apollo Server config. Introspection enables you to query a GraphQL server for information about the underlying schema. If the playground is enabled then introspection is automatically enabled - unless specifically disabled.
5 changes: 3 additions & 2 deletions docs/pages/docs/apis/config.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ Options:
See also the per-list `graphql.queryLimits` option in the [Schema API](./schema).
- `apolloConfig` (default: `undefined`): Allows you to pass extra options into the `ApolloServer` constructor.
- `playground` (default: `process.env.NODE_ENV !== 'production'`): If truthy, will enable the GraphQL Playground for testing queries and mutations in the browser.
To configure behaviour, pass an object of [GraphQL Playground settings](https://github.com/graphql/graphql-playground#settings).
- See the [Apollo docs](https://www.apollographql.com/docs/apollo-server/api/apollo-server/#constructor) for more supported options.
To configure behaviour, pass an object of [GraphQL Playground settings](https://github.com/graphql/graphql-playground#settings). See the [Apollo docs](https://www.apollographql.com/docs/apollo-server/api/apollo-server/#constructor) for more supported options.
- `introspection` (default: `undefined`): Introspection enables you to query a GraphQL server for information about the underlying schema. If the playground is enabled then introspection is automatically enabled, unless specifically disabled.

```typescript
export default config({
Expand All @@ -295,6 +295,7 @@ export default config({
queryLimits: { maxTotalResults: 100 },
apolloConfig: {
playground: process.env.NODE_ENV !== 'production',
introspection: process.env.NODE_ENV !== 'production',
/* ... */
},
},
Expand Down
29 changes: 22 additions & 7 deletions examples-staging/playground/keystone.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { config } from '@keystone-next/keystone';
import { lists } from './schema';

// graphql.apolloConfig.playground === false (playground not accessible in all cases)
// graphql.apolloConfig.playground === false (playground not accessible in all cases, introspection will be disabled by default)
// export default config({
// db: {
// provider: 'sqlite',
Expand All @@ -15,7 +15,7 @@ import { lists } from './schema';
// }
// });

// graphql.apolloConfig.playground === true (playground accessible in all cases)
// graphql.apolloConfig.playground === true (playground accessible in all cases, introspection will be enabled by default)
// export default config({
// db: {
// provider: 'sqlite',
Expand All @@ -25,11 +25,26 @@ import { lists } from './schema';
// graphql: {
// apolloConfig: {
// playground: true,
// }
// }
// },
// },
// });

// graphql.apolloConfig.playground === true && graphql.apolloConfig.introspection === false (playground accessible in all cases, introspection disabled)
// export default config({
// db: {
// provider: 'sqlite',
// url: process.env.DATABASE_URL || 'file:./keystone-example.db',
// },
// lists,
// graphql: {
// apolloConfig: {
// playground: true,
// introspection: false,
// },
// },
// });

// graphql.apolloConfig.playground === { settings: ... } (playground accessible in all cases with further customisation - https://www.apollographql.com/docs/apollo-server/testing/graphql-playground)
// graphql.apolloConfig.playground === { settings: ... } (playground accessible in all cases with further customisation - https://www.apollographql.com/docs/apollo-server/testing/graphql-playground, introspection will be enabled by default)
// export default config({
// db: {
// provider: 'sqlite',
Expand All @@ -47,7 +62,7 @@ import { lists } from './schema';
// }
// });

// process.env.NODE_ENV === 'production' (playground not accessible in production)
// process.env.NODE_ENV === 'production' (playground not accessible in production, introspection will be disabled by default)
// process.env.NODE_ENV = 'production';
// export default config({
// db: {
Expand All @@ -62,7 +77,7 @@ import { lists } from './schema';
// }
// });

// not specified at all (playground uses defaults)
// not specified at all (playground and introspection uses defaults, enabled in development and disabled in production)
export default config({
db: {
provider: 'sqlite',
Expand Down
33 changes: 27 additions & 6 deletions packages/keystone/src/lib/server/createApolloServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,22 @@ const _createApolloServerConfig = ({
}) => {
// Playground config, is /api/graphql available?
const apolloConfig = graphqlConfig?.apolloConfig;
const pp = apolloConfig?.playground;
const apolloConfigPlayground = apolloConfig?.playground;
let playground: Config['playground'];
const settings = { 'request.credentials': 'same-origin' };

if (typeof pp === 'boolean' && !pp) {
if (typeof apolloConfigPlayground === 'boolean' && !apolloConfigPlayground) {
// graphql.apolloConfig.playground === false (playground not accessible in all cases)
playground = false;
} else if (typeof pp === 'boolean') {
} else if (typeof apolloConfigPlayground === 'boolean') {
// graphql.apolloConfig.playground === true (playground accessible in all cases)
playground = { settings };
} else if (pp) {
} else if (apolloConfigPlayground) {
// graphql.apolloConfig.playground === { settings: ... } (playground accessible in all cases with further customisation - https://www.apollographql.com/docs/apollo-server/testing/graphql-playground)
playground = { ...pp, settings: { ...settings, ...pp.settings } };
playground = {
...apolloConfigPlayground,
settings: { ...settings, ...apolloConfigPlayground.settings },
};
} else if (process.env.NODE_ENV === 'production') {
// process.env.NODE_ENV === 'production' (playground not accessible in production)
playground = undefined;
Expand All @@ -84,6 +87,23 @@ const _createApolloServerConfig = ({
playground = { settings };
}

const apolloConfigIntrospection = apolloConfig?.introspection;
let introspection: Config['introspection'];

if (typeof apolloConfigIntrospection === 'boolean' && !apolloConfigIntrospection) {
// graphql.apolloConfig.introspection === false (introspection not accessible in all cases)
introspection = false;
} else if (typeof apolloConfigIntrospection === 'boolean') {
// graphql.apolloConfig.introspection === true (introspection accessible in all cases)
introspection = true;
} else if (process.env.NODE_ENV === 'production') {
// process.env.NODE_ENV === 'production' (introspection not accessible in production)
introspection = undefined;
} else if ((typeof playground === 'boolean' && playground) || typeof playground === 'object') {
// not specified at all (introspection enabled if playground is enabled or defined)
introspection = true;
}

return {
uploads: false,
schema: graphQLSchema,
Expand All @@ -100,8 +120,9 @@ const _createApolloServerConfig = ({
// }),
...apolloConfig,
formatError: formatError(graphqlConfig),
// Carefully inject the playground
// Carefully inject the playground and introspection variables
playground,
introspection,
// FIXME: Support for file handling configuration
// maxFileSize: 200 * 1024 * 1024,
// maxFiles: 5,
Expand Down