vscode-apollo 1.20.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/.circleci/config.yml +27 -18
  2. package/.git-blame-ignore-revs +2 -0
  3. package/.nvmrc +1 -1
  4. package/.vscode/launch.json +9 -4
  5. package/.vscode/tasks.json +58 -16
  6. package/.vscodeignore +12 -1
  7. package/CHANGELOG.md +78 -0
  8. package/CODEOWNERS +4 -0
  9. package/README.md +97 -48
  10. package/graphql.configuration.json +5 -1
  11. package/images/marketplace/apollo-wordmark.png +0 -0
  12. package/jest.config.ts +14 -4
  13. package/jest.e2e.config.js +17 -0
  14. package/package.json +67 -68
  15. package/renovate.json +7 -0
  16. package/sampleWorkspace/clientSchema/apollo.config.cjs +10 -0
  17. package/sampleWorkspace/clientSchema/src/clientSchema.js +16 -0
  18. package/sampleWorkspace/clientSchema/src/test.js +18 -0
  19. package/sampleWorkspace/fixtures/starwarsSchema.graphql +299 -0
  20. package/sampleWorkspace/httpSchema/apollo.config.ts +8 -0
  21. package/sampleWorkspace/httpSchema/src/test.js +9 -0
  22. package/sampleWorkspace/localSchema/apollo.config.js +8 -0
  23. package/sampleWorkspace/localSchema/src/test.js +8 -0
  24. package/sampleWorkspace/localSchemaArray/apollo.config.js +12 -0
  25. package/sampleWorkspace/localSchemaArray/planets.graphql +20 -0
  26. package/sampleWorkspace/localSchemaArray/src/test.js +12 -0
  27. package/sampleWorkspace/sampleWorkspace.code-workspace +20 -0
  28. package/sampleWorkspace/spotifyGraph/apollo.config.mjs +5 -0
  29. package/sampleWorkspace/spotifyGraph/src/test.js +11 -0
  30. package/src/__e2e__/mockServer.js +117 -0
  31. package/src/__e2e__/mocks.js +13094 -0
  32. package/src/__e2e__/run.js +23 -0
  33. package/src/__e2e__/runTests.js +44 -0
  34. package/src/__e2e__/setup.js +1 -0
  35. package/src/__e2e__/vscode-environment.js +16 -0
  36. package/src/__e2e__/vscode.js +1 -0
  37. package/src/build.js +57 -0
  38. package/src/env/index.ts +0 -3
  39. package/src/extension.ts +251 -225
  40. package/src/language-server/__e2e__/clientSchema.e2e.ts +147 -0
  41. package/src/language-server/__e2e__/httpSchema.e2e.ts +21 -0
  42. package/src/language-server/__e2e__/localSchema.e2e.ts +25 -0
  43. package/src/language-server/__e2e__/localSchemaArray.e2e.ts +31 -0
  44. package/src/language-server/__e2e__/studioGraph.e2e.ts +65 -0
  45. package/src/language-server/__e2e__/utils.ts +151 -0
  46. package/src/language-server/__tests__/diagnostics.test.ts +8 -8
  47. package/src/language-server/__tests__/fileSet.test.ts +1 -1
  48. package/src/language-server/__tests__/fixtures/starwarsSchema.ts +2 -2
  49. package/src/language-server/config/__tests__/config.ts +22 -96
  50. package/src/language-server/config/__tests__/loadConfig.ts +97 -221
  51. package/src/language-server/config/__tests__/utils.ts +22 -29
  52. package/src/language-server/config/config.ts +221 -156
  53. package/src/language-server/config/loadConfig.ts +26 -153
  54. package/src/language-server/config/utils.ts +5 -16
  55. package/src/language-server/diagnostics.ts +17 -8
  56. package/src/language-server/document.ts +16 -16
  57. package/src/language-server/engine/index.ts +57 -39
  58. package/src/language-server/engine/operations/frontendUrlRoot.ts +9 -1
  59. package/src/language-server/engine/operations/schemaTagsAndFieldStats.ts +9 -1
  60. package/src/language-server/errors/__tests__/NoMissingClientDirectives.test.ts +10 -5
  61. package/src/language-server/errors/logger.ts +1 -1
  62. package/src/language-server/errors/validation.ts +20 -23
  63. package/src/language-server/fileSet.ts +10 -12
  64. package/src/language-server/format.ts +1 -1
  65. package/src/language-server/graphqlTypes.ts +13020 -3455
  66. package/src/language-server/index.ts +0 -1
  67. package/src/language-server/languageProvider.ts +29 -32
  68. package/src/language-server/loadingHandler.ts +10 -27
  69. package/src/language-server/project/base.ts +32 -25
  70. package/src/language-server/project/client.ts +80 -114
  71. package/src/language-server/project/defaultClientSchema.ts +29 -4
  72. package/src/language-server/providers/schema/__tests__/file.ts +60 -19
  73. package/src/language-server/providers/schema/base.ts +2 -2
  74. package/src/language-server/providers/schema/endpoint.ts +15 -34
  75. package/src/language-server/providers/schema/engine.ts +25 -18
  76. package/src/language-server/providers/schema/file.ts +41 -32
  77. package/src/language-server/providers/schema/index.ts +5 -21
  78. package/src/language-server/server.ts +72 -50
  79. package/src/language-server/typings/graphql.d.ts +3 -3
  80. package/src/language-server/utilities/__tests__/graphql.test.ts +42 -54
  81. package/src/language-server/utilities/debouncer.ts +1 -1
  82. package/src/language-server/utilities/debug.ts +6 -5
  83. package/src/language-server/utilities/graphql.ts +17 -16
  84. package/src/language-server/utilities/source.ts +16 -16
  85. package/src/language-server/utilities/uri.ts +2 -2
  86. package/src/language-server/workspace.ts +29 -37
  87. package/src/languageServerClient.ts +4 -4
  88. package/src/messages.ts +38 -47
  89. package/src/tools/__tests__/buildServiceDefinition.test.ts +2 -2
  90. package/src/tools/buildServiceDefinition.ts +11 -11
  91. package/src/tools/schema/resolveObject.ts +1 -1
  92. package/src/tools/utilities/predicates.ts +1 -1
  93. package/src/utils.ts +7 -6
  94. package/syntaxes/graphql.dart.json +2 -4
  95. package/syntaxes/graphql.ex.json +1 -4
  96. package/tsconfig.build.json +8 -1
  97. package/tsconfig.json +5 -3
  98. package/src/env/fetch/fetch.ts +0 -32
  99. package/src/env/fetch/global.ts +0 -30
  100. package/src/env/fetch/index.d.ts +0 -2
  101. package/src/env/fetch/index.ts +0 -2
  102. package/src/env/fetch/url.ts +0 -9
  103. package/src/env/polyfills/array.ts +0 -17
  104. package/src/env/polyfills/index.ts +0 -2
  105. package/src/env/polyfills/object.ts +0 -7
  106. package/src/language-server/engine/GraphQLDataSource.ts +0 -124
  107. package/src/language-server/project/service.ts +0 -48
  108. package/src/language-server/typings/codemirror.d.ts +0 -4
