Skip to content

Commit efe7dae

Browse files
authored
fix(vite): avoid version-specific plugin return type (#928)
1 parent 7ac1cbc commit efe7dae

3 files changed

Lines changed: 132 additions & 4 deletions

File tree

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { describe, expect, it } from "vitest";
2+
import * as ts from "typescript";
3+
import { isAbsolute, join, normalize, relative } from "node:path";
4+
import { fileURLToPath } from "node:url";
5+
import { createRequire } from "node:module";
6+
7+
const fixturesDir = fileURLToPath(new URL(".", import.meta.url));
8+
const pluginSourceFile = fileURLToPath(new URL("../../vite-plugin/src/index.ts", import.meta.url));
9+
const pluginViteTypesFixtureDir = join(fixturesDir, "vite6");
10+
11+
const configSource = `
12+
import { defineConfig } from "vite";
13+
import { sentryVitePlugin } from "@sentry/vite-plugin";
14+
15+
export default defineConfig({
16+
plugins: [sentryVitePlugin()],
17+
});
18+
`;
19+
20+
function assertFixtureViteVersion(fixtureDir: string, expectedMajor: string): void {
21+
const requireFromFixture = createRequire(join(fixtureDir, "package.json"));
22+
const vitePackageJsonPath = requireFromFixture.resolve("vite/package.json");
23+
const relativeVitePackageJsonPath = relative(fixtureDir, vitePackageJsonPath);
24+
25+
expect(isAbsolute(relativeVitePackageJsonPath)).toBe(false);
26+
expect(relativeVitePackageJsonPath.startsWith("..")).toBe(false);
27+
expect(relativeVitePackageJsonPath.split(/[\\/]/)[0]).toBe("node_modules");
28+
29+
const vitePackageJson = requireFromFixture("vite/package.json") as { version: string };
30+
expect(vitePackageJson.version.split(".")[0]).toBe(expectedMajor);
31+
}
32+
33+
function getDiagnosticsForFixture(fixtureName: string, expectedMajor: string): string[] {
34+
const fixtureDir = join(fixturesDir, fixtureName);
35+
const fileName = join(fixtureDir, "sentry-vite-plugin-type-compat.mts");
36+
const isVirtualConfigFile = (path: string) => normalize(path) === normalize(fileName);
37+
38+
assertFixtureViteVersion(fixtureDir, expectedMajor);
39+
assertFixtureViteVersion(pluginViteTypesFixtureDir, "6");
40+
41+
const compilerOptions: ts.CompilerOptions = {
42+
esModuleInterop: true,
43+
module: ts.ModuleKind.Node16,
44+
moduleResolution: ts.ModuleResolutionKind.Node16,
45+
noEmit: true,
46+
skipLibCheck: true,
47+
strict: true,
48+
target: ts.ScriptTarget.ES2020,
49+
types: ["node"],
50+
};
51+
52+
const host = ts.createCompilerHost(compilerOptions);
53+
// eslint-disable-next-line @typescript-eslint/unbound-method
54+
const getSourceFile = host.getSourceFile;
55+
56+
host.fileExists = (path) => isVirtualConfigFile(path) || ts.sys.fileExists(path);
57+
host.readFile = (path) => (isVirtualConfigFile(path) ? configSource : ts.sys.readFile(path));
58+
host.getSourceFile = (path, languageVersion, onError, shouldCreateNewSourceFile) =>
59+
isVirtualConfigFile(path)
60+
? ts.createSourceFile(path, configSource, languageVersion, true)
61+
: getSourceFile(path, languageVersion, onError, shouldCreateNewSourceFile);
62+
host.resolveModuleNames = (moduleNames, containingFile) =>
63+
moduleNames.map((moduleName) => {
64+
if (moduleName === "@sentry/vite-plugin") {
65+
return {
66+
resolvedFileName: pluginSourceFile,
67+
extension: ts.Extension.Ts,
68+
};
69+
}
70+
71+
const resolutionContainingFile =
72+
moduleName === "vite" && containingFile === pluginSourceFile
73+
? join(pluginViteTypesFixtureDir, "sentry-vite-plugin-type-compat.mts")
74+
: containingFile;
75+
76+
return ts.resolveModuleName(
77+
moduleName,
78+
resolutionContainingFile,
79+
compilerOptions,
80+
ts.sys,
81+
undefined,
82+
undefined,
83+
ts.ModuleKind.ESNext
84+
).resolvedModule;
85+
});
86+
87+
const program = ts.createProgram([fileName], compilerOptions, host);
88+
89+
return ts
90+
.getPreEmitDiagnostics(program)
91+
.map((diagnostic) => ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"))
92+
.filter((message) => !message.includes("The current file is a CommonJS module"));
93+
}
94+
95+
describe("sentryVitePlugin type compatibility", () => {
96+
it.each([
97+
["vite6", "6"],
98+
["vite7", "7"],
99+
["vite8", "8"],
100+
])("is compatible with %s defineConfig plugins", (fixtureName, expectedMajor) => {
101+
expect(getDiagnosticsForFixture(fixtureName, expectedMajor)).toEqual([]);
102+
});
103+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "vite6-integration-tests",
3+
"version": "1.0.0",
4+
"private": true,
5+
"type": "module",
6+
"dependencies": {
7+
"vite": "6.4.1",
8+
"@sentry/vite-plugin": "5.2.1"
9+
},
10+
"pnpm": {
11+
"overrides": {
12+
"@sentry/bundler-plugin-core": "file:../../../bundler-plugin-core/sentry-bundler-plugin-core-5.2.1.tgz",
13+
"@sentry/rollup-plugin": "file:../../../rollup-plugin/sentry-rollup-plugin-5.2.1.tgz",
14+
"@sentry/vite-plugin": "file:../../../vite-plugin/sentry-vite-plugin-5.2.1.tgz",
15+
"@sentry/babel-plugin-component-annotate": "file:../../../babel-plugin-component-annotate/sentry-babel-plugin-component-annotate-5.2.1.tgz"
16+
},
17+
"patchedDependencies": {
18+
"@sentry/cli": "../patches/@sentry__cli.patch"
19+
}
20+
}
21+
}

packages/vite-plugin/src/index.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
import { SentryRollupPluginOptions } from "@sentry/rollup-plugin";
1+
import type { SentryRollupPluginOptions } from "@sentry/rollup-plugin";
22
import { _rollupPluginInternal } from "@sentry/rollup-plugin";
33
import { createRequire } from "node:module";
4-
import { Plugin } from "vite";
4+
5+
interface SentryVitePlugin {
6+
name: string;
7+
enforce: "pre";
8+
}
59

610
function getViteMajorVersion(): string | undefined {
711
try {
@@ -17,11 +21,11 @@ function getViteMajorVersion(): string | undefined {
1721
return undefined;
1822
}
1923

20-
export const sentryVitePlugin = (options?: SentryRollupPluginOptions): Plugin[] => {
24+
export const sentryVitePlugin = (options?: SentryRollupPluginOptions): SentryVitePlugin[] => {
2125
return [
2226
{
2327
enforce: "pre",
24-
...(_rollupPluginInternal(options, "vite", getViteMajorVersion()) as Plugin),
28+
..._rollupPluginInternal(options, "vite", getViteMajorVersion()),
2529
},
2630
];
2731
};

0 commit comments

Comments
 (0)