Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid detection if .js config file is ESM or CommonJs, just try both. #211

Merged
merged 4 commits into from
Sep 19, 2024
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/silent-badgers-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"vscode-apollo": patch
---

Avoid detection if .js config file is ESM or CommonJs, just try both.
8 changes: 8 additions & 0 deletions sampleWorkspace/configFileTypes/cjsConfig/apollo.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
client: {
service: {
name: "cjsConfig",
localSchemaFile: "./starwarsSchema.graphql",
},
},
};
4 changes: 4 additions & 0 deletions sampleWorkspace/configFileTypes/cjsConfig/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "test",
"type": "module"
}
8 changes: 8 additions & 0 deletions sampleWorkspace/configFileTypes/cjsConfig/src/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import gql from "graphql-tag";
gql`
query Test {
droid(id: "2000") {
name
}
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
client: {
service: {
name: "jsConfigWithCJS",
localSchemaFile: "./starwarsSchema.graphql",
},
},
};
4 changes: 4 additions & 0 deletions sampleWorkspace/configFileTypes/jsConfigWithCJS/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "test",
"type": "module"
}
8 changes: 8 additions & 0 deletions sampleWorkspace/configFileTypes/jsConfigWithCJS/src/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import gql from "graphql-tag";
gql`
query Test {
droid(id: "2000") {
name
}
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {
client: {
service: {
name: "jsConfigWithESM",
localSchemaFile: "./starwarsSchema.graphql",
},
},
};
4 changes: 4 additions & 0 deletions sampleWorkspace/configFileTypes/jsConfigWithESM/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "test",
"type": "commonjs"
Copy link
Member Author

Choose a reason for hiding this comment

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

Deliberately specifying the opposite here - the config file is .js with ESM contents, the package here has type: commonjs, we still want it to work.

The E2E tests will try all possible combinations on top.

}
8 changes: 8 additions & 0 deletions sampleWorkspace/configFileTypes/jsConfigWithESM/src/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import gql from "graphql-tag";
gql`
query Test {
droid(id: "2000") {
name
}
}
`;
8 changes: 8 additions & 0 deletions sampleWorkspace/configFileTypes/mjsConfig/apollo.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {
client: {
service: {
name: "mjsConfig",
localSchemaFile: "./starwarsSchema.graphql",
},
},
};
4 changes: 4 additions & 0 deletions sampleWorkspace/configFileTypes/mjsConfig/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "test",
"type": "commonjs"
}
8 changes: 8 additions & 0 deletions sampleWorkspace/configFileTypes/mjsConfig/src/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import gql from "graphql-tag";
gql`
query Test {
droid(id: "2000") {
name
}
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
client: {
service: {
name: "tsConfigWithCJS",
localSchemaFile: "./starwarsSchema.graphql",
},
},
};
4 changes: 4 additions & 0 deletions sampleWorkspace/configFileTypes/tsConfigWithCJS/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "test",
"type": "module"
}
8 changes: 8 additions & 0 deletions sampleWorkspace/configFileTypes/tsConfigWithCJS/src/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import gql from "graphql-tag";
gql`
query Test {
droid(id: "2000") {
name
}
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {
client: {
service: {
name: "tsConfigWithESM",
localSchemaFile: "./starwarsSchema.graphql",
},
},
};
4 changes: 4 additions & 0 deletions sampleWorkspace/configFileTypes/tsConfigWithESM/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "test",
"type": "commonjs"
}
8 changes: 8 additions & 0 deletions sampleWorkspace/configFileTypes/tsConfigWithESM/src/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import gql from "graphql-tag";
gql`
query Test {
droid(id: "2000") {
name
}
}
`;
3 changes: 3 additions & 0 deletions sampleWorkspace/sampleWorkspace.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
{
"path": "rover"
},
{
"path": "configFileTypes"
},
{
"path": "../src/language-server/__tests__/fixtures/documents"
}
Expand Down
37 changes: 37 additions & 0 deletions src/language-server/__e2e__/configFileTypes.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { writeFile } from "fs/promises";
import {
reloadService,
waitForLSP,
resolveRelativeToSampleWorkspace,
} from "./utils";

