diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 0c4dbf30cd..300c4582ab 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -120,6 +120,7 @@ "d3-force": "3.0.0", "dnd-core": "14.0.1", "dompurify": "3.4.13", + "driver.js": "1.8.0", "emojibase-data": "16.0.3", "fflate": "0.8.3", "frimousse": "0.3.0", diff --git a/apps/desktop/vite.config.ts b/apps/desktop/vite.config.ts index 46d5bea536..7627a62c47 100644 --- a/apps/desktop/vite.config.ts +++ b/apps/desktop/vite.config.ts @@ -155,6 +155,17 @@ export default defineConfig(({ command }) => ({ } } }, + // driver.js only enters the graph through the tour's DYNAMIC import chain + // (lib/tour/run-tour.ts), so the dep scanner never sees it at startup. Left + // alone, first use registers it as a missing dep at runtime — which (a) + // esbuild-prebundles the `?raw` IIFE import as a JS module, breaking the + // raw-text transform ("does not provide an export named 'default'"), and + // (b) triggers Vite's "new dependencies optimized" full page reload mid- + // session. It's pure ESM with no CJS deps, so serving it unoptimized is + // free. Query and bare forms all listed — exclusion matches exact ids. + optimizeDeps: { + exclude: ['driver.js', 'driver.js/dist/driver.js.iife.js', 'driver.js/dist/driver.js.iife.js?raw', 'driver.js/dist/driver.css?raw'] + }, resolve: { alias: { '@/debug/dev-only': debugEntry(command, process.env as Record), @@ -162,6 +173,20 @@ export default defineConfig(({ command }) => ({ '@hermes/plugin-sdk': path.resolve(__dirname, './src/sdk/index.ts'), '@hermes/shared/billing': path.resolve(__dirname, '../shared/src/billing-types.ts'), '@hermes/shared': path.resolve(__dirname, '../shared/src'), + // The tour tool's preview surface injects driver.js's prebuilt IIFE into + // the pane's guest page as raw source; the package's exports map doesn't + // expose that dist file (nor ./package.json), so resolve the main entry + // (dist/driver.js.cjs) and point at its sibling. Both keys on purpose: + // alias matching is exact, and the id reaches it with the `?raw` query + // still attached in dev but stripped in some build paths. + 'driver.js/dist/driver.js.iife.js?raw': `${path.join( + path.dirname(requireFromApp.resolve('driver.js')), + 'driver.js.iife.js' + )}?raw`, + 'driver.js/dist/driver.js.iife.js': path.join( + path.dirname(requireFromApp.resolve('driver.js')), + 'driver.js.iife.js' + ), react: reactDir, 'react-dom': reactDomDir, 'react/jsx-dev-runtime': path.join(reactDir, 'jsx-dev-runtime.js'), diff --git a/package-lock.json b/package-lock.json index 4b79b63afe..507d5ee0b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -106,6 +106,7 @@ "d3-force": "3.0.0", "dnd-core": "14.0.1", "dompurify": "3.4.13", + "driver.js": "1.8.0", "emojibase-data": "16.0.3", "fflate": "0.8.3", "frimousse": "0.3.0", @@ -9573,6 +9574,12 @@ "url": "https://dotenvx.com" } }, + "node_modules/driver.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/driver.js/-/driver.js-1.8.0.tgz", + "integrity": "sha512-+8/IO7h1v14IzWh2GP60N7T3PFZweXwdn5e5POuxRSBoCYUojsBxzqawPeXh3YZIibRy7EehYNEyxe7slwwtdg==", + "license": "MIT" + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",