-
Notifications
You must be signed in to change notification settings - Fork 98
Description
GraphQL Configuration protocol
In a nutshell, the simplest format is:
export type GraphQLConfiguration = {
schemaPath?: FilePath, // may be .json or .graphql
schemaUrl?: URL,
schemaJS?: ModulePath | ModuleName,
// If env is specified, use one of the app configs in here
env?: GraphQLConfigurationEnvs
// For multiple applications with overlapping files, bottom configuration options may be helpful
includeDirs?: Array<DirPath>,
excludeDirs?: Array<DirPath>,
// If you have customized validation rules to run
customValidationRules?: FilePath | Array<FilePath>,
// If you'd like to specify any other configurations, we provide a reserved namespace for it
extensions?: GraphQLConfigurationExtension
};
export type GraphQLConfigurationEnvs = {
production: GraphQLConfiguration,
development: GraphQLConfiguration,
// but really just the below
[envVarName: string]: GraphQLConfiguration
};
export type GraphQLConfigurationExtension = {
[toolName: string]: any,
};Note that I'd like to discourage the recursive pattern in using the EnvironmentalVariable - for example:
{
"schemaPath": "...",
"env": {
"production": {
"appProd": {
// BEWARE OF THE BELOW PATTERN!
"env": { ... }
}
}
}
}
Now the reasoning for it: let's start with a most simple use case - one app/one schema.
Single-app/single-schema
Usually a single app requires a schema path/url and an env variable to facilitate the build and deployment:
export type GraphQLAppConfig = {
schemaPath: FilePath,
schemaUrl: URL,
env: EnvironmentVariable
};
export type EnvironmentVariable = {
[envVarName: string]: GraphQLAppConfig
};Multiple-apps/isolated directories
For multiple apps with isolated directories, I like @wincent's idea about a common-default GraphQL configurations, but in spirit of keeping things simple at first, I'd like to propose an one-config-per-directory approach as our first draft. I think there's an edge case where we'd have multiple parent GraphQL configurations to consider:
./repo/.graphqlrc
./repo/appFamily/.graphqlrc
./repo/appFamily/app1/.graphqlrc
This can become a discussion of its own, which we can have separately ;)
Custom validation rules
You may want to run custom validation rules before building GraphQL apps/codegen/etc - customValidationRules is useful for that.
Reserved namespaces
@wincent made a suggestion to provide a way to include any other configurations if you desire. This namespace will contain an app/prod/organization/team-specific GraphQL configurations, and it will be treated as optional settings you'd like to use for your purpose.
{
"schemaPath": "path/to/schema",
"extensions": {
"my-tool": {
"here": "This is a tool-specific extension"
}
}
}
What is this repo, then?
I think this repo should serve two roles in a broader sense:
1. Maintain this protocol and become a town hall for discussions/improvements for this protocol.
2. Provide reference implementations of helper methods to lubricate adoption for this protocol.
An example of the reference implementation of the helper method: we mentioned a way to find this GraphQL configuration is to walk up a directory until it finds one. This basically can be implemented as such:
/**
* (From `graphql-language-service` repo:
* Finds a .graphqlrc configuration file, and returns null if not found.
* If the file isn't present in the provided directory path, walk up the
* directory tree until the file is found or it reaches the root directory.
*/
export function findGraphQLConfigDir(dirPath: string): ?string {
let currentPath = path.resolve(dirPath);
while (true) {
const filePath = path.join(currentPath, '.graphqlrc');
if (fs.existsSync(filePath)) {
break;
}
if (isRootDir(currentPath)) {
break;
}
currentPath = path.dirname(currentPath);
}
return !isRootDir(currentPath) ? currentPath : null;
}
function isRootDIr(path: string): boolean {
return path.dirname(path) === path;
}As there are several use cases, we can tackle each of them and present a way to use this configuration programmatically. I can begin by identifying/suggesting some of them below:
- A generalized module bundler configurations, using GraphQL configurations
- webpack, yeoman, babel, and etc...
- How to include custom validation rules in your application
- How to generate schema with provided schema path(s)
- Sending introspection query to the endpoint
- Parsing/building the schema using a local file path
- Compiling
GraphQLSchemaobject using schema definitions in .js - How to cache the schema
- local files, indexedDB, and etc...
Action items
There are many things to do! But when we successfully deliver this, I believe we can get to the point where we have a shared GraphQL configuration that everyone agrees on, with commonly-used techniques and best practices to configure your GraphQL environment.
- Write a draft for this protocol
- Populate this repository with those helper methods
- Discuss what the superset of those helper methods would be
- Prioritize by the most impactful and common ones and implement them
- Generalize existing implementations and move them here
- Update other remaining documentations, including this repo's README
- Suggest GraphQL configuration as a best-practice at
graphql.org
Lastly, although we've begun this proposal and made a bunch of suggestions, I'd love to have a collaborative effort in pushing this forward. It'll be amazing to see us working together to improve and deliver this proposal to the GraphQL community.
Please post your thoughts/concerns/questions! Also if you'd like to be responsible for one of the actions items above, don't be hesitate to do so :D