@dataramen/cli 0.0.64 → 0.0.66-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/bin/app.js +1 -1
- package/dist/code/migrations/1755358316764-usersManagement.js +1 -1
- package/dist/code/migrations/1758316062697-queriesHistory.js +1 -1
- package/dist/code/migrations/1760816916693-workbenchTabs.js +1 -1
- package/dist/code/migrations/1762376647080-link-tab-to-datasource.js +1 -1
- package/dist/code/server.js +7 -7
- package/dist/code/web/assets/index-DfOyABLn.js +193 -0
- package/dist/code/web/index.html +4 -3
- package/dist/package.json +1 -1
- package/package.json +1 -1
- package/dist/code/migrations/1760039807820-multipleWorkbenches.js +0 -1
- package/dist/code/migrations/1762683837767-addSearchIndexes.js +0 -1
- package/dist/code/web/assets/index-C1pR-axd.js +0 -193
package/bin/app.js
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
var se=Object.create;var R=Object.defineProperty;var ie=Object.getOwnPropertyDescriptor;var ae=Object.getOwnPropertyNames;var me=Object.getPrototypeOf,ce=Object.prototype.hasOwnProperty;var le=(e,t,o,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ae(t))!ce.call(e,r)&&r!==o&&R(e,r,{get:()=>t[r],enumerable:!(s=ie(t,r))||s.enumerable});return e};var c=(e,t,o)=>(o=e!=null?se(me(e)):{},le(t||!e||!e.__esModule?R(o,"default",{value:e,enumerable:!0}):o,e));var P=require("commander"),C=(e,t)=>{t.commands.forEach(o=>{e.command(o.command).description(o.description).action(o.handler)})};function _(){let e=new P.Command,t={id:"commander",setMetadata:o=>(e.name(o.name).description(o.description).version(o.version,"-v, --version","Show version"),t),setDefaultCommand:o=>(e.command("default",{hidden:!0,isDefault:!0}).action(o.handler),t),setModules:o=>(o.forEach(s=>{if(s.name==="root")C(e,s);else{let r=e.command(s.name).description(`(Module) ${s.description}`);C(r,s)}}),t),start:()=>(e.parse(),t),getHandler:()=>e};return t}var V=c(require("fs-extra")),y=require("node:path");var b=require("node:os"),M=require("node:path"),pe=(0,b.homedir)(),m="@dataramen/server",a=(0,M.join)(pe,".dataramen",".runtime","server");function A(e){let t;function o(){try{return t||(t=V.readJsonSync(e)),t}catch{return}}return o}var N=A((0,y.join)(__dirname,"..","package.json")),k=A((0,y.join)(a,"package.json"));var u=c(require("fs-extra")),p=require("node:path"),H=require("node:child_process"),O=require("node:util"),g=c(require("yocto-spinner")),f=(0,O.promisify)(H.exec);function W(){try{let e=k();if(!e)return!0;let t=u.readJsonSync((0,p.join)(__dirname,"..","dist","package.json"));return e.version!==t.version}catch{return!0}}async function $(){let e=(0,g.default)({text:"Checking if PM2 is installed"}).start();try{return await f("pm2 -v"),e.success("PM2 already installed"),!0}catch{return e.warning("PM2 not installed"),!1}}async function j(){let e=(0,g.default)({text:"Installing PM2"}).start();try{await f("npm i -g pm2"),e.success("Installed PM2")}catch{e.error("Failed to install PM2"),process.exit(1)}}async function v(){let e=(0,g.default)({text:"Stop running instances of "+m}).start();try{await f(`pm2 stop "${m}"`),e.warning("Stopped "+m)}catch{e.success("No running instances of "+m+" found")}}async function I(){let e=(0,g.default)({text:"Create local server"}).start();u.removeSync((0,p.join)(a,"code")),u.copySync((0,p.join)(__dirname,"..","dist","code"),(0,p.join)(a,"code")),u.copySync((0,p.join)(__dirname,"..","dist","package.json"),(0,p.join)(a,"package.json")),e.text="Install local server dependencies",await f("npm i",{cwd:a}),e.success("Local server installed")}var S=c(require("node:crypto"));var E=require("fs-extra"),w=require("node:path");function ue(e){try{return(0,E.readFileSync)((0,w.join)(a,e),"utf-8")}catch{return}}function de(e){let t={},o=ue(e);if(o){let s=o.split(`
|
|
3
3
|
`);for(let r of s){let i=r.trim();if(!i||i.startsWith("#"))continue;let d=i.indexOf("=");if(d===-1)continue;let T=i.slice(0,d).trim(),l=i.slice(d+1).trim();(l.startsWith('"')&&l.endsWith('"')||l.startsWith("'")&&l.endsWith("'"))&&(l=l.slice(1,-1)),t[T]=l}}return t}function fe(){let e={customValues:{},fileName:".env"};function t(){e.customValues=de(e.fileName)}function o(){let i=Object.entries(e.customValues).map(([d,T])=>`${d}=${T}`).join(`
|
|
4
4
|
`)+`
|
|
5
|
-
`;(0,E.writeFileSync)((0,w.join)(a,e.fileName),i,{encoding:"utf8"})}function s(r){if(e.customValues[r])return e.customValues[r]}return t(),{getNumber:r=>ge(s(r)),getString:r=>ve(s(r)),getBoolean:r=>Ee(s(r)),flush:o,set:(r,i)=>{e.customValues[r]=i.toString()},unset:r=>{delete e.customValues[r]},values:()=>({...e.customValues})}}function ge(e){if(!e)return;let t=Number(e);if(!isNaN(t)&&e.trim()!=="")return t;throw new Error("Wrong env value type")}function ve(e){if(e){if(typeof e=="string")return e;throw new Error("Wrong env value type")}}function Ee(e){if(!e)return;let t=e.toLowerCase();if(t==="true"||t==="1")return!0;if(t==="false"||t==="0")return!1;throw new Error("Wrong env value type")}var n=fe();function J(){let e=!1;if(!n.getString("SYMM_ENCRYPTION_KEY")){let t=S.randomBytes(32).toString("hex");n.set("SYMM_ENCRYPTION_KEY",t),console.log("Generated random SYMM_ENCRYPTION_KEY"),e=!0}if(!n.getString("JWT_SECRET")){let t=S.randomBytes(32).toString("hex");n.set("JWT_SECRET",t),console.log("Generated random JWT_SECRET"),e=!0}if(!n.getString("JWT_REFRESH_SECRET")){let t=S.randomBytes(32).toString("hex");n.set("JWT_REFRESH_SECRET",t),console.log("Generated random JWT_REFRESH_SECRET"),e=!0}e&&n.flush()}var F=require("node:net");async function L(e){return new Promise(t=>{let o=(0,F.createServer)().once("error",()=>{t(!1)}).once("listening",()=>{o.close()}).once("close",()=>t(!0)).listen(e,"127.0.0.1")})}var x=c(require("yocto-spinner"));var D=c(require("fs-extra")),K=require("node:path");var Se=async e=>{try{return(await fetch(e,{method:"GET",signal:AbortSignal.timeout(5e3)})).status===200}catch{return!1}},Y=async(e,t,o)=>{let s=Date.now();for(;Date.now()-s<t;){if(await Se(e))return!0;await new Promise(i=>setTimeout(i,o))}return!1};var B=c(require("open")),ye={command:"start",description:"Start local server, restarts if already running",handler:async()=>{await $()||await j(),await v();try{W()&&await I(),J();let t=n.getNumber("PORT")||4466;if(!t)throw new Error("PORT env variable not found");if(!await L(t))throw new Error(`Port ${t} is occupied by another process`);let s=(0,x.default)({text:"Starting new instance of "+m}).start(),r=D.readJsonSync((0,K.join)(a,"package.json"));await f(`pm2 start "${r.main}" --name "${m}" --no-autorestart -- "${a}/.env"`,{cwd:a}),s.success("Local server will be available in a couple of seconds");let i=(0,x.default)({text:"Waiting for the server to become available"}).start();await Y(`http://localhost:${t}/api/status`,3e4,1e3)?(await(0,B.default)(`http://localhost:${t}`),i.success(`App is running at http://localhost:${t}`)):i.error("Server failed to become available in time")}catch(t){console.error("Failed to start local server",t)}}},h=ye;var G=require("node:child_process");var we={command:"logs",description:"Listen for logs",handler:async()=>{(0,G.execSync)(`pm2 logs ${m}`,{stdio:"inherit"})}},U=we;var xe={command:"stop",description:"Stop the server",handler:v},Q=xe;var q=c(require("open")),Re={command:"open",description:"Open webapp",handler:async()=>{let e=n.getNumber("PORT");await(0,q.default)(`http://localhost:${e}`)}},z=Re;var X={name:"root",description:"Root module has no description",commands:[h,U,Q,z]};var Ce={command:"set <prop> <value>",description:"Set env value",module:"env",handler:async(e,t)=>{n.set(e,t),n.flush(),console.log(`Environment property set: ${e}`)}},Z=Ce;var Pe={command:"unset <prop>",description:"Remove env value",module:"env",handler:async e=>{n.unset(e),n.flush(),console.log(`Environment property unset: ${e}`)}},ee=Pe;var _e={command:"list",description:"List env values",module:"env",handler:async()=>{console.table(n.values())}},te=_e;var oe={name:"env",description:"Handle env variables",commands:[Z,ee,te]};var re=[X,oe],ne=h;var be=_();be.setMetadata({name:"dataramen",description:"A cozy web GUI for MySQL and PostgreSQL - built for developers who like to move fast and stay focused.",version:N().version}).setDefaultCommand(ne).setModules(re).start();
|
|
5
|
+
`;(0,E.writeFileSync)((0,w.join)(a,e.fileName),i,{encoding:"utf8"})}function s(r){if(e.customValues[r])return e.customValues[r]}return t(),{getNumber:r=>ge(s(r)),getString:r=>ve(s(r)),getBoolean:r=>Ee(s(r)),flush:o,set:(r,i)=>{e.customValues[r]=i.toString()},unset:r=>{delete e.customValues[r]},values:()=>({...e.customValues})}}function ge(e){if(!e)return;let t=Number(e);if(!isNaN(t)&&e.trim()!=="")return t;throw new Error("Wrong env value type")}function ve(e){if(e){if(typeof e=="string")return e;throw new Error("Wrong env value type")}}function Ee(e){if(!e)return;let t=e.toLowerCase();if(t==="true"||t==="1")return!0;if(t==="false"||t==="0")return!1;throw new Error("Wrong env value type")}var n=fe();function J(){let e=!1;if(!n.getString("SYMM_ENCRYPTION_KEY")){let t=S.randomBytes(32).toString("hex");n.set("SYMM_ENCRYPTION_KEY",t),console.log("Generated random SYMM_ENCRYPTION_KEY"),e=!0}if(!n.getString("JWT_SECRET")){let t=S.randomBytes(32).toString("hex");n.set("JWT_SECRET",t),console.log("Generated random JWT_SECRET"),e=!0}if(!n.getString("JWT_REFRESH_SECRET")){let t=S.randomBytes(32).toString("hex");n.set("JWT_REFRESH_SECRET",t),console.log("Generated random JWT_REFRESH_SECRET"),e=!0}e&&n.flush()}var F=require("node:net");async function L(e){return new Promise(t=>{let o=(0,F.createServer)().once("error",()=>{t(!1)}).once("listening",()=>{o.close()}).once("close",()=>t(!0)).listen(e,"127.0.0.1")})}var x=c(require("yocto-spinner"));var D=c(require("fs-extra")),K=require("node:path");var Se=async e=>{try{return(await fetch(e,{method:"GET",signal:AbortSignal.timeout(5e3)})).status===200}catch{return!1}},Y=async(e,t,o)=>{let s=Date.now();for(;Date.now()-s<t;){if(await Se(e))return!0;await new Promise(i=>setTimeout(i,o))}return!1};var B=c(require("open")),ye={command:"start",description:"Start local server, restarts if already running",handler:async()=>{await $()||await j(),await v();try{W()&&await I(),J();let t=n.getNumber("PORT")||4466;if(!t)throw new Error("PORT env variable not found");if(!await L(t))throw new Error(`Port ${t} is occupied by another process`);let s=(0,x.default)({text:"Starting new instance of "+m}).start(),r=D.readJsonSync((0,K.join)(a,"package.json"));await f(`pm2 start "${r.main}" --name "${m}" --no-autorestart -- local "${a}/.env"`,{cwd:a}),s.success("Local server will be available in a couple of seconds");let i=(0,x.default)({text:"Waiting for the server to become available"}).start();await Y(`http://localhost:${t}/api/status`,3e4,1e3)?(await(0,B.default)(`http://localhost:${t}`),i.success(`App is running at http://localhost:${t}`)):i.error("Server failed to become available in time")}catch(t){console.error("Failed to start local server",t)}}},h=ye;var G=require("node:child_process");var we={command:"logs",description:"Listen for logs",handler:async()=>{(0,G.execSync)(`pm2 logs ${m}`,{stdio:"inherit"})}},U=we;var xe={command:"stop",description:"Stop the server",handler:v},Q=xe;var q=c(require("open")),Re={command:"open",description:"Open webapp",handler:async()=>{let e=n.getNumber("PORT");await(0,q.default)(`http://localhost:${e}`)}},z=Re;var X={name:"root",description:"Root module has no description",commands:[h,U,Q,z]};var Ce={command:"set <prop> <value>",description:"Set env value",module:"env",handler:async(e,t)=>{n.set(e,t),n.flush(),console.log(`Environment property set: ${e}`)}},Z=Ce;var Pe={command:"unset <prop>",description:"Remove env value",module:"env",handler:async e=>{n.unset(e),n.flush(),console.log(`Environment property unset: ${e}`)}},ee=Pe;var _e={command:"list",description:"List env values",module:"env",handler:async()=>{console.table(n.values())}},te=_e;var oe={name:"env",description:"Handle env variables",commands:[Z,ee,te]};var re=[X,oe],ne=h;var be=_();be.setMetadata({name:"dataramen",description:"A cozy web GUI for MySQL and PostgreSQL - built for developers who like to move fast and stay focused.",version:N().version}).setDefaultCommand(ne).setModules(re).start();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var n=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var d=(s,e)=>{for(var a in e)n(s,a,{get:e[a],enumerable:!0})},b=(s,e,a,u)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of c(e))!p.call(s,r)&&r!==a&&n(s,r,{get:()=>e[r],enumerable:!(u=m(e,r))||u.enumerable});return s};var l=s=>b(n({},"__esModule",{value:!0}),s);var T={};d(T,{UsersManagement1755358316764:()=>i});module.exports=l(T);var o=require("typeorm");var y=process.env.APP_DB_TYPE==="sqlite"?"datetime":"timestamp",t={WorkbenchTabs:"workbench_tabs",Teams:"teams",Users:"users",UsersToTeams:"users_to_teams",UserSettings:"user_settings",DataSources:"data_sources",Query:"query",DbInspection:"db_inspection",SavedQueries:"saved_queries"};var i=class{name="UsersManagement1755358316764";async up(e){await e.addColumns(t.Users,[new o.TableColumn({name:"username",type:"varchar",isUnique:!0}),new o.TableColumn({name:"password",type:"varchar"})])}async down(e){await e.dropColumns(t.Users,["username","password"])}};0&&(module.exports={UsersManagement1755358316764});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var u=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var o=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var T=(s,e)=>{for(var m in e)u(s,m,{get:e[m],enumerable:!0})},N=(s,e,m,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of o(e))!c.call(s,n)&&n!==m&&u(s,n,{get:()=>e[n],enumerable:!(i=l(e,n))||i.enumerable});return s};var b=s=>N(u({},"__esModule",{value:!0}),s);var p={};T(p,{QueriesHistory1758316062697:()=>t});module.exports=b(p);var r=require("typeorm");var d=process.env.APP_DB_TYPE==="sqlite"?"datetime":"timestamp",a={WorkbenchTabs:"workbench_tabs",Teams:"teams",Users:"users",UsersToTeams:"users_to_teams",UserSettings:"user_settings",DataSources:"data_sources",Query:"query",DbInspection:"db_inspection",SavedQueries:"saved_queries"};var t=class{name="QueriesHistory1758316062697";async up(e){await e.createTable(new r.Table({name:a.SavedQueries,columns:[{name:"id",type:"uuid",isPrimary:!0,isGenerated:!0,generationStrategy:"uuid"},{name:"isPersonal",type:"boolean"},{name:"createdAt",type:d,default:"CURRENT_TIMESTAMP"},{name:"updatedAt",type:d,default:"CURRENT_TIMESTAMP"},{name:"teamId",type:"uuid",isNullable:!0},{name:"queryId",type:"uuid",isNullable:!1},{name:"userId",type:"uuid",isNullable:!1}]})),await e.createForeignKeys(a.SavedQueries,[new r.TableForeignKey({columnNames:["teamId"],referencedTableName:a.Teams,referencedColumnNames:["id"]}),new r.TableForeignKey({columnNames:["userId"],referencedTableName:a.Users,referencedColumnNames:["id"]}),new r.TableForeignKey({columnNames:["queryId"],referencedTableName:a.Query,referencedColumnNames:["id"]})]),await e.addColumns(a.Query,[new r.TableColumn({name:"userId",type:"uuid",isNullable:!0})]),await e.createForeignKeys(a.Query,[new r.TableForeignKey({columnNames:["userId"],referencedTableName:a.Users,referencedColumnNames:["id"]})])}async down(e){await e.dropForeignKeys(a.Query,[new r.TableForeignKey({columnNames:["userId"],referencedTableName:a.Users,referencedColumnNames:["id"]})]),await e.dropColumns(a.Query,["userId"]),await e.dropForeignKeys(a.SavedQueries,[new r.TableForeignKey({columnNames:["teamId"],referencedTableName:a.Teams,referencedColumnNames:["id"]}),new r.TableForeignKey({columnNames:["userId"],referencedTableName:a.Users,referencedColumnNames:["id"]}),new r.TableForeignKey({columnNames:["queryId"],referencedTableName:a.Query,referencedColumnNames:["id"]})]),await e.dropTable("saved_queries",!0)}};0&&(module.exports={QueriesHistory1758316062697});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var m=Object.defineProperty;var o=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var T=(s,e)=>{for(var t in e)m(s,t,{get:e[t],enumerable:!0})},b=(s,e,t,l)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of i(e))!c.call(s,n)&&n!==t&&m(s,n,{get:()=>e[n],enumerable:!(l=o(e,n))||l.enumerable});return s};var p=s=>b(m({},"__esModule",{value:!0}),s);var N={};T(N,{WorkbenchTabs1760816916693:()=>d});module.exports=p(N);var r=require("typeorm");var u=process.env.APP_DB_TYPE==="sqlite"?"datetime":"timestamp",a={WorkbenchTabs:"workbench_tabs",Teams:"teams",Users:"users",UsersToTeams:"users_to_teams",UserSettings:"user_settings",DataSources:"data_sources",Query:"query",DbInspection:"db_inspection",SavedQueries:"saved_queries"};var d=class{name="WorkbenchTabs1760816916693";async up(e){await e.createTable(new r.Table({name:a.WorkbenchTabs,columns:[{name:"id",type:"uuid",isPrimary:!0,isGenerated:!0,generationStrategy:"uuid"},{name:"createdAt",type:u,default:"CURRENT_TIMESTAMP"},{name:"updatedAt",type:u,default:"CURRENT_TIMESTAMP"},{name:"name",type:"varchar"},{name:"archived",type:"boolean",isNullable:!1,default:!1},{name:"teamId",type:"uuid",isNullable:!1},{name:"queryId",type:"uuid",isNullable:!0},{name:"userId",type:"uuid",isNullable:!1},{name:"opts",type:"json",default:"'{}'"}]})),await e.createForeignKeys(a.WorkbenchTabs,[new r.TableForeignKey({columnNames:["teamId"],referencedTableName:a.Teams,referencedColumnNames:["id"]}),new r.TableForeignKey({columnNames:["userId"],referencedTableName:a.Users,referencedColumnNames:["id"]}),new r.TableForeignKey({columnNames:["queryId"],referencedTableName:a.Query,referencedColumnNames:["id"]})])}async down(e){await e.dropForeignKeys(a.WorkbenchTabs,[new r.TableForeignKey({columnNames:["teamId"],referencedTableName:a.Teams,referencedColumnNames:["id"]}),new r.TableForeignKey({columnNames:["userId"],referencedTableName:a.Users,referencedColumnNames:["id"]}),new r.TableForeignKey({columnNames:["queryId"],referencedTableName:a.Query,referencedColumnNames:["id"]})]),await e.dropTable(a.WorkbenchTabs,!0)}};0&&(module.exports={WorkbenchTabs1760816916693});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var i=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var T=(a,e)=>{for(var t in e)i(a,t,{get:e[t],enumerable:!0})},
|
|
1
|
+
"use strict";var i=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var T=(a,e)=>{for(var t in e)i(a,t,{get:e[t],enumerable:!0})},S=(a,e,t,u)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of b(e))!p.call(a,r)&&r!==t&&i(a,r,{get:()=>e[r],enumerable:!(u=l(e,r))||u.enumerable});return a};var w=a=>S(i({},"__esModule",{value:!0}),a);var _={};T(_,{LinkTabToDatasource1762376647080:()=>c});module.exports=w(_);var o=require("typeorm");var C=process.env.APP_DB_TYPE==="sqlite"?"datetime":"timestamp",s={WorkbenchTabs:"workbench_tabs",Teams:"teams",Users:"users",UsersToTeams:"users_to_teams",UserSettings:"user_settings",DataSources:"data_sources",Query:"query",DbInspection:"db_inspection",SavedQueries:"saved_queries"};var m=new o.TableForeignKey({columnNames:["dataSourceId"],referencedTableName:s.DataSources,referencedColumnNames:["id"]}),d=new o.TableColumn({name:"dataSourceId",type:"uuid",isNullable:!0}),n=new o.TableColumn({name:"searchString",type:"varchar",isNullable:!0}),c=class{name="LinkTabToDatasource1762376647080";async up(e){await e.addColumns(s.WorkbenchTabs,[d,n]),await e.addColumns(s.SavedQueries,[n]),await e.createForeignKeys(s.WorkbenchTabs,[m])}async down(e){await e.dropForeignKeys(s.WorkbenchTabs,[m]),await e.dropColumns(s.WorkbenchTabs,[d,n]),await e.dropColumns(s.SavedQueries,[n])}};0&&(module.exports={LinkTabToDatasource1762376647080});
|
package/dist/code/server.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"use strict";var wr=Object.create;var xe=Object.defineProperty;var Er=Object.getOwnPropertyDescriptor;var Sr=Object.getOwnPropertyNames;var br=Object.getPrototypeOf,Rr=Object.prototype.hasOwnProperty;var Ir=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Sr(t))!Rr.call(e,a)&&a!==r&&xe(e,a,{get:()=>t[a],enumerable:!(o=Er(t,a))||o.enumerable});return e};var v=(e,t,r)=>(r=e!=null?wr(br(e)):{},Ir(t||!e||!e.__esModule?xe(r,"default",{value:e,enumerable:!0}):r,e));var ee=require("dotenv"),te=require("node:path"),Le=require("node:fs"),Nr=(()=>{try{let e=(0,Le.readFileSync)((0,te.join)(__dirname,"..","package.json"),"utf8");return JSON.parse(e)}catch{return{version:"0.0.0"}}})(),Me=[];process.argv[2]&&Me.push((0,te.resolve)(process.argv[2]));(0,ee.config)({path:Me});(0,ee.populate)(process.env,{SERVER_VERSION:Nr.version,APP_DB_TYPE:"sqlite",APP_DB_DATABASE:"<home>/.dataramen/.runtime/db.sqlite3",PROD:"true"},{override:!1});var Cr=["SYMM_ENCRYPTION_KEY","JWT_SECRET","JWT_REFRESH_SECRET"],Fe=()=>{let e=[];for(let t of Cr)process.env[t]||e.push(t);if(e.length>0)throw new Error("Following env variables are required but not provided: "+e.join(", "))};function Pr(e,t=void 0){return process.env[e]||t}function Or(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 Ar(e){return process.env[e]==="true"||process.env[e]==="TRUE"||process.env[e]==="1"}var T={str:Pr,num:Or,bool:Ar};var Wi=require("reflect-metadata"),lr=v(require("fastify")),mr=v(require("@fastify/cors")),dr=v(require("@fastify/static")),pr=v(require("qs"));var s=class extends Error{constructor(r,o){super(o);this.status=r;this.message=o}};var Ge=require("typeorm");var qe=require("typeorm");var y=T.str("APP_DB_TYPE")==="sqlite"?"datetime":"timestamp";var pe=new qe.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:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,default:()=>"CURRENT_TIMESTAMP"}},relations:{datasource:{target:()=>"DataSource",type:"many-to-one",joinTable:!1,cascade:!0}}});var Qe=require("typeorm");var fe=new Qe.EntitySchema({name:"Team",tableName:"teams",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,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 ke=require("typeorm");var ye=new ke.EntitySchema({name:"User",tableName:"users",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,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},queries:{type:"one-to-many",target:()=>"Query",inverseSide:"user"}}});var $e=require("typeorm");var Te=new $e.EntitySchema({name:"UserSettings",tableName:"user_settings",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,default:()=>"CURRENT_TIMESTAMP"}},relations:{user:{type:"one-to-one",target:()=>"User",inverseSide:"settings",joinColumn:!0}}});var Be=require("typeorm");var he=new Be.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:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,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:y,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 Ke=v(require("node:os")),Ve=require("node:path");var We=require("typeorm");var ge=new We.EntitySchema({name:"Query",tableName:"query",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},opts:{type:"json",default:"{}"},createdAt:{type:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,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},user:{type:"many-to-one",target:()=>"User",inverseSide:"queries",joinColumn:!0,nullable:!0}}});var He=require("typeorm"),we=new He.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"}}});var Ye=require("typeorm");var Ee=new Ye.EntitySchema({name:"SavedQuery",tableName:"saved_queries",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},isPersonal:{type:Boolean},createdAt:{type:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,default:()=>"CURRENT_TIMESTAMP",onUpdate:"CURRENT_TIMESTAMP"},searchString:{type:String,default:()=>null}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"queries",joinColumn:!0},user:{type:"many-to-one",target:()=>"User",inverseSide:"queries",joinColumn:!0,nullable:!0},query:{type:"one-to-one",target:()=>"Query",joinColumn:!0,nullable:!1}}});var je=require("typeorm");var Se=new je.EntitySchema({name:"WorkbenchTab",tableName:"workbench_tabs",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,default:()=>"CURRENT_TIMESTAMP",onUpdate:"CURRENT_TIMESTAMP"},opts:{type:"json",default:"{}"},archived:{type:Boolean,default:!1},searchString:{type:String,default:()=>null}},relations:{team:{type:"many-to-one",target:()=>"Team",joinColumn:!0},user:{type:"many-to-one",target:()=>"User",joinColumn:!0},dataSource:{type:"many-to-one",target:()=>"DataSource",joinColumn:!0}}});function _r(){let e=T.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>",Ke.default.homedir())),e}var h=new Ge.DataSource({type:T.str("APP_DB_TYPE"),database:_r(),host:T.str("APP_DB_HOST"),username:T.str("APP_DB_USERNAME"),password:T.str("APP_DB_PASSWORD"),port:T.num("APP_DB_PORT"),schema:T.str("APP_DB_SCHEMA"),logging:T.bool("APP_DB_LOGGING"),migrationsRun:!0,migrations:[Ve.posix.join(__dirname,"migrations","*.js")],entities:[pe,he,fe,ye,we,Te,ge,Ee,Se]}),ze=async()=>{if(!h.isInitialized)return h.initialize();throw new Error("Already initialized")},x=h.getRepository(pe),E=h.getRepository(he),F=h.getRepository(fe),R=h.getRepository(ye),C=h.getRepository(we),W=h.getRepository(Te),I=h.getRepository(ge),L=h.getRepository(Ee),P=h.getRepository(Se);var g=e=>(t,r,o)=>{e(t),o()};var j=require("jose");var Je=new TextEncoder,Xe=Je.encode(T.str("JWT_SECRET")),Ze=Je.encode(T.str("JWT_REFRESH_SECRET")),be=async({userId:e})=>new j.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("1h").sign(Xe),Re=async({userId:e})=>new j.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("10d").sign(Ze),et=async(e,t)=>{try{let{payload:r}=await(0,j.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")}},tt=async e=>et(e,Xe),rt=async e=>et(e,Ze);var d=(e,t)=>{let r=e.body;return t&&t(r),r},q=(e,t)=>{let r=e.query;return t&&t(r),r},p=(e,t)=>{let r=e.params;return t&&t(r),r};var at=v(require("bcryptjs"));var ot=e=>{if(!e?.username)throw new s(400,"Username is required");if(!e?.password)throw new s(400,"Password is required")};var re="DATARAMEN_refresh_token",Ie={httpOnly:!0,secure:T.bool("PROD"),sameSite:T.bool("PROD"),path:"/",maxAge:10*24*60*60},nt=g(e=>{e.route({method:"post",url:"/login",config:{isPublic:!0},handler:async(t,r)=>{let{username:o,password:a}=d(t,ot),n=await R.findOne({where:{username:o}});if(!n||!at.default.compareSync(a,n.password))throw new s(401,"Invalid credentials");let[i,u]=await Promise.all([be({userId:n?.id}),Re({userId:n?.id})]);return r.setCookie(re,u,Ie),{data:{accessToken:i}}}}),e.route({method:"post",url:"/refresh",config:{isPublic:!0},handler:async(t,r)=>{let o=t.cookies[re];if(!o)return r.code(401).send({message:"Missing refresh token"});let{userId:a}=await rt(o),[n,i]=await Promise.all([be({userId:a}),Re({userId:a})]);return r.setCookie(re,i,Ie),{data:{accessToken:n}}}}),e.route({method:"post",url:"/logout",config:{isPublic:!0},handler:async(t,r)=>(r.clearCookie(re,Ie),{data:!0})})});var st=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 ut=v(require("mysql2/promise"));function G(e){if(e!==void 0)return e.toLowerCase()}var vr=({database:e,password:t,user:r,url:o})=>ut.default.createConnection({host:o,user:r,database:e,password:t}),Dr=async e=>{let t=`
|
|
1
|
+
"use strict";var Or=Object.create;var Le=Object.defineProperty;var Pr=Object.getOwnPropertyDescriptor;var Ar=Object.getOwnPropertyNames;var _r=Object.getPrototypeOf,vr=Object.prototype.hasOwnProperty;var Dr=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Ar(t))!vr.call(e,a)&&a!==r&&Le(e,a,{get:()=>t[a],enumerable:!(o=Pr(t,a))||o.enumerable});return e};var _=(e,t,r)=>(r=e!=null?Or(_r(e)):{},Dr(t||!e||!e.__esModule?Le(r,"default",{value:e,enumerable:!0}):r,e));var te=require("dotenv"),re=require("node:path"),Me=require("node:fs"),Ur=(()=>{try{let e=(0,Me.readFileSync)((0,re.join)(__dirname,"..","package.json"),"utf8");return JSON.parse(e)}catch{return{version:"0.0.0"}}})(),Fe=[];process.argv[3]&&Fe.push((0,re.resolve)(process.argv[3]));(0,te.config)({path:Fe});(0,te.populate)(process.env,{SERVER_VERSION:Ur.version,APP_DB_TYPE:"sqlite",APP_DB_DATABASE:"<home>/.dataramen/.runtime/db.sqlite3",PROD:"true"},{override:!1});var xr=["SYMM_ENCRYPTION_KEY","JWT_SECRET","JWT_REFRESH_SECRET"],qe=()=>{let e=[];for(let t of xr)process.env[t]||e.push(t);if(e.length>0)throw new Error("Following env variables are required but not provided: "+e.join(", "))};function Lr(e,t=void 0){return process.env[e]||t}function Mr(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 Fr(e){return process.env[e]==="true"||process.env[e]==="TRUE"||process.env[e]==="1"}var T={str:Lr,num:Mr,bool:Fr};var Ou=require("reflect-metadata"),br=_(require("fastify")),Ir=_(require("qs"));var Ke=require("typeorm");var ke=require("typeorm");var y=T.str("APP_DB_TYPE")==="sqlite"?"datetime":"timestamp";var fe=new ke.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:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,default:()=>"CURRENT_TIMESTAMP"}},relations:{datasource:{target:()=>"DataSource",type:"many-to-one",joinTable:!1,cascade:!0}}});var Qe=require("typeorm");var ye=new Qe.EntitySchema({name:"Team",tableName:"teams",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,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 $e=require("typeorm");var Te=new $e.EntitySchema({name:"User",tableName:"users",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,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},queries:{type:"one-to-many",target:()=>"Query",inverseSide:"user"}}});var Be=require("typeorm");var he=new Be.EntitySchema({name:"UserSettings",tableName:"user_settings",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,default:()=>"CURRENT_TIMESTAMP"}},relations:{user:{type:"one-to-one",target:()=>"User",inverseSide:"settings",joinColumn:!0}}});var We=require("typeorm");var ge=new We.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:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,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:y,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 Ve=_(require("node:os")),ze=require("node:path");var He=require("typeorm");var we=new He.EntitySchema({name:"Query",tableName:"query",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},opts:{type:"json",default:"{}"},createdAt:{type:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,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},user:{type:"many-to-one",target:()=>"User",inverseSide:"queries",joinColumn:!0,nullable:!0}}});var Ye=require("typeorm"),Ee=new Ye.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"}}});var je=require("typeorm");var Se=new je.EntitySchema({name:"SavedQuery",tableName:"saved_queries",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},isPersonal:{type:Boolean},createdAt:{type:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,default:()=>"CURRENT_TIMESTAMP",onUpdate:"CURRENT_TIMESTAMP"},searchString:{type:String,default:()=>null}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"queries",joinColumn:!0},user:{type:"many-to-one",target:()=>"User",inverseSide:"queries",joinColumn:!0,nullable:!0},query:{type:"one-to-one",target:()=>"Query",joinColumn:!0,nullable:!1}}});var Ge=require("typeorm");var Re=new Ge.EntitySchema({name:"WorkbenchTab",tableName:"workbench_tabs",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:y,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:y,default:()=>"CURRENT_TIMESTAMP",onUpdate:"CURRENT_TIMESTAMP"},opts:{type:"json",default:"{}"},archived:{type:Boolean,default:!1},searchString:{type:String,default:()=>null}},relations:{team:{type:"many-to-one",target:()=>"Team",joinColumn:!0},user:{type:"many-to-one",target:()=>"User",joinColumn:!0},dataSource:{type:"many-to-one",target:()=>"DataSource",joinColumn:!0}}});function qr(){let e=T.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>",Ve.default.homedir())),e}var g=new Ke.DataSource({type:T.str("APP_DB_TYPE"),database:qr(),host:T.str("APP_DB_HOST"),username:T.str("APP_DB_USERNAME"),password:T.str("APP_DB_PASSWORD"),port:T.num("APP_DB_PORT"),schema:T.str("APP_DB_SCHEMA"),logging:T.bool("APP_DB_LOGGING"),migrationsRun:!0,migrations:[ze.posix.join(__dirname,"migrations","*.js")],entities:[fe,ge,ye,Te,Ee,he,we,Se,Re]}),Je=async()=>{if(!g.isInitialized)return g.initialize();throw new Error("Already initialized")},D=g.getRepository(fe),b=g.getRepository(ge),M=g.getRepository(ye),R=g.getRepository(Te),C=g.getRepository(Ee),B=g.getRepository(he),I=g.getRepository(we),U=g.getRepository(Se),O=g.getRepository(Re);var be=_(require("bcryptjs")),Y=async e=>{let t=await be.default.genSalt(10);return be.default.hash(e,t)};var Ie={teamName:"Default Team",username:"admin",password:"admin"},kr=async()=>{let e=await M.findOneBy({});return e||M.save(M.create({name:Ie.teamName}))},Xe=async()=>{let e=await C.findOne({where:{role:"owner"},relations:{user:!0}});if(e)return e.user;let t=await kr(),r=await Y(Ie.password),o=await R.save(R.create({username:Ie.username,password:r})),a=await C.save(C.create({user:o,team:t,role:"owner"}));return await R.update(o.id,{currentTeam:a}),o};var Qr={hosted:{bindServerUrl:"0.0.0.0",skipAuth:!1,name:"hosted"},local:{bindServerUrl:"127.0.0.1",skipAuth:!0,name:"local"}},Ze=process.argv[2];if(!Ze)throw new Error(`Invalid mode "${process.argv[2]}"`);var Q=Qr[Ze];var et=T.str("ALLOWED_ORIGINS","").split(",").map(e=>e.trim()),tt=T.num("PORT",4466),j={port:tt,host:Q.bindServerUrl,allowedOrigins:et.includes("*")?"*":[`http://localhost:${tt}`,...et]};var h=e=>(t,r,o)=>{e(t),o()};var G=require("jose");var s=class extends Error{constructor(r,o){super(o);this.status=r;this.message=o}};var rt=new TextEncoder,ot=rt.encode(T.str("JWT_SECRET")),at=rt.encode(T.str("JWT_REFRESH_SECRET")),Ne=async({userId:e})=>new G.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("1h").sign(ot),Ce=async({userId:e})=>new G.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("10d").sign(at),nt=async(e,t)=>{try{let{payload:r}=await(0,G.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")}},st=async e=>nt(e,ot),it=async e=>nt(e,at);var f=(e,t)=>{let r=e.body;return t&&t(r),r},x=(e,t)=>{let r=e.query;return t&&t(r),r},m=(e,t)=>{let r=e.params;return t&&t(r),r};var ct=_(require("bcryptjs"));var ut=e=>{if(!e?.username)throw new s(400,"Username is required");if(!e?.password)throw new s(400,"Password is required")};var oe="DATARAMEN_refresh_token",Oe={httpOnly:!0,secure:T.bool("PROD"),sameSite:T.bool("PROD"),path:"/",maxAge:10*24*60*60},lt=h(e=>{e.route({method:"post",url:"/login",config:{isPublic:!0},handler:async(t,r)=>{let{username:o,password:a}=f(t,ut),n=await R.findOne({where:{username:o}});if(!n||!ct.default.compareSync(a,n.password))throw new s(401,"Invalid credentials");let[i,u]=await Promise.all([Ne({userId:n?.id}),Ce({userId:n?.id})]);return r.setCookie(oe,u,Oe),{data:{accessToken:i}}}}),e.route({method:"post",url:"/refresh",config:{isPublic:!0},handler:async(t,r)=>{let o=t.cookies[oe];if(!o)return r.code(401).send({message:"Missing refresh token"});let{userId:a}=await it(o),[n,i]=await Promise.all([Ne({userId:a}),Ce({userId:a})]);return r.setCookie(oe,i,Oe),{data:{accessToken:n}}}}),e.route({method:"post",url:"/logout",config:{isPublic:!0},handler:async(t,r)=>(r.clearCookie(oe,Oe),{data:!0})})});var mt=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 pt=_(require("mysql2/promise"));function K(e){if(e!==void 0)return e.toLowerCase()}var $r=({database:e,password:t,user:r,url:o})=>pt.default.createConnection({host:o,user:r,database:e,password:t}),Br=async e=>{let t=`
|
|
2
2
|
SELECT LOWER(TABLE_NAME) as 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=
|
|
6
|
+
`,[r]=await e.execute(t),o={};return r.forEach(a=>{let n=K(a.TABLE_NAME),i=a.COLUMN_NAME;o[n]||(o[n]=[]),o[n].push(i)}),o},Wr=async e=>{let t=`
|
|
7
7
|
SELECT
|
|
8
8
|
LOWER(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},
|
|
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},Hr=async(e,t)=>{let o=(await t.query("SHOW TABLES"))[0],a=await Wr(t),n=await Br(t),i=o.map(async u=>{let d=K(Object.values(u)[0]),c=`select COLUMN_NAME, DATA_TYPE from information_schema.columns where table_schema = '${e.database}' and LOWER(table_name) = '${d}'`,[S]=await t.query(c),w=a[d];return{columns:S.map(l=>({name:l.COLUMN_NAME,type:l.DATA_TYPE,isPrimary:n[d]?.includes(l.COLUMN_NAME),ref:w?.[l.COLUMN_NAME]?{table:w[l.COLUMN_NAME].refTable,field:w[l.COLUMN_NAME].refField}:void 0})).sort((l,N)=>l.isPrimary&&N.isPrimary?l.name.localeCompare(N.name):l.isPrimary?-1:1),createdAt:new Date,tableName:d,updatedAt:new Date}});return Promise.all(i)},dt=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:K(u.orgTable),alias:u.name,full:u.orgTable?K(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)}},Yr=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}},jr=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}},ft=async e=>{let t=await $r(e),r=!1;return{dbType:"mysql",dataSource:e,inspectSchema:()=>Hr(e,t),executeQuery:(o,a)=>a.type==="SELECT"?jr(t,()=>dt(o,t,a)):Yr(t,()=>dt(o,t,a)),checkConnection:async()=>t.ping(),isClosed:()=>r,close:async()=>{if(!r)return r=!0,t.destroy()}}};var Tt=_(require("pg"));var Gr=async({database:e,password:t,user:r,url:o,port:a})=>{let n=new Tt.default.Client({host:o,user:r,database:e,password:t,port:a,query_timeout:1e4});return await n.connect(),n},Kr=async e=>{let r=await e.query(`
|
|
18
18
|
SELECT
|
|
19
19
|
LOWER(kcu.table_name) as table_name,
|
|
20
20
|
kcu.column_name,
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
tc.constraint_type = 'PRIMARY KEY'
|
|
29
29
|
ORDER BY
|
|
30
30
|
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},
|
|
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},Vr=async e=>{let r=await e.query(`
|
|
32
32
|
SELECT
|
|
33
33
|
LOWER(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},
|
|
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},zr=async(e,t)=>{let r=`SELECT LOWER(tablename) as tablename FROM pg_catalog.pg_tables WHERE schemaname = '${e.schema}'`,a=(await t.query(r)).rows,n=await Vr(t),i=await Kr(t),u=a.map(async d=>{let c=Object.values(d)[0],S=`
|
|
47
47
|
SELECT column_name, data_type
|
|
48
48
|
FROM information_schema.columns
|
|
49
49
|
WHERE
|
|
50
50
|
LOWER(table_name) = '${c}' and
|
|
51
51
|
table_schema = '${e.schema}'
|
|
52
|
-
`,{rows:w}=await t.query(
|
|
52
|
+
`,{rows:w}=await t.query(S),l=n[c];return{columns:w.map(N=>({name:N.column_name,type:N.data_type,isPrimary:i[c]?.includes(N.column_name),ref:l?.[N.column_name]?{table:l[N.column_name].refTable,field:l[N.column_name].refField}:void 0})).sort((N,L)=>N.isPrimary&&L.isPrimary?N.name.localeCompare(L.name):N.isPrimary?-1:1),createdAt:new Date,tableName:c,updatedAt:new Date}});return Promise.all(u)},Jr=async(e,t)=>{let r=`select LOWER(relname) as 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 75;`;return(await t.query(r)).rows.reduce((a,n)=>(a[n.row_key]={table:n.relname,column:n.attname},a),{})},lt=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(c=>`'${c.tableID}-${c.columnID}'`),f=await $r(u,t);return{columns:a.map(c=>{let b=f[`${c.tableID}-${c.columnID}`];return{column:b?.column||c.name,alias:c.name,table:b?.table||"",full:b?b.table+"."+b.column:c.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)}},Br=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}},Wr=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}},dt=async e=>{let t=await Fr(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:()=>kr(e,t),executeQuery:(n,i)=>a(()=>i.type==="SELECT"?Wr(t,()=>lt(n,t,i)):Br(t,()=>lt(n,t,i))),checkConnection:async()=>{},isClosed:()=>r,close:async()=>{if(!r)return r=!0,t.end()}}};var Q=async(e,t,r)=>{try{let o;if(t==="mysql")o=await ct(e);else if(t==="postgres")o=await dt(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 oe=v(require("node:crypto"));var pt="aes-256-gcm",Hr=12,ft=()=>{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},Yr=e=>{let t=oe.default.randomBytes(Hr),r=ft(),o=oe.default.createCipheriv(pt,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")}},jr=({encrypted:e,iv:t,tag:r})=>{let o=ft(),a=oe.default.createDecipheriv(pt,o,Buffer.from(t,"hex"));a.setAuthTag(Buffer.from(r,"hex"));let n=a.update(e,"hex","utf8");return n+=a.final("utf8"),n},ae={encrypt:Yr,decrypt:jr};var k=(e,t=!1)=>{if(t){let r=ae.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 yt=[{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"}],Gr=yt.reduce((e,t)=>(e[t.value]=t.label,e),{}),Qa=yt.reduce((e,t)=>(e[t.label]=t.value,e),{}),H=e=>e.map(t=>({label:Gr[t],value:t})),ka=H(["=","<>",">",">=","<","<=","IN","NOT IN","IS NULL","IS NOT NULL"]),$a=H(["=","<>","LIKE","NOT LIKE","IN","NOT IN","IS NULL","IS NOT NULL"]),Ba=H(["=","<>","IS NULL","IS NOT NULL"]),Wa=H(["=","<>",">",">=","<","<=","IS NULL","IS NOT NULL"]),Ha=H(["IS NULL","IS NOT NULL"]),Ya=H(["IN","NOT IN"]);var Ne=["char","varchar","binary","varbinary","blob","text","enum","set","character","character varying","text","citext","uuid","xml","json","jsonb"],Kr=new Set(Ne),ne=e=>Kr.has(e),Vr=["integer","smallint","decimal","numeric","float","real","double precision","int","smallint","integer","bigint","decimal","numeric","real","double precision","serial","bigserial","money"],zr=new Set(Vr),Tt=e=>zr.has(e);var ja=["date","datetime","timestamp","timestamptz"].reduce((e,t)=>(e[t]=!0,e),{});var Ce=e=>e.fn?e.distinct===!0?`${e.fn} distinct ${e.value}`:`${e.fn} ${e.value}`:e.value;var Pe={read_only:10,editor:20,admin:30,owner:40};var D=e=>e.startsWith("'")&&e.endsWith("'")||e.startsWith('"')&&e.endsWith('"')?e.slice(1,-1):e;var ht={operator:"LIKE",parse:e=>{let t=e.match(/^LIKE\s*["'](.*)["']$/i);if(t)return[{value:D(t[1])}]},stringify:(e,t)=>ne(t)?`${e.value?.[0].value}`:`LIKE "%${e.value?.[0].value}%"`},gt={operator:"NOT LIKE",parse:e=>{let t=e.match(/^NOT LIKE\s*["'](.*)["']$/i);if(t)return[{value:D(t[1])}]},stringify:e=>`NOT LIKE "%${e.value?.[0].value}%"`};function Et(e){return e===""?[]:Jr(e).map(Xr)}function Jr(e){let t=[],r=0,o="",a=!1,n=!1;for(;r<e.length;){let i=e[r];if((a||n)&&i==="\\"){o+=e[r+1],r+=2;continue}if(i==="'"&&!n){a=!a,o+=i,r++;continue}if(i==='"'&&!a){n=!n,o+=i,r++;continue}if(i===","&&!a&&!n){t.push(o.trim()),o="",r++;continue}o+=i,r++}if(o.trim()!==""&&t.push(o.trim()),a||n)throw new Error("Unterminated string literal");return t}function Xr(e){if(e.startsWith("'")&&e.endsWith("'"))return{value:wt(e.slice(1,-1),"'")};if(e.startsWith('"')&&e.endsWith('"'))return{value:wt(e.slice(1,-1),'"')};let t=Number(e);if(!Number.isNaN(t))return{value:t};throw new Error(`Invalid literal: ${e}`)}function wt(e,t){return e.replace(/\\(.)/g,(r,o)=>o)}var St={operator:"IN",parse:e=>{let t=e.match(/^in\s*\((.*)\)$/i);if(t)return Et(t[1])},stringify:e=>`IN (${e.value?.map(t=>`"${t.value}"`).join(", ")})`},bt={operator:"NOT IN",parse:e=>{let t=e.match(/^not\s+in\s*\((.*)\)$/i);if(t)return Et(t[1])},stringify:e=>`NOT IN (${e.value?.map(t=>`"${t.value}"`).join(", ")})`};var Rt={operator:"=",parse:e=>{let t=e.match(/^=\s*(.*)$/);if(t)return[{value:D(t[1])}]},stringify:(e,t)=>Tt(t)?`${e.value?.[0].value}`:`= ${e.value?.[0].value}`},It={operator:"!=",parse:e=>{let t=e.match(/^!=\s*(.*)$/);if(t)return[{value:D(t[1])}]},stringify:e=>`!= ${e.value?.[0].value}`},Nt={operator:"<>",parse:e=>{let t=e.match(/^<>\s*(.*)$/);if(t)return[{value:D(t[1])}]},stringify:e=>`<> ${e.value?.[0].value}`},Ct={operator:">",parse:e=>{let t=e.match(/^>\s*(.*)$/);if(t)return[{value:D(t[1])}]},stringify:e=>`> ${e.value?.[0].value}`},Pt={operator:">=",parse:e=>{let t=e.match(/^>=\s*(.*)$/);if(t)return[{value:D(t[1])}]},stringify:e=>`>= ${e.value?.[0].value}`},Ot={operator:"<",parse:e=>{let t=e.match(/^<\s*(.*)$/);if(t)return[{value:D(t[1])}]},stringify:e=>`< ${e.value?.[0].value}`},At={operator:"<=",parse:e=>{let t=e.match(/^<=\s*(.*)$/);if(t)return[{value:D(t[1])}]},stringify:e=>`<= ${e.value?.[0].value}`};var _t={operator:"IS NULL",parse:e=>{if(/^is\s+null$/i.test(e))return[]},stringify:()=>"IS NULL"},vt={operator:"IS NOT NULL",parse:e=>{if(/^is\s+not\s+null$/i.test(e))return[]},stringify:()=>"IS NOT NULL"};var Dt=[ht,gt,St,bt,Rt,It,Nt,Pt,Ct,At,Ot,_t,vt],Zr=Dt.reduce((e,t)=>(e[t.operator]=t,e),{});function eo(e,t){return Zr[e.operator]?.stringify(e,t)||""}function to(e){let t=e.trim();for(let r of Dt){let o=r.parse(t);if(o)return{operator:r.operator,value:o}}}var Ut={parse:to,stringify:eo};var S=e=>{let t=Pe[e];return r=>Pe[r.currentTeamRole]>=t},xt=async e=>{let t=e.routeOptions.config.requireRole;if(t&&!t(e.user))throw new s(403,"You are not authorized to perform this action")};var Lt=g(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=p(t),o=await E.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}=q(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}=d(t,st),n=E.create({...a,allowUpdate:!!a.allowUpdate,allowInsert:!!a.allowInsert,team:{id:r},owner:{id:o}}),i=await Q(k(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:f,encrypted:c}=ae.encrypt(n.dbPassword);return n.dbPassword=c,n.dbPasswordIv=f,n.dbPasswordTag=u,{data:await E.save(n)}}}),e.route({method:"put",url:"/:id",config:{requireRole:S("admin")},handler:async t=>{let{id:r}=p(t),o=d(t),a=await E.findOneBy({id:r});if(!a)throw new s(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,r)=>h.transaction(async()=>{let{id:o}=p(t);await Promise.all([x.delete({datasource:{id:o}}),I.delete({dataSource:{id:o}})]),await E.delete({id:o})})}),e.route({method:"post",url:"/:id/inspect",handler:async(t,r)=>{let{id:o}=p(t),a=await E.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 E.save(a);let i=await(await Q(k(a,!0),a.dbType,t)).inspectSchema();await x.delete({datasource:{id:o}}),await x.insert(i.sort().map(u=>x.create({tableName:u.tableName,columns:u.columns,datasource:{id:o}}))),a.status="READY",a.lastInspected=new Date,await E.save(a)}}),e.route({method:"get",url:"/:id/inspections",handler:async t=>{let{id:r}=p(t);return{data:await x.find({where:{datasource:{id:r}}})}}})});var B=require("typeorm"),Mt=g(e=>{e.route({method:"get",url:"/team/:teamId/datasources",handler:async t=>{let{teamId:r}=p(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 o=p(t).teamId||t.user.currentTeamId;return{data:(await L.find({where:[{isPersonal:!1,team:{id:o}},{isPersonal:!0,team:{id:o},user:{id:t.user.id}}],relations:{query:!0},select:{id:!0,query:{id:!0,name:!0,updatedAt:!0}}})).map(i=>({name:i.query.name,id:i.query.id,updatedAt:i.query.updatedAt,savedQueryId:i.id}))}}}),e.route({method:"get",url:"/team/:teamId/query",handler:async t=>{let{teamId:r}=p(t),{search:o,size:a,selectedDataSources:n}=q(t),i=o.length>3?parseInt(a)||20:8,u={};n?.length&&(u.id=(0,B.In)(n));let[f,c,b]=await Promise.all([x.find({where:{tableName:(0,B.Raw)(l=>`LOWER(${l}) LIKE :search`,{search:`%${o.toLowerCase()}%`}),datasource:u},relations:{datasource:!0},select:{id:!0,tableName:!0,datasource:{name:!0,id:!0}},order:{tableName:"ASC"},take:i}),P.find({where:{searchString:(0,B.Like)(`%${o.toLowerCase()}%`),team:{id:r},user:{id:t.user.id},dataSource:u},relations:{dataSource:!0},select:{id:!0,name:!0,updatedAt:!0,dataSource:{id:!0,name:!0}},order:{updatedAt:"ASC"},take:i}),L.find({where:{searchString:(0,B.Like)(`%${o.toLowerCase()}%`),team:{id:r},query:{dataSource:u}},relations:{query:{dataSource:!0}},select:{id:!0,updatedAt:!0,query:{id:!0,name:!0,dataSource:{name:!0}}},order:{updatedAt:"ASC"},take:i})]),w=[];return f.forEach(l=>{w.push({name:l.tableName,id:l.id,dataSourceName:l.datasource?.name||"--",dataSourceId:l.datasource?.id||"--",type:"table"})}),c.forEach(l=>{w.push({name:l.name,id:l.id,dataSourceName:l.dataSource?.name||"--",dataSourceId:l.dataSource?.id||"--",type:"tab"})}),b.forEach(l=>{w.push({name:l.query.name,id:l.query.id,dataSourceName:l.query.dataSource?.name||"--",dataSourceId:l.query.dataSource?.id||"--",type:"query"})}),{data:w}}}),e.route({method:"get",url:"/team/:teamId/tabs-history",handler:async t=>{let{teamId:r}=p(t),o=q(t),a=Number(o.page),n=Number(o.size),i=t.user.id,u=await P.find({where:{team:{id:r},user:{id:i}},relations:{dataSource:!0},order:{updatedAt:"DESC"},take:n+1,skip:a*n}),f=!1;return u.length>n&&(u.pop(),f=!0),{data:u.map(c=>({name:c.name,id:c.id,updatedAt:c.updatedAt,archived:c.archived,createdAt:c.createdAt,dataSourceId:c.dataSource?.id,dataSourceName:c.dataSource?.name,dataSourceType:c.dataSource?.dbType})),hasMore:f}}})});var Ft=g(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=p(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:S("editor")},handler:async t=>{let r=d(t),o=await E.findOne({where:{id:r.dataSourceId},relations:{team:!0}});return{data:await I.save(I.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}=p(t),o=d(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:S("editor")},handler:async t=>h.transaction(async()=>{let{id:r}=p(t);if(!(await I.delete({id:r})).affected)return{status:404,data:"Query not found"}})})});var se=e=>{let t=e.distinct===!0?"distinct ":"";return`${e.fn}(${t}${e.value})`},K={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:se,MAX:se,MIN:se,COUNT:se};var ie=e=>{let t=e.distinct===!0?"distinct ":"";return`${e.fn}(${t}${e.value})`},V={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:ie,MAX:ie,MIN:ie,COUNT:ie};var qt=["SUM","COUNT","AVG","MAX","MIN"],ro=["YEAR","MONTH","DAY",...qt],oo=ro.reduce((e,t)=>(e[t]=!0,e),{}),ao=qt.reduce((e,t)=>(e[t]=!0,e),{}),ue=e=>oo[e],Qt=e=>ao[e],kt=(e,t)=>e.fn&&ue(e.fn)?(t==="postgres"?K:V)[e.fn](e):e.value;var ce=e=>typeof e=="string",$t=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},z=(e,t)=>{let{column:r,operator:o,value:a,fn:n}=e,i=kt({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(l=>ce(l.value)?`'${l.value}'`:l.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 b=a?.[0],w;return ce(b?.value)&&b?.isColumn!==!0?w=`'${b?.value}'`:w=b?.value,`${i} ${o} ${w}`}};var le=class{constructor(t="mysql"){this.dialect=t,this.skeleton={type:"SELECT"}}addWhere(t){let r=z(t,this.dialect);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=z(t,this.dialect);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 $t(this.skeleton)}};var Yt=require("typeorm");var Bt=e=>ne(e)?"LIKE":"=",Wt=(e,t)=>{let r=[];for(let o of e)if(!(!o.column?.length||!o.value?.length||!o.isEnabled))if(o.isAdvanced){let a=Ut.parse(o.value);if(!a)throw new s(400,`Invalid value for '${o.column}': ${o.value}`);r.push({value:a.value,column:o.column,id:o.id,operator:a.operator||Bt(t[o.column]),connector:"AND"})}else r.push({value:o.value?[{value:o.value}]:[],column:o.column,id:o.id,operator:Bt(t[o.column]),connector:"AND"});return r};var me=async(e,t)=>{let{datasourceId:r,size:o=20,page:a,name:n}=t,{table:i,joins:u,groupBy:f,searchAll:c,orderBy:b}=t.opts,w=co(t.opts.columns,t.opts.groupBy,t.opts.aggregations),l=await E.findOne({where:{id:r},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser"]}),N=[i],M=[];if(!l)throw new s(404,"Data source not found");let hr=await I.save(I.create({user:{id:e.user.id},team:{id:e.user.currentTeamId},dataSource:{id:r},name:n,opts:t.opts})),A=new le(l.dbType);A.setTable(i),A.setLimit(o+1),A.setOffset(o*a),u&&(A.addJoin(...u),u.forEach(m=>{N.push(m.table)}));let ve=uo(w,b,l.dbType);ve.length>0&&A.addOrderBy(...ve),f&&f.length>0&&f.forEach(m=>A.addGroupBy(io(m,l.dbType)));let gr=await x.find({where:{tableName:(0,Yt.In)(N),datasource:{id:r}}});for(let m of gr)if(m.columns)for(let _ of m.columns)M.push({column:_.name,table:m.tableName||"",full:`${m.tableName}.${_.name}`,type:_.type});let De=M.reduce((m,_)=>(m[_.full]=_.type,m),{});Wt(t.opts.filters,De)?.forEach(m=>{m.fn&&Qt(m.fn)?A.addHaving(m):A.addWhere(m)});let X;if(w&&w.length>0?X=w.map(m=>so(m,l.dbType)):X=M.map(m=>`${m.full} as "${m.full}"`),A.selectColumns(X),c){let m=M.filter(_=>Ne.includes(_.type)&&X.some(de=>de.startsWith(_.full)));if(m.length>0){let _=m.map(de=>`LOWER(${de.full}) LIKE '%${c.toLowerCase()}%'`);A.addWhereRaw(`(${_.join(" OR ")})`,"AND")}}let Z=await(await Q(k(l,!0),l.dbType,e)).executeQuery(A.toSQL(),{type:"SELECT",allowBulkUpdate:!1}),Ue=Z.rows.length>o;return Ue&&Z.rows.pop(),{...Z,queryHistoryId:hr.id,tables:N,allColumns:M,columns:Z.columns.map(m=>({...m,type:De[m.full]})),hasMore:Ue}},jt=async(e,t)=>{let r=await E.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:f})=>typeof u=="string"?u&&u.startsWith("=")?`${f}=${u.substring(1)}`:`${f}='${u}'`:`${f}='${u}'`).join(", "),a=t.filters.map(u=>z(u,r.dbType)).join(" AND "),n=`UPDATE ${t.table} SET ${o} WHERE ${a}`;return(await Q(k(r,!0),r.dbType,e)).executeQuery(n,{type:"UPDATE",allowBulkUpdate:!1})},Gt=async(e,t)=>{let r=await E.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}=no(t.values),n=`INSERT INTO ${t.table} (${o}) VALUES (${a})`;return(await Q(k(r,!0),r.dbType,e)).executeQuery(n,{type:"INSERT",allowBulkUpdate:!1})},no=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}},so=(e,t)=>{if(e.fn){if(ue(e.fn))return`${(t==="postgres"?K:V)[e.fn](e)} as "${Ce(e)}"`;throw new Error("Function not allowed: "+e.fn)}return`${e.value} as "${e.value}"`},io=(e,t)=>{if(e.fn){if(ue(e.fn))return(t==="postgres"?K:V)[e.fn]({...e,value:Ht(e.value,t)});throw new Error("Function not allowed: "+e.fn)}return Ht(e.value,t)},Oe=(e,t)=>t==="postgres"?`"${e}"`:t==="mysql"?`\`${e}\``:e,Ht=(e,t)=>{let[r,o]=e.split(".");return Oe(r,t)+"."+Oe(o,t)},uo=(e,t,r)=>{if(e&&e.length>0){let o=e.reduce((a,n)=>(a.set(Ce(n),{isFn:!!(n.fn||n.distinct)}),a),new Map);t=t.filter(a=>o.has(a.column)).map(a=>o.get(a.column)?.isFn?{...a,column:Oe(a.column,r)}:a)}return t},co=(e,t,r)=>{let o=[];return t.length>0||r.length>0?o.push(...t,...r):e.length>0&&o.push(...e),o};var Kt=e=>{},lo=["--",";","DROP","drop"],Vt=e=>{if(ce(e.value)&&e.value.startsWith("=")){let t=e.value;lo.forEach(r=>{if(t.includes(r))throw new s(400,"Invalid input value for "+e.column)})}},zt=e=>{if(!e.table)throw new s(400,"Table is required");e.values.forEach(Vt)},Jt=e=>{if(!e.table)throw new s(400,"Table is required");e.values.forEach(Vt)};var Xt=g(e=>{e.route({method:"post",url:"/select",handler:async t=>{let r=d(t,Kt);return{data:await me(t,r)}}}),e.route({method:"post",url:"/insert",config:{requireRole:S("editor")},handler:async t=>{let r=d(t,zt);return{data:await Gt(t,r)}}}),e.route({method:"post",url:"/update",config:{requireRole:S("editor")},handler:async t=>{let r=d(t,Jt);return{data:await jt(t,r)}}})});var Zt=g(e=>{e.get("/",{config:{isPublic:!0}},async()=>({data:{active:!0,version:T.str("SERVER_VERSION")}}))});var er=g(e=>{e.route({method:"get",url:"/:id/users",handler:async t=>{let{id:r}=p(t),o=await F.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:S("editor")},handler:async t=>h.transaction(async()=>{let r=t.user.id,o=d(t),a=R.create();a.id=r;let n=F.create(o);await F.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:S("admin")},handler:async t=>{let{id:r}=p(t),{role:o,userId:a}=d(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:S("admin")},handler:async t=>h.transaction(async()=>{let{id:r}=p(t),{userId:o}=q(t);if((await C.findOneBy({user:{id:o},team:{id:r}}))?.role==="owner")throw new s(400,"Cannot delete team owner");await R.update(o,{currentTeam:null}),await C.delete({user:{id:o},team:{id:r}}),await R.delete({id:o})})})});var Ae=v(require("bcryptjs")),J=async e=>{let t=await Ae.default.genSalt(10);return Ae.default.hash(e,t)};var tr=g(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=await R.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=d(t);if(o.password&&(o.password=await J(o.password)),!(await R.update(r,o)).affected)throw new s(404,"User not found");let n=await R.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=>h.transaction(async()=>{let r=d(t),o=await J(r.password),a=await R.save(R.create({username:r.username,password:o})),n=await C.save(C.create({role:"read_only",team:{id:r.teamId},user:{id:a.id}}));await R.update(a.id,{currentTeam:{id:n.id}})})})});var rr=g(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}=d(t);if(!r.id)throw new s(400,"Settings id is required!");if(!(await W.update(r.id,r)).affected)throw new s(404,"You do not own these settings!");return{data:await W.findOneBy({id:r.id})}}})});function Y(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 or=g(e=>{e.route({method:"post",url:"/",config:{requireRole:S("editor")},handler:async t=>{let r=d(t),o=await I.findOne({where:{id:r.queryId}});if(!o)throw new s(400,"Query not found");let a=await L.save(L.create({isPersonal:!1,team:{id:t.user.currentTeamId},user:{id:t.user.id},query:{id:r.queryId},searchString:Y(o.opts,r.name)}));return await I.update(r.queryId,{name:r.name}),{data:a}}}),e.route({method:"delete",url:"/:id",config:{requireRole:S("editor")},handler:async t=>{let{id:r}=p(t);if(!(await L.delete({id:r})).affected)return{status:404,data:"Query not found"}}}),e.route({method:"patch",url:"/:id",handler:async t=>await h.transaction(async()=>{let{id:r}=p(t),o=d(t,i=>{if(!i.name)throw new s(400,"Name is required")}),a=await L.findOne({where:{id:r},relations:{query:!0}});if(!a)throw new s(400,"Query not found");let n=Y(a.query.opts,o.name);return await Promise.all([L.update({id:r},{searchString:n}),I.update({id:a.query.id},{name:o.name})]),{data:!0}})})});var ar=e=>{if(!e.queryId&&!(e.opts&&e.name))throw new s(400,"Either queryId or name and opts are required")};var nr=g(e=>{e.route({method:"get",url:"/",handler:async t=>{let{currentTeamId:r,id:o}=t.user;return{data:(await P.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}=p(t),{currentTeamId:o,id:a}=t.user,n=await P.findOne({where:{id:r,team:{id:o},user:{id:a}}});if(!n)throw new s(404,"Not Found");return{data:n}}}),e.route({method:"post",url:"/",handler:async t=>{let{opts:r,name:o,queryId:a}=d(t,ar),n,i,u=o;if(r)i=r.dataSourceId,n=r;else{let c=await I.findOne({where:{id:a},relations:{dataSource:!0}});if(!c)throw new s(404,"Query not Found");i=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||(u=c.name)}return{data:await P.save(P.create({name:u||new Date().toISOString(),opts:n,dataSource:{id:i},user:{id:t.user.id},team:{id:t.user.currentTeamId}}))}}}),e.route({method:"post",url:"/:id/run",handler:async t=>{let{id:r}=p(t),o=d(t),a=await P.findOne({where:{id:r},relations:{user:!0}});if(!a)throw new s(404,"Not found");if(a.user?.id!==t.user.id)throw new s(404,"Not found");return o&&P.update(r,{opts:o,searchString:Y(o,a.name),updatedAt:new Date}),{data:{result:await me(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}=p(t),o=d(t),a=await P.findOne({where:{id:r,user:{id:t.user.id}}});if(!a)throw new s(404,"Not Found");let n=a.searchString;return o.name&&(n=Y(a.opts,o.name)),await P.update(r,{...o,searchString:n}),{data:{id:r}}}}),e.route({method:"delete",url:"/:id",handler:async t=>{let{id:r}=p(t),o=t.user.id;return await P.delete({id:r,user:{id:o}}),{data:!0}}})});var fr=require("node:path");var mo=e=>e.routeOptions.config.isPublic?!0:!e.url.startsWith("/api/"),sr=async e=>{if(mo(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 tt(o),n=await R.findOne({where:{id:a},select:{id:!0,currentTeam:{role:!0,team:{id:!0}}},relations:{currentTeam:{team:!0}}});if(!n)throw new s(401,"User is not part of a team");e.user={id:a,currentTeamId:n.currentTeam.team.id,currentTeamRole:n.currentTeam.role}}catch{throw new s(401,"Unauthorized")}};var ir=(e,t)=>{e.__connections&&e.__connections.forEach(r=>{r.close()})};var yr=v(require("@fastify/cookie"));var _e={teamName:"Default Team",username:"admin",password:"admin"},po=async()=>{let e=await F.findOneBy({});return e||F.save(F.create({name:_e.teamName}))},ur=async()=>{let e=await C.findOne({where:{role:"owner"},relations:{user:!0}});if(e)return e.user;let t=await po(),r=await J(_e.password),o=await R.save(R.create({username:_e.username,password:r})),a=await C.save(C.create({user:o,team:t,role:"owner"}));return await R.update(o.id,{currentTeam:a}),o};var O=(0,lr.default)({querystringParser:e=>pr.default.parse(e)}),Tr=T.num("PORT",4466),cr=T.str("ALLOWED_ORIGINS","").split(",").map(e=>e.trim()),fo="0.0.0.0",yo=cr.includes("*")?"*":[`http://localhost:${Tr}`,...cr];function U(e,t){O.register(e,{prefix:t}),console.log("Registered "+t)}(async function(){Fe(),await O.register(yr.default,{}),await O.register(mr.default,{origin:yo,methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"],credentials:!0}),await O.register(dr.default,{root:(0,fr.join)(__dirname,"web")}),O.get("/",(t,r)=>{r.sendFile("index.html")}),O.addHook("onRequest",sr),O.addHook("onRequest",xt),O.addHook("onResponse",ir),U(nt,"/api/auth"),U(Lt,"/api/data-sources"),U(Mt,"/api/project"),U(Ft,"/api/queries"),U(Xt,"/api/runner"),U(Zt,"/api/status"),U(er,"/api/teams"),U(tr,"/api/users"),U(rr,"/api/user-settings"),U(or,"/api/saved-queries"),U(nr,"/api/workbench-tabs"),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 ze(),await ur(),O.listen({port:Tr,host:fo},(t,r)=>{t&&(console.error(t),process.exit(1)),console.log(`Server listening at ${r}`)})})();
|
|
57
|
+
limit 75;`;return(await t.query(r)).rows.reduce((a,n)=>(a[n.row_key]={table:n.relname,column:n.attname},a),{})},yt=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(c=>`'${c.tableID}-${c.columnID}'`),d=await Jr(u,t);return{columns:a.map(c=>{let S=d[`${c.tableID}-${c.columnID}`];return{column:S?.column||c.name,alias:c.name,table:S?.table||"",full:S?S.table+"."+S.column:c.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)}},Xr=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}},Zr=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}},ht=async e=>{let t=await Gr(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:()=>zr(e,t),executeQuery:(n,i)=>a(()=>i.type==="SELECT"?Zr(t,()=>yt(n,t,i)):Xr(t,()=>yt(n,t,i))),checkConnection:async()=>{},isClosed:()=>r,close:async()=>{if(!r)return r=!0,t.end()}}};var q=async(e,t,r)=>{try{let o;if(t==="mysql")o=await ft(e);else if(t==="postgres")o=await ht(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 ae=_(require("node:crypto"));var gt="aes-256-gcm",eo=12,wt=()=>{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},to=e=>{let t=ae.default.randomBytes(eo),r=wt(),o=ae.default.createCipheriv(gt,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")}},ro=({encrypted:e,iv:t,tag:r})=>{let o=wt(),a=ae.default.createDecipheriv(gt,o,Buffer.from(t,"hex"));a.setAuthTag(Buffer.from(r,"hex"));let n=a.update(e,"hex","utf8");return n+=a.final("utf8"),n},ne={encrypt:to,decrypt:ro};var k=(e,t=!1)=>{if(t){let r=ne.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"}],oo=Et.reduce((e,t)=>(e[t.value]=t.label,e),{}),sn=Et.reduce((e,t)=>(e[t.label]=t.value,e),{}),W=e=>e.map(t=>({label:oo[t],value:t})),un=W(["=","<>",">",">=","<","<=","IN","NOT IN","IS NULL","IS NOT NULL"]),cn=W(["=","<>","LIKE","NOT LIKE","IN","NOT IN","IS NULL","IS NOT NULL"]),ln=W(["=","<>","IS NULL","IS NOT NULL"]),mn=W(["=","<>",">",">=","<","<=","IS NULL","IS NOT NULL"]),dn=W(["IS NULL","IS NOT NULL"]),pn=W(["IN","NOT IN"]);var Pe=["char","varchar","binary","varbinary","blob","text","enum","set","character","character varying","text","citext","uuid","xml","json","jsonb"],ao=new Set(Pe),se=e=>ao.has(e),no=["integer","smallint","decimal","numeric","float","real","double precision","int","smallint","integer","bigint","decimal","numeric","real","double precision","serial","bigserial","money"],so=new Set(no),St=e=>so.has(e);var fn=["date","datetime","timestamp","timestamptz"].reduce((e,t)=>(e[t]=!0,e),{});var Ae=e=>e.fn?e.distinct===!0?`${e.fn} distinct ${e.value}`:`${e.fn} ${e.value}`:e.value;var _e={read_only:10,editor:20,admin:30,owner:40};var v=e=>e.startsWith("'")&&e.endsWith("'")||e.startsWith('"')&&e.endsWith('"')?e.slice(1,-1):e;var Rt={operator:"LIKE",parse:e=>{let t=e.match(/^LIKE\s*["'](.*)["']$/i);if(t)return[{value:v(t[1])}]},stringify:(e,t)=>se(t)?`${e.value?.[0].value}`:`LIKE "%${e.value?.[0].value}%"`},bt={operator:"NOT LIKE",parse:e=>{let t=e.match(/^NOT LIKE\s*["'](.*)["']$/i);if(t)return[{value:v(t[1])}]},stringify:e=>`NOT LIKE "%${e.value?.[0].value}%"`};function Nt(e){return e===""?[]:io(e).map(uo)}function io(e){let t=[],r=0,o="",a=!1,n=!1;for(;r<e.length;){let i=e[r];if((a||n)&&i==="\\"){o+=e[r+1],r+=2;continue}if(i==="'"&&!n){a=!a,o+=i,r++;continue}if(i==='"'&&!a){n=!n,o+=i,r++;continue}if(i===","&&!a&&!n){t.push(o.trim()),o="",r++;continue}o+=i,r++}if(o.trim()!==""&&t.push(o.trim()),a||n)throw new Error("Unterminated string literal");return t}function uo(e){if(e.startsWith("'")&&e.endsWith("'"))return{value:It(e.slice(1,-1),"'")};if(e.startsWith('"')&&e.endsWith('"'))return{value:It(e.slice(1,-1),'"')};let t=Number(e);if(!Number.isNaN(t))return{value:t};throw new Error(`Invalid literal: ${e}`)}function It(e,t){return e.replace(/\\(.)/g,(r,o)=>o)}var Ct={operator:"IN",parse:e=>{let t=e.match(/^in\s*\((.*)\)$/i);if(t)return Nt(t[1])},stringify:e=>`IN (${e.value?.map(t=>`"${t.value}"`).join(", ")})`},Ot={operator:"NOT IN",parse:e=>{let t=e.match(/^not\s+in\s*\((.*)\)$/i);if(t)return Nt(t[1])},stringify:e=>`NOT IN (${e.value?.map(t=>`"${t.value}"`).join(", ")})`};var Pt={operator:"=",parse:e=>{let t=e.match(/^=\s*(.*)$/);if(t)return[{value:v(t[1])}]},stringify:(e,t)=>St(t)?`${e.value?.[0].value}`:`= ${e.value?.[0].value}`},At={operator:"!=",parse:e=>{let t=e.match(/^!=\s*(.*)$/);if(t)return[{value:v(t[1])}]},stringify:e=>`!= ${e.value?.[0].value}`},_t={operator:"<>",parse:e=>{let t=e.match(/^<>\s*(.*)$/);if(t)return[{value:v(t[1])}]},stringify:e=>`<> ${e.value?.[0].value}`},vt={operator:">",parse:e=>{let t=e.match(/^>\s*(.*)$/);if(t)return[{value:v(t[1])}]},stringify:e=>`> ${e.value?.[0].value}`},Dt={operator:">=",parse:e=>{let t=e.match(/^>=\s*(.*)$/);if(t)return[{value:v(t[1])}]},stringify:e=>`>= ${e.value?.[0].value}`},Ut={operator:"<",parse:e=>{let t=e.match(/^<\s*(.*)$/);if(t)return[{value:v(t[1])}]},stringify:e=>`< ${e.value?.[0].value}`},xt={operator:"<=",parse:e=>{let t=e.match(/^<=\s*(.*)$/);if(t)return[{value:v(t[1])}]},stringify:e=>`<= ${e.value?.[0].value}`};var Lt={operator:"IS NULL",parse:e=>{if(/^is\s+null$/i.test(e))return[]},stringify:()=>"IS NULL"},Mt={operator:"IS NOT NULL",parse:e=>{if(/^is\s+not\s+null$/i.test(e))return[]},stringify:()=>"IS NOT NULL"};var Ft=[Rt,bt,Ct,Ot,Pt,At,_t,Dt,vt,xt,Ut,Lt,Mt],co=Ft.reduce((e,t)=>(e[t.operator]=t,e),{});function lo(e,t){return co[e.operator]?.stringify(e,t)||""}function mo(e){let t=e.trim();for(let r of Ft){let o=r.parse(t);if(o)return{operator:r.operator,value:o}}}var qt={parse:mo,stringify:lo};var E=e=>{let t=_e[e];return r=>_e[r.currentTeamRole]>=t},kt=async e=>{let t=e.routeOptions.config.requireRole;if(t&&!t(e.user))throw new s(403,"You are not authorized to perform this action")};var Qt=h(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=m(t),o=await b.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}=x(t);return{data:await b.find({where:{team:{id:r}},order:{createdAt:"DESC"}})}}}),e.route({url:"/",method:"post",config:{requireRole:E("admin")},handler:async t=>{let{teamId:r,ownerId:o,...a}=f(t,mt),n=b.create({...a,allowUpdate:!!a.allowUpdate,allowInsert:!!a.allowInsert,team:{id:r},owner:{id:o}}),i=await q(k(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:c}=ne.encrypt(n.dbPassword);return n.dbPassword=c,n.dbPasswordIv=d,n.dbPasswordTag=u,{data:await b.save(n)}}}),e.route({method:"put",url:"/:id",config:{requireRole:E("admin")},handler:async t=>{let{id:r}=m(t),o=f(t),a=await b.findOneBy({id:r});if(!a)throw new s(404,"Data source not found");let n=b.merge(a,o);return await b.save(n),{data:n}}}),e.route({method:"delete",url:"/:id",config:{requireRole:E("admin")},handler:async(t,r)=>g.transaction(async()=>{let{id:o}=m(t);await Promise.all([D.delete({datasource:{id:o}}),I.delete({dataSource:{id:o}})]),await b.delete({id:o})})}),e.route({method:"post",url:"/:id/inspect",handler:async(t,r)=>{let{id:o}=m(t),a=await b.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 b.save(a);let i=await(await q(k(a,!0),a.dbType,t)).inspectSchema();await D.delete({datasource:{id:o}}),await D.insert(i.sort().map(u=>D.create({tableName:u.tableName,columns:u.columns,datasource:{id:o}}))),a.status="READY",a.lastInspected=new Date,await b.save(a)}}),e.route({method:"get",url:"/:id/inspections",handler:async t=>{let{id:r}=m(t);return{data:await D.find({where:{datasource:{id:r}}})}}})});var $=require("typeorm"),$t=h(e=>{e.route({method:"get",url:"/team/:teamId/datasources",handler:async t=>{let{teamId:r}=m(t);return{data:await b.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 o=m(t).teamId||t.user.currentTeamId;return{data:(await U.find({where:[{isPersonal:!1,team:{id:o}},{isPersonal:!0,team:{id:o},user:{id:t.user.id}}],relations:{query:!0},select:{id:!0,query:{id:!0,name:!0,updatedAt:!0}}})).map(i=>({name:i.query.name,id:i.query.id,updatedAt:i.query.updatedAt,savedQueryId:i.id}))}}}),e.route({method:"get",url:"/team/:teamId/query",handler:async t=>{let{teamId:r}=m(t),{search:o,size:a,selectedDataSources:n}=x(t),i=o.length>3?parseInt(a)||20:8,u={};n?.length&&(u.id=(0,$.In)(n));let[d,c,S]=await Promise.all([D.find({where:{tableName:(0,$.Raw)(l=>`LOWER(${l}) LIKE :search`,{search:`%${o.toLowerCase()}%`}),datasource:u},relations:{datasource:!0},select:{id:!0,tableName:!0,datasource:{name:!0,id:!0}},order:{tableName:"ASC"},take:i}),O.find({where:{searchString:(0,$.Like)(`%${o.toLowerCase()}%`),team:{id:r},user:{id:t.user.id},dataSource:u},relations:{dataSource:!0},select:{id:!0,name:!0,updatedAt:!0,dataSource:{id:!0,name:!0}},order:{updatedAt:"ASC"},take:i}),U.find({where:{searchString:(0,$.Like)(`%${o.toLowerCase()}%`),team:{id:r},query:{dataSource:u}},relations:{query:{dataSource:!0}},select:{id:!0,updatedAt:!0,query:{id:!0,name:!0,dataSource:{name:!0}}},order:{updatedAt:"ASC"},take:i})]),w=[];return d.forEach(l=>{w.push({name:l.tableName,id:l.id,dataSourceName:l.datasource?.name||"--",dataSourceId:l.datasource?.id||"--",type:"table"})}),c.forEach(l=>{w.push({name:l.name,id:l.id,dataSourceName:l.dataSource?.name||"--",dataSourceId:l.dataSource?.id||"--",type:"tab"})}),S.forEach(l=>{w.push({name:l.query.name,id:l.query.id,dataSourceName:l.query.dataSource?.name||"--",dataSourceId:l.query.dataSource?.id||"--",type:"query"})}),{data:w}}}),e.route({method:"get",url:"/team/:teamId/tabs-history",handler:async t=>{let{teamId:r}=m(t),o=x(t),a=Number(o.page),n=Number(o.size),i=t.user.id,u=await O.find({where:{team:{id:r},user:{id:i}},relations:{dataSource:!0},order:{updatedAt:"DESC"},take:n+1,skip:a*n}),d=!1;return u.length>n&&(u.pop(),d=!0),{data:u.map(c=>({name:c.name,id:c.id,updatedAt:c.updatedAt,archived:c.archived,createdAt:c.createdAt,dataSourceId:c.dataSource?.id,dataSourceName:c.dataSource?.name,dataSourceType:c.dataSource?.dbType})),hasMore:d}}})});var Bt=h(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=m(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:E("editor")},handler:async t=>{let r=f(t),o=await b.findOne({where:{id:r.dataSourceId},relations:{team:!0}});return{data:await I.save(I.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:E("editor")},handler:async t=>{let{id:r}=m(t),o=f(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:E("editor")},handler:async t=>g.transaction(async()=>{let{id:r}=m(t);if(!(await I.delete({id:r})).affected)return{status:404,data:"Query not found"}})})});var ie=e=>{let t=e.distinct===!0?"distinct ":"";return`${e.fn}(${t}${e.value})`},V={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:ie,MAX:ie,MIN:ie,COUNT:ie};var ue=e=>{let t=e.distinct===!0?"distinct ":"";return`${e.fn}(${t}${e.value})`},z={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:ue,MAX:ue,MIN:ue,COUNT:ue};var Wt=["SUM","COUNT","AVG","MAX","MIN"],po=["YEAR","MONTH","DAY",...Wt],fo=po.reduce((e,t)=>(e[t]=!0,e),{}),yo=Wt.reduce((e,t)=>(e[t]=!0,e),{}),ce=e=>fo[e],Ht=e=>yo[e],Yt=(e,t)=>e.fn&&ce(e.fn)?(t==="postgres"?V:z)[e.fn](e):e.value;var le=e=>typeof e=="string",jt=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},J=(e,t)=>{let{column:r,operator:o,value:a,fn:n}=e,i=Yt({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(l=>le(l.value)?`'${l.value}'`:l.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 S=a?.[0],w;return le(S?.value)&&S?.isColumn!==!0?w=`'${S?.value}'`:w=S?.value,`${i} ${o} ${w}`}};var X=class{constructor(t="mysql"){this.dialect=t,this.skeleton={type:"SELECT"}}addWhere(t){let r=J(t,this.dialect);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=J(t,this.dialect);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 jt(this.skeleton)}};var zt=require("typeorm");var Gt=e=>se(e)?"LIKE":"=",Kt=(e,t)=>{let r=[];for(let o of e)if(!(!o.column?.length||!o.value?.length||o.isEnabled===!1))if(o.isAdvanced){let a=qt.parse(o.value);if(!a)throw new s(400,`Invalid value for '${o.column}': ${o.value}`);r.push({value:a.value,column:o.column,id:o.id,operator:a.operator||Gt(t[o.column]),connector:"AND"})}else r.push({value:o.value?[{value:o.value}]:[],column:o.column,id:o.id,operator:Gt(t[o.column]),connector:"AND"});return r};var me=async(e,t)=>{let{datasourceId:r,size:o=20,page:a,name:n}=t,{table:i,joins:u,groupBy:d,searchAll:c,orderBy:S}=t.opts,w=Eo(t.opts.columns,t.opts.groupBy,t.opts.aggregations),l=await de(r),N=[i],L=[];if(!l)throw new s(404,"Data source not found");let Nr=await I.save(I.create({user:{id:e.user.id},team:{id:e.user.currentTeamId},dataSource:{id:r},name:n,opts:t.opts})),P=new X(l.dbType);P.setTable(i),P.setLimit(o+1),P.setOffset(o*a),u&&(P.addJoin(...u),u.forEach(p=>{N.push(p.table)}));let De=wo(w,S,l.dbType);De.length>0&&P.addOrderBy(...De),d&&d.length>0&&d.forEach(p=>P.addGroupBy(go(p,l.dbType)));let Cr=await D.find({where:{tableName:(0,zt.In)(N),datasource:{id:r}}});for(let p of Cr)if(p.columns)for(let A of p.columns)L.push({column:A.name,table:p.tableName||"",full:`${p.tableName}.${A.name}`,type:A.type});let Ue=L.reduce((p,A)=>(p[A.full]=A.type,p),{});Kt(t.opts.filters,Ue)?.forEach(p=>{p.fn&&Ht(p.fn)?P.addHaving(p):P.addWhere(p)});let Z;if(w&&w.length>0?Z=w.map(p=>ho(p,l.dbType)):Z=L.map(p=>`${p.full} as "${p.full}"`),P.selectColumns(Z),c){let p=L.filter(A=>Pe.includes(A.type)&&Z.some(pe=>pe.startsWith(A.full)));if(p.length>0){let A=p.map(pe=>`LOWER(${pe.full}) LIKE '%${c.toLowerCase()}%'`);P.addWhereRaw(`(${A.join(" OR ")})`,"AND")}}let ee=await(await q(k(l,!0),l.dbType,e)).executeQuery(P.toSQL(),{type:"SELECT",allowBulkUpdate:!1}),xe=ee.rows.length>o;return xe&&ee.rows.pop(),{...ee,queryHistoryId:Nr.id,tables:N,allColumns:L,columns:ee.columns.map(p=>({...p,type:Ue[p.full]})),hasMore:xe}},Jt=async(e,t)=>{let r=await de(t.dataSourceId);if(!r)throw new s(400,"Invalid datasource");let o=await q(k(r,!0),r.dbType,e),a=new X(r.dbType);a.setTable(t.table),a.setLimit(2);for(let[u,d]of Object.entries(t.props))a.addWhere({value:[{value:d}],column:u,connector:"AND",isEnabled:!0,operator:"=",id:"dummy"});let n=a.toSQL(),i=await o.executeQuery(n,{type:"SELECT",allowBulkUpdate:!1});if(i.rows.length>1)throw new s(400,"Found multiple rows for given query");if(i.rows.length<1)throw new s(404,"Entity not found");return{entity:i.rows[0],columns:i.columns,sql:n}},Xt=async(e,t)=>{let r=await de(t.datasourceId);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=>J(u,r.dbType)).join(" AND "),n=`UPDATE ${t.table} SET ${o} WHERE ${a}`;return(await q(k(r,!0),r.dbType,e)).executeQuery(n,{type:"UPDATE",allowBulkUpdate:!1})},Zt=async(e,t)=>{let r=await de(t.datasourceId);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}=To(t.values),n=`INSERT INTO ${t.table} (${o}) VALUES (${a})`;return(await q(k(r,!0),r.dbType,e)).executeQuery(n,{type:"INSERT",allowBulkUpdate:!1})},To=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}},ho=(e,t)=>{if(e.fn){if(ce(e.fn))return`${(t==="postgres"?V:z)[e.fn](e)} as "${Ae(e)}"`;throw new Error("Function not allowed: "+e.fn)}return`${e.value} as "${e.value}"`},go=(e,t)=>{if(e.fn){if(ce(e.fn))return(t==="postgres"?V:z)[e.fn]({...e,value:Vt(e.value,t)});throw new Error("Function not allowed: "+e.fn)}return Vt(e.value,t)},ve=(e,t)=>t==="postgres"?`"${e}"`:t==="mysql"?`\`${e}\``:e,Vt=(e,t)=>{let[r,o]=e.split(".");return ve(r,t)+"."+ve(o,t)},wo=(e,t,r)=>{if(e&&e.length>0){let o=e.reduce((a,n)=>(a.set(Ae(n),{isFn:!!(n.fn||n.distinct)}),a),new Map);t=t.filter(a=>o.has(a.column)).map(a=>o.get(a.column)?.isFn?{...a,column:ve(a.column,r)}:a)}return t},Eo=(e,t,r)=>{let o=[];return t.length>0||r.length>0?o.push(...t,...r):e.length>0&&o.push(...e),o};async function de(e){return b.findOne({where:{id:e},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser","allowUpdate","allowInsert"]})}var er=e=>{},So=["--",";","DROP","drop"],tr=e=>{if(le(e.value)&&e.value.startsWith("=")){let t=e.value;So.forEach(r=>{if(t.includes(r))throw new s(400,"Invalid input value for "+e.column)})}},rr=e=>{if(!e.table)throw new s(400,"Table is required");e.values.forEach(tr)},or=e=>{if(!e.table)throw new s(400,"Table is required");e.values.forEach(tr)};var ar=h(e=>{e.route({method:"post",url:"/:dsId/select",handler:async t=>{let r=f(t,er);return{data:await me(t,r)}}}),e.route({method:"get",url:"/:dsId/entity/:table",handler:async t=>{let{dsId:r,table:o}=m(t),a=x(t);return{data:await Jt(t,{table:o,dataSourceId:r,props:a})}}}),e.route({method:"post",url:"/:dsId/insert",config:{requireRole:E("editor")},handler:async t=>{let r=f(t,rr);return{data:await Zt(t,r)}}}),e.route({method:"post",url:"/:dsId/update",config:{requireRole:E("editor")},handler:async t=>{let r=f(t,or);return{data:await Xt(t,r)}}})});var nr=h(e=>{e.get("/",{config:{isPublic:!0}},async()=>({data:{active:!0,version:T.str("SERVER_VERSION")}}))});var sr=h(e=>{e.route({method:"get",url:"/:id/users",handler:async t=>{let{id:r}=m(t),o=await M.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:E("editor")},handler:async t=>g.transaction(async()=>{let r=t.user.id,o=f(t),a=R.create();a.id=r;let n=M.create(o);await M.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:E("admin")},handler:async t=>{let{id:r}=m(t),{role:o,userId:a}=f(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:E("admin")},handler:async t=>g.transaction(async()=>{let{id:r}=m(t),{userId:o}=x(t);if((await C.findOneBy({user:{id:o},team:{id:r}}))?.role==="owner")throw new s(400,"Cannot delete team owner");await R.update(o,{currentTeam:null}),await C.delete({user:{id:o},team:{id:r}}),await R.delete({id:o})})})});var ir=h(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=await R.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=f(t);if(o.password&&(o.password=await Y(o.password)),!(await R.update(r,o)).affected)throw new s(404,"User not found");let n=await R.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:E("admin")},handler:async t=>g.transaction(async()=>{let r=f(t),o=await Y(r.password),a=await R.save(R.create({username:r.username,password:o})),n=await C.save(C.create({role:"read_only",team:{id:r.teamId},user:{id:a.id}}));await R.update(a.id,{currentTeam:{id:n.id}})})})});var ur=h(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}=f(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})}}})});function H(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 cr=h(e=>{e.route({method:"post",url:"/",config:{requireRole:E("editor")},handler:async t=>{let r=f(t),o=await I.findOne({where:{id:r.queryId}});if(!o)throw new s(400,"Query not found");let a=await U.save(U.create({isPersonal:!1,team:{id:t.user.currentTeamId},user:{id:t.user.id},query:{id:r.queryId},searchString:H(o.opts,r.name)}));return await I.update(r.queryId,{name:r.name}),{data:a}}}),e.route({method:"delete",url:"/:id",config:{requireRole:E("editor")},handler:async t=>{let{id:r}=m(t);if(!(await U.delete({id:r})).affected)return{status:404,data:"Query not found"}}}),e.route({method:"patch",url:"/:id",handler:async t=>await g.transaction(async()=>{let{id:r}=m(t),o=f(t,i=>{if(!i.name)throw new s(400,"Name is required")}),a=await U.findOne({where:{id:r},relations:{query:!0}});if(!a)throw new s(400,"Query not found");let n=H(a.query.opts,o.name);return await Promise.all([U.update({id:r},{searchString:n}),I.update({id:a.query.id},{name:o.name})]),{data:!0}})})});var lr=e=>{if(!e.queryId&&!(e.opts&&e.name))throw new s(400,"Either queryId or name and opts are required")};var mr=h(e=>{e.route({method:"get",url:"/",handler:async t=>{let{currentTeamId:r,id:o}=t.user;return{data:(await O.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}=m(t),{currentTeamId:o,id:a}=t.user,n=await O.findOne({where:{id:r,team:{id:o},user:{id:a}}});if(!n)throw new s(404,"Not Found");return{data:n}}}),e.route({method:"post",url:"/",handler:async t=>{let{opts:r,name:o,queryId:a}=f(t,lr),n,i,u=o;if(r)i=r.dataSourceId,n=r;else{let c=await I.findOne({where:{id:a},relations:{dataSource:!0}});if(!c)throw new s(404,"Query not Found");i=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||(u=c.name)}return{data:await O.save(O.create({name:u||new Date().toISOString(),opts:n,dataSource:{id:i},user:{id:t.user.id},team:{id:t.user.currentTeamId}}))}}}),e.route({method:"post",url:"/:id/run",handler:async t=>{let{id:r}=m(t),o=f(t),a=await O.findOne({where:{id:r},relations:{user:!0}});if(!a)throw new s(404,"Not found");if(a.user?.id!==t.user.id)throw new s(404,"Not found");return o&&O.update(r,{opts:o,searchString:H(o,a.name),updatedAt:new Date}),{data:{result:await me(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}=m(t),o=f(t),a=await O.findOne({where:{id:r,user:{id:t.user.id}}});if(!a)throw new s(404,"Not Found");let n=a.searchString;return o.name&&(n=H(a.opts,o.name)),await O.update(r,{...o,searchString:n}),{data:{id:r}}}}),e.route({method:"delete",url:"/:id",handler:async t=>{let{id:r}=m(t),o=t.user.id;return await O.delete({id:r,user:{id:o}}),{data:!0}}})});var dr=h(e=>{e.route({method:"get",url:"/client.config.js",handler:(t,r)=>{let o={skipAuth:Q.skipAuth,modeName:Q.name};r.type("application/javascript").send(`window.__CLIENT_CONFIG__ = ${JSON.stringify(o)};`)}}),e.route({method:"get",url:"/",handler:(t,r)=>{r.sendFile("index.html")}})});var Ro=[[dr,"/"],[lt,"/api/auth"],[Qt,"/api/data-sources"],[$t,"/api/project"],[Bt,"/api/queries"],[ar,"/api/runner"],[nr,"/api/status"],[sr,"/api/teams"],[ir,"/api/users"],[ur,"/api/user-settings"],[cr,"/api/saved-queries"],[mr,"/api/workbench-tabs"]],pr=e=>{for(let[t,r]of Ro)e.register(t,{prefix:r}),console.log("Registered "+r)};var bo=e=>e.routeOptions.config.isPublic?!0:!e.url.startsWith("/api/"),Io=async e=>{let t=await C.findOne({where:{role:"owner"},relations:{user:!0,team:!0}});if(!t)throw new s(401,"User is not part of a team");e.user={id:t.user.id,currentTeamId:t.team.id,currentTeamRole:t.role}},No=async e=>{let t=e.headers.authorization;if(!t)throw new s(401,"Missing auth token");let[r,o]=t.split(" ");try{let{userId:a}=await st(o),n=await R.findOne({where:{id:a},select:{id:!0,currentTeam:{role:!0,team:{id:!0}}},relations:{currentTeam:{team:!0}}});if(!n)throw new s(401,"User is not part of a team");e.user={id:a,currentTeamId:n.currentTeam.team.id,currentTeamRole:n.currentTeam.role}}catch{throw new s(401,"Unauthorized")}},fr=async e=>{bo(e)||(Q.skipAuth?await Io(e):await No(e))};var yr=(e,t)=>{e.__connections&&e.__connections.forEach(r=>{r.close()})};var Tr=e=>{e.addHook("onRequest",fr),e.addHook("onRequest",kt),e.addHook("onResponse",yr)};var hr=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 s?o.status(t.status).send({error:t.message}):o.status(500).send({error:"Internal Server Error"})})};var gr=_(require("@fastify/cookie")),wr=_(require("@fastify/cors"));var Er=_(require("@fastify/static")),Sr=require("node:path"),Rr=e=>{e.register(gr.default,{}),e.register(wr.default,{origin:j.allowedOrigins,methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"],credentials:!0}),e.register(Er.default,{root:(0,Sr.join)(__dirname,"web")})};(async function(){let t=(0,br.default)({querystringParser:r=>Ir.default.parse(r)});qe(),Rr(t),Tr(t),pr(t),hr(t),await t.after(),await Je(),await Xe(),t.listen({port:j.port,host:j.host},(r,o)=>{r&&(console.error(r),process.exit(1)),console.log(`Server listening at ${o}`)})})();
|