diff --git a/npm-packages/common/config/rush/pnpm-lock.yaml b/npm-packages/common/config/rush/pnpm-lock.yaml index 88088b64d..52239ae75 100644 --- a/npm-packages/common/config/rush/pnpm-lock.yaml +++ b/npm-packages/common/config/rush/pnpm-lock.yaml @@ -1547,6 +1547,9 @@ importers: '@convex-dev/design-system': specifier: workspace:* version: link:../@convex-dev/design-system + '@monaco-editor/react': + specifier: 4.7.0 + version: 4.7.0(monaco-editor@0.40.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-icons': specifier: ~1.3.0 version: 1.3.2(react@18.3.1) @@ -1556,6 +1559,12 @@ importers: dashboard-common: specifier: workspace:* version: link:../dashboard-common + monaco-editor: + specifier: 0.40.0 + version: 0.40.0 + monaco-editor-webpack-plugin: + specifier: ~7.1.1 + version: 7.1.1(monaco-editor@0.40.0)(webpack@5.102.1) next: specifier: ^15.5.6 version: 15.5.6(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.94.0) @@ -18474,6 +18483,12 @@ packages: moment@2.30.1: resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} + monaco-editor-webpack-plugin@7.1.1: + resolution: {integrity: sha512-WxdbFHS3Wtz4V9hzhe/Xog5hQRSMxmDLkEEYZwqMDHgJlkZo00HVFZR0j5d0nKypjTUkkygH3dDSXERLG4757A==} + peerDependencies: + monaco-editor: '>= 0.31.0' + webpack: ^4.5.0 || 5.x + monaco-editor@0.40.0: resolution: {integrity: sha512-1wymccLEuFSMBvCk/jT1YDW/GuxMLYwnFwF9CDyYCxoTw2Pt379J3FUhwy9c43j51JdcxVPjwk0jm0EVDsBS2g==} @@ -43797,6 +43812,12 @@ snapshots: moment@2.30.1: {} + monaco-editor-webpack-plugin@7.1.1(monaco-editor@0.40.0)(webpack@5.102.1): + dependencies: + loader-utils: 2.0.4 + monaco-editor: 0.40.0 + webpack: 5.102.1 + monaco-editor@0.40.0: {} mri@1.2.0: {} diff --git a/npm-packages/dashboard-self-hosted/next.config.js b/npm-packages/dashboard-self-hosted/next.config.js index 053e4e55b..f6900279e 100644 --- a/npm-packages/dashboard-self-hosted/next.config.js +++ b/npm-packages/dashboard-self-hosted/next.config.js @@ -107,6 +107,19 @@ const nextConfig = { }; } + if ( + !isServer && + process.env.NEXT_PUBLIC_LOAD_MONACO_INTERNALLY === "true" + ) { + const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin"); + config.plugins.push( + new MonacoWebpackPlugin({ + languages: ["json", "typescript", "javascript"], + filename: "static/[name].worker.js", + }), + ); + } + return config; }, }; diff --git a/npm-packages/dashboard-self-hosted/package.json b/npm-packages/dashboard-self-hosted/package.json index 40247218a..0ee67a9d6 100644 --- a/npm-packages/dashboard-self-hosted/package.json +++ b/npm-packages/dashboard-self-hosted/package.json @@ -22,7 +22,10 @@ "react-dom": "^18.0.0", "react-use": "~17.6.0", "system-udfs": "workspace:*", - "zod": "^3.24.0" + "zod": "^3.24.0", + "@monaco-editor/react": "4.7.0", + "monaco-editor": "0.40.0", + "monaco-editor-webpack-plugin": "~7.1.1" }, "devDependencies": { "@tailwindcss/forms": "^0.5.10", diff --git a/npm-packages/dashboard-self-hosted/src/lib/monacoInternalLoader.ts b/npm-packages/dashboard-self-hosted/src/lib/monacoInternalLoader.ts new file mode 100644 index 000000000..f561541fb --- /dev/null +++ b/npm-packages/dashboard-self-hosted/src/lib/monacoInternalLoader.ts @@ -0,0 +1,8 @@ +import { loader } from "@monaco-editor/react"; +import * as monaco from "monaco-editor"; + +loader.config({ monaco }); + +loader.init().then((_monacoInstance) => { + /* ... */ +}); diff --git a/npm-packages/dashboard-self-hosted/src/pages/_app.tsx b/npm-packages/dashboard-self-hosted/src/pages/_app.tsx index ee569451c..2c7e4e3df 100644 --- a/npm-packages/dashboard-self-hosted/src/pages/_app.tsx +++ b/npm-packages/dashboard-self-hosted/src/pages/_app.tsx @@ -40,6 +40,10 @@ import { z } from "zod"; import { UIProvider } from "@ui/UIContext"; import Link from "next/link"; +if (process.env.NEXT_PUBLIC_LOAD_MONACO_INTERNALLY === "true") { + import("../lib/monacoInternalLoader").then((a) => a); +} + // Context for self-hosted dashboard sidebar settings const SelfHostedSettingsContext = createContext<{ visiblePages?: string[]; diff --git a/self-hosted/README.md b/self-hosted/README.md index 25032f947..0a0a0d8ff 100644 --- a/self-hosted/README.md +++ b/self-hosted/README.md @@ -395,6 +395,10 @@ npx convex import --replace-all random identifier plus the version of the backend in use. You may opt out of the beacon by setting the environment variable `DISABLE_BEACON` to `true`. +## Dashboard optional configuration + +- The dashboard uses the **monaco-editor** npm package for all the editor-like elements. By default, monaco loads it's core from a CDN. You could configure it to load internally by setting the `NEXT_PUBLIC_LOAD_MONACO_INTERNALLY` environment variable to `true` + ## Running the dashboard locally From the `npm-packages/dashboard-self-hosted` directory, run: diff --git a/self-hosted/docker/docker-compose.yml b/self-hosted/docker/docker-compose.yml index cda24a406..c6842792e 100644 --- a/self-hosted/docker/docker-compose.yml +++ b/self-hosted/docker/docker-compose.yml @@ -53,6 +53,7 @@ services: - "${DASHBOARD_PORT:-6791}:6791" environment: - NEXT_PUBLIC_DEPLOYMENT_URL=${NEXT_PUBLIC_DEPLOYMENT_URL:-http://127.0.0.1:${PORT:-3210}} + - NEXT_PUBLIC_LOAD_MONACO_INTERNALLY depends_on: backend: condition: service_healthy