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) • 5.68 kB
JavaScript
import e from"../../../../lib/ioredis-cluster/index.mjs";import*as s from"../../shared.mjs";import n from"../../../../lib/redis-static-commands.mjs";import{buildCommandMeta as o}from"../../../../lib/redis-command-meta.mjs";const t="socket.io connection-connect",r=async e=>{const{socket:t,redis:r,payload:a}=e,{db:i}=a;let c,d=n;if(!0===e.payload.connection.cluster)c=1;else try{c=(await r.config("get","databases"))[1],console.info(e.payload.connection.name,"instance successfully works the database listing")}catch(s){console.warn(e.payload.connection.name,"instance get databases listing is disabled",s),c=await(async()=>{let e=!0,s=0,n=0;for(await new Promise(e=>setTimeout(e,1e3));e;)try{await r.call("select",s),s>512&&(console.warn("limiting to max 512 database index, as it could crash with a big db index number"),e=!1),s++}catch(n){console.error(n),console.warn("found wrong current db index",s),e=!1}if(n=s,i<=n)try{await r.call("select",i)}catch(e){console.error(e)}return console.log("calculated max databases index",n),n})()}console.info(e.payload.connection.name,"databases got",c);try{d=await r.command(),console.info(e.payload.connection.name,"instance command listing is available")}catch(s){console.warn(e.payload.connection.name,"instance command listing is not available, not all redis instances are not available command listing",s)}const l=await s.detectModules(r);l.length>0&&console.info(e.payload.connection.name,"modules detected:",l.map(e=>e.name).join(", ")),await s.getFullInfoAndSendSocket({setDb:!0,redis:r,responseEvent:e.responseEvent,socket:t,extend:{databases:c,commands:d,commandsMeta:o(d),modules:l},payload:a})};export default async n=>{const{socket:o,payload:a}=n,{connection:i,db:c}=a;try{if(o.p3xrs.connectionId!==i.id&&s.disconnectRedis({socket:o}),void 0!==o.p3xrs.ioredis&&"ready"!==o.p3xrs.ioredis.status&&(console.warn(t,"stale redis connection detected (status:",o.p3xrs.ioredis.status+"), cleaning up before reconnect"),s.disconnectRedis({socket:o})),p3xrs.redisConnections.hasOwnProperty(i.id)||(p3xrs.redisConnections[i.id]={connection:i,clients:[]}),p3xrs.redisConnections[i.id].clients.includes(o.id)||(console.info(t,"added new socket.id",o.id,"to",i.id,"name with",i.name),p3xrs.redisConnections[i.id].clients.push(o.id)),void 0!==o.p3xrs.ioredis)console.info(t,"redis was already connected"),o.p3xrs.connectionId=i.id,await r({redis:o.p3xrs.ioredis,socket:o,responseEvent:n.responseEvent,payload:a}),s.sendStatus({socket:o});else{const a=p3xrs.connections.list.find(e=>n.payload.connection.id===e.id);if(void 0===a)throw new Error("auto-connection-failed");i.askAuth&&(a.username=void 0,a.password=void 0,i.username&&(a.username=i.username),i.password&&(a.password=i.password));let c=Object.assign({},a);const d=c.sentinelName;delete c.name,delete c.id,c.retryStrategy=null,c.clusterRetryStrategy=null,c.tlsWithoutCert?c.tls={servername:c.host}:"string"==typeof c.tlsCa&&""!==c.tlsCa.trim()&&(c.tls={cert:c.tlsCrt,key:c.tlsKey,ca:c.tlsCa,servername:c.host}),c.hasOwnProperty("tls")&&(c.tls.rejectUnauthorized=void 0!==c.tlsRejectUnauthorized&&c.tlsRejectUnauthorized,c.tls.hasOwnProperty("servername")||(c.tls.servername=c.host));const l=()=>{s.disconnectRedis({socket:o}),o.p3xrs.connectionId=void 0,o.p3xrs.ioredis=void 0,o.p3xrs.ioredisSubscriber=void 0};let p=a.nodes||[];if(!0===c.ssh){const{createTunnel:e}=await import("tunnel-ssh"),s=await import("net"),t={host:c.sshHost,port:c.sshPort,username:c.sshUsername};c.sshPrivateKey?t.privateKey=c.sshPrivateKey:t.password=c.sshPassword;const r=[];let[a,i]=await e({autoClose:!0},null,t,{dstAddr:c.host,dstPort:c.port});if(r.push(a),c.port=a.address().port,p.length>0){p=p.map(e=>Object.assign({},e));for(const e of p){const n=await new Promise((n,o)=>{const t=s.createServer(s=>{i.forwardOut("127.0.0.1",0,e.host||"localhost",e.port,(e,n)=>{e?s.end():s.pipe(n).pipe(s)})});t.listen(0,"127.0.0.1",()=>n(t)),t.on("error",o)});r.push(n),e.port=n.address().port}}o.p3xrs.tunnels=r,o.p3xrs.sshClient=i,i.on("error",async e=>{console.error("ssh client error",e),l(),o.emit(n.responseEvent,{status:"error",error:e.message})});for(const e of r)e.on("error",async e=>{console.error("ssh tunnel server error",e),l(),o.emit(n.responseEvent,{status:"error",error:e.message})})}(c.hasOwnProperty("sentinel")&&!0===c.sentinel||!0===c.cluster)&&(c=[c].concat(p)),Array.isArray(c)&&c[0].hasOwnProperty("sentinel")&&!0===c[0].sentinel&&(c={sentinels:c,name:d,sentinelPassword:c[0].password,sentinelRetryStrategy:()=>!1});let m=new e(c),u=new e(c);o.p3xrs.connectionId=i.id,o.p3xrs.readonly=!0===a.readonly,o.p3xrs.ioredis=m,o.p3xrs.ioredisSubscriber=u;let y=!1;const w=async function(e){e||((e=new Error("Connection is closed.")).p3xCode="disconnect");const t="socket.io connection-connect redis error fun";console.warn(t,i.id,i.name,"error"),console.error(e),console.warn(t,"didConnected",y),y||o.emit(n.responseEvent,{status:"error",error:e.message});const r={connectionId:o.p3xrs.connectionId,error:e.message,status:"error"};console.warn(t,"disconnectedData",r),o.p3xrs.io.emit("redis-disconnected",r);try{await s.disconnectRedis({socket:o})}catch(e){console.warn(t,"disconnectRedis"),console.error(e)}l(),s.sendStatus({socket:o})};m.on("error",w),m.on("disconnect",w),u.on("error",w),m.on("connect",async function(){try{console.info(t,n.payload.connection.id,n.payload.connection.name,"connected"),y=!0,await r({redis:m,socket:o,responseEvent:n.responseEvent,payload:n.payload})}catch(e){console.error(e),o.emit(n.responseEvent,{status:"error",error:e.message})}finally{s.sendStatus({socket:o})}})}}catch(e){console.error(e),o.emit(n.responseEvent,{status:"error",error:e.message})}};