-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Fix custom tool transpilation and bundling #10242
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
Merged
Merged
Changes from 1 commit
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
482cead
Fix custom tool transpilation and bundling
cte 7e05c57
Simplify
cte 8e0adc0
PR feedback
cte efcec28
Use execa
cte d79ccf4
Simplify more stuff
cte d470945
This should be a dev dependency
cte af6d5be
Cleanup
cte File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,9 @@ | ||
| export { getGitSha } from "./git.js" | ||
| export { copyPaths, copyWasms, copyLocales, setupLocaleWatcher, generatePackageJson } from "./esbuild.js" | ||
| export { | ||
| copyPaths, | ||
| copyWasms, | ||
| copyEsbuildWasm, | ||
| copyLocales, | ||
| setupLocaleWatcher, | ||
| generatePackageJson, | ||
| } from "./esbuild.js" |
189 changes: 189 additions & 0 deletions
189
packages/core/src/custom-tools/__tests__/esbuild-runner.spec.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| import fs from "fs" | ||
| import os from "os" | ||
| import path from "path" | ||
| import { fileURLToPath } from "url" | ||
|
|
||
| import { getEsbuildScriptPath, runEsbuild } from "../esbuild-runner.js" | ||
|
|
||
| const __dirname = path.dirname(fileURLToPath(import.meta.url)) | ||
|
|
||
| describe("esbuild-runner", () => { | ||
| describe("getEsbuildScriptPath", () => { | ||
| it("should find esbuild-wasm script in node_modules in development", () => { | ||
| const scriptPath = getEsbuildScriptPath() | ||
|
|
||
| // Should find the script | ||
| expect(typeof scriptPath).toBe("string") | ||
| expect(scriptPath.length).toBeGreaterThan(0) | ||
|
|
||
| // The script should exist | ||
| expect(fs.existsSync(scriptPath)).toBe(true) | ||
|
|
||
| // Should be the esbuild script (not a binary) | ||
| expect(scriptPath).toMatch(/esbuild$/) | ||
| }) | ||
|
|
||
| it("should prefer production path when extensionPath is provided and script exists", () => { | ||
| // Create a temporary directory with a fake script | ||
| const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "esbuild-runner-test-")) | ||
| const binDir = path.join(tempDir, "dist", "bin") | ||
| fs.mkdirSync(binDir, { recursive: true }) | ||
|
|
||
| const fakeScriptPath = path.join(binDir, "esbuild") | ||
| fs.writeFileSync(fakeScriptPath, "#!/usr/bin/env node\nconsole.log('fake esbuild')") | ||
|
|
||
| try { | ||
| const result = getEsbuildScriptPath(tempDir) | ||
| expect(result).toBe(fakeScriptPath) | ||
| } finally { | ||
| // Cleanup | ||
| fs.rmSync(tempDir, { recursive: true, force: true }) | ||
| } | ||
| }) | ||
|
|
||
| it("should fall back to node_modules when production script does not exist", () => { | ||
| // Pass a non-existent extension path | ||
| const result = getEsbuildScriptPath("/nonexistent/extension/path") | ||
|
|
||
| // Should fall back to development path | ||
| expect(typeof result).toBe("string") | ||
| expect(result.length).toBeGreaterThan(0) | ||
| expect(fs.existsSync(result)).toBe(true) | ||
| }) | ||
| }) | ||
|
|
||
| describe("runEsbuild", () => { | ||
| let tempDir: string | ||
|
|
||
| beforeEach(() => { | ||
| tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "esbuild-runner-test-")) | ||
| }) | ||
|
|
||
| afterEach(() => { | ||
| fs.rmSync(tempDir, { recursive: true, force: true }) | ||
| }) | ||
|
|
||
| it("should compile a TypeScript file to ESM", async () => { | ||
| // Create a simple TypeScript file | ||
| const inputFile = path.join(tempDir, "input.ts") | ||
| const outputFile = path.join(tempDir, "output.mjs") | ||
|
|
||
| fs.writeFileSync( | ||
| inputFile, | ||
| ` | ||
| export const greeting = "Hello, World!" | ||
| export function add(a: number, b: number): number { | ||
| return a + b | ||
| } | ||
| `, | ||
| ) | ||
|
|
||
| await runEsbuild({ | ||
| entryPoint: inputFile, | ||
| outfile: outputFile, | ||
| format: "esm", | ||
| platform: "node", | ||
| target: "node18", | ||
| bundle: true, | ||
| }) | ||
|
|
||
| // Verify output file exists | ||
| expect(fs.existsSync(outputFile)).toBe(true) | ||
|
|
||
| // Verify output content is valid JavaScript | ||
| const outputContent = fs.readFileSync(outputFile, "utf-8") | ||
| expect(outputContent).toContain("Hello, World!") | ||
| expect(outputContent).toContain("add") | ||
| }, 30000) | ||
|
|
||
| it("should generate inline source maps when specified", async () => { | ||
| const inputFile = path.join(tempDir, "input.ts") | ||
| const outputFile = path.join(tempDir, "output.mjs") | ||
|
|
||
| fs.writeFileSync(inputFile, `export const value = 42`) | ||
|
|
||
| await runEsbuild({ | ||
| entryPoint: inputFile, | ||
| outfile: outputFile, | ||
| format: "esm", | ||
| sourcemap: "inline", | ||
| }) | ||
|
|
||
| const outputContent = fs.readFileSync(outputFile, "utf-8") | ||
| expect(outputContent).toContain("sourceMappingURL=data:") | ||
| }, 30000) | ||
|
|
||
| it("should throw an error for invalid TypeScript", async () => { | ||
| const inputFile = path.join(tempDir, "invalid.ts") | ||
| const outputFile = path.join(tempDir, "output.mjs") | ||
|
|
||
| // Write syntactically invalid TypeScript | ||
| fs.writeFileSync(inputFile, `export const value = {{{ invalid syntax`) | ||
|
|
||
| await expect( | ||
| runEsbuild({ | ||
| entryPoint: inputFile, | ||
| outfile: outputFile, | ||
| format: "esm", | ||
| }), | ||
| ).rejects.toThrow() | ||
| }, 30000) | ||
|
|
||
| it("should throw an error for non-existent file", async () => { | ||
| const nonExistentFile = path.join(tempDir, "does-not-exist.ts") | ||
| const outputFile = path.join(tempDir, "output.mjs") | ||
|
|
||
| await expect( | ||
| runEsbuild({ | ||
| entryPoint: nonExistentFile, | ||
| outfile: outputFile, | ||
| format: "esm", | ||
| }), | ||
| ).rejects.toThrow() | ||
| }, 30000) | ||
|
|
||
| it("should bundle dependencies when bundle option is true", async () => { | ||
| // Create two files where one imports the other | ||
| const libFile = path.join(tempDir, "lib.ts") | ||
| const mainFile = path.join(tempDir, "main.ts") | ||
| const outputFile = path.join(tempDir, "output.mjs") | ||
|
|
||
| fs.writeFileSync(libFile, `export const PI = 3.14159`) | ||
| fs.writeFileSync( | ||
| mainFile, | ||
| ` | ||
| import { PI } from "./lib.js" | ||
| export const circumference = (r: number) => 2 * PI * r | ||
| `, | ||
| ) | ||
|
|
||
| await runEsbuild({ | ||
| entryPoint: mainFile, | ||
| outfile: outputFile, | ||
| format: "esm", | ||
| bundle: true, | ||
| }) | ||
|
|
||
| const outputContent = fs.readFileSync(outputFile, "utf-8") | ||
| // The PI constant should be bundled inline | ||
| expect(outputContent).toContain("3.14159") | ||
| }, 30000) | ||
|
|
||
| it("should respect platform option", async () => { | ||
| const inputFile = path.join(tempDir, "input.ts") | ||
| const outputFile = path.join(tempDir, "output.mjs") | ||
|
|
||
| fs.writeFileSync(inputFile, `export const value = process.env.NODE_ENV`) | ||
|
|
||
| await runEsbuild({ | ||
| entryPoint: inputFile, | ||
| outfile: outputFile, | ||
| format: "esm", | ||
| platform: "node", | ||
| }) | ||
|
|
||
| // File should be created successfully | ||
| expect(fs.existsSync(outputFile)).toBe(true) | ||
| }, 30000) | ||
| }) | ||
| }) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.