@dataramen/cli 0.0.76 → 0.0.77-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/code/server.js +1 -1
- package/dist/code/web/assets/{index-S0ueSkRi.js → index-B0tXrAXl.js} +10 -10
- package/dist/code/web/assets/index-C4WprvjC.css +1 -0
- package/dist/code/web/assets/{main-DKrfRG9h.js → main-DG-Mm6ns.js} +3 -3
- package/dist/code/web/assets/main-DgXVgGCC.css +1 -0
- package/dist/code/web/assets/{setup-BUBw3xVi.js → setup-vNeTTZW6.js} +1 -1
- package/dist/code/web/index.html +4 -4
- package/dist/code/web/setup.html +3 -3
- package/dist/package.json +1 -1
- package/package.json +1 -1
- package/dist/code/web/assets/index-CkKvF1pw.css +0 -1
- package/dist/code/web/assets/main-BjjR8SfP.css +0 -1
package/dist/code/server.js
CHANGED
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
left join pg_class on pg_attribute.attrelid = pg_class.oid
|
|
55
55
|
where
|
|
56
56
|
concat(pg_class.oid, '-', attnum) IN (${e.join(", ")})
|
|
57
|
-
limit 75;`;return(await t.query(r)).rows.reduce((a,n)=>(a[n.row_key]={table:n.relname,column:n.attname},a),{})},It=async(e,t,r,o)=>{try{console.log(`[PG CONN] Query: ${e}`),console.log(`[PG CONN] Params: ${JSON.stringify(t,null,2)}`);let{rows:a,fields:n,command:u,rowCount:s}=await r.query({text:e,rowMode:"array",values:t});if(u==="UPDATE"||u==="INSERT"||u==="DELETE"){if(s!=null&&s>1&&o.allowBulkUpdate!==!0)throw new Error("[PG CONN] Bulk update performed without permission.");return{columns:[{column:"affectedRows",alias:"Affected rows",full:"affectedRows"}],rows:[[s]],query:e}}if(u==="SELECT"){let m=n.map(l=>`'${l.tableID}-${l.columnID}'`),c=await vo(m,r);return{columns:n.map(l=>{let p=c[`${l.tableID}-${l.columnID}`];return{column:p?.column||l.name,alias:l.name,table:p?.table||"",full:p?p.table+"."+p.column:l.name}}),rows:a,query:e}}throw new Error(`[PG CONN] Unsupported command: ${u}`)}catch(a){throw a instanceof i?a:new i(400,a.message)}},_o=async(e,t)=>{await e.query("BEGIN");try{let r=await t();return await e.query("COMMIT"),console.log("[PG CONN] Commit"),r}catch(r){throw await e.query("ROLLBACK"),console.log("[PG CONN] Rollback"),r}},Uo=async(e,t)=>{await e.query("BEGIN READ ONLY");try{let r=await t();return console.log("[PG CONN] Read only rollback"),await e.query("ROLLBACK"),r}catch(r){throw console.log("[PG CONN] Rollback"),await e.query("ROLLBACK"),r}},xe=async e=>{let t=await Po(e),r=!1,o=!1,a=async n=>(o||await t.query(`SET search_path TO ${e.schema}`),n());return{dbType:"postgres",dataSource:e,inspectSchema:()=>xo(e,t),executeQuery:n=>a(()=>n.type==="SELECT"?Uo(t,()=>It(n.sql,n.params,t,n)):_o(t,()=>It(n.sql,n.params,t,n))),checkConnection:async()=>{},isClosed:()=>r,close:async()=>{if(!r)return r=!0,t.end()}}};var $=async(e,t,r)=>{try{let o;if(t==="mysql")o=await De(e);else if(t==="postgres")o=await xe(e);else throw new i(500,`Connection manager for ${t} not found`);return r.__connections?r.__connections.push(o):r.__connections=[o],o}catch(o){throw console.error(o),o instanceof i?o:o?.code==="ECONNREFUSED"?new i(500,"Failed to connect to the database"):new i(500,o.message)}},Rt=async(e,t)=>{try{let r;if(t==="mysql")r=await De(e);else if(t==="postgres")r=await xe(e);else throw new i(500,`Connection manager for ${t} not found`);return r}catch(r){throw console.error(r),r instanceof i?r:r?.code==="ECONNREFUSED"?new i(500,"Failed to connect to the database"):new i(500,r.message)}};var ce=O(require("node:crypto"));var Nt="aes-256-gcm",Lo=12,At=()=>{let e=T.str("SYMM_ENCRYPTION_KEY");if(!e)throw new Error("Missing ENCRYPTION_KEY in environment variables.");let t=Buffer.from(e,"hex");if(t.length!==32)throw new Error("ENCRYPTION_KEY must be a 64-character hex string (256 bits).");return t},ko=e=>{let t=ce.default.randomBytes(Lo),r=At(),o=ce.default.createCipheriv(Nt,r,t),a=o.update(e,"utf8","hex");a+=o.final("hex");let n=o.getAuthTag();return{encrypted:a,iv:t.toString("hex"),tag:n.toString("hex")}},qo=({encrypted:e,iv:t,tag:r})=>{let o=At(),a=ce.default.createDecipheriv(Nt,o,Buffer.from(t,"hex"));a.setAuthTag(Buffer.from(r,"hex"));let n=a.update(e,"hex","utf8");return n+=a.final("utf8"),n},me={encrypt:ko,decrypt:qo};var U=(e,t=!1)=>{if(t){let r=me.decrypt({encrypted:e.dbPassword,tag:e.dbPasswordTag,iv:e.dbPasswordIv});return{url:e.dbUrl,user:e.dbUser,database:e.dbDatabase,password:r,port:e.dbPort,schema:e.dbSchema}}return{url:e.dbUrl,user:e.dbUser,database:e.dbDatabase,password:e.dbPassword,port:e.dbPort,schema:e.dbSchema}};var Pt=[{value:"=",label:"equals"},{value:"<>",label:"not equal"},{value:">",label:"greater than"},{value:">=",label:"greater than or equal"},{value:"<",label:"less than"},{value:"<=",label:"less than or equal"},{value:"LIKE",label:"like"},{value:"NOT LIKE",label:"not like"},{value:"CONTAINS",label:"contains"},{value:"NOT CONTAINS",label:"not contains"},{value:"IN",label:"in list"},{value:"NOT IN",label:"not in list"},{value:"IS NULL",label:"is null"},{value:"IS NOT NULL",label:"is not null"}],Bo=Pt.reduce((e,t)=>(e[t.value]=t.label,e),{}),Ts=Pt.reduce((e,t)=>(e[t.label]=t.value,e),{}),Y=e=>e.map(t=>({label:Bo[t],value:t})),gs=Y(["=","<>",">",">=","<","<=","IN","NOT IN","IS NULL","IS NOT NULL"]),hs=Y(["=","<>","LIKE","NOT LIKE","IN","NOT IN","IS NULL","IS NOT NULL","CONTAINS","NOT CONTAINS"]),bs=Y(["=","<>","IS NULL","IS NOT NULL"]),ws=Y(["=","<>",">",">=","<","<=","IS NULL","IS NOT NULL"]),Ss=Y(["IS NULL","IS NOT NULL"]),Es=Y(["IN","NOT IN"]),Fo=["char","varchar","binary","varbinary","blob","text","enum","set","character","character varying","text","citext","uuid","xml","json","jsonb"],Mo=new Set(Fo),le=e=>Mo.has(e),Qo=["integer","smallint","decimal","numeric","float","real","double precision","int","smallint","integer","bigint","decimal","numeric","real","double precision","serial","bigserial","money"],$o=new Set(Qo),Ot=e=>$o.has(e);var Is=["date","datetime","timestamp","timestamptz"].reduce((e,t)=>(e[t]=!0,e),{});var ve={read_only:10,editor:20,admin:30,owner:40};var P=e=>e.startsWith("'")&&e.endsWith("'")||e.startsWith('"')&&e.endsWith('"')?e.slice(1,-1):e;var Dt={operator:"LIKE",parse:e=>{let t=e.match(/^LIKE\s*["'](.*)["']$/i);if(t)return[{value:P(t[1])}]},stringify:e=>`LIKE "%${e[0]?.value}%"`},xt={operator:"NOT LIKE",parse:e=>{let t=e.match(/^NOT LIKE\s*["'](.*)["']$/i);if(t)return[{value:P(t[1])}]},stringify:e=>`NOT LIKE "%${e[0]?.value}%"`},vt={operator:"CONTAINS",parse:e=>{let t=e.match(/^CONTAINS\s*["'](.*)["']$/i);if(t)return[{value:P(t[1])}]},stringify:(e,t)=>le(t)?`${e[0]?.value}`:`CONTAINS "%${e[0]?.value}%"`},_t={operator:"NOT CONTAINS",parse:e=>{let t=e.match(/^NOT CONTAINS\s*["'](.*)["']$/i);if(t)return[{value:P(t[1])}]},stringify:e=>`NOT CONTAINS "%${e[0]?.value}%"`};function Lt(e){return e===""?[]:Ho(e).map(Wo)}function Ho(e){let t=[],r=0,o="",a=!1,n=!1;for(;r<e.length;){let u=e[r];if((a||n)&&u==="\\"){o+=e[r+1],r+=2;continue}if(u==="'"&&!n){a=!a,o+=u,r++;continue}if(u==='"'&&!a){n=!n,o+=u,r++;continue}if(u===","&&!a&&!n){t.push(o.trim()),o="",r++;continue}o+=u,r++}if(o.trim()!==""&&t.push(o.trim()),a||n)throw new Error("Unterminated string literal");return t}function Wo(e){if(e.startsWith("'")&&e.endsWith("'"))return{value:Ut(e.slice(1,-1),"'")};if(e.startsWith('"')&&e.endsWith('"'))return{value:Ut(e.slice(1,-1),'"')};let t=Number(e);if(!Number.isNaN(t))return{value:t};throw new Error(`Invalid literal: ${e}`)}function Ut(e,t){return e.replace(/\\(.)/g,(r,o)=>o)}var kt={operator:"IN",parse:e=>{let t=e.match(/^in\s*\((.*)\)$/i);if(t)return Lt(t[1])},stringify:e=>`IN (${e?.map(t=>`"${t.value}"`).join(", ")})`},qt={operator:"NOT IN",parse:e=>{let t=e.match(/^not\s+in\s*\((.*)\)$/i);if(t)return Lt(t[1])},stringify:e=>`NOT IN (${e?.map(t=>`"${t.value}"`).join(", ")})`};var Bt={operator:"=",parse:e=>{let t=e.match(/^=\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:(e,t)=>Ot(t)?`${e[0]?.value}`:`= ${e[0]?.value}`},Ft={operator:"!=",parse:e=>{let t=e.match(/^!=\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`!= ${e[0]?.value}`},Mt={operator:"<>",parse:e=>{let t=e.match(/^<>\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`<> ${e[0]?.value}`},Qt={operator:">",parse:e=>{let t=e.match(/^>\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`> ${e[0]?.value}`},$t={operator:">=",parse:e=>{let t=e.match(/^>=\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`>= ${e[0]?.value}`},Ht={operator:"<",parse:e=>{let t=e.match(/^<\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`< ${e[0]?.value}`},Wt={operator:"<=",parse:e=>{let t=e.match(/^<=\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`<= ${e[0]?.value}`};var Yt={operator:"IS NULL",parse:e=>{if(/^is\s+null$/i.test(e))return[]},stringify:()=>"IS NULL"},Gt={operator:"IS NOT NULL",parse:e=>{if(/^is\s+not\s+null$/i.test(e))return[]},stringify:()=>"IS NOT NULL"};var Yo=[Dt,vt,xt,_t,kt,qt,Bt,Ft,Mt,$t,Qt,Wt,Ht,Yt,Gt];function Go(e){let t=e.trim();for(let r of Yo){let o=r.parse(t);if(o)return{operator:r.operator,value:o}}}var jt={parse:Go};var S=e=>{let t=ve[e];return r=>ve[r.currentTeamRole]>=t},Kt=async e=>{let t=e.routeOptions.config.requireRole;if(t&&!t(e.user))throw new i(403,"You are not authorized to perform this action")};var de=async(e,t)=>{let r=await e.find(B,{where:{datasource:{id:t}},select:["id"]});for(let o of r){let a=await e.find(q,{where:{tableId:o.id},select:["id"]});await e.remove(q,a),await e.delete(B,o)}};function jo(e){let t=new Map;for(let r of e)r.columns?.forEach(o=>{if(o.ref){let a=`${o.ref.table}.${o.ref.field}`,n=t.get(a)||[];n.push({table:r.tableName,field:o.name}),t.set(a,n)}});return t}var Vt=async e=>{let t=await E.findOne({where:{id:e},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser"]});if(!t)throw new Error("Data source not found");return t.status="INSPECTING",await E.save(t),b.transaction(async r=>{let a=await(await Rt(U(t,!0),t.dbType)).inspectSchema();await de(r,t.id);let n=jo(a);for(let u of a){let s=await r.save(B,{datasource:{id:e},name:u.tableName});if(u.columns){let m=[];for(let c of u.columns)m.push(se.create({table:{id:s.id},name:c.name,isPrimary:!!c.isPrimary,type:c.type,meta:{refs:c.ref,referencedBy:n.get(`${s.name}.${c.name}`)}}));await r.save(q,m)}}await r.save(Q,{id:e,status:"READY",lastInspected:new Date})}).catch(r=>{console.error(r),E.save({id:e,status:"FAILED"})}),!0};var zt=h(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=y(t),o=await E.findOne({where:{id:r}});if(!o)throw new i(404,"Data source not found");return{data:o}}}),e.route({method:"get",url:"/",handler:async t=>{let{teamId:r}=v(t);return{data:await E.find({where:{team:{id:r}},order:{createdAt:"DESC"}})}}}),e.route({url:"/",method:"post",config:{requireRole:S("admin")},handler:async t=>{let{teamId:r,ownerId:o,...a}=f(t,bt),n=E.create({...a,allowUpdate:!!a.allowUpdate,allowInsert:!!a.allowInsert,team:{id:r},owner:{id:o}}),u=await $(U(n),n.dbType,t);try{await u.checkConnection()}catch{throw new i(400,"Cannot connect to the database, please check datasource configuration")}let{tag:s,iv:m,encrypted:c}=me.encrypt(n.dbPassword);return n.dbPassword=c,n.dbPasswordIv=m,n.dbPasswordTag=s,{data:await E.save(n)}}}),e.route({method:"put",url:"/:id",config:{requireRole:S("admin")},handler:async t=>{let{id:r}=y(t),o=f(t),a=await E.findOneBy({id:r});if(!a)throw new i(404,"Data source not found");let n=E.merge(a,o);return await E.save(n),{data:n}}}),e.route({method:"delete",url:"/:id",config:{requireRole:S("admin")},handler:async t=>b.transaction(async r=>{let{id:o}=y(t);await Promise.all([de(r,o),r.delete(K,{dataSource:{id:o}})]),await r.delete(Q,{id:o})})}),e.route({method:"post",url:"/:id/inspect",handler:async(t,r)=>{let{id:o}=y(t);return{data:{started:await Vt(o)}}}}),e.route({method:"get",url:"/:id/inspections",handler:async t=>{let{id:r}=y(t);return{data:(await ie.find({where:{datasource:{id:r}},relations:{columns:!0},order:{name:"ASC",columns:{isPrimary:"DESC",name:"ASC"}}})).map(n=>({tableName:n.name,id:n.id,updatedAt:n.updatedAt,createdAt:n.createdAt,columns:n.columns.map(u=>({name:u.name,type:u.type,isPrimary:u.isPrimary,ref:u.meta?.refs}))}))}}})});var L=require("typeorm"),Jt=h(e=>{e.route({method:"get",url:"/team/:teamId/datasources",handler:async t=>{let{teamId:r}=y(t);return{data:await E.find({where:{team:{id:r}},order:{name:"ASC"},select:{id:!0,name:!0,updatedAt:!0,dbType:!0,description:!0,allowInsert:!0,allowUpdate:!0}})}}}),e.route({method:"get",url:"/team/:teamId/queries",handler:async t=>{let r=y(t),o=v(t),a=r.teamId||t.user.currentTeamId,n=Number(o.size)||20,u=Number(o.page)||0,s=o.nameFilter?.length?{name:(0,L.Raw)(p=>`LOWER(${p}) LIKE :search`,{search:`%${o.nameFilter.toLowerCase()}%`})}:void 0,m=await _.find({where:[{isPersonal:!1,team:{id:a},query:s},{isPersonal:!0,team:{id:a},query:s,user:{id:t.user.id}}],relations:{query:{dataSource:!0}},take:n+1,skip:u*n,select:{id:!0,query:{id:!0,name:!0,updatedAt:!0,dataSource:{name:!0,dbType:!0}}},order:{query:{updatedAt:"DESC"}}}),c=m.length>n;return c&&m.pop(),{data:m.map(p=>({name:p.query.name,id:p.query.id,updatedAt:p.query.updatedAt,savedQueryId:p.id,datasourceName:p.query.dataSource.name,datasourceType:p.query.dataSource.dbType})),hasMore:c}}}),e.route({method:"get",url:"/team/:teamId/query",handler:async t=>{let{teamId:r}=y(t),{search:o,size:a,selectedDataSources:n}=v(t),u=o.length>3?parseInt(a)||20:8,s={};n?.length&&(s.id=(0,L.In)(n));let[m,c,l]=await Promise.all([ie.find({where:{name:(0,L.Raw)(d=>`LOWER(${d}) LIKE :search`,{search:`%${o.toLowerCase()}%`}),datasource:s},relations:{datasource:!0},select:{id:!0,name:!0,datasource:{name:!0,id:!0}},order:{name:"ASC"},take:u}),A.find({where:{searchString:(0,L.Like)(`%${o.toLowerCase()}%`),team:{id:r},user:{id:t.user.id},dataSource:s},relations:{dataSource:!0},select:{id:!0,name:!0,updatedAt:!0,dataSource:{id:!0,name:!0}},order:{updatedAt:"ASC"},take:u}),_.find({where:{searchString:(0,L.Like)(`%${o.toLowerCase()}%`),team:{id:r},query:{dataSource:s}},relations:{query:{dataSource:!0}},select:{id:!0,updatedAt:!0,query:{id:!0,name:!0,dataSource:{name:!0}}},order:{updatedAt:"ASC"},take:u})]),p=[];return m.forEach(d=>{p.push({name:d.name,id:d.id,dataSourceName:d.datasource?.name||"--",dataSourceId:d.datasource?.id||"--",type:"table"})}),c.forEach(d=>{p.push({name:d.name,id:d.id,dataSourceName:d.dataSource?.name||"--",dataSourceId:d.dataSource?.id||"--",type:"tab"})}),l.forEach(d=>{p.push({name:d.query.name,id:d.query.id,dataSourceName:d.query.dataSource?.name||"--",dataSourceId:d.query.dataSource?.id||"--",type:"query"})}),{data:p}}}),e.route({method:"get",url:"/team/:teamId/tabs-history",handler:async t=>{let{teamId:r}=y(t),o=v(t),a=Number(o.page),n=Number(o.size),u=t.user.id,s={team:{id:r},user:{id:u}};o.nameFilter?.length&&(s.name=(0,L.Like)(`%${o.nameFilter}%`)),o.archived&&(s.archived=o.archived==="true");let m=await A.find({where:s,relations:{dataSource:!0},order:{updatedAt:"DESC"},take:n+1,skip:a*n}),c=!1;return m.length>n&&(m.pop(),c=!0),{data:m.map(l=>({name:l.name,id:l.id,updatedAt:l.updatedAt,archived:l.archived,createdAt:l.createdAt,dataSourceId:l.dataSource?.id,dataSourceName:l.dataSource?.name,dataSourceType:l.dataSource?.dbType})),hasMore:c}}})});var Xt=h(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=y(t),o=await R.findOne({where:{id:r},select:{dataSource:{id:!0}},relations:{dataSource:!0}});return o?{data:o}:{status:404,data:"Query not found"}}}),e.route({method:"post",url:"/",config:{requireRole:S("editor")},handler:async t=>{let r=f(t),o=await E.findOne({where:{id:r.dataSourceId},relations:{team:!0}});return{data:await R.save(R.create({name:r.name,opts:r.opts,team:{id:o?.team.id},dataSource:{id:r.dataSourceId},user:{id:t.user.id}}))}}}),e.route({method:"patch",url:"/:id",config:{requireRole:S("editor")},handler:async t=>{let{id:r}=y(t),o=f(t);if(!(await R.update(r,o)).affected)throw new i(404,"Query not found");return{data:await R.findOneBy({id:r})}}}),e.route({method:"delete",url:"/:id",config:{requireRole:S("editor")},handler:async t=>b.transaction(async()=>{let{id:r}=y(t);if(!(await R.delete({id:r})).affected)return{status:404,data:"Query not found"}})})});var Zt=e=>e&&le(e)?"CONTAINS":"=",Ue=(e,t)=>{let r=[];for(let o of e){if(!o.column?.length||!o.value?.length||o.isEnabled===!1)continue;let[a,n]=o.column.split("."),u=t(a,n);if(o.isAdvanced){let s=jt.parse(o.value);if(!s)throw new i(400,`Invalid value for '${o.column}': ${o.value}`);r.push({value:s.value,column:o.column,operator:s.operator||Zt(u?.type),fn:o.fn})}else r.push({value:o.value?[{value:o.value}]:[],column:o.column,operator:Zt(u?.type),fn:o.fn})}return r},er=e=>{let t=[e.table];return e.joins&&e.joins.forEach(({table:r})=>t.push(r)),t},_e=e=>({column:e.value,fn:e.fn,distinct:e.distinct}),tr=(e,t,r)=>{let o=[];return t.length>0||r.length>0?o.push(...t.map(_e),...r.map(_e)):e.length>0&&o.push(...e.map(_e)),o},Ko=e=>e.isPrimary&&e.table?.name?{table:e.table.name,field:e.name}:e?.meta?.refs,Vo=e=>e?.meta?.referencedBy,rr=(e,t,r)=>t.map((o,a)=>{let n=o.table?r(o.table,o.column):void 0,u=n?Ko(n):void 0,s=n?Vo(n):void 0;return{...o,full:e[a].fn?e[a].column:o.full,type:n?.type,fn:e[a].fn,ref:u,referencedBy:s}}),or=e=>{let t=[],r=[];for(let o of e)o.referencedBy?.forEach(a=>{t.push({id:[a.table,a.field,o.column,o.table].join("."),fromColumn:a.field,fromTable:a.table,toColumn:o.column,toTable:o.table,direction:"in"})}),o.ref&&(r.push({id:[o.column,o.table,o.ref.table,o.ref.field].join("."),fromColumn:o.column,fromTable:o.table,toColumn:o.ref.field,toTable:o.ref.table,direction:"out"}),t.push({id:[o.column,o.table,o.ref.table,o.ref.field].join("."),fromColumn:o.column,fromTable:o.table,toColumn:o.ref.field,toTable:o.ref.table,direction:"out"}));return{hooks:t,entities:r}};var Le=require("typeorm"),ar=new Le.DataSource({type:"mysql"}),nr=new Le.DataSource({type:"postgres"}),G=e=>{switch(e){case"postgres":return nr.createQueryBuilder();case"mysql":return ar.createQueryBuilder();default:throw new Error("Unsupported database connection")}},pe={postgres:nr.driver,mysql:ar.driver};var X=(e,t,r)=>{let{column:o,operator:a,value:n}=e,u="_"+t;switch(a){case"IS NULL":case"IS NOT NULL":return[`${o} ${a}`,{value:void 0}];case"IN":case"NOT IN":return[`${o} ${a} (:...${u})`,{[u]:n?.map(c=>c.value)}];case"LIKE":case"CONTAINS":return[`${o} ${r==="postgres"?"ILIKE":"LIKE"} :${u}`,{[u]:a==="CONTAINS"?`%${n?.[0].value}%`:n?.[0].value}];case"NOT LIKE":case"NOT CONTAINS":return[`${o} ${r==="postgres"?"NOT ILIKE":"NOT LIKE"} :${u}`,{[u]:a==="NOT CONTAINS"?`%${n?.[0].value}%`:n?.[0].value}];default:return[`${o} ${a} :${u}`,{[u]:n?.[0]?.value}]}};var sr=e=>{let t=pe[e];return r=>{if(r.includes(".")){let[o,a]=r.split(".");return t.escape(o)+"."+t.escape(a)}return r==="*"?r:t.escape(r)}};var ir=["SUM","COUNT","AVG","MAX","MIN"],zo=["YEAR","MONTH","DAY",...ir],Jo=zo.reduce((e,t)=>(e[t]=!0,e),{}),Xo=ir.reduce((e,t)=>(e[t]=!0,e),{}),ur=e=>Jo[e],cr=e=>Xo[e];var fe=(e,t,r=!1)=>r?`${t}(distinct ${e})`:`${t}(${e})`,mr={YEAR:e=>`EXTRACT(YEAR FROM ${e})`,MONTH:e=>`EXTRACT(MONTH FROM ${e})`,DAY:e=>`EXTRACT(DAY FROM ${e})`,SUM:(e,t,r)=>r?`COALESCE(SUM(distinct ${e}), 0)`:`COALESCE(SUM(${e}), 0)`,AVG:fe,MAX:fe,MIN:fe,COUNT:fe};var ye=(e,t,r=!1)=>r?`${t}(distinct ${e})`:`${t}(${e})`,lr={YEAR:e=>`YEAR(${e})`,MONTH:e=>`MONTH(${e})`,DAY:e=>`DAY(${e})`,SUM:(e,t,r)=>r?`coalesce(${t}(distinct ${e}), 0)`:`coalesce(${t}(${e}), 0)`,AVG:ye,MAX:ye,MIN:ye,COUNT:ye};var Zo=e=>{let t=[];return e.fn&&t.push(e.fn),e.distinct&&t.push("distinct"),t.push(e.column),t.join(" ")},ea=e=>{let t=sr(e),r=e==="postgres"?mr:lr;return o=>o.fn&&ur(o.fn)?r[o.fn](t(o.column),o.fn,o.distinct):t(o.column)};function dr(e,t){let r=G(t.dbType).from(e,e),o=!1,a=0,n=ea(t.dbType),u={};return{setColumns(s){s.forEach(m=>{let c=Zo(m);u[c]=c,r.addSelect(n(m),c)})},setLimit:s=>{r.limit(s),o=!0},setOffset(s){r.offset(s)},addOrderBy(s,m){r.addOrderBy(s,m)},addJoin({table:s,alias:m,on:c}){r.leftJoin(s,m||s,c)},addWhere(s){let[m,c]=X({...s,operator:s.operator||"=",column:n(s)},++a,t.dbType);r.andWhere(m,c)},addHaving(s){let[m,c]=X({...s,operator:s.operator||"=",column:n(s)},++a,t.dbType);r.andHaving(m,c)},addGroupBy(s){r.addGroupBy(n(s))},hasAlias(s){return!!u[s]},build(){o||r.limit(50);let[s,m]=r.getQueryAndParameters();return{sql:s,params:m}}}}var pr=(e,t)=>{let r=G(t.dbType).update(e),o=0;return{addWhere(a){let[n,u]=X(a,++o,t.dbType);r.andWhere(n,u)},setParams(a){let n={};for(let[u,s]of Object.entries(a)){let m=`${s}`;m.startsWith("=")?n[u]=()=>m.substring(1):n[u]=m}r.set(n)},build(){let[a,n]=r.getQueryAndParameters();return{sql:a,params:n}}}};var fr=(e,t)=>{let r=G(t.dbType).insert().into(e);return{setValues(o){let a={};for(let[n,u]of Object.entries(o)){let s=`${u}`;s.startsWith("=")?a[n]=()=>s.substring(1):a[n]=s}r.values([a])},build(){let[o,a]=r.getQueryAndParameters();return{sql:o,params:a}}}};var ke=dr,yr=pr,Tr=fr;var gr=require("typeorm"),hr=async(e,t)=>{let r=await se.find({where:{table:{name:(0,gr.In)(t),datasource:{id:e}}},relations:{table:!0},order:{table:{name:"ASC"},isPrimary:"DESC",name:"ASC"}}),o=[];for(let s of r)o.push({column:s.name,table:s.table.name||"",full:`${s.table.name}.${s.name}`,type:s.type});let a=o.reduce((s,m)=>(s[m.full]=m.type,s),{});return{getAllColumns(){return o},hasColumn(s){return!!a[s]||s==="*"},getAvailableJoins:()=>{let s=[],m=new Set(t);for(let c of r)if(c.meta?.referencedBy?.forEach(l=>{m.has(l.table)||s.push({id:[l.table,l.field,c.name,c.table.name].join("."),fromColumn:l.field,fromTable:l.table,toColumn:c.name,toTable:c.table.name,direction:"in"})}),c.meta?.refs){let l=c.meta.refs;m.has(l.table)||s.push({id:[c.name,c.table.name,l.table,l.field].join("."),fromColumn:c.name,fromTable:c.table.name,toColumn:l.field,toTable:l.table,direction:"out"})}return s},getColumnByName:(s,m)=>{for(let c of r)if(c.name===m&&c.table.name===s)return c}}};async function ta(e,t,r){return R.save(R.create({user:{id:e},team:{id:t},dataSource:{id:r.datasourceId},name:r.name,opts:r.opts}))}var Te=async(e,t)=>{let{datasourceId:r,size:o=20,page:a}=t,{table:n,joins:u,groupBy:s,orderBy:m}=t.opts,c=await ge(r);if(!c)throw new i(404,"Datasource not found");let l=tr(t.opts.columns,t.opts.groupBy,t.opts.aggregations),p=er(t.opts),d=await hr(r,p),N=d.getAllColumns(),k;l&&l.length>0?k=l:k=N.map(I=>({column:I.full})),k.forEach(I=>{if(!d.hasColumn(I.column))throw new i(400,`Invalid column ${I.column}`)});let eo=ta(e.user.id,e.user.currentTeamId,t),x=ke(n,c);x.setLimit(o+1),x.setOffset(o*a),x.setColumns(k),u&&u.forEach(x.addJoin),m.length>0&&m.forEach(({column:I,direction:so})=>{x.hasAlias(I)&&x.addOrderBy(pe[c.dbType].escape(I),so)}),s&&s.length>0&&s.forEach(I=>{d.hasColumn(I.value)&&x.addGroupBy({column:I.value,fn:I.fn,distinct:I.distinct})}),Ue(t.opts.filters,d.getColumnByName).forEach(I=>{I.fn&&cr(I.fn)?x.addHaving(I):x.addWhere(I)});let{sql:to,params:ro}=x.build(),ee=await(await $(U(c,!0),c.dbType,e)).executeQuery({sql:to,params:ro,type:"SELECT",allowBulkUpdate:!1}),Be=ee.rows.length>o;Be&&ee.rows.pop();let{id:oo}=await eo,Fe=rr(k,ee.columns,d.getColumnByName),{hooks:ao,entities:no}=or(Fe);return{...ee,queryHistoryId:oo,tables:p,allColumns:N,availableHooks:ao,availableEntities:no,availableJoins:d.getAvailableJoins(),columns:Fe,hasMore:Be}},br=async(e,t)=>{let r=await ge(t.dataSourceId);if(!r)throw new i(400,"Invalid datasource");let o=await $(U(r,!0),r.dbType,e),a=ke(t.table,r);a.setLimit(2);for(let[m,c]of Object.entries(t.props))a.addWhere({value:[{value:c}],column:m});let{sql:n,params:u}=a.build(),s=await o.executeQuery({sql:n,params:u,type:"SELECT",allowBulkUpdate:!1});if(s.rows.length>1)throw new i(400,"Found multiple rows for given query");if(s.rows.length<1)throw new i(404,"Entity not found");return{entity:s.rows[0],columns:s.columns,sql:n}},wr=async(e,t)=>{let r=await ge(t.datasourceId);if(!r)throw new i(404,"Data source not found");if(!r.allowUpdate)throw new i(403,"This datasource does not allow update operations");let o=yr(t.table,r);o.setParams(t.values),Ue(t.filters,()=>{}).forEach(s=>{o.addWhere(s)});let{sql:a,params:n}=o.build();return(await $(U(r,!0),r.dbType,e)).executeQuery({sql:a,params:n,type:"UPDATE",allowBulkUpdate:!1})},Sr=async(e,t)=>{let r=await ge(t.datasourceId);if(!r)throw new i(404,"Data source not found");if(!r.allowInsert)throw new i(403,"This datasource does not allow insert operations");let o=Tr(t.table,r);o.setValues(t.values);let{sql:a,params:n}=o.build();return(await $(U(r,!0),r.dbType,e)).executeQuery({sql:a,type:"INSERT",params:n,allowBulkUpdate:!1})};async function ge(e){return E.findOne({where:{id:e},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser","allowUpdate","allowInsert"]})}var Er=e=>{},ra=["--",";","DROP","drop"],Ir=([e,t])=>{if(typeof t=="string"&&t.startsWith("=")){let r=t;ra.forEach(o=>{if(r.includes(o))throw new i(400,"Invalid input value for "+e)})}},Cr=e=>{if(!e.table)throw new i(400,"Table is required");Object.entries(e.values).forEach(Ir)},Rr=e=>{if(!e.table)throw new i(400,"Table is required");Object.entries(e.values).forEach(Ir)};var Nr=h(e=>{e.route({method:"post",url:"/:dsId/select",handler:async t=>{let r=f(t,Er);return{data:await Te(t,r)}}}),e.route({method:"get",url:"/:dsId/entity/:table",handler:async t=>{let{dsId:r,table:o}=y(t),a=v(t);return{data:await br(t,{table:o,dataSourceId:r,props:a})}}}),e.route({method:"post",url:"/:dsId/insert",config:{requireRole:S("editor")},handler:async t=>{let r=f(t,Cr);return{data:await Sr(t,r)}}}),e.route({method:"post",url:"/:dsId/update",config:{requireRole:S("editor")},handler:async t=>{let r=f(t,Rr);return{data:await wr(t,r)}}})});var Ar=h(e=>{e.get("/",{config:{isPublic:!0}},async()=>({data:{active:!0,version:T.str("SERVER_VERSION")}}))});var Pr=h(e=>{e.route({method:"get",url:"/:id/users",handler:async t=>{let{id:r}=y(t),o=await F.findOne({where:{id:r},relations:{users:{user:!0}}});if(!o)throw new i(404,"Team not found");return{data:o.users.map(a=>({role:a.role,id:a.user.id,name:a.user.username}))}}}),e.route({method:"post",url:"/",config:{requireRole:S("editor")},handler:async t=>b.transaction(async()=>{let r=t.user.id,o=f(t),a=w.create();a.id=r;let n=F.create(o);await F.save(n);let u=C.create({user:a,team:n});return await C.save(u),{data:n}})}),e.route({method:"patch",url:"/:id/user-role",config:{requireRole:S("admin")},handler:async t=>{let{id:r}=y(t),{role:o,userId:a}=f(t,({role:u})=>{if(u==="owner")throw new i(400,"Only one owner is allowed")});if((await C.findOneBy({user:{id:a},team:{id:r}}))?.role==="owner")throw new i(400,"Cannot change owner role");await C.update({user:{id:a},team:{id:r}},{role:o})}}),e.route({method:"delete",url:"/:id",config:{requireRole:S("admin")},handler:async t=>b.transaction(async()=>{let{id:r}=y(t),{userId:o}=v(t);if((await C.findOneBy({user:{id:o},team:{id:r}}))?.role==="owner")throw new i(400,"Cannot delete team owner");await w.update(o,{currentTeam:null}),await C.delete({user:{id:o},team:{id:r}}),await w.delete({id:o})})})});var qe=O(require("bcryptjs")),Z=async e=>{let t=await qe.default.genSalt(10);return qe.default.hash(e,t)};var Or=h(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=await w.findOne({where:{id:t.user.id},relations:{currentTeam:{team:!0}}});if(!r)throw new i(404,"User not found");return{data:{id:r.id,teamId:r.currentTeam?.team.id,teamName:r.currentTeam?.team.name,teamRole:r.currentTeam?.role,username:r.username}}}}),e.route({method:"patch",url:"/",handler:async t=>{let r=t.user.id,o=f(t);if(o.password&&(o.password=await Z(o.password)),!(await w.update(r,o)).affected)throw new i(404,"User not found");let n=await w.findOne({where:{id:r},relations:{currentTeam:{team:!0}}});return{data:{id:n?.id,teamId:n?.currentTeam?.team.id,teamName:n?.currentTeam?.team.name,teamRole:n?.currentTeam?.role,username:n?.username}}}}),e.route({method:"post",url:"/",config:{requireRole:S("admin")},handler:async t=>b.transaction(async()=>{let r=f(t),o=await Z(r.password),a=await w.save(w.create({username:r.username,password:o})),n=await C.save(C.create({role:"read_only",team:{id:r.teamId},user:{id:a.id}}));await w.update(a.id,{currentTeam:{id:n.id}})})})});var Dr=h(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=t.user.id,o=await W.findOneBy({user:{id:r}});return o||(o=await W.save(W.create({user:{id:r}}))),{data:o}}}),e.route({method:"patch",url:"/",handler:async t=>{let{settings:r}=f(t);if(!r.id)throw new i(400,"Settings id is required!");if(!(await W.update(r.id,r)).affected)throw new i(404,"You do not own these settings!");return{data:await W.findOneBy({id:r.id})}}})});function j(e,...t){let r=[...t];if(e.searchAll&&r.push(e.searchAll),e.filters)for(let o of e.filters)o.value&&r.push(o.value);return r.map(o=>o.toLowerCase()).join(",")}var xr=h(e=>{e.route({method:"post",url:"/",config:{requireRole:S("editor")},handler:async t=>{let r=f(t),o=await R.findOne({where:{id:r.queryId}});if(!o)throw new i(400,"Query not found");let a=await _.save(_.create({isPersonal:!1,team:{id:t.user.currentTeamId},user:{id:t.user.id},query:{id:r.queryId},searchString:j(o.opts,r.name)}));return await R.update(r.queryId,{name:r.name}),{data:a}}}),e.route({method:"delete",url:"/:id",config:{requireRole:S("editor")},handler:async t=>{let{id:r}=y(t);if(!(await _.delete({id:r})).affected)return{status:404,data:"Query not found"}}}),e.route({method:"patch",url:"/:id",handler:async t=>await b.transaction(async()=>{let{id:r}=y(t),o=f(t,u=>{if(!u.name)throw new i(400,"Name is required")}),a=await _.findOne({where:{id:r},relations:{query:!0}});if(!a)throw new i(400,"Query not found");let n=j(a.query.opts,o.name);return await Promise.all([_.update({id:r},{searchString:n}),R.update({id:a.query.id},{name:o.name})]),{data:!0}})})});var vr=e=>{if(!e.queryId&&!(e.opts&&e.name))throw new i(400,"Either queryId or name and opts are required")};var _r=h(e=>{e.route({method:"get",url:"/",handler:async t=>{let{currentTeamId:r,id:o}=t.user;return{data:(await A.find({where:{team:{id:r},user:{id:o},archived:!1},select:["id","name"]})).map(n=>({name:n.name,id:n.id}))}}}),e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=y(t),{currentTeamId:o,id:a}=t.user,n=await A.findOne({where:{id:r,team:{id:o},user:{id:a}}});if(!n)throw new i(404,"Not Found");return{data:n}}}),e.route({method:"post",url:"/",handler:async t=>{let{opts:r,name:o,queryId:a}=f(t,vr),n,u,s=o;if(r)u=r.dataSourceId,n=r;else{let c=await R.findOne({where:{id:a},relations:{dataSource:!0}});if(!c)throw new i(404,"Query not Found");u=c.dataSource.id,n={table:c.opts.table,filters:c.opts.filters,joins:c.opts.joins,orderBy:c.opts.orderBy,columns:c.opts.columns,groupBy:c.opts.groupBy,searchAll:c.opts.searchAll,aggregations:c.opts.aggregations,dataSourceId:c.dataSource.id,page:0,size:50},o||(s=c.name)}return{data:await A.save(A.create({name:s||new Date().toISOString(),opts:n||{},dataSource:{id:u},user:{id:t.user.id},team:{id:t.user.currentTeamId}}))}}}),e.route({method:"post",url:"/:id/run",handler:async t=>{let{id:r}=y(t),o=f(t),a=await A.findOne({where:{id:r},relations:{user:!0}});if(!a)throw new i(404,"Not found");if(a.user?.id!==t.user.id)throw new i(404,"Not found");return o&&A.update(r,{opts:o||{},searchString:j(o,a.name),updatedAt:new Date}),{data:{result:await Te(t,{datasourceId:o.dataSourceId,size:o.size,name:a.name,page:o.page,opts:{table:o.table,filters:o.filters,joins:o.joins,orderBy:o.orderBy,columns:o.columns,groupBy:o.groupBy,searchAll:o.searchAll,aggregations:o.aggregations}})}}}}),e.route({method:"patch",url:"/:id",handler:async t=>{let{id:r}=y(t),o=f(t),a=await A.findOne({where:{id:r,user:{id:t.user.id}}});if(!a)throw new i(404,"Not Found");let n=a.searchString;return o.name&&(n=j(a.opts,o.name)),await A.update(r,{...o,searchString:n}),{data:{id:r}}}}),e.route({method:"delete",url:"/:id",handler:async t=>{let{id:r}=y(t),o=t.user.id;return await A.delete({id:r,user:{id:o}}),{data:!0}}})});var kr=require("node:crypto");var Ur=require("node:crypto"),Lr={teamName:"Default Team",username:"admin"},oa=async()=>{let e=await F.findOneBy({});return e||F.save(F.create({name:Lr.teamName}))},he=async e=>{let t=await C.findOne({where:{role:"owner"},relations:{user:!0}});if(t)return t.user;let r=await oa(),o=await Z(e?.password||(0,Ur.randomBytes)(32).toString("hex")),a=await w.save(w.create({username:e?.name||Lr.username,password:o})),n=await C.save(C.create({user:a,team:r,role:"owner"}));return await w.update(a.id,{currentTeam:n}),a};var be={setupAccessToken:void 0},qr=()=>(be.setupAccessToken=(0,kr.randomBytes)(32).toString("hex"),be.setupAccessToken),aa=e=>{if(!be.setupAccessToken)throw new i(400,"Setup already performed");if(!e||e!==be.setupAccessToken)throw new i(400,"Invalid setup access token")},H=async()=>D.skipAuth?!1:await w.count()<1,Br=async e=>{aa(e.setupAccessToken),await he({name:e.userName,password:e.userPassword})};var Fr=h(e=>{e.route({method:"get",url:"/client.config.js",handler:(t,r)=>{let o={skipAuth:D.skipAuth,modeName:D.name,usesCustomDb:Ye(),serverVersion:T.str("SERVER_VERSION","--")};return r.type("application/javascript").send(`window.__CLIENT_CONFIG__ = ${JSON.stringify(o)};`)}}),e.route({method:"get",url:"/",handler:async(t,r)=>await H()?r.redirect("/setup"):r.sendFile("index.html")}),e.route({method:"get",url:"/setup",handler:async(t,r)=>await H()?r.sendFile("setup.html"):r.redirect("/")})});var Mr=e=>{if(!e.setupAccessToken)throw new i(400,"Invalid setup access token");if(!e.userPassword||e.userPassword.length<8)throw new i(400,"Password should be at least 8 chars long");if(!e.userName)throw new i(400,"User name is required")};var Qr=h(e=>{e.route({method:"post",url:"/",config:{isPublic:!0},handler:async t=>{if(!await H())throw new i(400,"Setup has already been completed");let o=f(t,Mr);return await Br(o),{data:!0}}})});var na=[[Fr,"/"],[ht,"/api/auth"],[zt,"/api/data-sources"],[Jt,"/api/project"],[Xt,"/api/queries"],[Nr,"/api/runner"],[Ar,"/api/status"],[Pr,"/api/teams"],[Or,"/api/users"],[Dr,"/api/user-settings"],[xr,"/api/saved-queries"],[_r,"/api/workbench-tabs"],[Qr,"/api/setup"]],$r=e=>{for(let[t,r]of na)e.register(t,{prefix:r}),console.log("Registered "+r)};var sa=e=>e.routeOptions.config.isPublic?!0:!e.url.startsWith("/api/"),ia=async()=>C.findOne({where:{role:"owner"},relations:{user:!0,team:!0}}),ua=async e=>{let t=await ia();if(!t)throw new i(401,"User is not part of a team");e.user={id:t.user.id,currentTeamId:t.team.id,currentTeamRole:t.role}},ca=async e=>{let t=e.headers.authorization;if(!t)throw new i(401,"Missing auth token");let[r,o]=t.split(" "),{userId:a}=await ft(o),n=await w.findOne({where:{id:a},select:{id:!0,currentTeam:{role:!0,team:{id:!0}}},relations:{currentTeam:{team:!0}}});if(!n)throw new i(401,"Unauthorized");e.user={id:a,currentTeamId:n.currentTeam.team.id,currentTeamRole:n.currentTeam.role}},Hr=async e=>{sa(e)||(D.skipAuth?await ua(e):await ca(e))};var Wr=(e,t)=>{e.__connections&&e.__connections.forEach(r=>{r.close()})};var Yr=e=>{e.addHook("onRequest",Hr),e.addHook("onRequest",Kt),e.addHook("onResponse",Wr)};var Gr=e=>{e.setNotFoundHandler((t,r)=>{if(t.raw.url?.startsWith("/api/")){r.code(404).send({error:"API route not found"});return}r.sendFile("index.html")}),e.setErrorHandler((t,r,o)=>{console.error(t),t instanceof i?o.status(t.status).send({error:t.message}):o.status(500).send({error:"Internal Server Error"})})};var jr=O(require("@fastify/cookie")),Kr=O(require("@fastify/cors"));var Vr=O(require("@fastify/static")),zr=require("node:path"),Jr=e=>{e.register(jr.default,{}),e.register(Kr.default,{origin:V.allowedOrigins,methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"],credentials:!0}),e.register(Vr.default,{root:(0,zr.join)(__dirname,"web")})};(async function(){let t=(0,Xr.default)({querystringParser:o=>Zr.default.parse(o)});if(We(),Jr(t),Yr(t),$r(t),Gr(t),await t.after(),await it(),t.listen({port:V.port,host:V.host},(o,a)=>{o&&(console.error(o),process.exit(1)),console.log(`Server listening at ${a}`)}),await H()){let o=qr();console.log(`Setup access token:
|
|
57
|
+
limit 75;`;return(await t.query(r)).rows.reduce((a,n)=>(a[n.row_key]={table:n.relname,column:n.attname},a),{})},It=async(e,t,r,o)=>{try{console.log(`[PG CONN] Query: ${e}`),console.log(`[PG CONN] Params: ${JSON.stringify(t,null,2)}`);let{rows:a,fields:n,command:u,rowCount:s}=await r.query({text:e,rowMode:"array",values:t});if(u==="UPDATE"||u==="INSERT"||u==="DELETE"){if(s!=null&&s>1&&o.allowBulkUpdate!==!0)throw new Error("[PG CONN] Bulk update performed without permission.");return{columns:[{column:"affectedRows",alias:"Affected rows",full:"affectedRows"}],rows:[[s]],query:e}}if(u==="SELECT"){let m=n.map(l=>`'${l.tableID}-${l.columnID}'`),c=await vo(m,r);return{columns:n.map(l=>{let p=c[`${l.tableID}-${l.columnID}`];return{column:p?.column||l.name,alias:l.name,table:p?.table||"",full:p?p.table+"."+p.column:l.name}}),rows:a,query:e}}throw new Error(`[PG CONN] Unsupported command: ${u}`)}catch(a){throw a instanceof i?a:new i(400,a.message)}},_o=async(e,t)=>{await e.query("BEGIN");try{let r=await t();return await e.query("COMMIT"),console.log("[PG CONN] Commit"),r}catch(r){throw await e.query("ROLLBACK"),console.log("[PG CONN] Rollback"),r}},Uo=async(e,t)=>{await e.query("BEGIN READ ONLY");try{let r=await t();return console.log("[PG CONN] Read only rollback"),await e.query("ROLLBACK"),r}catch(r){throw console.log("[PG CONN] Rollback"),await e.query("ROLLBACK"),r}},xe=async e=>{let t=await Po(e),r=!1,o=!1,a=async n=>(o||await t.query(`SET search_path TO ${e.schema}`),n());return{dbType:"postgres",dataSource:e,inspectSchema:()=>xo(e,t),executeQuery:n=>a(()=>n.type==="SELECT"?Uo(t,()=>It(n.sql,n.params,t,n)):_o(t,()=>It(n.sql,n.params,t,n))),checkConnection:async()=>{},isClosed:()=>r,close:async()=>{if(!r)return r=!0,t.end()}}};var $=async(e,t,r)=>{try{let o;if(t==="mysql")o=await De(e);else if(t==="postgres")o=await xe(e);else throw new i(500,`Connection manager for ${t} not found`);return r.__connections?r.__connections.push(o):r.__connections=[o],o}catch(o){throw console.error(o),o instanceof i?o:o?.code==="ECONNREFUSED"?new i(500,"Failed to connect to the database"):new i(500,o.message)}},Rt=async(e,t)=>{try{let r;if(t==="mysql")r=await De(e);else if(t==="postgres")r=await xe(e);else throw new i(500,`Connection manager for ${t} not found`);return r}catch(r){throw console.error(r),r instanceof i?r:r?.code==="ECONNREFUSED"?new i(500,"Failed to connect to the database"):new i(500,r.message)}};var ce=O(require("node:crypto"));var Nt="aes-256-gcm",Lo=12,At=()=>{let e=T.str("SYMM_ENCRYPTION_KEY");if(!e)throw new Error("Missing ENCRYPTION_KEY in environment variables.");let t=Buffer.from(e,"hex");if(t.length!==32)throw new Error("ENCRYPTION_KEY must be a 64-character hex string (256 bits).");return t},ko=e=>{let t=ce.default.randomBytes(Lo),r=At(),o=ce.default.createCipheriv(Nt,r,t),a=o.update(e,"utf8","hex");a+=o.final("hex");let n=o.getAuthTag();return{encrypted:a,iv:t.toString("hex"),tag:n.toString("hex")}},qo=({encrypted:e,iv:t,tag:r})=>{let o=At(),a=ce.default.createDecipheriv(Nt,o,Buffer.from(t,"hex"));a.setAuthTag(Buffer.from(r,"hex"));let n=a.update(e,"hex","utf8");return n+=a.final("utf8"),n},me={encrypt:ko,decrypt:qo};var U=(e,t=!1)=>{if(t){let r=me.decrypt({encrypted:e.dbPassword,tag:e.dbPasswordTag,iv:e.dbPasswordIv});return{url:e.dbUrl,user:e.dbUser,database:e.dbDatabase,password:r,port:e.dbPort,schema:e.dbSchema}}return{url:e.dbUrl,user:e.dbUser,database:e.dbDatabase,password:e.dbPassword,port:e.dbPort,schema:e.dbSchema}};var Pt=[{value:"=",label:"equals"},{value:"<>",label:"not equal"},{value:">",label:"greater than"},{value:">=",label:"greater than or equal"},{value:"<",label:"less than"},{value:"<=",label:"less than or equal"},{value:"LIKE",label:"like"},{value:"NOT LIKE",label:"not like"},{value:"CONTAINS",label:"contains"},{value:"NOT CONTAINS",label:"not contains"},{value:"IN",label:"in list"},{value:"NOT IN",label:"not in list"},{value:"IS NULL",label:"is null"},{value:"IS NOT NULL",label:"is not null"}],Bo=Pt.reduce((e,t)=>(e[t.value]=t.label,e),{}),Ts=Pt.reduce((e,t)=>(e[t.label]=t.value,e),{}),Y=e=>e.map(t=>({label:Bo[t],value:t})),gs=Y(["=","<>",">",">=","<","<=","IN","NOT IN","IS NULL","IS NOT NULL"]),hs=Y(["=","<>","LIKE","NOT LIKE","IN","NOT IN","IS NULL","IS NOT NULL","CONTAINS","NOT CONTAINS"]),bs=Y(["=","<>","IS NULL","IS NOT NULL"]),ws=Y(["=","<>",">",">=","<","<=","IS NULL","IS NOT NULL"]),Ss=Y(["IS NULL","IS NOT NULL"]),Es=Y(["IN","NOT IN"]),Fo=["char","varchar","binary","varbinary","blob","text","enum","set","character","character varying","text","citext","uuid","xml","json","jsonb"],Mo=new Set(Fo),le=e=>Mo.has(e),Qo=["integer","smallint","decimal","numeric","float","real","double precision","int","smallint","integer","bigint","decimal","numeric","real","double precision","serial","bigserial","money"],$o=new Set(Qo),Ot=e=>$o.has(e);var Is=["date","datetime","timestamp","timestamptz"].reduce((e,t)=>(e[t]=!0,e),{});var ve={read_only:10,editor:20,admin:30,owner:40};var P=e=>e.startsWith("'")&&e.endsWith("'")||e.startsWith('"')&&e.endsWith('"')?e.slice(1,-1):e;var Dt={operator:"LIKE",parse:e=>{let t=e.match(/^LIKE\s*["'](.*)["']$/i);if(t)return[{value:P(t[1])}]},stringify:e=>`LIKE "%${e[0]?.value}%"`},xt={operator:"NOT LIKE",parse:e=>{let t=e.match(/^NOT LIKE\s*["'](.*)["']$/i);if(t)return[{value:P(t[1])}]},stringify:e=>`NOT LIKE "%${e[0]?.value}%"`},vt={operator:"CONTAINS",parse:e=>{let t=e.match(/^CONTAINS\s*["'](.*)["']$/i);if(t)return[{value:P(t[1])}]},stringify:(e,t)=>le(t)?`${e[0]?.value}`:`CONTAINS "%${e[0]?.value}%"`},_t={operator:"NOT CONTAINS",parse:e=>{let t=e.match(/^NOT CONTAINS\s*["'](.*)["']$/i);if(t)return[{value:P(t[1])}]},stringify:e=>`NOT CONTAINS "%${e[0]?.value}%"`};function Lt(e){return e===""?[]:Ho(e).map(Wo)}function Ho(e){let t=[],r=0,o="",a=!1,n=!1;for(;r<e.length;){let u=e[r];if((a||n)&&u==="\\"){o+=e[r+1],r+=2;continue}if(u==="'"&&!n){a=!a,o+=u,r++;continue}if(u==='"'&&!a){n=!n,o+=u,r++;continue}if(u===","&&!a&&!n){t.push(o.trim()),o="",r++;continue}o+=u,r++}if(o.trim()!==""&&t.push(o.trim()),a||n)throw new Error("Unterminated string literal");return t}function Wo(e){if(e.startsWith("'")&&e.endsWith("'"))return{value:Ut(e.slice(1,-1),"'")};if(e.startsWith('"')&&e.endsWith('"'))return{value:Ut(e.slice(1,-1),'"')};let t=Number(e);if(!Number.isNaN(t))return{value:t};throw new Error(`Invalid literal: ${e}`)}function Ut(e,t){return e.replace(/\\(.)/g,(r,o)=>o)}var kt={operator:"IN",parse:e=>{let t=e.match(/^in\s*\((.*)\)$/i);if(t)return Lt(t[1])},stringify:e=>`IN (${e?.map(t=>`"${t.value}"`).join(", ")})`},qt={operator:"NOT IN",parse:e=>{let t=e.match(/^not\s+in\s*\((.*)\)$/i);if(t)return Lt(t[1])},stringify:e=>`NOT IN (${e?.map(t=>`"${t.value}"`).join(", ")})`};var Bt={operator:"=",parse:e=>{let t=e.match(/^=\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:(e,t)=>Ot(t)?`${e[0]?.value}`:`= ${e[0]?.value}`},Ft={operator:"!=",parse:e=>{let t=e.match(/^!=\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`!= ${e[0]?.value}`},Mt={operator:"<>",parse:e=>{let t=e.match(/^<>\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`<> ${e[0]?.value}`},Qt={operator:">",parse:e=>{let t=e.match(/^>\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`> ${e[0]?.value}`},$t={operator:">=",parse:e=>{let t=e.match(/^>=\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`>= ${e[0]?.value}`},Ht={operator:"<",parse:e=>{let t=e.match(/^<\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`< ${e[0]?.value}`},Wt={operator:"<=",parse:e=>{let t=e.match(/^<=\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`<= ${e[0]?.value}`};var Yt={operator:"IS NULL",parse:e=>{if(/^is\s+null$/i.test(e))return[]},stringify:()=>"IS NULL"},Gt={operator:"IS NOT NULL",parse:e=>{if(/^is\s+not\s+null$/i.test(e))return[]},stringify:()=>"IS NOT NULL"};var Yo=[Dt,vt,xt,_t,kt,qt,Bt,Ft,Mt,$t,Qt,Wt,Ht,Yt,Gt];function Go(e){let t=e.trim();for(let r of Yo){let o=r.parse(t);if(o)return{operator:r.operator,value:o}}}var jt={parse:Go};var S=e=>{let t=ve[e];return r=>ve[r.currentTeamRole]>=t},Kt=async e=>{let t=e.routeOptions.config.requireRole;if(t&&!t(e.user))throw new i(403,"You are not authorized to perform this action")};var de=async(e,t)=>{let r=await e.find(B,{where:{datasource:{id:t}},select:["id"]});for(let o of r){let a=await e.find(q,{where:{tableId:o.id},select:["id"]});await e.remove(q,a),await e.delete(B,o)}};function jo(e){let t=new Map;for(let r of e)r.columns?.forEach(o=>{if(o.ref){let a=`${o.ref.table}.${o.ref.field}`,n=t.get(a)||[];n.push({table:r.tableName,field:o.name}),t.set(a,n)}});return t}var Vt=async e=>{let t=await E.findOne({where:{id:e},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser"]});if(!t)throw new Error("Data source not found");return t.status="INSPECTING",await E.save(t),b.transaction(async r=>{let a=await(await Rt(U(t,!0),t.dbType)).inspectSchema();await de(r,t.id);let n=jo(a);for(let u of a){let s=await r.save(B,{datasource:{id:e},name:u.tableName});if(u.columns){let m=[];for(let c of u.columns)m.push(se.create({table:{id:s.id},name:c.name,isPrimary:!!c.isPrimary,type:c.type,meta:{refs:c.ref,referencedBy:n.get(`${s.name}.${c.name}`)}}));await r.save(q,m)}}await r.save(Q,{id:e,status:"READY",lastInspected:new Date})}).catch(r=>{console.error(r),E.save({id:e,status:"FAILED"})}),!0};var zt=h(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=y(t),o=await E.findOne({where:{id:r}});if(!o)throw new i(404,"Data source not found");return{data:o}}}),e.route({method:"get",url:"/",handler:async t=>{let{teamId:r}=v(t);return{data:await E.find({where:{team:{id:r}},order:{createdAt:"DESC"}})}}}),e.route({url:"/",method:"post",config:{requireRole:S("admin")},handler:async t=>{let{teamId:r,ownerId:o,...a}=f(t,bt),n=E.create({...a,allowUpdate:!!a.allowUpdate,allowInsert:!!a.allowInsert,team:{id:r},owner:{id:o}}),u=await $(U(n),n.dbType,t);try{await u.checkConnection()}catch{throw new i(400,"Cannot connect to the database, please check datasource configuration")}let{tag:s,iv:m,encrypted:c}=me.encrypt(n.dbPassword);return n.dbPassword=c,n.dbPasswordIv=m,n.dbPasswordTag=s,{data:await E.save(n)}}}),e.route({method:"put",url:"/:id",config:{requireRole:S("admin")},handler:async t=>{let{id:r}=y(t),o=f(t),a=await E.findOneBy({id:r});if(!a)throw new i(404,"Data source not found");let n=E.merge(a,o);return await E.save(n),{data:n}}}),e.route({method:"delete",url:"/:id",config:{requireRole:S("admin")},handler:async t=>b.transaction(async r=>{let{id:o}=y(t);await Promise.all([de(r,o),r.delete(K,{dataSource:{id:o}})]),await r.delete(Q,{id:o})})}),e.route({method:"post",url:"/:id/inspect",handler:async(t,r)=>{let{id:o}=y(t);return{data:{started:await Vt(o)}}}}),e.route({method:"get",url:"/:id/inspections",handler:async t=>{let{id:r}=y(t);return{data:(await ie.find({where:{datasource:{id:r}},relations:{columns:!0},order:{name:"ASC",columns:{isPrimary:"DESC",name:"ASC"}}})).map(n=>({tableName:n.name,id:n.id,updatedAt:n.updatedAt,createdAt:n.createdAt,columns:n.columns.map(u=>({name:u.name,type:u.type,isPrimary:u.isPrimary,ref:u.meta?.refs}))}))}}})});var L=require("typeorm"),Jt=h(e=>{e.route({method:"get",url:"/team/:teamId/datasources",handler:async t=>{let{teamId:r}=y(t);return{data:await E.find({where:{team:{id:r}},order:{name:"ASC"},select:{id:!0,name:!0,updatedAt:!0,dbType:!0,description:!0,allowInsert:!0,allowUpdate:!0}})}}}),e.route({method:"get",url:"/team/:teamId/queries",handler:async t=>{let r=y(t),o=v(t),a=r.teamId||t.user.currentTeamId,n=Number(o.size)||20,u=Number(o.page)||0,s=o.nameFilter?.length?{name:(0,L.Raw)(p=>`LOWER(${p}) LIKE :search`,{search:`%${o.nameFilter.toLowerCase()}%`})}:void 0,m=await _.find({where:[{isPersonal:!1,team:{id:a},query:s},{isPersonal:!0,team:{id:a},query:s,user:{id:t.user.id}}],relations:{query:{dataSource:!0}},take:n+1,skip:u*n,select:{id:!0,query:{id:!0,name:!0,updatedAt:!0,dataSource:{name:!0,dbType:!0}}},order:{query:{updatedAt:"DESC"}}}),c=m.length>n;return c&&m.pop(),{data:m.map(p=>({name:p.query.name,id:p.query.id,updatedAt:p.query.updatedAt,savedQueryId:p.id,datasourceName:p.query.dataSource.name,datasourceType:p.query.dataSource.dbType})),hasMore:c}}}),e.route({method:"get",url:"/team/:teamId/query",handler:async t=>{let{teamId:r}=y(t),{search:o,size:a,selectedDataSources:n}=v(t),u=o.length>3?parseInt(a)||20:8,s={};n?.length&&(s.id=(0,L.In)(n));let[m,c,l]=await Promise.all([ie.find({where:{name:(0,L.Raw)(d=>`LOWER(${d}) LIKE :search`,{search:`%${o.toLowerCase()}%`}),datasource:s},relations:{datasource:!0},select:{id:!0,name:!0,datasource:{name:!0,id:!0}},order:{name:"ASC"},take:u}),A.find({where:{searchString:(0,L.Like)(`%${o.toLowerCase()}%`),team:{id:r},user:{id:t.user.id},dataSource:s},relations:{dataSource:!0},select:{id:!0,name:!0,updatedAt:!0,dataSource:{id:!0,name:!0}},order:{updatedAt:"ASC"},take:u}),_.find({where:{searchString:(0,L.Like)(`%${o.toLowerCase()}%`),team:{id:r},query:{dataSource:s}},relations:{query:{dataSource:!0}},select:{id:!0,updatedAt:!0,query:{id:!0,name:!0,dataSource:{name:!0}}},order:{updatedAt:"ASC"},take:u})]),p=[];return m.forEach(d=>{p.push({name:d.name,id:d.id,dataSourceName:d.datasource?.name||"--",dataSourceId:d.datasource?.id||"--",type:"table"})}),c.forEach(d=>{p.push({name:d.name,id:d.id,dataSourceName:d.dataSource?.name||"--",dataSourceId:d.dataSource?.id||"--",type:"tab"})}),l.forEach(d=>{p.push({name:d.query.name,id:d.query.id,dataSourceName:d.query.dataSource?.name||"--",dataSourceId:d.query.dataSource?.id||"--",type:"query"})}),{data:p}}}),e.route({method:"get",url:"/team/:teamId/tabs-history",handler:async t=>{let{teamId:r}=y(t),o=v(t),a=Number(o.page),n=Number(o.size),u=t.user.id,s={team:{id:r},user:{id:u}};o.nameFilter?.length&&(s.name=(0,L.Like)(`%${o.nameFilter}%`)),o.archived&&(s.archived=o.archived==="true");let m=await A.find({where:s,relations:{dataSource:!0},order:{updatedAt:"DESC"},take:n+1,skip:a*n}),c=!1;return m.length>n&&(m.pop(),c=!0),{data:m.map(l=>({name:l.name,id:l.id,updatedAt:l.updatedAt,archived:l.archived,createdAt:l.createdAt,dataSourceId:l.dataSource?.id,dataSourceName:l.dataSource?.name,dataSourceType:l.dataSource?.dbType})),hasMore:c}}})});var Xt=h(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=y(t),o=await R.findOne({where:{id:r},select:{dataSource:{id:!0}},relations:{dataSource:!0}});return o?{data:o}:{status:404,data:"Query not found"}}}),e.route({method:"post",url:"/",config:{requireRole:S("editor")},handler:async t=>{let r=f(t),o=await E.findOne({where:{id:r.dataSourceId},relations:{team:!0}});return{data:await R.save(R.create({name:r.name,opts:r.opts,team:{id:o?.team.id},dataSource:{id:r.dataSourceId},user:{id:t.user.id}}))}}}),e.route({method:"patch",url:"/:id",config:{requireRole:S("editor")},handler:async t=>{let{id:r}=y(t),o=f(t);if(!(await R.update(r,o)).affected)throw new i(404,"Query not found");return{data:await R.findOneBy({id:r})}}}),e.route({method:"delete",url:"/:id",config:{requireRole:S("editor")},handler:async t=>b.transaction(async()=>{let{id:r}=y(t);if(!(await R.delete({id:r})).affected)return{status:404,data:"Query not found"}})})});var Zt=e=>e&&le(e)?"CONTAINS":"=",Ue=(e,t)=>{let r=[];for(let o of e){if(!o.column?.length||!o.value?.length||o.isEnabled===!1)continue;let[a,n]=o.column.split("."),u=t(a,n);if(o.isAdvanced){let s=jt.parse(o.value);if(!s)throw new i(400,`Invalid value for '${o.column}': ${o.value}`);r.push({value:s.value,column:o.column,operator:s.operator||Zt(u?.type),fn:o.fn})}else r.push({value:o.value?[{value:o.value}]:[],column:o.column,operator:Zt(u?.type),fn:o.fn})}return r},er=e=>{let t=[e.table];return e.joins&&e.joins.forEach(({table:r})=>t.push(r)),t},_e=e=>({column:e.value,fn:e.fn,distinct:e.distinct}),tr=(e,t,r)=>{let o=[];return t.length>0||r.length>0?o.push(...t.map(_e),...r.map(_e)):e.length>0&&o.push(...e.map(_e)),o},Ko=e=>e.isPrimary&&e.table?.name?{table:e.table.name,field:e.name}:e?.meta?.refs,Vo=e=>e?.meta?.referencedBy,rr=(e,t,r)=>t.map((o,a)=>{let n=o.table?r(o.table,o.column):void 0,u=n?Ko(n):void 0,s=n?Vo(n):void 0;return{...o,full:e[a].fn?e[a].column:o.full,type:n?.type,fn:e[a].fn,ref:u,referencedBy:s}}),or=e=>{let t=[],r=[];for(let o of e)o.referencedBy?.forEach(a=>{t.push({id:[a.table,a.field,o.table,o.column].join("."),fromColumn:a.field,fromTable:a.table,toColumn:o.column,toTable:o.table,direction:"in"})}),o.ref&&(r.push({id:[o.column,o.table,o.ref.table,o.ref.field].join("."),fromColumn:o.column,fromTable:o.table,toColumn:o.ref.field,toTable:o.ref.table,direction:"out"}),o.ref.table!==o.table&&t.push({id:[o.column,o.table,o.ref.table,o.ref.field].join("."),fromColumn:o.column,fromTable:o.table,toColumn:o.ref.field,toTable:o.ref.table,direction:"out"}));return{hooks:t,entities:r}};var Le=require("typeorm"),ar=new Le.DataSource({type:"mysql"}),nr=new Le.DataSource({type:"postgres"}),G=e=>{switch(e){case"postgres":return nr.createQueryBuilder();case"mysql":return ar.createQueryBuilder();default:throw new Error("Unsupported database connection")}},pe={postgres:nr.driver,mysql:ar.driver};var X=(e,t,r)=>{let{column:o,operator:a,value:n}=e,u="_"+t;switch(a){case"IS NULL":case"IS NOT NULL":return[`${o} ${a}`,{value:void 0}];case"IN":case"NOT IN":return[`${o} ${a} (:...${u})`,{[u]:n?.map(c=>c.value)}];case"LIKE":case"CONTAINS":return[`${o} ${r==="postgres"?"ILIKE":"LIKE"} :${u}`,{[u]:a==="CONTAINS"?`%${n?.[0].value}%`:n?.[0].value}];case"NOT LIKE":case"NOT CONTAINS":return[`${o} ${r==="postgres"?"NOT ILIKE":"NOT LIKE"} :${u}`,{[u]:a==="NOT CONTAINS"?`%${n?.[0].value}%`:n?.[0].value}];default:return[`${o} ${a} :${u}`,{[u]:n?.[0]?.value}]}};var sr=e=>{let t=pe[e];return r=>{if(r.includes(".")){let[o,a]=r.split(".");return t.escape(o)+"."+t.escape(a)}return r==="*"?r:t.escape(r)}};var ir=["SUM","COUNT","AVG","MAX","MIN"],zo=["YEAR","MONTH","DAY",...ir],Jo=zo.reduce((e,t)=>(e[t]=!0,e),{}),Xo=ir.reduce((e,t)=>(e[t]=!0,e),{}),ur=e=>Jo[e],cr=e=>Xo[e];var fe=(e,t,r=!1)=>r?`${t}(distinct ${e})`:`${t}(${e})`,mr={YEAR:e=>`EXTRACT(YEAR FROM ${e})`,MONTH:e=>`EXTRACT(MONTH FROM ${e})`,DAY:e=>`EXTRACT(DAY FROM ${e})`,SUM:(e,t,r)=>r?`COALESCE(SUM(distinct ${e}), 0)`:`COALESCE(SUM(${e}), 0)`,AVG:fe,MAX:fe,MIN:fe,COUNT:fe};var ye=(e,t,r=!1)=>r?`${t}(distinct ${e})`:`${t}(${e})`,lr={YEAR:e=>`YEAR(${e})`,MONTH:e=>`MONTH(${e})`,DAY:e=>`DAY(${e})`,SUM:(e,t,r)=>r?`coalesce(${t}(distinct ${e}), 0)`:`coalesce(${t}(${e}), 0)`,AVG:ye,MAX:ye,MIN:ye,COUNT:ye};var Zo=e=>{let t=[];return e.fn&&t.push(e.fn),e.distinct&&t.push("distinct"),t.push(e.column),t.join(" ")},ea=e=>{let t=sr(e),r=e==="postgres"?mr:lr;return o=>o.fn&&ur(o.fn)?r[o.fn](t(o.column),o.fn,o.distinct):t(o.column)};function dr(e,t){let r=G(t.dbType).from(e,e),o=!1,a=0,n=ea(t.dbType),u={};return{setColumns(s){s.forEach(m=>{let c=Zo(m);u[c]=c,r.addSelect(n(m),c)})},setLimit:s=>{r.limit(s),o=!0},setOffset(s){r.offset(s)},addOrderBy(s,m){r.addOrderBy(s,m)},addJoin({table:s,alias:m,on:c}){r.leftJoin(s,m||s,c)},addWhere(s){let[m,c]=X({...s,operator:s.operator||"=",column:n(s)},++a,t.dbType);r.andWhere(m,c)},addHaving(s){let[m,c]=X({...s,operator:s.operator||"=",column:n(s)},++a,t.dbType);r.andHaving(m,c)},addGroupBy(s){r.addGroupBy(n(s))},hasAlias(s){return!!u[s]},build(){o||r.limit(50);let[s,m]=r.getQueryAndParameters();return{sql:s,params:m}}}}var pr=(e,t)=>{let r=G(t.dbType).update(e),o=0;return{addWhere(a){let[n,u]=X(a,++o,t.dbType);r.andWhere(n,u)},setParams(a){let n={};for(let[u,s]of Object.entries(a)){let m=`${s}`;m.startsWith("=")?n[u]=()=>m.substring(1):n[u]=m}r.set(n)},build(){let[a,n]=r.getQueryAndParameters();return{sql:a,params:n}}}};var fr=(e,t)=>{let r=G(t.dbType).insert().into(e);return{setValues(o){let a={};for(let[n,u]of Object.entries(o)){let s=`${u}`;s.startsWith("=")?a[n]=()=>s.substring(1):a[n]=s}r.values([a])},build(){let[o,a]=r.getQueryAndParameters();return{sql:o,params:a}}}};var ke=dr,yr=pr,Tr=fr;var gr=require("typeorm"),hr=async(e,t)=>{let r=await se.find({where:{table:{name:(0,gr.In)(t),datasource:{id:e}}},relations:{table:!0},order:{table:{name:"ASC"},isPrimary:"DESC",name:"ASC"}}),o=[];for(let s of r)o.push({column:s.name,table:s.table.name||"",full:`${s.table.name}.${s.name}`,type:s.type});let a=o.reduce((s,m)=>(s[m.full]=m.type,s),{});return{getAllColumns(){return o},hasColumn(s){return!!a[s]||s==="*"},getAvailableJoins:()=>{let s=[],m=new Set(t);for(let c of r)if(c.meta?.referencedBy?.forEach(l=>{m.has(l.table)||s.push({id:[l.table,l.field,c.name,c.table.name].join("."),fromColumn:l.field,fromTable:l.table,toColumn:c.name,toTable:c.table.name,direction:"in"})}),c.meta?.refs){let l=c.meta.refs;m.has(l.table)||s.push({id:[c.name,c.table.name,l.table,l.field].join("."),fromColumn:c.name,fromTable:c.table.name,toColumn:l.field,toTable:l.table,direction:"out"})}return s},getColumnByName:(s,m)=>{for(let c of r)if(c.name===m&&c.table.name===s)return c}}};async function ta(e,t,r){return R.save(R.create({user:{id:e},team:{id:t},dataSource:{id:r.datasourceId},name:r.name,opts:r.opts}))}var Te=async(e,t)=>{let{datasourceId:r,size:o=20,page:a}=t,{table:n,joins:u,groupBy:s,orderBy:m}=t.opts,c=await ge(r);if(!c)throw new i(404,"Datasource not found");let l=tr(t.opts.columns,t.opts.groupBy,t.opts.aggregations),p=er(t.opts),d=await hr(r,p),N=d.getAllColumns(),k;l&&l.length>0?k=l:k=N.map(I=>({column:I.full})),k.forEach(I=>{if(!d.hasColumn(I.column))throw new i(400,`Invalid column ${I.column}`)});let eo=ta(e.user.id,e.user.currentTeamId,t),x=ke(n,c);x.setLimit(o+1),x.setOffset(o*a),x.setColumns(k),u&&u.forEach(x.addJoin),m.length>0&&m.forEach(({column:I,direction:so})=>{x.hasAlias(I)&&x.addOrderBy(pe[c.dbType].escape(I),so)}),s&&s.length>0&&s.forEach(I=>{d.hasColumn(I.value)&&x.addGroupBy({column:I.value,fn:I.fn,distinct:I.distinct})}),Ue(t.opts.filters,d.getColumnByName).forEach(I=>{I.fn&&cr(I.fn)?x.addHaving(I):x.addWhere(I)});let{sql:to,params:ro}=x.build(),ee=await(await $(U(c,!0),c.dbType,e)).executeQuery({sql:to,params:ro,type:"SELECT",allowBulkUpdate:!1}),Be=ee.rows.length>o;Be&&ee.rows.pop();let{id:oo}=await eo,Fe=rr(k,ee.columns,d.getColumnByName),{hooks:ao,entities:no}=or(Fe);return{...ee,queryHistoryId:oo,tables:p,allColumns:N,availableHooks:ao,availableEntities:no,availableJoins:d.getAvailableJoins(),columns:Fe,hasMore:Be}},br=async(e,t)=>{let r=await ge(t.dataSourceId);if(!r)throw new i(400,"Invalid datasource");let o=await $(U(r,!0),r.dbType,e),a=ke(t.table,r);a.setLimit(2);for(let[m,c]of Object.entries(t.props))a.addWhere({value:[{value:c}],column:m});let{sql:n,params:u}=a.build(),s=await o.executeQuery({sql:n,params:u,type:"SELECT",allowBulkUpdate:!1});if(s.rows.length>1)throw new i(400,"Found multiple rows for given query");if(s.rows.length<1)throw new i(404,"Entity not found");return{entity:s.rows[0],columns:s.columns,sql:n}},wr=async(e,t)=>{let r=await ge(t.datasourceId);if(!r)throw new i(404,"Data source not found");if(!r.allowUpdate)throw new i(403,"This datasource does not allow update operations");let o=yr(t.table,r);o.setParams(t.values),Ue(t.filters,()=>{}).forEach(s=>{o.addWhere(s)});let{sql:a,params:n}=o.build();return(await $(U(r,!0),r.dbType,e)).executeQuery({sql:a,params:n,type:"UPDATE",allowBulkUpdate:!1})},Sr=async(e,t)=>{let r=await ge(t.datasourceId);if(!r)throw new i(404,"Data source not found");if(!r.allowInsert)throw new i(403,"This datasource does not allow insert operations");let o=Tr(t.table,r);o.setValues(t.values);let{sql:a,params:n}=o.build();return(await $(U(r,!0),r.dbType,e)).executeQuery({sql:a,type:"INSERT",params:n,allowBulkUpdate:!1})};async function ge(e){return E.findOne({where:{id:e},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser","allowUpdate","allowInsert"]})}var Er=e=>{},ra=["--",";","DROP","drop"],Ir=([e,t])=>{if(typeof t=="string"&&t.startsWith("=")){let r=t;ra.forEach(o=>{if(r.includes(o))throw new i(400,"Invalid input value for "+e)})}},Cr=e=>{if(!e.table)throw new i(400,"Table is required");Object.entries(e.values).forEach(Ir)},Rr=e=>{if(!e.table)throw new i(400,"Table is required");Object.entries(e.values).forEach(Ir)};var Nr=h(e=>{e.route({method:"post",url:"/:dsId/select",handler:async t=>{let r=f(t,Er);return{data:await Te(t,r)}}}),e.route({method:"get",url:"/:dsId/entity/:table",handler:async t=>{let{dsId:r,table:o}=y(t),a=v(t);return{data:await br(t,{table:o,dataSourceId:r,props:a})}}}),e.route({method:"post",url:"/:dsId/insert",config:{requireRole:S("editor")},handler:async t=>{let r=f(t,Cr);return{data:await Sr(t,r)}}}),e.route({method:"post",url:"/:dsId/update",config:{requireRole:S("editor")},handler:async t=>{let r=f(t,Rr);return{data:await wr(t,r)}}})});var Ar=h(e=>{e.get("/",{config:{isPublic:!0}},async()=>({data:{active:!0,version:T.str("SERVER_VERSION")}}))});var Pr=h(e=>{e.route({method:"get",url:"/:id/users",handler:async t=>{let{id:r}=y(t),o=await F.findOne({where:{id:r},relations:{users:{user:!0}}});if(!o)throw new i(404,"Team not found");return{data:o.users.map(a=>({role:a.role,id:a.user.id,name:a.user.username}))}}}),e.route({method:"post",url:"/",config:{requireRole:S("editor")},handler:async t=>b.transaction(async()=>{let r=t.user.id,o=f(t),a=w.create();a.id=r;let n=F.create(o);await F.save(n);let u=C.create({user:a,team:n});return await C.save(u),{data:n}})}),e.route({method:"patch",url:"/:id/user-role",config:{requireRole:S("admin")},handler:async t=>{let{id:r}=y(t),{role:o,userId:a}=f(t,({role:u})=>{if(u==="owner")throw new i(400,"Only one owner is allowed")});if((await C.findOneBy({user:{id:a},team:{id:r}}))?.role==="owner")throw new i(400,"Cannot change owner role");await C.update({user:{id:a},team:{id:r}},{role:o})}}),e.route({method:"delete",url:"/:id",config:{requireRole:S("admin")},handler:async t=>b.transaction(async()=>{let{id:r}=y(t),{userId:o}=v(t);if((await C.findOneBy({user:{id:o},team:{id:r}}))?.role==="owner")throw new i(400,"Cannot delete team owner");await w.update(o,{currentTeam:null}),await C.delete({user:{id:o},team:{id:r}}),await w.delete({id:o})})})});var qe=O(require("bcryptjs")),Z=async e=>{let t=await qe.default.genSalt(10);return qe.default.hash(e,t)};var Or=h(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=await w.findOne({where:{id:t.user.id},relations:{currentTeam:{team:!0}}});if(!r)throw new i(404,"User not found");return{data:{id:r.id,teamId:r.currentTeam?.team.id,teamName:r.currentTeam?.team.name,teamRole:r.currentTeam?.role,username:r.username}}}}),e.route({method:"patch",url:"/",handler:async t=>{let r=t.user.id,o=f(t);if(o.password&&(o.password=await Z(o.password)),!(await w.update(r,o)).affected)throw new i(404,"User not found");let n=await w.findOne({where:{id:r},relations:{currentTeam:{team:!0}}});return{data:{id:n?.id,teamId:n?.currentTeam?.team.id,teamName:n?.currentTeam?.team.name,teamRole:n?.currentTeam?.role,username:n?.username}}}}),e.route({method:"post",url:"/",config:{requireRole:S("admin")},handler:async t=>b.transaction(async()=>{let r=f(t),o=await Z(r.password),a=await w.save(w.create({username:r.username,password:o})),n=await C.save(C.create({role:"read_only",team:{id:r.teamId},user:{id:a.id}}));await w.update(a.id,{currentTeam:{id:n.id}})})})});var Dr=h(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=t.user.id,o=await W.findOneBy({user:{id:r}});return o||(o=await W.save(W.create({user:{id:r}}))),{data:o}}}),e.route({method:"patch",url:"/",handler:async t=>{let{settings:r}=f(t);if(!r.id)throw new i(400,"Settings id is required!");if(!(await W.update(r.id,r)).affected)throw new i(404,"You do not own these settings!");return{data:await W.findOneBy({id:r.id})}}})});function j(e,...t){let r=[...t];if(e.searchAll&&r.push(e.searchAll),e.filters)for(let o of e.filters)o.value&&r.push(o.value);return r.map(o=>o.toLowerCase()).join(",")}var xr=h(e=>{e.route({method:"post",url:"/",config:{requireRole:S("editor")},handler:async t=>{let r=f(t),o=await R.findOne({where:{id:r.queryId}});if(!o)throw new i(400,"Query not found");let a=await _.save(_.create({isPersonal:!1,team:{id:t.user.currentTeamId},user:{id:t.user.id},query:{id:r.queryId},searchString:j(o.opts,r.name)}));return await R.update(r.queryId,{name:r.name}),{data:a}}}),e.route({method:"delete",url:"/:id",config:{requireRole:S("editor")},handler:async t=>{let{id:r}=y(t);if(!(await _.delete({id:r})).affected)return{status:404,data:"Query not found"}}}),e.route({method:"patch",url:"/:id",handler:async t=>await b.transaction(async()=>{let{id:r}=y(t),o=f(t,u=>{if(!u.name)throw new i(400,"Name is required")}),a=await _.findOne({where:{id:r},relations:{query:!0}});if(!a)throw new i(400,"Query not found");let n=j(a.query.opts,o.name);return await Promise.all([_.update({id:r},{searchString:n}),R.update({id:a.query.id},{name:o.name})]),{data:!0}})})});var vr=e=>{if(!e.queryId&&!(e.opts&&e.name))throw new i(400,"Either queryId or name and opts are required")};var _r=h(e=>{e.route({method:"get",url:"/",handler:async t=>{let{currentTeamId:r,id:o}=t.user;return{data:(await A.find({where:{team:{id:r},user:{id:o},archived:!1},select:["id","name"]})).map(n=>({name:n.name,id:n.id}))}}}),e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=y(t),{currentTeamId:o,id:a}=t.user,n=await A.findOne({where:{id:r,team:{id:o},user:{id:a}}});if(!n)throw new i(404,"Not Found");return{data:n}}}),e.route({method:"post",url:"/",handler:async t=>{let{opts:r,name:o,queryId:a}=f(t,vr),n,u,s=o;if(r)u=r.dataSourceId,n=r;else{let c=await R.findOne({where:{id:a},relations:{dataSource:!0}});if(!c)throw new i(404,"Query not Found");u=c.dataSource.id,n={table:c.opts.table,filters:c.opts.filters,joins:c.opts.joins,orderBy:c.opts.orderBy,columns:c.opts.columns,groupBy:c.opts.groupBy,searchAll:c.opts.searchAll,aggregations:c.opts.aggregations,dataSourceId:c.dataSource.id,page:0,size:50},o||(s=c.name)}return{data:await A.save(A.create({name:s||new Date().toISOString(),opts:n||{},dataSource:{id:u},user:{id:t.user.id},team:{id:t.user.currentTeamId}}))}}}),e.route({method:"post",url:"/:id/run",handler:async t=>{let{id:r}=y(t),o=f(t),a=await A.findOne({where:{id:r},relations:{user:!0}});if(!a)throw new i(404,"Not found");if(a.user?.id!==t.user.id)throw new i(404,"Not found");return o&&A.update(r,{opts:o||{},searchString:j(o,a.name),updatedAt:new Date}),{data:{result:await Te(t,{datasourceId:o.dataSourceId,size:o.size,name:a.name,page:o.page,opts:{table:o.table,filters:o.filters,joins:o.joins,orderBy:o.orderBy,columns:o.columns,groupBy:o.groupBy,searchAll:o.searchAll,aggregations:o.aggregations}})}}}}),e.route({method:"patch",url:"/:id",handler:async t=>{let{id:r}=y(t),o=f(t),a=await A.findOne({where:{id:r,user:{id:t.user.id}}});if(!a)throw new i(404,"Not Found");let n=a.searchString;return o.name&&(n=j(a.opts,o.name)),await A.update(r,{...o,searchString:n}),{data:{id:r}}}}),e.route({method:"delete",url:"/:id",handler:async t=>{let{id:r}=y(t),o=t.user.id;return await A.delete({id:r,user:{id:o}}),{data:!0}}})});var kr=require("node:crypto");var Ur=require("node:crypto"),Lr={teamName:"Default Team",username:"admin"},oa=async()=>{let e=await F.findOneBy({});return e||F.save(F.create({name:Lr.teamName}))},he=async e=>{let t=await C.findOne({where:{role:"owner"},relations:{user:!0}});if(t)return t.user;let r=await oa(),o=await Z(e?.password||(0,Ur.randomBytes)(32).toString("hex")),a=await w.save(w.create({username:e?.name||Lr.username,password:o})),n=await C.save(C.create({user:a,team:r,role:"owner"}));return await w.update(a.id,{currentTeam:n}),a};var be={setupAccessToken:void 0},qr=()=>(be.setupAccessToken=(0,kr.randomBytes)(32).toString("hex"),be.setupAccessToken),aa=e=>{if(!be.setupAccessToken)throw new i(400,"Setup already performed");if(!e||e!==be.setupAccessToken)throw new i(400,"Invalid setup access token")},H=async()=>D.skipAuth?!1:await w.count()<1,Br=async e=>{aa(e.setupAccessToken),await he({name:e.userName,password:e.userPassword})};var Fr=h(e=>{e.route({method:"get",url:"/client.config.js",handler:(t,r)=>{let o={skipAuth:D.skipAuth,modeName:D.name,usesCustomDb:Ye(),serverVersion:T.str("SERVER_VERSION","--")};return r.type("application/javascript").send(`window.__CLIENT_CONFIG__ = ${JSON.stringify(o)};`)}}),e.route({method:"get",url:"/",handler:async(t,r)=>await H()?r.redirect("/setup"):r.sendFile("index.html")}),e.route({method:"get",url:"/setup",handler:async(t,r)=>await H()?r.sendFile("setup.html"):r.redirect("/")})});var Mr=e=>{if(!e.setupAccessToken)throw new i(400,"Invalid setup access token");if(!e.userPassword||e.userPassword.length<8)throw new i(400,"Password should be at least 8 chars long");if(!e.userName)throw new i(400,"User name is required")};var Qr=h(e=>{e.route({method:"post",url:"/",config:{isPublic:!0},handler:async t=>{if(!await H())throw new i(400,"Setup has already been completed");let o=f(t,Mr);return await Br(o),{data:!0}}})});var na=[[Fr,"/"],[ht,"/api/auth"],[zt,"/api/data-sources"],[Jt,"/api/project"],[Xt,"/api/queries"],[Nr,"/api/runner"],[Ar,"/api/status"],[Pr,"/api/teams"],[Or,"/api/users"],[Dr,"/api/user-settings"],[xr,"/api/saved-queries"],[_r,"/api/workbench-tabs"],[Qr,"/api/setup"]],$r=e=>{for(let[t,r]of na)e.register(t,{prefix:r}),console.log("Registered "+r)};var sa=e=>e.routeOptions.config.isPublic?!0:!e.url.startsWith("/api/"),ia=async()=>C.findOne({where:{role:"owner"},relations:{user:!0,team:!0}}),ua=async e=>{let t=await ia();if(!t)throw new i(401,"User is not part of a team");e.user={id:t.user.id,currentTeamId:t.team.id,currentTeamRole:t.role}},ca=async e=>{let t=e.headers.authorization;if(!t)throw new i(401,"Missing auth token");let[r,o]=t.split(" "),{userId:a}=await ft(o),n=await w.findOne({where:{id:a},select:{id:!0,currentTeam:{role:!0,team:{id:!0}}},relations:{currentTeam:{team:!0}}});if(!n)throw new i(401,"Unauthorized");e.user={id:a,currentTeamId:n.currentTeam.team.id,currentTeamRole:n.currentTeam.role}},Hr=async e=>{sa(e)||(D.skipAuth?await ua(e):await ca(e))};var Wr=(e,t)=>{e.__connections&&e.__connections.forEach(r=>{r.close()})};var Yr=e=>{e.addHook("onRequest",Hr),e.addHook("onRequest",Kt),e.addHook("onResponse",Wr)};var Gr=e=>{e.setNotFoundHandler((t,r)=>{if(t.raw.url?.startsWith("/api/")){r.code(404).send({error:"API route not found"});return}r.sendFile("index.html")}),e.setErrorHandler((t,r,o)=>{console.error(t),t instanceof i?o.status(t.status).send({error:t.message}):o.status(500).send({error:"Internal Server Error"})})};var jr=O(require("@fastify/cookie")),Kr=O(require("@fastify/cors"));var Vr=O(require("@fastify/static")),zr=require("node:path"),Jr=e=>{e.register(jr.default,{}),e.register(Kr.default,{origin:V.allowedOrigins,methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"],credentials:!0}),e.register(Vr.default,{root:(0,zr.join)(__dirname,"web")})};(async function(){let t=(0,Xr.default)({querystringParser:o=>Zr.default.parse(o)});if(We(),Jr(t),Yr(t),$r(t),Gr(t),await t.after(),await it(),t.listen({port:V.port,host:V.host},(o,a)=>{o&&(console.error(o),process.exit(1)),console.log(`Server listening at ${a}`)}),await H()){let o=qr();console.log(`Setup access token:
|
|
58
58
|
${o}`),console.log("Use the above token to finish the setup process when opening the app for the first time.")}else await he()})();
|