|
| 1 | +/** |
| 2 | + * Cross-runtime environment variable helper |
| 3 | + */ |
| 4 | + |
| 5 | +type Runtime = |
| 6 | + | 'node' |
| 7 | + | 'deno' |
| 8 | + | 'bun' |
| 9 | + | 'cloudflare' |
| 10 | + | 'fastly' |
| 11 | + | 'edge-light' |
| 12 | + | 'other'; |
| 13 | + |
| 14 | +let detectedRuntime: Runtime | null = null; |
| 15 | + |
| 16 | +/** |
| 17 | + * Detect the current runtime environment. |
| 18 | + * This function checks for various runtime environments such as Node.js, Deno, Bun, Cloudflare Workers, Fastly, and Edge Light. |
| 19 | + * It returns a string representing the detected runtime and caches the result for future calls. |
| 20 | + * @returns The detected runtime environment as a string. |
| 21 | + */ |
| 22 | +export function detectRuntime(): Runtime { |
| 23 | + if (detectedRuntime) { |
| 24 | + return detectedRuntime; |
| 25 | + } |
| 26 | + |
| 27 | + const global = globalThis as any; |
| 28 | + |
| 29 | + if (typeof process !== 'undefined' && process.release?.name === 'node') { |
| 30 | + detectedRuntime = 'node'; |
| 31 | + } else if (typeof global.Deno !== 'undefined') { |
| 32 | + detectedRuntime = 'deno'; |
| 33 | + } else if ( |
| 34 | + typeof navigator !== 'undefined' && |
| 35 | + navigator.userAgent?.includes('Bun') |
| 36 | + ) { |
| 37 | + detectedRuntime = 'bun'; |
| 38 | + } else if ( |
| 39 | + typeof navigator !== 'undefined' && |
| 40 | + navigator.userAgent?.includes('Cloudflare') |
| 41 | + ) { |
| 42 | + detectedRuntime = 'cloudflare'; |
| 43 | + } else if (typeof global !== 'undefined' && 'fastly' in global) { |
| 44 | + detectedRuntime = 'fastly'; |
| 45 | + } else if (typeof global !== 'undefined' && 'EdgeRuntime' in global) { |
| 46 | + detectedRuntime = 'edge-light'; |
| 47 | + } else { |
| 48 | + detectedRuntime = 'other'; |
| 49 | + } |
| 50 | + |
| 51 | + return detectedRuntime; |
| 52 | +} |
| 53 | + |
| 54 | +function getEnvironmentVariable(key: string): string | undefined { |
| 55 | + const runtime = detectRuntime(); |
| 56 | + const global = globalThis as any; |
| 57 | + |
| 58 | + try { |
| 59 | + switch (runtime) { |
| 60 | + case 'node': |
| 61 | + case 'bun': |
| 62 | + case 'edge-light': |
| 63 | + return process.env[key]; |
| 64 | + |
| 65 | + case 'deno': |
| 66 | + return global.Deno.env.get(key); |
| 67 | + |
| 68 | + case 'cloudflare': |
| 69 | + return global.env?.[key] ?? global[key]; |
| 70 | + |
| 71 | + case 'fastly': |
| 72 | + return global[key]; |
| 73 | + |
| 74 | + default: |
| 75 | + return process?.env?.[key] ?? global.env?.[key] ?? global[key]; |
| 76 | + } |
| 77 | + } catch { |
| 78 | + return undefined; |
| 79 | + } |
| 80 | +} |
| 81 | + |
| 82 | +/** |
| 83 | + * Get an environment variable value, trying to access it in different runtimes. |
| 84 | + * @param key - The name of the environment variable. |
| 85 | + * @param defaultValue - The default value to return if the variable is not found. |
| 86 | + * @return The value of the environment variable or the default value. |
| 87 | + */ |
| 88 | +export function getEnv<T = string>( |
| 89 | + key: string, |
| 90 | + defaultValue?: T, |
| 91 | +): string | T | undefined { |
| 92 | + return getEnvironmentVariable(key) ?? defaultValue; |
| 93 | +} |
0 commit comments