@dataramen/cli 0.0.46-beta.2 → 0.0.46

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.
@@ -1,9 +1,9 @@
1
- "use strict";var qt=Object.create;var Re=Object.defineProperty;var Bt=Object.getOwnPropertyDescriptor;var Ft=Object.getOwnPropertyNames;var Qt=Object.getPrototypeOf,kt=Object.prototype.hasOwnProperty;var $t=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Ft(t))!kt.call(e,a)&&a!==r&&Re(e,a,{get:()=>t[a],enumerable:!(o=Bt(t,a))||o.enumerable});return e};var _=(e,t,r)=>(r=e!=null?qt(Qt(e)):{},$t(t||!e||!e.__esModule?Re(r,"default",{value:e,enumerable:!0}):r,e));var K=require("dotenv"),V=require("node:path"),Se=require("node:fs"),Ht=(()=>{try{let e=(0,Se.readFileSync)((0,V.join)(__dirname,"..","package.json"),"utf8");return JSON.parse(e)}catch{return{version:"0.0.0"}}})(),be=[];process.argv[2]&&be.push((0,V.resolve)(process.argv[2]));(0,K.config)({path:be});(0,K.populate)(process.env,{SERVER_VERSION:Ht.version,APP_DB_TYPE:"sqlite",APP_DB_DATABASE:"<home>/.dataramen/.runtime/db.sqlite3",PROD:"true"},{override:!1});var Yt=["SYMM_ENCRYPTION_KEY","JWT_SECRET","JWT_REFRESH_SECRET"],Ce=()=>{let e=[];for(let t of Yt)process.env[t]||e.push(t);if(e.length>0)throw new Error("Following env variables are required but not provided: "+e.join(", "))};function Wt(e,t=void 0){return process.env[e]||t}function jt(e,t=void 0){let r=process.env[e];if(!r)return t;let o=Number(r);return!isNaN(o)&&r.trim()!==""?o:t}function Gt(e){return process.env[e]==="true"||process.env[e]==="TRUE"||process.env[e]==="1"}var m={str:Wt,num:jt,bool:Gt};var as=require("reflect-metadata"),_t=_(require("fastify")),Pt=_(require("@fastify/cors")),Dt=_(require("@fastify/static")),Ut=_(require("qs"));var s=class extends Error{constructor(r,o){super(o);this.status=r;this.message=o}};var Ue=require("typeorm");var Ne=require("typeorm");var h=m.str("APP_DB_TYPE")==="sqlite"?"datetime":"timestamp";var ne=new Ne.EntitySchema({name:"DatabaseInspection",tableName:"db_inspection",columns:{id:{type:String,unique:!0,primary:!0,generated:"uuid"},tableName:{nullable:!0,type:String},columns:{type:"json",nullable:!0},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"}},relations:{datasource:{target:()=>"DataSource",type:"many-to-one",joinTable:!1,cascade:!0}}});var Ie=require("typeorm");var se=new Ie.EntitySchema({name:"Team",tableName:"teams",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"}},relations:{users:{type:"one-to-many",target:()=>"UsersToTeams",inverseSide:"team"},queries:{type:"one-to-many",target:()=>"Query",inverseSide:"team"},datasources:{type:"one-to-many",target:()=>"DataSource",inverseSide:"team"}}});var Oe=require("typeorm");var ie=new Oe.EntitySchema({name:"User",tableName:"users",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},username:{type:String,unique:!0},password:{type:String}},relations:{teams:{type:"one-to-many",target:()=>"UsersToTeams",inverseSide:"user"},settings:{type:"one-to-one",target:()=>"UserSettings",inverseSide:"user"},currentTeam:{type:"one-to-one",target:()=>"UsersToTeams",inverseSide:"user",joinColumn:!0}}});var Ae=require("typeorm");var ue=new Ae.EntitySchema({name:"UserSettings",tableName:"user_settings",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"}},relations:{user:{type:"one-to-one",target:()=>"User",inverseSide:"settings",joinColumn:!0}}});var _e=require("typeorm");var ce=new _e.EntitySchema({name:"DataSource",tableName:"data_sources",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},dbUrl:{type:String},dbPort:{type:Number,nullable:!0},dbUser:{type:String},dbPassword:{type:String,nullable:!0,select:!1},dbPasswordIv:{type:String,nullable:!0,select:!1},dbPasswordTag:{type:String,nullable:!0,select:!1},dbType:{type:String},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},name:{type:String},description:{type:String,nullable:!0},dbDatabase:{type:String},dbSchema:{type:String,nullable:!0},allowInsert:{type:Boolean,default:!1},allowUpdate:{type:Boolean,default:!1},lastInspected:{type:h,nullable:!0,default:null},status:{type:String,nullable:!0}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"datasources",joinColumn:!0},inspections:{type:"one-to-many",target:()=>"DatabaseInspection",inverseSide:"datasource"},queries:{type:"one-to-many",target:()=>"Query",inverseSide:"dataSource"},owner:{type:"many-to-one",target:()=>"User",joinColumn:!0}}});var xe=_(require("node:os")),ve=require("node:path");var Pe=require("typeorm");var le=new Pe.EntitySchema({name:"Query",tableName:"query",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},opts:{type:"json",default:"{}"},isTrash:{type:Boolean,default:!1,nullable:!0},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP",onUpdate:"CURRENT_TIMESTAMP"}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"queries",joinColumn:!0},dataSource:{type:"many-to-one",target:()=>"DataSource",inverseSide:"datasources",joinColumn:!0}}});var De=require("typeorm"),me=new De.EntitySchema({name:"UsersToTeams",tableName:"users_to_teams",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},role:{type:"varchar",default:"admin",nullable:!1}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"users"},user:{type:"many-to-one",target:()=>"User",inverseSide:"teams"}}});function Kt(){let e=m.str("APP_DB_DATABASE");if(!e)throw new Error("Bad value for TYPEORM_DATABASE. Please check your config!");return e.startsWith("<home>")&&(e=e.replace("<home>",xe.default.homedir())),e}var w=new Ue.DataSource({type:m.str("APP_DB_TYPE"),database:Kt(),host:m.str("APP_DB_HOST"),username:m.str("APP_DB_USERNAME"),password:m.str("APP_DB_PASSWORD"),port:m.num("APP_DB_PORT"),schema:m.str("APP_DB_SCHEMA"),logging:m.bool("APP_DB_LOGGING"),migrationsRun:!0,migrations:[ve.posix.join(__dirname,"migrations","*.js")],entities:[ne,ce,se,ie,me,ue,le]}),Me=async()=>{if(!w.isInitialized)return w.initialize();throw new Error("Already initialized")},P=w.getRepository(ne),T=w.getRepository(ce),x=w.getRepository(se),b=w.getRepository(ie),C=w.getRepository(me),B=w.getRepository(ue),I=w.getRepository(le);var E=e=>(t,r,o)=>{e(t),o()};var k=require("jose");var Le=new TextEncoder,qe=Le.encode(m.str("JWT_SECRET")),Be=Le.encode(m.str("JWT_REFRESH_SECRET")),de=async({userId:e})=>new k.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("1h").sign(qe),pe=async({userId:e})=>new k.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("10d").sign(Be),Fe=async(e,t)=>{try{let{payload:r}=await(0,k.jwtVerify)(e,t);if(!r.sub)throw new s(401,"Failed to verify access token");return{userId:r.sub}}catch(r){throw r instanceof s?r:r instanceof Error?new s(401,r.message):new s(401,"Failed to verify refresh token")}},Qe=async e=>Fe(e,qe),ke=async e=>Fe(e,Be);var g=(e,t)=>{let r=e.body;return t&&t(r),r},v=(e,t)=>{let r=e.query;return t&&t(r),r},R=(e,t)=>{let r=e.params;return t&&t(r),r};var He=_(require("bcryptjs"));var $e=e=>{if(!e?.username)throw new s(400,"Username is required");if(!e?.password)throw new s(400,"Password is required")};var z="DATARAMEN_refresh_token",fe={httpOnly:!0,secure:m.bool("PROD"),sameSite:m.bool("PROD"),path:"/",maxAge:10*24*60*60},Ye=E(e=>{e.route({method:"post",url:"/login",config:{isPublic:!0},handler:async(t,r)=>{let{username:o,password:a}=g(t,$e),n=await b.findOne({where:{username:o}});if(!n||!He.default.compareSync(a,n.password))throw new s(401,"Invalid credentials");let[i,u]=await Promise.all([de({userId:n?.id}),pe({userId:n?.id})]);return r.setCookie(z,u,fe),{data:{accessToken:i}}}}),e.route({method:"post",url:"/refresh",config:{isPublic:!0},handler:async(t,r)=>{let o=t.cookies[z];if(!o)return r.code(401).send({message:"Missing refresh token"});let{userId:a}=await ke(o),[n,i]=await Promise.all([de({userId:a}),pe({userId:a})]);return r.setCookie(z,i,fe),{data:{accessToken:n}}}}),e.route({method:"post",url:"/logout",config:{isPublic:!0},handler:async(t,r)=>(r.clearCookie(z,fe),{data:!0})})});var We=e=>{if(!e.dbUrl)throw new s(400,"url is required");if(!e.dbUser)throw new s(400,"user is required");if(!e.dbType)throw new s(400,"type is required");if(!e.name)throw new s(400,"name is required");if(!e.dbDatabase)throw new s(400,"database is required")};var Ge=_(require("mysql2/promise"));var Vt=({database:e,password:t,user:r,url:o})=>Ge.default.createConnection({host:o,user:r,database:e,password:t}),zt=async e=>{let t=`
1
+ "use strict";var Lt=Object.create;var Ee=Object.defineProperty;var qt=Object.getOwnPropertyDescriptor;var Ft=Object.getOwnPropertyNames;var Bt=Object.getPrototypeOf,Qt=Object.prototype.hasOwnProperty;var kt=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Ft(t))!Qt.call(e,a)&&a!==r&&Ee(e,a,{get:()=>t[a],enumerable:!(o=qt(t,a))||o.enumerable});return e};var _=(e,t,r)=>(r=e!=null?Lt(Bt(e)):{},kt(t||!e||!e.__esModule?Ee(r,"default",{value:e,enumerable:!0}):r,e));var G=require("dotenv"),K=require("node:path"),Re=require("node:fs"),$t=(()=>{try{let e=(0,Re.readFileSync)((0,K.join)(__dirname,"..","package.json"),"utf8");return JSON.parse(e)}catch{return{version:"0.0.0"}}})(),Se=[];process.argv[2]&&Se.push((0,K.resolve)(process.argv[2]));(0,G.config)({path:Se});(0,G.populate)(process.env,{SERVER_VERSION:$t.version,APP_DB_TYPE:"sqlite",APP_DB_DATABASE:"<home>/.dataramen/.runtime/db.sqlite3",PROD:"true"},{override:!1});var Ht=["SYMM_ENCRYPTION_KEY","JWT_SECRET","JWT_REFRESH_SECRET"],be=()=>{let e=[];for(let t of Ht)process.env[t]||e.push(t);if(e.length>0)throw new Error("Following env variables are required but not provided: "+e.join(", "))};function Yt(e,t=void 0){return process.env[e]||t}function Wt(e,t=void 0){let r=process.env[e];if(!r)return t;let o=Number(r);return!isNaN(o)&&r.trim()!==""?o:t}function jt(e){return process.env[e]==="true"||process.env[e]==="TRUE"||process.env[e]==="1"}var m={str:Yt,num:Wt,bool:jt};var os=require("reflect-metadata"),At=_(require("fastify")),_t=_(require("@fastify/cors")),Pt=_(require("@fastify/static")),Dt=_(require("qs"));var s=class extends Error{constructor(r,o){super(o);this.status=r;this.message=o}};var De=require("typeorm");var Ce=require("typeorm");var h=m.str("APP_DB_TYPE")==="sqlite"?"datetime":"timestamp";var ae=new Ce.EntitySchema({name:"DatabaseInspection",tableName:"db_inspection",columns:{id:{type:String,unique:!0,primary:!0,generated:"uuid"},tableName:{nullable:!0,type:String},columns:{type:"json",nullable:!0},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"}},relations:{datasource:{target:()=>"DataSource",type:"many-to-one",joinTable:!1,cascade:!0}}});var Ne=require("typeorm");var ne=new Ne.EntitySchema({name:"Team",tableName:"teams",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"}},relations:{users:{type:"one-to-many",target:()=>"UsersToTeams",inverseSide:"team"},queries:{type:"one-to-many",target:()=>"Query",inverseSide:"team"},datasources:{type:"one-to-many",target:()=>"DataSource",inverseSide:"team"}}});var Ie=require("typeorm");var se=new Ie.EntitySchema({name:"User",tableName:"users",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},username:{type:String,unique:!0},password:{type:String}},relations:{teams:{type:"one-to-many",target:()=>"UsersToTeams",inverseSide:"user"},settings:{type:"one-to-one",target:()=>"UserSettings",inverseSide:"user"},currentTeam:{type:"one-to-one",target:()=>"UsersToTeams",inverseSide:"user",joinColumn:!0}}});var Oe=require("typeorm");var ie=new Oe.EntitySchema({name:"UserSettings",tableName:"user_settings",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"}},relations:{user:{type:"one-to-one",target:()=>"User",inverseSide:"settings",joinColumn:!0}}});var Ae=require("typeorm");var ue=new Ae.EntitySchema({name:"DataSource",tableName:"data_sources",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},dbUrl:{type:String},dbPort:{type:Number,nullable:!0},dbUser:{type:String},dbPassword:{type:String,nullable:!0,select:!1},dbPasswordIv:{type:String,nullable:!0,select:!1},dbPasswordTag:{type:String,nullable:!0,select:!1},dbType:{type:String},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},name:{type:String},description:{type:String,nullable:!0},dbDatabase:{type:String},dbSchema:{type:String,nullable:!0},allowInsert:{type:Boolean,default:!1},allowUpdate:{type:Boolean,default:!1},lastInspected:{type:h,nullable:!0,default:null},status:{type:String,nullable:!0}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"datasources",joinColumn:!0},inspections:{type:"one-to-many",target:()=>"DatabaseInspection",inverseSide:"datasource"},queries:{type:"one-to-many",target:()=>"Query",inverseSide:"dataSource"},owner:{type:"many-to-one",target:()=>"User",joinColumn:!0}}});var Ue=_(require("node:os")),xe=require("node:path");var _e=require("typeorm");var ce=new _e.EntitySchema({name:"Query",tableName:"query",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},opts:{type:"json",default:"{}"},isTrash:{type:Boolean,default:!1,nullable:!0},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP",onUpdate:"CURRENT_TIMESTAMP"}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"queries",joinColumn:!0},dataSource:{type:"many-to-one",target:()=>"DataSource",inverseSide:"datasources",joinColumn:!0}}});var Pe=require("typeorm"),le=new Pe.EntitySchema({name:"UsersToTeams",tableName:"users_to_teams",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},role:{type:"varchar",default:"admin",nullable:!1}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"users"},user:{type:"many-to-one",target:()=>"User",inverseSide:"teams"}}});function Gt(){let e=m.str("APP_DB_DATABASE");if(!e)throw new Error("Bad value for TYPEORM_DATABASE. Please check your config!");return e.startsWith("<home>")&&(e=e.replace("<home>",Ue.default.homedir())),e}var E=new De.DataSource({type:m.str("APP_DB_TYPE"),database:Gt(),host:m.str("APP_DB_HOST"),username:m.str("APP_DB_USERNAME"),password:m.str("APP_DB_PASSWORD"),port:m.num("APP_DB_PORT"),schema:m.str("APP_DB_SCHEMA"),logging:m.bool("APP_DB_LOGGING"),migrationsRun:!0,migrations:[xe.posix.join(__dirname,"migrations","*.js")],entities:[ae,ue,ne,se,le,ie,ce]}),ve=async()=>{if(!E.isInitialized)return E.initialize();throw new Error("Already initialized")},P=E.getRepository(ae),T=E.getRepository(ue),x=E.getRepository(ne),b=E.getRepository(se),C=E.getRepository(le),q=E.getRepository(ie),O=E.getRepository(ce);var R=e=>(t,r,o)=>{e(t),o()};var Q=require("jose");var Me=new TextEncoder,Le=Me.encode(m.str("JWT_SECRET")),qe=Me.encode(m.str("JWT_REFRESH_SECRET")),me=async({userId:e})=>new Q.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("1h").sign(Le),de=async({userId:e})=>new Q.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("10d").sign(qe),Fe=async(e,t)=>{try{let{payload:r}=await(0,Q.jwtVerify)(e,t);if(!r.sub)throw new s(401,"Failed to verify access token");return{userId:r.sub}}catch(r){throw r instanceof s?r:r instanceof Error?new s(401,r.message):new s(401,"Failed to verify refresh token")}},Be=async e=>Fe(e,Le),Qe=async e=>Fe(e,qe);var g=(e,t)=>{let r=e.body;return t&&t(r),r},v=(e,t)=>{let r=e.query;return t&&t(r),r},S=(e,t)=>{let r=e.params;return t&&t(r),r};var $e=_(require("bcryptjs"));var ke=e=>{if(!e?.username)throw new s(400,"Username is required");if(!e?.password)throw new s(400,"Password is required")};var V="DATARAMEN_refresh_token",pe={httpOnly:!0,secure:m.bool("PROD"),sameSite:m.bool("PROD"),path:"/",maxAge:10*24*60*60},He=R(e=>{e.route({method:"post",url:"/login",config:{isPublic:!0},handler:async(t,r)=>{let{username:o,password:a}=g(t,ke),n=await b.findOne({where:{username:o}});if(!n||!$e.default.compareSync(a,n.password))throw new s(401,"Invalid credentials");let[i,u]=await Promise.all([me({userId:n?.id}),de({userId:n?.id})]);return r.setCookie(V,u,pe),{data:{accessToken:i}}}}),e.route({method:"post",url:"/refresh",config:{isPublic:!0},handler:async(t,r)=>{let o=t.cookies[V];if(!o)return r.code(401).send({message:"Missing refresh token"});let{userId:a}=await Qe(o),[n,i]=await Promise.all([me({userId:a}),de({userId:a})]);return r.setCookie(V,i,pe),{data:{accessToken:n}}}}),e.route({method:"post",url:"/logout",config:{isPublic:!0},handler:async(t,r)=>(r.clearCookie(V,pe),{data:!0})})});var Ye=e=>{if(!e.dbUrl)throw new s(400,"url is required");if(!e.dbUser)throw new s(400,"user is required");if(!e.dbType)throw new s(400,"type is required");if(!e.name)throw new s(400,"name is required");if(!e.dbDatabase)throw new s(400,"database is required")};var je=_(require("mysql2/promise"));var Kt=({database:e,password:t,user:r,url:o})=>je.default.createConnection({host:o,user:r,database:e,password:t}),Vt=async e=>{let t=`
2
2
  SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION
3
3
  FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
4
4
  WHERE CONSTRAINT_NAME = 'PRIMARY'
5
5
  ORDER BY TABLE_NAME, ORDINAL_POSITION;
6
- `,[r]=await e.execute(t),o={};return r.forEach(a=>{let n=a.TABLE_NAME,i=a.COLUMN_NAME;o[n]||(o[n]=[]),o[n].push(i)}),o},Jt=async e=>{let t=`
6
+ `,[r]=await e.execute(t),o={};return r.forEach(a=>{let n=a.TABLE_NAME,i=a.COLUMN_NAME;o[n]||(o[n]=[]),o[n].push(i)}),o},zt=async e=>{let t=`
7
7
  SELECT
8
8
  TABLE_NAME AS table_name,
9
9
  COLUMN_NAME AS field,
@@ -14,7 +14,7 @@
14
14
  WHERE
15
15
  REFERENCED_TABLE_NAME IS NOT NULL
16
16
  AND CONSTRAINT_SCHEMA = DATABASE();
17
- `,[r]=await e.execute(t),o={};return Array.isArray(r)&&r.forEach(a=>{o[a.table_name]||(o[a.table_name]={}),o[a.table_name][a.field]={refTable:a.referenced_table,refField:a.referenced_field}}),o},Xt=async(e,t)=>{let o=(await t.query("SHOW TABLES"))[0],a=await Jt(t),n=await zt(t),i=o.map(async u=>{let y=Object.values(u)[0],l=`select COLUMN_NAME, DATA_TYPE from information_schema.columns where table_schema = '${e.database}' and table_name = '${y}'`,[d]=await t.query(l),p=a[y];return{columns:d.map(c=>({name:c.COLUMN_NAME,type:c.DATA_TYPE,isPrimary:n[y]?.includes(c.COLUMN_NAME),ref:p?.[c.COLUMN_NAME]?{table:p[c.COLUMN_NAME].refTable,field:p[c.COLUMN_NAME].refField}:void 0})).sort((c,S)=>c.isPrimary&&S.isPrimary?c.name.localeCompare(S.name):c.isPrimary?-1:1),createdAt:new Date,tableName:y,updatedAt:new Date}});return Promise.all(i)},je=async(e,t,r)=>{try{console.log(`[MYSQL CONN] Query: ${e}`);let[o,a]=await t.query({sql:e,rowsAsArray:!0}),n=o?.constructor?.name;if(n==="ResultSetHeader"){let i=o;if(i.affectedRows>1&&r.allowBulkUpdate!==!0)throw new Error("[MYSQL CONN] Bulk update performed without permission.");return{columns:[{column:"affectedRows",alias:"Affected rows",full:"affectedRows"}],rows:[[i.affectedRows]],query:e}}else if(n==="Array"){let i=o;return{columns:a?.map(u=>({column:u.orgName||u.name,table:u.orgTable,alias:u.name,full:u.orgTable?u.orgTable+"."+u.orgName:u.name}))||[],rows:i,query:e}}throw new Error(`[MYSQL CONN] Unknown result type: ${n}`)}catch(o){throw console.error(o),o instanceof s?o:new s(400,o.message)}},Zt=async(e,t)=>{await e.beginTransaction();try{let r=await t();return await e.commit(),console.log("[MYSQL CONN] Commit"),r}catch(r){throw await e.rollback(),console.warn(r.message),console.log("[MYSQL CONN] Rollback"),r}},er=async(e,t)=>{await e.query("START TRANSACTION READ ONLY");try{let r=await t();return console.log("[MYSQL CONN] Read only rollback"),await e.query("ROLLBACK"),r}catch(r){throw console.warn(r.message),await e.query("ROLLBACK"),r}},Ke=async e=>{let t=await Vt(e),r=!1;return{dbType:"mysql",dataSource:e,inspectSchema:()=>Xt(e,t),executeQuery:(o,a)=>a.type==="SELECT"?er(t,()=>je(o,t,a)):Zt(t,()=>je(o,t,a)),checkConnection:async()=>t.ping(),isClosed:()=>r,close:async()=>{if(!r)return r=!0,t.destroy()}}};var ze=_(require("pg"));var tr=async({database:e,password:t,user:r,url:o,port:a})=>{let n=new ze.default.Client({host:o,user:r,database:e,password:t,port:a,query_timeout:1e4});return await n.connect(),n},rr=async e=>{let r=await e.query(`
17
+ `,[r]=await e.execute(t),o={};return Array.isArray(r)&&r.forEach(a=>{o[a.table_name]||(o[a.table_name]={}),o[a.table_name][a.field]={refTable:a.referenced_table,refField:a.referenced_field}}),o},Jt=async(e,t)=>{let o=(await t.query("SHOW TABLES"))[0],a=await zt(t),n=await Vt(t),i=o.map(async u=>{let d=Object.values(u)[0],l=`select COLUMN_NAME, DATA_TYPE from information_schema.columns where table_schema = '${e.database}' and table_name = '${d}'`,[p]=await t.query(l),c=a[d];return{columns:p.map(f=>({name:f.COLUMN_NAME,type:f.DATA_TYPE,isPrimary:n[d]?.includes(f.COLUMN_NAME),ref:c?.[f.COLUMN_NAME]?{table:c[f.COLUMN_NAME].refTable,field:c[f.COLUMN_NAME].refField}:void 0})).sort((f,w)=>f.isPrimary&&w.isPrimary?f.name.localeCompare(w.name):f.isPrimary?-1:1),createdAt:new Date,tableName:d,updatedAt:new Date}});return Promise.all(i)},We=async(e,t,r)=>{try{console.log(`[MYSQL CONN] Query: ${e}`);let[o,a]=await t.query({sql:e,rowsAsArray:!0}),n=o?.constructor?.name;if(n==="ResultSetHeader"){let i=o;if(i.affectedRows>1&&r.allowBulkUpdate!==!0)throw new Error("[MYSQL CONN] Bulk update performed without permission.");return{columns:[{column:"affectedRows",alias:"Affected rows",full:"affectedRows"}],rows:[[i.affectedRows]],query:e}}else if(n==="Array"){let i=o;return{columns:a?.map(u=>({column:u.orgName||u.name,table:u.orgTable,alias:u.name,full:u.orgTable?u.orgTable+"."+u.orgName:u.name}))||[],rows:i,query:e}}throw new Error(`[MYSQL CONN] Unknown result type: ${n}`)}catch(o){throw console.error(o),o instanceof s?o:new s(400,o.message)}},Xt=async(e,t)=>{await e.beginTransaction();try{let r=await t();return await e.commit(),console.log("[MYSQL CONN] Commit"),r}catch(r){throw await e.rollback(),console.warn(r.message),console.log("[MYSQL CONN] Rollback"),r}},Zt=async(e,t)=>{await e.query("START TRANSACTION READ ONLY");try{let r=await t();return console.log("[MYSQL CONN] Read only rollback"),await e.query("ROLLBACK"),r}catch(r){throw console.warn(r.message),await e.query("ROLLBACK"),r}},Ge=async e=>{let t=await Kt(e),r=!1;return{dbType:"mysql",dataSource:e,inspectSchema:()=>Jt(e,t),executeQuery:(o,a)=>a.type==="SELECT"?Zt(t,()=>We(o,t,a)):Xt(t,()=>We(o,t,a)),checkConnection:async()=>t.ping(),isClosed:()=>r,close:async()=>{if(!r)return r=!0,t.destroy()}}};var Ve=_(require("pg"));var er=async({database:e,password:t,user:r,url:o,port:a})=>{let n=new Ve.default.Client({host:o,user:r,database:e,password:t,port:a,query_timeout:1e4});return await n.connect(),n},tr=async e=>{let r=await e.query(`
18
18
  SELECT
19
19
  kcu.table_name,
20
20
  kcu.column_name,
@@ -28,7 +28,7 @@
28
28
  tc.constraint_type = 'PRIMARY KEY'
29
29
  ORDER BY
30
30
  kcu.table_name, kcu.ordinal_position;
31
- `),o={};return r.rows.forEach(a=>{let n=a.table_name,i=a.column_name;o[n]||(o[n]=[]),o[n].push(i)}),o},or=async e=>{let r=await e.query(`
31
+ `),o={};return r.rows.forEach(a=>{let n=a.table_name,i=a.column_name;o[n]||(o[n]=[]),o[n].push(i)}),o},rr=async e=>{let r=await e.query(`
32
32
  SELECT
33
33
  tc.table_name AS table_name,
34
34
  kcu.column_name AS field,
@@ -43,15 +43,15 @@
43
43
  ON ccu.constraint_name = tc.constraint_name
44
44
  AND ccu.table_schema = tc.table_schema
45
45
  WHERE tc.constraint_type = 'FOREIGN KEY';
46
- `),o={};return r.rows.forEach(a=>{o[a.table_name]||(o[a.table_name]={}),o[a.table_name][a.field]={refTable:a.referenced_table,refField:a.referenced_field}}),o},ar=async(e,t)=>{let r=`SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = '${e.schema}'`,a=(await t.query(r)).rows,n=await or(t),i=await rr(t),u=a.map(async y=>{let l=Object.values(y)[0],d=`
46
+ `),o={};return r.rows.forEach(a=>{o[a.table_name]||(o[a.table_name]={}),o[a.table_name][a.field]={refTable:a.referenced_table,refField:a.referenced_field}}),o},or=async(e,t)=>{let r=`SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = '${e.schema}'`,a=(await t.query(r)).rows,n=await rr(t),i=await tr(t),u=a.map(async d=>{let l=Object.values(d)[0],p=`
47
47
  SELECT column_name, data_type
48
48
  FROM information_schema.columns
49
49
  WHERE
50
50
  table_name = '${l}' and
51
51
  table_schema = '${e.schema}'
52
- `,{rows:p}=await t.query(d),c=n[l];return{columns:p.map(S=>({name:S.column_name,type:S.data_type,isPrimary:i[l]?.includes(S.column_name),ref:c?.[S.column_name]?{table:c[S.column_name].refTable,field:c[S.column_name].refField}:void 0})).sort((S,M)=>S.isPrimary&&M.isPrimary?S.name.localeCompare(M.name):S.isPrimary?-1:1),createdAt:new Date,tableName:l,updatedAt:new Date}});return Promise.all(u)},nr=async(e,t)=>{let r=`select relname, attname, concat(pg_class.oid, '-', attnum) as row_key
52
+ `,{rows:c}=await t.query(p),f=n[l];return{columns:c.map(w=>({name:w.column_name,type:w.data_type,isPrimary:i[l]?.includes(w.column_name),ref:f?.[w.column_name]?{table:f[w.column_name].refTable,field:f[w.column_name].refField}:void 0})).sort((w,I)=>w.isPrimary&&I.isPrimary?w.name.localeCompare(I.name):w.isPrimary?-1:1),createdAt:new Date,tableName:l,updatedAt:new Date}});return Promise.all(u)},ar=async(e,t)=>{let r=`select relname, attname, concat(pg_class.oid, '-', attnum) as row_key
53
53
  from pg_attribute
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 25;`;return(await t.query(r)).rows.reduce((a,n)=>(a[n.row_key]={table:n.relname,column:n.attname},a),{})},Ve=async(e,t,r)=>{try{console.log(`[PG CONN] Query: ${e}`);let{rows:o,fields:a,command:n,rowCount:i}=await t.query({text:e,rowMode:"array"});if(n==="UPDATE"||n==="INSERT"||n==="DELETE"){if(i!=null&&i>1&&r.allowBulkUpdate!==!0)throw new Error("[PG CONN] Bulk update performed without permission.");return{columns:[{column:"affectedRows",alias:"Affected rows",full:"affectedRows"}],rows:[[i]],query:e}}if(n==="SELECT"){let u=a.map(l=>`'${l.tableID}-${l.columnID}'`),y=await nr(u,t);return{columns:a.map(l=>{let d=y[`${l.tableID}-${l.columnID}`];return{column:d?.column||l.name,alias:l.name,table:d?.table||"",full:d?d.table+"."+d.column:l.name}}),rows:o,query:e}}throw new Error(`[PG CONN] Unsupported command: ${n}`)}catch(o){throw o instanceof s?o:new s(400,o.message)}},sr=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}},ir=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}},Je=async e=>{let t=await tr(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:()=>ar(e,t),executeQuery:(n,i)=>a(()=>i.type==="SELECT"?ir(t,()=>Ve(n,t,i)):sr(t,()=>Ve(n,t,i))),checkConnection:async()=>{},isClosed:()=>r,close:async()=>{if(!r)return r=!0,t.end()}}};var L=async(e,t,r)=>{try{let o;if(t==="mysql")o=await Ke(e);else if(t==="postgres")o=await Je(e);else throw new s(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 s?o:o?.code==="ECONNREFUSED"?new s(500,"Failed to connect to the database"):new s(500,o.message)}};var J=_(require("node:crypto"));var Xe="aes-256-gcm",ur=12,Ze=()=>{let e=m.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},cr=e=>{let t=J.default.randomBytes(ur),r=Ze(),o=J.default.createCipheriv(Xe,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")}},lr=({encrypted:e,iv:t,tag:r})=>{let o=Ze(),a=J.default.createDecipheriv(Xe,o,Buffer.from(t,"hex"));a.setAuthTag(Buffer.from(r,"hex"));let n=a.update(e,"hex","utf8");return n+=a.final("utf8"),n},X={encrypt:cr,decrypt:lr};var q=(e,t=!1)=>{if(t){let r=X.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 et=[{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:"contains"},{value:"NOT LIKE",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"}],mr=et.reduce((e,t)=>(e[t.value]=t.label,e),{}),Fo=et.reduce((e,t)=>(e[t.label]=t.value,e),{}),F=e=>e.map(t=>({label:mr[t],value:t})),Qo=F(["=","<>",">",">=","<","<=","IN","NOT IN","IS NULL","IS NOT NULL"]),ko=F(["=","<>","LIKE","NOT LIKE","IN","NOT IN","IS NULL","IS NOT NULL"]),$o=F(["=","<>","IS NULL","IS NOT NULL"]),Ho=F(["=","<>",">",">=","<","<=","IS NULL","IS NOT NULL"]),Yo=F(["IS NULL","IS NOT NULL"]),Wo=F(["IN","NOT IN"]);var tt=["char","varchar","binary","varbinary","blob","text","enum","set","character","character varying","text","citext","uuid","xml","json","jsonb"];var jo=["date","datetime","timestamp","timestamptz"].reduce((e,t)=>(e[t]=!0,e),{});var ye=e=>e.fn?e.distinct===!0?`${e.fn} distinct ${e.value}`:`${e.fn} ${e.value}`:e.value;var Te={read_only:10,editor:20,admin:30,owner:40};var N=e=>{let t=Te[e];return r=>Te[r]>=t},rt=async e=>{let t=e.routeOptions.config.requireRole;if(t&&!t(e.user.currentTeamRole))throw new s(403,"You are not authorized to perform this action")};var ot=E(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=R(t),o=await T.findOne({where:{id:r}});if(!o)throw new s(404,"Data source not found");return{data:o}}}),e.route({method:"get",url:"/",handler:async t=>{let{teamId:r}=v(t);return{data:await T.find({where:{team:{id:r}},order:{createdAt:"DESC"}})}}}),e.route({url:"/",method:"post",config:{requireRole:N("admin")},handler:async t=>{let{teamId:r,ownerId:o,...a}=g(t,We),n=T.create({...a,allowUpdate:!!a.allowUpdate,allowInsert:!!a.allowInsert,team:{id:r},owner:{id:o}}),i=await L(q(n),n.dbType,t);try{await i.checkConnection()}catch{throw new s(400,"Cannot connect to the database, please check datasource configuration")}let{tag:u,iv:y,encrypted:l}=X.encrypt(n.dbPassword);return n.dbPassword=l,n.dbPasswordIv=y,n.dbPasswordTag=u,{data:await T.save(n)}}}),e.route({method:"put",url:"/:id",config:{requireRole:N("admin")},handler:async t=>{let{id:r}=R(t),o=g(t),a=await T.findOneBy({id:r});if(!a)throw new s(404,"Data source not found");let n=T.merge(a,o);return await T.save(n),{data:n}}}),e.route({method:"delete",url:"/:id",config:{requireRole:N("admin")},handler:async(t,r)=>w.transaction(async()=>{let{id:o}=R(t);await Promise.all([P.delete({datasource:{id:o}}),I.delete({dataSource:{id:o}})]),await T.delete({id:o})})}),e.route({method:"post",url:"/:id/inspect",handler:async(t,r)=>{let{id:o}=R(t),a=await T.findOne({where:{id:o},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser"]});if(!a)throw new Error("Data source not found");a.status="INSPECTING",await T.save(a);let i=await(await L(q(a,!0),a.dbType,t)).inspectSchema();await P.delete({datasource:{id:o}}),await P.insert(i.sort().map(u=>P.create({tableName:u.tableName,columns:u.columns,datasource:{id:o}}))),a.status="READY",a.lastInspected=new Date,await T.save(a)}}),e.route({method:"get",url:"/:id/inspections",handler:async t=>{let{id:r}=R(t);return{data:await P.find({where:{datasource:{id:r}}})}}})});var $=require("typeorm"),at=E(e=>{e.route({method:"get",url:"/team/:teamId/datasources",handler:async(t,r)=>{let{teamId:o}=R(t);return{data:await T.find({where:{team:{id:o}},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,r)=>{let{teamId:o}=R(t);return{data:await I.find({where:{team:{id:o},isTrash:!1},order:{name:"ASC"},select:{id:!0,name:!0,updatedAt:!0}})}}}),e.route({method:"get",url:"/team/:teamId/query",handler:async t=>{let{teamId:r}=R(t),{search:o,size:a,selectedDataSources:n}=v(t),i=(parseInt(a)||20)/2,u={team:{id:r}};n?.length&&(u.id=(0,$.In)(n));let[y,l]=await Promise.all([P.find({where:{tableName:(0,$.Like)(`%${o}%`),datasource:u},relations:{datasource:!0},select:{id:!0,tableName:!0,datasource:{name:!0,id:!0}},order:{tableName:"ASC"},take:i}),I.find({where:{name:(0,$.Like)(`%${o}%`),isTrash:!1,dataSource:u},relations:{dataSource:!0},select:{id:!0,name:!0,dataSource:{name:!0,id:!0}},order:{name:"ASC"},take:i})]),d=[];return y.forEach(p=>{d.push({name:p.tableName,id:p.id,dataSourceName:p.datasource?.name||"--",dataSourceId:p.datasource?.id||"--",type:"table"})}),l.forEach(p=>{d.push({name:p.name,id:p.id,dataSourceName:p.dataSource?.name||"--",dataSourceId:p.dataSource?.id||"--",type:"query"})}),{data:d}}})});function nt(e,t=void 0){try{if(e){let r=e.split("&"),o={};for(let a of r){let n=a.split(":");o[n[0]]=n[1]}return o}}catch{}return t}var st=require("typeorm");var it=E(e=>{e.route({method:"get",url:"/",handler:async t=>{let{dataSourceId:r,teamId:o,limit:a,orderBy:n,name:i}=v(t);if(!r&&!o)throw new s(400,"Either dsId or teamId is required");let u={isTrash:!1};return r&&(u.dataSource={id:r}),o&&(u.team={id:o}),i&&(u.name=(0,st.Like)(`%${i}%`)),{data:await I.find({where:u,take:a,order:nt(n,{createdAt:"DESC"})})}}}),e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=R(t),o=await I.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:N("editor")},handler:async t=>{let r=g(t),o=await T.findOne({where:{id:r.dataSourceId},relations:{team:!0}});return{data:await I.save(I.create({name:r.name,isTrash:!1,opts:r.opts,team:{id:o?.team.id},dataSource:{id:r.dataSourceId}}))}}}),e.route({method:"patch",url:"/:id",config:{requireRole:N("editor")},handler:async t=>{let{id:r}=R(t),o=g(t);if(!(await I.update(r,o)).affected)throw new s(404,"Query not found");return{data:await I.findOneBy({id:r})}}}),e.route({method:"delete",url:"/:id",config:{requireRole:N("editor")},handler:async t=>w.transaction(async()=>{let{id:r}=R(t);if(!(await I.delete({id:r})).affected)return{status:404,data:"Query not found"}})})});var Z=e=>{let t=e.distinct===!0?"distinct ":"";return`${e.fn}(${t}${e.value})`},H={YEAR:e=>`EXTRACT(YEAR FROM ${e.value})`,MONTH:e=>`EXTRACT(MONTH FROM ${e.value})`,DAY:e=>`EXTRACT(DAY FROM ${e.value})`,SUM:e=>`COALESCE(SUM(${e.distinct===!0?"distinct ":""}${e.value}), 0)`,AVG:Z,MAX:Z,MIN:Z,COUNT:Z};var ee=e=>{let t=e.distinct===!0?"distinct ":"";return`${e.fn}(${t}${e.value})`},Y={YEAR:e=>`YEAR(${e.value})`,MONTH:e=>`MONTH(${e.value})`,DAY:e=>`DAY(${e.value})`,SUM:e=>{let t=e.distinct===!0?"distinct ":"";return`coalesce(${e.fn}(${t}${e.value}), 0)`},AVG:ee,MAX:ee,MIN:ee,COUNT:ee};var ut=["SUM","COUNT","AVG","MAX","MIN"],dr=["YEAR","MONTH","DAY",...ut],pr=dr.reduce((e,t)=>(e[t]=!0,e),{}),fr=ut.reduce((e,t)=>(e[t]=!0,e),{}),te=e=>pr[e],ct=e=>fr[e],lt=(e,t)=>e.fn&&te(e.fn)?(t==="postgres"?H:Y)[e.fn](e):e.value;var re=e=>typeof e=="string",mt=e=>{let t="SELECT ";if(e.columns&&e.columns.length>0?t+=e.columns.join(", "):t+="*",e.table&&(t+=` FROM ${e.table}`),e.joins&&e.joins.length>0&&e.joins.forEach(r=>{t+=` ${r.type} JOIN ${r.table} ON ${r.on}`}),e.where&&(t+=` WHERE ${e.where}`),e.groupBy&&e.groupBy.length>0&&(t+=` GROUP BY ${e.groupBy.join(", ")}`),e.having&&(t+=` HAVING ${e.having}`),e.orderBy&&e.orderBy.length>0){let r=e.orderBy.reduce((a,n)=>(a[n.column]=n.direction,a),{}),o=Object.entries(r).map(([a,n])=>`${a} ${n}`);t+=` ORDER BY ${o.join(", ")}`}return e.limit!==void 0&&(t+=` LIMIT ${e.limit}`),e.offset!==void 0&&(t+=` OFFSET ${e.offset}`),t},W=(e,t)=>{let{column:r,operator:o,value:a,fn:n}=e,i=lt({value:r,fn:n},t);switch(o){case"IS NULL":case"IS NOT NULL":return`${i} ${o}`;case"IN":case"NOT IN":let u=a?.map(c=>re(c.value)?`'${c.value}'`:c.value).join(", ");return`${i} ${o} (${u})`;case"LIKE":return`${i} ${t==="postgres"?"ILIKE":"LIKE"} '%${a?.[0].value}%'`;case"NOT LIKE":return`${i} ${t==="postgres"?"NOT ILIKE":"NOT LIKE"} '%${a?.[0].value}%'`;default:let d=a?.[0],p;return re(d?.value)&&d?.isColumn!==!0?p=`'${d?.value}'`:p=d?.value,`${i} ${o} ${p}`}};var oe=class{constructor(t="mysql"){this.dialect=t,this.skeleton={type:"SELECT"}}addWhere(t){let r=W(t,this.dialect);if(t.isEnabled!==!1)if(this.skeleton.where){let o=t.connector||"AND";this.skeleton.where+=` ${o} ${r}`}else this.skeleton.where=r;return this}addWhereRaw(t,r="AND"){return this.skeleton.where?this.skeleton.where+=` ${r} ${t}`:this.skeleton.where=t,this}clearWhere(){return this.skeleton.where=void 0,this}addHaving(t){let r=W(t,this.dialect);if(t.isEnabled!==!1)if(this.skeleton.having){let o=t.connector||"AND";this.skeleton.having+=` ${o} ${r}`}else this.skeleton.having=r;return this}clearHaving(){return this.skeleton.having=void 0,this}addOrderBy(...t){return this.skeleton.orderBy||(this.skeleton.orderBy=[]),this.skeleton.orderBy.push(...t),this}clearOrderBy(){return this.skeleton.orderBy=void 0,this}setLimit(t){return this.skeleton.limit=t,this}setOffset(t){return this.skeleton.offset=t,this}addGroupBy(t){this.skeleton.groupBy||(this.skeleton.groupBy=[]);let r=this.skeleton.groupBy.findIndex(o=>o===t);return r>-1?this.skeleton.groupBy[r]=t:this.skeleton.groupBy.push(t),this}setTable(t){return this.skeleton.table=t,this}addJoin(...t){return this.skeleton.joins||(this.skeleton.joins=[]),this.skeleton.joins.push(...t),this}selectColumns(t){if(this.skeleton.type!=="SELECT")throw new Error("Column selection is only supported for SELECT queries");return this.skeleton.columns=t,this}toSQL(){return mt(this.skeleton)}};var pt=require("typeorm");var ft=async(e,t)=>{let{table:r,datasourceId:o,filters:a,joins:n,orderBy:i,size:u,page:y,columns:l,groupBy:d,searchAll:p}=t,c=await T.findOne({where:{id:o},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser"]}),S=[r],M=[];if(!c)throw new s(404,"Data source not found");let A=new oe(c.dbType);A.setTable(r),A.setLimit(u||20),A.setOffset(u*y),a?.forEach(f=>{f.fn&&ct(f.fn)?A.addHaving(f):A.addWhere(f)}),n&&(A.addJoin(...n),n.forEach(f=>{S.push(f.table)}));let Ee=hr(t,c.dbType);Ee.length>0&&A.addOrderBy(...Ee),d&&d.length>0&&d.forEach(f=>A.addGroupBy(gr(f,c.dbType)));let Lt=await P.find({where:{tableName:(0,pt.In)(S),datasource:{id:o}}});for(let f of Lt)if(f.columns)for(let U of f.columns)M.push({column:U.name,table:f.tableName||"",full:`${f.tableName}.${U.name}`,type:U.type});let G;if(l&&l.length>0?G=l.map(f=>Tr(f,c.dbType)):G=M.map(f=>`${f.full} as "${f.full}"`),A.selectColumns(G),p){let f=M.filter(U=>tt.includes(U.type)&&G.some(ae=>ae.startsWith(U.full)));if(f.length>0){let U=f.map(ae=>`LOWER(${ae.full}) LIKE '%${p.toLowerCase()}%'`);A.addWhereRaw(`(${U.join(" OR ")})`,"AND")}}return{...await(await L(q(c,!0),c.dbType,e)).executeQuery(A.toSQL(),{type:"SELECT",allowBulkUpdate:!1}),tables:S,allColumns:M}},yt=async(e,t)=>{let r=await T.findOne({where:{id:t.datasourceId},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser","allowUpdate"]});if(!r)throw new s(404,"Data source not found");if(!r.allowUpdate)throw new s(403,"This datasource does not allow update operations");let o=t.values.map(({value:u,column:y})=>typeof u=="string"?u&&u.startsWith("=")?`${y}=${u.substring(1)}`:`${y}='${u}'`:`${y}='${u}'`).join(", "),a=t.filters.map(u=>W(u,r.dbType)).join(" AND "),n=`UPDATE ${t.table} SET ${o} WHERE ${a}`;return(await L(q(r,!0),r.dbType,e)).executeQuery(n,{type:"UPDATE",allowBulkUpdate:!1})},Tt=async(e,t)=>{let r=await T.findOne({where:{id:t.datasourceId},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser","allowInsert"]});if(!r)throw new s(404,"Data source not found");if(!r.allowInsert)throw new s(403,"This datasource does not allow insert operations");let{keys:o,values:a}=yr(t.values),n=`INSERT INTO ${t.table} (${o}) VALUES (${a})`;return(await L(q(r,!0),r.dbType,e)).executeQuery(n,{type:"INSERT",allowBulkUpdate:!1})},yr=e=>{let t=e.map(({column:o})=>o).join(", "),r=e.map(({value:o})=>typeof o=="string"?o&&o.startsWith("=")?o.substring(1):`'${o}'`:o).join(", ");return{keys:t,values:r}},Tr=(e,t)=>{if(e.fn){if(te(e.fn))return`${(t==="postgres"?H:Y)[e.fn](e)} as "${ye(e)}"`;throw new Error("Function not allowed: "+e.fn)}return`${e.value} as "${e.value}"`},gr=(e,t)=>{if(e.fn){if(te(e.fn))return(t==="postgres"?H:Y)[e.fn]({...e,value:dt(e.value,t)});throw new Error("Function not allowed: "+e.fn)}return dt(e.value,t)},ge=(e,t)=>t==="postgres"?`"${e}"`:t==="mysql"?`\`${e}\``:e,dt=(e,t)=>{let[r,o]=e.split(".");return ge(r,t)+"."+ge(o,t)},hr=(e,t)=>{if(!e.orderBy)return[];let r=e.orderBy;if(e.columns&&e.columns.length>0){let o=e.columns.reduce((a,n)=>(a.set(ye(n),{isFn:!!(n.fn||n.distinct)}),a),new Map);r=e.orderBy.filter(a=>o.has(a.column)).map(a=>o.get(a.column)?.isFn?{...a,column:ge(a.column,t)}:a)}return r};var gt=e=>{if(!e.table)throw new s(400,"Table is required")},wr=["--",";","DROP","drop"],ht=e=>{if(re(e.value)&&e.value.startsWith("=")){let t=e.value;wr.forEach(r=>{if(t.includes(r))throw new s(400,"Invalid input value for "+e.column)})}},wt=e=>{if(!e.table)throw new s(400,"Table is required");e.values.forEach(ht)},Et=e=>{if(!e.table)throw new s(400,"Table is required");e.values.forEach(ht)};var Rt=E(e=>{e.route({method:"post",url:"/select",handler:async t=>{let r=g(t,gt);return{data:await ft(t,r)}}}),e.route({method:"post",url:"/insert",config:{requireRole:N("editor")},handler:async t=>{let r=g(t,wt);return{data:await Tt(t,r)}}}),e.route({method:"post",url:"/update",config:{requireRole:N("editor")},handler:async t=>{let r=g(t,Et);return{data:await yt(t,r)}}})});var St=E(e=>{e.get("/",{config:{isPublic:!0}},async()=>({data:{active:!0,version:m.str("SERVER_VERSION")}}))});var bt=E(e=>{e.route({method:"get",url:"/:id/users",handler:async t=>{let{id:r}=R(t),o=await x.findOne({where:{id:r},relations:{users:{user:!0}}});if(!o)throw new s(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:N("editor")},handler:async t=>w.transaction(async()=>{let r=t.user.id,o=g(t),a=b.create();a.id=r;let n=x.create(o);await x.save(n);let i=C.create({user:a,team:n});return await C.save(i),{data:n}})}),e.route({method:"patch",url:"/:id/user-role",config:{requireRole:N("admin")},handler:async t=>{let{id:r}=R(t),{role:o,userId:a}=g(t,({role:i})=>{if(i==="owner")throw new s(400,"Only one owner is allowed")});if((await C.findOneBy({user:{id:a},team:{id:r}}))?.role==="owner")throw new s(400,"Cannot change owner role");await C.update({user:{id:a},team:{id:r}},{role:o})}}),e.route({method:"delete",url:"/:id",config:{requireRole:N("admin")},handler:async t=>w.transaction(async()=>{let{id:r}=R(t),{userId:o}=v(t);if((await C.findOneBy({user:{id:o},team:{id:r}}))?.role==="owner")throw new s(400,"Cannot delete team owner");await b.update(o,{currentTeam:null}),await C.delete({user:{id:o},team:{id:r}}),await b.delete({id:o})})})});var he=_(require("bcryptjs")),j=async e=>{let t=await he.default.genSalt(10);return he.default.hash(e,t)};var Ct=E(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=await b.findOne({where:{id:t.user.id},relations:{currentTeam:{team:!0}}});if(!r)throw new s(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=g(t);if(o.password&&(o.password=await j(o.password)),!(await b.update(r,o)).affected)throw new s(404,"User not found");let n=await b.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:"/",handler:async t=>w.transaction(async()=>{let r=g(t),o=await j(r.password),a=await b.save(b.create({username:r.username,password:o})),n=await C.save(C.create({role:"read_only",team:{id:r.teamId},user:{id:a.id}}));await b.update(a.id,{currentTeam:{id:n.id}})})})});var Nt=E(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=t.user.id,o=await B.findOneBy({user:{id:r}});return o||(o=await B.save(B.create({user:{id:r}}))),{data:o}}}),e.route({method:"patch",url:"/",handler:async t=>{let{settings:r}=g(t);if(!r.id)throw new s(400,"Settings id is required!");if(!(await B.update(r.id,r)).affected)throw new s(404,"You do not own these settings!");return{data:await B.findOneBy({id:r.id})}}})});var xt=require("node:path");var Er=e=>e.routeOptions.config.isPublic?!0:!e.url.startsWith("/api/"),It=async e=>{if(Er(e))return;let t=e.headers.authorization;if(!t)throw new s(401,"Missing auth token");let[r,o]=t.split(" ");try{let{userId:a}=await Qe(o),n=await C.findOneBy({user:{id:a}});if(!n)throw new s(401,"User is not part of a team");e.user={id:a,currentTeamRole:n.role}}catch{throw new s(401,"Unauthorized")}};var Ot=(e,t)=>{e.__connections&&e.__connections.forEach(r=>{r.close()})};var vt=_(require("@fastify/cookie"));var we={teamName:"Default Team",username:"admin",password:"admin"},Rr=async()=>{let e=await x.findOneBy({});return e||x.save(x.create({name:we.teamName}))},At=async()=>{let e=await C.findOne({where:{role:"owner"},relations:{user:!0}});if(e)return e.user;let t=await Rr(),r=await j(we.password),o=await b.save(b.create({username:we.username,password:r})),a=await C.save(C.create({user:o,team:t,role:"owner"}));return await b.update(o.id,{currentTeam:a}),o};var O=(0,_t.default)({querystringParser:e=>Ut.default.parse(e)}),Mt=m.num("PORT",4466),Sr=m.str("ALLOWED_ORIGINS","").split(",").map(e=>e.trim()),br="0.0.0.0",Cr=[`http://localhost:${Mt}`,...Sr];function D(e,t){O.register(e,{prefix:t}),console.log("Registered "+t)}(async function(){Ce(),await O.register(vt.default,{}),await O.register(Pt.default,{origin:(t,r)=>{!t||Cr.includes(t)?r(null,!0):r(new Error("Not allowed by CORS"),!1)},methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"],credentials:!0}),await O.register(Dt.default,{root:(0,xt.join)(__dirname,"web")}),O.get("/",(t,r)=>{r.sendFile("index.html")}),O.addHook("onRequest",It),O.addHook("onRequest",rt),O.addHook("onResponse",Ot),D(Ye,"/api/auth"),D(ot,"/api/data-sources"),D(at,"/api/project"),D(it,"/api/queries"),D(Rt,"/api/runner"),D(St,"/api/status"),D(bt,"/api/teams"),D(Ct,"/api/users"),D(Nt,"/api/user-settings"),O.setNotFoundHandler((t,r)=>{if(t.raw.url?.startsWith("/api/")){r.code(404).send({error:"API route not found"});return}r.sendFile("index.html")}),O.setErrorHandler((t,r,o)=>{if(console.error(t),t instanceof s){o.status(t.status).send({error:t.message});return}else o.status(500).send({error:"Internal Server Error"})}),await O.after(),await Me(),await At(),O.listen({port:Mt,host:br},(t,r)=>{t&&(console.error(t),process.exit(1)),console.log(`Server listening at ${r}`)})})();
57
+ limit 25;`;return(await t.query(r)).rows.reduce((a,n)=>(a[n.row_key]={table:n.relname,column:n.attname},a),{})},Ke=async(e,t,r)=>{try{console.log(`[PG CONN] Query: ${e}`);let{rows:o,fields:a,command:n,rowCount:i}=await t.query({text:e,rowMode:"array"});if(n==="UPDATE"||n==="INSERT"||n==="DELETE"){if(i!=null&&i>1&&r.allowBulkUpdate!==!0)throw new Error("[PG CONN] Bulk update performed without permission.");return{columns:[{column:"affectedRows",alias:"Affected rows",full:"affectedRows"}],rows:[[i]],query:e}}if(n==="SELECT"){let u=a.map(l=>`'${l.tableID}-${l.columnID}'`),d=await ar(u,t);return{columns:a.map(l=>{let p=d[`${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:o,query:e}}throw new Error(`[PG CONN] Unsupported command: ${n}`)}catch(o){throw o instanceof s?o:new s(400,o.message)}},nr=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}},sr=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}},ze=async e=>{let t=await er(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:()=>or(e,t),executeQuery:(n,i)=>a(()=>i.type==="SELECT"?sr(t,()=>Ke(n,t,i)):nr(t,()=>Ke(n,t,i))),checkConnection:async()=>{},isClosed:()=>r,close:async()=>{if(!r)return r=!0,t.end()}}};var M=async(e,t,r)=>{try{let o;if(t==="mysql")o=await Ge(e);else if(t==="postgres")o=await ze(e);else throw new s(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 s?o:o?.code==="ECONNREFUSED"?new s(500,"Failed to connect to the database"):new s(500,o.message)}};var z=_(require("node:crypto"));var Je="aes-256-gcm",ir=12,Xe=()=>{let e=m.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},ur=e=>{let t=z.default.randomBytes(ir),r=Xe(),o=z.default.createCipheriv(Je,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")}},cr=({encrypted:e,iv:t,tag:r})=>{let o=Xe(),a=z.default.createDecipheriv(Je,o,Buffer.from(t,"hex"));a.setAuthTag(Buffer.from(r,"hex"));let n=a.update(e,"hex","utf8");return n+=a.final("utf8"),n},J={encrypt:ur,decrypt:cr};var L=(e,t=!1)=>{if(t){let r=J.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 Ze=[{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:"contains"},{value:"NOT LIKE",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"}],lr=Ze.reduce((e,t)=>(e[t.value]=t.label,e),{}),Fo=Ze.reduce((e,t)=>(e[t.label]=t.value,e),{}),F=e=>e.map(t=>({label:lr[t],value:t})),Bo=F(["=","<>",">",">=","<","<=","IN","NOT IN","IS NULL","IS NOT NULL"]),Qo=F(["=","<>","LIKE","NOT LIKE","IN","NOT IN","IS NULL","IS NOT NULL"]),ko=F(["=","<>","IS NULL","IS NOT NULL"]),$o=F(["=","<>",">",">=","<","<=","IS NULL","IS NOT NULL"]),Ho=F(["IS NULL","IS NOT NULL"]),Yo=F(["IN","NOT IN"]);var et=["char","varchar","binary","varbinary","blob","text","enum","set","character","character varying","text","citext","uuid","xml","json","jsonb"];var Wo=["date","datetime","timestamp","timestamptz"].reduce((e,t)=>(e[t]=!0,e),{});var fe=e=>e.fn?e.distinct===!0?`${e.fn} distinct ${e.value}`:`${e.fn} ${e.value}`:e.value;var ye={read_only:10,editor:20,admin:30,owner:40};var N=e=>{let t=ye[e];return r=>ye[r]>=t},tt=async e=>{let t=e.routeOptions.config.requireRole;if(t&&!t(e.user.currentTeamRole))throw new s(403,"You are not authorized to perform this action")};var rt=R(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=S(t),o=await T.findOne({where:{id:r}});if(!o)throw new s(404,"Data source not found");return{data:o}}}),e.route({method:"get",url:"/",handler:async t=>{let{teamId:r}=v(t);return{data:await T.find({where:{team:{id:r}},order:{createdAt:"DESC"}})}}}),e.route({url:"/",method:"post",config:{requireRole:N("admin")},handler:async t=>{let{teamId:r,ownerId:o,...a}=g(t,Ye),n=T.create({...a,allowUpdate:!!a.allowUpdate,allowInsert:!!a.allowInsert,team:{id:r},owner:{id:o}}),i=await M(L(n),n.dbType,t);try{await i.checkConnection()}catch{throw new s(400,"Cannot connect to the database, please check datasource configuration")}let{tag:u,iv:d,encrypted:l}=J.encrypt(n.dbPassword);return n.dbPassword=l,n.dbPasswordIv=d,n.dbPasswordTag=u,{data:await T.save(n)}}}),e.route({method:"put",url:"/:id",config:{requireRole:N("admin")},handler:async t=>{let{id:r}=S(t),o=g(t),a=await T.findOneBy({id:r});if(!a)throw new s(404,"Data source not found");let n=T.merge(a,o);return await T.save(n),{data:n}}}),e.route({method:"delete",url:"/:id",config:{requireRole:N("admin")},handler:async(t,r)=>E.transaction(async()=>{let{id:o}=S(t);await Promise.all([P.delete({datasource:{id:o}}),O.delete({dataSource:{id:o}})]),await T.delete({id:o})})}),e.route({method:"post",url:"/:id/inspect",handler:async(t,r)=>{let{id:o}=S(t),a=await T.findOne({where:{id:o},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser"]});if(!a)throw new Error("Data source not found");a.status="INSPECTING",await T.save(a);let i=await(await M(L(a,!0),a.dbType,t)).inspectSchema();await P.delete({datasource:{id:o}}),await P.insert(i.sort().map(u=>P.create({tableName:u.tableName,columns:u.columns,datasource:{id:o}}))),a.status="READY",a.lastInspected=new Date,await T.save(a)}}),e.route({method:"get",url:"/:id/inspections",handler:async t=>{let{id:r}=S(t);return{data:await P.find({where:{datasource:{id:r}}})}}})});var k=require("typeorm"),ot=R(e=>{e.route({method:"get",url:"/team/:teamId/datasources",handler:async(t,r)=>{let{teamId:o}=S(t);return{data:await T.find({where:{team:{id:o}},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,r)=>{let{teamId:o}=S(t);return{data:await O.find({where:{team:{id:o},isTrash:!1},order:{name:"ASC"},select:{id:!0,name:!0,updatedAt:!0}})}}}),e.route({method:"get",url:"/team/:teamId/query",handler:async t=>{let{teamId:r}=S(t),{search:o,size:a,selectedDataSources:n}=v(t),i=(parseInt(a)||20)/2,u={team:{id:r}};n?.length&&(u.id=(0,k.In)(n));let[d,l]=await Promise.all([P.find({where:{tableName:(0,k.Like)(`%${o}%`),datasource:u},relations:{datasource:!0},select:{id:!0,tableName:!0,datasource:{name:!0,id:!0}},order:{tableName:"ASC"},take:i}),O.find({where:{name:(0,k.Like)(`%${o}%`),isTrash:!1,dataSource:u},relations:{dataSource:!0},select:{id:!0,name:!0,dataSource:{name:!0,id:!0}},order:{name:"ASC"},take:i})]),p=[];return d.forEach(c=>{p.push({name:c.tableName,id:c.id,dataSourceName:c.datasource?.name||"--",dataSourceId:c.datasource?.id||"--",type:"table"})}),l.forEach(c=>{p.push({name:c.name,id:c.id,dataSourceName:c.dataSource?.name||"--",dataSourceId:c.dataSource?.id||"--",type:"query"})}),{data:p}}})});function at(e,t=void 0){try{if(e){let r=e.split("&"),o={};for(let a of r){let n=a.split(":");o[n[0]]=n[1]}return o}}catch{}return t}var nt=require("typeorm");var st=R(e=>{e.route({method:"get",url:"/",handler:async t=>{let{dataSourceId:r,teamId:o,limit:a,orderBy:n,name:i}=v(t);if(!r&&!o)throw new s(400,"Either dsId or teamId is required");let u={isTrash:!1};return r&&(u.dataSource={id:r}),o&&(u.team={id:o}),i&&(u.name=(0,nt.Like)(`%${i}%`)),{data:await O.find({where:u,take:a,order:at(n,{createdAt:"DESC"})})}}}),e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=S(t),o=await O.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:N("editor")},handler:async t=>{let r=g(t),o=await T.findOne({where:{id:r.dataSourceId},relations:{team:!0}});return{data:await O.save(O.create({name:r.name,isTrash:!1,opts:r.opts,team:{id:o?.team.id},dataSource:{id:r.dataSourceId}}))}}}),e.route({method:"patch",url:"/:id",config:{requireRole:N("editor")},handler:async t=>{let{id:r}=S(t),o=g(t);if(!(await O.update(r,o)).affected)throw new s(404,"Query not found");return{data:await O.findOneBy({id:r})}}}),e.route({method:"delete",url:"/:id",config:{requireRole:N("editor")},handler:async t=>E.transaction(async()=>{let{id:r}=S(t);if(!(await O.delete({id:r})).affected)return{status:404,data:"Query not found"}})})});var X=e=>{let t=e.distinct===!0?"distinct ":"";return`${e.fn}(${t}${e.value})`},$={YEAR:e=>`EXTRACT(YEAR FROM ${e.value})`,MONTH:e=>`EXTRACT(MONTH FROM ${e.value})`,DAY:e=>`EXTRACT(DAY FROM ${e.value})`,SUM:e=>`COALESCE(SUM(${e.distinct===!0?"distinct ":""}${e.value}), 0)`,AVG:X,MAX:X,MIN:X,COUNT:X};var Z=e=>{let t=e.distinct===!0?"distinct ":"";return`${e.fn}(${t}${e.value})`},H={YEAR:e=>`YEAR(${e.value})`,MONTH:e=>`MONTH(${e.value})`,DAY:e=>`DAY(${e.value})`,SUM:e=>{let t=e.distinct===!0?"distinct ":"";return`coalesce(${e.fn}(${t}${e.value}), 0)`},AVG:Z,MAX:Z,MIN:Z,COUNT:Z};var it=["SUM","COUNT","AVG","MAX","MIN"],mr=["YEAR","MONTH","DAY",...it],dr=mr.reduce((e,t)=>(e[t]=!0,e),{}),pr=it.reduce((e,t)=>(e[t]=!0,e),{}),ee=e=>dr[e],ut=e=>pr[e],ct=(e,t)=>e.fn&&ee(e.fn)?(t==="postgres"?$:H)[e.fn](e):e.value;var te=e=>typeof e=="string",lt=e=>{let t="SELECT ";if(e.columns&&e.columns.length>0?t+=e.columns.join(", "):t+="*",e.table&&(t+=` FROM ${e.table}`),e.joins&&e.joins.length>0&&e.joins.forEach(r=>{t+=` ${r.type} JOIN ${r.table} ON ${r.on}`}),e.where&&(t+=` WHERE ${e.where}`),e.groupBy&&e.groupBy.length>0&&(t+=` GROUP BY ${e.groupBy.join(", ")}`),e.having&&(t+=` HAVING ${e.having}`),e.orderBy&&e.orderBy.length>0){let r=e.orderBy.reduce((a,n)=>(a[n.column]=n.direction,a),{}),o=Object.entries(r).map(([a,n])=>`${a} ${n}`);t+=` ORDER BY ${o.join(", ")}`}return e.limit!==void 0&&(t+=` LIMIT ${e.limit}`),e.offset!==void 0&&(t+=` OFFSET ${e.offset}`),t},Y=(e,t)=>{let{column:r,operator:o,value:a,fn:n}=e,i=ct({value:r,fn:n},t);switch(o){case"IS NULL":case"IS NOT NULL":return`${i} ${o}`;case"IN":case"NOT IN":let u=a?.map(f=>te(f.value)?`'${f.value}'`:f.value).join(", ");return`${i} ${o} (${u})`;case"LIKE":return`${i} ${t==="postgres"?"ILIKE":"LIKE"} '%${a?.[0].value}%'`;case"NOT LIKE":return`${i} ${t==="postgres"?"NOT ILIKE":"NOT LIKE"} '%${a?.[0].value}%'`;default:let p=a?.[0],c;return te(p?.value)&&p?.isColumn!==!0?c=`'${p?.value}'`:c=p?.value,`${i} ${o} ${c}`}};var re=class{constructor(t="mysql"){this.dialect=t,this.skeleton={type:"SELECT"}}addWhere(t){let r=Y(t,this.dialect);if(t.isEnabled!==!1)if(this.skeleton.where){let o=t.connector||"AND";this.skeleton.where+=` ${o} ${r}`}else this.skeleton.where=r;return this}addWhereRaw(t,r="AND"){return this.skeleton.where?this.skeleton.where+=` ${r} ${t}`:this.skeleton.where=t,this}clearWhere(){return this.skeleton.where=void 0,this}addHaving(t){let r=Y(t,this.dialect);if(t.isEnabled!==!1)if(this.skeleton.having){let o=t.connector||"AND";this.skeleton.having+=` ${o} ${r}`}else this.skeleton.having=r;return this}clearHaving(){return this.skeleton.having=void 0,this}addOrderBy(...t){return this.skeleton.orderBy||(this.skeleton.orderBy=[]),this.skeleton.orderBy.push(...t),this}clearOrderBy(){return this.skeleton.orderBy=void 0,this}setLimit(t){return this.skeleton.limit=t,this}setOffset(t){return this.skeleton.offset=t,this}addGroupBy(t){this.skeleton.groupBy||(this.skeleton.groupBy=[]);let r=this.skeleton.groupBy.findIndex(o=>o===t);return r>-1?this.skeleton.groupBy[r]=t:this.skeleton.groupBy.push(t),this}setTable(t){return this.skeleton.table=t,this}addJoin(...t){return this.skeleton.joins||(this.skeleton.joins=[]),this.skeleton.joins.push(...t),this}selectColumns(t){if(this.skeleton.type!=="SELECT")throw new Error("Column selection is only supported for SELECT queries");return this.skeleton.columns=t,this}toSQL(){return lt(this.skeleton)}};var dt=require("typeorm");var pt=async(e,t)=>{let{table:r,datasourceId:o,filters:a,joins:n,size:i,page:u,columns:d,groupBy:l,searchAll:p}=t,c=await T.findOne({where:{id:o},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser"]}),f=[r],w=[];if(!c)throw new s(404,"Data source not found");let I=new re(c.dbType);I.setTable(r),I.setLimit(i||20),I.setOffset(i*u),a?.forEach(y=>{y.fn&&ut(y.fn)?I.addHaving(y):I.addWhere(y)}),n&&(I.addJoin(...n),n.forEach(y=>{f.push(y.table)}));let we=gr(t,c.dbType);we.length>0&&I.addOrderBy(...we),l&&l.length>0&&l.forEach(y=>I.addGroupBy(Tr(y,c.dbType)));let Mt=await P.find({where:{tableName:(0,dt.In)(f),datasource:{id:o}}});for(let y of Mt)if(y.columns)for(let U of y.columns)w.push({column:U.name,table:y.tableName||"",full:`${y.tableName}.${U.name}`,type:U.type});let j;if(d&&d.length>0?j=d.map(y=>yr(y,c.dbType)):j=w.map(y=>`${y.full} as "${y.full}"`),I.selectColumns(j),p){let y=w.filter(U=>et.includes(U.type)&&j.some(oe=>oe.startsWith(U.full)));if(y.length>0){let U=y.map(oe=>`LOWER(${oe.full}) LIKE '%${p.toLowerCase()}%'`);I.addWhereRaw(`(${U.join(" OR ")})`,"AND")}}return{...await(await M(L(c,!0),c.dbType,e)).executeQuery(I.toSQL(),{type:"SELECT",allowBulkUpdate:!1}),tables:f,allColumns:w}},ft=async(e,t)=>{let r=await T.findOne({where:{id:t.datasourceId},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser","allowUpdate"]});if(!r)throw new s(404,"Data source not found");if(!r.allowUpdate)throw new s(403,"This datasource does not allow update operations");let o=t.values.map(({value:u,column:d})=>typeof u=="string"?u&&u.startsWith("=")?`${d}=${u.substring(1)}`:`${d}='${u}'`:`${d}='${u}'`).join(", "),a=t.filters.map(u=>Y(u,r.dbType)).join(" AND "),n=`UPDATE ${t.table} SET ${o} WHERE ${a}`;return(await M(L(r,!0),r.dbType,e)).executeQuery(n,{type:"UPDATE",allowBulkUpdate:!1})},yt=async(e,t)=>{let r=await T.findOne({where:{id:t.datasourceId},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser","allowInsert"]});if(!r)throw new s(404,"Data source not found");if(!r.allowInsert)throw new s(403,"This datasource does not allow insert operations");let{keys:o,values:a}=fr(t.values),n=`INSERT INTO ${t.table} (${o}) VALUES (${a})`;return(await M(L(r,!0),r.dbType,e)).executeQuery(n,{type:"INSERT",allowBulkUpdate:!1})},fr=e=>{let t=e.map(({column:o})=>o).join(", "),r=e.map(({value:o})=>typeof o=="string"?o&&o.startsWith("=")?o.substring(1):`'${o}'`:o).join(", ");return{keys:t,values:r}},yr=(e,t)=>{if(e.fn){if(ee(e.fn))return`${(t==="postgres"?$:H)[e.fn](e)} as "${fe(e)}"`;throw new Error("Function not allowed: "+e.fn)}return`${e.value} as "${e.value}"`},Tr=(e,t)=>{if(e.fn){if(ee(e.fn))return(t==="postgres"?$:H)[e.fn]({...e,value:mt(e.value,t)});throw new Error("Function not allowed: "+e.fn)}return mt(e.value,t)},Te=(e,t)=>t==="postgres"?`"${e}"`:t==="mysql"?`\`${e}\``:e,mt=(e,t)=>{let[r,o]=e.split(".");return Te(r,t)+"."+Te(o,t)},gr=(e,t)=>{if(!e.orderBy)return[];let r=e.orderBy;if(e.columns&&e.columns.length>0){let o=e.columns.reduce((a,n)=>(a.set(fe(n),{isFn:!!(n.fn||n.distinct)}),a),new Map);r=e.orderBy.filter(a=>o.has(a.column)).map(a=>o.get(a.column)?.isFn?{...a,column:Te(a.column,t)}:a)}return r};var Tt=e=>{if(!e.table)throw new s(400,"Table is required")},hr=["--",";","DROP","drop"],gt=e=>{if(te(e.value)&&e.value.startsWith("=")){let t=e.value;hr.forEach(r=>{if(t.includes(r))throw new s(400,"Invalid input value for "+e.column)})}},ht=e=>{if(!e.table)throw new s(400,"Table is required");e.values.forEach(gt)},wt=e=>{if(!e.table)throw new s(400,"Table is required");e.values.forEach(gt)};var Et=R(e=>{e.route({method:"post",url:"/select",handler:async t=>{let r=g(t,Tt);return{data:await pt(t,r)}}}),e.route({method:"post",url:"/insert",config:{requireRole:N("editor")},handler:async t=>{let r=g(t,ht);return{data:await yt(t,r)}}}),e.route({method:"post",url:"/update",config:{requireRole:N("editor")},handler:async t=>{let r=g(t,wt);return{data:await ft(t,r)}}})});var Rt=R(e=>{e.get("/",{config:{isPublic:!0}},async()=>({data:{active:!0,version:m.str("SERVER_VERSION")}}))});var St=R(e=>{e.route({method:"get",url:"/:id/users",handler:async t=>{let{id:r}=S(t),o=await x.findOne({where:{id:r},relations:{users:{user:!0}}});if(!o)throw new s(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:N("editor")},handler:async t=>E.transaction(async()=>{let r=t.user.id,o=g(t),a=b.create();a.id=r;let n=x.create(o);await x.save(n);let i=C.create({user:a,team:n});return await C.save(i),{data:n}})}),e.route({method:"patch",url:"/:id/user-role",config:{requireRole:N("admin")},handler:async t=>{let{id:r}=S(t),{role:o,userId:a}=g(t,({role:i})=>{if(i==="owner")throw new s(400,"Only one owner is allowed")});if((await C.findOneBy({user:{id:a},team:{id:r}}))?.role==="owner")throw new s(400,"Cannot change owner role");await C.update({user:{id:a},team:{id:r}},{role:o})}}),e.route({method:"delete",url:"/:id",config:{requireRole:N("admin")},handler:async t=>E.transaction(async()=>{let{id:r}=S(t),{userId:o}=v(t);if((await C.findOneBy({user:{id:o},team:{id:r}}))?.role==="owner")throw new s(400,"Cannot delete team owner");await b.update(o,{currentTeam:null}),await C.delete({user:{id:o},team:{id:r}}),await b.delete({id:o})})})});var ge=_(require("bcryptjs")),W=async e=>{let t=await ge.default.genSalt(10);return ge.default.hash(e,t)};var bt=R(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=await b.findOne({where:{id:t.user.id},relations:{currentTeam:{team:!0}}});if(!r)throw new s(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=g(t);if(o.password&&(o.password=await W(o.password)),!(await b.update(r,o)).affected)throw new s(404,"User not found");let n=await b.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:"/",handler:async t=>E.transaction(async()=>{let r=g(t),o=await W(r.password),a=await b.save(b.create({username:r.username,password:o})),n=await C.save(C.create({role:"read_only",team:{id:r.teamId},user:{id:a.id}}));await b.update(a.id,{currentTeam:{id:n.id}})})})});var Ct=R(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=t.user.id,o=await q.findOneBy({user:{id:r}});return o||(o=await q.save(q.create({user:{id:r}}))),{data:o}}}),e.route({method:"patch",url:"/",handler:async t=>{let{settings:r}=g(t);if(!r.id)throw new s(400,"Settings id is required!");if(!(await q.update(r.id,r)).affected)throw new s(404,"You do not own these settings!");return{data:await q.findOneBy({id:r.id})}}})});var Ut=require("node:path");var wr=e=>e.routeOptions.config.isPublic?!0:!e.url.startsWith("/api/"),Nt=async e=>{if(wr(e))return;let t=e.headers.authorization;if(!t)throw new s(401,"Missing auth token");let[r,o]=t.split(" ");try{let{userId:a}=await Be(o),n=await C.findOneBy({user:{id:a}});if(!n)throw new s(401,"User is not part of a team");e.user={id:a,currentTeamRole:n.role}}catch{throw new s(401,"Unauthorized")}};var It=(e,t)=>{e.__connections&&e.__connections.forEach(r=>{r.close()})};var xt=_(require("@fastify/cookie"));var he={teamName:"Default Team",username:"admin",password:"admin"},Er=async()=>{let e=await x.findOneBy({});return e||x.save(x.create({name:he.teamName}))},Ot=async()=>{let e=await C.findOne({where:{role:"owner"},relations:{user:!0}});if(e)return e.user;let t=await Er(),r=await W(he.password),o=await b.save(b.create({username:he.username,password:r})),a=await C.save(C.create({user:o,team:t,role:"owner"}));return await b.update(o.id,{currentTeam:a}),o};var A=(0,At.default)({querystringParser:e=>Dt.default.parse(e)}),vt=m.num("PORT",4466),Rr=m.str("ALLOWED_ORIGINS","").split(",").map(e=>e.trim()),Sr="0.0.0.0",br=[`http://localhost:${vt}`,...Rr];function D(e,t){A.register(e,{prefix:t}),console.log("Registered "+t)}(async function(){be(),await A.register(xt.default,{}),await A.register(_t.default,{origin:(t,r)=>{!t||br.includes(t)?r(null,!0):r(new Error("Not allowed by CORS"),!1)},methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"],credentials:!0}),await A.register(Pt.default,{root:(0,Ut.join)(__dirname,"web")}),A.get("/",(t,r)=>{r.sendFile("index.html")}),A.addHook("onRequest",Nt),A.addHook("onRequest",tt),A.addHook("onResponse",It),D(He,"/api/auth"),D(rt,"/api/data-sources"),D(ot,"/api/project"),D(st,"/api/queries"),D(Et,"/api/runner"),D(Rt,"/api/status"),D(St,"/api/teams"),D(bt,"/api/users"),D(Ct,"/api/user-settings"),A.setNotFoundHandler((t,r)=>{if(t.raw.url?.startsWith("/api/")){r.code(404).send({error:"API route not found"});return}r.sendFile("index.html")}),A.setErrorHandler((t,r,o)=>{if(console.error(t),t instanceof s){o.status(t.status).send({error:t.message});return}else o.status(500).send({error:"Internal Server Error"})}),await A.after(),await ve(),await Ot(),A.listen({port:vt,host:Sr},(t,r)=>{t&&(console.error(t),process.exit(1)),console.log(`Server listening at ${r}`)})})();