db-studio 1.10.0 → 1.11.0

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.
Files changed (90) hide show
  1. package/dist/index.js +6 -6
  2. package/dist/index.js.map +1 -1
  3. package/dist/web-dist/assets/{_pathlessLayout-eo6iLvBo.js → _pathlessLayout-CJRtdlfu.js} +73 -73
  4. package/dist/web-dist/assets/_pathlessLayout-CJRtdlfu.js.map +1 -0
  5. package/dist/web-dist/assets/_pathlessLayout-ciCuJ1PR.js +1 -0
  6. package/dist/web-dist/assets/{_pathlessLayout-CEv6uosT.js.map → _pathlessLayout-ciCuJ1PR.js.map} +1 -1
  7. package/dist/web-dist/assets/_queryId-6swfGplM.js +1 -0
  8. package/dist/web-dist/assets/{_queryId-Bq64AuuI.js.map → _queryId-6swfGplM.js.map} +1 -1
  9. package/dist/web-dist/assets/{_table-Bt9of1on.js → _table-DHk3bHnN.js} +1 -1
  10. package/dist/web-dist/assets/{_table-Bt9of1on.js.map → _table-DHk3bHnN.js.map} +1 -1
  11. package/dist/web-dist/assets/_table-dUsH_2LP.js +1 -0
  12. package/dist/web-dist/assets/{_table-CQhKMAcZ.js.map → _table-dUsH_2LP.js.map} +1 -1
  13. package/dist/web-dist/assets/{browser-CFsrLhq1.js → browser-CKmBpcoz.js} +1 -1
  14. package/dist/web-dist/assets/{browser-CFsrLhq1.js.map → browser-CKmBpcoz.js.map} +1 -1
  15. package/dist/web-dist/assets/code-editor-C9H5SO98.js +9 -0
  16. package/dist/web-dist/assets/code-editor-C9H5SO98.js.map +1 -0
  17. package/dist/web-dist/assets/database.store-BvoUSH8Y.js +1 -0
  18. package/dist/web-dist/assets/database.store-BvoUSH8Y.js.map +1 -0
  19. package/dist/web-dist/assets/{dist-B90HBock.js → dist-C-7rnx4R.js} +1 -1
  20. package/dist/web-dist/assets/{dist-B90HBock.js.map → dist-C-7rnx4R.js.map} +1 -1
  21. package/dist/web-dist/assets/highlighted-body-OFNGDK62-qZDgwznf.js +1 -0
  22. package/dist/web-dist/assets/{highlighted-body-OFNGDK62-BGFI1Y6G.js.map → highlighted-body-OFNGDK62-qZDgwznf.js.map} +1 -1
  23. package/dist/web-dist/assets/icons-0UA1AvNu.js +1 -0
  24. package/dist/web-dist/assets/icons-0UA1AvNu.js.map +1 -0
  25. package/dist/web-dist/assets/index-BSNZ1oRs.js +35 -0
  26. package/dist/web-dist/assets/index-BSNZ1oRs.js.map +1 -0
  27. package/dist/web-dist/assets/index-BWKgNfEb.css +2 -0
  28. package/dist/web-dist/assets/{indexes-BKOZUa9Z.js → indexes-D-oUHra7.js} +1 -1
  29. package/dist/web-dist/assets/{indexes-BKOZUa9Z.js.map → indexes-D-oUHra7.js.map} +1 -1
  30. package/dist/web-dist/assets/{logs-DHha3vDy.js → logs-wkipM6zd.js} +1 -1
  31. package/dist/web-dist/assets/{logs-DHha3vDy.js.map → logs-wkipM6zd.js.map} +1 -1
  32. package/dist/web-dist/assets/mermaid-GHXKKRXX-BZ1Tdv8E.js +1 -0
  33. package/dist/web-dist/assets/middleware-CCyr6cvp.js +1 -0
  34. package/dist/web-dist/assets/middleware-CCyr6cvp.js.map +1 -0
  35. package/dist/web-dist/assets/popover-WwEzK7ho.js +1 -0
  36. package/dist/web-dist/assets/popover-WwEzK7ho.js.map +1 -0
  37. package/dist/web-dist/assets/query-runner-B-lngX3P.js +9 -0
  38. package/dist/web-dist/assets/query-runner-B-lngX3P.js.map +1 -0
  39. package/dist/web-dist/assets/{radix-ui-BUv2Nuc1.js → radix-ui-6dcJ5m4U.js} +1 -1
  40. package/dist/web-dist/assets/{radix-ui-BUv2Nuc1.js.map → radix-ui-6dcJ5m4U.js.map} +1 -1
  41. package/dist/web-dist/assets/react-B_x-GW6a.js +1 -0
  42. package/dist/web-dist/assets/react-B_x-GW6a.js.map +1 -0
  43. package/dist/web-dist/assets/{react-dom-0lXVP1OR.js → react-dom-CsRkF-uK.js} +1 -1
  44. package/dist/web-dist/assets/{react-dom-0lXVP1OR.js.map → react-dom-CsRkF-uK.js.map} +1 -1
  45. package/dist/web-dist/assets/{redis-value-CJoRCZun.js → redis-value-Dq29EMpv.js} +1 -1
  46. package/dist/web-dist/assets/{redis-value-CJoRCZun.js.map → redis-value-Dq29EMpv.js.map} +1 -1
  47. package/dist/web-dist/assets/runner-CL63BPMX.js +1 -0
  48. package/dist/web-dist/assets/{runner-CZKDzRoU.js.map → runner-CL63BPMX.js.map} +1 -1
  49. package/dist/web-dist/assets/schema-BNzZaUjg.js +64 -0
  50. package/dist/web-dist/assets/schema-BNzZaUjg.js.map +1 -0
  51. package/dist/web-dist/assets/{schema-0sozVL-z.js → schema-CIr5j9z3.js} +1 -1
  52. package/dist/web-dist/assets/{schema-0sozVL-z.js.map → schema-CIr5j9z3.js.map} +1 -1
  53. package/dist/web-dist/assets/{table-CPQhgD-a.js → table-BoQghHv7.js} +1 -1
  54. package/dist/web-dist/assets/{table-CPQhgD-a.js.map → table-BoQghHv7.js.map} +1 -1
  55. package/dist/web-dist/assets/tanstack-C-qfmRNM.js +10 -0
  56. package/dist/web-dist/assets/tanstack-C-qfmRNM.js.map +1 -0
  57. package/dist/web-dist/assets/toggle-group-CxRlYNqR.js +1 -0
  58. package/dist/web-dist/assets/toggle-group-CxRlYNqR.js.map +1 -0
  59. package/dist/web-dist/assets/{tooltip-DinwklI8.js → tooltip-1-bWFncb.js} +2 -2
  60. package/dist/web-dist/assets/{tooltip-DinwklI8.js.map → tooltip-1-bWFncb.js.map} +1 -1
  61. package/dist/web-dist/assets/{visualizer-DTPn0ywW.js → visualizer-qFaRAy7F.js} +1 -1
  62. package/dist/web-dist/assets/{visualizer-DTPn0ywW.js.map → visualizer-qFaRAy7F.js.map} +1 -1
  63. package/dist/web-dist/index.html +13 -11
  64. package/package.json +1 -1
  65. package/dist/web-dist/assets/_pathlessLayout-CEv6uosT.js +0 -1
  66. package/dist/web-dist/assets/_pathlessLayout-eo6iLvBo.js.map +0 -1
  67. package/dist/web-dist/assets/_queryId-Bq64AuuI.js +0 -1
  68. package/dist/web-dist/assets/_table-CQhKMAcZ.js +0 -1
  69. package/dist/web-dist/assets/code-editor-DQ86aZkm.js +0 -9
  70. package/dist/web-dist/assets/code-editor-DQ86aZkm.js.map +0 -1
  71. package/dist/web-dist/assets/database.store-KDHkiedw.js +0 -1
  72. package/dist/web-dist/assets/database.store-KDHkiedw.js.map +0 -1
  73. package/dist/web-dist/assets/highlighted-body-OFNGDK62-BGFI1Y6G.js +0 -1
  74. package/dist/web-dist/assets/icons-Bm7rSZLJ.js +0 -1
  75. package/dist/web-dist/assets/icons-Bm7rSZLJ.js.map +0 -1
  76. package/dist/web-dist/assets/index-BtqHnOp0.js +0 -23
  77. package/dist/web-dist/assets/index-BtqHnOp0.js.map +0 -1
  78. package/dist/web-dist/assets/index-ktDWx_UP.css +0 -2
  79. package/dist/web-dist/assets/mermaid-GHXKKRXX-DjR37lQN.js +0 -1
  80. package/dist/web-dist/assets/popover-Cm3PsrMh.js +0 -1
  81. package/dist/web-dist/assets/popover-Cm3PsrMh.js.map +0 -1
  82. package/dist/web-dist/assets/query-runner-6BhVPaC9.js +0 -9
  83. package/dist/web-dist/assets/query-runner-6BhVPaC9.js.map +0 -1
  84. package/dist/web-dist/assets/runner-CZKDzRoU.js +0 -1
  85. package/dist/web-dist/assets/schema-cZHeTHA0.js +0 -64
  86. package/dist/web-dist/assets/schema-cZHeTHA0.js.map +0 -1
  87. package/dist/web-dist/assets/tanstack-D6l4LIt3.js +0 -10
  88. package/dist/web-dist/assets/tanstack-D6l4LIt3.js.map +0 -1
  89. package/dist/web-dist/assets/toggle-group-BRWnLosM.js +0 -1
  90. package/dist/web-dist/assets/toggle-group-BRWnLosM.js.map +0 -1
package/dist/index.js CHANGED
@@ -130,7 +130,7 @@ ${s.join(`,
130
130
  `)).recordset[0]?.constraint_name;u&&await i.request().query(`ALTER TABLE [${t}] DROP CONSTRAINT [${u}]`);let m=o?"NULL":"NOT NULL";await i.request().query(`ALTER TABLE [${t}] ALTER COLUMN [${r}] ${a} ${m}`),s?.trim()&&await i.request().query(`ALTER TABLE [${t}] ADD DEFAULT ${s.trim()} FOR [${r}]`)}async renameColumn(e){let{tableName:t,columnName:r,newColumnName:a,db:o}=e,s=await V(o);await this.assertTableExists(s,t),await this.assertColumnExists(s,t,r);let c=await s.request().input("tableName",t).input("columnName",a).query(`
131
131
  SELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.COLUMNS
132
132
  WHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND COLUMN_NAME = @columnName AND TABLE_SCHEMA = 'dbo'
133
- `);if(Number(c.recordset[0]?.cnt??0)>0)throw new q(409,{message:`Column "${a}" already exists in table "${t}"`});await s.request().query(`EXEC sp_rename '${t}.${r}', '${a}', 'COLUMN'`)}async addRecord({db:e,params:t}){let{tableName:r,data:a}=t,o=await V(e),s=await this.getBooleanColumnSet(r,e),c=await o.request().input("tableName",r).query("SELECT name FROM sys.columns WHERE object_id = OBJECT_ID(@tableName) AND is_identity = 1"),i=new Set(c.recordset.map(y=>y.name)),l=Object.keys(a).filter(y=>!i.has(y)),u=l.map(y=>{let g=a[y];return s.has(y)&&typeof g=="string"?g==="true"?1:0:g}),m=l.map(y=>`[${y}]`).join(", "),p=l.map((y,g)=>`@param${g}`).join(", "),d=o.request();l.forEach((y,g)=>{d.input(`param${g}`,u[g])});let f=await d.query(`INSERT INTO [${r}] (${m}) VALUES (${p})`);if(f.rowsAffected[0]===0)throw new q(500,{message:`Failed to insert record into "${r}"`});return{insertedCount:f.rowsAffected[0]??0}}async updateRecords({params:e,db:t}){let{tableName:r,updates:a,primaryKey:o}=e,s=await V(t),c=await this.getBooleanColumnSet(r,t),i=new Map;for(let u of a){let m=u.rowData[o];if(m==null)throw new q(400,{message:`Primary key "${o}" not found in row data.`});i.has(m)||i.set(m,[]),i.get(m)?.push({columnName:u.columnName,value:u.value})}let l=s.transaction();await l.begin();try{let u=0;for(let[m,p]of i.entries()){let d=l.request(),f=p.map((g,E)=>`[${g.columnName}] = @value${E}`);p.forEach((g,E)=>{let T=g.value;T!==null&&typeof T=="object"&&(T=JSON.stringify(T)),c.has(g.columnName)&&typeof T=="string"&&(T=T==="true"?1:0),d.input(`value${E}`,T)}),d.input("pkValue",m);let y=await d.query(`UPDATE [${r}] SET ${f.join(", ")} WHERE [${o}] = @pkValue`);if(y.rowsAffected[0]===0)throw new q(404,{message:`Record with ${o} = ${m} not found in table "${r}"`});u+=y.rowsAffected[0]??0}return await l.commit(),{updatedCount:u}}catch(u){throw await l.rollback(),u instanceof q?u:new q(500,{message:`Failed to update records in "${r}"`})}}async deleteRecords({tableName:e,primaryKeys:t,db:r}){let a=await V(r),o=t[0]?.columnName;if(!o)throw new q(400,{message:"Primary key column name is required"});let s=t.map(i=>i.value),c=a.transaction();await c.begin();try{let i=c.request();s.forEach((m,p)=>{i.input(`pk${p}`,m)});let l=s.map((m,p)=>`@pk${p}`).join(", "),u=await i.query(`DELETE FROM [${e}] WHERE [${o}] IN (${l})`);return await c.commit(),{deletedCount:u.rowsAffected[0]??0,fkViolation:!1,relatedRecords:[]}}catch(i){if(await c.rollback(),i.number===Xs)return{deletedCount:0,fkViolation:!0,relatedRecords:await this.getRelatedRecords(e,t,r)};throw i instanceof q?i:new q(500,{message:`Failed to delete records from "${e}"`})}}async forceDeleteRecords({tableName:e,primaryKeys:t,db:r}){let a=await V(r),o=t[0]?.columnName;if(!o)throw new q(400,{message:"Primary key column name is required"});let s=t.map(i=>i.value),c=a.transaction();await c.begin();try{let i=await this.getForeignKeyReferences(e,r),l=0,u=new Set,m=new Set,p=async(g,E,T,S)=>{let C=`${g}.${E}`;if(S.has(C))return;S.add(C);let R=await this.getForeignKeyReferences(g,r);for(let x of R){let O=c.request();T.forEach((G,re)=>{O.input(`val${re}`,G)});let $=T.map((G,re)=>`@val${re}`).join(", "),j=(await O.query(`SELECT [${x.referencedColumn}] FROM [${g}] WHERE [${E}] IN (${$})`)).recordset.map(G=>G[x.referencedColumn]);j.length>0&&await p(x.referencingTable,x.referencingColumn,j,S)}let w=c.request();T.forEach((x,O)=>{w.input(`delVal${O}`,x)});let A=T.map((x,O)=>`@delVal${O}`).join(", "),_=await w.query(`DELETE FROM [${g}] WHERE [${E}] IN (${A})`);l+=_.rowsAffected[0]??0,u.add(g)};for(let g of i)u.has(g.referencingTable)||await p(g.referencingTable,g.referencingColumn,s,m);let d=c.request();s.forEach((g,E)=>{d.input(`mainPk${E}`,g)});let f=s.map((g,E)=>`@mainPk${E}`).join(", "),y=await d.query(`DELETE FROM [${e}] WHERE [${o}] IN (${f})`);return await c.commit(),{deletedCount:(y.rowsAffected[0]??0)+l}}catch(i){throw await c.rollback(),i instanceof q?i:new q(500,{message:`Failed to force delete records from "${e}"`})}}async bulkInsertRecords({tableName:e,records:t,db:r}){if(!t||t.length===0)throw new q(400,{message:"At least one record is required"});let o=(await V(r)).transaction();try{let s=Object.keys(t[0]),c=s.map(l=>`[${l}]`).join(", "),i=await this.getBooleanColumnSet(e,r);await o.begin();for(let l=0;l<t.length;l++){let u=t[l],m=o.request(),p=s.map(f=>{let y=u[f];return i.has(f)&&typeof y=="string"?y==="true"?1:0:y}),d=s.map((f,y)=>`@p${l}_${y}`).join(", ");s.forEach((f,y)=>{m.input(`p${l}_${y}`,p[y])});try{await m.query(`INSERT INTO [${e}] (${c}) VALUES (${d})`)}catch(f){throw new q(500,{message:`Failed to insert record ${l+1}: ${f instanceof Error?f.message:String(f)}`})}}return await o.commit(),{success:!0,message:`Successfully inserted ${t.length} record${t.length!==1?"s":""}`,successCount:t.length,failureCount:0}}catch(s){throw await o.rollback(),s instanceof q?s:new q(500,{message:`Failed to bulk insert records into "${e}"`})}}async executeQuery({query:e,db:t}){let r=await V(t);if(!e?.trim())throw new q(400,{message:"Query is required"});let a=e.trim().replace(/;+$/,""),o=performance.now(),s=await r.request().query(a),c=performance.now()-o;if(s.recordset){let i=s.recordset;return{columns:s.recordset.columns?Object.keys(s.recordset.columns):Object.keys(i[0]??{}),rows:i,rowCount:i.length,duration:c,message:i.length===0?"OK":void 0}}return{columns:[],rows:[],rowCount:s.rowsAffected[0]??0,duration:c,message:`OK \u2014 ${s.rowsAffected[0]??0} row(s) affected`}}async getForeignKeyReferences(e,t){return(await(await V(t)).request().input("tableName",e).query(`
133
+ `);if(Number(c.recordset[0]?.cnt??0)>0)throw new q(409,{message:`Column "${a}" already exists in table "${t}"`});await s.request().query(`EXEC sp_rename '${t}.${r}', '${a}', 'COLUMN'`)}async addRecord({db:e,params:t}){let{tableName:r,data:a}=t,o=await V(e),s=await this.getBooleanColumnSet(r,e),c=await o.request().input("tableName",r).query("SELECT name FROM sys.columns WHERE object_id = OBJECT_ID(@tableName) AND is_identity = 1"),i=new Set(c.recordset.map(y=>y.name)),l=Object.keys(a).filter(y=>!i.has(y)),u=l.map(y=>{let g=a[y];return s.has(y)&&typeof g=="string"?g==="true"?1:0:g}),m=l.map(y=>`[${y}]`).join(", "),p=l.map((y,g)=>`@param${g}`).join(", "),d=o.request();l.forEach((y,g)=>{d.input(`param${g}`,u[g])});let f=await d.query(`INSERT INTO [${r}] (${m}) VALUES (${p})`);if(f.rowsAffected[0]===0)throw new q(500,{message:`Failed to insert record into "${r}"`});return{insertedCount:f.rowsAffected[0]??0}}async updateRecords({params:e,db:t}){let{tableName:r,updates:a,primaryKey:o}=e,s=await V(t),c=await this.getBooleanColumnSet(r,t),i=new Map;for(let u of a){let m=u.rowData[o];if(m==null)throw new q(400,{message:`Primary key "${o}" not found in row data.`});i.has(m)||i.set(m,[]),i.get(m)?.push({columnName:u.columnName,value:u.value})}let l=s.transaction();await l.begin();try{let u=0;for(let[m,p]of i.entries()){let d=l.request(),f=p.map((g,E)=>`[${g.columnName}] = @value${E}`);p.forEach((g,E)=>{let T=g.value;T!==null&&typeof T=="object"&&(T=JSON.stringify(T)),c.has(g.columnName)&&typeof T=="string"&&(T=T==="true"?1:0),d.input(`value${E}`,T)}),d.input("pkValue",m);let y=await d.query(`UPDATE [${r}] SET ${f.join(", ")} WHERE [${o}] = @pkValue`);if(y.rowsAffected[0]===0)throw new q(404,{message:`Record with ${o} = ${m} not found in table "${r}"`});u+=y.rowsAffected[0]??0}return await l.commit(),{updatedCount:u}}catch(u){throw await l.rollback(),u instanceof q?u:new q(500,{message:`Failed to update records in "${r}"`})}}async deleteRecords({tableName:e,primaryKeys:t,db:r}){let a=await V(r),o=t[0]?.columnName;if(!o)throw new q(400,{message:"Primary key column name is required"});let s=t.map(i=>i.value),c=a.transaction();await c.begin();try{let i=c.request();s.forEach((m,p)=>{i.input(`pk${p}`,m)});let l=s.map((m,p)=>`@pk${p}`).join(", "),u=await i.query(`DELETE FROM [${e}] WHERE [${o}] IN (${l})`);return await c.commit(),{deletedCount:u.rowsAffected[0]??0,fkViolation:!1,relatedRecords:[]}}catch(i){if(await c.rollback(),i.number===Xs)return{deletedCount:0,fkViolation:!0,relatedRecords:await this.getRelatedRecords(e,t,r)};throw i instanceof q?i:new q(500,{message:`Failed to delete records from "${e}"`})}}async forceDeleteRecords({tableName:e,primaryKeys:t,db:r}){let a=await V(r),o=t[0]?.columnName;if(!o)throw new q(400,{message:"Primary key column name is required"});let s=t.map(i=>i.value),c=a.transaction();await c.begin();try{let i=await this.getForeignKeyReferences(e,r),l=0,u=new Set,m=new Set,p=async(g,E,T,S)=>{let C=`${g}.${E}`;if(S.has(C))return;S.add(C);let R=await this.getForeignKeyReferences(g,r);for(let x of R){let $=c.request();T.forEach((G,re)=>{$.input(`val${re}`,G)});let O=T.map((G,re)=>`@val${re}`).join(", "),j=(await $.query(`SELECT [${x.referencedColumn}] FROM [${g}] WHERE [${E}] IN (${O})`)).recordset.map(G=>G[x.referencedColumn]);j.length>0&&await p(x.referencingTable,x.referencingColumn,j,S)}let w=c.request();T.forEach((x,$)=>{w.input(`delVal${$}`,x)});let A=T.map((x,$)=>`@delVal${$}`).join(", "),_=await w.query(`DELETE FROM [${g}] WHERE [${E}] IN (${A})`);l+=_.rowsAffected[0]??0,u.add(g)};for(let g of i)u.has(g.referencingTable)||await p(g.referencingTable,g.referencingColumn,s,m);let d=c.request();s.forEach((g,E)=>{d.input(`mainPk${E}`,g)});let f=s.map((g,E)=>`@mainPk${E}`).join(", "),y=await d.query(`DELETE FROM [${e}] WHERE [${o}] IN (${f})`);return await c.commit(),{deletedCount:(y.rowsAffected[0]??0)+l}}catch(i){throw await c.rollback(),i instanceof q?i:new q(500,{message:`Failed to force delete records from "${e}"`})}}async bulkInsertRecords({tableName:e,records:t,db:r}){if(!t||t.length===0)throw new q(400,{message:"At least one record is required"});let o=(await V(r)).transaction();try{let s=Object.keys(t[0]),c=s.map(l=>`[${l}]`).join(", "),i=await this.getBooleanColumnSet(e,r);await o.begin();for(let l=0;l<t.length;l++){let u=t[l],m=o.request(),p=s.map(f=>{let y=u[f];return i.has(f)&&typeof y=="string"?y==="true"?1:0:y}),d=s.map((f,y)=>`@p${l}_${y}`).join(", ");s.forEach((f,y)=>{m.input(`p${l}_${y}`,p[y])});try{await m.query(`INSERT INTO [${e}] (${c}) VALUES (${d})`)}catch(f){throw new q(500,{message:`Failed to insert record ${l+1}: ${f instanceof Error?f.message:String(f)}`})}}return await o.commit(),{success:!0,message:`Successfully inserted ${t.length} record${t.length!==1?"s":""}`,successCount:t.length,failureCount:0}}catch(s){throw await o.rollback(),s instanceof q?s:new q(500,{message:`Failed to bulk insert records into "${e}"`})}}async executeQuery({query:e,db:t}){let r=await V(t);if(!e?.trim())throw new q(400,{message:"Query is required"});let a=e.trim().replace(/;+$/,""),o=performance.now(),s=await r.request().query(a),c=performance.now()-o;if(s.recordset){let i=s.recordset;return{columns:s.recordset.columns?Object.keys(s.recordset.columns):Object.keys(i[0]??{}),rows:i,rowCount:i.length,duration:c,message:i.length===0?"OK":void 0}}return{columns:[],rows:[],rowCount:s.rowsAffected[0]??0,duration:c,message:`OK \u2014 ${s.rowsAffected[0]??0} row(s) affected`}}async getForeignKeyReferences(e,t){return(await(await V(t)).request().input("tableName",e).query(`
134
134
  SELECT
135
135
  fk.name AS constraint_name,
136
136
  OBJECT_NAME(fk.parent_object_id) AS referencing_table,
@@ -146,7 +146,7 @@ ${s.join(`,
146
146
  `);if(Number(r.recordset[0]?.cnt??0)===0)throw new q(404,{message:`Table "${t}" does not exist`})}async assertColumnExists(e,t,r){let a=await e.request().input("tableName",t).input("columnName",r).query(`
147
147
  SELECT COUNT(*) as cnt FROM INFORMATION_SCHEMA.COLUMNS
148
148
  WHERE TABLE_CATALOG = DB_NAME() AND TABLE_NAME = @tableName AND COLUMN_NAME = @columnName AND TABLE_SCHEMA = 'dbo'
149
- `);if(Number(a.recordset[0]?.cnt??0)===0)throw new q(404,{message:`Column "${r}" does not exist in table "${t}"`})}parseCheckConstraintValues(e){let t=e.match(/'([^']+)'/g);return!t||t.length===0?null:t.map(r=>r.slice(1,-1))}makeCursor(e){return this.encodeCursor({values:{_offset:e},sortColumns:["_offset"]})}decodeOffsetCursor(e){let t=this.decodeCursor(e);return Number(t?.values._offset??0)}}});function kr(n){if(n.length===0)return{clause:"",values:[]};let e=[],t=[];for(let r of n){let a=`\`${r.columnName}\``;switch(r.operator){case"=":case"!=":case">":case">=":case"<":case"<=":e.push(`${a} ${r.operator} ?`),t.push(r.value);break;case"is":r.value.toLowerCase()==="null"?e.push(`${a} IS NULL`):(e.push(`${a} = ?`),t.push(r.value));break;case"is not":r.value.toLowerCase()==="null"?e.push(`${a} IS NOT NULL`):(e.push(`${a} != ?`),t.push(r.value));break;case"like":case"ilike":e.push(`${a} LIKE ?`),t.push(r.value);break;case"not like":case"not ilike":e.push(`${a} NOT LIKE ?`),t.push(r.value);break;default:break}}return e.length===0?{clause:"",values:[]}:{clause:`WHERE ${e.join(" AND ")}`,values:t}}function Ir(n,e){return Array.isArray(n)?n.length===0?"":`ORDER BY ${n.map(t=>`\`${t.columnName}\` ${t.direction.toUpperCase()}`).join(", ")}`:n&&typeof n=="string"?`ORDER BY \`${n}\` ${e?.toUpperCase()||"ASC"}`:""}function qr(n,e,t){let{values:r,sortColumns:a}=n;if(a.length===0)return{clause:"",values:[]};let i=t==="asc"===(e==="asc")?">":"<",l=a.map(p=>`\`${p}\``).join(", "),u=a.map(()=>"?").join(", "),m=a.map(p=>r[p]);return{clause:`(${l}) ${i} (${u})`,values:m}}function ei(n,e){if(e)return"JSON";let t=n.toLowerCase().trim();return{serial:"INT AUTO_INCREMENT",serial4:"INT AUTO_INCREMENT",bigserial:"BIGINT AUTO_INCREMENT",serial8:"BIGINT AUTO_INCREMENT",int:"INT",int4:"INT",integer:"INT",bigint:"BIGINT",int8:"BIGINT",smallint:"SMALLINT",int2:"SMALLINT",numeric:"DECIMAL",decimal:"DECIMAL",real:"FLOAT",float4:"FLOAT",float:"FLOAT","double precision":"DOUBLE",float8:"DOUBLE",money:"DECIMAL(19, 4)",boolean:"TINYINT(1)",bool:"TINYINT(1)",text:"LONGTEXT",varchar:"VARCHAR(255)","character varying":"VARCHAR(255)",char:"CHAR(1)",character:"CHAR(1)",bpchar:"CHAR",uuid:"CHAR(36)",json:"JSON",jsonb:"JSON",xml:"LONGTEXT",date:"DATE",time:"TIME","time without time zone":"TIME",timestamp:"DATETIME","timestamp without time zone":"DATETIME","timestamp with time zone":"DATETIME",timestamptz:"DATETIME",interval:"VARCHAR(255)",bytea:"LONGBLOB",inet:"VARCHAR(45)",cidr:"VARCHAR(45)",macaddr:"VARCHAR(17)",macaddr8:"VARCHAR(23)",point:"POINT",line:"LINESTRING",polygon:"POLYGON"}[t]||n.toUpperCase()}function ti(n,e){if(!n?.trim())return null;let t=n.trim().toLowerCase();return t.includes("(")&&t.includes(")")?t.includes("uuid()")?!e.toUpperCase().includes("CHAR")&&!e.toUpperCase().includes("TEXT")?null:"(UUID())":t.includes("current_timestamp")||t.includes("now()")?"(CURRENT_TIMESTAMP)":t.includes("current_date")?"(CURRENT_DATE)":`(${n.trim()})`:t==="null"?"NULL":t==="true"?"1":t==="false"?"0":n.trim()}function qt(n,e={}){let t=ei(n.columnType,n.isArray??!1),r=`\`${n.columnName}\` ${t}`;if(!n.isNullable&&!n.isPrimaryKey&&(r+=" NOT NULL"),n.defaultValue&&!t.includes("AUTO_INCREMENT")){let a=ti(n.defaultValue,t);a!==null&&(r+=` DEFAULT ${a}`)}return(n.isIdentity||e.preserveAutoIncrement)&&!t.includes("AUTO_INCREMENT")&&(r+=" AUTO_INCREMENT"),e.includeUnique&&n.isUnique&&!n.isPrimaryKey&&(r+=" UNIQUE"),e.includePrimaryKey&&n.isPrimaryKey&&(r+=" PRIMARY KEY"),r}var ba=N(()=>{"use strict"});import{HTTPException as k}from"hono/http-exception";var ga,ri,Ut,ha=N(()=>{"use strict";Re();qe();Be();tt();ba();ga=1451,ri=1217,Ut=class extends ce{async runQuery(e,t,r){let a=z(e),[o]=await a.execute(t,r);return o}quoteIdentifier(e){return`\`${e}\``}mapToUniversalType(e){return Pt(e)}mapFromUniversalType(e){return{text:"LONGTEXT",number:"INT",boolean:"TINYINT(1)",json:"JSON",date:"DATETIME",array:"JSON",enum:"TEXT"}[e]??"LONGTEXT"}buildTableDataQuery(e){let{tableName:t,cursor:r="",limit:a=50,direction:o="asc",sort:s=[],order:c="asc",filters:i=[]}=e,l=[],u=c;Array.isArray(s)&&s.length>0?(l=s.map(R=>R.columnName),u=s[0].direction):typeof s=="string"&&s&&(l=[s]);let{clause:m,values:p}=kr(i),d="",f=[];if(r){let R=this.decodeCursor(r);if(R){let w=qr(R,o,u);d=w.clause,f=w.values}}let y="";m&&d?y=`WHERE ${m.replace(/^WHERE\s+/i,"")} AND ${d}`:m?y=m:d&&(y=`WHERE ${d}`);let g=Ir((Array.isArray(s),s),c),E=g;o==="desc"?g?E=g.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"):l.length>0&&(E=`ORDER BY ${l.map(R=>`\`${R}\` ${u==="asc"?"DESC":"ASC"}`).join(", ")}`):!g&&l.length>0&&(E=`ORDER BY ${l.map(R=>`\`${R}\` ${u.toUpperCase()}`).join(", ")}`);let T=`SELECT * FROM \`${t}\` ${y} ${E} LIMIT ${a+1}`,S=[...p,...f],C=`SELECT COUNT(*) as total FROM \`${t}\` ${m}`;return{sql:T,values:S,countSql:C,countValues:p}}normalizeRows(e){return e.map(t=>this.normalizeRow(t))}buildCursors(e,t,r){if(t.length===0)return{nextCursor:null,prevCursor:null};let{direction:a="asc",sort:o=[],cursor:s}=e,c=[];Array.isArray(o)&&o.length>0?c=o.map(d=>d.columnName):typeof o=="string"&&o&&(c=[o]);let i=d=>this.encodeCursor({values:Object.fromEntries(c.map(f=>[f,d[f]])),sortColumns:c}),l=t[0],u=t[t.length-1],m=null,p=null;return a==="asc"?(r&&(m=i(u)),s&&(p=i(l))):(s&&(m=i(u)),r&&(p=i(l))),{nextCursor:m,prevCursor:p}}async getTableData(e){let{tableName:t,db:r,limit:a=50,direction:o="asc",sort:s=[],order:c="asc",cursor:i,filters:l=[]}=e,u=z(r),m=await this.getPrimaryKeyColumns(u,t),p=[],d=c;Array.isArray(s)&&s.length>0?(p=s.map(j=>j.columnName),d=s[0].direction):typeof s=="string"&&s&&(p=[s]);let f=[...p,...m.filter(j=>!p.includes(j))],{clause:y,values:g}=kr(l),E="",T=[];if(i){let j=this.decodeCursor(i);if(j){let G=qr(j,o,d);E=G.clause,T=G.values}}let S="";y&&E?S=`WHERE ${y.replace(/^WHERE\s+/i,"")} AND ${E}`:y?S=y:E&&(S=`WHERE ${E}`);let C=Ir((Array.isArray(s),s),c),R=C;o==="desc"?C?R=C.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"):f.length>0&&(R=`ORDER BY ${f.map(j=>`\`${j}\` ${d==="asc"?"DESC":"ASC"}`).join(", ")}`):!C&&f.length>0&&(R=`ORDER BY ${f.map(j=>`\`${j}\` ${d.toUpperCase()}`).join(", ")}`);let[w]=await u.execute(`SELECT COUNT(*) as total FROM \`${t}\` ${y}`,g),A=Number(w[0]?.total??0),[_]=await u.execute(`SELECT * FROM \`${t}\` ${S} ${R} LIMIT ${Math.floor(a)+1}`,[...g,...T]),x=_,O=x.length>a;O&&(x=x.slice(0,a)),o==="desc"&&(x=x.reverse());let $=null,U=null;if(x.length>0&&f.length>0){let j=x[0],G=x[x.length-1],re=J=>({values:Object.fromEntries(f.map(Z=>[Z,J[Z]])),sortColumns:f});o==="asc"?(O&&($=this.encodeCursor(re(G))),i&&(U=this.encodeCursor(re(j)))):(i&&($=this.encodeCursor(re(G))),O&&(U=this.encodeCursor(re(j))))}return{data:x,meta:{limit:a,total:A,hasNextPage:o==="asc"?O:!!i,hasPreviousPage:o==="asc"?!!i:O,nextCursor:$,prevCursor:U}}}async getDatabasesList(){let e=z(),[t]=await e.execute(`
149
+ `);if(Number(a.recordset[0]?.cnt??0)===0)throw new q(404,{message:`Column "${r}" does not exist in table "${t}"`})}parseCheckConstraintValues(e){let t=e.match(/'([^']+)'/g);return!t||t.length===0?null:t.map(r=>r.slice(1,-1))}makeCursor(e){return this.encodeCursor({values:{_offset:e},sortColumns:["_offset"]})}decodeOffsetCursor(e){let t=this.decodeCursor(e);return Number(t?.values._offset??0)}}});function kr(n){if(n.length===0)return{clause:"",values:[]};let e=[],t=[];for(let r of n){let a=`\`${r.columnName}\``;switch(r.operator){case"=":case"!=":case">":case">=":case"<":case"<=":e.push(`${a} ${r.operator} ?`),t.push(r.value);break;case"is":r.value.toLowerCase()==="null"?e.push(`${a} IS NULL`):(e.push(`${a} = ?`),t.push(r.value));break;case"is not":r.value.toLowerCase()==="null"?e.push(`${a} IS NOT NULL`):(e.push(`${a} != ?`),t.push(r.value));break;case"like":case"ilike":e.push(`${a} LIKE ?`),t.push(r.value);break;case"not like":case"not ilike":e.push(`${a} NOT LIKE ?`),t.push(r.value);break;default:break}}return e.length===0?{clause:"",values:[]}:{clause:`WHERE ${e.join(" AND ")}`,values:t}}function Ir(n,e){return Array.isArray(n)?n.length===0?"":`ORDER BY ${n.map(t=>`\`${t.columnName}\` ${t.direction.toUpperCase()}`).join(", ")}`:n&&typeof n=="string"?`ORDER BY \`${n}\` ${e?.toUpperCase()||"ASC"}`:""}function qr(n,e,t){let{values:r,sortColumns:a}=n;if(a.length===0)return{clause:"",values:[]};let i=t==="asc"===(e==="asc")?">":"<",l=a.map(p=>`\`${p}\``).join(", "),u=a.map(()=>"?").join(", "),m=a.map(p=>r[p]);return{clause:`(${l}) ${i} (${u})`,values:m}}function ei(n,e){if(e)return"JSON";let t=n.toLowerCase().trim();return{serial:"INT AUTO_INCREMENT",serial4:"INT AUTO_INCREMENT",bigserial:"BIGINT AUTO_INCREMENT",serial8:"BIGINT AUTO_INCREMENT",int:"INT",int4:"INT",integer:"INT",bigint:"BIGINT",int8:"BIGINT",smallint:"SMALLINT",int2:"SMALLINT",numeric:"DECIMAL",decimal:"DECIMAL",real:"FLOAT",float4:"FLOAT",float:"FLOAT","double precision":"DOUBLE",float8:"DOUBLE",money:"DECIMAL(19, 4)",boolean:"TINYINT(1)",bool:"TINYINT(1)",text:"LONGTEXT",varchar:"VARCHAR(255)","character varying":"VARCHAR(255)",char:"CHAR(1)",character:"CHAR(1)",bpchar:"CHAR",uuid:"CHAR(36)",json:"JSON",jsonb:"JSON",xml:"LONGTEXT",date:"DATE",time:"TIME","time without time zone":"TIME",timestamp:"DATETIME","timestamp without time zone":"DATETIME","timestamp with time zone":"DATETIME",timestamptz:"DATETIME",interval:"VARCHAR(255)",bytea:"LONGBLOB",inet:"VARCHAR(45)",cidr:"VARCHAR(45)",macaddr:"VARCHAR(17)",macaddr8:"VARCHAR(23)",point:"POINT",line:"LINESTRING",polygon:"POLYGON"}[t]||n.toUpperCase()}function ti(n,e){if(!n?.trim())return null;let t=n.trim().toLowerCase();return t.includes("(")&&t.includes(")")?t.includes("uuid()")?!e.toUpperCase().includes("CHAR")&&!e.toUpperCase().includes("TEXT")?null:"(UUID())":t.includes("current_timestamp")||t.includes("now()")?"(CURRENT_TIMESTAMP)":t.includes("current_date")?"(CURRENT_DATE)":`(${n.trim()})`:t==="null"?"NULL":t==="true"?"1":t==="false"?"0":n.trim()}function qt(n,e={}){let t=ei(n.columnType,n.isArray??!1),r=`\`${n.columnName}\` ${t}`;if(!n.isNullable&&!n.isPrimaryKey&&(r+=" NOT NULL"),n.defaultValue&&!t.includes("AUTO_INCREMENT")){let a=ti(n.defaultValue,t);a!==null&&(r+=` DEFAULT ${a}`)}return(n.isIdentity||e.preserveAutoIncrement)&&!t.includes("AUTO_INCREMENT")&&(r+=" AUTO_INCREMENT"),e.includeUnique&&n.isUnique&&!n.isPrimaryKey&&(r+=" UNIQUE"),e.includePrimaryKey&&n.isPrimaryKey&&(r+=" PRIMARY KEY"),r}var ba=N(()=>{"use strict"});import{HTTPException as k}from"hono/http-exception";var ga,ri,Ut,ha=N(()=>{"use strict";Re();qe();Be();tt();ba();ga=1451,ri=1217,Ut=class extends ce{async runQuery(e,t,r){let a=z(e),[o]=await a.execute(t,r);return o}quoteIdentifier(e){return`\`${e}\``}mapToUniversalType(e){return Pt(e)}mapFromUniversalType(e){return{text:"LONGTEXT",number:"INT",boolean:"TINYINT(1)",json:"JSON",date:"DATETIME",array:"JSON",enum:"TEXT"}[e]??"LONGTEXT"}buildTableDataQuery(e){let{tableName:t,cursor:r="",limit:a=50,direction:o="asc",sort:s=[],order:c="asc",filters:i=[]}=e,l=[],u=c;Array.isArray(s)&&s.length>0?(l=s.map(R=>R.columnName),u=s[0].direction):typeof s=="string"&&s&&(l=[s]);let{clause:m,values:p}=kr(i),d="",f=[];if(r){let R=this.decodeCursor(r);if(R){let w=qr(R,o,u);d=w.clause,f=w.values}}let y="";m&&d?y=`WHERE ${m.replace(/^WHERE\s+/i,"")} AND ${d}`:m?y=m:d&&(y=`WHERE ${d}`);let g=Ir((Array.isArray(s),s),c),E=g;o==="desc"?g?E=g.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"):l.length>0&&(E=`ORDER BY ${l.map(R=>`\`${R}\` ${u==="asc"?"DESC":"ASC"}`).join(", ")}`):!g&&l.length>0&&(E=`ORDER BY ${l.map(R=>`\`${R}\` ${u.toUpperCase()}`).join(", ")}`);let T=`SELECT * FROM \`${t}\` ${y} ${E} LIMIT ${a+1}`,S=[...p,...f],C=`SELECT COUNT(*) as total FROM \`${t}\` ${m}`;return{sql:T,values:S,countSql:C,countValues:p}}normalizeRows(e){return e.map(t=>this.normalizeRow(t))}buildCursors(e,t,r){if(t.length===0)return{nextCursor:null,prevCursor:null};let{direction:a="asc",sort:o=[],cursor:s}=e,c=[];Array.isArray(o)&&o.length>0?c=o.map(d=>d.columnName):typeof o=="string"&&o&&(c=[o]);let i=d=>this.encodeCursor({values:Object.fromEntries(c.map(f=>[f,d[f]])),sortColumns:c}),l=t[0],u=t[t.length-1],m=null,p=null;return a==="asc"?(r&&(m=i(u)),s&&(p=i(l))):(s&&(m=i(u)),r&&(p=i(l))),{nextCursor:m,prevCursor:p}}async getTableData(e){let{tableName:t,db:r,limit:a=50,direction:o="asc",sort:s=[],order:c="asc",cursor:i,filters:l=[]}=e,u=z(r),m=await this.getPrimaryKeyColumns(u,t),p=[],d=c;Array.isArray(s)&&s.length>0?(p=s.map(j=>j.columnName),d=s[0].direction):typeof s=="string"&&s&&(p=[s]);let f=[...p,...m.filter(j=>!p.includes(j))],{clause:y,values:g}=kr(l),E="",T=[];if(i){let j=this.decodeCursor(i);if(j){let G=qr(j,o,d);E=G.clause,T=G.values}}let S="";y&&E?S=`WHERE ${y.replace(/^WHERE\s+/i,"")} AND ${E}`:y?S=y:E&&(S=`WHERE ${E}`);let C=Ir((Array.isArray(s),s),c),R=C;o==="desc"?C?R=C.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"):f.length>0&&(R=`ORDER BY ${f.map(j=>`\`${j}\` ${d==="asc"?"DESC":"ASC"}`).join(", ")}`):!C&&f.length>0&&(R=`ORDER BY ${f.map(j=>`\`${j}\` ${d.toUpperCase()}`).join(", ")}`);let[w]=await u.execute(`SELECT COUNT(*) as total FROM \`${t}\` ${y}`,g),A=Number(w[0]?.total??0),[_]=await u.execute(`SELECT * FROM \`${t}\` ${S} ${R} LIMIT ${Math.floor(a)+1}`,[...g,...T]),x=_,$=x.length>a;$&&(x=x.slice(0,a)),o==="desc"&&(x=x.reverse());let O=null,U=null;if(x.length>0&&f.length>0){let j=x[0],G=x[x.length-1],re=J=>({values:Object.fromEntries(f.map(Z=>[Z,J[Z]])),sortColumns:f});o==="asc"?($&&(O=this.encodeCursor(re(G))),i&&(U=this.encodeCursor(re(j)))):(i&&(O=this.encodeCursor(re(G))),$&&(U=this.encodeCursor(re(j))))}return{data:x,meta:{limit:a,total:A,hasNextPage:o==="asc"?$:!!i,hasPreviousPage:o==="asc"?!!i:$,nextCursor:O,prevCursor:U}}}async getDatabasesList(){let e=z(),[t]=await e.execute(`
150
150
  SELECT
