mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-21 21:50:49 +02:00

* refactor(Ask/Edit): consolidate ask/edit controllers between the main modules and openAI controllers to reduce repetition of code and increase reusability * fix(winston/logger): circular dependency issue * fix(config/scripts): fix script imports * refactor(indexSync): make not configured message an info log message * chore: create a rollup script for api/server/index.js to check circular dependencies * chore: bump @keyv/redis
163 lines
5.4 KiB
JavaScript
163 lines
5.4 KiB
JavaScript
/**
|
|
* Upgrade script
|
|
*/
|
|
const fs = require('fs');
|
|
const dotenv = require('dotenv');
|
|
const { exit } = require('process');
|
|
|
|
// Suppress default warnings
|
|
const originalConsoleWarn = console.warn;
|
|
console.warn = () => {};
|
|
const loader = require('./loader');
|
|
console.warn = originalConsoleWarn;
|
|
|
|
// Old Paths
|
|
const apiEnvPath = loader.resolve('api/.env');
|
|
const clientEnvPath = loader.resolve('client/.env');
|
|
|
|
// Load into env
|
|
dotenv.config({
|
|
path: loader.resolve(apiEnvPath),
|
|
});
|
|
dotenv.config({
|
|
path: loader.resolve(clientEnvPath),
|
|
});
|
|
// JS was doing spooky actions at a distance, lets prevent that
|
|
const initEnv = JSON.parse(JSON.stringify(process.env));
|
|
|
|
// New Paths
|
|
const rootEnvPath = loader.resolve('.env');
|
|
const devEnvPath = loader.resolve('.env.development');
|
|
const prodEnvPath = loader.resolve('.env.production');
|
|
|
|
if (fs.existsSync(rootEnvPath)) {
|
|
console.error('Root env file already exists! Aborting');
|
|
exit(1);
|
|
}
|
|
|
|
// Validate old configs
|
|
if (!fs.existsSync(apiEnvPath)) {
|
|
console.error('Api env doesn\'t exit! Did you mean to run install?');
|
|
exit(1);
|
|
}
|
|
if (!fs.existsSync(clientEnvPath)) {
|
|
console.error('Client env doesn\'t exit! But api/.env does. Manual upgrade required');
|
|
exit(1);
|
|
}
|
|
|
|
/**
|
|
* Refactor the ENV if it has a prod_/dev_ version
|
|
*
|
|
* @param {*} varDev
|
|
* @param {*} varProd
|
|
* @param {*} varName
|
|
*/
|
|
function refactorPairedEnvVar(varDev, varProd, varName) {
|
|
// Lets validate if either of these are undefined, if so lets use the non-undefined one
|
|
if (initEnv[varDev] === undefined && initEnv[varProd] === undefined) {
|
|
console.error(`Both ${varDev} and ${varProd} are undefined! Manual intervention required!`);
|
|
} else if (initEnv[varDev] === undefined) {
|
|
fs.appendFileSync(rootEnvPath, `\n${varName}=${initEnv[varProd]}`);
|
|
} else if (initEnv[varProd] === undefined) {
|
|
fs.appendFileSync(rootEnvPath, `\n${varName}=${initEnv[varDev]}`);
|
|
} else if (initEnv[varDev] === initEnv[varProd]) {
|
|
fs.appendFileSync(rootEnvPath, `\n${varName}=${initEnv[varDev]}`);
|
|
} else {
|
|
fs.appendFileSync(rootEnvPath, `${varName}=${initEnv[varProd]}\n`);
|
|
fs.appendFileSync(devEnvPath, `${varName}=${initEnv[varDev]}\n`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Upgrade the env files!
|
|
* 1. /api/.env will merge into /.env
|
|
* 2. /client/.env will merge into /.env
|
|
* 3. Any prod_/dev_ keys will be split up into .env.development / .env.production files (if they are different)
|
|
*/
|
|
if (fs.existsSync(apiEnvPath)) {
|
|
fs.copyFileSync(apiEnvPath, rootEnvPath);
|
|
fs.copyFileSync(apiEnvPath, rootEnvPath + '.api.bak');
|
|
fs.unlinkSync(apiEnvPath);
|
|
}
|
|
|
|
// Clean up Domain variables
|
|
fs.appendFileSync(
|
|
rootEnvPath,
|
|
'\n\n##########################\n# Domain Variables:\n# Note: DOMAIN_ vars are passed to vite\n##########################\n',
|
|
);
|
|
refactorPairedEnvVar('CLIENT_URL_DEV', 'CLIENT_URL_PROD', 'DOMAIN_CLIENT');
|
|
refactorPairedEnvVar('SERVER_URL_DEV', 'SERVER_URL_PROD', 'DOMAIN_SERVER');
|
|
|
|
// Remove the old vars
|
|
const removeEnvs = {
|
|
NODE_ENV: 'remove',
|
|
OPENAI_KEY: 'remove',
|
|
CLIENT_URL_DEV: 'remove',
|
|
CLIENT_URL_PROD: 'remove',
|
|
SERVER_URL_DEV: 'remove',
|
|
SERVER_URL_PROD: 'remove',
|
|
JWT_SECRET_DEV: 'remove', // Lets regen
|
|
JWT_SECRET_PROD: 'remove', // Lets regen
|
|
VITE_APP_TITLE: 'remove',
|
|
// Comments to remove:
|
|
'#JWT:': 'remove',
|
|
'# Add a secure secret for production if deploying to live domain.': 'remove',
|
|
'# Site URLs:': 'remove',
|
|
'# Don\'t forget to set Node env to development in the Server configuration section above':
|
|
'remove',
|
|
'# if you want to run in dev mode': 'remove',
|
|
'# Change these values to domain if deploying:': 'remove',
|
|
'# Set Node env to development if running in dev mode.': 'remove',
|
|
};
|
|
loader.writeEnvFile(rootEnvPath, removeEnvs);
|
|
|
|
/**
|
|
* Lets make things more secure!
|
|
* 1. Add CREDS_KEY
|
|
* 2. Add CREDS_IV
|
|
* 3. Add JWT_SECRET
|
|
*/
|
|
fs.appendFileSync(
|
|
rootEnvPath,
|
|
'\n\n##########################\n# Secure Keys:\n##########################\n',
|
|
);
|
|
loader.addSecureEnvVar(rootEnvPath, 'CREDS_KEY', 32);
|
|
loader.addSecureEnvVar(rootEnvPath, 'CREDS_IV', 16);
|
|
loader.addSecureEnvVar(rootEnvPath, 'JWT_SECRET', 32);
|
|
|
|
// Lets update the openai key name, not the best spot in the env file but who cares ¯\_(ツ)_/¯
|
|
loader.writeEnvFile(rootEnvPath, { OPENAI_API_KEY: initEnv['OPENAI_KEY'] });
|
|
|
|
// TODO: we need to copy over the value of: APP_TITLE
|
|
fs.appendFileSync(
|
|
rootEnvPath,
|
|
'\n\n##########################\n# Frontend Vite Variables:\n##########################\n',
|
|
);
|
|
const frontend = {
|
|
APP_TITLE: initEnv['VITE_APP_TITLE'] || '"LibreChat"',
|
|
ALLOW_REGISTRATION: 'true',
|
|
};
|
|
loader.writeEnvFile(rootEnvPath, frontend);
|
|
|
|
// Ensure .env.development and .env.production files end with a newline
|
|
if (fs.existsSync(devEnvPath)) {
|
|
fs.appendFileSync(devEnvPath, '\n');
|
|
}
|
|
if (fs.existsSync(prodEnvPath)) {
|
|
fs.appendFileSync(prodEnvPath, '\n');
|
|
}
|
|
// Remove client file
|
|
fs.copyFileSync(clientEnvPath, rootEnvPath + '.client.bak');
|
|
fs.unlinkSync(clientEnvPath);
|
|
|
|
console.log('###############################################');
|
|
console.log('Upgrade completed! Please review the new .env file and make any changes as needed.');
|
|
console.log('###############################################');
|
|
|
|
// if the .env.development file exists, lets tell the user
|
|
if (fs.existsSync(devEnvPath)) {
|
|
console.log(
|
|
'NOTE: A .env.development file was created. This will take precedence over the .env file when running in dev mode.',
|
|
);
|
|
console.log('###############################################');
|
|
}
|