@dataramen/cli 0.0.69 → 0.0.70
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/cli.js +1 -1
- package/dist/code/server.js +8 -8
- package/dist/code/web/assets/index-CuM5yTKj.css +1 -0
- package/dist/code/web/assets/index-VGcygI3P.js +190 -0
- package/dist/code/web/assets/main-CKMVXs0c.js +4 -0
- package/dist/code/web/assets/main-D6h5BZfN.css +1 -0
- package/dist/code/web/assets/{setup-CbifUuH4.js → setup-XBuZP5zl.js} +1 -1
- package/dist/code/web/index.html +4 -4
- package/dist/code/web/setup.html +3 -3
- package/dist/package.json +1 -1
- package/package.json +3 -2
- package/dist/code/web/assets/index-D_yzt1XG.css +0 -1
- package/dist/code/web/assets/index-g8K5wnQd.js +0 -190
- package/dist/code/web/assets/main-BbebNQDt.js +0 -4
- package/dist/code/web/assets/main-DQXEBF5j.css +0 -1
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 -- --mode=
|
|
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 -- --mode=cli --env="${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();
|
package/dist/code/cli.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 -- --mode=
|
|
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 -- --mode=cli --env="${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();
|
package/dist/code/server.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"use strict";var Qr=Object.create;var Qe=Object.defineProperty;var $r=Object.getOwnPropertyDescriptor;var Br=Object.getOwnPropertyNames;var Wr=Object.getPrototypeOf,Hr=Object.prototype.hasOwnProperty;var Yr=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Br(t))!Hr.call(e,a)&&a!==r&&Qe(e,a,{get:()=>t[a],enumerable:!(o=$r(t,a))||o.enumerable});return e};var _=(e,t,r)=>(r=e!=null?Qr(Wr(e)):{},Yr(t||!e||!e.__esModule?Qe(r,"default",{value:e,enumerable:!0}):r,e));var ae=require("dotenv"),ne=require("node:path"),Be=require("node:fs");var oe=e=>{function t(a,n=void 0){return e[a]||n}function r(a,n=void 0){let i=e[a];if(!i)return n;let u=Number(i);return!isNaN(u)&&i.trim()!==""?u:n}function o(a){return e[a]==="true"||e[a]==="TRUE"||e[a]==="1"}return{str:t,num:r,bool:o}};function jr(e){let t={mode:void 0,env:void 0};for(let r of e){if(!r.startsWith("--"))continue;let[o,...a]=r.slice(2).split("=");if(!o||a.length===0)continue;let n=a.join("=");n=n.replace(/^["'](.+)["']$/,"$1"),t[o]=n}return t}var j=oe(jr(process.argv.slice(2)));var Gr=(()=>{try{let e=(0,Be.readFileSync)((0,ne.join)(__dirname,"..","package.json"),"utf8");return JSON.parse(e)}catch{return{version:"0.0.0"}}})(),We=[],$e=j.str("env");$e&&We.push((0,ne.resolve)($e));(0,ae.config)({path:We});var we={APP_DB_TYPE:"sqlite",APP_DB_DATABASE:"<home>/.dataramen/.runtime/db.sqlite3"};(0,ae.populate)(process.env,{SERVER_VERSION:Gr.version,PROD:"true",...we},{override:!1});var Kr=["SYMM_ENCRYPTION_KEY","JWT_SECRET","JWT_REFRESH_SECRET"],He=()=>{let e=[];for(let t of Kr)process.env[t]||e.push(t);if(e.length>0)throw new Error("Following env variables are required but not provided: "+e.join(", "))},T=oe(process.env),Ye=()=>T.str("APP_DB_TYPE")!==we.APP_DB_TYPE&&T.str("APP_DB_DATABASE")!==we.APP_DB_DATABASE;var cc=require("reflect-metadata"),Mr=_(require("fastify")),kr=_(require("qs"));var tt=require("typeorm");var je=require("typeorm");var g=T.str("APP_DB_TYPE")==="sqlite"?"datetime":"timestamp";var Se=new je.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:g,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:g,default:()=>"CURRENT_TIMESTAMP"}},relations:{datasource:{target:()=>"DataSource",type:"many-to-one",joinTable:!1,cascade:!0}}});var Ge=require("typeorm");var Ee=new Ge.EntitySchema({name:"Team",tableName:"teams",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:g,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:g,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 Re=new Ke.EntitySchema({name:"User",tableName:"users",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:g,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:g,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 Ve=require("typeorm");var be=new Ve.EntitySchema({name:"UserSettings",tableName:"user_settings",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:g,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:g,default:()=>"CURRENT_TIMESTAMP"}},relations:{user:{type:"one-to-one",target:()=>"User",inverseSide:"settings",joinColumn:!0}}});var ze=require("typeorm");var Ie=new ze.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:g,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:g,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:g,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 rt=_(require("node:os")),ot=require("node:path");var Je=require("typeorm");var Ne=new Je.EntitySchema({name:"Query",tableName:"query",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},opts:{type:"json",default:"{}"},createdAt:{type:g,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:g,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 Xe=require("typeorm"),Ce=new Xe.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 Ze=require("typeorm");var Ae=new Ze.EntitySchema({name:"SavedQuery",tableName:"saved_queries",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},isPersonal:{type:Boolean},createdAt:{type:g,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:g,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 et=require("typeorm");var Pe=new et.EntitySchema({name:"WorkbenchTab",tableName:"workbench_tabs",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:g,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:g,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 Vr(){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>",rt.default.homedir())),e}var w=new tt.DataSource({type:T.str("APP_DB_TYPE"),database:Vr(),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:[ot.posix.join(__dirname,"migrations","*.js")],entities:[Se,Ie,Ee,Re,Ce,be,Ne,Ae,Pe]}),at=async()=>{if(!w.isInitialized)return w.initialize();throw new Error("Already initialized")},D=w.getRepository(Se),b=w.getRepository(Ie),k=w.getRepository(Ee),S=w.getRepository(Re),C=w.getRepository(Ce),W=w.getRepository(be),I=w.getRepository(Ne),x=w.getRepository(Ae),A=w.getRepository(Pe);var zr={hosted:{bindServerUrl:"0.0.0.0",skipAuth:!1,name:"hosted"},local:{bindServerUrl:"127.0.0.1",skipAuth:!0,name:"local"}},nt=j.str("mode");if(!nt)throw new Error(`Invalid mode "${j.str("mode")}"`);var L=zr[nt];var st=T.str("ALLOWED_ORIGINS","").split(",").map(e=>e.trim()),it=T.num("PORT",4466),G={port:it,host:L.bindServerUrl,allowedOrigins:st.includes("*")?"*":[`http://localhost:${it}`,...st]};var h=e=>(t,r,o)=>{e(t),o()};var K=require("jose");var s=class extends Error{constructor(r,o){super(o);this.status=r;this.message=o}};var ut=new TextEncoder,ct=ut.encode(T.str("JWT_SECRET")),lt=ut.encode(T.str("JWT_REFRESH_SECRET")),Oe=async({userId:e})=>new K.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("1h").sign(ct),_e=async({userId:e})=>new K.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("10d").sign(lt),mt=async(e,t)=>{try{let{payload:r}=await(0,K.jwtVerify)(e,t);if(!r.sub)throw new s(401,"Failed to verify access token");return{userId:r.sub}}catch(r){throw r instanceof s?r:r instanceof Error?new s(401,r.message):new s(401,"Failed to verify refresh token")}},dt=async e=>mt(e,ct),pt=async e=>mt(e,lt);var f=(e,t)=>{let r=e.body;return t&&t(r),r},U=(e,t)=>{let r=e.query;return t&&t(r),r},d=(e,t)=>{let r=e.params;return t&&t(r),r};var yt=_(require("bcryptjs"));var ft=e=>{if(!e?.username)throw new s(400,"Username is required");if(!e?.password)throw new s(400,"Password is required")};var se="DATARAMEN_refresh_token",ve={httpOnly:!0,secure:T.bool("PROD"),sameSite:T.bool("PROD"),path:"/",maxAge:10*24*60*60},Tt=h(e=>{e.route({method:"post",url:"/login",config:{isPublic:!0},handler:async(t,r)=>{let{username:o,password:a}=f(t,ft),n=await S.findOne({where:{username:o}});if(!n||!yt.default.compareSync(a,n.password))throw new s(401,"Invalid credentials");let[i,u]=await Promise.all([Oe({userId:n?.id}),_e({userId:n?.id})]);return r.setCookie(se,u,ve),{data:{accessToken:i}}}}),e.route({method:"post",url:"/refresh",config:{isPublic:!0},handler:async(t,r)=>{let o=t.cookies[se];if(!o)return r.code(401).send({message:"Missing refresh token"});let{userId:a}=await pt(o),[n,i]=await Promise.all([Oe({userId:a}),_e({userId:a})]);return r.setCookie(se,i,ve),{data:{accessToken:n}}}}),e.route({method:"post",url:"/logout",config:{isPublic:!0},handler:async(t,r)=>(r.clearCookie(se,ve),{data:!0})})});var ht=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 wt=_(require("mysql2/promise"));function V(e){if(e!==void 0)return e.toLowerCase()}var Jr=({database:e,password:t,user:r,url:o})=>wt.default.createConnection({host:o,user:r,database:e,password:t}),Xr=async e=>{let t=`
|
|
1
|
+
"use strict";var Qr=Object.create;var $e=Object.defineProperty;var $r=Object.getOwnPropertyDescriptor;var Br=Object.getOwnPropertyNames;var Wr=Object.getPrototypeOf,Hr=Object.prototype.hasOwnProperty;var Yr=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Br(t))!Hr.call(e,a)&&a!==r&&$e(e,a,{get:()=>t[a],enumerable:!(o=$r(t,a))||o.enumerable});return e};var v=(e,t,r)=>(r=e!=null?Qr(Wr(e)):{},Yr(t||!e||!e.__esModule?$e(r,"default",{value:e,enumerable:!0}):r,e));var ae=require("dotenv"),ne=require("node:path"),We=require("node:fs");var re=e=>{function t(a,n=void 0){return e[a]||n}function r(a,n=void 0){let i=e[a];if(!i)return n;let u=Number(i);return!isNaN(u)&&i.trim()!==""?u:n}function o(a){return e[a]==="true"||e[a]==="TRUE"||e[a]==="1"}return{str:t,num:r,bool:o}};function jr(e){let t={mode:void 0,env:void 0};for(let r of e){if(!r.startsWith("--"))continue;let[o,...a]=r.slice(2).split("=");if(!o||a.length===0)continue;let n=a.join("=");n=n.replace(/^["'](.+)["']$/,"$1"),t[o]=n}return t}var oe=re(jr(process.argv.slice(2)));var Gr=(()=>{try{let e=(0,We.readFileSync)((0,ne.join)(__dirname,"..","package.json"),"utf8");return JSON.parse(e)}catch{return{version:"0.0.0"}}})(),He=[],Be=oe.str("env");Be&&He.push((0,ne.resolve)(Be));(0,ae.config)({path:He});var Se={APP_DB_TYPE:"sqlite",APP_DB_DATABASE:"<home>/.dataramen/.runtime/db.sqlite3"};(0,ae.populate)(process.env,{SERVER_VERSION:Gr.version,PROD:"true",...Se},{override:!1});var Kr=["SYMM_ENCRYPTION_KEY","JWT_SECRET","JWT_REFRESH_SECRET"],Ye=()=>{let e=[];for(let t of Kr)process.env[t]||e.push(t);if(e.length>0)throw new Error("Following env variables are required but not provided: "+e.join(", "))},y=re(process.env),je=()=>y.str("APP_DB_TYPE")!==Se.APP_DB_TYPE&&y.str("APP_DB_DATABASE")!==Se.APP_DB_DATABASE;var fc=require("reflect-metadata"),Mr=v(require("fastify")),kr=v(require("qs"));var rt=require("typeorm");var Ge=require("typeorm");var Vr={default:{bindServerUrl:"0.0.0.0",skipAuth:!1,name:"default"},docker:{bindServerUrl:"0.0.0.0",skipAuth:!1,name:"docker"},cli:{bindServerUrl:"127.0.0.1",skipAuth:!0,name:"cli"},dev:{bindServerUrl:"127.0.0.1",skipAuth:!0,name:"dev"}},zr=oe.str("mode","default"),_=Vr[zr];var h=y.str("APP_DB_TYPE")==="sqlite"?"datetime":"timestamp",se=_.name==="docker"?e=>e==="localhost"||e==="127.0.0.1"?"host.docker.internal":e:e=>e;var Ee=new Ge.EntitySchema({name:"DatabaseInspection",tableName:"db_inspection",columns:{id:{type:String,unique:!0,primary:!0,generated:"uuid"},tableName:{nullable:!0,type:String},columns:{type:"json",nullable:!0},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"}},relations:{datasource:{target:()=>"DataSource",type:"many-to-one",joinTable:!1,cascade:!0}}});var Ke=require("typeorm");var Re=new Ke.EntitySchema({name:"Team",tableName:"teams",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"}},relations:{users:{type:"one-to-many",target:()=>"UsersToTeams",inverseSide:"team"},queries:{type:"one-to-many",target:()=>"Query",inverseSide:"team"},datasources:{type:"one-to-many",target:()=>"DataSource",inverseSide:"team"}}});var Ve=require("typeorm");var be=new Ve.EntitySchema({name:"User",tableName:"users",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},username:{type:String,unique:!0},password:{type:String}},relations:{teams:{type:"one-to-many",target:()=>"UsersToTeams",inverseSide:"user"},settings:{type:"one-to-one",target:()=>"UserSettings",inverseSide:"user"},currentTeam:{type:"one-to-one",target:()=>"UsersToTeams",inverseSide:"user",joinColumn:!0},queries:{type:"one-to-many",target:()=>"Query",inverseSide:"user"}}});var ze=require("typeorm");var Ie=new ze.EntitySchema({name:"UserSettings",tableName:"user_settings",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"}},relations:{user:{type:"one-to-one",target:()=>"User",inverseSide:"settings",joinColumn:!0}}});var Je=require("typeorm");var Ne=new Je.EntitySchema({name:"DataSource",tableName:"data_sources",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},dbUrl:{type:String},dbPort:{type:Number,nullable:!0},dbUser:{type:String},dbPassword:{type:String,nullable:!0,select:!1},dbPasswordIv:{type:String,nullable:!0,select:!1},dbPasswordTag:{type:String,nullable:!0,select:!1},dbType:{type:String},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},name:{type:String},description:{type:String,nullable:!0},dbDatabase:{type:String},dbSchema:{type:String,nullable:!0},allowInsert:{type:Boolean,default:!1},allowUpdate:{type:Boolean,default:!1},lastInspected:{type:h,nullable:!0,default:null},status:{type:String,nullable:!0}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"datasources",joinColumn:!0},inspections:{type:"one-to-many",target:()=>"DatabaseInspection",inverseSide:"datasource"},queries:{type:"one-to-many",target:()=>"Query",inverseSide:"dataSource"},owner:{type:"many-to-one",target:()=>"User",joinColumn:!0}}});var ot=v(require("node:os")),at=require("node:path");var Xe=require("typeorm");var Ce=new Xe.EntitySchema({name:"Query",tableName:"query",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},opts:{type:"json",default:"{}"},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,default:()=>"CURRENT_TIMESTAMP",onUpdate:"CURRENT_TIMESTAMP"}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"queries",joinColumn:!0},dataSource:{type:"many-to-one",target:()=>"DataSource",inverseSide:"datasources",joinColumn:!0},user:{type:"many-to-one",target:()=>"User",inverseSide:"queries",joinColumn:!0,nullable:!0}}});var Ze=require("typeorm"),Ae=new Ze.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 et=require("typeorm");var Pe=new et.EntitySchema({name:"SavedQuery",tableName:"saved_queries",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},isPersonal:{type:Boolean},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,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 tt=require("typeorm");var Oe=new tt.EntitySchema({name:"WorkbenchTab",tableName:"workbench_tabs",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:h,default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:h,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 Jr(){let e=y.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>",ot.default.homedir())),e}var w=new rt.DataSource({type:y.str("APP_DB_TYPE"),database:Jr(),host:y.str("APP_DB_HOST"),username:y.str("APP_DB_USERNAME"),password:y.str("APP_DB_PASSWORD"),port:y.num("APP_DB_PORT"),schema:y.str("APP_DB_SCHEMA"),logging:y.bool("APP_DB_LOGGING"),migrationsRun:!0,migrations:[at.posix.join(__dirname,"migrations","*.js")],entities:[Ee,Ne,Re,be,Ae,Ie,Ce,Pe,Oe]}),nt=async()=>{if(!w.isInitialized)return w.initialize();throw new Error("Already initialized")},U=w.getRepository(Ee),b=w.getRepository(Ne),k=w.getRepository(Re),S=w.getRepository(be),C=w.getRepository(Ae),W=w.getRepository(Ie),I=w.getRepository(Ce),x=w.getRepository(Pe),A=w.getRepository(Oe);var st=y.str("ALLOWED_ORIGINS","").split(",").map(e=>e.trim()),it=y.num("PORT",4466),j={port:it,host:_.bindServerUrl,allowedOrigins:st.includes("*")?"*":[`http://localhost:${it}`,...st]};var g=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 ut=new TextEncoder,ct=ut.encode(y.str("JWT_SECRET")),lt=ut.encode(y.str("JWT_REFRESH_SECRET")),ve=async({userId:e})=>new G.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("1h").sign(ct),_e=async({userId:e})=>new G.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("10d").sign(lt),mt=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")}},dt=async e=>mt(e,ct),pt=async e=>mt(e,lt);var f=(e,t)=>{let r=e.body;return t&&t(r),r},L=(e,t)=>{let r=e.query;return t&&t(r),r},d=(e,t)=>{let r=e.params;return t&&t(r),r};var yt=v(require("bcryptjs"));var ft=e=>{if(!e?.username)throw new s(400,"Username is required");if(!e?.password)throw new s(400,"Password is required")};var ie="DATARAMEN_refresh_token",De={httpOnly:!0,secure:y.bool("PROD"),sameSite:y.bool("PROD"),path:"/",maxAge:14400*60},Tt=g(e=>{e.route({method:"post",url:"/login",config:{isPublic:!0},handler:async(t,r)=>{let{username:o,password:a}=f(t,ft),n=await S.findOne({where:{username:o}});if(!n||!yt.default.compareSync(a,n.password))throw new s(401,"Invalid credentials");let[i,u]=await Promise.all([ve({userId:n?.id}),_e({userId:n?.id})]);return r.setCookie(ie,u,De),{data:{accessToken:i}}}}),e.route({method:"post",url:"/refresh",config:{isPublic:!0},handler:async(t,r)=>{let o=t.cookies[ie];if(!o)return r.code(401).send({message:"Missing refresh token"});let{userId:a}=await pt(o),[n,i]=await Promise.all([ve({userId:a}),_e({userId:a})]);return r.setCookie(ie,i,De),{data:{accessToken:n}}}}),e.route({method:"post",url:"/logout",config:{isPublic:!0},handler:async(t,r)=>(r.clearCookie(ie,De),{data:!0})})});var gt=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 wt=v(require("mysql2/promise"));function K(e){if(e!==void 0)return e.toLowerCase()}var Xr=({database:e,password:t,user:r,url:o})=>wt.default.createConnection({host:se(o),user:r,database:e,password:t}),Zr=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},eo=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},to=async(e,t)=>{let o=(await t.query("SHOW TABLES"))[0],a=await eo(t),n=await Zr(t),i=o.map(async u=>{let m=K(Object.values(u)[0]),c=`select COLUMN_NAME, DATA_TYPE from information_schema.columns where table_schema = '${e.database}' and LOWER(table_name) = '${m}'`,[E]=await t.query(c),p=a[m];return{columns:E.map(l=>({name:l.COLUMN_NAME,type:l.DATA_TYPE,isPrimary:n[m]?.includes(l.COLUMN_NAME),ref:p?.[l.COLUMN_NAME]?{table:p[l.COLUMN_NAME].refTable,field:p[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:m,updatedAt:new Date}});return Promise.all(i)},ht=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)}},ro=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}},oo=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}},St=async e=>{let t=await Xr(e),r=!1;return{dbType:"mysql",dataSource:e,inspectSchema:()=>to(e,t),executeQuery:(o,a)=>a.type==="SELECT"?oo(t,()=>ht(o,t,a)):ro(t,()=>ht(o,t,a)),checkConnection:async()=>t.ping(),isClosed:()=>r,close:async()=>{if(!r)return r=!0,t.destroy()}}};var Rt=v(require("pg"));var ao=async({database:e,password:t,user:r,url:o,port:a})=>{let n=new Rt.default.Client({host:se(o),user:r,database:e,password:t,port:a,query_timeout:1e4});return await n.connect(),n},no=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},so=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,16 +43,16 @@
|
|
|
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},io=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 so(t),i=await no(t),u=a.map(async m=>{let c=Object.values(m)[0],E=`
|
|
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:p}=await t.query(E),l=n[c];return{columns:p.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,M)=>N.isPrimary&&M.isPrimary?N.name.localeCompare(M.name):N.isPrimary?-1:1),createdAt:new Date,tableName:c,updatedAt:new Date}});return Promise.all(u)},
|
|
52
|
+
`,{rows:p}=await t.query(E),l=n[c];return{columns:p.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,M)=>N.isPrimary&&M.isPrimary?N.name.localeCompare(M.name):N.isPrimary?-1:1),createdAt:new Date,tableName:c,updatedAt:new Date}});return Promise.all(u)},uo=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),{})},Et=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}'`),m=await io(u,t);return{columns:a.map(c=>{let E=m[`${c.tableID}-${c.columnID}`];return{column:E?.column||c.name,alias:c.name,table:E?.table||"",full:E?E.table+"."+E.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)}},uo=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}},co=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}},bt=async e=>{let t=await oo(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:()=>so(e,t),executeQuery:(n,i)=>a(()=>i.type==="SELECT"?co(t,()=>Et(n,t,i)):uo(t,()=>Et(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 St(e);else if(t==="postgres")o=await bt(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 ie=_(require("node:crypto"));var It="aes-256-gcm",lo=12,Nt=()=>{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},mo=e=>{let t=ie.default.randomBytes(lo),r=Nt(),o=ie.default.createCipheriv(It,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")}},po=({encrypted:e,iv:t,tag:r})=>{let o=Nt(),a=ie.default.createDecipheriv(It,o,Buffer.from(t,"hex"));a.setAuthTag(Buffer.from(r,"hex"));let n=a.update(e,"hex","utf8");return n+=a.final("utf8"),n},ue={encrypt:mo,decrypt:po};var F=(e,t=!1)=>{if(t){let r=ue.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 Ct=[{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"}],fo=Ct.reduce((e,t)=>(e[t.value]=t.label,e),{}),En=Ct.reduce((e,t)=>(e[t.label]=t.value,e),{}),H=e=>e.map(t=>({label:fo[t],value:t})),Rn=H(["=","<>",">",">=","<","<=","IN","NOT IN","IS NULL","IS NOT NULL"]),bn=H(["=","<>","LIKE","NOT LIKE","IN","NOT IN","IS NULL","IS NOT NULL"]),In=H(["=","<>","IS NULL","IS NOT NULL"]),Nn=H(["=","<>",">",">=","<","<=","IS NULL","IS NOT NULL"]),Cn=H(["IS NULL","IS NOT NULL"]),An=H(["IN","NOT IN"]);var De=["char","varchar","binary","varbinary","blob","text","enum","set","character","character varying","text","citext","uuid","xml","json","jsonb"],yo=new Set(De),ce=e=>yo.has(e),To=["integer","smallint","decimal","numeric","float","real","double precision","int","smallint","integer","bigint","decimal","numeric","real","double precision","serial","bigserial","money"],ho=new Set(To),At=e=>ho.has(e);var Pn=["date","datetime","timestamp","timestamptz"].reduce((e,t)=>(e[t]=!0,e),{});var xe=e=>e.fn?e.distinct===!0?`${e.fn} distinct ${e.value}`:`${e.fn} ${e.value}`:e.value;var Ue={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 Pt={operator:"LIKE",parse:e=>{let t=e.match(/^LIKE\s*["'](.*)["']$/i);if(t)return[{value:v(t[1])}]},stringify:(e,t)=>ce(t)?`${e.value?.[0].value}`:`LIKE "%${e.value?.[0].value}%"`},Ot={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 vt(e){return e===""?[]:go(e).map(wo)}function go(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 wo(e){if(e.startsWith("'")&&e.endsWith("'"))return{value:_t(e.slice(1,-1),"'")};if(e.startsWith('"')&&e.endsWith('"'))return{value:_t(e.slice(1,-1),'"')};let t=Number(e);if(!Number.isNaN(t))return{value:t};throw new Error(`Invalid literal: ${e}`)}function _t(e,t){return e.replace(/\\(.)/g,(r,o)=>o)}var Dt={operator:"IN",parse:e=>{let t=e.match(/^in\s*\((.*)\)$/i);if(t)return vt(t[1])},stringify:e=>`IN (${e.value?.map(t=>`"${t.value}"`).join(", ")})`},xt={operator:"NOT IN",parse:e=>{let t=e.match(/^not\s+in\s*\((.*)\)$/i);if(t)return vt(t[1])},stringify:e=>`NOT IN (${e.value?.map(t=>`"${t.value}"`).join(", ")})`};var Ut={operator:"=",parse:e=>{let t=e.match(/^=\s*(.*)$/);if(t)return[{value:v(t[1])}]},stringify:(e,t)=>At(t)?`${e.value?.[0].value}`:`= ${e.value?.[0].value}`},Lt={operator:"!=",parse:e=>{let t=e.match(/^!=\s*(.*)$/);if(t)return[{value:v(t[1])}]},stringify:e=>`!= ${e.value?.[0].value}`},Mt={operator:"<>",parse:e=>{let t=e.match(/^<>\s*(.*)$/);if(t)return[{value:v(t[1])}]},stringify:e=>`<> ${e.value?.[0].value}`},kt={operator:">",parse:e=>{let t=e.match(/^>\s*(.*)$/);if(t)return[{value:v(t[1])}]},stringify:e=>`> ${e.value?.[0].value}`},qt={operator:">=",parse:e=>{let t=e.match(/^>=\s*(.*)$/);if(t)return[{value:v(t[1])}]},stringify:e=>`>= ${e.value?.[0].value}`},Ft={operator:"<",parse:e=>{let t=e.match(/^<\s*(.*)$/);if(t)return[{value:v(t[1])}]},stringify:e=>`< ${e.value?.[0].value}`},Qt={operator:"<=",parse:e=>{let t=e.match(/^<=\s*(.*)$/);if(t)return[{value:v(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"},Bt={operator:"IS NOT NULL",parse:e=>{if(/^is\s+not\s+null$/i.test(e))return[]},stringify:()=>"IS NOT NULL"};var Wt=[Pt,Ot,Dt,xt,Ut,Lt,Mt,qt,kt,Qt,Ft,$t,Bt],So=Wt.reduce((e,t)=>(e[t.operator]=t,e),{});function Eo(e,t){return So[e.operator]?.stringify(e,t)||""}function Ro(e){let t=e.trim();for(let r of Wt){let o=r.parse(t);if(o)return{operator:r.operator,value:o}}}var Ht={parse:Ro,stringify:Eo};var R=e=>{let t=Ue[e];return r=>Ue[r.currentTeamRole]>=t},Yt=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 jt=h(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=d(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}=U(t);return{data:await b.find({where:{team:{id:r}},order:{createdAt:"DESC"}})}}}),e.route({url:"/",method:"post",config:{requireRole:R("admin")},handler:async t=>{let{teamId:r,ownerId:o,...a}=f(t,ht),n=b.create({...a,allowUpdate:!!a.allowUpdate,allowInsert:!!a.allowInsert,team:{id:r},owner:{id:o}}),i=await q(F(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:m,encrypted:c}=ue.encrypt(n.dbPassword);return n.dbPassword=c,n.dbPasswordIv=m,n.dbPasswordTag=u,{data:await b.save(n)}}}),e.route({method:"put",url:"/:id",config:{requireRole:R("admin")},handler:async t=>{let{id:r}=d(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:R("admin")},handler:async(t,r)=>w.transaction(async()=>{let{id:o}=d(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}=d(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(F(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}=d(t);return{data:await D.find({where:{datasource:{id:r}}})}}})});var $=require("typeorm"),Gt=h(e=>{e.route({method:"get",url:"/team/:teamId/datasources",handler:async t=>{let{teamId:r}=d(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 r=d(t),o=U(t),a=r.teamId||t.user.currentTeamId,n=Number(o.size)||20,i=Number(o.page)||0,u=o.nameFilter?.length?{name:(0,$.Raw)(p=>`LOWER(${p}) LIKE :search`,{search:`%${o.nameFilter.toLowerCase()}%`})}:void 0,m=await x.find({where:[{isPersonal:!1,team:{id:a},query:u},{isPersonal:!0,team:{id:a},query:u,user:{id:t.user.id}}],relations:{query:{dataSource:!0}},take:n+1,skip:i*n,select:{id:!0,query:{id:!0,name:!0,updatedAt:!0,dataSource:{name:!0,dbType:!0}}},order:{query:{updatedAt:"DESC"}}}),c=m.length>n;return c&&m.pop(),{data:m.map(p=>({name:p.query.name,id:p.query.id,updatedAt:p.query.updatedAt,savedQueryId:p.id,datasourceName:p.query.dataSource.name,datasourceType:p.query.dataSource.dbType})),hasMore:c}}}),e.route({method:"get",url:"/team/:teamId/count-saved-queries",handler:async t=>{let o=d(t).teamId||t.user.currentTeamId;return{data:await x.count({where:[{isPersonal:!1,team:{id:o}},{isPersonal:!0,team:{id:o},user:{id:t.user.id}}],select:{id:!0}})}}}),e.route({method:"get",url:"/team/:teamId/query",handler:async t=>{let{teamId:r}=d(t),{search:o,size:a,selectedDataSources:n}=U(t),i=o.length>3?parseInt(a)||20:8,u={};n?.length&&(u.id=(0,$.In)(n));let[m,c,E]=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}),A.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}),x.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})]),p=[];return m.forEach(l=>{p.push({name:l.tableName,id:l.id,dataSourceName:l.datasource?.name||"--",dataSourceId:l.datasource?.id||"--",type:"table"})}),c.forEach(l=>{p.push({name:l.name,id:l.id,dataSourceName:l.dataSource?.name||"--",dataSourceId:l.dataSource?.id||"--",type:"tab"})}),E.forEach(l=>{p.push({name:l.query.name,id:l.query.id,dataSourceName:l.query.dataSource?.name||"--",dataSourceId:l.query.dataSource?.id||"--",type:"query"})}),{data:p}}}),e.route({method:"get",url:"/team/:teamId/tabs-history",handler:async t=>{let{teamId:r}=d(t),o=U(t),a=Number(o.page),n=Number(o.size),i=t.user.id,u=await A.find({where:{team:{id:r},user:{id:i},archived:o.archived?o.archived==="true":void 0},relations:{dataSource:!0},order:{updatedAt:"DESC"},take:n+1,skip:a*n}),m=!1;return u.length>n&&(u.pop(),m=!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:m}}})});var Kt=h(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=d(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:R("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:R("editor")},handler:async t=>{let{id:r}=d(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:R("editor")},handler:async t=>w.transaction(async()=>{let{id:r}=d(t);if(!(await I.delete({id:r})).affected)return{status:404,data:"Query not found"}})})});var le=e=>{let t=e.distinct===!0?"distinct ":"";return`${e.fn}(${t}${e.value})`},z={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:le,MAX:le,MIN:le,COUNT:le};var me=e=>{let t=e.distinct===!0?"distinct ":"";return`${e.fn}(${t}${e.value})`},J={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:me,MAX:me,MIN:me,COUNT:me};var Vt=["SUM","COUNT","AVG","MAX","MIN"],bo=["YEAR","MONTH","DAY",...Vt],Io=bo.reduce((e,t)=>(e[t]=!0,e),{}),No=Vt.reduce((e,t)=>(e[t]=!0,e),{}),de=e=>Io[e],zt=e=>No[e],Jt=(e,t)=>e.fn&&de(e.fn)?(t==="postgres"?z:J)[e.fn](e):e.value;var pe=e=>typeof e=="string",Xt=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},X=(e,t)=>{let{column:r,operator:o,value:a,fn:n}=e,i=Jt({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=>pe(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 E=a?.[0],p;return pe(E?.value)&&E?.isColumn!==!0?p=`'${E?.value}'`:p=E?.value,`${i} ${o} ${p}`}};var Z=class{constructor(t="mysql"){this.dialect=t,this.skeleton={type:"SELECT"}}addWhere(t){let r=X(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=X(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 Xt(this.skeleton)}};var rr=require("typeorm");var Zt=e=>ce(e)?"LIKE":"=",er=(e,t)=>{let r=[];for(let o of e)if(!(!o.column?.length||!o.value?.length||o.isEnabled===!1))if(o.isAdvanced){let a=Ht.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||Zt(t[o.column]),connector:"AND"})}else r.push({value:o.value?[{value:o.value}]:[],column:o.column,id:o.id,operator:Zt(t[o.column]),connector:"AND"});return r};var fe=async(e,t)=>{let{datasourceId:r,size:o=20,page:a,name:n}=t,{table:i,joins:u,groupBy:m,searchAll:c,orderBy:E}=t.opts,p=_o(t.opts.columns,t.opts.groupBy,t.opts.aggregations),l=await ye(r),N=[i],M=[];if(!l)throw new s(404,"Data source not found");let qr=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 Z(l.dbType);P.setTable(i),P.setLimit(o+1),P.setOffset(o*a),u&&(P.addJoin(...u),u.forEach(y=>{N.push(y.table)}));let ke=Oo(p,E,l.dbType);ke.length>0&&P.addOrderBy(...ke),m&&m.length>0&&m.forEach(y=>P.addGroupBy(Po(y,l.dbType)));let Fr=await D.find({where:{tableName:(0,rr.In)(N),datasource:{id:r}}});for(let y of Fr)if(y.columns)for(let O of y.columns)M.push({column:O.name,table:y.tableName||"",full:`${y.tableName}.${O.name}`,type:O.type});let qe=M.reduce((y,O)=>(y[O.full]=O.type,y),{});er(t.opts.filters,qe)?.forEach(y=>{y.fn&&zt(y.fn)?P.addHaving(y):P.addWhere(y)});let te;if(p&&p.length>0?te=p.map(y=>Ao(y,l.dbType)):te=M.map(y=>`${y.full} as "${y.full}"`),P.selectColumns(te),c){let y=M.filter(O=>De.includes(O.type)&&te.some(ge=>ge.startsWith(O.full)));if(y.length>0){let O=y.map(ge=>`LOWER(${ge.full}) LIKE '%${c.toLowerCase()}%'`);P.addWhereRaw(`(${O.join(" OR ")})`,"AND")}}let re=await(await q(F(l,!0),l.dbType,e)).executeQuery(P.toSQL(),{type:"SELECT",allowBulkUpdate:!1}),Fe=re.rows.length>o;return Fe&&re.rows.pop(),{...re,queryHistoryId:qr.id,tables:N,allColumns:M,columns:re.columns.map(y=>({...y,type:qe[y.full]})),hasMore:Fe}},or=async(e,t)=>{let r=await ye(t.dataSourceId);if(!r)throw new s(400,"Invalid datasource");let o=await q(F(r,!0),r.dbType,e),a=new Z(r.dbType);a.setTable(t.table),a.setLimit(2);for(let[u,m]of Object.entries(t.props))a.addWhere({value:[{value:m}],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}},ar=async(e,t)=>{let r=await ye(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:m})=>typeof u=="string"?u&&u.startsWith("=")?`${m}=${u.substring(1)}`:`${m}='${u}'`:`${m}='${u}'`).join(", "),a=t.filters.map(u=>X(u,r.dbType)).join(" AND "),n=`UPDATE ${t.table} SET ${o} WHERE ${a}`;return(await q(F(r,!0),r.dbType,e)).executeQuery(n,{type:"UPDATE",allowBulkUpdate:!1})},nr=async(e,t)=>{let r=await ye(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}=Co(t.values),n=`INSERT INTO ${t.table} (${o}) VALUES (${a})`;return(await q(F(r,!0),r.dbType,e)).executeQuery(n,{type:"INSERT",allowBulkUpdate:!1})},Co=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}},Ao=(e,t)=>{if(e.fn){if(de(e.fn))return`${(t==="postgres"?z:J)[e.fn](e)} as "${xe(e)}"`;throw new Error("Function not allowed: "+e.fn)}return`${e.value} as "${e.value}"`},Po=(e,t)=>{if(e.fn){if(de(e.fn))return(t==="postgres"?z:J)[e.fn]({...e,value:tr(e.value,t)});throw new Error("Function not allowed: "+e.fn)}return tr(e.value,t)},Le=(e,t)=>t==="postgres"?`"${e}"`:t==="mysql"?`\`${e}\``:e,tr=(e,t)=>{let[r,o]=e.split(".");return Le(r,t)+"."+Le(o,t)},Oo=(e,t,r)=>{if(e&&e.length>0){let o=e.reduce((a,n)=>(a.set(xe(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:Le(a.column,r)}:a)}return t},_o=(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 ye(e){return b.findOne({where:{id:e},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser","allowUpdate","allowInsert"]})}var sr=e=>{},vo=["--",";","DROP","drop"],ir=e=>{if(pe(e.value)&&e.value.startsWith("=")){let t=e.value;vo.forEach(r=>{if(t.includes(r))throw new s(400,"Invalid input value for "+e.column)})}},ur=e=>{if(!e.table)throw new s(400,"Table is required");e.values.forEach(ir)},cr=e=>{if(!e.table)throw new s(400,"Table is required");e.values.forEach(ir)};var lr=h(e=>{e.route({method:"post",url:"/:dsId/select",handler:async t=>{let r=f(t,sr);return{data:await fe(t,r)}}}),e.route({method:"get",url:"/:dsId/entity/:table",handler:async t=>{let{dsId:r,table:o}=d(t),a=U(t);return{data:await or(t,{table:o,dataSourceId:r,props:a})}}}),e.route({method:"post",url:"/:dsId/insert",config:{requireRole:R("editor")},handler:async t=>{let r=f(t,ur);return{data:await nr(t,r)}}}),e.route({method:"post",url:"/:dsId/update",config:{requireRole:R("editor")},handler:async t=>{let r=f(t,cr);return{data:await ar(t,r)}}})});var mr=h(e=>{e.get("/",{config:{isPublic:!0}},async()=>({data:{active:!0,version:T.str("SERVER_VERSION")}}))});var dr=h(e=>{e.route({method:"get",url:"/:id/users",handler:async t=>{let{id:r}=d(t),o=await k.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:R("editor")},handler:async t=>w.transaction(async()=>{let r=t.user.id,o=f(t),a=S.create();a.id=r;let n=k.create(o);await k.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:R("admin")},handler:async t=>{let{id:r}=d(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:R("admin")},handler:async t=>w.transaction(async()=>{let{id:r}=d(t),{userId:o}=U(t);if((await C.findOneBy({user:{id:o},team:{id:r}}))?.role==="owner")throw new s(400,"Cannot delete team owner");await S.update(o,{currentTeam:null}),await C.delete({user:{id:o},team:{id:r}}),await S.delete({id:o})})})});var Me=_(require("bcryptjs")),ee=async e=>{let t=await Me.default.genSalt(10);return Me.default.hash(e,t)};var pr=h(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=await S.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 ee(o.password)),!(await S.update(r,o)).affected)throw new s(404,"User not found");let n=await S.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:R("admin")},handler:async t=>w.transaction(async()=>{let r=f(t),o=await ee(r.password),a=await S.save(S.create({username:r.username,password:o})),n=await C.save(C.create({role:"read_only",team:{id:r.teamId},user:{id:a.id}}));await S.update(a.id,{currentTeam:{id:n.id}})})})});var fr=h(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=t.user.id,o=await W.findOneBy({user:{id:r}});return o||(o=await W.save(W.create({user:{id:r}}))),{data:o}}}),e.route({method:"patch",url:"/",handler:async t=>{let{settings:r}=f(t);if(!r.id)throw new 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 yr=h(e=>{e.route({method:"post",url:"/",config:{requireRole:R("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 x.save(x.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:R("editor")},handler:async t=>{let{id:r}=d(t);if(!(await x.delete({id:r})).affected)return{status:404,data:"Query not found"}}}),e.route({method:"patch",url:"/:id",handler:async t=>await w.transaction(async()=>{let{id:r}=d(t),o=f(t,i=>{if(!i.name)throw new s(400,"Name is required")}),a=await x.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([x.update({id:r},{searchString:n}),I.update({id:a.query.id},{name:o.name})]),{data:!0}})})});var Tr=e=>{if(!e.queryId&&!(e.opts&&e.name))throw new s(400,"Either queryId or name and opts are required")};var hr=h(e=>{e.route({method:"get",url:"/",handler:async t=>{let{currentTeamId:r,id:o}=t.user;return{data:(await A.find({where:{team:{id:r},user:{id:o},archived:!1},select:["id","name"]})).map(n=>({name:n.name,id:n.id}))}}}),e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=d(t),{currentTeamId:o,id:a}=t.user,n=await A.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,Tr),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 A.save(A.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}=d(t),o=f(t),a=await A.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&&A.update(r,{opts:o,searchString:Y(o,a.name),updatedAt:new Date}),{data:{result:await fe(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}=d(t),o=f(t),a=await A.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 A.update(r,{...o,searchString:n}),{data:{id:r}}}}),e.route({method:"delete",url:"/:id",handler:async t=>{let{id:r}=d(t),o=t.user.id;return await A.delete({id:r,user:{id:o}}),{data:!0}}})});var Sr=require("node:crypto");var gr=require("node:crypto"),wr={teamName:"Default Team",username:"admin"},Do=async()=>{let e=await k.findOneBy({});return e||k.save(k.create({name:wr.teamName}))},Te=async e=>{let t=await C.findOne({where:{role:"owner"},relations:{user:!0}});if(t)return t.user;let r=await Do(),o=await ee(e?.password||(0,gr.randomBytes)(32).toString("hex")),a=await S.save(S.create({username:e?.name||wr.username,password:o})),n=await C.save(C.create({user:a,team:r,role:"owner"}));return await S.update(a.id,{currentTeam:n}),a};var he={setupAccessToken:void 0},Er=()=>(he.setupAccessToken=(0,Sr.randomBytes)(32).toString("hex"),he.setupAccessToken),xo=e=>{if(!he.setupAccessToken)throw new s(400,"Setup already performed");if(!e||e!==he.setupAccessToken)throw new s(400,"Invalid setup access token")},B=async()=>L.skipAuth?!1:await S.count()<1,Rr=async e=>{xo(e.setupAccessToken),await Te({name:e.userName,password:e.userPassword})};var br=h(e=>{e.route({method:"get",url:"/client.config.js",handler:(t,r)=>{let o={skipAuth:L.skipAuth,modeName:L.name,usesCustomDb:Ye()};return r.type("application/javascript").send(`window.__CLIENT_CONFIG__ = ${JSON.stringify(o)};`)}}),e.route({method:"get",url:"/",handler:async(t,r)=>await B()?r.redirect("/setup"):r.sendFile("index.html")}),e.route({method:"get",url:"/setup",handler:async(t,r)=>await B()?r.sendFile("setup.html"):r.redirect("/")})});var Ir=e=>{if(!e.setupAccessToken)throw new s(400,"Invalid setup access token");if(!e.userPassword||e.userPassword.length<8)throw new s(400,"Password should be at least 8 chars long");if(!e.userName)throw new s(400,"User name is required")};var Nr=h(e=>{e.route({method:"post",url:"/",config:{isPublic:!0},handler:async t=>{if(!await B())throw new s(400,"Setup has already been completed");let o=f(t,Ir);return await Rr(o),{data:!0}}})});var Uo=[[br,"/"],[Tt,"/api/auth"],[jt,"/api/data-sources"],[Gt,"/api/project"],[Kt,"/api/queries"],[lr,"/api/runner"],[mr,"/api/status"],[dr,"/api/teams"],[pr,"/api/users"],[fr,"/api/user-settings"],[yr,"/api/saved-queries"],[hr,"/api/workbench-tabs"],[Nr,"/api/setup"]],Cr=e=>{for(let[t,r]of Uo)e.register(t,{prefix:r}),console.log("Registered "+r)};var Lo=e=>e.routeOptions.config.isPublic?!0:!e.url.startsWith("/api/"),Mo=async()=>C.findOne({where:{role:"owner"},relations:{user:!0,team:!0}}),ko=async e=>{let t=await Mo();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}},qo=async e=>{let t=e.headers.authorization;if(!t)throw new s(401,"Missing auth token");let[r,o]=t.split(" "),{userId:a}=await dt(o),n=await S.findOne({where:{id:a},select:{id:!0,currentTeam:{role:!0,team:{id:!0}}},relations:{currentTeam:{team:!0}}});if(!n)throw new s(401,"Unauthorized");e.user={id:a,currentTeamId:n.currentTeam.team.id,currentTeamRole:n.currentTeam.role}},Ar=async e=>{Lo(e)||(L.skipAuth?await ko(e):await qo(e))};var Pr=(e,t)=>{e.__connections&&e.__connections.forEach(r=>{r.close()})};var Or=e=>{e.addHook("onRequest",Ar),e.addHook("onRequest",Yt),e.addHook("onResponse",Pr)};var _r=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 vr=_(require("@fastify/cookie")),Dr=_(require("@fastify/cors"));var xr=_(require("@fastify/static")),Ur=require("node:path"),Lr=e=>{e.register(vr.default,{}),e.register(Dr.default,{origin:G.allowedOrigins,methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"],credentials:!0}),e.register(xr.default,{root:(0,Ur.join)(__dirname,"web")})};(async function(){let t=(0,Mr.default)({querystringParser:o=>kr.default.parse(o)});if(He(),Lr(t),Or(t),Cr(t),_r(t),await t.after(),await at(),t.listen({port:G.port,host:G.host},(o,a)=>{o&&(console.error(o),process.exit(1)),console.log(`Server listening at ${a}`)}),await B()){let o=Er();console.log(`Setup access token:
|
|
58
|
-
${o}`),console.log("Use the above token to finish the setup process when opening the app for the first time.")}else await
|
|
57
|
+
limit 75;`;return(await t.query(r)).rows.reduce((a,n)=>(a[n.row_key]={table:n.relname,column:n.attname},a),{})},Et=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}'`),m=await uo(u,t);return{columns:a.map(c=>{let E=m[`${c.tableID}-${c.columnID}`];return{column:E?.column||c.name,alias:c.name,table:E?.table||"",full:E?E.table+"."+E.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)}},co=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}},lo=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}},bt=async e=>{let t=await ao(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:()=>io(e,t),executeQuery:(n,i)=>a(()=>i.type==="SELECT"?lo(t,()=>Et(n,t,i)):co(t,()=>Et(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 St(e);else if(t==="postgres")o=await bt(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 ue=v(require("node:crypto"));var It="aes-256-gcm",mo=12,Nt=()=>{let e=y.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},po=e=>{let t=ue.default.randomBytes(mo),r=Nt(),o=ue.default.createCipheriv(It,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")}},fo=({encrypted:e,iv:t,tag:r})=>{let o=Nt(),a=ue.default.createDecipheriv(It,o,Buffer.from(t,"hex"));a.setAuthTag(Buffer.from(r,"hex"));let n=a.update(e,"hex","utf8");return n+=a.final("utf8"),n},ce={encrypt:po,decrypt:fo};var F=(e,t=!1)=>{if(t){let r=ce.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 Ct=[{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"}],yo=Ct.reduce((e,t)=>(e[t.value]=t.label,e),{}),Cn=Ct.reduce((e,t)=>(e[t.label]=t.value,e),{}),H=e=>e.map(t=>({label:yo[t],value:t})),An=H(["=","<>",">",">=","<","<=","IN","NOT IN","IS NULL","IS NOT NULL"]),Pn=H(["=","<>","LIKE","NOT LIKE","IN","NOT IN","IS NULL","IS NOT NULL"]),On=H(["=","<>","IS NULL","IS NOT NULL"]),vn=H(["=","<>",">",">=","<","<=","IS NULL","IS NOT NULL"]),_n=H(["IS NULL","IS NOT NULL"]),Dn=H(["IN","NOT IN"]);var Ue=["char","varchar","binary","varbinary","blob","text","enum","set","character","character varying","text","citext","uuid","xml","json","jsonb"],To=new Set(Ue),le=e=>To.has(e),go=["integer","smallint","decimal","numeric","float","real","double precision","int","smallint","integer","bigint","decimal","numeric","real","double precision","serial","bigserial","money"],ho=new Set(go),At=e=>ho.has(e);var Un=["date","datetime","timestamp","timestamptz"].reduce((e,t)=>(e[t]=!0,e),{});var xe=e=>e.fn?e.distinct===!0?`${e.fn} distinct ${e.value}`:`${e.fn} ${e.value}`:e.value;var Le={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 Pt={operator:"LIKE",parse:e=>{let t=e.match(/^LIKE\s*["'](.*)["']$/i);if(t)return[{value:D(t[1])}]},stringify:(e,t)=>le(t)?`${e.value?.[0].value}`:`LIKE "%${e.value?.[0].value}%"`},Ot={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 _t(e){return e===""?[]:wo(e).map(So)}function wo(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 So(e){if(e.startsWith("'")&&e.endsWith("'"))return{value:vt(e.slice(1,-1),"'")};if(e.startsWith('"')&&e.endsWith('"'))return{value:vt(e.slice(1,-1),'"')};let t=Number(e);if(!Number.isNaN(t))return{value:t};throw new Error(`Invalid literal: ${e}`)}function vt(e,t){return e.replace(/\\(.)/g,(r,o)=>o)}var Dt={operator:"IN",parse:e=>{let t=e.match(/^in\s*\((.*)\)$/i);if(t)return _t(t[1])},stringify:e=>`IN (${e.value?.map(t=>`"${t.value}"`).join(", ")})`},Ut={operator:"NOT IN",parse:e=>{let t=e.match(/^not\s+in\s*\((.*)\)$/i);if(t)return _t(t[1])},stringify:e=>`NOT IN (${e.value?.map(t=>`"${t.value}"`).join(", ")})`};var xt={operator:"=",parse:e=>{let t=e.match(/^=\s*(.*)$/);if(t)return[{value:D(t[1])}]},stringify:(e,t)=>At(t)?`${e.value?.[0].value}`:`= ${e.value?.[0].value}`},Lt={operator:"!=",parse:e=>{let t=e.match(/^!=\s*(.*)$/);if(t)return[{value:D(t[1])}]},stringify:e=>`!= ${e.value?.[0].value}`},Mt={operator:"<>",parse:e=>{let t=e.match(/^<>\s*(.*)$/);if(t)return[{value:D(t[1])}]},stringify:e=>`<> ${e.value?.[0].value}`},kt={operator:">",parse:e=>{let t=e.match(/^>\s*(.*)$/);if(t)return[{value:D(t[1])}]},stringify:e=>`> ${e.value?.[0].value}`},qt={operator:">=",parse:e=>{let t=e.match(/^>=\s*(.*)$/);if(t)return[{value:D(t[1])}]},stringify:e=>`>= ${e.value?.[0].value}`},Ft={operator:"<",parse:e=>{let t=e.match(/^<\s*(.*)$/);if(t)return[{value:D(t[1])}]},stringify:e=>`< ${e.value?.[0].value}`},Qt={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"},Bt={operator:"IS NOT NULL",parse:e=>{if(/^is\s+not\s+null$/i.test(e))return[]},stringify:()=>"IS NOT NULL"};var Wt=[Pt,Ot,Dt,Ut,xt,Lt,Mt,qt,kt,Qt,Ft,$t,Bt],Eo=Wt.reduce((e,t)=>(e[t.operator]=t,e),{});function Ro(e,t){return Eo[e.operator]?.stringify(e,t)||""}function bo(e){let t=e.trim();for(let r of Wt){let o=r.parse(t);if(o)return{operator:r.operator,value:o}}}var Ht={parse:bo,stringify:Ro};var R=e=>{let t=Le[e];return r=>Le[r.currentTeamRole]>=t},Yt=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 jt=g(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=d(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}=L(t);return{data:await b.find({where:{team:{id:r}},order:{createdAt:"DESC"}})}}}),e.route({url:"/",method:"post",config:{requireRole:R("admin")},handler:async t=>{let{teamId:r,ownerId:o,...a}=f(t,gt),n=b.create({...a,allowUpdate:!!a.allowUpdate,allowInsert:!!a.allowInsert,team:{id:r},owner:{id:o}}),i=await q(F(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:m,encrypted:c}=ce.encrypt(n.dbPassword);return n.dbPassword=c,n.dbPasswordIv=m,n.dbPasswordTag=u,{data:await b.save(n)}}}),e.route({method:"put",url:"/:id",config:{requireRole:R("admin")},handler:async t=>{let{id:r}=d(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:R("admin")},handler:async(t,r)=>w.transaction(async()=>{let{id:o}=d(t);await Promise.all([U.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}=d(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(F(a,!0),a.dbType,t)).inspectSchema();await U.delete({datasource:{id:o}}),await U.insert(i.sort().map(u=>U.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}=d(t);return{data:await U.find({where:{datasource:{id:r}}})}}})});var $=require("typeorm"),Gt=g(e=>{e.route({method:"get",url:"/team/:teamId/datasources",handler:async t=>{let{teamId:r}=d(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 r=d(t),o=L(t),a=r.teamId||t.user.currentTeamId,n=Number(o.size)||20,i=Number(o.page)||0,u=o.nameFilter?.length?{name:(0,$.Raw)(p=>`LOWER(${p}) LIKE :search`,{search:`%${o.nameFilter.toLowerCase()}%`})}:void 0,m=await x.find({where:[{isPersonal:!1,team:{id:a},query:u},{isPersonal:!0,team:{id:a},query:u,user:{id:t.user.id}}],relations:{query:{dataSource:!0}},take:n+1,skip:i*n,select:{id:!0,query:{id:!0,name:!0,updatedAt:!0,dataSource:{name:!0,dbType:!0}}},order:{query:{updatedAt:"DESC"}}}),c=m.length>n;return c&&m.pop(),{data:m.map(p=>({name:p.query.name,id:p.query.id,updatedAt:p.query.updatedAt,savedQueryId:p.id,datasourceName:p.query.dataSource.name,datasourceType:p.query.dataSource.dbType})),hasMore:c}}}),e.route({method:"get",url:"/team/:teamId/count-saved-queries",handler:async t=>{let o=d(t).teamId||t.user.currentTeamId;return{data:await x.count({where:[{isPersonal:!1,team:{id:o}},{isPersonal:!0,team:{id:o},user:{id:t.user.id}}],select:{id:!0}})}}}),e.route({method:"get",url:"/team/:teamId/query",handler:async t=>{let{teamId:r}=d(t),{search:o,size:a,selectedDataSources:n}=L(t),i=o.length>3?parseInt(a)||20:8,u={};n?.length&&(u.id=(0,$.In)(n));let[m,c,E]=await Promise.all([U.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}),A.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}),x.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})]),p=[];return m.forEach(l=>{p.push({name:l.tableName,id:l.id,dataSourceName:l.datasource?.name||"--",dataSourceId:l.datasource?.id||"--",type:"table"})}),c.forEach(l=>{p.push({name:l.name,id:l.id,dataSourceName:l.dataSource?.name||"--",dataSourceId:l.dataSource?.id||"--",type:"tab"})}),E.forEach(l=>{p.push({name:l.query.name,id:l.query.id,dataSourceName:l.query.dataSource?.name||"--",dataSourceId:l.query.dataSource?.id||"--",type:"query"})}),{data:p}}}),e.route({method:"get",url:"/team/:teamId/tabs-history",handler:async t=>{let{teamId:r}=d(t),o=L(t),a=Number(o.page),n=Number(o.size),i=t.user.id,u=await A.find({where:{team:{id:r},user:{id:i},archived:o.archived?o.archived==="true":void 0},relations:{dataSource:!0},order:{updatedAt:"DESC"},take:n+1,skip:a*n}),m=!1;return u.length>n&&(u.pop(),m=!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:m}}})});var Kt=g(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=d(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:R("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:R("editor")},handler:async t=>{let{id:r}=d(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:R("editor")},handler:async t=>w.transaction(async()=>{let{id:r}=d(t);if(!(await I.delete({id:r})).affected)return{status:404,data:"Query not found"}})})});var me=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:me,MAX:me,MIN:me,COUNT:me};var de=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:de,MAX:de,MIN:de,COUNT:de};var Vt=["SUM","COUNT","AVG","MAX","MIN"],Io=["YEAR","MONTH","DAY",...Vt],No=Io.reduce((e,t)=>(e[t]=!0,e),{}),Co=Vt.reduce((e,t)=>(e[t]=!0,e),{}),pe=e=>No[e],zt=e=>Co[e],Jt=(e,t)=>e.fn&&pe(e.fn)?(t==="postgres"?V:z)[e.fn](e):e.value;var fe=e=>typeof e=="string",Xt=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=Jt({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=>fe(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 E=a?.[0],p;return fe(E?.value)&&E?.isColumn!==!0?p=`'${E?.value}'`:p=E?.value,`${i} ${o} ${p}`}};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 Xt(this.skeleton)}};var rr=require("typeorm");var Zt=e=>le(e)?"LIKE":"=",er=(e,t)=>{let r=[];for(let o of e)if(!(!o.column?.length||!o.value?.length||o.isEnabled===!1))if(o.isAdvanced){let a=Ht.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||Zt(t[o.column]),connector:"AND"})}else r.push({value:o.value?[{value:o.value}]:[],column:o.column,id:o.id,operator:Zt(t[o.column]),connector:"AND"});return r};var ye=async(e,t)=>{let{datasourceId:r,size:o=20,page:a,name:n}=t,{table:i,joins:u,groupBy:m,searchAll:c,orderBy:E}=t.opts,p=_o(t.opts.columns,t.opts.groupBy,t.opts.aggregations),l=await Te(r),N=[i],M=[];if(!l)throw new s(404,"Data source not found");let qr=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(T=>{N.push(T.table)}));let qe=vo(p,E,l.dbType);qe.length>0&&P.addOrderBy(...qe),m&&m.length>0&&m.forEach(T=>P.addGroupBy(Oo(T,l.dbType)));let Fr=await U.find({where:{tableName:(0,rr.In)(N),datasource:{id:r}}});for(let T of Fr)if(T.columns)for(let O of T.columns)M.push({column:O.name,table:T.tableName||"",full:`${T.tableName}.${O.name}`,type:O.type});let Fe=M.reduce((T,O)=>(T[O.full]=O.type,T),{});er(t.opts.filters,Fe)?.forEach(T=>{T.fn&&zt(T.fn)?P.addHaving(T):P.addWhere(T)});let ee;if(p&&p.length>0?ee=p.map(T=>Po(T,l.dbType)):ee=M.map(T=>`${T.full} as "${T.full}"`),P.selectColumns(ee),c){let T=M.filter(O=>Ue.includes(O.type)&&ee.some(we=>we.startsWith(O.full)));if(T.length>0){let O=T.map(we=>`LOWER(${we.full}) LIKE '%${c.toLowerCase()}%'`);P.addWhereRaw(`(${O.join(" OR ")})`,"AND")}}let te=await(await q(F(l,!0),l.dbType,e)).executeQuery(P.toSQL(),{type:"SELECT",allowBulkUpdate:!1}),Qe=te.rows.length>o;return Qe&&te.rows.pop(),{...te,queryHistoryId:qr.id,tables:N,allColumns:M,columns:te.columns.map(T=>({...T,type:Fe[T.full]})),hasMore:Qe}},or=async(e,t)=>{let r=await Te(t.dataSourceId);if(!r)throw new s(400,"Invalid datasource");let o=await q(F(r,!0),r.dbType,e),a=new X(r.dbType);a.setTable(t.table),a.setLimit(2);for(let[u,m]of Object.entries(t.props))a.addWhere({value:[{value:m}],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}},ar=async(e,t)=>{let r=await Te(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:m})=>typeof u=="string"?u&&u.startsWith("=")?`${m}=${u.substring(1)}`:`${m}='${u}'`:`${m}='${u}'`).join(", "),a=t.filters.map(u=>J(u,r.dbType)).join(" AND "),n=`UPDATE ${t.table} SET ${o} WHERE ${a}`;return(await q(F(r,!0),r.dbType,e)).executeQuery(n,{type:"UPDATE",allowBulkUpdate:!1})},nr=async(e,t)=>{let r=await Te(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}=Ao(t.values),n=`INSERT INTO ${t.table} (${o}) VALUES (${a})`;return(await q(F(r,!0),r.dbType,e)).executeQuery(n,{type:"INSERT",allowBulkUpdate:!1})},Ao=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}},Po=(e,t)=>{if(e.fn){if(pe(e.fn))return`${(t==="postgres"?V:z)[e.fn](e)} as "${xe(e)}"`;throw new Error("Function not allowed: "+e.fn)}return`${e.value} as "${e.value}"`},Oo=(e,t)=>{if(e.fn){if(pe(e.fn))return(t==="postgres"?V:z)[e.fn]({...e,value:tr(e.value,t)});throw new Error("Function not allowed: "+e.fn)}return tr(e.value,t)},Me=(e,t)=>t==="postgres"?`"${e}"`:t==="mysql"?`\`${e}\``:e,tr=(e,t)=>{let[r,o]=e.split(".");return Me(r,t)+"."+Me(o,t)},vo=(e,t,r)=>{if(e&&e.length>0){let o=e.reduce((a,n)=>(a.set(xe(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:Me(a.column,r)}:a)}return t},_o=(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 Te(e){return b.findOne({where:{id:e},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser","allowUpdate","allowInsert"]})}var sr=e=>{},Do=["--",";","DROP","drop"],ir=e=>{if(fe(e.value)&&e.value.startsWith("=")){let t=e.value;Do.forEach(r=>{if(t.includes(r))throw new s(400,"Invalid input value for "+e.column)})}},ur=e=>{if(!e.table)throw new s(400,"Table is required");e.values.forEach(ir)},cr=e=>{if(!e.table)throw new s(400,"Table is required");e.values.forEach(ir)};var lr=g(e=>{e.route({method:"post",url:"/:dsId/select",handler:async t=>{let r=f(t,sr);return{data:await ye(t,r)}}}),e.route({method:"get",url:"/:dsId/entity/:table",handler:async t=>{let{dsId:r,table:o}=d(t),a=L(t);return{data:await or(t,{table:o,dataSourceId:r,props:a})}}}),e.route({method:"post",url:"/:dsId/insert",config:{requireRole:R("editor")},handler:async t=>{let r=f(t,ur);return{data:await nr(t,r)}}}),e.route({method:"post",url:"/:dsId/update",config:{requireRole:R("editor")},handler:async t=>{let r=f(t,cr);return{data:await ar(t,r)}}})});var mr=g(e=>{e.get("/",{config:{isPublic:!0}},async()=>({data:{active:!0,version:y.str("SERVER_VERSION")}}))});var dr=g(e=>{e.route({method:"get",url:"/:id/users",handler:async t=>{let{id:r}=d(t),o=await k.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:R("editor")},handler:async t=>w.transaction(async()=>{let r=t.user.id,o=f(t),a=S.create();a.id=r;let n=k.create(o);await k.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:R("admin")},handler:async t=>{let{id:r}=d(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:R("admin")},handler:async t=>w.transaction(async()=>{let{id:r}=d(t),{userId:o}=L(t);if((await C.findOneBy({user:{id:o},team:{id:r}}))?.role==="owner")throw new s(400,"Cannot delete team owner");await S.update(o,{currentTeam:null}),await C.delete({user:{id:o},team:{id:r}}),await S.delete({id:o})})})});var ke=v(require("bcryptjs")),Z=async e=>{let t=await ke.default.genSalt(10);return ke.default.hash(e,t)};var pr=g(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=await S.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 Z(o.password)),!(await S.update(r,o)).affected)throw new s(404,"User not found");let n=await S.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:R("admin")},handler:async t=>w.transaction(async()=>{let r=f(t),o=await Z(r.password),a=await S.save(S.create({username:r.username,password:o})),n=await C.save(C.create({role:"read_only",team:{id:r.teamId},user:{id:a.id}}));await S.update(a.id,{currentTeam:{id:n.id}})})})});var fr=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}=f(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 yr=g(e=>{e.route({method:"post",url:"/",config:{requireRole:R("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 x.save(x.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:R("editor")},handler:async t=>{let{id:r}=d(t);if(!(await x.delete({id:r})).affected)return{status:404,data:"Query not found"}}}),e.route({method:"patch",url:"/:id",handler:async t=>await w.transaction(async()=>{let{id:r}=d(t),o=f(t,i=>{if(!i.name)throw new s(400,"Name is required")}),a=await x.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([x.update({id:r},{searchString:n}),I.update({id:a.query.id},{name:o.name})]),{data:!0}})})});var Tr=e=>{if(!e.queryId&&!(e.opts&&e.name))throw new s(400,"Either queryId or name and opts are required")};var gr=g(e=>{e.route({method:"get",url:"/",handler:async t=>{let{currentTeamId:r,id:o}=t.user;return{data:(await A.find({where:{team:{id:r},user:{id:o},archived:!1},select:["id","name"]})).map(n=>({name:n.name,id:n.id}))}}}),e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=d(t),{currentTeamId:o,id:a}=t.user,n=await A.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,Tr),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 A.save(A.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}=d(t),o=f(t),a=await A.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&&A.update(r,{opts:o,searchString:Y(o,a.name),updatedAt:new Date}),{data:{result:await ye(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}=d(t),o=f(t),a=await A.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 A.update(r,{...o,searchString:n}),{data:{id:r}}}}),e.route({method:"delete",url:"/:id",handler:async t=>{let{id:r}=d(t),o=t.user.id;return await A.delete({id:r,user:{id:o}}),{data:!0}}})});var Sr=require("node:crypto");var hr=require("node:crypto"),wr={teamName:"Default Team",username:"admin"},Uo=async()=>{let e=await k.findOneBy({});return e||k.save(k.create({name:wr.teamName}))},ge=async e=>{let t=await C.findOne({where:{role:"owner"},relations:{user:!0}});if(t)return t.user;let r=await Uo(),o=await Z(e?.password||(0,hr.randomBytes)(32).toString("hex")),a=await S.save(S.create({username:e?.name||wr.username,password:o})),n=await C.save(C.create({user:a,team:r,role:"owner"}));return await S.update(a.id,{currentTeam:n}),a};var he={setupAccessToken:void 0},Er=()=>(he.setupAccessToken=(0,Sr.randomBytes)(32).toString("hex"),he.setupAccessToken),xo=e=>{if(!he.setupAccessToken)throw new s(400,"Setup already performed");if(!e||e!==he.setupAccessToken)throw new s(400,"Invalid setup access token")},B=async()=>_.skipAuth?!1:await S.count()<1,Rr=async e=>{xo(e.setupAccessToken),await ge({name:e.userName,password:e.userPassword})};var br=g(e=>{e.route({method:"get",url:"/client.config.js",handler:(t,r)=>{let o={skipAuth:_.skipAuth,modeName:_.name,usesCustomDb:je(),serverVersion:y.str("SERVER_VERSION","--")};return r.type("application/javascript").send(`window.__CLIENT_CONFIG__ = ${JSON.stringify(o)};`)}}),e.route({method:"get",url:"/",handler:async(t,r)=>await B()?r.redirect("/setup"):r.sendFile("index.html")}),e.route({method:"get",url:"/setup",handler:async(t,r)=>await B()?r.sendFile("setup.html"):r.redirect("/")})});var Ir=e=>{if(!e.setupAccessToken)throw new s(400,"Invalid setup access token");if(!e.userPassword||e.userPassword.length<8)throw new s(400,"Password should be at least 8 chars long");if(!e.userName)throw new s(400,"User name is required")};var Nr=g(e=>{e.route({method:"post",url:"/",config:{isPublic:!0},handler:async t=>{if(!await B())throw new s(400,"Setup has already been completed");let o=f(t,Ir);return await Rr(o),{data:!0}}})});var Lo=[[br,"/"],[Tt,"/api/auth"],[jt,"/api/data-sources"],[Gt,"/api/project"],[Kt,"/api/queries"],[lr,"/api/runner"],[mr,"/api/status"],[dr,"/api/teams"],[pr,"/api/users"],[fr,"/api/user-settings"],[yr,"/api/saved-queries"],[gr,"/api/workbench-tabs"],[Nr,"/api/setup"]],Cr=e=>{for(let[t,r]of Lo)e.register(t,{prefix:r}),console.log("Registered "+r)};var Mo=e=>e.routeOptions.config.isPublic?!0:!e.url.startsWith("/api/"),ko=async()=>C.findOne({where:{role:"owner"},relations:{user:!0,team:!0}}),qo=async e=>{let t=await ko();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}},Fo=async e=>{let t=e.headers.authorization;if(!t)throw new s(401,"Missing auth token");let[r,o]=t.split(" "),{userId:a}=await dt(o),n=await S.findOne({where:{id:a},select:{id:!0,currentTeam:{role:!0,team:{id:!0}}},relations:{currentTeam:{team:!0}}});if(!n)throw new s(401,"Unauthorized");e.user={id:a,currentTeamId:n.currentTeam.team.id,currentTeamRole:n.currentTeam.role}},Ar=async e=>{Mo(e)||(_.skipAuth?await qo(e):await Fo(e))};var Pr=(e,t)=>{e.__connections&&e.__connections.forEach(r=>{r.close()})};var Or=e=>{e.addHook("onRequest",Ar),e.addHook("onRequest",Yt),e.addHook("onResponse",Pr)};var vr=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 _r=v(require("@fastify/cookie")),Dr=v(require("@fastify/cors"));var Ur=v(require("@fastify/static")),xr=require("node:path"),Lr=e=>{e.register(_r.default,{}),e.register(Dr.default,{origin:j.allowedOrigins,methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"],credentials:!0}),e.register(Ur.default,{root:(0,xr.join)(__dirname,"web")})};(async function(){let t=(0,Mr.default)({querystringParser:o=>kr.default.parse(o)});if(Ye(),Lr(t),Or(t),Cr(t),vr(t),await t.after(),await nt(),t.listen({port:j.port,host:j.host},(o,a)=>{o&&(console.error(o),process.exit(1)),console.log(`Server listening at ${a}`)}),await B()){let o=Er();console.log(`Setup access token:
|
|
58
|
+
${o}`),console.log("Use the above token to finish the setup process when opening the app for the first time.")}else await ge()})();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import"https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap";@import"https://fonts.googleapis.com/css2?family=Comfortaa:wght@300..700&display=swap";@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-800:oklch(44.4% .177 26.899);--color-yellow-50:oklch(98.7% .026 102.212);--color-yellow-200:oklch(94.5% .129 101.54);--color-yellow-800:oklch(47.6% .114 61.907);--color-green-50:oklch(98.2% .018 155.826);--color-green-200:oklch(92.5% .084 155.995);--color-green-800:oklch(44.8% .119 151.328);--color-blue-50:oklch(97% .014 254.604);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-800:oklch(42.4% .199 265.638);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--font-weight-semibold:600;--radius-md:.375rem;--radius-lg:.5rem;--animate-spin:spin 1s linear infinite;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{._pointer-events-none_1ilh6_2{pointer-events:none}._visible_1ilh6_2{visibility:visible}._sr-only_1ilh6_2{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}._relative_1ilh6_2{position:relative}._sticky_1ilh6_2{position:sticky}._top-0_1ilh6_2{top:calc(var(--spacing)*0)}._z-0_1ilh6_2{z-index:0}._z-1_1ilh6_2{z-index:1}._z-10_1ilh6_2{z-index:10}._z-100_1ilh6_2{z-index:100}._col-span-2_1ilh6_2{grid-column:span 2/span 2}._m-2_1ilh6_2{margin:calc(var(--spacing)*2)}._mx-2_1ilh6_2{margin-inline:calc(var(--spacing)*2)}._mx-auto_1ilh6_2{margin-inline:auto}._my-2_1ilh6_2{margin-block:calc(var(--spacing)*2)}._my-10_1ilh6_2{margin-block:calc(var(--spacing)*10)}._mt-1_1ilh6_2{margin-top:calc(var(--spacing)*1)}._mt-2_1ilh6_2{margin-top:calc(var(--spacing)*2)}._mt-4_1ilh6_2{margin-top:calc(var(--spacing)*4)}._mt-8_1ilh6_2{margin-top:calc(var(--spacing)*8)}._mt-10_1ilh6_2{margin-top:calc(var(--spacing)*10)}._mr-2_1ilh6_2{margin-right:calc(var(--spacing)*2)}._mb-1_1ilh6_2{margin-bottom:calc(var(--spacing)*1)}._mb-2_1ilh6_2{margin-bottom:calc(var(--spacing)*2)}._mb-4_1ilh6_2{margin-bottom:calc(var(--spacing)*4)}._mb-10_1ilh6_2{margin-bottom:calc(var(--spacing)*10)}._block_1ilh6_2{display:block}._flex_1ilh6_2{display:flex}._grid_1ilh6_2{display:grid}._hidden_1ilh6_2{display:none}._table_1ilh6_2{display:table}._h-0\.5_1ilh6_2{height:calc(var(--spacing)*.5)}._h-1_1ilh6_2{height:calc(var(--spacing)*1)}._h-8_1ilh6_2{height:calc(var(--spacing)*8)}._h-screen_1ilh6_2{height:100vh}._max-h-full_1ilh6_2{max-height:100%}._max-h-screen_1ilh6_2{max-height:100vh}._min-h-screen_1ilh6_2{min-height:100vh}._w-8_1ilh6_2{width:calc(var(--spacing)*8)}._w-full_1ilh6_2{width:100%}._max-w-none_1ilh6_2{max-width:none}._max-w-xl_1ilh6_2{max-width:var(--container-xl)}._min-w-md_1ilh6_2{min-width:var(--container-md)}._flex-1_1ilh6_2{flex:1}._rotate-180_1ilh6_2{rotate:180deg}._transform_1ilh6_2{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}._animate-spin_1ilh6_2{animation:var(--animate-spin)}._cursor-pointer_1ilh6_2{cursor:pointer}._grid-cols-2_1ilh6_2{grid-template-columns:repeat(2,minmax(0,1fr))}._grid-cols-4_1ilh6_2{grid-template-columns:repeat(4,minmax(0,1fr))}._flex-col_1ilh6_2{flex-direction:column}._items-center_1ilh6_2{align-items:center}._justify-between_1ilh6_2{justify-content:space-between}._justify-center_1ilh6_2{justify-content:center}._justify-end_1ilh6_2{justify-content:flex-end}._gap-1_1ilh6_2{gap:calc(var(--spacing)*1)}._gap-2_1ilh6_2{gap:calc(var(--spacing)*2)}._gap-8_1ilh6_2{gap:calc(var(--spacing)*8)}._justify-self-center_1ilh6_2{justify-self:center}._justify-self-end_1ilh6_2{justify-self:flex-end}._truncate_1ilh6_2{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._overflow-auto_1ilh6_2{overflow:auto}._overflow-hidden_1ilh6_2{overflow:hidden}._overflow-x-auto_1ilh6_2{overflow-x:auto}._overflow-y-auto_1ilh6_2{overflow-y:auto}._rounded_1ilh6_2{border-radius:.25rem}._rounded-lg_1ilh6_2{border-radius:var(--radius-lg)}._rounded-md_1ilh6_2{border-radius:var(--radius-md)}._rounded-t-md_1ilh6_2{border-top-left-radius:var(--radius-md);border-top-right-radius:var(--radius-md)}._rounded-b-lg_1ilh6_2{border-bottom-right-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg)}._rounded-b-md_1ilh6_2{border-bottom-right-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}._border_1ilh6_2{border-style:var(--tw-border-style);border-width:1px}._border-y_1ilh6_2{border-block-style:var(--tw-border-style);border-block-width:1px}._border-t_1ilh6_2{border-top-style:var(--tw-border-style);border-top-width:1px}._border-b_1ilh6_2{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}._border-blue-500_1ilh6_2{border-color:var(--color-blue-500)}._border-gray-200_1ilh6_2{border-color:var(--color-gray-200)}._border-t-gray-200_1ilh6_2{border-top-color:var(--color-gray-200)}._bg-\(--bg\)_1ilh6_2{background-color:var(--bg)}._bg-gray-50_1ilh6_2{background-color:var(--color-gray-50)}._bg-gray-100_1ilh6_2{background-color:var(--color-gray-100)}._bg-gray-800_1ilh6_2{background-color:var(--color-gray-800)}._bg-gray-900_1ilh6_2{background-color:var(--color-gray-900)}._bg-green-200_1ilh6_2{background-color:var(--color-green-200)}._bg-white_1ilh6_2{background-color:var(--color-white)}._bg-white\!_1ilh6_2{background-color:var(--color-white)!important}._bg-yellow-200_1ilh6_2{background-color:var(--color-yellow-200)}._fill-blue-600_1ilh6_2{fill:var(--color-blue-600)}._p-0\.5_1ilh6_2{padding:calc(var(--spacing)*.5)}._p-1_1ilh6_2{padding:calc(var(--spacing)*1)}._p-2_1ilh6_2{padding:calc(var(--spacing)*2)}._p-4_1ilh6_2{padding:calc(var(--spacing)*4)}._px-1\.5_1ilh6_2{padding-inline:calc(var(--spacing)*1.5)}._px-2_1ilh6_2{padding-inline:calc(var(--spacing)*2)}._px-4_1ilh6_2{padding-inline:calc(var(--spacing)*4)}._py-0\.5_1ilh6_2{padding-block:calc(var(--spacing)*.5)}._py-1_1ilh6_2{padding-block:calc(var(--spacing)*1)}._py-2_1ilh6_2{padding-block:calc(var(--spacing)*2)}._py-4_1ilh6_2{padding-block:calc(var(--spacing)*4)}._py-10_1ilh6_2{padding-block:calc(var(--spacing)*10)}._pb-24_1ilh6_2{padding-bottom:calc(var(--spacing)*24)}._pl-5\!_1ilh6_2{padding-left:calc(var(--spacing)*5)!important}._text-center_1ilh6_2{text-align:center}._text-left_1ilh6_2{text-align:left}._font-mono_1ilh6_2{font-family:var(--font-mono)}._text-3xl_1ilh6_2{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}._text-lg_1ilh6_2{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}._text-sm_1ilh6_2{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}._text-xl_1ilh6_2{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}._text-xs_1ilh6_2{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}._text-xs\!_1ilh6_2{font-size:var(--text-xs)!important;line-height:var(--tw-leading,var(--text-xs--line-height))!important}._font-semibold_1ilh6_2{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}._whitespace-nowrap_1ilh6_2{white-space:nowrap}._text-\(--text-color-primary\)_1ilh6_2{color:var(--text-color-primary)}._text-\(--text-color-secondary\)_1ilh6_2{color:var(--text-color-secondary)}._text-black\/30_1ilh6_2{color:#0000004d}@supports (color:color-mix(in lab,red,red)){._text-black\/30_1ilh6_2{color:color-mix(in oklab,var(--color-black)30%,transparent)}}._text-blue-600_1ilh6_2{color:var(--color-blue-600)}._text-blue-800_1ilh6_2{color:var(--color-blue-800)}._text-gray-100_1ilh6_2{color:var(--color-gray-100)}._text-gray-200_1ilh6_2{color:var(--color-gray-200)}._text-gray-300_1ilh6_2{color:var(--color-gray-300)}._text-gray-600_1ilh6_2{color:var(--color-gray-600)}._text-gray-800_1ilh6_2{color:var(--color-gray-800)}._text-green-800_1ilh6_2{color:var(--color-green-800)}._text-red-500_1ilh6_2{color:var(--color-red-500)}._text-red-600_1ilh6_2{color:var(--color-red-600)}._text-white_1ilh6_2{color:var(--color-white)}._text-yellow-800_1ilh6_2{color:var(--color-yellow-800)}._capitalize_1ilh6_2{text-transform:capitalize}._italic_1ilh6_2{font-style:italic}._underline_1ilh6_2{text-decoration-line:underline}._opacity-30_1ilh6_2{opacity:.3}._opacity-40_1ilh6_2{opacity:.4}._shadow-md_1ilh6_2{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}._blur_1ilh6_2{--tw-blur:blur(8px);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}._filter_1ilh6_2{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}@media(hover:hover){._hover\:bg-gray-100_1ilh6_2:hover{background-color:var(--color-gray-100)}._hover\:bg-gray-600_1ilh6_2:hover{background-color:var(--color-gray-600)}}@media(min-width:48rem){._md\:grid_1ilh6_2{display:grid}._md\:w-2xl_1ilh6_2{width:var(--container-2xl)}._md\:grid-cols-3_1ilh6_2{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:64rem){._lg\:w-lg_1ilh6_2{width:var(--container-lg)}._lg\:w-sm_1ilh6_2{width:var(--container-sm)}._lg\:flex-row_1ilh6_2{flex-direction:row}._lg\:items-center_1ilh6_2{align-items:center}._lg\:pb-12_1ilh6_2{padding-bottom:calc(var(--spacing)*12)}}@media(prefers-color-scheme:dark){._dark\:text-gray-600_1ilh6_2{color:var(--color-gray-600)}}}._alert_1ilh6_2{padding:calc(var(--spacing)*4);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}._info_1ilh6_2{background-color:var(--color-blue-50);color:var(--color-blue-800)}._danger_1ilh6_2{background-color:var(--color-red-50);color:var(--color-red-800)}._success_1ilh6_2{background-color:var(--color-green-50);color:var(--color-green-800)}._warning_1ilh6_2{background-color:var(--color-yellow-50);color:var(--color-yellow-800)}._dark_1ilh6_2{background-color:var(--color-gray-50);color:var(--color-gray-800)}@keyframes _spin_1ilh6_1{to{transform:rotate(360deg)}}@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-yellow-200:oklch(94.5% .129 101.54);--color-yellow-800:oklch(47.6% .114 61.907);--color-green-200:oklch(92.5% .084 155.995);--color-green-800:oklch(44.8% .119 151.328);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--font-weight-semibold:600;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--animate-spin:spin 1s linear infinite;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--bg:#fff;--bg-sec:#f9f9f9;--bg-ter:#f2f2f2;--bg-quat:#e9e9e9;--text-color-primary:#212121;--text-color-secondary:#6b6b6b}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components{.hotkey{cursor:pointer;border-radius:var(--radius-sm);text-align:center;min-width:26px;max-width:26px;min-height:22px;max-height:22px;font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);justify-content:center;align-items:center;display:none}@media(min-width:64rem){.hotkey{display:flex}}.hotkey.secondary{border:1px solid var(--bg-ter);background-color:var(--bg)}.hotkey:not(.secondary){border:1px solid var(--bg-ter);background-color:var(--bg-sec)}.comfortaa{font-family:Comfortaa,sans-serif}}@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.relative{position:relative}.sticky{position:sticky}.top-0{top:calc(var(--spacing)*0)}.z-0{z-index:0}.z-1{z-index:1}.z-10{z-index:10}.z-100{z-index:100}.col-span-2{grid-column:span 2/span 2}.m-2{margin:calc(var(--spacing)*2)}.mx-2{margin-inline:calc(var(--spacing)*2)}.mx-auto{margin-inline:auto}.my-2{margin-block:calc(var(--spacing)*2)}.my-10{margin-block:calc(var(--spacing)*10)}.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-lead);margin-top:1.2em;margin-bottom:1.2em;font-size:1.25em;line-height:1.6}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-links);font-weight:500;text-decoration:underline}.prose :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:decimal}.prose :where(ol[type=A]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=A s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=I s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:disc}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-counters);font-weight:400}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.25em;font-weight:600}.prose :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-quotes);border-inline-start-width:.25rem;border-inline-start-color:var(--tw-prose-quote-borders);quotes:"“""”""‘""’";margin-top:1.6em;margin-bottom:1.6em;padding-inline-start:1em;font-style:italic;font-weight:500}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:0;margin-bottom:.888889em;font-size:2.25em;font-weight:800;line-height:1.11111}.prose :where(h1 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:900}.prose :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:2em;margin-bottom:1em;font-size:1.5em;font-weight:700;line-height:1.33333}.prose :where(h2 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:800}.prose :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.6em;margin-bottom:.6em;font-size:1.25em;font-weight:600;line-height:1.6}.prose :where(h3 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.5em;margin-bottom:.5em;font-weight:600;line-height:1.5}.prose :where(h4 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em;display:block}.prose :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-kbd);box-shadow:0 0 0 1px var(--tw-prose-kbd-shadows),0 3px 0 var(--tw-prose-kbd-shadows);padding-top:.1875em;padding-inline-end:.375em;padding-bottom:.1875em;border-radius:.3125rem;padding-inline-start:.375em;font-family:inherit;font-size:.875em;font-weight:500}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code);font-size:.875em;font-weight:600}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:"`"}.prose :where(a code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h1 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.9em}.prose :where(h4 code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);padding-top:.857143em;padding-inline-end:1.14286em;padding-bottom:.857143em;border-radius:.375rem;margin-top:1.71429em;margin-bottom:1.71429em;padding-inline-start:1.14286em;font-size:.875em;font-weight:400;line-height:1.71429;overflow-x:auto}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit;background-color:#0000;border-width:0;border-radius:0;padding:0}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:none}.prose :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){table-layout:auto;width:100%;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.71429}.prose :where(thead):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);vertical-align:bottom;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em;font-weight:600}.prose :where(tbody tr):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~=not-prose],[class~=not-prose] *)){border-top-width:1px;border-top-color:var(--tw-prose-th-borders)}.prose :where(tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:top}.prose :where(th,td):not(:where([class~=not-prose],[class~=not-prose] *)){text-align:start}.prose :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-captions);margin-top:.857143em;font-size:.875em;line-height:1.42857}.prose{--tw-prose-body:oklch(37.3% .034 259.733);--tw-prose-headings:oklch(21% .034 264.665);--tw-prose-lead:oklch(44.6% .03 256.802);--tw-prose-links:oklch(21% .034 264.665);--tw-prose-bold:oklch(21% .034 264.665);--tw-prose-counters:oklch(55.1% .027 264.364);--tw-prose-bullets:oklch(87.2% .01 258.338);--tw-prose-hr:oklch(92.8% .006 264.531);--tw-prose-quotes:oklch(21% .034 264.665);--tw-prose-quote-borders:oklch(92.8% .006 264.531);--tw-prose-captions:oklch(55.1% .027 264.364);--tw-prose-kbd:oklch(21% .034 264.665);--tw-prose-kbd-shadows:oklab(21% -.00316127 -.0338527/.1);--tw-prose-code:oklch(21% .034 264.665);--tw-prose-pre-code:oklch(92.8% .006 264.531);--tw-prose-pre-bg:oklch(27.8% .033 256.848);--tw-prose-th-borders:oklch(87.2% .01 258.338);--tw-prose-td-borders:oklch(92.8% .006 264.531);--tw-prose-invert-body:oklch(87.2% .01 258.338);--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:oklch(70.7% .022 261.325);--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:oklch(70.7% .022 261.325);--tw-prose-invert-bullets:oklch(44.6% .03 256.802);--tw-prose-invert-hr:oklch(37.3% .034 259.733);--tw-prose-invert-quotes:oklch(96.7% .003 264.542);--tw-prose-invert-quote-borders:oklch(37.3% .034 259.733);--tw-prose-invert-captions:oklch(70.7% .022 261.325);--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:#ffffff1a;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:oklch(87.2% .01 258.338);--tw-prose-invert-pre-bg:#00000080;--tw-prose-invert-th-borders:oklch(44.6% .03 256.802);--tw-prose-invert-td-borders:oklch(37.3% .034 259.733);font-size:1rem;line-height:1.75}.prose :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.375em}.prose :where(.prose>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(.prose>ul>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ul>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(.prose>ol>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ol>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-inline-start:1.625em}.prose :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.571429em;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(.prose>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(.prose>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-8{margin-top:calc(var(--spacing)*8)}.mt-10{margin-top:calc(var(--spacing)*10)}.mr-2{margin-right:calc(var(--spacing)*2)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-10{margin-bottom:calc(var(--spacing)*10)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.table{display:table}.h-0\.5{height:calc(var(--spacing)*.5)}.h-1{height:calc(var(--spacing)*1)}.h-8{height:calc(var(--spacing)*8)}.h-screen{height:100vh}.max-h-full{max-height:100%}.max-h-screen{max-height:100vh}.min-h-screen{min-height:100vh}.w-8{width:calc(var(--spacing)*8)}.w-full{width:100%}.max-w-none{max-width:none}.max-w-xl{max-width:var(--container-xl)}.min-w-md{min-width:var(--container-md)}.flex-1{flex:1}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-8{gap:calc(var(--spacing)*8)}.justify-self-center{justify-self:center}.justify-self-end{justify-self:flex-end}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-t-md{border-top-left-radius:var(--radius-md);border-top-right-radius:var(--radius-md)}.rounded-b-lg{border-bottom-right-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg)}.rounded-b-md{border-bottom-right-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-y{border-block-style:var(--tw-border-style);border-block-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-blue-500{border-color:var(--color-blue-500)}.border-gray-200{border-color:var(--color-gray-200)}.border-t-gray-200{border-top-color:var(--color-gray-200)}.bg-\(--bg\){background-color:var(--bg)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-800{background-color:var(--color-gray-800)}.bg-gray-900{background-color:var(--color-gray-900)}.bg-green-200{background-color:var(--color-green-200)}.bg-white{background-color:var(--color-white)}.bg-white\!{background-color:var(--color-white)!important}.bg-yellow-200{background-color:var(--color-yellow-200)}.fill-blue-600{fill:var(--color-blue-600)}.p-0\.5{padding:calc(var(--spacing)*.5)}.p-1{padding:calc(var(--spacing)*1)}.p-2{padding:calc(var(--spacing)*2)}.p-4{padding:calc(var(--spacing)*4)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-4{padding-inline:calc(var(--spacing)*4)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-2{padding-block:calc(var(--spacing)*2)}.py-4{padding-block:calc(var(--spacing)*4)}.py-10{padding-block:calc(var(--spacing)*10)}.pb-24{padding-bottom:calc(var(--spacing)*24)}.pl-5\!{padding-left:calc(var(--spacing)*5)!important}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-xs\!{font-size:var(--text-xs)!important;line-height:var(--tw-leading,var(--text-xs--line-height))!important}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.whitespace-nowrap{white-space:nowrap}.text-\(--text-color-primary\){color:var(--text-color-primary)}.text-\(--text-color-secondary\){color:var(--text-color-secondary)}.text-black\/30{color:#0000004d}@supports (color:color-mix(in lab,red,red)){.text-black\/30{color:color-mix(in oklab,var(--color-black)30%,transparent)}}.text-blue-600{color:var(--color-blue-600)}.text-blue-800{color:var(--color-blue-800)}.text-gray-100{color:var(--color-gray-100)}.text-gray-200{color:var(--color-gray-200)}.text-gray-300{color:var(--color-gray-300)}.text-gray-600{color:var(--color-gray-600)}.text-gray-800{color:var(--color-gray-800)}.text-green-800{color:var(--color-green-800)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-white{color:var(--color-white)}.text-yellow-800{color:var(--color-yellow-800)}.capitalize{text-transform:capitalize}.italic{font-style:italic}.underline{text-decoration-line:underline}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}@media(hover:hover){.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-gray-600:hover{background-color:var(--color-gray-600)}}@media(min-width:48rem){.md\:grid{display:grid}.md\:w-2xl{width:var(--container-2xl)}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:64rem){.lg\:w-lg{width:var(--container-lg)}.lg\:w-sm{width:var(--container-sm)}.lg\:flex-row{flex-direction:row}.lg\:items-center{align-items:center}.lg\:pb-12{padding-bottom:calc(var(--spacing)*12)}}@media(prefers-color-scheme:dark){.dark\:text-gray-600{color:var(--color-gray-600)}}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}.scrollbar::-webkit-scrollbar{border-radius:10pt;width:5px}.scrollbar::-webkit-scrollbar-track{background-color:var(--color-gray-100);border-radius:10px}.scrollbar::-webkit-scrollbar-thumb{background-color:var(--color-gray-300);border-radius:10px}.scrollbar::-webkit-scrollbar-thumb:hover{background-color:var(--color-gray-400)}}.page-container{max-width:100%;padding:calc(var(--spacing)*4)}.page-content{width:100%;max-width:1024px;padding-bottom:calc(var(--spacing)*12);flex-direction:column;margin-left:auto;margin-right:auto;display:flex}@media(min-width:48rem){.page-content{padding-bottom:calc(var(--spacing)*0)}}.hr-slide{cursor:col-resize;-webkit-user-select:none;user-select:none;z-index:1;width:8px;height:100%;position:absolute;right:-4px}@media(hover:hover){.hr-slide:hover{background-color:var(--color-blue-200)}}.hl-slide{cursor:col-resize;-webkit-user-select:none;user-select:none;z-index:1;width:8px;height:100%;position:absolute;left:-4px}@media(hover:hover){.hl-slide:hover{background-color:var(--color-blue-200)}}.vb-slide{cursor:row-resize;-webkit-user-select:none;user-select:none;z-index:1;width:100%;height:8px;position:absolute;bottom:-4px}@media(hover:hover){.vb-slide:hover{background-color:var(--color-blue-200)}}.vt-slide{cursor:row-resize;-webkit-user-select:none;user-select:none;z-index:1;width:100%;height:8px;position:absolute;top:-4px}@media(hover:hover){.vt-slide:hover{background-color:var(--color-blue-200)}}.input{border:1px solid var(--bg-quat);border-radius:var(--radius-lg);background-color:var(--bg-sec);padding:calc(var(--spacing)*1);outline-style:var(--tw-outline-style);outline-width:0}.input:focus{border-color:var(--color-blue-400)}.input:disabled{cursor:not-allowed;background-color:var(--bg-ter)}.form{gap:calc(var(--spacing)*2);background-color:var(--color-white);flex-direction:column;display:flex}.form.shadow{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.form.padding{padding:calc(var(--spacing)*4)}.button{cursor:pointer;padding-inline:calc(var(--spacing)*2);padding-block:calc(var(--spacing)*.5);--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold);border-radius:8px}.button:disabled{opacity:.6;cursor:not-allowed}.button.primary{border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-blue-600);background-color:var(--color-blue-600);color:var(--color-white)}.button.primary:hover:not(:disabled){border-color:var(--color-blue-700);background-color:var(--color-blue-700)}.button.secondary{background-color:var(--color-gray-300);color:var(--color-gray-800)}.button.tertiary{border:1px solid var(--bg-quat);background-color:var(--color-white);color:var(--color-gray-700)}.button.tertiary:hover{background-color:var(--bg-sec)}.button.floating{--animation-speed:.1s;--animation-fn:ease-in-out;border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-white);transition:border var(--animation-speed)var(--animation-fn),box-shadow var(--animation-speed)var(--animation-fn);outline:none}.button.floating:hover:not(:disabled){border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-blue-500);--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.button.danger{color:#fff;background-color:#dc3545}.button.danger:hover{background-color:#bf2e3c}.page-head{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height));--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.roboto{font-family:Roboto,sans-serif}.context-menu-container{border-radius:var(--radius-lg);border-style:var(--tw-border-style);border-width:1px;border-color:var(--color-gray-200);background-color:var(--color-white);min-width:150px;max-width:400px;max-height:400px;padding:calc(var(--spacing)*2);--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);overflow:hidden}.context-menu-item{cursor:pointer;border-radius:var(--radius-lg);text-align:left;text-overflow:ellipsis;white-space:nowrap;width:100%;padding:2px 4px;font-size:15px;display:block;overflow:hidden}@media(hover:hover){.context-menu-item:hover{background-color:var(--color-gray-100)}}.a{color:var(--color-blue-400);text-decoration-line:underline}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@keyframes spin{to{transform:rotate(360deg)}}
|