Files
supabase/scripts/generateLocalEnv.js
Alaister Young f05ab582da chore(studio): wire self-hosted run + e2e env handling for TanStack build
Previous setup ran the studio under `vite preview` and signalled e2e
mode via `NODE_ENV=test`. That broke twice on this branch:

1. `NODE_ENV=test` in the shell overrides Vite's default
   `NODE_ENV=production` for `vite build`, which makes
   `@vitejs/plugin-react` emit the dev JSX runtime (`jsxDEV`). The
   production SSR bundle doesn't have `jsxDEV` available, so every SSR
   request crashed with `TypeError: jsxDEV is not a function`.
2. `vite preview` is a static SPA preview; it can't reuse the
   `fetch`-handler shape that `apps/studio/api/server.js` exposes to
   Vercel. Self-hosted prod needs its own HTTP listener for the same
   handler.

Changes:

- Swap `NODE_ENV=test` for `MODE=test` end-to-end. `vite build --mode
  test` keeps `NODE_ENV=production` automatically (per Vite docs), so
  the React plugin stays on the prod JSX runtime and TanStack Start
  bakes the right `NODE_ENV` into the SSR bundle. `.env.test` overrides
  load through the standard `loadEnv(mode, ...)` order, so the
  developer's `.env.local` no longer leaks `NEXT_PUBLIC_IS_PLATFORM=true`
  into e2e builds.
- Explicitly set `NEXT_PUBLIC_IS_PLATFORM=false` in
  `generateLocalEnv.js` so `.env.test` (which loads after `.env.local`)
  wins regardless of what a developer has set locally.
- Add `apps/studio/scripts/serve.js`: a small zero-dep Node HTTP
  adapter that loads env files, serves `dist/client/*` statics with
  proper cache headers, and forwards everything else to the
  `fetch`-handler exported by `dist/server/server.js` — the same
  handler `api/server.js` hands to Vercel. `pnpm start` runs this;
  `pnpm preview` keeps the old `vite preview` flow as a debug
  escape-hatch.
- Add `dist/**` to studio's turbo outputs so cached builds restore
  the Vite output (not just the legacy `.next/**`).
- Declare `MODE`, `PORT` in turbo env so cache invalidates correctly
  when switching between test and production builds.
2026-05-15 16:19:59 +08:00

66 lines
2.1 KiB
JavaScript

const fs = require('fs')
const generatedEnv = require('../keys.json')
/**
* This script takes the API keys from the local environment, merges them with some predefined variables and saves them
* to a env.test file in the studio app. This is needed to prepare the studio so that it can be run with the local
* environment as the backend.
*/
const defaultEnv = {
// NEXT_ANALYTICS_BACKEND_PROVIDER: 'postgres',
// SUPABASE_REST_URL: 'http://127.0.0.1:54321/rest/v1/',
// NEXT_PUBLIC_ENABLE_LOGS: 'false',
// E2E tests target self-hosted studio (no auth). Explicitly written so that
// .env.test overrides any IS_PLATFORM=true that a developer's .env.local
// might set for their own platform-mode work.
NEXT_PUBLIC_IS_PLATFORM: 'false',
PG_META_CRYPTO_KEY: 'SAMPLE_KEY',
POSTGRES_PASSWORD: 'postgres',
POSTGRES_HOST: 'db',
POSTGRES_DB: 'postgres',
POSTGRES_PORT: '5432',
SUPABASE_ANON_KEY: '$ANON_KEY',
SUPABASE_SERVICE_KEY: '$SERVICE_ROLE_KEY',
SUPABASE_URL: '$API_URL',
STUDIO_PG_META_URL: '$API_URL/pg',
SUPABASE_PUBLIC_URL: '$API_URL',
SENTRY_IGNORE_API_RESOLUTION_ERROR: '1',
LOGFLARE_URL: 'http://127.0.0.1:54327',
LOGFLARE_PRIVATE_ACCESS_TOKEN: 'api-key',
LOGFLARE_API_KEY: 'api-key',
NEXT_PUBLIC_SITE_URL: 'http://localhost:8082',
NEXT_PUBLIC_GOTRUE_URL: '$SUPABASE_PUBLIC_URL/auth/v1',
NEXT_PUBLIC_HCAPTCHA_SITE_KEY: '10000000-ffff-ffff-ffff-000000000001',
NEXT_PUBLIC_NODE_ENV: 'test',
SNIPPETS_MANAGEMENT_FOLDER: '../../supabase/snippets',
EDGE_FUNCTIONS_MANAGEMENT_FOLDER: '../../supabase/functions', // path relative to studio project
}
const environment = { ...generatedEnv, ...defaultEnv }
fs.writeFileSync(
'./apps/studio/.env.test',
Object.keys(environment)
.map((key) => `${key}=${environment[key]}`)
.join('\n')
)
const STUDIO_URL = environment.NEXT_PUBLIC_SITE_URL
const WEB_SERVER_PORT = new URL(STUDIO_URL).port ?? undefined
const API_URL = environment.API_URL
const e2eTestEnv = {
STUDIO_URL,
API_URL,
WEB_SERVER_PORT,
IS_PLATFORM: 'false',
}
fs.writeFileSync(
'./e2e/studio/.env.local',
Object.keys(e2eTestEnv)
.map((key) => `${key}=${e2eTestEnv[key]}`)
.join('\n')
)