@@ -3,30 +3,21 @@ import {
3
3
  ClientConfig,
4
4
  ClientServiceConfig,
5
5
  LocalServiceConfig,
6
- ServiceConfig,
7
- ApolloConfigFormat,
6
+ ParsedApolloConfigFormat,
8
7
  } from "./config";
9
8
  import { ServiceSpecifier, ServiceIDAndTag } from "../engine";
10
9
 
11
10
  export function isClientConfig(config: ApolloConfig): config is ClientConfig {
12
- return config.isClient;
11
+ return config instanceof ClientConfig;
13
12
  }
14
13
 
15
14
  // checks the `config.client.service` object for a localSchemaFile
16
15
  export function isLocalServiceConfig(
17
- config: ClientServiceConfig
16
+ config: ClientServiceConfig,
18
17
  ): config is LocalServiceConfig {
19
18
  return !!(config as LocalServiceConfig).localSchemaFile;
20
19
  }
21
20
 
22
- export function isServiceConfig(config: ApolloConfig): config is ServiceConfig {
23
- return config.isService;
24
- }
25
-
26
- export function isServiceKey(key?: string) {
27
- return key && /service:.*:.*/.test(key);
28
- }
29
-
30
21
  export function getServiceFromKey(key?: string) {
31
22
  if (key) {
32
23
  const [type, service] = key.split(":");
@@ -35,13 +26,11 @@ export function getServiceFromKey(key?: string) {
35
26
  return;
36
27
  }
37
28
 
38
- export function getGraphIdFromConfig(config: ApolloConfigFormat) {
39
- if (config.service && config.service.name)
40
- return parseServiceSpecifier(config.service.name)[0];
29
+ export function getGraphIdFromConfig(config: ParsedApolloConfigFormat) {
41
30
  if (config.client) {
42
31
  if (typeof config.client.service === "string") {
43
32
  return parseServiceSpecifier(
44
- config.client.service as ServiceSpecifier
33
+ config.client.service as ServiceSpecifier,
45
34
  )[0];
46
35
  }
47
36
  return config.client.service && config.client.service.name;
@@ -2,11 +2,20 @@ import {
2
2
  GraphQLSchema,
3
3
  GraphQLError,
4
4
  FragmentDefinitionNode,
5
- findDeprecatedUsages,
6
5
  isExecutableDefinitionNode,
6
+ DocumentNode,
7
+ validate,
8
+ NoDeprecatedCustomRule,
7
9
  } from "graphql";
8
10
 
9
- import { Diagnostic, DiagnosticSeverity } from "vscode-languageserver";
11
+ function findDeprecatedUsages(
12
+ schema: GraphQLSchema,
13
+ ast: DocumentNode,
14
+ ): ReadonlyArray<GraphQLError> {
15
+ return validate(schema, ast, [NoDeprecatedCustomRule]);
16
+ }
17
+
18
+ import { Diagnostic, DiagnosticSeverity } from "vscode-languageserver/node";
10
19
 
11
20
  import { GraphQLDocument } from "./document";
12
21
  import { highlightNodeForNode } from "./utilities/graphql";
@@ -23,7 +32,7 @@ export function collectExecutableDefinitionDiagnositics(
23
32
  schema: GraphQLSchema,
24
33
  queryDocument: GraphQLDocument,
25
34
  fragments: { [fragmentName: string]: FragmentDefinitionNode } = {},
26
- rules?: ValidationRule[]
35
+ rules?: ValidationRule[],
27
36
  ): Diagnostic[] {
28
37
  const ast = queryDocument.ast;
29
38
  if (!ast) return queryDocument.syntaxErrors;
@@ -39,19 +48,19 @@ export function collectExecutableDefinitionDiagnositics(
39
48
  schema,
40
49
  astWithExecutableDefinitions,
41
50
  fragments,
42
- rules
51
+ rules,
43
52
  )) {
44
53
  diagnostics.push(
45
- ...diagnosticsFromError(error, DiagnosticSeverity.Error, "Validation")
54
+ ...diagnosticsFromError(error, DiagnosticSeverity.Error, "Validation"),
46
55
  );
47
56
  }
48
57
 
49
58
  for (const error of findDeprecatedUsages(
50
59
  schema,
51
- astWithExecutableDefinitions
60
+ astWithExecutableDefinitions,
52
61
  )) {
53
62
  diagnostics.push(
54
- ...diagnosticsFromError(error, DiagnosticSeverity.Warning, "Deprecation")
63
+ ...diagnosticsFromError(error, DiagnosticSeverity.Warning, "Deprecation"),
55
64
  );
56
65
  }
57
66
 
@@ -61,7 +70,7 @@ export function collectExecutableDefinitionDiagnositics(
61
70
  export function diagnosticsFromError(
62
71
  error: GraphQLError,
63
72
  severity: DiagnosticSeverity,
64
- type: string
73
+ type: string,
65
74
  ): GraphQLDiagnostic[] {
66
75
  if (!error.nodes) {
67
76
  return [];
@@ -6,9 +6,9 @@ import {
6
6
  Position,
7
7
  Diagnostic,
8
8
  DiagnosticSeverity,
9
- } from "vscode-languageserver";
9
+ } from "vscode-languageserver/node";
10
10
 
11
- import { getRange as rangeOfTokenAtLocation } from "graphql-language-service-interface/dist/getDiagnostics";
11
+ import { getRange as rangeOfTokenAtLocation } from "graphql-language-service";
12
12
 
13
13
  import {
14
14
  positionFromSourceLocation,
@@ -30,7 +30,7 @@ export class GraphQLDocument {
30
30
  // So we use the online parser to get the range of the token at that location
31
31
  const range = rangeInContainingDocument(
32
32
  source,
33
- rangeOfTokenAtLocation(error.locations[0], source.body)
33
+ rangeOfTokenAtLocation(error.locations[0], source.body),
34
34
  );
35
35
  this.syntaxErrors.push({
36
36
  severity: DiagnosticSeverity.Error,
@@ -45,7 +45,7 @@ export class GraphQLDocument {
45
45
  if (position.line < this.source.locationOffset.line - 1) return false;
46
46
  const end = positionFromSourceLocation(
47
47
  this.source,
48
- getLocation(this.source, this.source.body.length)
48
+ getLocation(this.source, this.source.body.length),
49
49
  );
50
50
  return position.line <= end.line;
51
51
  }
@@ -53,7 +53,7 @@ export class GraphQLDocument {
53
53
 
54
54
  export function extractGraphQLDocuments(
55
55
  document: TextDocument,
56
- tagName: string = "gql"
56
+ tagName: string = "gql",
57
57
  ): GraphQLDocument[] | null {
58
58
  switch (document.languageId) {
59
59
  case "graphql":
@@ -84,7 +84,7 @@ export function extractGraphQLDocuments(
84
84
 
85
85
  function extractGraphQLDocumentsFromJSTemplateLiterals(
86
86
  document: TextDocument,
87
- tagName: string
87
+ tagName: string,
88
88
  ): GraphQLDocument[] | null {
89
89
  const text = document.getText();
90
90
 
@@ -92,7 +92,7 @@ function extractGraphQLDocumentsFromJSTemplateLiterals(
92
92
 
93
93
  const regExp = new RegExp(
94
94
  `(?:${tagName}(?:\\s|\\()*\`|\`#graphql)([\\s\\S]+?)\`\\)?`,
95
- "gm"
95
+ "gm",
96
96
  );
97
97
 
98
98
  let result;
@@ -114,7 +114,7 @@ function extractGraphQLDocumentsFromJSTemplateLiterals(
114
114
 
115
115
  function extractGraphQLDocumentsFromPythonStrings(
116
116
  document: TextDocument,
117
- tagName: string
117
+ tagName: string,
118
118
  ): GraphQLDocument[] | null {
119
119
  const text = document.getText();
120
120
 
@@ -122,7 +122,7 @@ function extractGraphQLDocumentsFromPythonStrings(
122
122
 
123
123
  const regExp = new RegExp(
124
124
  `\\b(${tagName}\\s*\\(\\s*[bfru]*("(?:"")?|'(?:'')?))([\\s\\S]+?)\\2\\s*\\)`,
125
- "gm"
125
+ "gm",
126
126
  );
127
127
 
128
128
  let result;
@@ -144,7 +144,7 @@ function extractGraphQLDocumentsFromPythonStrings(
144
144
 
145
145
  function extractGraphQLDocumentsFromRubyStrings(
146
146
  document: TextDocument,
147
- tagName: string
147
+ tagName: string,
148
148
  ): GraphQLDocument[] | null {
149
149
  const text = document.getText();
150
150
 
@@ -171,7 +171,7 @@ function extractGraphQLDocumentsFromRubyStrings(
171
171
 
172
172
  function extractGraphQLDocumentsFromDartStrings(
173
173
  document: TextDocument,
174
- tagName: string
174
+ tagName: string,
175
175
  ): GraphQLDocument[] | null {
176
176
  const text = document.getText();
177
177
 
@@ -179,7 +179,7 @@ function extractGraphQLDocumentsFromDartStrings(
179
179
 
180
180
  const regExp = new RegExp(
181
181
  `\\b(${tagName}\\(\\s*r?("""|'''))([\\s\\S]+?)\\2\\s*\\)`,
182
- "gm"
182
+ "gm",
183
183
  );
184
184
 
185
185
  let result;
@@ -201,7 +201,7 @@ function extractGraphQLDocumentsFromDartStrings(
201
201
 
202
202
  function extractGraphQLDocumentsFromReasonStrings(
203
203
  document: TextDocument,
204
- tagName: string
204
+ tagName: string,
205
205
  ): GraphQLDocument[] | null {
206
206
  const text = document.getText();
207
207
 
@@ -214,7 +214,7 @@ function extractGraphQLDocumentsFromReasonStrings(
214
214
  }
215
215
 
216
216
  const reasonRegexp = new RegExp(
217
- /(?<=\[%(graphql|relay\.\w*)[\s\S]*{\|)[.\s\S]+?(?=\|})/gm
217
+ /(?<=\[%(graphql|relay\.\w*)[\s\S]*{\|)[.\s\S]+?(?=\|})/gm,
218
218
  );
219
219
 
220
220
  let result;
@@ -236,14 +236,14 @@ function extractGraphQLDocumentsFromReasonStrings(
236
236
 
237
237
  function extractGraphQLDocumentsFromElixirStrings(
238
238
  document: TextDocument,
239
- tagName: string
239
+ tagName: string,
240
240
  ): GraphQLDocument[] | null {
241
241
  const text = document.getText();
242
242
  const documents: GraphQLDocument[] = [];
243
243
 
244
244
  const regExp = new RegExp(
245
245
  `\\b(${tagName}\\(\\s*r?("""))([\\s\\S]+?)\\2\\s*\\)`,
246
- "gm"
246
+ "gm",
247
247
  );
248
248
 
249
249
  let result;
@@ -1,16 +1,18 @@
1
- import { GraphQLDataSource } from "./GraphQLDataSource";
2
- import { DefaultEngineConfig } from "../config";
3
1
  import { SCHEMA_TAGS_AND_FIELD_STATS } from "./operations/schemaTagsAndFieldStats";
4
- import {
5
- FrontendUrlRootQuery,
6
- SchemaTagsAndFieldStatsQuery,
7
- } from "../graphqlTypes";
8
2
  import { FRONTEND_URL_ROOT } from "./operations/frontendUrlRoot";
3
+ import {
4
+ ApolloClient,
5
+ ApolloLink,
6
+ createHttpLink,
7
+ InMemoryCache,
8
+ } from "@apollo/client/core";
9
+ import { setContext } from "@apollo/client/link/context";
10
+ import { onError } from "@apollo/client/link/error";
9
11
 
10
12
  export interface ClientIdentity {
11
- name?: string;
12
- version?: string;
13
- referenceID?: string;
13
+ name: string;
14
+ version: string;
15
+ referenceID: string;
14
16
  }
15
17
 
16
18
  export type ServiceID = string;
@@ -27,54 +29,69 @@ export function noServiceError(service: string | undefined, endpoint?: string) {
27
29
  } from Apollo at ${endpoint}. Please check your API key and graph ID`;
28
30
  }
29
31
 
30
- export class ApolloEngineClient extends GraphQLDataSource {
32
+ export class ApolloEngineClient {
33
+ public readonly client: ApolloClient<any>;
34
+ public readonly query: ApolloClient<any>["query"];
35
+
31
36
  constructor(
32
- private engineKey: string,
33
- engineEndpoint: string = DefaultEngineConfig.endpoint,
34
- private clientIdentity?: ClientIdentity
37
+ private readonly engineKey: string,
38
+ baseURL: string,
39
+ private readonly clientIdentity: ClientIdentity,
35
40
  ) {
36
- super();
37
- this.baseURL = engineEndpoint;
38
- }
39
-
40
- // XXX fix typings on base package
41
- willSendRequest(request: any) {
42
- if (!request.headers) request.headers = {};
43
- request.headers["x-api-key"] = this.engineKey;
44
- if (this.clientIdentity && this.clientIdentity.name) {
45
- request.headers["apollo-client-name"] = this.clientIdentity.name;
46
- request.headers["apollo-client-reference-id"] =
47
- this.clientIdentity.referenceID;
48
- request.headers["apollo-client-version"] = this.clientIdentity.version;
49
- return;
50
- }
51
-
52
- // default values
53
- request.headers["apollo-client-name"] = "Apollo Language Server";
54
- request.headers["apollo-client-reference-id"] =
55
- "146d29c0-912c-46d3-b686-920e52586be6";
56
- request.headers["apollo-client-version"] =
57
- require("../../package.json").version;
41
+ const link = ApolloLink.from([
42
+ onError(({ graphQLErrors, networkError, operation }) => {
43
+ const { result, response } = operation.getContext();
44
+ if (graphQLErrors) {
45
+ graphQLErrors.map((graphqlError) =>
46
+ console.error(`[GraphQL error]: ${graphqlError.message}`),
47
+ );
48
+ }
49
+
50
+ if (networkError) {
51
+ console.log(`[Network Error]: ${networkError}`);
52
+ }
53
+
54
+ if (response && response.status >= 400) {
55
+ console.log(`[Network Error] ${response.bodyText}`);
56
+ }
57
+ }),
58
+ createHttpLink({
59
+ uri: baseURL,
60
+ headers: {
61
+ ["x-api-key"]: this.engineKey,
62
+ ["apollo-client-name"]: this.clientIdentity.name,
63
+ ["apollo-client-reference-id"]: this.clientIdentity.referenceID,
64
+ ["apollo-client-version"]: this.clientIdentity.version,
65
+ },
66
+ }),
67
+ ]);
68
+
69
+ this.client = new ApolloClient({
70
+ link,
71
+ cache: new InMemoryCache(),
72
+ });
73
+ this.query = this.client.query.bind(this.client);
58
74
  }
59
75
 
60
76
  async loadSchemaTagsAndFieldLatencies(serviceID: string) {
61
- const { data, errors } = await this.execute<SchemaTagsAndFieldStatsQuery>({
77
+ const { data, errors } = await this.client.query({
62
78
  query: SCHEMA_TAGS_AND_FIELD_STATS,
63
79
  variables: {
64
80
  id: serviceID,
65
81
  },
82
+ fetchPolicy: "no-cache",
66
83
  });
67
84
 
68
85
  if (!(data && data.service && data.service.schemaTags) || errors) {
69
86
  throw new Error(
70
87
  errors
71
88
  ? errors.map((error) => error.message).join("\n")
72
- : "No service returned. Make sure your service name and API key match"
89
+ : "No service returned. Make sure your service name and API key match",
73
90
  );
74
91
  }
75
92
 
76
93
  const schemaTags: string[] = data.service.schemaTags.map(
77
- ({ tag }: { tag: string }) => tag
94
+ ({ tag }: { tag: string }) => tag,
78
95
  );
79
96
 
80
97
  const fieldLatenciesMS: FieldLatenciesMS = new Map();
@@ -96,8 +113,9 @@ export class ApolloEngineClient extends GraphQLDataSource {
96
113
  }
97
114
 
98
115
  async loadFrontendUrlRoot() {
99
- const { data } = await this.execute<FrontendUrlRootQuery>({
116
+ const { data } = await this.client.query({
100
117
  query: FRONTEND_URL_ROOT,
118
+ fetchPolicy: "cache-first",
101
119
  });
102
120
 
103
121
  return data?.frontendUrlRoot;
@@ -1,6 +1,14 @@
1
+ import { TypedDocumentNode } from "@apollo/client/core";
1
2
  import gql from "graphql-tag";
3
+ import type {
4
+ FrontendUrlRootQuery,
5
+ FrontendUrlRootQueryVariables,
6
+ } from "src/language-server/graphqlTypes";
2
7
 
3
- export const FRONTEND_URL_ROOT = gql`
8
+ export const FRONTEND_URL_ROOT: TypedDocumentNode<
9
+ FrontendUrlRootQuery,
10
+ FrontendUrlRootQueryVariables
11
+ > = gql`
4
12
  query FrontendUrlRoot {
5
13
  frontendUrlRoot
6
14
  }
@@ -1,6 +1,14 @@
1
+ import { TypedDocumentNode } from "@apollo/client/core";
1
2
  import gql from "graphql-tag";
3
+ import type {
4
+ SchemaTagsAndFieldStatsQuery,
5
+ SchemaTagsAndFieldStatsQueryVariables,
6
+ } from "src/language-server/graphqlTypes";
2
7
 
3
- export const SCHEMA_TAGS_AND_FIELD_STATS = gql`
8
+ export const SCHEMA_TAGS_AND_FIELD_STATS: TypedDocumentNode<
9
+ SchemaTagsAndFieldStatsQuery,
10
+ SchemaTagsAndFieldStatsQueryVariables
11
+ > = gql`
4
12
  query SchemaTagsAndFieldStats($id: ID!) {
5
13
  service(id: $id) {
6
14
  schemaTags {
@@ -4,8 +4,8 @@ import { basename } from "path";
4
4
 
5
5
  import { vol } from "memfs";
6
6
  import { LoadingHandler } from "../../loadingHandler";
7
- import { ApolloConfig, ClientConfig } from "../../config";
8
- import URI from "vscode-uri";
7
+ import { ClientConfig, parseApolloConfig } from "../../config";
8
+ import { URI } from "vscode-uri";
9
9
 
10
10
  const serviceSchema = /* GraphQL */ `
11
11
  type Query {
@@ -130,7 +130,7 @@ const f = /* GraphQL */ `
130
130
 
131
131
  const rootURI = URI.file(process.cwd());
132
132
 
133
- const config = new ApolloConfig({
133
+ const config = parseApolloConfig({
134
134
  client: {
135
135
  service: {
136
136
  name: "server",
@@ -141,7 +141,7 @@ const config = new ApolloConfig({
141
141
  validationRules: [NoMissingClientDirectives],
142
142
  },
143
143
  engine: {},
144
- }) as ClientConfig;
144
+ });
145
145
 
146
146
  class MockLoadingHandler implements LoadingHandler {
147
147
  handle<T>(_message: string, value: Promise<T>): Promise<T> {
@@ -179,9 +179,14 @@ describe("client state", () => {
179
179
 
180
180
  it("should report validation errors for missing @client directives", async () => {
181
181
  const project = new GraphQLClientProject({
182
- config,
182
+ config: config as ClientConfig,
183
183
  loadingHandler: new MockLoadingHandler(),
184
184
  configFolderURI: rootURI,
185
+ clientIdentity: {
186
+ name: "",
187
+ version: "",
188
+ referenceID: "",
189
+ },
185
190
  });
186
191
 
187
192
  const errors = Object.create(null);
@@ -35,7 +35,7 @@ export function logError(error: Error) {
35
35
  export function logErrorMessage(
36
36
  message: string,
37
37
  fileName?: string,
38
- lineNumber?: number
38
+ lineNumber?: number,
39
39
  ) {
40
40
  if (isRunningFromXcodeScript) {
41
41
  if (fileName && lineNumber) {
@@ -18,7 +18,7 @@ import {
18
18
  isObjectType,
19
19
  } from "graphql";
20
20
 
21
- import { TextEdit } from "vscode-languageserver";
21
+ import { TextEdit } from "vscode-languageserver/node";
22
22
 
23
23
  import { ToolError, logError } from "./logger";
24
24
  import { ValidationRule } from "graphql/validation/ValidationContext";
@@ -35,7 +35,7 @@ export interface CodeActionInfo {
35
35
  edits: TextEdit[];
36
36
  }
37
37
 
38
- const specifiedRulesToBeRemoved = [NoUnusedFragmentsRule];
38
+ const specifiedRulesToBeRemoved: ValidationRule[] = [NoUnusedFragmentsRule];
39
39
 
40
40
  export const defaultValidationRules: ValidationRule[] = [
41
41
  NoAnonymousQueries,
@@ -48,7 +48,7 @@ export function getValidationErrors(
48
48
  schema: GraphQLSchema,
49
49
  document: DocumentNode,
50
50
  fragments?: { [fragmentName: string]: FragmentDefinitionNode },
51
- rules: ValidationRule[] = defaultValidationRules
51
+ rules: ValidationRule[] = defaultValidationRules,
52
52
  ) {
53
53
  const typeInfo = new TypeInfo(schema);
54
54
 
@@ -83,7 +83,7 @@ export function getValidationErrors(
83
83
 
84
84
  export function validateQueryDocument(
85
85
  schema: GraphQLSchema,
86
- document: DocumentNode
86
+ document: DocumentNode,
87
87
  ) {
88
88
  try {
89
89
  const validationErrors = getValidationErrors(schema, document);
@@ -106,7 +106,7 @@ export function NoAnonymousQueries(context: ValidationContext) {
106
106
  context.reportError(
107
107
  new GraphQLError("Apollo does not support anonymous operations", [
108
108
  node,
109
- ])
109
+ ]),
110
110
  );
111
111
  }
112
112
  return false;
@@ -122,8 +122,8 @@ export function NoTypenameAlias(context: ValidationContext) {
122
122
  context.reportError(
123
123
  new GraphQLError(
124
124
  "Apollo needs to be able to insert __typename when needed, please do not use it as an alias",
125
- [node]
126
- )
125
+ [node],
126
+ ),
127
127
  );
128
128
  }
129
129
  },
@@ -138,7 +138,7 @@ function hasClientSchema(schema: GraphQLSchema): boolean {
138
138
  return Boolean(
139
139
  (query && query.clientSchema) ||
140
140
  (mutation && mutation.clientSchema) ||
141
- (subscription && subscription.clientSchema)
141
+ (subscription && subscription.clientSchema),
142
142
  );
143
143
  }
144
144
 
@@ -152,17 +152,14 @@ export function NoMissingClientDirectives(context: ValidationContext) {
152
152
  // together correctly
153
153
  // XXX we have a simplified version of this in @apollo/gateway that we could probably use
154
154
  // intead of this
155
- const executionContext = buildExecutionContext(
155
+ const executionContext = buildExecutionContext({
156
156
  schema,
157
- root,
158
- Object.create(null),
159
- Object.create(null),
160
- undefined,
161
- undefined,
162
- undefined
163
- );
157
+ document: root,
158
+ rootValue: Object.create(null),
159
+ contextValue: Object.create(null),
160
+ });
164
161
  function visitor(
165
- node: FieldNode | InlineFragmentNode | FragmentDefinitionNode
162
+ node: FieldNode | InlineFragmentNode | FragmentDefinitionNode,
166
163
  ) {
167
164
  // In cases where we are looking at a FragmentDefinition, there is no parent type
168
165
  // but instead, the FragmentDefinition contains the type that we can read from the
@@ -194,7 +191,7 @@ export function NoMissingClientDirectives(context: ValidationContext) {
194
191
  // fields are simple because we can just see if the name exists in the local fields
195
192
  // array on the parent type
196
193
  selectsClientFieldSet = Boolean(
197
- clientFields && clientFields.includes(fieldDef?.name || "")
194
+ clientFields && clientFields.includes(fieldDef?.name || ""),
198
195
  );
199
196
  message += `local field "${node.name.value}"`;
200
197
  break;
@@ -207,7 +204,7 @@ export function NoMissingClientDirectives(context: ValidationContext) {
207
204
  executionContext as ExecutionContext,
208
205
  node.selectionSet,
209
206
  Object.create(null),
210
- Object.create(null)
207
+ Object.create(null),
211
208
  );
212
209
 
213
210
  // once we have a list of fields on the fragment, we can compare them
@@ -215,7 +212,7 @@ export function NoMissingClientDirectives(context: ValidationContext) {
215
212
  // subset of the overall local fields types
216
213
  const fieldNames = Object.entries(fields).map(([name]) => name);
217
214
  selectsClientFieldSet = fieldNames.every(
218
- (field) => clientFields && clientFields.includes(field)
215
+ (field) => clientFields && clientFields.includes(field),
219
216
  );
220
217
  message += `fragment ${
221
218
  "name" in node ? `"${node.name.value}" ` : ""
@@ -247,9 +244,9 @@ export function NoMissingClientDirectives(context: ValidationContext) {
247
244
  TextEdit.insert(
248
245
  positionFromSourceLocation(
249
246
  source,
250
- getLocation(source, locToInsertDirective)
247
+ getLocation(source, locToInsertDirective),
251
248
  ),
252
- " @client"
249
+ " @client",
253
250
  ),
254
251
  ],
255
252
  };
@@ -257,7 +254,7 @@ export function NoMissingClientDirectives(context: ValidationContext) {
257
254
  }
258
255
 
259
256
  context.reportError(
260
- new GraphQLError(message, [node], null, null, null, null, extensions)
257
+ new GraphQLError(message, [node], null, null, null, null, extensions),
261
258
  );
262
259
  }
263
260
 
@@ -1,7 +1,7 @@
1
- import minimatch from "minimatch";
2
- import glob from "glob";
1
+ import { minimatch } from "minimatch";
2
+ import { globSync } from "glob";
3
3
  import { invariant } from "../tools";
4
- import URI from "vscode-uri";
4
+ import { URI } from "vscode-uri";
5
5
  import { normalizeURI } from "./utilities";
6
6
  import { resolve } from "path";
7
7
 
@@ -37,13 +37,13 @@ export class FileSet {
37
37
  this.includes.some((include) => {
38
38
  return minimatch(
39
39
  normalizedFilePath,
40
- resolve(this.rootURI.fsPath, include)
40
+ resolve(this.rootURI.fsPath, include),
41
41
  );
42
42
  }) &&
43
43
  !this.excludes.some((exclude) => {
44
44
  return minimatch(
45
45
  normalizedFilePath,
46
- resolve(this.rootURI.fsPath, exclude)
46
+ resolve(this.rootURI.fsPath, exclude),
47
47
  );
48
48
  })
49
49
  );
@@ -54,12 +54,10 @@ export class FileSet {
54
54
  // `includes` globs into a single pattern and pass to glob.sync. The `ignore` option does, however, allow
55
55
  // an array of globs to ignore, so we can pass it in directly
56
56
  const joinedIncludes = `{${this.includes.join(",")}}`;
57
- return glob
58
- .sync(joinedIncludes, {
59
- cwd: this.rootURI.fsPath,
60
- absolute: true,
61
- ignore: this.excludes,
62
- })
63
- .map(normalizeURI);
57
+ return globSync(joinedIncludes, {
58
+ cwd: this.rootURI.fsPath,
59
+ absolute: true,
60
+ ignore: this.excludes,
61
+ }).map(normalizeURI);
64
62
  }
65
63
  }
@@ -4,7 +4,7 @@ export function formatMS(
4
4
  ms: number,
5
5
  d: number,
6
6
  allowMicros = false,
7
- allowNanos = true
7
+ allowNanos = true,
8
8
  ) {
9
9
  if (ms === 0 || ms === null) return "0";
10
10
  const bounds = [