151
151
  s.SCHEMA_NAME AS name,
152
152
  CONCAT(ROUND(COALESCE(SUM(t.data_length + t.index_length), 0) / 1024 / 1024, 2), ' MB') AS size,
@@ -190,7 +190,7 @@ ${s.join(`,
190
190
  AND kcu.REFERENCED_TABLE_NAME IS NOT NULL
191
191
  WHERE c.TABLE_SCHEMA = DATABASE()
192
192
  AND c.TABLE_NAME = ?
193
- ORDER BY c.ORDINAL_POSITION`,[e]);if(!a||a.length===0)throw new k(404,{message:`Table "${e}" does not exist`});return a.map(o=>{let s=o.dataType==="enum"||o.dataType==="set";return{columnName:o.columnName,dataType:Pt(o.dataType,o.columnType),dataTypeLabel:fr(o.dataType,o.columnType),isNullable:!!o.isNullable,columnDefault:o.columnDefault??null,isPrimaryKey:!!o.isPrimaryKey,isForeignKey:!!o.isForeignKey,referencedTable:o.referencedTable??null,referencedColumn:o.referencedColumn??null,enumValues:s?this.parseMysqlEnumValues(o.columnType):null}})}async addColumn(e){let{tableName:t,columnName:r,columnType:a,defaultValue:o,isPrimaryKey:s,isNullable:c,isUnique:i,isIdentity:l,isArray:u,db:m}=e,p=z(m);await this.assertTableExists(p,t);let[d]=await p.execute("SELECT COUNT(*) as cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?",[t,r]);if(Number(d[0]?.cnt??0)>0)throw new k(409,{message:`Column "${r}" already exists in table "${t}"`});let f=qt({columnName:r,columnType:a,defaultValue:o,isPrimaryKey:s,isNullable:c,isUnique:i,isIdentity:l,isArray:u},{includePrimaryKey:!0,includeUnique:!0});await p.execute(`ALTER TABLE \`${t}\` ADD COLUMN ${f}`)}async deleteColumn(e){let{tableName:t,columnName:r,db:a}=e,o=z(a);await this.assertTableExists(o,t),await this.assertColumnExists(o,t,r);let[s]=await o.execute(`ALTER TABLE \`${t}\` DROP COLUMN \`${r}\``);return{deletedCount:s.affectedRows}}async alterColumn(e){let{tableName:t,columnName:r,columnType:a,isNullable:o,defaultValue:s,db:c}=e,i=z(c);await this.assertTableExists(i,t);let[l]=await i.execute("SELECT EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ? LIMIT 1",[t,r]),u=l[0];if(!u)throw new k(404,{message:`Column "${r}" does not exist in table "${t}"`});let m=qt({columnName:r,columnType:a,defaultValue:s,isNullable:o},{preserveAutoIncrement:u.EXTRA?.toLowerCase().includes("auto_increment")});await i.execute(`ALTER TABLE \`${t}\` MODIFY COLUMN ${m}`)}async renameColumn(e){let{tableName:t,columnName:r,newColumnName:a,db:o}=e,s=z(o);await this.assertTableExists(s,t),await this.assertColumnExists(s,t,r);let[c]=await s.execute("SELECT COUNT(*) as cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?",[t,a]);if(Number(c[0]?.cnt??0)>0)throw new k(409,{message:`Column "${a}" already exists in table "${t}"`});await s.execute(`ALTER TABLE \`${t}\` RENAME COLUMN \`${r}\` TO \`${a}\``)}async addRecord({db:e,params:t}){let{tableName:r,data:a}=t,o=z(e),s=await this.getBooleanColumnSet(r,e),c=Object.keys(a),i=Object.values(a).map((u,m)=>s.has(c[m])&&typeof u=="string"?u==="true"?1:0:u),[l]=await o.execute(`INSERT INTO \`${r}\` (${c.map(u=>`\`${u}\``).join(", ")}) VALUES (${c.map(()=>"?").join(", ")})`,i);if(l.affectedRows===0)throw new k(500,{message:`Failed to insert record into "${r}"`});return{insertedCount:l.affectedRows}}async updateRecords({params:e,db:t}){let{tableName:r,updates:a,primaryKey:o}=e,s=z(t),c=await this.getBooleanColumnSet(r,t),i=new Map;for(let u of a){let m=u.rowData[o];if(m==null)throw new k(400,{message:`Primary key "${o}" not found in row data.`});i.has(m)||i.set(m,[]),i.get(m)?.push({columnName:u.columnName,value:u.value})}let l=await s.getConnection();await l.beginTransaction();try{let u=0;for(let[m,p]of i.entries()){let d=p.map(g=>`\`${g.columnName}\` = ?`),f=p.map(g=>g.value!==null&&typeof g.value=="object"?JSON.stringify(g.value):c.has(g.columnName)&&typeof g.value=="string"?g.value==="true"?1:0:g.value);f.push(m);let[y]=await l.execute(`UPDATE \`${r}\` SET ${d.join(", ")} WHERE \`${o}\` = ?`,f);if(y.affectedRows===0)throw new k(404,{message:`Record with ${o} = ${m} not found in table "${r}"`});u+=y.affectedRows}return await l.commit(),{updatedCount:u}}catch(u){throw await l.rollback(),u instanceof k?u:new k(500,{message:`Failed to update records in "${r}"`})}finally{l.release()}}async deleteRecords({tableName:e,primaryKeys:t,db:r}){let a=z(r),o=t[0]?.columnName;if(!o)throw new k(400,{message:"Primary key column name is required"});let s=t.map(l=>l.value),c=s.map(()=>"?").join(", "),i=await a.getConnection();await i.beginTransaction();try{let[l]=await i.execute(`DELETE FROM \`${e}\` WHERE \`${o}\` IN (${c})`,s);return await i.commit(),{deletedCount:l.affectedRows,fkViolation:!1,relatedRecords:[]}}catch(l){if(await i.rollback(),l.errno===ga)return{deletedCount:0,fkViolation:!0,relatedRecords:await this.getRelatedRecords(e,t,r)};throw l instanceof k?l:new k(500,{message:`Failed to delete records from "${e}"`})}finally{i.release()}}async forceDeleteRecords({tableName:e,primaryKeys:t,db:r}){let a=z(r),o=t[0]?.columnName;if(!o)throw new k(400,{message:"Primary key column name is required"});let s=t.map(i=>i.value),c=await a.getConnection();await c.beginTransaction();try{await c.execute("SET FOREIGN_KEY_CHECKS = 0");let i=await this.getForeignKeyReferences(e,r),l=0,u=new Set,m=new Set,p=async(y,g,E,T)=>{let S=`${y}.${g}`;if(T.has(S))return;T.add(S);let C=await this.getForeignKeyReferences(y,r);for(let A of C){let _=E.map(()=>"?").join(", "),[x]=await c.execute(`SELECT \`${A.referencedColumn}\` FROM \`${y}\` WHERE \`${g}\` IN (${_})`,E),O=x.map($=>$[A.referencedColumn]);O.length>0&&await p(A.referencingTable,A.referencingColumn,O,T)}let R=E.map(()=>"?").join(", "),[w]=await c.execute(`DELETE FROM \`${y}\` WHERE \`${g}\` IN (${R})`,E);l+=w.affectedRows,u.add(y)};for(let y of i)u.has(y.referencingTable)||await p(y.referencingTable,y.referencingColumn,s,m);let d=s.map(()=>"?").join(", "),[f]=await c.execute(`DELETE FROM \`${e}\` WHERE \`${o}\` IN (${d})`,s);return await c.execute("SET FOREIGN_KEY_CHECKS = 1"),await c.commit(),{deletedCount:f.affectedRows+l}}catch(i){throw await c.execute("SET FOREIGN_KEY_CHECKS = 1").catch(()=>{}),await c.rollback(),i instanceof k?i:new k(500,{message:`Failed to force delete records from "${e}"`})}finally{c.release()}}async bulkInsertRecords({tableName:e,records:t,db:r}){if(!t||t.length===0)throw new k(400,{message:"At least one record is required"});let o=await z(r).getConnection();try{let s=Object.keys(t[0]),c=s.map(l=>`\`${l}\``).join(", "),i=await this.getBooleanColumnSet(e,r);await o.beginTransaction();for(let l=0;l<t.length;l++){let u=t[l],m=s.map(p=>{let d=u[p];return i.has(p)&&typeof d=="string"?d==="true"?1:0:d});try{await o.execute(`INSERT INTO \`${e}\` (${c}) VALUES (${s.map(()=>"?").join(", ")})`,m)}catch(p){throw new k(500,{message:`Failed to insert record ${l+1}: ${p instanceof Error?p.message:String(p)}`})}}return await o.commit(),{success:!0,message:`Successfully inserted ${t.length} record${t.length!==1?"s":""}`,successCount:t.length,failureCount:0}}catch(s){throw await o.rollback(),s instanceof k?s:new k(500,{message:`Failed to bulk insert records into "${e}"`})}finally{o.release()}}async executeQuery({query:e,db:t}){let r=z(t);if(!e?.trim())throw new k(400,{message:"Query is required"});let a=e.trim().replace(/;+$/,""),o=performance.now(),[s,c]=await r.execute(a),i=performance.now()-o;if(Array.isArray(s)){let u=s;return{columns:c?c.map(p=>p.name):Object.keys(u[0]??{}),rows:u,rowCount:u.length,duration:i,message:u.length===0?"OK":void 0}}let l=s;return{columns:[],rows:[],rowCount:l.affectedRows,duration:i,message:`OK \u2014 ${l.affectedRows} row(s) affected`}}async getPrimaryKeyColumns(e,t){let[r]=await e.execute(`SELECT COLUMN_NAME as column_name
193
+ ORDER BY c.ORDINAL_POSITION`,[e]);if(!a||a.length===0)throw new k(404,{message:`Table "${e}" does not exist`});return a.map(o=>{let s=o.dataType==="enum"||o.dataType==="set";return{columnName:o.columnName,dataType:Pt(o.dataType,o.columnType),dataTypeLabel:fr(o.dataType,o.columnType),isNullable:!!o.isNullable,columnDefault:o.columnDefault??null,isPrimaryKey:!!o.isPrimaryKey,isForeignKey:!!o.isForeignKey,referencedTable:o.referencedTable??null,referencedColumn:o.referencedColumn??null,enumValues:s?this.parseMysqlEnumValues(o.columnType):null}})}async addColumn(e){let{tableName:t,columnName:r,columnType:a,defaultValue:o,isPrimaryKey:s,isNullable:c,isUnique:i,isIdentity:l,isArray:u,db:m}=e,p=z(m);await this.assertTableExists(p,t);let[d]=await p.execute("SELECT COUNT(*) as cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?",[t,r]);if(Number(d[0]?.cnt??0)>0)throw new k(409,{message:`Column "${r}" already exists in table "${t}"`});let f=qt({columnName:r,columnType:a,defaultValue:o,isPrimaryKey:s,isNullable:c,isUnique:i,isIdentity:l,isArray:u},{includePrimaryKey:!0,includeUnique:!0});await p.execute(`ALTER TABLE \`${t}\` ADD COLUMN ${f}`)}async deleteColumn(e){let{tableName:t,columnName:r,db:a}=e,o=z(a);await this.assertTableExists(o,t),await this.assertColumnExists(o,t,r);let[s]=await o.execute(`ALTER TABLE \`${t}\` DROP COLUMN \`${r}\``);return{deletedCount:s.affectedRows}}async alterColumn(e){let{tableName:t,columnName:r,columnType:a,isNullable:o,defaultValue:s,db:c}=e,i=z(c);await this.assertTableExists(i,t);let[l]=await i.execute("SELECT EXTRA FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ? LIMIT 1",[t,r]),u=l[0];if(!u)throw new k(404,{message:`Column "${r}" does not exist in table "${t}"`});let m=qt({columnName:r,columnType:a,defaultValue:s,isNullable:o},{preserveAutoIncrement:u.EXTRA?.toLowerCase().includes("auto_increment")});await i.execute(`ALTER TABLE \`${t}\` MODIFY COLUMN ${m}`)}async renameColumn(e){let{tableName:t,columnName:r,newColumnName:a,db:o}=e,s=z(o);await this.assertTableExists(s,t),await this.assertColumnExists(s,t,r);let[c]=await s.execute("SELECT COUNT(*) as cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?",[t,a]);if(Number(c[0]?.cnt??0)>0)throw new k(409,{message:`Column "${a}" already exists in table "${t}"`});await s.execute(`ALTER TABLE \`${t}\` RENAME COLUMN \`${r}\` TO \`${a}\``)}async addRecord({db:e,params:t}){let{tableName:r,data:a}=t,o=z(e),s=await this.getBooleanColumnSet(r,e),c=Object.keys(a),i=Object.values(a).map((u,m)=>s.has(c[m])&&typeof u=="string"?u==="true"?1:0:u),[l]=await o.execute(`INSERT INTO \`${r}\` (${c.map(u=>`\`${u}\``).join(", ")}) VALUES (${c.map(()=>"?").join(", ")})`,i);if(l.affectedRows===0)throw new k(500,{message:`Failed to insert record into "${r}"`});return{insertedCount:l.affectedRows}}async updateRecords({params:e,db:t}){let{tableName:r,updates:a,primaryKey:o}=e,s=z(t),c=await this.getBooleanColumnSet(r,t),i=new Map;for(let u of a){let m=u.rowData[o];if(m==null)throw new k(400,{message:`Primary key "${o}" not found in row data.`});i.has(m)||i.set(m,[]),i.get(m)?.push({columnName:u.columnName,value:u.value})}let l=await s.getConnection();await l.beginTransaction();try{let u=0;for(let[m,p]of i.entries()){let d=p.map(g=>`\`${g.columnName}\` = ?`),f=p.map(g=>g.value!==null&&typeof g.value=="object"?JSON.stringify(g.value):c.has(g.columnName)&&typeof g.value=="string"?g.value==="true"?1:0:g.value);f.push(m);let[y]=await l.execute(`UPDATE \`${r}\` SET ${d.join(", ")} WHERE \`${o}\` = ?`,f);if(y.affectedRows===0)throw new k(404,{message:`Record with ${o} = ${m} not found in table "${r}"`});u+=y.affectedRows}return await l.commit(),{updatedCount:u}}catch(u){throw await l.rollback(),u instanceof k?u:new k(500,{message:`Failed to update records in "${r}"`})}finally{l.release()}}async deleteRecords({tableName:e,primaryKeys:t,db:r}){let a=z(r),o=t[0]?.columnName;if(!o)throw new k(400,{message:"Primary key column name is required"});let s=t.map(l=>l.value),c=s.map(()=>"?").join(", "),i=await a.getConnection();await i.beginTransaction();try{let[l]=await i.execute(`DELETE FROM \`${e}\` WHERE \`${o}\` IN (${c})`,s);return await i.commit(),{deletedCount:l.affectedRows,fkViolation:!1,relatedRecords:[]}}catch(l){if(await i.rollback(),l.errno===ga)return{deletedCount:0,fkViolation:!0,relatedRecords:await this.getRelatedRecords(e,t,r)};throw l instanceof k?l:new k(500,{message:`Failed to delete records from "${e}"`})}finally{i.release()}}async forceDeleteRecords({tableName:e,primaryKeys:t,db:r}){let a=z(r),o=t[0]?.columnName;if(!o)throw new k(400,{message:"Primary key column name is required"});let s=t.map(i=>i.value),c=await a.getConnection();await c.beginTransaction();try{await c.execute("SET FOREIGN_KEY_CHECKS = 0");let i=await this.getForeignKeyReferences(e,r),l=0,u=new Set,m=new Set,p=async(y,g,E,T)=>{let S=`${y}.${g}`;if(T.has(S))return;T.add(S);let C=await this.getForeignKeyReferences(y,r);for(let A of C){let _=E.map(()=>"?").join(", "),[x]=await c.execute(`SELECT \`${A.referencedColumn}\` FROM \`${y}\` WHERE \`${g}\` IN (${_})`,E),$=x.map(O=>O[A.referencedColumn]);$.length>0&&await p(A.referencingTable,A.referencingColumn,$,T)}let R=E.map(()=>"?").join(", "),[w]=await c.execute(`DELETE FROM \`${y}\` WHERE \`${g}\` IN (${R})`,E);l+=w.affectedRows,u.add(y)};for(let y of i)u.has(y.referencingTable)||await p(y.referencingTable,y.referencingColumn,s,m);let d=s.map(()=>"?").join(", "),[f]=await c.execute(`DELETE FROM \`${e}\` WHERE \`${o}\` IN (${d})`,s);return await c.execute("SET FOREIGN_KEY_CHECKS = 1"),await c.commit(),{deletedCount:f.affectedRows+l}}catch(i){throw await c.execute("SET FOREIGN_KEY_CHECKS = 1").catch(()=>{}),await c.rollback(),i instanceof k?i:new k(500,{message:`Failed to force delete records from "${e}"`})}finally{c.release()}}async bulkInsertRecords({tableName:e,records:t,db:r}){if(!t||t.length===0)throw new k(400,{message:"At least one record is required"});let o=await z(r).getConnection();try{let s=Object.keys(t[0]),c=s.map(l=>`\`${l}\``).join(", "),i=await this.getBooleanColumnSet(e,r);await o.beginTransaction();for(let l=0;l<t.length;l++){let u=t[l],m=s.map(p=>{let d=u[p];return i.has(p)&&typeof d=="string"?d==="true"?1:0:d});try{await o.execute(`INSERT INTO \`${e}\` (${c}) VALUES (${s.map(()=>"?").join(", ")})`,m)}catch(p){throw new k(500,{message:`Failed to insert record ${l+1}: ${p instanceof Error?p.message:String(p)}`})}}return await o.commit(),{success:!0,message:`Successfully inserted ${t.length} record${t.length!==1?"s":""}`,successCount:t.length,failureCount:0}}catch(s){throw await o.rollback(),s instanceof k?s:new k(500,{message:`Failed to bulk insert records into "${e}"`})}finally{o.release()}}async executeQuery({query:e,db:t}){let r=z(t);if(!e?.trim())throw new k(400,{message:"Query is required"});let a=e.trim().replace(/;+$/,""),o=performance.now(),[s,c]=await r.execute(a),i=performance.now()-o;if(Array.isArray(s)){let u=s;return{columns:c?c.map(p=>p.name):Object.keys(u[0]??{}),rows:u,rowCount:u.length,duration:i,message:u.length===0?"OK":void 0}}let l=s;return{columns:[],rows:[],rowCount:l.affectedRows,duration:i,message:`OK \u2014 ${l.affectedRows} row(s) affected`}}async getPrimaryKeyColumns(e,t){let[r]=await e.execute(`SELECT COLUMN_NAME as column_name
194
194
  FROM information_schema.COLUMNS
195
195
  WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_KEY = 'PRI'
196
196
  ORDER BY ORDINAL_POSITION`,[t]);return r.map(a=>a.column_name)}async getForeignKeyReferences(e,t){let r=z(t),[a]=await r.execute(`SELECT
@@ -206,7 +206,7 @@ ${s.join(`,
206
206
  AND kcu.TABLE_NAME = tc.TABLE_NAME
207
207
  WHERE tc.CONSTRAINT_TYPE = 'FOREIGN KEY'
208
208
  AND kcu.TABLE_SCHEMA = DATABASE()
209
- AND kcu.REFERENCED_TABLE_NAME = ?`,[e]);return a.map(o=>({constraintName:o.constraint_name,referencingTable:o.referencing_table,referencingColumn:o.referencing_column,referencedTable:o.referenced_table,referencedColumn:o.referenced_column}))}async getRelatedRecordsForTable(e,t){let r=await this.getForeignKeyReferences(e,t);if(r.length===0)return[];let a=z(t),o=[];for(let s of r){let[c]=await a.execute(`SELECT * FROM \`${s.referencingTable}\` LIMIT 100`);c.length>0&&o.push({tableName:s.referencingTable,columnName:s.referencingColumn,constraintName:s.constraintName,records:c})}return o}async getRelatedRecords(e,t,r){let a=await this.getForeignKeyReferences(e,r);if(a.length===0)return[];let o=z(r),s=t.map(l=>l.value),c=[],i=new Map;for(let l of a){let u=`${l.referencingTable}.${l.referencingColumn}`;i.has(u)||i.set(u,[]),i.get(u)?.push(l)}for(let[,l]of i){let u=l[0];if(!u||!t.find(f=>f.columnName===u.referencedColumn))continue;let p=s.map(()=>"?").join(", "),[d]=await o.execute(`SELECT * FROM \`${u.referencingTable}\` WHERE \`${u.referencingColumn}\` IN (${p}) LIMIT 100`,s);d.length>0&&c.push({tableName:u.referencingTable,columnName:u.referencingColumn,constraintName:u.constraintName,records:d})}return c}async getTableRowCount(e,t){let[r]=await e.execute(`SELECT COUNT(*) as count FROM \`${t}\``);return Number(r[0]?.count??0)}async getBooleanColumnSet(e,t){let r=await this.getTableColumns({tableName:e,db:t});return new Set(r.filter(a=>a.dataTypeLabel==="boolean").map(a=>a.columnName))}async assertTableExists(e,t){let[r]=await e.execute("SELECT COUNT(*) as cnt FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?",[t]);if(Number(r[0]?.cnt??0)===0)throw new k(404,{message:`Table "${t}" does not exist`})}async assertColumnExists(e,t,r){let[a]=await e.execute("SELECT COUNT(*) as cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?",[t,r]);if(Number(a[0]?.cnt??0)===0)throw new k(404,{message:`Column "${r}" does not exist in table "${t}"`})}parseMysqlEnumValues(e){let t=e.match(/^(?:enum|set)\((.+)\)$/i);return t?.[1]?t[1].split(",").map(r=>r.trim().replace(/^'|'$/g,"")):null}}});function Ur(n){if(n.length===0)return{clause:"",values:[]};let e=[],t=[];for(let r of n){let a=t.length+1,o=`"${r.columnName}"`;switch(r.operator){case"=":case"!=":case">":case">=":case"<":case"<=":e.push(`${o} ${r.operator} $${a}`),t.push(r.value);break;case"is":r.value.toLowerCase()==="null"?e.push(`${o} IS NULL`):(e.push(`${o} = $${a}`),t.push(r.value));break;case"is not":r.value.toLowerCase()==="null"?e.push(`${o} IS NOT NULL`):(e.push(`${o} != $${a}`),t.push(r.value));break;case"like":e.push(`${o}::text LIKE $${a}`),t.push(r.value);break;case"not like":e.push(`${o}::text NOT LIKE $${a}`),t.push(r.value);break;case"ilike":e.push(`${o}::text ILIKE $${a}`),t.push(r.value);break;case"not ilike":e.push(`${o}::text NOT ILIKE $${a}`),t.push(r.value);break;default:break}}return e.length===0?{clause:"",values:[]}:{clause:`WHERE ${e.join(" AND ")}`,values:t}}function Br(n,e){return Array.isArray(n)?n.length===0?"":`ORDER BY ${n.map(r=>`"${r.columnName}" ${r.direction.toUpperCase()}`).join(", ")}`:n&&typeof n=="string"?`ORDER BY "${n}" ${e?.toUpperCase()||"ASC"}`:""}function Fr(n,e,t,r){let{values:a,sortColumns:o}=n,s=[],c=[],u=t==="asc"===(e==="asc");if(o.length>0){let m=o.map(f=>`"${f}"`).join(", "),p=o.map((f,y)=>`$${r+y}`).join(", "),d=u?">":"<";s.push(`(${m}) ${d} (${p})`);for(let f of o)c.push(a[f])}return{clause:s.length>0?`(${s.join(" AND ")})`:"",values:c}}var Ta=N(()=>{"use strict"});import{HTTPException as M}from"hono/http-exception";var Bt,Ea=N(()=>{"use strict";Re();qe();Be();tt();Ta();Bt=class extends ce{async runQuery(e,t,r){return(await Q(e).query(t,r)).rows}quoteIdentifier(e){return`"${e}"`}mapToUniversalType(e){return xt(e)}mapFromUniversalType(e){return{text:"TEXT",number:"INTEGER",boolean:"BOOLEAN",json:"JSONB",date:"TIMESTAMP WITH TIME ZONE",array:"TEXT[]",enum:"TEXT"}[e]??"TEXT"}buildTableDataQuery(e){let{tableName:t,cursor:r="",limit:a=50,direction:o="asc",sort:s=[],order:c="asc",filters:i=[],db:l}=e,u=Q(l),m=[],p=c;Array.isArray(s)&&s.length>0?(m=s.map(O=>O.columnName),p=s[0].direction):typeof s=="string"&&s&&(m=[s]);let d=m.length>0?[...m]:["ctid"],{clause:f,values:y}=Ur(i),g="",E=[];if(r){let O=this.decodeCursor(r);if(O){let $=Fr(O,o,p,y.length+1);g=$.clause,E=$.values}}let T="";f&&g?T=`WHERE ${f.replace(/^WHERE\s+/i,"")} AND ${g}`:f?T=f:g&&(T=`WHERE ${g}`);let S=Br((Array.isArray(s),s),c),C=S;o==="desc"?S?C=S.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"):C=`ORDER BY ${d.map($=>`"${$}" ${p==="asc"?"DESC":"ASC"}`).join(", ")}`:!S&&d.length>0&&(C=`ORDER BY ${d.map($=>`"${$}" ${p.toUpperCase()}`).join(", ")}`);let R=y.length+E.length+1,w=`SELECT * FROM "${t}" ${T} ${C} LIMIT $${R}`,A=[...y,...E,a+1],_=`SELECT COUNT(*) as total FROM "${t}" ${f}`;return{sql:w,values:A,countSql:_,countValues:y}}normalizeRows(e){return e.map(t=>this.normalizeRow(t))}buildCursors(e,t,r){if(t.length===0)return{nextCursor:null,prevCursor:null};let{direction:a="asc",sort:o=[],cursor:s}=e,c=[];Array.isArray(o)&&o.length>0?c=o.map(d=>d.columnName):typeof o=="string"&&o&&(c=[o]),c.length===0&&(c=["ctid"]);let i=d=>{let f={values:Object.fromEntries(c.map(y=>[y,d[y]])),sortColumns:c};return this.encodeCursor(f)},l=t[0],u=t[t.length-1],m=null,p=null;return a==="asc"?(r&&(m=i(u)),s&&(p=i(l))):(s&&(m=i(u)),r&&(p=i(l))),{nextCursor:m,prevCursor:p}}async getTableData(e){let{tableName:t,db:r,limit:a=50,direction:o="asc",sort:s=[],order:c="asc",cursor:i,filters:l=[]}=e,u=Q(r),m=await this.getPrimaryKeyColumns(u,t),p=[],d=c;Array.isArray(s)&&s.length>0?(p=s.map(J=>J.columnName),d=s[0].direction):typeof s=="string"&&s&&(p=[s]);let f=[...p,...m.filter(J=>!p.includes(J))];f.length===0&&f.push("ctid");let{clause:y,values:g}=Ur(l),E="",T=[];if(i){let J=this.decodeCursor(i);if(J){let Z=Fr(J,o,d,g.length+1);E=Z.clause,T=Z.values}}let S="";y&&E?S=`WHERE ${y.replace(/^WHERE\s+/i,"")} AND ${E}`:y?S=y:E&&(S=`WHERE ${E}`);let C=Br((Array.isArray(s),s),c),R=C;o==="desc"?C?R=C.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"):R=`ORDER BY ${f.map(Z=>`"${Z}" ${d==="asc"?"DESC":"ASC"}`).join(", ")}`:!C&&f.length>0&&(R=`ORDER BY ${f.map(Z=>`"${Z}" ${d.toUpperCase()}`).join(", ")}`);let w=await u.query(`SELECT COUNT(*) as total FROM "${t}" ${y}`,g),A=Number(w.rows[0].total),_=g.length+T.length+1,x=await u.query(`SELECT * FROM "${t}" ${S} ${R} LIMIT $${_}`,[...g,...T,a+1]),$=x.fields&&x.fields.length>0?x.rows.filter(J=>Object.keys(J).length>0):x.rows,U=$.length>a;U&&($=$.slice(0,a)),o==="desc"&&($=$.reverse());let j=J=>({values:Object.fromEntries(f.map(Z=>[Z,J[Z]])),sortColumns:f}),G=null,re=null;if($.length>0){let J=$[0],Z=$[$.length-1];o==="asc"?(U&&(G=this.encodeCursor(j(Z))),i&&(re=this.encodeCursor(j(J)))):(i&&(G=this.encodeCursor(j(Z))),U&&(re=this.encodeCursor(j(J))))}return{data:$,meta:{limit:a,total:A,hasNextPage:o==="asc"?U:!!i,hasPreviousPage:o==="asc"?!!i:U,nextCursor:G,prevCursor:re}}}async getDatabasesList(){let e=Q(),{rows:t}=await e.query(`
209
+ AND kcu.REFERENCED_TABLE_NAME = ?`,[e]);return a.map(o=>({constraintName:o.constraint_name,referencingTable:o.referencing_table,referencingColumn:o.referencing_column,referencedTable:o.referenced_table,referencedColumn:o.referenced_column}))}async getRelatedRecordsForTable(e,t){let r=await this.getForeignKeyReferences(e,t);if(r.length===0)return[];let a=z(t),o=[];for(let s of r){let[c]=await a.execute(`SELECT * FROM \`${s.referencingTable}\` LIMIT 100`);c.length>0&&o.push({tableName:s.referencingTable,columnName:s.referencingColumn,constraintName:s.constraintName,records:c})}return o}async getRelatedRecords(e,t,r){let a=await this.getForeignKeyReferences(e,r);if(a.length===0)return[];let o=z(r),s=t.map(l=>l.value),c=[],i=new Map;for(let l of a){let u=`${l.referencingTable}.${l.referencingColumn}`;i.has(u)||i.set(u,[]),i.get(u)?.push(l)}for(let[,l]of i){let u=l[0];if(!u||!t.find(f=>f.columnName===u.referencedColumn))continue;let p=s.map(()=>"?").join(", "),[d]=await o.execute(`SELECT * FROM \`${u.referencingTable}\` WHERE \`${u.referencingColumn}\` IN (${p}) LIMIT 100`,s);d.length>0&&c.push({tableName:u.referencingTable,columnName:u.referencingColumn,constraintName:u.constraintName,records:d})}return c}async getTableRowCount(e,t){let[r]=await e.execute(`SELECT COUNT(*) as count FROM \`${t}\``);return Number(r[0]?.count??0)}async getBooleanColumnSet(e,t){let r=await this.getTableColumns({tableName:e,db:t});return new Set(r.filter(a=>a.dataTypeLabel==="boolean").map(a=>a.columnName))}async assertTableExists(e,t){let[r]=await e.execute("SELECT COUNT(*) as cnt FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?",[t]);if(Number(r[0]?.cnt??0)===0)throw new k(404,{message:`Table "${t}" does not exist`})}async assertColumnExists(e,t,r){let[a]=await e.execute("SELECT COUNT(*) as cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?",[t,r]);if(Number(a[0]?.cnt??0)===0)throw new k(404,{message:`Column "${r}" does not exist in table "${t}"`})}parseMysqlEnumValues(e){let t=e.match(/^(?:enum|set)\((.+)\)$/i);return t?.[1]?t[1].split(",").map(r=>r.trim().replace(/^'|'$/g,"")):null}}});function Ur(n){if(n.length===0)return{clause:"",values:[]};let e=[],t=[];for(let r of n){let a=t.length+1,o=`"${r.columnName}"`;switch(r.operator){case"=":case"!=":case">":case">=":case"<":case"<=":e.push(`${o} ${r.operator} $${a}`),t.push(r.value);break;case"is":r.value.toLowerCase()==="null"?e.push(`${o} IS NULL`):(e.push(`${o} = $${a}`),t.push(r.value));break;case"is not":r.value.toLowerCase()==="null"?e.push(`${o} IS NOT NULL`):(e.push(`${o} != $${a}`),t.push(r.value));break;case"like":e.push(`${o}::text LIKE $${a}`),t.push(r.value);break;case"not like":e.push(`${o}::text NOT LIKE $${a}`),t.push(r.value);break;case"ilike":e.push(`${o}::text ILIKE $${a}`),t.push(r.value);break;case"not ilike":e.push(`${o}::text NOT ILIKE $${a}`),t.push(r.value);break;default:break}}return e.length===0?{clause:"",values:[]}:{clause:`WHERE ${e.join(" AND ")}`,values:t}}function Br(n,e){return Array.isArray(n)?n.length===0?"":`ORDER BY ${n.map(r=>`"${r.columnName}" ${r.direction.toUpperCase()}`).join(", ")}`:n&&typeof n=="string"?`ORDER BY "${n}" ${e?.toUpperCase()||"ASC"}`:""}function Fr(n,e,t,r){let{values:a,sortColumns:o}=n,s=[],c=[],u=t==="asc"===(e==="asc");if(o.length>0){let m=o.map(f=>`"${f}"`).join(", "),p=o.map((f,y)=>`$${r+y}`).join(", "),d=u?">":"<";s.push(`(${m}) ${d} (${p})`);for(let f of o)c.push(a[f])}return{clause:s.length>0?`(${s.join(" AND ")})`:"",values:c}}var Ta=N(()=>{"use strict"});import{HTTPException as M}from"hono/http-exception";var Bt,Ea=N(()=>{"use strict";Re();qe();Be();tt();Ta();Bt=class extends ce{async runQuery(e,t,r){return(await Q(e).query(t,r)).rows}quoteIdentifier(e){return`"${e}"`}mapToUniversalType(e){return xt(e)}mapFromUniversalType(e){return{text:"TEXT",number:"INTEGER",boolean:"BOOLEAN",json:"JSONB",date:"TIMESTAMP WITH TIME ZONE",array:"TEXT[]",enum:"TEXT"}[e]??"TEXT"}buildTableDataQuery(e){let{tableName:t,cursor:r="",limit:a=50,direction:o="asc",sort:s=[],order:c="asc",filters:i=[],db:l}=e,u=Q(l),m=[],p=c;Array.isArray(s)&&s.length>0?(m=s.map($=>$.columnName),p=s[0].direction):typeof s=="string"&&s&&(m=[s]);let d=m.length>0?[...m]:["ctid"],{clause:f,values:y}=Ur(i),g="",E=[];if(r){let $=this.decodeCursor(r);if($){let O=Fr($,o,p,y.length+1);g=O.clause,E=O.values}}let T="";f&&g?T=`WHERE ${f.replace(/^WHERE\s+/i,"")} AND ${g}`:f?T=f:g&&(T=`WHERE ${g}`);let S=Br((Array.isArray(s),s),c),C=S;o==="desc"?S?C=S.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"):C=`ORDER BY ${d.map(O=>`"${O}" ${p==="asc"?"DESC":"ASC"}`).join(", ")}`:!S&&d.length>0&&(C=`ORDER BY ${d.map(O=>`"${O}" ${p.toUpperCase()}`).join(", ")}`);let R=y.length+E.length+1,w=`SELECT * FROM "${t}" ${T} ${C} LIMIT $${R}`,A=[...y,...E,a+1],_=`SELECT COUNT(*) as total FROM "${t}" ${f}`;return{sql:w,values:A,countSql:_,countValues:y}}normalizeRows(e){return e.map(t=>this.normalizeRow(t))}buildCursors(e,t,r){if(t.length===0)return{nextCursor:null,prevCursor:null};let{direction:a="asc",sort:o=[],cursor:s}=e,c=[];Array.isArray(o)&&o.length>0?c=o.map(d=>d.columnName):typeof o=="string"&&o&&(c=[o]),c.length===0&&(c=["ctid"]);let i=d=>{let f={values:Object.fromEntries(c.map(y=>[y,d[y]])),sortColumns:c};return this.encodeCursor(f)},l=t[0],u=t[t.length-1],m=null,p=null;return a==="asc"?(r&&(m=i(u)),s&&(p=i(l))):(s&&(m=i(u)),r&&(p=i(l))),{nextCursor:m,prevCursor:p}}async getTableData(e){let{tableName:t,db:r,limit:a=50,direction:o="asc",sort:s=[],order:c="asc",cursor:i,filters:l=[]}=e,u=Q(r),m=await this.getPrimaryKeyColumns(u,t),p=[],d=c;Array.isArray(s)&&s.length>0?(p=s.map(J=>J.columnName),d=s[0].direction):typeof s=="string"&&s&&(p=[s]);let f=[...p,...m.filter(J=>!p.includes(J))];f.length===0&&f.push("ctid");let{clause:y,values:g}=Ur(l),E="",T=[];if(i){let J=this.decodeCursor(i);if(J){let Z=Fr(J,o,d,g.length+1);E=Z.clause,T=Z.values}}let S="";y&&E?S=`WHERE ${y.replace(/^WHERE\s+/i,"")} AND ${E}`:y?S=y:E&&(S=`WHERE ${E}`);let C=Br((Array.isArray(s),s),c),R=C;o==="desc"?C?R=C.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"):R=`ORDER BY ${f.map(Z=>`"${Z}" ${d==="asc"?"DESC":"ASC"}`).join(", ")}`:!C&&f.length>0&&(R=`ORDER BY ${f.map(Z=>`"${Z}" ${d.toUpperCase()}`).join(", ")}`);let w=await u.query(`SELECT COUNT(*) as total FROM "${t}" ${y}`,g),A=Number(w.rows[0].total),_=g.length+T.length+1,x=await u.query(`SELECT * FROM "${t}" ${S} ${R} LIMIT $${_}`,[...g,...T,a+1]),O=x.fields&&x.fields.length>0?x.rows.filter(J=>Object.keys(J).length>0):x.rows,U=O.length>a;U&&(O=O.slice(0,a)),o==="desc"&&(O=O.reverse());let j=J=>({values:Object.fromEntries(f.map(Z=>[Z,J[Z]])),sortColumns:f}),G=null,re=null;if(O.length>0){let J=O[0],Z=O[O.length-1];o==="asc"?(U&&(G=this.encodeCursor(j(Z))),i&&(re=this.encodeCursor(j(J)))):(i&&(G=this.encodeCursor(j(Z))),U&&(re=this.encodeCursor(j(J))))}return{data:O,meta:{limit:a,total:A,hasNextPage:o==="asc"?U:!!i,hasPreviousPage:o==="asc"?!!i:U,nextCursor:G,prevCursor:re}}}async getDatabasesList(){let e=Q(),{rows:t}=await e.query(`
210
210
  SELECT
211
211
  d.datname as name,
212
212
  pg_size_pretty(pg_database_size(d.datname)) as size,
@@ -286,7 +286,7 @@ ${s.join(`,
286
286
  -- Columns: key (text, PK), value (json: [{member, score}, ...]), ttl (number)
287
287
  -- Backed by: ZRANGE WITHSCORES / ZADD / EXPIRE`,streams:`-- Redis stream keys
288
288
  -- Columns: key (text, PK), length (number), first-id (text), last-id (text), ttl (number)
289
- -- Backed by: XINFO STREAM / XADD / EXPIRE (read-only \u2014 streams are append-only)`},Vt=class extends ce{countCache=new Map;runQuery(){throw new D(501,{message:"runQuery is not supported for Redis"})}buildTableDataQuery(e){throw new D(501,{message:"buildTableDataQuery is not supported for Redis"})}normalizeRows(e){return e.map(t=>this.normalizeRow(t))}buildCursors(){return{nextCursor:null,prevCursor:null}}quoteIdentifier(e){return e}mapToUniversalType(e){switch(e.toLowerCase()){case"string":return"text";case"hash":return"json";case"list":case"set":return"array";case"zset":case"stream":return"json";case"integer":case"number":case"ttl":return"number";default:return"text"}}mapFromUniversalType(e){return"string"}async scanKeys(e){try{let{db:t,limit:r,search:a,exactPattern:o,type:s,cursor:c}=e,i=ae(t),l=await ue(i),u="0";if(c){let T=hi(c);if(!T||T.search!==a||T.exactPattern!==o||T.type!==s)throw new D(400,{message:"Invalid or stale key scan cursor"});u=T.scanCursor}let m=a?o?a:`*${Ei(a)}*`:"*",p=[u,"MATCH",m,"COUNT",r];s&&p.push("TYPE",s);let[d,f]=await l.scanBuffer(...p),y=Buffer.isBuffer(d)?d.toString("utf8"):d,g=l.pipeline();for(let T of f)g.call("TYPE",T),g.pttl(T),g.call("MEMORY","USAGE",T);let E=await g.exec()??[];return{keys:f.map((T,S)=>{let C=S*3,R=E[C+2]?.[1];return{key:me(T),type:jt(E[C]?.[1]),ttlMs:Number(E[C+1]?.[1]??-2),memoryBytes:R==null?null:Number(R)}}),nextCursor:y==="0"?null:gi({scanCursor:y,search:a,exactPattern:o,type:s}),hasMore:y!=="0"}}catch(t){throw this.wrapError(t)}}async getKeyDetails(e){try{let{db:t,key:r,cursor:a,limit:o,full:s,direction:c}=e,i=Kt(r),l=await ue(ae(t)),[u,m,p,d]=await Promise.all([l.callBuffer("TYPE",i),l.pttl(i),l.call("MEMORY","USAGE",i).catch(()=>null),l.callBuffer("DUMP",i)]),f=d;if(!f)throw new D(404,{message:"Redis key no longer exists"});let y=jt(u),g={key:me(i),type:y,ttlMs:Number(m),memoryBytes:p===null?null:Number(p),revision:Fe(f)},E=a?Ti(a):null;if(a&&(!E||E.key!==r||E.type!==y||E.direction!==c))throw new D(400,{message:"Invalid or stale key details cursor"});if(y==="string"){let T=await l.strlen(i),S=s?yi:fi,C=await l.getrangeBuffer(i,0,S-1);return{...g,length:T,value:{kind:"string",value:me(C),truncated:T>S},nextCursor:null,hasMore:!1}}if(y==="hash"){let[T,S]=await Promise.all([l.hlen(i),l.hscanBuffer(i,E?.cursor??"0","COUNT",String(o))]),[C,R]=S,w=Buffer.isBuffer(C)?C.toString("utf8"):C,A=[];for(let _=0;_<R.length;_+=2)A.push({field:me(R[_]),value:me(R[_+1])});return{...g,length:T,value:{kind:"hash",entries:A},nextCursor:w==="0"?null:it({key:r,type:y,cursor:w,direction:c}),hasMore:w!=="0"}}if(y==="list"){let T=Number.parseInt(E?.cursor??"0",10),S=await l.llen(i),C=await l.lrangeBuffer(i,T,T+o-1),R=T+C.length,w=R<S;return{...g,length:S,value:{kind:"list",entries:C.map((A,_)=>({index:T+_,value:me(A)}))},nextCursor:w?it({key:r,type:y,cursor:String(R),direction:c}):null,hasMore:w}}if(y==="set"){let[T,S]=await Promise.all([l.scard(i),l.sscanBuffer(i,E?.cursor??"0","COUNT",String(o))]),[C,R]=S,w=Buffer.isBuffer(C)?C.toString("utf8"):C;return{...g,length:T,value:{kind:"set",members:R.map(me)},nextCursor:w==="0"?null:it({key:r,type:y,cursor:w,direction:c}),hasMore:w!=="0"}}if(y==="zset"){let[T,S]=await Promise.all([l.zcard(i),l.zscanBuffer(i,E?.cursor??"0","COUNT",String(o))]),[C,R]=S,w=Buffer.isBuffer(C)?C.toString("utf8"):C,A=[];for(let _=0;_<R.length;_+=2)A.push({member:me(R[_]),score:(()=>{let x=R[_+1].toString("utf8");return x==="inf"?"inf":x==="-inf"?"-inf":Number(x)})()});return{...g,length:T,value:{kind:"zset",entries:A},nextCursor:w==="0"?null:it({key:r,type:y,cursor:w,direction:c}),hasMore:w!=="0"}}if(y==="stream"){let T=E?.cursor??(c==="forward"?"-":"+"),[S,C]=await Promise.all([l.xlen(i),c==="forward"?l.xrangeBuffer(i,T,"+","COUNT",o+1):l.xrevrangeBuffer(i,T,"-","COUNT",o+1)]),R=C.length>o,A=C.slice(0,o).map(([x,O])=>{let $=[];for(let U=0;U<O.length;U+=2)$.push({field:me(O[U]),value:me(O[U+1])});return{id:x.toString("utf8"),fields:$}}),_=A.at(-1)?.id;return{...g,length:S,value:{kind:"stream",entries:A},nextCursor:R&&_?it({key:r,type:y,cursor:`(${_}`,direction:c}):null,hasMore:R}}return{...g,length:null,value:{kind:"unknown"},nextCursor:null,hasMore:!1}}catch(t){throw this.wrapError(t)}}async getStringChunk(e){try{let t=await ue(ae(e.db)),r=Kt(e.key),a=jt(await t.callBuffer("TYPE",r));if(a==="unknown")throw new D(404,{message:"Redis key no longer exists"});if(de(a,"string"),e.expectedRevision){let i=await t.callBuffer("DUMP",r);if(!i||Fe(i)!==e.expectedRevision)throw lt()}let o=await t.strlen(r),s=await t.getrangeBuffer(r,e.offset,e.offset+e.limit-1),c=e.offset+s.length;return{chunk:me(s),length:o,nextOffset:c<o?c:null,hasMore:c<o}}catch(t){throw this.wrapError(t)}}async createKey(e){let t=null;try{t=await Nt(ae(e.db));let r=W(e.key.base64);if(await t.watch(r),await t.exists(r)!==0)throw new D(409,{message:"A Redis key with this name already exists."});if(e.type!==e.value.kind)throw new D(400,{message:"The initial value does not match the selected Redis key type."});let a=t.multi();switch(e.value.kind){case"string":a.set(r,W(e.value.value.base64));break;case"hash":a.hset(r,...e.value.entries.flatMap(({field:s,value:c})=>[W(s.base64),W(c.base64)]));break;case"list":a.rpush(r,...e.value.entries.map(s=>W(s.base64)));break;case"set":a.sadd(r,...e.value.members.map(s=>W(s.base64)));break;case"zset":a.zadd(r,...e.value.entries.flatMap(({member:s,score:c})=>[c,W(s.base64)]));break;case"stream":a.xadd(r,e.value.id,...e.value.fields.flatMap(({field:s,value:c})=>[W(s.base64),W(c.base64)]));break}e.ttlMs!==null&&a.pexpire(r,e.ttlMs),Hr(await a.exec());let o=await t.callBuffer("DUMP",r);if(!o)throw lt();return{key:me(r),revision:Fe(o),deleted:!1}}catch(r){throw this.wrapError(r)}finally{t&&await t.quit().catch(()=>t?.disconnect())}}async applyKeyAction(e){let t=null;try{t=await Nt(ae(e.db));let r=Kt(e.key),a=e.operation.action==="rename"?W(e.operation.newKey.base64):null;a&&!a.equals(r)?await t.watch(r,a):await t.watch(r);let[o,s,c]=await Promise.all([t.callBuffer("DUMP",r),t.callBuffer("TYPE",r),t.pttl(r)]),i=o;if(!i)throw new D(404,{message:"Redis key no longer exists"});if(!e.force&&Fe(i)!==e.expectedRevision)throw lt();let l=jt(s);if(a&&!a.equals(r)&&await t.exists(a)!==0)throw new D(409,{message:"A Redis key with the new name already exists."});let u=t.multi();switch(e.operation.action){case"rename":if(!a||a.equals(r))return{key:me(r),revision:Fe(i),deleted:!1};u.rename(r,a);break;case"setTtl":e.operation.ttlMs===null?u.persist(r):u.pexpire(r,e.operation.ttlMs);break;case"setString":de(l,"string"),u.set(r,W(e.operation.value.base64)),c>0&&u.pexpire(r,c);break;case"upsertHash":de(l,"hash"),u.hset(r,W(e.operation.field.base64),W(e.operation.value.base64));break;case"deleteHash":de(l,"hash"),u.hdel(r,W(e.operation.field.base64));break;case"pushList":de(l,"list"),e.operation.side==="left"?u.lpush(r,W(e.operation.value.base64)):u.rpush(r,W(e.operation.value.base64));break;case"setList":de(l,"list"),u.lset(r,e.operation.index,W(e.operation.value.base64));break;case"deleteList":{de(l,"list");let d=Buffer.concat([Buffer.from("db-studio:list-delete:"),ii(32)]);u.lset(r,e.operation.index,d),u.lrem(r,1,d);break}case"addSet":de(l,"set"),u.sadd(r,W(e.operation.member.base64));break;case"removeSet":de(l,"set"),u.srem(r,W(e.operation.member.base64));break;case"upsertZset":de(l,"zset"),u.zadd(r,e.operation.score,W(e.operation.member.base64));break;case"removeZset":de(l,"zset"),u.zrem(r,W(e.operation.member.base64));break;case"appendStream":de(l,"stream"),u.xadd(r,e.operation.id,...e.operation.fields.flatMap(({field:d,value:f})=>[W(d.base64),W(f.base64)]));break;case"deleteStream":de(l,"stream"),u.xdel(r,e.operation.id);break}Hr(await u.exec());let m=a&&!a.equals(r)?a:r,p=await t.callBuffer("DUMP",m);return{key:me(m),revision:p?Fe(p):null,deleted:p===null}}catch(r){throw this.wrapError(r)}finally{t&&await t.quit().catch(()=>t?.disconnect())}}async deleteKey(e){let t=null;try{t=await Nt(ae(e.db));let r=Kt(e.key);await t.watch(r);let a=await t.callBuffer("DUMP",r);if(!a)throw new D(404,{message:"Redis key no longer exists"});if(!e.force&&Fe(a)!==e.expectedRevision)throw lt();let o=t.multi().del(r);return Hr(await o.exec()),{deleted:!0}}catch(r){throw this.wrapError(r)}finally{t&&await t.quit().catch(()=>t?.disconnect())}}async getDatabasesList(){try{let e=await ue(Ue()),t=1,r=!1,a=null;try{a=await e.call("CONFIG","GET","databases")}catch(i){if(!Kr(i))throw i}if(Array.isArray(a)&&a.length>=2){let i=Number.parseInt(String(a[1]),10);Number.isFinite(i)&&i>0&&(t=i,r=!0)}let o="";try{o=await e.info("keyspace")}catch(i){if(!Kr(i))throw i}let s=Si(o);return(r?Array.from({length:t},(i,l)=>l):[Ue()]).map(i=>({name:String(i),size:`${s.get(i)??0} keys`,owner:"n/a",encoding:"n/a"}))}catch(e){throw this.wrapError(e)}}async getCurrentDatabase(){return{db:String(Ue())}}async getDatabaseConnectionInfo(){try{let e=await ue(Ue()),[t,r]=await Promise.all([e.info("server"),e.info("clients")]),a=Pa(t),o=Pa(r),s=Number.parseInt(o.maxclients??"0",10);if(!Number.isFinite(s)||s===0){let i=await e.call("CONFIG","GET","maxclients").catch(l=>{if(!Kr(l))throw l;return null});Array.isArray(i)&&i.length>=2&&(s=Number.parseInt(String(i[1]),10)||0)}let c=e.options;return{host:c.host??null,port:c.port??null,user:c.username||"default",database:String(c.db??Ue()),version:a.redis_version??"unknown",active_connections:Number.parseInt(o.connected_clients??"0",10)||0,max_connections:s||0}}catch(e){throw this.wrapError(e)}}async getTablesList(e){try{let t=ae(e),r=await this.getCachedCounts(t);return ct.map(a=>({tableName:a,rowCount:r[a]}))}catch(t){throw this.wrapError(t)}}async createTable(){throw new D(400,{message:"Redis tables are fixed; cannot create new ones"})}async deleteTable(e){throw new D(400,{message:"Bulk deletion of Redis tables is not supported. Use FLUSHDB from the query runner to clear the entire logical database."})}async getTableSchema({tableName:e}){let t=ve(e);return Ci[t]}async getTableColumns({tableName:e}){let t=ve(e);return xa[t]}async addColumn(e){throw new D(400,{message:Ft})}async deleteColumn(e){throw new D(400,{message:Ft})}async alterColumn(e){throw new D(400,{message:Ft})}async renameColumn(e){throw new D(400,{message:Ft})}async getTableData(e){try{let{tableName:t,db:r,cursor:a,limit:o=50,direction:s="asc",sort:c,filters:i}=e;if(s==="desc")throw new D(400,{message:ui});if(c&&c.length>0)throw new D(400,{message:li});if(i&&i.length>0)throw new D(400,{message:ci});let l=ve(t),u=jr[l],m=ae(r),p=await ue(m),d="0";if(a){let A=Ri(a);if(!A||A.type!==l)throw new D(400,{message:"Invalid or mismatched cursor"});d=A.scanCursor}let f=[],y=0,g=!1;for(;f.length<o&&y<mi;){let[A,_]=await p.scan(d,"MATCH","*","COUNT",Math.max(o*2,100),"TYPE",u);if(f.push(..._),d=A,y++,A==="0"){g=!0;break}}let E=f.slice(0,o),T=f.slice(o),S=await this.hydrateRows(p,l,E),C=await p.dbsize(),R=!g||T.length>0,w=R&&!g?wi({scanCursor:d,type:l}):null;return{data:S,meta:{limit:o,total:C,hasNextPage:R,hasPreviousPage:!1,nextCursor:w,prevCursor:null}}}catch(t){throw this.wrapError(t)}}async hydrateRows(e,t,r){if(r.length===0)return[];let a=e.pipeline();for(let i of r)a.ttl(i);let o=await a.exec()??[],s=e.pipeline();for(let i of r)switch(t){case"strings":s.get(i);break;case"hashes":s.hgetall(i);break;case"lists":s.lrange(i,0,-1);break;case"sets":s.smembers(i);break;case"zsets":s.zrange(i,0,-1,"WITHSCORES");break;case"streams":s.xinfo("STREAM",i);break}let c=await s.exec()??[];return r.map((i,l)=>{let u=o[l]?.[1]??-2,m=c[l]?.[1];if(t==="streams"){let d=Di(m);return this.normalizeRow({key:i,length:d.length,"first-id":d.firstId,"last-id":d.lastId,ttl:u})}let p;switch(t){case"strings":p=m??null;break;case"hashes":p=m;break;case"lists":case"sets":p=m;break;case"zsets":p=Ai(m);break}return this.normalizeRow({key:i,value:p,ttl:u})})}async getCachedCounts(e){let t=this.countCache.get(e);if(t&&Date.now()-t.timestamp<di)return t.counts;let r=await ue(e),a={},o=r.pipeline();for(let c of ct)o.scan("0","MATCH","*","COUNT",pi,"TYPE",jr[c]);let s=await o.exec()??[];return ct.forEach((c,i)=>{let l=s[i]?.[1];a[c]=l?.[1]?.length??0}),this.countCache.set(e,{timestamp:Date.now(),counts:a}),a}async addRecord({db:e,params:t}){try{let{tableName:r,data:a}=t,o=ve(r),s=$a(a),c=Vr(a),i=await ue(ae(e));return await this.writeRecord(i,o,s,a.value,{mode:"create",ttl:c}),this.countCache.delete(ae(e)),{insertedCount:1}}catch(r){throw this.wrapError(r)}}async updateRecords({db:e,params:t}){try{let{tableName:r,updates:a,primaryKey:o}=t,s=ve(r),c=o||"key",i=await ue(ae(e)),l=new Map;for(let m of a){let p=m.rowData[c];if(p==null)throw new D(400,{message:`Primary key "${c}" not found in row data`});let d=String(p),f=l.get(d)??{...m.rowData};f[m.columnName]=m.value,l.set(d,f)}let u=0;for(let[m,p]of l.entries()){let d=p.value,f=Vr(p);await this.writeRecord(i,s,m,d,{mode:"update",ttl:f}),u++}return{updatedCount:u}}catch(r){throw this.wrapError(r)}}async deleteRecords(e){try{let{tableName:t,primaryKeys:r,db:a}=e;ve(t);let o=await ue(ae(a)),s=r.map(i=>String(i.value));if(s.length===0)return{deletedCount:0,fkViolation:!1,relatedRecords:[]};let c=await o.del(...s);return this.countCache.delete(ae(a)),{deletedCount:c,fkViolation:!1,relatedRecords:[]}}catch(t){throw this.wrapError(t)}}async forceDeleteRecords(e){return{deletedCount:(await this.deleteRecords(e)).deletedCount}}async bulkInsertRecords(e){try{let{tableName:t,records:r,db:a}=e;if(!r||r.length===0)throw new D(400,{message:"At least one record is required"});let o=ve(t),s=await ue(ae(a)),c=[],i=0;for(let l=0;l<r.length;l++){let u=r[l];try{let m=$a(u),p=Vr(u);await this.writeRecord(s,o,m,u.value,{mode:"create",ttl:p}),i++}catch(m){c.push({recordIndex:l,error:m instanceof Error?m.message:String(m)})}}return this.countCache.delete(ae(a)),{success:c.length===0,message:`Inserted ${i} of ${r.length} record${r.length===1?"":"s"}`,successCount:i,failureCount:c.length,...c.length>0?{errors:c}:{}}}catch(t){throw this.wrapError(t)}}async exportTableData({tableName:e,db:t}){try{let r=ve(e),a=ae(t),o=await ue(a),s=jr[r],c=[],i="0";do{let[m,p]=await o.scan(i,"MATCH","*","COUNT",1e3,"TYPE",s);c.push(...p),i=m}while(i!=="0");if(c.length===0)throw new D(404,{message:`Table "${e}" has no data`});let l=await this.hydrateRows(o,r,c);return{cols:xa[r].map(m=>m.columnName),rows:l}}catch(r){throw this.wrapError(r)}}async writeRecord(e,t,r,a,o){if(t==="streams"&&o.mode==="update")throw new D(400,{message:"Streams are append-only; updating a stream record is not supported"});if(o.mode==="create")if(t==="strings"){if(await e.set(r,typeof a=="string"?a:JSON.stringify(a),"NX")===null)throw new D(409,{message:`Key "${r}" already exists`})}else{if(await e.exists(r))throw new D(409,{message:`Key "${r}" already exists`});await this.writeCollectionValue(e,t,r,a)}else if(t==="strings"){if(await e.set(r,typeof a=="string"?a:JSON.stringify(a),"XX")===null)throw new D(404,{message:`Key "${r}" does not exist`})}else{if(!await e.exists(r))throw new D(404,{message:`Key "${r}" does not exist`});await e.del(r),await this.writeCollectionValue(e,t,r,a)}o.ttl!==null&&o.ttl>0&&await e.expire(r,o.ttl)}async writeCollectionValue(e,t,r,a){switch(t){case"hashes":{let o=Oa(a,"hash"),s=[];for(let[c,i]of Object.entries(o))s.push(c,Ht(i));if(s.length===0)throw new D(400,{message:"Hash must have at least one field"});await e.hset(r,...s);return}case"lists":{let o=va(a,"list");if(o.length===0)throw new D(400,{message:"List must have at least one element"});await e.rpush(r,...o.map(Ht));return}case"sets":{let o=va(a,"set");if(o.length===0)throw new D(400,{message:"Set must have at least one member"});await e.sadd(r,...o.map(Ht));return}case"zsets":{let o=Ni(a);if(o.length===0)throw new D(400,{message:"Sorted set must have at least one member"});let s=[];for(let c of o)s.push(c.score,c.member);await e.zadd(r,...s);return}case"streams":{let o=Oa(a,"stream"),s=[];for(let[c,i]of Object.entries(o))s.push(c,Ht(i));if(s.length===0)throw new D(400,{message:"Stream entry must have at least one field"});await e.xadd(r,"*",...s);return}}}async executeQuery({query:e,db:t}){let r=performance.now();try{if(!e?.trim())throw new D(400,{message:"Query is required"});let a;try{a=Aa(e.trim())}catch(u){throw new D(400,{message:u instanceof Error?u.message:"Invalid Redis command"})}if(a.length===0)throw new D(400,{message:"Empty command"});let o=await ue(ae(t)),[s,...c]=a,i;try{i=await o.call(s,...c)}catch(u){let m=u instanceof Error?u.message:String(u);return{columns:["error"],rows:[{error:m}],rowCount:0,duration:performance.now()-r,error:m}}return{...Da(a,i),duration:performance.now()-r,message:typeof i=="string"?i:void 0}}catch(a){throw this.wrapError(a)}}}});function zr(n){if(!n.length)return{clause:"",values:[]};let e=[],t=[];for(let r of n){let a=`"${r.columnName}"`;switch(r.operator){case"=":case"!=":case">":case">=":case"<":case"<=":e.push(`${a} ${r.operator} ?`),t.push(r.value);break;case"is":r.value.toLowerCase()==="null"?e.push(`${a} IS NULL`):(e.push(`${a} = ?`),t.push(r.value));break;case"is not":r.value.toLowerCase()==="null"?e.push(`${a} IS NOT NULL`):(e.push(`${a} != ?`),t.push(r.value));break;case"like":e.push(`CAST(${a} AS TEXT) LIKE ?`),t.push(r.value);break;case"not like":e.push(`CAST(${a} AS TEXT) NOT LIKE ?`),t.push(r.value);break;case"ilike":e.push(`CAST(${a} AS TEXT) LIKE ? COLLATE NOCASE`),t.push(r.value);break;case"not ilike":e.push(`CAST(${a} AS TEXT) NOT LIKE ? COLLATE NOCASE`),t.push(r.value);break;default:break}}return e.length?{clause:`WHERE ${e.join(" AND ")}`,values:t}:{clause:"",values:[]}}function Wr(n,e){return Array.isArray(n)?n.length?`ORDER BY ${n.map(t=>`"${t.columnName}" ${t.direction.toUpperCase()}`).join(", ")}`:"":n&&typeof n=="string"?`ORDER BY "${n}" ${e?.toUpperCase()||"ASC"}`:""}function Yr(n,e,t){let{values:r,sortColumns:a}=n;if(!a.length)return{clause:"",values:[]};let i=t==="asc"===(e==="asc")?">":"<",l=a.map(p=>`"${p}"`).join(", "),u=a.map(()=>"?").join(", "),m=a.map(p=>r[p]);return{clause:`(${l}) ${i} (${u})`,values:m}}var Ma=N(()=>{"use strict"});import{statSync as _i}from"fs";import{HTTPException as I}from"hono/http-exception";var zt,ka=N(()=>{"use strict";Re();qe();Be();Ma();zt=class extends ce{async runQuery(e,t,r){return X().prepare(t).all(...r)}quoteIdentifier(e){return`"${e}"`}mapToUniversalType(e){return Ot(e)}mapFromUniversalType(e){return{text:"TEXT",number:"INTEGER",boolean:"INTEGER",json:"TEXT",date:"TEXT",array:"TEXT",enum:"TEXT"}[e]??"TEXT"}buildTableDataQuery(e){let{tableName:t,cursor:r="",limit:a=50,direction:o="asc",sort:s=[],order:c="asc",filters:i=[]}=e,l=[],u=c;Array.isArray(s)&&s.length>0?(l=s.map(R=>R.columnName),u=s[0].direction):typeof s=="string"&&s&&(l=[s]),l.length||(l=["rowid"]);let{clause:m,values:p}=zr(i),d="",f=[];if(r){let R=this.decodeCursor(r);if(R){let w=Yr(R,o,u);d=w.clause,f=w.values}}let y="";m&&d?y=`WHERE ${m.replace(/^WHERE\s+/i,"")} AND ${d}`:m?y=m:d&&(y=`WHERE ${d}`);let g=Wr((Array.isArray(s),s),c),E=g;o==="desc"?g?E=g.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"):E=`ORDER BY ${l.map(R=>`"${R}" ${u==="asc"?"DESC":"ASC"}`).join(", ")}`:g||(E=`ORDER BY ${l.map(R=>`"${R}" ${u.toUpperCase()}`).join(", ")}`);let T=`SELECT * FROM "${t}" ${y} ${E} LIMIT ?`,S=[...p,...f,a+1],C=`SELECT COUNT(*) as total FROM "${t}" ${m}`;return{sql:T,values:S,countSql:C,countValues:p}}normalizeRows(e){return e.map(t=>this.normalizeRow(t))}buildCursors(e,t,r){if(!t.length)return{nextCursor:null,prevCursor:null};let{direction:a="asc",sort:o=[],cursor:s}=e,c=[];Array.isArray(o)&&o.length>0?c=o.map(d=>d.columnName):typeof o=="string"&&o&&(c=[o]),c.length||(c=["rowid"]);let i=d=>{let f={values:Object.fromEntries(c.map(y=>[y,d[y]])),sortColumns:c};return this.encodeCursor(f)},l=t[0],u=t[t.length-1],m=null,p=null;return a==="asc"?(r&&(m=i(u)),s&&(p=i(l))):(s&&(m=i(u)),r&&(p=i(l))),{nextCursor:m,prevCursor:p}}async getTableData(e){try{let{tableName:t,db:r,limit:a=50,direction:o="asc",sort:s=[],order:c="asc",cursor:i,filters:l=[]}=e,u=X(),p=u.prepare(`PRAGMA table_info("${t}")`).all().filter(B=>B.pk>0).sort((B,le)=>B.pk-le.pk).map(B=>B.name),d=[],f=c;Array.isArray(s)&&s.length>0?(d=s.map(B=>B.columnName),f=s[0].direction):typeof s=="string"&&s&&(d=[s]);let y=[...d,...p.filter(B=>!d.includes(B))],g=y.length===0;g&&y.push("rowid");let{clause:E,values:T}=zr(l),S="",C=[];if(i){let B=this.decodeCursor(i);if(B){let le=Yr(B,o,f);S=le.clause,C=le.values}}let R="";E&&S?R=`WHERE ${E.replace(/^WHERE\s+/i,"")} AND ${S}`:E?R=E:S&&(R=`WHERE ${S}`);let w=Wr((Array.isArray(s),s),c),A=p.filter(B=>!d.includes(B)),_=w;if(o==="desc")if(w){if(_=w.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"),A.length){let B=f==="asc"?"DESC":"ASC";_+=`, ${A.map(le=>`"${le}" ${B}`).join(", ")}`}}else _=`ORDER BY ${y.map(B=>`"${B}" ${f==="asc"?"DESC":"ASC"}`).join(", ")}`;else w?A.length&&(_+=`, ${A.map(B=>`"${B}" ${f.toUpperCase()}`).join(", ")}`):_=`ORDER BY ${y.map(B=>`"${B}" ${f.toUpperCase()}`).join(", ")}`;let x=u.prepare(`SELECT COUNT(*) as total FROM "${t}" ${E}`).get(...T),O=Number(x?.total??0),$=g?"*, rowid":"*",U=u.prepare(`SELECT ${$} FROM "${t}" ${R} ${_} LIMIT ?`).all(...T,...C,a+1),j=U.length>a,G=j?U.slice(0,a):U;o==="desc"&&(G=G.reverse());let re=B=>({values:Object.fromEntries(y.map(le=>[le,B[le]])),sortColumns:y}),J=null,Z=null;if(G.length>0){let B=G[0],le=G[G.length-1];o==="asc"?(j&&(J=this.encodeCursor(re(le))),i&&(Z=this.encodeCursor(re(B)))):(i&&(J=this.encodeCursor(re(le))),j&&(Z=this.encodeCursor(re(B))))}return{data:g?G.map(({rowid:B,...le})=>le):G,meta:{limit:a,total:O,hasNextPage:o==="asc"?j:!!i,hasPreviousPage:o==="asc"?!!i:j,nextCursor:J,prevCursor:Z}}}catch(t){throw this.wrapError(t)}}async getDatabasesList(){try{let t=X().prepare("PRAGMA database_list").all();if(!t.length)throw new I(500,{message:"No databases returned from SQLite"});return t.map(r=>({name:r.name,size:this.getFileSize(r.file),owner:"",encoding:"UTF-8"}))}catch(e){throw e instanceof I?e:this.wrapError(e)}}async getCurrentDatabase(){try{return{db:X().prepare("PRAGMA database_list").all().find(a=>a.name==="main")?.name??"main"}}catch(e){throw this.wrapError(e)}}async getDatabaseConnectionInfo(){try{return{host:null,port:null,user:"",database:"main",version:`SQLite ${X().prepare("SELECT sqlite_version() as version").get().version}`,active_connections:1,max_connections:1}}catch(e){throw this.wrapError(e)}}async getTablesList(e){try{let t=X();return t.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name").all().map(a=>{let o=t.prepare(`SELECT COUNT(*) as count FROM "${a.name}"`).get();return{tableName:a.name,rowCount:o?.count??0}})}catch(t){throw this.wrapError(t)}}async createTable({tableData:e,db:t}){let{tableName:r,fields:a,foreignKeys:o}=e,s=X(),c=a.map(l=>{if(l.isPrimaryKey&&l.isIdentity)return`"${l.columnName}" INTEGER PRIMARY KEY AUTOINCREMENT`;let u=`"${l.columnName}" ${l.columnType}`;return l.isPrimaryKey&&(u+=" PRIMARY KEY"),l.isUnique&&!l.isPrimaryKey&&(u+=" UNIQUE"),!l.isNullable&&!l.isPrimaryKey&&(u+=" NOT NULL"),l.defaultValue?.trim()&&!l.isIdentity&&(u+=` DEFAULT ${l.defaultValue.trim()}`),u}),i=o?.map(l=>`FOREIGN KEY ("${l.columnName}") REFERENCES "${l.referencedTable}" ("${l.referencedColumn}") ON UPDATE ${l.onUpdate} ON DELETE ${l.onDelete}`)??[];s.prepare(`CREATE TABLE "${r}" (${[...c,...i].join(", ")})`).run()}async deleteTable(e){let{tableName:t,cascade:r}=e,a=X();if(!a.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(t))throw new I(404,{message:`Table "${t}" does not exist`});let c=a.prepare(`SELECT COUNT(*) as count FROM "${t}"`).get()?.count??0;if(!r&&this.getFkReferencesForTable(a,t).length>0)return{deletedCount:0,fkViolation:!0,relatedRecords:this.getRelatedRecordsForTable(a,t)};try{return a.prepare(`DROP TABLE "${t}"`).run(),{deletedCount:c,fkViolation:!1,relatedRecords:[]}}catch(i){if((i instanceof Error?i.message:String(i)).includes("FOREIGN KEY constraint"))return{deletedCount:0,fkViolation:!0,relatedRecords:this.getRelatedRecordsForTable(a,t)};throw i instanceof I?i:new I(500,{message:`Failed to delete table "${t}"`})}}async getTableSchema({tableName:e,db:t}){try{let a=X().prepare("SELECT sql FROM sqlite_master WHERE type='table' AND name=?").get(e);if(!a)throw new I(404,{message:`Table "${e}" does not exist`});return a.sql}catch(r){throw r instanceof I?r:this.wrapError(r)}}async getTableColumns({tableName:e,db:t}){try{let r=X();if(!r.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(e))throw new I(404,{message:`Table "${e}" does not exist`});let o=r.prepare(`PRAGMA table_info("${e}")`).all(),s=r.prepare(`PRAGMA foreign_key_list("${e}")`).all(),c=new Map;for(let i of s)c.set(i.from,i);return o.map(i=>{let l=c.get(i.name),u=i.type.toLowerCase();return{columnName:i.name,dataType:Ot(u),dataTypeLabel:br(u),isNullable:i.notnull===0&&i.pk===0,columnDefault:i.dflt_value,isPrimaryKey:i.pk>0,isForeignKey:c.has(i.name),referencedTable:l?.table??null,referencedColumn:l?.to??null,enumValues:null}})}catch(r){throw r instanceof I?r:this.wrapError(r)}}async addColumn(e){let{tableName:t,columnName:r,columnType:a,defaultValue:o,isNullable:s,isUnique:c,db:i}=e,l=X();if(!l.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(t))throw new I(404,{message:`Table "${t}" does not exist`});if(l.prepare(`PRAGMA table_info("${t}")`).all().some(d=>d.name===r))throw new I(409,{message:`Column "${r}" already exists in table "${t}"`});let p=`"${r}" ${a}`;c&&(p+=" UNIQUE"),s||(p+=" NOT NULL"),o?.trim()&&(p+=` DEFAULT ${o.trim()}`);try{l.prepare(`ALTER TABLE "${t}" ADD COLUMN ${p}`).run()}catch(d){throw this.wrapError(d)}}async deleteColumn(e){let{tableName:t,columnName:r,db:a}=e,o=X();if(!o.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(t))throw new I(404,{message:`Table "${t}" does not exist`});if(!o.prepare(`PRAGMA table_info("${t}")`).all().some(i=>i.name===r))throw new I(404,{message:`Column "${r}" does not exist in table "${t}"`});try{o.prepare(`ALTER TABLE "${t}" DROP COLUMN "${r}"`).run()}catch(i){throw this.wrapError(i)}return{deletedCount:1}}async alterColumn(e){let{tableName:t,columnName:r,columnType:a,isNullable:o,defaultValue:s,db:c}=e,i=X();if(!i.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(t))throw new I(404,{message:`Table "${t}" does not exist`});let u=i.prepare(`PRAGMA table_info("${t}")`).all();if(!u.some(w=>w.name===r))throw new I(404,{message:`Column "${r}" does not exist in table "${t}"`});let m=u.filter(w=>w.pk>0).sort((w,A)=>w.pk-A.pk),p=m.length>1,d=u.map(w=>{let A=w.name===r,_=A?a:w.type,x=A?o:w.notnull===0,O=A?s?.trim()||null:w.dflt_value,$=w.pk>0,U=`"${w.name}" ${_}`;return!p&&$&&(U+=" PRIMARY KEY"),!$&&!x&&(U+=" NOT NULL"),O&&(U+=` DEFAULT ${O}`),U});p&&d.push(`PRIMARY KEY (${m.map(w=>`"${w.name}"`).join(", ")})`);let f=i.prepare(`PRAGMA foreign_key_list("${t}")`).all(),y=new Map;for(let w of f){let A=y.get(w.id)??[];A.push(w),y.set(w.id,A)}let g=Array.from(y.values()).map(w=>{let A=w.map(U=>`"${U.from}"`).join(", "),_=w.map(U=>`"${U.to}"`).join(", "),{table:x,on_update:O,on_delete:$}=w[0];return`FOREIGN KEY (${A}) REFERENCES "${x}" (${_}) ON UPDATE ${O} ON DELETE ${$}`}),E=u.map(w=>`"${w.name}"`).join(", "),T=`${t}_alter_${Date.now()}`,S=i.prepare("SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name=? AND sql IS NOT NULL").all(t),C=i.prepare("SELECT sql FROM sqlite_master WHERE type='trigger' AND tbl_name=?").all(t);i.pragma("foreign_keys = OFF");let R=i.transaction(()=>{i.prepare(`CREATE TABLE "${T}" (${[...d,...g].join(", ")})`).run(),i.prepare(`INSERT INTO "${T}" (${E}) SELECT ${E} FROM "${t}"`).run(),i.prepare(`DROP TABLE "${t}"`).run(),i.prepare(`ALTER TABLE "${T}" RENAME TO "${t}"`).run()});try{R();for(let{sql:w}of S)i.prepare(w).run();for(let{sql:w}of C)i.prepare(w).run()}catch(w){throw w instanceof I?w:this.wrapError(w)}finally{i.pragma("foreign_keys = ON")}}async renameColumn(e){let{tableName:t,columnName:r,newColumnName:a,db:o}=e,s=X();if(!s.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(t))throw new I(404,{message:`Table "${t}" does not exist`});let i=s.prepare(`PRAGMA table_info("${t}")`).all();if(!i.some(l=>l.name===r))throw new I(404,{message:`Column "${r}" does not exist in table "${t}"`});if(i.some(l=>l.name===a))throw new I(409,{message:`Column "${a}" already exists in table "${t}"`});try{s.prepare(`ALTER TABLE "${t}" RENAME COLUMN "${r}" TO "${a}"`).run()}catch(l){throw this.wrapError(l)}}async addRecord({params:e}){let{tableName:t,data:r}=e,a=X(),o=Object.keys(r);if(!o.length)throw new I(400,{message:"No data provided for insert"});let s=Object.values(r).map(l=>l!==null&&typeof l=="object"?JSON.stringify(l):l),c=o.map(l=>`"${l}"`).join(", "),i=o.map(()=>"?").join(", ");try{let l=a.prepare(`INSERT INTO "${t}" (${c}) VALUES (${i})`).run(...s);if(l.changes===0)throw new I(500,{message:`Failed to insert record into "${t}"`});return{insertedCount:l.changes}}catch(l){throw this.wrapError(l)}}async updateRecords({db:e,params:t}){let{tableName:r,updates:a,primaryKey:o}=t,s=X(),c=new Map;for(let l of a){let u=l.rowData[o];if(u==null)throw new I(400,{message:`Primary key "${o}" not found in row data.`});c.has(u)||c.set(u,[]),c.get(u)?.push({columnName:l.columnName,value:l.value})}let i=s.transaction(()=>{let l=0;for(let[u,m]of c.entries()){let p=m.map(y=>`"${y.columnName}" = ?`).join(", "),d=[...m.map(y=>y.value!==null&&typeof y.value=="object"?JSON.stringify(y.value):y.value),u],f=s.prepare(`UPDATE "${r}" SET ${p} WHERE "${o}" = ?`).run(...d);if(f.changes===0)throw new I(404,{message:`Record with ${o} = ${u} not found in table "${r}"`});l+=f.changes}return l});try{return{updatedCount:i()}}catch(l){throw l instanceof I?l:this.wrapError(l)}}async deleteRecords({tableName:e,primaryKeys:t,db:r}){let a=X(),o=t[0]?.columnName;if(!o)throw new I(400,{message:"Primary key column name is required"});let s=t.map(l=>l.value),c=s.map(()=>"?").join(", "),i=a.transaction(()=>a.prepare(`DELETE FROM "${e}" WHERE "${o}" IN (${c})`).run(...s).changes);try{return{deletedCount:i(),fkViolation:!1,relatedRecords:[]}}catch(l){if((l instanceof Error?l.message:String(l)).includes("FOREIGN KEY constraint failed"))return{deletedCount:0,fkViolation:!0,relatedRecords:this.getRelatedRecords(a,e,t)};throw this.wrapError(l)}}async forceDeleteRecords({tableName:e,primaryKeys:t,db:r}){let a=X(),o=t[0]?.columnName;if(!o)throw new I(400,{message:"Primary key column name is required"});let s=t.map(i=>i.value);a.pragma("foreign_keys = OFF");let c=a.transaction(()=>{let i=this.getFkReferencesForTable(a,e),l=0;for(let p of i){let d=s.map(()=>"?").join(", "),f=a.prepare(`DELETE FROM "${p.referencingTable}" WHERE "${p.referencingColumn}" IN (${d})`).run(...s);l+=f.changes}let u=s.map(()=>"?").join(", ");return a.prepare(`DELETE FROM "${e}" WHERE "${o}" IN (${u})`).run(...s).changes+l});try{return{deletedCount:c()}}catch(i){throw i instanceof I?i:this.wrapError(i)}finally{a.pragma("foreign_keys = ON")}}async bulkInsertRecords({tableName:e,records:t,db:r}){if(!t?.length)throw new I(400,{message:"At least one record is required"});let a=X(),o=Object.keys(t[0]),s=o.map(u=>`"${u}"`).join(", "),c=o.map(()=>"?").join(", "),i=a.prepare(`INSERT INTO "${e}" (${s}) VALUES (${c})`),l=a.transaction(u=>{let m=0;for(let p of u){let d=o.map(f=>{let y=p[f];return y!==null&&typeof y=="object"?JSON.stringify(y):y});i.run(...d),m++}return m});try{let u=l(t);return{success:!0,message:`Bulk insert completed: ${u} records inserted`,successCount:u,failureCount:0}}catch(u){throw u instanceof I?u:this.wrapError(u)}}async executeQuery({query:e,db:t}){let r=X();if(!e?.trim())throw new I(400,{message:"Query is required"});let a=e.trim().replace(/;+$/,""),o=performance.now();try{let s=r.prepare(a);if(s.reader){let l=s.all(),u=performance.now()-o;return{columns:l.length>0?Object.keys(l[0]):[],rows:l,rowCount:l.length,duration:u,message:l.length===0?"OK":void 0}}let c=s.run(),i=performance.now()-o;return{columns:[],rows:[],rowCount:c.changes,duration:i,message:`OK (${c.changes} rows affected)`}}catch(s){throw this.wrapError(s)}}getFileSize(e){if(!e)return"in-memory";try{let r=_i(e).size;return r<1024?`${r} B`:r<1024*1024?`${(r/1024).toFixed(1)} KB`:`${(r/(1024*1024)).toFixed(1)} MB`}catch{return"N/A"}}getFkReferencesForTable(e,t){let r=e.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'").all(),a=[];for(let o of r){if(o.name===t)continue;let s=e.prepare(`PRAGMA foreign_key_list("${o.name}")`).all();for(let c of s)c.table===t&&a.push({constraintName:`fk_${o.name}_${c.from}_${t}_${c.to}`,referencingTable:o.name,referencingColumn:c.from,referencedTable:t,referencedColumn:c.to})}return a}getRelatedRecordsForTable(e,t){let r=this.getFkReferencesForTable(e,t);if(!r.length)return[];let a=[];for(let o of r){let s=e.prepare(`SELECT * FROM "${o.referencingTable}" LIMIT 100`).all();s.length>0&&a.push({tableName:o.referencingTable,columnName:o.referencingColumn,constraintName:o.constraintName,records:s})}return a}getRelatedRecords(e,t,r){let a=this.getFkReferencesForTable(e,t);if(!a.length)return[];let o=[];for(let s of a){if(!r.find(m=>m.columnName===s.referencedColumn))continue;let i=r.map(m=>m.value),l=i.map(()=>"?").join(", "),u=e.prepare(`SELECT * FROM "${s.referencingTable}" WHERE "${s.referencingColumn}" IN (${l}) LIMIT 100`).all(...i);u.length>0&&o.push({tableName:s.referencingTable,columnName:s.referencingColumn,constraintName:s.constraintName,records:u})}return o}}});function Ia(){pe.register("pg",new Bt),pe.register("mysql",new Ut),pe.register("mssql",new It),pe.register("mongodb",new Dt),pe.register("sqlite",new zt),pe.register("redis",new Vt)}var qa=N(()=>{"use strict";Pe();$n();ya();ha();Ea();La();ka()});import{HTTPException as xi}from"hono/http-exception";import{DatabaseError as Pi}from"pg";import{ZodError as $i}from"zod";function Ua(n,e){if(n instanceof xi)return e.json({error:n.message??"Internal server error"},n.status);if(n instanceof $i){let t=n.issues[0];return e.json({error:"Validation error",details:t.message},400)}if(n instanceof Error){let t=n;if(t.code==="ECONNREFUSED"||t.code==="ENOTFOUND"||t.code==="ETIMEDOUT"||t.code==="ER_ACCESS_DENIED_ERROR"||t.code==="ER_BAD_HOST_ERROR"||t.code==="ECONNRESET"||t.errno===1045||t.errno===2003||t.errno===2002||n.message.includes("ECONNREFUSED")||n.message.includes("connection refused")||n.message.includes("timeout expired")||n.message.includes("Connection terminated")||n.message.includes("MongoNetworkError")||n.message.includes("MongoServerSelectionError")||n instanceof Pi&&n.code?.startsWith("08"))return e.json({error:"Database connection failed",details:n.message},503)}return e.json({error:n instanceof Error?n.message:"Internal server error"},500)}var Ba=N(()=>{"use strict"});function ja(n){let e=n.dbType.toLowerCase(),t=n.dbType==="pg"?"PostgreSQL":n.dbType;return e.includes("mongo")?`You are a database assistant for db-studio. Your responses must be CONCISE and FOCUSED.
289
+ -- Backed by: XINFO STREAM / XADD / EXPIRE (read-only \u2014 streams are append-only)`},Vt=class extends ce{countCache=new Map;runQuery(){throw new D(501,{message:"runQuery is not supported for Redis"})}buildTableDataQuery(e){throw new D(501,{message:"buildTableDataQuery is not supported for Redis"})}normalizeRows(e){return e.map(t=>this.normalizeRow(t))}buildCursors(){return{nextCursor:null,prevCursor:null}}quoteIdentifier(e){return e}mapToUniversalType(e){switch(e.toLowerCase()){case"string":return"text";case"hash":return"json";case"list":case"set":return"array";case"zset":case"stream":return"json";case"integer":case"number":case"ttl":return"number";default:return"text"}}mapFromUniversalType(e){return"string"}async scanKeys(e){try{let{db:t,limit:r,search:a,exactPattern:o,type:s,cursor:c}=e,i=ae(t),l=await ue(i),u="0";if(c){let T=hi(c);if(!T||T.search!==a||T.exactPattern!==o||T.type!==s)throw new D(400,{message:"Invalid or stale key scan cursor"});u=T.scanCursor}let m=a?o?a:`*${Ei(a)}*`:"*",p=[u,"MATCH",m,"COUNT",r];s&&p.push("TYPE",s);let[d,f]=await l.scanBuffer(...p),y=Buffer.isBuffer(d)?d.toString("utf8"):d,g=l.pipeline();for(let T of f)g.call("TYPE",T),g.pttl(T),g.call("MEMORY","USAGE",T);let E=await g.exec()??[];return{keys:f.map((T,S)=>{let C=S*3,R=E[C+2]?.[1];return{key:me(T),type:jt(E[C]?.[1]),ttlMs:Number(E[C+1]?.[1]??-2),memoryBytes:R==null?null:Number(R)}}),nextCursor:y==="0"?null:gi({scanCursor:y,search:a,exactPattern:o,type:s}),hasMore:y!=="0"}}catch(t){throw this.wrapError(t)}}async getKeyDetails(e){try{let{db:t,key:r,cursor:a,limit:o,full:s,direction:c}=e,i=Kt(r),l=await ue(ae(t)),[u,m,p,d]=await Promise.all([l.callBuffer("TYPE",i),l.pttl(i),l.call("MEMORY","USAGE",i).catch(()=>null),l.callBuffer("DUMP",i)]),f=d;if(!f)throw new D(404,{message:"Redis key no longer exists"});let y=jt(u),g={key:me(i),type:y,ttlMs:Number(m),memoryBytes:p===null?null:Number(p),revision:Fe(f)},E=a?Ti(a):null;if(a&&(!E||E.key!==r||E.type!==y||E.direction!==c))throw new D(400,{message:"Invalid or stale key details cursor"});if(y==="string"){let T=await l.strlen(i),S=s?yi:fi,C=await l.getrangeBuffer(i,0,S-1);return{...g,length:T,value:{kind:"string",value:me(C),truncated:T>S},nextCursor:null,hasMore:!1}}if(y==="hash"){let[T,S]=await Promise.all([l.hlen(i),l.hscanBuffer(i,E?.cursor??"0","COUNT",String(o))]),[C,R]=S,w=Buffer.isBuffer(C)?C.toString("utf8"):C,A=[];for(let _=0;_<R.length;_+=2)A.push({field:me(R[_]),value:me(R[_+1])});return{...g,length:T,value:{kind:"hash",entries:A},nextCursor:w==="0"?null:it({key:r,type:y,cursor:w,direction:c}),hasMore:w!=="0"}}if(y==="list"){let T=Number.parseInt(E?.cursor??"0",10),S=await l.llen(i),C=await l.lrangeBuffer(i,T,T+o-1),R=T+C.length,w=R<S;return{...g,length:S,value:{kind:"list",entries:C.map((A,_)=>({index:T+_,value:me(A)}))},nextCursor:w?it({key:r,type:y,cursor:String(R),direction:c}):null,hasMore:w}}if(y==="set"){let[T,S]=await Promise.all([l.scard(i),l.sscanBuffer(i,E?.cursor??"0","COUNT",String(o))]),[C,R]=S,w=Buffer.isBuffer(C)?C.toString("utf8"):C;return{...g,length:T,value:{kind:"set",members:R.map(me)},nextCursor:w==="0"?null:it({key:r,type:y,cursor:w,direction:c}),hasMore:w!=="0"}}if(y==="zset"){let[T,S]=await Promise.all([l.zcard(i),l.zscanBuffer(i,E?.cursor??"0","COUNT",String(o))]),[C,R]=S,w=Buffer.isBuffer(C)?C.toString("utf8"):C,A=[];for(let _=0;_<R.length;_+=2)A.push({member:me(R[_]),score:(()=>{let x=R[_+1].toString("utf8");return x==="inf"?"inf":x==="-inf"?"-inf":Number(x)})()});return{...g,length:T,value:{kind:"zset",entries:A},nextCursor:w==="0"?null:it({key:r,type:y,cursor:w,direction:c}),hasMore:w!=="0"}}if(y==="stream"){let T=E?.cursor??(c==="forward"?"-":"+"),[S,C]=await Promise.all([l.xlen(i),c==="forward"?l.xrangeBuffer(i,T,"+","COUNT",o+1):l.xrevrangeBuffer(i,T,"-","COUNT",o+1)]),R=C.length>o,A=C.slice(0,o).map(([x,$])=>{let O=[];for(let U=0;U<$.length;U+=2)O.push({field:me($[U]),value:me($[U+1])});return{id:x.toString("utf8"),fields:O}}),_=A.at(-1)?.id;return{...g,length:S,value:{kind:"stream",entries:A},nextCursor:R&&_?it({key:r,type:y,cursor:`(${_}`,direction:c}):null,hasMore:R}}return{...g,length:null,value:{kind:"unknown"},nextCursor:null,hasMore:!1}}catch(t){throw this.wrapError(t)}}async getStringChunk(e){try{let t=await ue(ae(e.db)),r=Kt(e.key),a=jt(await t.callBuffer("TYPE",r));if(a==="unknown")throw new D(404,{message:"Redis key no longer exists"});if(de(a,"string"),e.expectedRevision){let i=await t.callBuffer("DUMP",r);if(!i||Fe(i)!==e.expectedRevision)throw lt()}let o=await t.strlen(r),s=await t.getrangeBuffer(r,e.offset,e.offset+e.limit-1),c=e.offset+s.length;return{chunk:me(s),length:o,nextOffset:c<o?c:null,hasMore:c<o}}catch(t){throw this.wrapError(t)}}async createKey(e){let t=null;try{t=await Nt(ae(e.db));let r=W(e.key.base64);if(await t.watch(r),await t.exists(r)!==0)throw new D(409,{message:"A Redis key with this name already exists."});if(e.type!==e.value.kind)throw new D(400,{message:"The initial value does not match the selected Redis key type."});let a=t.multi();switch(e.value.kind){case"string":a.set(r,W(e.value.value.base64));break;case"hash":a.hset(r,...e.value.entries.flatMap(({field:s,value:c})=>[W(s.base64),W(c.base64)]));break;case"list":a.rpush(r,...e.value.entries.map(s=>W(s.base64)));break;case"set":a.sadd(r,...e.value.members.map(s=>W(s.base64)));break;case"zset":a.zadd(r,...e.value.entries.flatMap(({member:s,score:c})=>[c,W(s.base64)]));break;case"stream":a.xadd(r,e.value.id,...e.value.fields.flatMap(({field:s,value:c})=>[W(s.base64),W(c.base64)]));break}e.ttlMs!==null&&a.pexpire(r,e.ttlMs),Hr(await a.exec());let o=await t.callBuffer("DUMP",r);if(!o)throw lt();return{key:me(r),revision:Fe(o),deleted:!1}}catch(r){throw this.wrapError(r)}finally{t&&await t.quit().catch(()=>t?.disconnect())}}async applyKeyAction(e){let t=null;try{t=await Nt(ae(e.db));let r=Kt(e.key),a=e.operation.action==="rename"?W(e.operation.newKey.base64):null;a&&!a.equals(r)?await t.watch(r,a):await t.watch(r);let[o,s,c]=await Promise.all([t.callBuffer("DUMP",r),t.callBuffer("TYPE",r),t.pttl(r)]),i=o;if(!i)throw new D(404,{message:"Redis key no longer exists"});if(!e.force&&Fe(i)!==e.expectedRevision)throw lt();let l=jt(s);if(a&&!a.equals(r)&&await t.exists(a)!==0)throw new D(409,{message:"A Redis key with the new name already exists."});let u=t.multi();switch(e.operation.action){case"rename":if(!a||a.equals(r))return{key:me(r),revision:Fe(i),deleted:!1};u.rename(r,a);break;case"setTtl":e.operation.ttlMs===null?u.persist(r):u.pexpire(r,e.operation.ttlMs);break;case"setString":de(l,"string"),u.set(r,W(e.operation.value.base64)),c>0&&u.pexpire(r,c);break;case"upsertHash":de(l,"hash"),u.hset(r,W(e.operation.field.base64),W(e.operation.value.base64));break;case"deleteHash":de(l,"hash"),u.hdel(r,W(e.operation.field.base64));break;case"pushList":de(l,"list"),e.operation.side==="left"?u.lpush(r,W(e.operation.value.base64)):u.rpush(r,W(e.operation.value.base64));break;case"setList":de(l,"list"),u.lset(r,e.operation.index,W(e.operation.value.base64));break;case"deleteList":{de(l,"list");let d=Buffer.concat([Buffer.from("db-studio:list-delete:"),ii(32)]);u.lset(r,e.operation.index,d),u.lrem(r,1,d);break}case"addSet":de(l,"set"),u.sadd(r,W(e.operation.member.base64));break;case"removeSet":de(l,"set"),u.srem(r,W(e.operation.member.base64));break;case"upsertZset":de(l,"zset"),u.zadd(r,e.operation.score,W(e.operation.member.base64));break;case"removeZset":de(l,"zset"),u.zrem(r,W(e.operation.member.base64));break;case"appendStream":de(l,"stream"),u.xadd(r,e.operation.id,...e.operation.fields.flatMap(({field:d,value:f})=>[W(d.base64),W(f.base64)]));break;case"deleteStream":de(l,"stream"),u.xdel(r,e.operation.id);break}Hr(await u.exec());let m=a&&!a.equals(r)?a:r,p=await t.callBuffer("DUMP",m);return{key:me(m),revision:p?Fe(p):null,deleted:p===null}}catch(r){throw this.wrapError(r)}finally{t&&await t.quit().catch(()=>t?.disconnect())}}async deleteKey(e){let t=null;try{t=await Nt(ae(e.db));let r=Kt(e.key);await t.watch(r);let a=await t.callBuffer("DUMP",r);if(!a)throw new D(404,{message:"Redis key no longer exists"});if(!e.force&&Fe(a)!==e.expectedRevision)throw lt();let o=t.multi().del(r);return Hr(await o.exec()),{deleted:!0}}catch(r){throw this.wrapError(r)}finally{t&&await t.quit().catch(()=>t?.disconnect())}}async getDatabasesList(){try{let e=await ue(Ue()),t=1,r=!1,a=null;try{a=await e.call("CONFIG","GET","databases")}catch(i){if(!Kr(i))throw i}if(Array.isArray(a)&&a.length>=2){let i=Number.parseInt(String(a[1]),10);Number.isFinite(i)&&i>0&&(t=i,r=!0)}let o="";try{o=await e.info("keyspace")}catch(i){if(!Kr(i))throw i}let s=Si(o);return(r?Array.from({length:t},(i,l)=>l):[Ue()]).map(i=>({name:String(i),size:`${s.get(i)??0} keys`,owner:"n/a",encoding:"n/a"}))}catch(e){throw this.wrapError(e)}}async getCurrentDatabase(){return{db:String(Ue())}}async getDatabaseConnectionInfo(){try{let e=await ue(Ue()),[t,r]=await Promise.all([e.info("server"),e.info("clients")]),a=Pa(t),o=Pa(r),s=Number.parseInt(o.maxclients??"0",10);if(!Number.isFinite(s)||s===0){let i=await e.call("CONFIG","GET","maxclients").catch(l=>{if(!Kr(l))throw l;return null});Array.isArray(i)&&i.length>=2&&(s=Number.parseInt(String(i[1]),10)||0)}let c=e.options;return{host:c.host??null,port:c.port??null,user:c.username||"default",database:String(c.db??Ue()),version:a.redis_version??"unknown",active_connections:Number.parseInt(o.connected_clients??"0",10)||0,max_connections:s||0}}catch(e){throw this.wrapError(e)}}async getTablesList(e){try{let t=ae(e),r=await this.getCachedCounts(t);return ct.map(a=>({tableName:a,rowCount:r[a]}))}catch(t){throw this.wrapError(t)}}async createTable(){throw new D(400,{message:"Redis tables are fixed; cannot create new ones"})}async deleteTable(e){throw new D(400,{message:"Bulk deletion of Redis tables is not supported. Use FLUSHDB from the query runner to clear the entire logical database."})}async getTableSchema({tableName:e}){let t=ve(e);return Ci[t]}async getTableColumns({tableName:e}){let t=ve(e);return xa[t]}async addColumn(e){throw new D(400,{message:Ft})}async deleteColumn(e){throw new D(400,{message:Ft})}async alterColumn(e){throw new D(400,{message:Ft})}async renameColumn(e){throw new D(400,{message:Ft})}async getTableData(e){try{let{tableName:t,db:r,cursor:a,limit:o=50,direction:s="asc",sort:c,filters:i}=e;if(s==="desc")throw new D(400,{message:ui});if(c&&c.length>0)throw new D(400,{message:li});if(i&&i.length>0)throw new D(400,{message:ci});let l=ve(t),u=jr[l],m=ae(r),p=await ue(m),d="0";if(a){let A=Ri(a);if(!A||A.type!==l)throw new D(400,{message:"Invalid or mismatched cursor"});d=A.scanCursor}let f=[],y=0,g=!1;for(;f.length<o&&y<mi;){let[A,_]=await p.scan(d,"MATCH","*","COUNT",Math.max(o*2,100),"TYPE",u);if(f.push(..._),d=A,y++,A==="0"){g=!0;break}}let E=f.slice(0,o),T=f.slice(o),S=await this.hydrateRows(p,l,E),C=await p.dbsize(),R=!g||T.length>0,w=R&&!g?wi({scanCursor:d,type:l}):null;return{data:S,meta:{limit:o,total:C,hasNextPage:R,hasPreviousPage:!1,nextCursor:w,prevCursor:null}}}catch(t){throw this.wrapError(t)}}async hydrateRows(e,t,r){if(r.length===0)return[];let a=e.pipeline();for(let i of r)a.ttl(i);let o=await a.exec()??[],s=e.pipeline();for(let i of r)switch(t){case"strings":s.get(i);break;case"hashes":s.hgetall(i);break;case"lists":s.lrange(i,0,-1);break;case"sets":s.smembers(i);break;case"zsets":s.zrange(i,0,-1,"WITHSCORES");break;case"streams":s.xinfo("STREAM",i);break}let c=await s.exec()??[];return r.map((i,l)=>{let u=o[l]?.[1]??-2,m=c[l]?.[1];if(t==="streams"){let d=Di(m);return this.normalizeRow({key:i,length:d.length,"first-id":d.firstId,"last-id":d.lastId,ttl:u})}let p;switch(t){case"strings":p=m??null;break;case"hashes":p=m;break;case"lists":case"sets":p=m;break;case"zsets":p=Ai(m);break}return this.normalizeRow({key:i,value:p,ttl:u})})}async getCachedCounts(e){let t=this.countCache.get(e);if(t&&Date.now()-t.timestamp<di)return t.counts;let r=await ue(e),a={},o=r.pipeline();for(let c of ct)o.scan("0","MATCH","*","COUNT",pi,"TYPE",jr[c]);let s=await o.exec()??[];return ct.forEach((c,i)=>{let l=s[i]?.[1];a[c]=l?.[1]?.length??0}),this.countCache.set(e,{timestamp:Date.now(),counts:a}),a}async addRecord({db:e,params:t}){try{let{tableName:r,data:a}=t,o=ve(r),s=$a(a),c=Vr(a),i=await ue(ae(e));return await this.writeRecord(i,o,s,a.value,{mode:"create",ttl:c}),this.countCache.delete(ae(e)),{insertedCount:1}}catch(r){throw this.wrapError(r)}}async updateRecords({db:e,params:t}){try{let{tableName:r,updates:a,primaryKey:o}=t,s=ve(r),c=o||"key",i=await ue(ae(e)),l=new Map;for(let m of a){let p=m.rowData[c];if(p==null)throw new D(400,{message:`Primary key "${c}" not found in row data`});let d=String(p),f=l.get(d)??{...m.rowData};f[m.columnName]=m.value,l.set(d,f)}let u=0;for(let[m,p]of l.entries()){let d=p.value,f=Vr(p);await this.writeRecord(i,s,m,d,{mode:"update",ttl:f}),u++}return{updatedCount:u}}catch(r){throw this.wrapError(r)}}async deleteRecords(e){try{let{tableName:t,primaryKeys:r,db:a}=e;ve(t);let o=await ue(ae(a)),s=r.map(i=>String(i.value));if(s.length===0)return{deletedCount:0,fkViolation:!1,relatedRecords:[]};let c=await o.del(...s);return this.countCache.delete(ae(a)),{deletedCount:c,fkViolation:!1,relatedRecords:[]}}catch(t){throw this.wrapError(t)}}async forceDeleteRecords(e){return{deletedCount:(await this.deleteRecords(e)).deletedCount}}async bulkInsertRecords(e){try{let{tableName:t,records:r,db:a}=e;if(!r||r.length===0)throw new D(400,{message:"At least one record is required"});let o=ve(t),s=await ue(ae(a)),c=[],i=0;for(let l=0;l<r.length;l++){let u=r[l];try{let m=$a(u),p=Vr(u);await this.writeRecord(s,o,m,u.value,{mode:"create",ttl:p}),i++}catch(m){c.push({recordIndex:l,error:m instanceof Error?m.message:String(m)})}}return this.countCache.delete(ae(a)),{success:c.length===0,message:`Inserted ${i} of ${r.length} record${r.length===1?"":"s"}`,successCount:i,failureCount:c.length,...c.length>0?{errors:c}:{}}}catch(t){throw this.wrapError(t)}}async exportTableData({tableName:e,db:t}){try{let r=ve(e),a=ae(t),o=await ue(a),s=jr[r],c=[],i="0";do{let[m,p]=await o.scan(i,"MATCH","*","COUNT",1e3,"TYPE",s);c.push(...p),i=m}while(i!=="0");if(c.length===0)throw new D(404,{message:`Table "${e}" has no data`});let l=await this.hydrateRows(o,r,c);return{cols:xa[r].map(m=>m.columnName),rows:l}}catch(r){throw this.wrapError(r)}}async writeRecord(e,t,r,a,o){if(t==="streams"&&o.mode==="update")throw new D(400,{message:"Streams are append-only; updating a stream record is not supported"});if(o.mode==="create")if(t==="strings"){if(await e.set(r,typeof a=="string"?a:JSON.stringify(a),"NX")===null)throw new D(409,{message:`Key "${r}" already exists`})}else{if(await e.exists(r))throw new D(409,{message:`Key "${r}" already exists`});await this.writeCollectionValue(e,t,r,a)}else if(t==="strings"){if(await e.set(r,typeof a=="string"?a:JSON.stringify(a),"XX")===null)throw new D(404,{message:`Key "${r}" does not exist`})}else{if(!await e.exists(r))throw new D(404,{message:`Key "${r}" does not exist`});await e.del(r),await this.writeCollectionValue(e,t,r,a)}o.ttl!==null&&o.ttl>0&&await e.expire(r,o.ttl)}async writeCollectionValue(e,t,r,a){switch(t){case"hashes":{let o=Oa(a,"hash"),s=[];for(let[c,i]of Object.entries(o))s.push(c,Ht(i));if(s.length===0)throw new D(400,{message:"Hash must have at least one field"});await e.hset(r,...s);return}case"lists":{let o=va(a,"list");if(o.length===0)throw new D(400,{message:"List must have at least one element"});await e.rpush(r,...o.map(Ht));return}case"sets":{let o=va(a,"set");if(o.length===0)throw new D(400,{message:"Set must have at least one member"});await e.sadd(r,...o.map(Ht));return}case"zsets":{let o=Ni(a);if(o.length===0)throw new D(400,{message:"Sorted set must have at least one member"});let s=[];for(let c of o)s.push(c.score,c.member);await e.zadd(r,...s);return}case"streams":{let o=Oa(a,"stream"),s=[];for(let[c,i]of Object.entries(o))s.push(c,Ht(i));if(s.length===0)throw new D(400,{message:"Stream entry must have at least one field"});await e.xadd(r,"*",...s);return}}}async executeQuery({query:e,db:t}){let r=performance.now();try{if(!e?.trim())throw new D(400,{message:"Query is required"});let a;try{a=Aa(e.trim())}catch(u){throw new D(400,{message:u instanceof Error?u.message:"Invalid Redis command"})}if(a.length===0)throw new D(400,{message:"Empty command"});let o=await ue(ae(t)),[s,...c]=a,i;try{i=await o.call(s,...c)}catch(u){let m=u instanceof Error?u.message:String(u);return{columns:["error"],rows:[{error:m}],rowCount:0,duration:performance.now()-r,error:m}}return{...Da(a,i),duration:performance.now()-r,message:typeof i=="string"?i:void 0}}catch(a){throw this.wrapError(a)}}}});function zr(n){if(!n.length)return{clause:"",values:[]};let e=[],t=[];for(let r of n){let a=`"${r.columnName}"`;switch(r.operator){case"=":case"!=":case">":case">=":case"<":case"<=":e.push(`${a} ${r.operator} ?`),t.push(r.value);break;case"is":r.value.toLowerCase()==="null"?e.push(`${a} IS NULL`):(e.push(`${a} = ?`),t.push(r.value));break;case"is not":r.value.toLowerCase()==="null"?e.push(`${a} IS NOT NULL`):(e.push(`${a} != ?`),t.push(r.value));break;case"like":e.push(`CAST(${a} AS TEXT) LIKE ?`),t.push(r.value);break;case"not like":e.push(`CAST(${a} AS TEXT) NOT LIKE ?`),t.push(r.value);break;case"ilike":e.push(`CAST(${a} AS TEXT) LIKE ? COLLATE NOCASE`),t.push(r.value);break;case"not ilike":e.push(`CAST(${a} AS TEXT) NOT LIKE ? COLLATE NOCASE`),t.push(r.value);break;default:break}}return e.length?{clause:`WHERE ${e.join(" AND ")}`,values:t}:{clause:"",values:[]}}function Wr(n,e){return Array.isArray(n)?n.length?`ORDER BY ${n.map(t=>`"${t.columnName}" ${t.direction.toUpperCase()}`).join(", ")}`:"":n&&typeof n=="string"?`ORDER BY "${n}" ${e?.toUpperCase()||"ASC"}`:""}function Yr(n,e,t){let{values:r,sortColumns:a}=n;if(!a.length)return{clause:"",values:[]};let i=t==="asc"===(e==="asc")?">":"<",l=a.map(p=>`"${p}"`).join(", "),u=a.map(()=>"?").join(", "),m=a.map(p=>r[p]);return{clause:`(${l}) ${i} (${u})`,values:m}}var Ma=N(()=>{"use strict"});import{statSync as _i}from"fs";import{HTTPException as I}from"hono/http-exception";var zt,ka=N(()=>{"use strict";Re();qe();Be();Ma();zt=class extends ce{async runQuery(e,t,r){return X().prepare(t).all(...r)}quoteIdentifier(e){return`"${e}"`}mapToUniversalType(e){return Ot(e)}mapFromUniversalType(e){return{text:"TEXT",number:"INTEGER",boolean:"INTEGER",json:"TEXT",date:"TEXT",array:"TEXT",enum:"TEXT"}[e]??"TEXT"}buildTableDataQuery(e){let{tableName:t,cursor:r="",limit:a=50,direction:o="asc",sort:s=[],order:c="asc",filters:i=[]}=e,l=[],u=c;Array.isArray(s)&&s.length>0?(l=s.map(R=>R.columnName),u=s[0].direction):typeof s=="string"&&s&&(l=[s]),l.length||(l=["rowid"]);let{clause:m,values:p}=zr(i),d="",f=[];if(r){let R=this.decodeCursor(r);if(R){let w=Yr(R,o,u);d=w.clause,f=w.values}}let y="";m&&d?y=`WHERE ${m.replace(/^WHERE\s+/i,"")} AND ${d}`:m?y=m:d&&(y=`WHERE ${d}`);let g=Wr((Array.isArray(s),s),c),E=g;o==="desc"?g?E=g.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"):E=`ORDER BY ${l.map(R=>`"${R}" ${u==="asc"?"DESC":"ASC"}`).join(", ")}`:g||(E=`ORDER BY ${l.map(R=>`"${R}" ${u.toUpperCase()}`).join(", ")}`);let T=`SELECT * FROM "${t}" ${y} ${E} LIMIT ?`,S=[...p,...f,a+1],C=`SELECT COUNT(*) as total FROM "${t}" ${m}`;return{sql:T,values:S,countSql:C,countValues:p}}normalizeRows(e){return e.map(t=>this.normalizeRow(t))}buildCursors(e,t,r){if(!t.length)return{nextCursor:null,prevCursor:null};let{direction:a="asc",sort:o=[],cursor:s}=e,c=[];Array.isArray(o)&&o.length>0?c=o.map(d=>d.columnName):typeof o=="string"&&o&&(c=[o]),c.length||(c=["rowid"]);let i=d=>{let f={values:Object.fromEntries(c.map(y=>[y,d[y]])),sortColumns:c};return this.encodeCursor(f)},l=t[0],u=t[t.length-1],m=null,p=null;return a==="asc"?(r&&(m=i(u)),s&&(p=i(l))):(s&&(m=i(u)),r&&(p=i(l))),{nextCursor:m,prevCursor:p}}async getTableData(e){try{let{tableName:t,db:r,limit:a=50,direction:o="asc",sort:s=[],order:c="asc",cursor:i,filters:l=[]}=e,u=X(),p=u.prepare(`PRAGMA table_info("${t}")`).all().filter(B=>B.pk>0).sort((B,le)=>B.pk-le.pk).map(B=>B.name),d=[],f=c;Array.isArray(s)&&s.length>0?(d=s.map(B=>B.columnName),f=s[0].direction):typeof s=="string"&&s&&(d=[s]);let y=[...d,...p.filter(B=>!d.includes(B))],g=y.length===0;g&&y.push("rowid");let{clause:E,values:T}=zr(l),S="",C=[];if(i){let B=this.decodeCursor(i);if(B){let le=Yr(B,o,f);S=le.clause,C=le.values}}let R="";E&&S?R=`WHERE ${E.replace(/^WHERE\s+/i,"")} AND ${S}`:E?R=E:S&&(R=`WHERE ${S}`);let w=Wr((Array.isArray(s),s),c),A=p.filter(B=>!d.includes(B)),_=w;if(o==="desc")if(w){if(_=w.replace(/\bASC\b/gi,"TEMP_DESC").replace(/\bDESC\b/gi,"ASC").replace(/TEMP_DESC/g,"DESC"),A.length){let B=f==="asc"?"DESC":"ASC";_+=`, ${A.map(le=>`"${le}" ${B}`).join(", ")}`}}else _=`ORDER BY ${y.map(B=>`"${B}" ${f==="asc"?"DESC":"ASC"}`).join(", ")}`;else w?A.length&&(_+=`, ${A.map(B=>`"${B}" ${f.toUpperCase()}`).join(", ")}`):_=`ORDER BY ${y.map(B=>`"${B}" ${f.toUpperCase()}`).join(", ")}`;let x=u.prepare(`SELECT COUNT(*) as total FROM "${t}" ${E}`).get(...T),$=Number(x?.total??0),O=g?"*, rowid":"*",U=u.prepare(`SELECT ${O} FROM "${t}" ${R} ${_} LIMIT ?`).all(...T,...C,a+1),j=U.length>a,G=j?U.slice(0,a):U;o==="desc"&&(G=G.reverse());let re=B=>({values:Object.fromEntries(y.map(le=>[le,B[le]])),sortColumns:y}),J=null,Z=null;if(G.length>0){let B=G[0],le=G[G.length-1];o==="asc"?(j&&(J=this.encodeCursor(re(le))),i&&(Z=this.encodeCursor(re(B)))):(i&&(J=this.encodeCursor(re(le))),j&&(Z=this.encodeCursor(re(B))))}return{data:g?G.map(({rowid:B,...le})=>le):G,meta:{limit:a,total:$,hasNextPage:o==="asc"?j:!!i,hasPreviousPage:o==="asc"?!!i:j,nextCursor:J,prevCursor:Z}}}catch(t){throw this.wrapError(t)}}async getDatabasesList(){try{let t=X().prepare("PRAGMA database_list").all();if(!t.length)throw new I(500,{message:"No databases returned from SQLite"});return t.map(r=>({name:r.name,size:this.getFileSize(r.file),owner:"",encoding:"UTF-8"}))}catch(e){throw e instanceof I?e:this.wrapError(e)}}async getCurrentDatabase(){try{return{db:X().prepare("PRAGMA database_list").all().find(a=>a.name==="main")?.name??"main"}}catch(e){throw this.wrapError(e)}}async getDatabaseConnectionInfo(){try{return{host:null,port:null,user:"",database:"main",version:`SQLite ${X().prepare("SELECT sqlite_version() as version").get().version}`,active_connections:1,max_connections:1}}catch(e){throw this.wrapError(e)}}async getTablesList(e){try{let t=X();return t.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name").all().map(a=>{let o=t.prepare(`SELECT COUNT(*) as count FROM "${a.name}"`).get();return{tableName:a.name,rowCount:o?.count??0}})}catch(t){throw this.wrapError(t)}}async createTable({tableData:e,db:t}){let{tableName:r,fields:a,foreignKeys:o}=e,s=X(),c=a.map(l=>{if(l.isPrimaryKey&&l.isIdentity)return`"${l.columnName}" INTEGER PRIMARY KEY AUTOINCREMENT`;let u=`"${l.columnName}" ${l.columnType}`;return l.isPrimaryKey&&(u+=" PRIMARY KEY"),l.isUnique&&!l.isPrimaryKey&&(u+=" UNIQUE"),!l.isNullable&&!l.isPrimaryKey&&(u+=" NOT NULL"),l.defaultValue?.trim()&&!l.isIdentity&&(u+=` DEFAULT ${l.defaultValue.trim()}`),u}),i=o?.map(l=>`FOREIGN KEY ("${l.columnName}") REFERENCES "${l.referencedTable}" ("${l.referencedColumn}") ON UPDATE ${l.onUpdate} ON DELETE ${l.onDelete}`)??[];s.prepare(`CREATE TABLE "${r}" (${[...c,...i].join(", ")})`).run()}async deleteTable(e){let{tableName:t,cascade:r}=e,a=X();if(!a.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(t))throw new I(404,{message:`Table "${t}" does not exist`});let c=a.prepare(`SELECT COUNT(*) as count FROM "${t}"`).get()?.count??0;if(!r&&this.getFkReferencesForTable(a,t).length>0)return{deletedCount:0,fkViolation:!0,relatedRecords:this.getRelatedRecordsForTable(a,t)};try{return a.prepare(`DROP TABLE "${t}"`).run(),{deletedCount:c,fkViolation:!1,relatedRecords:[]}}catch(i){if((i instanceof Error?i.message:String(i)).includes("FOREIGN KEY constraint"))return{deletedCount:0,fkViolation:!0,relatedRecords:this.getRelatedRecordsForTable(a,t)};throw i instanceof I?i:new I(500,{message:`Failed to delete table "${t}"`})}}async getTableSchema({tableName:e,db:t}){try{let a=X().prepare("SELECT sql FROM sqlite_master WHERE type='table' AND name=?").get(e);if(!a)throw new I(404,{message:`Table "${e}" does not exist`});return a.sql}catch(r){throw r instanceof I?r:this.wrapError(r)}}async getTableColumns({tableName:e,db:t}){try{let r=X();if(!r.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(e))throw new I(404,{message:`Table "${e}" does not exist`});let o=r.prepare(`PRAGMA table_info("${e}")`).all(),s=r.prepare(`PRAGMA foreign_key_list("${e}")`).all(),c=new Map;for(let i of s)c.set(i.from,i);return o.map(i=>{let l=c.get(i.name),u=i.type.toLowerCase();return{columnName:i.name,dataType:Ot(u),dataTypeLabel:br(u),isNullable:i.notnull===0&&i.pk===0,columnDefault:i.dflt_value,isPrimaryKey:i.pk>0,isForeignKey:c.has(i.name),referencedTable:l?.table??null,referencedColumn:l?.to??null,enumValues:null}})}catch(r){throw r instanceof I?r:this.wrapError(r)}}async addColumn(e){let{tableName:t,columnName:r,columnType:a,defaultValue:o,isNullable:s,isUnique:c,db:i}=e,l=X();if(!l.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(t))throw new I(404,{message:`Table "${t}" does not exist`});if(l.prepare(`PRAGMA table_info("${t}")`).all().some(d=>d.name===r))throw new I(409,{message:`Column "${r}" already exists in table "${t}"`});let p=`"${r}" ${a}`;c&&(p+=" UNIQUE"),s||(p+=" NOT NULL"),o?.trim()&&(p+=` DEFAULT ${o.trim()}`);try{l.prepare(`ALTER TABLE "${t}" ADD COLUMN ${p}`).run()}catch(d){throw this.wrapError(d)}}async deleteColumn(e){let{tableName:t,columnName:r,db:a}=e,o=X();if(!o.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(t))throw new I(404,{message:`Table "${t}" does not exist`});if(!o.prepare(`PRAGMA table_info("${t}")`).all().some(i=>i.name===r))throw new I(404,{message:`Column "${r}" does not exist in table "${t}"`});try{o.prepare(`ALTER TABLE "${t}" DROP COLUMN "${r}"`).run()}catch(i){throw this.wrapError(i)}return{deletedCount:1}}async alterColumn(e){let{tableName:t,columnName:r,columnType:a,isNullable:o,defaultValue:s,db:c}=e,i=X();if(!i.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(t))throw new I(404,{message:`Table "${t}" does not exist`});let u=i.prepare(`PRAGMA table_info("${t}")`).all();if(!u.some(w=>w.name===r))throw new I(404,{message:`Column "${r}" does not exist in table "${t}"`});let m=u.filter(w=>w.pk>0).sort((w,A)=>w.pk-A.pk),p=m.length>1,d=u.map(w=>{let A=w.name===r,_=A?a:w.type,x=A?o:w.notnull===0,$=A?s?.trim()||null:w.dflt_value,O=w.pk>0,U=`"${w.name}" ${_}`;return!p&&O&&(U+=" PRIMARY KEY"),!O&&!x&&(U+=" NOT NULL"),$&&(U+=` DEFAULT ${$}`),U});p&&d.push(`PRIMARY KEY (${m.map(w=>`"${w.name}"`).join(", ")})`);let f=i.prepare(`PRAGMA foreign_key_list("${t}")`).all(),y=new Map;for(let w of f){let A=y.get(w.id)??[];A.push(w),y.set(w.id,A)}let g=Array.from(y.values()).map(w=>{let A=w.map(U=>`"${U.from}"`).join(", "),_=w.map(U=>`"${U.to}"`).join(", "),{table:x,on_update:$,on_delete:O}=w[0];return`FOREIGN KEY (${A}) REFERENCES "${x}" (${_}) ON UPDATE ${$} ON DELETE ${O}`}),E=u.map(w=>`"${w.name}"`).join(", "),T=`${t}_alter_${Date.now()}`,S=i.prepare("SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name=? AND sql IS NOT NULL").all(t),C=i.prepare("SELECT sql FROM sqlite_master WHERE type='trigger' AND tbl_name=?").all(t);i.pragma("foreign_keys = OFF");let R=i.transaction(()=>{i.prepare(`CREATE TABLE "${T}" (${[...d,...g].join(", ")})`).run(),i.prepare(`INSERT INTO "${T}" (${E}) SELECT ${E} FROM "${t}"`).run(),i.prepare(`DROP TABLE "${t}"`).run(),i.prepare(`ALTER TABLE "${T}" RENAME TO "${t}"`).run()});try{R();for(let{sql:w}of S)i.prepare(w).run();for(let{sql:w}of C)i.prepare(w).run()}catch(w){throw w instanceof I?w:this.wrapError(w)}finally{i.pragma("foreign_keys = ON")}}async renameColumn(e){let{tableName:t,columnName:r,newColumnName:a,db:o}=e,s=X();if(!s.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(t))throw new I(404,{message:`Table "${t}" does not exist`});let i=s.prepare(`PRAGMA table_info("${t}")`).all();if(!i.some(l=>l.name===r))throw new I(404,{message:`Column "${r}" does not exist in table "${t}"`});if(i.some(l=>l.name===a))throw new I(409,{message:`Column "${a}" already exists in table "${t}"`});try{s.prepare(`ALTER TABLE "${t}" RENAME COLUMN "${r}" TO "${a}"`).run()}catch(l){throw this.wrapError(l)}}async addRecord({params:e}){let{tableName:t,data:r}=e,a=X(),o=Object.keys(r);if(!o.length)throw new I(400,{message:"No data provided for insert"});let s=Object.values(r).map(l=>l!==null&&typeof l=="object"?JSON.stringify(l):l),c=o.map(l=>`"${l}"`).join(", "),i=o.map(()=>"?").join(", ");try{let l=a.prepare(`INSERT INTO "${t}" (${c}) VALUES (${i})`).run(...s);if(l.changes===0)throw new I(500,{message:`Failed to insert record into "${t}"`});return{insertedCount:l.changes}}catch(l){throw this.wrapError(l)}}async updateRecords({db:e,params:t}){let{tableName:r,updates:a,primaryKey:o}=t,s=X(),c=new Map;for(let l of a){let u=l.rowData[o];if(u==null)throw new I(400,{message:`Primary key "${o}" not found in row data.`});c.has(u)||c.set(u,[]),c.get(u)?.push({columnName:l.columnName,value:l.value})}let i=s.transaction(()=>{let l=0;for(let[u,m]of c.entries()){let p=m.map(y=>`"${y.columnName}" = ?`).join(", "),d=[...m.map(y=>y.value!==null&&typeof y.value=="object"?JSON.stringify(y.value):y.value),u],f=s.prepare(`UPDATE "${r}" SET ${p} WHERE "${o}" = ?`).run(...d);if(f.changes===0)throw new I(404,{message:`Record with ${o} = ${u} not found in table "${r}"`});l+=f.changes}return l});try{return{updatedCount:i()}}catch(l){throw l instanceof I?l:this.wrapError(l)}}async deleteRecords({tableName:e,primaryKeys:t,db:r}){let a=X(),o=t[0]?.columnName;if(!o)throw new I(400,{message:"Primary key column name is required"});let s=t.map(l=>l.value),c=s.map(()=>"?").join(", "),i=a.transaction(()=>a.prepare(`DELETE FROM "${e}" WHERE "${o}" IN (${c})`).run(...s).changes);try{return{deletedCount:i(),fkViolation:!1,relatedRecords:[]}}catch(l){if((l instanceof Error?l.message:String(l)).includes("FOREIGN KEY constraint failed"))return{deletedCount:0,fkViolation:!0,relatedRecords:this.getRelatedRecords(a,e,t)};throw this.wrapError(l)}}async forceDeleteRecords({tableName:e,primaryKeys:t,db:r}){let a=X(),o=t[0]?.columnName;if(!o)throw new I(400,{message:"Primary key column name is required"});let s=t.map(i=>i.value);a.pragma("foreign_keys = OFF");let c=a.transaction(()=>{let i=this.getFkReferencesForTable(a,e),l=0;for(let p of i){let d=s.map(()=>"?").join(", "),f=a.prepare(`DELETE FROM "${p.referencingTable}" WHERE "${p.referencingColumn}" IN (${d})`).run(...s);l+=f.changes}let u=s.map(()=>"?").join(", ");return a.prepare(`DELETE FROM "${e}" WHERE "${o}" IN (${u})`).run(...s).changes+l});try{return{deletedCount:c()}}catch(i){throw i instanceof I?i:this.wrapError(i)}finally{a.pragma("foreign_keys = ON")}}async bulkInsertRecords({tableName:e,records:t,db:r}){if(!t?.length)throw new I(400,{message:"At least one record is required"});let a=X(),o=Object.keys(t[0]),s=o.map(u=>`"${u}"`).join(", "),c=o.map(()=>"?").join(", "),i=a.prepare(`INSERT INTO "${e}" (${s}) VALUES (${c})`),l=a.transaction(u=>{let m=0;for(let p of u){let d=o.map(f=>{let y=p[f];return y!==null&&typeof y=="object"?JSON.stringify(y):y});i.run(...d),m++}return m});try{let u=l(t);return{success:!0,message:`Bulk insert completed: ${u} records inserted`,successCount:u,failureCount:0}}catch(u){throw u instanceof I?u:this.wrapError(u)}}async executeQuery({query:e,db:t}){let r=X();if(!e?.trim())throw new I(400,{message:"Query is required"});let a=e.trim().replace(/;+$/,""),o=performance.now();try{let s=r.prepare(a);if(s.reader){let l=s.all(),u=performance.now()-o;return{columns:l.length>0?Object.keys(l[0]):[],rows:l,rowCount:l.length,duration:u,message:l.length===0?"OK":void 0}}let c=s.run(),i=performance.now()-o;return{columns:[],rows:[],rowCount:c.changes,duration:i,message:`OK (${c.changes} rows affected)`}}catch(s){throw this.wrapError(s)}}getFileSize(e){if(!e)return"in-memory";try{let r=_i(e).size;return r<1024?`${r} B`:r<1024*1024?`${(r/1024).toFixed(1)} KB`:`${(r/(1024*1024)).toFixed(1)} MB`}catch{return"N/A"}}getFkReferencesForTable(e,t){let r=e.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'").all(),a=[];for(let o of r){if(o.name===t)continue;let s=e.prepare(`PRAGMA foreign_key_list("${o.name}")`).all();for(let c of s)c.table===t&&a.push({constraintName:`fk_${o.name}_${c.from}_${t}_${c.to}`,referencingTable:o.name,referencingColumn:c.from,referencedTable:t,referencedColumn:c.to})}return a}getRelatedRecordsForTable(e,t){let r=this.getFkReferencesForTable(e,t);if(!r.length)return[];let a=[];for(let o of r){let s=e.prepare(`SELECT * FROM "${o.referencingTable}" LIMIT 100`).all();s.length>0&&a.push({tableName:o.referencingTable,columnName:o.referencingColumn,constraintName:o.constraintName,records:s})}return a}getRelatedRecords(e,t,r){let a=this.getFkReferencesForTable(e,t);if(!a.length)return[];let o=[];for(let s of a){if(!r.find(m=>m.columnName===s.referencedColumn))continue;let i=r.map(m=>m.value),l=i.map(()=>"?").join(", "),u=e.prepare(`SELECT * FROM "${s.referencingTable}" WHERE "${s.referencingColumn}" IN (${l}) LIMIT 100`).all(...i);u.length>0&&o.push({tableName:s.referencingTable,columnName:s.referencingColumn,constraintName:s.constraintName,records:u})}return o}}});function Ia(){pe.register("pg",new Bt),pe.register("mysql",new Ut),pe.register("mssql",new It),pe.register("mongodb",new Dt),pe.register("sqlite",new zt),pe.register("redis",new Vt)}var qa=N(()=>{"use strict";Pe();$n();ya();ha();Ea();La();ka()});import{HTTPException as xi}from"hono/http-exception";import{DatabaseError as Pi}from"pg";import{ZodError as $i}from"zod";function Ua(n,e){if(n instanceof xi)return e.json({error:n.message??"Internal server error"},n.status);if(n instanceof $i){let t=n.issues[0];return e.json({error:"Validation error",details:t.message},400)}if(n instanceof Error){let t=n;if(t.code==="ECONNREFUSED"||t.code==="ENOTFOUND"||t.code==="ETIMEDOUT"||t.code==="ER_ACCESS_DENIED_ERROR"||t.code==="ER_BAD_HOST_ERROR"||t.code==="ECONNRESET"||t.errno===1045||t.errno===2003||t.errno===2002||n.message.includes("ECONNREFUSED")||n.message.includes("connection refused")||n.message.includes("timeout expired")||n.message.includes("Connection terminated")||n.message.includes("MongoNetworkError")||n.message.includes("MongoServerSelectionError")||n instanceof Pi&&n.code?.startsWith("08"))return e.json({error:"Database connection failed",details:n.message},503)}return e.json({error:n instanceof Error?n.message:"Internal server error"},500)}var Ba=N(()=>{"use strict"});function ja(n){let e=n.dbType.toLowerCase(),t=n.dbType==="pg"?"PostgreSQL":n.dbType;return e.includes("mongo")?`You are a database assistant for db-studio. Your responses must be CONCISE and FOCUSED.
290
290
 
291
291
  **Your Role:**
292
292
  1. Keep responses SHORT - 2-3 sentences maximum unless generating a query
@@ -414,5 +414,5 @@ This will return the 5 customers with the highest total order value. You might a
414
414
  `)}if(n.relationships&&n.relationships.length>0){t+=`
415
415
  **Relationships:**
416
416
  `;for(let r of n.relationships)t+=` - ${r.fromTable}.${r.fromColumn} -> ${r.toTable}.${r.toColumn}
417
- `}return t}var Ka=N(()=>{"use strict"});function Oi(n){let e={name:n.columnName,type:n.dataTypeLabel,nullable:n.isNullable};return n.isPrimaryKey&&(e.isPrimaryKey=!0),n.isForeignKey&&n.referencedTable&&n.referencedColumn&&(e.foreignKey=`${n.referencedTable}.${n.referencedColumn}`),n.enumValues&&n.enumValues.length>0&&(e.enumValues=n.enumValues,e.description=`Enum values: ${n.enumValues.join(", ")}`),e}function vi(n){let e=[];for(let t of n)for(let r of t.columns)if(r.foreignKey){let[a,o]=r.foreignKey.split(".");e.push({fromTable:t.name,fromColumn:r.name,toTable:a,toColumn:o})}return e}function Li(n){if(n==null)return"";if(n instanceof Date)return n.toISOString();if(typeof n=="bigint")return n.toString();if(typeof n=="object")try{return JSON.stringify(n)}catch{return String(n)}return String(n)}async function Mi(n,e,t){try{return(await n.getTableData({tableName:e,db:t,limit:3})).data.map(a=>Object.fromEntries(Object.entries(a).map(([o,s])=>[o,Li(s)])))}catch{return[]}}async function ki(n,e={}){let t=$e(),{includeSampleData:r=!1,maxTables:a}=e,o=L(t);try{let s=await o.getTablesList(n),i=s.slice(0,a??s.length).map(m=>m.tableName).map(async m=>{let[p,d]=await Promise.all([o.getTableColumns({tableName:m,db:n}),r?Mi(o,m,n):Promise.resolve([])]),f={name:m,columns:p.map(Oi)};return d.length>0&&(f.sampleData=d),f}),l=await Promise.all(i),u=vi(l);return{dbType:t,tables:l,relationships:u}}catch(s){throw new Error(`Failed to fetch database schema: ${s instanceof Error?s.message:"Unknown error"}`)}}async function Ha(n){return ki(n,{includeSampleData:!0,includeDescriptions:!0})}var Va=N(()=>{"use strict";Pe();ke()});import{zValidator as Ii}from"@hono/zod-validator";import{Hono as qi}from"hono";var za,Wa=N(()=>{"use strict";et();Re();Ka();Va();za=new qi().basePath("/chat").get("/limit",async n=>{let e=await fetch(`${Ce.PROXY_URL}/chat/limit`,{headers:{"cf-connecting-ip":n.req.header("cf-connecting-ip")??"","x-real-ip":n.req.header("x-real-ip")??"","x-forwarded-for":n.req.header("x-forwarded-for")??"","x-api-key":n.req.header("x-api-key")??""}}),t=await e.json();return n.json(t,e.status)}).post("/",Ii("json",mr),async n=>{let{messages:e,data:t}=n.req.valid("json"),{db:r,conversationId:a}=t,o=await Ha(r),s=ja(o),c={messages:e,conversationId:a,systemPrompt:s},i=await fetch(`${Ce.PROXY_URL}/chat`,{method:"POST",headers:{"Content-Type":"application/json","cf-connecting-ip":n.req.header("cf-connecting-ip")??"","x-real-ip":n.req.header("x-real-ip")??"","x-forwarded-for":n.req.header("x-forwarded-for")??"","x-api-key":n.req.header("x-api-key")??""},body:JSON.stringify(c)});if(!i.ok){let m=await i.json();return n.json({error:m.error||"Proxy request failed"},i.status)}let{readable:l,writable:u}=new TransformStream;return i.body?.pipeTo(u),new Response(l,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})})});import{Hono as Ui}from"hono";var Ya,Ga=N(()=>{"use strict";Pe();ke();Ya=new Ui().basePath("/databases").get("/",async n=>{let e=$e(),r=await L(e).getDatabasesList();return n.json({data:{databases:r,dbType:e}},200)}).get("/current",async n=>{let e=$e(),r=await L(e).getCurrentDatabase();return n.json({data:{db:r.db,dbType:e}},200)}).get("/connection",async n=>{let e=$e(),r=await L(e).getDatabaseConnectionInfo();return n.json({data:r},200)})});import{zValidator as ye}from"@hono/zod-validator";import{Hono as Bi}from"hono";var Qa,Ja=N(()=>{"use strict";Re();Pe();Qa=new Bi().basePath("/keys").get("/",ye("query",Rr),async n=>{let e=n.req.valid("query"),t=n.get("dbType"),r=Ie(L(t),t);return n.json({data:await r.scanKeys(e)},200)}).post("/",ye("query",P),ye("json",Ar),async n=>{let{db:e}=n.req.valid("query"),t=n.req.valid("json"),r=n.get("dbType"),a=Ie(L(r),r);return n.json({data:await a.createKey({db:e,...t})},200)}).get("/:key/raw",ye("param",Qe),ye("query",Nr),async n=>{let{key:e}=n.req.valid("param"),t=n.req.valid("query"),r=n.get("dbType"),a=Ie(L(r),r);return n.json({data:await a.getStringChunk({...t,key:e})},200)}).get("/:key",ye("param",Qe),ye("query",Sr),async n=>{let{key:e}=n.req.valid("param"),t=n.req.valid("query"),r=n.get("dbType"),a=Ie(L(r),r);return n.json({data:await a.getKeyDetails({...t,key:e})},200)}).post("/:key/actions",ye("param",Qe),ye("query",P),ye("json",Dr),async n=>{let{key:e}=n.req.valid("param"),{db:t}=n.req.valid("query"),r=n.req.valid("json"),a=n.get("dbType"),o=Ie(L(a),a);return n.json({data:await o.applyKeyAction({db:t,key:e,...r})},200)}).delete("/:key",ye("param",Qe),ye("query",_r),async n=>{let{key:e}=n.req.valid("param"),t=n.req.valid("query"),r=n.get("dbType"),a=Ie(L(r),r);return n.json({data:await a.deleteKey({...t,key:e})},200)})});import{zValidator as Xa}from"@hono/zod-validator";import{Hono as Fi}from"hono";var Za,eo=N(()=>{"use strict";Re();Pe();Za=new Fi().basePath("/query").post("/",Xa("query",P),Xa("json",Er),async n=>{let{query:e}=n.req.valid("json"),{db:t}=n.req.valid("query"),r=n.get("dbType"),o=await L(r).executeQuery({query:e,db:t});return n.json({data:o},200)})});import{zValidator as xe}from"@hono/zod-validator";import{Hono as ji}from"hono";var to,ro=N(()=>{"use strict";Re();Pe();to=new ji().basePath("/records").post("/",xe("query",P),xe("json",lr),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,data:r}=n.req.valid("json"),a=n.get("dbType"),o=L(a),{insertedCount:s}=await o.addRecord({db:e,params:{tableName:t,data:r}});return n.json({data:`Record inserted into "${t}" with ${s} rows inserted`},200)}).patch("/",xe("query",P),xe("json",$r),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,primaryKey:r,updates:a}=n.req.valid("json"),o=n.get("dbType"),s=L(o),{updatedCount:c}=await s.updateRecords({params:{tableName:t,primaryKey:r,updates:a},db:e});return n.json({data:`Updated ${c} records in "${t}"`},200)}).delete("/",xe("query",P),xe("json",vt),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,primaryKeys:r}=n.req.valid("json"),a=n.get("dbType"),o=L(a),{deletedCount:s,fkViolation:c,relatedRecords:i}=await o.deleteRecords({tableName:t,primaryKeys:r,db:e});return c?n.json({data:{deletedCount:0,fkViolation:!0,relatedRecords:i}},409):n.json({data:{deletedCount:s,fkViolation:!1,relatedRecords:[]}},200)}).delete("/force",xe("query",P),xe("json",vt),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,primaryKeys:r}=n.req.valid("json"),a=n.get("dbType"),s=await L(a).forceDeleteRecords({tableName:t,primaryKeys:r,db:e});return n.json({data:s},200)}).post("/bulk",xe("query",P),xe("json",ur),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,records:r}=n.req.valid("json"),a=n.get("dbType"),s=await L(a).bulkInsertRecords({tableName:t,records:r,db:e});return n.json({data:s},200)})});import{utils as ut,write as Ki}from"xlsx";function no({cols:n,rows:e,format:t,tableName:r}){switch(t){case"json":{let a=JSON.stringify(e??[],null,2);return new Uint8Array(Buffer.from(a,"utf-8"))}case"csv":{let a=[n,...e?.map(c=>n?.map(i=>c[i]))??[]],o=ut.aoa_to_sheet(a),s=ut.sheet_to_csv(o);return new Uint8Array(Buffer.from(s,"utf-8"))}case"xlsx":{let a=[n,...e?.map(i=>n?.map(l=>i[l]))??[]],o=ut.aoa_to_sheet(a),s=ut.book_new();ut.book_append_sheet(s,o,r.slice(0,31));let c=Ki(s,{bookType:"xlsx",type:"buffer"});return new Uint8Array(c)}}}var ao=N(()=>{"use strict"});import{zValidator as Y}from"@hono/zod-validator";import{Hono as Hi}from"hono";var oo,so=N(()=>{"use strict";Re();Pe();ao();oo=new Hi().basePath("/tables").get("/",Y("query",P),async n=>{let{db:e}=n.req.valid("query"),t=n.get("dbType"),a=await L(t).getTablesList(e);return n.json({data:a},200)}).post("/",Y("query",P),Y("json",hr),async n=>{let{db:e}=n.req.valid("query"),t=n.req.valid("json"),r=n.get("dbType");return await L(r).createTable({tableData:t,db:e}),n.json({data:`Table ${t.tableName} created successfully`},200)}).delete("/:tableName",Y("query",Tr),Y("param",ge),async n=>{let{db:e,cascade:t}=n.req.valid("query"),{tableName:r}=n.req.valid("param"),a=n.get("dbType"),s=await L(a).deleteTable({tableName:r,db:e,cascade:t});return n.json({data:s},200)}).delete("/:tableName/columns/:columnName",Y("query",cr),Y("param",oe),async n=>{let{db:e,cascade:t}=n.req.valid("query"),{tableName:r,columnName:a}=n.req.valid("param"),o=n.get("dbType"),s=L(o),{deletedCount:c}=await s.deleteColumn({tableName:r,columnName:a,cascade:t,db:e});return n.json({data:`Column "${a}" deleted successfully from table "${r}" with ${c} rows deleted`},200)}).post("/:tableName/columns",Y("query",P),Y("param",ge),Y("json",Te),async n=>{let{db:e}=n.req.valid("query"),{tableName:t}=n.req.valid("param"),r=n.req.valid("json"),a=n.get("dbType");return await L(a).addColumn({tableName:t,db:e,...r}),n.json({data:`Column "${r.columnName}" added successfully to table "${t}"`},200)}).patch("/:tableName/columns/:columnName/rename",Y("query",P),Y("param",oe),Y("json",Mt),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,columnName:r}=n.req.valid("param"),a=n.req.valid("json"),o=n.get("dbType");return await L(o).renameColumn({tableName:t,columnName:r,db:e,...a}),n.json({data:`Column "${r}" renamed to "${a.newColumnName}" in table "${t}"`},200)}).patch("/:tableName/columns/:columnName",Y("query",P),Y("param",oe),Y("json",We),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,columnName:r}=n.req.valid("param"),a=n.req.valid("json"),o=n.get("dbType");return await L(o).alterColumn({tableName:t,columnName:r,db:e,...a}),n.json({data:`Column "${r}" updated successfully in table "${t}"`},200)}).get("/:tableName/columns",Y("query",P),Y("param",ge),async n=>{let{db:e}=n.req.valid("query"),{tableName:t}=n.req.valid("param"),r=n.get("dbType"),o=await L(r).getTableColumns({tableName:t,db:e});return n.json({data:o},200)}).get("/:tableName/schema",Y("query",P),Y("param",ge),async n=>{let{db:e}=n.req.valid("query"),{tableName:t}=n.req.valid("param"),r=n.get("dbType"),o=await L(r).getTableSchema({tableName:t,db:e});return n.json({data:{schema:o}},200)}).get("/:tableName/data",Y("param",ge),Y("query",Pr),async n=>{let{tableName:e}=n.req.valid("param"),{cursor:t,limit:r,direction:a,sort:o,order:s,filters:c,db:i}=n.req.valid("query"),l=n.get("dbType"),m=await L(l).getTableData({tableName:e,cursor:t,limit:r,direction:a,sort:o,order:s,filters:c,db:i});return n.json({data:m},200)}).get("/:tableName/export",Y("param",ge),Y("query",wr),async n=>{let{tableName:e}=n.req.valid("param"),{db:t,format:r}=n.req.valid("query"),a=n.get("dbType"),o=L(a),{cols:s,rows:c}=await o.exportTableData({tableName:e,db:t}),i=no({cols:s,rows:c,format:r,tableName:e}),l;switch(r){case"csv":l="text/csv";break;case"xlsx":l="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";break;case"json":l="application/json";break}return new Response(i,{headers:{"Content-Type":l??"","Content-Disposition":`attachment; filename="${e}_export.${r}"`}})})});var co={};Yt(co,{createServer:()=>Zi});import{existsSync as io}from"fs";import Me from"path";import{fileURLToPath as Vi}from"url";import{serveStatic as mt}from"@hono/node-server/serve-static";import{zValidator as zi}from"@hono/zod-validator";import{Hono as Wi}from"hono";import{cors as Yi}from"hono/cors";import{HTTPException as Gi}from"hono/http-exception";import{logger as Qi}from"hono/logger";import{prettyJSON as Ji}from"hono/pretty-json";import{z as lo}from"zod";var Le,dt,Xi,Zi,uo=N(()=>{"use strict";et();Pe();qa();Ba();Wa();Ga();Ja();eo();ro();so();({API_PREFIX:Le}=Ce),dt=()=>{if(process.env.NODE_ENV==="development")return Me.resolve(process.cwd(),"../web/dist");let n=Me.dirname(Vi(import.meta.url)),e=Me.resolve(n,"./web-dist"),t=Me.resolve(process.cwd(),"../web/dist"),r=Me.resolve(e,"index.html"),a=Me.resolve(t,"index.html");return!io(r)&&io(a)?t:e},Xi=lo.object({dbType:lo.string().refine(n=>pe.getSupportedTypes().includes(n),{message:`Invalid database type. Supported types: ${pe.getSupportedTypes().join(", ")}`})}),Zi=()=>{Ia();let n=new Wi({strict:!1}).use("/*",Yi({origin:process.env.ALLOWED_ORIGINS?.split(",").map(e=>e.trim())??[],allowMethods:["GET","POST","PUT","DELETE","OPTIONS"],allowHeaders:["Content-Type"]})).use(Ji({space:2})).use(process.env.NODE_ENV==="development"?Qi():(e,t)=>t()).use("/favicon.ico",mt({path:Me.resolve(dt(),"favicon.ico")})).onError(Ua).route(Le,Ya).route(Le,za).use("/assets/*",mt({root:dt()})).use("/image.png",mt({root:dt()})).use(`${Le}/:dbType/*`,zi("param",Xi,(e,t)=>{if(!e.success){let r=t.req.param("dbType");throw new Gi(400,{message:`Invalid database type: "${r}". Supported types: ${pe.getSupportedTypes().join(", ")}`})}}),async(e,t)=>{let{dbType:r}=e.req.valid("param");e.set("dbType",r),await t()}).route(`${Le}/:dbType`,oo).route(`${Le}/:dbType`,to).route(`${Le}/:dbType`,Za).route(`${Le}/:dbType`,Qa);return process.env.NODE_ENV!=="test"&&(n.all(`${Le}/*`,e=>e.json({error:"Not found"},404)),n.use("/*",mt({root:dt()})),n.get("/*",mt({path:Me.resolve(dt(),"index.html")}))),{app:n}}});et();import{intro as el,log as Wt,outro as mo,spinner as tl}from"@clack/prompts";import{serve as rl}from"@hono/node-server";import pt from"picocolors";import{program as Qt}from"commander";var an=()=>{Qt.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("--open","Open db-studio in the default browser").option("--no-open","Do not open db-studio in the default browser").option("-s, --status","Show status of the server").option("-h, --help","Show help").option("-v, --version","Show version").parse(process.argv);let n=Qt.opts(),e=process.argv.includes("--open"),t=process.argv.includes("--no-open");return e&&t&&Qt.error("Do not combine --open and --no-open"),{...n,open:e?!0:t?!1:void 0}};import{readFile as fo}from"fs/promises";import{resolve as yo}from"path";import{cancel as ft,isCancel as Jt,note as on,select as bo,spinner as go,text as sn}from"@clack/prompts";import{parse as ho}from"dotenv";import Xt from"picocolors";var ln=async(n,e)=>{let t=e||"DATABASE_URL";if(n?.[t])return n[t];if(process.env[t])return process.env[t];let r=go();r.start("Looking for database connection..."),n?on(Xt.red(`${t} not found in .env or process.env`)):on(Xt.red(`No .env file found and ${t} not set in process.env`));let a=await bo({message:`How do you want to provide ${t}?`,options:[{value:"manual",label:"Enter connection string manually"},{value:"other-env",label:"Use different .env file"},{value:"cancel",label:"Cancel / Exit"}],initialValue:"manual"});if((Jt(a)||a==="cancel")&&(ft("No database connection provided. Exiting..."),process.exit(0)),a==="other-env"){r.start("Waiting for path...");let s=await sn({message:"Enter path to .env file",placeholder:"~/projects/myapp/.env.local or ./special.env",validate(i){if(!i?.trim())return"Path is required"}});Jt(s)&&(ft("Cancelled."),process.exit(0)),r.stop("Trying custom .env...");let c=yo(s);try{let i=await fo(c,"utf-8"),l=ho(i);if(l[t])return l[t];throw new Error(`${t} still missing in custom file`)}catch(i){let l=i;ft(`Cannot read or parse file: ${Xt.dim(l.message)}`),process.exit(1)}}r.stop("Manual input...");let o=await sn({message:`Paste your ${t}`,placeholder:"postgresql://user:password@localhost:5432/mydb or sqlite:///path/to/db.sqlite",validate(s){if(!s?.trim())return"Connection string is required!";if(!s.trim().startsWith("sqlite://"))try{new URL(s);return}catch{return"Must be a valid URL format"}}});return Jt(o)&&(ft("Cancelled."),process.exit(0)),o.trim()};import{access as To,readFile as Eo}from"fs/promises";import{dirname as wo,resolve as Zt}from"path";import{parse as Ro}from"dotenv";var Co=async n=>{let e=Zt(n);for(;;){let t=Zt(e,".env");try{return await To(t),t}catch{}let r=wo(e);if(r===e)return null;e=r}},je=async n=>{let e;if(n?e=Zt(n):e=await Co(process.cwd()),!e)return null;try{let t=await Eo(e,"utf-8");return Ro(t)}catch(t){if(t instanceof Error&&t.message.includes("ENOENT"))return null;throw t}};import So from"open";var cn=n=>n===!0,un=async n=>{await So(n)};Gt();import{intro as No,outro as Ao}from"@clack/prompts";import mn from"picocolors";var dn=()=>{No(mn.inverse(" db-studio ")),Ao(mn.green(`For more information, visit: ${rn.SITE_DOCS_LINK}`))};et();import{intro as Do,note as _o,outro as pn}from"@clack/prompts";import yt from"picocolors";var fn=async(n,e,t)=>{Do(yt.inverse(" db-studio "));let r=t||Ce.VAR_NAME,a=null;if(e)a=e;else{let o=n?await je(n):await je();o?.[r]?a=o[r]:process.env[r]&&(a=process.env[r]??null)}a?pn(yt.green(`\u2713 Database connection configured (using ${r})`)):(_o(yt.red(`\u2717 ${r} not found`),"Status"),pn(yt.yellow("\u26A0 No database connection configured")))};import{intro as Po,outro as $o}from"@clack/prompts";import bn from"picocolors";var yn={name:"db-studio",type:"module",version:"1.10.0",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 client","database gui","database browser","sql client","sql editor","query tool","table editor","data editor","postgres","postgresql","postgresql client","postgresql gui","pgadmin alternative","mysql","mysql client","ai sql","er diagram","database management","database studio"],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:"Apache-2.0",bin:{"db-studio":"./dist/index.js"},files:["dist"],scripts:{dev:"portless run","dev:app":"NODE_ENV=development tsx watch src/index.ts",build:"tsup --minify --sourcemap",prepack:"cd ../web && bun run build && cd ../server && bun run build",start:`sh -c 'APP_PORT=\${PORT:-3333}; portless proxy start >/dev/null && portless alias db-studio "$APP_PORT" --force >/dev/null && HOST=127.0.0.1 PORT="$APP_PORT" DB_STUDIO_SERVER_URL=https://db-studio.localhost node dist/index.js'`,format:"biome check --write --unsafe",test:"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage"},portless:{name:"api.db-studio",script:"dev:app"},dependencies:{"@clack/prompts":"^1.0.1","@hono/node-server":"^2.0.0","@hono/zod-validator":"^0.9.0","better-sqlite3":"^13.0.3",commander:"^15.0.0",dotenv:"^17.3.1",hono:"^4.10.4",ioredis:"^6.0.0",mongodb:"^7.1.1",mssql:"^12.2.0",mysql2:"^3.18.2",open:"^11.0.0",pg:"^8.13.1",picocolors:"^1.1.1",xlsx:"^0.18.5",zod:"^4.2.1"},devDependencies:{"@biomejs/biome":"^2.2.6","@db-studio/shared":"workspace:*","@types/better-sqlite3":"^9.6.0","@types/mssql":"^12.3.0","@types/node":"^26.0.0","@types/pg":"^8.16.0","@vitest/coverage-v8":"^4.0.17",tsup:"^8.5.1",tsx:"^4.7.1",typescript:"^7.0.2",vitest:"^4.0.17"}};var gn=()=>{Po(bn.inverse(" db-studio ")),$o(bn.green(`\u{1F680} db-studio v${yn.version}`))};var nl=async()=>{let{env:n,port:e,databaseUrl:t,varName:r,open:a,status:o,help:s,version:c}=an();s&&(dn(),process.exit(0)),c&&(gn(),process.exit(0)),o&&(await fn(n,t,r),process.exit(0)),el(pt.inverse(" db-studio "));let i=Number.parseInt(e??process.env.PORT??String(Ce.PORT),10),l=process.env.HOST,u=r||Ce.VAR_NAME,m=n?await je(n):await je(),p=!!m?.[u],d=!!process.env[u],f=t||await ln(m,u),y=t?"Using database URL from --database-url":p?`Found ${u} in ${n??".env"}`:d?`Found ${u} in environment`:"Using database URL provided interactively";Wt.success(y),process.env.DATABASE_URL=f;let{checkDatabaseConnection:g,getDatabaseConnectionDetails:E}=await Promise.resolve().then(()=>(Sn(),Cn)),{type:T,name:S,destination:C}=E(f),R=tl();R.start(`Connecting to ${S}...`);try{await g(T),R.stop(`Connected to ${S} at ${C}`)}catch(x){throw R.stop(`Could not connect to ${S} at ${C}`),x}let{createServer:w}=await Promise.resolve().then(()=>(uo(),co)),{app:A}=w();rl({fetch:A.fetch,hostname:l,port:i});let _=process.env.DB_STUDIO_SERVER_URL??process.env.PORTLESS_URL??`http://localhost:${i}`;if(Wt.success(`Server listening at ${pt.cyan(_)}`),cn(a))try{await un(_),Wt.success("Opened db-studio in your browser")}catch{Wt.warn(`Could not open your browser. Visit ${pt.cyan(_)}`)}mo(pt.green("Ready"))};nl().catch(n=>{let t=(n instanceof Error?n.message:String(n)).replace(/\b(?:postgres(?:ql)?|mysql2?|mssql|sqlserver|mongodb(?:\+srv)?|sqlite|rediss?):\/\/\S+/gi,"the configured database");mo(pt.red(`Startup failed: ${t}`)),process.exit(1)});export{nl as main};
417
+ `}return t}var Ka=N(()=>{"use strict"});function Oi(n){let e={name:n.columnName,type:n.dataTypeLabel,nullable:n.isNullable};return n.isPrimaryKey&&(e.isPrimaryKey=!0),n.isForeignKey&&n.referencedTable&&n.referencedColumn&&(e.foreignKey=`${n.referencedTable}.${n.referencedColumn}`),n.enumValues&&n.enumValues.length>0&&(e.enumValues=n.enumValues,e.description=`Enum values: ${n.enumValues.join(", ")}`),e}function vi(n){let e=[];for(let t of n)for(let r of t.columns)if(r.foreignKey){let[a,o]=r.foreignKey.split(".");e.push({fromTable:t.name,fromColumn:r.name,toTable:a,toColumn:o})}return e}function Li(n){if(n==null)return"";if(n instanceof Date)return n.toISOString();if(typeof n=="bigint")return n.toString();if(typeof n=="object")try{return JSON.stringify(n)}catch{return String(n)}return String(n)}async function Mi(n,e,t){try{return(await n.getTableData({tableName:e,db:t,limit:3})).data.map(a=>Object.fromEntries(Object.entries(a).map(([o,s])=>[o,Li(s)])))}catch{return[]}}async function ki(n,e={}){let t=$e(),{includeSampleData:r=!1,maxTables:a}=e,o=L(t);try{let s=await o.getTablesList(n),i=s.slice(0,a??s.length).map(m=>m.tableName).map(async m=>{let[p,d]=await Promise.all([o.getTableColumns({tableName:m,db:n}),r?Mi(o,m,n):Promise.resolve([])]),f={name:m,columns:p.map(Oi)};return d.length>0&&(f.sampleData=d),f}),l=await Promise.all(i),u=vi(l);return{dbType:t,tables:l,relationships:u}}catch(s){throw new Error(`Failed to fetch database schema: ${s instanceof Error?s.message:"Unknown error"}`)}}async function Ha(n){return ki(n,{includeSampleData:!0,includeDescriptions:!0})}var Va=N(()=>{"use strict";Pe();ke()});import{zValidator as Ii}from"@hono/zod-validator";import{Hono as qi}from"hono";var za,Wa=N(()=>{"use strict";et();Re();Ka();Va();za=new qi().basePath("/chat").get("/limit",async n=>{let e=await fetch(`${Ce.PROXY_URL}/chat/limit`,{headers:{"cf-connecting-ip":n.req.header("cf-connecting-ip")??"","x-real-ip":n.req.header("x-real-ip")??"","x-forwarded-for":n.req.header("x-forwarded-for")??"","x-api-key":n.req.header("x-api-key")??""}}),t=await e.json();return n.json(t,e.status)}).post("/",Ii("json",mr),async n=>{let{messages:e,data:t}=n.req.valid("json"),{db:r,conversationId:a}=t,o=await Ha(r),s=ja(o),c={messages:e,conversationId:a,systemPrompt:s},i=await fetch(`${Ce.PROXY_URL}/chat`,{method:"POST",headers:{"Content-Type":"application/json","cf-connecting-ip":n.req.header("cf-connecting-ip")??"","x-real-ip":n.req.header("x-real-ip")??"","x-forwarded-for":n.req.header("x-forwarded-for")??"","x-api-key":n.req.header("x-api-key")??""},body:JSON.stringify(c)});if(!i.ok){let m=await i.json();return n.json({error:m.error||"Proxy request failed"},i.status)}let{readable:l,writable:u}=new TransformStream;return i.body?.pipeTo(u),new Response(l,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})})});import{Hono as Ui}from"hono";var Ya,Ga=N(()=>{"use strict";Pe();ke();Ya=new Ui().basePath("/databases").get("/",async n=>{let e=$e(),r=await L(e).getDatabasesList();return n.json({data:{databases:r,dbType:e}},200)}).get("/current",async n=>{let e=$e(),r=await L(e).getCurrentDatabase();return n.json({data:{db:r.db,dbType:e}},200)}).get("/connection",async n=>{let e=$e(),r=await L(e).getDatabaseConnectionInfo();return n.json({data:r},200)})});import{zValidator as ye}from"@hono/zod-validator";import{Hono as Bi}from"hono";var Qa,Ja=N(()=>{"use strict";Re();Pe();Qa=new Bi().basePath("/keys").get("/",ye("query",Rr),async n=>{let e=n.req.valid("query"),t=n.get("dbType"),r=Ie(L(t),t);return n.json({data:await r.scanKeys(e)},200)}).post("/",ye("query",P),ye("json",Ar),async n=>{let{db:e}=n.req.valid("query"),t=n.req.valid("json"),r=n.get("dbType"),a=Ie(L(r),r);return n.json({data:await a.createKey({db:e,...t})},200)}).get("/:key/raw",ye("param",Qe),ye("query",Nr),async n=>{let{key:e}=n.req.valid("param"),t=n.req.valid("query"),r=n.get("dbType"),a=Ie(L(r),r);return n.json({data:await a.getStringChunk({...t,key:e})},200)}).get("/:key",ye("param",Qe),ye("query",Sr),async n=>{let{key:e}=n.req.valid("param"),t=n.req.valid("query"),r=n.get("dbType"),a=Ie(L(r),r);return n.json({data:await a.getKeyDetails({...t,key:e})},200)}).post("/:key/actions",ye("param",Qe),ye("query",P),ye("json",Dr),async n=>{let{key:e}=n.req.valid("param"),{db:t}=n.req.valid("query"),r=n.req.valid("json"),a=n.get("dbType"),o=Ie(L(a),a);return n.json({data:await o.applyKeyAction({db:t,key:e,...r})},200)}).delete("/:key",ye("param",Qe),ye("query",_r),async n=>{let{key:e}=n.req.valid("param"),t=n.req.valid("query"),r=n.get("dbType"),a=Ie(L(r),r);return n.json({data:await a.deleteKey({...t,key:e})},200)})});import{zValidator as Xa}from"@hono/zod-validator";import{Hono as Fi}from"hono";var Za,eo=N(()=>{"use strict";Re();Pe();Za=new Fi().basePath("/query").post("/",Xa("query",P),Xa("json",Er),async n=>{let{query:e}=n.req.valid("json"),{db:t}=n.req.valid("query"),r=n.get("dbType"),o=await L(r).executeQuery({query:e,db:t});return n.json({data:o},200)})});import{zValidator as xe}from"@hono/zod-validator";import{Hono as ji}from"hono";var to,ro=N(()=>{"use strict";Re();Pe();to=new ji().basePath("/records").post("/",xe("query",P),xe("json",lr),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,data:r}=n.req.valid("json"),a=n.get("dbType"),o=L(a),{insertedCount:s}=await o.addRecord({db:e,params:{tableName:t,data:r}});return n.json({data:`Record inserted into "${t}" with ${s} rows inserted`},200)}).patch("/",xe("query",P),xe("json",$r),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,primaryKey:r,updates:a}=n.req.valid("json"),o=n.get("dbType"),s=L(o),{updatedCount:c}=await s.updateRecords({params:{tableName:t,primaryKey:r,updates:a},db:e});return n.json({data:`Updated ${c} records in "${t}"`},200)}).delete("/",xe("query",P),xe("json",vt),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,primaryKeys:r}=n.req.valid("json"),a=n.get("dbType"),o=L(a),{deletedCount:s,fkViolation:c,relatedRecords:i}=await o.deleteRecords({tableName:t,primaryKeys:r,db:e});return c?n.json({data:{deletedCount:0,fkViolation:!0,relatedRecords:i}},409):n.json({data:{deletedCount:s,fkViolation:!1,relatedRecords:[]}},200)}).delete("/force",xe("query",P),xe("json",vt),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,primaryKeys:r}=n.req.valid("json"),a=n.get("dbType"),s=await L(a).forceDeleteRecords({tableName:t,primaryKeys:r,db:e});return n.json({data:s},200)}).post("/bulk",xe("query",P),xe("json",ur),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,records:r}=n.req.valid("json"),a=n.get("dbType"),s=await L(a).bulkInsertRecords({tableName:t,records:r,db:e});return n.json({data:s},200)})});import{utils as ut,write as Ki}from"xlsx";function no({cols:n,rows:e,format:t,tableName:r}){switch(t){case"json":{let a=JSON.stringify(e??[],null,2);return new Uint8Array(Buffer.from(a,"utf-8"))}case"csv":{let a=[n,...e?.map(c=>n?.map(i=>c[i]))??[]],o=ut.aoa_to_sheet(a),s=ut.sheet_to_csv(o);return new Uint8Array(Buffer.from(s,"utf-8"))}case"xlsx":{let a=[n,...e?.map(i=>n?.map(l=>i[l]))??[]],o=ut.aoa_to_sheet(a),s=ut.book_new();ut.book_append_sheet(s,o,r.slice(0,31));let c=Ki(s,{bookType:"xlsx",type:"buffer"});return new Uint8Array(c)}}}var ao=N(()=>{"use strict"});import{zValidator as Y}from"@hono/zod-validator";import{Hono as Hi}from"hono";var oo,so=N(()=>{"use strict";Re();Pe();ao();oo=new Hi().basePath("/tables").get("/",Y("query",P),async n=>{let{db:e}=n.req.valid("query"),t=n.get("dbType"),a=await L(t).getTablesList(e);return n.json({data:a},200)}).post("/",Y("query",P),Y("json",hr),async n=>{let{db:e}=n.req.valid("query"),t=n.req.valid("json"),r=n.get("dbType");return await L(r).createTable({tableData:t,db:e}),n.json({data:`Table ${t.tableName} created successfully`},200)}).delete("/:tableName",Y("query",Tr),Y("param",ge),async n=>{let{db:e,cascade:t}=n.req.valid("query"),{tableName:r}=n.req.valid("param"),a=n.get("dbType"),s=await L(a).deleteTable({tableName:r,db:e,cascade:t});return n.json({data:s},200)}).delete("/:tableName/columns/:columnName",Y("query",cr),Y("param",oe),async n=>{let{db:e,cascade:t}=n.req.valid("query"),{tableName:r,columnName:a}=n.req.valid("param"),o=n.get("dbType"),s=L(o),{deletedCount:c}=await s.deleteColumn({tableName:r,columnName:a,cascade:t,db:e});return n.json({data:`Column "${a}" deleted successfully from table "${r}" with ${c} rows deleted`},200)}).post("/:tableName/columns",Y("query",P),Y("param",ge),Y("json",Te),async n=>{let{db:e}=n.req.valid("query"),{tableName:t}=n.req.valid("param"),r=n.req.valid("json"),a=n.get("dbType");return await L(a).addColumn({tableName:t,db:e,...r}),n.json({data:`Column "${r.columnName}" added successfully to table "${t}"`},200)}).patch("/:tableName/columns/:columnName/rename",Y("query",P),Y("param",oe),Y("json",Mt),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,columnName:r}=n.req.valid("param"),a=n.req.valid("json"),o=n.get("dbType");return await L(o).renameColumn({tableName:t,columnName:r,db:e,...a}),n.json({data:`Column "${r}" renamed to "${a.newColumnName}" in table "${t}"`},200)}).patch("/:tableName/columns/:columnName",Y("query",P),Y("param",oe),Y("json",We),async n=>{let{db:e}=n.req.valid("query"),{tableName:t,columnName:r}=n.req.valid("param"),a=n.req.valid("json"),o=n.get("dbType");return await L(o).alterColumn({tableName:t,columnName:r,db:e,...a}),n.json({data:`Column "${r}" updated successfully in table "${t}"`},200)}).get("/:tableName/columns",Y("query",P),Y("param",ge),async n=>{let{db:e}=n.req.valid("query"),{tableName:t}=n.req.valid("param"),r=n.get("dbType"),o=await L(r).getTableColumns({tableName:t,db:e});return n.json({data:o},200)}).get("/:tableName/schema",Y("query",P),Y("param",ge),async n=>{let{db:e}=n.req.valid("query"),{tableName:t}=n.req.valid("param"),r=n.get("dbType"),o=await L(r).getTableSchema({tableName:t,db:e});return n.json({data:{schema:o}},200)}).get("/:tableName/data",Y("param",ge),Y("query",Pr),async n=>{let{tableName:e}=n.req.valid("param"),{cursor:t,limit:r,direction:a,sort:o,order:s,filters:c,db:i}=n.req.valid("query"),l=n.get("dbType"),m=await L(l).getTableData({tableName:e,cursor:t,limit:r,direction:a,sort:o,order:s,filters:c,db:i});return n.json({data:m},200)}).get("/:tableName/export",Y("param",ge),Y("query",wr),async n=>{let{tableName:e}=n.req.valid("param"),{db:t,format:r}=n.req.valid("query"),a=n.get("dbType"),o=L(a),{cols:s,rows:c}=await o.exportTableData({tableName:e,db:t}),i=no({cols:s,rows:c,format:r,tableName:e}),l;switch(r){case"csv":l="text/csv";break;case"xlsx":l="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";break;case"json":l="application/json";break}return new Response(i,{headers:{"Content-Type":l??"","Content-Disposition":`attachment; filename="${e}_export.${r}"`}})})});var co={};Yt(co,{createServer:()=>Zi});import{existsSync as io}from"fs";import Me from"path";import{fileURLToPath as Vi}from"url";import{serveStatic as mt}from"@hono/node-server/serve-static";import{zValidator as zi}from"@hono/zod-validator";import{Hono as Wi}from"hono";import{cors as Yi}from"hono/cors";import{HTTPException as Gi}from"hono/http-exception";import{logger as Qi}from"hono/logger";import{prettyJSON as Ji}from"hono/pretty-json";import{z as lo}from"zod";var Le,dt,Xi,Zi,uo=N(()=>{"use strict";et();Pe();qa();Ba();Wa();Ga();Ja();eo();ro();so();({API_PREFIX:Le}=Ce),dt=()=>{if(process.env.NODE_ENV==="development")return Me.resolve(process.cwd(),"../web/dist");let n=Me.dirname(Vi(import.meta.url)),e=Me.resolve(n,"./web-dist"),t=Me.resolve(process.cwd(),"../web/dist"),r=Me.resolve(e,"index.html"),a=Me.resolve(t,"index.html");return!io(r)&&io(a)?t:e},Xi=lo.object({dbType:lo.string().refine(n=>pe.getSupportedTypes().includes(n),{message:`Invalid database type. Supported types: ${pe.getSupportedTypes().join(", ")}`})}),Zi=()=>{Ia();let n=new Wi({strict:!1}).use("/*",Yi({origin:e=>{if(!e)return;if((process.env.ALLOWED_ORIGINS?.split(",").map(r=>r.trim()).filter(Boolean)??[]).includes(e))return e;if(process.env.NODE_ENV==="development")try{let r=new URL(e);if(r.hostname==="localhost"||r.hostname.endsWith(".localhost")||r.hostname==="127.0.0.1")return e}catch{}},allowMethods:["GET","POST","PUT","DELETE","OPTIONS"],allowHeaders:["Content-Type"]})).use(Ji({space:2})).use(process.env.NODE_ENV==="development"?Qi():(e,t)=>t()).use("/favicon.ico",mt({path:Me.resolve(dt(),"favicon.ico")})).onError(Ua).route(Le,Ya).route(Le,za).use("/assets/*",mt({root:dt()})).use("/image.png",mt({root:dt()})).use(`${Le}/:dbType/*`,zi("param",Xi,(e,t)=>{if(!e.success){let r=t.req.param("dbType");throw new Gi(400,{message:`Invalid database type: "${r}". Supported types: ${pe.getSupportedTypes().join(", ")}`})}}),async(e,t)=>{let{dbType:r}=e.req.valid("param");e.set("dbType",r),await t()}).route(`${Le}/:dbType`,oo).route(`${Le}/:dbType`,to).route(`${Le}/:dbType`,Za).route(`${Le}/:dbType`,Qa);return process.env.NODE_ENV!=="test"&&(n.all(`${Le}/*`,e=>e.json({error:"Not found"},404)),n.use("/*",mt({root:dt()})),n.get("/*",mt({path:Me.resolve(dt(),"index.html")}))),{app:n}}});et();import{intro as el,log as Wt,outro as mo,spinner as tl}from"@clack/prompts";import{serve as rl}from"@hono/node-server";import pt from"picocolors";import{program as Qt}from"commander";var an=()=>{Qt.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("--open","Open db-studio in the default browser").option("--no-open","Do not open db-studio in the default browser").option("-s, --status","Show status of the server").option("-h, --help","Show help").option("-v, --version","Show version").parse(process.argv);let n=Qt.opts(),e=process.argv.includes("--open"),t=process.argv.includes("--no-open");return e&&t&&Qt.error("Do not combine --open and --no-open"),{...n,open:e?!0:t?!1:void 0}};import{readFile as fo}from"fs/promises";import{resolve as yo}from"path";import{cancel as ft,isCancel as Jt,note as on,select as bo,spinner as go,text as sn}from"@clack/prompts";import{parse as ho}from"dotenv";import Xt from"picocolors";var ln=async(n,e)=>{let t=e||"DATABASE_URL";if(n?.[t])return n[t];if(process.env[t])return process.env[t];let r=go();r.start("Looking for database connection..."),n?on(Xt.red(`${t} not found in .env or process.env`)):on(Xt.red(`No .env file found and ${t} not set in process.env`));let a=await bo({message:`How do you want to provide ${t}?`,options:[{value:"manual",label:"Enter connection string manually"},{value:"other-env",label:"Use different .env file"},{value:"cancel",label:"Cancel / Exit"}],initialValue:"manual"});if((Jt(a)||a==="cancel")&&(ft("No database connection provided. Exiting..."),process.exit(0)),a==="other-env"){r.start("Waiting for path...");let s=await sn({message:"Enter path to .env file",placeholder:"~/projects/myapp/.env.local or ./special.env",validate(i){if(!i?.trim())return"Path is required"}});Jt(s)&&(ft("Cancelled."),process.exit(0)),r.stop("Trying custom .env...");let c=yo(s);try{let i=await fo(c,"utf-8"),l=ho(i);if(l[t])return l[t];throw new Error(`${t} still missing in custom file`)}catch(i){let l=i;ft(`Cannot read or parse file: ${Xt.dim(l.message)}`),process.exit(1)}}r.stop("Manual input...");let o=await sn({message:`Paste your ${t}`,placeholder:"postgresql://user:password@localhost:5432/mydb or sqlite:///path/to/db.sqlite",validate(s){if(!s?.trim())return"Connection string is required!";if(!s.trim().startsWith("sqlite://"))try{new URL(s);return}catch{return"Must be a valid URL format"}}});return Jt(o)&&(ft("Cancelled."),process.exit(0)),o.trim()};import{access as To,readFile as Eo}from"fs/promises";import{dirname as wo,resolve as Zt}from"path";import{parse as Ro}from"dotenv";var Co=async n=>{let e=Zt(n);for(;;){let t=Zt(e,".env");try{return await To(t),t}catch{}let r=wo(e);if(r===e)return null;e=r}},je=async n=>{let e;if(n?e=Zt(n):e=await Co(process.cwd()),!e)return null;try{let t=await Eo(e,"utf-8");return Ro(t)}catch(t){if(t instanceof Error&&t.message.includes("ENOENT"))return null;throw t}};import So from"open";var cn=n=>n===!0,un=async n=>{await So(n)};Gt();import{intro as No,outro as Ao}from"@clack/prompts";import mn from"picocolors";var dn=()=>{No(mn.inverse(" db-studio ")),Ao(mn.green(`For more information, visit: ${rn.SITE_DOCS_LINK}`))};et();import{intro as Do,note as _o,outro as pn}from"@clack/prompts";import yt from"picocolors";var fn=async(n,e,t)=>{Do(yt.inverse(" db-studio "));let r=t||Ce.VAR_NAME,a=null;if(e)a=e;else{let o=n?await je(n):await je();o?.[r]?a=o[r]:process.env[r]&&(a=process.env[r]??null)}a?pn(yt.green(`\u2713 Database connection configured (using ${r})`)):(_o(yt.red(`\u2717 ${r} not found`),"Status"),pn(yt.yellow("\u26A0 No database connection configured")))};import{intro as Po,outro as $o}from"@clack/prompts";import bn from"picocolors";var yn={name:"db-studio",type:"module",version:"1.11.0",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 client","database gui","database browser","sql client","sql editor","query tool","table editor","data editor","postgres","postgresql","postgresql client","postgresql gui","pgadmin alternative","mysql","mysql client","ai sql","er diagram","database management","database studio"],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:"Apache-2.0",bin:{"db-studio":"./dist/index.js"},files:["dist"],scripts:{dev:"portless run","dev:app":"NODE_ENV=development tsx watch src/index.ts",build:"tsup --minify --sourcemap",prepack:"cd ../web && bun run build && cd ../server && bun run build",start:`sh -c 'APP_PORT=\${PORT:-3333}; portless proxy start >/dev/null && portless alias db-studio "$APP_PORT" --force >/dev/null && HOST=127.0.0.1 PORT="$APP_PORT" DB_STUDIO_SERVER_URL=https://db-studio.localhost node dist/index.js'`,format:"biome check --write --unsafe",test:"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage"},portless:{name:"api.db-studio",script:"dev:app"},dependencies:{"@clack/prompts":"^1.0.1","@hono/node-server":"^2.0.0","@hono/zod-validator":"^0.9.0","better-sqlite3":"^13.0.3",commander:"^15.0.0",dotenv:"^17.3.1",hono:"^4.10.4",ioredis:"^6.0.0",mongodb:"^7.1.1",mssql:"^12.2.0",mysql2:"^3.18.2",open:"^11.0.0",pg:"^8.13.1",picocolors:"^1.1.1",xlsx:"^0.18.5",zod:"^4.2.1"},devDependencies:{"@biomejs/biome":"^2.2.6","@db-studio/shared":"workspace:*","@types/better-sqlite3":"^9.6.0","@types/mssql":"^12.3.0","@types/node":"^26.0.0","@types/pg":"^8.16.0","@vitest/coverage-v8":"^4.0.17",tsup:"^8.5.1",tsx:"^4.7.1",typescript:"^7.0.2",vitest:"^4.0.17"}};var gn=()=>{Po(bn.inverse(" db-studio ")),$o(bn.green(`\u{1F680} db-studio v${yn.version}`))};var nl=async()=>{let{env:n,port:e,databaseUrl:t,varName:r,open:a,status:o,help:s,version:c}=an();s&&(dn(),process.exit(0)),c&&(gn(),process.exit(0)),o&&(await fn(n,t,r),process.exit(0)),el(pt.inverse(" db-studio "));let i=n?await je(n):await je();if(i)for(let[x,$]of Object.entries(i))process.env[x]===void 0&&(process.env[x]=$);let l=Number.parseInt(e??process.env.PORT??String(Ce.PORT),10),u=process.env.HOST,m=r||Ce.VAR_NAME,p=!!i?.[m],d=!!process.env[m],f=t||await ln(i,m),y=t?"Using database URL from --database-url":p?`Found ${m} in ${n??".env"}`:d?`Found ${m} in environment`:"Using database URL provided interactively";Wt.success(y),process.env.DATABASE_URL=f;let{checkDatabaseConnection:g,getDatabaseConnectionDetails:E}=await Promise.resolve().then(()=>(Sn(),Cn)),{type:T,name:S,destination:C}=E(f),R=tl();R.start(`Connecting to ${S}...`);try{await g(T),R.stop(`Connected to ${S} at ${C}`)}catch(x){throw R.stop(`Could not connect to ${S} at ${C}`),x}let{createServer:w}=await Promise.resolve().then(()=>(uo(),co)),{app:A}=w();rl({fetch:A.fetch,hostname:u,port:l});let _=process.env.DB_STUDIO_SERVER_URL??process.env.PORTLESS_URL??`http://localhost:${l}`;if(Wt.success(`Server listening at ${pt.cyan(_)}`),cn(a))try{await un(_),Wt.success("Opened db-studio in your browser")}catch{Wt.warn(`Could not open your browser. Visit ${pt.cyan(_)}`)}mo(pt.green("Ready"))};process.env.NODE_ENV!=="test"&&nl().catch(n=>{let t=(n instanceof Error?n.message:String(n)).replace(/\b(?:postgres(?:ql)?|mysql2?|mssql|sqlserver|mongodb(?:\+srv)?|sqlite|rediss?):\/\/\S+/gi,"the configured database");mo(pt.red(`Startup failed: ${t}`)),process.exit(1)});export{nl as main};
418
418
  //# sourceMappingURL=index.js.map