test.each([
["cjsConfig", "commonjs"],
["cjsConfig", "module"],
["mjsConfig", "module"],
["mjsConfig", "commonjs"],
["jsConfigWithCJS", "commonjs"],
["jsConfigWithCJS", "module"],
["jsConfigWithESM", "module"],
["jsConfigWithESM", "commonjs"],
["tsConfigWithCJS", "commonjs"],
["tsConfigWithCJS", "module"],
["tsConfigWithESM", "module"],
["tsConfigWithESM", "commonjs"],
] as const)("%s with `type: '%s'`", async (project, moduleType) => {
await writeFile(
resolveRelativeToSampleWorkspace(`configFileTypes/${project}/package.json`),
JSON.stringify(
{
name: "test",
type: moduleType,
},
undefined,
2,
),
"utf-8",
);
await reloadService();
const stats = await waitForLSP(`configFileTypes/${project}/src/test.js`);
expect(stats.serviceId).toBe(project);
});
3 changes: 2 additions & 1 deletion src/language-server/__e2e__/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { VSCodeGraphQLExtension } from "src/extension";
function resolve(file: string) {
return join(__dirname, "..", "..", "..", "sampleWorkspace", file);
}
export { resolve as resolveRelativeToSampleWorkspace };

export type GetPositionFn = ReturnType<typeof getPositionForEditor>;
export function getPositionForEditor(editor: vscode.TextEditor) {
Expand Down Expand Up @@ -65,7 +66,7 @@ export function waitForLSP(file: string) {
uri.toString(),
);
expect(stats.loaded).toBe(true);
return stats;
return stats as ProjectStats & { loaded: true };
});
}

Expand Down
16 changes: 4 additions & 12 deletions src/language-server/config/cache-busting-resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,12 @@ async function resolve(specifier, context, nextResolve) {
if (context.importAttributes.as !== "cachebust") {
return nextResolve(specifier, context);
}
if (context.importAttributes.format) {
// no need to resolve at all, we have all necessary information
return {
url: bustFileName(specifier),
format: context.importAttributes.format,
importAttributes: context.importAttributes,
shortCircuit: true,
};
}
const result = await nextResolve(specifier, context);
// no need to resolve at all, we have all necessary information
return {
...result,
url: bustFileName(result.url),
url: bustFileName(specifier),
format: context.importAttributes.format,
importAttributes: context.importAttributes,
shortCircuit: true,
Comment on lines +29 to +32
Copy link
Member Author

Choose a reason for hiding this comment

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

We don't trust the original detection algorithm at all anymore, format is required now and we just pass this in from the outside.

};
}

Expand Down
2 changes: 1 addition & 1 deletion src/language-server/config/cache-busting-resolver.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export type ImportAttributes =
| {
as: "cachebust";
contents: string;
format?: Format;
format: Format;
}
| { as?: undefined };

Expand Down
49 changes: 33 additions & 16 deletions src/language-server/config/loadTsConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Loader } from "cosmiconfig";
import { dirname } from "node:path";
import { dirname, extname } from "node:path";
import typescript from "typescript";
import { pathToFileURL } from "node:url";
import { register } from "node:module";
Expand Down Expand Up @@ -59,19 +59,7 @@ async function load(
error.message = `TypeScript Error in ${filepath}:\n${error.message}`;
throw error;
}
// eslint-disable-next-line @typescript-eslint/return-await
const imported = await import(
filepath,
//@ts-ignore
{
with: {
as: "cachebust",
contents: transpiledContent,
format: type,
} satisfies ImportAttributes,
}
);
return imported.default;
return loadCachebustedJs(filepath, transpiledContent, type);
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -92,15 +80,44 @@ function resolveTsConfig(directory: string): any {
}

export const loadJs: Loader = async function loadJs(filepath, contents) {
const extension = extname(filepath);
if (extension === ".mjs") {
return loadCachebustedJs(filepath, contents, "module");
}
if (extension === ".cjs") {
return loadCachebustedJs(filepath, contents, "commonjs");
}
try {
return await loadCachebustedJs(filepath, contents, "module");
} catch (error) {
if (
error instanceof Error &&
// [ERROR] ReferenceError: module is not defined in ES module scope
error.message.includes("module is not defined")
) {
return loadCachebustedJs(filepath, contents, "commonjs");
} else {
throw error;
}
}
};

async function loadCachebustedJs(
filename: string,
contents: string,
type: "module" | "commonjs",
) {
return (
await import(
filepath, // @ts-ignore
filename,
// @ts-ignore
{
with: {
as: "cachebust",
contents,
format: type,
} satisfies ImportAttributes,
}
)
).default;
};
}