|
| 1 | +/** |
| 2 | + * Public env exposure for client bundles |
| 3 | + * |
| 4 | + * Mirrors the server-side `$env` template context (process.ts:762) onto the |
| 5 | + * client side via build-time substitution. Any env var matching `envPrefix` |
| 6 | + * (default `STX_PUBLIC_`) gets inlined as `import.meta.env.STX_PUBLIC_*` in |
| 7 | + * scripts bundled for the browser. |
| 8 | + * |
| 9 | + * .env: STX_PUBLIC_API_URL=https://api.example.com |
| 10 | + * store: const api = import.meta.env.STX_PUBLIC_API_URL |
| 11 | + * built: const api = "https://api.example.com" |
| 12 | + * |
| 13 | + * Vite-style. Build-time, zero runtime cost. |
| 14 | + */ |
| 15 | + |
| 16 | +import process from 'node:process' |
| 17 | + |
| 18 | +/** |
| 19 | + * Build the `define` map every client bundler/transpiler should pass to |
| 20 | + * Bun.build / new Bun.Transpiler({ define }). |
| 21 | + * |
| 22 | + * Returns substitutions for both `import.meta.env.<KEY>` (preferred, Vite- |
| 23 | + * compatible) and a single `import.meta.env` literal that maps to the full |
| 24 | + * object so consumers can do `if (import.meta.env.X)` and similar idiomatic |
| 25 | + * patterns. |
| 26 | + */ |
| 27 | +export function getPublicEnvDefine(envPrefix: string = 'STX_PUBLIC_'): Record<string, string> { |
| 28 | + const define: Record<string, string> = {} |
| 29 | + const envObject: Record<string, string> = {} |
| 30 | + |
| 31 | + for (const [key, value] of Object.entries(process.env)) { |
| 32 | + if (!key.startsWith(envPrefix) || value === undefined) |
| 33 | + continue |
| 34 | + define[`import.meta.env.${key}`] = JSON.stringify(value) |
| 35 | + envObject[key] = value |
| 36 | + } |
| 37 | + |
| 38 | + // Whole-object substitution lets `Object.keys(import.meta.env)` and similar |
| 39 | + // dynamic patterns work, not just direct key access. |
| 40 | + define['import.meta.env'] = JSON.stringify(envObject) |
| 41 | + |
| 42 | + return define |
| 43 | +} |
| 44 | + |
| 45 | +/** |
| 46 | + * Get the public env values as a plain object. Useful for places that want |
| 47 | + * the raw map (e.g. tests, debugging) rather than the define-shaped strings. |
| 48 | + */ |
| 49 | +export function getPublicEnv(envPrefix: string = 'STX_PUBLIC_'): Record<string, string> { |
| 50 | + const out: Record<string, string> = {} |
| 51 | + for (const [key, value] of Object.entries(process.env)) { |
| 52 | + if (key.startsWith(envPrefix) && value !== undefined) |
| 53 | + out[key] = value |
| 54 | + } |
| 55 | + return out |
| 56 | +} |
0 commit comments