From 82fbcf7ebb01d77319f74f55a014be29fd1b2703 Mon Sep 17 00:00:00 2001 From: martincupela Date: Wed, 3 Jun 2026 14:18:05 +0200 Subject: [PATCH] chore(demo): support local reference to stream-chat-js --- examples/vite/.env.example | 3 +- examples/vite/vite.config.ts | 81 +++++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/examples/vite/.env.example b/examples/vite/.env.example index 3e87a2c891..0d106a471d 100644 --- a/examples/vite/.env.example +++ b/examples/vite/.env.example @@ -1,3 +1,4 @@ VITE_STREAM_KEY="" VITE_USER_TOKEN="" -VITE_USER_ID="" \ No newline at end of file +VITE_USER_ID="" +STREAM_CHAT_JS_PATH="" diff --git a/examples/vite/vite.config.ts b/examples/vite/vite.config.ts index 55d4f8167d..324fc1dc92 100644 --- a/examples/vite/vite.config.ts +++ b/examples/vite/vite.config.ts @@ -1,15 +1,76 @@ +import { existsSync, readFileSync } from 'node:fs'; +import { createRequire } from 'node:module'; +import { dirname, resolve } from 'node:path'; import { defineConfig, loadEnv } from 'vite'; import babel from 'vite-plugin-babel'; import react from '@vitejs/plugin-react'; +const require = createRequire(import.meta.url); + +// Resolve the actual installed package root from the example app's dependency graph. +// This avoids assuming a fixed sibling-repo layout and works with portal/symlinked installs. +const getPackageRoot = (packageName: string, fromDirectory: string) => { + const packageEntry = require.resolve(packageName, { paths: [fromDirectory] }); + let currentDirectory = dirname(packageEntry); + + while (true) { + const packageJsonPath = resolve(currentDirectory, 'package.json'); + + if (existsSync(packageJsonPath)) { + const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as { + name?: string; + }; + + if (packageJson.name === packageName) { + return currentDirectory; + } + } + + const parentDirectory = dirname(currentDirectory); + + if (parentDirectory === currentDirectory) { + throw new Error(`Could not locate package root for "${packageName}"`); + } + + currentDirectory = parentDirectory; + } +}; + // https://vitejs.dev/config/ -export default defineConfig(() => { +export default defineConfig(({ mode }) => { const rootDir = process.cwd(); + const streamChatReactRoot = getPackageRoot('stream-chat-react', rootDir); // Load shared .env file - const env = loadEnv('', rootDir, ''); + const env = loadEnv(mode, rootDir, ''); + const streamChatJsRoot = env.STREAM_CHAT_JS_PATH + ? resolve(rootDir, env.STREAM_CHAT_JS_PATH) + : undefined; + const localStreamChatEntry = streamChatJsRoot + ? resolve(streamChatJsRoot, 'dist/esm/index.mjs') + : undefined; + + if (localStreamChatEntry && !existsSync(localStreamChatEntry)) { + throw new Error( + `STREAM_CHAT_JS_PATH must point to a built stream-chat-js checkout. Missing ${localStreamChatEntry}`, + ); + } + return { plugins: [ + ...(localStreamChatEntry + ? [ + { + enforce: 'pre' as const, + name: 'resolve-local-stream-chat', + resolveId(source: string) { + if (source === 'stream-chat') { + return localStreamChatEntry; + } + }, + }, + ] + : []), react(), babel({ babelConfig: { @@ -20,5 +81,21 @@ export default defineConfig(() => { define: { 'process.env': env, // need `process.env` access }, + optimizeDeps: { + // Keep local `stream-chat` out of Vite's prebundle so the browser loads the + // SDK build directly and DevTools can follow its sourcemaps back to source files. + // Its local ESM build still imports a few CommonJS deps that need Vite interop. + include: ['base64-js', 'form-data', 'isomorphic-ws', 'axios'], + exclude: localStreamChatEntry ? ['stream-chat'] : [], + }, + server: { + fs: { + allow: [ + rootDir, + streamChatReactRoot, + ...(streamChatJsRoot ? [streamChatJsRoot] : []), + ], + }, + }, }; });