db-studio 1.2.21 → 1.2.22
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/core-dist/assets/{_baseUniq-riwirsMn.js → _baseUniq-BnS4oWxG.js} +1 -1
- package/dist/core-dist/assets/{_pathlessLayout-DmCNfa5q.js → _pathlessLayout-J4rDhSFV.js} +2 -2
- package/dist/core-dist/assets/{_queryId-DuU-RQq2.js → _queryId-BGnLBhn8.js} +1 -1
- package/dist/core-dist/assets/{_table-DKcTbCMo.js → _table-C_4RREBi.js} +1 -1
- package/dist/core-dist/assets/{arc-Bmwb62d7.js → arc-BzayzQuy.js} +1 -1
- package/dist/core-dist/assets/{architectureDiagram-VXUJARFQ-DAdKU_Vv.js → architectureDiagram-VXUJARFQ-CDKgWmU1.js} +1 -1
- package/dist/core-dist/assets/{blockDiagram-VD42YOAC-CKWdAOVU.js → blockDiagram-VD42YOAC-DajA7Gs0.js} +1 -1
- package/dist/core-dist/assets/{c4Diagram-YG6GDRKO-B_sL4HQA.js → c4Diagram-YG6GDRKO-DFgrz0k6.js} +1 -1
- package/dist/core-dist/assets/{cdoe-editor-DAlfFmLj.js → cdoe-editor-Bv60qmc3.js} +1 -1
- package/dist/core-dist/assets/channel-D7_kpMKZ.js +1 -0
- package/dist/core-dist/assets/{chunk-4BX2VUAB-Cce3fVJH.js → chunk-4BX2VUAB-B3yeq0dh.js} +1 -1
- package/dist/core-dist/assets/{chunk-55IACEB6-QBcon4M7.js → chunk-55IACEB6-DFZ6X9qg.js} +1 -1
- package/dist/core-dist/assets/{chunk-B4BG7PRW-BSf5pb79.js → chunk-B4BG7PRW-BmPKklye.js} +1 -1
- package/dist/core-dist/assets/{chunk-DI55MBZ5-DftEFpN1.js → chunk-DI55MBZ5-BA4d2Wbt.js} +1 -1
- package/dist/core-dist/assets/{chunk-FMBD7UC4-4VeSB__T.js → chunk-FMBD7UC4-XJsNmwVW.js} +1 -1
- package/dist/core-dist/assets/{chunk-QN33PNHL-B8h-nEFL.js → chunk-QN33PNHL-CujeLF1b.js} +1 -1
- package/dist/core-dist/assets/{chunk-QZHKN3VN-DMYBfSug.js → chunk-QZHKN3VN-BGMtvFJQ.js} +1 -1
- package/dist/core-dist/assets/{chunk-TZMSLE5B-Ct-1qAdT.js → chunk-TZMSLE5B-JJzEtNYD.js} +1 -1
- package/dist/core-dist/assets/classDiagram-2ON5EDUG-CeZr_QVj.js +1 -0
- package/dist/core-dist/assets/classDiagram-v2-WZHVMYZB-CeZr_QVj.js +1 -0
- package/dist/core-dist/assets/clone-Bq17CDff.js +1 -0
- package/dist/core-dist/assets/{code-block-IT6T5CEO-DA6hEb7Y.js → code-block-IT6T5CEO-mzJGOnKv.js} +1 -1
- package/dist/core-dist/assets/{cose-bilkent-S5V4N54A-CloLjUMy.js → cose-bilkent-S5V4N54A-CG3x36O6.js} +1 -1
- package/dist/core-dist/assets/{dagre-6UL2VRFP-2A2fgc9Z.js → dagre-6UL2VRFP-CUAYXvH9.js} +1 -1
- package/dist/core-dist/assets/{diagram-PSM6KHXK-DPA5DEpE.js → diagram-PSM6KHXK-CjdajvGI.js} +1 -1
- package/dist/core-dist/assets/{diagram-QEK2KX5R-C4bOPS0Q.js → diagram-QEK2KX5R-BwP9Rm7l.js} +1 -1
- package/dist/core-dist/assets/{diagram-S2PKOQOG-tq0GNkdW.js → diagram-S2PKOQOG-RojbbeSs.js} +1 -1
- package/dist/core-dist/assets/{erDiagram-Q2GNP2WA-PM-4jbqi.js → erDiagram-Q2GNP2WA-D9N7nS0_.js} +1 -1
- package/dist/core-dist/assets/{flowDiagram-NV44I4VS-T1UN3giy.js → flowDiagram-NV44I4VS-BD4JG33X.js} +1 -1
- package/dist/core-dist/assets/{ganttDiagram-JELNMOA3-BonXgJoj.js → ganttDiagram-JELNMOA3-D4z9L9nY.js} +1 -1
- package/dist/core-dist/assets/{gitGraphDiagram-NY62KEGX-BuVB_0wZ.js → gitGraphDiagram-NY62KEGX-B2yHGcIC.js} +1 -1
- package/dist/core-dist/assets/{graph-DYVP2SvU.js → graph-CNujjUl6.js} +1 -1
- package/dist/core-dist/assets/index-B4CH9odE.js +1 -0
- package/dist/core-dist/assets/index-Dq7-70tK.js +58 -0
- package/dist/core-dist/assets/{index-C6Oo3d0L.js → index-pzKFI-Vs.js} +1 -1
- package/dist/core-dist/assets/{infoDiagram-WHAUD3N6-CbjR8HY4.js → infoDiagram-WHAUD3N6-BvkFeyEE.js} +1 -1
- package/dist/core-dist/assets/{journeyDiagram-XKPGCS4Q-CCwLC7Dr.js → journeyDiagram-XKPGCS4Q-CkG5moWM.js} +1 -1
- package/dist/core-dist/assets/{kanban-definition-3W4ZIXB7-DUawu5sK.js → kanban-definition-3W4ZIXB7-CfaZK5R9.js} +1 -1
- package/dist/core-dist/assets/{layout-IC-bH2B0.js → layout-CrsquEuM.js} +1 -1
- package/dist/core-dist/assets/{linear-ZJuqjgQK.js → linear-bD-svMHh.js} +1 -1
- package/dist/core-dist/assets/{mermaid-VLURNSYL-CN8SKxCb.js → mermaid-VLURNSYL-BZBKtjwf.js} +4 -4
- package/dist/core-dist/assets/{mermaid.core-CaljvboY.js → mermaid.core-DmainLbW.js} +5 -5
- package/dist/core-dist/assets/{min-DmRs0sgj.js → min-Cs3I0vDk.js} +1 -1
- package/dist/core-dist/assets/{mindmap-definition-VGOIOE7T-fkttDhdk.js → mindmap-definition-VGOIOE7T-COrHba51.js} +1 -1
- package/dist/core-dist/assets/{pieDiagram-ADFJNKIX-ByGngzi8.js → pieDiagram-ADFJNKIX-C_wSihFn.js} +1 -1
- package/dist/core-dist/assets/{quadrantDiagram-AYHSOK5B-DO_C9v_v.js → quadrantDiagram-AYHSOK5B-6QBSTaSf.js} +1 -1
- package/dist/core-dist/assets/{queries.store-DZ-MnOG6.js → queries.store-BqdJNevl.js} +1 -1
- package/dist/core-dist/assets/{requirementDiagram-UZGBJVZJ-BDzpQlVK.js → requirementDiagram-UZGBJVZJ-BmH--ndW.js} +1 -1
- package/dist/core-dist/assets/{runner-tab-CxwQsug8.js → runner-tab-FdI7lq06.js} +3 -3
- package/dist/core-dist/assets/{sankeyDiagram-TZEHDZUN-HnCFDh0I.js → sankeyDiagram-TZEHDZUN-BgePY74D.js} +1 -1
- package/dist/core-dist/assets/{scroll-area-DP3yG54v.js → scroll-area-NHyDhTA5.js} +1 -1
- package/dist/core-dist/assets/{sequenceDiagram-WL72ISMW-ZzL5mp2w.js → sequenceDiagram-WL72ISMW-DyKFIest.js} +1 -1
- package/dist/core-dist/assets/{stateDiagram-FKZM4ZOC-DVgE6W5u.js → stateDiagram-FKZM4ZOC-CoTNg4O5.js} +1 -1
- package/dist/core-dist/assets/stateDiagram-v2-4FDKWEC3-VLFCTZ_U.js +1 -0
- package/dist/core-dist/assets/{timeline-definition-IT6M3QCI-C2z733gB.js → timeline-definition-IT6M3QCI-BvUQ9Pv-.js} +1 -1
- package/dist/core-dist/assets/{treemap-KMMF4GRG-D-vNn6yN.js → treemap-KMMF4GRG-DLmWUMp8.js} +1 -1
- package/dist/core-dist/assets/{xychartDiagram-PRI3JC2R-BGDvUT2K.js → xychartDiagram-PRI3JC2R-3ZAFpM_j.js} +1 -1
- package/dist/core-dist/index.html +1 -1
- package/dist/index.js +19 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/core-dist/assets/channel-pRz1hcM0.js +0 -1
- package/dist/core-dist/assets/classDiagram-2ON5EDUG-Dw839vW9.js +0 -1
- package/dist/core-dist/assets/classDiagram-v2-WZHVMYZB-Dw839vW9.js +0 -1
- package/dist/core-dist/assets/clone-DIzOT_B6.js +0 -1
- package/dist/core-dist/assets/index-BKhtUOFL.js +0 -1
- package/dist/core-dist/assets/index-jesypFsg.js +0 -58
- package/dist/core-dist/assets/stateDiagram-v2-4FDKWEC3-DffmOHiZ.js +0 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var No=Object.defineProperty;var l=(t,e)=>()=>(t&&(e=t(t=0)),e);var vo=(t,e)=>{for(var o in e)No(t,o,{get:e[o],enumerable:!0})};var Ne=l(()=>{"use strict"});var P,ve=l(()=>{"use strict";P={PORT:3333,ENV:".env",VAR_NAME:"DATABASE_URL",BASE_URL:"http://localhost:3333",PROXY_URL:process.env.NODE_ENV==="development"?"http://localhost:8787":"https://db-studio-proxy.husamql3.workers.dev"}});var _e=l(()=>{"use strict"});var Ae,de=l(()=>{"use strict";Ae={AUTHOR:"H\xFCsam \u{1F951} <devhsmq@gmail.com>",AUTHOR_NAME:"H\xFCsam",AUTHOR_AVATAR:"/avocado.png",AUTHOR_USERNAME:"husamql3",AUTHOR_GITHUB_LINK:"https://github.com/husamql3",SITE_DESCRIPTION:"The modern pgAdmin alternative that works with every database.",SITE_KEYWORDS:["database","management","studio","spreadsheet","ai","sql"],SITE_TITLE:"DB Studio",SITE_NAME:"dbstudio.sh",SITE_URL:"https://dbstudio.sh",SITE_X_LINK:"https://x.com/dbstudio_sh",SITE_GITHUB_LINK:"https://github.com/husamql3/db-studio",SITE_DOCS_LINK:"https://dbstudio.sh/docs",SITE_CHANGELOG_LINK:"https://dbstudio.sh/changelog",SITE_ROADMAP_LINK:"https://dbstudio.sh/roadmap",SITE_IMAGE:"/og-image.png",SITE_IMAGE_WIDTH:"1200",SITE_IMAGE_HEIGHT:"630",SITE_IMAGE_ALT:"dbstudio.sh \u2013 Modern database management studio",SITE_COLOR:"#1447e6"}});var $e=l(()=>{"use strict"});var X=l(()=>{"use strict";Ne();ve();_e();de();$e()});import{z as G}from"zod";var We,Ve=l(()=>{"use strict";We=G.object({tableName:G.string("Table name is required"),data:G.record(G.string("Column name is required"),G.any())})});var Be=l(()=>{"use strict"});import{z as K}from"zod";var g,Ko,te,va,Qe,oe,U=l(()=>{"use strict";g=K.object({db:K.string("Database name is required")}),Ko=["pg"],te=K.enum(Ko,{message:"Invalid database type"}),va=g.extend({dbType:te}),Qe=K.object({dbType:te}),oe=K.object({tableName:K.string("Table name is required")})});import{z as W}from"zod";var Ye,Ge=l(()=>{"use strict";U();Ye=W.object({messages:W.array(W.object({role:W.enum(["user","assistant"]),content:W.string("Content is required")})),conversationId:W.string().optional(),db:g.shape.db})});var Je=l(()=>{"use strict"});import{z as x}from"zod";var Wo,Vo,I,Bo,Qo,Ia,be=l(()=>{"use strict";Wo=["text","boolean","number","enum","json","date","array"],Vo=x.enum(Wo),I={text:"text",boolean:"boolean",number:"number",enum:"enum",json:"json",date:"date",array:"array"},Bo=["int","bigint","smallint","numeric","float","double","money","boolean","text","varchar","char","json","jsonb","xml","uuid","date","time","timestamp","timestamptz","interval","bytea","inet","cidr","macaddr","macaddr8","point","line","polygon","array","enum"],Qo=x.enum(Bo),Ia=x.object({columnName:x.string(),dataType:Vo,dataTypeLabel:Qo,isNullable:x.boolean(),columnDefault:x.string().nullable(),isPrimaryKey:x.boolean(),isForeignKey:x.boolean(),referencedTable:x.string().nullable(),referencedColumn:x.string().nullable(),enumValues:x.array(x.string()).nullable()})});function Xe(t){let e=t?.toLowerCase().trim()||"";return e.includes("[]")||e==="date"||e==="time"||e==="time without time zone"||e.startsWith("time(")||e==="timestamp"||e==="timestamp without time zone"||e.startsWith("timestamp(")||e==="timestamp with time zone"||e==="timestamptz"||e.startsWith("timestamp with time zone(")?I.date:e==="integer"||e==="int"||e==="int4"||e==="bigint"||e==="int8"||e==="smallint"||e==="int2"||e==="decimal"||e.startsWith("decimal(")||e==="numeric"||e.startsWith("numeric(")||e==="real"||e==="float4"||e==="double precision"||e==="float8"||e==="float"||e==="serial"||e==="serial4"||e==="bigserial"||e==="serial8"||e==="money"?I.number:e==="boolean"||e==="bool"?I.boolean:e==="json"||e==="jsonb"?I.json:e.startsWith("user-defined")||e==="enum"||e==="text"||e==="xml"?I.text:e==="character varying"||e.startsWith("varchar")||e.startsWith("character varying(")||e==="character"||e.startsWith("char")||e.startsWith("character(")||e==="bpchar"||e==="uuid"||e==="interval"||e.startsWith("interval")||e==="bytea"||e==="point"||e==="line"||e==="polygon"||e==="inet"||e==="cidr"||e==="macaddr"||e==="macaddr8"?I.text:I.text}function Ze(t){if(!t)return d.text;let e=t.toLowerCase().trim();return e==="integer"||e==="int"||e==="int4"||e==="serial"||e==="serial4"?d.int:e==="bigint"||e==="int8"||e==="bigserial"||e==="serial8"?d.bigint:e==="smallint"||e==="int2"?d.smallint:e==="decimal"||e.startsWith("decimal(")||e==="numeric"||e.startsWith("numeric(")?d.numeric:e==="real"||e==="float4"?d.float:e==="double precision"||e==="float8"||e==="float"?d.double:e==="money"?d.money:e==="boolean"||e==="bool"?d.boolean:e==="text"?d.text:e==="character varying"||e.startsWith("varchar")||e.startsWith("character varying(")?d.varchar:e==="character"||e.startsWith("char")||e.startsWith("character(")||e==="bpchar"?d.char:e==="json"?d.json:e==="jsonb"?d.jsonb:e==="xml"?d.xml:e==="uuid"?d.uuid:e==="date"?d.date:e==="time"||e==="time without time zone"||e.startsWith("time(")?d.time:e==="timestamp"||e==="timestamp without time zone"||e.startsWith("timestamp(")?d.timestamp:e==="timestamp with time zone"||e==="timestamptz"||e.startsWith("timestamp with time zone(")?d.timestamptz:e==="interval"||e.startsWith("interval")?d.interval:e==="bytea"?d.bytea:e==="inet"?d.inet:e==="cidr"?d.cidr:e==="macaddr"?d.macaddr:e==="macaddr8"?d.macaddr8:e==="point"?d.point:e==="line"?d.line:e==="polygon"?d.polygon:e.startsWith("array")||e.includes("[]")?d.text:e.startsWith("user-defined")||e==="enum"?d.enum:d.text}var d,et=l(()=>{"use strict";be();d={int:"int",bigint:"bigint",smallint:"smallint",numeric:"numeric",float:"float",double:"double",money:"money",boolean:"boolean",text:"text",varchar:"varchar",char:"char",json:"json",jsonb:"jsonb",xml:"xml",uuid:"uuid",date:"date",time:"time",timestamp:"timestamp",timestamptz:"timestamptz",interval:"interval",bytea:"bytea",inet:"inet",cidr:"cidr",macaddr:"macaddr",macaddr8:"macaddr8",point:"point",line:"line",polygon:"polygon",array:"array",enum:"enum"}});import{z as S}from"zod";var Yo,tt,Go,Jo,ot,rt=l(()=>{"use strict";Yo=["CASCADE","SET NULL","SET DEFAULT","RESTRICT","NO ACTION"],tt=S.enum(Yo),Go=S.object({columnName:S.string("Column name is required"),columnType:S.string("Column type is required"),defaultValue:S.string().optional(),isPrimaryKey:S.boolean().default(!1),isNullable:S.boolean().default(!1),isUnique:S.boolean().default(!1),isIdentity:S.boolean().default(!1),isArray:S.boolean().default(!1)}),Jo=S.object({columnName:S.string("Column name is required"),referencedTable:S.string("Referenced table is required"),referencedColumn:S.string("Referenced column is required"),onUpdate:tt.default("NO ACTION"),onDelete:tt.default("NO ACTION")}),ot=S.object({tableName:S.string("Table name is required"),fields:S.array(Go).min(1,"At least one field is required"),foreignKeys:S.array(Jo).optional()})});import{z as D}from"zod";var Xo,za,at,nt=l(()=>{"use strict";U();Xo=D.object({name:D.string("Name is required"),size:D.string("Size is required"),owner:D.string("Owner is required"),encoding:D.string("Encoding is required")}),za=D.object({databases:D.array(Xo),dbType:te}),at=D.object({version:D.string("Version is required"),database:D.string("Database is required"),user:D.string("User is required"),host:D.string("Host is required").nullable(),port:D.number("Port is required").nullable(),active_connections:D.coerce.number("Active connections is required"),max_connections:D.coerce.number("Max connections is required")})});var st=l(()=>{"use strict"});import{z as N}from"zod";var it,re,Va,Ba,ct=l(()=>{"use strict";U();it=g.extend({cascade:N.string().optional().transform(t=>t==="true")}),re=N.object({tableName:N.string("Table name is required"),columnName:N.string("Column name is required")}),Va=N.object({db:g.shape.db,tableName:re.shape.tableName,columnName:re.shape.columnName,cascade:N.boolean().optional()}),Ba=N.object({message:N.string("Message is required"),tableName:N.string("Table name is required"),columnName:N.string("Column name is required"),deletedCount:N.number("Deleted count is required").default(0)})});import{z as V}from"zod";var he,lt=l(()=>{"use strict";he=V.object({tableName:V.string("Table name is required"),primaryKeys:V.array(V.object({columnName:V.string("Column name is required"),value:V.any()})).min(1,"At least one primary key is required")})});import{z as mt}from"zod";var ut,pt=l(()=>{"use strict";ut=mt.object({query:mt.string("Query is required")})});import{z as Zo}from"zod";var er,dt,ft=l(()=>{"use strict";U();er=["csv","xlsx"],dt=g.extend({format:Zo.enum(er,{message:"Invalid format. Supported formats: csv, xlsx"})})});var yt=l(()=>{"use strict"});import{z as b}from"zod";var an,ae,nn,tr,sn,bt,ht=l(()=>{"use strict";U();an=b.object({columnName:b.string(),operator:b.string(),value:b.string()}),ae=["asc","desc"],nn=b.object({columnName:b.string(),direction:b.enum(ae)}),tr=b.object({limit:b.number(),total:b.number(),hasNextPage:b.boolean(),hasPreviousPage:b.boolean(),nextCursor:b.string().nullable(),prevCursor:b.string().nullable()}),sn=b.object({data:b.array(b.record(b.string(),b.unknown())),meta:tr}),bt=b.object({db:g.shape.db,cursor:b.string().optional(),limit:b.string().optional().default("50").transform(Number),direction:b.enum(ae).optional().default(ae[0]),sort:b.string().optional().transform(t=>{if(!t)return"";try{let e=JSON.parse(t);return Array.isArray(e)?e:t}catch{return t}}),order:b.enum(ae).optional(),filters:b.string().optional().transform(t=>{if(!t)return[];try{return JSON.parse(t)}catch{return[]}})})});import{z as ge}from"zod";var mn,gt=l(()=>{"use strict";mn=ge.object({tableName:ge.string("Table name is required"),rowCount:ge.coerce.number("Row count is required")})});import{z as A}from"zod";var Tt,St=l(()=>{"use strict";Tt=A.object({tableName:A.string("Table name is required"),primaryKey:A.string("Primary key is required").default("id"),updates:A.array(A.object({rowData:A.record(A.string("Column name is required"),A.any()),columnName:A.string("Column name is required"),value:A.any()},{message:"Each update must have a row data, column name, and value."})).min(1,"At least one update is required")})});var L=l(()=>{"use strict";Ve();Be();Ge();Je();et();be();rt();U();nt();st();ct();lt();pt();ft();yt();ht();gt();St()});import{HTTPException as or}from"hono/http-exception";import{DatabaseError as rr}from"pg";import{ZodError as ar}from"zod";function Et(t,e){if(t instanceof or)return t.getResponse();if(t instanceof ar){let o=t.issues[0];return e.json({error:"Validation error",details:o.message},400)}return t instanceof Error&&(t.message.includes("ECONNREFUSED")||t.message.includes("connection refused")||t.message.includes("timeout expired")||t.message.includes("Connection terminated")||t instanceof rr&&t.code?.startsWith("08"))?e.json({error:"Database connection failed",details:t.message},503):e.json({error:t instanceof Error?t.message:"Internal server error"},500)}var Dt,wt=l(()=>{"use strict";Dt=(t,e)=>{if(!t.success){let o=t.error?.issues[0];return e.json({error:"Validation error",details:o?.message??"Unknown validation error"},400)}}});import{Pool as nr}from"pg";var ne,sr,Te,Ct=l(()=>{"use strict";ne=null,sr=()=>{if(!ne){if(!process.env.DATABASE_URL)throw new Error("DATABASE_URL is not set. Please provide a database connection string.");try{ne=new nr({connectionString:process.env.DATABASE_URL}),ne.on("error",t=>{})}catch(t){throw t}}return ne},Te=new Proxy({},{get(t,e){try{return sr()[e]}catch(o){throw o}}})});import{Pool as Rt}from"pg";var Se,xt,y,Ee,C=l(()=>{"use strict";Se=class{pools=new Map;baseConfig=null;constructor(){this.initializeBaseConfig()}detectDbType(e){let o=e.protocol.replace(":","");return"pg"}initializeBaseConfig(){let e=process.env.DATABASE_URL;if(!e)throw new Error("DATABASE_URL is not set. Please provide a database connection string.");try{let o=new URL(e);this.baseConfig={url:e,host:o.hostname,port:Number.parseInt(o.port,10)||5432,user:o.username,password:o.password,dbType:this.detectDbType(o)}}catch(o){throw new Error(`Failed to parse DATABASE_URL: ${o}`)}}getDbType(){if(!this.baseConfig)throw new Error("Base configuration not initialized");return this.baseConfig.dbType}buildConnectionString(e){if(!this.baseConfig)throw new Error("Base configuration not initialized");if(!e){let o=this.baseConfig.url;o&&(e=new URL(o).pathname.slice(1))}try{let o=new URL(this.baseConfig.url);return o.pathname=`/${e}`,o.toString()}catch(o){throw new Error(`Failed to build connection string for database "${e}": ${o instanceof Error?o.message:String(o)}`)}}getPool(e){let o=this.buildConnectionString(e);if(!this.pools.has(o)){let r={connectionString:o,max:10,idleTimeoutMillis:3e4,connectionTimeoutMillis:2e3},a=new Rt(r);a.on("error",n=>{}),this.pools.set(o,a)}return this.pools.get(o)??new Rt({connectionString:o})}async closePool(e){let o=this.pools.get(e);o&&(await o.end(),this.pools.delete(e))}async closePoolByDatabase(e){let o=this.buildConnectionString(e);await this.closePool(o)}async closeAll(){let e=Array.from(this.pools.entries()).map(async([o,r])=>{await r.end()});await Promise.all(e),this.pools.clear()}getActivePools(){return Array.from(this.pools.keys())}},xt=new Se,y=t=>xt.getPool(t),Ee=()=>xt.getDbType()});import{HTTPException as ir}from"hono/http-exception";async function se({tableName:t,db:e}){let o=y(e),r=`
|
|
2
|
+
var No=Object.defineProperty;var l=(t,e)=>()=>(t&&(e=t(t=0)),e);var vo=(t,e)=>{for(var o in e)No(t,o,{get:e[o],enumerable:!0})};var _e=l(()=>{"use strict"});var P,Ae=l(()=>{"use strict";P={PORT:3333,ENV:".env",VAR_NAME:"DATABASE_URL",BASE_URL:"http://localhost:3333",PROXY_URL:process.env.NODE_ENV==="development"?"http://localhost:8787":"https://db-studio-proxy.husamql3.workers.dev"}});var $e=l(()=>{"use strict"});var Pe,ye=l(()=>{"use strict";Pe={AUTHOR:"H\xFCsam \u{1F951} <devhsmq@gmail.com>",AUTHOR_NAME:"H\xFCsam",AUTHOR_AVATAR:"/avocado.png",AUTHOR_USERNAME:"husamql3",AUTHOR_GITHUB_LINK:"https://github.com/husamql3",SITE_DESCRIPTION:"The modern pgAdmin alternative that works with every database.",SITE_KEYWORDS:["database","management","studio","spreadsheet","ai","sql"],SITE_TITLE:"DB Studio",SITE_NAME:"dbstudio.sh",SITE_URL:"https://dbstudio.sh",SITE_X_LINK:"https://x.com/dbstudio_sh",SITE_GITHUB_LINK:"https://github.com/husamql3/db-studio",SITE_DOCS_LINK:"https://dbstudio.sh/docs",SITE_CHANGELOG_LINK:"https://dbstudio.sh/changelog",SITE_ROADMAP_LINK:"https://dbstudio.sh/roadmap",SITE_IMAGE:"/og-image.png",SITE_IMAGE_WIDTH:"1200",SITE_IMAGE_HEIGHT:"630",SITE_IMAGE_ALT:"dbstudio.sh \u2013 Modern database management studio",SITE_COLOR:"#1447e6"}});var qe=l(()=>{"use strict"});var X=l(()=>{"use strict";_e();Ae();$e();ye();qe()});import{z as G}from"zod";var Be,Qe=l(()=>{"use strict";Be=G.object({tableName:G.string("Table name is required"),data:G.record(G.string("Column name is required"),G.any())})});var Ye=l(()=>{"use strict"});import{z as K}from"zod";var g,Ko,te,va,Ge,oe,U=l(()=>{"use strict";g=K.object({db:K.string("Database name is required")}),Ko=["pg"],te=K.enum(Ko,{message:"Invalid database type"}),va=g.extend({dbType:te}),Ge=K.object({dbType:te}),oe=K.object({tableName:K.string("Table name is required")})});import{z as W}from"zod";var Je,Xe=l(()=>{"use strict";U();Je=W.object({messages:W.array(W.object({role:W.enum(["user","assistant"]),content:W.string("Content is required")})),conversationId:W.string().optional(),db:g.shape.db})});var Ze=l(()=>{"use strict"});import{z as x}from"zod";var Wo,Vo,I,Bo,Qo,Ia,ge=l(()=>{"use strict";Wo=["text","boolean","number","enum","json","date","array"],Vo=x.enum(Wo),I={text:"text",boolean:"boolean",number:"number",enum:"enum",json:"json",date:"date",array:"array"},Bo=["int","bigint","smallint","numeric","float","double","money","boolean","text","varchar","char","json","jsonb","xml","uuid","date","time","timestamp","timestamptz","interval","bytea","inet","cidr","macaddr","macaddr8","point","line","polygon","array","enum"],Qo=x.enum(Bo),Ia=x.object({columnName:x.string(),dataType:Vo,dataTypeLabel:Qo,isNullable:x.boolean(),columnDefault:x.string().nullable(),isPrimaryKey:x.boolean(),isForeignKey:x.boolean(),referencedTable:x.string().nullable(),referencedColumn:x.string().nullable(),enumValues:x.array(x.string()).nullable()})});function et(t){let e=t?.toLowerCase().trim()||"";return e.includes("[]")||e==="date"||e==="time"||e==="time without time zone"||e.startsWith("time(")||e==="timestamp"||e==="timestamp without time zone"||e.startsWith("timestamp(")||e==="timestamp with time zone"||e==="timestamptz"||e.startsWith("timestamp with time zone(")?I.date:e==="integer"||e==="int"||e==="int4"||e==="bigint"||e==="int8"||e==="smallint"||e==="int2"||e==="decimal"||e.startsWith("decimal(")||e==="numeric"||e.startsWith("numeric(")||e==="real"||e==="float4"||e==="double precision"||e==="float8"||e==="float"||e==="serial"||e==="serial4"||e==="bigserial"||e==="serial8"||e==="money"?I.number:e==="boolean"||e==="bool"?I.boolean:e==="json"||e==="jsonb"?I.json:e.startsWith("user-defined")||e==="enum"||e==="text"||e==="xml"?I.text:e==="character varying"||e.startsWith("varchar")||e.startsWith("character varying(")||e==="character"||e.startsWith("char")||e.startsWith("character(")||e==="bpchar"||e==="uuid"||e==="interval"||e.startsWith("interval")||e==="bytea"||e==="point"||e==="line"||e==="polygon"||e==="inet"||e==="cidr"||e==="macaddr"||e==="macaddr8"?I.text:I.text}function tt(t){if(!t)return d.text;let e=t.toLowerCase().trim();return e==="integer"||e==="int"||e==="int4"||e==="serial"||e==="serial4"?d.int:e==="bigint"||e==="int8"||e==="bigserial"||e==="serial8"?d.bigint:e==="smallint"||e==="int2"?d.smallint:e==="decimal"||e.startsWith("decimal(")||e==="numeric"||e.startsWith("numeric(")?d.numeric:e==="real"||e==="float4"?d.float:e==="double precision"||e==="float8"||e==="float"?d.double:e==="money"?d.money:e==="boolean"||e==="bool"?d.boolean:e==="text"?d.text:e==="character varying"||e.startsWith("varchar")||e.startsWith("character varying(")?d.varchar:e==="character"||e.startsWith("char")||e.startsWith("character(")||e==="bpchar"?d.char:e==="json"?d.json:e==="jsonb"?d.jsonb:e==="xml"?d.xml:e==="uuid"?d.uuid:e==="date"?d.date:e==="time"||e==="time without time zone"||e.startsWith("time(")?d.time:e==="timestamp"||e==="timestamp without time zone"||e.startsWith("timestamp(")?d.timestamp:e==="timestamp with time zone"||e==="timestamptz"||e.startsWith("timestamp with time zone(")?d.timestamptz:e==="interval"||e.startsWith("interval")?d.interval:e==="bytea"?d.bytea:e==="inet"?d.inet:e==="cidr"?d.cidr:e==="macaddr"?d.macaddr:e==="macaddr8"?d.macaddr8:e==="point"?d.point:e==="line"?d.line:e==="polygon"?d.polygon:e.startsWith("array")||e.includes("[]")?d.text:e.startsWith("user-defined")||e==="enum"?d.enum:d.text}var d,ot=l(()=>{"use strict";ge();d={int:"int",bigint:"bigint",smallint:"smallint",numeric:"numeric",float:"float",double:"double",money:"money",boolean:"boolean",text:"text",varchar:"varchar",char:"char",json:"json",jsonb:"jsonb",xml:"xml",uuid:"uuid",date:"date",time:"time",timestamp:"timestamp",timestamptz:"timestamptz",interval:"interval",bytea:"bytea",inet:"inet",cidr:"cidr",macaddr:"macaddr",macaddr8:"macaddr8",point:"point",line:"line",polygon:"polygon",array:"array",enum:"enum"}});import{z as S}from"zod";var Yo,rt,Go,Jo,at,nt=l(()=>{"use strict";Yo=["CASCADE","SET NULL","SET DEFAULT","RESTRICT","NO ACTION"],rt=S.enum(Yo),Go=S.object({columnName:S.string("Column name is required"),columnType:S.string("Column type is required"),defaultValue:S.string().optional(),isPrimaryKey:S.boolean().default(!1),isNullable:S.boolean().default(!1),isUnique:S.boolean().default(!1),isIdentity:S.boolean().default(!1),isArray:S.boolean().default(!1)}),Jo=S.object({columnName:S.string("Column name is required"),referencedTable:S.string("Referenced table is required"),referencedColumn:S.string("Referenced column is required"),onUpdate:rt.default("NO ACTION"),onDelete:rt.default("NO ACTION")}),at=S.object({tableName:S.string("Table name is required"),fields:S.array(Go).min(1,"At least one field is required"),foreignKeys:S.array(Jo).optional()})});import{z as D}from"zod";var Xo,za,st,it=l(()=>{"use strict";U();Xo=D.object({name:D.string("Name is required"),size:D.string("Size is required"),owner:D.string("Owner is required"),encoding:D.string("Encoding is required")}),za=D.object({databases:D.array(Xo),dbType:te}),st=D.object({version:D.string("Version is required"),database:D.string("Database is required"),user:D.string("User is required"),host:D.string("Host is required").nullable(),port:D.number("Port is required").nullable(),active_connections:D.coerce.number("Active connections is required"),max_connections:D.coerce.number("Max connections is required")})});var ct=l(()=>{"use strict"});import{z as N}from"zod";var lt,re,Va,Ba,mt=l(()=>{"use strict";U();lt=g.extend({cascade:N.string().optional().transform(t=>t==="true")}),re=N.object({tableName:N.string("Table name is required"),columnName:N.string("Column name is required")}),Va=N.object({db:g.shape.db,tableName:re.shape.tableName,columnName:re.shape.columnName,cascade:N.boolean().optional()}),Ba=N.object({message:N.string("Message is required"),tableName:N.string("Table name is required"),columnName:N.string("Column name is required"),deletedCount:N.number("Deleted count is required").default(0)})});import{z as V}from"zod";var Te,ut=l(()=>{"use strict";Te=V.object({tableName:V.string("Table name is required"),primaryKeys:V.array(V.object({columnName:V.string("Column name is required"),value:V.any()})).min(1,"At least one primary key is required")})});import{z as pt}from"zod";var dt,ft=l(()=>{"use strict";dt=pt.object({query:pt.string("Query is required")})});import{z as Zo}from"zod";var er,yt,bt=l(()=>{"use strict";U();er=["csv","xlsx"],yt=g.extend({format:Zo.enum(er,{message:"Invalid format. Supported formats: csv, xlsx"})})});var ht=l(()=>{"use strict"});import{z as b}from"zod";var an,ae,nn,tr,sn,gt,Tt=l(()=>{"use strict";U();an=b.object({columnName:b.string(),operator:b.string(),value:b.string()}),ae=["asc","desc"],nn=b.object({columnName:b.string(),direction:b.enum(ae)}),tr=b.object({limit:b.number(),total:b.number(),hasNextPage:b.boolean(),hasPreviousPage:b.boolean(),nextCursor:b.string().nullable(),prevCursor:b.string().nullable()}),sn=b.object({data:b.array(b.record(b.string(),b.unknown())),meta:tr}),gt=b.object({db:g.shape.db,cursor:b.string().optional(),limit:b.string().optional().default("50").transform(Number),direction:b.enum(ae).optional().default(ae[0]),sort:b.string().optional().transform(t=>{if(!t)return"";try{let e=JSON.parse(t);return Array.isArray(e)?e:t}catch{return t}}),order:b.enum(ae).optional(),filters:b.string().optional().transform(t=>{if(!t)return[];try{return JSON.parse(t)}catch{return[]}})})});import{z as Se}from"zod";var mn,St=l(()=>{"use strict";mn=Se.object({tableName:Se.string("Table name is required"),rowCount:Se.coerce.number("Row count is required")})});import{z as A}from"zod";var Et,Dt=l(()=>{"use strict";Et=A.object({tableName:A.string("Table name is required"),primaryKey:A.string("Primary key is required").default("id"),updates:A.array(A.object({rowData:A.record(A.string("Column name is required"),A.any()),columnName:A.string("Column name is required"),value:A.any()},{message:"Each update must have a row data, column name, and value."})).min(1,"At least one update is required")})});var L=l(()=>{"use strict";Qe();Ye();Xe();Ze();ot();ge();nt();U();it();ct();mt();ut();ft();bt();ht();Tt();St();Dt()});import{HTTPException as or}from"hono/http-exception";import{DatabaseError as rr}from"pg";import{ZodError as ar}from"zod";function wt(t,e){if(t instanceof or)return t.getResponse();if(t instanceof ar){let o=t.issues[0];return e.json({error:"Validation error",details:o.message},400)}return t instanceof Error&&(t.message.includes("ECONNREFUSED")||t.message.includes("connection refused")||t.message.includes("timeout expired")||t.message.includes("Connection terminated")||t instanceof rr&&t.code?.startsWith("08"))?e.json({error:"Database connection failed",details:t.message},503):e.json({error:t instanceof Error?t.message:"Internal server error"},500)}var Ct,Rt=l(()=>{"use strict";Ct=(t,e)=>{if(!t.success){let o=t.error?.issues[0];return e.json({error:"Validation error",details:o?.message??"Unknown validation error"},400)}}});import{Pool as nr}from"pg";var ne,sr,Ee,xt=l(()=>{"use strict";ne=null,sr=()=>{if(!ne){if(!process.env.DATABASE_URL)throw new Error("DATABASE_URL is not set. Please provide a database connection string.");try{ne=new nr({connectionString:process.env.DATABASE_URL}),ne.on("error",t=>{})}catch(t){throw t}}return ne},Ee=new Proxy({},{get(t,e){try{return sr()[e]}catch(o){throw o}}})});import{Pool as Nt}from"pg";var De,vt,y,we,C=l(()=>{"use strict";De=class{pools=new Map;baseConfig=null;constructor(){this.initializeBaseConfig()}detectDbType(e){let o=e.protocol.replace(":","");return"pg"}initializeBaseConfig(){let e=process.env.DATABASE_URL;if(!e)throw new Error("DATABASE_URL is not set. Please provide a database connection string.");try{let o=new URL(e);this.baseConfig={url:e,host:o.hostname,port:Number.parseInt(o.port,10)||5432,user:o.username,password:o.password,dbType:this.detectDbType(o)}}catch(o){throw new Error(`Failed to parse DATABASE_URL: ${o}`)}}getDbType(){if(!this.baseConfig)throw new Error("Base configuration not initialized");return this.baseConfig.dbType}buildConnectionString(e){if(!this.baseConfig)throw new Error("Base configuration not initialized");if(!e){let o=this.baseConfig.url;o&&(e=new URL(o).pathname.slice(1))}try{let o=new URL(this.baseConfig.url);return o.pathname=`/${e}`,o.toString()}catch(o){throw new Error(`Failed to build connection string for database "${e}": ${o instanceof Error?o.message:String(o)}`)}}getPool(e){let o=this.buildConnectionString(e);if(!this.pools.has(o)){let r={connectionString:o,max:10,idleTimeoutMillis:3e4,connectionTimeoutMillis:2e3},a=new Nt(r);a.on("error",n=>{}),this.pools.set(o,a)}return this.pools.get(o)??new Nt({connectionString:o})}async closePool(e){let o=this.pools.get(e);o&&(await o.end(),this.pools.delete(e))}async closePoolByDatabase(e){let o=this.buildConnectionString(e);await this.closePool(o)}async closeAll(){let e=Array.from(this.pools.entries()).map(async([o,r])=>{await r.end()});await Promise.all(e),this.pools.clear()}getActivePools(){return Array.from(this.pools.keys())}},vt=new De,y=t=>vt.getPool(t),we=()=>vt.getDbType()});import{HTTPException as ir}from"hono/http-exception";async function se({tableName:t,db:e}){let o=y(e),r=`
|
|
3
3
|
SELECT
|
|
4
4
|
c.column_name as "columnName",
|
|
5
5
|
c.data_type as "dataType",
|
|
@@ -48,18 +48,18 @@ var No=Object.defineProperty;var l=(t,e)=>()=>(t&&(e=t(t=0)),e);var vo=(t,e)=>{f
|
|
|
48
48
|
WHERE c.table_schema = 'public'
|
|
49
49
|
AND c.table_name = $1
|
|
50
50
|
ORDER BY c.ordinal_position;
|
|
51
|
-
`,{rows:a}=await o.query(r,[t]);if(!a||a.length===0)throw new ir(404,{message:`Table "${t}" does not exist`});return a.map(n=>{let i=null;return n.enumValues&&(Array.isArray(n.enumValues)?i=n.enumValues:typeof n.enumValues=="string"&&(i=n.enumValues.replace(/[{}]/g,"").split(",").filter(Boolean))),{columnName:n.columnName,dataType:
|
|
51
|
+
`,{rows:a}=await o.query(r,[t]);if(!a||a.length===0)throw new ir(404,{message:`Table "${t}" does not exist`});return a.map(n=>{let i=null;return n.enumValues&&(Array.isArray(n.enumValues)?i=n.enumValues:typeof n.enumValues=="string"&&(i=n.enumValues.replace(/[{}]/g,"").split(",").filter(Boolean))),{columnName:n.columnName,dataType:et(n.dataType),dataTypeLabel:tt(n.dataType),isNullable:n.isNullable,columnDefault:n.columnDefault,isPrimaryKey:n.isPrimaryKey,isForeignKey:n.isForeignKey,referencedTable:n.referencedTable,referencedColumn:n.referencedColumn,enumValues:i}})}var Ce=l(()=>{"use strict";L();C()});async function cr(t){let e=y(t),o=`
|
|
52
52
|
SELECT table_name
|
|
53
53
|
FROM information_schema.tables
|
|
54
54
|
WHERE table_schema = 'public'
|
|
55
55
|
AND table_type = 'BASE TABLE'
|
|
56
56
|
ORDER BY table_name;
|
|
57
|
-
`,{rows:r}=await e.query(o);return r.map(a=>a.table_name)}async function lr(t){let e=await
|
|
57
|
+
`,{rows:r}=await e.query(o);return r.map(a=>a.table_name)}async function lr(t){let e=await Ee.connect();try{return(await e.query(`
|
|
58
58
|
SELECT obj_description(oid) as description
|
|
59
59
|
FROM pg_class
|
|
60
60
|
WHERE relname = $1
|
|
61
61
|
AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public');
|
|
62
|
-
`,[t])).rows[0]?.description||void 0}finally{e.release()}}async function mr(t){let e=await
|
|
62
|
+
`,[t])).rows[0]?.description||void 0}finally{e.release()}}async function mr(t){let e=await Ee.connect();try{return(await e.query(`SELECT * FROM "${t}" LIMIT 3`)).rows}catch{return[]}finally{e.release()}}function ur(t){let e={name:t.columnName,type:t.dataTypeLabel,nullable:t.isNullable};return t.isPrimaryKey&&(e.isPrimaryKey=!0),t.isForeignKey&&t.referencedTable&&t.referencedColumn&&(e.foreignKey=`${t.referencedTable}.${t.referencedColumn}`),t.enumValues&&t.enumValues.length>0&&(e.enumValues=t.enumValues,e.description=`Enum values: ${t.enumValues.join(", ")}`),e}function pr(t){let e=[];for(let o of t)for(let r of o.columns)if(r.foreignKey){let[a,n]=r.foreignKey.split(".");e.push({fromTable:o.name,fromColumn:r.name,toTable:a,toColumn:n})}return e}async function dr(t,e={}){let{includeSampleData:o=!1,includeDescriptions:r=!0}=e;try{let n=(await cr(t)).map(async s=>{let[u,c,p]=await Promise.all([se({tableName:s,db:t}),r?lr(s):Promise.resolve(void 0),o?mr(s):Promise.resolve([])]),h={name:s,columns:u.map(ur)};return c&&(h.description=c),p.length>0&&(h.sampleData=p.map(E=>Object.fromEntries(Object.entries(E).map(([f,T])=>[f,String(T)])))),h}),i=await Promise.all(n),m=pr(i);return{dbType:"PostgreSQL",tables:i,relationships:m}}catch(a){throw new Error(`Failed to fetch database schema: ${a instanceof Error?a.message:"Unknown error"}`)}}async function _t(t){return dr(t,{includeSampleData:!0,includeDescriptions:!0})}var At=l(()=>{"use strict";xt();C();Ce()});function $t(t){return`You are a database assistant for db-studio. Your responses must be CONCISE and FOCUSED.
|
|
63
63
|
|
|
64
64
|
**Your Role:**
|
|
65
65
|
1. Keep responses SHORT - 2-3 sentences maximum unless generating SQL
|
|
@@ -126,7 +126,7 @@ This will return the 5 customers with the highest total order value. You might a
|
|
|
126
126
|
`)}if(t.relationships&&t.relationships.length>0){e+=`
|
|
127
127
|
**Relationships:**
|
|
128
128
|
`;for(let o of t.relationships)e+=` - ${o.fromTable}.${o.fromColumn} -> ${o.toTable}.${o.toColumn}
|
|
129
|
-
`}return e}var
|
|
129
|
+
`}return e}var Pt=l(()=>{"use strict"});import{zValidator as yr}from"@hono/zod-validator";import{Hono as br}from"hono";var qt,It=l(()=>{"use strict";X();L();At();Pt();qt=new br().basePath("/chat").post("/",yr("json",Je),async t=>{let{messages:e,conversationId:o,db:r}=t.req.valid("json"),a=await _t(r),n=$t(a),i={messages:e,conversationId:o,systemPrompt:n},m=await fetch(`${P.PROXY_URL}/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)});if(!m.ok){let c=await m.json();return t.json({error:c.error||"Proxy request failed"},m.status)}let{readable:s,writable:u}=new TransformStream;return m.body?.pipeTo(u),new Response(s,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})})});function Lt(){let t=process.env.DATABASE_URL;if(!t)return{host:"localhost",port:5432};try{let e=new URL(t);return{host:e.hostname||"localhost",port:Number.parseInt(e.port,10)||5432}}catch{return{host:"localhost",port:5432}}}var Ot=l(()=>{"use strict"});import{HTTPException as Re}from"hono/http-exception";async function jt(){let t=y(),e=`
|
|
130
130
|
SELECT
|
|
131
131
|
d.datname as name,
|
|
132
132
|
pg_size_pretty(pg_database_size(d.datname)) as size,
|
|
@@ -135,7 +135,7 @@ This will return the 5 customers with the highest total order value. You might a
|
|
|
135
135
|
FROM pg_catalog.pg_database d
|
|
136
136
|
WHERE d.datistemplate = false
|
|
137
137
|
ORDER BY d.datname;
|
|
138
|
-
`,{rows:o}=await t.query(e);if(!o[0])throw new
|
|
138
|
+
`,{rows:o}=await t.query(e);if(!o[0])throw new Re(500,{message:"No databases returned from database"});return o}async function Ut(){let t=y(),e="SELECT current_database() as database;",{rows:o}=await t.query(e);if(!o[0])throw new Re(500,{message:"No current database returned from database"});return o[0]}async function kt(){let t=y(),e=`
|
|
139
139
|
SELECT
|
|
140
140
|
version() as version,
|
|
141
141
|
current_database() as database,
|
|
@@ -144,11 +144,11 @@ This will return the 5 customers with the highest total order value. You might a
|
|
|
144
144
|
inet_server_port() as port,
|
|
145
145
|
(SELECT count(*) FROM pg_stat_activity WHERE datname = current_database()) as active_connections,
|
|
146
146
|
(SELECT setting::int FROM pg_settings WHERE name = 'max_connections') as max_connections;
|
|
147
|
-
`,{rows:o}=await t.query(e);if(!o[0])throw new
|
|
147
|
+
`,{rows:o}=await t.query(e);if(!o[0])throw new Re(500,{message:"No connection information returned from database"});let r=st.parse(o[0]),a=Lt();return{host:r.host||a.host,port:r.port||a.port,user:r.user,database:r.database,version:r.version.toString(),active_connections:r.active_connections,max_connections:r.max_connections}}var Ft=l(()=>{"use strict";L();C();Ot()});import{Hono as hr}from"hono";var Ht,zt=l(()=>{"use strict";Ft();C();Ht=new hr().basePath("/databases").get("/",async t=>{let e=await jt(),o=we();return t.json({data:{databases:e,dbType:o}},200)}).get("/current",async t=>{let e=await Ut(),o=we();return t.json({data:{...e,dbType:o}},200)}).get("/connection",async t=>{let e=await kt();return t.json({data:e},200)})});import{HTTPException as gr}from"hono/http-exception";var Mt,Kt=l(()=>{"use strict";C();Mt=async({query:t,db:e})=>{let o=y(e);if(!t||!t.trim())throw new gr(400,{message:"Query is required"});let r=t.trim().replace(/;+$/,""),a=performance.now(),n=await o.query(r),i=performance.now()-a;return{columns:n.fields.map(s=>s.name),rows:n.rows,rowCount:n.rows.length,duration:i,message:n.rows.length===0?"OK":void 0}}});import{zValidator as Wt}from"@hono/zod-validator";import{Hono as Tr}from"hono";var Vt,Bt=l(()=>{"use strict";L();Kt();Vt=new Tr().basePath("/query").post("/",Wt("query",g),Wt("json",dt),async t=>{let{query:e}=t.req.valid("json"),{db:o}=t.req.valid("query"),r=await Mt({query:e,db:o});return t.json({data:r},200)})});import{HTTPException as Sr}from"hono/http-exception";async function Qt({db:t,params:e}){let{tableName:o,data:r}=e,a=y(t),n=Object.keys(r),i=Object.values(r),m=n.map((p,h)=>`$${h+1}`).join(", "),s=n.map(p=>`"${p}"`).join(", "),u=`
|
|
148
148
|
INSERT INTO "${o}" (${s})
|
|
149
149
|
VALUES (${m})
|
|
150
150
|
RETURNING *
|
|
151
|
-
`,c=await a.query(u,i);if(c.rowCount===0)throw new Sr(500,{message:`Failed to insert record into "${o}"`});return{insertedCount:c.rowCount??0}}var
|
|
151
|
+
`,c=await a.query(u,i);if(c.rowCount===0)throw new Sr(500,{message:`Failed to insert record into "${o}"`});return{insertedCount:c.rowCount??0}}var Yt=l(()=>{"use strict";C()});import{HTTPException as B}from"hono/http-exception";async function xe(t,e){return(await y(e).query(`
|
|
152
152
|
SELECT
|
|
153
153
|
tc.constraint_name,
|
|
154
154
|
tc.table_name as referencing_table,
|
|
@@ -164,45 +164,45 @@ This will return the 5 customers with the highest total order value. You might a
|
|
|
164
164
|
AND ccu.table_schema = tc.table_schema
|
|
165
165
|
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
166
166
|
AND ccu.table_name = $1
|
|
167
|
-
`,[t])).rows.map(({row:n})=>({constraintName:n.constraint_name,referencingTable:n.referencing_table,referencingColumn:n.referencing_column,referencedTable:n.referenced_table,referencedColumn:n.referenced_column}))}async function Er(t,e,o){let r=await
|
|
167
|
+
`,[t])).rows.map(({row:n})=>({constraintName:n.constraint_name,referencingTable:n.referencing_table,referencingColumn:n.referencing_column,referencedTable:n.referenced_table,referencedColumn:n.referenced_column}))}async function Er(t,e,o){let r=await xe(t,o);if(r.length===0)return[];let a=[],n=y(o),i=new Map;for(let s of r){let u=`${s.referencingTable}.${s.referencingColumn}`;i.has(u)||i.set(u,[]),i.get(u)?.push(s)}let m=e.map(s=>s.value);for(let[s,u]of i){let c=u[0];if(!c||!e.find(T=>T.columnName===c.referencedColumn))continue;let h=m.map((T,_)=>`$${_+1}`).join(", "),E=`
|
|
168
168
|
SELECT * FROM "${c.referencingTable}"
|
|
169
169
|
WHERE "${c.referencingColumn}" IN (${h})
|
|
170
170
|
LIMIT 100
|
|
171
|
-
`,f=await n.query(E,m);f.rows.length>0&&a.push({tableName:c.referencingTable,columnName:c.referencingColumn,constraintName:c.constraintName,records:f.rows})}return a}async function
|
|
171
|
+
`,f=await n.query(E,m);f.rows.length>0&&a.push({tableName:c.referencingTable,columnName:c.referencingColumn,constraintName:c.constraintName,records:f.rows})}return a}async function Gt({tableName:t,primaryKeys:e,db:o}){let r=y(o),a=e[0]?.columnName;if(!a)throw new B(400,{message:"Primary key column name is required"});let n=e.map(s=>s.value),i=n.map((s,u)=>`$${u+1}`).join(", "),m=`
|
|
172
172
|
DELETE FROM "${t}"
|
|
173
173
|
WHERE "${a}" IN (${i})
|
|
174
174
|
RETURNING *
|
|
175
|
-
`;await r.query("BEGIN");try{let s=await r.query(m,n);return await r.query("COMMIT"),{deletedCount:s.rowCount??0}}catch(s){if(await r.query("ROLLBACK"),s.code==="23503")return{deletedCount:0,fkViolation:!0,relatedRecords:await Er(t,e,o)};throw s instanceof B?s:new B(500,{message:`Failed to delete records from "${t}"`})}}async function
|
|
175
|
+
`;await r.query("BEGIN");try{let s=await r.query(m,n);return await r.query("COMMIT"),{deletedCount:s.rowCount??0}}catch(s){if(await r.query("ROLLBACK"),s.code==="23503")return{deletedCount:0,fkViolation:!0,relatedRecords:await Er(t,e,o)};throw s instanceof B?s:new B(500,{message:`Failed to delete records from "${t}"`})}}async function Jt({tableName:t,primaryKeys:e,db:o}){let r=y(o),a=e[0]?.columnName;if(!a)throw new B(400,{message:"Primary key column name is required"});let n=e.map(i=>i.value);await r.query("BEGIN");try{let i=await xe(t,o),m=0,s=new Set,u=async(f,T,_)=>{let k=await xe(f,o);for(let j of k){let Q=_.map((q,Y)=>`$${Y+1}`).join(", "),z=`
|
|
176
176
|
SELECT "${j.referencedColumn}" FROM "${f}"
|
|
177
177
|
WHERE "${T}" IN (${Q})
|
|
178
178
|
`,R=(await r.query(z,_)).rows.map(({row:q})=>q[j.referencedColumn]);R.length>0&&await u(j.referencingTable,j.referencingColumn,R)}let F=_.map((j,Q)=>`$${Q+1}`).join(", "),H=`
|
|
179
179
|
DELETE FROM "${f}"
|
|
180
180
|
WHERE "${T}" IN (${F})
|
|
181
|
-
`,
|
|
181
|
+
`,de=await r.query(H,_);m+=de.rowCount??0,s.add(f)};for(let f of i)s.has(f.referencingTable)||await u(f.referencingTable,f.referencingColumn,n);let c=n.map((f,T)=>`$${T+1}`).join(", "),p=`
|
|
182
182
|
DELETE FROM "${t}"
|
|
183
183
|
WHERE "${a}" IN (${c})
|
|
184
184
|
RETURNING *
|
|
185
|
-
`,h=await r.query(p,n);return await r.query("COMMIT"),{deletedCount:(h.rowCount??0)+m}}catch(i){throw await r.query("ROLLBACK"),i instanceof B?i:new B(500,{message:`Failed to force delete records from "${t}"`})}}var
|
|
185
|
+
`,h=await r.query(p,n);return await r.query("COMMIT"),{deletedCount:(h.rowCount??0)+m}}catch(i){throw await r.query("ROLLBACK"),i instanceof B?i:new B(500,{message:`Failed to force delete records from "${t}"`})}}var Xt=l(()=>{"use strict";C()});import{HTTPException as ie}from"hono/http-exception";async function Zt({params:t,db:e}){let{tableName:o,updates:r,primaryKey:a}=t,n=y(e),i=new Map;for(let m of r){let s=m.rowData[a];if(s==null)throw new ie(400,{message:`Primary key "${a}" not found in row data. Please ensure the row has a "${a}" column.`});i.has(s)||i.set(s,[]),i.get(s)?.push({columnName:m.columnName,value:m.value,rowData:m.rowData})}await n.query("BEGIN");try{let m=0;for(let[s,u]of i.entries()){let c=u.map((f,T)=>`"${f.columnName}" = $${T+1}`),p=u.map(f=>f.value!==null&&typeof f.value=="object"?JSON.stringify(f.value):f.value);p.push(s);let h=`
|
|
186
186
|
UPDATE "${o}"
|
|
187
187
|
SET ${c.join(", ")}
|
|
188
188
|
WHERE "${a}" = $${p.length}
|
|
189
189
|
RETURNING *
|
|
190
|
-
`,E=await n.query(h,p);if(E.rowCount===0)throw new ie(404,{message:`Record with ${a} = ${s} not found in table "${o}"`});m+=E.rowCount??0}return await n.query("COMMIT"),{updatedCount:m}}catch(m){throw await n.query("ROLLBACK"),m instanceof ie?m:new ie(500,{message:`Failed to update records in "${o}"`})}}var
|
|
190
|
+
`,E=await n.query(h,p);if(E.rowCount===0)throw new ie(404,{message:`Record with ${a} = ${s} not found in table "${o}"`});m+=E.rowCount??0}return await n.query("COMMIT"),{updatedCount:m}}catch(m){throw await n.query("ROLLBACK"),m instanceof ie?m:new ie(500,{message:`Failed to update records in "${o}"`})}}var eo=l(()=>{"use strict";C()});import{zValidator as O}from"@hono/zod-validator";import{Hono as Dr}from"hono";var to,oo=l(()=>{"use strict";L();Yt();Xt();eo();to=new Dr().basePath("/records").post("/",O("query",g),O("json",Be),async t=>{let{db:e}=t.req.valid("query"),{tableName:o,data:r}=t.req.valid("json"),{insertedCount:a}=await Qt({db:e,params:{tableName:o,data:r}});return t.json({data:`Record inserted into "${o}" with ${a} rows inserted`},200)}).patch("/",O("query",g),O("json",Et),async t=>{let{db:e}=t.req.valid("query"),{tableName:o,primaryKey:r,updates:a}=t.req.valid("json"),{updatedCount:n}=await Zt({params:{tableName:o,primaryKey:r,updates:a},db:e});return t.json({data:`Updated ${n} records in "${o}"`},200)}).delete("/",O("query",g),O("json",Te),async t=>{let{db:e}=t.req.valid("query"),{tableName:o,primaryKeys:r}=t.req.valid("json"),{deletedCount:a}=await Gt({tableName:o,primaryKeys:r,db:e});return t.json({data:`Deleted ${a} records from "${o}"`},200)}).delete("/force",O("query",g),O("json",Te),async t=>{let{db:e}=t.req.valid("query"),{tableName:o,primaryKeys:r}=t.req.valid("json"),{deletedCount:a}=await Jt({tableName:o,primaryKeys:r,db:e});return t.json({data:`Deleted ${a} records from "${o}"`},200)})});async function ro({tableData:t,db:e}){let{tableName:o,fields:r,foreignKeys:a}=t,n=y(e),i=r.map(c=>{let p=`"${c.columnName}" ${c.columnType}`;return c.isArray&&(p+="[]"),c.isPrimaryKey&&(p+=" PRIMARY KEY"),c.isUnique&&!c.isPrimaryKey&&(p+=" UNIQUE"),c.isNullable||(p+=" NOT NULL"),c.isIdentity&&(p+=" GENERATED ALWAYS AS IDENTITY"),c.defaultValue&&!c.isIdentity&&(p+=` DEFAULT ${c.defaultValue}`),p}),m=a?.map(c=>`CONSTRAINT "${`fk_${o}_${c.columnName}_${c.referencedTable}_${c.referencedColumn}`}" FOREIGN KEY ("${c.columnName}") REFERENCES "${c.referencedTable}" ("${c.referencedColumn}") ON UPDATE ${c.onUpdate} ON DELETE ${c.onDelete}`)||[],s=[...i,...m],u=`
|
|
191
191
|
CREATE TABLE "${o}" (
|
|
192
192
|
${s.join(`,
|
|
193
193
|
`)}
|
|
194
194
|
);
|
|
195
|
-
`;await n.query(u)}var
|
|
195
|
+
`;await n.query(u)}var ao=l(()=>{"use strict";C()});import{HTTPException as no}from"hono/http-exception";async function so(t){let{tableName:e,columnName:o,cascade:r,db:a}=t,n=y(a),i=`
|
|
196
196
|
SELECT EXISTS (
|
|
197
197
|
SELECT 1 FROM information_schema.tables
|
|
198
198
|
WHERE table_name = $1 AND table_schema = 'public'
|
|
199
199
|
) as exists;
|
|
200
|
-
`,{rows:m}=await n.query(i,[e]);if(!m[0]?.exists)throw new
|
|
200
|
+
`,{rows:m}=await n.query(i,[e]);if(!m[0]?.exists)throw new no(404,{message:`Table "${e}" does not exist`});let s=`
|
|
201
201
|
SELECT EXISTS (
|
|
202
202
|
SELECT 1 FROM information_schema.columns
|
|
203
203
|
WHERE table_name = $1 AND column_name = $2 AND table_schema = 'public'
|
|
204
204
|
) as exists;
|
|
205
|
-
`,{rows:u}=await n.query(s,[e,o]);if(!u[0]?.exists)throw new
|
|
205
|
+
`,{rows:u}=await n.query(s,[e,o]);if(!u[0]?.exists)throw new no(404,{message:`Column "${o}" does not exist in table "${e}"`});let p=`ALTER TABLE "${e}" DROP COLUMN "${o}" ${r?"CASCADE":"RESTRICT"}`,{rowCount:h}=await n.query(p);return{deletedCount:h??0}}var io=l(()=>{"use strict";C()});import{HTTPException as wr}from"hono/http-exception";async function co({tableName:t,db:e}){let o=y(e),{rows:r}=await o.query(`SELECT * FROM "${t}"`);if(!r||r.length===0)throw new wr(404,{message:`Table "${t}" does not exist or has no data`});return{cols:Object.keys(r[0]),rows:r}}var lo=l(()=>{"use strict";C()});import{HTTPException as Cr}from"hono/http-exception";async function mo(t){let e=y(t),o=`
|
|
206
206
|
SELECT
|
|
207
207
|
t.table_name as "tableName",
|
|
208
208
|
COALESCE(s.n_live_tup, 0)::integer as "rowCount"
|
|
@@ -211,9 +211,9 @@ This will return the 5 customers with the highest total order value. You might a
|
|
|
211
211
|
WHERE t.table_schema = 'public'
|
|
212
212
|
AND t.table_type = 'BASE TABLE'
|
|
213
213
|
ORDER BY t.table_name;
|
|
214
|
-
`,{rows:r}=await e.query(o);if(!r[0])throw new Cr(500,{message:"No tables returned from database"});return r}var
|
|
214
|
+
`,{rows:r}=await e.query(o);if(!r[0])throw new Cr(500,{message:"No tables returned from database"});return r}var uo=l(()=>{"use strict";C()});function po(t){if(t.length===0)return{clause:"",values:[]};let e=[],o=[];for(let r of t){let a=o.length+1,n=`"${r.columnName}"`;switch(r.operator){case"=":case"!=":case">":case">=":case"<":case"<=":e.push(`${n} ${r.operator} $${a}`),o.push(r.value);break;case"is":r.value.toLowerCase()==="null"?e.push(`${n} IS NULL`):(e.push(`${n} = $${a}`),o.push(r.value));break;case"is not":r.value.toLowerCase()==="null"?e.push(`${n} IS NOT NULL`):(e.push(`${n} != $${a}`),o.push(r.value));break;case"like":e.push(`${n}::text LIKE $${a}`),o.push(r.value);break;case"not like":e.push(`${n}::text NOT LIKE $${a}`),o.push(r.value);break;case"ilike":e.push(`${n}::text ILIKE $${a}`),o.push(r.value);break;case"not ilike":e.push(`${n}::text NOT ILIKE $${a}`),o.push(r.value);break;default:break}}return e.length===0?{clause:"",values:[]}:{clause:`WHERE ${e.join(" AND ")}`,values:o}}function fo(t,e){return Array.isArray(t)?t.length===0?"":`ORDER BY ${t.map(r=>`"${r.columnName}" ${r.direction.toUpperCase()}`).join(", ")}`:t&&typeof t=="string"?`ORDER BY "${t}" ${e?.toUpperCase()||"ASC"}`:""}function yo(t,e,o,r){let{values:a,sortColumns:n}=t,i=[],m=[],c=o==="asc"===(e==="asc");if(n.length>0){let p=n.map(f=>`"${f}"`).join(", "),h=n.map((f,T)=>`$${r+T}`).join(", "),E=c?">":"<";i.push(`(${p}) ${E} (${h})`);for(let f of n)m.push(a[f])}return{clause:i.length>0?`(${i.join(" AND ")})`:"",values:m}}var bo=l(()=>{"use strict"});var ce,Rr,xr,ho,go=l(()=>{"use strict";C();bo();ce=t=>Buffer.from(JSON.stringify(t)).toString("base64url"),Rr=t=>{try{return JSON.parse(Buffer.from(t,"base64url").toString("utf-8"))}catch{return null}},xr=async(t,e)=>{let o=`"${e}"`;return(await t.query(`SELECT a.attname as column_name
|
|
215
215
|
FROM pg_index i
|
|
216
216
|
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
|
|
217
217
|
WHERE i.indrelid = $1::regclass AND i.indisprimary
|
|
218
|
-
ORDER BY array_position(i.indkey, a.attnum)`,[o])).rows.map(a=>a.column_name)},yo=async({tableName:t,cursor:e="",limit:o=50,direction:r="asc",sort:a=[],order:n="asc",filters:i=[],db:m})=>{let s=y(m),u=await xr(s,t),c=[],p=n;Array.isArray(a)&&a.length>0?(c=a.map(w=>w.columnName),p=a[0].direction):typeof a=="string"&&a&&(c=[a]);let h=[...c,...u.filter(w=>!c.includes(w))];h.length===0&&h.push("ctid");let{clause:E,values:f}=mo(i),T="",_=[];if(e){let w=Rr(e);if(w){let $=po(w,r,p,f.length+1);T=$.clause,_=$.values}}let k="";E&&T?k=`WHERE ${E.replace(/^WHERE\s+/i,"")} AND ${T}`:E?k=E:T&&(k=`WHERE ${T}`);let F=uo((Array.isArray(a),a),n),H=F;r==="desc"?F?H=F.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"):H=`ORDER BY ${h.map($=>`"${$}" ${p==="asc"?"DESC":"ASC"}`).join(", ")}`:!F&&h.length>0&&(H=`ORDER BY ${h.map($=>`"${$}" ${p.toUpperCase()}`).join(", ")}`);let ue=await s.query(`SELECT COUNT(*) as total FROM "${t}" ${E}`,f),j=Number(ue.rows[0].total),Q=f.length+_.length+1,z=await s.query(`SELECT * FROM "${t}" ${k} ${H} LIMIT $${Q}`,[...f,..._,o+1]),R=z.fields&&z.fields.length>0?z.rows.filter(w=>Object.keys(w).length>0):z.rows,q=R.length>o;q&&(R=R.slice(0,o)),r==="desc"&&(R=R.reverse());let Y=null,pe=null;if(R.length>0){let w=R[0],$=R[R.length-1],J=xo=>({values:Object.fromEntries(h.map(xe=>[xe,xo[xe]])),sortColumns:h});r==="asc"?(q&&(Y=ce(J($))),e&&(pe=ce(J(w)))):(e&&(Y=ce(J($))),q&&(pe=ce(J(w))))}return{data:R,meta:{limit:o,total:j,hasNextPage:r==="asc"?q:!!e,hasPreviousPage:r==="asc"?!!e:q,nextCursor:Y,prevCursor:pe}}}});import{utils as le,write as Nr}from"xlsx";function ho({cols:t,rows:e,format:o,tableName:r}){let a=[t,...e?.map(s=>t?.map(u=>s[u]))??[]],n=le.aoa_to_sheet(a),i=le.book_new();if(le.book_append_sheet(i,n,r.slice(0,31)),o==="csv"){let s=le.sheet_to_csv(n);return new Uint8Array(Buffer.from(s,"utf-8"))}let m=Nr(i,{bookType:"xlsx",type:"buffer"});return new Uint8Array(m)}var go=l(()=>{"use strict"});import{zValidator as v}from"@hono/zod-validator";import{Hono as vr}from"hono";var To,So=l(()=>{"use strict";L();oo();no();io();De();lo();bo();go();To=new vr().basePath("/tables").get("/",v("query",g),async t=>{let{db:e}=t.req.valid("query"),o=await co(e);return t.json({data:o},200)}).post("/",v("query",g),v("json",ot),async t=>{let{db:e}=t.req.valid("query"),o=t.req.valid("json");return await to({tableData:o,db:e}),t.json({data:`Table ${o.tableName} created successfully`},200)}).delete("/:tableName/columns/:columnName",v("query",it),v("param",re),async t=>{let{db:e,cascade:o}=t.req.valid("query"),{tableName:r,columnName:a}=t.req.valid("param"),{deletedCount:n}=await ao({tableName:r,columnName:a,cascade:o,db:e});return t.json({data:`Column "${a}" deleted successfully from table "${r}" with ${n} rows deleted`},200)}).get("/:tableName/columns",v("query",g),v("param",oe),async t=>{let{db:e}=t.req.valid("query"),{tableName:o}=t.req.valid("param"),r=await se({tableName:o,db:e});return t.json({data:r},200)}).get("/:tableName/data",v("param",oe),v("query",bt),async t=>{let{tableName:e}=t.req.valid("param"),{cursor:o,limit:r,direction:a,sort:n,order:i,filters:m,db:s}=t.req.valid("query"),u=await yo({tableName:e,cursor:o,limit:r,direction:a,sort:n,order:i,filters:m,db:s});return t.json({data:u},200)}).get("/:tableName/export",v("param",oe),v("query",dt),async t=>{let{tableName:e}=t.req.valid("param"),{db:o,format:r}=t.req.valid("query"),{cols:a,rows:n}=await so({tableName:e,db:o}),i=ho({cols:a,rows:n,format:r,tableName:e}),m=r==="csv"?"text/csv":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";return new Response(i,{headers:{"Content-Type":m,"Content-Disposition":`attachment; filename="${e}_export.${r}"`}})})});var wo={};vo(wo,{createServer:()=>Lr});import me from"path";import{fileURLToPath as _r}from"url";import{serveStatic as Eo}from"@hono/node-server/serve-static";import{zValidator as Ar}from"@hono/zod-validator";import{Hono as $r}from"hono";import{cors as Pr}from"hono/cors";import{logger as qr}from"hono/logger";import{prettyJSON as Ir}from"hono/pretty-json";var Do,Lr,Co=l(()=>{"use strict";L();wt();Pt();Ft();Wt();eo();So();Do=()=>{if(process.env.NODE_ENV==="development")return me.resolve(process.cwd(),"../core/dist");let t=me.dirname(_r(import.meta.url));return me.resolve(t,"./core-dist")},Lr=()=>({app:new $r({strict:!1}).use("/*",Pr()).use(Ir({space:2})).use(process.env.NODE_ENV==="development"?qr():(e,o)=>o()).use("/favicon.ico",Eo({path:me.resolve(Do(),"favicon.ico")})).use("*",async(e,o)=>{e.header("Access-Control-Allow-Origin","*"),e.header("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS"),e.header("Access-Control-Allow-Headers","Content-Type"),await o()}).onError(Et).route("/",kt).use("/:dbType/*",Ar("param",Qe,Dt)).use("/:dbType/*",async(e,o)=>{let r=e.req.param("dbType");e.set("dbType",r),await o()}).route("/:dbType",To).route("/:dbType",Zt).route("/:dbType",Kt).route("/:dbType",$t).use("/*",Eo({root:Do()}))})});X();import{intro as Or,outro as jr}from"@clack/prompts";import{serve as Ur}from"@hono/node-server";import kr from"open";import Re from"picocolors";import{program as Pe}from"commander";var qe=()=>(Pe.name("db-studio").option("-e, --env <path>","Path to custom .env file").option("-p, --port <port>","Port to run the server on").option("-d, --database-url <url>","Database URL to use").option("-n, --var-name <name>","Custom environment variable name (default: DATABASE_URL)").option("-s, --status","Show status of the server").option("-h, --help","Show help").option("-v, --version","Show version").parse(process.argv),Pe.opts());import{readFile as _o}from"fs/promises";import{resolve as Ao}from"path";import{cancel as Z,isCancel as fe,note as Ie,select as $o,spinner as Po,text as Le}from"@clack/prompts";import{parse as qo}from"dotenv";import ye from"picocolors";var Oe=async(t,e)=>{let o=e||"DATABASE_URL";if(t?.[o])return t[o];let r=Po();r.start("Looking for database connection..."),t?Ie(ye.red(`${o} not found in .env`)):Ie(ye.red("No .env file found in current directory"));let a=await $o({message:`How do you want to provide ${o}?`,options:[{value:"manual",label:"Enter connection string manually"},{value:"other-env",label:"Use different .env file"},{value:"cancel",label:"Cancel / Exit"}],initialValue:"manual"});if((fe(a)||a==="cancel")&&(Z("No database connection provided. Exiting..."),process.exit(0)),a==="other-env"){r.start("Waiting for path...");let i=await Le({message:"Enter path to .env file",placeholder:"~/projects/myapp/.env.local or ./special.env",validate(s){if(!s.trim())return"Path is required"}});fe(i)&&(Z("Cancelled."),process.exit(0)),r.stop("Trying custom .env...");let m=Ao(i);try{let s=await _o(m,"utf-8"),u=qo(s);if(u[o])return u[o];throw new Error(`${o} still missing in custom file`)}catch(s){let u=s;Z(`Cannot read or parse file: ${ye.dim(u.message)}`),process.exit(1)}}r.stop("Manual input...");let n=await Le({message:`Paste your ${o}`,placeholder:"postgresql://user:password@localhost:5432/mydb",validate(i){if(!i.trim())return"Connection string is required!";try{new URL(i);return}catch{return"Must be a valid URL format"}}});return fe(n)&&(Z("Cancelled."),process.exit(0)),n.trim()};import{access as Io,readFile as Lo}from"fs/promises";import{resolve as je}from"path";import{parse as Oo}from"dotenv";var M=async t=>{let e=t?je(t):je(process.cwd(),".env");try{await Io(e);let o=await Lo(e,"utf-8");return Oo(o)}catch(o){if(o instanceof Error&&o.message.includes("ENOENT"))return null;throw o}};de();import{intro as jo,outro as Uo}from"@clack/prompts";import Ue from"picocolors";var ke=()=>{jo(Ue.inverse(" db-studio ")),Uo(Ue.green(`For more information, visit: ${Ae.SITE_DOCS_LINK}`))};X();import{intro as ko,note as Fo,outro as Fe}from"@clack/prompts";import ee from"picocolors";var He=async(t,e,o)=>{ko(ee.inverse(" db-studio "));let r=o||P.VAR_NAME,a=null;if(e)a=e;else{let n=t?await M(t):await M(P.ENV);n?.[r]&&(a=n[r])}a?Fe(ee.green(`\u2713 Database connection configured (using ${r})`)):(Fo(ee.red(`\u2717 ${r} not found`),"Status"),Fe(ee.yellow("\u26A0 No database connection configured")))};import{intro as zo,outro as Mo}from"@clack/prompts";import Me from"picocolors";var ze={name:"db-studio",type:"module",version:"1.2.21",description:"Modern database client for PostgreSQL with spreadsheet-like grid, AI-powered SQL assistance, ER diagrams, fast data browsing and editing. CLI tool, upcoming desktop & web versions.",keywords:["database","database client","postgres","postgresql","database gui","sql client","database studio","postgres gui","ai sql","sql editor","er diagram","database management","data browser","spreadsheet database","postgres admin","mysql client","sqlite client","database tool","developer tools"],author:"H\xFCsam \u{1F951} <devhsmq@gmail.com>",homepage:"https://dbstudio.sh",repository:{type:"git",url:"git+https://github.com/husamql3/db-studio.git"},bugs:{url:"https://github.com/husamql3/db-studio/issues"},license:"MIT",bin:{"db-studio":"./dist/index.js"},files:["dist"],scripts:{dev:"NODE_ENV=development tsx watch src/index.ts",build:"tsup --minify --sourcemap",prepack:"cd ../core && bun run build && cd ../server && bun run build",start:"node dist/index.js",check:"biome check --write --unsafe --verbose",test:"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage"},dependencies:{"@clack/prompts":"^0.11.0","@hono/node-server":"^1.19.7","@hono/zod-validator":"^0.7.6",commander:"^12.1.0",dotenv:"^16.4.7",hono:"^4.10.4",open:"^10.0.2",pg:"^8.13.1",picocolors:"^1.1.1",xlsx:"^0.18.5",zod:"^4.2.1"},devDependencies:{"@biomejs/biome":"^2.2.6","@types/node":"^20.11.17","@types/pg":"^8.16.0","@vitest/coverage-v8":"^4.0.17",shared:"workspace:*",tsup:"^8.5.1",tsx:"^4.7.1",typescript:"^5.8.3",vitest:"^4.0.17"}};var Ke=()=>{zo(Me.inverse(" db-studio ")),Mo(Me.green(`\u{1F680} db-studio v${ze.version}`))};var Fr=async()=>{let{env:t,port:e,databaseUrl:o,varName:r,status:a,help:n,version:i}=qe();n&&(ke(),process.exit(0)),i&&(Ke(),process.exit(0)),a&&(await He(t,o,r),process.exit(0)),Or(Re.inverse(" db-studio "));let m=e?parseInt(e,10):P.PORT,s=r||P.VAR_NAME,u=t?await M(t):await M(P.ENV),c=o||await Oe(u,s);process.env.DATABASE_URL=c;let{createServer:p}=await Promise.resolve().then(()=>(Co(),wo)),{app:h}=p();Ur({fetch:h.fetch,port:m}),jr(Re.green(`Server running at ${Re.cyan(`http://localhost:${m}`)}`)),process.env.NODE_ENV&&process.env.NODE_ENV!=="development"&&await kr(`http://localhost:${m}`)};Fr().catch(t=>{process.exit(1)});export{Fr as main};
|
|
218
|
+
ORDER BY array_position(i.indkey, a.attnum)`,[o])).rows.map(a=>a.column_name)},ho=async({tableName:t,cursor:e="",limit:o=50,direction:r="asc",sort:a=[],order:n="asc",filters:i=[],db:m})=>{let s=y(m),u=await xr(s,t),c=[],p=n;Array.isArray(a)&&a.length>0?(c=a.map(w=>w.columnName),p=a[0].direction):typeof a=="string"&&a&&(c=[a]);let h=[...c,...u.filter(w=>!c.includes(w))];h.length===0&&h.push("ctid");let{clause:E,values:f}=po(i),T="",_=[];if(e){let w=Rr(e);if(w){let $=yo(w,r,p,f.length+1);T=$.clause,_=$.values}}let k="";E&&T?k=`WHERE ${E.replace(/^WHERE\s+/i,"")} AND ${T}`:E?k=E:T&&(k=`WHERE ${T}`);let F=fo((Array.isArray(a),a),n),H=F;r==="desc"?F?H=F.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"):H=`ORDER BY ${h.map($=>`"${$}" ${p==="asc"?"DESC":"ASC"}`).join(", ")}`:!F&&h.length>0&&(H=`ORDER BY ${h.map($=>`"${$}" ${p.toUpperCase()}`).join(", ")}`);let de=await s.query(`SELECT COUNT(*) as total FROM "${t}" ${E}`,f),j=Number(de.rows[0].total),Q=f.length+_.length+1,z=await s.query(`SELECT * FROM "${t}" ${k} ${H} LIMIT $${Q}`,[...f,..._,o+1]),R=z.fields&&z.fields.length>0?z.rows.filter(w=>Object.keys(w).length>0):z.rows,q=R.length>o;q&&(R=R.slice(0,o)),r==="desc"&&(R=R.reverse());let Y=null,fe=null;if(R.length>0){let w=R[0],$=R[R.length-1],J=xo=>({values:Object.fromEntries(h.map(ve=>[ve,xo[ve]])),sortColumns:h});r==="asc"?(q&&(Y=ce(J($))),e&&(fe=ce(J(w)))):(e&&(Y=ce(J($))),q&&(fe=ce(J(w))))}return{data:R,meta:{limit:o,total:j,hasNextPage:r==="asc"?q:!!e,hasPreviousPage:r==="asc"?!!e:q,nextCursor:Y,prevCursor:fe}}}});import{utils as le,write as Nr}from"xlsx";function To({cols:t,rows:e,format:o,tableName:r}){let a=[t,...e?.map(s=>t?.map(u=>s[u]))??[]],n=le.aoa_to_sheet(a),i=le.book_new();if(le.book_append_sheet(i,n,r.slice(0,31)),o==="csv"){let s=le.sheet_to_csv(n);return new Uint8Array(Buffer.from(s,"utf-8"))}let m=Nr(i,{bookType:"xlsx",type:"buffer"});return new Uint8Array(m)}var So=l(()=>{"use strict"});import{zValidator as v}from"@hono/zod-validator";import{Hono as vr}from"hono";var Eo,Do=l(()=>{"use strict";L();ao();io();lo();Ce();uo();go();So();Eo=new vr().basePath("/tables").get("/",v("query",g),async t=>{let{db:e}=t.req.valid("query"),o=await mo(e);return t.json({data:o},200)}).post("/",v("query",g),v("json",at),async t=>{let{db:e}=t.req.valid("query"),o=t.req.valid("json");return await ro({tableData:o,db:e}),t.json({data:`Table ${o.tableName} created successfully`},200)}).delete("/:tableName/columns/:columnName",v("query",lt),v("param",re),async t=>{let{db:e,cascade:o}=t.req.valid("query"),{tableName:r,columnName:a}=t.req.valid("param"),{deletedCount:n}=await so({tableName:r,columnName:a,cascade:o,db:e});return t.json({data:`Column "${a}" deleted successfully from table "${r}" with ${n} rows deleted`},200)}).get("/:tableName/columns",v("query",g),v("param",oe),async t=>{let{db:e}=t.req.valid("query"),{tableName:o}=t.req.valid("param"),r=await se({tableName:o,db:e});return t.json({data:r},200)}).get("/:tableName/data",v("param",oe),v("query",gt),async t=>{let{tableName:e}=t.req.valid("param"),{cursor:o,limit:r,direction:a,sort:n,order:i,filters:m,db:s}=t.req.valid("query"),u=await ho({tableName:e,cursor:o,limit:r,direction:a,sort:n,order:i,filters:m,db:s});return t.json({data:u},200)}).get("/:tableName/export",v("param",oe),v("query",yt),async t=>{let{tableName:e}=t.req.valid("param"),{db:o,format:r}=t.req.valid("query"),{cols:a,rows:n}=await co({tableName:e,db:o}),i=To({cols:a,rows:n,format:r,tableName:e}),m=r==="csv"?"text/csv":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";return new Response(i,{headers:{"Content-Type":m,"Content-Disposition":`attachment; filename="${e}_export.${r}"`}})})});var wo={};vo(wo,{createServer:()=>Lr});import pe from"path";import{fileURLToPath as _r}from"url";import{serveStatic as me}from"@hono/node-server/serve-static";import{zValidator as Ar}from"@hono/zod-validator";import{Hono as $r}from"hono";import{cors as Pr}from"hono/cors";import{logger as qr}from"hono/logger";import{prettyJSON as Ir}from"hono/pretty-json";var ue,Lr,Co=l(()=>{"use strict";L();Rt();It();zt();Bt();oo();Do();ue=()=>{if(process.env.NODE_ENV==="development")return pe.resolve(process.cwd(),"../core/dist");let t=pe.dirname(_r(import.meta.url));return pe.resolve(t,"./core-dist")},Lr=()=>({app:new $r({strict:!1}).use("/*",Pr()).use(Ir({space:2})).use(process.env.NODE_ENV==="development"?qr():(e,o)=>o()).use("/favicon.ico",me({path:pe.resolve(ue(),"favicon.ico")})).use("*",async(e,o)=>{e.header("Access-Control-Allow-Origin","*"),e.header("Access-Control-Allow-Methods","GET, POST, PUT, DELETE, OPTIONS"),e.header("Access-Control-Allow-Headers","Content-Type"),await o()}).onError(wt).route("/",Ht).use("/assets/*",me({root:ue()})).use("/image.png",me({root:ue()})).use("/:dbType/*",Ar("param",Ge,Ct)).use("/:dbType/*",async(e,o)=>{let r=e.req.param("dbType");e.set("dbType",r),await o()}).route("/:dbType",Eo).route("/:dbType",to).route("/:dbType",Vt).route("/:dbType",qt).use("/*",me({root:ue()}))})});X();import{intro as Or,outro as jr}from"@clack/prompts";import{serve as Ur}from"@hono/node-server";import kr from"open";import Ne from"picocolors";import{program as Ie}from"commander";var Le=()=>(Ie.name("db-studio").option("-e, --env <path>","Path to custom .env file").option("-p, --port <port>","Port to run the server on").option("-d, --database-url <url>","Database URL to use").option("-n, --var-name <name>","Custom environment variable name (default: DATABASE_URL)").option("-s, --status","Show status of the server").option("-h, --help","Show help").option("-v, --version","Show version").parse(process.argv),Ie.opts());import{readFile as _o}from"fs/promises";import{resolve as Ao}from"path";import{cancel as Z,isCancel as be,note as Oe,select as $o,spinner as Po,text as je}from"@clack/prompts";import{parse as qo}from"dotenv";import he from"picocolors";var Ue=async(t,e)=>{let o=e||"DATABASE_URL";if(t?.[o])return t[o];let r=Po();r.start("Looking for database connection..."),t?Oe(he.red(`${o} not found in .env`)):Oe(he.red("No .env file found in current directory"));let a=await $o({message:`How do you want to provide ${o}?`,options:[{value:"manual",label:"Enter connection string manually"},{value:"other-env",label:"Use different .env file"},{value:"cancel",label:"Cancel / Exit"}],initialValue:"manual"});if((be(a)||a==="cancel")&&(Z("No database connection provided. Exiting..."),process.exit(0)),a==="other-env"){r.start("Waiting for path...");let i=await je({message:"Enter path to .env file",placeholder:"~/projects/myapp/.env.local or ./special.env",validate(s){if(!s.trim())return"Path is required"}});be(i)&&(Z("Cancelled."),process.exit(0)),r.stop("Trying custom .env...");let m=Ao(i);try{let s=await _o(m,"utf-8"),u=qo(s);if(u[o])return u[o];throw new Error(`${o} still missing in custom file`)}catch(s){let u=s;Z(`Cannot read or parse file: ${he.dim(u.message)}`),process.exit(1)}}r.stop("Manual input...");let n=await je({message:`Paste your ${o}`,placeholder:"postgresql://user:password@localhost:5432/mydb",validate(i){if(!i.trim())return"Connection string is required!";try{new URL(i);return}catch{return"Must be a valid URL format"}}});return be(n)&&(Z("Cancelled."),process.exit(0)),n.trim()};import{access as Io,readFile as Lo}from"fs/promises";import{resolve as ke}from"path";import{parse as Oo}from"dotenv";var M=async t=>{let e=t?ke(t):ke(process.cwd(),".env");try{await Io(e);let o=await Lo(e,"utf-8");return Oo(o)}catch(o){if(o instanceof Error&&o.message.includes("ENOENT"))return null;throw o}};ye();import{intro as jo,outro as Uo}from"@clack/prompts";import Fe from"picocolors";var He=()=>{jo(Fe.inverse(" db-studio ")),Uo(Fe.green(`For more information, visit: ${Pe.SITE_DOCS_LINK}`))};X();import{intro as ko,note as Fo,outro as ze}from"@clack/prompts";import ee from"picocolors";var Me=async(t,e,o)=>{ko(ee.inverse(" db-studio "));let r=o||P.VAR_NAME,a=null;if(e)a=e;else{let n=t?await M(t):await M(P.ENV);n?.[r]&&(a=n[r])}a?ze(ee.green(`\u2713 Database connection configured (using ${r})`)):(Fo(ee.red(`\u2717 ${r} not found`),"Status"),ze(ee.yellow("\u26A0 No database connection configured")))};import{intro as zo,outro as Mo}from"@clack/prompts";import We from"picocolors";var Ke={name:"db-studio",type:"module",version:"1.2.22",description:"Modern database client for PostgreSQL with spreadsheet-like grid, AI-powered SQL assistance, ER diagrams, fast data browsing and editing. CLI tool, upcoming desktop & web versions.",keywords:["database","database client","postgres","postgresql","database gui","sql client","database studio","postgres gui","ai sql","sql editor","er diagram","database management","data browser","spreadsheet database","postgres admin","mysql client","sqlite client","database tool","developer tools"],author:"H\xFCsam \u{1F951} <devhsmq@gmail.com>",homepage:"https://dbstudio.sh",repository:{type:"git",url:"git+https://github.com/husamql3/db-studio.git"},bugs:{url:"https://github.com/husamql3/db-studio/issues"},license:"MIT",bin:{"db-studio":"./dist/index.js"},files:["dist"],scripts:{dev:"NODE_ENV=development tsx watch src/index.ts",build:"tsup --minify --sourcemap",prepack:"cd ../core && bun run build && cd ../server && bun run build",start:"node dist/index.js",check:"biome check --write --unsafe --verbose",test:"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage"},dependencies:{"@clack/prompts":"^0.11.0","@hono/node-server":"^1.19.7","@hono/zod-validator":"^0.7.6",commander:"^12.1.0",dotenv:"^16.4.7",hono:"^4.10.4",open:"^10.0.2",pg:"^8.13.1",picocolors:"^1.1.1",xlsx:"^0.18.5",zod:"^4.2.1"},devDependencies:{"@biomejs/biome":"^2.2.6","@types/node":"^20.11.17","@types/pg":"^8.16.0","@vitest/coverage-v8":"^4.0.17",shared:"workspace:*",tsup:"^8.5.1",tsx:"^4.7.1",typescript:"^5.8.3",vitest:"^4.0.17"}};var Ve=()=>{zo(We.inverse(" db-studio ")),Mo(We.green(`\u{1F680} db-studio v${Ke.version}`))};var Fr=async()=>{let{env:t,port:e,databaseUrl:o,varName:r,status:a,help:n,version:i}=Le();n&&(He(),process.exit(0)),i&&(Ve(),process.exit(0)),a&&(await Me(t,o,r),process.exit(0)),Or(Ne.inverse(" db-studio "));let m=e?parseInt(e,10):P.PORT,s=r||P.VAR_NAME,u=t?await M(t):await M(P.ENV),c=o||await Ue(u,s);process.env.DATABASE_URL=c;let{createServer:p}=await Promise.resolve().then(()=>(Co(),wo)),{app:h}=p();Ur({fetch:h.fetch,port:m}),jr(Ne.green(`Server running at ${Ne.cyan(`http://localhost:${m}`)}`)),process.env.NODE_ENV&&process.env.NODE_ENV!=="development"&&await kr(`http://localhost:${m}`)};Fr().catch(t=>{process.exit(1)});export{Fr as main};
|
|
219
219
|
//# sourceMappingURL=index.js.map
|