UNPKG

@xrengine/server-core

Version:

Shared components for XREngine server

388 lines (358 loc) 11.7 kB
import appRootPath from 'app-root-path' import * as chargebeeInst from 'chargebee' import dotenv from 'dotenv-flow' import path from 'path' import url from 'url' import multiLogger from './ServerLogger' const { register } = require('trace-unhandled') register() const logger = multiLogger.child({ component: 'server-core:config' }) const kubernetesEnabled = process.env.KUBERNETES === 'true' const testEnabled = process.env.TEST === 'true' // ensure process fails properly process.on('exit', async (code) => { const message = `Server EXIT(${code}).` if (code === 0) { logger.info(message) } else { logger.fatal(message) } }) process.on('SIGTERM', async (err) => { logger.warn(err, 'Server SIGTERM.') process.exit(1) }) process.on('SIGINT', () => { logger.warn('RECEIVED SIGINT.') process.exit(1) }) // emitted when an uncaught JavaScript exception bubbles process.on('uncaughtException', (err) => { logger.fatal(err, 'UNCAUGHT EXCEPTION.') process.exit(1) }) //emitted whenever a Promise is rejected and no error handler is attached to it process.on('unhandledRejection', (reason, p) => { logger.fatal({ reason, promise: p }, 'UNHANDLED PROMISE REJECTION.') process.exit(1) }) if (process.env.APP_ENV === 'development' || process.env.LOCAL === 'true') { // Avoids DEPTH_ZERO_SELF_SIGNED_CERT error for self-signed certs - needed for local storage provider process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' var fs = require('fs') if (!fs.existsSync(appRootPath.path + '/.env') && !fs.existsSync(appRootPath.path + '/.env.local')) { var fromEnvPath = appRootPath.path + '/.env.local.default' var toEnvPath = appRootPath.path + '/.env.local' fs.copyFileSync(fromEnvPath, toEnvPath, fs.constants.COPYFILE_EXCL) } } if (!kubernetesEnabled) { dotenv.config({ path: appRootPath.path, silent: true }) } /** * Database */ export const db = { username: testEnabled ? process.env.MYSQL_TEST_USER! : process.env.MYSQL_USER!, password: testEnabled ? process.env.MYSQL_TEST_PASSWORD! : process.env.MYSQL_PASSWORD!, database: testEnabled ? process.env.MYSQL_TEST_DATABASE! : process.env.MYSQL_DATABASE!, host: testEnabled ? process.env.MYSQL_TEST_HOST! : process.env.MYSQL_HOST!, port: testEnabled ? process.env.MYSQL_TEST_PORT! : process.env.MYSQL_PORT!, dialect: 'mysql', forceRefresh: process.env.FORCE_DB_REFRESH === 'true', url: '', charset: 'utf8mb4', collate: 'utf8mb4_general_ci', pool: { max: parseInt(process.env.SEQUELIZE_POOL_MAX || '5') } } db.url = (testEnabled ? process.env.MYSQL_TEST_URL : process.env.MYSQL_URL) || `mysql://${db.username}:${db.password}@${db.host}:${db.port}/${db.database}` /** * Server / backend */ const server = { mode: process.env.SERVER_MODE!, hostname: process.env.SERVER_HOST!, port: process.env.SERVER_PORT!, clientHost: process.env.APP_HOST!, // Public directory (used for favicon.ico, logo, etc) rootDir: process.env.BUILD_MODE! === 'individual' ? path.resolve(appRootPath.path) : path.resolve(appRootPath.path, 'packages', 'server'), publicDir: process.env.SERVER_PUBLIC_DIR! || (process.env.BUILD_MODE === 'individual' ? path.resolve(appRootPath.path, 'public') : path.resolve(appRootPath.path, 'packages', 'server', 'public')), nodeModulesDir: path.resolve(__dirname, '../..', 'node_modules'), localStorageProvider: process.env.LOCAL_STORAGE_PROVIDER!, localStorageProviderPort: process.env.LOCAL_STORAGE_PROVIDER_PORT!, corsServerPort: process.env.CORS_SERVER_PORT!, storageProvider: process.env.STORAGE_PROVIDER!, gaTrackingId: process.env.GOOGLE_ANALYTICS_TRACKING_ID!, hub: { endpoint: process.env.HUB_ENDPOINT! }, paginate: { default: 10, max: 100 }, url: '', certPath: appRootPath.path.toString() + '/' + process.env.CERT, keyPath: appRootPath.path.toString() + '/' + process.env.KEY, gitPem: '', local: process.env.LOCAL === 'true', releaseName: process.env.RELEASE_NAME || 'local', matchmakerEmulationMode: process.env.MATCHMAKER_EMULATION_MODE === 'true', instanceserverUnreachableTimeoutSeconds: process.env.INSTANCESERVER_UNREACHABLE_TIMEOUT_SECONDS ? parseInt(process.env.INSTANCESERVER_UNREACHABLE_TIMEOUT_SECONDS) : 10 } const obj = kubernetesEnabled ? { protocol: 'https', hostname: server.hostname } : { protocol: 'https', ...server } server.url = process.env.SERVER_URL || url.format(obj) /** * Client / frontend */ const client = { logo: process.env.APP_LOGO!, title: process.env.APP_TITLE!, get dist() { if (process.env.SERVE_CLIENT_FROM_STORAGE_PROVIDER === 'true') { if (process.env.STORAGE_PROVIDER === 'aws' && process.env.STORAGE_CLOUDFRONT_DOMAIN) { return `https://${process.env.STORAGE_CLOUDFRONT_DOMAIN}/client/` } else if (process.env.STORAGE_PROVIDER === 'local') { return `https://${process.env.LOCAL_STORAGE_PROVIDER}/client/` } } return client.url }, url: process.env.APP_URL || (process.env.VITE_LOCAL_BUILD ? 'http://' + process.env.APP_HOST + ':' + process.env.APP_PORT : 'https://' + process.env.APP_HOST + ':' + process.env.APP_PORT), releaseName: process.env.RELEASE_NAME || 'local' } // TODO: rename to 'instanceserver' const instanceserver = { clientHost: process.env.APP_HOST!, hostname: process.env.INSTANCESERVER_HOST, rtc_start_port: parseInt(process.env.RTC_START_PORT!), rtc_end_port: parseInt(process.env.RTC_END_PORT!), rtc_port_block_size: parseInt(process.env.RTC_PORT_BLOCK_SIZE!), identifierDigits: 5, local: process.env.LOCAL === 'true', domain: process.env.INSTANCESERVER_DOMAIN || 'instanceserver.etherealengine.com', releaseName: process.env.RELEASE_NAME || 'local', port: process.env.INSTANCESERVER_PORT!, locationName: process.env.PRELOAD_LOCATION_NAME!, shutdownDelayMs: parseInt(process.env.INSTANCESERVER_SHUTDOWN_DELAY_MS!) || 0 } /** * Task server generator */ const taskserver = { port: process.env.TASKSERVER_PORT!, processInterval: process.env.TASKSERVER_PROCESS_INTERVAL_SECONDS! } /** * Email / SMTP */ const email = { smtp: { host: process.env.SMTP_HOST!, port: parseInt(process.env.SMTP_PORT!), secure: process.env.SMTP_SECURE === 'true', auth: { user: process.env.SMTP_USER!, pass: process.env.SMTP_PASS! } }, // Name and email of default sender (for login emails, etc) from: `${process.env.SMTP_FROM_NAME}` + ` <${process.env.SMTP_FROM_EMAIL}>`, subject: { // Subject of the Login Link email 'new-user': 'Signup', location: 'Location invitation', instance: 'Location invitation', login: 'Login link', friend: 'Friend request', group: 'Group invitation', party: 'Party invitation' }, smsNameCharacterLimit: 20 } /** * Authentication */ const authentication = { service: 'identity-provider', entity: 'identity-provider', secret: process.env.AUTH_SECRET!, authStrategies: ['jwt', 'local', 'discord', 'facebook', 'github', 'google', 'linkedin', 'twitter', 'didWallet'], local: { usernameField: 'email', passwordField: 'password' }, jwtOptions: { expiresIn: '30 days' }, bearerToken: { numBytes: 16 }, callback: { discord: process.env.DISCORD_CALLBACK_URL || `${client.url}/auth/oauth/discord`, facebook: process.env.FACEBOOK_CALLBACK_URL || `${client.url}/auth/oauth/facebook`, github: process.env.GITHUB_CALLBACK_URL || `${client.url}/auth/oauth/github`, google: process.env.GOOGLE_CALLBACK_URL || `${client.url}/auth/oauth/google`, linkedin: process.env.LINKEDIN_CALLBACK_URL || `${client.url}/auth/oauth/linkedin`, twitter: process.env.TWITTER_CALLBACK_URL || `${client.url}/auth/oauth/twitter` // didWallet does not have a callback endpoint }, oauth: { defaults: { host: server.hostname !== '127.0.0.1' && server.hostname !== 'localhost' ? server.hostname : server.hostname + ':' + server.port, protocol: 'https' }, discord: { key: process.env.DISCORD_CLIENT_ID!, secret: process.env.DISCORD_CLIENT_SECRET!, scope: ['identify', 'email'], custom_params: { prompt: 'none' } }, facebook: { key: process.env.FACEBOOK_CLIENT_ID!, secret: process.env.FACEBOOK_CLIENT_SECRET! }, github: { appid: process.env.GITHUB_APP_ID!, key: process.env.GITHUB_CLIENT_ID!, secret: process.env.GITHUB_CLIENT_SECRET!, scope: ['repo', 'user'] }, google: { key: process.env.GOOGLE_CLIENT_ID!, secret: process.env.GOOGLE_CLIENT_SECRET!, scope: ['profile', 'email'] }, linkedin: { key: process.env.LINKEDIN_CLIENT_ID!, secret: process.env.LINKEDIN_CLIENT_SECRET!, scope: ['r_liteprofile', 'r_emailaddress'] }, twitter: { key: process.env.TWITTER_CLIENT_ID!, secret: process.env.TWITTER_CLIENT_SECRET! } } } /** * AWS */ const aws = { keys: { accessKeyId: process.env.STORAGE_AWS_ACCESS_KEY_ID!, secretAccessKey: process.env.STORAGE_AWS_ACCESS_KEY_SECRET! }, route53: { hostedZoneId: process.env.ROUTE53_HOSTED_ZONE_ID!, keys: { accessKeyId: process.env.ROUTE53_ACCESS_KEY_ID!, secretAccessKey: process.env.ROUTE53_ACCESS_KEY_SECRET! } }, s3: { baseUrl: 'https://s3.amazonaws.com', endpoint: process.env.STORAGE_S3_ENDPOINT!, staticResourceBucket: process.env.STORAGE_S3_STATIC_RESOURCE_BUCKET!, region: process.env.STORAGE_S3_REGION!, avatarDir: process.env.STORAGE_S3_AVATAR_DIRECTORY!, s3DevMode: process.env.STORAGE_S3_DEV_MODE! }, cloudfront: { domain: process.env.STORAGE_CLOUDFRONT_DOMAIN!, distributionId: process.env.STORAGE_CLOUDFRONT_DISTRIBUTION_ID!, region: process.env.STORAGE_CLOUDFRONT_REGION || process.env.STORAGE_S3_REGION }, sms: { accessKeyId: process.env.AWS_SMS_ACCESS_KEY_ID!, applicationId: process.env.AWS_SMS_APPLICATION_ID!, region: process.env.AWS_SMS_REGION!, senderId: process.env.AWS_SMS_SENDER_ID!, secretAccessKey: process.env.AWS_SMS_SECRET_ACCESS_KEY! } } const chargebee = { url: process.env.CHARGEBEE_SITE + '.chargebee.com' || 'dummy.not-chargebee.com', apiKey: process.env.CHARGEBEE_API_KEY! } const coil = { paymentPointer: process.env.COIL_PAYMENT_POINTER, clientId: process.env.COIL_API_CLIENT_ID, clientSecret: process.env.COIL_API_CLIENT_SECRET } const redis = { enabled: process.env.REDIS_ENABLED === 'true', address: process.env.REDIS_ADDRESS!, port: process.env.REDIS_PORT!, password: process.env.REDIS_PASSWORD == '' || process.env.REDIS_PASSWORD == null ? null! : process.env.REDIS_PASSWORD! } /** * Scope */ const scopes = { guest: process.env.DEFAULT_GUEST_SCOPES?.split(',') || [], user: process.env.DEFAULT_USER_SCOPES?.split(',') || [] } const blockchain = { blockchainUrl: process.env.BLOCKCHAIN_URL, blockchainUrlSecret: process.env.BLOCKCHAIN_URL_SECRET } const ipfs = { enabled: process.env.USE_IPFS } /** * Full config */ const config = { deployStage: process.env.DEPLOY_STAGE!, authentication, aws, chargebee, client, coil, db, email, instanceserver, ipfs, server, taskserver, redis, scopes, blockchain, kubernetes: { enabled: kubernetesEnabled, serviceHost: process.env.KUBERNETES_SERVICE_HOST!, tcpPort: process.env.KUBERNETES_PORT_443_TCP_PORT! }, noSSL: process.env.NOSSL === 'true', localBuild: process.env.VITE_LOCAL_BUILD === 'true', testEnabled } chargebeeInst.configure({ site: process.env.CHARGEBEE_SITE!, api_key: config.chargebee.apiKey }) export default config