From 10823bcf838f1a5bd53fda5dc002c17ed3bad7bf Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Date: Mon, 20 Jul 2026 21:17:22 -0300 Subject: [PATCH] fix(dashboard): repair monaco deep import broken by 0.56 exports map (#7897) (#7922) monaco-editor 0.56.0 (bumped in #7897) ships a restrictive `exports` map ("./*.js" -> "./esm/vs/*.js", "./*" -> "./esm/vs/*.js") that rewrites every subpath by prepending esm/vs/. The pre-0.56 deep import `monaco-editor/esm/vs/editor/editor.api` therefore resolved to the doubled, non-existent `esm/vs/esm/vs/editor/editor.api.js` and broke the production Turbopack build (Module not found in MonacoEditor.tsx). Switch to the 0.56-compatible specifier `monaco-editor/editor/editor.api.js`, which resolves to the same file (esm/vs/editor/editor.api.js) as before. Adds tests/unit/monaco-editor-import-path.test.ts as a regression guard: asserts the specifier has no esm/vs/ prefix and resolves to editor.api.js against the installed monaco 0.56. --- src/shared/components/MonacoEditor.tsx | 2 +- tests/unit/monaco-editor-import-path.test.ts | 35 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/unit/monaco-editor-import-path.test.ts diff --git a/src/shared/components/MonacoEditor.tsx b/src/shared/components/MonacoEditor.tsx index 11f601f82f..ba00f24294 100644 --- a/src/shared/components/MonacoEditor.tsx +++ b/src/shared/components/MonacoEditor.tsx @@ -11,7 +11,7 @@ const MonacoEditor = dynamic( async () => { const [{ default: Editor, loader }, monaco] = await Promise.all([ import("@monaco-editor/react"), - import("monaco-editor/esm/vs/editor/editor.api"), + import("monaco-editor/editor/editor.api.js"), ]); loader.config({ monaco }); return Editor; diff --git a/tests/unit/monaco-editor-import-path.test.ts b/tests/unit/monaco-editor-import-path.test.ts new file mode 100644 index 0000000000..eb01906ea8 --- /dev/null +++ b/tests/unit/monaco-editor-import-path.test.ts @@ -0,0 +1,35 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { createRequire } from "node:module"; +import { readFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import path from "node:path"; + +const require = createRequire(import.meta.url); +const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); +const monacoComponent = path.join(repoRoot, "src/shared/components/MonacoEditor.tsx"); + +// Regression guard for #7897 (monaco-editor 0.55.1 -> 0.56.0). Monaco 0.56 shipped a +// restrictive `exports` map (`"./*.js": "./esm/vs/*.js"`, `"./*": "./esm/vs/*.js"`) that +// rewrites every subpath by prepending `esm/vs/`. The pre-0.56 deep import +// `monaco-editor/esm/vs/editor/editor.api` therefore resolves to the doubled, non-existent +// `esm/vs/esm/vs/editor/editor.api.js` and breaks the production (Turbopack) build. The +// 0.56-compatible specifier drops the `esm/vs/` prefix: `monaco-editor/editor/editor.api.js`. + +test("MonacoEditor.tsx uses the 0.56-compatible monaco specifier (no esm/vs prefix)", () => { + const src = readFileSync(monacoComponent, "utf8"); + const match = src.match(/import\(\s*["'](monaco-editor\/[^"']+)["']\s*\)/); + assert.ok(match, "expected a dynamic import of a monaco-editor subpath in MonacoEditor.tsx"); + const specifier = match[1]; + assert.ok( + !specifier.includes("esm/vs/"), + `monaco deep import must not include the esm/vs/ prefix under monaco 0.56 exports (got "${specifier}")` + ); +}); + +test("the monaco specifier resolves to a real file under the installed monaco-editor", () => { + const src = readFileSync(monacoComponent, "utf8"); + const specifier = src.match(/import\(\s*["'](monaco-editor\/[^"']+)["']\s*\)/)![1]; + const resolved = require.resolve(specifier); + assert.ok(resolved.endsWith("editor.api.js"), `expected to resolve editor.api.js, got ${resolved}`); +});