Fix runtime env detection for SIT domains (#634)
This commit is contained in:
parent
4a03a0e783
commit
bdc3dc405f
@ -33,6 +33,8 @@ const YAML_SOURCES: Record<RuntimeSourceKey, string | undefined> = {
|
||||
const parsedYamlCache: Partial<Record<RuntimeSourceKey, Record<string, unknown>>> = {}
|
||||
const runtimeConfigCache = new Map<string, RuntimeConfig>()
|
||||
|
||||
const LOCAL_HOSTNAMES = new Set(['localhost', '127.0.0.1', '[::1]'])
|
||||
|
||||
function isPlainRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
||||
}
|
||||
@ -159,6 +161,15 @@ function detectHostname(hostnameOverride?: string): { hostname?: string; detecte
|
||||
|
||||
for (const candidate of envCandidates) {
|
||||
const hostname = sanitizeHostname(candidate.value)
|
||||
if (!hostname) {
|
||||
continue
|
||||
}
|
||||
|
||||
const likelyMachineHostname = !hostname.includes('.') && !LOCAL_HOSTNAMES.has(hostname)
|
||||
if (likelyMachineHostname) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (hostname) {
|
||||
return { hostname, detectedBy: candidate.source }
|
||||
}
|
||||
@ -167,15 +178,129 @@ function detectHostname(hostnameOverride?: string): { hostname?: string; detecte
|
||||
return { hostname: undefined, detectedBy: 'default' }
|
||||
}
|
||||
|
||||
function normalizeEnvironmentKey(value?: string): RuntimeEnvironment | undefined {
|
||||
if (!value) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const normalized = value
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]+/g, '_')
|
||||
.replace(/^_+|_+$/g, '')
|
||||
|
||||
const mapping: Record<string, RuntimeEnvironment> = {
|
||||
prod: 'prod',
|
||||
production: 'prod',
|
||||
release: 'prod',
|
||||
main: 'prod',
|
||||
live: 'prod',
|
||||
sit: 'sit',
|
||||
staging: 'sit',
|
||||
test: 'sit',
|
||||
qa: 'sit',
|
||||
uat: 'sit',
|
||||
dev: 'sit',
|
||||
development: 'sit',
|
||||
preview: 'sit',
|
||||
preprod: 'sit',
|
||||
}
|
||||
|
||||
return mapping[normalized]
|
||||
}
|
||||
|
||||
function detectEnvironmentFromEnvVars(): { environment: RuntimeEnvironment; matchedRule: string } | undefined {
|
||||
const envCandidates: Array<{ source: string; value?: string; allowProd?: boolean }> = [
|
||||
{ source: 'RUNTIME_ENV', value: process.env.RUNTIME_ENV },
|
||||
{ source: 'NEXT_RUNTIME_ENV', value: process.env.NEXT_RUNTIME_ENV },
|
||||
{ source: 'APP_ENV', value: process.env.APP_ENV },
|
||||
{ source: 'ENVIRONMENT', value: process.env.ENVIRONMENT },
|
||||
{ source: 'STAGE', value: process.env.STAGE },
|
||||
{ source: 'NODE_ENV', value: process.env.NODE_ENV, allowProd: false },
|
||||
]
|
||||
|
||||
for (const candidate of envCandidates) {
|
||||
const normalized = normalizeEnvironmentKey(candidate.value)
|
||||
if (!normalized) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (!candidate.allowProd && normalized === 'prod') {
|
||||
continue
|
||||
}
|
||||
|
||||
return { environment: normalized, matchedRule: `env:${candidate.source}` }
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
function detectEnvironmentFromHostnamePattern(hostname: string):
|
||||
| { environment: RuntimeEnvironment; matchedRule: string }
|
||||
| undefined {
|
||||
const normalized = hostname.toLowerCase()
|
||||
|
||||
if (normalized.startsWith('dev.') || normalized.startsWith('dev-') || normalized.includes('.dev.')) {
|
||||
return { environment: 'sit', matchedRule: 'dev-subdomain' }
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
function detectEnvironmentFromUrlHints(): { environment: RuntimeEnvironment; matchedRule: string } | undefined {
|
||||
const urlCandidates = [
|
||||
{ source: 'RUNTIME_HOSTNAME', value: process.env.RUNTIME_HOSTNAME },
|
||||
{ source: 'NEXT_RUNTIME_HOSTNAME', value: process.env.NEXT_RUNTIME_HOSTNAME },
|
||||
{ source: 'RUNTIME_DASHBOARD_URL', value: process.env.RUNTIME_DASHBOARD_URL },
|
||||
{ source: 'NEXT_PUBLIC_DASHBOARD_URL', value: process.env.NEXT_PUBLIC_DASHBOARD_URL },
|
||||
{ source: 'DASHBOARD_URL', value: process.env.DASHBOARD_URL },
|
||||
{ source: 'ACCOUNT_SERVICE_URL', value: process.env.ACCOUNT_SERVICE_URL },
|
||||
{ source: 'NEXT_PUBLIC_ACCOUNT_SERVICE_URL', value: process.env.NEXT_PUBLIC_ACCOUNT_SERVICE_URL },
|
||||
{ source: 'SERVER_SERVICE_URL', value: process.env.SERVER_SERVICE_URL },
|
||||
{ source: 'NEXT_PUBLIC_SERVER_SERVICE_URL', value: process.env.NEXT_PUBLIC_SERVER_SERVICE_URL },
|
||||
{ source: 'NEXT_PUBLIC_API_BASE_URL', value: process.env.NEXT_PUBLIC_API_BASE_URL },
|
||||
{ source: 'API_BASE_URL', value: process.env.API_BASE_URL },
|
||||
{ source: 'AUTH_URL', value: process.env.AUTH_URL },
|
||||
{ source: 'NEXT_PUBLIC_AUTH_URL', value: process.env.NEXT_PUBLIC_AUTH_URL },
|
||||
]
|
||||
|
||||
for (const candidate of urlCandidates) {
|
||||
const hostname = sanitizeHostname(candidate.value)
|
||||
if (!hostname) {
|
||||
continue
|
||||
}
|
||||
|
||||
const detected = detectEnvironmentFromHostnamePattern(hostname)
|
||||
if (detected) {
|
||||
return { ...detected, matchedRule: `env-url:${candidate.source}` }
|
||||
}
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
function detectEnvironment(hostname?: string): { environment: RuntimeEnvironment; region: RuntimeRegion; matchedRule: string } {
|
||||
const normalized = hostname?.toLowerCase() ?? ''
|
||||
|
||||
let environment: RuntimeEnvironment = 'prod'
|
||||
let matchedRule = 'default'
|
||||
|
||||
if (normalized.startsWith('dev.') || normalized.startsWith('dev-') || normalized.includes('.dev.')) {
|
||||
environment = 'sit'
|
||||
matchedRule = 'dev-subdomain'
|
||||
const envOverride = detectEnvironmentFromEnvVars()
|
||||
if (envOverride) {
|
||||
environment = envOverride.environment
|
||||
matchedRule = envOverride.matchedRule
|
||||
} else {
|
||||
const hostnameMatch = normalized ? detectEnvironmentFromHostnamePattern(normalized) : undefined
|
||||
if (hostnameMatch) {
|
||||
environment = hostnameMatch.environment
|
||||
matchedRule = hostnameMatch.matchedRule
|
||||
} else {
|
||||
const hintMatch = detectEnvironmentFromUrlHints()
|
||||
if (hintMatch) {
|
||||
environment = hintMatch.environment
|
||||
matchedRule = hintMatch.matchedRule
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let region: RuntimeRegion = 'default'
|
||||
|
||||
Loading…
Reference in New Issue
Block a user