228 lines
6.6 KiB
JavaScript
228 lines
6.6 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
const mysql = require('mysql2/promise');
|
|
const dotenv = require('dotenv');
|
|
|
|
dotenv.config();
|
|
dotenv.config({ path: path.resolve(__dirname, '../../.env') });
|
|
dotenv.config({ path: path.resolve(__dirname, '../.env') });
|
|
|
|
const DEFAULT_SYSTEM_DB_CONFIG = {
|
|
driver: 'mysql',
|
|
host: '',
|
|
port: 3306,
|
|
database: '',
|
|
username: '',
|
|
hasPassword: false,
|
|
};
|
|
|
|
const ENV_MAPPING = {
|
|
driver: 'LOCAL_DB_TYPE',
|
|
host: 'LOCAL_DB_HOST',
|
|
port: 'LOCAL_DB_PORT',
|
|
database: 'LOCAL_DB_NAME',
|
|
username: 'LOCAL_DB_USER',
|
|
password: 'LOCAL_DB_PASSWORD',
|
|
};
|
|
|
|
function getEnvFilePath() {
|
|
return path.resolve(process.cwd(), '.env');
|
|
}
|
|
|
|
function getStoredConfigFilePath() {
|
|
return path.resolve(process.cwd(), 'database', 'system-db.config.json');
|
|
}
|
|
|
|
function serializeEnvValue(value) {
|
|
const stringValue = String(value ?? '');
|
|
if (!stringValue) {
|
|
return '';
|
|
}
|
|
|
|
if (/[\s#"']/u.test(stringValue)) {
|
|
return JSON.stringify(stringValue);
|
|
}
|
|
|
|
return stringValue;
|
|
}
|
|
|
|
function parseConfigFromEnv(source) {
|
|
return {
|
|
driver: source[ENV_MAPPING.driver] || DEFAULT_SYSTEM_DB_CONFIG.driver,
|
|
host: source[ENV_MAPPING.host] || DEFAULT_SYSTEM_DB_CONFIG.host,
|
|
port: Number(source[ENV_MAPPING.port] || DEFAULT_SYSTEM_DB_CONFIG.port),
|
|
database: source[ENV_MAPPING.database] || DEFAULT_SYSTEM_DB_CONFIG.database,
|
|
username: source[ENV_MAPPING.username] || DEFAULT_SYSTEM_DB_CONFIG.username,
|
|
hasPassword: Boolean(source[ENV_MAPPING.password]),
|
|
};
|
|
}
|
|
|
|
function parseRuntimeConfig(source) {
|
|
return {
|
|
driver: source[ENV_MAPPING.driver] || DEFAULT_SYSTEM_DB_CONFIG.driver,
|
|
host: source[ENV_MAPPING.host] || DEFAULT_SYSTEM_DB_CONFIG.host,
|
|
port: Number(source[ENV_MAPPING.port] || DEFAULT_SYSTEM_DB_CONFIG.port),
|
|
database: source[ENV_MAPPING.database] || DEFAULT_SYSTEM_DB_CONFIG.database,
|
|
username: source[ENV_MAPPING.username] || DEFAULT_SYSTEM_DB_CONFIG.username,
|
|
password: source[ENV_MAPPING.password] || '',
|
|
};
|
|
}
|
|
|
|
function hasCompleteConfig(config) {
|
|
return Boolean(
|
|
config
|
|
&& String(config.host || '').trim()
|
|
&& String(config.database || '').trim()
|
|
&& String(config.username || '').trim()
|
|
);
|
|
}
|
|
|
|
function readStoredConfigFile() {
|
|
const filePath = getStoredConfigFilePath();
|
|
if (!fs.existsSync(filePath)) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
const raw = fs.readFileSync(filePath, 'utf8');
|
|
const parsed = JSON.parse(raw);
|
|
return {
|
|
driver: parsed.driver || DEFAULT_SYSTEM_DB_CONFIG.driver,
|
|
host: parsed.host || '',
|
|
port: Number(parsed.port || DEFAULT_SYSTEM_DB_CONFIG.port),
|
|
database: parsed.database || '',
|
|
username: parsed.username || '',
|
|
password: parsed.password || '',
|
|
};
|
|
} catch (_error) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function writeStoredConfigFile(input) {
|
|
const filePath = getStoredConfigFilePath();
|
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
fs.writeFileSync(filePath, JSON.stringify({
|
|
driver: input.driver || DEFAULT_SYSTEM_DB_CONFIG.driver,
|
|
host: input.host || '',
|
|
port: Number(input.port || DEFAULT_SYSTEM_DB_CONFIG.port),
|
|
database: input.database || '',
|
|
username: input.username || '',
|
|
password: input.password || '',
|
|
}, null, 2), 'utf8');
|
|
}
|
|
|
|
function getSystemDbRuntimeConfig() {
|
|
const envConfig = parseRuntimeConfig(process.env);
|
|
if (hasCompleteConfig(envConfig)) {
|
|
return envConfig;
|
|
}
|
|
|
|
const storedConfig = readStoredConfigFile();
|
|
if (hasCompleteConfig(storedConfig || {})) {
|
|
return storedConfig;
|
|
}
|
|
|
|
return envConfig;
|
|
}
|
|
|
|
function getSystemDbConfig() {
|
|
const runtimeConfig = getSystemDbRuntimeConfig();
|
|
return {
|
|
driver: runtimeConfig.driver || DEFAULT_SYSTEM_DB_CONFIG.driver,
|
|
host: runtimeConfig.host || DEFAULT_SYSTEM_DB_CONFIG.host,
|
|
port: Number(runtimeConfig.port || DEFAULT_SYSTEM_DB_CONFIG.port),
|
|
database: runtimeConfig.database || DEFAULT_SYSTEM_DB_CONFIG.database,
|
|
username: runtimeConfig.username || DEFAULT_SYSTEM_DB_CONFIG.username,
|
|
hasPassword: Boolean(runtimeConfig.password),
|
|
};
|
|
}
|
|
|
|
async function testSystemDbConnection(input) {
|
|
const connection = await mysql.createConnection({
|
|
host: input.host,
|
|
port: Number(input.port || 3306),
|
|
user: input.username,
|
|
password: input.password,
|
|
database: input.database,
|
|
charset: 'utf8mb4',
|
|
connectTimeout: 10000,
|
|
});
|
|
|
|
await connection.ping();
|
|
await connection.end();
|
|
}
|
|
|
|
async function saveSystemDbConfig(input) {
|
|
const envFilePath = getEnvFilePath();
|
|
const content = fs.existsSync(envFilePath) ? fs.readFileSync(envFilePath, 'utf8') : '';
|
|
const parsedEnv = dotenv.parse(content);
|
|
const nextEnv = {
|
|
...parsedEnv,
|
|
[ENV_MAPPING.driver]: input.driver || DEFAULT_SYSTEM_DB_CONFIG.driver,
|
|
[ENV_MAPPING.host]: input.host || '',
|
|
[ENV_MAPPING.port]: String(input.port || 3306),
|
|
[ENV_MAPPING.database]: input.database || '',
|
|
[ENV_MAPPING.username]: input.username || '',
|
|
};
|
|
|
|
if (input.password) {
|
|
nextEnv[ENV_MAPPING.password] = input.password;
|
|
} else if (!nextEnv[ENV_MAPPING.password]) {
|
|
nextEnv[ENV_MAPPING.password] = '';
|
|
}
|
|
|
|
const lines = content ? content.split(/\r?\n/) : [];
|
|
const handledKeys = new Set();
|
|
const nextLines = lines.map((line) => {
|
|
const match = line.match(/^([A-Z0-9_]+)=(.*)$/);
|
|
if (!match) {
|
|
return line;
|
|
}
|
|
|
|
const [, key] = match;
|
|
if (!Object.values(ENV_MAPPING).includes(key)) {
|
|
return line;
|
|
}
|
|
|
|
handledKeys.add(key);
|
|
return `${key}=${serializeEnvValue(nextEnv[key])}`;
|
|
});
|
|
|
|
for (const key of Object.values(ENV_MAPPING)) {
|
|
if (!handledKeys.has(key)) {
|
|
nextLines.push(`${key}=${serializeEnvValue(nextEnv[key])}`);
|
|
}
|
|
}
|
|
|
|
const nextContent = `${nextLines.filter((line, index, array) => !(line === '' && index === array.length - 1)).join('\n')}\n`;
|
|
fs.writeFileSync(envFilePath, nextContent, 'utf8');
|
|
|
|
process.env[ENV_MAPPING.driver] = nextEnv[ENV_MAPPING.driver];
|
|
process.env[ENV_MAPPING.host] = nextEnv[ENV_MAPPING.host];
|
|
process.env[ENV_MAPPING.port] = nextEnv[ENV_MAPPING.port];
|
|
process.env[ENV_MAPPING.database] = nextEnv[ENV_MAPPING.database];
|
|
process.env[ENV_MAPPING.username] = nextEnv[ENV_MAPPING.username];
|
|
if (input.password) {
|
|
process.env[ENV_MAPPING.password] = input.password;
|
|
}
|
|
|
|
writeStoredConfigFile({
|
|
driver: nextEnv[ENV_MAPPING.driver],
|
|
host: nextEnv[ENV_MAPPING.host],
|
|
port: nextEnv[ENV_MAPPING.port],
|
|
database: nextEnv[ENV_MAPPING.database],
|
|
username: nextEnv[ENV_MAPPING.username],
|
|
password: input.password || nextEnv[ENV_MAPPING.password] || '',
|
|
});
|
|
|
|
return getSystemDbConfig();
|
|
}
|
|
|
|
module.exports = {
|
|
getSystemDbConfig,
|
|
getSystemDbRuntimeConfig,
|
|
saveSystemDbConfig,
|
|
testSystemDbConnection,
|
|
};
|