Files
linux-odyssey/server/src/config.ts
T

119 lines
3.4 KiB
TypeScript

import validator from 'validator'
import { config as dotenvConfig } from 'dotenv'
import path from 'path'
import fs from 'fs'
import { get } from './utils/env.js'
// Import dotenv and load ../.env
dotenvConfig({ path: '../.env' })
if (process.env.NODE_ENV !== 'production') {
dotenvConfig({ path: '../.env.dev' })
}
function getTrustProxies(key: string): string[] {
const value = process.env[key]
if (!value) {
return []
}
return value
.split(',')
.map((p) => validator.trim(p))
.filter((p) => validator.isIPRange(p) || validator.isIP(p))
}
function getUrl(key: string): string {
const url = get(key, '')
if (validator.isURL(url)) {
return validator.trim(url)
}
return ''
}
function createConfig() {
const isProduction = process.env.NODE_ENV === 'production'
const host = get('HOST', '0.0.0.0')
const port = Number(get('PORT', 3000))
const baseUrl = get('BASE_URL', `http://${host}:${port}`)
const backendUrl = get('BACKEND_URL', `http://host.docker.internal:${port}`)
const url = new URL(baseUrl)
const projectRoot = getProjectRoot()
return {
host,
port,
baseUrl,
domain: url.hostname,
protocol: url.protocol,
backendUrl,
db: get('MONGO_URL', 'mongodb://localhost:27017/odyssey-test'),
secret: get('SECRET_KEY', ''),
isProduction: process.env.NODE_ENV === 'production',
containerExpiry: Number(process.env.CONTAINER_EXPIRY ?? 60) * 1000 * 60,
sessionMaxAge:
Number(process.env.SESSION_MAX_AGE ?? 7 * 24) * 1000 * 60 * 60,
google: {
clientID: get('GOOGLE_CLIENT_ID', ''),
clientSecret: get('GOOGLE_CLIENT_SECRET', ''),
},
github: {
clientID: get('GITHUB_CLIENT_ID', ''),
clientSecret: get('GITHUB_CLIENT_SECRET', ''),
},
trustedProxies: getTrustProxies('TRUSTED_PROXIES'),
surveyUrl: getUrl('SURVEY_URL'),
bugReportUrl: getUrl('BUG_REPORT_URL'),
rateLimit: {
maxFailedAttempts: Number(
process.env.RATE_LIMIT_MAX_FAILED_ATTEMPTS ?? 5
),
lockoutTime:
Number(process.env.RATE_LIMIT_LOCKOUT_TIME ?? 10) * 60 * 1000,
},
projectRoot,
docker: {
network: get('DOCKER_NETWORK', 'linux-odyssey-players-dev'),
defaultImage: get('QUEST_IMAGE', 'linuxodyssey/quest-base'),
imagePrefix: get('DOCKER_PREFIX', 'linuxodyssey/quest-'),
mountQuest: !isProduction && process.env.MOUNT_QUEST === 'true',
mountCLI: !isProduction && process.env.MOUNT_CLI === 'true',
hostProjectRoot: get('HOST_PROJECT_ROOT', projectRoot),
},
log: {
path: get('LOG_PATH', path.join(projectRoot, 'logs')),
},
testing: {
enabled: !isProduction && process.env.TESTING === 'true',
username: get('TESTING_USERNAME', ''),
password: get('TESTING_PASSWORD', ''),
},
}
}
function getProjectRoot(): string {
// Start from the current file's directory
let currentDir = __dirname
// Keep going up until we find the root package.json with workspaces
while (currentDir !== path.parse(currentDir).root) {
const packageJsonPath = path.join(currentDir, 'package.json')
if (fs.existsSync(packageJsonPath)) {
return path.join(currentDir, '..')
}
currentDir = path.dirname(currentDir)
}
throw new Error('Could not find project root directory')
}
const config = createConfig()
export function getQuestImage(id: string): string {
// TODO: handle staging images (add version tag)
return `${config.docker.imagePrefix}${id}`
}
export default config