p3x-redis-ui-server
Version:
🏍️ P3X Redis UI server — Socket.IO backend for the dual Angular + React frontend with AI queries, 54 languages, and auto data decompression
2 lines (1 loc) • 7.17 kB
JavaScript
import e from"path";import s from"fs";import t from"os";import{program as o}from"commander";import{parseBoolean as r,readPasswordHashFromFile as n}from"./http-auth.mjs";const i=e=>Boolean(e)&&"object"==typeof e&&!Array.isArray(e),p=(e,s)=>{const t=i(e)?{...e}:{};if(!i(s))return t;for(const[e,o]of Object.entries(s))Array.isArray(o)?t[e]=o.slice():i(o)?t[e]=p(i(t[e])?t[e]:{},o):t[e]=o;return t},c=e=>{if(e&&s.existsSync(e))try{const t=s.readFileSync(e,"utf8");return JSON.parse(t)}catch(s){return void console.warn(`Could not read config ${e}:`,s.message)}};export default async()=>{const a=JSON.parse(s.readFileSync(new URL("../../package.json",import.meta.url),"utf8"));p3xrs.version=a.version,o.version(a.version).option("-c, --config [config]","Set the p3xr.json p3x-redis-ui-server configuration, see more help in p3x-redis-ui-server").option("-r, --readonly-connections","Set the connections to be readonly, no adding, saving or delete a connection").option("-n, --connections-file-name [filename]","Set the connections file name, overrides default .p3xrs-conns.json").option("--http-auth-enable","Enable HTTP Basic auth").option("--http-auth-disable","Disable HTTP Basic auth").option("--http-auth-username [username]","HTTP Basic auth username").option("--http-auth-password [password]","HTTP Basic auth plain password").option("--http-auth-password-hash [hash]","HTTP Basic auth bcrypt password hash").option("--http-auth-password-hash-file [file]","Read HTTP Basic auth bcrypt password hash from file").option("--groq-api-key [key]","Groq API key for AI-powered Redis query translation (get a free key at console.groq.com)").option("--groq-api-key-readonly","Prevent users from changing the Groq API key via the UI").parse(process.argv);const h=o.opts();if(process.versions.hasOwnProperty("electron")||process.env.hasOwnProperty("P3XRS_DOCKER_HOME")){const s={http:{"port-info":"this is ommitted, it will be default 7843",port:process.env.hasOwnProperty("P3XRS_DOCKER_HOME")?7843:global.p3xrsElectronPort,"bind-info":"the interface with listen to, could be 127.0.0.1 or 0.0.0.0 or specific interface",bind:"0.0.0.0"},connections:{"home-dir-info":"if the dir config is empty or home, the connections are saved in the home folder, otherwise it will resolve the directory set as it is, either relative ./ or absolute starting with /. NodeJs will resolve this directory in p3xrs.connections.dir","home-dir":"home"},"static-info":"This is the best configuration, if it starts with ~, then it is in resolve the path in the node_modules, otherwise it resolves to the current process current working directory.",static:"~p3x-redis-ui-material/dist",httpAuth:{enabled:!1,username:"admin",password:"",passwordHash:""},treeDividers:[":","/","|","-","@"]};let o="";try{const e=await import("electron"),s=e.default?.app||e.app;s&&"function"==typeof s.getPath&&(o=s.getPath("userData"))}catch(e){o=""}const r=("string"==typeof process.env.P3XRS_ELECTRON_CONFIG_DIR?process.env.P3XRS_ELECTRON_CONFIG_DIR.trim():"")||o||t.homedir();p3xrs.configPath=e.resolve(r,"p3xrs.json");let n=c(p3xrs.configPath);if(!n||!i(n.p3xrs)){const s=e.resolve(process.cwd(),"p3xrs.json"),t=c(s);t&&i(t.p3xrs)&&(n=t)}const a=n&&i(n.p3xrs)?n.p3xrs:{};p3xrs.cfg=p(s,a),h.readonlyConnections?p3xrs.cfg.readonlyConnections=!0:p3xrs.cfg.readonlyConnections=!1,"string"==typeof h.groqApiKey&&h.groqApiKey.trim()&&(p3xrs.cfg.groqApiKey=h.groqApiKey.trim()),h.groqApiKeyReadonly&&(p3xrs.cfg.groqApiKeyReadonly=!0)}else{if(!h.config){const t=(t,o)=>{let r=t;for(;r!==e.resolve(r,"..");){const t=e.join(r,o);if(s.existsSync(t))return t;r=e.resolve(r,"..")}throw new Error("The specified configuration file could not be found.")},o=()=>{const e=process.cwd();return t(e,"p3xrs.json")};h.config=o()}const t=e.resolve(process.cwd(),h.config);p3xrs.configPath=t,p3xrs.cfg=JSON.parse(s.readFileSync(t,"utf8")).p3xrs,h.readonlyConnections&&(p3xrs.cfg.readonlyConnections=!0),"string"==typeof h.groqApiKey&&h.groqApiKey.trim()&&(p3xrs.cfg.groqApiKey=h.groqApiKey.trim()),h.groqApiKeyReadonly&&(p3xrs.cfg.groqApiKeyReadonly=!0),void 0!==h.connectionsFileName&&h.connectionsFileName&&(p3xrs.cfg.connectionsFileName=h.connectionsFileName)}(()=>{p3xrs.cfg.httpAuth&&"object"==typeof p3xrs.cfg.httpAuth||(p3xrs.cfg.server&&"object"==typeof p3xrs.cfg.server.httpAuth?p3xrs.cfg.httpAuth=Object.assign({},p3xrs.cfg.server.httpAuth):p3xrs.cfg.httpAuth={});const e=p3xrs.cfg.httpAuth;if("string"!=typeof p3xrs.cfg.httpUser||e.username||(e.username=p3xrs.cfg.httpUser),"string"!=typeof p3xrs.cfg.httpPassword||e.password||(e.password=p3xrs.cfg.httpPassword),"string"==typeof process.env.HTTP_USER&&""!==process.env.HTTP_USER.trim()&&(e.username=process.env.HTTP_USER.trim()),"string"==typeof process.env.HTTP_PASSWORD&&(e.password=process.env.HTTP_PASSWORD),"string"==typeof process.env.HTTP_PASSWORD_HASH&&""!==process.env.HTTP_PASSWORD_HASH.trim()&&(e.passwordHash=process.env.HTTP_PASSWORD_HASH.trim()),"string"==typeof process.env.HTTP_PASSWORD_HASH_FILE&&""!==process.env.HTTP_PASSWORD_HASH_FILE.trim()){const s=n(process.env.HTTP_PASSWORD_HASH_FILE);s&&(e.passwordHash=s)}const s=r(process.env.HTTP_AUTH_ENABLED);if(void 0!==s&&(e.enabled=s),"string"==typeof h.httpAuthUsername&&""!==h.httpAuthUsername.trim()&&(e.username=h.httpAuthUsername.trim()),"string"==typeof h.httpAuthPassword&&(e.password=h.httpAuthPassword),"string"==typeof h.httpAuthPasswordHash&&""!==h.httpAuthPasswordHash.trim()&&(e.passwordHash=h.httpAuthPasswordHash.trim()),"string"==typeof h.httpAuthPasswordHashFile&&""!==h.httpAuthPasswordHashFile.trim()){const s=n(h.httpAuthPasswordHashFile);s&&(e.passwordHash=s)}!0===h.httpAuthEnable&&(e.enabled=!0),!0===h.httpAuthDisable&&(e.enabled=!1)})();const f=p3xrs.cfg&&p3xrs.cfg.httpAuth&&"object"==typeof p3xrs.cfg.httpAuth?p3xrs.cfg.httpAuth:{},d=!0===r(f.enabled),g="string"==typeof f.passwordHash&&f.passwordHash.trim().length>0,l="string"==typeof f.password&&f.password.length>0;return console.info(`http auth: ${d?"enabled":"disabled"} (user=${f.username||"admin"}, hash=${g?"set":"empty"}, plain=${l?"set":"empty"})`),void 0===p3xrs.cfg.connectionsFileName&&(p3xrs.cfg.connectionsFileName=".p3xrs-conns.json"),p3xrs.cfg.hasOwnProperty("static")||(p3xrs.cfg.static="~p3x-redis-ui-material/dist"),p3xrs.cfg.hasOwnProperty("connections")||(p3xrs.cfg.connections={}),p3xrs.cfg.connections.hasOwnProperty("home-dir")||(p3xrs.cfg.connections="home"),"home"===p3xrs.cfg.connections["home-dir"]&&(p3xrs.cfg.connections["home-dir"]=t.homedir()),process.env.hasOwnProperty("P3XRS_DOCKER_HOME")&&(p3xrs.cfg.connections["home-dir"]=process.env.P3XRS_DOCKER_HOME),process.env.FLATPAK_ID&&(p3xrs.cfg.connections["home-dir"]="/var/data/"),process.env.hasOwnProperty("P3XRS_PORT")&&(p3xrs.cfg.http.port=process.env.P3XRS_PORT),p3xrs.cfg.connections.home=e.resolve(p3xrs.cfg.connections["home-dir"],p3xrs.cfg.connectionsFileName),console.info("using home config is",p3xrs.cfg.connections.home),s.existsSync(p3xrs.cfg.connections.home)||s.writeFileSync(p3xrs.cfg.connections.home,JSON.stringify({update:new Date,list:[]},null,4)),p3xrs.connections=JSON.parse(s.readFileSync(p3xrs.cfg.connections.home,"utf8")),!0};