Skip to content

Commit e96112e

Browse files
committed
fix(vite): avoid version-specific plugin return type
1 parent 7ac1cbc commit e96112e

3 files changed

Lines changed: 128 additions & 4 deletions

File tree

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { describe, expect, it } from "vitest";
2+
import * as ts from "typescript";
3+
import { join } 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+
24+
expect(vitePackageJsonPath).toContain(`${fixtureDir}/node_modules/`);
25+
26+
const vitePackageJson = requireFromFixture("vite/package.json") as { version: string };
27+
expect(vitePackageJson.version.split(".")[0]).toBe(expectedMajor);
28+
}
29+
30+
function getDiagnosticsForFixture(fixtureName: string, expectedMajor: string): string[] {
31+
const fixtureDir = join(fixturesDir, fixtureName);
32+
const fileName = join(fixtureDir, "sentry-vite-plugin-type-compat.mts");
33+
34+
assertFixtureViteVersion(fixtureDir, expectedMajor);
35+
assertFixtureViteVersion(pluginViteTypesFixtureDir, "6");
36+
37+
const compilerOptions: ts.CompilerOptions = {
38+
esModuleInterop: true,
39+
module: ts.ModuleKind.Node16,
40+
moduleResolution: ts.ModuleResolutionKind.Node16,
41+
noEmit: true,
42+
skipLibCheck: true,
43+
strict: true,
44+
target: ts.ScriptTarget.ES2020,
45+
types: ["node"],
46+
};
47+
48+
const host = ts.createCompilerHost(compilerOptions);
49+
// eslint-disable-next-line @typescript-eslint/unbound-method
50+
const getSourceFile = host.getSourceFile;
51+
52+
host.fileExists = (path) => path === fileName || ts.sys.fileExists(path);
53+
host.readFile = (path) => (path === fileName ? configSource : ts.sys.readFile(path));
54+
host.getSourceFile = (path, languageVersion, onError, shouldCreateNewSourceFile) =>
55+
path === fileName
56+
? ts.createSourceFile(path, configSource, languageVersion, true)
57+
: getSourceFile(path, languageVersion, onError, shouldCreateNewSourceFile);
58+
host.resolveModuleNames = (moduleNames, containingFile) =>
59+
moduleNames.map((moduleName) => {
60+
if (moduleName === "@sentry/vite-plugin") {
61+
return {
62+
resolvedFileName: pluginSourceFile,
63+
extension: ts.Extension.Ts,
64+
};
65+
}
66+
67+
const resolutionContainingFile =
68+
moduleName === "vite" && containingFile === pluginSourceFile
69+
? join(pluginViteTypesFixtureDir, "sentry-vite-plugin-type-compat.mts")
70+
: containingFile;
71+
72+
return ts.resolveModuleName(
73+
moduleName,
74+
resolutionContainingFile,
75+
compilerOptions,
76+
ts.sys,
77+
undefined,
78+
undefined,
79+
ts.ModuleKind.ESNext
80+
).resolvedModule;
81+
});
82+
83+
const program = ts.createProgram([fileName], compilerOptions, host);
84+
85+
return ts
86+
.getPreEmitDiagnostics(program)
87+
.map((diagnostic) => ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"))
88+
.filter((message) => !message.includes("The current file is a CommonJS module"));
89+
}
90+
91+
describe("sentryVitePlugin type compatibility", () => {
92+
it.each([
93+
["vite6", "6"],
94+
["vite7", "7"],
95+
["vite8", "8"],
96+
])("is compatible with %s defineConfig plugins", (fixtureName, expectedMajor) => {
97+
expect(getDiagnosticsForFixture(fixtureName, expectedMajor)).toEqual([]);
98+
});
99+
});
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)