Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/dry-humans-roll.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"vscode-apollo": patch
---

Prevent configuration file parsing loop when transpiling TypeScript configs.
40 changes: 25 additions & 15 deletions src/language-server/config/loadTsConfig.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,50 @@
import { Loader, defaultLoaders } from "cosmiconfig";
import { dirname } from "node:path";
import { rm, writeFile } from "node:fs/promises";
import { existsSync } from "node:fs";
import typescript from "typescript";

// implementation based on https://github.com/cosmiconfig/cosmiconfig/blob/a5a842547c13392ebb89a485b9e56d9f37e3cbd3/src/loaders.ts
// Copyright (c) 2015 David Clark licensed MIT. Full license can be found here:
// https://github.com/cosmiconfig/cosmiconfig/blob/a5a842547c13392ebb89a485b9e56d9f37e3cbd3/LICENSE

let typescript: typeof import("typescript");
export const loadTs: Loader = async function loadTs(filepath, content) {
try {
return await defaultLoaders[".ts"](filepath, content);
return await load(filepath, content, ".vscode-extension-ignore.mjs", {
module: typescript.ModuleKind.ES2022,
});
} catch (error) {
if (
!(error instanceof Error) ||
!error.message.includes("module is not defined")
)
error instanceof Error &&
// [ERROR] ReferenceError: module is not defined in ES module scope
error.message.includes("module is not defined")
) {
return await load(filepath, content, ".vscode-extension-ignore.cjs", {
module: typescript.ModuleKind.CommonJS,
});
} else {
throw error;
}
}
};

if (typescript === undefined) {
typescript = await import("typescript");
}
const compiledFilepath = `${filepath.slice(0, -2)}cjs`;
async function load(
filepath: string,
content: string,
extension: string,
compilerOptions: Partial<import("typescript").CompilerOptions>,
) {
const compiledFilepath = `${filepath}${extension}`;
let transpiledContent;
try {
try {
const config = resolveTsConfig(dirname(filepath)) ?? {};
config.compilerOptions = {
...config.compilerOptions,
module: typescript.ModuleKind.CommonJS,

moduleResolution: typescript.ModuleResolutionKind.Bundler,
target: typescript.ScriptTarget.ES2022,
noEmit: false,
...compilerOptions,
};
transpiledContent = typescript.transpileModule(
content,
Expand All @@ -46,11 +58,9 @@ export const loadTs: Loader = async function loadTs(filepath, content) {
// eslint-disable-next-line @typescript-eslint/return-await
return await defaultLoaders[".js"](compiledFilepath, transpiledContent);
} finally {
if (existsSync(compiledFilepath)) {
await rm(compiledFilepath);
}
await rm(compiledFilepath, { force: true });
}
};
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function resolveTsConfig(directory: string): any {
Expand Down
3 changes: 3 additions & 0 deletions src/language-server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ documents.onDidClose(
connection.onDidChangeWatchedFiles((params) => {
const handledByProject = new Map<GraphQLProject, FileEvent[]>();
for (const { uri, type } of params.changes) {
if (uri.match(/vscode-extension-ignore.[mc]?js$/)) {
continue;
}
const fsPath = URI.parse(uri).fsPath;
const fileName = basename(fsPath);
if (
Expand Down
3 changes: 0 additions & 3 deletions src/language-server/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,6 @@ export class GraphQLWorkspace {
}
// If project exists, update the config
if (project && config) {
if (equal(project.config.rawConfig, config.rawConfig)) {
return;
}
Comment on lines -218 to -220
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this logic when I saw that there were too many file events happening, but didn't know why and assumed the reason was something outside the scope of this Extension.

Removing it here again, since sometimes we actually want a restart even if the config didn't really change.

await Promise.all(project.updateConfig(config));
this.reloadService();
}
Expand Down