@dataramen/cli 0.0.73 → 0.0.98-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/code/migrations/1754425464078-InitialMigration.js +1 -1
- package/dist/code/migrations/1755358316764-usersManagement.js +1 -1
- package/dist/code/migrations/1758316062697-queriesHistory.js +1 -1
- package/dist/code/migrations/1760816916693-workbenchTabs.js +1 -1
- package/dist/code/migrations/1762376647080-link-tab-to-datasource.js +1 -1
- package/dist/code/migrations/1769858483453-refactor-inspection-schema.js +1 -0
- package/dist/code/server.js +8 -8
- package/dist/code/web/assets/{index-CTun7vf0.js → index-BNd44o4r.js} +1 -1
- package/dist/code/web/assets/index-C8sgzTqd.css +1 -0
- package/dist/code/web/assets/main-D8VRxhVd.css +1 -0
- package/dist/code/web/assets/main-fuXA9XXi.js +4 -0
- package/dist/code/web/assets/{setup-BSiuM7Qi.js → setup-CWeNdYDy.js} +1 -1
- package/dist/code/web/index.html +4 -4
- package/dist/code/web/setup.html +3 -3
- package/dist/package.json +1 -1
- package/package.json +1 -1
- package/dist/code/web/assets/index-DKw3bdNh.css +0 -1
- package/dist/code/web/assets/main-D_i-Ns_a.js +0 -4
- package/dist/code/web/assets/main-dVK02n3V.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var u=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var
|
|
1
|
+
"use strict";var u=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var b=(t,e)=>{for(var l in e)u(t,l,{get:e[l],enumerable:!0})},p=(t,e,l,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let m of c(e))!T.call(t,m)&&m!==l&&u(t,m,{get:()=>e[m],enumerable:!(o=i(e,m))||o.enumerable});return t};var N=t=>p(u({},"__esModule",{value:!0}),t);var f={};b(f,{InitialMigration1754425464078:()=>d});module.exports=N(f);var a=require("typeorm");var s=process.env.APP_DB_TYPE==="sqlite"?"datetime":"timestamp";var n=(t={})=>{let e=process.env.APP_DB_TYPE==="mysql";return{name:"id",type:e?"char":"uuid",length:e?"36":void 0,isPrimary:!0,...t}},r=(t,e={})=>{let l=process.env.APP_DB_TYPE==="mysql";return{name:t,type:l?"char":"uuid",length:l?"36":void 0,...e}};var d=class{name="InitialMigration1754425464078";async up(e){await e.createTable(new a.Table({name:"teams",columns:[n(),{name:"name",type:"varchar",isNullable:!1},{name:"createdAt",type:s,default:"CURRENT_TIMESTAMP"},{name:"updatedAt",type:s,default:"CURRENT_TIMESTAMP"}]})),await e.createTable(new a.Table({name:"users",columns:[n(),{name:"createdAt",type:s,default:"CURRENT_TIMESTAMP"},{name:"updatedAt",type:s,default:"CURRENT_TIMESTAMP"},r("currentTeamId",{isNullable:!0})]})),await e.createTable(new a.Table({name:"users_to_teams",columns:[n(),{name:"role",type:"varchar",isNullable:!1,default:"'admin'"},r("teamId",{isNullable:!0}),r("userId",{isNullable:!0})]})),await e.createTable(new a.Table({name:"user_settings",columns:[n(),{name:"createdAt",type:s,default:"CURRENT_TIMESTAMP"},{name:"updatedAt",type:s,default:"CURRENT_TIMESTAMP"},r("userId",{isUnique:!0})]})),await e.createTable(new a.Table({name:"data_sources",columns:[n(),{name:"dbUrl",type:"varchar"},{name:"dbPort",type:"int",isNullable:!0},{name:"dbUser",type:"varchar"},{name:"dbPassword",type:"varchar",isNullable:!0},{name:"dbPasswordIv",type:"varchar",isNullable:!0},{name:"dbPasswordTag",type:"varchar",isNullable:!0},{name:"dbType",type:"varchar"},{name:"createdAt",type:s,default:"CURRENT_TIMESTAMP"},{name:"updatedAt",type:s,default:"CURRENT_TIMESTAMP"},{name:"name",type:"varchar"},{name:"description",type:"varchar",isNullable:!0},{name:"dbDatabase",type:"varchar"},{name:"dbSchema",type:"varchar",isNullable:!0},{name:"allowInsert",type:"boolean",default:!1},{name:"allowUpdate",type:"boolean",default:!1},{name:"lastInspected",type:s,isNullable:!0},{name:"status",type:"varchar",isNullable:!0},r("teamId",{isNullable:!0}),r("ownerId",{isNullable:!0})]})),await e.createTable(new a.Table({name:"query",columns:[n(),{name:"name",type:"varchar"},{name:"opts",type:"json",isNullable:!1},{name:"isTrash",type:"boolean",isNullable:!0,default:!1},{name:"createdAt",type:s,default:"CURRENT_TIMESTAMP"},{name:"updatedAt",type:s,default:"CURRENT_TIMESTAMP"},r("teamId",{isNullable:!0}),r("dataSourceId",{isNullable:!0})]})),await e.createForeignKey("users",new a.TableForeignKey({columnNames:["currentTeamId"],referencedTableName:"users_to_teams",referencedColumnNames:["id"]})),await e.createForeignKeys("users_to_teams",[new a.TableForeignKey({columnNames:["teamId"],referencedTableName:"teams",referencedColumnNames:["id"]}),new a.TableForeignKey({columnNames:["userId"],referencedTableName:"users",referencedColumnNames:["id"]})]),await e.createForeignKey("user_settings",new a.TableForeignKey({columnNames:["userId"],referencedTableName:"users",referencedColumnNames:["id"]})),await e.createForeignKeys("data_sources",[new a.TableForeignKey({columnNames:["teamId"],referencedTableName:"teams",referencedColumnNames:["id"]}),new a.TableForeignKey({columnNames:["ownerId"],referencedTableName:"users",referencedColumnNames:["id"]})]),await e.createForeignKeys("query",[new a.TableForeignKey({columnNames:["teamId"],referencedTableName:"teams",referencedColumnNames:["id"]}),new a.TableForeignKey({columnNames:["dataSourceId"],referencedTableName:"data_sources",referencedColumnNames:["id"]})])}async down(e){await e.dropTable("query",!0),await e.dropTable("data_sources",!0),await e.dropTable("user_settings",!0),await e.dropTable("users_to_teams",!0),await e.dropTable("users",!0),await e.dropTable("teams",!0)}};0&&(module.exports={InitialMigration1754425464078});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var n=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var c=(s,e)=>{for(var r in e)n(s,r,{get:e[r],enumerable:!0})},b=(s,e,r,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of l(e))!p.call(s,a)&&a!==r&&n(s,a,{get:()=>e[a],enumerable:!(i=m(e,a))||i.enumerable});return s};var d=s=>b(n({},"__esModule",{value:!0}),s);var T={};c(T,{UsersManagement1755358316764:()=>u});module.exports=d(T);var o=require("typeorm");var _=process.env.APP_DB_TYPE==="sqlite"?"datetime":"timestamp",t={WorkbenchTabs:"workbench_tabs",Teams:"teams",Users:"users",UsersToTeams:"users_to_teams",UserSettings:"user_settings",DataSources:"data_sources",Query:"query",SavedQueries:"saved_queries",DatabaseColumn:"database_columns",DatabaseTable:"database_tables"};var u=class{name="UsersManagement1755358316764";async up(e){await e.addColumns(t.Users,[new o.TableColumn({name:"username",type:"varchar",isUnique:!0}),new o.TableColumn({name:"password",type:"varchar"})])}async down(e){await e.dropColumns(t.Users,["username","password"])}};0&&(module.exports={UsersManagement1755358316764});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var t=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var N=(r,e)=>{for(var n in e)t(r,n,{get:e[n],enumerable:!0})},p=(r,e,n,d)=>{if(e&&typeof e=="object"||typeof e=="function")for(let m of T(e))!b.call(r,m)&&m!==n&&t(r,m,{get:()=>e[m],enumerable:!(d=c(e,m))||d.enumerable});return r};var f=r=>p(t({},"__esModule",{value:!0}),r);var y={};N(y,{QueriesHistory1758316062697:()=>u});module.exports=f(y);var s=require("typeorm");var o=process.env.APP_DB_TYPE==="sqlite"?"datetime":"timestamp",a={WorkbenchTabs:"workbench_tabs",Teams:"teams",Users:"users",UsersToTeams:"users_to_teams",UserSettings:"user_settings",DataSources:"data_sources",Query:"query",SavedQueries:"saved_queries",DatabaseColumn:"database_columns",DatabaseTable:"database_tables"},i=(r={})=>{let e=process.env.APP_DB_TYPE==="mysql";return{name:"id",type:e?"char":"uuid",length:e?"36":void 0,isPrimary:!0,...r}},l=(r,e={})=>{let n=process.env.APP_DB_TYPE==="mysql";return{name:r,type:n?"char":"uuid",length:n?"36":void 0,...e}};var u=class{name="QueriesHistory1758316062697";async up(e){await e.createTable(new s.Table({name:a.SavedQueries,columns:[i(),{name:"isPersonal",type:"boolean"},{name:"createdAt",type:o,default:"CURRENT_TIMESTAMP"},{name:"updatedAt",type:o,default:"CURRENT_TIMESTAMP"},l("teamId",{isNullable:!0}),l("queryId",{isNullable:!1}),l("userId",{isNullable:!1})]})),await e.createForeignKeys(a.SavedQueries,[new s.TableForeignKey({columnNames:["teamId"],referencedTableName:a.Teams,referencedColumnNames:["id"]}),new s.TableForeignKey({columnNames:["userId"],referencedTableName:a.Users,referencedColumnNames:["id"]}),new s.TableForeignKey({columnNames:["queryId"],referencedTableName:a.Query,referencedColumnNames:["id"]})]),await e.addColumns(a.Query,[new s.TableColumn(l("userId",{isNullable:!0}))]),await e.createForeignKeys(a.Query,[new s.TableForeignKey({columnNames:["userId"],referencedTableName:a.Users,referencedColumnNames:["id"]})])}async down(e){await e.dropForeignKeys(a.Query,[new s.TableForeignKey({columnNames:["userId"],referencedTableName:a.Users,referencedColumnNames:["id"]})]),await e.dropColumns(a.Query,["userId"]),await e.dropForeignKeys(a.SavedQueries,[new s.TableForeignKey({columnNames:["teamId"],referencedTableName:a.Teams,referencedColumnNames:["id"]}),new s.TableForeignKey({columnNames:["userId"],referencedTableName:a.Users,referencedColumnNames:["id"]}),new s.TableForeignKey({columnNames:["queryId"],referencedTableName:a.Query,referencedColumnNames:["id"]})]),await e.dropTable("saved_queries",!0)}};0&&(module.exports={QueriesHistory1758316062697});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var m=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var
|
|
1
|
+
"use strict";var m=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var p=(a,e)=>{for(var r in e)m(a,r,{get:e[r],enumerable:!0})},f=(a,e,r,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let l of b(e))!T.call(a,l)&&l!==r&&m(a,l,{get:()=>e[l],enumerable:!(i=d(e,l))||i.enumerable});return a};var N=a=>f(m({},"__esModule",{value:!0}),a);var y={};p(y,{WorkbenchTabs1760816916693:()=>u});module.exports=N(y);var n=require("typeorm");var o=process.env.APP_DB_TYPE==="sqlite"?"datetime":"timestamp",s={WorkbenchTabs:"workbench_tabs",Teams:"teams",Users:"users",UsersToTeams:"users_to_teams",UserSettings:"user_settings",DataSources:"data_sources",Query:"query",SavedQueries:"saved_queries",DatabaseColumn:"database_columns",DatabaseTable:"database_tables"},c=(a={})=>{let e=process.env.APP_DB_TYPE==="mysql";return{name:"id",type:e?"char":"uuid",length:e?"36":void 0,isPrimary:!0,...a}},t=(a,e={})=>{let r=process.env.APP_DB_TYPE==="mysql";return{name:a,type:r?"char":"uuid",length:r?"36":void 0,...e}};var u=class{name="WorkbenchTabs1760816916693";async up(e){await e.createTable(new n.Table({name:s.WorkbenchTabs,columns:[c(),{name:"createdAt",type:o,default:"CURRENT_TIMESTAMP"},{name:"updatedAt",type:o,default:"CURRENT_TIMESTAMP"},{name:"name",type:"varchar"},{name:"archived",type:"boolean",isNullable:!1,default:!1},{name:"opts",type:"json",isNullable:!1},t("teamId",{isNullable:!1}),t("queryId",{isNullable:!0}),t("userId",{isNullable:!1})]})),await e.createForeignKeys(s.WorkbenchTabs,[new n.TableForeignKey({columnNames:["teamId"],referencedTableName:s.Teams,referencedColumnNames:["id"]}),new n.TableForeignKey({columnNames:["userId"],referencedTableName:s.Users,referencedColumnNames:["id"]}),new n.TableForeignKey({columnNames:["queryId"],referencedTableName:s.Query,referencedColumnNames:["id"]})])}async down(e){await e.dropForeignKeys(s.WorkbenchTabs,[new n.TableForeignKey({columnNames:["teamId"],referencedTableName:s.Teams,referencedColumnNames:["id"]}),new n.TableForeignKey({columnNames:["userId"],referencedTableName:s.Users,referencedColumnNames:["id"]}),new n.TableForeignKey({columnNames:["queryId"],referencedTableName:s.Query,referencedColumnNames:["id"]})]),await e.dropTable(s.WorkbenchTabs,!0)}};0&&(module.exports={WorkbenchTabs1760816916693});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var i=Object.defineProperty;var
|
|
1
|
+
"use strict";var i=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var C=(a,e)=>{for(var o in e)i(a,o,{get:e[o],enumerable:!0})},_=(a,e,o,u)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of p(e))!T.call(a,t)&&t!==o&&i(a,t,{get:()=>e[t],enumerable:!(u=b(e,t))||u.enumerable});return a};var P=a=>_(i({},"__esModule",{value:!0}),a);var y={};C(y,{LinkTabToDatasource1762376647080:()=>l});module.exports=P(y);var r=require("typeorm");var S=process.env.APP_DB_TYPE==="sqlite"?"datetime":"timestamp",s={WorkbenchTabs:"workbench_tabs",Teams:"teams",Users:"users",UsersToTeams:"users_to_teams",UserSettings:"user_settings",DataSources:"data_sources",Query:"query",SavedQueries:"saved_queries",DatabaseColumn:"database_columns",DatabaseTable:"database_tables"};var m=(a,e={})=>{let o=process.env.APP_DB_TYPE==="mysql";return{name:a,type:o?"char":"uuid",length:o?"36":void 0,...e}};var c=new r.TableForeignKey({columnNames:["dataSourceId"],referencedTableName:s.DataSources,referencedColumnNames:["id"]}),d=new r.TableColumn(m("dataSourceId",{isNullable:!0})),n=new r.TableColumn({name:"searchString",type:"varchar",isNullable:!0}),l=class{name="LinkTabToDatasource1762376647080";async up(e){await e.addColumns(s.WorkbenchTabs,[d,n]),await e.addColumns(s.SavedQueries,[n]),await e.createForeignKeys(s.WorkbenchTabs,[c])}async down(e){await e.dropForeignKeys(s.WorkbenchTabs,[c]),await e.dropColumns(s.WorkbenchTabs,[d,n]),await e.dropColumns(s.SavedQueries,[n])}};0&&(module.exports={LinkTabToDatasource1762376647080});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var r=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var y=(a,e)=>{for(var s in e)r(a,s,{get:e[s],enumerable:!0})},C=(a,e,s,T)=>{if(e&&typeof e=="object"||typeof e=="function")for(let l of d(e))!p.call(a,l)&&l!==s&&r(a,l,{get:()=>e[l],enumerable:!(T=c(e,l))||T.enumerable});return a};var P=a=>C(r({},"__esModule",{value:!0}),a);var D={};y(D,{RefactorInspectionSchema1769858483453:()=>b});module.exports=P(D);var n=require("typeorm");var o=process.env.APP_DB_TYPE==="sqlite"?"datetime":"timestamp",t={WorkbenchTabs:"workbench_tabs",Teams:"teams",Users:"users",UsersToTeams:"users_to_teams",UserSettings:"user_settings",DataSources:"data_sources",Query:"query",SavedQueries:"saved_queries",DatabaseColumn:"database_columns",DatabaseTable:"database_tables"},m=(a={})=>{let e=process.env.APP_DB_TYPE==="mysql";return{name:"id",type:e?"char":"uuid",length:e?"36":void 0,isPrimary:!0,...a}},i=(a,e={})=>{let s=process.env.APP_DB_TYPE==="mysql";return{name:a,type:s?"char":"uuid",length:s?"36":void 0,...e}};var u=new n.TableForeignKey({columnNames:["dataSourceId"],referencedTableName:t.DataSources,referencedColumnNames:["id"]}),_=new n.TableForeignKey({columnNames:["tableId"],referencedTableName:t.DatabaseTable,referencedColumnNames:["id"]}),b=class{name="RefactorInspectionSchema1769858483453";async up(e){await e.createTable(new n.Table({name:t.DatabaseTable,columns:[m(),{name:"createdAt",type:o,default:"CURRENT_TIMESTAMP"},{name:"updatedAt",type:o,default:"CURRENT_TIMESTAMP"},{name:"name",type:"varchar"},i("dataSourceId",{isNullable:!1})]})),await e.createForeignKeys(t.DatabaseTable,[u]),await e.createTable(new n.Table({name:t.DatabaseColumn,columns:[m(),{name:"createdAt",type:o,default:"CURRENT_TIMESTAMP"},{name:"updatedAt",type:o,default:"CURRENT_TIMESTAMP"},{name:"name",type:"varchar"},{name:"type",type:"varchar"},{name:"isPrimary",type:"boolean"},{name:"meta",type:"json",isNullable:!0},i("tableId",{isNullable:!1})]})),await e.createForeignKeys(t.DatabaseColumn,[_])}async down(e){await e.dropForeignKeys(t.DatabaseColumn,[u]),await e.dropTable(t.DatabaseColumn),await e.dropForeignKeys(t.DatabaseTable,[u]),await e.dropTable(t.DatabaseTable)}};0&&(module.exports={RefactorInspectionSchema1769858483453});
|
package/dist/code/server.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"use strict";var Vr=Object.create;var Ue=Object.defineProperty;var zr=Object.getOwnPropertyDescriptor;var Jr=Object.getOwnPropertyNames;var Xr=Object.getPrototypeOf,Zr=Object.prototype.hasOwnProperty;var eo=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Jr(t))!Zr.call(e,a)&&a!==r&&Ue(e,a,{get:()=>t[a],enumerable:!(o=zr(t,a))||o.enumerable});return e};var P=(e,t,r)=>(r=e!=null?Vr(Xr(e)):{},eo(t||!e||!e.__esModule?Ue(r,"default",{value:e,enumerable:!0}):r,e));var ee=require("dotenv"),te=require("node:path"),qe=require("node:fs");var X=e=>{function t(a,n=void 0){return e[a]||n}function r(a,n=void 0){let s=e[a];if(!s)return n;let u=Number(s);return!isNaN(u)&&s.trim()!==""?u:n}function o(a){return e[a]==="true"||e[a]==="TRUE"||e[a]==="1"}return{str:t,num:r,bool:o}};function to(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 Z=X(to(process.argv.slice(2)));var ro=(()=>{try{let e=(0,qe.readFileSync)((0,te.join)(__dirname,"..","package.json"),"utf8");return JSON.parse(e)}catch{return{version:"0.0.0"}}})(),ke=[],Le=Z.str("env");Le&&ke.push((0,te.resolve)(Le));(0,ee.config)({path:ke});var fe={APP_DB_TYPE:"sqlite",APP_DB_DATABASE:"<home>/.dataramen/.runtime/db.sqlite3"};(0,ee.populate)(process.env,{SERVER_VERSION:ro.version,PROD:"true",...fe},{override:!1});var oo=["SYMM_ENCRYPTION_KEY","JWT_SECRET","JWT_REFRESH_SECRET"],Me=()=>{let e=[];for(let t of oo)process.env[t]||e.push(t);if(e.length>0)throw new Error("Following env variables are required but not provided: "+e.join(", "))},T=X(process.env),Qe=()=>T.str("APP_DB_TYPE")!==fe.APP_DB_TYPE&&T.str("APP_DB_DATABASE")!==fe.APP_DB_DATABASE;var Gc=require("reflect-metadata"),$r=P(require("fastify")),Wr=P(require("qs"));var Ve=require("typeorm");var Fe=require("typeorm");var ao={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"}},no=Z.str("mode","default"),D=ao[no];var h=T.str("APP_DB_TYPE")==="sqlite"?"datetime":"timestamp",re=D.name==="docker"?e=>e==="localhost"||e==="127.0.0.1"?"host.docker.internal":e:e=>e;var ye=new Fe.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,createDate:!0},updatedAt:{type:h,updateDate:!0}},relations:{datasource:{target:()=>"DataSource",type:"many-to-one",joinTable:!1,cascade:!0}}});var Be=require("typeorm");var Te=new Be.EntitySchema({name:"Team",tableName:"teams",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:h,createDate:!0},updatedAt:{type:h,updateDate:!0}},relations:{users:{type:"one-to-many",target:()=>"UsersToTeams",inverseSide:"team"},queries:{type:"one-to-many",target:()=>"Query",inverseSide:"team"},datasources:{type:"one-to-many",target:()=>"DataSource",inverseSide:"team"}}});var $e=require("typeorm");var ge=new $e.EntitySchema({name:"User",tableName:"users",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:h,createDate:!0},updatedAt:{type:h,updateDate:!0},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 We=require("typeorm");var he=new We.EntitySchema({name:"UserSettings",tableName:"user_settings",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:h,createDate:!0},updatedAt:{type:h,updateDate:!0}},relations:{user:{type:"one-to-one",target:()=>"User",inverseSide:"settings",joinColumn:!0}}});var He=require("typeorm");var we=new He.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,createDate:!0},updatedAt:{type:h,updateDate:!0},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 ze=P(require("node:os")),Je=require("node:path");var Ye=require("typeorm");var Se=new Ye.EntitySchema({name:"Query",tableName:"query",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},opts:{type:"json",nullable:!1},createdAt:{type:h,createDate:!0},updatedAt:{type:h,updateDate:!0}},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 Ge=require("typeorm"),be=new Ge.EntitySchema({name:"UsersToTeams",tableName:"users_to_teams",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},role:{type:"varchar",default:"admin",nullable:!1}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"users"},user:{type:"many-to-one",target:()=>"User",inverseSide:"teams"}}});var je=require("typeorm");var Ee=new je.EntitySchema({name:"SavedQuery",tableName:"saved_queries",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},isPersonal:{type:Boolean},createdAt:{type:h,createDate:!0},updatedAt:{type:h,updateDate:!0},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 Ke=require("typeorm");var Ie=new Ke.EntitySchema({name:"WorkbenchTab",tableName:"workbench_tabs",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:h,createDate:!0},updatedAt:{type:h,updateDate:!0},opts:{type:"json",nullable:!1},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 so(){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>",ze.default.homedir())),e}var w=new Ve.DataSource({type:T.str("APP_DB_TYPE"),database:so(),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:[Je.posix.join(__dirname,"migrations","*.js")],entities:[ye,we,Te,ge,be,he,Se,Ee,Ie]}),Xe=async()=>{if(!w.isInitialized)return w.initialize();throw new Error("Already initialized")},v=w.getRepository(ye),E=w.getRepository(we),k=w.getRepository(Te),S=w.getRepository(ge),N=w.getRepository(be),$=w.getRepository(he),I=w.getRepository(Se),_=w.getRepository(Ee),O=w.getRepository(Ie);var Ze=T.str("ALLOWED_ORIGINS","").split(",").map(e=>e.trim()),et=T.num("PORT",4466),G={port:et,host:D.bindServerUrl,allowedOrigins:Ze.includes("*")?"*":[`http://localhost:${et}`,...Ze]};var g=e=>(t,r,o)=>{e(t),o()};var j=require("jose");var i=class extends Error{constructor(r,o){super(o);this.status=r;this.message=o}};var tt=new TextEncoder,rt=tt.encode(T.str("JWT_SECRET")),ot=tt.encode(T.str("JWT_REFRESH_SECRET")),Re=async({userId:e})=>new j.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("1h").sign(rt),Ce=async({userId:e})=>new j.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("10d").sign(ot),at=async(e,t)=>{try{let{payload:r}=await(0,j.jwtVerify)(e,t);if(!r.sub)throw new i(401,"Failed to verify access token");return{userId:r.sub}}catch(r){throw r instanceof i?r:r instanceof Error?new i(401,r.message):new i(401,"Failed to verify refresh token")}},nt=async e=>at(e,rt),st=async e=>at(e,ot);var y=(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 ut=P(require("bcryptjs"));var it=e=>{if(!e?.username)throw new i(400,"Username is required");if(!e?.password)throw new i(400,"Password is required")};var oe="DATARAMEN_refresh_token",Ne={httpOnly:!0,secure:T.bool("PROD"),sameSite:T.bool("PROD"),path:"/",maxAge:14400*60},ct=g(e=>{e.route({method:"post",url:"/login",config:{isPublic:!0},handler:async(t,r)=>{let{username:o,password:a}=y(t,it),n=await S.findOne({where:{username:o}});if(!n||!ut.default.compareSync(a,n.password))throw new i(401,"Invalid credentials");let[s,u]=await Promise.all([Re({userId:n?.id}),Ce({userId:n?.id})]);return r.setCookie(oe,u,Ne),{data:{accessToken:s}}}}),e.route({method:"post",url:"/refresh",config:{isPublic:!0},handler:async(t,r)=>{let o=t.cookies[oe];if(!o)return r.code(401).send({message:"Missing refresh token"});let{userId:a}=await st(o),[n,s]=await Promise.all([Re({userId:a}),Ce({userId:a})]);return r.setCookie(oe,s,Ne),{data:{accessToken:n}}}}),e.route({method:"post",url:"/logout",config:{isPublic:!0},handler:async(t,r)=>(r.clearCookie(oe,Ne),{data:!0})})});var mt=e=>{if(!e.dbUrl)throw new i(400,"url is required");if(!e.dbUser)throw new i(400,"user is required");if(!e.dbType)throw new i(400,"type is required");if(!e.name)throw new i(400,"name is required");if(!e.dbDatabase)throw new i(400,"database is required")};var pt=P(require("mysql2/promise"));function K(e){if(e!==void 0)return e.toLowerCase()}var io=({database:e,password:t,user:r,url:o})=>pt.default.createConnection({host:re(o),user:r,database:e,password:t,dateStrings:!0}),uo=async e=>{let t=`
|
|
1
|
+
"use strict";var Zr=Object.create;var ke=Object.defineProperty;var eo=Object.getOwnPropertyDescriptor;var to=Object.getOwnPropertyNames;var ro=Object.getPrototypeOf,oo=Object.prototype.hasOwnProperty;var ao=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of to(t))!oo.call(e,a)&&a!==r&&ke(e,a,{get:()=>t[a],enumerable:!(o=eo(t,a))||o.enumerable});return e};var O=(e,t,r)=>(r=e!=null?Zr(ro(e)):{},ao(t||!e||!e.__esModule?ke(r,"default",{value:e,enumerable:!0}):r,e));var te=require("dotenv"),re=require("node:path"),Be=require("node:fs");var Z=e=>{function t(a,n=void 0){return e[a]||n}function r(a,n=void 0){let s=e[a];if(!s)return n;let u=Number(s);return!isNaN(u)&&s.trim()!==""?u:n}function o(a){return e[a]==="true"||e[a]==="TRUE"||e[a]==="1"}return{str:t,num:r,bool:o}};function no(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 ee=Z(no(process.argv.slice(2)));var so=(()=>{try{let e=(0,Be.readFileSync)((0,re.join)(__dirname,"..","package.json"),"utf8");return JSON.parse(e)}catch{return{version:"0.0.0"}}})(),Qe=[],Me=ee.str("env");Me&&Qe.push((0,re.resolve)(Me));(0,te.config)({path:Qe});var ye={APP_DB_TYPE:"sqlite",APP_DB_DATABASE:"<home>/.dataramen/.runtime/db.sqlite3"};(0,te.populate)(process.env,{SERVER_VERSION:so.version,PROD:"true",...ye},{override:!1});var io=["SYMM_ENCRYPTION_KEY","JWT_SECRET","JWT_REFRESH_SECRET"],Fe=()=>{let e=[];for(let t of io)process.env[t]||e.push(t);if(e.length>0)throw new Error("Following env variables are required but not provided: "+e.join(", "))},T=Z(process.env),$e=()=>T.str("APP_DB_TYPE")!==ye.APP_DB_TYPE&&T.str("APP_DB_DATABASE")!==ye.APP_DB_DATABASE;var nm=require("reflect-metadata"),Gr=O(require("fastify")),jr=O(require("qs"));var Ze=require("typeorm");var We=require("typeorm");var uo={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"}},co=ee.str("mode","default"),D=uo[co];var g=T.str("APP_DB_TYPE")==="sqlite"?"datetime":"timestamp",oe=D.name==="docker"?e=>e==="localhost"||e==="127.0.0.1"?"host.docker.internal":e:e=>e;var Te=new We.EntitySchema({name:"Team",tableName:"teams",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:g,createDate:!0},updatedAt:{type:g,updateDate:!0}},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 He=require("typeorm");var ge=new He.EntitySchema({name:"User",tableName:"users",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:g,createDate:!0},updatedAt:{type:g,updateDate:!0},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 Ye=require("typeorm");var he=new Ye.EntitySchema({name:"UserSettings",tableName:"user_settings",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:g,createDate:!0},updatedAt:{type:g,updateDate:!0}},relations:{user:{type:"one-to-one",target:()=>"User",inverseSide:"settings",joinColumn:!0}}});var Ge=require("typeorm");var we=new Ge.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,createDate:!0},updatedAt:{type:g,updateDate:!0},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},queries:{type:"one-to-many",target:()=>"Query",inverseSide:"dataSource"},owner:{type:"many-to-one",target:()=>"User",joinColumn:!0}}});var et=O(require("node:os")),tt=require("node:path");var je=require("typeorm");var Se=new je.EntitySchema({name:"Query",tableName:"query",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},opts:{type:"json",nullable:!1},createdAt:{type:g,createDate:!0},updatedAt:{type:g,updateDate:!0}},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 Ke=require("typeorm"),be=new Ke.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 Ve=require("typeorm");var Ee=new Ve.EntitySchema({name:"SavedQuery",tableName:"saved_queries",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},isPersonal:{type:Boolean},createdAt:{type:g,createDate:!0},updatedAt:{type:g,updateDate:!0},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 ze=require("typeorm");var Ie=new ze.EntitySchema({name:"WorkbenchTab",tableName:"workbench_tabs",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:g,createDate:!0},updatedAt:{type:g,updateDate:!0},opts:{type:"json",nullable:!1},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}}});var Je=require("typeorm");var Re=new Je.EntitySchema({name:"DatabaseColumn",tableName:"database_columns",columns:{id:{type:String,unique:!0,primary:!0,generated:"uuid"},name:{nullable:!0,type:String},type:{type:String},isPrimary:{type:Boolean},createdAt:{type:g,createDate:!0},updatedAt:{type:g,updateDate:!0},meta:{type:"json",nullable:!0}},relations:{table:{target:()=>"DatabaseTable",type:"many-to-one",inverseSide:"columns"}}});var Xe=require("typeorm");var Ce=new Xe.EntitySchema({name:"DatabaseTable",tableName:"database_tables",columns:{id:{type:String,unique:!0,primary:!0,generated:"uuid"},name:{nullable:!0,type:String},createdAt:{type:g,createDate:!0},updatedAt:{type:g,updateDate:!0}},relations:{datasource:{target:()=>"DataSource",type:"many-to-one"},columns:{target:()=>"DatabaseColumn",type:"one-to-many",inverseSide:"table"}}});function mo(){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>",et.default.homedir())),e}var w=new Ze.DataSource({type:T.str("APP_DB_TYPE"),database:mo(),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:[tt.posix.join(__dirname,"migrations","*.js")],entities:[we,Te,ge,be,he,Se,Ee,Ie,Ce,Re]}),rt=async()=>{if(!w.isInitialized)return w.initialize();throw new Error("Already initialized")},E=w.getRepository(we),k=w.getRepository(Te),S=w.getRepository(ge),C=w.getRepository(be),$=w.getRepository(he),I=w.getRepository(Se),v=w.getRepository(Ee),A=w.getRepository(Ie),W=w.getRepository(Re),U=w.getRepository(Ce);var ot=T.str("ALLOWED_ORIGINS","").split(",").map(e=>e.trim()),at=T.num("PORT",4466),j={port:at,host:D.bindServerUrl,allowedOrigins:ot.includes("*")?"*":[`http://localhost:${at}`,...ot]};var h=e=>(t,r,o)=>{e(t),o()};var K=require("jose");var i=class extends Error{constructor(r,o){super(o);this.status=r;this.message=o}};var nt=new TextEncoder,st=nt.encode(T.str("JWT_SECRET")),it=nt.encode(T.str("JWT_REFRESH_SECRET")),Ne=async({userId:e})=>new K.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("1h").sign(st),Ae=async({userId:e})=>new K.SignJWT({sub:e}).setProtectedHeader({alg:"HS256"}).setExpirationTime("10d").sign(it),ut=async(e,t)=>{try{let{payload:r}=await(0,K.jwtVerify)(e,t);if(!r.sub)throw new i(401,"Failed to verify access token");return{userId:r.sub}}catch(r){throw r instanceof i?r:r instanceof Error?new i(401,r.message):new i(401,"Failed to verify refresh token")}},ct=async e=>ut(e,st),mt=async e=>ut(e,it);var y=(e,t)=>{let r=e.body;return t&&t(r),r},_=(e,t)=>{let r=e.query;return t&&t(r),r},f=(e,t)=>{let r=e.params;return t&&t(r),r};var dt=O(require("bcryptjs"));var lt=e=>{if(!e?.username)throw new i(400,"Username is required");if(!e?.password)throw new i(400,"Password is required")};var ae="DATARAMEN_refresh_token",Pe={httpOnly:!0,secure:T.bool("PROD"),sameSite:T.bool("PROD"),path:"/",maxAge:14400*60},pt=h(e=>{e.route({method:"post",url:"/login",config:{isPublic:!0},handler:async(t,r)=>{let{username:o,password:a}=y(t,lt),n=await S.findOne({where:{username:o}});if(!n||!dt.default.compareSync(a,n.password))throw new i(401,"Invalid credentials");let[s,u]=await Promise.all([Ne({userId:n?.id}),Ae({userId:n?.id})]);return r.setCookie(ae,u,Pe),{data:{accessToken:s}}}}),e.route({method:"post",url:"/refresh",config:{isPublic:!0},handler:async(t,r)=>{let o=t.cookies[ae];if(!o)return r.code(401).send({message:"Missing refresh token"});let{userId:a}=await mt(o),[n,s]=await Promise.all([Ne({userId:a}),Ae({userId:a})]);return r.setCookie(ae,s,Pe),{data:{accessToken:n}}}}),e.route({method:"post",url:"/logout",config:{isPublic:!0},handler:async(t,r)=>(r.clearCookie(ae,Pe),{data:!0})})});var ft=e=>{if(!e.dbUrl)throw new i(400,"url is required");if(!e.dbUser)throw new i(400,"user is required");if(!e.dbType)throw new i(400,"type is required");if(!e.name)throw new i(400,"name is required");if(!e.dbDatabase)throw new i(400,"database is required")};var gt=O(require("mysql2/promise"));function V(e){if(e!==void 0)return e.toLowerCase()}var lo=({database:e,password:t,user:r,url:o})=>gt.default.createConnection({host:oe(o),user:r,database:e,password:t,dateStrings:!0}),po=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=V(a.TABLE_NAME),s=a.COLUMN_NAME;o[n]||(o[n]=[]),o[n].push(s)}),o},fo=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},yo=async(e,t)=>{let o=(await t.query("SHOW TABLES"))[0],a=await fo(t),n=await po(t),s=o.map(async u=>{let c=V(Object.values(u)[0]),m=`select COLUMN_NAME, DATA_TYPE from information_schema.columns where table_schema = '${e.database}' and LOWER(table_name) = '${c}'`,[d]=await t.query(m),l=a[c];return{columns:d.map(p=>({name:p.COLUMN_NAME,type:p.DATA_TYPE,isPrimary:n[c]?.includes(p.COLUMN_NAME),ref:l?.[p.COLUMN_NAME]?{table:l[p.COLUMN_NAME].refTable,field:l[p.COLUMN_NAME].refField}:void 0})),createdAt:new Date,tableName:c,updatedAt:new Date}});return Promise.all(s)},yt=async(e,t,r,o)=>{try{console.log(`[MYSQL CONN] Query: ${e}`),console.log(`[MYSQL CONN] Params: ${JSON.stringify(t)}`);let[a,n]=await r.query({sql:e,rowsAsArray:!0,values:t,timeout:1e4}),s=a?.constructor?.name;if(s==="ResultSetHeader"){let u=a;if(u.affectedRows>1&&o.allowBulkUpdate!==!0)throw new Error("[MYSQL CONN] Bulk update performed without permission.");return{columns:[{column:"affectedRows",alias:"Affected rows",full:"affectedRows"}],rows:[[u.affectedRows]],query:e}}else if(s==="Array"){let u=a;return{columns:n?.map(c=>({column:c.orgName||c.name,table:V(c.orgTable),alias:c.name,full:c.orgTable?V(c.orgTable)+"."+c.orgName:c.name}))||[],rows:u,query:e}}throw new Error(`[MYSQL CONN] Unknown result type: ${s}`)}catch(a){throw console.error(a),a instanceof i?a:new i(400,a.message)}},To=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}},go=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}},ht=async e=>{let t=await lo(e),r=!1;return{dbType:"mysql",dataSource:e,inspectSchema:()=>yo(e,t),executeQuery:o=>o.type==="SELECT"?go(t,()=>yt(o.sql,o.params,t,o)):To(t,()=>yt(o.sql,o.params,t,o)),checkConnection:async()=>t.ping(),isClosed:()=>r,close:async()=>{if(!r)return r=!0,t.destroy()}}};var St=O(require("pg"));var ho=async({database:e,password:t,user:r,url:o,port:a})=>{let n=new St.default.Client({host:oe(o),user:r,database:e,password:t,port:a,query_timeout:1e4});return await n.connect(),n},wo=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,s=a.column_name;o[n]||(o[n]=[]),o[n].push(s)}),o},
|
|
31
|
+
`),o={};return r.rows.forEach(a=>{let n=a.table_name,s=a.column_name;o[n]||(o[n]=[]),o[n].push(s)}),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},bo=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),s=await wo(t),u=a.map(async c=>{let m=Object.values(c)[0],d=`
|
|
47
47
|
SELECT column_name, data_type
|
|
48
48
|
FROM information_schema.columns
|
|
49
49
|
WHERE
|
|
50
50
|
LOWER(table_name) = '${m}' and
|
|
51
51
|
table_schema = '${e.schema}'
|
|
52
|
-
`,{rows:
|
|
52
|
+
`,{rows:l}=await t.query(d),p=n[m];return{columns:l.map(N=>({name:N.column_name,type:N.data_type,isPrimary:s[m]?.includes(N.column_name),ref:p?.[N.column_name]?{table:p[N.column_name].refTable,field:p[N.column_name].refField}:void 0})).sort((N,q)=>N.isPrimary&&q.isPrimary?N.name.localeCompare(q.name):N.isPrimary?-1:1),createdAt:new Date,tableName:m,updatedAt:new Date}});return Promise.all(u)},Eo=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),{})},yt=async(e,t,r,o)=>{try{console.log(`[PG CONN] Query: ${e}`),console.log(`[PG CONN] Params: ${JSON.stringify(t,null,2)}`);let{rows:a,fields:n,command:s,rowCount:u}=await r.query({text:e,rowMode:"array",values:t});if(s==="UPDATE"||s==="INSERT"||s==="DELETE"){if(u!=null&&u>1&&o.allowBulkUpdate!==!0)throw new Error("[PG CONN] Bulk update performed without permission.");return{columns:[{column:"affectedRows",alias:"Affected rows",full:"affectedRows"}],rows:[[u]],query:e}}if(s==="SELECT"){let c=n.map(p=>`'${p.tableID}-${p.columnID}'`),m=await ho(c,r);return{columns:n.map(p=>{let f=m[`${p.tableID}-${p.columnID}`];return{column:f?.column||p.name,alias:p.name,table:f?.table||"",full:f?f.table+"."+f.column:p.name}}),rows:a,query:e}}throw new Error(`[PG CONN] Unsupported command: ${s}`)}catch(a){throw a instanceof i?a:new i(400,a.message)}},wo=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}},So=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}},gt=async e=>{let t=await fo(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:()=>go(e,t),executeQuery:n=>a(()=>n.type==="SELECT"?So(t,()=>yt(n.sql,n.params,t,n)):wo(t,()=>yt(n.sql,n.params,t,n))),checkConnection:async()=>{},isClosed:()=>r,close:async()=>{if(!r)return r=!0,t.end()}}};var M=async(e,t,r)=>{try{let o;if(t==="mysql")o=await ft(e);else if(t==="postgres")o=await gt(e);else throw new i(500,`Connection manager for ${t} not found`);return r.__connections?r.__connections.push(o):r.__connections=[o],o}catch(o){throw console.error(o),o instanceof i?o:o?.code==="ECONNREFUSED"?new i(500,"Failed to connect to the database"):new i(500,o.message)}};var ae=P(require("node:crypto"));var ht="aes-256-gcm",bo=12,wt=()=>{let e=T.str("SYMM_ENCRYPTION_KEY");if(!e)throw new Error("Missing ENCRYPTION_KEY in environment variables.");let t=Buffer.from(e,"hex");if(t.length!==32)throw new Error("ENCRYPTION_KEY must be a 64-character hex string (256 bits).");return t},Eo=e=>{let t=ae.default.randomBytes(bo),r=wt(),o=ae.default.createCipheriv(ht,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")}},Io=({encrypted:e,iv:t,tag:r})=>{let o=wt(),a=ae.default.createDecipheriv(ht,o,Buffer.from(t,"hex"));a.setAuthTag(Buffer.from(r,"hex"));let n=a.update(e,"hex","utf8");return n+=a.final("utf8"),n},ne={encrypt:Eo,decrypt:Io};var Q=(e,t=!1)=>{if(t){let r=ne.decrypt({encrypted:e.dbPassword,tag:e.dbPasswordTag,iv:e.dbPasswordIv});return{url:e.dbUrl,user:e.dbUser,database:e.dbDatabase,password:r,port:e.dbPort,schema:e.dbSchema}}return{url:e.dbUrl,user:e.dbUser,database:e.dbDatabase,password:e.dbPassword,port:e.dbPort,schema:e.dbSchema}};var St=[{value:"=",label:"equals"},{value:"<>",label:"not equal"},{value:">",label:"greater than"},{value:">=",label:"greater than or equal"},{value:"<",label:"less than"},{value:"<=",label:"less than or equal"},{value:"LIKE",label:"like"},{value:"NOT LIKE",label:"not like"},{value:"CONTAINS",label:"contains"},{value:"NOT CONTAINS",label:"not contains"},{value:"IN",label:"in list"},{value:"NOT IN",label:"not in list"},{value:"IS NULL",label:"is null"},{value:"IS NOT NULL",label:"is not null"}],Ro=St.reduce((e,t)=>(e[t.value]=t.label,e),{}),jn=St.reduce((e,t)=>(e[t.label]=t.value,e),{}),W=e=>e.map(t=>({label:Ro[t],value:t})),Kn=W(["=","<>",">",">=","<","<=","IN","NOT IN","IS NULL","IS NOT NULL"]),Vn=W(["=","<>","LIKE","NOT LIKE","IN","NOT IN","IS NULL","IS NOT NULL","CONTAINS","NOT CONTAINS"]),zn=W(["=","<>","IS NULL","IS NOT NULL"]),Jn=W(["=","<>",">",">=","<","<=","IS NULL","IS NOT NULL"]),Xn=W(["IS NULL","IS NOT NULL"]),Zn=W(["IN","NOT IN"]),Co=["char","varchar","binary","varbinary","blob","text","enum","set","character","character varying","text","citext","uuid","xml","json","jsonb"],No=new Set(Co),se=e=>No.has(e),Oo=["integer","smallint","decimal","numeric","float","real","double precision","int","smallint","integer","bigint","decimal","numeric","real","double precision","serial","bigserial","money"],Ao=new Set(Oo),bt=e=>Ao.has(e);var es=["date","datetime","timestamp","timestamptz"].reduce((e,t)=>(e[t]=!0,e),{});var Oe={read_only:10,editor:20,admin:30,owner:40};var A=e=>e.startsWith("'")&&e.endsWith("'")||e.startsWith('"')&&e.endsWith('"')?e.slice(1,-1):e;var Et={operator:"LIKE",parse:e=>{let t=e.match(/^LIKE\s*["'](.*)["']$/i);if(t)return[{value:A(t[1])}]},stringify:e=>`LIKE "%${e[0]?.value}%"`},It={operator:"NOT LIKE",parse:e=>{let t=e.match(/^NOT LIKE\s*["'](.*)["']$/i);if(t)return[{value:A(t[1])}]},stringify:e=>`NOT LIKE "%${e[0]?.value}%"`},Rt={operator:"CONTAINS",parse:e=>{let t=e.match(/^CONTAINS\s*["'](.*)["']$/i);if(t)return[{value:A(t[1])}]},stringify:(e,t)=>se(t)?`${e[0]?.value}`:`CONTAINS "%${e[0]?.value}%"`},Ct={operator:"NOT CONTAINS",parse:e=>{let t=e.match(/^NOT CONTAINS\s*["'](.*)["']$/i);if(t)return[{value:A(t[1])}]},stringify:e=>`NOT CONTAINS "%${e[0]?.value}%"`};function Ot(e){return e===""?[]:Po(e).map(Do)}function Po(e){let t=[],r=0,o="",a=!1,n=!1;for(;r<e.length;){let s=e[r];if((a||n)&&s==="\\"){o+=e[r+1],r+=2;continue}if(s==="'"&&!n){a=!a,o+=s,r++;continue}if(s==='"'&&!a){n=!n,o+=s,r++;continue}if(s===","&&!a&&!n){t.push(o.trim()),o="",r++;continue}o+=s,r++}if(o.trim()!==""&&t.push(o.trim()),a||n)throw new Error("Unterminated string literal");return t}function Do(e){if(e.startsWith("'")&&e.endsWith("'"))return{value:Nt(e.slice(1,-1),"'")};if(e.startsWith('"')&&e.endsWith('"'))return{value:Nt(e.slice(1,-1),'"')};let t=Number(e);if(!Number.isNaN(t))return{value:t};throw new Error(`Invalid literal: ${e}`)}function Nt(e,t){return e.replace(/\\(.)/g,(r,o)=>o)}var At={operator:"IN",parse:e=>{let t=e.match(/^in\s*\((.*)\)$/i);if(t)return Ot(t[1])},stringify:e=>`IN (${e?.map(t=>`"${t.value}"`).join(", ")})`},Pt={operator:"NOT IN",parse:e=>{let t=e.match(/^not\s+in\s*\((.*)\)$/i);if(t)return Ot(t[1])},stringify:e=>`NOT IN (${e?.map(t=>`"${t.value}"`).join(", ")})`};var Dt={operator:"=",parse:e=>{let t=e.match(/^=\s*(.*)$/);if(t)return[{value:A(t[1])}]},stringify:(e,t)=>bt(t)?`${e[0]?.value}`:`= ${e[0]?.value}`},xt={operator:"!=",parse:e=>{let t=e.match(/^!=\s*(.*)$/);if(t)return[{value:A(t[1])}]},stringify:e=>`!= ${e[0]?.value}`},vt={operator:"<>",parse:e=>{let t=e.match(/^<>\s*(.*)$/);if(t)return[{value:A(t[1])}]},stringify:e=>`<> ${e[0]?.value}`},_t={operator:">",parse:e=>{let t=e.match(/^>\s*(.*)$/);if(t)return[{value:A(t[1])}]},stringify:e=>`> ${e[0]?.value}`},Ut={operator:">=",parse:e=>{let t=e.match(/^>=\s*(.*)$/);if(t)return[{value:A(t[1])}]},stringify:e=>`>= ${e[0]?.value}`},Lt={operator:"<",parse:e=>{let t=e.match(/^<\s*(.*)$/);if(t)return[{value:A(t[1])}]},stringify:e=>`< ${e[0]?.value}`},qt={operator:"<=",parse:e=>{let t=e.match(/^<=\s*(.*)$/);if(t)return[{value:A(t[1])}]},stringify:e=>`<= ${e[0]?.value}`};var kt={operator:"IS NULL",parse:e=>{if(/^is\s+null$/i.test(e))return[]},stringify:()=>"IS NULL"},Mt={operator:"IS NOT NULL",parse:e=>{if(/^is\s+not\s+null$/i.test(e))return[]},stringify:()=>"IS NOT NULL"};var xo=[Et,Rt,It,Ct,At,Pt,Dt,xt,vt,Ut,_t,qt,Lt,kt,Mt];function vo(e){let t=e.trim();for(let r of xo){let o=r.parse(t);if(o)return{operator:r.operator,value:o}}}var Qt={parse:vo};var b=e=>{let t=Oe[e];return r=>Oe[r.currentTeamRole]>=t},Ft=async e=>{let t=e.routeOptions.config.requireRole;if(t&&!t(e.user))throw new i(403,"You are not authorized to perform this action")};var Bt=g(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=d(t),o=await E.findOne({where:{id:r}});if(!o)throw new i(404,"Data source not found");return{data:o}}}),e.route({method:"get",url:"/",handler:async t=>{let{teamId:r}=U(t);return{data:await E.find({where:{team:{id:r}},order:{createdAt:"DESC"}})}}}),e.route({url:"/",method:"post",config:{requireRole:b("admin")},handler:async t=>{let{teamId:r,ownerId:o,...a}=y(t,mt),n=E.create({...a,allowUpdate:!!a.allowUpdate,allowInsert:!!a.allowInsert,team:{id:r},owner:{id:o}}),s=await M(Q(n),n.dbType,t);try{await s.checkConnection()}catch{throw new i(400,"Cannot connect to the database, please check datasource configuration")}let{tag:u,iv:c,encrypted:m}=ne.encrypt(n.dbPassword);return n.dbPassword=m,n.dbPasswordIv=c,n.dbPasswordTag=u,{data:await E.save(n)}}}),e.route({method:"put",url:"/:id",config:{requireRole:b("admin")},handler:async t=>{let{id:r}=d(t),o=y(t),a=await E.findOneBy({id:r});if(!a)throw new i(404,"Data source not found");let n=E.merge(a,o);return await E.save(n),{data:n}}}),e.route({method:"delete",url:"/:id",config:{requireRole:b("admin")},handler:async(t,r)=>w.transaction(async()=>{let{id:o}=d(t);await Promise.all([v.delete({datasource:{id:o}}),I.delete({dataSource:{id:o}})]),await E.delete({id:o})})}),e.route({method:"post",url:"/:id/inspect",handler:async(t,r)=>{let{id:o}=d(t),a=await E.findOne({where:{id:o},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser"]});if(!a)throw new Error("Data source not found");a.status="INSPECTING",await E.save(a);let s=await(await M(Q(a,!0),a.dbType,t)).inspectSchema();await v.delete({datasource:{id:o}}),await v.insert(s.sort().map(u=>v.create({tableName:u.tableName,columns:u.columns,datasource:{id:o}}))),a.status="READY",a.lastInspected=new Date,await E.save(a)}}),e.route({method:"get",url:"/:id/inspections",handler:async t=>{let{id:r}=d(t);return{data:await v.find({where:{datasource:{id:r}}})}}})});var L=require("typeorm"),$t=g(e=>{e.route({method:"get",url:"/team/:teamId/datasources",handler:async t=>{let{teamId:r}=d(t);return{data:await E.find({where:{team:{id:r}},order:{name:"ASC"},select:{id:!0,name:!0,updatedAt:!0,dbType:!0,description:!0,allowInsert:!0,allowUpdate:!0}})}}}),e.route({method:"get",url:"/team/:teamId/queries",handler:async t=>{let r=d(t),o=U(t),a=r.teamId||t.user.currentTeamId,n=Number(o.size)||20,s=Number(o.page)||0,u=o.nameFilter?.length?{name:(0,L.Raw)(f=>`LOWER(${f}) LIKE :search`,{search:`%${o.nameFilter.toLowerCase()}%`})}:void 0,c=await _.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:s*n,select:{id:!0,query:{id:!0,name:!0,updatedAt:!0,dataSource:{name:!0,dbType:!0}}},order:{query:{updatedAt:"DESC"}}}),m=c.length>n;return m&&c.pop(),{data:c.map(f=>({name:f.query.name,id:f.query.id,updatedAt:f.query.updatedAt,savedQueryId:f.id,datasourceName:f.query.dataSource.name,datasourceType:f.query.dataSource.dbType})),hasMore:m}}}),e.route({method:"get",url:"/team/:teamId/count-saved-queries",handler:async t=>{let o=d(t).teamId||t.user.currentTeamId;return{data:await _.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),s=o.length>3?parseInt(a)||20:8,u={};n?.length&&(u.id=(0,L.In)(n));let[c,m,p]=await Promise.all([v.find({where:{tableName:(0,L.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:s}),O.find({where:{searchString:(0,L.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:s}),_.find({where:{searchString:(0,L.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:s})]),f=[];return c.forEach(l=>{f.push({name:l.tableName,id:l.id,dataSourceName:l.datasource?.name||"--",dataSourceId:l.datasource?.id||"--",type:"table"})}),m.forEach(l=>{f.push({name:l.name,id:l.id,dataSourceName:l.dataSource?.name||"--",dataSourceId:l.dataSource?.id||"--",type:"tab"})}),p.forEach(l=>{f.push({name:l.query.name,id:l.query.id,dataSourceName:l.query.dataSource?.name||"--",dataSourceId:l.query.dataSource?.id||"--",type:"query"})}),{data:f}}}),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),s=t.user.id,u={team:{id:r},user:{id:s}};o.nameFilter?.length&&(u.name=(0,L.Like)(`%${o.nameFilter}%`)),o.archived&&(u.archived=o.archived==="true");let c=await O.find({where:u,relations:{dataSource:!0},order:{updatedAt:"DESC"},take:n+1,skip:a*n}),m=!1;return c.length>n&&(c.pop(),m=!0),{data:c.map(p=>({name:p.name,id:p.id,updatedAt:p.updatedAt,archived:p.archived,createdAt:p.createdAt,dataSourceId:p.dataSource?.id,dataSourceName:p.dataSource?.name,dataSourceType:p.dataSource?.dbType})),hasMore:m}}})});var Wt=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:b("editor")},handler:async t=>{let r=y(t),o=await E.findOne({where:{id:r.dataSourceId},relations:{team:!0}});return{data:await I.save(I.create({name:r.name,opts:r.opts,team:{id:o?.team.id},dataSource:{id:r.dataSourceId},user:{id:t.user.id}}))}}}),e.route({method:"patch",url:"/:id",config:{requireRole:b("editor")},handler:async t=>{let{id:r}=d(t),o=y(t);if(!(await I.update(r,o)).affected)throw new i(404,"Query not found");return{data:await I.findOneBy({id:r})}}}),e.route({method:"delete",url:"/:id",config:{requireRole:b("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 Ht=e=>se(e)?"CONTAINS":"=",Pe=(e,t)=>{let r=[];for(let o of e)if(!(!o.column?.length||!o.value?.length||o.isEnabled===!1))if(o.isAdvanced){let a=Qt.parse(o.value);if(!a)throw new i(400,`Invalid value for '${o.column}': ${o.value}`);r.push({value:a.value,column:o.column,operator:a.operator||Ht(t(o.column)),fn:o.fn})}else r.push({value:o.value?[{value:o.value}]:[],column:o.column,operator:Ht(t(o.column)),fn:o.fn});return r},Yt=e=>{let t=[e.table];return e.joins&&e.joins.forEach(({table:r})=>t.push(r)),t},Ae=e=>({column:e.value,fn:e.fn,distinct:e.distinct}),Gt=(e,t,r)=>{let o=[];return t.length>0||r.length>0?o.push(...t.map(Ae),...r.map(Ae)):e.length>0&&o.push(...e.map(Ae)),o},jt=(e,t,r)=>t.map((o,a)=>({...o,full:e[a].fn?e[a].column:o.full,type:r(o.full),fn:e[a].fn}));var De=require("typeorm"),Kt=new De.DataSource({type:"mysql"}),Vt=new De.DataSource({type:"postgres"}),H=e=>{switch(e){case"postgres":return Vt.createQueryBuilder();case"mysql":return Kt.createQueryBuilder();default:throw new Error("Unsupported database connection")}},ie={postgres:Vt.driver,mysql:Kt.driver};var V=(e,t,r)=>{let{column:o,operator:a,value:n}=e,s="_"+t;switch(a){case"IS NULL":case"IS NOT NULL":return[`${o} ${a}`,{value:void 0}];case"IN":case"NOT IN":return[`${o} ${a} (:...${s})`,{[s]:n?.map(m=>m.value)}];case"LIKE":case"CONTAINS":return[`${o} ${r==="postgres"?"ILIKE":"LIKE"} :${s}`,{[s]:a==="CONTAINS"?`%${n?.[0].value}%`:n?.[0].value}];case"NOT LIKE":case"NOT CONTAINS":return[`${o} ${r==="postgres"?"NOT ILIKE":"NOT LIKE"} :${s}`,{[s]:a==="NOT CONTAINS"?`%${n?.[0].value}%`:n?.[0].value}];default:return[`${o} ${a} :${s}`,{[s]:n?.[0]?.value}]}};var zt=e=>{let t=ie[e];return r=>{if(r.includes(".")){let[o,a]=r.split(".");return t.escape(o)+"."+t.escape(a)}return r==="*"?r:t.escape(r)}};var Jt=["SUM","COUNT","AVG","MAX","MIN"],_o=["YEAR","MONTH","DAY",...Jt],Uo=_o.reduce((e,t)=>(e[t]=!0,e),{}),Lo=Jt.reduce((e,t)=>(e[t]=!0,e),{}),Xt=e=>Uo[e],Zt=e=>Lo[e];var ue=(e,t,r=!1)=>r?`${t}(distinct ${e})`:`${t}(${e})`,er={YEAR:e=>`EXTRACT(YEAR FROM ${e})`,MONTH:e=>`EXTRACT(MONTH FROM ${e})`,DAY:e=>`EXTRACT(DAY FROM ${e})`,SUM:(e,t,r)=>r?`COALESCE(SUM(distinct ${e}), 0)`:`COALESCE(SUM(${e}), 0)`,AVG:ue,MAX:ue,MIN:ue,COUNT:ue};var ce=(e,t,r=!1)=>r?`${t}(distinct ${e})`:`${t}(${e})`,tr={YEAR:e=>`YEAR(${e})`,MONTH:e=>`MONTH(${e})`,DAY:e=>`DAY(${e})`,SUM:(e,t,r)=>r?`coalesce(${t}(distinct ${e}), 0)`:`coalesce(${t}(${e}), 0)`,AVG:ce,MAX:ce,MIN:ce,COUNT:ce};var qo=e=>{let t=[];return e.fn&&t.push(e.fn),e.distinct&&t.push("distinct"),t.push(e.column),t.join(" ")},ko=e=>{let t=zt(e),r=e==="postgres"?er:tr;return o=>o.fn&&Xt(o.fn)?r[o.fn](t(o.column),o.fn,o.distinct):t(o.column)};function rr(e,t){let r=H(t.dbType).from(e,e),o=!1,a=0,n=ko(t.dbType),s={};return{setColumns(u){u.forEach(c=>{let m=qo(c);s[m]=m,r.addSelect(n(c),m)})},setLimit:u=>{r.limit(u),o=!0},setOffset(u){r.skip(u)},addOrderBy(u,c){r.addOrderBy(u,c)},addJoin({table:u,alias:c,on:m}){r.leftJoin(u,c||u,m)},addWhere(u){let[c,m]=V({...u,operator:u.operator||"=",column:n(u)},++a,t.dbType);r.andWhere(c,m)},addHaving(u){let[c,m]=V({...u,operator:u.operator||"=",column:n(u)},++a,t.dbType);r.andHaving(c,m)},addGroupBy(u){r.addGroupBy(n(u))},hasAlias(u){return!!s[u]},build(){o||r.limit(50);let[u,c]=r.getQueryAndParameters();return{sql:u,params:c}}}}var or=(e,t)=>{let r=H(t.dbType).update(e),o=0;return{addWhere(a){let[n,s]=V(a,++o,t.dbType);r.andWhere(n,s)},setParams(a){let n={};for(let[s,u]of Object.entries(a)){let c=`${u}`;c.startsWith("=")?n[s]=()=>c.substring(1):n[s]=c}r.set(n)},build(){let[a,n]=r.getQueryAndParameters();return{sql:a,params:n}}}};var ar=(e,t)=>{let r=H(t.dbType).insert().into(e);return{setValues(o){let a={};for(let[n,s]of Object.entries(o)){let u=`${s}`;u.startsWith("=")?a[n]=()=>u.substring(1):a[n]=u}r.values([a])},build(){let[o,a]=r.getQueryAndParameters();return{sql:o,params:a}}}};var xe=rr,nr=or,sr=ar;var ir=require("typeorm"),ur=async(e,t)=>{let r=await v.find({where:{tableName:(0,ir.In)(t),datasource:{id:e}}}),o=[];for(let s of r)if(s.columns)for(let u of s.columns)o.push({column:u.name,table:s.tableName||"",full:`${s.tableName}.${u.name}`,type:u.type});let a=o.reduce((s,u)=>(s[u.full]=u.type,s),{});return{getAllColumns(){return o},getColumnType:s=>a[s],hasColumn(s){return!!a[s]||s==="*"}}};async function Mo(e,t,r){return I.save(I.create({user:{id:e},team:{id:t},dataSource:{id:r.datasourceId},name:r.name,opts:r.opts}))}var me=async(e,t)=>{let{datasourceId:r,size:o=20,page:a}=t,{table:n,joins:s,groupBy:u,orderBy:c}=t.opts,m=await le(r);if(!m)throw new i(404,"Datasource not found");let p=Gt(t.opts.columns,t.opts.groupBy,t.opts.aggregations),f=Yt(t.opts),l=await ur(r,f),C=l.getAllColumns(),q;p&&p.length>0?q=p:q=C.map(R=>({column:R.full})),q.forEach(R=>{if(!l.hasColumn(R.column))throw new i(400,`Invalid column ${R.column}`)});let Hr=Mo(e.user.id,e.user.currentTeamId,t),x=xe(n,m);x.setLimit(o+1),x.setOffset(o*a),x.setColumns(q),s&&s.forEach(x.addJoin),c.length>0&&c.forEach(({column:R,direction:Kr})=>{x.hasAlias(R)&&x.addOrderBy(ie[m.dbType].escape(R),Kr)}),u&&u.length>0&&u.forEach(R=>{l.hasColumn(R.value)&&x.addGroupBy({column:R.value,fn:R.fn,distinct:R.distinct})}),Pe(t.opts.filters,l.getColumnType).forEach(R=>{R.fn&&Zt(R.fn)?x.addHaving(R):x.addWhere(R)});let{sql:Yr,params:Gr}=x.build(),J=await(await M(Q(m,!0),m.dbType,e)).executeQuery({sql:Yr,params:Gr,type:"SELECT",allowBulkUpdate:!1}),_e=J.rows.length>o;_e&&J.rows.pop();let{id:jr}=await Hr;return{...J,queryHistoryId:jr,tables:f,allColumns:C,columns:jt(q,J.columns,l.getColumnType),hasMore:_e}},cr=async(e,t)=>{let r=await le(t.dataSourceId);if(!r)throw new i(400,"Invalid datasource");let o=await M(Q(r,!0),r.dbType,e),a=xe(t.table,r);a.setLimit(2);for(let[c,m]of Object.entries(t.props))a.addWhere({value:[{value:m}],column:c});let{sql:n,params:s}=a.build(),u=await o.executeQuery({sql:n,params:s,type:"SELECT",allowBulkUpdate:!1});if(u.rows.length>1)throw new i(400,"Found multiple rows for given query");if(u.rows.length<1)throw new i(404,"Entity not found");return{entity:u.rows[0],columns:u.columns,sql:n}},mr=async(e,t)=>{let r=await le(t.datasourceId);if(!r)throw new i(404,"Data source not found");if(!r.allowUpdate)throw new i(403,"This datasource does not allow update operations");let o=nr(t.table,r);o.setParams(t.values),Pe(t.filters,()=>"=").forEach(u=>{o.addWhere(u)});let{sql:a,params:n}=o.build();return(await M(Q(r,!0),r.dbType,e)).executeQuery({sql:a,params:n,type:"UPDATE",allowBulkUpdate:!1})},lr=async(e,t)=>{let r=await le(t.datasourceId);if(!r)throw new i(404,"Data source not found");if(!r.allowInsert)throw new i(403,"This datasource does not allow insert operations");let o=sr(t.table,r);o.setValues(t.values);let{sql:a,params:n}=o.build();return(await M(Q(r,!0),r.dbType,e)).executeQuery({sql:a,type:"INSERT",params:n,allowBulkUpdate:!1})};async function le(e){return E.findOne({where:{id:e},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser","allowUpdate","allowInsert"]})}var dr=e=>{},Qo=["--",";","DROP","drop"],pr=([e,t])=>{if(typeof t=="string"&&t.startsWith("=")){let r=t;Qo.forEach(o=>{if(r.includes(o))throw new i(400,"Invalid input value for "+e)})}},fr=e=>{if(!e.table)throw new i(400,"Table is required");Object.entries(e.values).forEach(pr)},yr=e=>{if(!e.table)throw new i(400,"Table is required");Object.entries(e.values).forEach(pr)};var Tr=g(e=>{e.route({method:"post",url:"/:dsId/select",handler:async t=>{let r=y(t,dr);return{data:await me(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 cr(t,{table:o,dataSourceId:r,props:a})}}}),e.route({method:"post",url:"/:dsId/insert",config:{requireRole:b("editor")},handler:async t=>{let r=y(t,fr);return{data:await lr(t,r)}}}),e.route({method:"post",url:"/:dsId/update",config:{requireRole:b("editor")},handler:async t=>{let r=y(t,yr);return{data:await mr(t,r)}}})});var gr=g(e=>{e.get("/",{config:{isPublic:!0}},async()=>({data:{active:!0,version:T.str("SERVER_VERSION")}}))});var hr=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 i(404,"Team not found");return{data:o.users.map(a=>({role:a.role,id:a.user.id,name:a.user.username}))}}}),e.route({method:"post",url:"/",config:{requireRole:b("editor")},handler:async t=>w.transaction(async()=>{let r=t.user.id,o=y(t),a=S.create();a.id=r;let n=k.create(o);await k.save(n);let s=N.create({user:a,team:n});return await N.save(s),{data:n}})}),e.route({method:"patch",url:"/:id/user-role",config:{requireRole:b("admin")},handler:async t=>{let{id:r}=d(t),{role:o,userId:a}=y(t,({role:s})=>{if(s==="owner")throw new i(400,"Only one owner is allowed")});if((await N.findOneBy({user:{id:a},team:{id:r}}))?.role==="owner")throw new i(400,"Cannot change owner role");await N.update({user:{id:a},team:{id:r}},{role:o})}}),e.route({method:"delete",url:"/:id",config:{requireRole:b("admin")},handler:async t=>w.transaction(async()=>{let{id:r}=d(t),{userId:o}=U(t);if((await N.findOneBy({user:{id:o},team:{id:r}}))?.role==="owner")throw new i(400,"Cannot delete team owner");await S.update(o,{currentTeam:null}),await N.delete({user:{id:o},team:{id:r}}),await S.delete({id:o})})})});var ve=P(require("bcryptjs")),z=async e=>{let t=await ve.default.genSalt(10);return ve.default.hash(e,t)};var wr=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 i(404,"User not found");return{data:{id:r.id,teamId:r.currentTeam?.team.id,teamName:r.currentTeam?.team.name,teamRole:r.currentTeam?.role,username:r.username}}}}),e.route({method:"patch",url:"/",handler:async t=>{let r=t.user.id,o=y(t);if(o.password&&(o.password=await z(o.password)),!(await S.update(r,o)).affected)throw new i(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:b("admin")},handler:async t=>w.transaction(async()=>{let r=y(t),o=await z(r.password),a=await S.save(S.create({username:r.username,password:o})),n=await N.save(N.create({role:"read_only",team:{id:r.teamId},user:{id:a.id}}));await S.update(a.id,{currentTeam:{id:n.id}})})})});var Sr=g(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=t.user.id,o=await $.findOneBy({user:{id:r}});return o||(o=await $.save($.create({user:{id:r}}))),{data:o}}}),e.route({method:"patch",url:"/",handler:async t=>{let{settings:r}=y(t);if(!r.id)throw new i(400,"Settings id is required!");if(!(await $.update(r.id,r)).affected)throw new i(404,"You do not own these settings!");return{data:await $.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 br=g(e=>{e.route({method:"post",url:"/",config:{requireRole:b("editor")},handler:async t=>{let r=y(t),o=await I.findOne({where:{id:r.queryId}});if(!o)throw new i(400,"Query not found");let a=await _.save(_.create({isPersonal:!1,team:{id:t.user.currentTeamId},user:{id:t.user.id},query:{id:r.queryId},searchString:Y(o.opts,r.name)}));return await I.update(r.queryId,{name:r.name}),{data:a}}}),e.route({method:"delete",url:"/:id",config:{requireRole:b("editor")},handler:async t=>{let{id:r}=d(t);if(!(await _.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=y(t,s=>{if(!s.name)throw new i(400,"Name is required")}),a=await _.findOne({where:{id:r},relations:{query:!0}});if(!a)throw new i(400,"Query not found");let n=Y(a.query.opts,o.name);return await Promise.all([_.update({id:r},{searchString:n}),I.update({id:a.query.id},{name:o.name})]),{data:!0}})})});var Er=e=>{if(!e.queryId&&!(e.opts&&e.name))throw new i(400,"Either queryId or name and opts are required")};var Ir=g(e=>{e.route({method:"get",url:"/",handler:async t=>{let{currentTeamId:r,id:o}=t.user;return{data:(await O.find({where:{team:{id:r},user:{id:o},archived:!1},select:["id","name"]})).map(n=>({name:n.name,id:n.id}))}}}),e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=d(t),{currentTeamId:o,id:a}=t.user,n=await O.findOne({where:{id:r,team:{id:o},user:{id:a}}});if(!n)throw new i(404,"Not Found");return{data:n}}}),e.route({method:"post",url:"/",handler:async t=>{let{opts:r,name:o,queryId:a}=y(t,Er),n,s,u=o;if(r)s=r.dataSourceId,n=r;else{let m=await I.findOne({where:{id:a},relations:{dataSource:!0}});if(!m)throw new i(404,"Query not Found");s=m.dataSource.id,n={table:m.opts.table,filters:m.opts.filters,joins:m.opts.joins,orderBy:m.opts.orderBy,columns:m.opts.columns,groupBy:m.opts.groupBy,searchAll:m.opts.searchAll,aggregations:m.opts.aggregations,dataSourceId:m.dataSource.id,page:0,size:50},o||(u=m.name)}return{data:await O.save(O.create({name:u||new Date().toISOString(),opts:n||{},dataSource:{id:s},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=y(t),a=await O.findOne({where:{id:r},relations:{user:!0}});if(!a)throw new i(404,"Not found");if(a.user?.id!==t.user.id)throw new i(404,"Not found");return o&&O.update(r,{opts:o||{},searchString:Y(o,a.name),updatedAt:new Date}),{data:{result:await me(t,{datasourceId:o.dataSourceId,size:o.size,name:a.name,page:o.page,opts:{table:o.table,filters:o.filters,joins:o.joins,orderBy:o.orderBy,columns:o.columns,groupBy:o.groupBy,searchAll:o.searchAll,aggregations:o.aggregations}})}}}}),e.route({method:"patch",url:"/:id",handler:async t=>{let{id:r}=d(t),o=y(t),a=await O.findOne({where:{id:r,user:{id:t.user.id}}});if(!a)throw new i(404,"Not Found");let n=a.searchString;return o.name&&(n=Y(a.opts,o.name)),await O.update(r,{...o,searchString:n}),{data:{id:r}}}}),e.route({method:"delete",url:"/:id",handler:async t=>{let{id:r}=d(t),o=t.user.id;return await O.delete({id:r,user:{id:o}}),{data:!0}}})});var Nr=require("node:crypto");var Rr=require("node:crypto"),Cr={teamName:"Default Team",username:"admin"},Fo=async()=>{let e=await k.findOneBy({});return e||k.save(k.create({name:Cr.teamName}))},de=async e=>{let t=await N.findOne({where:{role:"owner"},relations:{user:!0}});if(t)return t.user;let r=await Fo(),o=await z(e?.password||(0,Rr.randomBytes)(32).toString("hex")),a=await S.save(S.create({username:e?.name||Cr.username,password:o})),n=await N.save(N.create({user:a,team:r,role:"owner"}));return await S.update(a.id,{currentTeam:n}),a};var pe={setupAccessToken:void 0},Or=()=>(pe.setupAccessToken=(0,Nr.randomBytes)(32).toString("hex"),pe.setupAccessToken),Bo=e=>{if(!pe.setupAccessToken)throw new i(400,"Setup already performed");if(!e||e!==pe.setupAccessToken)throw new i(400,"Invalid setup access token")},B=async()=>D.skipAuth?!1:await S.count()<1,Ar=async e=>{Bo(e.setupAccessToken),await de({name:e.userName,password:e.userPassword})};var Pr=g(e=>{e.route({method:"get",url:"/client.config.js",handler:(t,r)=>{let o={skipAuth:D.skipAuth,modeName:D.name,usesCustomDb:Qe(),serverVersion:T.str("SERVER_VERSION","--")};return r.type("application/javascript").send(`window.__CLIENT_CONFIG__ = ${JSON.stringify(o)};`)}}),e.route({method:"get",url:"/",handler:async(t,r)=>await 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 Dr=e=>{if(!e.setupAccessToken)throw new i(400,"Invalid setup access token");if(!e.userPassword||e.userPassword.length<8)throw new i(400,"Password should be at least 8 chars long");if(!e.userName)throw new i(400,"User name is required")};var xr=g(e=>{e.route({method:"post",url:"/",config:{isPublic:!0},handler:async t=>{if(!await B())throw new i(400,"Setup has already been completed");let o=y(t,Dr);return await Ar(o),{data:!0}}})});var $o=[[Pr,"/"],[ct,"/api/auth"],[Bt,"/api/data-sources"],[$t,"/api/project"],[Wt,"/api/queries"],[Tr,"/api/runner"],[gr,"/api/status"],[hr,"/api/teams"],[wr,"/api/users"],[Sr,"/api/user-settings"],[br,"/api/saved-queries"],[Ir,"/api/workbench-tabs"],[xr,"/api/setup"]],vr=e=>{for(let[t,r]of $o)e.register(t,{prefix:r}),console.log("Registered "+r)};var Wo=e=>e.routeOptions.config.isPublic?!0:!e.url.startsWith("/api/"),Ho=async()=>N.findOne({where:{role:"owner"},relations:{user:!0,team:!0}}),Yo=async e=>{let t=await Ho();if(!t)throw new i(401,"User is not part of a team");e.user={id:t.user.id,currentTeamId:t.team.id,currentTeamRole:t.role}},Go=async e=>{let t=e.headers.authorization;if(!t)throw new i(401,"Missing auth token");let[r,o]=t.split(" "),{userId:a}=await nt(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 i(401,"Unauthorized");e.user={id:a,currentTeamId:n.currentTeam.team.id,currentTeamRole:n.currentTeam.role}},_r=async e=>{Wo(e)||(D.skipAuth?await Yo(e):await Go(e))};var Ur=(e,t)=>{e.__connections&&e.__connections.forEach(r=>{r.close()})};var Lr=e=>{e.addHook("onRequest",_r),e.addHook("onRequest",Ft),e.addHook("onResponse",Ur)};var qr=e=>{e.setNotFoundHandler((t,r)=>{if(t.raw.url?.startsWith("/api/")){r.code(404).send({error:"API route not found"});return}r.sendFile("index.html")}),e.setErrorHandler((t,r,o)=>{console.error(t),t instanceof i?o.status(t.status).send({error:t.message}):o.status(500).send({error:"Internal Server Error"})})};var kr=P(require("@fastify/cookie")),Mr=P(require("@fastify/cors"));var Qr=P(require("@fastify/static")),Fr=require("node:path"),Br=e=>{e.register(kr.default,{}),e.register(Mr.default,{origin:G.allowedOrigins,methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"],credentials:!0}),e.register(Qr.default,{root:(0,Fr.join)(__dirname,"web")})};(async function(){let t=(0,$r.default)({querystringParser:o=>Wr.default.parse(o)});if(Me(),Br(t),Lr(t),vr(t),qr(t),await t.after(),await Xe(),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=Or();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),{})},wt=async(e,t,r,o)=>{try{console.log(`[PG CONN] Query: ${e}`),console.log(`[PG CONN] Params: ${JSON.stringify(t,null,2)}`);let{rows:a,fields:n,command:s,rowCount:u}=await r.query({text:e,rowMode:"array",values:t});if(s==="UPDATE"||s==="INSERT"||s==="DELETE"){if(u!=null&&u>1&&o.allowBulkUpdate!==!0)throw new Error("[PG CONN] Bulk update performed without permission.");return{columns:[{column:"affectedRows",alias:"Affected rows",full:"affectedRows"}],rows:[[u]],query:e}}if(s==="SELECT"){let c=n.map(d=>`'${d.tableID}-${d.columnID}'`),m=await Eo(c,r);return{columns:n.map(d=>{let l=m[`${d.tableID}-${d.columnID}`];return{column:l?.column||d.name,alias:d.name,table:l?.table||"",full:l?l.table+"."+l.column:d.name}}),rows:a,query:e}}throw new Error(`[PG CONN] Unsupported command: ${s}`)}catch(a){throw a instanceof i?a:new i(400,a.message)}},Io=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}},Ro=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 ho(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:()=>bo(e,t),executeQuery:n=>a(()=>n.type==="SELECT"?Ro(t,()=>wt(n.sql,n.params,t,n)):Io(t,()=>wt(n.sql,n.params,t,n))),checkConnection:async()=>{},isClosed:()=>r,close:async()=>{if(!r)return r=!0,t.end()}}};var M=async(e,t,r)=>{try{let o;if(t==="mysql")o=await ht(e);else if(t==="postgres")o=await bt(e);else throw new i(500,`Connection manager for ${t} not found`);return r.__connections?r.__connections.push(o):r.__connections=[o],o}catch(o){throw console.error(o),o instanceof i?o:o?.code==="ECONNREFUSED"?new i(500,"Failed to connect to the database"):new i(500,o.message)}};var ne=O(require("node:crypto"));var Et="aes-256-gcm",Co=12,It=()=>{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},No=e=>{let t=ne.default.randomBytes(Co),r=It(),o=ne.default.createCipheriv(Et,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")}},Ao=({encrypted:e,iv:t,tag:r})=>{let o=It(),a=ne.default.createDecipheriv(Et,o,Buffer.from(t,"hex"));a.setAuthTag(Buffer.from(r,"hex"));let n=a.update(e,"hex","utf8");return n+=a.final("utf8"),n},se={encrypt:No,decrypt:Ao};var B=(e,t=!1)=>{if(t){let r=se.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 Rt=[{value:"=",label:"equals"},{value:"<>",label:"not equal"},{value:">",label:"greater than"},{value:">=",label:"greater than or equal"},{value:"<",label:"less than"},{value:"<=",label:"less than or equal"},{value:"LIKE",label:"like"},{value:"NOT LIKE",label:"not like"},{value:"CONTAINS",label:"contains"},{value:"NOT CONTAINS",label:"not contains"},{value:"IN",label:"in list"},{value:"NOT IN",label:"not in list"},{value:"IS NULL",label:"is null"},{value:"IS NOT NULL",label:"is not null"}],Po=Rt.reduce((e,t)=>(e[t.value]=t.label,e),{}),ts=Rt.reduce((e,t)=>(e[t.label]=t.value,e),{}),H=e=>e.map(t=>({label:Po[t],value:t})),rs=H(["=","<>",">",">=","<","<=","IN","NOT IN","IS NULL","IS NOT NULL"]),os=H(["=","<>","LIKE","NOT LIKE","IN","NOT IN","IS NULL","IS NOT NULL","CONTAINS","NOT CONTAINS"]),as=H(["=","<>","IS NULL","IS NOT NULL"]),ns=H(["=","<>",">",">=","<","<=","IS NULL","IS NOT NULL"]),ss=H(["IS NULL","IS NOT NULL"]),is=H(["IN","NOT IN"]),Oo=["char","varchar","binary","varbinary","blob","text","enum","set","character","character varying","text","citext","uuid","xml","json","jsonb"],Do=new Set(Oo),ie=e=>Do.has(e),xo=["integer","smallint","decimal","numeric","float","real","double precision","int","smallint","integer","bigint","decimal","numeric","real","double precision","serial","bigserial","money"],vo=new Set(xo),Ct=e=>vo.has(e);var us=["date","datetime","timestamp","timestamptz"].reduce((e,t)=>(e[t]=!0,e),{});var Oe={read_only:10,editor:20,admin:30,owner:40};var P=e=>e.startsWith("'")&&e.endsWith("'")||e.startsWith('"')&&e.endsWith('"')?e.slice(1,-1):e;var Nt={operator:"LIKE",parse:e=>{let t=e.match(/^LIKE\s*["'](.*)["']$/i);if(t)return[{value:P(t[1])}]},stringify:e=>`LIKE "%${e[0]?.value}%"`},At={operator:"NOT LIKE",parse:e=>{let t=e.match(/^NOT LIKE\s*["'](.*)["']$/i);if(t)return[{value:P(t[1])}]},stringify:e=>`NOT LIKE "%${e[0]?.value}%"`},Pt={operator:"CONTAINS",parse:e=>{let t=e.match(/^CONTAINS\s*["'](.*)["']$/i);if(t)return[{value:P(t[1])}]},stringify:(e,t)=>ie(t)?`${e[0]?.value}`:`CONTAINS "%${e[0]?.value}%"`},Ot={operator:"NOT CONTAINS",parse:e=>{let t=e.match(/^NOT CONTAINS\s*["'](.*)["']$/i);if(t)return[{value:P(t[1])}]},stringify:e=>`NOT CONTAINS "%${e[0]?.value}%"`};function xt(e){return e===""?[]:_o(e).map(Uo)}function _o(e){let t=[],r=0,o="",a=!1,n=!1;for(;r<e.length;){let s=e[r];if((a||n)&&s==="\\"){o+=e[r+1],r+=2;continue}if(s==="'"&&!n){a=!a,o+=s,r++;continue}if(s==='"'&&!a){n=!n,o+=s,r++;continue}if(s===","&&!a&&!n){t.push(o.trim()),o="",r++;continue}o+=s,r++}if(o.trim()!==""&&t.push(o.trim()),a||n)throw new Error("Unterminated string literal");return t}function Uo(e){if(e.startsWith("'")&&e.endsWith("'"))return{value:Dt(e.slice(1,-1),"'")};if(e.startsWith('"')&&e.endsWith('"'))return{value:Dt(e.slice(1,-1),'"')};let t=Number(e);if(!Number.isNaN(t))return{value:t};throw new Error(`Invalid literal: ${e}`)}function Dt(e,t){return e.replace(/\\(.)/g,(r,o)=>o)}var vt={operator:"IN",parse:e=>{let t=e.match(/^in\s*\((.*)\)$/i);if(t)return xt(t[1])},stringify:e=>`IN (${e?.map(t=>`"${t.value}"`).join(", ")})`},_t={operator:"NOT IN",parse:e=>{let t=e.match(/^not\s+in\s*\((.*)\)$/i);if(t)return xt(t[1])},stringify:e=>`NOT IN (${e?.map(t=>`"${t.value}"`).join(", ")})`};var Ut={operator:"=",parse:e=>{let t=e.match(/^=\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:(e,t)=>Ct(t)?`${e[0]?.value}`:`= ${e[0]?.value}`},Lt={operator:"!=",parse:e=>{let t=e.match(/^!=\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`!= ${e[0]?.value}`},qt={operator:"<>",parse:e=>{let t=e.match(/^<>\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`<> ${e[0]?.value}`},kt={operator:">",parse:e=>{let t=e.match(/^>\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`> ${e[0]?.value}`},Mt={operator:">=",parse:e=>{let t=e.match(/^>=\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`>= ${e[0]?.value}`},Bt={operator:"<",parse:e=>{let t=e.match(/^<\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`< ${e[0]?.value}`},Qt={operator:"<=",parse:e=>{let t=e.match(/^<=\s*(.*)$/);if(t)return[{value:P(t[1])}]},stringify:e=>`<= ${e[0]?.value}`};var Ft={operator:"IS NULL",parse:e=>{if(/^is\s+null$/i.test(e))return[]},stringify:()=>"IS NULL"},$t={operator:"IS NOT NULL",parse:e=>{if(/^is\s+not\s+null$/i.test(e))return[]},stringify:()=>"IS NOT NULL"};var Lo=[Nt,Pt,At,Ot,vt,_t,Ut,Lt,qt,Mt,kt,Qt,Bt,Ft,$t];function qo(e){let t=e.trim();for(let r of Lo){let o=r.parse(t);if(o)return{operator:r.operator,value:o}}}var Wt={parse:qo};var b=e=>{let t=Oe[e];return r=>Oe[r.currentTeamRole]>=t},Ht=async e=>{let t=e.routeOptions.config.requireRole;if(t&&!t(e.user))throw new i(403,"You are not authorized to perform this action")};var De=async e=>{let t=await W.find({where:{table:{datasource:{id:e}}},relations:{table:!0}});await W.remove(t),await U.delete({datasource:{id:e}})};function ko(e){let t=new Map;for(let r of e)r.columns?.forEach(o=>{if(o.ref){let a=`${o.ref.table}.${o.ref.field}`,n=t.get(a)||[];n.push({table:r.tableName,field:o.name}),t.set(a,n)}});return t}var Yt=h(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=f(t),o=await E.findOne({where:{id:r}});if(!o)throw new i(404,"Data source not found");return{data:o}}}),e.route({method:"get",url:"/",handler:async t=>{let{teamId:r}=_(t);return{data:await E.find({where:{team:{id:r}},order:{createdAt:"DESC"}})}}}),e.route({url:"/",method:"post",config:{requireRole:b("admin")},handler:async t=>{let{teamId:r,ownerId:o,...a}=y(t,ft),n=E.create({...a,allowUpdate:!!a.allowUpdate,allowInsert:!!a.allowInsert,team:{id:r},owner:{id:o}}),s=await M(B(n),n.dbType,t);try{await s.checkConnection()}catch{throw new i(400,"Cannot connect to the database, please check datasource configuration")}let{tag:u,iv:c,encrypted:m}=se.encrypt(n.dbPassword);return n.dbPassword=m,n.dbPasswordIv=c,n.dbPasswordTag=u,{data:await E.save(n)}}}),e.route({method:"put",url:"/:id",config:{requireRole:b("admin")},handler:async t=>{let{id:r}=f(t),o=y(t),a=await E.findOneBy({id:r});if(!a)throw new i(404,"Data source not found");let n=E.merge(a,o);return await E.save(n),{data:n}}}),e.route({method:"delete",url:"/:id",config:{requireRole:b("admin")},handler:async t=>w.transaction(async()=>{let{id:r}=f(t);await Promise.all([De(r),I.delete({dataSource:{id:r}})]),await E.delete({id:r})})}),e.route({method:"post",url:"/:id/inspect",handler:async(t,r)=>{let{id:o}=f(t),a=await E.findOne({where:{id:o},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser"]});if(!a)throw new Error("Data source not found");a.status="INSPECTING",await E.save(a);let s=await(await M(B(a,!0),a.dbType,t)).inspectSchema();await De(a.id);let u=ko(s);for(let c of s){let m=await U.save({datasource:{id:o},name:c.tableName});if(c.columns){let d=[];for(let l of c.columns)d.push(W.create({table:{id:m.id},name:l.name,isPrimary:l.isPrimary,type:l.type,meta:{refs:l.ref,referencedBy:u.get(`${m.name}.${l.name}`)}}));await W.save(d)}}a.status="READY",a.lastInspected=new Date,await E.save(a)}}),e.route({method:"get",url:"/:id/inspections",handler:async t=>{let{id:r}=f(t);return{data:(await U.find({where:{datasource:{id:r}},relations:{columns:!0},order:{name:"ASC",columns:{isPrimary:"DESC",name:"ASC"}}})).map(n=>({tableName:n.name,id:n.id,updatedAt:n.updatedAt,createdAt:n.createdAt,columns:n.columns.map(s=>({name:s.name,type:s.type,isPrimary:s.isPrimary,ref:s.meta?.refs}))}))}}})});var L=require("typeorm"),Gt=h(e=>{e.route({method:"get",url:"/team/:teamId/datasources",handler:async t=>{let{teamId:r}=f(t);return{data:await E.find({where:{team:{id:r}},order:{name:"ASC"},select:{id:!0,name:!0,updatedAt:!0,dbType:!0,description:!0,allowInsert:!0,allowUpdate:!0}})}}}),e.route({method:"get",url:"/team/:teamId/queries",handler:async t=>{let r=f(t),o=_(t),a=r.teamId||t.user.currentTeamId,n=Number(o.size)||20,s=Number(o.page)||0,u=o.nameFilter?.length?{name:(0,L.Raw)(l=>`LOWER(${l}) LIKE :search`,{search:`%${o.nameFilter.toLowerCase()}%`})}:void 0,c=await v.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:s*n,select:{id:!0,query:{id:!0,name:!0,updatedAt:!0,dataSource:{name:!0,dbType:!0}}},order:{query:{updatedAt:"DESC"}}}),m=c.length>n;return m&&c.pop(),{data:c.map(l=>({name:l.query.name,id:l.query.id,updatedAt:l.query.updatedAt,savedQueryId:l.id,datasourceName:l.query.dataSource.name,datasourceType:l.query.dataSource.dbType})),hasMore:m}}}),e.route({method:"get",url:"/team/:teamId/count-saved-queries",handler:async t=>{let o=f(t).teamId||t.user.currentTeamId;return{data:await v.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}=f(t),{search:o,size:a,selectedDataSources:n}=_(t),s=o.length>3?parseInt(a)||20:8,u={};n?.length&&(u.id=(0,L.In)(n));let[c,m,d]=await Promise.all([U.find({where:{name:(0,L.Raw)(p=>`LOWER(${p}) LIKE :search`,{search:`%${o.toLowerCase()}%`}),datasource:u},relations:{datasource:!0},select:{id:!0,name:!0,datasource:{name:!0,id:!0}},order:{name:"ASC"},take:s}),A.find({where:{searchString:(0,L.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:s}),v.find({where:{searchString:(0,L.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:s})]),l=[];return c.forEach(p=>{l.push({name:p.name,id:p.id,dataSourceName:p.datasource?.name||"--",dataSourceId:p.datasource?.id||"--",type:"table"})}),m.forEach(p=>{l.push({name:p.name,id:p.id,dataSourceName:p.dataSource?.name||"--",dataSourceId:p.dataSource?.id||"--",type:"tab"})}),d.forEach(p=>{l.push({name:p.query.name,id:p.query.id,dataSourceName:p.query.dataSource?.name||"--",dataSourceId:p.query.dataSource?.id||"--",type:"query"})}),{data:l}}}),e.route({method:"get",url:"/team/:teamId/tabs-history",handler:async t=>{let{teamId:r}=f(t),o=_(t),a=Number(o.page),n=Number(o.size),s=t.user.id,u={team:{id:r},user:{id:s}};o.nameFilter?.length&&(u.name=(0,L.Like)(`%${o.nameFilter}%`)),o.archived&&(u.archived=o.archived==="true");let c=await A.find({where:u,relations:{dataSource:!0},order:{updatedAt:"DESC"},take:n+1,skip:a*n}),m=!1;return c.length>n&&(c.pop(),m=!0),{data:c.map(d=>({name:d.name,id:d.id,updatedAt:d.updatedAt,archived:d.archived,createdAt:d.createdAt,dataSourceId:d.dataSource?.id,dataSourceName:d.dataSource?.name,dataSourceType:d.dataSource?.dbType})),hasMore:m}}})});var jt=h(e=>{e.route({method:"get",url:"/:id",handler:async t=>{let{id:r}=f(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:b("editor")},handler:async t=>{let r=y(t),o=await E.findOne({where:{id:r.dataSourceId},relations:{team:!0}});return{data:await I.save(I.create({name:r.name,opts:r.opts,team:{id:o?.team.id},dataSource:{id:r.dataSourceId},user:{id:t.user.id}}))}}}),e.route({method:"patch",url:"/:id",config:{requireRole:b("editor")},handler:async t=>{let{id:r}=f(t),o=y(t);if(!(await I.update(r,o)).affected)throw new i(404,"Query not found");return{data:await I.findOneBy({id:r})}}}),e.route({method:"delete",url:"/:id",config:{requireRole:b("editor")},handler:async t=>w.transaction(async()=>{let{id:r}=f(t);if(!(await I.delete({id:r})).affected)return{status:404,data:"Query not found"}})})});var Kt=e=>ie(e)?"CONTAINS":"=",ve=(e,t)=>{let r=[];for(let o of e)if(!(!o.column?.length||!o.value?.length||o.isEnabled===!1))if(o.isAdvanced){let a=Wt.parse(o.value);if(!a)throw new i(400,`Invalid value for '${o.column}': ${o.value}`);r.push({value:a.value,column:o.column,operator:a.operator||Kt(t(o.column)),fn:o.fn})}else r.push({value:o.value?[{value:o.value}]:[],column:o.column,operator:Kt(t(o.column)),fn:o.fn});return r},Vt=e=>{let t=[e.table];return e.joins&&e.joins.forEach(({table:r})=>t.push(r)),t},xe=e=>({column:e.value,fn:e.fn,distinct:e.distinct}),zt=(e,t,r)=>{let o=[];return t.length>0||r.length>0?o.push(...t.map(xe),...r.map(xe)):e.length>0&&o.push(...e.map(xe)),o},Jt=(e,t,r,o,a)=>t.map((n,s)=>({...n,full:e[s].fn?e[s].column:n.full,type:r(n.full),fn:e[s].fn,ref:n.table?o(n.table,n.column):void 0,referencedBy:n.table?a(n.table,n.column):void 0}));var _e=require("typeorm"),Xt=new _e.DataSource({type:"mysql"}),Zt=new _e.DataSource({type:"postgres"}),Y=e=>{switch(e){case"postgres":return Zt.createQueryBuilder();case"mysql":return Xt.createQueryBuilder();default:throw new Error("Unsupported database connection")}},ue={postgres:Zt.driver,mysql:Xt.driver};var z=(e,t,r)=>{let{column:o,operator:a,value:n}=e,s="_"+t;switch(a){case"IS NULL":case"IS NOT NULL":return[`${o} ${a}`,{value:void 0}];case"IN":case"NOT IN":return[`${o} ${a} (:...${s})`,{[s]:n?.map(m=>m.value)}];case"LIKE":case"CONTAINS":return[`${o} ${r==="postgres"?"ILIKE":"LIKE"} :${s}`,{[s]:a==="CONTAINS"?`%${n?.[0].value}%`:n?.[0].value}];case"NOT LIKE":case"NOT CONTAINS":return[`${o} ${r==="postgres"?"NOT ILIKE":"NOT LIKE"} :${s}`,{[s]:a==="NOT CONTAINS"?`%${n?.[0].value}%`:n?.[0].value}];default:return[`${o} ${a} :${s}`,{[s]:n?.[0]?.value}]}};var er=e=>{let t=ue[e];return r=>{if(r.includes(".")){let[o,a]=r.split(".");return t.escape(o)+"."+t.escape(a)}return r==="*"?r:t.escape(r)}};var tr=["SUM","COUNT","AVG","MAX","MIN"],Mo=["YEAR","MONTH","DAY",...tr],Bo=Mo.reduce((e,t)=>(e[t]=!0,e),{}),Qo=tr.reduce((e,t)=>(e[t]=!0,e),{}),rr=e=>Bo[e],or=e=>Qo[e];var ce=(e,t,r=!1)=>r?`${t}(distinct ${e})`:`${t}(${e})`,ar={YEAR:e=>`EXTRACT(YEAR FROM ${e})`,MONTH:e=>`EXTRACT(MONTH FROM ${e})`,DAY:e=>`EXTRACT(DAY FROM ${e})`,SUM:(e,t,r)=>r?`COALESCE(SUM(distinct ${e}), 0)`:`COALESCE(SUM(${e}), 0)`,AVG:ce,MAX:ce,MIN:ce,COUNT:ce};var me=(e,t,r=!1)=>r?`${t}(distinct ${e})`:`${t}(${e})`,nr={YEAR:e=>`YEAR(${e})`,MONTH:e=>`MONTH(${e})`,DAY:e=>`DAY(${e})`,SUM:(e,t,r)=>r?`coalesce(${t}(distinct ${e}), 0)`:`coalesce(${t}(${e}), 0)`,AVG:me,MAX:me,MIN:me,COUNT:me};var Fo=e=>{let t=[];return e.fn&&t.push(e.fn),e.distinct&&t.push("distinct"),t.push(e.column),t.join(" ")},$o=e=>{let t=er(e),r=e==="postgres"?ar:nr;return o=>o.fn&&rr(o.fn)?r[o.fn](t(o.column),o.fn,o.distinct):t(o.column)};function sr(e,t){let r=Y(t.dbType).from(e,e),o=!1,a=0,n=$o(t.dbType),s={};return{setColumns(u){u.forEach(c=>{let m=Fo(c);s[m]=m,r.addSelect(n(c),m)})},setLimit:u=>{r.limit(u),o=!0},setOffset(u){r.skip(u)},addOrderBy(u,c){r.addOrderBy(u,c)},addJoin({table:u,alias:c,on:m}){r.leftJoin(u,c||u,m)},addWhere(u){let[c,m]=z({...u,operator:u.operator||"=",column:n(u)},++a,t.dbType);r.andWhere(c,m)},addHaving(u){let[c,m]=z({...u,operator:u.operator||"=",column:n(u)},++a,t.dbType);r.andHaving(c,m)},addGroupBy(u){r.addGroupBy(n(u))},hasAlias(u){return!!s[u]},build(){o||r.limit(50);let[u,c]=r.getQueryAndParameters();return{sql:u,params:c}}}}var ir=(e,t)=>{let r=Y(t.dbType).update(e),o=0;return{addWhere(a){let[n,s]=z(a,++o,t.dbType);r.andWhere(n,s)},setParams(a){let n={};for(let[s,u]of Object.entries(a)){let c=`${u}`;c.startsWith("=")?n[s]=()=>c.substring(1):n[s]=c}r.set(n)},build(){let[a,n]=r.getQueryAndParameters();return{sql:a,params:n}}}};var ur=(e,t)=>{let r=Y(t.dbType).insert().into(e);return{setValues(o){let a={};for(let[n,s]of Object.entries(o)){let u=`${s}`;u.startsWith("=")?a[n]=()=>u.substring(1):a[n]=u}r.values([a])},build(){let[o,a]=r.getQueryAndParameters();return{sql:o,params:a}}}};var Ue=sr,cr=ir,mr=ur;var lr=require("typeorm"),dr=async(e,t)=>{let r=await U.find({where:{name:(0,lr.In)(t),datasource:{id:e}},relations:{columns:!0},order:{name:"ASC",columns:{isPrimary:"DESC",name:"ASC"}}}),o=[];for(let c of r)if(c.columns)for(let m of c.columns)o.push({column:m.name,table:c.name||"",full:`${c.name}.${m.name}`,type:m.type});let a=o.reduce((c,m)=>(c[m.full]=m.type,c),{});return{getAllColumns(){return o},getColumnType:c=>a[c],hasColumn(c){return!!a[c]||c==="*"},getColumnRef:(c,m)=>{for(let d of r)if(d.name===c){for(let l of d.columns)if(l.name===m)return l.meta?.refs}},getColumnReferencedBy:(c,m)=>{for(let d of r)if(d.name===c){for(let l of d.columns)if(l.name===m)return l.meta?.referencedBy}}}};async function Wo(e,t,r){return I.save(I.create({user:{id:e},team:{id:t},dataSource:{id:r.datasourceId},name:r.name,opts:r.opts}))}var le=async(e,t)=>{let{datasourceId:r,size:o=20,page:a}=t,{table:n,joins:s,groupBy:u,orderBy:c}=t.opts,m=await de(r);if(!m)throw new i(404,"Datasource not found");let d=zt(t.opts.columns,t.opts.groupBy,t.opts.aggregations),l=Vt(t.opts),p=await dr(r,l),N=p.getAllColumns(),q;d&&d.length>0?q=d:q=N.map(R=>({column:R.full})),q.forEach(R=>{if(!p.hasColumn(R.column))throw new i(400,`Invalid column ${R.column}`)});let Kr=Wo(e.user.id,e.user.currentTeamId,t),x=Ue(n,m);x.setLimit(o+1),x.setOffset(o*a),x.setColumns(q),s&&s.forEach(x.addJoin),c.length>0&&c.forEach(({column:R,direction:Xr})=>{x.hasAlias(R)&&x.addOrderBy(ue[m.dbType].escape(R),Xr)}),u&&u.length>0&&u.forEach(R=>{p.hasColumn(R.value)&&x.addGroupBy({column:R.value,fn:R.fn,distinct:R.distinct})}),ve(t.opts.filters,p.getColumnType).forEach(R=>{R.fn&&or(R.fn)?x.addHaving(R):x.addWhere(R)});let{sql:Vr,params:zr}=x.build(),X=await(await M(B(m,!0),m.dbType,e)).executeQuery({sql:Vr,params:zr,type:"SELECT",allowBulkUpdate:!1}),qe=X.rows.length>o;qe&&X.rows.pop();let{id:Jr}=await Kr;return{...X,queryHistoryId:Jr,tables:l,allColumns:N,columns:Jt(q,X.columns,p.getColumnType,p.getColumnRef,p.getColumnReferencedBy),hasMore:qe}},pr=async(e,t)=>{let r=await de(t.dataSourceId);if(!r)throw new i(400,"Invalid datasource");let o=await M(B(r,!0),r.dbType,e),a=Ue(t.table,r);a.setLimit(2);for(let[c,m]of Object.entries(t.props))a.addWhere({value:[{value:m}],column:c});let{sql:n,params:s}=a.build(),u=await o.executeQuery({sql:n,params:s,type:"SELECT",allowBulkUpdate:!1});if(u.rows.length>1)throw new i(400,"Found multiple rows for given query");if(u.rows.length<1)throw new i(404,"Entity not found");return{entity:u.rows[0],columns:u.columns,sql:n}},fr=async(e,t)=>{let r=await de(t.datasourceId);if(!r)throw new i(404,"Data source not found");if(!r.allowUpdate)throw new i(403,"This datasource does not allow update operations");let o=cr(t.table,r);o.setParams(t.values),ve(t.filters,()=>"=").forEach(u=>{o.addWhere(u)});let{sql:a,params:n}=o.build();return(await M(B(r,!0),r.dbType,e)).executeQuery({sql:a,params:n,type:"UPDATE",allowBulkUpdate:!1})},yr=async(e,t)=>{let r=await de(t.datasourceId);if(!r)throw new i(404,"Data source not found");if(!r.allowInsert)throw new i(403,"This datasource does not allow insert operations");let o=mr(t.table,r);o.setValues(t.values);let{sql:a,params:n}=o.build();return(await M(B(r,!0),r.dbType,e)).executeQuery({sql:a,type:"INSERT",params:n,allowBulkUpdate:!1})};async function de(e){return E.findOne({where:{id:e},select:["id","dbType","dbDatabase","dbPassword","dbPasswordTag","dbPasswordIv","dbPort","dbUrl","dbSchema","dbUser","allowUpdate","allowInsert"]})}var Tr=e=>{},Ho=["--",";","DROP","drop"],gr=([e,t])=>{if(typeof t=="string"&&t.startsWith("=")){let r=t;Ho.forEach(o=>{if(r.includes(o))throw new i(400,"Invalid input value for "+e)})}},hr=e=>{if(!e.table)throw new i(400,"Table is required");Object.entries(e.values).forEach(gr)},wr=e=>{if(!e.table)throw new i(400,"Table is required");Object.entries(e.values).forEach(gr)};var Sr=h(e=>{e.route({method:"post",url:"/:dsId/select",handler:async t=>{let r=y(t,Tr);return{data:await le(t,r)}}}),e.route({method:"get",url:"/:dsId/entity/:table",handler:async t=>{let{dsId:r,table:o}=f(t),a=_(t);return{data:await pr(t,{table:o,dataSourceId:r,props:a})}}}),e.route({method:"post",url:"/:dsId/insert",config:{requireRole:b("editor")},handler:async t=>{let r=y(t,hr);return{data:await yr(t,r)}}}),e.route({method:"post",url:"/:dsId/update",config:{requireRole:b("editor")},handler:async t=>{let r=y(t,wr);return{data:await fr(t,r)}}})});var br=h(e=>{e.get("/",{config:{isPublic:!0}},async()=>({data:{active:!0,version:T.str("SERVER_VERSION")}}))});var Er=h(e=>{e.route({method:"get",url:"/:id/users",handler:async t=>{let{id:r}=f(t),o=await k.findOne({where:{id:r},relations:{users:{user:!0}}});if(!o)throw new i(404,"Team not found");return{data:o.users.map(a=>({role:a.role,id:a.user.id,name:a.user.username}))}}}),e.route({method:"post",url:"/",config:{requireRole:b("editor")},handler:async t=>w.transaction(async()=>{let r=t.user.id,o=y(t),a=S.create();a.id=r;let n=k.create(o);await k.save(n);let s=C.create({user:a,team:n});return await C.save(s),{data:n}})}),e.route({method:"patch",url:"/:id/user-role",config:{requireRole:b("admin")},handler:async t=>{let{id:r}=f(t),{role:o,userId:a}=y(t,({role:s})=>{if(s==="owner")throw new i(400,"Only one owner is allowed")});if((await C.findOneBy({user:{id:a},team:{id:r}}))?.role==="owner")throw new i(400,"Cannot change owner role");await C.update({user:{id:a},team:{id:r}},{role:o})}}),e.route({method:"delete",url:"/:id",config:{requireRole:b("admin")},handler:async t=>w.transaction(async()=>{let{id:r}=f(t),{userId:o}=_(t);if((await C.findOneBy({user:{id:o},team:{id:r}}))?.role==="owner")throw new i(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 Le=O(require("bcryptjs")),J=async e=>{let t=await Le.default.genSalt(10);return Le.default.hash(e,t)};var Ir=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 i(404,"User not found");return{data:{id:r.id,teamId:r.currentTeam?.team.id,teamName:r.currentTeam?.team.name,teamRole:r.currentTeam?.role,username:r.username}}}}),e.route({method:"patch",url:"/",handler:async t=>{let r=t.user.id,o=y(t);if(o.password&&(o.password=await J(o.password)),!(await S.update(r,o)).affected)throw new i(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:b("admin")},handler:async t=>w.transaction(async()=>{let r=y(t),o=await J(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 Rr=h(e=>{e.route({method:"get",url:"/",handler:async t=>{let r=t.user.id,o=await $.findOneBy({user:{id:r}});return o||(o=await $.save($.create({user:{id:r}}))),{data:o}}}),e.route({method:"patch",url:"/",handler:async t=>{let{settings:r}=y(t);if(!r.id)throw new i(400,"Settings id is required!");if(!(await $.update(r.id,r)).affected)throw new i(404,"You do not own these settings!");return{data:await $.findOneBy({id:r.id})}}})});function G(e,...t){let r=[...t];if(e.searchAll&&r.push(e.searchAll),e.filters)for(let o of e.filters)o.value&&r.push(o.value);return r.map(o=>o.toLowerCase()).join(",")}var Cr=h(e=>{e.route({method:"post",url:"/",config:{requireRole:b("editor")},handler:async t=>{let r=y(t),o=await I.findOne({where:{id:r.queryId}});if(!o)throw new i(400,"Query not found");let a=await v.save(v.create({isPersonal:!1,team:{id:t.user.currentTeamId},user:{id:t.user.id},query:{id:r.queryId},searchString:G(o.opts,r.name)}));return await I.update(r.queryId,{name:r.name}),{data:a}}}),e.route({method:"delete",url:"/:id",config:{requireRole:b("editor")},handler:async t=>{let{id:r}=f(t);if(!(await v.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}=f(t),o=y(t,s=>{if(!s.name)throw new i(400,"Name is required")}),a=await v.findOne({where:{id:r},relations:{query:!0}});if(!a)throw new i(400,"Query not found");let n=G(a.query.opts,o.name);return await Promise.all([v.update({id:r},{searchString:n}),I.update({id:a.query.id},{name:o.name})]),{data:!0}})})});var Nr=e=>{if(!e.queryId&&!(e.opts&&e.name))throw new i(400,"Either queryId or name and opts are required")};var Ar=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}=f(t),{currentTeamId:o,id:a}=t.user,n=await A.findOne({where:{id:r,team:{id:o},user:{id:a}}});if(!n)throw new i(404,"Not Found");return{data:n}}}),e.route({method:"post",url:"/",handler:async t=>{let{opts:r,name:o,queryId:a}=y(t,Nr),n,s,u=o;if(r)s=r.dataSourceId,n=r;else{let m=await I.findOne({where:{id:a},relations:{dataSource:!0}});if(!m)throw new i(404,"Query not Found");s=m.dataSource.id,n={table:m.opts.table,filters:m.opts.filters,joins:m.opts.joins,orderBy:m.opts.orderBy,columns:m.opts.columns,groupBy:m.opts.groupBy,searchAll:m.opts.searchAll,aggregations:m.opts.aggregations,dataSourceId:m.dataSource.id,page:0,size:50},o||(u=m.name)}return{data:await A.save(A.create({name:u||new Date().toISOString(),opts:n||{},dataSource:{id:s},user:{id:t.user.id},team:{id:t.user.currentTeamId}}))}}}),e.route({method:"post",url:"/:id/run",handler:async t=>{let{id:r}=f(t),o=y(t),a=await A.findOne({where:{id:r},relations:{user:!0}});if(!a)throw new i(404,"Not found");if(a.user?.id!==t.user.id)throw new i(404,"Not found");return o&&A.update(r,{opts:o||{},searchString:G(o,a.name),updatedAt:new Date}),{data:{result:await le(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}=f(t),o=y(t),a=await A.findOne({where:{id:r,user:{id:t.user.id}}});if(!a)throw new i(404,"Not Found");let n=a.searchString;return o.name&&(n=G(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}=f(t),o=t.user.id;return await A.delete({id:r,user:{id:o}}),{data:!0}}})});var Dr=require("node:crypto");var Pr=require("node:crypto"),Or={teamName:"Default Team",username:"admin"},Yo=async()=>{let e=await k.findOneBy({});return e||k.save(k.create({name:Or.teamName}))},pe=async e=>{let t=await C.findOne({where:{role:"owner"},relations:{user:!0}});if(t)return t.user;let r=await Yo(),o=await J(e?.password||(0,Pr.randomBytes)(32).toString("hex")),a=await S.save(S.create({username:e?.name||Or.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 fe={setupAccessToken:void 0},xr=()=>(fe.setupAccessToken=(0,Dr.randomBytes)(32).toString("hex"),fe.setupAccessToken),Go=e=>{if(!fe.setupAccessToken)throw new i(400,"Setup already performed");if(!e||e!==fe.setupAccessToken)throw new i(400,"Invalid setup access token")},F=async()=>D.skipAuth?!1:await S.count()<1,vr=async e=>{Go(e.setupAccessToken),await pe({name:e.userName,password:e.userPassword})};var _r=h(e=>{e.route({method:"get",url:"/client.config.js",handler:(t,r)=>{let o={skipAuth:D.skipAuth,modeName:D.name,usesCustomDb:$e(),serverVersion:T.str("SERVER_VERSION","--")};return r.type("application/javascript").send(`window.__CLIENT_CONFIG__ = ${JSON.stringify(o)};`)}}),e.route({method:"get",url:"/",handler:async(t,r)=>await F()?r.redirect("/setup"):r.sendFile("index.html")}),e.route({method:"get",url:"/setup",handler:async(t,r)=>await F()?r.sendFile("setup.html"):r.redirect("/")})});var Ur=e=>{if(!e.setupAccessToken)throw new i(400,"Invalid setup access token");if(!e.userPassword||e.userPassword.length<8)throw new i(400,"Password should be at least 8 chars long");if(!e.userName)throw new i(400,"User name is required")};var Lr=h(e=>{e.route({method:"post",url:"/",config:{isPublic:!0},handler:async t=>{if(!await F())throw new i(400,"Setup has already been completed");let o=y(t,Ur);return await vr(o),{data:!0}}})});var jo=[[_r,"/"],[pt,"/api/auth"],[Yt,"/api/data-sources"],[Gt,"/api/project"],[jt,"/api/queries"],[Sr,"/api/runner"],[br,"/api/status"],[Er,"/api/teams"],[Ir,"/api/users"],[Rr,"/api/user-settings"],[Cr,"/api/saved-queries"],[Ar,"/api/workbench-tabs"],[Lr,"/api/setup"]],qr=e=>{for(let[t,r]of jo)e.register(t,{prefix:r}),console.log("Registered "+r)};var Ko=e=>e.routeOptions.config.isPublic?!0:!e.url.startsWith("/api/"),Vo=async()=>C.findOne({where:{role:"owner"},relations:{user:!0,team:!0}}),zo=async e=>{let t=await Vo();if(!t)throw new i(401,"User is not part of a team");e.user={id:t.user.id,currentTeamId:t.team.id,currentTeamRole:t.role}},Jo=async e=>{let t=e.headers.authorization;if(!t)throw new i(401,"Missing auth token");let[r,o]=t.split(" "),{userId:a}=await ct(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 i(401,"Unauthorized");e.user={id:a,currentTeamId:n.currentTeam.team.id,currentTeamRole:n.currentTeam.role}},kr=async e=>{Ko(e)||(D.skipAuth?await zo(e):await Jo(e))};var Mr=(e,t)=>{e.__connections&&e.__connections.forEach(r=>{r.close()})};var Br=e=>{e.addHook("onRequest",kr),e.addHook("onRequest",Ht),e.addHook("onResponse",Mr)};var Qr=e=>{e.setNotFoundHandler((t,r)=>{if(t.raw.url?.startsWith("/api/")){r.code(404).send({error:"API route not found"});return}r.sendFile("index.html")}),e.setErrorHandler((t,r,o)=>{console.error(t),t instanceof i?o.status(t.status).send({error:t.message}):o.status(500).send({error:"Internal Server Error"})})};var Fr=O(require("@fastify/cookie")),$r=O(require("@fastify/cors"));var Wr=O(require("@fastify/static")),Hr=require("node:path"),Yr=e=>{e.register(Fr.default,{}),e.register($r.default,{origin:j.allowedOrigins,methods:["GET","POST","PUT","PATCH","DELETE","OPTIONS"],credentials:!0}),e.register(Wr.default,{root:(0,Hr.join)(__dirname,"web")})};(async function(){let t=(0,Gr.default)({querystringParser:o=>jr.default.parse(o)});if(Fe(),Yr(t),Br(t),qr(t),Qr(t),await t.after(),await rt(),t.listen({port:j.port,host:j.host},(o,a)=>{o&&(console.error(o),process.exit(1)),console.log(`Server listening at ${a}`)}),await F()){let o=xr();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 pe()})();
|
|
@@ -187,4 +187,4 @@ to {
|
|
|
187
187
|
> * {
|
|
188
188
|
pointer-events: auto;
|
|
189
189
|
}
|
|
190
|
-
`,bi=16,cb=({reverseOrder:a,position:c="top-center",toastOptions:s,gutter:f,children:o,toasterId:y,containerStyle:h,containerClassName:m})=>{let{toasts:E,handlers:v}=t1(s,y);return at.createElement("div",{"data-rht-toaster":y||"",style:{position:"fixed",zIndex:9999,top:bi,left:bi,right:bi,bottom:bi,pointerEvents:"none",...h},className:m,onMouseEnter:v.startPause,onMouseLeave:v.endPause},E.map(T=>{let _=T.position||c,j=v.calculateOffset(T,{reverseOrder:a,gutter:f,defaultPosition:c}),Z=O1(_,j);return at.createElement(A1,{id:T.id,key:T.id,onHeightUpdate:v.updateHeight,className:T.visible?z1:"",style:Z},T.type==="custom"?_i(T.message,T):o?o(T):at.createElement(T1,{toast:T,position:_}))}))},_1=Qt;const D1=new sp({defaultOptions:{queries:{staleTime:1e3*60*5,retry:(a,c)=>bf(c)&&c.response?.status===404?!1:a<3}},mutationCache:new Ay({onError:a=>{bf(a)&&a.status&&a.status>=400&&a.status<500&&a.response?.data.error&&_1.error(a.response.data.error)}})}),R1=async()=>{if(__CLIENT_CONFIG__.skipAuth)return"dummy-refresh-token";const{data:a}=await Cf.post("/auth/refresh");return a.data.accessToken},M1=async a=>{const{data:c}=await Cf.post("/auth/login",a);return c.data.accessToken},yy=()=>{D1.invalidateQueries({queryKey:["accessToken"]})},em=(()=>{let a=Promise.resolve(wg()),c=!1;const s=async()=>{await Cf.post("/auth/logout"),gi(void 0),window.location.reload()};return{get:async()=>a,refresh:()=>(c||(c=!0,a=R1().then(h=>(gi(h),h)).catch(()=>{gi(void 0),s()}).finally(()=>{c=!1,yy()})),a),login:h=>(c||(c=!0,a=M1(h).then(m=>(gi(m),m)).finally(()=>{c=!1,yy()})),a),logout:s}})(),lm=Mt.create({baseURL:"/api",withCredentials:!0});lm.interceptors.request.use(async a=>{const c=await em.get();return c&&(a.headers.Authorization=`Bearer ${c}`),a});lm.interceptors.response.use(a=>a,a=>(bf(a)&&a.status===401&&a?.response?.data.error!=="Missing auth token"&&em.refresh(),Promise.reject(a)));const Cf=Mt.create({baseURL:"/api",withCredentials:!0}),U1="
|
|
190
|
+
`,bi=16,cb=({reverseOrder:a,position:c="top-center",toastOptions:s,gutter:f,children:o,toasterId:y,containerStyle:h,containerClassName:m})=>{let{toasts:E,handlers:v}=t1(s,y);return at.createElement("div",{"data-rht-toaster":y||"",style:{position:"fixed",zIndex:9999,top:bi,left:bi,right:bi,bottom:bi,pointerEvents:"none",...h},className:m,onMouseEnter:v.startPause,onMouseLeave:v.endPause},E.map(T=>{let _=T.position||c,j=v.calculateOffset(T,{reverseOrder:a,gutter:f,defaultPosition:c}),Z=O1(_,j);return at.createElement(A1,{id:T.id,key:T.id,onHeightUpdate:v.updateHeight,className:T.visible?z1:"",style:Z},T.type==="custom"?_i(T.message,T):o?o(T):at.createElement(T1,{toast:T,position:_}))}))},_1=Qt;const D1=new sp({defaultOptions:{queries:{staleTime:1e3*60*5,retry:(a,c)=>bf(c)&&c.response?.status===404?!1:a<3}},mutationCache:new Ay({onError:a=>{bf(a)&&a.status&&a.status>=400&&a.status<500&&a.response?.data.error&&_1.error(a.response.data.error)}})}),R1=async()=>{if(__CLIENT_CONFIG__.skipAuth)return"dummy-refresh-token";const{data:a}=await Cf.post("/auth/refresh");return a.data.accessToken},M1=async a=>{const{data:c}=await Cf.post("/auth/login",a);return c.data.accessToken},yy=()=>{D1.invalidateQueries({queryKey:["accessToken"]})},em=(()=>{let a=Promise.resolve(wg()),c=!1;const s=async()=>{await Cf.post("/auth/logout"),gi(void 0),window.location.reload()};return{get:async()=>a,refresh:()=>(c||(c=!0,a=R1().then(h=>(gi(h),h)).catch(()=>{gi(void 0),s()}).finally(()=>{c=!1,yy()})),a),login:h=>(c||(c=!0,a=M1(h).then(m=>(gi(m),m)).finally(()=>{c=!1,yy()})),a),logout:s}})(),lm=Mt.create({baseURL:"/api",withCredentials:!0});lm.interceptors.request.use(async a=>{const c=await em.get();return c&&(a.headers.Authorization=`Bearer ${c}`),a});lm.interceptors.response.use(a=>a,a=>(bf(a)&&a.status===401&&a?.response?.data.error!=="Missing auth token"&&em.refresh(),Promise.reject(a)));const Cf=Mt.create({baseURL:"/api",withCredentials:!0}),U1="_alert_1hze3_2",C1="_info_1hze3_2",N1="_danger_1hze3_2",H1="_success_1hze3_2",q1="_warning_1hze3_2",x1="_dark_1hze3_2",Vn={alert:U1,info:C1,danger:N1,success:H1,warning:q1,dark:x1};function nm(a){var c,s,f="";if(typeof a=="string"||typeof a=="number")f+=a;else if(typeof a=="object")if(Array.isArray(a)){var o=a.length;for(c=0;c<o;c++)a[c]&&(s=nm(a[c]))&&(f&&(f+=" "),f+=s)}else for(s in a)a[s]&&(f&&(f+=" "),f+=s);return f}function B1(){for(var a,c,s=0,f="",o=arguments.length;s<o;s++)(a=arguments[s])&&(c=nm(a))&&(f&&(f+=" "),f+=c);return f}const sb=({variant:a,noRounded:c,className:s,children:f,...o})=>Mv.jsx("div",{className:B1(Vn.alert,!c&&"rounded-lg",(a==="info"||!a)&&Vn.info,a==="danger"&&Vn.danger,a==="dark"&&Vn.dark,a==="warning"&&Vn.warning,a==="success"&&Vn.success,s),role:"alert",...o,children:f}),fb=a=>{const[c,s]=at.useState(a),[f,o]=at.useState([]),y=at.useRef(a),h=at.useCallback((v,T)=>{s(_=>({..._,[v]:T}))},[]),m=at.useCallback(v=>T=>{T.target.type==="checkbox"?h(v,T.target.checked):h(v,T.target.value),o(_=>_.includes(v)?_:[..._,v])},[h]),E=at.useCallback(()=>{s(y.current),o([])},[]);return[c,{set:h,change:m,reset:E,touched:f}]};export{em as A,B1 as B,fb as C,sb as D,_1 as E,J1 as F,my as G,w1 as H,cb as I,Cf as J,j1 as R,Di as S,qv as a,Zv as b,of as c,Gv as d,rf as e,gy as f,ap as g,Jv as h,Ri as i,te as j,$h as k,X1 as l,G1 as m,Be as n,Va as o,Pv as p,ip as q,at as r,Q1 as s,Xv as t,Mv as u,Y1 as v,D1 as w,lm as x,bf as y,L1 as z};
|
|
@@ -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-600:oklch(62.7% .194 149.214);--color-green-800:oklch(44.8% .119 151.328);--color-blue-50:oklch(97% .014 254.604);--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-auto_1hze3_2{pointer-events:auto}._pointer-events-none_1hze3_2{pointer-events:none}._visible_1hze3_2{visibility:visible}._sr-only_1hze3_2{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}._absolute_1hze3_2{position:absolute}._relative_1hze3_2{position:relative}._sticky_1hze3_2{position:sticky}._top-0_1hze3_2{top:calc(var(--spacing)*0)}._top-2_1hze3_2{top:calc(var(--spacing)*2)}._right-2_1hze3_2{right:calc(var(--spacing)*2)}._z-0_1hze3_2{z-index:0}._z-1_1hze3_2{z-index:1}._z-10_1hze3_2{z-index:10}._z-100_1hze3_2{z-index:100}._col-span-2_1hze3_2{grid-column:span 2/span 2}._m-2_1hze3_2{margin:calc(var(--spacing)*2)}._mx-1_1hze3_2{margin-inline:calc(var(--spacing)*1)}._mx-2_1hze3_2{margin-inline:calc(var(--spacing)*2)}._mx-auto_1hze3_2{margin-inline:auto}._my-2_1hze3_2{margin-block:calc(var(--spacing)*2)}._my-10_1hze3_2{margin-block:calc(var(--spacing)*10)}._mt-1_1hze3_2{margin-top:calc(var(--spacing)*1)}._mt-2_1hze3_2{margin-top:calc(var(--spacing)*2)}._mt-4_1hze3_2{margin-top:calc(var(--spacing)*4)}._mt-8_1hze3_2{margin-top:calc(var(--spacing)*8)}._mt-10_1hze3_2{margin-top:calc(var(--spacing)*10)}._mr-1_1hze3_2{margin-right:calc(var(--spacing)*1)}._mr-2_1hze3_2{margin-right:calc(var(--spacing)*2)}._mb-0\.5_1hze3_2{margin-bottom:calc(var(--spacing)*.5)}._mb-1_1hze3_2{margin-bottom:calc(var(--spacing)*1)}._mb-2_1hze3_2{margin-bottom:calc(var(--spacing)*2)}._mb-4_1hze3_2{margin-bottom:calc(var(--spacing)*4)}._mb-10_1hze3_2{margin-bottom:calc(var(--spacing)*10)}._ml-1_1hze3_2{margin-left:calc(var(--spacing)*1)}._block_1hze3_2{display:block}._flex_1hze3_2{display:flex}._grid_1hze3_2{display:grid}._hidden_1hze3_2{display:none}._table_1hze3_2{display:table}._h-0\.5_1hze3_2{height:calc(var(--spacing)*.5)}._h-1_1hze3_2{height:calc(var(--spacing)*1)}._h-8_1hze3_2{height:calc(var(--spacing)*8)}._h-screen_1hze3_2{height:100vh}._max-h-full_1hze3_2{max-height:100%}._max-h-screen_1hze3_2{max-height:100vh}._min-h-screen_1hze3_2{min-height:100vh}._w-8_1hze3_2{width:calc(var(--spacing)*8)}._w-full_1hze3_2{width:100%}._max-w-none_1hze3_2{max-width:none}._max-w-xl_1hze3_2{max-width:var(--container-xl)}._flex-1_1hze3_2{flex:1}._rotate-180_1hze3_2{rotate:180deg}._transform_1hze3_2{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}._animate-spin_1hze3_2{animation:var(--animate-spin)}._cursor-auto\!_1hze3_2{cursor:auto!important}._cursor-pointer_1hze3_2{cursor:pointer}._grid-cols-2_1hze3_2{grid-template-columns:repeat(2,minmax(0,1fr))}._grid-cols-4_1hze3_2{grid-template-columns:repeat(4,minmax(0,1fr))}._flex-col_1hze3_2{flex-direction:column}._items-center_1hze3_2{align-items:center}._justify-between_1hze3_2{justify-content:space-between}._justify-center_1hze3_2{justify-content:center}._justify-end_1hze3_2{justify-content:flex-end}._gap-1_1hze3_2{gap:calc(var(--spacing)*1)}._gap-2_1hze3_2{gap:calc(var(--spacing)*2)}._gap-8_1hze3_2{gap:calc(var(--spacing)*8)}._justify-self-center_1hze3_2{justify-self:center}._justify-self-end_1hze3_2{justify-self:flex-end}._truncate_1hze3_2{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}._overflow-auto_1hze3_2{overflow:auto}._overflow-hidden_1hze3_2{overflow:hidden}._overflow-x-auto_1hze3_2{overflow-x:auto}._overflow-y-auto_1hze3_2{overflow-y:auto}._rounded_1hze3_2{border-radius:.25rem}._rounded-full_1hze3_2{border-radius:3.40282e38px}._rounded-lg_1hze3_2{border-radius:var(--radius-lg)}._rounded-md_1hze3_2{border-radius:var(--radius-md)}._rounded-t-md_1hze3_2{border-top-left-radius:var(--radius-md);border-top-right-radius:var(--radius-md)}._rounded-r-none\!_1hze3_2{border-top-right-radius:0!important;border-bottom-right-radius:0!important}._rounded-b-lg_1hze3_2{border-bottom-right-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-lg)}._rounded-b-md_1hze3_2{border-bottom-right-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}._border_1hze3_2{border-style:var(--tw-border-style);border-width:1px}._border-t_1hze3_2{border-top-style:var(--tw-border-style);border-top-width:1px}._border-b_1hze3_2{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}._border-gray-200_1hze3_2{border-color:var(--color-gray-200)}._border-red-600_1hze3_2{border-color:var(--color-red-600)}._border-t-gray-200_1hze3_2{border-top-color:var(--color-gray-200)}._bg-\(--bg\)_1hze3_2{background-color:var(--bg)}._bg-gray-50_1hze3_2{background-color:var(--color-gray-50)}._bg-gray-100_1hze3_2{background-color:var(--color-gray-100)}._bg-gray-800_1hze3_2{background-color:var(--color-gray-800)}._bg-gray-900_1hze3_2{background-color:var(--color-gray-900)}._bg-green-200_1hze3_2{background-color:var(--color-green-200)}._bg-white_1hze3_2{background-color:var(--color-white)}._bg-yellow-200_1hze3_2{background-color:var(--color-yellow-200)}._fill-blue-600_1hze3_2{fill:var(--color-blue-600)}._p-0\.5_1hze3_2{padding:calc(var(--spacing)*.5)}._p-1_1hze3_2{padding:calc(var(--spacing)*1)}._p-2_1hze3_2{padding:calc(var(--spacing)*2)}._p-4_1hze3_2{padding:calc(var(--spacing)*4)}._px-1\.5_1hze3_2{padding-inline:calc(var(--spacing)*1.5)}._px-2_1hze3_2{padding-inline:calc(var(--spacing)*2)}._px-4_1hze3_2{padding-inline:calc(var(--spacing)*4)}._py-0\.5_1hze3_2{padding-block:calc(var(--spacing)*.5)}._py-1_1hze3_2{padding-block:calc(var(--spacing)*1)}._py-2_1hze3_2{padding-block:calc(var(--spacing)*2)}._py-4_1hze3_2{padding-block:calc(var(--spacing)*4)}._py-10_1hze3_2{padding-block:calc(var(--spacing)*10)}._pb-24_1hze3_2{padding-bottom:calc(var(--spacing)*24)}._pl-5\!_1hze3_2{padding-left:calc(var(--spacing)*5)!important}._text-center_1hze3_2{text-align:center}._text-left_1hze3_2{text-align:left}._font-mono_1hze3_2{font-family:var(--font-mono)}._text-3xl_1hze3_2{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}._text-lg_1hze3_2{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}._text-sm_1hze3_2{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}._text-xl_1hze3_2{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}._text-xs_1hze3_2{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}._text-xs\!_1hze3_2{font-size:var(--text-xs)!important;line-height:var(--tw-leading,var(--text-xs--line-height))!important}._font-semibold_1hze3_2{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}._whitespace-nowrap_1hze3_2{white-space:nowrap}._text-\(--text-color-primary\)_1hze3_2{color:var(--text-color-primary)}._text-\(--text-color-secondary\)_1hze3_2{color:var(--text-color-secondary)}._text-black\/30_1hze3_2{color:#0000004d}@supports (color:color-mix(in lab,red,red)){._text-black\/30_1hze3_2{color:color-mix(in oklab,var(--color-black)30%,transparent)}}._text-blue-600_1hze3_2{color:var(--color-blue-600)}._text-blue-800_1hze3_2{color:var(--color-blue-800)}._text-gray-100_1hze3_2{color:var(--color-gray-100)}._text-gray-200_1hze3_2{color:var(--color-gray-200)}._text-gray-300_1hze3_2{color:var(--color-gray-300)}._text-gray-600_1hze3_2{color:var(--color-gray-600)}._text-green-600_1hze3_2{color:var(--color-green-600)}._text-green-800_1hze3_2{color:var(--color-green-800)}._text-red-500_1hze3_2{color:var(--color-red-500)}._text-red-600_1hze3_2{color:var(--color-red-600)}._text-white_1hze3_2{color:var(--color-white)}._text-yellow-800_1hze3_2{color:var(--color-yellow-800)}._capitalize_1hze3_2{text-transform:capitalize}._italic_1hze3_2{font-style:italic}._underline_1hze3_2{text-decoration-line:underline}._opacity-30_1hze3_2{opacity:.3}._opacity-40_1hze3_2{opacity:.4}._shadow-md_1hze3_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_1hze3_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_1hze3_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,)}._outline-none_1hze3_2{--tw-outline-style:none;outline-style:none}@media(hover:hover){._hover\:bg-\(--bg-sec\)_1hze3_2:hover{background-color:var(--bg-sec)}._hover\:bg-\(--bg-ter\)_1hze3_2:hover{background-color:var(--bg-ter)}._hover\:bg-gray-100_1hze3_2:hover{background-color:var(--color-gray-100)}._hover\:bg-gray-600_1hze3_2:hover{background-color:var(--color-gray-600)}}@media(min-width:48rem){._md\:grid_1hze3_2{display:grid}._md\:w-2xl_1hze3_2{width:var(--container-2xl)}._md\:grid-cols-3_1hze3_2{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:64rem){._lg\:w-lg_1hze3_2{width:var(--container-lg)}._lg\:w-md_1hze3_2{width:var(--container-md)}._lg\:w-sm_1hze3_2{width:var(--container-sm)}._lg\:flex-row_1hze3_2{flex-direction:row}._lg\:items-center_1hze3_2{align-items:center}._lg\:pb-12_1hze3_2{padding-bottom:calc(var(--spacing)*12)}}@media(prefers-color-scheme:dark){._dark\:text-gray-600_1hze3_2{color:var(--color-gray-600)}}}._alert_1hze3_2{padding:calc(var(--spacing)*4);font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}._info_1hze3_2{background-color:var(--color-blue-50);color:var(--color-blue-800)}._danger_1hze3_2{background-color:var(--color-red-50);color:var(--color-red-800)}._success_1hze3_2{background-color:var(--color-green-50);color:var(--color-green-800)}._warning_1hze3_2{background-color:var(--color-yellow-50);color:var(--color-yellow-800)}._dark_1hze3_2{background-color:var(--color-gray-50);color:var(--color-gray-800)}@keyframes _spin_1hze3_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-600:oklch(62.7% .194 149.214);--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-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-auto{pointer-events:auto}.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}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.top-0{top:calc(var(--spacing)*0)}.top-2{top:calc(var(--spacing)*2)}.right-2{right:calc(var(--spacing)*2)}.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-1{margin-inline:calc(var(--spacing)*1)}.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-1{margin-right:calc(var(--spacing)*1)}.mr-2{margin-right:calc(var(--spacing)*2)}.mb-0\.5{margin-bottom:calc(var(--spacing)*.5)}.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)}.ml-1{margin-left:calc(var(--spacing)*1)}.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)}.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-auto\!{cursor:auto!important}.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-full{border-radius:3.40282e38px}.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-r-none\!{border-top-right-radius:0!important;border-bottom-right-radius:0!important}.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-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-gray-200{border-color:var(--color-gray-200)}.border-red-600{border-color:var(--color-red-600)}.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-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-green-600{color:var(--color-green-600)}.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,)}.outline-none{--tw-outline-style:none;outline-style:none}@media(hover:hover){.hover\:bg-\(--bg-sec\):hover{background-color:var(--bg-sec)}.hover\:bg-\(--bg-ter\):hover{background-color:var(--bg-ter)}.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-md{width:var(--container-md)}.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);background-color:var(--color-white);padding:calc(var(--spacing)*1);outline-style:var(--tw-outline-style);border-radius:.25rem;outline-width:0}.input:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);--tw-ring-color:var(--color-blue-400);--tw-ring-inset:inset}.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;border-radius:var(--radius-md);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)}.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.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)}}
|