-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Move gui
option into constructor and use playground
#1297
Conversation
gui
optionsgui
options
Although I know we want to remain less tied to the GraphQL Playground GUI options, we definitely want to support a wider variety of options to be passed in. This adds support for specifying partial options either statically or dynamically for the gui, which can be extended to allow for a wider array of guis than only GraphQL playground.
gui
optionsgui
options
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zionts Thank you so much for the PR! A couple of requests to bring the settings more in line with the other patterns we uses in the ApolloServer
constructor.
Love the is Partial
, definitely learned something with this PR.
partialGuiOverrides = gui(req); | ||
} | ||
|
||
console.log('partial enabled', partialGuiOverrides.enabled); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove the console.log's before we merge
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops! Thanks for catching.
@@ -29,9 +30,27 @@ export interface ServerRegistration { | |||
bodyParserConfig?: OptionsJson | boolean; | |||
onHealthCheck?: (req: express.Request) => Promise<any>; | |||
disableHealthCheck?: boolean; | |||
gui?: boolean; | |||
gui?: ((req: express.Request) => Partial<GuiOptions>) | Partial<GuiOptions>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's important to retain the option to use or return a boolean for the gui option. Also, we'll have to include this logic across all of the integrations that use a gui. If you think of another way to encapsulate this logic, I'm happy to go for it.
} | ||
|
||
export interface GuiOptions { | ||
enabled: boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to include an enabled boolean, provided that we can use a boolean instead of a configuration. subscriptions are a good example of how this configuration is done in the engine constructor.
} | ||
|
||
export interface GuiOptions { | ||
enabled: boolean; | ||
playgroundSettings: Partial<ISettings>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stubailo was interested in a defaultQuery
option. This should probably include a query, variables, operationName, and headers. The playground settings could take precedence with a console.warn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added in the GraphQL Tabs options, which support this by default. If we add more options in the future, we may want to have a graphqlPlayground field which specifies all of the settings we allow and do a check that exactly one gui
option is configured, but I really don't feel the need to over-abstract something that only has one allowable GUI at the moment.
It's also important to note that these changes should be added to the Playground documentation https://www.apollographql.com/docs/apollo-server/v2/features/playground.html. Probably in a separate PR |
@evans I'm happy to add to the docs as well, but I'm waiting on a merge since I don't want to have to re-write them 😝 |
Does GUI have a For example, https://scaneos.io/gqapi/graphql When opened, it uses https://scaneos.io/graphql as default API URL, while it's wrong. GraphQL Engine have this option: engine.listen(
{
port: 3002,
expressApp: app,
graphqlPaths: [process.env.NODE_ENV === 'production' ? '/gqapi/graphql' : '/graphql'],
}) |
? {} | ||
: nonDynamicGui; | ||
|
||
// Disallow endpoints in pre-fill settings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we actually need to do this. I think this was my misunderstanding what "endpoint" is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're assertion is correct. The endpoint is where that tab is pointed at
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're almost there! I'm okay with the fact that we are only supporting apollo-server/-express
for now. It will make future contributions much easier if the gui configuration functions are placed apollo-server-core.
Thank you again for the PR!
? {} | ||
: nonDynamicGui; | ||
|
||
// Disallow endpoints in pre-fill settings |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're assertion is correct. The endpoint is where that tab is pointed at
app.use(path, (req, res, next) => { | ||
if (guiEnabled && req.method === 'GET') { | ||
// We cannot do an existence check on `gui` since it may be a boolean | ||
const nonDynamicGui: NonDynamicGuiConfig = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we put this configuration in a helper function and place the setting of guiOptions
after the cors options above?
It will put the configuration code together and reduce the complexity of this middleware
|
||
// This is necessary to make TypeScript happy, since it cannot smart-cast types via conditional logic | ||
function isBoolean(gui: NonDynamicGuiConfig): gui is boolean { | ||
return typeof gui === typeof true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be possible with an if statement like so:
if(typeof gui === 'boolean') {
...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay! Yay for TS compile-time type-casting not being absolute trash 🎉 I preferred doing it the ... typeof true
way to leave out the hard-coded string. I assume that's fine, but you'd prefer this logic not to be made a function if it doesn't need to be.
@@ -160,6 +224,8 @@ export class ApolloServer extends ApolloServerBase { | |||
endpoint: path, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to make this endpoint
configurable? or should we be using tabs
like:
{
tabs: [{ endpoint: '/graphql' }]
}
Though it doesn't you can set a subscription endpoint for a tab.
@zionts Hey, it looks like this supports This is what it looks like: The number next to each group indicates how many tabs are open. I'm not sure how, but the playground remembers which tabs I have open between server restarts. I'd love to configure default tabs for new team members & to add these "remembered" tabs with a partial (& a restore defaults button!) but that might be out of scope. Here's how I got this working with
|
Thinking about this more, I think a cleaner solution is to rename |
export function createPlaygroundOptions( | ||
gui: GuiConfig = {}, | ||
): PlaygroundRenderPageOptions | undefined { | ||
const isDev = process.env.NODE_ENV === 'production'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!==
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes! Good catch. Thank you
gui
optionsgui
option into constructor and use playground
Although I know we want to remain less tied to the GraphQL Playground
GUI options, we definitely want to support a wider variety of options to
be passed in. This adds support for specifying partial options either
statically or dynamically for the gui, which can be extended to allow
for a wider array of guis than only GraphQL playground.
TODO: