2020-12-28 13:48:47 +02:00
|
|
|
import { rtrimSlashes } from '@joplin/lib/path-utils';
|
2021-07-10 12:16:13 +02:00
|
|
|
import { Config, DatabaseConfig, DatabaseConfigClient, Env, MailerConfig, RouteType, StripeConfig, StripePublicConfig } from './utils/types';
|
2021-01-18 12:13:26 +02:00
|
|
|
import * as pathUtils from 'path';
|
2021-05-26 15:53:27 +02:00
|
|
|
import { readFile } from 'fs-extra';
|
2020-12-28 13:48:47 +02:00
|
|
|
|
2021-01-18 12:13:26 +02:00
|
|
|
export interface EnvVariables {
|
2021-06-03 15:21:02 +02:00
|
|
|
APP_NAME?: string;
|
|
|
|
|
2021-01-18 12:13:26 +02:00
|
|
|
APP_BASE_URL?: string;
|
2021-05-25 16:42:21 +02:00
|
|
|
USER_CONTENT_BASE_URL?: string;
|
|
|
|
API_BASE_URL?: string;
|
|
|
|
|
2021-01-18 12:13:26 +02:00
|
|
|
APP_PORT?: string;
|
|
|
|
DB_CLIENT?: string;
|
|
|
|
RUNNING_IN_DOCKER?: string;
|
2020-12-28 13:48:47 +02:00
|
|
|
|
2021-01-18 12:13:26 +02:00
|
|
|
POSTGRES_PASSWORD?: string;
|
|
|
|
POSTGRES_DATABASE?: string;
|
|
|
|
POSTGRES_USER?: string;
|
|
|
|
POSTGRES_HOST?: string;
|
|
|
|
POSTGRES_PORT?: string;
|
|
|
|
|
2021-05-25 11:49:47 +02:00
|
|
|
MAILER_ENABLED?: string;
|
|
|
|
MAILER_HOST?: string;
|
|
|
|
MAILER_PORT?: string;
|
|
|
|
MAILER_SECURE?: string;
|
|
|
|
MAILER_AUTH_USER?: string;
|
|
|
|
MAILER_AUTH_PASSWORD?: string;
|
|
|
|
MAILER_NOREPLY_NAME?: string;
|
|
|
|
MAILER_NOREPLY_EMAIL?: string;
|
|
|
|
|
2021-05-25 12:13:35 +02:00
|
|
|
// This must be the full path to the database file
|
2021-01-18 12:13:26 +02:00
|
|
|
SQLITE_DATABASE?: string;
|
2021-06-03 15:21:02 +02:00
|
|
|
|
|
|
|
STRIPE_SECRET_KEY?: string;
|
|
|
|
STRIPE_WEBHOOK_SECRET?: string;
|
2021-06-04 17:08:21 +02:00
|
|
|
|
|
|
|
SIGNUP_ENABLED?: string;
|
2021-06-04 18:09:09 +02:00
|
|
|
TERMS_ENABLED?: string;
|
2021-06-16 16:02:26 +02:00
|
|
|
ACCOUNT_TYPES_ENABLED?: string;
|
2021-06-08 12:08:40 +02:00
|
|
|
|
|
|
|
ERROR_STACK_TRACES?: string;
|
2021-07-11 12:35:49 +02:00
|
|
|
|
|
|
|
SUPPORT_EMAIL?: string;
|
|
|
|
BUSINESS_EMAIL?: string;
|
2020-12-28 13:48:47 +02:00
|
|
|
}
|
|
|
|
|
2021-01-18 12:13:26 +02:00
|
|
|
let runningInDocker_: boolean = false;
|
|
|
|
|
|
|
|
export function runningInDocker(): boolean {
|
|
|
|
return runningInDocker_;
|
2020-12-28 13:48:47 +02:00
|
|
|
}
|
|
|
|
|
2021-01-18 12:13:26 +02:00
|
|
|
function databaseHostFromEnv(runningInDocker: boolean, env: EnvVariables): string {
|
|
|
|
if (env.POSTGRES_HOST) {
|
|
|
|
// When running within Docker, the app localhost is different from the
|
|
|
|
// host's localhost. To access the latter, Docker defines a special host
|
|
|
|
// called "host.docker.internal", so here we swap the values if necessary.
|
|
|
|
if (runningInDocker && ['localhost', '127.0.0.1'].includes(env.POSTGRES_HOST)) {
|
|
|
|
return 'host.docker.internal';
|
|
|
|
} else {
|
|
|
|
return env.POSTGRES_HOST;
|
|
|
|
}
|
|
|
|
}
|
2020-12-28 13:48:47 +02:00
|
|
|
|
2021-01-18 12:13:26 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
function databaseConfigFromEnv(runningInDocker: boolean, env: EnvVariables): DatabaseConfig {
|
|
|
|
if (env.DB_CLIENT === 'pg') {
|
|
|
|
return {
|
|
|
|
client: DatabaseConfigClient.PostgreSQL,
|
|
|
|
name: env.POSTGRES_DATABASE || 'joplin',
|
|
|
|
user: env.POSTGRES_USER || 'joplin',
|
|
|
|
password: env.POSTGRES_PASSWORD || 'joplin',
|
|
|
|
port: env.POSTGRES_PORT ? Number(env.POSTGRES_PORT) : 5432,
|
|
|
|
host: databaseHostFromEnv(runningInDocker, env) || 'localhost',
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
client: DatabaseConfigClient.SQLite,
|
2021-05-25 12:13:35 +02:00
|
|
|
name: env.SQLITE_DATABASE,
|
2021-01-18 12:13:26 +02:00
|
|
|
asyncStackTraces: true,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-05-25 11:49:47 +02:00
|
|
|
function mailerConfigFromEnv(env: EnvVariables): MailerConfig {
|
|
|
|
return {
|
|
|
|
enabled: env.MAILER_ENABLED !== '0',
|
|
|
|
host: env.MAILER_HOST || '',
|
|
|
|
port: Number(env.MAILER_PORT || 587),
|
|
|
|
secure: !!Number(env.MAILER_SECURE) || true,
|
|
|
|
authUser: env.MAILER_AUTH_USER || '',
|
|
|
|
authPassword: env.MAILER_AUTH_PASSWORD || '',
|
|
|
|
noReplyName: env.MAILER_NOREPLY_NAME || '',
|
|
|
|
noReplyEmail: env.MAILER_NOREPLY_EMAIL || '',
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-07-10 12:16:13 +02:00
|
|
|
function stripeConfigFromEnv(publicConfig: StripePublicConfig, env: EnvVariables): StripeConfig {
|
2021-06-03 15:21:02 +02:00
|
|
|
return {
|
2021-07-10 12:16:13 +02:00
|
|
|
...publicConfig,
|
2021-06-03 15:21:02 +02:00
|
|
|
secretKey: env.STRIPE_SECRET_KEY || '',
|
|
|
|
webhookSecret: env.STRIPE_WEBHOOK_SECRET || '',
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-01-18 12:13:26 +02:00
|
|
|
function baseUrlFromEnv(env: any, appPort: number): string {
|
|
|
|
if (env.APP_BASE_URL) {
|
|
|
|
return rtrimSlashes(env.APP_BASE_URL);
|
2020-12-28 13:48:47 +02:00
|
|
|
} else {
|
2021-01-18 12:13:26 +02:00
|
|
|
return `http://localhost:${appPort}`;
|
2020-12-28 13:48:47 +02:00
|
|
|
}
|
2021-01-18 12:13:26 +02:00
|
|
|
}
|
|
|
|
|
2021-05-26 15:53:27 +02:00
|
|
|
interface PackageJson {
|
|
|
|
version: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readPackageJson(filePath: string): Promise<PackageJson> {
|
|
|
|
const text = await readFile(filePath, 'utf8');
|
|
|
|
return JSON.parse(text);
|
|
|
|
}
|
|
|
|
|
2021-01-18 12:13:26 +02:00
|
|
|
let config_: Config = null;
|
|
|
|
|
2021-06-03 15:21:02 +02:00
|
|
|
export async function initConfig(envType: Env, env: EnvVariables, overrides: any = null) {
|
2021-01-18 12:13:26 +02:00
|
|
|
runningInDocker_ = !!env.RUNNING_IN_DOCKER;
|
2020-12-28 13:48:47 +02:00
|
|
|
|
2021-01-18 12:13:26 +02:00
|
|
|
const rootDir = pathUtils.dirname(__dirname);
|
2021-05-26 15:53:27 +02:00
|
|
|
|
|
|
|
const packageJson = await readPackageJson(`${rootDir}/package.json`);
|
2021-07-10 12:16:13 +02:00
|
|
|
const stripePublicConfigs = JSON.parse(await readFile(`${rootDir}/stripeConfig.json`, 'utf8'));
|
2021-07-22 18:32:10 +02:00
|
|
|
const stripePublicConfig = stripePublicConfigs[envType === Env.BuildTypes ? Env.Dev : envType];
|
2021-07-10 12:16:13 +02:00
|
|
|
if (!stripePublicConfig) throw new Error('Could not load Stripe config');
|
2021-05-26 15:53:27 +02:00
|
|
|
|
|
|
|
const viewDir = `${rootDir}/src/views`;
|
2021-01-18 12:13:26 +02:00
|
|
|
const appPort = env.APP_PORT ? Number(env.APP_PORT) : 22300;
|
2021-05-25 16:42:21 +02:00
|
|
|
const baseUrl = baseUrlFromEnv(env, appPort);
|
2021-07-16 17:56:21 +02:00
|
|
|
const supportEmail = env.SUPPORT_EMAIL || 'SUPPORT_EMAIL'; // Defaults to "SUPPORT_EMAIL" so that server admin knows they have to set it.
|
2021-01-18 12:13:26 +02:00
|
|
|
|
|
|
|
config_ = {
|
2021-05-26 15:53:27 +02:00
|
|
|
appVersion: packageJson.version,
|
2021-06-03 15:21:02 +02:00
|
|
|
appName: env.APP_NAME || 'Joplin Server',
|
2021-07-25 13:03:23 +02:00
|
|
|
isJoplinCloud: env.API_BASE_URL.includes('.joplincloud.com'),
|
2021-06-03 15:21:02 +02:00
|
|
|
env: envType,
|
2021-01-18 12:13:26 +02:00
|
|
|
rootDir: rootDir,
|
|
|
|
viewDir: viewDir,
|
|
|
|
layoutDir: `${viewDir}/layouts`,
|
2021-01-29 20:45:11 +02:00
|
|
|
tempDir: `${rootDir}/temp`,
|
2021-01-18 12:13:26 +02:00
|
|
|
logDir: `${rootDir}/logs`,
|
|
|
|
database: databaseConfigFromEnv(runningInDocker_, env),
|
2021-05-25 11:49:47 +02:00
|
|
|
mailer: mailerConfigFromEnv(env),
|
2021-07-10 12:16:13 +02:00
|
|
|
stripe: stripeConfigFromEnv(stripePublicConfig, env),
|
2021-01-18 12:13:26 +02:00
|
|
|
port: appPort,
|
2021-05-25 16:42:21 +02:00
|
|
|
baseUrl,
|
2021-06-08 12:08:40 +02:00
|
|
|
showErrorStackTraces: (env.ERROR_STACK_TRACES === undefined && envType === Env.Dev) || env.ERROR_STACK_TRACES === '1',
|
2021-05-25 16:42:21 +02:00
|
|
|
apiBaseUrl: env.API_BASE_URL ? env.API_BASE_URL : baseUrl,
|
|
|
|
userContentBaseUrl: env.USER_CONTENT_BASE_URL ? env.USER_CONTENT_BASE_URL : baseUrl,
|
2021-06-04 17:08:21 +02:00
|
|
|
signupEnabled: env.SIGNUP_ENABLED === '1',
|
2021-06-04 18:09:09 +02:00
|
|
|
termsEnabled: env.TERMS_ENABLED === '1',
|
2021-06-16 16:02:26 +02:00
|
|
|
accountTypesEnabled: env.ACCOUNT_TYPES_ENABLED === '1',
|
2021-07-11 12:35:49 +02:00
|
|
|
supportEmail,
|
|
|
|
businessEmail: env.BUSINESS_EMAIL || supportEmail,
|
2021-05-13 18:57:37 +02:00
|
|
|
...overrides,
|
2021-01-18 12:13:26 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-05-25 16:42:21 +02:00
|
|
|
export function baseUrl(type: RouteType): string {
|
|
|
|
if (type === RouteType.Web) return config().baseUrl;
|
|
|
|
if (type === RouteType.Api) return config().apiBaseUrl;
|
|
|
|
if (type === RouteType.UserContent) return config().userContentBaseUrl;
|
|
|
|
throw new Error(`Unknown type: ${type}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
// User content URL is not supported for now so only show the URL if the
|
|
|
|
// user content is hosted on the same domain. Needs to get cookie working
|
|
|
|
// across domains to get user content url working.
|
|
|
|
export function showItemUrls(config: Config): boolean {
|
|
|
|
return config.userContentBaseUrl === config.baseUrl;
|
|
|
|
}
|
|
|
|
|
2021-01-18 12:13:26 +02:00
|
|
|
function config(): Config {
|
|
|
|
if (!config_) throw new Error('Config has not been initialized!');
|
|
|
|
return config_;
|
2020-12-28 13:48:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export default config;
|