From 9dd097e11e4013430c59c4b58b57c08f148ff72a Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Mon, 15 Jun 2026 17:51:51 +0200 Subject: [PATCH] fix(front): set up Monaco workers for GraphQL playground (#21620) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem The GraphQL API playground (`/settings/playground/graphql/core`) crashes with: ``` Uncaught Error: Cannot read properties of undefined (reading 'toUrl') at FileAccessImpl.toUri (monaco-editor) at WorkerManager.getLanguageServiceWorker (graphqlMode) at DiagnosticsAdapter._doValidate (graphqlMode) ``` ## Root cause GraphiQL 5 (adopted in the React 19 migration, #21531) renders its editors with **Monaco** instead of CodeMirror. Monaco spawns web workers for GraphQL validation/autocomplete and needs a `globalThis.MonacoEnvironment.getWorker` factory. None was ever configured, so Monaco fell back to a main-thread worker whose URL resolves to `undefined` → the `toUrl` crash. ## Why not the official helper GraphiQL ships `@graphiql/react/setup-workers/vite`, but its bundled `?worker` imports are incompatible with our rolldown-based Vite setup: - **pre-bundled** (in `optimizeDeps`): esbuild's optimizer can't process `?worker` → the dep 504s and the page fails to load the chunk. - **excluded** from `optimizeDeps`: rolldown tries to load `editor.worker.js?worker` as a literal path → `UNLOADABLE_DEPENDENCY`, crashing the dev server. ## Fix - Register `MonacoEnvironment.getWorker` in **app source** (`setupGraphiqlMonacoWorkers.ts`), where Vite's worker plugin handles `?worker` reliably, and side-effect import it from `GraphQLPlayground.tsx` before GraphiQL mounts. - Align `monaco-editor` to `0.52.2` and add `monaco-graphql@1.8.0` as direct deps so the workers run on the **same deduped Monaco instance** GraphiQL uses on the main thread (a version mismatch would break the worker protocol). ## Verification Ran the playground locally against the dev server: - Editor renders, syntax highlighting works, operation name parses (GraphQL language service alive). - All three worker files (`editor`, `json`, `graphql`) load `200` and instantiate as module workers. - Console is free of `toUrl` / `Cannot read` errors and the "must define MonacoEnvironment.getWorker" warning. - `oxlint`, `oxfmt`, and `nx typecheck twenty-front` pass. Review in cubic --- packages/twenty-front/package.json | 3 ++- .../components/GraphQLPlayground.tsx | 1 + .../utils/setupGraphiqlMonacoWorkers.ts | 22 +++++++++++++++++++ yarn.lock | 12 +++------- 4 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 packages/twenty-front/src/modules/settings/playground/utils/setupGraphiqlMonacoWorkers.ts diff --git a/packages/twenty-front/package.json b/packages/twenty-front/package.json index 807084f771..e5cfc1db80 100644 --- a/packages/twenty-front/package.json +++ b/packages/twenty-front/package.json @@ -186,8 +186,9 @@ "jest": "29.7.0", "jest-environment-jsdom": "30.0.0-beta.3", "jest-fetch-mock": "^3.0.3", - "monaco-editor": "^0.51.0", + "monaco-editor": "0.52.2", "monaco-editor-auto-typings": "^0.4.5", + "monaco-graphql": "1.8.0", "msw": "^2.12.7", "msw-storybook-addon": "^2.0.6", "optionator": "^0.9.1", diff --git a/packages/twenty-front/src/modules/settings/playground/components/GraphQLPlayground.tsx b/packages/twenty-front/src/modules/settings/playground/components/GraphQLPlayground.tsx index a674650e23..e6432f728d 100644 --- a/packages/twenty-front/src/modules/settings/playground/components/GraphQLPlayground.tsx +++ b/packages/twenty-front/src/modules/settings/playground/components/GraphQLPlayground.tsx @@ -1,3 +1,4 @@ +import '@/settings/playground/utils/setupGraphiqlMonacoWorkers'; import { isPlaygroundApiKeyFresh, playgroundApiKeyState, diff --git a/packages/twenty-front/src/modules/settings/playground/utils/setupGraphiqlMonacoWorkers.ts b/packages/twenty-front/src/modules/settings/playground/utils/setupGraphiqlMonacoWorkers.ts new file mode 100644 index 0000000000..b3c9c3700d --- /dev/null +++ b/packages/twenty-front/src/modules/settings/playground/utils/setupGraphiqlMonacoWorkers.ts @@ -0,0 +1,22 @@ +import { type Environment } from 'monaco-editor'; +import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker'; +import JsonWorker from 'monaco-editor/esm/vs/language/json/json.worker.js?worker'; +import GraphqlWorker from 'monaco-graphql/esm/graphql.worker.js?worker'; + +// GraphiQL 5's Monaco editors need a worker factory; without it Monaco throws "Cannot read properties of undefined (reading 'toUrl')". +const monacoEnvironment: Environment = { + getWorker: (_workerId, label) => { + switch (label) { + case 'json': + return new JsonWorker(); + case 'graphql': + return new GraphqlWorker(); + default: + return new EditorWorker(); + } + }, +}; + +( + globalThis as unknown as { MonacoEnvironment?: Environment } +).MonacoEnvironment = monacoEnvironment; diff --git a/yarn.lock b/yarn.lock index fceaed3ebc..8263e6b8e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -42629,14 +42629,7 @@ __metadata: languageName: node linkType: hard -"monaco-editor@npm:^0.51.0": - version: 0.51.0 - resolution: "monaco-editor@npm:0.51.0" - checksum: 10c0/7fde310c747e46cd7293e1a0f5e1fa85c389df9a1f8db03b9ccd58fd45356ab021a591b46198d19345566ad54556158f6489e2da4ad428a7a6ca3ea7b504afcb - languageName: node - linkType: hard - -"monaco-graphql@npm:^1.8.0": +"monaco-graphql@npm:1.8.0, monaco-graphql@npm:^1.8.0": version: 1.8.0 resolution: "monaco-graphql@npm:1.8.0" dependencies: @@ -53537,8 +53530,9 @@ __metadata: lodash.uniqby: "npm:^4.7.0" marked: "npm:^17.0.1" microdiff: "npm:^1.3.2" - monaco-editor: "npm:^0.51.0" + monaco-editor: "npm:0.52.2" monaco-editor-auto-typings: "npm:^0.4.5" + monaco-graphql: "npm:1.8.0" msw: "npm:^2.12.7" msw-storybook-addon: "npm:^2.0.6" optionator: "npm:^0.9.1"