vscode-apollo 1.19.3 → 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 (179) hide show
  1. package/.changeset/README.md +8 -0
  2. package/.changeset/config.json +14 -0
  3. package/.circleci/config.yml +91 -0
  4. package/.eslintrc.js +10 -0
  5. package/.git-blame-ignore-revs +2 -0
  6. package/.gitattributes +1 -0
  7. package/.github/workflows/release.yml +95 -0
  8. package/.gitleaks.toml +26 -0
  9. package/.nvmrc +1 -0
  10. package/.prettierrc +5 -0
  11. package/.vscode/launch.json +66 -0
  12. package/.vscode/settings.json +16 -0
  13. package/.vscode/tasks.json +60 -0
  14. package/.vscodeignore +28 -1
  15. package/CHANGELOG.md +250 -1
  16. package/CODEOWNERS +4 -0
  17. package/LICENSE +2 -2
  18. package/README.md +104 -55
  19. package/codegen.yml +12 -0
  20. package/graphql.configuration.json +5 -1
  21. package/images/IconRun.svg +8 -0
  22. package/images/marketplace/apollo-wordmark.png +0 -0
  23. package/jest.config.ts +21 -0
  24. package/jest.e2e.config.js +17 -0
  25. package/package.json +102 -23
  26. package/renovate.json +30 -0
  27. package/sampleWorkspace/clientSchema/apollo.config.cjs +10 -0
  28. package/sampleWorkspace/clientSchema/src/clientSchema.js +16 -0
  29. package/sampleWorkspace/clientSchema/src/test.js +18 -0
  30. package/sampleWorkspace/fixtures/starwarsSchema.graphql +299 -0
  31. package/sampleWorkspace/httpSchema/apollo.config.ts +8 -0
  32. package/sampleWorkspace/httpSchema/src/test.js +9 -0
  33. package/sampleWorkspace/localSchema/apollo.config.js +8 -0
  34. package/sampleWorkspace/localSchema/src/test.js +8 -0
  35. package/sampleWorkspace/localSchemaArray/apollo.config.js +12 -0
  36. package/sampleWorkspace/localSchemaArray/planets.graphql +20 -0
  37. package/sampleWorkspace/localSchemaArray/src/test.js +12 -0
  38. package/sampleWorkspace/sampleWorkspace.code-workspace +20 -0
  39. package/sampleWorkspace/spotifyGraph/apollo.config.mjs +5 -0
  40. package/sampleWorkspace/spotifyGraph/src/test.js +11 -0
  41. package/src/__e2e__/mockServer.js +117 -0
  42. package/src/__e2e__/mocks.js +13094 -0
  43. package/src/__e2e__/run.js +23 -0
  44. package/src/__e2e__/runTests.js +44 -0
  45. package/src/__e2e__/setup.js +1 -0
  46. package/src/__e2e__/vscode-environment.js +16 -0
  47. package/src/__e2e__/vscode.js +1 -0
  48. package/src/__mocks__/fs.js +3 -0
  49. package/src/__tests__/statusBar.test.ts +8 -7
  50. package/src/build.js +57 -0
  51. package/src/debug.ts +2 -5
  52. package/src/env/index.ts +1 -0
  53. package/src/env/typescript-utility-types.ts +2 -0
  54. package/src/extension.ts +265 -170
  55. package/src/language-server/__e2e__/clientSchema.e2e.ts +147 -0
  56. package/src/language-server/__e2e__/httpSchema.e2e.ts +21 -0
  57. package/src/language-server/__e2e__/localSchema.e2e.ts +25 -0
  58. package/src/language-server/__e2e__/localSchemaArray.e2e.ts +31 -0
  59. package/src/language-server/__e2e__/studioGraph.e2e.ts +65 -0
  60. package/src/language-server/__e2e__/utils.ts +151 -0
  61. package/src/language-server/__tests__/diagnostics.test.ts +86 -0
  62. package/src/language-server/__tests__/document.test.ts +187 -0
  63. package/src/language-server/__tests__/fileSet.test.ts +46 -0
  64. package/src/language-server/__tests__/fixtures/starwarsSchema.ts +1917 -0
  65. package/src/language-server/config/__tests__/config.ts +54 -0
  66. package/src/language-server/config/__tests__/loadConfig.ts +384 -0
  67. package/src/language-server/config/__tests__/utils.ts +99 -0
  68. package/src/language-server/config/config.ts +284 -0
  69. package/src/language-server/config/index.ts +3 -0
  70. package/src/language-server/config/loadConfig.ts +101 -0
  71. package/src/language-server/config/utils.ts +45 -0
  72. package/src/language-server/diagnostics.ts +118 -0
  73. package/src/language-server/document.ts +277 -0
  74. package/src/language-server/engine/index.ts +123 -0
  75. package/src/language-server/engine/operations/frontendUrlRoot.ts +15 -0
  76. package/src/language-server/engine/operations/schemaTagsAndFieldStats.ts +32 -0
  77. package/src/language-server/errors/__tests__/NoMissingClientDirectives.test.ts +225 -0
  78. package/src/language-server/errors/logger.ts +58 -0
  79. package/src/language-server/errors/validation.ts +274 -0
  80. package/src/language-server/fileSet.ts +63 -0
  81. package/src/language-server/format.ts +48 -0
  82. package/src/language-server/graphqlTypes.ts +16741 -0
  83. package/src/language-server/index.ts +28 -0
  84. package/src/language-server/languageProvider.ts +795 -0
  85. package/src/language-server/loadingHandler.ts +47 -0
  86. package/src/language-server/project/base.ts +406 -0
  87. package/src/language-server/project/client.ts +568 -0
  88. package/src/language-server/project/defaultClientSchema.ts +70 -0
  89. package/src/language-server/providers/schema/__tests__/file.ts +191 -0
  90. package/src/language-server/providers/schema/base.ts +15 -0
  91. package/src/language-server/providers/schema/endpoint.ts +138 -0
  92. package/src/language-server/providers/schema/engine.ts +204 -0
  93. package/src/language-server/providers/schema/file.ts +176 -0
  94. package/src/language-server/providers/schema/index.ts +59 -0
  95. package/src/language-server/server.ts +274 -0
  96. package/src/language-server/typings/graphql.d.ts +27 -0
  97. package/src/language-server/utilities/__tests__/graphql.test.ts +399 -0
  98. package/src/language-server/utilities/__tests__/uri.ts +55 -0
  99. package/src/language-server/utilities/debouncer.ts +8 -0
  100. package/src/language-server/utilities/debug.ts +90 -0
  101. package/src/language-server/utilities/graphql.ts +433 -0
  102. package/src/language-server/utilities/index.ts +3 -0
  103. package/src/language-server/utilities/source.ts +182 -0
  104. package/src/language-server/utilities/uri.ts +19 -0
  105. package/src/language-server/workspace.ts +254 -0
  106. package/src/languageServerClient.ts +22 -15
  107. package/src/messages.ts +75 -0
  108. package/src/statusBar.ts +5 -5
  109. package/src/tools/__tests__/buildServiceDefinition.test.ts +491 -0
  110. package/src/tools/__tests__/snapshotSerializers/astSerializer.ts +19 -0
  111. package/src/tools/__tests__/snapshotSerializers/graphQLTypeSerializer.ts +14 -0
  112. package/src/tools/buildServiceDefinition.ts +241 -0
  113. package/src/tools/index.ts +6 -0
  114. package/src/tools/schema/index.ts +2 -0
  115. package/src/tools/schema/resolveObject.ts +18 -0
  116. package/src/tools/schema/resolverMap.ts +23 -0
  117. package/src/tools/utilities/graphql.ts +22 -0
  118. package/src/tools/utilities/index.ts +3 -0
  119. package/src/tools/utilities/invariant.ts +5 -0
  120. package/src/tools/utilities/predicates.ts +5 -0
  121. package/src/utils.ts +7 -21
  122. package/syntaxes/graphql.dart.json +2 -4
  123. package/syntaxes/graphql.ex.json +1 -4
  124. package/syntaxes/graphql.js.json +3 -3
  125. package/syntaxes/graphql.json +13 -9
  126. package/syntaxes/graphql.lua.json +51 -0
  127. package/syntaxes/graphql.rb.json +1 -1
  128. package/tsconfig.build.json +11 -0
  129. package/tsconfig.json +22 -7
  130. package/create-server-symlink.js +0 -8
  131. package/lib/debug.d.ts +0 -11
  132. package/lib/debug.d.ts.map +0 -1
  133. package/lib/debug.js +0 -48
  134. package/lib/debug.js.map +0 -1
  135. package/lib/extension.d.ts +0 -4
  136. package/lib/extension.d.ts.map +0 -1
  137. package/lib/extension.js +0 -187
  138. package/lib/extension.js.map +0 -1
  139. package/lib/languageServerClient.d.ts +0 -4
  140. package/lib/languageServerClient.d.ts.map +0 -1
  141. package/lib/languageServerClient.js +0 -57
  142. package/lib/languageServerClient.js.map +0 -1
  143. package/lib/statusBar.d.ts +0 -24
  144. package/lib/statusBar.d.ts.map +0 -1
  145. package/lib/statusBar.js +0 -46
  146. package/lib/statusBar.js.map +0 -1
  147. package/lib/testRunner/index.d.ts +0 -3
  148. package/lib/testRunner/index.d.ts.map +0 -1
  149. package/lib/testRunner/index.js +0 -49
  150. package/lib/testRunner/index.js.map +0 -1
  151. package/lib/testRunner/jest-config.d.ts +0 -14
  152. package/lib/testRunner/jest-config.d.ts.map +0 -1
  153. package/lib/testRunner/jest-config.js +0 -18
  154. package/lib/testRunner/jest-config.js.map +0 -1
  155. package/lib/testRunner/jest-vscode-environment.d.ts +0 -2
  156. package/lib/testRunner/jest-vscode-environment.d.ts.map +0 -1
  157. package/lib/testRunner/jest-vscode-environment.js +0 -19
  158. package/lib/testRunner/jest-vscode-environment.js.map +0 -1
  159. package/lib/testRunner/jest-vscode-framework-setup.d.ts +0 -1
  160. package/lib/testRunner/jest-vscode-framework-setup.d.ts.map +0 -1
  161. package/lib/testRunner/jest-vscode-framework-setup.js +0 -3
  162. package/lib/testRunner/jest-vscode-framework-setup.js.map +0 -1
  163. package/lib/testRunner/vscode-test-script.d.ts +0 -2
  164. package/lib/testRunner/vscode-test-script.d.ts.map +0 -1
  165. package/lib/testRunner/vscode-test-script.js +0 -23
  166. package/lib/testRunner/vscode-test-script.js.map +0 -1
  167. package/lib/utils.d.ts +0 -18
  168. package/lib/utils.d.ts.map +0 -1
  169. package/lib/utils.js +0 -52
  170. package/lib/utils.js.map +0 -1
  171. package/src/testRunner/README.md +0 -23
  172. package/src/testRunner/index.ts +0 -72
  173. package/src/testRunner/jest-config.ts +0 -17
  174. package/src/testRunner/jest-vscode-environment.ts +0 -25
  175. package/src/testRunner/jest-vscode-framework-setup.ts +0 -10
  176. package/src/testRunner/jest.d.ts +0 -37
  177. package/src/testRunner/vscode-test-script.ts +0 -38
  178. package/tsconfig.test.json +0 -4
  179. package/tsconfig.tsbuildinfo +0 -2486
