drixio 1.1.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +133 -97
- package/dist/studio/assets/index-B2SFgnu7.js +254 -0
- package/dist/studio/assets/index-CCy0fVAv.css +1 -0
- package/dist/studio/index.html +48 -0
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -1,66 +1,102 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
2
|
+
var Jt=Object.defineProperty;var E=(s,a)=>()=>(s&&(a=s(s=0)),a);var L=(s,a)=>{for(var t in a)Jt(s,t,{get:a[t],enumerable:!0})};import N from"picocolors";function Oe(){console.log(`
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
`+
|
|
6
|
-
`)+
|
|
5
|
+
`+N.bold(Xt(` \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
6
|
+
`)+Zt(` \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2551 \u255A\u2588\u2588\u2557\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557
|
|
7
7
|
`)+ea(` \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
8
8
|
`)+ta(` \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
9
9
|
`)+aa(` \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u255D \u2588\u2588\u2557 \u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D
|
|
10
|
-
`)+oa(" \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D")))}function se(
|
|
11
|
-
\u2554${r}\u2557`));let o=72-
|
|
12
|
-
`))}function Fe(
|
|
10
|
+
`)+oa(" \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D")))}function se(s,a){let r="\u2550".repeat(72);console.log(N.cyan(`
|
|
11
|
+
\u2554${r}\u2557`));let o=72-s.length,e=Math.max(0,Math.floor(o/2)),n=Math.max(0,o-e),c=" ".repeat(e)+N.bold(N.white(s))+" ".repeat(n);console.log(N.cyan("\u2551")+c+N.cyan("\u2551")),console.log(N.cyan(`\u2560${"\u2550".repeat(72)}\u2563`));let i=(l,m)=>{let p=l.padEnd(12),u=` ${N.bold(p)}: ${m}`,d=` ${p}: `+m.replace(/\x1b\[[0-9;]*m/g,""),f=" ".repeat(Math.max(0,72-d.length));console.log(N.cyan("\u2551")+u+f+N.cyan("\u2551"))};for(let l of a)i(l.label,l.value);console.log(N.cyan(`\u255A${"\u2550".repeat(72)}\u255D`)),console.log(N.dim(` Use arrow keys to navigate \u2022 Enter to select \u2022 Ctrl+C to exit
|
|
12
|
+
`))}function Fe(s){let a=" Lightweight Interactive TUI Database Client \u2022 v1.1.3 ",t="None",r="-",o="None";s.type==="unknown"?o=N.dim("No configuration found. Please run check to configure."):(t=s.type.toUpperCase(),r=s.targetUrl,o=s.source===".env"?"Loaded from project .env file":s.source==="auto-detected"?"Auto-detected local SQLite file":"Manual connection config"),se(a,[{label:"Database",value:t},{label:"Target",value:r.length>45?"..."+r.slice(-42):r},{label:"Source",value:o},{label:"Working Dir",value:process.cwd().length>45?"..."+process.cwd().slice(-42):process.cwd()}])}var J,Xt,Zt,ea,ta,aa,oa,Se=E(()=>{"use strict";J=(s,a,t)=>r=>`\x1B[38;2;${s};${a};${t}m${r}\x1B[39m`,Xt=J(0,255,255),Zt=J(0,230,245),ea=J(0,210,235),ta=J(0,188,220),aa=J(0,168,205),oa=J(0,148,188)});var $e,We=E(()=>{"use strict";$e=class{dbPath;db=null;constructor(a){this.dbPath=a}async getDb(){if(!this.db){if(!(await import("fs")).existsSync(this.dbPath))throw new Error(`Failed to found database file at: ${this.dbPath}`);let t=await import("sqlite");this.db=new t.DatabaseSync(this.dbPath)}return this.db}quoteIdentifier(a){return`"${a.replace(/"/g,'""')}"`}async getTables(){return(await this.getDb()).prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' ORDER BY name;").all().map(r=>r.name)}async getSchema(a){let t=await this.getDb(),r=this.quoteIdentifier(a),e=t.prepare(`PRAGMA table_info(${r})`).all(),c=t.prepare(`PRAGMA foreign_key_list(${r})`).all();return e.map(i=>{let l=c.find(m=>m.from===i.name);return{name:i.name,type:i.type,isPk:i.pk>0,nullable:i.notnull===0,defaultValue:i.dflt_value!=null?String(i.dflt_value):void 0,fkTarget:l?{table:l.table,column:l.to}:void 0}})}async getIndexes(a){let t=await this.getDb(),r=this.quoteIdentifier(a),e=t.prepare(`PRAGMA index_list(${r})`).all(),n=[];for(let c of e){if(c.origin==="pk")continue;let l=t.prepare(`PRAGMA index_info(${this.quoteIdentifier(c.name)})`).all();n.push({name:c.name,columns:l.map(m=>m.name),isUnique:c.unique>0})}return n}async getData(a,t=50,r=0,o,e){let n=await this.getDb(),i=(await this.getSchema(a)).map(u=>u.name),l=`SELECT * FROM ${this.quoteIdentifier(a)}`;o&&(l+=` WHERE ${o}`),e&&(l+=` ORDER BY ${this.quoteIdentifier(e.col)} ${e.asc?"ASC":"DESC"}`),l+=` LIMIT ${t} OFFSET ${r}`;let p=n.prepare(l).all();return{columns:i,rows:p}}async query(a){let t=await this.getDb(),r=a.trim().toUpperCase();if(r.startsWith("SELECT")||r.startsWith("PRAGMA")||r.startsWith("EXPLAIN")||r.startsWith("WITH")){let n=t.prepare(a).all(),c=[];return n.length>0&&(c=Object.keys(n[0])),{columns:c,rows:n}}else return t.prepare(a).run(),{columns:["Result"],rows:[{Result:"Success"}]}}async executeSql(a){(await this.getDb()).exec(a)}async close(){this.db&&(this.db.close(),this.db=null)}async insert(a,t){if(t.length===0)return;let r=await this.getDb(),o=Object.keys(t[0]),e=o.map(l=>this.quoteIdentifier(l)).join(", "),n=o.map(()=>"?").join(", "),c=`INSERT INTO ${this.quoteIdentifier(a)} (${e}) VALUES (${n})`,i=r.prepare(c);for(let l of t){let m=o.map(p=>l[p]);i.run(...m)}}}});import na from"pg";var xe,je=E(()=>{"use strict";xe=class{client;connected=!1;constructor(a){this.client=new na.Client({connectionString:a})}async connectIfNecessary(){this.connected||(await this.client.connect(),this.connected=!0)}quoteIdentifier(a){return`"${a.replace(/"/g,'""')}"`}async getTables(){return await this.connectIfNecessary(),(await this.client.query(`
|
|
13
13
|
SELECT tablename
|
|
14
14
|
FROM pg_catalog.pg_tables
|
|
15
15
|
WHERE schemaname != 'pg_catalog' AND schemaname != 'information_schema'
|
|
16
16
|
ORDER BY tablename;
|
|
17
|
-
`)).rows.map(r=>r.tablename)}async getSchema(
|
|
18
|
-
SELECT c.column_name, c.data_type, c.is_nullable,
|
|
17
|
+
`)).rows.map(r=>r.tablename)}async getSchema(a){return await this.connectIfNecessary(),(await this.client.query(`
|
|
18
|
+
SELECT c.column_name, c.data_type, c.is_nullable, c.column_default,
|
|
19
19
|
(SELECT count(*)
|
|
20
20
|
FROM information_schema.key_column_usage kcu
|
|
21
21
|
JOIN information_schema.table_constraints tc
|
|
22
22
|
ON kcu.constraint_name = tc.constraint_name
|
|
23
23
|
WHERE tc.constraint_type = 'PRIMARY KEY'
|
|
24
24
|
AND kcu.table_name = c.table_name
|
|
25
|
-
AND kcu.column_name = c.column_name) as is_pk
|
|
25
|
+
AND kcu.column_name = c.column_name) as is_pk,
|
|
26
|
+
(SELECT ccu.table_name || '.' || ccu.column_name
|
|
27
|
+
FROM information_schema.table_constraints tc
|
|
28
|
+
JOIN information_schema.key_column_usage kcu
|
|
29
|
+
ON tc.constraint_name = kcu.constraint_name
|
|
30
|
+
JOIN information_schema.constraint_column_usage ccu
|
|
31
|
+
ON ccu.constraint_name = tc.constraint_name
|
|
32
|
+
WHERE tc.constraint_type = 'FOREIGN KEY'
|
|
33
|
+
AND tc.table_name = c.table_name
|
|
34
|
+
AND kcu.column_name = c.column_name
|
|
35
|
+
LIMIT 1) as fk_target
|
|
26
36
|
FROM information_schema.columns c
|
|
27
37
|
WHERE c.table_name = $1;
|
|
28
|
-
`,[
|
|
38
|
+
`,[a])).rows.map(o=>{let e;if(o.fk_target){let n=o.fk_target.split(".");e={table:n[0],column:n[1]}}return{name:o.column_name,type:o.data_type,isPk:parseInt(o.is_pk)>0,nullable:o.is_nullable==="YES",defaultValue:o.column_default!=null?String(o.column_default):void 0,fkTarget:e}})}async getIndexes(a){await this.connectIfNecessary();let o=(await this.client.query(`
|
|
39
|
+
SELECT
|
|
40
|
+
i.relname as index_name,
|
|
41
|
+
a.attname as column_name,
|
|
42
|
+
ix.indisunique as is_unique,
|
|
43
|
+
ix.indisprimary as is_primary
|
|
44
|
+
FROM
|
|
45
|
+
pg_class t,
|
|
46
|
+
pg_class i,
|
|
47
|
+
pg_index ix,
|
|
48
|
+
pg_attribute a
|
|
49
|
+
WHERE
|
|
50
|
+
t.oid = ix.indrelid
|
|
51
|
+
AND i.oid = ix.indexrelid
|
|
52
|
+
AND a.attrelid = t.oid
|
|
53
|
+
AND a.attnum = ANY(ix.indkey)
|
|
54
|
+
AND t.relkind = 'r'
|
|
55
|
+
AND t.relname = $1
|
|
56
|
+
ORDER BY
|
|
57
|
+
i.relname, a.attnum;
|
|
58
|
+
`,[a])).rows,e=new Map;for(let n of o){if(n.is_primary)continue;let c=n.index_name;e.has(c)||e.set(c,{name:c,columns:[],isUnique:n.is_unique}),e.get(c).columns.push(n.column_name)}return Array.from(e.values())}async getData(a,t=50,r=0,o,e){await this.connectIfNecessary();let c=(await this.getSchema(a)).map(m=>m.name),i=`SELECT * FROM ${this.quoteIdentifier(a)}`;o&&(i+=` WHERE ${o}`),e&&(i+=` ORDER BY ${this.quoteIdentifier(e.col)} ${e.asc?"ASC":"DESC"}`),i+=" LIMIT $1 OFFSET $2";let l=await this.client.query(i,[t,r]);return{columns:c,rows:l.rows}}async query(a){await this.connectIfNecessary();let t=await this.client.query(a),r=[];return t.fields&&(r=t.fields.map(o=>o.name)),{columns:r,rows:t.rows||[]}}async executeSql(a){await this.connectIfNecessary(),await this.client.query(a)}async close(){this.connected&&(await this.client.end(),this.connected=!1)}async insert(a,t){if(t.length===0)return;await this.connectIfNecessary();let r=Object.keys(t[0]),o=r.map(e=>this.quoteIdentifier(e)).join(", ");for(let e of t){let n=r.map((l,m)=>`$${m+1}`).join(", "),c=`INSERT INTO ${this.quoteIdentifier(a)} (${o}) VALUES (${n})`,i=r.map(l=>e[l]);await this.client.query(c,i)}}}});import sa from"mysql2/promise";var Te,Qe=E(()=>{"use strict";Te=class{connection;pool=null;constructor(a){this.connection=a}async getPool(){return this.pool||(this.pool=sa.createPool(this.connection)),this.pool}quoteIdentifier(a){return`\`${a.replace(/`/g,"``")}\``}async getTables(){let a=await this.getPool(),[t]=await a.query("SHOW TABLES;");return t.map(r=>Object.values(r)[0])}async getSchema(a){let t=await this.getPool(),[r]=await t.query(`SHOW COLUMNS FROM ${this.quoteIdentifier(a)}`),o=r,[e]=await t.query(`
|
|
59
|
+
SELECT COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
|
|
60
|
+
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
|
61
|
+
WHERE TABLE_SCHEMA = DATABASE()
|
|
62
|
+
AND TABLE_NAME = ?
|
|
63
|
+
AND REFERENCED_TABLE_NAME IS NOT NULL
|
|
64
|
+
`,[a]),n=e;return o.map(c=>{let i=n.find(p=>p.COLUMN_NAME===c.Field),l;if(c.Type.toUpperCase().startsWith("ENUM")){let p=c.Type.match(/enum\((.*?)\)/i);p&&(l=p[1].split(",").map(u=>u.trim().replace(/^'|'$/g,"")))}return{name:c.Field,type:c.Type,isPk:c.Key==="PRI",nullable:c.Null==="YES",defaultValue:c.Default!=null?String(c.Default):void 0,enumValues:l,fkTarget:i?{table:i.REFERENCED_TABLE_NAME,column:i.REFERENCED_COLUMN_NAME}:void 0}})}async getIndexes(a){let t=await this.getPool(),[r]=await t.query(`SHOW INDEX FROM ${this.quoteIdentifier(a)}`),o=new Map;for(let e of r){if(e.Key_name==="PRIMARY")continue;let n=e.Key_name;o.has(n)||o.set(n,{name:n,columns:[],isUnique:e.Non_unique===0}),o.get(n).columns.push(e.Column_name)}return Array.from(o.values())}async getData(a,t=50,r=0,o,e){let n=await this.getPool(),i=(await this.getSchema(a)).map(p=>p.name),l=`SELECT * FROM ${this.quoteIdentifier(a)}`;o&&(l+=` WHERE ${o}`),e&&(l+=` ORDER BY ${this.quoteIdentifier(e.col)} ${e.asc?"ASC":"DESC"}`),l+=` LIMIT ${t} OFFSET ${r}`;let[m]=await n.query(l);return{columns:i,rows:m}}async query(a){let t=await this.getPool(),[r,o]=await t.query(a),e=[],n=[];return o&&Array.isArray(o)?(e=o.map(c=>c.name),n=r):(e=["Result"],n=[{Result:"Success",AffectedRows:r.affectedRows}]),{columns:e,rows:n}}async executeSql(a){await(await this.getPool()).query(a)}async close(){this.pool&&(await this.pool.end(),this.pool=null)}async insert(a,t){if(t.length===0)return;let r=await this.getPool(),o=Object.keys(t[0]),e=o.map(i=>this.quoteIdentifier(i)).join(", "),n=o.map(()=>"?").join(", "),c=`INSERT INTO ${this.quoteIdentifier(a)} (${e}) VALUES (${n})`;for(let i of t){let l=o.map(m=>i[m]);await r.query(c,l)}}}});var Ve={};L(Ve,{createDBAdapter:()=>h});function h(s){switch(s.type){case"sqlite":return new $e(s.targetUrl);case"postgres":return new xe(s.targetUrl);case"mysql":return new Te(s.targetUrl);default:throw new Error(`Unsupported database type: ${s.type}`)}}var A=E(()=>{"use strict";We();je();Qe()});function j(s){switch(s){case"sqlite":return new De;case"postgres":return new Le;case"mysql":return new Ne;default:return new De}}var De,Le,Ne,Ae=E(()=>{"use strict";De=class{quoteIdentifier(a){return`"${a}"`}escapeString(a){return a.replace(/'/g,"''")}buildCreateTable(a,t){let r=t.map(e=>{let n="";return e.type==="Integer"&&(n="INTEGER"),e.type==="Text"&&(n="TEXT"),e.type==="Boolean"&&(n="BOOLEAN"),e.type==="Decimal"&&(n="REAL"),e.type==="DateTime"&&(n="DATETIME"),e.type==="Enum"&&e.enumValues&&(n=`TEXT CHECK(${this.quoteIdentifier(e.name)} IN (${e.enumValues.map(c=>`'${this.escapeString(c)}'`).join(", ")}))`),e.isPk&&e.type==="Integer"?n="INTEGER PRIMARY KEY AUTOINCREMENT":e.isPk?n+=" PRIMARY KEY":e.nullable||(n+=" NOT NULL"),e.defaultValue&&e.defaultValue!=="AutoInc"&&!e.defaultValue.startsWith("FK ->")&&(e.defaultValue==="Timestamp"?n+=" DEFAULT CURRENT_TIMESTAMP":n+=` DEFAULT ${e.defaultValue}`),` ${this.quoteIdentifier(e.name)} ${n}`}),o=t.filter(e=>e.fkTarget).map(e=>` FOREIGN KEY (${this.quoteIdentifier(e.name)}) REFERENCES ${this.quoteIdentifier(e.fkTarget.table)}(${this.quoteIdentifier(e.fkTarget.column)})`);return o.length>0&&r.push(...o),`CREATE TABLE ${this.quoteIdentifier(a)} (
|
|
29
65
|
${r.join(`,
|
|
30
66
|
`)}
|
|
31
|
-
);`}},Le=class{quoteIdentifier(
|
|
67
|
+
);`}},Le=class{quoteIdentifier(a){return`"${a}"`}escapeString(a){return a.replace(/'/g,"''")}buildCreateTable(a,t){let r=t.map(e=>{let n="";return e.isPk&&e.type==="Integer"?n="SERIAL PRIMARY KEY":(e.type==="Integer"&&(n="INTEGER"),e.type==="Text"&&(n="TEXT"),e.type==="Boolean"&&(n="BOOLEAN"),e.type==="Decimal"&&(n="NUMERIC"),e.type==="DateTime"&&(n="TIMESTAMP"),e.type==="Enum"&&e.enumValues&&(n=`VARCHAR(255) CHECK(${this.quoteIdentifier(e.name)} IN (${e.enumValues.map(c=>`'${this.escapeString(c)}'`).join(", ")}))`),e.isPk&&(n+=" PRIMARY KEY"),!e.nullable&&!e.isPk&&(n+=" NOT NULL")),e.defaultValue&&e.defaultValue!=="AutoInc"&&!e.defaultValue.startsWith("FK ->")&&(e.defaultValue==="Timestamp"?n+=" DEFAULT CURRENT_TIMESTAMP":n+=` DEFAULT ${e.defaultValue}`),` ${this.quoteIdentifier(e.name)} ${n}`}),o=t.filter(e=>e.fkTarget).map(e=>` FOREIGN KEY (${this.quoteIdentifier(e.name)}) REFERENCES ${this.quoteIdentifier(e.fkTarget.table)}(${this.quoteIdentifier(e.fkTarget.column)})`);return o.length>0&&r.push(...o),`CREATE TABLE ${this.quoteIdentifier(a)} (
|
|
32
68
|
${r.join(`,
|
|
33
69
|
`)}
|
|
34
|
-
);`}},
|
|
70
|
+
);`}},Ne=class{quoteIdentifier(a){return`\`${a}\``}escapeString(a){return a.replace(/'/g,"''")}buildCreateTable(a,t){let r=t.map(e=>{let n="";return e.type==="Integer"&&(n="INT"),e.type==="Text"&&(n="VARCHAR(255)"),e.type==="Boolean"&&(n="BOOLEAN"),e.type==="Decimal"&&(n="DOUBLE"),e.type==="DateTime"&&(n="DATETIME"),e.type==="Enum"&&e.enumValues&&(n=`VARCHAR(255) CHECK(${this.quoteIdentifier(e.name)} IN (${e.enumValues.map(c=>`'${this.escapeString(c)}'`).join(", ")}))`),e.isPk&&e.type==="Integer"?n+=" AUTO_INCREMENT PRIMARY KEY":e.isPk&&(n+=" PRIMARY KEY"),!e.nullable&&!e.isPk&&(n+=" NOT NULL"),e.defaultValue&&e.defaultValue!=="AutoInc"&&!e.defaultValue.startsWith("FK ->")&&(e.defaultValue==="Timestamp"?n+=" DEFAULT CURRENT_TIMESTAMP":n+=` DEFAULT ${e.defaultValue}`),` ${this.quoteIdentifier(e.name)} ${n}`}),o=t.filter(e=>e.fkTarget).map(e=>` FOREIGN KEY (${this.quoteIdentifier(e.name)}) REFERENCES ${this.quoteIdentifier(e.fkTarget.table)}(${this.quoteIdentifier(e.fkTarget.column)})`);return o.length>0&&r.push(...o),`CREATE TABLE ${this.quoteIdentifier(a)} (
|
|
35
71
|
${r.join(`,
|
|
36
72
|
`)}
|
|
37
|
-
);`}}});import
|
|
38
|
-
\u2554${d}\u2557`)),r){let f=m-2-r.length,y=Math.max(0,Math.floor(f/2)),b=Math.max(0,f-y),x=" ".repeat(y)
|
|
39
|
-
(${o.rows.length} rows)`)),await
|
|
73
|
+
);`}}});import $ from"picocolors";function ee(s,a,t={}){let{title:r,emptyMessage:o="No records found",maxColWidth:e=30}=t,n={},c=0;for(let f of s){let y=f.length;for(let x of a){let k=String(x[f]??"");k.length>y&&(y=k.length)}let b=Math.max(f.length,Math.min(e,y));n[f]=b,c+=b}let i=3*(s.length-1),l=c+i+4,m=Math.max(74,l),p=m-4-i;if(c<p&&s.length>0){let f=s[s.length-1];n[f]+=p-c}let u=(f,y)=>f.length>y?f.slice(0,y-3)+"...":f,d="\u2550".repeat(m-2);if(console.log($.cyan(`
|
|
74
|
+
\u2554${d}\u2557`)),r){let f=m-2-r.length,y=Math.max(0,Math.floor(f/2)),b=Math.max(0,f-y),x=" ".repeat(y)+$.bold($.white(r))+" ".repeat(b);console.log($.cyan("\u2551")+x+$.cyan("\u2551")),console.log($.cyan(`\u2560${d}\u2563`))}if(s.length>0){let f=s.map(y=>$.bold($.white(u(y,n[y]).padEnd(n[y])))).join($.cyan(" \u2551 "));console.log($.cyan("\u2551 ")+f+$.cyan(" \u2551")),console.log($.cyan(`\u2560${d}\u2563`))}if(a.length===0){let f=m-4-o.length,y=Math.max(0,Math.floor(f/2)),b=Math.max(0,f-y);console.log($.cyan("\u2551 ")+" ".repeat(y)+$.yellow(o)+" ".repeat(b)+$.cyan(" \u2551"))}else for(let f of a){let y=s.map(b=>$.white(u(String(f[b]??""),n[b]).padEnd(n[b]))).join($.cyan(" \u2551 "));console.log($.cyan("\u2551 ")+y+$.cyan(" \u2551"))}console.log($.cyan(`\u255A${d}\u255D`))}var Ce=E(()=>{"use strict"});var at={};L(at,{runQueryCommand:()=>ga});import ce from"picocolors";async function ga(s,a){s.type==="unknown"&&(console.log(ce.red("Error: No database connection found. Cannot run query.")),process.exit(1));let t=h(s),r=a[0];if(!r){let{input:o}=await import("@inquirer/prompts");r=await o({message:"Enter your SQL query:"})}(!r||r.trim()==="")&&(console.log(ce.yellow("No query provided. Exiting.")),process.exit(0));try{let o=await t.query(r);o.columns.length===0&&(console.log(ce.yellow("Query executed successfully. (No output)")),process.exit(0)),ee(o.columns,o.rows,{title:"Query Result",maxColWidth:50}),console.log(ce.dim(`
|
|
75
|
+
(${o.rows.length} rows)`)),await t.close(),process.exit(0)}catch(o){console.log(ce.red(`
|
|
40
76
|
Query Error: ${o.message}
|
|
41
|
-
`)),process.exit(1)}}var ot=E(()=>{"use strict";
|
|
42
|
-
Starting export to ${i}...`));for(let m of l)try{if(
|
|
77
|
+
`)),process.exit(1)}}var ot=E(()=>{"use strict";A();Ce()});var nt={};L(nt,{runExportCommand:()=>fa});import U from"picocolors";import me from"fs/promises";import ue from"path";async function fa(s,a,t){s.type==="unknown"&&(console.log(U.red("Error: No database connection found. Cannot run export.")),process.exit(1));let r=h(s),o=a[0],e=t.format,n=t["schema-only"],{select:c}=await import("@inquirer/prompts");if(!o){let m=await r.getTables();m.length===0&&(console.log(U.yellow("No tables found in the database.")),process.exit(0));let p=[{name:"All Tables (*)",value:"*"},...m.map(u=>({name:u,value:u}))];o=await c({message:"Which table do you want to export?",choices:p})}e||(e=await c({message:"Which format do you want to export?",choices:[{name:"CSV",value:"csv"},{name:"JSON",value:"json"}]}));let i=ue.join(process.cwd(),"drixio_exports");await me.mkdir(i,{recursive:!0});let l=o==="*"?await r.getTables():[o];console.log(U.cyan(`
|
|
78
|
+
Starting export to ${i}...`));for(let m of l)try{if(n){let p=await r.getSchema(m);if(e==="json"){let u=ue.join(i,`${m}_schema.json`);await me.writeFile(u,JSON.stringify(p,null,2),"utf-8"),console.log(U.green(`\u2714 Exported Schema (JSON): ${m}`))}else{let u=ue.join(i,`${m}_schema.csv`),d=`Name,Type,IsPrimaryKey,Nullable
|
|
43
79
|
`,f=p.map(y=>`"${y.name}","${y.type}","${y.isPk}","${y.nullable}"`).join(`
|
|
44
80
|
`);await me.writeFile(u,d+f,"utf-8"),console.log(U.green(`\u2714 Exported Schema (CSV): ${m}`))}}else{let p=await r.getData(m,9999999,0);if(e==="json"){let u=ue.join(i,`${m}_data.json`);await me.writeFile(u,JSON.stringify(p.rows,null,2),"utf-8"),console.log(U.green(`\u2714 Exported Data (JSON): ${m} (${p.rows.length} rows)`))}else{let u=ue.join(i,`${m}_data.csv`),d="";if(p.columns.length>0){let f=p.columns.join(",")+`
|
|
45
81
|
`,y=p.rows.map(b=>p.columns.map(x=>`"${String(b[x]??"").replace(/"/g,'""')}"`).join(",")).join(`
|
|
46
|
-
`);d=f+y}await me.writeFile(u,d,"utf-8"),console.log(U.green(`\u2714 Exported Data (CSV): ${m} (${p.rows.length} rows)`))}}}catch(p){console.log(U.red(`\u2718 Failed to export table ${m}: ${p.message}`))}await r.close(),console.log(U.cyan("Export complete.")),process.exit(0)}var st=E(()=>{"use strict";
|
|
47
|
-
Starting Drixio Studio on http://localhost:${
|
|
48
|
-
`)),ha({fetch:
|
|
49
|
-
Starting database backup...`)),console.log(
|
|
50
|
-
`)),await
|
|
51
|
-
Backup Error: ${o.message}`))}finally{await r.close()}console.log(
|
|
52
|
-
Backup successfully completed at ${
|
|
82
|
+
`);d=f+y}await me.writeFile(u,d,"utf-8"),console.log(U.green(`\u2714 Exported Data (CSV): ${m} (${p.rows.length} rows)`))}}}catch(p){console.log(U.red(`\u2718 Failed to export table ${m}: ${p.message}`))}await r.close(),console.log(U.cyan("Export complete.")),process.exit(0)}var st=E(()=>{"use strict";A()});import{Hono as ya}from"hono";function rt(s,a){let t=new ya,r=h(a);t.get("/tables",async o=>{try{let e=await r.getTables();return o.json({success:!0,data:e})}catch(e){return o.json({success:!1,error:e.message},500)}}),t.get("/tables/stats",async o=>{try{let e=await r.getTables(),n={};for(let c of e)try{let i=await r.query(`SELECT COUNT(*) as c FROM ${r.quoteIdentifier(c)}`);if(i&&i.rows&&i.rows.length>0){let l=i.rows[0],m=Object.values(l)[0];n[c]=parseInt(String(m),10)||0}else n[c]=0}catch{n[c]=0}return o.json({success:!0,data:n})}catch(e){return o.json({success:!1,error:e.message},500)}}),t.get("/tables/:name/schema",async o=>{let e=o.req.param("name");try{let n=await r.getSchema(e);return o.json({success:!0,data:n})}catch(n){return o.json({success:!1,error:n.message},500)}}),t.get("/tables/:name/indexes",async o=>{let e=o.req.param("name");try{let n=await r.getIndexes(e);return o.json({success:!0,data:n})}catch(n){return o.json({success:!1,error:n.message},500)}}),t.get("/tables/:name/data",async o=>{let e=o.req.param("name"),n=parseInt(o.req.query("limit")||"50",10),c=parseInt(o.req.query("offset")||"0",10),i=o.req.query("where")||"",l=o.req.query("orderCol"),m=o.req.query("orderAsc"),p;l&&(p={col:l,asc:m!=="false"});try{let u=await r.getData(e,n,c,i,p);return o.json({success:!0,data:u})}catch(u){return o.json({success:!1,error:u.message},500)}}),t.post("/query",async o=>{try{let{sql:e}=await o.req.json(),n=await r.query(e);return o.json({success:!0,data:n})}catch(e){return o.json({success:!1,error:e.message},500)}}),s.route("/api",t)}var it=E(()=>{"use strict";A()});var ct={};L(ct,{runStudio:()=>xa});import{serve as ha}from"@hono/node-server";import{Hono as wa}from"hono";import{serveStatic as ba}from"@hono/node-server/serve-static";import Ea from"open";import pe from"path";import lt from"picocolors";import{fileURLToPath as Sa}from"url";async function xa(s){let a=new wa;rt(a,s);let r=qe.includes("src")||qe.includes("server")?pe.resolve(qe,"../../dist/studio"):pe.resolve(qe,"./studio"),o=await import("fs/promises");a.use("/*",ba({root:pe.relative(process.cwd(),r)})),a.get("*",async c=>{let i=pe.join(r,"index.html");try{let l=await o.readFile(i,"utf-8");return c.html(l)}catch{return c.text("Drixio Studio static files not found. Did you run build?",404)}});let e=process.env.PORT?parseInt(process.env.PORT,10):51213,n=await Ta(e);console.log(lt.cyan(`
|
|
83
|
+
Starting Drixio Studio on http://localhost:${n}...`)),console.log(lt.dim(`Press Ctrl+C to stop the server.
|
|
84
|
+
`)),ha({fetch:a.fetch,port:n}),await Ea(`http://localhost:${n}`)}async function Ta(s){let a=await import("net"),t=s;for(;;){if(await new Promise(o=>{let e=a.createServer();e.unref(),e.on("error",()=>o(!1)),e.listen(t,()=>{e.close(()=>o(!0))})}))return t;t++}}var $a,qe,mt=E(()=>{"use strict";it();$a=Sa(import.meta.url),qe=pe.dirname($a)});var ut={};L(ut,{runBackupCommand:()=>Da});import I from"picocolors";import Ie from"fs/promises";import ve from"path";async function Da(s){s.type==="unknown"&&(console.log(I.red("Error: No database connection found. Cannot run backup.")),process.exit(1));let a=new Date().toISOString().replace(/[:.]/g,"-"),t=ve.join(process.cwd(),`drixio_backup_${a}`);if(console.log(I.cyan(`
|
|
85
|
+
Starting database backup...`)),console.log(I.dim(`Database: ${s.type}`)),console.log(I.dim(`Target: ${s.targetUrl}`)),console.log(I.dim(`Backup Directory: ${t}
|
|
86
|
+
`)),await Ie.mkdir(t,{recursive:!0}),s.type==="sqlite")try{let o=ve.basename(s.targetUrl)||"database.sqlite",e=ve.join(t,o);await Ie.copyFile(s.targetUrl,e),console.log(I.green(`\u2714 Copied raw SQLite file to ${e}`))}catch(o){console.log(I.red(`\u2718 Failed to copy SQLite file: ${o.message}`))}let r=h(s);try{let o=await r.getTables();o.length===0&&console.log(I.yellow("No tables found to backup."));for(let e of o)try{let n=await r.getSchema(e),c=await r.getData(e,9999999,0),i={table:e,schema:n,totalRows:c.rows.length,data:c.rows},l=ve.join(t,`${e}.json`);await Ie.writeFile(l,JSON.stringify(i,null,2),"utf-8"),console.log(I.green(`\u2714 Dumped table: ${e} (${c.rows.length} rows)`))}catch(n){console.log(I.red(`\u2718 Failed to dump table ${e}: ${n.message}`))}}catch(o){console.log(I.red(`
|
|
87
|
+
Backup Error: ${o.message}`))}finally{await r.close()}console.log(I.cyan(`
|
|
88
|
+
Backup successfully completed at ${t}`)),process.exit(0)}var pt=E(()=>{"use strict";A()});var gt={};L(gt,{runImportCommand:()=>qa});import M from"picocolors";import dt from"fs/promises";import Aa from"path";function Ca(s){let a=s.split(/\r?\n/).filter(e=>e.trim()!=="");if(a.length===0)return[];let t=e=>{let n=[],c="",i=!1;for(let l=0;l<e.length;l++){let m=e[l];m==='"'&&e[l+1]==='"'?(c+='"',l++):m==='"'?i=!i:m===","&&!i?(n.push(c),c=""):c+=m}return n.push(c),n},r=t(a[0]),o=[];for(let e=1;e<a.length;e++){let n=t(a[e]),c={};r.forEach((i,l)=>{c[i]=n[l]??""}),o.push(c)}return o}async function qa(s,a,t){s.type==="unknown"&&(console.log(M.red("Error: No database connection found. Cannot run import.")),process.exit(1));let r=h(s),o=a[0],e=t.table,{input:n,select:c}=await import("@inquirer/prompts");o||(o=await n({message:"Enter the path to your CSV or JSON file:"}));let i=Aa.resolve(process.cwd(),o);try{await dt.access(i)}catch{console.log(M.red(`Error: File not found at ${i}`)),process.exit(1)}if(!e){let d=await r.getTables();d.length===0&&(console.log(M.yellow("No tables found. Please create a table first.")),process.exit(1)),e=await c({message:"Which table do you want to import data into?",choices:d.map(f=>({name:f,value:f}))})}console.log(M.cyan(`
|
|
53
89
|
Reading file...`));let l=await dt.readFile(i,"utf-8"),m=[];if(o.toLowerCase().endsWith(".json"))try{if(m=JSON.parse(l),!Array.isArray(m))throw new Error("JSON root must be an array of objects.")}catch(d){console.log(M.red(`Invalid JSON format: ${d.message}`)),process.exit(1)}else o.toLowerCase().endsWith(".csv")?m=Ca(l):(console.log(M.red("Error: Unsupported file extension. Please provide a .csv or .json file.")),process.exit(1));m.length===0&&(console.log(M.yellow("No data found to import.")),process.exit(0)),console.log(M.cyan(`Importing ${m.length} rows into '${e}'...`));let p=500,u=0;try{for(let d=0;d<m.length;d+=p){let f=m.slice(d,d+p);await r.insert(e,f),u+=f.length,process.stdout.write(`\r${M.dim(`Progress: ${u} / ${m.length}`)}`)}console.log(M.green(`
|
|
54
90
|
|
|
55
91
|
\u2714 Successfully imported ${u} rows into ${e}!`))}catch(d){console.log(M.red(`
|
|
56
|
-
\u2718 Import failed at row ${u}: ${d.message}`))}finally{await r.close()}process.exit(0)}var ft=E(()=>{"use strict";
|
|
57
|
-
Analyzing schema for table '${r}'...`));let i;try{i=await
|
|
92
|
+
\u2718 Import failed at row ${u}: ${d.message}`))}finally{await r.close()}process.exit(0)}var ft=E(()=>{"use strict";A()});var yt={};L(yt,{runSeedCommand:()=>La});import _ from"picocolors";function de(s){let a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t="";for(let r=0;r<s;r++)t+=a.charAt(Math.floor(Math.random()*a.length));return t}function va(){let s=["gmail.com","yahoo.com","outlook.com","example.com"],a=de(8).toLowerCase(),t=s[Math.floor(Math.random()*s.length)];return`${a}@${t}`}function Ra(s){let a=s.name.toLowerCase();if(a.includes("email"))return va();if(a.includes("phone"))return`+1${Math.floor(Math.random()*9e9+1e9)}`;if(a.includes("name"))return`User_${de(5)}`;if(a.includes("url")||a.includes("link"))return`https://example.com/${de(6)}`;if(a.includes("date")||a.includes("time")||a.includes("created")||a.includes("updated"))return new Date(Date.now()-Math.floor(Math.random()*1e10)).toISOString().replace("T"," ").slice(0,19);let t=s.type.toLowerCase();return t.includes("int")||t.includes("num")||t.includes("float")||t.includes("double")?Math.floor(Math.random()*1e3):t.includes("bool")||t==="tinyint(1)"?Math.random()>.5:t.includes("char")||t.includes("text")||t.includes("string")?de(10):de(5)}async function La(s,a){s.type==="unknown"&&(console.log(_.red("Error: No database connection found. Cannot run seed.")),process.exit(1));let t=h(s),r=a[0],o=a[1],{input:e,select:n}=await import("@inquirer/prompts");if(!r){let d=await t.getTables();d.length===0&&(console.log(_.yellow("No tables found. Please create a table first.")),process.exit(1)),r=await n({message:"Which table do you want to seed with fake data?",choices:d.map(f=>({name:f,value:f}))})}let c=parseInt(o);if(isNaN(c)||c<=0){let d=await e({message:"How many rows to generate?",default:"50"});c=parseInt(d),(isNaN(c)||c<=0)&&(console.log(_.red("Error: Invalid count number.")),process.exit(1))}console.log(_.cyan(`
|
|
93
|
+
Analyzing schema for table '${r}'...`));let i;try{i=await t.getSchema(r)}catch(d){console.log(_.red(`Error: ${d.message}`)),process.exit(1)}let l=i.filter(d=>!d.isPk);l.length===0&&console.log(_.yellow("Table only has Primary Key columns. Seeding might fail if they don't auto-increment.")),console.log(_.cyan(`Generating ${c} records...`));let m=[];for(let d=0;d<c;d++){let f={};for(let y of l.length>0?l:i)f[y.name]=Ra(y);m.push(f)}let p=500,u=0;try{s.type==="sqlite"?await t.executeSql("PRAGMA foreign_keys = OFF;"):s.type==="mysql"?await t.executeSql("SET FOREIGN_KEY_CHECKS = 0;"):s.type==="postgres"&&await t.executeSql("SET session_replication_role = replica;");for(let d=0;d<m.length;d+=p){let f=m.slice(d,d+p);await t.insert(r,f),u+=f.length,process.stdout.write(`\r${_.dim(`Progress: ${u} / ${c}`)}`)}console.log(_.green(`
|
|
58
94
|
|
|
59
|
-
\u2714 Successfully seeded ${u} fake records into ${r}!`))}catch(d){console.log(
|
|
60
|
-
\u2718 Seed failed: ${d.message}`))}finally{try{
|
|
61
|
-
Scanning database to generate ER diagram...`));try{let
|
|
62
|
-
`;for(let
|
|
63
|
-
`;let c=await
|
|
95
|
+
\u2714 Successfully seeded ${u} fake records into ${r}!`))}catch(d){console.log(_.red(`
|
|
96
|
+
\u2718 Seed failed: ${d.message}`))}finally{try{s.type==="sqlite"?await t.executeSql("PRAGMA foreign_keys = ON;"):s.type==="mysql"?await t.executeSql("SET FOREIGN_KEY_CHECKS = 1;"):s.type==="postgres"&&await t.executeSql("SET session_replication_role = DEFAULT;")}catch{}await t.close()}process.exit(0)}var ht=E(()=>{"use strict";A()});var wt={};L(wt,{runDiagramCommand:()=>ka});import Q from"picocolors";import Na from"fs/promises";import Ia from"path";async function ka(s){s.type==="unknown"&&(console.log(Q.red("Error: No database connection found. Cannot generate diagram.")),process.exit(1));let a=h(s);console.log(Q.cyan(`
|
|
97
|
+
Scanning database to generate ER diagram...`));try{let t=await a.getTables();t.length===0&&(console.log(Q.yellow("No tables found in the database.")),process.exit(0));let r=`erDiagram
|
|
98
|
+
`;for(let n of t){r+=` ${n} {
|
|
99
|
+
`;let c=await a.getSchema(n);for(let i of c){let l=i.type.replace(/\s+/g,"_").replace(/[^a-zA-Z0-9_]/g,""),m=i.isPk?" PK":"";r+=` ${l} ${i.name}${m}
|
|
64
100
|
`}r+=` }
|
|
65
101
|
`}let o=`
|
|
66
102
|
# Database Schema Diagram
|
|
@@ -70,93 +106,93 @@ You can paste this Mermaid code directly into [Draw.io](https://app.diagrams.net
|
|
|
70
106
|
\`\`\`mermaid
|
|
71
107
|
${r}
|
|
72
108
|
\`\`\`
|
|
73
|
-
`,e=
|
|
74
|
-
\u2714 Diagram generated successfully!`)),console.log(
|
|
75
|
-
\u2718 Failed to generate diagram: ${
|
|
76
|
-
Executing SQL script from ${
|
|
77
|
-
Scanning database to generate TypeScript interfaces...`));try{let
|
|
78
|
-
// Database: ${
|
|
109
|
+
`,e=Ia.resolve(process.cwd(),"drixio_schema.md");await Na.writeFile(e,o.trim(),"utf-8"),console.log(Q.green(`
|
|
110
|
+
\u2714 Diagram generated successfully!`)),console.log(Q.white(`Output saved to: ${Q.bold(e)}`)),console.log(Q.dim("Tip: Open this file in VSCode with a Markdown viewer or paste it into Draw.io."))}catch(t){console.log(Q.red(`
|
|
111
|
+
\u2718 Failed to generate diagram: ${t.message}`))}finally{await a.close()}process.exit(0)}var bt=E(()=>{"use strict";A()});var St={};L(St,{runExecCommand:()=>Ba});import oe from"picocolors";import Et from"fs/promises";import Pa from"path";async function Ba(s,a){s.type==="unknown"&&(console.log(oe.red("Error: No database connection found. Cannot run exec.")),process.exit(1));let t=a[0],{input:r}=await import("@inquirer/prompts");t||(t=await r({message:"Enter the path to your .sql file:"}));let o=Pa.resolve(process.cwd(),t);try{await Et.access(o)}catch{console.log(oe.red(`Error: File not found at ${o}`)),process.exit(1)}let e=await Et.readFile(o,"utf-8");e.trim()||(console.log(oe.yellow("File is empty.")),process.exit(0));let n=h(s);console.log(oe.cyan(`
|
|
112
|
+
Executing SQL script from ${t}...`));try{await n.executeSql(e),console.log(oe.green("\u2714 Script executed successfully!"))}catch(c){console.log(oe.red(`\u2718 Execution failed: ${c.message}`))}finally{await n.close()}process.exit(0)}var $t=E(()=>{"use strict";A()});var xt={};L(xt,{runGenerateTypesCommand:()=>Fa});import Y from"picocolors";import Ma from"fs/promises";import _a from"path";function Oa(s){let a=s.toLowerCase();return a.includes("int")||a.includes("num")||a.includes("float")||a.includes("double")||a.includes("real")?"number":a.includes("bool")||a==="tinyint(1)"?"boolean":a.includes("char")||a.includes("text")||a.includes("uuid")||a.includes("string")?"string":a.includes("date")||a.includes("time")?"Date":a.includes("json")?"any":"string"}async function Fa(s){s.type==="unknown"&&(console.log(Y.red("Error: No database connection found. Cannot generate types.")),process.exit(1));let a=h(s);console.log(Y.cyan(`
|
|
113
|
+
Scanning database to generate TypeScript interfaces...`));try{let t=await a.getTables();t.length===0&&(console.log(Y.yellow("No tables found in the database.")),process.exit(0));let r=`// Generated by Drixio CLI
|
|
114
|
+
// Database: ${s.type.toUpperCase()}
|
|
79
115
|
|
|
80
|
-
`;for(let e of
|
|
81
|
-
`;let c=await
|
|
116
|
+
`;for(let e of t){let n=e.charAt(0).toUpperCase()+e.slice(1).replace(/_([a-z])/g,i=>i[1].toUpperCase());r+=`export interface ${n} {
|
|
117
|
+
`;let c=await a.getSchema(e);for(let i of c){let l=Oa(i.type),m=i.nullable?"?":"";r+=` ${i.name}${m}: ${l};
|
|
82
118
|
`}r+=`}
|
|
83
119
|
|
|
84
|
-
`}let o=
|
|
85
|
-
`,"utf-8"),console.log(
|
|
86
|
-
\u2718 Failed to generate types: ${
|
|
87
|
-
Initializing a local ${o} database...`));let e="";if(o==="sqlite"){let i=
|
|
88
|
-
Connecting to local server to create database '${u}'...`));try{if(o==="mysql"){let b=await(await import("mysql2/promise")).createConnection({host:i,port:parseInt(l),user:m,password:p});await b.query(`CREATE DATABASE IF NOT EXISTS \`${u}\``),await b.end()}else if(o==="postgres"){let y=await import("pg"),b=new y.Client({host:i,port:parseInt(l),user:m,password:p,database:"postgres"});await b.connect(),(await b.query("SELECT 1 FROM pg_database WHERE datname = $1",[u])).rowCount===0&&await b.query(`CREATE DATABASE "${u}"`),await b.end()}console.log(
|
|
89
|
-
Could not connect to the local ${o} server on ${i}:${l}.`)),(y.code==="ECONNREFUSED"||y.message.includes("ECONNREFUSED")||y.message.includes("connect"))&&(console.log(
|
|
90
|
-
\u{1F4A1} It seems you don't have ${o} installed or running locally.`)),o==="mysql"?console.log(
|
|
120
|
+
`}let o=_a.resolve(process.cwd(),"drixio-types.d.ts");await Ma.writeFile(o,r.trim()+`
|
|
121
|
+
`,"utf-8"),console.log(Y.green("\u2714 TypeScript interfaces generated successfully!")),console.log(Y.white(`Output saved to: ${Y.bold(o)}`))}catch(t){console.log(Y.red(`
|
|
122
|
+
\u2718 Failed to generate types: ${t.message}`))}finally{await a.close()}process.exit(0)}var Tt=E(()=>{"use strict";A()});var At={};L(At,{runInitCommand:()=>Ua});import S from"picocolors";import Re from"fs/promises";import Dt from"path";async function Ua(s){let{select:a,input:t,password:r}=await import("@inquirer/prompts"),o=s[0];(!o||!["sqlite","mysql","postgres"].includes(o.toLowerCase()))&&(o=await a({message:"Which database do you want to initialize locally?",choices:[{name:"SQLite (Local File)",value:"sqlite"},{name:"MySQL (Local Server)",value:"mysql"},{name:"PostgreSQL (Local Server)",value:"postgres"}]})),o=o.toLowerCase(),console.log(S.cyan(`
|
|
123
|
+
Initializing a local ${o} database...`));let e="";if(o==="sqlite"){let i=s[1]||"database.sqlite";!i.endsWith(".sqlite")&&!i.endsWith(".db")&&(i+=".sqlite");let l=Dt.resolve(process.cwd(),i);try{await Re.access(l),console.log(S.yellow(`File ${i} already exists.`))}catch{await Re.writeFile(l,""),console.log(S.green(`\u2714 Created local database file: ${i}`))}e=`file:${i}`}else{console.log(S.dim("Please provide credentials for your local server (e.g. running via XAMPP, Homebrew, etc.)"));let i=await t({message:"Server Host:",default:"localhost"}),l=await t({message:"Server Port:",default:o==="mysql"?"3306":"5432"}),m=await t({message:"Username:",default:o==="mysql"?"root":"postgres"}),p=await r({message:"Password (leave empty if none):"}),u=s[1];u||(u=await t({message:"New Database Name (e.g. my_project):"})),(!u||!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(u))&&(console.log(S.red("Invalid database name. Please use only letters, numbers, and underscores.")),process.exit(1)),console.log(S.cyan(`
|
|
124
|
+
Connecting to local server to create database '${u}'...`));try{if(o==="mysql"){let b=await(await import("mysql2/promise")).createConnection({host:i,port:parseInt(l),user:m,password:p});await b.query(`CREATE DATABASE IF NOT EXISTS \`${u}\``),await b.end()}else if(o==="postgres"){let y=await import("pg"),b=new y.Client({host:i,port:parseInt(l),user:m,password:p,database:"postgres"});await b.connect(),(await b.query("SELECT 1 FROM pg_database WHERE datname = $1",[u])).rowCount===0&&await b.query(`CREATE DATABASE "${u}"`),await b.end()}console.log(S.green(`\u2714 Created local database: ${u}`))}catch(y){console.log(S.red(`\u2718 Failed to create database on server: ${y.message}`)),console.log(S.dim(`
|
|
125
|
+
Could not connect to the local ${o} server on ${i}:${l}.`)),(y.code==="ECONNREFUSED"||y.message.includes("ECONNREFUSED")||y.message.includes("connect"))&&(console.log(S.yellow(`
|
|
126
|
+
\u{1F4A1} It seems you don't have ${o} installed or running locally.`)),o==="mysql"?console.log(S.white(`\u{1F449} Download MySQL here: ${S.cyan("https://dev.mysql.com/downloads/installer/")}`)):o==="postgres"&&(console.log(S.white(`\u{1F449} Download PostgreSQL here: ${S.cyan("https://www.postgresql.org/download/")}`)),console.log(S.white(`\u{1F449} Or use Postgres.app for Mac: ${S.cyan("https://postgresapp.com/")}`))),console.log(S.dim("(Alternatively, you can run 'drixio init sqlite' for a zero-install local database!)"))),process.exit(1)}let d=o==="postgres"?"postgres://":"mysql://",f=p?`${m}:${p}`:`${m}`;e=`${d}${f}@${i}:${l}/${u}`}let n=Dt.resolve(process.cwd(),".env"),c="";try{c=await Re.readFile(n,"utf-8")}catch{}c.includes("DATABASE_URL=")?(c=c.replace(/DATABASE_URL=.*/g,`DATABASE_URL=${e}`),console.log(S.yellow("\u2714 Updated existing .env file with new DATABASE_URL"))):(c+=(c.endsWith(`
|
|
91
127
|
`)||c.length===0?"":`
|
|
92
128
|
`)+`DATABASE_URL=${e}
|
|
93
|
-
`,console.log(
|
|
94
|
-
\u{1F389} Initialization Complete!`)),console.log(
|
|
95
|
-
Connecting to local server to drop database '${
|
|
96
|
-
\u2713 `),style:{message:u=>g.bold(g.white(u)),highlight:u=>{let d=u.replace(/\x1b\[[0-9;]*m/g,"");return g.cyan(d)}}},message:"Add another column?",default:!0})}
|
|
129
|
+
`,console.log(S.green("\u2714 Saved connection string to .env file"))),await Re.writeFile(n,c,"utf-8"),console.log(S.green(`
|
|
130
|
+
\u{1F389} Initialization Complete!`)),console.log(S.white(`You can now run ${S.bold("npx drixio")} to manage it!`)),process.exit(0)}var Ct=E(()=>{"use strict"});var qt={};L(qt,{runDropDbCommand:()=>Qa});import V from"picocolors";import Wa from"fs/promises";import ja from"path";async function Qa(s){let{select:a,input:t,password:r,confirm:o}=await import("@inquirer/prompts"),e=s[0];(!e||!["sqlite","mysql","postgres"].includes(e.toLowerCase()))&&(e=await a({message:"Which database type do you want to drop?",choices:[{name:"SQLite (Local File)",value:"sqlite"},{name:"MySQL (Local Server)",value:"mysql"},{name:"PostgreSQL (Local Server)",value:"postgres"}]})),e=e.toLowerCase();let n=s[1];if(e==="sqlite"){n||(n=await t({message:"Enter the SQLite filename to delete (e.g. database.sqlite):",default:"database.sqlite"})),!n.endsWith(".sqlite")&&!n.endsWith(".db")&&(n+=".sqlite"),await o({message:`Are you absolutely sure you want to delete ${n}? This cannot be undone!`,default:!1})||(console.log(V.yellow("Aborted.")),process.exit(0));let i=ja.resolve(process.cwd(),n);try{await Wa.unlink(i),console.log(V.green(`\u2714 Deleted local database file: ${n}`))}catch(l){console.log(V.red(`\u2718 Failed to delete file: ${l.message}`))}}else{console.log(V.dim(`Please provide credentials for your local ${e} server to drop a database.`));let c=await t({message:"Server Host:",default:"localhost"}),i=await t({message:"Server Port:",default:e==="mysql"?"3306":"5432"}),l=await t({message:"Username:",default:e==="mysql"?"root":"postgres"}),m=await r({message:"Password (leave empty if none):"});n||(n=await t({message:"Which Database Name do you want to DROP?"})),await o({message:`Are you absolutely sure you want to DROP DATABASE '${n}' from ${c}? All data will be lost!`,default:!1})||(console.log(V.yellow("Aborted.")),process.exit(0)),console.log(V.cyan(`
|
|
131
|
+
Connecting to local server to drop database '${n}'...`));try{if(e==="mysql"){let d=await(await import("mysql2/promise")).createConnection({host:c,port:parseInt(i),user:l,password:m});await d.query(`DROP DATABASE IF EXISTS \`${n}\``),await d.end()}else if(e==="postgres"){let u=await import("pg"),d=new u.Client({host:c,port:parseInt(i),user:l,password:m,database:"postgres"});await d.connect(),await d.query(`DROP DATABASE IF EXISTS "${n}"`),await d.end()}console.log(V.green(`\u2714 Dropped database: ${n}`))}catch(u){console.log(V.red(`\u2718 Failed to drop database on server: ${u.message}`)),process.exit(1)}}process.exit(0)}var vt=E(()=>{"use strict"});import{select as Va,Separator as Ka}from"@inquirer/prompts";import G from"picocolors";var Rt,Lt=E(()=>{"use strict";Rt=async()=>await Va({message:"Table Manager - Choose an action:",theme:{prefix:G.cyan("\u2713 "),icon:{cursor:G.cyan("\u203A ")},style:{message:s=>G.bold(G.white(s)),highlight:s=>{let a=s.replace(/\x1b\[[0-9;]*m/g,"");return a.includes(" Back")?G.red(a):G.cyan(a)}}},choices:[{name:" Create New Table",value:"create",description:"Build a new database table."},{name:" Modify Existing Table",value:"modify",description:"Modify an existing table's schema structure."},{name:" Drop Table",value:"drop",description:"Delete an entire table and its data."},new Ka,{name:G.dim(" Back"),value:"back",description:"Back to the main menu."}]})});import{input as ke,select as ne,confirm as Nt}from"@inquirer/prompts";import ge from"picocolors";async function fe(s,a,t=[],r=""){let o="";for(;!o;){if(o=await ke({message:"Column name (leave empty to cancel/finish):",default:r}),!o.trim())return{col:null,isPk:!1};/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(o)?t.includes(o)&&(console.log(ge.red("Column name already exists!")),o=""):(console.log(ge.red("Invalid column name. Use only letters, numbers, and underscores.")),o="")}let e=await ne({message:`Select type for column '${o}':`,choices:[{name:"Integer",value:"Integer"},{name:"Text (String)",value:"Text"},{name:"Boolean",value:"Boolean"},{name:"Decimal (Float)",value:"Decimal"},{name:"DateTime",value:"DateTime"},{name:"Enum",value:"Enum"}]}),n;e==="Enum"&&(n=(await ke({message:"Enter comma-separated Enum values (e.g. active, pending, deleted):"})).split(",").map(d=>d.trim()).filter(d=>d),n.length===0&&console.log(ge.yellow("Warning: No enum values provided.")));let c="";e==="DateTime"&&await Nt({message:"Set default to CURRENT_TIMESTAMP?",default:!1})&&(c="Timestamp");let i=!1,l;if(e!=="DateTime"){let u=[{name:"None",value:"none"}];a||u.push({name:"Primary Key",value:"pk"}),u.push({name:"Foreign Key",value:"fk"});let d=await ne({message:`Key type for '${o}':`,choices:u});if(d==="pk")i=!0,e==="Integer"&&(c="AutoInc");else if(d==="fk"){let f=await s.getTables();if(f.length>0){let y=await ne({message:"Select target table:",choices:f.map(x=>({name:x,value:x}))}),b=await s.getSchema(y);if(b.length>0){let x=await ne({message:"Select target column:",choices:b.map(k=>({name:`${k.name} (${k.type})`,value:k.name}))});l={table:y,column:x},c=`FK -> ${y}.${x}`}else console.log(ge.yellow("Target table has no columns."))}else console.log(ge.yellow("No other tables found to link to."))}}let m=!1;if(i||(m=await Nt({message:`Can '${o}' be NULL?`,default:!0})),!i&&!l&&e!=="DateTime")if(e==="Boolean")c=await ne({message:`Default value for '${o}':`,choices:[{name:"None",value:""},{name:"TRUE",value:"TRUE"},{name:"FALSE",value:"FALSE"}]});else if(e==="Enum"&&n)c=await ne({message:`Default value for '${o}':`,choices:[{name:"None",value:""},...n.map(d=>({name:d,value:`'${d}'`}))]});else{let u=await ke({message:`Default value for '${o}' (leave empty for none):`});u&&(e==="Text"?c=`'${u.replace(/'/g,"''")}'`:c=u)}return{col:{name:o,type:e,isPk:i,nullable:m,defaultValue:c,fkTarget:l,enumValues:n},isPk:i}}var Pe=E(()=>{"use strict"});import{input as Ha,confirm as It}from"@inquirer/prompts";import g from"picocolors";async function Pt(s){let a=h(s),t="";for(;!t;)t=await Ha({message:"Enter the new table name:"}),/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t)||(console.log(g.red("Invalid table name. Use only letters, numbers, and underscores.")),t="");let r=[],o=!1,e=!0;for(;e;){kt(t,r);let l=r.map(u=>u.name),{col:m,isPk:p}=await fe(a,o,l);if(!m)break;p&&(o=!0),r.push(m),e=await It({theme:{prefix:g.cyan(`
|
|
132
|
+
\u2713 `),style:{message:u=>g.bold(g.white(u)),highlight:u=>{let d=u.replace(/\x1b\[[0-9;]*m/g,"");return g.cyan(d)}}},message:"Add another column?",default:!0})}kt(t,r),console.log(g.dim("Generating SQL..."));let c=j(s.type).buildCreateTable(t,r);if(console.log(g.cyan(`
|
|
97
133
|
--- SQL Preview ---`)),console.log(g.yellow(c)),console.log(g.cyan(`-------------------
|
|
98
|
-
`)),await
|
|
99
|
-
\u2713 Table '${
|
|
100
|
-
x Error creating table: ${l.message}`))}finally{await
|
|
101
|
-
`);let
|
|
102
|
-
`))}var Bt=E(()=>{"use strict";
|
|
103
|
-
Initiating SQL table writer for experts. Please ensure database connection is properly configured.`)),
|
|
104
|
-
No database connection found. Please setup first.`));return}try{let
|
|
105
|
-
x Failed to read file: ${e.message}`));return}let o=r;if(
|
|
134
|
+
`)),await It({message:"Do you want to execute this SQL to build the table?",default:!0}))try{console.log(g.dim("Executing SQL...")),await a.executeSql(c),console.log(g.green(`
|
|
135
|
+
\u2713 Table '${t}' created successfully!`))}catch(l){console.log(g.red(`
|
|
136
|
+
x Error creating table: ${l.message}`))}finally{await a.close()}else console.log(g.yellow("Aborted table creation.")),await a.close();await Ya()}async function Ya(){let{input:s}=await import("@inquirer/prompts");await s({message:"Press Enter to continue..."})}function kt(s,a){console.clear(),console.log(`
|
|
137
|
+
`);let t={name:20,type:18,key:8,nullable:10,defaultCol:16},r=t.name+t.type+t.key+t.nullable+t.defaultCol+14;console.log(g.cyan(`\u2554${"\u2550".repeat(r)}\u2557`));let o=r-s.length,e=Math.max(0,Math.floor(o/2)),n=Math.max(0,o-e),c=" ".repeat(e)+g.bold(g.white(s))+" ".repeat(n);console.log(g.cyan("\u2551")+c+g.cyan("\u2551"));let i=(l,m,p)=>g.cyan(l+"\u2550".repeat(t.name+2)+m+"\u2550".repeat(t.type+2)+m+"\u2550".repeat(t.key+2)+m+"\u2550".repeat(t.nullable+2)+m+"\u2550".repeat(t.defaultCol+2)+p);console.log(i("\u2560","\u2566","\u2563")),console.log(g.cyan("\u2551 ")+g.bold(g.white("Column Name".padEnd(t.name)))+g.cyan(" \u2551 ")+g.bold(g.white("Type".padEnd(t.type)))+g.cyan(" \u2551 ")+g.bold(g.white("Key".padEnd(t.key)))+g.cyan(" \u2551 ")+g.bold(g.white("Nullable".padEnd(t.nullable)))+g.cyan(" \u2551 ")+g.bold(g.white("Default".padEnd(t.defaultCol)))+g.cyan(" \u2551")),a.length>0&&console.log(i("\u2560","\u256C","\u2563"));for(let l=0;l<a.length;l++){let m=a[l],p=g.white(m.name.padEnd(t.name)),u=g.white(m.type.padEnd(t.type)),d=m.isPk?"PK":"-",f=m.isPk?g.green(d.padEnd(t.key)):g.dim(d.padEnd(t.key)),y=m.nullable?"Yes":"No",b=m.nullable?g.green(y.padEnd(t.nullable)):g.dim(y.padEnd(t.nullable)),x=m.defaultValue||"-",k=m.defaultValue?g.yellow(x.padEnd(t.defaultCol)):g.dim(x.padEnd(t.defaultCol));console.log(g.cyan("\u2551 ")+p+g.cyan(" \u2551 ")+u+g.cyan(" \u2551 ")+f+g.cyan(" \u2551 ")+b+g.cyan(" \u2551 ")+k+g.cyan(" \u2551"))}if(a.length===0){console.log(i("\u2560","\u2569","\u2563"));let l="No columns added yet",m=Math.max(0,Math.floor((r-l.length)/2)),p=Math.max(0,r-l.length-m);console.log(g.cyan("\u2551")+" ".repeat(m)+g.dim(l)+" ".repeat(p)+g.cyan("\u2551")),console.log(g.cyan(`\u255A${"\u2550".repeat(r)}\u255D`))}else console.log(i("\u255A","\u2569","\u255D"));console.log(g.dim(` Leave empty the Column Name to cancel.
|
|
138
|
+
`))}var Bt=E(()=>{"use strict";Ae();A();Pe()});import Ga from"fs/promises";import za from"path";import{input as Ja}from"@inquirer/prompts";import K from"picocolors";async function Mt(s){if(console.log(K.green(`
|
|
139
|
+
Initiating SQL table writer for experts. Please ensure database connection is properly configured.`)),s.type==="unknown"){console.log(K.yellow(`
|
|
140
|
+
No database connection found. Please setup first.`));return}try{let a=await Ja({message:"Enter the path to your .md or .sql file:"});if(a&&a.trim()){let t=za.resolve(process.cwd(),a.trim()),r="";try{r=await Ga.readFile(t,"utf-8")}catch(e){console.log(K.red(`
|
|
141
|
+
x Failed to read file: ${e.message}`));return}let o=r;if(t.toLowerCase().endsWith(".md")){let e=[...r.matchAll(/```(?:sql)?\n([\s\S]*?)```/gi)];e.length>0&&(o=e.map(n=>n[1].trim()).join(`
|
|
106
142
|
|
|
107
|
-
`))}if(o.trim()){console.log(K.dim("Executing SQL..."));let e=h(
|
|
143
|
+
`))}if(o.trim()){console.log(K.dim("Executing SQL..."));let e=h(s);try{await e.executeSql(o),console.log(K.green(`
|
|
108
144
|
\u2713 SQL executed successfully!`))}finally{await e.close()}}else console.log(K.yellow(`
|
|
109
145
|
\u26A0\uFE0F No SQL found in the file. Aborted.`))}else console.log(K.yellow(`
|
|
110
|
-
No file path entered. Aborted.`))}catch(
|
|
111
|
-
Error executing SQL: ${
|
|
112
|
-
`)[1].trim().replace(/,$/,""),p=`ALTER TABLE ${e} ADD COLUMN ${m}`;
|
|
113
|
-
`)[1].trim().replace(/,$/,""),u="";
|
|
114
|
-
No database connection found. Please setup first.`)),await Be();return}let
|
|
115
|
-
`)&&(
|
|
116
|
-
`),
|
|
117
|
-
`),await re.writeFile(t,
|
|
118
|
-
--- Add Data to [${
|
|
119
|
-
Executing: `)+w.yellow(c));try{await
|
|
120
|
-
--- Edit Data in [${
|
|
121
|
-
Executing: `)+w.yellow(p));try{await
|
|
122
|
-
--- Delete Data from [${
|
|
123
|
-
Executing: `)+w.yellow(i));try{await
|
|
124
|
-
--- Expert Mode: Execute Raw SQL ---`));try{let
|
|
125
|
-
x Failed to read file: ${e.message}`));return}let o=r;if(
|
|
146
|
+
No file path entered. Aborted.`))}catch(a){console.log(K.red(`
|
|
147
|
+
Error executing SQL: ${a.message}`))}}var _t=E(()=>{"use strict";A()});import{select as ye,confirm as Ot,input as Xa}from"@inquirer/prompts";import C from"picocolors";async function Ft(s){let a=h(s);try{let t=await a.getTables();if(t.length===0){console.log(C.yellow("No tables found in the database."));return}let r=await ye({message:"Select a table to drop:",choices:t.map(e=>({name:e,value:e}))});if(await Ot({message:`Are you sure you want to DROP TABLE '${r}'? This will delete all its data!`,default:!1})){let e=`DROP TABLE ${r}`;s.type==="sqlite"||s.type==="postgres"?e=`DROP TABLE "${r}"`:s.type==="mysql"&&(e=`DROP TABLE \`${r}\``),await a.executeSql(e),console.log(C.green(`\u2713 Table '${r}' dropped successfully.`))}}catch(t){console.log(C.red(`Error: ${t.message}`))}finally{await a.close()}}async function he(s,a){let t=h(s),r=j(s.type);try{let o=await t.getTables();if(o.length===0){console.log(C.yellow("No tables found in the database."));return}let e=await ye({message:"Select a table to modify:",choices:o.map(c=>({name:c,value:c}))}),n=await t.getSchema(e);if(a==="add"){let c=n.some(m=>m.isPk),i=n.map(m=>m.name),{col:l}=await fe(t,c,i);if(l){let m=r.buildCreateTable("tmp",[l]).split(`
|
|
148
|
+
`)[1].trim().replace(/,$/,""),p=`ALTER TABLE ${e} ADD COLUMN ${m}`;s.type==="sqlite"||s.type==="postgres"?p=`ALTER TABLE "${e}" ADD COLUMN ${m}`:s.type==="mysql"&&(p=`ALTER TABLE \`${e}\` ADD COLUMN ${m}`),await t.executeSql(p),console.log(C.green(`\u2713 Column '${l.name}' added successfully.`))}}else if(a==="rename"){if(n.length===0)return console.log(C.yellow("Table has no columns."));let c=await ye({message:"Select a column to rename:",choices:n.map(l=>({name:`${l.name} (${l.type})`,value:l.name}))}),i=await Xa({message:`New name for '${c}':`});if(i&&i!==c){let l=`ALTER TABLE ${e} RENAME COLUMN ${c} TO ${i}`;s.type==="sqlite"||s.type==="postgres"?l=`ALTER TABLE "${e}" RENAME COLUMN "${c}" TO "${i}"`:s.type==="mysql"&&(l=`ALTER TABLE \`${e}\` RENAME COLUMN \`${c}\` TO \`${i}\``),await t.executeSql(l),console.log(C.green(`\u2713 Column renamed to '${i}' successfully.`))}}else if(a==="modify"){if(n.length===0)return console.log(C.yellow("Table has no columns."));if(s.type==="sqlite"){console.log(C.yellow("SQLite does not support altering column types directly. Please recreate the table."));return}let c=await ye({message:"Select a column to modify:",choices:n.map(p=>({name:`${p.name} (${p.type})`,value:p.name}))}),i=n.some(p=>p.isPk&&p.name!==c),l=n.map(p=>p.name).filter(p=>p!==c),{col:m}=await fe(t,i,l,c);if(m){let p=r.buildCreateTable("tmp",[m]).split(`
|
|
149
|
+
`)[1].trim().replace(/,$/,""),u="";s.type==="postgres"?(console.log(C.yellow("Note: Complex constraint modifications might require raw SQL in Postgres.")),u=`ALTER TABLE "${e}" ALTER COLUMN ${p.replace(m.name,`"${m.name}" TYPE`)}`):s.type==="mysql"&&(u=`ALTER TABLE \`${e}\` MODIFY COLUMN ${p}`);try{await t.executeSql(u),console.log(C.green(`\u2713 Column '${c}' modified successfully.`))}catch(d){console.log(C.red("x Could not modify column automatically. Try using Raw SQL.")),console.log(C.dim(d.message))}}}else if(a==="delete"){if(n.length===0)return console.log(C.yellow("Table has no columns."));let c=await ye({message:"Select a column to delete:",choices:n.map(l=>({name:`${l.name} (${l.type})`,value:l.name}))});if(await Ot({message:`Are you sure you want to delete column '${c}'? Data will be lost!`,default:!1})){let l=`ALTER TABLE ${e} DROP COLUMN ${c}`;s.type==="sqlite"||s.type==="postgres"?l=`ALTER TABLE "${e}" DROP COLUMN "${c}"`:s.type==="mysql"&&(l=`ALTER TABLE \`${e}\` DROP COLUMN \`${c}\``);try{await t.executeSql(l),console.log(C.green(`\u2713 Column '${c}' deleted successfully.`))}catch(m){console.log(C.red(`x Error deleting column: ${m.message}`))}}}}catch(o){console.log(C.red(`Error: ${o.message}`))}finally{await t.close()}}var Ut=E(()=>{"use strict";A();Ae();Pe()});var jt={};L(jt,{runTableManagerFlow:()=>eo});import W from"picocolors";import{select as Wt,Separator as Za}from"@inquirer/prompts";async function eo(s){if(s.type==="unknown"){console.log(W.yellow(`
|
|
150
|
+
No database connection found. Please setup first.`)),await Be();return}let a=await Promise.resolve().then(()=>(A(),Ve)).then(r=>r.createDBAdapter(s)),t=!0;for(;t;){console.clear();let r="Scanning...";try{r=`${(await a.getTables()).length} tables detected`}catch(n){r=W.red(n.message)}let o=s.targetUrl;switch(se(` Table Builder & Manager \u2022 [${s.type.toUpperCase()}]`,[{label:"Database",value:s.type.toUpperCase()},{label:"Target",value:o.length>45?"..."+o.slice(-42):o},{label:"Tables",value:r}]),await Rt()){case"create":let n=await Wt({message:"How do you want to create the table?",theme:{prefix:W.cyan("\u2713 "),icon:{cursor:W.cyan("\u203A ")},style:{message:c=>W.bold(W.white(c)),highlight:c=>{let i=c.replace(/\x1b\[[0-9;]*m/g,"");return i.includes("Cancel")?W.red(i):W.cyan(i)}}},choices:[{name:" Interactive Wizard (Beginner Friendly)",value:"wizard",description:"Follow the step-by-step guide to build your table."},{name:" Raw SQL (Experts)",value:"sql",description:"Write / Import your own CREATE TABLE statement."},new Za,{name:W.dim(" Cancel"),value:"cancel",description:"Back to Table Manager"}]});n==="wizard"?await Pt(s):n==="sql"&&await Mt(s);break;case"modify":await to(s);break;case"drop":await Ft(s),await Be();break;case"back":t=!1;break}}await a.close()}async function to(s){let a=await Wt({message:"Modify Table Actions:",choices:[{name:"Add Column",value:"add_col"},{name:"Rename Column",value:"rename_col"},{name:"Modify Column Settings (MySQL/Postgres)",value:"mod_col",disabled:s.type==="sqlite"},{name:"Delete Column",value:"del_col"},{name:" Back",value:"back"}]});if(a!=="back"){switch(a){case"add_col":await he(s,"add");break;case"rename_col":await he(s,"rename");break;case"mod_col":await he(s,"modify");break;case"del_col":await he(s,"delete");break}await Be()}}async function Be(){let{input:s}=await import("@inquirer/prompts");await s({message:"Press Enter to continue..."})}var Qt=E(()=>{"use strict";Lt();Bt();_t();Ut();Se()});Se();import D from"picocolors";import re from"fs/promises";import X from"path";async function q(s){let a=process.cwd();if(s){let e="sqlite";return s.startsWith("postgres://")||s.startsWith("postgresql://")?e="postgres":s.startsWith("mysql://")?e="mysql":e="sqlite",{type:e,targetUrl:s.replace("file:",""),source:"manual"}}let t=[".","prisma","db","database","src/db","src/database"];for(let e of t)try{let n=X.join(a,e),i=(await re.readdir(n)).find(l=>l.endsWith(".db")||l.endsWith(".sqlite")||l.endsWith(".sqlite3"));if(i)return{type:"sqlite",targetUrl:X.join(n,i),source:"auto-detected"}}catch{}let r=X.join(a,"prisma","schema.prisma");try{let e=await re.readFile(r,"utf-8"),n=e.match(/provider\s*=\s*["']([^"']+)["']/),c=e.match(/url\s*=\s*(?:env\(["']([^"']+)["']\)|["']([^"']+)["'])/);if(n){let i=n[1];i==="postgresql"&&(i="postgres");let l="";if(c&&c[2]&&(l=c[2],l.startsWith("file:")&&(l=X.join(a,"prisma",l.replace("file:","")))),l&&(i==="sqlite"||i==="postgres"||i==="mysql"))return{type:i,targetUrl:l,source:".env"}}}catch{}let o=X.join(a,".env");try{let e=await re.readFile(o,"utf-8"),n=["DATABASE_URL","DB_URL","POSTGRES_URL","POSTGRES_PRISMA_URL","MYSQL_URL"];for(let c of n){let i=new RegExp(`${c}\\s*=\\s*["']?([^"'\\r\\n]+)["']?`),l=e.match(i);if(l){let m=l[1];if(m.startsWith("file:")||m.endsWith(".db")||m.includes(".sqlite"))return{type:"sqlite",targetUrl:m.replace("file:",""),source:".env"};if(m.startsWith("postgres://")||m.startsWith("postgresql://"))return{type:"postgres",targetUrl:m,source:".env"};if(m.startsWith("mysql://"))return{type:"mysql",targetUrl:m,source:".env"}}}}catch{}return{type:"unknown",targetUrl:"",source:"manual"}}async function Ue(s){let a=X.join(process.cwd(),".env"),t="";try{t=await re.readFile(a,"utf-8")}catch{}let r=/DATABASE_URL\s*=\s*["']?([^"'\r\n]+)["']?/;r.test(t)?t=t.replace(r,`DATABASE_URL="${s}"`):(t&&!t.endsWith(`
|
|
151
|
+
`)&&(t+=`
|
|
152
|
+
`),t+=`DATABASE_URL="${s}"
|
|
153
|
+
`),await re.writeFile(a,t,"utf-8")}A();import{select as Je,Separator as le}from"@inquirer/prompts";import T from"picocolors";import{select as ra}from"@inquirer/prompts";import Z from"picocolors";var Ke=async s=>await ra({message:"Select a table to edit data:",theme:{prefix:Z.cyan("\u2713 "),icon:{cursor:Z.cyan("\u203A ")},style:{message:a=>Z.bold(Z.white(a)),highlight:a=>{let t=a.replace(/\x1b\[[0-9;]*m/g,"");return t.includes(" Back")?Z.red(t):Z.cyan(t)}}},choices:s});Ae();import{input as ie,select as ia}from"@inquirer/prompts";import w from"picocolors";import la from"fs/promises";import ca from"path";async function He(s,a,t,r){let o=j(a);console.log(w.cyan(`
|
|
154
|
+
--- Add Data to [${t}] ---`)),console.log(w.dim("Leave a field completely empty (press Enter) to skip it (e.g. for AutoInc or NULL)"));let e=[],n=[];for(let i of r){if(i.isPk&&(i.type.toLowerCase().includes("int")||i.type.toLowerCase()==="integer")){console.log(w.dim(`Skipping '${i.name}' (Auto Increment Primary Key)`));continue}let l=await ie({message:`Value for '${i.name}' (${i.type}):`});l.trim()!==""&&(e.push(o.quoteIdentifier(i.name)),n.push(`'${o.escapeString(l)}'`))}if(e.length===0){console.log(w.yellow("No data entered. Aborted."));return}let c=`INSERT INTO ${o.quoteIdentifier(t)} (${e.join(", ")}) VALUES (${n.join(", ")});`;console.log(w.dim(`
|
|
155
|
+
Executing: `)+w.yellow(c));try{await s.executeSql(c),console.log(w.green("\u2713 Data added successfully!"))}catch(i){console.log(w.red(`x Failed to add data: ${i.message}`))}}async function Ye(s,a,t,r){let o=j(a);if(console.log(w.cyan(`
|
|
156
|
+
--- Edit Data in [${t}] ---`)),r.length===0)return;let n=(r.find(u=>u.isPk)||r[0]).name,c=await ie({message:`Enter the '${n}' of the record you want to edit:`});if(!c.trim()){console.log(w.yellow("Aborted."));return}let i=await ia({message:"Which column do you want to update?",choices:r.map(u=>({name:u.name,value:u.name}))}),l=await ie({message:`New value for '${i}' (leave empty for NULL):`}),m="NULL";l.trim()!==""&&(m=`'${o.escapeString(l)}'`);let p=`UPDATE ${o.quoteIdentifier(t)} SET ${o.quoteIdentifier(i)} = ${m} WHERE ${o.quoteIdentifier(n)} = '${o.escapeString(c)}';`;console.log(w.dim(`
|
|
157
|
+
Executing: `)+w.yellow(p));try{await s.executeSql(p),console.log(w.green("\u2713 Data updated successfully!"))}catch(u){console.log(w.red(`x Failed to update data: ${u.message}`))}}async function Ge(s,a,t,r){let o=j(a);if(console.log(w.cyan(`
|
|
158
|
+
--- Delete Data from [${t}] ---`)),r.length===0)return;let n=(r.find(l=>l.isPk)||r[0]).name,c=await ie({message:`Enter the '${n}' of the record you want to delete:`});if(!c.trim()){console.log(w.yellow("Aborted."));return}let i=`DELETE FROM ${o.quoteIdentifier(t)} WHERE ${o.quoteIdentifier(n)} = '${o.escapeString(c)}';`;console.log(w.dim(`
|
|
159
|
+
Executing: `)+w.yellow(i));try{await s.executeSql(i),console.log(w.green("\u2713 Data deleted successfully!"))}catch(l){console.log(w.red(`x Failed to delete data: ${l.message}`))}}async function ze(s){console.log(w.cyan(`
|
|
160
|
+
--- Expert Mode: Execute Raw SQL ---`));try{let a=await ie({message:"Enter the path to your .md or .sql file:"});if(a&&a.trim()){let t=ca.resolve(process.cwd(),a.trim()),r="";try{r=await la.readFile(t,"utf-8")}catch(e){console.log(w.red(`
|
|
161
|
+
x Failed to read file: ${e.message}`));return}let o=r;if(t.toLowerCase().endsWith(".md")){let e=[...r.matchAll(/```(?:sql)?\n([\s\S]*?)```/gi)];e.length>0&&(o=e.map(n=>n[1].trim()).join(`
|
|
126
162
|
|
|
127
163
|
`))}if(o.trim()){console.log(w.dim(`
|
|
128
|
-
Executing SQL...`)),console.log(w.yellow(o));try{await
|
|
164
|
+
Executing SQL...`)),console.log(w.yellow(o));try{await s.executeSql(o),console.log(w.green(`
|
|
129
165
|
\u2713 SQL executed successfully!`))}catch(e){console.log(w.red(`
|
|
130
166
|
x Error executing SQL: ${e.message}`))}}else console.log(w.yellow(`
|
|
131
167
|
\u26A0\uFE0F No SQL found in the file. Aborted.`))}else console.log(w.yellow(`
|
|
132
|
-
No file path entered. Aborted.`))}catch(
|
|
133
|
-
Error: ${
|
|
134
|
-
Error fetching data: ${
|
|
135
|
-
`)),u="";let{input:R}=await import("@inquirer/prompts");await R({message:"Click Enter to continue..."});continue}let
|
|
136
|
-
Exporting data...`));let R=await
|
|
137
|
-
`,
|
|
138
|
-
`),Ee=be.join(
|
|
139
|
-
Exported to ${Ee}`))}else{let F=be.join(
|
|
168
|
+
No file path entered. Aborted.`))}catch(a){console.log(w.red(`
|
|
169
|
+
Error: ${a.message}`))}}Ce();Se();async function Xe(s){let a=h(s),t=!0;for(;t;){console.clear();let r=[],o=0,e="Scanning...";try{r=await a.getTables();for(let i of r)try{let l=s.type==="mysql"?"`":'"',m=await a.query(`SELECT COUNT(*) as count FROM ${l}${i}${l}`);m.rows.length>0&&m.rows[0].count!=null&&(o+=Number(m.rows[0].count))}catch{}e=`${o.toLocaleString()} rows across ${r.length} tables`}catch(i){e=T.red(i.message)}let n=s.targetUrl,c=s.source===".env"?"Loaded from project .env file":s.source==="auto-detected"?"Auto-detected local SQLite file":"Manual connection config";se(` Data Browser & Editor \u2022 [${s.type.toUpperCase()}]`,[{label:"Database",value:s.type.toUpperCase()},{label:"Target",value:n.length>45?"..."+n.slice(-42):n},{label:"Source",value:c},{label:"Total Data",value:e}]);try{if(r.length===0){console.log(T.yellow("No tables found in this database.")),await te(),await a.close();return}let i=[...r.map(f=>({name:f,value:f})),new le,{name:T.dim(" Back"),value:"BACK"}],l=await Ke(i);if(l==="BACK"){t=!1;continue}let m=!0,p=1,u="",d=50;for(;m;){console.clear();let f=(p-1)*d,y=await a.getSchema(l),b=y.map(P=>P.name),x;try{x=await a.getData(l,d,f,u)}catch(P){console.log(T.red(`
|
|
170
|
+
Error fetching data: ${P.message}
|
|
171
|
+
`)),u="";let{input:R}=await import("@inquirer/prompts");await R({message:"Click Enter to continue..."});continue}let k=x.rows,Kt=` ${l} (Page ${p}) `;ee(b,k,{title:Kt,maxColWidth:30});let Ht=k.length===d,Yt=p>1,we=[{name:"Add Data",value:"add"},{name:"Edit Data",value:"edit"},{name:"Delete Data",value:"delete"},new le,{name:"Search Data",value:"search"},{name:u?"Clear Search":T.dim("Clear Search (disabled)"),value:u?"clear_search":"noop"},new le,{name:"Export to CSV",value:"exportCsv"},{name:"Export to JSON",value:"exportJson"},new le];Yt&&we.push({name:"Previous Page",value:"prev"}),Ht&&we.push({name:"Next Page",value:"next"}),we.push({name:T.dim(" Back"),value:"BACK"});let v=await Je({message:"Select an action for this table:",theme:{prefix:T.cyan("\u2713 "),icon:{cursor:T.cyan("\u203A ")},style:{message:P=>T.bold(T.white(P)),highlight:P=>{let R=P.replace(/\x1b\[[0-9;]*m/g,"");return R.includes(" Back")?T.red(R):T.cyan(R)}}},choices:we});if(v==="prev"){p--;continue}if(v==="next"){p++;continue}if(v==="noop")continue;if(v==="BACK"){m=!1;continue}if(v==="clear_search"){u="",p=1;continue}if(v==="search"){let{input:P}=await import("@inquirer/prompts"),O=(await P({message:"Enter Search (e.g. `age > 18` or `John` for fuzzy search):"})).trim();if(O){if(/[=<>]|LIKE|IN|AND|OR/i.test(O))u=O;else{let z=y.filter(F=>F.type.toLowerCase().includes("char")||F.type.toLowerCase().includes("text"));if(z.length>0){let F=s.type==="postgres"?"ILIKE":"LIKE";u=z.map(Ee=>`"${Ee.name}" ${F} '%${O.replace(/'/g,"''")}%'`).join(" OR ")}else u=`"${y[0].name}" = '${O}'`}p=1}continue}if(v==="exportCsv"||v==="exportJson"){try{console.log(T.yellow(`
|
|
172
|
+
Exporting data...`));let R=await a.getData(l,9999999,0,u),O=await import("fs/promises"),be=await import("path"),z=be.join(process.cwd(),"drixio_exports");if(await O.mkdir(z,{recursive:!0}),v==="exportCsv"){let F=R.columns.join(",")+`
|
|
173
|
+
`,_e=R.rows.map(Gt=>R.columns.map(zt=>`"${String(Gt[zt]??"").replace(/"/g,'""')}"`).join(",")).join(`
|
|
174
|
+
`),Ee=be.join(z,`${l}.csv`);await O.writeFile(Ee,F+_e,"utf-8"),console.log(T.green(`
|
|
175
|
+
Exported to ${Ee}`))}else{let F=be.join(z,`${l}.json`);await O.writeFile(F,JSON.stringify(R.rows,null,2),"utf-8"),console.log(T.green(`
|
|
140
176
|
Exported to ${F}`))}}catch(R){console.log(T.red(`
|
|
141
|
-
Export Error: ${R.message}`))}let{input:
|
|
142
|
-
x Error: ${i.message}`)),await te(),
|
|
177
|
+
Export Error: ${R.message}`))}let{input:P}=await import("@inquirer/prompts");await P({message:"Click Enter to continue..."});continue}let Me=await Je({message:`Select mode for ${v} data:`,choices:[{name:"Beginner (Interactive Step-by-Step)",value:"beginner"},{name:"Expert (Load SQL from .sql or .md file)",value:"expert"},new le,{name:T.dim("Cancel"),value:"cancel"}]});if(Me!=="cancel"){if(Me==="expert"){await ze(a),await te();continue}v==="add"?(await He(a,s.type,l,y),await te()):v==="edit"?(await Ye(a,s.type,l,y),await te()):v==="delete"&&(await Ge(a,s.type,l,y),await te())}}}catch(i){console.log(T.red(`
|
|
178
|
+
x Error: ${i.message}`)),await te(),t=!1}}await a.close()}async function te(){let{input:s}=await import("@inquirer/prompts");await s({message:"Press Enter to continue..."})}import{select as ma,input as ua}from"@inquirer/prompts";import ae from"picocolors";A();async function Ze(s){let a=await ma({message:"What method you want to use to setup database connection?",choices:[{name:" Auto-Config",value:"auto",description:"Automatically detect and setup database connection (May fail for some cases)."},{name:" Manual Config",value:"manual",description:"Manually setup database connection by entering parameters step by step."}]}),t=s;switch(a){case"auto":let r=await q();r.type!=="unknown"?(t=r,console.log(ae.green(`
|
|
143
179
|
Database connection setup successfully.`))):console.log(ae.red(`
|
|
144
|
-
Failed to auto-detect database connection. Please try manual configuration.`));break;case"manual":let o=await ua({message:"Enter the database connection URL: "});if(o){let e=await
|
|
145
|
-
Testing connection...`));try{let
|
|
146
|
-
x Connection failed: ${
|
|
180
|
+
Failed to auto-detect database connection. Please try manual configuration.`));break;case"manual":let o=await ua({message:"Enter the database connection URL: "});if(o){let e=await q(o);console.log(ae.dim(`
|
|
181
|
+
Testing connection...`));try{let n=h(e);await n.getTables(),await n.close(),t=e,await Ue(o),console.log(ae.green("\u2713 Database connection setup successfully and saved to .env!"))}catch(n){console.log(ae.red(`
|
|
182
|
+
x Connection failed: ${n.message}
|
|
147
183
|
Please enter a valid database URL or check your database status.`))}}else console.log(ae.red(`
|
|
148
|
-
Failed to detect database connection. Please enter valid database URL.`));break}return
|
|
184
|
+
Failed to detect database connection. Please enter valid database URL.`));break}return t}import{select as pa,Separator as da}from"@inquirer/prompts";import H from"picocolors";var et=async s=>await pa({message:"Select an action:",theme:{prefix:H.cyan("\u2713 "),icon:{cursor:H.cyan("\u203A ")},style:{message:a=>H.bold(H.white(a)),highlight:a=>{let t=a.replace(/\x1b\[[0-9;]*m/g,"");return t.includes("Exit")?H.red(t):H.cyan(t)}}},choices:[{name:" Data Browser & Editor",value:"editor",description:"View, insert, update, and delete row data in your tables.",disabled:s.type==="unknown"},{name:" Run Raw SQL (REPL)",value:"repl",description:"Execute arbitrary SQL queries interactively.",disabled:s.type==="unknown"},{name:" Table Builder & Manager",value:"table",description:"Create new tables, or modify/drop existing tables.",disabled:s.type==="unknown"},new da,{name:s.type==="unknown"?" Setup Connection":" Connection Settings",value:s.type==="unknown"?"setup":"re-configure",description:s.type==="unknown"?"Setup the database connection manually.":"Re-configure the database connection."},{name:H.dim(" Exit"),value:"exit",description:"Exit the Drixio CLI application."}]});A();Ce();import B from"picocolors";async function tt(s){if(s.type==="unknown")return;let a=h(s),t=!0,{input:r}=await import("@inquirer/prompts");for(console.clear(),console.log(B.cyan(`
|
|
149
185
|
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557`)),console.log(B.cyan("\u2551 Interactive SQL REPL \u2551")),console.log(B.cyan("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563")),console.log(B.cyan("\u2551 ")+B.dim("Type your SQL queries directly. Type 'exit' or 'quit' to Back.")+" "+B.cyan("\u2551")),console.log(B.cyan(`\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
150
|
-
`));
|
|
151
|
-
(${
|
|
186
|
+
`));t;)try{let e=(await r({message:B.green(`${s.type}>`)})).trim();if(e.toLowerCase()==="exit"||e.toLowerCase()==="quit"){t=!1;continue}if(e==="")continue;let n=await a.query(e);if(n.columns.length===0){console.log(B.yellow("Query executed successfully. (No output)"));continue}ee(n.columns,n.rows,{title:"Query Result",maxColWidth:50}),console.log(B.dim(`
|
|
187
|
+
(${n.rows.length} rows)`)),console.log()}catch(o){o.name==="ExitPromptError"?t=!1:console.log(B.red(`
|
|
152
188
|
Error: ${o.message}
|
|
153
|
-
`))}}import{parseArgs as
|
|
189
|
+
`))}}import{parseArgs as ao}from"util";async function Vt(){let s=process.argv.slice(2),a;s.length>0&&(s[0].startsWith("postgres://")||s[0].startsWith("postgresql://")||s[0].startsWith("mysql://")||s[0].startsWith("file:"))&&(a=s[0]);let{positionals:t,values:r}=ao({args:s,options:{format:{type:"string"},"schema-only":{type:"boolean"},table:{type:"string"},help:{type:"boolean"}},strict:!1,allowPositionals:!0});r.help&&(console.log(D.cyan(`
|
|
154
190
|
Drixio CLI - Modern Database Manager
|
|
155
191
|
`)),console.log(`${D.bold("Usage:")} npx drixio [command] [options]
|
|
156
192
|
`),console.log(`${D.bold("Commands:")}`),console.log(` ${D.green("query")} "<sql>" Run a quick SQL query`),console.log(` ${D.green("exec")} <file.sql> Execute a SQL script file`),console.log(` ${D.green("export")} [table] Export table(s) to CSV/JSON`),console.log(` ${D.green("import")} [file] Import JSON/CSV into a table`),console.log(` ${D.green("seed")} [table] [count] Generate fake data for a table`),console.log(` ${D.green("diagram")} Generate a Mermaid ER diagram`),console.log(` ${D.green("generate-types")} Generate TypeScript interfaces`),console.log(` ${D.green("backup")} Backup the entire database`),console.log(` ${D.green("studio")} Launch the Web UI Studio`),console.log(` ${D.green("init")} [db_type] Initialize a local database & .env`),console.log(` ${D.green("drop-db")} [db_type] Drop a local database`),console.log(`
|
|
157
193
|
${D.bold("Options:")}`),console.log(" --help Show this help message"),console.log(" --format <type> Specify export format (csv|json)"),console.log(" --schema-only Export schema without data"),console.log(" --table <name> Specify table for import"),console.log(`
|
|
158
|
-
If you don't provide a command, Drixio will launch the Interactive UI!`),process.exit(0));let o=
|
|
159
|
-
No database connection found. Please run ${D.bold("drixio check")} first.`)),await c()):await
|
|
160
|
-
Thanks for using Drixio. Goodbye!`));break}async function c(){let{input:i}=await import("@inquirer/prompts");await i({message:"Click Enter to continue..."})}}
|
|
194
|
+
If you don't provide a command, Drixio will launch the Interactive UI!`),process.exit(0));let o=a?void 0:t[0];if(o==="query"){let{runQueryCommand:i}=await Promise.resolve().then(()=>(ot(),at)),l=await q();await i(l,t.slice(1));return}if(o==="export"){let{runExportCommand:i}=await Promise.resolve().then(()=>(st(),nt)),l=await q();await i(l,t.slice(1),r);return}if(o==="studio"){let{runStudio:i}=await Promise.resolve().then(()=>(mt(),ct)),l=await q();await i(l);return}if(o==="backup"){let{runBackupCommand:i}=await Promise.resolve().then(()=>(pt(),ut)),l=await q();await i(l);return}if(o==="import"){let{runImportCommand:i}=await Promise.resolve().then(()=>(ft(),gt)),l=await q();await i(l,t.slice(1),r);return}if(o==="seed"){let{runSeedCommand:i}=await Promise.resolve().then(()=>(ht(),yt)),l=await q();await i(l,t.slice(1));return}if(o==="diagram"){let{runDiagramCommand:i}=await Promise.resolve().then(()=>(bt(),wt)),l=await q();await i(l);return}if(o==="exec"){let{runExecCommand:i}=await Promise.resolve().then(()=>($t(),St)),l=await q();await i(l,t.slice(1));return}if(o==="generate-types"){let{runGenerateTypesCommand:i}=await Promise.resolve().then(()=>(Tt(),xt)),l=await q();await i(l);return}if(o==="init"){let{runInitCommand:i}=await Promise.resolve().then(()=>(Ct(),At));await i(t.slice(1));return}if(o==="drop-db"){let{runDropDbCommand:i}=await Promise.resolve().then(()=>(vt(),qt));await i(t.slice(1));return}let e=!0,n=await q(a);for(;e;)switch(console.clear(),Oe(),Fe(n),await et(n)){case"editor":n.type==="unknown"?(console.log(D.yellow(`
|
|
195
|
+
No database connection found. Please run ${D.bold("drixio check")} first.`)),await c()):await Xe(n);break;case"table":let{runTableManagerFlow:l}=await Promise.resolve().then(()=>(Qt(),jt));await l(n);break;case"repl":await tt(n);break;case"setup":case"re-configure":n=await Ze(n),await c();break;case"exit":e=!1,console.log(D.dim(`
|
|
196
|
+
Thanks for using Drixio. Goodbye!`));break}async function c(){let{input:i}=await import("@inquirer/prompts");await i({message:"Click Enter to continue..."})}}Vt().catch(s=>{s.name==="ExitPromptError"&&(console.log(`
|
|
161
197
|
Exit Drixio.`),process.exit(0)),console.error(`
|
|
162
|
-
Error: `,
|
|
198
|
+
Error: `,s),process.exit(1)});
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],enumerable:!0});return n||e(r,Symbol.toStringTag,{value:`Module`}),r};(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var n=`
|
|
2
|
+
<header>
|
|
3
|
+
<div id="current-path">
|
|
4
|
+
<span id="db-name">database</span>
|
|
5
|
+
<span id="slash">/</span>
|
|
6
|
+
<div id="current-table">
|
|
7
|
+
<span class="material-symbols-outlined" id="table-icon"> table </span>
|
|
8
|
+
<span id="table-name">users</span>
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
<div class="header-actions">
|
|
14
|
+
<button id="export-btn" class="secondary" title="Export Data / DDL" style="display: flex; align-items: center; gap: 6px; padding: 6px 12px; background: transparent; border: 1px solid var(--color-border); border-radius: 6px; cursor: pointer; color: var(--color-text-secondary); font-size: 13px; font-weight: 500;">
|
|
15
|
+
<span class="material-symbols-outlined" style="font-size: 18px;">download</span>
|
|
16
|
+
Export
|
|
17
|
+
</button>
|
|
18
|
+
</div>
|
|
19
|
+
</header>
|
|
20
|
+
`,r=`
|
|
21
|
+
<aside>
|
|
22
|
+
<div id="sidebar-header">
|
|
23
|
+
<span class="material-symbols-outlined" id="database-icon"> database </span>
|
|
24
|
+
<h1 id="brand-title">
|
|
25
|
+
DRIXIO
|
|
26
|
+
<p id="brand-subtitle">STUDIO</p>
|
|
27
|
+
</h1>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div id="sidebar-content">
|
|
31
|
+
<div id="search-bar">
|
|
32
|
+
<span class="material-symbols-outlined" id="search-icon"> search </span>
|
|
33
|
+
<input type="text" placeholder="Search" id="search-input" />
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<nav id="table-nav">
|
|
37
|
+
<!-- Display All Table -->
|
|
38
|
+
</nav>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div id="sidebar-footer">
|
|
42
|
+
<button id="theme-toggle" title="Toggle Dark Mode">
|
|
43
|
+
<span class="material-symbols-outlined" id="theme-icon">dark_mode</span>
|
|
44
|
+
Theme
|
|
45
|
+
</button>
|
|
46
|
+
</div>
|
|
47
|
+
</aside>
|
|
48
|
+
`,i=`
|
|
49
|
+
<nav id="tab-nav">
|
|
50
|
+
<button
|
|
51
|
+
type="button"
|
|
52
|
+
class="tab-btn"
|
|
53
|
+
onclick="handleSwitchTab('data-btn')"
|
|
54
|
+
id="data-btn"
|
|
55
|
+
>
|
|
56
|
+
<span class="material-symbols-outlined" id="data-icon"> table_rows </span>
|
|
57
|
+
Data
|
|
58
|
+
</button>
|
|
59
|
+
<button
|
|
60
|
+
class="tab-btn"
|
|
61
|
+
onclick="handleSwitchTab('schema-btn')"
|
|
62
|
+
id="schema-btn"
|
|
63
|
+
>
|
|
64
|
+
<span class="material-symbols-outlined" id="schema-icon">
|
|
65
|
+
grid_layout_side
|
|
66
|
+
</span>
|
|
67
|
+
Schema (Table)
|
|
68
|
+
</button>
|
|
69
|
+
|
|
70
|
+
<div style="flex: 1;"></div>
|
|
71
|
+
|
|
72
|
+
<button class="tab-btn" onclick="handleSwitchTab('status-btn')" id="status-btn">
|
|
73
|
+
<span class="material-symbols-outlined" id="status-icon"> database </span>
|
|
74
|
+
Database Status
|
|
75
|
+
</button>
|
|
76
|
+
<button class="tab-btn" onclick="handleSwitchTab('erd-btn')" id="erd-btn">
|
|
77
|
+
<span class="material-symbols-outlined" id="erd-icon"> schema </span>
|
|
78
|
+
ERD Visualization
|
|
79
|
+
</button>
|
|
80
|
+
<button class="tab-btn" onclick="handleSwitchTab('sql-btn')" id="sql-btn">
|
|
81
|
+
<span class="material-symbols-outlined" id="sql-icon"> code </span>
|
|
82
|
+
SQL Console
|
|
83
|
+
</button>
|
|
84
|
+
</nav>
|
|
85
|
+
`,a=t({executeRawQuery:()=>d,fetchTableIndexes:()=>u,fetchTableSchema:()=>l,fetchTableStats:()=>s,fetchTableWithName:()=>c,fetchTables:()=>o});async function o(){return await(await fetch(`/api/tables`)).json()}async function s(){return await(await fetch(`/api/tables/stats`)).json()}async function c(e,t={}){let{where:n=``,limit:r=50,offset:i=0,orderCol:a,orderAsc:o}=t,s=new URLSearchParams;n&&s.append(`where`,n),s.append(`limit`,r.toString()),s.append(`offset`,i.toString()),a&&(s.append(`orderCol`,a),s.append(`orderAsc`,o===!1?`false`:`true`));let c=`/api/tables/${e}/data?${s.toString()}`;return await(await fetch(c)).json()}async function l(e){return await(await fetch(`/api/tables/${e}/schema`)).json()}async function u(e){return await(await fetch(`/api/tables/${e}/indexes`)).json()}async function d(e){return await(await fetch(`/api/query`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sql:e})})).json()}async function f(){try{let e=await o(),t=document.getElementById(`table-nav`),n=document.getElementById(`not-found-msg`);n&&n.remove(),e.success&&e.data&&e.data.length>0?(e.data.forEach(e=>{let n=document.createElement(`button`);n.type=`button`,n.className=`table-btn`,n.innerHTML=`<span>${e}</span><span class="table-btn-badge" id="badge-${e}" style="display:none;"></span>`,n.onclick=()=>{window.AppState.currentTable=e,window.AppState.currentTableBtnElement=n,window.AppState.currentTab===`erd-btn`||window.AppState.currentTab===`sql-btn`||window.AppState.currentTab===`status-btn`?window.handleSwitchTab(`data-btn`):window.renderCurrentView()},t.appendChild(n)}),window.handleSwitchTab(`data-btn`),s().then(e=>{e.success&&e.data&&Object.entries(e.data).forEach(([e,t])=>{let n=document.getElementById(`badge-${e}`);n&&(n.textContent=Number(t).toLocaleString(),n.style.display=`inline-flex`)})}).catch(e=>console.error(`Failed to load table stats:`,e))):(t.innerHTML=`<div id="not-found-msg">No Tables Found.</div>`,window.handleSwitchTab(`data-btn`))}catch(e){console.error(`Failed to fetch tables:`,e)}}var p=t({bindCellSelection:()=>h,bindColumnResizer:()=>_,renderSelection:()=>m});function m(e,t){document.querySelectorAll(`#${e} .cell-in-range, #${e} .cell-selected, #${e} .range-top, #${e} .range-bottom, #${e} .range-left, #${e} .range-right, #${e} .row-header-selected`).forEach(e=>{e.classList.remove(`cell-in-range`,`cell-selected`,`range-top`,`range-bottom`,`range-left`,`range-right`,`row-header-selected`)});let n=t.selection;if(n.startRow===-1)return;let r=Math.min(n.startRow,n.endRow),i=Math.max(n.startRow,n.endRow),a=Math.min(n.startCol,n.endCol),o=Math.max(n.startCol,n.endCol);document.querySelectorAll(`#${e} td.data-cell`).forEach(e=>{let s=parseInt(e.dataset.rowIdx),c=parseInt(e.dataset.colIdx);s>=r&&s<=i&&c>=a&&c<=o&&(e.classList.add(`cell-in-range`),s===r&&e.classList.add(`range-top`),s===i&&e.classList.add(`range-bottom`),c===a&&e.classList.add(`range-left`),c===o&&e.classList.add(`range-right`),s===n.startRow&&c===n.startCol&&(e.classList.add(`cell-selected`),t.selectedCell=e))}),n.isDraggingRow&&document.querySelectorAll(`#${e} td.row-header`).forEach(e=>{let t=parseInt(e.dataset.rowIdx);t>=r&&t<=i&&e.classList.add(`row-header-selected`)})}function h(e,t,n,r){e.addEventListener(`mousedown`,e=>{if(e.target.tagName===`INPUT`||e.target.tagName===`SELECT`)return;let i=e.target.closest(`td.row-header`);if(i&&e.button!==2){let e=parseInt(i.dataset.rowIdx);n.selection={isDragging:!1,isDraggingRow:!0,startRow:e,endRow:e,startCol:0,endCol:r-1},m(t,n);return}let a=e.target.closest(`td.data-cell`);if(!a)return;let o=parseInt(a.dataset.rowIdx),s=parseInt(a.dataset.colIdx);n.selection={isDragging:!0,startRow:o,startCol:s,endRow:o,endCol:s},m(t,n)}),e.addEventListener(`mouseover`,e=>{if(n.selection.isDraggingRow){let r=e.target.closest(`td.row-header`);if(!r)return;n.selection.endRow=parseInt(r.dataset.rowIdx),m(t,n);return}if(!n.selection.isDragging)return;let r=e.target.closest(`td.data-cell`);r&&(n.selection.endRow=parseInt(r.dataset.rowIdx),n.selection.endCol=parseInt(r.dataset.colIdx),m(t,n))}),e.addEventListener(`mouseup`,()=>{n.selection&&(n.selection.isDragging=!1,n.selection.isDraggingRow=!1)}),e.addEventListener(`contextmenu`,e=>{let r=e.target.closest(`td.row-header`);if(!r)return;let i=parseInt(r.dataset.rowIdx),a=n.selection,o=Math.min(a.startRow,a.endRow),s=Math.max(a.startRow,a.endRow);a.startRow!==-1&&i>=o&&i<=s&&(e.preventDefault(),g(e.pageX,e.pageY,n,t))})}function g(e,t,n,r){let i=document.getElementById(`grid-context-menu`);i||(i=document.createElement(`div`),i.id=`grid-context-menu`,i.className=`context-menu`,document.body.appendChild(i),document.addEventListener(`click`,()=>{i.style.display=`none`}));let a=n.selection,o=Math.min(a.startRow,a.endRow),s=Math.max(a.startRow,a.endRow),c=s-o+1;i.innerHTML=`
|
|
86
|
+
<div class="menu-item delete-action">
|
|
87
|
+
<span class="material-symbols-outlined">delete</span>
|
|
88
|
+
Delete ${c} Row${c>1?`s`:``}
|
|
89
|
+
</div>
|
|
90
|
+
`,i.style.left=`${e}px`,i.style.top=`${t}px`,i.style.display=`block`,i.querySelector(`.delete-action`).onclick=e=>{e.stopPropagation(),i.style.display=`none`;let t=document.querySelectorAll(`#${r} tbody tr:not(.ghost-row-tr)`);for(let e=o;e<=s;e++){let r=t[e];if(!r)continue;let i=r.querySelector(`td.data-cell`);if(i){let e=i.dataset.pk;e!==`undefined`&&e!=null&&(n.pendingDeletes||=new Set,n.pendingDeletes.add(e),r.classList.add(`row-deleted`))}}let a=document.getElementById(`btn-save-changes`);a&&a.classList.add(`has-changes`)}}function _(e,t){let n=document.createElement(`div`);n.className=`resizer`,e.appendChild(n),n.addEventListener(`click`,e=>e.stopPropagation()),n.addEventListener(`mousedown`,n=>{n.preventDefault(),n.stopPropagation();let r=n.pageX,i=e.offsetWidth,a=!1,o=n=>{a=!0,t&&(t.isResizing=!0);let o=i+(n.pageX-r);e.style.width=o+`px`,e.style.minWidth=o+`px`,e.style.maxWidth=o+`px`},s=()=>{document.removeEventListener(`mousemove`,o),document.removeEventListener(`mouseup`,s),document.body.style.cursor=``,a&&setTimeout(()=>{t&&(t.isResizing=!1)},100)};document.body.style.cursor=`col-resize`,document.addEventListener(`mousemove`,o),document.addEventListener(`mouseup`,s)})}var v=t({duplicateDataRows:()=>C,markRowDeleted:()=>x,saveDataGridEdits:()=>y,unmarkRowDeleted:()=>S,updateCell:()=>b});async function y(){if(!window.DataGrid)return;let{pendingEdits:e,pendingInserts:t,pkColumn:n}=window.DataGrid,r=window.AppState.currentTable;if(!r||!n){alert(`Cannot save: No Primary Key detected for this table.`);return}let i=[];for(let[t,a]of Object.entries(e)){if(Object.keys(a).length===0)continue;let e=Object.entries(a).map(([e,t])=>t===``?`"${e}" = NULL`:`"${e}" = '${t.replace(/'/g,`''`)}'`).join(`, `);i.push(`UPDATE "${r}" SET ${e} WHERE "${n}" = '${t.replace(/'/g,`''`)}';`)}for(let e=0;e<t.length;e++){let n=t[e];if(Object.keys(n).length===0||!Object.values(n).some(e=>e!==``))continue;let a=Object.keys(n),o=a.map(e=>{let t=n[e];return t===``?`NULL`:`'${t.replace(/'/g,`''`)}'`});i.push(`INSERT INTO "${r}" ("${a.join(`", "`)}") VALUES (${o.join(`, `)});`)}if(window.DataGrid.pendingDeletes)for(let e of window.DataGrid.pendingDeletes)i.push(`DELETE FROM "${r}" WHERE "${n}" = '${e.replace(/'/g,`''`)}';`);if(i.length===0)return;let a=!0,o=``;for(let e of i)try{let t=await d(e);if(!t.success){a=!1,o=t.error;break}}catch(e){a=!1,o=e.message;break}a?(window.renderCurrentView(),window.showToast&&window.showToast(`Data saved successfully!`)):(window.showToast?window.showToast(`Save failed: `+o,`error`):alert(`Save failed:
|
|
91
|
+
`+o),document.querySelectorAll(`.cell-edited`).forEach(e=>{e.classList.remove(`cell-edited`),e.classList.add(`cell-error`)})),window.updateSidebarDirtyState?.()}function b(e,t,n,r=!0){if(r&&window.DataGrid.currentTransaction){let n=e.textContent;(n===`null`||e.classList.contains(`ghost-row`))&&(n=``),n!==t&&window.DataGrid.currentTransaction.push({td:e,oldVal:n,newVal:t})}let i=e.dataset.col;if(e.innerHTML=t||(e.dataset.insertIndex===void 0?`<em>null</em>`:`+ New`),e.dataset.insertIndex!==void 0){let r=parseInt(e.dataset.insertIndex);if(window.DataGrid.pendingInserts[r]||(window.DataGrid.pendingInserts[r]={}),t&&(window.DataGrid.pendingInserts[r][i]=t,e.classList.add(`cell-edited`),e.classList.remove(`ghost-row`),r===window.DataGrid.pendingInserts.length-1)){e.closest(`tr`).classList.remove(`ghost-row-tr`),window.DataGrid.pendingInserts.push({});let t=document.querySelector(`#data-grid-table-${window.AppState.currentTable} tbody`),i=document.createElement(`tr`);i.className=`ghost-row-tr`;let a=parseInt(e.dataset.rowIdx)+1;i.innerHTML+=`<td class="row-header" data-row-idx="${a}">*</td>`,n.forEach((e,t)=>{i.innerHTML+=`<td class="data-cell ghost-row" data-row-idx="${a}" data-col-idx="${t}" data-insert-index="${r+1}" data-col="${e}">+ New</td>`}),t.appendChild(i)}}else{let n=e.dataset.pk;t===e.dataset.original?(e.classList.remove(`cell-edited`),e.classList.remove(`cell-error`),window.DataGrid.pendingEdits[n]&&delete window.DataGrid.pendingEdits[n][i]):(window.DataGrid.pendingEdits[n]||(window.DataGrid.pendingEdits[n]={}),window.DataGrid.pendingEdits[n][i]=t,e.classList.add(`cell-edited`),e.classList.remove(`cell-error`))}window.updateSidebarDirtyState?.()}function x(e,t=!0){let n=document.querySelector(`td.data-cell[data-row-idx="${e}"]`)?.closest(`tr`);if(!n||n.classList.contains(`ghost-row-tr`)||n.classList.contains(`row-deleted`))return;let r=n.querySelector(`td.data-cell`)?.dataset.pk;r!==void 0&&(t&&window.DataGrid.currentTransaction&&window.DataGrid.currentTransaction.push({type:`delete`,rowIdx:e,pk:r}),window.DataGrid.pendingDeletes.add(r),n.classList.add(`row-deleted`)),window.updateSidebarDirtyState?.()}function S(e,t){let n=document.querySelector(`td.data-cell[data-row-idx="${e}"]`)?.closest(`tr`);n&&n.classList.remove(`row-deleted`),window.DataGrid.pendingDeletes.delete(t),window.updateSidebarDirtyState?.()}function C(e,t){e.forEach(e=>{let n=window.AppState.currentTable,r=document.querySelector(`#data-grid-table-${n} td.data-cell[data-row-idx="${e}"]`)?.closest(`tr`);if(!r||r.classList.contains(`ghost-row-tr`))return;let i=document.querySelector(`#data-grid-table-${n} .ghost-row-tr`);i&&t.forEach((e,n)=>{let a=r.querySelector(`td.data-cell[data-col-idx="${n}"]`),o=i.querySelector(`td.data-cell[data-col-idx="${n}"]`);if(a&&o){let n=a.dataset.insertIndex===void 0?a.classList.contains(`cell-edited`)?window.DataGrid.pendingEdits[a.dataset.pk]?.[e]:a.dataset.original:window.DataGrid.pendingInserts[a.dataset.insertIndex][e];n!=null&&n!==`null`&&b(o,n,t,!0)}})})}var w=`modulepreload`,T=function(e,t){return new URL(e,t).href},E={},D=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=T(t,n),t=s(t),t in E)return;E[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:w,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})};function O(e,t,n){e.addEventListener(`dblclick`,e=>{let r=e.target.closest(`td.data-cell`);if(!r||r.querySelector(`input, select`))return;let i=r.dataset.col,o=t.find(e=>e.name===i),s=o?.type?.toUpperCase()||``,c=s.includes(`ENUM`),l=s===`DATE`,u=s.includes(`DATETIME`)||s.includes(`TIMESTAMP`),d=s.includes(`BOOL`)||s===`TINYINT(1)`,f=r.textContent===`null`||r.textContent===`+ New`?``:r.textContent,p;if(o&&o.fkTarget){p=document.createElement(`select`);let e=document.createElement(`option`);e.value=f,e.textContent=`Loading...`,p.appendChild(e),D(async()=>{let{executeRawQuery:e}=await Promise.resolve().then(()=>a);return{executeRawQuery:e}},void 0,import.meta.url).then(({executeRawQuery:t})=>{let{table:n,column:r}=o.fkTarget;t(`SELECT * FROM "${n}" LIMIT 100`).then(e=>{if(e.success&&e.data&&e.data.rows){if(p.innerHTML=``,o.nullable){let e=document.createElement(`option`);e.value=``,e.textContent=`-- None --`,p.appendChild(e)}let t=r;if(e.data.columns){let n=[`name`,`title`,`label`,`description`],r=e.data.columns.find(e=>n.includes(e.toLowerCase()));r&&(t=r)}if(e.data.rows.forEach(e=>{let n=String(e[r]),i=t===r?n:`${n} - ${e[t]}`,a=document.createElement(`option`);a.value=n,a.textContent=i,n===f&&(a.selected=!0),p.appendChild(a)}),f&&!e.data.rows.find(e=>String(e[r])===f)){let e=document.createElement(`option`);e.value=f,e.textContent=`${f} (Not in limit)`,e.selected=!0,p.appendChild(e)}}}).catch(t=>{e.textContent=`Error loading options`})})}else if(c){let e=o.type.match(/enum\((.*?)\)/i),t=[];e&&(t=e[1].split(`,`).map(e=>e.trim().replace(/^'|'$/g,``))),p=document.createElement(`select`),t.forEach(e=>{let t=document.createElement(`option`);t.value=e,t.textContent=e,e===f&&(t.selected=!0),p.appendChild(t)})}else if(l)p=document.createElement(`input`),p.type=`date`,p.value=f;else if(u){p=document.createElement(`input`),p.type=`datetime-local`;let e=f.replace(` `,`T`).slice(0,16);p.value=e}else d?(p=document.createElement(`input`),p.type=`checkbox`,p.checked=f===`1`||f.toLowerCase()===`true`):(p=document.createElement(`input`),p.type=`text`,p.value=f);let m=!1,h=()=>{m=!0;let e=document.getElementById(`modal-editor-overlay`),t=document.getElementById(`modal-textarea`),n=document.getElementById(`modal-cancel-btn`),r=document.getElementById(`modal-save-btn`),a=document.getElementById(`modal-title`);a.textContent=`Edit ${i}`,t.value=p.value,e.style.display=`flex`,t.focus();let o=()=>{e.style.display=`none`,r.onclick=null,n.onclick=null,m=!1,p.focus()};n.onclick=o,r.onclick=()=>{p.value=t.value,o(),g()}};if(r.innerHTML=``,r.appendChild(p),s===``||!c&&!l&&!u&&!d&&!(o&&o.fkTarget)){let e=document.createElement(`span`);e.className=`material-symbols-outlined cell-expand-btn`,e.textContent=`open_in_full`,e.onmousedown=e=>e.preventDefault(),e.onclick=()=>h(),r.appendChild(e),p.style.width=`100%`,p.style.paddingRight=`32px`,p.addEventListener(`keydown`,e=>{e.key===`Enter`&&e.shiftKey?(e.preventDefault(),h()):e.key===`Enter`&&p.blur()})}else p.addEventListener(`keydown`,e=>{e.key===`Enter`&&p.blur()});p.focus();let g=()=>{if(m)return;let e=d?p.checked?`1`:`0`:p.value;u&&e&&(e=e.replace(`T`,` `)+`:00`),window.DataGrid.currentTransaction=[],b(r,e,n),window.DataGrid.currentTransaction.length>0&&window.DataGrid.history.push(window.DataGrid.currentTransaction),window.DataGrid.currentTransaction=null};p.addEventListener(`blur`,()=>{setTimeout(()=>{m||g()},100)})})}function k(){let e=window.AppState?.currentTable;if(!e)return``;let t=document.getElementById(`filter-val-${e}`)?.value.trim(),n=document.getElementById(`filter-op-${e}`)?.value,r=document.getElementById(`filter-col-${e}`)?.value,i=``;if(t||n===`IS NULL`){let e=t;e&&!e.startsWith(`'`)&&!e.endsWith(`'`)&&isNaN(Number(e))&&(e.toUpperCase().includes(` AND `)||e.toUpperCase().includes(` OR `)||(e=`'${e.replace(/'/g,`''`)}'`)),i=`"${r}" ${n} ${e}`}return i}function A(e,t,n,r){let i=`<td class="row-header" data-row-idx="${t}">${t+1}</td>`,a=n?e[n]:t;return r.forEach((n,r)=>{let o=e[n]===null?`null`:String(e[n]),s=o.replace(/"/g,`"`),c=o===`null`?`<em>null</em>`:o.replace(/</g,`<`);i+=`<td class="data-cell" data-row-idx="${t}" data-col-idx="${r}" data-pk="${a}" data-col="${n}" data-original="${s}">${c}</td>`}),i}async function j(e,t,n=``,r=!1,i=null){document.querySelectorAll(`.table-btn`).forEach(e=>e.classList.remove(`active`)),t&&t.classList.add(`active`);let a=document.getElementById(`table-name`);a&&(a.textContent=e);let o=i||document.getElementById(`main-content`);r||(o.innerHTML=`<div style='padding:24px;'>Loading...</div>`);try{let i=await l(e);if(!i.success)throw Error(i.error);let a=i.data,s=a.find(e=>e.isPk)?.name;(!r||!window.DataGrid)&&(window.DataGrid={schema:a,pkColumn:s,pendingEdits:{},pendingInserts:[{}],pendingDeletes:new Set,selectedCell:null,history:[],currentTransaction:null,sortState:{col:s||a[0].name,asc:!0},pagination:{limit:50,offset:0,isLoading:!1,hasMore:!0},selection:{isDragging:!1,isDraggingRow:!1,startRow:-1,startCol:-1,endRow:-1,endCol:-1}}),window.TableStates&&window.TableStates[e]&&(window.TableStates[e].dataGrid=window.DataGrid);let u=await c(e,{where:n,limit:window.DataGrid.pagination.limit,offset:window.DataGrid.pagination.offset,orderCol:window.DataGrid.sortState.col,orderAsc:window.DataGrid.sortState.asc});if(u.success&&u.data){let n=u.data.rows,i=u.data.columns;window.DataGrid.pagination.hasMore=n.length===window.DataGrid.pagination.limit;let l=i.map(e=>`<option value="${e}">${e}</option>`).join(``);r||(o.innerHTML=`
|
|
92
|
+
<div class="toolbar">
|
|
93
|
+
<div class="filter-group">
|
|
94
|
+
<div class="filter-icon-container">
|
|
95
|
+
<span class="material-symbols-outlined" id="filter-icon">filter_list</span>
|
|
96
|
+
<span>Filter</span>
|
|
97
|
+
</div>
|
|
98
|
+
<select id="filter-col-${e}" class="filter-select">${l}</select>
|
|
99
|
+
<select id="filter-op-${e}" class="filter-select">
|
|
100
|
+
<option value="=">=</option>
|
|
101
|
+
<option value=">">></option>
|
|
102
|
+
<option value="<"><</option>
|
|
103
|
+
<option value=">=">>=</option>
|
|
104
|
+
<option value="<="><=</option>
|
|
105
|
+
<option value="LIKE">LIKE</option>
|
|
106
|
+
<option value="!=">!=</option>
|
|
107
|
+
</select>
|
|
108
|
+
<input type="text" id="filter-val-${e}" class="filter-input" placeholder="Enter value..." />
|
|
109
|
+
</div>
|
|
110
|
+
<div style="flex:1;"></div>
|
|
111
|
+
<button id="btn-refresh-data-${e}" class="refresh-btn" title="Refresh Data (F5)"><span class="material-symbols-outlined">refresh</span></button>
|
|
112
|
+
</div>
|
|
113
|
+
<div class="table-container" id="data-grid-container-${e}"></div>
|
|
114
|
+
`);let d=`<table class="data-table" id="data-grid-table-${e}"><thead><tr>`;d+=`<th class="row-header">#</th>`,i.forEach(e=>{let t=a.find(t=>t.name===e),n=``,r=``;t&&(t.isPk&&(n=` <span style="opacity:0.5; font-size:10px;">(PK)</span>`),t.name.toLowerCase().includes(`id`)&&!t.isPk&&(n=` <span style="opacity:0.5; font-size:10px;">(FK)</span>`),r=`<br><span style="font-weight:normal; opacity:0.7; font-size:10px; font-family:monospace;">${t.type}</span>`);let i=``;window.DataGrid.sortState.col===e&&(i=window.DataGrid.sortState.asc?`▲`:`▼`),d+=`<th class="sortable" data-col="${e}" style="cursor:pointer; user-select:none;">
|
|
115
|
+
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
116
|
+
<div>${e}${n}${r}</div>
|
|
117
|
+
<div class="sort-arrow" style="font-size:10px; opacity:0.8; margin-left: 8px; width: 12px; text-align: right;">${i}</div>
|
|
118
|
+
</div>
|
|
119
|
+
</th>`}),d+=`</tr></thead><tbody>`,n&&n.length>0&&n.forEach((e,t)=>{d+=`<tr>${A(e,t,s,i)}</tr>`}),d+=`<tr class="ghost-row-tr">`;let f=n?n.length:0;d+=`<td class="row-header" data-row-idx="${f}">*</td>`,i.forEach((e,t)=>{d+=`<td class="data-cell ghost-row" data-row-idx="${f}" data-col-idx="${t}" data-insert-index="0" data-col="${e}">+ New</td>`}),d+=`</tr></tbody></table>`;let p=document.getElementById(`data-grid-container-${e}`);if(!p)return;if(p.innerHTML=d,document.querySelectorAll(`th.sortable`).forEach(n=>{n.onclick=r=>{if(window.DataGrid&&window.DataGrid.isResizing)return;if(Object.keys(window.DataGrid.pendingEdits).length>0||window.DataGrid.pendingInserts.length>1||window.DataGrid.pendingDeletes.size>0){alert(`You have unsaved changes. Please save changes before sorting.`);return}let i=n.dataset.col;window.DataGrid.sortState.col===i?window.DataGrid.sortState.asc=!window.DataGrid.sortState.asc:(window.DataGrid.sortState.col=i,window.DataGrid.sortState.asc=!0),window.DataGrid.pagination.offset=0,j(e,t,k(),!0)},_(n,window.DataGrid)}),h(p,`data-grid-table-${e}`,window.DataGrid,i.length),O(p,a,i),!r){let n=document.getElementById(`filter-val-${e}`),r=(n=!0)=>{n&&window.DataGrid&&(window.DataGrid.pagination.offset=0),j(e,t,k(),!0)},a;n&&n.addEventListener(`input`,()=>{clearTimeout(a),a=setTimeout(()=>r(!0),400)});let o=document.getElementById(`filter-col-${e}`),l=document.getElementById(`filter-op-${e}`);o&&o.addEventListener(`change`,()=>r(!0)),l&&l.addEventListener(`change`,()=>r(!0));let u=()=>{(Object.keys(window.DataGrid.pendingEdits).length>0||window.DataGrid.pendingInserts.length>1||window.DataGrid.pendingDeletes.size>0)&&!confirm(`You have unsaved changes. Are you sure you want to refresh and discard them?`)||(window.DataGrid.pendingEdits={},window.DataGrid.pendingInserts=[{}],window.DataGrid.pendingDeletes=new Set,window.DataGrid.history=[],window.DataGrid.currentTransaction=null,window.updateSidebarDirtyState?.(),r(!1))},d=document.getElementById(`btn-refresh-data-${e}`);d&&(d.onclick=u),window.DataGrid.refreshData=u;let f=async()=>{if(window.DataGrid.pagination.isLoading||!window.DataGrid.pagination.hasMore)return;window.DataGrid.pagination.isLoading=!0,window.DataGrid.pagination.offset+=window.DataGrid.pagination.limit;let t={where:k(),limit:window.DataGrid.pagination.limit,offset:window.DataGrid.pagination.offset,orderCol:window.DataGrid.sortState.col,orderAsc:window.DataGrid.sortState.asc};try{let n=await c(e,t);if(window.DataGrid.pagination.isLoading=!1,n.success&&n.data){let t=n.data.rows;window.DataGrid.pagination.hasMore=t.length===window.DataGrid.pagination.limit;let r=document.querySelector(`#data-grid-table-${e} tbody`);if(!r)return;let a=r.querySelector(`.ghost-row-tr`);a&&r.removeChild(a);let o=window.DataGrid.pagination.offset;if(t.forEach((e,t)=>{let n=document.createElement(`tr`);n.innerHTML=A(e,o+t,s,i),r.appendChild(n)}),a){let e=o+t.length,n=a.querySelector(`.row-header`);n&&(n.dataset.rowIdx=e),a.querySelectorAll(`.ghost-row`).forEach(t=>{t.dataset.rowIdx=e}),r.appendChild(a)}}}catch{window.DataGrid.pagination.isLoading=!1}};setTimeout(()=>{let t=document.getElementById(`data-grid-container-${e}`);t&&t.addEventListener(`scroll`,e=>{let{scrollTop:t,scrollHeight:n,clientHeight:r}=e.target;t+r>=n-50&&f()})},50)}}else o.innerHTML=`<div style="padding:24px; color:red;">Error: ${u.error}</div>`}catch(e){o.innerHTML=`<div style="padding:24px; color:red;">Failed to load data: ${e.message}</div>`}}var M=t({duplicateSchemaRows:()=>L,markSchemaRowDeleted:()=>F,saveSchemaEdits:()=>N,unmarkSchemaRowDeleted:()=>I,updateSchemaCell:()=>P});async function N(){if(!window.SchemaGrid)return;let{pendingEdits:e,pendingInserts:t,pendingDeletes:n}=window.SchemaGrid,r=window.AppState.currentTable;if(!r)return;let i=[];if(n)for(let e of n)i.push(`ALTER TABLE "${r}" DROP COLUMN "${e}";`);for(let[t,n]of Object.entries(e)){let e=t;if(n.name&&n.name!==t&&(i.push(`ALTER TABLE "${r}" RENAME COLUMN "${t}" TO "${n.name}";`),e=n.name),Object.keys(n).filter(e=>e!==`name`).length>0){let a=window.SchemaGrid.schema?.find(e=>e.name===t)||{},o=n.type===void 0?a.type:n.type,s=[],c=n.isPk===void 0?a.isPk:n.isPk,l=String(c).toUpperCase();if((l===`1`||l===`TRUE`||l===`YES`||l.includes(`PK`)||l===`KEY`)&&s.push(`PRIMARY KEY`),l.includes(`FK:`)){let e=l.match(/FK:\s*([^\s,]+)/i);if(e&&e[1]){let t=e[1].split(`.`);t.length===2&&s.push(`REFERENCES "${t[0]}"("${t[1]}")`)}}let u=n.nullable===void 0?a.nullable:n.nullable;(u===`0`||u===`No`||u===!1)&&s.push(`NOT NULL`);let d=n.defaultValue===void 0?a.defaultValue:n.defaultValue;d&&s.push(`DEFAULT '${String(d).replace(/'/g,`''`)}'`),i.push(`ALTER TABLE "${r}" MODIFY COLUMN "${e}" ${o} ${s.join(` `)};`)}}for(let e=0;e<t.length;e++){let n=t[e];if(Object.keys(n).length===0||!n.name||n.name.trim()===``)continue;let a=n.name.trim(),o=n.type||`TEXT`,s=[],c=String(n.isPk||``).toUpperCase();if((c===`1`||c===`TRUE`||c===`YES`||c.includes(`PK`)||c===`KEY`)&&s.push(`PRIMARY KEY`),c.includes(`FK:`)){let e=c.match(/FK:\s*([^\s,]+)/i);if(e&&e[1]){let t=e[1].split(`.`);t.length===2&&s.push(`REFERENCES "${t[0]}"("${t[1]}")`)}}(n.nullable===`0`||n.nullable===`false`||n.nullable===`No`)&&s.push(`NOT NULL`),n.defaultValue&&s.push(`DEFAULT '${n.defaultValue.replace(/'/g,`''`)}'`),i.push(`ALTER TABLE "${r}" ADD COLUMN "${a}" ${o} ${s.join(` `)};`)}if(window.SchemaGrid.pendingIndexEdits){for(let e of window.SchemaGrid.pendingIndexEdits.dropped)e&&e.trim()!==``&&i.push(`DROP INDEX "${e}";`);for(let e of window.SchemaGrid.pendingIndexEdits.added){let t=``;t=e.name&&e.name.trim()!==``?`"${e.name}"`:`"idx_${r}_${e.columns.join(`_`)}_${Date.now()}"`;let n=e.isUnique?`UNIQUE`:``,a=e.columns.map(e=>`"${e}"`).join(`, `);i.push(`CREATE ${n} INDEX IF NOT EXISTS ${t} ON "${r}" (${a});`)}}if(i.length===0)return;let a=!0,o=``;for(let e of i)try{let t=await d(e);if(!t.success){a=!1,o=t.error;break}}catch(e){a=!1,o=e.message;break}a?(window.renderCurrentView(),window.showToast&&window.showToast(`Schema saved successfully!`)):(o.includes(`near "MODIFY": syntax error`)?o=`SQLite: Currently does not support modifying existing column types or constraints directly. You can only Rename columns or Add new columns.`:o.includes(`syntax error`)&&(o=`SQLite: `+o),window.showToast?window.showToast(`Save failed: `+o,`error`):alert(`Save failed:
|
|
120
|
+
`+o),document.querySelectorAll(`.cell-edited`).forEach(e=>{e.classList.remove(`cell-edited`),e.classList.add(`cell-error`)})),window.updateSidebarDirtyState?.()}function P(e,t,n,r=!0){if(r&&window.SchemaGrid.currentTransaction){let n=e.textContent;(n===`null`||e.classList.contains(`ghost-row`))&&(n=``),n!==t&&window.SchemaGrid.currentTransaction.push({td:e,oldVal:n,newVal:t})}let i=e.dataset.colKey;if(e.innerHTML=t||(e.dataset.insertIndex===void 0?`<span style="color:var(--color-text-soft)">-</span>`:`+ New`),e.dataset.insertIndex!==void 0){let r=parseInt(e.dataset.insertIndex);if(window.SchemaGrid.pendingInserts[r]||(window.SchemaGrid.pendingInserts[r]={}),t&&(window.SchemaGrid.pendingInserts[r][i]=t,e.classList.add(`cell-edited`),e.classList.remove(`ghost-row`),r===window.SchemaGrid.pendingInserts.length-1)){e.closest(`tr`).classList.remove(`ghost-row-tr`),window.SchemaGrid.pendingInserts.push({});let t=document.querySelector(`#schema-grid-table-${window.AppState.currentTable} tbody`),i=document.createElement(`tr`);i.className=`ghost-row-tr`;let a=parseInt(e.dataset.rowIdx)+1;i.innerHTML+=`<td class="row-header" data-row-idx="${a}">*</td>`,n.forEach((e,t)=>{i.innerHTML+=`<td class="data-cell ghost-row" data-row-idx="${a}" data-col-idx="${t}" data-insert-index="${r+1}" data-col-key="${e}">+ New</td>`}),t.appendChild(i)}}else{let n=e.dataset.pk,r=e.dataset.original;r===`-`&&(r=``),t===r?(e.classList.remove(`cell-edited`),e.classList.remove(`cell-error`),window.SchemaGrid.pendingEdits[n]&&delete window.SchemaGrid.pendingEdits[n][i]):(window.SchemaGrid.pendingEdits[n]||(window.SchemaGrid.pendingEdits[n]={}),window.SchemaGrid.pendingEdits[n][i]=t,e.classList.add(`cell-edited`),e.classList.remove(`cell-error`))}window.updateSidebarDirtyState?.()}function F(e,t=!0){let n=document.querySelector(`#schema-grid-table td.data-cell[data-row-idx="${e}"]`)?.closest(`tr`);if(!n||n.classList.contains(`ghost-row-tr`)||n.classList.contains(`row-deleted`))return;let r=n.querySelector(`td.data-cell`)?.dataset.pk;r!==void 0&&(t&&window.SchemaGrid.currentTransaction&&window.SchemaGrid.currentTransaction.push({type:`delete`,rowIdx:e,pk:r}),window.SchemaGrid.pendingDeletes.add(r),n.classList.add(`row-deleted`)),window.updateSidebarDirtyState?.()}function I(e,t){let n=document.querySelector(`#schema-grid-table td.data-cell[data-row-idx="${e}"]`)?.closest(`tr`);n&&n.classList.remove(`row-deleted`),window.SchemaGrid.pendingDeletes.delete(t),window.updateSidebarDirtyState?.()}function L(e,t){e.forEach(e=>{let n=window.AppState.currentTable,r=document.querySelector(`#schema-grid-table-${n} td.data-cell[data-row-idx="${e}"]`)?.closest(`tr`);if(!r||r.classList.contains(`ghost-row-tr`))return;let i=document.querySelector(`#schema-grid-table-${n} .ghost-row-tr`);i&&t.forEach((e,n)=>{let a=r.querySelector(`td.data-cell[data-col-idx="${n}"]`),o=i.querySelector(`td.data-cell[data-col-idx="${n}"]`);if(a&&o){let n=a.dataset.insertIndex===void 0?a.classList.contains(`cell-edited`)?window.SchemaGrid.pendingEdits[a.dataset.pk]?.[e]:a.dataset.original:window.SchemaGrid.pendingInserts[a.dataset.insertIndex][e];n!=null&&n!==`null`&&(e===`name`&&(n+=`_copy`),P(o,n,t,!0))}})})}function R(){let e=window.SchemaGrid;if(!e)return;let t=document.getElementById(`index-modal`);t&&t.remove();let n=[...e.indexes],r=[...e.pendingIndexEdits.added],i=new Set(e.pendingIndexEdits.dropped),a=n.filter(e=>!i.has(e.name)).concat(r),o=e.schema.map(e=>e.name);e.pendingInserts.forEach(e=>{e.name&&e.name.trim()!==``&&o.push(e.name.trim())});let s=o.map(e=>`<option value="${e}">${e}</option>`).join(``);t=document.createElement(`div`),t.id=`index-modal`,t.style.cssText=`
|
|
121
|
+
position: fixed; top:0; left:0; width:100vw; height:100vh; background:rgba(0,0,0,0.5);
|
|
122
|
+
display:flex; justify-content:center; align-items:center; z-index:9999;
|
|
123
|
+
`,t.innerHTML=`
|
|
124
|
+
<div style="background:var(--color-bg-primary); width:500px; border-radius:8px; box-shadow:0 4px 12px rgba(0,0,0,0.2); overflow:hidden; display:flex; flex-direction:column;">
|
|
125
|
+
<div style="padding:16px; border-bottom:1px solid var(--color-border); display:flex; justify-content:space-between; align-items:center;">
|
|
126
|
+
<h3 style="margin:0;">Manage Indexes</h3>
|
|
127
|
+
<button id="close-idx-modal" style="background:none; border:none; color:var(--color-text-primary); cursor:pointer;"><span class="material-symbols-outlined">close</span></button>
|
|
128
|
+
</div>
|
|
129
|
+
<div style="padding:16px; max-height:300px; overflow-y:auto;" id="idx-list-container">
|
|
130
|
+
</div>
|
|
131
|
+
<div style="padding:16px; border-top:1px solid var(--color-border); background:var(--color-bg-secondary);">
|
|
132
|
+
<div style="font-weight:500; margin-bottom:8px;">Add New Index</div>
|
|
133
|
+
<div style="display:flex; flex-direction:column; gap:8px;">
|
|
134
|
+
<input type="text" id="new-idx-name" placeholder="Index Name (Optional)" style="padding:6px; border-radius:4px; border:1px solid var(--color-border); background:var(--color-bg-primary); color:var(--color-text-primary);" />
|
|
135
|
+
<select id="new-idx-cols" multiple style="padding:6px; border-radius:4px; border:1px solid var(--color-border); background:var(--color-bg-primary); color:var(--color-text-primary); height:80px;">
|
|
136
|
+
${s}
|
|
137
|
+
</select>
|
|
138
|
+
<div style="font-size:12px; color:var(--color-text-soft);">Hold Ctrl/Cmd to select multiple columns</div>
|
|
139
|
+
<label style="display:flex; align-items:center; gap:6px; cursor:pointer;">
|
|
140
|
+
<input type="checkbox" id="new-idx-unique" /> Unique Index
|
|
141
|
+
</label>
|
|
142
|
+
<button id="add-idx-btn" class="primary" style="align-self:flex-end; padding:6px 16px; border-radius:4px; border:none; cursor:pointer;">Add</button>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
<div style="padding:16px; border-top:1px solid var(--color-border); display:flex; justify-content:flex-end; gap:8px;">
|
|
146
|
+
<button id="cancel-idx-btn" class="secondary" style="padding:6px 16px; border-radius:4px; border:1px solid var(--color-border); cursor:pointer;">Cancel</button>
|
|
147
|
+
<button id="save-idx-btn" class="primary" style="padding:6px 16px; border-radius:4px; border:none; cursor:pointer;">Save Changes</button>
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
`,document.body.appendChild(t);let c=()=>t.remove();document.getElementById(`close-idx-modal`).onclick=c,document.getElementById(`cancel-idx-btn`).onclick=c;let l=()=>{let e=a.map((e,t)=>`
|
|
151
|
+
<div class="index-row" style="display:flex; gap:8px; align-items:center; margin-bottom:8px; padding:8px; background:var(--color-bg-primary); border:1px solid var(--color-border); border-radius:4px;">
|
|
152
|
+
<div style="flex:1;"><strong>${e.name||`-`}</strong></div>
|
|
153
|
+
<div style="flex:2; font-size:12px; color:var(--color-text-secondary);">${e.columns.join(`, `)}</div>
|
|
154
|
+
<div style="width:60px; font-size:12px; text-align:center;">${e.isUnique?`UNIQUE`:``}</div>
|
|
155
|
+
<button class="icon-btn delete-idx-btn" data-idx="${t}" style="color:var(--color-error); border:none; background:none; cursor:pointer;"><span class="material-symbols-outlined" style="font-size:18px;">delete</span></button>
|
|
156
|
+
</div>
|
|
157
|
+
`).join(``);a.length===0&&(e=`<div style="padding:16px; text-align:center; color:var(--color-text-secondary);">No indexes yet.</div>`),document.getElementById(`idx-list-container`).innerHTML=e,document.querySelectorAll(`.delete-idx-btn`).forEach(e=>{e.onclick=e=>{let t=parseInt(e.currentTarget.dataset.idx,10);a.splice(t,1),l()}})};l(),document.getElementById(`add-idx-btn`).onclick=()=>{let e=document.getElementById(`new-idx-name`).value.trim(),t=document.getElementById(`new-idx-cols`),n=Array.from(t.selectedOptions).map(e=>e.value),r=document.getElementById(`new-idx-unique`).checked;if(n.length===0){alert(`Please select at least one column for the index.`);return}a.push({name:e,columns:n,isUnique:r}),document.getElementById(`new-idx-name`).value=``,document.getElementById(`new-idx-unique`).checked=!1,t.selectedIndex=-1,l()},document.getElementById(`save-idx-btn`).onclick=()=>{let t=[],r=new Set;n.forEach(e=>{a.find(t=>t.name===e.name&&JSON.stringify(t.columns)===JSON.stringify(e.columns))||r.add(e.name)}),a.forEach(e=>{n.find(t=>t.name===e.name&&JSON.stringify(t.columns)===JSON.stringify(e.columns))||t.push(e)}),e.pendingIndexEdits.added=t,e.pendingIndexEdits.dropped=Array.from(r),window.updateSidebarDirtyState?.(),window.renderSchemaGrid(),c()}}async function z(e,t){if(!window.SchemaGrid)return;let n=document.getElementById(`pkfk-modal`);n&&n.remove();let r=e.dataset.insertIndex!==void 0,i=t.includes(`PK`),a=t.includes(`FK`),o=``,s=``;if(a){let e=t.match(/FK \((.*?)\)/);if(e&&e[1]){let t=e[1].split(`.`);t.length===2&&(o=t[0],s=t[1])}else{let e=t.match(/FK:\s*([^\s,]+)/i);if(e&&e[1]){let t=e[1].split(`.`);t.length===2&&(o=t[0],s=t[1])}}}n=document.createElement(`div`),n.id=`pkfk-modal`,n.style.cssText=`
|
|
158
|
+
position: fixed; top:0; left:0; width:100vw; height:100vh; background:rgba(0,0,0,0.5);
|
|
159
|
+
display:flex; justify-content:center; align-items:center; z-index:9999;
|
|
160
|
+
`,n.innerHTML=`
|
|
161
|
+
<div style="background:var(--color-bg-primary); width:400px; border-radius:8px; box-shadow:0 4px 12px rgba(0,0,0,0.2); overflow:hidden; display:flex; flex-direction:column;">
|
|
162
|
+
<div style="padding:16px; border-bottom:1px solid var(--color-border); display:flex; justify-content:space-between; align-items:center;">
|
|
163
|
+
<h3 style="margin:0;">Manage Keys</h3>
|
|
164
|
+
<button id="close-pkfk-modal" style="background:none; border:none; color:var(--color-text-primary); cursor:pointer;"><span class="material-symbols-outlined">close</span></button>
|
|
165
|
+
</div>
|
|
166
|
+
<div style="padding:16px; display:flex; flex-direction:column; gap:16px;">
|
|
167
|
+
<label style="display:flex; align-items:center; gap:8px; cursor:pointer;">
|
|
168
|
+
<input type="checkbox" id="modal-is-pk" ${i?`checked`:``} />
|
|
169
|
+
<strong>Primary Key (PK)</strong>
|
|
170
|
+
</label>
|
|
171
|
+
|
|
172
|
+
<div style="border-top: 1px solid var(--color-border); margin: 8px 0;"></div>
|
|
173
|
+
|
|
174
|
+
<label style="display:flex; align-items:center; gap:8px; cursor:${r?`pointer`:`not-allowed`}; opacity:${r?`1`:`0.6`};">
|
|
175
|
+
<input type="checkbox" id="modal-is-fk" ${a?`checked`:``} ${r?``:`disabled`} />
|
|
176
|
+
<strong>Foreign Key (FK)</strong>
|
|
177
|
+
</label>
|
|
178
|
+
|
|
179
|
+
${r?``:`<div style="font-size:11px; color:var(--color-text-soft); margin-top:-12px; margin-left:24px;">Note: FKs can only be added when creating new columns.</div>`}
|
|
180
|
+
|
|
181
|
+
<div id="fk-settings-container" style="display:${a?`flex`:`none`}; flex-direction:column; gap:8px; padding-left: 24px;">
|
|
182
|
+
<div>
|
|
183
|
+
<div style="font-size:12px; color:var(--color-text-secondary); margin-bottom:4px;">Target Table</div>
|
|
184
|
+
<select id="modal-fk-table" style="width:100%; padding:6px; border-radius:4px; border:1px solid var(--color-border); background:var(--color-bg-primary); color:var(--color-text-primary);">
|
|
185
|
+
<option value="">Loading tables...</option>
|
|
186
|
+
</select>
|
|
187
|
+
</div>
|
|
188
|
+
<div>
|
|
189
|
+
<div style="font-size:12px; color:var(--color-text-secondary); margin-bottom:4px;">Target Column</div>
|
|
190
|
+
<select id="modal-fk-col" style="width:100%; padding:6px; border-radius:4px; border:1px solid var(--color-border); background:var(--color-bg-primary); color:var(--color-text-primary);" ${o?``:`disabled`}>
|
|
191
|
+
<option value="">Select a table first</option>
|
|
192
|
+
</select>
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
<div style="padding:16px; border-top:1px solid var(--color-border); background:var(--color-bg-secondary); display:flex; justify-content:flex-end; gap:8px;">
|
|
197
|
+
<button id="cancel-pkfk-btn" class="secondary" style="padding:6px 16px; border-radius:4px; border:1px solid var(--color-border); cursor:pointer;">Cancel</button>
|
|
198
|
+
<button id="save-pkfk-btn" class="primary" style="padding:6px 16px; border-radius:4px; border:none; cursor:pointer;">Save</button>
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
`,document.body.appendChild(n);let c=()=>n.remove();document.getElementById(`close-pkfk-modal`).onclick=c,document.getElementById(`cancel-pkfk-btn`).onclick=c;let l=document.getElementById(`modal-is-fk`),u=document.getElementById(`fk-settings-container`),d=document.getElementById(`modal-fk-table`),f=document.getElementById(`modal-fk-col`);l.addEventListener(`change`,e=>{u.style.display=e.target.checked?`flex`:`none`});try{let e=await(await fetch(`/api/tables`)).json();e.success&&e.data&&(d.innerHTML=`<option value="">-- Select Table --</option>`+e.data.map(e=>`<option value="${e}" ${e===o?`selected`:``}>${e}</option>`).join(``),o&&p(o,s))}catch{d.innerHTML=`<option value="">Error loading tables</option>`}async function p(e,t=``){f.disabled=!0,f.innerHTML=`<option value="">Loading columns...</option>`;try{let n=await(await fetch(`/api/tables/${e}/schema`)).json();n.success&&n.data&&(f.innerHTML=`<option value="">-- Select Column --</option>`+n.data.map(e=>`<option value="${e.name}" ${e.name===t?`selected`:``}>${e.name}</option>`).join(``),f.disabled=!1)}catch{f.innerHTML=`<option value="">Error loading columns</option>`}}d.addEventListener(`change`,e=>{let t=e.target.value;t?p(t):(f.innerHTML=`<option value="">Select a table first</option>`,f.disabled=!0)}),document.getElementById(`save-pkfk-btn`).onclick=()=>{let t=document.getElementById(`modal-is-pk`).checked,n=document.getElementById(`modal-is-fk`).checked,r=d.value,l=f.value;if(t===i&&n===a&&r===o&&l===s){c();return}let u=``;if(t&&n){if(!r||!l){alert(`Please select both Target Table and Target Column for the Foreign Key.`);return}u=`PK, FK: ${r}.${l}`}else if(t)u=`PK`;else if(n){if(!r||!l){alert(`Please select both Target Table and Target Column for the Foreign Key.`);return}u=`FK: ${r}.${l}`}window.SchemaGrid.currentTransaction=[];let p=[`name`,`type`,`isPk`,`nullable`,`defaultValue`,`indexing`];D(async()=>{let{updateSchemaCell:e}=await Promise.resolve().then(()=>M);return{updateSchemaCell:e}},void 0,import.meta.url).then(({updateSchemaCell:t})=>{t(e,u,p),window.SchemaGrid.currentTransaction.length>0&&window.SchemaGrid.history.push(window.SchemaGrid.currentTransaction),window.SchemaGrid.currentTransaction=null}),c()}}function B(e,t){e.addEventListener(`click`,e=>{e.target.closest(`.manage-indexes-cell`)&&R()}),e.addEventListener(`dblclick`,e=>{let n=e.target.closest(`td.data-cell`);if(!n||n.querySelector(`input, select`))return;let r=n.dataset.colKey;n.dataset.insertIndex;let i=n.textContent===`-`||n.textContent===`+ New`||n.textContent===`No`||n.textContent===`null`?``:n.textContent===`Yes`?`1`:n.textContent,a;if(r===`isPk`){z(n,n.textContent);return}else if(r===`nullable`)a=document.createElement(`select`),[`No`,`Yes`].forEach(e=>{let t=document.createElement(`option`);t.value=e,t.textContent=e,(e===`Yes`&&i===`1`||e===`No`&&i===``)&&(t.selected=!0),a.appendChild(t)});else if(r===`type`){a=document.createElement(`select`);let e=[`INTEGER`,`TEXT`,`REAL`,`BLOB`,`NUMERIC`,`BOOLEAN`,`DATE`,`DATETIME`,`JSON`,`VARCHAR(255)`,`DECIMAL(10,2)`,`UUID`];i&&!e.some(e=>e.toUpperCase()===i.toUpperCase())&&e.unshift(i),e.forEach(e=>{let t=document.createElement(`option`);t.value=e,t.textContent=e,e.toUpperCase()===i.toUpperCase()&&(t.selected=!0),a.appendChild(t)})}else a=document.createElement(`input`),a.type=`text`,a.value=i;n.innerHTML=``,n.appendChild(a),a.style.width=`100%`,a.addEventListener(`keydown`,e=>{e.key===`Enter`&&a.blur()}),a.focus();let o=()=>{let e=a.value;window.SchemaGrid.currentTransaction=[],P(n,e,t),window.SchemaGrid.currentTransaction.length>0&&window.SchemaGrid.history.push(window.SchemaGrid.currentTransaction),window.SchemaGrid.currentTransaction=null};a.addEventListener(`blur`,()=>{o()})})}async function V(e,t,n=null){document.querySelectorAll(`.table-btn`).forEach(e=>e.classList.remove(`active`)),t&&t.classList.add(`active`);let r=document.getElementById(`table-name`);r&&(r.textContent=e+` (Schema)`);let i=n||document.getElementById(`main-content`);i.innerHTML=`<div style='padding:24px;'>Loading Schema...</div>`;try{let[n,r]=await Promise.all([l(e),u(e)]);if(n.success&&n.data){let a=n.data,o=r.success&&r.data?r.data:[];window.SchemaGrid={schema:a,indexes:o,pendingEdits:{},pendingIndexEdits:{added:[],dropped:[]},pendingInserts:[{}],pendingDeletes:new Set,selectedCell:null,history:[],currentTransaction:null,sortState:{colKey:null,asc:!0},filterText:``,isResizing:!1,selection:{startRow:-1,startCol:-1,endRow:-1,endCol:-1,isDragging:!1}},window.TableStates&&window.TableStates[e]&&(window.TableStates[e].schemaGrid=window.SchemaGrid),i.innerHTML=`
|
|
202
|
+
<div class="toolbar">
|
|
203
|
+
<div class="filter-group">
|
|
204
|
+
<div class="filter-icon-container">
|
|
205
|
+
<span class="material-symbols-outlined">search</span>
|
|
206
|
+
<span>Search</span>
|
|
207
|
+
</div>
|
|
208
|
+
<input type="text" id="schema-search-val-${e}" class="filter-input" placeholder="Search name or type..." style="width: 250px;" value="${window.SchemaGrid.filterText}" />
|
|
209
|
+
</div>
|
|
210
|
+
<div style="flex:1;"></div>
|
|
211
|
+
<button id="btn-refresh-schema-${e}" class="refresh-btn" title="Refresh Schema (F5)"><span class="material-symbols-outlined">refresh</span></button>
|
|
212
|
+
</div>
|
|
213
|
+
<div id="schema-grid-container-${e}" class="table-container"></div>
|
|
214
|
+
`,window.renderSchemaGrid=()=>{let t=document.getElementById(`schema-grid-container-${e}`);if(!t)return;let n=[...window.SchemaGrid.schema];if(window.SchemaGrid.filterText){let e=window.SchemaGrid.filterText.toLowerCase();n=n.filter(t=>t.name&&t.name.toLowerCase().includes(e)||t.type&&t.type.toLowerCase().includes(e))}window.SchemaGrid.sortState.colKey&&n.sort((e,t)=>{let n=window.SchemaGrid.sortState.colKey,r=e[n],i=t[n];return r??=``,i??=``,r<i?window.SchemaGrid.sortState.asc?-1:1:r>i?window.SchemaGrid.sortState.asc?1:-1:0});let r=[`name`,`type`,`isPk`,`nullable`,`defaultValue`,`indexing`],i=[`Name`,`Type`,`PK/FK`,`Nullable`,`Default Value`,`Indexing`],a=`<table class="data-table" id="schema-grid-table-${e}"><thead><tr><th class="row-header">#</th>`;r.forEach((e,t)=>{let n=``;window.SchemaGrid.sortState.colKey===e&&(n=window.SchemaGrid.sortState.asc?`▲`:`▼`),a+=`<th class="sortable" data-col-key="${e}">
|
|
215
|
+
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
216
|
+
<div>${i[t]}</div>
|
|
217
|
+
<div class="sort-arrow" style="font-size:10px; opacity:0.8; margin-left: 8px; width: 12px; text-align: right;">${n}</div>
|
|
218
|
+
</div>
|
|
219
|
+
</th>`}),a+=`</tr></thead><tbody>`,n&&n.length>0&&n.forEach((e,t)=>{a+=`<tr><td class="row-header" data-row-idx="${t}">${t+1}</td>`,r.forEach((r,i)=>{if(r===`indexing`){if(t===0){let e=(n?n.length:0)+1,t=window.SchemaGrid.indexes.length,r=window.SchemaGrid.pendingIndexEdits.added.length,i=window.SchemaGrid.pendingIndexEdits.dropped.length,o=t+r-i;a+=`<td class="data-cell manage-indexes-cell" rowspan="${e}" style="text-align:center; vertical-align:middle; cursor:pointer; color:var(--color-brand-500); font-weight:500; border-left: 1px solid var(--color-border);">
|
|
220
|
+
Manage Indexes (${o})
|
|
221
|
+
</td>`}return}let o=e[r];if(r===`isPk`){let t=o,n=!!e.fkTarget;o=t&&n?`PK, FK (${e.fkTarget.table}.${e.fkTarget.column})`:t?`PK`:n?`FK (${e.fkTarget.table}.${e.fkTarget.column})`:`-`}else r===`nullable`?o=o?`Yes`:`No`:o??=``;let s=String(o).replace(/"/g,`"`),c=o===``?`<span style="color:var(--color-text-soft)">-</span>`:String(o).replace(/</g,`<`);a+=`<td class="data-cell" data-row-idx="${t}" data-col-idx="${i}" data-pk="${e.name}" data-col-key="${r}" data-original="${s}">${c}</td>`}),a+=`</tr>`}),a+=`<tr class="ghost-row-tr">`;let o=n?n.length:0;a+=`<td class="row-header" data-row-idx="${o}">*</td>`,r.forEach((e,t)=>{e!==`indexing`&&(a+=`<td class="data-cell ghost-row" data-row-idx="${o}" data-col-idx="${t}" data-insert-index="0" data-col-key="${e}">+ New</td>`)}),a+=`</tr></tbody></table>`,t.innerHTML=a,document.querySelectorAll(`#schema-grid-table-${e} th.sortable`).forEach(e=>{e.onclick=t=>{if(window.SchemaGrid.isResizing)return;if(Object.keys(window.SchemaGrid.pendingEdits).length>0||window.SchemaGrid.pendingInserts.length>1||window.SchemaGrid.pendingDeletes.size>0||window.SchemaGrid.pendingIndexEdits.added.length>0||window.SchemaGrid.pendingIndexEdits.dropped.length>0){alert(`You have unsaved changes! Please press Ctrl+S to save them before sorting.`);return}let n=e.dataset.colKey;window.SchemaGrid.sortState.colKey===n?window.SchemaGrid.sortState.asc=!window.SchemaGrid.sortState.asc:(window.SchemaGrid.sortState.colKey=n,window.SchemaGrid.sortState.asc=!0),window.SchemaGrid.selection={startRow:-1,startCol:-1,endRow:-1,endCol:-1,isDragging:!1},window.renderSchemaGrid()},_(e,window.SchemaGrid)}),h(t,`schema-grid-table-${e}`,window.SchemaGrid,r.length),B(t,r)},window.renderSchemaGrid();let s=document.getElementById(`schema-search-val-${e}`);s&&s.addEventListener(`input`,e=>{window.SchemaGrid.filterText=e.target.value,window.SchemaGrid.selection={startRow:-1,startCol:-1,endRow:-1,endCol:-1,isDragging:!1},window.renderSchemaGrid()});let c=document.getElementById(`btn-refresh-schema-${e}`);c&&(c.onclick=()=>{(Object.keys(window.SchemaGrid.pendingEdits).length>0||window.SchemaGrid.pendingInserts.length>1||window.SchemaGrid.pendingDeletes.size>0||window.SchemaGrid.pendingIndexEdits.added.length>0||window.SchemaGrid.pendingIndexEdits.dropped.length>0)&&!confirm(`You have unsaved changes. Are you sure you want to refresh and discard them?`)||(window.SchemaGrid.pendingEdits={},window.SchemaGrid.pendingInserts=[{}],window.SchemaGrid.pendingDeletes.clear(),window.SchemaGrid.pendingIndexEdits={added:[],dropped:[]},window.SchemaGrid.history=[],window.SchemaGrid.currentTransaction=null,window.updateSidebarDirtyState?.(),V(e,t,document.getElementById(`view-schema-btn-${e}`)))})}else i.innerHTML=`<div style="padding:24px; color:red;">Error: ${n.error}</div>`}catch(e){i.innerHTML=`<div style="padding:24px; color:red;">Failed to load schema: ${e.message}</div>`}}function H(e,t){document.querySelectorAll(`.table-btn`).forEach(e=>e.classList.remove(`active`)),t&&t.classList.add(`active`);let n=document.getElementById(`table-name`);n&&(n.textContent=`SQL Console`);let r=document.getElementById(`main-content`);r.innerHTML=`
|
|
222
|
+
<div id="console-container" style="display: flex; flex-direction: column; flex: 1; height: 100%; min-width: 0;">
|
|
223
|
+
<div id="console-editor-pane" style="flex: 1; display: flex; flex-direction: column; border-bottom: 1px solid var(--color-border); position: relative; min-height: 200px;">
|
|
224
|
+
<div id="sql-editor" style="flex: 1; font-size: 14px;"></div>
|
|
225
|
+
<button id="run-sql-btn" class="primary" style="position: absolute; bottom: 16px; right: 24px; padding: 8px 16px; border-radius: 6px; border: none; background-color: var(--color-primary); color: #fff; font-weight: 600; cursor: pointer; box-shadow: 0 4px 6px rgba(0,0,0,0.1); z-index: 50; display: flex; align-items: center; gap: 6px; transition: all 0.2s;">
|
|
226
|
+
<span class="material-symbols-outlined" style="font-size: 18px;">play_arrow</span> Run (Ctrl+Enter)
|
|
227
|
+
</button>
|
|
228
|
+
</div>
|
|
229
|
+
<div id="console-results-pane" style="flex: 1; display: flex; flex-direction: column; overflow: hidden; background: #fff; min-height: 200px;">
|
|
230
|
+
<div id="console-results-header" style="padding: 8px 16px; background-color: var(--color-bg-secondary); border-bottom: 1px solid var(--color-border); font-size: 12px; color: var(--color-text-soft); font-weight: 600;">RESULTS</div>
|
|
231
|
+
<div class="table-container" id="console-table-container" style="flex: 1;">
|
|
232
|
+
<div style="padding: 24px; color: var(--color-text-soft); text-align: center; font-size: 14px;">Run a query to see results.</div>
|
|
233
|
+
</div>
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
`;let i=window.ace.edit(`sql-editor`);i.setTheme(`ace/theme/chrome`),i.session.setMode(`ace/mode/sql`),i.setOptions({showPrintMargin:!1,fontSize:`14px`,fontFamily:`ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace`,highlightActiveLine:!0}),window.AppState.lastQuery?i.setValue(window.AppState.lastQuery,1):i.setValue(`-- Enter your SQL query here
|
|
237
|
+
SELECT * FROM sqlite_master;
|
|
238
|
+
`,1),i.focus();let a=async()=>{let e=i.getValue().trim();if(!e)return;window.AppState.lastQuery=e;let t=document.getElementById(`console-table-container`),n=document.getElementById(`console-results-header`);n.textContent=`EXECUTING...`,n.style.color=`var(--color-primary)`,t.innerHTML=`<div style="padding: 24px; text-align: center; color: var(--color-text-soft);">Executing query...</div>`;try{let r=await d(e);if(!r.success){n.textContent=`ERROR`,n.style.color=`red`,t.innerHTML=`<div style="padding: 24px; color: red; font-family: monospace; white-space: pre-wrap;">${r.error}</div>`;return}let i=r.data.rows||[];if(n.textContent=`SUCCESS - ${i.length} rows returned`,n.style.color=`green`,i.length===0){t.innerHTML=`<div style="padding: 24px; text-align: center; color: var(--color-text-soft);">0 rows returned.</div>`;return}let a=Object.keys(i[0]),o=document.createElement(`table`);o.className=`data-table`;let s=document.createElement(`thead`),c=document.createElement(`tr`),l=document.createElement(`th`);l.className=`row-header`,l.textContent=`#`,c.appendChild(l),a.forEach(e=>{let t=document.createElement(`th`);t.textContent=e;let n=document.createElement(`div`);n.className=`resizer`,t.appendChild(n),n.addEventListener(`click`,e=>e.stopPropagation()),n.addEventListener(`mousedown`,e=>{e.preventDefault(),e.stopPropagation();let n=e.pageX,r=t.offsetWidth,i=e=>{let i=r+(e.pageX-n);t.style.width=i+`px`,t.style.minWidth=i+`px`,t.style.maxWidth=i+`px`},a=()=>{document.removeEventListener(`mousemove`,i),document.removeEventListener(`mouseup`,a),document.body.style.cursor=``};document.body.style.cursor=`col-resize`,document.addEventListener(`mousemove`,i),document.addEventListener(`mouseup`,a)}),c.appendChild(t)}),s.appendChild(c),o.appendChild(s);let u=document.createElement(`tbody`);i.forEach((e,t)=>{let n=document.createElement(`tr`),r=document.createElement(`td`);r.className=`row-header`,r.textContent=t+1,n.appendChild(r),a.forEach(t=>{let r=document.createElement(`td`),i=e[t];if(i===null){let e=document.createElement(`span`);e.textContent=`NULL`,e.style.color=`var(--color-text-soft)`,e.style.fontStyle=`italic`,r.appendChild(e)}else r.textContent=String(i);n.appendChild(r)}),u.appendChild(n)}),o.appendChild(u),t.innerHTML=``,t.appendChild(o)}catch(e){n.textContent=`ERROR`,n.style.color=`red`,t.innerHTML=`<div style="padding: 24px; color: red; font-family: monospace; white-space: pre-wrap;">${e.message}</div>`}};document.getElementById(`run-sql-btn`).onclick=a,i.commands.addCommand({name:`run`,bindKey:{win:`Ctrl-Enter`,mac:`Command-Enter`},exec:function(){a()}})}var U=document.getElementById(`header-container`),W=document.getElementById(`sidebar-container`),G=document.getElementById(`tab-container`);U.innerHTML=n,W.innerHTML=r,G.innerHTML=i,window.AppState={currentTable:null,currentTab:`data-btn`,currentTableBtnElement:null},window.TableStates={},window.ViewCache={},window.updateSidebarDirtyState=function(){document.querySelectorAll(`.table-btn`).forEach(e=>{let t=e.dataset.table,n=e.querySelector(`span`).textContent,r=t||n.replace(/\s*\*$/,``),i=window.TableStates[r],a=!1;if(i){if(i.dataGrid){let e=i.dataGrid;(Object.keys(e.pendingEdits||{}).length>0||e.pendingInserts&&e.pendingInserts.length>1||e.pendingDeletes&&e.pendingDeletes.size>0)&&(a=!0)}if(i.schemaGrid){let e=i.schemaGrid,t=e.pendingIndexEdits&&(e.pendingIndexEdits.added.length>0||e.pendingIndexEdits.dropped.length>0);(Object.keys(e.pendingEdits||{}).length>0||e.pendingInserts&&e.pendingInserts.length>1||e.pendingDeletes&&e.pendingDeletes.size>0||t)&&(a=!0)}}let o=e.querySelector(`span`),s=o.textContent.replace(/\s*\*$/,``);a?(o.textContent=s+` *`,o.style.fontWeight=`bold`):(o.textContent=s,o.style.fontWeight=`normal`)})},window.handleSwitchTab=function(e){document.querySelectorAll(`.tab-btn`).forEach(e=>e.classList.remove(`isCurrentTab`));let t=document.getElementById(e);if(t&&t.classList.add(`isCurrentTab`),window.AppState.currentTab=e,e===`erd-btn`||e===`sql-btn`||e===`status-btn`)window.AppState.currentTable=null,window.AppState.currentTableBtnElement=null,document.querySelectorAll(`.table-btn`).forEach(e=>e.classList.remove(`active`));else if((e===`data-btn`||e===`schema-btn`)&&!window.AppState.currentTable){let e=document.querySelector(`.table-btn`);e&&(window.AppState.currentTable=e.querySelector(`span`).textContent,window.AppState.currentTableBtnElement=e,e.classList.add(`active`))}window.renderCurrentView()},window.renderEmptyState=function(e){e.innerHTML=`
|
|
239
|
+
<div class="empty-state">
|
|
240
|
+
<div class="icon-container">
|
|
241
|
+
<span class="material-symbols-outlined">database</span>
|
|
242
|
+
</div>
|
|
243
|
+
<h2>No Table Selected</h2>
|
|
244
|
+
<p>Select a table from the sidebar to view its data, schema, or run SQL queries.</p>
|
|
245
|
+
</div>
|
|
246
|
+
`},window.renderCurrentView=function(e=``,t=!1){let n=[`erd-btn`,`sql-btn`,`status-btn`].includes(window.AppState.currentTab),r=document.getElementById(`main-content`);document.querySelectorAll(`.view-container`).forEach(e=>e.style.display=`none`);let i=n?`view-${window.AppState.currentTab}`:`view-${window.AppState.currentTab}-${window.AppState.currentTable}`,a=document.getElementById(i);if(a||(a=document.createElement(`div`),a.id=i,a.className=`view-container`,a.style.width=`100%`,a.style.flex=`1`,a.style.display=`flex`,a.style.flexDirection=`column`,a.style.overflow=`hidden`,r.appendChild(a)),a.style.display=`flex`,!window.AppState.currentTable&&!n){window.renderEmptyState(a);return}let o=window.AppState.currentTable;o&&!window.TableStates[o]&&(window.TableStates[o]={dataGrid:null,schemaGrid:null}),window.AppState.currentTab===`data-btn`?(window.TableStates[o].dataGrid&&(window.DataGrid=window.TableStates[o].dataGrid),(!window.TableStates[o].dataGrid||!a.hasChildNodes())&&j(o,window.AppState.currentTableBtnElement,e,t,a)):window.AppState.currentTab===`schema-btn`?(window.TableStates[o].schemaGrid&&(window.SchemaGrid=window.TableStates[o].schemaGrid),(!window.TableStates[o].schemaGrid||!a.hasChildNodes())&&V(o,window.AppState.currentTableBtnElement,a)):window.AppState.currentTab===`console-btn`?a.hasChildNodes()||H(o,window.AppState.currentTableBtnElement,a):window.AppState.currentTab===`erd-btn`?a.hasChildNodes()||(a.innerHTML=`<div style='padding:24px; color: var(--color-text-soft);'>ERD Visualization coming soon!</div>`):window.AppState.currentTab===`status-btn`&&(a.hasChildNodes()||(a.innerHTML=`<div style='padding:24px; color: var(--color-text-soft);'>Database Status Dashboard coming soon!</div>`)),document.querySelectorAll(`.table-btn`).forEach(e=>e.classList.remove(`active`)),window.AppState.currentTableBtnElement&&window.AppState.currentTableBtnElement.classList.add(`active`)},window.saveDataGridEdits=y,window.saveSchemaEdits=N,document.addEventListener(`DOMContentLoaded`,()=>{f();let e=localStorage.getItem(`drixio-theme`),t=window.matchMedia&&window.matchMedia(`(prefers-color-scheme: dark)`).matches;if(e===`dark`||!e&&t){document.documentElement.setAttribute(`data-theme`,`dark`);let e=document.getElementById(`theme-icon`);e&&(e.textContent=`light_mode`)}let n=document.getElementById(`theme-toggle`);n&&n.addEventListener(`click`,()=>{let e=document.documentElement.getAttribute(`data-theme`)===`dark`,t=e?`light`:`dark`;document.documentElement.setAttribute(`data-theme`,t),localStorage.setItem(`drixio-theme`,t),document.getElementById(`theme-icon`).textContent=e?`dark_mode`:`light_mode`}),window.showToast=function(e,t=`success`){let n=document.getElementById(`toast-container`);if(!n)return;let r=document.createElement(`div`);r.className=`toast ${t}`,r.innerHTML=`<span class="material-symbols-outlined">${t===`success`?`check_circle`:`error`}</span> <span>${e}</span>`,n.appendChild(r),setTimeout(()=>{r.parentNode&&r.parentNode.removeChild(r)},3e3)},document.addEventListener(`mouseup`,()=>{window.DataGrid&&window.DataGrid.selection&&(window.DataGrid.selection.isDragging=!1),window.SchemaGrid&&window.SchemaGrid.selection&&(window.SchemaGrid.selection.isDragging=!1)}),document.addEventListener(`contextmenu`,e=>{let t=window.AppState?.currentTab===`data-btn`,n=window.AppState?.currentTab===`schema-btn`;if(!t&&!n||t&&!window.DataGrid||n&&!window.SchemaGrid)return;let r=e.target.closest(`td.row-header`);if(!r)return;e.preventDefault();let i=parseInt(r.dataset.rowIdx);document.getElementById(`custom-context-menu`)?.remove();let a=document.createElement(`div`);a.id=`custom-context-menu`,a.className=`context-menu`,a.style.top=`${e.clientY}px`,a.style.left=`${e.clientX}px`,a.innerHTML=`
|
|
247
|
+
<div class="context-menu-item" id="cmenu-duplicate">
|
|
248
|
+
<span class="material-symbols-outlined" style="font-size:16px;">content_copy</span> Duplicate Row(s)
|
|
249
|
+
</div>
|
|
250
|
+
<div class="context-menu-item danger" id="cmenu-delete">
|
|
251
|
+
<span class="material-symbols-outlined" style="font-size:16px;">delete</span> Delete Row(s)
|
|
252
|
+
</div>
|
|
253
|
+
`,document.body.appendChild(a);let o=e=>{let r=[i],o=t?window.DataGrid:window.SchemaGrid;if(o&&o.selection&&o.selection.startRow!==-1){let e=o.selection,t=Math.min(e.startRow,e.endRow),n=Math.max(e.startRow,e.endRow);if(i>=t&&i<=n){r=[];for(let e=t;e<=n;e++)r.push(e)}}t?D(()=>Promise.resolve().then(()=>v).then(t=>{window.DataGrid.currentTransaction=[],e===`delete`?r.forEach(e=>t.markRowDeleted(e)):e===`duplicate`&&(t.duplicateDataRows(r,window.DataGrid.schema.map(e=>e.name)),setTimeout(()=>{let e=document.getElementById(`data-grid-container-${window.AppState.currentTable}`);e&&(e.scrollTop=e.scrollHeight)},50)),window.DataGrid.currentTransaction.length>0&&window.DataGrid.history.push(window.DataGrid.currentTransaction),window.DataGrid.currentTransaction=null}),void 0,import.meta.url):n&&D(()=>Promise.resolve().then(()=>M).then(t=>{window.SchemaGrid.currentTransaction=[],e===`delete`?r.forEach(e=>t.markSchemaRowDeleted(e)):e===`duplicate`&&(t.duplicateSchemaRows(r,[`name`,`type`,`isPk`,`nullable`,`defaultValue`,`Index`]),setTimeout(()=>{let e=document.getElementById(`schema-grid-container-${window.AppState.currentTable}`);e&&(e.scrollTop=e.scrollHeight)},50)),window.SchemaGrid.currentTransaction.length>0&&window.SchemaGrid.history.push(window.SchemaGrid.currentTransaction),window.SchemaGrid.currentTransaction=null}),void 0,import.meta.url),a.remove()};document.getElementById(`cmenu-duplicate`).onclick=()=>o(`duplicate`),document.getElementById(`cmenu-delete`).onclick=()=>o(`delete`);let s=e=>{a.contains(e.target)||(a.remove(),document.removeEventListener(`click`,s))};setTimeout(()=>document.addEventListener(`click`,s),0)}),document.addEventListener(`keydown`,e=>{let t=window.AppState?.currentTab===`data-btn`,n=window.AppState?.currentTab===`schema-btn`;if(e.key===`F5`){t&&window.DataGrid?.refreshData?(e.preventDefault(),window.DataGrid.refreshData()):n&&document.getElementById(`btn-refresh-schema`)&&(e.preventDefault(),document.getElementById(`btn-refresh-schema`).click());return}if(!(!t&&!n)&&!(e.target.tagName===`INPUT`||e.target.tagName===`SELECT`||e.target.tagName===`TEXTAREA`)){if([`ArrowUp`,`ArrowDown`,`ArrowLeft`,`ArrowRight`].includes(e.key)){let n=t?window.DataGrid:window.SchemaGrid;if(!n||!n.selection)return;e.preventDefault();let r=n.selection;if(r.startRow===-1)return;let i=t?n.schema.length:5,a=window.AppState?.currentTable,o=document.querySelectorAll(t?`#data-grid-table-${a} tbody tr`:`#schema-grid-table-${a} tbody tr`),s=o.length>0?o.length-1:0,c=e.shiftKey?r.endRow:r.startRow,l=e.shiftKey?r.endCol:r.startCol;e.key===`ArrowUp`&&(c=Math.max(0,c-1)),e.key===`ArrowDown`&&(c=Math.min(s,c+1)),e.key===`ArrowLeft`&&(l=Math.max(0,l-1)),e.key===`ArrowRight`&&(l=Math.min(i-1,l+1)),e.shiftKey?(r.endRow=c,r.endCol=l):(r.startRow=c,r.endRow=c,r.startCol=l,r.endCol=l);let u=t?`data-grid-table-${a}`:`schema-grid-table-${a}`;D(()=>Promise.resolve().then(()=>p).then(e=>e.renderSelection(u,n)),void 0,import.meta.url),setTimeout(()=>{let e=document.querySelector(t?`#data-grid-table-${a} td.data-cell[data-row-idx="${c}"][data-col-idx="${l}"]`:`#schema-grid-table-${a} td.data-cell[data-row-idx="${c}"][data-col-idx="${l}"]`);if(e){let n=document.getElementById(t?`data-grid-container`:`schema-grid-container`);if(n){let t=e.getBoundingClientRect(),r=n.getBoundingClientRect();t.bottom>r.bottom?n.scrollTop+=t.bottom-r.bottom+5:t.top<r.top+30&&(n.scrollTop-=r.top+30-t.top),t.right>r.right?n.scrollLeft+=t.right-r.right+5:t.left<r.left+50&&(n.scrollLeft-=r.left+50-t.left)}}},5);return}if((e.key===`Delete`||e.key===`Backspace`)&&(t?D(()=>Promise.resolve().then(()=>v).then(e=>{window.DataGrid.currentTransaction=[],document.querySelectorAll(`#data-grid-table-${window.AppState.currentTable} .cell-in-range`).forEach(t=>e.updateCell(t,``,window.DataGrid.schema.map(e=>e.name))),window.DataGrid.currentTransaction.length>0&&window.DataGrid.history.push(window.DataGrid.currentTransaction),window.DataGrid.currentTransaction=null}),void 0,import.meta.url):n&&D(()=>Promise.resolve().then(()=>M).then(e=>{window.SchemaGrid.currentTransaction=[];let t=[`name`,`type`,`isPk`,`nullable`,`defaultValue`];document.querySelectorAll(`#schema-grid-table-${window.AppState.currentTable} .cell-in-range`).forEach(n=>{(n.dataset.insertIndex!==void 0||n.dataset.colKey===`name`)&&e.updateSchemaCell(n,``,t)}),window.SchemaGrid.currentTransaction.length>0&&window.SchemaGrid.history.push(window.SchemaGrid.currentTransaction),window.SchemaGrid.currentTransaction=null}),void 0,import.meta.url)),e.key.toLowerCase()===`s`&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),t&&window.saveDataGridEdits(),n&&window.saveSchemaEdits()),e.key.toLowerCase()===`c`&&(e.ctrlKey||e.metaKey)){let e=(t?window.DataGrid:window.SchemaGrid).selection;if(e.startRow===-1)return;let n=Math.min(e.startRow,e.endRow),r=Math.max(e.startRow,e.endRow),i=Math.min(e.startCol,e.endCol),a=Math.max(e.startCol,e.endCol),o=``;for(let e=n;e<=r;e++){let n=[];for(let r=i;r<=a;r++){let i=document.querySelector(t?`#data-grid-table-${window.AppState.currentTable} td.data-cell[data-row-idx="${e}"][data-col-idx="${r}"]`:`#schema-grid-table-${window.AppState.currentTable} td.data-cell[data-row-idx="${e}"][data-col-idx="${r}"]`);if(i){let e=i.textContent.replace(/^null$|^\+ New$/,``);n.push(e)}}o+=n.join(` `)+`
|
|
254
|
+
`}navigator.clipboard.writeText(o.trimEnd()),document.querySelectorAll(`.cell-in-range`).forEach(e=>{e.style.backgroundColor=`#bfdbfe`,setTimeout(()=>e.style.backgroundColor=``,150)})}if(e.key===`-`&&(e.ctrlKey||e.metaKey)){e.preventDefault();let r=t?window.DataGrid:window.SchemaGrid,i=r.selection;if(i.startRow===-1)return;let a=Math.min(i.startRow,i.endRow),o=Math.max(i.startRow,i.endRow);t?D(()=>Promise.resolve().then(()=>v).then(e=>{r.currentTransaction=[];for(let t=a;t<=o;t++)e.markRowDeleted(t);r.currentTransaction.length>0&&r.history.push(r.currentTransaction),r.currentTransaction=null}),void 0,import.meta.url):n&&D(()=>Promise.resolve().then(()=>M).then(e=>{r.currentTransaction=[];for(let t=a;t<=o;t++)e.markSchemaRowDeleted(t);r.currentTransaction.length>0&&r.history.push(r.currentTransaction),r.currentTransaction=null}),void 0,import.meta.url)}if(e.key.toLowerCase()===`z`&&(e.ctrlKey||e.metaKey)){if(e.preventDefault(),t){let e=window.DataGrid.history?.pop();e&&D(()=>Promise.resolve().then(()=>v).then(t=>{let n=window.DataGrid.schema.map(e=>e.name);for(let r=e.length-1;r>=0;r--){let i=e[r];i.type===`delete`?t.unmarkRowDeleted(i.rowIdx,i.pk):t.updateCell(i.td,i.oldVal,n,!1)}}),void 0,import.meta.url)}else if(n){let e=window.SchemaGrid.history?.pop();e&&D(()=>Promise.resolve().then(()=>M).then(t=>{let n=[`name`,`type`,`isPk`,`nullable`,`defaultValue`];for(let r=e.length-1;r>=0;r--){let i=e[r];i.type===`delete`?t.unmarkSchemaRowDeleted(i.rowIdx,i.pk):t.updateSchemaCell(i.td,i.oldVal,n,!1)}}),void 0,import.meta.url)}}}}),document.addEventListener(`paste`,e=>{let t=window.AppState?.currentTab===`data-btn`,n=window.AppState?.currentTab===`schema-btn`;if(!t&&!n)return;let r=t?window.DataGrid:window.SchemaGrid;if(!r||e.target.tagName===`INPUT`||e.target.tagName===`SELECT`||e.target.tagName===`TEXTAREA`)return;let i=r.selection;if(i.startRow===-1)return;let a=e.clipboardData.getData(`text`);if(!a)return;e.preventDefault();let o=a.split(/\r?\n/).map(e=>e.split(` `)),s=Math.min(i.startRow,i.endRow),c=Math.min(i.startCol,i.endCol);r.currentTransaction=[],t?D(()=>Promise.resolve().then(()=>v).then(e=>{let t=r.schema.map(e=>e.name);o.forEach(n=>{n.forEach((n,r)=>{let i=c+r,a=document.querySelector(`#data-grid-table-${window.AppState.currentTable} td.data-cell[data-row-idx="${s}"][data-col-idx="${i}"]`);a&&e.updateCell(a,n,t)}),s++}),r.currentTransaction.length>0&&r.history.push(r.currentTransaction),r.currentTransaction=null}),void 0,import.meta.url):n&&D(()=>Promise.resolve().then(()=>M).then(e=>{let t=[`name`,`type`,`isPk`,`nullable`,`defaultValue`];o.forEach(n=>{n.forEach((n,r)=>{let i=c+r,a=document.querySelector(`#schema-grid-table-${window.AppState.currentTable} td.data-cell[data-row-idx="${s}"][data-col-idx="${i}"]`);a&&(a.dataset.insertIndex!==void 0||a.dataset.colKey===`name`)&&e.updateSchemaCell(a,n,t)}),s++}),r.currentTransaction.length>0&&r.history.push(r.currentTransaction),r.currentTransaction=null}),void 0,import.meta.url)})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap";:root{--color-bg-primary:#fff;--color-bg-secondary:#f8fafc;--color-bg-secondary-dark:#f1f5f9;--color-primary:#2c68ec;--color-primary-active:#eff6ff;--color-primary-dark:#285bb8;--color-text:#0f172a;--color-text-soft:#94a3b8;--color-text-secondary:#64748b;--color-border:#e2e8f0;--color-border-soft:#f1f5f9;--ring-primary-2:0 0 0 2px #2c68ec33;--font-inter:"Inter", sans-serif;--color-btn-active-text:var(--color-primary);--color-cell-range-bg:#dbeafe;--color-cell-edited-bg:#fffbeb;--color-cell-edited-text:#b45309;--color-cell-error-bg:#fef2f2;--color-row-deleted-bg:#fee2e2;--color-row-deleted-text:#ef4444;--color-ghost-row-bg:#f8fafc}[data-theme=dark]{--color-bg-primary:#0f172a;--color-bg-secondary:#1e293b;--color-bg-secondary-dark:#334155;--color-primary:#3b82f6;--color-primary-active:#1e3a8a;--color-primary-dark:#60a5fa;--color-text:#f8fafc;--color-text-soft:#64748b;--color-text-secondary:#cbd5e1;--color-border:#334155;--color-border-soft:#1e293b;--ring-primary-2:0 0 0 2px #3b82f633;--color-btn-active-text:#fff;--color-cell-range-bg:#3b82f626;--color-cell-edited-bg:#f59e0b26;--color-cell-edited-text:#fbbf24;--color-cell-error-bg:#ef444426;--color-row-deleted-bg:#ef444426;--color-row-deleted-text:#f87171;--color-ghost-row-bg:var(--color-bg-secondary)}body,html{background-color:var(--color-bg-primary);width:100vw;height:100vh;color:var(--color-text);font-family:var(--font-inter);margin:0;padding:0;display:flex;overflow:hidden}main{flex-direction:column;flex:1;min-width:0;display:flex}aside{border-right:1px var(--color-border) solid;box-sizing:border-box;flex-direction:column;width:256px;height:100vh;display:flex}#sidebar-header{border-bottom:1px var(--color-border-soft) solid;box-sizing:border-box;align-items:center;gap:8px;height:64px;padding:0 16px;display:flex}.table-btn{color:var(--color-text-secondary);cursor:pointer;letter-spacing:.5px;background-color:#0000;border:1px solid #0000;border-radius:8px;outline:none;justify-content:space-between;align-items:center;padding:10px 16px;font-size:12px;font-weight:500;transition:all .2s;display:flex}#sidebar-footer{flex:1;align-items:center;min-width:0;display:flex}aside{border-right:1px var(--color-border) solid;flex-direction:column;width:256px;height:100vh;display:flex}#sidebar-header{border-bottom:1px var(--color-border-soft) solid;align-items:center;gap:8px;height:64px;padding:0 16px;display:flex}#database-icon{color:var(--color-primary);font-size:26px}#brand-title{letter-spacing:.5px;align-items:center;gap:4px;margin:0;padding:0;font-size:16px;font-weight:bolder;line-height:1;display:flex}#brand-subtitle{background-color:var(--color-primary);color:#fff;border-radius:5px;align-items:center;height:100%;padding:4px 6px;font-size:12px;font-weight:600;line-height:1;display:flex}#sidebar-content{flex-direction:column;flex:1;gap:24px;padding:16px;display:flex}#search-bar{background-color:var(--color-bg-secondary);border:1px var(--color-border) solid;border-radius:8px;outline:none;align-items:center;padding:0 4px;transition:all .1s linear;display:flex;overflow:hidden}#search-bar:focus-within{border:1px var(--color-primary) solid;box-shadow:var(--ring-primary-2);background-color:var(--color-bg-primary);transform:scale(1.02)}#search-icon{color:var(--color-text-soft);margin:0 3px 0 6px;font-size:20px;transition:all .1s linear}#search-bar:focus-within #search-icon{color:var(--color-primary);transform:scale(1.15)}#search-input{width:100%;height:34px;color:var(--color-text);background-color:#0000;border:none;outline:none;font-size:12px}#search-input::placeholder{color:var(--color-text-soft)}#table-nav{flex-direction:column;flex:1;gap:6px;display:flex;overflow-y:auto}#table-nav::-webkit-scrollbar{width:4px}#table-nav::-webkit-scrollbar-track{background:0 0}#table-nav::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:4px}#table-nav::-webkit-scrollbar-thumb:hover{background:var(--color-text-soft)}.table-btn{color:var(--color-text-secondary);cursor:pointer;background-color:#0000;border:1px solid #0000;border-radius:8px;outline:none;justify-content:space-between;align-items:center;padding:10px 16px;font-size:12px;font-weight:500;transition:all .2s;display:flex}.table-btn:hover{background-color:var(--color-bg-secondary);color:var(--color-text)}.table-btn:active{transform:scale(.97)}.table-btn.active{background-color:var(--color-primary-active);border:1px var(--color-primary) solid;color:var(--color-btn-active-text);font-weight:600}.table-btn-badge{background-color:var(--color-bg-secondary-dark);color:var(--color-text-secondary);border-radius:10px;justify-content:center;align-items:center;min-width:16px;min-height:16px;padding:1px;font-size:8px;font-weight:600;line-height:1;display:flex}.table-btn.active .table-btn-badge{background-color:var(--color-primary);color:#fff}#not-found-msg{color:var(--color-text-soft);flex:1;justify-content:center;align-items:center;font-size:12px;font-weight:400;display:flex}#sidebar-footer{border-top:1px var(--color-border-soft) solid;justify-content:center;align-items:center;max-height:fit-content;margin-top:auto;padding:16px;display:flex}#theme-toggle{background-color:var(--color-bg-secondary);color:var(--color-text-secondary);border:1px var(--color-border) solid;cursor:pointer;border-radius:8px;outline:none;justify-content:center;align-items:center;gap:8px;width:100%;padding:12px 24px;font-weight:600;transition:all .1s linear;display:flex}#theme-toggle:hover{color:var(--color-primary);border-color:var(--color-primary);background-color:var(--color-bg-primary)}header{border-bottom:1px var(--color-border) solid;box-sizing:border-box;justify-content:space-between;align-items:center;width:100%;height:64px;padding:0 32px;font-size:14px;font-weight:300;display:flex;position:sticky;top:0}#current-path{text-transform:lowercase;align-items:center;gap:10px;display:flex}#db-name{color:var(--color-text-secondary)}#slash{color:var(--color-text-soft);font-size:18px;font-weight:lighter}#current-table{align-items:center;gap:4px;display:flex}#table-icon{color:var(--color-primary);font-size:20px}#table-name{color:var(--color-text);font-weight:600}#tab-nav{border-bottom:1px var(--color-border) solid;gap:24px;height:48px;padding:0 32px;display:flex}.tab-btn{height:100%;color:var(--color-text-secondary);cursor:pointer;background-color:#0000;border:none;border-bottom:2px solid #0000;outline:none;align-items:center;gap:8px;padding:0 6px;font-size:12px;font-weight:300;line-height:1;transition:all .1s linear;display:flex}.tab-btn:hover{border-bottom:2px var(--color-border) solid;color:var(--color-text)}.tab-btn.isCurrentTab{border-bottom:2px var(--color-primary) solid;color:var(--color-primary)}.tab-btn .material-symbols-outlined{font-size:16px}#main-content{background-color:var(--color-bg-primary);flex-direction:column;flex:1;min-width:0;display:flex;overflow:hidden}.toolbar{border-bottom:1px var(--color-border) solid;background-color:var(--color-bg-secondary);flex-shrink:0;align-items:center;height:48px;display:flex}.filter-group{flex:1;align-items:center;height:100%;transition:all .15s;display:flex;overflow:hidden}.filter-icon-container{background-color:var(--color-bg-secondary);border-right:1px var(--color-border) solid;align-items:center;gap:6px;height:100%;padding:0 16px;font-size:16px;display:flex}.filter-icon-container .material-symbols-outlined{color:var(--color-text-secondary);font-size:18px}.filter-icon-container span:not(.material-symbols-outlined){text-transform:uppercase;color:var(--color-text-secondary);font-size:13px;font-weight:500}.filter-select{height:100%;color:var(--color-text-secondary);border:none;border-right:1px var(--color-border) solid;cursor:pointer;background-color:#0000;outline:none;padding:0 16px;font-size:13px;font-weight:500}.filter-select:hover{background-color:var(--color-bg-secondary)}.filter-input{height:100%;color:var(--color-text);background:0 0;border:none;outline:none;flex:1;padding:0 20px;font-size:13px;font-weight:200}.filter-input::placeholder{color:var(--color-text-soft)}#btn-run-query{background-color:var(--color-primary);color:#fff;border:none;border-right:1px var(--color-border) solid;cursor:pointer;border-radius:8px;outline:none;justify-content:center;align-items:center;gap:8px;padding:8px 12px;font-size:10px;font-weight:700;transition:all .1s linear;display:flex}#btn-run-query:hover{background-color:var(--color-primary-dark)}#btn-run-query .material-symbols-outlined{margin-bottom:.5px;font-size:16px}#btn-clear-query{background-color:var(--color-bg-primary);color:var(--color-text-secondary);border:none;border:1px var(--color-border) solid;cursor:pointer;border-radius:8px;outline:none;justify-content:center;align-items:center;gap:8px;margin-left:16px;padding:8px 12px;font-size:10px;font-weight:700;transition:all .1s linear;display:flex}#btn-clear-query:hover{background-color:var(--color-bg-secondary-dark);color:var(--color-text)}#btn-run-query:active,#btn-clear-query:active,.btn-primary:active,.btn-secondary:active,.table-btn:active{transform:scale(.96)}#btn-clear-query .material-symbols-outlined{margin-bottom:.5px;font-size:16px}.refresh-btn{background-color:var(--color-bg-secondary);border:1px var(--color-border) solid;color:var(--color-text-secondary);cursor:pointer;border-radius:8px;outline:none;justify-content:center;align-items:center;gap:8px;margin:16px;padding:6px;font-size:10px;font-weight:700;transition:all .1s linear;display:flex}.refresh-btn:hover{background-color:var(--color-bg-secondary-dark);color:var(--color-text)}.refresh-btn .material-symbols-outlined{margin-bottom:.5px;font-size:18px}.sql-console-wrapper{flex-direction:column;height:100%;display:flex}.sql-editor{resize:vertical;border:none;border-bottom:1px var(--color-border) solid;background-color:var(--color-bg-primary);width:100%;height:200px;min-height:100px;color:var(--color-text);outline:none;padding:16px;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:13px}.sql-editor:focus{background-color:#fcfcfc}.table-container{background-color:var(--color-bg-primary);scrollbar-width:none;-ms-overflow-style:none;flex:1;width:100%;min-width:0;overflow:auto}.table-container::-webkit-scrollbar{display:none}.data-table{border-collapse:separate;border-spacing:0;-webkit-user-select:none;user-select:none;width:max-content;min-width:100%}.data-table input,.data-table select{-webkit-user-select:text;user-select:text;box-sizing:border-box}.data-table th,.data-table td{text-align:left;border-bottom:1px var(--color-border-soft) solid;border-right:1px var(--color-border-soft) solid;white-space:nowrap;cursor:cell;height:24px;padding:8px 16px;font-size:13px;position:relative}.data-table th{background-color:var(--color-primary);color:#fff;text-transform:uppercase;letter-spacing:.5px;z-index:10;border-bottom:1px var(--color-border) solid;box-shadow:0 1px 0 var(--color-border);cursor:default;border-right:1px solid #fff3;font-size:11px;font-weight:600;position:sticky;top:0}.data-table td.cell-in-range{background-color:var(--color-cell-range-bg)}.data-table td.cell-in-range:after{content:"";box-sizing:border-box;pointer-events:none;border-top:var(--border-t,0);border-bottom:var(--border-b,0);border-left:var(--border-l,0);border-right:var(--border-r,0);position:absolute;inset:0}.data-table td.range-top{--border-t:2px solid var(--color-primary)}.data-table td.range-bottom{--border-b:2px solid var(--color-primary)}.data-table td.range-left{--border-l:2px solid var(--color-primary)}.data-table td.range-right{--border-r:2px solid var(--color-primary)}.data-table td.cell-selected{background-color:var(--color-bg-primary);z-index:5;box-shadow:inset 0 0 0 2px var(--color-primary)}.data-table td.row-header,.data-table th.row-header{z-index:9;background-color:var(--color-bg-secondary);color:var(--color-text-soft);text-align:center;border-right:1px var(--color-border) solid;width:32px;min-width:32px;padding:8px 4px;font-weight:500;position:sticky;left:0}.data-table th.row-header{z-index:11;background-color:var(--color-primary);color:#fff}.data-table td.cell-edited{background-color:var(--color-cell-edited-bg);color:var(--color-cell-edited-text);font-weight:700}.data-table td.cell-error{background-color:var(--color-cell-error-bg)}.data-table td.cell-error:not(.cell-in-range):not(.cell-selected){box-shadow:inset 0 0 0 2px #ef4444}.data-table tr.row-deleted td{text-decoration:line-through;background-color:var(--color-row-deleted-bg)!important;color:var(--color-row-deleted-text)!important}.data-table td.ghost-row{color:var(--color-text-soft);background-color:var(--color-ghost-row-bg);font-style:italic}.data-table td input,.data-table td select{box-sizing:border-box;width:100%;height:100%;color:var(--color-text);background-color:var(--color-bg-primary);box-shadow:var(--ring-primary-2);border:none;outline:none;padding:0 16px;font-family:inherit;font-size:13px;position:absolute;top:0;left:0}.data-table tbody tr:hover:not(:has(.manage-indexes-cell:hover)){background-color:var(--color-bg-secondary)}.manage-indexes-cell{background-color:var(--color-bg-primary)!important}.manage-indexes-cell:hover{background-color:var(--color-bg-secondary)!important}.context-menu{background-color:var(--color-bg-primary);border:1px var(--color-border) solid;z-index:9999;border-radius:6px;flex-direction:column;min-width:150px;padding:4px;display:flex;position:absolute;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.context-menu-item{color:var(--color-text);cursor:pointer;border-radius:4px;align-items:center;gap:8px;padding:8px 12px;font-size:13px;display:flex}.context-menu-item:hover{background-color:var(--color-bg-secondary)}.context-menu-item.danger{color:#ef4444}.context-menu-item.danger:hover{background-color:#fef2f2}.resizer{cursor:col-resize;-webkit-user-select:none;user-select:none;z-index:10;width:8px;height:100%;position:absolute;top:0;right:-4px}.resizer:hover,.resizer:active{background-color:var(--color-primary);opacity:.5}.cell-expand-btn{cursor:pointer;color:var(--color-text-soft);background-color:var(--color-bg-primary);border:1px var(--color-border) solid;z-index:10;border-radius:4px;justify-content:center;align-items:center;padding:3px;font-size:14px;transition:all .1s;display:flex;position:absolute;top:50%;right:6px;transform:translateY(-50%);box-shadow:0 2px 4px #0000000d}.cell-expand-btn:hover{color:var(--color-primary);border-color:var(--color-primary)}#modal-editor-overlay{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:9999;background-color:#0f172a66;justify-content:center;align-items:center;width:100vw;height:100vh;display:flex;position:fixed;top:0;left:0}.modal-editor-container{background-color:var(--color-bg-primary);background-color:rgba(var(--color-bg-primary), .85);background:var(--color-bg-primary);border-radius:12px;flex-direction:column;width:600px;max-width:90vw;height:500px;max-height:90vh;display:flex;overflow:hidden;box-shadow:0 10px 25px -5px #0000001a,0 8px 10px -6px #0000001a}.modal-header{border-bottom:1px var(--color-border) solid;color:var(--color-text);align-items:center;gap:8px;padding:16px 20px;display:flex}.modal-header h3{margin:0;font-size:16px;font-weight:600}.modal-header .material-symbols-outlined{color:var(--color-primary)}#modal-textarea{resize:none;color:var(--color-text);background-color:var(--color-bg-secondary-dark);border:none;outline:none;flex:1;padding:20px;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:13px}#modal-textarea:focus{background-color:var(--color-bg-primary)}.modal-footer{border-top:1px var(--color-border) solid;background-color:var(--color-bg-secondary);justify-content:flex-end;gap:12px;padding:16px 20px;display:flex}.modal-footer button{cursor:pointer;border:1px var(--color-border) solid;background-color:var(--color-bg-primary);color:var(--color-text);border-radius:6px;padding:8px 16px;font-size:13px;font-weight:500;transition:all .2s}.modal-footer button:active{transform:scale(.97)}.modal-footer button:hover{background-color:var(--color-bg-secondary-dark)}.modal-footer button.primary{background-color:var(--color-primary);color:#fff;border-color:var(--color-primary)}.modal-footer button.primary:hover{background-color:var(--color-primary-dark)}.empty-state{flex-direction:column;flex:1;justify-content:center;align-items:center;display:flex}.empty-state .icon-container{background-color:var(--color-primary);color:#fff;border-radius:10px;justify-content:center;align-items:center;width:64px;height:64px;display:flex;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.empty-state .material-symbols-outlined{font-size:36px}.empty-state h2{color:var(--color-text);margin-top:32px;margin-bottom:10px;font-size:24px;font-weight:700}.empty-state p{color:var(--color-text-secondary);text-align:center;max-width:500px;margin:0;font-size:16px;line-height:1.5}#toast-container{z-index:10000;flex-direction:column;gap:10px;display:flex;position:fixed;bottom:20px;right:20px}.toast{background-color:var(--color-bg-primary);color:var(--color-text);border-left:4px solid var(--color-primary);opacity:0;border-radius:8px;align-items:center;gap:8px;padding:12px 20px;font-size:14px;font-weight:500;animation:.3s ease-out forwards slideIn,.3s ease-in 2.7s forwards fadeOut;display:flex;transform:translate(100%);box-shadow:0 4px 12px #00000026}.toast.error{border-left-color:#ef4444}@keyframes slideIn{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}#theme-toggle{color:var(--color-text-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:6px;transition:all .2s;display:flex}#theme-toggle:hover{background-color:var(--color-bg-secondary);color:var(--color-text)}#theme-toggle:active{transform:scale(.9)}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<link
|
|
7
|
+
rel="stylesheet"
|
|
8
|
+
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200"
|
|
9
|
+
/>
|
|
10
|
+
|
|
11
|
+
<title>DRIXIO STUDIO</title>
|
|
12
|
+
<!-- Ace Editor for SQL Console -->
|
|
13
|
+
<script
|
|
14
|
+
src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.7/ace.js"
|
|
15
|
+
integrity="sha512-V127u0iE/681x9Z+S3Xz/2aQeY6k/Q+TtwO046sA4K8E0KqNqP/n139xJqG1oE31g3m8L7u5T1WwH0tOWePjxw=="
|
|
16
|
+
crossorigin="anonymous"
|
|
17
|
+
referrerpolicy="no-referrer"
|
|
18
|
+
></script>
|
|
19
|
+
<script type="module" crossorigin src="./assets/index-B2SFgnu7.js"></script>
|
|
20
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CCy0fVAv.css">
|
|
21
|
+
</head>
|
|
22
|
+
|
|
23
|
+
<body>
|
|
24
|
+
<div id="sidebar-container"></div>
|
|
25
|
+
<main>
|
|
26
|
+
<div id="header-container"></div>
|
|
27
|
+
<div id="tab-container"></div>
|
|
28
|
+
<div id="main-content"></div>
|
|
29
|
+
</main>
|
|
30
|
+
|
|
31
|
+
<div id="modal-editor-overlay" style="display: none">
|
|
32
|
+
<div class="modal-editor-container">
|
|
33
|
+
<div class="modal-header">
|
|
34
|
+
<span class="material-symbols-outlined">edit_document</span>
|
|
35
|
+
<h3 id="modal-title">Edit Cell</h3>
|
|
36
|
+
</div>
|
|
37
|
+
<textarea id="modal-textarea" placeholder="Enter value..."></textarea>
|
|
38
|
+
<div class="modal-footer">
|
|
39
|
+
<button type="button" id="modal-cancel-btn">Cancel</button>
|
|
40
|
+
<button type="button" id="modal-save-btn" class="primary">
|
|
41
|
+
Save
|
|
42
|
+
</button>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
<div id="toast-container"></div>
|
|
47
|
+
</body>
|
|
48
|
+
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drixio",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "A lightweight interactive TUI database client",
|
|
5
5
|
"bin": {
|
|
6
6
|
"drixio": "dist/cli.js"
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"dev": "tsx bin/cli.ts",
|
|
53
|
+
"dev:studio": "vite --config studio/vite.config.ts",
|
|
53
54
|
"build:cli": "tsup",
|
|
54
55
|
"build:studio": "vite build --config studio/vite.config.ts",
|
|
55
56
|
"build": "pnpm build:cli && pnpm build:studio"
|