vscode-apollo 2.2.1 → 2.3.1
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.
- package/.circleci/config.yml +1 -17
- package/.github/workflows/E2E.yml +27 -0
- package/.github/workflows/build-prs.yml +1 -1
- package/CHANGELOG.md +22 -0
- package/README.md +71 -52
- package/jest.e2e.config.js +2 -0
- package/package.json +31 -3
- package/renovate.json +5 -5
- package/sampleWorkspace/localSchemaArray/apollo.config.json +9 -0
- package/sampleWorkspace/localSchemaArray/src/test.js +1 -1
- package/sampleWorkspace/rover/apollo.config.yaml +3 -0
- package/sampleWorkspace/rover/src/test.graphql +11 -10
- package/sampleWorkspace/rover/supergraph.yaml +0 -0
- package/schemas/apollo.config.schema.json +184 -0
- package/src/__e2e__/runTests.js +1 -0
- package/src/build.js +53 -1
- package/src/language-server/__e2e__/clientSchema.e2e.ts +58 -28
- package/src/language-server/__e2e__/httpSchema.e2e.ts +23 -4
- package/src/language-server/__e2e__/localSchema.e2e.ts +23 -4
- package/src/language-server/__e2e__/localSchemaArray.e2e.ts +31 -6
- package/src/language-server/__e2e__/rover.e2e.ts +150 -0
- package/src/language-server/__e2e__/studioGraph.e2e.ts +18 -6
- package/src/language-server/__e2e__/utils.ts +114 -13
- package/src/language-server/config/__tests__/loadConfig.ts +35 -2
- package/src/language-server/config/cache-busting-resolver.js +65 -0
- package/src/language-server/config/cache-busting-resolver.types.ts +45 -0
- package/src/language-server/config/config.ts +133 -57
- package/src/language-server/config/loadConfig.ts +27 -6
- package/src/language-server/config/loadTsConfig.ts +74 -38
- package/src/language-server/project/base.ts +8 -8
- package/src/language-server/project/rover/project.ts +6 -0
- package/src/language-server/server.ts +8 -7
- package/src/language-server/workspace.ts +2 -5
- package/src/languageServerClient.ts +3 -1
- package/sampleWorkspace/localSchemaArray/apollo.config.js +0 -12
- package/sampleWorkspace/rover/apollo.config.js +0 -3
- /package/sampleWorkspace/localSchema/{apollo.config.js → apollo.config.ts} +0 -0
|
@@ -1,56 +1,78 @@
|
|
|
1
|
-
import { Loader
|
|
1
|
+
import { Loader } from "cosmiconfig";
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
3
|
+
import typescript from "typescript";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { register } from "node:module";
|
|
6
|
+
import { ImportAttributes } from "./cache-busting-resolver.types";
|
|
6
7
|
// implementation based on https://github.com/cosmiconfig/cosmiconfig/blob/a5a842547c13392ebb89a485b9e56d9f37e3cbd3/src/loaders.ts
|
|
7
8
|
// Copyright (c) 2015 David Clark licensed MIT. Full license can be found here:
|
|
8
9
|
// https://github.com/cosmiconfig/cosmiconfig/blob/a5a842547c13392ebb89a485b9e56d9f37e3cbd3/LICENSE
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
if (process.env.JEST_WORKER_ID === undefined) {
|
|
12
|
+
register(
|
|
13
|
+
pathToFileURL(require.resolve("./config/cache-busting-resolver.js")),
|
|
14
|
+
);
|
|
15
|
+
} else {
|
|
16
|
+
register(pathToFileURL(require.resolve("./cache-busting-resolver.js")));
|
|
17
|
+
}
|
|
18
|
+
|
|
11
19
|
export const loadTs: Loader = async function loadTs(filepath, content) {
|
|
12
20
|
try {
|
|
13
|
-
return await
|
|
21
|
+
return await load(filepath, content, "module", {
|
|
22
|
+
module: typescript.ModuleKind.ES2022,
|
|
23
|
+
});
|
|
14
24
|
} catch (error) {
|
|
15
25
|
if (
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
26
|
+
error instanceof Error &&
|
|
27
|
+
// [ERROR] ReferenceError: module is not defined in ES module scope
|
|
28
|
+
error.message.includes("module is not defined")
|
|
29
|
+
) {
|
|
30
|
+
return await load(filepath, content, "commonjs", {
|
|
31
|
+
module: typescript.ModuleKind.CommonJS,
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
19
34
|
throw error;
|
|
35
|
+
}
|
|
20
36
|
}
|
|
37
|
+
};
|
|
21
38
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
39
|
+
async function load(
|
|
40
|
+
filepath: string,
|
|
41
|
+
content: string,
|
|
42
|
+
type: "module" | "commonjs",
|
|
43
|
+
compilerOptions: Partial<import("typescript").CompilerOptions>,
|
|
44
|
+
) {
|
|
26
45
|
let transpiledContent;
|
|
46
|
+
|
|
27
47
|
try {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
config.compilerOptions
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
await writeFile(compiledFilepath, transpiledContent);
|
|
42
|
-
} catch (error: any) {
|
|
43
|
-
error.message = `TypeScript Error in ${filepath}:\n${error.message}`;
|
|
44
|
-
throw error;
|
|
45
|
-
}
|
|
46
|
-
// eslint-disable-next-line @typescript-eslint/return-await
|
|
47
|
-
return await defaultLoaders[".js"](compiledFilepath, transpiledContent);
|
|
48
|
-
} finally {
|
|
49
|
-
if (existsSync(compiledFilepath)) {
|
|
50
|
-
await rm(compiledFilepath);
|
|
51
|
-
}
|
|
48
|
+
const config = resolveTsConfig(dirname(filepath)) ?? {};
|
|
49
|
+
config.compilerOptions = {
|
|
50
|
+
...config.compilerOptions,
|
|
51
|
+
|
|
52
|
+
moduleResolution: typescript.ModuleResolutionKind.Bundler,
|
|
53
|
+
target: typescript.ScriptTarget.ES2022,
|
|
54
|
+
noEmit: false,
|
|
55
|
+
...compilerOptions,
|
|
56
|
+
};
|
|
57
|
+
transpiledContent = typescript.transpileModule(content, config).outputText;
|
|
58
|
+
} catch (error: any) {
|
|
59
|
+
error.message = `TypeScript Error in ${filepath}:\n${error.message}`;
|
|
60
|
+
throw error;
|
|
52
61
|
}
|
|
53
|
-
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/return-await
|
|
63
|
+
const imported = await import(
|
|
64
|
+
filepath,
|
|
65
|
+
//@ts-ignore
|
|
66
|
+
{
|
|
67
|
+
with: {
|
|
68
|
+
as: "cachebust",
|
|
69
|
+
contents: transpiledContent,
|
|
70
|
+
format: type,
|
|
71
|
+
} satisfies ImportAttributes,
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
return imported.default;
|
|
75
|
+
}
|
|
54
76
|
|
|
55
77
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
56
78
|
function resolveTsConfig(directory: string): any {
|
|
@@ -68,3 +90,17 @@ function resolveTsConfig(directory: string): any {
|
|
|
68
90
|
}
|
|
69
91
|
return;
|
|
70
92
|
}
|
|
93
|
+
|
|
94
|
+
export const loadJs: Loader = async function loadJs(filepath, contents) {
|
|
95
|
+
return (
|
|
96
|
+
await import(
|
|
97
|
+
filepath, // @ts-ignore
|
|
98
|
+
{
|
|
99
|
+
with: {
|
|
100
|
+
as: "cachebust",
|
|
101
|
+
contents,
|
|
102
|
+
} satisfies ImportAttributes,
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
).default;
|
|
106
|
+
};
|
|
@@ -18,7 +18,13 @@ import { TextDocument } from "vscode-languageserver-textdocument";
|
|
|
18
18
|
|
|
19
19
|
import type { LoadingHandler } from "../loadingHandler";
|
|
20
20
|
import { FileSet } from "../fileSet";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
ApolloConfig,
|
|
23
|
+
ClientConfig,
|
|
24
|
+
envFileNames,
|
|
25
|
+
RoverConfig,
|
|
26
|
+
supportedConfigFileNames,
|
|
27
|
+
} from "../config";
|
|
22
28
|
import type { ProjectStats } from "../../messages";
|
|
23
29
|
|
|
24
30
|
export type DocumentUri = string;
|
|
@@ -67,13 +73,7 @@ export abstract class GraphQLProject {
|
|
|
67
73
|
|
|
68
74
|
this.configFileSet = new FileSet({
|
|
69
75
|
rootURI: this.rootURI,
|
|
70
|
-
includes:
|
|
71
|
-
".env",
|
|
72
|
-
"apollo.config.js",
|
|
73
|
-
"apollo.config.cjs",
|
|
74
|
-
"apollo.config.mjs",
|
|
75
|
-
"apollo.config.ts",
|
|
76
|
-
],
|
|
76
|
+
includes: supportedConfigFileNames.concat(envFileNames),
|
|
77
77
|
excludes: [],
|
|
78
78
|
});
|
|
79
79
|
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
SemanticTokensRegistrationType,
|
|
25
25
|
SemanticTokensOptions,
|
|
26
26
|
SemanticTokensRegistrationOptions,
|
|
27
|
+
DefinitionRequest,
|
|
27
28
|
} from "vscode-languageserver/node";
|
|
28
29
|
import cp from "node:child_process";
|
|
29
30
|
import { GraphQLProjectConfig } from "../base";
|
|
@@ -281,6 +282,11 @@ export class RoverProject extends GraphQLProject {
|
|
|
281
282
|
this.sendRequest(HoverRequest.type, virtualParams, token),
|
|
282
283
|
);
|
|
283
284
|
|
|
285
|
+
onDefinition: GraphQLProject["onDefinition"] = async (params, token) =>
|
|
286
|
+
this.documents.insideVirtualDocument(params, (virtualParams) =>
|
|
287
|
+
this.sendRequest(DefinitionRequest.type, virtualParams, token),
|
|
288
|
+
);
|
|
289
|
+
|
|
284
290
|
onUnhandledRequest: GraphQLProject["onUnhandledRequest"] = async (
|
|
285
291
|
type,
|
|
286
292
|
params,
|
|
@@ -9,7 +9,8 @@ import {
|
|
|
9
9
|
FileEvent,
|
|
10
10
|
} from "vscode-languageserver/node";
|
|
11
11
|
import { TextDocument } from "vscode-languageserver-textdocument";
|
|
12
|
-
import type
|
|
12
|
+
import { type QuickPickItem } from "vscode";
|
|
13
|
+
import { basename } from "node:path";
|
|
13
14
|
import { GraphQLWorkspace } from "./workspace";
|
|
14
15
|
import { LanguageServerLoadingHandler } from "./loadingHandler";
|
|
15
16
|
import { debounceHandler, Debug } from "./utilities";
|
|
@@ -23,6 +24,7 @@ import { isValidationError } from "zod-validation-error";
|
|
|
23
24
|
import { GraphQLProject } from "./project/base";
|
|
24
25
|
import type { LanguageIdExtensionMap } from "../tools/utilities/languageInformation";
|
|
25
26
|
import { setLanguageIdExtensionMap } from "./utilities/languageIdForExtension";
|
|
27
|
+
import { envFileNames, supportedConfigFileNames } from "./config";
|
|
26
28
|
|
|
27
29
|
export type InitializationOptions = {
|
|
28
30
|
languageIdExtensionMap: LanguageIdExtensionMap;
|
|
@@ -190,14 +192,13 @@ documents.onDidClose(
|
|
|
190
192
|
connection.onDidChangeWatchedFiles((params) => {
|
|
191
193
|
const handledByProject = new Map<GraphQLProject, FileEvent[]>();
|
|
192
194
|
for (const { uri, type } of params.changes) {
|
|
195
|
+
const fsPath = URI.parse(uri).fsPath;
|
|
196
|
+
const fileName = basename(fsPath);
|
|
193
197
|
if (
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
uri.endsWith("apollo.config.mjs") ||
|
|
197
|
-
uri.endsWith("apollo.config.ts") ||
|
|
198
|
-
uri.endsWith(".env")
|
|
198
|
+
supportedConfigFileNames.includes(fileName) ||
|
|
199
|
+
envFileNames.includes(fileName)
|
|
199
200
|
) {
|
|
200
|
-
workspace.
|
|
201
|
+
workspace.reloadProjectForConfigOrCompanionFile(uri);
|
|
201
202
|
}
|
|
202
203
|
|
|
203
204
|
// Don't respond to changes in files that are currently open,
|
|
@@ -125,7 +125,7 @@ export class GraphQLWorkspace {
|
|
|
125
125
|
|
|
126
126
|
*/
|
|
127
127
|
const apolloConfigFiles: string[] = globSync(
|
|
128
|
-
"**/apollo.config.@(js|ts|cjs|mjs)",
|
|
128
|
+
"**/apollo.config.@(js|ts|cjs|mjs|yaml|yml|json)",
|
|
129
129
|
{
|
|
130
130
|
cwd: URI.parse(folder.uri).fsPath,
|
|
131
131
|
absolute: true,
|
|
@@ -197,7 +197,7 @@ export class GraphQLWorkspace {
|
|
|
197
197
|
});
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
async
|
|
200
|
+
async reloadProjectForConfigOrCompanionFile(configUri: DocumentUri) {
|
|
201
201
|
const configPath = dirname(URI.parse(configUri).fsPath);
|
|
202
202
|
let config: ApolloConfig | null;
|
|
203
203
|
let error;
|
|
@@ -215,9 +215,6 @@ export class GraphQLWorkspace {
|
|
|
215
215
|
}
|
|
216
216
|
// If project exists, update the config
|
|
217
217
|
if (project && config) {
|
|
218
|
-
if (equal(project.config.rawConfig, config.rawConfig)) {
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
218
|
await Promise.all(project.updateConfig(config));
|
|
222
219
|
this.reloadService();
|
|
223
220
|
}
|
|
@@ -52,7 +52,9 @@ export function getLanguageServerClient(
|
|
|
52
52
|
documentSelector: supportedLanguageIds,
|
|
53
53
|
synchronize: {
|
|
54
54
|
fileEvents: [
|
|
55
|
-
workspace.createFileSystemWatcher(
|
|
55
|
+
workspace.createFileSystemWatcher(
|
|
56
|
+
"**/{.env?(.local),apollo.config.{json,yml,yaml}}",
|
|
57
|
+
),
|
|
56
58
|
workspace.createFileSystemWatcher(
|
|
57
59
|
"**/*{" + supportedExtensions.join(",") + "}",
|
|
58
60
|
),
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
client: {
|
|
3
|
-
service: {
|
|
4
|
-
name: "localMultiSchema",
|
|
5
|
-
localSchemaFile: [
|
|
6
|
-
"./starwarsSchema.graphql",
|
|
7
|
-
// this documents an unfixed bug: in this multi-folder-workspace, this looks for files relative to the first folder in the .code-workspace file
|
|
8
|
-
"./planets.graphql",
|
|
9
|
-
],
|
|
10
|
-
},
|
|
11
|
-
},
|
|
12
|
-
};
|
|
File without changes
|