Skip to content

Commit

Permalink
fix: pre-cacheing schema bugs, new server config options (#1636)
Browse files Browse the repository at this point in the history
- cache paths were not matching up b/c of last minute change
- improve documentation, improve underlying interfaces
- add all loadConfig options as startServer param, deprecate configDir
- cleanup
  • Loading branch information
acao committed Aug 10, 2020
1 parent 27cd185 commit d989456
Show file tree
Hide file tree
Showing 11 changed files with 326 additions and 215 deletions.
23 changes: 15 additions & 8 deletions packages/graphql-language-service-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,26 @@

> Note: As of 3.0.0, this package has been renamed from `graphql-language-service` to `graphql-language-service-cli`. please now use the `graphql-lsp` bin, instead of the `graphql` binary.
[![NPM](https://img.shields.io/npm/v/graphql-language-service.svg)](https://npmjs.com/graphql-language-service)
![npm downloads](https://img.shields.io/npm/dm/graphql-language-service?label=npm%20downloads)
[![NPM](https://img.shields.io/npm/v/graphql-language-service-cli.svg)](https://npmjs.com/graphql-language-service-cli)
![npm downloads](https://img.shields.io/npm/dm/graphql-language-service-vli?label=npm%20downloads)
![Snyk Vulnerabilities for npm package](https://img.shields.io/snyk/vulnerabilities/npm/codemirror-graphql)
[![License](https://img.shields.io/npm/l/graphql-language-service.svg?style=flat-square)](LICENSE)

_We welcome your feedback and suggestions._

GraphQL Language Service provides an interface for building GraphQL language services for IDEs.

Partial support for [Microsoft's Language Server Protocol](https://github.com/Microsoft/language-server-protocol) is in place, with more to come in the future.
Almost 100% for [Microsoft's Language Server Protocol](https://github.com/Microsoft/language-server-protocol) is in place

Supported features include:

- Diagnostics (GraphQL syntax linting/validations) (**spec-compliant**)
- Autocomplete suggestions (**spec-compliant**)
- Hyperlink to fragment definitions and named types (type, input, enum) definitions (**spec-compliant**)
- Outline view support for queries
- Outline view support for queries and SDL
- Symbols support across the workspace

see more information at [`graphql-language-service-server`](https://npmjs.com/graphql-language-service-server)

## Installation and Usage

Expand All @@ -28,6 +31,8 @@ An LSP-compatible client with a file watcher that sends watch notifications to t

**DROPPED**: GraphQL Language Service no longer depends on [Watchman](https://facebook.github.io/watchman/)

Only node 9 or greater, and npm or yarn are required dependencies.

### Installation

with `yarn`:
Expand All @@ -42,20 +47,22 @@ with `npm`:
npm i -g graphql-language-service-cli
```

either will install the `graphql-lsp` bin globally

### GraphQL configuration file (`.graphqlrc.yml`)

Check out [graphql-config](https://graphql-config.com/docs/introduction)

The graphql features we support are:
The custom graphql language configurations are:

- `customDirectives` - `['@myExampleDirective']`
- `customValidationRules` - returns rules array with parameter `ValidationContext` from `graphql/validation`;
- `customValidationRules` - returns rules array with parameter `ValidationContext` from `graphql/validation`

### Using the command-line interface

The node executable contains several commands: `server` and the command-line language service methods (`validate`, `autocomplete`, `outline`).
`graphql-lsp server --schema=localhost:3000`

Improving this list is a work-in-progress.
The node executable contains several commands: `server` and the command-line language service methods (`validate`, `autocomplete`, `outline`).

```
Expand Down
6 changes: 3 additions & 3 deletions packages/graphql-language-service-cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import yargs from 'yargs';
import client from './client';

import { Logger, startServer } from 'graphql-language-service-server';
import { tmpdir } from 'os';

const { argv } = yargs
.usage(
Expand Down Expand Up @@ -104,7 +103,8 @@ const { argv } = yargs
const command = argv._.pop();

if (!command) {
throw Error('no command supplied');
process.stdout.write('no command supplied');
process.exit(0);
}

switch (command) {
Expand All @@ -129,7 +129,7 @@ switch (command) {
try {
startServer(options);
} catch (error) {
const logger = new Logger(tmpdir());
const logger = new Logger();
logger.error(error);
}
break;
Expand Down
31 changes: 20 additions & 11 deletions packages/graphql-language-service-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,20 @@ The library includes a node executable file which you can find in `./node_module

Check out [graphql-config](https://graphql-config.com/docs/introduction)

#### `.graphqlrc` or `.graphqlrc.yml/yaml`
#### `.graphqlrc` or `.graphqlrc.yml/yaml` or `graphql.config.yml`

```yaml
schema: 'packages/api/src/schema.graphql'
documents: 'packages/app/src/components/**/*.graphql'
documents: 'packages/app/src/components/**/*.{tsx,ts}'
extensions:
endpoints:
example:
url: 'http://localhost:8000'
customExtension:
foo: true
```

#### `.graphqlrc` or `.graphqlrc.json`
#### `.graphqlrc` or `.graphqlrc.json` or `graphql.config.json`

```json
{ "schema": "https://localhost:8000" }
Expand All @@ -64,7 +67,7 @@ extensions:
module.exports = { schema: 'https://localhost:8000' };
```

#### custom `loadConfig`
#### custom `startServer`

use graphql config [`loadConfig`](https://graphql-config.com/docs/load-config) for further customization:

Expand All @@ -73,14 +76,20 @@ import { loadConfig } from 'graphql-config'; // 3.0.0 or later!

await startServer({
method: 'node',
config: loadConfig({
// myPlatform.config.js works now!
// or instead of configName, an exact path (relative from rootDir or absolute)

// deprecated for: loadConfigOptions.rootDir. root directory for graphql config file(s), or for relative resolution for exact `filePath`. default process.cwd()
// configDir: '',
loadConfigOptions: {
// any of the options for graphql-config@3 `loadConfig()`

// rootDir is same as `configDir` before, the path where the graphql config file would be found by cosmic-config
rootDir: 'config/',
// or - the relative or absolute path to your file
filePath: 'exact/path/to/config.js (also supports yml, json)',
// myPlatform.config.js/json/yaml works now!
configName: 'myPlatform',
// or instead of configName, an exact path (relative from rootDir or absolute)
filePath: 'exact/path/to/config.js (also supports yml, json)'
// rootDir to look for config file(s), or for relative resolution for exact `filePath`. default process.cwd()
rootDir: '',
})
},
});
```

Expand Down
63 changes: 32 additions & 31 deletions packages/graphql-language-service-server/src/GraphQLCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
import { parseDocument } from './parseDocument';
import stringToHash from './stringToHash';
import glob from 'glob';
import { GraphQLExtensionDeclaration } from 'graphql-config/extension';
import { LoadConfigOptions } from './types';

// Maximum files to read when processing GraphQL files.
const MAX_READS = 200;
Expand All @@ -53,26 +53,26 @@ const {
DIRECTIVE_DEFINITION,
} = Kind;

export async function getGraphQLCache(
configDir: Uri,
parser: typeof parseDocument,
extensions: GraphQLExtensionDeclaration[] = [],
config?: GraphQLConfig,
fileExtensions: string[] = [],
// loadConfigOptions?: Parameters<typeof loadConfig>,
): Promise<GraphQLCacheInterface> {
const graphQLConfig =
config ??
(await loadConfig({
rootDir: configDir,
extensions,
}));
return new GraphQLCache(
configDir,
graphQLConfig as GraphQLConfig,
export async function getGraphQLCache({
parser,
loadConfigOptions,
config,
}: {
parser: typeof parseDocument;
loadConfigOptions: LoadConfigOptions;
config?: GraphQLConfig;
}): Promise<GraphQLCacheInterface> {
let graphQLConfig;
if (config) {
graphQLConfig = config;
} else {
graphQLConfig = await loadConfig(loadConfigOptions);
}
return new GraphQLCache({
configDir: loadConfigOptions.rootDir as string,
config: graphQLConfig as GraphQLConfig,
parser,
fileExtensions,
);
});
}

export class GraphQLCache implements GraphQLCacheInterface {
Expand All @@ -84,23 +84,24 @@ export class GraphQLCache implements GraphQLCacheInterface {
_fragmentDefinitionsCache: Map<Uri, Map<string, FragmentInfo>>;
_typeDefinitionsCache: Map<Uri, Map<string, ObjectTypeInfo>>;
_parser: typeof parseDocument;
_fileExtensions: string[];

constructor(
configDir: Uri,
graphQLConfig: GraphQLConfig,
parser: typeof parseDocument,
fileExtensions: string[],
) {

constructor({
configDir,
config,
parser,
}: {
configDir: Uri;
config: GraphQLConfig;
parser: typeof parseDocument;
}) {
this._configDir = configDir;
this._graphQLConfig = graphQLConfig;
this._graphQLConfig = config;
this._graphQLFileListCache = new Map();
this._schemaMap = new Map();
this._fragmentDefinitionsCache = new Map();
this._typeDefinitionsCache = new Map();
this._typeExtensionMap = new Map();
this._parser = parser;
this._fileExtensions = fileExtensions;
}

getGraphQLConfig = (): GraphQLConfig => this._graphQLConfig;
Expand Down Expand Up @@ -807,7 +808,7 @@ export class GraphQLCache implements GraphQLCacheInterface {
let queries: CachedContent[] = [];
if (content.trim().length !== 0) {
try {
queries = this._parser(content, filePath, this._fileExtensions);
queries = this._parser(content, filePath);
if (queries.length === 0) {
// still resolve with an empty ast
resolve({
Expand Down
Loading

0 comments on commit d989456

Please sign in to comment.