@@ -0,0 +1,47 @@
1
+ import { LanguageServerNotifications as Notifications } from "../messages";
2
+ import { Connection, NotificationType } from "vscode-languageserver/node";
3
+
4
+ // XXX I think we want to combine this into an interface
5
+ // with the errors tooling as well
6
+
7
+ export interface LoadingHandler {
8
+ handle<T>(message: string, value: Promise<T>): Promise<T>;
9
+ handleSync<T>(message: string, value: () => T): T;
10
+ showError(message: string): void;
11
+ }
12
+
13
+ export class LanguageServerLoadingHandler implements LoadingHandler {
14
+ constructor(private connection: Connection) {}
15
+ private latestLoadingToken = 0;
16
+ async handle<T>(message: string, value: Promise<T>): Promise<T> {
17
+ const token = this.latestLoadingToken;
18
+ this.latestLoadingToken += 1;
19
+ this.connection.sendNotification(Notifications.Loading, { message, token });
20
+ try {
21
+ const ret = await value;
22
+ this.connection.sendNotification(Notifications.LoadingComplete, token);
23
+ return ret;
24
+ } catch (e) {
25
+ this.connection.sendNotification(Notifications.LoadingComplete, token);
26
+ this.showError(`Error in "${message}": ${e}`);
27
+ throw e;
28
+ }
29
+ }
30
+ handleSync<T>(message: string, value: () => T): T {
31
+ const token = this.latestLoadingToken;
32
+ this.latestLoadingToken += 1;
33
+ this.connection.sendNotification(Notifications.Loading, { message, token });
34
+ try {
35
+ const ret = value();
36
+ this.connection.sendNotification(Notifications.LoadingComplete, token);
37
+ return ret;
38
+ } catch (e) {
39
+ Notifications.LoadingComplete,
40
+ this.showError(`Error in "${message}": ${e}`);
41
+ throw e;
42
+ }
43
+ }
44
+ showError(message: string) {
45
+ this.connection.window.showErrorMessage(message);
46
+ }
47
+ }
@@ -0,0 +1,406 @@
1
+ import path, { extname } from "path";
2
+ import { lstatSync, readFileSync } from "fs";
3
+ import { URI } from "vscode-uri";
4
+
5
+ import {
6
+ TypeSystemDefinitionNode,
7
+ isTypeSystemDefinitionNode,
8
+ TypeSystemExtensionNode,
9
+ isTypeSystemExtensionNode,
10
+ DefinitionNode,
11
+ GraphQLSchema,
12
+ Kind,
13
+ } from "graphql";
14
+
15
+ import {
16
+ TextDocument,
17
+ NotificationHandler,
18
+ PublishDiagnosticsParams,
19
+ Position,
20
+ } from "vscode-languageserver/node";
21
+
22
+ import { GraphQLDocument, extractGraphQLDocuments } from "../document";
23
+
24
+ import type { LoadingHandler } from "../loadingHandler";
25
+ import { FileSet } from "../fileSet";
26
+ import {
27
+ ApolloConfig,
28
+ ClientConfig,
29
+ isClientConfig,
30
+ isLocalServiceConfig,
31
+ keyEnvVar,
32
+ RoverConfig,
33
+ } from "../config";
34
+ import {
35
+ schemaProviderFromConfig,
36
+ GraphQLSchemaProvider,
37
+ SchemaResolveConfig,
38
+ } from "../providers/schema";
39
+ import { ApolloEngineClient, ClientIdentity } from "../engine";
40
+ import type { ProjectStats } from "../../messages";
41
+
42
+ export type DocumentUri = string;
43
+
44
+ const fileAssociations: { [extension: string]: string } = {
45
+ ".graphql": "graphql",
46
+ ".gql": "graphql",
47
+ ".js": "javascript",
48
+ ".ts": "typescript",
49
+ ".jsx": "javascriptreact",
50
+ ".tsx": "typescriptreact",
51
+ ".vue": "vue",
52
+ ".svelte": "svelte",
53
+ ".py": "python",
54
+ ".rb": "ruby",
55
+ ".dart": "dart",
56
+ ".re": "reason",
57
+ ".ex": "elixir",
58
+ ".exs": "elixir",
59
+ };
60
+
61
+ interface GraphQLProjectConfig {
62
+ clientIdentity: ClientIdentity;
63
+ config: ClientConfig | RoverConfig;
64
+ configFolderURI: URI;
65
+ loadingHandler: LoadingHandler;
66
+ }
67
+
68
+ export abstract class GraphQLProject implements GraphQLSchemaProvider {
69
+ public schemaProvider: GraphQLSchemaProvider;
70
+ protected _onDiagnostics?: NotificationHandler<PublishDiagnosticsParams>;
71
+
72
+ private _isReady: boolean;
73
+ private readyPromise: Promise<void>;
74
+ protected engineClient?: ApolloEngineClient;
75
+
76
+ private needsValidation = false;
77
+
78
+ protected documentsByFile: Map<DocumentUri, GraphQLDocument[]> = new Map();
79
+
80
+ public config: ApolloConfig;
81
+ public schema?: GraphQLSchema;
82
+ private fileSet: FileSet;
83
+ private rootURI: URI;
84
+ protected loadingHandler: LoadingHandler;
85
+
86
+ protected lastLoadDate?: number;
87
+
88
+ constructor({
89
+ config,
90
+ configFolderURI,
91
+ loadingHandler,
92
+ clientIdentity,
93
+ }: GraphQLProjectConfig) {
94
+ this.config = config;
95
+ this.loadingHandler = loadingHandler;
96
+ // the URI of the folder _containing_ the apollo.config.js is the true project's root.
97
+ // if a config doesn't have a uri associated, we can assume the `rootURI` is the project's root.
98
+ this.rootURI = config.configDirURI || configFolderURI;
99
+
100
+ const { includes = [], excludes = [] } = isClientConfig(config)
101
+ ? config.client
102
+ : {
103
+ /** TODO */
104
+ };
105
+ const fileSet = new FileSet({
106
+ rootURI: this.rootURI,
107
+ includes: [
108
+ ...includes,
109
+ ".env",
110
+ "apollo.config.js",
111
+ "apollo.config.cjs",
112
+ "apollo.config.mjs",
113
+ "apollo.config.ts",
114
+ ],
115
+ // We do not want to include the local schema file in our list of documents
116
+ excludes: [...excludes, ...this.getRelativeLocalSchemaFilePaths()],
117
+ configURI: config.configURI,
118
+ });
119
+
120
+ this.fileSet = fileSet;
121
+ this.schemaProvider = schemaProviderFromConfig(config, clientIdentity);
122
+ const { engine } = config;
123
+ if (engine.apiKey) {
124
+ this.engineClient = new ApolloEngineClient(
125
+ engine.apiKey!,
126
+ engine.endpoint,
127
+ clientIdentity,
128
+ );
129
+ }
130
+
131
+ this._isReady = false;
132
+ // FIXME: Instead of `Promise.all`, we should catch individual promise rejections
133
+ // so we can show multiple errors.
134
+ this.readyPromise = Promise.all(this.initialize())
135
+ .then(() => {
136
+ this._isReady = true;
137
+ })
138
+ .catch((error) => {
139
+ console.error(error);
140
+ this.loadingHandler.showError(
141
+ `Error initializing Apollo GraphQL project "${this.displayName}": ${error}`,
142
+ );
143
+ });
144
+ }
145
+
146
+ abstract get displayName(): string;
147
+
148
+ protected abstract initialize(): Promise<void>[];
149
+
150
+ abstract getProjectStats(): ProjectStats;
151
+
152
+ get isReady(): boolean {
153
+ return this._isReady;
154
+ }
155
+
156
+ get engine(): ApolloEngineClient {
157
+ // handle error states for missing engine config
158
+ // all in the same place :tada:
159
+ if (!this.engineClient) {
160
+ throw new Error(`Unable to find ${keyEnvVar}`);
161
+ }
162
+ return this.engineClient!;
163
+ }
164
+
165
+ get whenReady(): Promise<void> {
166
+ return this.readyPromise;
167
+ }
168
+
169
+ public updateConfig(config: ApolloConfig) {
170
+ this.config = config;
171
+ return this.initialize();
172
+ }
173
+
174
+ public resolveSchema(config: SchemaResolveConfig): Promise<GraphQLSchema> {
175
+ this.lastLoadDate = +new Date();
176
+ return this.schemaProvider.resolveSchema(config);
177
+ }
178
+
179
+ public resolveFederatedServiceSDL() {
180
+ return this.schemaProvider.resolveFederatedServiceSDL();
181
+ }
182
+
183
+ public onSchemaChange(handler: NotificationHandler<GraphQLSchema>) {
184
+ this.lastLoadDate = +new Date();
185
+ return this.schemaProvider.onSchemaChange(handler);
186
+ }
187
+
188
+ onDiagnostics(handler: NotificationHandler<PublishDiagnosticsParams>) {
189
+ this._onDiagnostics = handler;
190
+ }
191
+
192
+ includesFile(uri: DocumentUri) {
193
+ return this.fileSet.includesFile(uri);
194
+ }
195
+
196
+ allIncludedFiles() {
197
+ return this.fileSet.allFiles();
198
+ }
199
+
200
+ async scanAllIncludedFiles() {
201
+ await this.loadingHandler.handle(
202
+ `Loading queries for ${this.displayName}`,
203
+ (async () => {
204
+ for (const filePath of this.allIncludedFiles()) {
205
+ const uri = URI.file(filePath).toString();
206
+
207
+ // If we already have query documents for this file, that means it was either
208
+ // opened or changed before we got a chance to read it.
209
+ if (this.documentsByFile.has(uri)) continue;
210
+
211
+ this.fileDidChange(uri);
212
+ }
213
+ })(),
214
+ );
215
+ }
216
+
217
+ fileDidChange(uri: DocumentUri) {
218
+ const filePath = URI.parse(uri).fsPath;
219
+ const extension = extname(filePath);
220
+ const languageId = fileAssociations[extension];
221
+
222
+ // Don't process files of an unsupported filetype
223
+ if (!languageId) return;
224
+
225
+ // Don't process directories. Directories might be named like files so
226
+ // we have to explicitly check.
227
+ if (!lstatSync(filePath).isFile()) return;
228
+
229
+ const contents = readFileSync(filePath, "utf8");
230
+ const document = TextDocument.create(uri, languageId, -1, contents);
231
+ this.documentDidChange(document);
232
+ }
233
+
234
+ fileWasDeleted(uri: DocumentUri) {
235
+ this.removeGraphQLDocumentsFor(uri);
236
+ this.checkForDuplicateOperations();
237
+ }
238
+
239
+ documentDidChange(document: TextDocument) {
240
+ const documents = extractGraphQLDocuments(
241
+ document,
242
+ this.config.client && this.config.client.tagName,
243
+ );
244
+ if (documents) {
245
+ this.documentsByFile.set(document.uri, documents);
246
+ this.invalidate();
247
+ } else {
248
+ this.removeGraphQLDocumentsFor(document.uri);
249
+ }
250
+ this.checkForDuplicateOperations();
251
+ }
252
+
253
+ checkForDuplicateOperations(): void {
254
+ const filePathForOperationName: Record<string, string> = {};
255
+ for (const [fileUri, documentsForFile] of this.documentsByFile.entries()) {
256
+ const filePath = URI.parse(fileUri).fsPath;
257
+ for (const document of documentsForFile) {
258
+ if (!document.ast) continue;
259
+ for (const definition of document.ast.definitions) {
260
+ if (
261
+ definition.kind === Kind.OPERATION_DEFINITION &&
262
+ definition.name
263
+ ) {
264
+ const operationName = definition.name.value;
265
+ if (operationName in filePathForOperationName) {
266
+ const conflictingFilePath =
267
+ filePathForOperationName[operationName];
268
+ throw new Error(
269
+ `️️There are multiple definitions for the \`${definition.name.value}\` operation. Please fix all naming conflicts before continuing.\nConflicting definitions found at ${filePath} and ${conflictingFilePath}.`,
270
+ );
271
+ }
272
+ filePathForOperationName[operationName] = filePath;
273
+ }
274
+ }
275
+ }
276
+ }
277
+ }
278
+
279
+ private removeGraphQLDocumentsFor(uri: DocumentUri) {
280
+ if (this.documentsByFile.has(uri)) {
281
+ this.documentsByFile.delete(uri);
282
+
283
+ if (this._onDiagnostics) {
284
+ this._onDiagnostics({ uri: uri, diagnostics: [] });
285
+ }
286
+
287
+ this.invalidate();
288
+ }
289
+ }
290
+
291
+ protected invalidate() {
292
+ if (!this.needsValidation && this.isReady) {
293
+ setTimeout(() => {
294
+ this.validateIfNeeded();
295
+ }, 0);
296
+ this.needsValidation = true;
297
+ }
298
+ }
299
+
300
+ private validateIfNeeded() {
301
+ if (!this.needsValidation || !this.isReady) return;
302
+
303
+ this.validate();
304
+
305
+ this.needsValidation = false;
306
+ }
307
+
308
+ private getRelativeLocalSchemaFilePaths(): string[] {
309
+ const serviceConfig =
310
+ isClientConfig(this.config) &&
311
+ typeof this.config.client.service === "object" &&
312
+ isLocalServiceConfig(this.config.client.service)
313
+ ? this.config.client.service
314
+ : undefined;
315
+ const localSchemaFile = serviceConfig?.localSchemaFile;
316
+ return (
317
+ localSchemaFile === undefined
318
+ ? []
319
+ : Array.isArray(localSchemaFile)
320
+ ? localSchemaFile
321
+ : [localSchemaFile]
322
+ ).map((filePath) =>
323
+ path.relative(this.rootURI.fsPath, path.join(process.cwd(), filePath)),
324
+ );
325
+ }
326
+
327
+ abstract validate(): void;
328
+
329
+ clearAllDiagnostics() {
330
+ if (!this._onDiagnostics) return;
331
+
332
+ for (const uri of this.documentsByFile.keys()) {
333
+ this._onDiagnostics({ uri, diagnostics: [] });
334
+ }
335
+ }
336
+
337
+ documentsAt(uri: DocumentUri): GraphQLDocument[] | undefined {
338
+ return this.documentsByFile.get(uri);
339
+ }
340
+
341
+ documentAt(
342
+ uri: DocumentUri,
343
+ position: Position,
344
+ ): GraphQLDocument | undefined {
345
+ const queryDocuments = this.documentsByFile.get(uri);
346
+ if (!queryDocuments) return undefined;
347
+
348
+ return queryDocuments.find((document) =>
349
+ document.containsPosition(position),
350
+ );
351
+ }
352
+
353
+ get documents(): GraphQLDocument[] {
354
+ const documents: GraphQLDocument[] = [];
355
+ for (const documentsForFile of this.documentsByFile.values()) {
356
+ documents.push(...documentsForFile);
357
+ }
358
+ return documents;
359
+ }
360
+
361
+ get definitions(): DefinitionNode[] {
362
+ const definitions = [];
363
+
364
+ for (const document of this.documents) {
365
+ if (!document.ast) continue;
366
+
367
+ definitions.push(...document.ast.definitions);
368
+ }
369
+
370
+ return definitions;
371
+ }
372
+
373
+ definitionsAt(uri: DocumentUri): DefinitionNode[] {
374
+ const documents = this.documentsAt(uri);
375
+ if (!documents) return [];
376
+
377
+ const definitions = [];
378
+
379
+ for (const document of documents) {
380
+ if (!document.ast) continue;
381
+
382
+ definitions.push(...document.ast.definitions);
383
+ }
384
+
385
+ return definitions;
386
+ }
387
+
388
+ get typeSystemDefinitionsAndExtensions(): (
389
+ | TypeSystemDefinitionNode
390
+ | TypeSystemExtensionNode
391
+ )[] {
392
+ const definitionsAndExtensions = [];
393
+ for (const document of this.documents) {
394
+ if (!document.ast) continue;
395
+ for (const definition of document.ast.definitions) {
396
+ if (
397
+ isTypeSystemDefinitionNode(definition) ||
398
+ isTypeSystemExtensionNode(definition)
399
+ ) {
400
+ definitionsAndExtensions.push(definition);
401
+ }
402
+ }
403
+ }
404
+ return definitionsAndExtensions;
405
+ }
406
+ }