diff --git a/apps/studio/.npmrc b/apps/studio/.npmrc new file mode 100644 index 000000000..94558d3bc --- /dev/null +++ b/apps/studio/.npmrc @@ -0,0 +1,3 @@ +# Vercel doesn't support symlinked directories in serverless functions. +# Use hoisted node-linker to create a flat node_modules structure without symlinks. +node-linker=hoisted diff --git a/apps/studio/package.json b/apps/studio/package.json index c6eeff7e7..a6b3912e9 100644 --- a/apps/studio/package.json +++ b/apps/studio/package.json @@ -23,6 +23,7 @@ "@ai-sdk/openai": "^3.0.52", "@ai-sdk/react": "^3.0.160", "@hono/node-server": "^1.19.14", + "@libsql/client": "^0.17.2", "@objectstack/client": "workspace:*", "@objectstack/client-react": "workspace:*", "@objectstack/driver-memory": "workspace:*", @@ -57,6 +58,7 @@ "@radix-ui/react-toast": "^1.2.15", "@radix-ui/react-tooltip": "^1.2.8", "ai": "^6.0.158", + "better-sqlite3": "^12.8.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "hono": "^4.12.12", diff --git a/apps/studio/scripts/build-vercel.sh b/apps/studio/scripts/build-vercel.sh index 10a5507f4..00571fc20 100755 --- a/apps/studio/scripts/build-vercel.sh +++ b/apps/studio/scripts/build-vercel.sh @@ -28,31 +28,15 @@ cd apps/studio # 2. Bundle API serverless function node scripts/bundle-api.mjs -# 3. Copy native/external modules into local node_modules for Vercel packaging. +# 3. Copy @ai-sdk packages from monorepo root. # -# Unlike hotcrm (which uses shamefully-hoist=true), this monorepo uses pnpm's -# default strict node_modules structure. Transitive native dependencies like -# better-sqlite3 only exist in the monorepo root's node_modules/.pnpm/ virtual -# store — they're NOT symlinked into apps/studio/node_modules/. +# The @ai-sdk packages are workspace dependencies that pnpm doesn't hoist into +# apps/studio/node_modules by default. We copy them here so Vercel's includeFiles +# pattern can find them. # -# The vercel.json includeFiles pattern references node_modules/ relative to -# apps/studio/, so we must copy the actual module files here for Vercel to -# include them in the serverless function's deployment package. -# -# Note: @libsql/client is now bundled by esbuild, so we no longer copy it. -echo "[build-vercel] Copying external native modules to local node_modules..." -for mod in better-sqlite3; do - src="../../node_modules/$mod" - if [ -e "$src" ]; then - dest="node_modules/$mod" - mkdir -p "$(dirname "$dest")" - cp -rL "$src" "$dest" - echo "[build-vercel] ✓ Copied $mod" - else - echo "[build-vercel] ⚠ $mod not found at $src (skipped)" - fi -done -# Copy the @ai-sdk scope (dynamically loaded provider packages) +# Note: .npmrc configures node-linker=hoisted to prevent pnpm from creating symlinks, +# which Vercel's serverless function packaging doesn't support. +echo "[build-vercel] Copying @ai-sdk packages..." if [ -d "../../node_modules/@ai-sdk" ]; then mkdir -p "node_modules/@ai-sdk" for pkg in ../../node_modules/@ai-sdk/*/; do diff --git a/apps/studio/scripts/bundle-api.mjs b/apps/studio/scripts/bundle-api.mjs index 9f1d8fc81..1dc897e69 100644 --- a/apps/studio/scripts/bundle-api.mjs +++ b/apps/studio/scripts/bundle-api.mjs @@ -16,9 +16,8 @@ import { build } from 'esbuild'; // Packages that cannot be bundled (native bindings / optional drivers) const EXTERNAL = [ - // @libsql/client is now bundled (pure JS, no native bindings) - // Bundling it solves Vercel deployment issues where external packages - // aren't properly included in the serverless function despite includeFiles config + // @libsql/client must be external — bundling breaks internal HttpClient2 class constructor + '@libsql/client', 'better-sqlite3', // AI SDK provider packages — dynamically imported based on env vars '@ai-sdk/anthropic', diff --git a/apps/studio/vercel.json b/apps/studio/vercel.json index 96e8daf72..eb63e91d8 100644 --- a/apps/studio/vercel.json +++ b/apps/studio/vercel.json @@ -13,7 +13,7 @@ "api/**/*.js": { "memory": 1024, "maxDuration": 300, - "includeFiles": "node_modules/{better-sqlite3,@ai-sdk}/**" + "includeFiles": "node_modules/{@libsql/client,better-sqlite3,@ai-sdk}/**" } }, "headers": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 560a03771..f33cfd327 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -145,6 +145,9 @@ importers: '@hono/node-server': specifier: ^1.19.14 version: 1.19.14(hono@4.12.12) + '@libsql/client': + specifier: ^0.17.2 + version: 0.17.2 '@objectstack/client': specifier: workspace:* version: link:../../packages/client @@ -247,6 +250,9 @@ importers: ai: specifier: ^6.0.158 version: 6.0.158(zod@4.3.6) + better-sqlite3: + specifier: ^12.8.0 + version: 12.9.0 class-variance-authority: specifier: ^0.7.1 version: 0.7.1