drixio 1.1.0 β 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -25
- package/dist/cli.js +34 -34
- package/package.json +13 -3
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# π
|
|
1
|
+
# π Drixio - The Ultimate Zero-Dependency Database CLI & TUI
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**Drixio** is a lightning-fast, zero-dependency Database Manager designed entirely for your terminal. It supports **SQLite**, **PostgreSQL**, and **MySQL**.
|
|
4
4
|
|
|
5
|
-
Say goodbye to heavy GUI tools like DBeaver or TablePlus.
|
|
5
|
+
Say goodbye to heavy GUI tools like DBeaver or TablePlus. Drixio allows you to instantly view, edit, query, backup, and visually diagram your databases right from your CLI!
|
|
6
6
|
|
|
7
7
|
## β¨ Features
|
|
8
8
|
|
|
@@ -19,85 +19,85 @@ Say goodbye to heavy GUI tools like DBeaver or TablePlus. Drix allows you to ins
|
|
|
19
19
|
You don't need to install anything. Just run:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
npx
|
|
22
|
+
npx drixio
|
|
23
23
|
```
|
|
24
|
-
|
|
24
|
+
Drixio will automatically scan your project for a `.env` file containing a `DATABASE_URL` (e.g., `DATABASE_URL=postgres://user:pass@localhost:5432/mydb`). If it doesn't find one, it will launch a setup wizard to help you connect!
|
|
25
25
|
|
|
26
26
|
You can also pass a connection string directly:
|
|
27
27
|
```bash
|
|
28
|
-
npx
|
|
28
|
+
npx drixio "mysql://user:pass@localhost:3306/mydb"
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
33
33
|
## π οΈ Powerful Subcommands
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
Drixio is not just a TUI; it comes with powerful quick-commands for your CI/CD pipelines or rapid local development.
|
|
36
36
|
|
|
37
37
|
### π 1. Initialize a Local Database
|
|
38
|
-
Don't have a database yet?
|
|
38
|
+
Don't have a database yet? Drixio can create one for you!
|
|
39
39
|
```bash
|
|
40
|
-
npx
|
|
41
|
-
npx
|
|
42
|
-
npx
|
|
40
|
+
npx drixio init sqlite
|
|
41
|
+
npx drixio init postgres
|
|
42
|
+
npx drixio init mysql
|
|
43
43
|
```
|
|
44
44
|
*(For Postgres and MySQL, it connects to your local server and runs `CREATE DATABASE`, then automatically drops a configured `.env` file in your workspace!)*
|
|
45
45
|
|
|
46
46
|
### π 2. Quick Query
|
|
47
47
|
Run SQL instantly and get a beautifully formatted ASCII table result.
|
|
48
48
|
```bash
|
|
49
|
-
npx
|
|
49
|
+
npx drixio query "SELECT * FROM users WHERE age > 18"
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
### π₯ 3. Import Data
|
|
53
|
-
Import massive CSV or JSON files safely.
|
|
53
|
+
Import massive CSV or JSON files safely. Drixio uses smart chunking to prevent memory overload.
|
|
54
54
|
```bash
|
|
55
|
-
npx
|
|
55
|
+
npx drixio import data.csv --table users
|
|
56
56
|
```
|
|
57
57
|
|
|
58
58
|
### π€ 4. Export Data
|
|
59
59
|
Export your tables to CSV or JSON.
|
|
60
60
|
```bash
|
|
61
|
-
npx
|
|
62
|
-
npx
|
|
61
|
+
npx drixio export users --format csv
|
|
62
|
+
npx drixio export * --format json --schema-only
|
|
63
63
|
```
|
|
64
64
|
|
|
65
65
|
### π± 5. Generate Fake Data (Seed)
|
|
66
|
-
Need 500 fake users for testing? Easy.
|
|
66
|
+
Need 500 fake users for testing? Easy. Drixio intelligently analyzes your column names and types to generate realistic data.
|
|
67
67
|
```bash
|
|
68
|
-
npx
|
|
68
|
+
npx drixio seed users 500
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
### πΊοΈ 6. Generate ER Diagram
|
|
72
|
-
Automatically generates a `
|
|
72
|
+
Automatically generates a `drixio_schema.md` containing a Mermaid.js diagram of your database.
|
|
73
73
|
```bash
|
|
74
|
-
npx
|
|
74
|
+
npx drixio diagram
|
|
75
75
|
```
|
|
76
76
|
*Tip: Paste the output into Draw.io (Arrange > Insert > Advanced > Mermaid) for a stunning visual layout!*
|
|
77
77
|
|
|
78
78
|
### π§© 7. Generate TypeScript Interfaces
|
|
79
79
|
Tired of manually writing types? Auto-generate them from your schema!
|
|
80
80
|
```bash
|
|
81
|
-
npx
|
|
81
|
+
npx drixio generate-types
|
|
82
82
|
```
|
|
83
|
-
*(Outputs `
|
|
83
|
+
*(Outputs `drixio-types.d.ts` with all your table interfaces)*
|
|
84
84
|
|
|
85
85
|
### π 8. Execute SQL Script
|
|
86
86
|
Run entire `.sql` files instantly. Perfect for database migrations.
|
|
87
87
|
```bash
|
|
88
|
-
npx
|
|
88
|
+
npx drixio exec ./migrations/init.sql
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
### π¦ 9. Database Backup
|
|
92
92
|
Backup your entire database. For SQLite, it performs a secure binary copy. For Postgres/MySQL, it dumps schema and data into JSON.
|
|
93
93
|
```bash
|
|
94
|
-
npx
|
|
94
|
+
npx drixio backup
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
## β Help
|
|
98
98
|
To view all commands and options:
|
|
99
99
|
```bash
|
|
100
|
-
npx
|
|
100
|
+
npx drixio --help
|
|
101
101
|
```
|
|
102
102
|
|
|
103
103
|
---
|
package/dist/cli.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var Zt=Object.defineProperty;var E=(n,t)=>()=>(n&&(t=n(n=0)),t);var L=(n,t)=>{for(var a in t)Zt(n,a,{get:t[a],enumerable:!0})};import
|
|
2
|
+
var Zt=Object.defineProperty;var E=(n,t)=>()=>(n&&(t=n(n=0)),t);var L=(n,t)=>{for(var a in t)Zt(n,a,{get:t[a],enumerable:!0})};import P from"picocolors";function _e(){console.log(`
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
`+
|
|
6
|
-
`)+Xt(`
|
|
7
|
-
`)+ea(`
|
|
8
|
-
`)+ta(`
|
|
9
|
-
`)+aa(`
|
|
10
|
-
`)+oa("
|
|
11
|
-
\u2554${r}\u2557`));let o=72-n.length,e=Math.max(0,Math.floor(o/2)),s=Math.max(0,o-e),c=" ".repeat(e)+
|
|
12
|
-
`))}function Fe(n){let t=" Lightweight Interactive TUI Database Client \u2022 v1.
|
|
5
|
+
`+P.bold(Jt(` \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
|
+
`)+Xt(` \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
|
+
`)+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
|
+
`)+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
|
+
`)+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(n,t){let r="\u2550".repeat(72);console.log(P.cyan(`
|
|
11
|
+
\u2554${r}\u2557`));let o=72-n.length,e=Math.max(0,Math.floor(o/2)),s=Math.max(0,o-e),c=" ".repeat(e)+P.bold(P.white(n))+" ".repeat(s);console.log(P.cyan("\u2551")+c+P.cyan("\u2551")),console.log(P.cyan(`\u2560${"\u2550".repeat(72)}\u2563`));let i=(l,m)=>{let p=l.padEnd(12),u=` ${P.bold(p)}: ${m}`,d=` ${p}: `+m.replace(/\x1b\[[0-9;]*m/g,""),f=" ".repeat(Math.max(0,72-d.length));console.log(P.cyan("\u2551")+u+f+P.cyan("\u2551"))};for(let l of t)i(l.label,l.value);console.log(P.cyan(`\u255A${"\u2550".repeat(72)}\u255D`)),console.log(P.dim(` Use arrow keys to navigate \u2022 Enter to select \u2022 Ctrl+C to exit
|
|
12
|
+
`))}function Fe(n){let t=" Lightweight Interactive TUI Database Client \u2022 v1.1.1 ",a="None",r="-",o="None";n.type==="unknown"?o=P.dim("No configuration found. Please run check to configure."):(a=n.type.toUpperCase(),r=n.targetUrl,o=n.source===".env"?"Loaded from project .env file":n.source==="auto-detected"?"Auto-detected local SQLite file":"Manual connection config"),se(t,[{label:"Database",value:a},{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 Z,Jt,Xt,ea,ta,aa,oa,$e=E(()=>{"use strict";Z=(n,t,a)=>r=>`\x1B[38;2;${n};${t};${a}m${r}\x1B[39m`,Jt=Z(0,255,255),Xt=Z(0,230,245),ea=Z(0,210,235),ta=Z(0,188,220),aa=Z(0,168,205),oa=Z(0,148,188)});var Se,We=E(()=>{"use strict";Se=class{dbPath;db=null;constructor(t){this.dbPath=t}async getDb(){if(!this.db){if(!(await import("fs")).existsSync(this.dbPath))throw new Error(`Failed to found database file at: ${this.dbPath}`);let a=await import("sqlite");this.db=new a.DatabaseSync(this.dbPath)}return this.db}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(t){let a=await this.getDb();if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(t))throw new Error(`Invalid table name: ${t}`);return a.prepare(`PRAGMA table_info("${t}")`).all().map(e=>({name:e.name,type:e.type,isPk:e.pk>0,nullable:e.notnull===0}))}async getData(t,a=50,r=0,o,e){let s=await this.getDb();if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(t))throw new Error(`Invalid table name: ${t}`);let i=(await this.getSchema(t)).map(u=>u.name),l=`SELECT * FROM "${t}"`;o&&(l+=` WHERE ${o}`),e&&(l+=` ORDER BY "${e.col}" ${e.asc?"ASC":"DESC"}`),l+=` LIMIT ${a} OFFSET ${r}`;let p=s.prepare(l).all();return{columns:i,rows:p}}async query(t){let r=(await this.getDb()).prepare(t);if(t.trim().toUpperCase().startsWith("SELECT")||t.trim().toUpperCase().startsWith("PRAGMA")){let e=r.all(),s=[];return e.length>0&&(s=Object.keys(e[0])),{columns:s,rows:e}}else return r.run(),{columns:["Result"],rows:[{Result:"Success"}]}}async executeSql(t){(await this.getDb()).exec(t)}async close(){this.db&&(this.db.close(),this.db=null)}async insert(t,a){if(a.length===0)return;let r=await this.getDb(),o=Object.keys(a[0]),e=o.map(()=>"?").join(", "),s=`INSERT INTO "${t}" ("${o.join('", "')}") VALUES (${e})`,c=r.prepare(s);for(let i of a){let l=o.map(m=>i[m]);c.run(...l)}}}});import na from"pg";var xe,je=E(()=>{"use strict";xe=class{client;connected=!1;constructor(t){this.client=new na.Client({connectionString:t})}async connectIfNecessary(){this.connected||(await this.client.connect(),this.connected=!0)}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'
|
|
@@ -25,30 +25,30 @@ var Zt=Object.defineProperty;var E=(n,t)=>()=>(n&&(t=n(n=0)),t);var L=(n,t)=>{fo
|
|
|
25
25
|
AND kcu.column_name = c.column_name) as is_pk
|
|
26
26
|
FROM information_schema.columns c
|
|
27
27
|
WHERE c.table_name = $1;
|
|
28
|
-
`,[t])).rows.map(o=>({name:o.column_name,type:o.data_type,isPk:parseInt(o.is_pk)>0,nullable:o.is_nullable==="YES"}))}async getData(t,a=50,r=0,o,e){if(await this.connectIfNecessary(),!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t))throw new Error(`Invalid table name: ${t}`);let c=(await this.getSchema(t)).map(m=>m.name),i=`SELECT * FROM "${t}"`;o&&(i+=` WHERE ${o}`),e&&(i+=` ORDER BY "${e.col}" ${e.asc?"ASC":"DESC"}`),i+=" LIMIT $1 OFFSET $2";let l=await this.client.query(i,[a,r]);return{columns:c,rows:l.rows}}async query(t){await this.connectIfNecessary();let a=await this.client.query(t),r=[];return a.fields&&(r=a.fields.map(o=>o.name)),{columns:r,rows:a.rows||[]}}async executeSql(t){await this.connectIfNecessary(),await this.client.query(t)}async close(){this.connected&&(await this.client.end(),this.connected=!1)}async insert(t,a){if(a.length===0)return;await this.connectIfNecessary();let r=Object.keys(a[0]);for(let o of a){let e=r.map((i,l)=>`$${l+1}`).join(", "),s=`INSERT INTO "${t}" ("${r.join('", "')}") VALUES (${e})`,c=r.map(i=>o[i]);await this.client.query(s,c)}}}});import sa from"mysql2/promise";var Te,Ve=E(()=>{"use strict";Te=class{connection;pool=null;constructor(t){this.connection=t}async getPool(){return this.pool||(this.pool=sa.createPool(this.connection)),this.pool}async getTables(){let t=await this.getPool(),[a]=await t.query("SHOW TABLES;");return a.map(r=>Object.values(r)[0])}async getSchema(t){let a=await this.getPool();if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t))throw new Error(`Invalid table name: ${t}`);let[r]=await a.query(`SHOW COLUMNS FROM \`${t}\``);return r.map(e=>({name:e.Field,type:e.Type,isPk:e.Key==="PRI",nullable:e.Null==="YES",extra:e.Extra}))}async getData(t,a=50,r=0,o,e){let s=await this.getPool();if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t))throw new Error(`Invalid table name: ${t}`);let i=(await this.getSchema(t)).map(p=>p.name),l=`SELECT * FROM \`${t}\``;o&&(l+=` WHERE ${o}`),e&&(l+=` ORDER BY \`${e.col}\` ${e.asc?"ASC":"DESC"}`),l+=` LIMIT ${a} OFFSET ${r}`;let[m]=await s.query(l);return{columns:i,rows:m}}async query(t){let a=await this.getPool(),[r,o]=await a.query(t),e=[],s=[];return o&&Array.isArray(o)?(e=o.map(c=>c.name),s=r):(e=["Result"],s=[{Result:"Success",AffectedRows:r.affectedRows}]),{columns:e,rows:s}}async executeSql(t){await(await this.getPool()).query(t)}async close(){this.pool&&(await this.pool.end(),this.pool=null)}async insert(t,a){if(a.length===0)return;let r=await this.getPool(),o=Object.keys(a[0]);for(let e of a){let s=o.map(()=>"?").join(", "),c=`INSERT INTO \`${t}\` (\`${o.join("`, `")}\`) VALUES (${s})`,i=o.map(l=>e[l]);await r.query(c,i)}}}});var Qe={};L(Qe,{createDBAdapter:()=>h});function h(n){switch(n.type){case"sqlite":return new Se(n.targetUrl);case"postgres":return new xe(n.targetUrl);case"mysql":return new Te(n.targetUrl);default:throw new Error(`Unsupported database type: ${n.type}`)}}var C=E(()=>{"use strict";We();je();Ve()});function j(n){switch(n){case"sqlite":return new De;case"postgres":return new Le;case"mysql":return new
|
|
28
|
+
`,[t])).rows.map(o=>({name:o.column_name,type:o.data_type,isPk:parseInt(o.is_pk)>0,nullable:o.is_nullable==="YES"}))}async getData(t,a=50,r=0,o,e){if(await this.connectIfNecessary(),!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t))throw new Error(`Invalid table name: ${t}`);let c=(await this.getSchema(t)).map(m=>m.name),i=`SELECT * FROM "${t}"`;o&&(i+=` WHERE ${o}`),e&&(i+=` ORDER BY "${e.col}" ${e.asc?"ASC":"DESC"}`),i+=" LIMIT $1 OFFSET $2";let l=await this.client.query(i,[a,r]);return{columns:c,rows:l.rows}}async query(t){await this.connectIfNecessary();let a=await this.client.query(t),r=[];return a.fields&&(r=a.fields.map(o=>o.name)),{columns:r,rows:a.rows||[]}}async executeSql(t){await this.connectIfNecessary(),await this.client.query(t)}async close(){this.connected&&(await this.client.end(),this.connected=!1)}async insert(t,a){if(a.length===0)return;await this.connectIfNecessary();let r=Object.keys(a[0]);for(let o of a){let e=r.map((i,l)=>`$${l+1}`).join(", "),s=`INSERT INTO "${t}" ("${r.join('", "')}") VALUES (${e})`,c=r.map(i=>o[i]);await this.client.query(s,c)}}}});import sa from"mysql2/promise";var Te,Ve=E(()=>{"use strict";Te=class{connection;pool=null;constructor(t){this.connection=t}async getPool(){return this.pool||(this.pool=sa.createPool(this.connection)),this.pool}async getTables(){let t=await this.getPool(),[a]=await t.query("SHOW TABLES;");return a.map(r=>Object.values(r)[0])}async getSchema(t){let a=await this.getPool();if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t))throw new Error(`Invalid table name: ${t}`);let[r]=await a.query(`SHOW COLUMNS FROM \`${t}\``);return r.map(e=>({name:e.Field,type:e.Type,isPk:e.Key==="PRI",nullable:e.Null==="YES",extra:e.Extra}))}async getData(t,a=50,r=0,o,e){let s=await this.getPool();if(!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(t))throw new Error(`Invalid table name: ${t}`);let i=(await this.getSchema(t)).map(p=>p.name),l=`SELECT * FROM \`${t}\``;o&&(l+=` WHERE ${o}`),e&&(l+=` ORDER BY \`${e.col}\` ${e.asc?"ASC":"DESC"}`),l+=` LIMIT ${a} OFFSET ${r}`;let[m]=await s.query(l);return{columns:i,rows:m}}async query(t){let a=await this.getPool(),[r,o]=await a.query(t),e=[],s=[];return o&&Array.isArray(o)?(e=o.map(c=>c.name),s=r):(e=["Result"],s=[{Result:"Success",AffectedRows:r.affectedRows}]),{columns:e,rows:s}}async executeSql(t){await(await this.getPool()).query(t)}async close(){this.pool&&(await this.pool.end(),this.pool=null)}async insert(t,a){if(a.length===0)return;let r=await this.getPool(),o=Object.keys(a[0]);for(let e of a){let s=o.map(()=>"?").join(", "),c=`INSERT INTO \`${t}\` (\`${o.join("`, `")}\`) VALUES (${s})`,i=o.map(l=>e[l]);await r.query(c,i)}}}});var Qe={};L(Qe,{createDBAdapter:()=>h});function h(n){switch(n.type){case"sqlite":return new Se(n.targetUrl);case"postgres":return new xe(n.targetUrl);case"mysql":return new Te(n.targetUrl);default:throw new Error(`Unsupported database type: ${n.type}`)}}var C=E(()=>{"use strict";We();je();Ve()});function j(n){switch(n){case"sqlite":return new De;case"postgres":return new Le;case"mysql":return new Pe;default:return new De}}var De,Le,Pe,Ce=E(()=>{"use strict";De=class{quoteIdentifier(t){return`"${t}"`}escapeString(t){return t.replace(/'/g,"''")}buildCreateTable(t,a){let r=a.map(e=>{let s="";return e.type==="Integer"&&(s="INTEGER"),e.type==="Text"&&(s="TEXT"),e.type==="Boolean"&&(s="BOOLEAN"),e.type==="Decimal"&&(s="REAL"),e.type==="DateTime"&&(s="DATETIME"),e.type==="Enum"&&e.enumValues&&(s=`TEXT CHECK(${this.quoteIdentifier(e.name)} IN (${e.enumValues.map(c=>`'${this.escapeString(c)}'`).join(", ")}))`),e.isPk&&e.type==="Integer"?s="INTEGER PRIMARY KEY AUTOINCREMENT":e.isPk?s+=" PRIMARY KEY":e.nullable||(s+=" NOT NULL"),e.defaultValue&&e.defaultValue!=="AutoInc"&&!e.defaultValue.startsWith("FK ->")&&(e.defaultValue==="Timestamp"?s+=" DEFAULT CURRENT_TIMESTAMP":s+=` DEFAULT ${e.defaultValue}`),` ${this.quoteIdentifier(e.name)} ${s}`}),o=a.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(t)} (
|
|
29
29
|
${r.join(`,
|
|
30
30
|
`)}
|
|
31
31
|
);`}},Le=class{quoteIdentifier(t){return`"${t}"`}escapeString(t){return t.replace(/'/g,"''")}buildCreateTable(t,a){let r=a.map(e=>{let s="";return e.isPk&&e.type==="Integer"?s="SERIAL PRIMARY KEY":(e.type==="Integer"&&(s="INTEGER"),e.type==="Text"&&(s="TEXT"),e.type==="Boolean"&&(s="BOOLEAN"),e.type==="Decimal"&&(s="NUMERIC"),e.type==="DateTime"&&(s="TIMESTAMP"),e.type==="Enum"&&e.enumValues&&(s=`VARCHAR(255) CHECK(${this.quoteIdentifier(e.name)} IN (${e.enumValues.map(c=>`'${this.escapeString(c)}'`).join(", ")}))`),e.isPk&&(s+=" PRIMARY KEY"),!e.nullable&&!e.isPk&&(s+=" NOT NULL")),e.defaultValue&&e.defaultValue!=="AutoInc"&&!e.defaultValue.startsWith("FK ->")&&(e.defaultValue==="Timestamp"?s+=" DEFAULT CURRENT_TIMESTAMP":s+=` DEFAULT ${e.defaultValue}`),` ${this.quoteIdentifier(e.name)} ${s}`}),o=a.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(t)} (
|
|
32
32
|
${r.join(`,
|
|
33
33
|
`)}
|
|
34
|
-
);`}},
|
|
34
|
+
);`}},Pe=class{quoteIdentifier(t){return`\`${t}\``}escapeString(t){return t.replace(/'/g,"''")}buildCreateTable(t,a){let r=a.map(e=>{let s="";return e.type==="Integer"&&(s="INT"),e.type==="Text"&&(s="VARCHAR(255)"),e.type==="Boolean"&&(s="BOOLEAN"),e.type==="Decimal"&&(s="DOUBLE"),e.type==="DateTime"&&(s="DATETIME"),e.type==="Enum"&&e.enumValues&&(s=`VARCHAR(255) CHECK(${this.quoteIdentifier(e.name)} IN (${e.enumValues.map(c=>`'${this.escapeString(c)}'`).join(", ")}))`),e.isPk&&e.type==="Integer"?s+=" AUTO_INCREMENT PRIMARY KEY":e.isPk&&(s+=" PRIMARY KEY"),!e.nullable&&!e.isPk&&(s+=" NOT NULL"),e.defaultValue&&e.defaultValue!=="AutoInc"&&!e.defaultValue.startsWith("FK ->")&&(e.defaultValue==="Timestamp"?s+=" DEFAULT CURRENT_TIMESTAMP":s+=` DEFAULT ${e.defaultValue}`),` ${this.quoteIdentifier(e.name)} ${s}`}),o=a.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(t)} (
|
|
35
35
|
${r.join(`,
|
|
36
36
|
`)}
|
|
37
37
|
);`}}});import S from"picocolors";function ee(n,t,a={}){let{title:r,emptyMessage:o="No records found",maxColWidth:e=30}=a,s={},c=0;for(let f of n){let y=f.length;for(let x of t){let I=String(x[f]??"");I.length>y&&(y=I.length)}let b=Math.max(f.length,Math.min(e,y));s[f]=b,c+=b}let i=3*(n.length-1),l=c+i+4,m=Math.max(74,l),p=m-4-i;if(c<p&&n.length>0){let f=n[n.length-1];s[f]+=p-c}let u=(f,y)=>f.length>y?f.slice(0,y-3)+"...":f,d="\u2550".repeat(m-2);if(console.log(S.cyan(`
|
|
38
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)+S.bold(S.white(r))+" ".repeat(b);console.log(S.cyan("\u2551")+x+S.cyan("\u2551")),console.log(S.cyan(`\u2560${d}\u2563`))}if(n.length>0){let f=n.map(y=>S.bold(S.white(u(y,s[y]).padEnd(s[y])))).join(S.cyan(" \u2551 "));console.log(S.cyan("\u2551 ")+f+S.cyan(" \u2551")),console.log(S.cyan(`\u2560${d}\u2563`))}if(t.length===0){let f=m-4-o.length,y=Math.max(0,Math.floor(f/2)),b=Math.max(0,f-y);console.log(S.cyan("\u2551 ")+" ".repeat(y)+S.yellow(o)+" ".repeat(b)+S.cyan(" \u2551"))}else for(let f of t){let y=n.map(b=>S.white(u(String(f[b]??""),s[b]).padEnd(s[b]))).join(S.cyan(" \u2551 "));console.log(S.cyan("\u2551 ")+y+S.cyan(" \u2551"))}console.log(S.cyan(`\u255A${d}\u255D`))}var ve=E(()=>{"use strict"});var at={};L(at,{runQueryCommand:()=>ga});import ce from"picocolors";async function ga(n,t){n.type==="unknown"&&(console.log(ce.red("Error: No database connection found. Cannot run query.")),process.exit(1));let a=h(n),r=t[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 a.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(`
|
|
39
39
|
(${o.rows.length} rows)`)),await a.close(),process.exit(0)}catch(o){console.log(ce.red(`
|
|
40
40
|
Query Error: ${o.message}
|
|
41
|
-
`)),process.exit(1)}}var ot=E(()=>{"use strict";C();ve()});var nt={};L(nt,{runExportCommand:()=>fa});import U from"picocolors";import me from"fs/promises";import ue from"path";async function fa(n,t,a){n.type==="unknown"&&(console.log(U.red("Error: No database connection found. Cannot run export.")),process.exit(1));let r=h(n),o=t[0],e=a.format,s=a["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(),"
|
|
41
|
+
`)),process.exit(1)}}var ot=E(()=>{"use strict";C();ve()});var nt={};L(nt,{runExportCommand:()=>fa});import U from"picocolors";import me from"fs/promises";import ue from"path";async function fa(n,t,a){n.type==="unknown"&&(console.log(U.red("Error: No database connection found. Cannot run export.")),process.exit(1));let r=h(n),o=t[0],e=a.format,s=a["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(`
|
|
42
42
|
Starting export to ${i}...`));for(let m of l)try{if(s){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
43
|
`,f=p.map(y=>`"${y.name}","${y.type}","${y.isPk}","${y.nullable}"`).join(`
|
|
44
44
|
`);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
45
|
`,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";C()});import{Hono as ya}from"hono";function rt(n,t){let a=new ya,r=h(t);a.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)}}),a.get("/tables/stats",async o=>{try{let e=await r.getTables(),s={};for(let c of e)try{let i=await r.query(`SELECT COUNT(*) as c FROM "${c}"`);if(i&&i.rows&&i.rows.length>0){let l=i.rows[0],m=Object.values(l)[0];s[c]=parseInt(String(m),10)||0}else s[c]=0}catch{s[c]=0}return o.json({success:!0,data:s})}catch(e){return o.json({success:!1,error:e.message},500)}}),a.get("/tables/:name/schema",async o=>{let e=o.req.param("name");try{let s=await r.getSchema(e);return o.json({success:!0,data:s})}catch(s){return o.json({success:!1,error:s.message},500)}}),a.get("/tables/:name/data",async o=>{let e=o.req.param("name"),s=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,s,c,i,p);return o.json({success:!0,data:u})}catch(u){return o.json({success:!1,error:u.message},500)}}),a.post("/query",async o=>{try{let{sql:e}=await o.req.json(),s=await r.query(e);return o.json({success:!0,data:s})}catch(e){return o.json({success:!1,error:e.message},500)}}),n.route("/api",a)}var it=E(()=>{"use strict";C()});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 $a}from"url";async function xa(n){let t=new wa;rt(t,n);let r=Ae.includes("src")||Ae.includes("server")?pe.resolve(Ae,"../../dist/studio"):pe.resolve(Ae,"./studio"),o=await import("fs/promises");t.use("/*",ba({root:pe.relative(process.cwd(),r)})),t.get("*",async s=>{let c=pe.join(r,"index.html");try{let i=await o.readFile(c,"utf-8");return s.html(i)}catch{return s.text("
|
|
47
|
-
Starting
|
|
48
|
-
`)),ha({fetch:t.fetch,port:e}),await Ea(`http://localhost:${e}`)}var Sa,Ae,mt=E(()=>{"use strict";it();Sa=$a(import.meta.url),Ae=pe.dirname(Sa)});var ut={};L(ut,{runBackupCommand:()=>Ta});import
|
|
49
|
-
Starting database backup...`)),console.log(
|
|
50
|
-
`)),await
|
|
51
|
-
Backup Error: ${o.message}`))}finally{await r.close()}console.log(
|
|
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";C()});import{Hono as ya}from"hono";function rt(n,t){let a=new ya,r=h(t);a.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)}}),a.get("/tables/stats",async o=>{try{let e=await r.getTables(),s={};for(let c of e)try{let i=await r.query(`SELECT COUNT(*) as c FROM "${c}"`);if(i&&i.rows&&i.rows.length>0){let l=i.rows[0],m=Object.values(l)[0];s[c]=parseInt(String(m),10)||0}else s[c]=0}catch{s[c]=0}return o.json({success:!0,data:s})}catch(e){return o.json({success:!1,error:e.message},500)}}),a.get("/tables/:name/schema",async o=>{let e=o.req.param("name");try{let s=await r.getSchema(e);return o.json({success:!0,data:s})}catch(s){return o.json({success:!1,error:s.message},500)}}),a.get("/tables/:name/data",async o=>{let e=o.req.param("name"),s=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,s,c,i,p);return o.json({success:!0,data:u})}catch(u){return o.json({success:!1,error:u.message},500)}}),a.post("/query",async o=>{try{let{sql:e}=await o.req.json(),s=await r.query(e);return o.json({success:!0,data:s})}catch(e){return o.json({success:!1,error:e.message},500)}}),n.route("/api",a)}var it=E(()=>{"use strict";C()});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 $a}from"url";async function xa(n){let t=new wa;rt(t,n);let r=Ae.includes("src")||Ae.includes("server")?pe.resolve(Ae,"../../dist/studio"):pe.resolve(Ae,"./studio"),o=await import("fs/promises");t.use("/*",ba({root:pe.relative(process.cwd(),r)})),t.get("*",async s=>{let c=pe.join(r,"index.html");try{let i=await o.readFile(c,"utf-8");return s.html(i)}catch{return s.text("Drixio Studio static files not found. Did you run build?",404)}});let e=3e3;console.log(lt.cyan(`
|
|
47
|
+
Starting Drixio Studio on http://localhost:${e}...`)),console.log(lt.dim(`Press Ctrl+C to stop the server.
|
|
48
|
+
`)),ha({fetch:t.fetch,port:e}),await Ea(`http://localhost:${e}`)}var Sa,Ae,mt=E(()=>{"use strict";it();Sa=$a(import.meta.url),Ae=pe.dirname(Sa)});var ut={};L(ut,{runBackupCommand:()=>Ta});import k from"picocolors";import ke from"fs/promises";import qe from"path";async function Ta(n){n.type==="unknown"&&(console.log(k.red("Error: No database connection found. Cannot run backup.")),process.exit(1));let t=new Date().toISOString().replace(/[:.]/g,"-"),a=qe.join(process.cwd(),`drixio_backup_${t}`);if(console.log(k.cyan(`
|
|
49
|
+
Starting database backup...`)),console.log(k.dim(`Database: ${n.type}`)),console.log(k.dim(`Target: ${n.targetUrl}`)),console.log(k.dim(`Backup Directory: ${a}
|
|
50
|
+
`)),await ke.mkdir(a,{recursive:!0}),n.type==="sqlite")try{let o=qe.basename(n.targetUrl)||"database.sqlite",e=qe.join(a,o);await ke.copyFile(n.targetUrl,e),console.log(k.green(`\u2714 Copied raw SQLite file to ${e}`))}catch(o){console.log(k.red(`\u2718 Failed to copy SQLite file: ${o.message}`))}let r=h(n);try{let o=await r.getTables();o.length===0&&console.log(k.yellow("No tables found to backup."));for(let e of o)try{let s=await r.getSchema(e),c=await r.getData(e,9999999,0),i={table:e,schema:s,totalRows:c.rows.length,data:c.rows},l=qe.join(a,`${e}.json`);await ke.writeFile(l,JSON.stringify(i,null,2),"utf-8"),console.log(k.green(`\u2714 Dumped table: ${e} (${c.rows.length} rows)`))}catch(s){console.log(k.red(`\u2718 Failed to dump table ${e}: ${s.message}`))}}catch(o){console.log(k.red(`
|
|
51
|
+
Backup Error: ${o.message}`))}finally{await r.close()}console.log(k.cyan(`
|
|
52
52
|
Backup successfully completed at ${a}`)),process.exit(0)}var pt=E(()=>{"use strict";C()});var gt={};L(gt,{runImportCommand:()=>va});import M from"picocolors";import dt from"fs/promises";import Da from"path";function Ca(n){let t=n.split(/\r?\n/).filter(e=>e.trim()!=="");if(t.length===0)return[];let a=e=>{let s=[],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?(s.push(c),c=""):c+=m}return s.push(c),s},r=a(t[0]),o=[];for(let e=1;e<t.length;e++){let s=a(t[e]),c={};r.forEach((i,l)=>{c[i]=s[l]??""}),o.push(c)}return o}async function va(n,t,a){n.type==="unknown"&&(console.log(M.red("Error: No database connection found. Cannot run import.")),process.exit(1));let r=h(n),o=t[0],e=a.table,{input:s,select:c}=await import("@inquirer/prompts");o||(o=await s({message:"Enter the path to your CSV or JSON file:"}));let i=Da.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
53
|
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
54
|
|
|
@@ -57,7 +57,7 @@ Reading file...`));let l=await dt.readFile(i,"utf-8"),m=[];if(o.toLowerCase().en
|
|
|
57
57
|
Analyzing schema for table '${r}'...`));let i;try{i=await a.getSchema(r)}catch(d){console.log(O.red(`Error: ${d.message}`)),process.exit(1)}let l=i.filter(d=>!d.isPk);l.length===0&&console.log(O.yellow("Table only has Primary Key columns. Seeding might fail if they don't auto-increment.")),console.log(O.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]=qa(y);m.push(f)}let p=500,u=0;try{n.type==="sqlite"?await a.executeSql("PRAGMA foreign_keys = OFF;"):n.type==="mysql"?await a.executeSql("SET FOREIGN_KEY_CHECKS = 0;"):n.type==="postgres"&&await a.executeSql("SET session_replication_role = replica;");for(let d=0;d<m.length;d+=p){let f=m.slice(d,d+p);await a.insert(r,f),u+=f.length,process.stdout.write(`\r${O.dim(`Progress: ${u} / ${c}`)}`)}console.log(O.green(`
|
|
58
58
|
|
|
59
59
|
\u2714 Successfully seeded ${u} fake records into ${r}!`))}catch(d){console.log(O.red(`
|
|
60
|
-
\u2718 Seed failed: ${d.message}`))}finally{try{n.type==="sqlite"?await a.executeSql("PRAGMA foreign_keys = ON;"):n.type==="mysql"?await a.executeSql("SET FOREIGN_KEY_CHECKS = 1;"):n.type==="postgres"&&await a.executeSql("SET session_replication_role = DEFAULT;")}catch{}await a.close()}process.exit(0)}var ht=E(()=>{"use strict";C()});var wt={};L(wt,{runDiagramCommand:()=>
|
|
60
|
+
\u2718 Seed failed: ${d.message}`))}finally{try{n.type==="sqlite"?await a.executeSql("PRAGMA foreign_keys = ON;"):n.type==="mysql"?await a.executeSql("SET FOREIGN_KEY_CHECKS = 1;"):n.type==="postgres"&&await a.executeSql("SET session_replication_role = DEFAULT;")}catch{}await a.close()}process.exit(0)}var ht=E(()=>{"use strict";C()});var wt={};L(wt,{runDiagramCommand:()=>ka});import V from"picocolors";import La from"fs/promises";import Pa from"path";async function ka(n){n.type==="unknown"&&(console.log(V.red("Error: No database connection found. Cannot generate diagram.")),process.exit(1));let t=h(n);console.log(V.cyan(`
|
|
61
61
|
Scanning database to generate ER diagram...`));try{let a=await t.getTables();a.length===0&&(console.log(V.yellow("No tables found in the database.")),process.exit(0));let r=`erDiagram
|
|
62
62
|
`;for(let s of a){r+=` ${s} {
|
|
63
63
|
`;let c=await t.getSchema(s);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}
|
|
@@ -70,32 +70,32 @@ You can paste this Mermaid code directly into [Draw.io](https://app.diagrams.net
|
|
|
70
70
|
\`\`\`mermaid
|
|
71
71
|
${r}
|
|
72
72
|
\`\`\`
|
|
73
|
-
`,e=
|
|
73
|
+
`,e=Pa.resolve(process.cwd(),"drixio_schema.md");await La.writeFile(e,o.trim(),"utf-8"),console.log(V.green(`
|
|
74
74
|
\u2714 Diagram generated successfully!`)),console.log(V.white(`Output saved to: ${V.bold(e)}`)),console.log(V.dim("Tip: Open this file in VSCode with a Markdown viewer or paste it into Draw.io."))}catch(a){console.log(V.red(`
|
|
75
75
|
\u2718 Failed to generate diagram: ${a.message}`))}finally{await t.close()}process.exit(0)}var bt=E(()=>{"use strict";C()});var $t={};L($t,{runExecCommand:()=>Na});import oe from"picocolors";import Et from"fs/promises";import Ia from"path";async function Na(n,t){n.type==="unknown"&&(console.log(oe.red("Error: No database connection found. Cannot run exec.")),process.exit(1));let a=t[0],{input:r}=await import("@inquirer/prompts");a||(a=await r({message:"Enter the path to your .sql file:"}));let o=Ia.resolve(process.cwd(),a);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 s=h(n);console.log(oe.cyan(`
|
|
76
76
|
Executing SQL script from ${a}...`));try{await s.executeSql(e),console.log(oe.green("\u2714 Script executed successfully!"))}catch(c){console.log(oe.red(`\u2718 Execution failed: ${c.message}`))}finally{await s.close()}process.exit(0)}var St=E(()=>{"use strict";C()});var xt={};L(xt,{runGenerateTypesCommand:()=>_a});import H from"picocolors";import Ba from"fs/promises";import Ma from"path";function Oa(n){let t=n.toLowerCase();return t.includes("int")||t.includes("num")||t.includes("float")||t.includes("double")||t.includes("real")?"number":t.includes("bool")||t==="tinyint(1)"?"boolean":t.includes("char")||t.includes("text")||t.includes("uuid")||t.includes("string")?"string":t.includes("date")||t.includes("time")?"Date":t.includes("json")?"any":"string"}async function _a(n){n.type==="unknown"&&(console.log(H.red("Error: No database connection found. Cannot generate types.")),process.exit(1));let t=h(n);console.log(H.cyan(`
|
|
77
|
-
Scanning database to generate TypeScript interfaces...`));try{let a=await t.getTables();a.length===0&&(console.log(H.yellow("No tables found in the database.")),process.exit(0));let r=`// Generated by
|
|
77
|
+
Scanning database to generate TypeScript interfaces...`));try{let a=await t.getTables();a.length===0&&(console.log(H.yellow("No tables found in the database.")),process.exit(0));let r=`// Generated by Drixio CLI
|
|
78
78
|
// Database: ${n.type.toUpperCase()}
|
|
79
79
|
|
|
80
80
|
`;for(let e of a){let s=e.charAt(0).toUpperCase()+e.slice(1).replace(/_([a-z])/g,i=>i[1].toUpperCase());r+=`export interface ${s} {
|
|
81
81
|
`;let c=await t.getSchema(e);for(let i of c){let l=Oa(i.type),m=i.nullable?"?":"";r+=` ${i.name}${m}: ${l};
|
|
82
82
|
`}r+=`}
|
|
83
83
|
|
|
84
|
-
`}let o=Ma.resolve(process.cwd(),"
|
|
84
|
+
`}let o=Ma.resolve(process.cwd(),"drixio-types.d.ts");await Ba.writeFile(o,r.trim()+`
|
|
85
85
|
`,"utf-8"),console.log(H.green("\u2714 TypeScript interfaces generated successfully!")),console.log(H.white(`Output saved to: ${H.bold(o)}`))}catch(a){console.log(H.red(`
|
|
86
86
|
\u2718 Failed to generate types: ${a.message}`))}finally{await t.close()}process.exit(0)}var Tt=E(()=>{"use strict";C()});var Ct={};L(Ct,{runInitCommand:()=>Fa});import $ from"picocolors";import Re from"fs/promises";import Dt from"path";async function Fa(n){let{select:t,input:a,password:r}=await import("@inquirer/prompts"),o=n[0];(!o||!["sqlite","mysql","postgres"].includes(o.toLowerCase()))&&(o=await t({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($.cyan(`
|
|
87
87
|
Initializing a local ${o} database...`));let e="";if(o==="sqlite"){let i=n[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($.yellow(`File ${i} already exists.`))}catch{await Re.writeFile(l,""),console.log($.green(`\u2714 Created local database file: ${i}`))}e=`file:${i}`}else{console.log($.dim("Please provide credentials for your local server (e.g. running via XAMPP, Homebrew, etc.)"));let i=await a({message:"Server Host:",default:"localhost"}),l=await a({message:"Server Port:",default:o==="mysql"?"3306":"5432"}),m=await a({message:"Username:",default:o==="mysql"?"root":"postgres"}),p=await r({message:"Password (leave empty if none):"}),u=n[1];u||(u=await a({message:"New Database Name (e.g. my_project):"})),(!u||!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(u))&&(console.log($.red("Invalid database name. Please use only letters, numbers, and underscores.")),process.exit(1)),console.log($.cyan(`
|
|
88
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($.green(`\u2714 Created local database: ${u}`))}catch(y){console.log($.red(`\u2718 Failed to create database on server: ${y.message}`)),console.log($.dim(`
|
|
89
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($.yellow(`
|
|
90
|
-
\u{1F4A1} It seems you don't have ${o} installed or running locally.`)),o==="mysql"?console.log($.white(`\u{1F449} Download MySQL here: ${$.cyan("https://dev.mysql.com/downloads/installer/")}`)):o==="postgres"&&(console.log($.white(`\u{1F449} Download PostgreSQL here: ${$.cyan("https://www.postgresql.org/download/")}`)),console.log($.white(`\u{1F449} Or use Postgres.app for Mac: ${$.cyan("https://postgresapp.com/")}`))),console.log($.dim("(Alternatively, you can run '
|
|
90
|
+
\u{1F4A1} It seems you don't have ${o} installed or running locally.`)),o==="mysql"?console.log($.white(`\u{1F449} Download MySQL here: ${$.cyan("https://dev.mysql.com/downloads/installer/")}`)):o==="postgres"&&(console.log($.white(`\u{1F449} Download PostgreSQL here: ${$.cyan("https://www.postgresql.org/download/")}`)),console.log($.white(`\u{1F449} Or use Postgres.app for Mac: ${$.cyan("https://postgresapp.com/")}`))),console.log($.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 s=Dt.resolve(process.cwd(),".env"),c="";try{c=await Re.readFile(s,"utf-8")}catch{}c.includes("DATABASE_URL=")?(c=c.replace(/DATABASE_URL=.*/g,`DATABASE_URL=${e}`),console.log($.yellow("\u2714 Updated existing .env file with new DATABASE_URL"))):(c+=(c.endsWith(`
|
|
91
91
|
`)||c.length===0?"":`
|
|
92
92
|
`)+`DATABASE_URL=${e}
|
|
93
93
|
`,console.log($.green("\u2714 Saved connection string to .env file"))),await Re.writeFile(s,c,"utf-8"),console.log($.green(`
|
|
94
|
-
\u{1F389} Initialization Complete!`)),console.log($.white(`You can now run ${$.bold("npx
|
|
95
|
-
Connecting to local server to drop database '${s}'...`));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 \`${s}\``),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 "${s}"`),await d.end()}console.log(Q.green(`\u2714 Dropped database: ${s}`))}catch(u){console.log(Q.red(`\u2718 Failed to drop database on server: ${u.message}`)),process.exit(1)}}process.exit(0)}var qt=E(()=>{"use strict"});import{select as Va,Separator as Qa}from"@inquirer/prompts";import Y from"picocolors";var Rt,Lt=E(()=>{"use strict";Rt=async()=>await Va({message:"Table Manager - Choose an action:",theme:{prefix:Y.cyan("\u2713 "),icon:{cursor:Y.cyan("\u203A ")},style:{message:n=>Y.bold(Y.white(n)),highlight:n=>{let t=n.replace(/\x1b\[[0-9;]*m/g,"");return t.includes(" Back")?Y.red(t):Y.cyan(t)}}},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 Qa,{name:Y.dim(" Back"),value:"back",description:"Back to the main menu."}]})});import{input as Ie,select as ne,confirm as
|
|
94
|
+
\u{1F389} Initialization Complete!`)),console.log($.white(`You can now run ${$.bold("npx drixio")} to manage it!`)),process.exit(0)}var vt=E(()=>{"use strict"});var At={};L(At,{runDropDbCommand:()=>ja});import Q from"picocolors";import Ua from"fs/promises";import Wa from"path";async function ja(n){let{select:t,input:a,password:r,confirm:o}=await import("@inquirer/prompts"),e=n[0];(!e||!["sqlite","mysql","postgres"].includes(e.toLowerCase()))&&(e=await t({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 s=n[1];if(e==="sqlite"){s||(s=await a({message:"Enter the SQLite filename to delete (e.g. database.sqlite):",default:"database.sqlite"})),!s.endsWith(".sqlite")&&!s.endsWith(".db")&&(s+=".sqlite"),await o({message:`Are you absolutely sure you want to delete ${s}? This cannot be undone!`,default:!1})||(console.log(Q.yellow("Aborted.")),process.exit(0));let i=Wa.resolve(process.cwd(),s);try{await Ua.unlink(i),console.log(Q.green(`\u2714 Deleted local database file: ${s}`))}catch(l){console.log(Q.red(`\u2718 Failed to delete file: ${l.message}`))}}else{console.log(Q.dim(`Please provide credentials for your local ${e} server to drop a database.`));let c=await a({message:"Server Host:",default:"localhost"}),i=await a({message:"Server Port:",default:e==="mysql"?"3306":"5432"}),l=await a({message:"Username:",default:e==="mysql"?"root":"postgres"}),m=await r({message:"Password (leave empty if none):"});s||(s=await a({message:"Which Database Name do you want to DROP?"})),await o({message:`Are you absolutely sure you want to DROP DATABASE '${s}' from ${c}? All data will be lost!`,default:!1})||(console.log(Q.yellow("Aborted.")),process.exit(0)),console.log(Q.cyan(`
|
|
95
|
+
Connecting to local server to drop database '${s}'...`));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 \`${s}\``),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 "${s}"`),await d.end()}console.log(Q.green(`\u2714 Dropped database: ${s}`))}catch(u){console.log(Q.red(`\u2718 Failed to drop database on server: ${u.message}`)),process.exit(1)}}process.exit(0)}var qt=E(()=>{"use strict"});import{select as Va,Separator as Qa}from"@inquirer/prompts";import Y from"picocolors";var Rt,Lt=E(()=>{"use strict";Rt=async()=>await Va({message:"Table Manager - Choose an action:",theme:{prefix:Y.cyan("\u2713 "),icon:{cursor:Y.cyan("\u203A ")},style:{message:n=>Y.bold(Y.white(n)),highlight:n=>{let t=n.replace(/\x1b\[[0-9;]*m/g,"");return t.includes(" Back")?Y.red(t):Y.cyan(t)}}},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 Qa,{name:Y.dim(" Back"),value:"back",description:"Back to the main menu."}]})});import{input as Ie,select as ne,confirm as Pt}from"@inquirer/prompts";import ge from"picocolors";async function fe(n,t,a=[],r=""){let o="";for(;!o;){if(o=await Ie({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)?a.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"}]}),s;e==="Enum"&&(s=(await Ie({message:"Enter comma-separated Enum values (e.g. active, pending, deleted):"})).split(",").map(d=>d.trim()).filter(d=>d),s.length===0&&console.log(ge.yellow("Warning: No enum values provided.")));let c="";e==="DateTime"&&await Pt({message:"Set default to CURRENT_TIMESTAMP?",default:!1})&&(c="Timestamp");let i=!1,l;if(e!=="DateTime"){let u=[{name:"None",value:"none"}];t||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 n.getTables();if(f.length>0){let y=await ne({message:"Select target table:",choices:f.map(x=>({name:x,value:x}))}),b=await n.getSchema(y);if(b.length>0){let x=await ne({message:"Select target column:",choices:b.map(I=>({name:`${I.name} (${I.type})`,value:I.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 Pt({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"&&s)c=await ne({message:`Default value for '${o}':`,choices:[{name:"None",value:""},...s.map(d=>({name:d,value:`'${d}'`}))]});else{let u=await Ie({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:s},isPk:i}}var Ne=E(()=>{"use strict"});import{input as Ka,confirm as kt}from"@inquirer/prompts";import g from"picocolors";async function Nt(n){let t=h(n),a="";for(;!a;)a=await Ka({message:"Enter the new table name:"}),/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(a)||(console.log(g.red("Invalid table name. Use only letters, numbers, and underscores.")),a="");let r=[],o=!1,e=!0;for(;e;){It(a,r);let l=r.map(u=>u.name),{col:m,isPk:p}=await fe(t,o,l);if(!m)break;p&&(o=!0),r.push(m),e=await kt({theme:{prefix:g.cyan(`
|
|
96
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})}It(a,r),console.log(g.dim("Generating SQL..."));let c=j(n.type).buildCreateTable(a,r);if(console.log(g.cyan(`
|
|
97
97
|
--- SQL Preview ---`)),console.log(g.yellow(c)),console.log(g.cyan(`-------------------
|
|
98
|
-
`)),await
|
|
98
|
+
`)),await kt({message:"Do you want to execute this SQL to build the table?",default:!0}))try{console.log(g.dim("Executing SQL...")),await t.executeSql(c),console.log(g.green(`
|
|
99
99
|
\u2713 Table '${a}' created successfully!`))}catch(l){console.log(g.red(`
|
|
100
100
|
x Error creating table: ${l.message}`))}finally{await t.close()}else console.log(g.yellow("Aborted table creation.")),await t.close();await za()}async function za(){let{input:n}=await import("@inquirer/prompts");await n({message:"Press Enter to continue..."})}function It(n,t){console.clear(),console.log(`
|
|
101
101
|
`);let a={name:20,type:18,key:8,nullable:10,defaultCol:16},r=a.name+a.type+a.key+a.nullable+a.defaultCol+14;console.log(g.cyan(`\u2554${"\u2550".repeat(r)}\u2557`));let o=r-n.length,e=Math.max(0,Math.floor(o/2)),s=Math.max(0,o-e),c=" ".repeat(e)+g.bold(g.white(n))+" ".repeat(s);console.log(g.cyan("\u2551")+c+g.cyan("\u2551"));let i=(l,m,p)=>g.cyan(l+"\u2550".repeat(a.name+2)+m+"\u2550".repeat(a.type+2)+m+"\u2550".repeat(a.key+2)+m+"\u2550".repeat(a.nullable+2)+m+"\u2550".repeat(a.defaultCol+2)+p);console.log(i("\u2560","\u2566","\u2563")),console.log(g.cyan("\u2551 ")+g.bold(g.white("Column Name".padEnd(a.name)))+g.cyan(" \u2551 ")+g.bold(g.white("Type".padEnd(a.type)))+g.cyan(" \u2551 ")+g.bold(g.white("Key".padEnd(a.key)))+g.cyan(" \u2551 ")+g.bold(g.white("Nullable".padEnd(a.nullable)))+g.cyan(" \u2551 ")+g.bold(g.white("Default".padEnd(a.defaultCol)))+g.cyan(" \u2551")),t.length>0&&console.log(i("\u2560","\u256C","\u2563"));for(let l=0;l<t.length;l++){let m=t[l],p=g.white(m.name.padEnd(a.name)),u=g.white(m.type.padEnd(a.type)),d=m.isPk?"PK":"-",f=m.isPk?g.green(d.padEnd(a.key)):g.dim(d.padEnd(a.key)),y=m.nullable?"Yes":"No",b=m.nullable?g.green(y.padEnd(a.nullable)):g.dim(y.padEnd(a.nullable)),x=m.defaultValue||"-",I=m.defaultValue?g.yellow(x.padEnd(a.defaultCol)):g.dim(x.padEnd(a.defaultCol));console.log(g.cyan("\u2551 ")+p+g.cyan(" \u2551 ")+u+g.cyan(" \u2551 ")+f+g.cyan(" \u2551 ")+b+g.cyan(" \u2551 ")+I+g.cyan(" \u2551"))}if(t.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.
|
|
@@ -133,7 +133,7 @@ No file path entered. Aborted.`))}catch(t){console.log(w.red(`
|
|
|
133
133
|
Error: ${t.message}`))}}ve();$e();async function Je(n){let t=h(n),a=!0;for(;a;){console.clear();let r=[],o=0,e="Scanning...";try{r=await t.getTables();for(let i of r)try{let l=n.type==="mysql"?"`":'"',m=await t.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 s=n.targetUrl,c=n.source===".env"?"Loaded from project .env file":n.source==="auto-detected"?"Auto-detected local SQLite file":"Manual connection config";se(` Data Browser & Editor \u2022 [${n.type.toUpperCase()}]`,[{label:"Database",value:n.type.toUpperCase()},{label:"Target",value:s.length>45?"..."+s.slice(-42):s},{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 t.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"){a=!1;continue}let m=!0,p=1,u="",d=50;for(;m;){console.clear();let f=(p-1)*d,y=await t.getSchema(l),b=y.map(N=>N.name),x;try{x=await t.getData(l,d,f,u)}catch(N){console.log(T.red(`
|
|
134
134
|
Error fetching data: ${N.message}
|
|
135
135
|
`)),u="";let{input:R}=await import("@inquirer/prompts");await R({message:"Click Enter to continue..."});continue}let I=x.rows,Kt=` ${l} (Page ${p}) `;ee(b,I,{title:Kt,maxColWidth:30});let zt=I.length===d,Ht=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];Ht&&we.push({name:"Previous Page",value:"prev"}),zt&&we.push({name:"Next Page",value:"next"}),we.push({name:T.dim(" Back"),value:"BACK"});let q=await Ze({message:"Select an action for this table:",theme:{prefix:T.cyan("\u2713 "),icon:{cursor:T.cyan("\u203A ")},style:{message:N=>T.bold(T.white(N)),highlight:N=>{let R=N.replace(/\x1b\[[0-9;]*m/g,"");return R.includes(" Back")?T.red(R):T.cyan(R)}}},choices:we});if(q==="prev"){p--;continue}if(q==="next"){p++;continue}if(q==="noop")continue;if(q==="BACK"){m=!1;continue}if(q==="clear_search"){u="",p=1;continue}if(q==="search"){let{input:N}=await import("@inquirer/prompts"),_=(await N({message:"Enter Search (e.g. `age > 18` or `John` for fuzzy search):"})).trim();if(_){if(/[=<>]|LIKE|IN|AND|OR/i.test(_))u=_;else{let G=y.filter(F=>F.type.toLowerCase().includes("char")||F.type.toLowerCase().includes("text"));if(G.length>0){let F=n.type==="postgres"?"ILIKE":"LIKE";u=G.map(Ee=>`"${Ee.name}" ${F} '%${_.replace(/'/g,"''")}%'`).join(" OR ")}else u=`"${y[0].name}" = '${_}'`}p=1}continue}if(q==="exportCsv"||q==="exportJson"){try{console.log(T.yellow(`
|
|
136
|
-
Exporting data...`));let R=await t.getData(l,9999999,0,u),_=await import("fs/promises"),be=await import("path"),G=be.join(process.cwd(),"
|
|
136
|
+
Exporting data...`));let R=await t.getData(l,9999999,0,u),_=await import("fs/promises"),be=await import("path"),G=be.join(process.cwd(),"drixio_exports");if(await _.mkdir(G,{recursive:!0}),q==="exportCsv"){let F=R.columns.join(",")+`
|
|
137
137
|
`,Oe=R.rows.map(Yt=>R.columns.map(Gt=>`"${String(Yt[Gt]??"").replace(/"/g,'""')}"`).join(",")).join(`
|
|
138
138
|
`),Ee=be.join(G,`${l}.csv`);await _.writeFile(Ee,F+Oe,"utf-8"),console.log(T.green(`
|
|
139
139
|
Exported to ${Ee}`))}else{let F=be.join(G,`${l}.json`);await _.writeFile(F,JSON.stringify(R.rows,null,2),"utf-8"),console.log(T.green(`
|
|
@@ -145,18 +145,18 @@ Failed to auto-detect database connection. Please try manual configuration.`));b
|
|
|
145
145
|
Testing connection...`));try{let s=h(e);await s.getTables(),await s.close(),a=e,await Ue(o),console.log(ae.green("\u2713 Database connection setup successfully and saved to .env!"))}catch(s){console.log(ae.red(`
|
|
146
146
|
x Connection failed: ${s.message}
|
|
147
147
|
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 a}import{select as pa,Separator as da}from"@inquirer/prompts";import z from"picocolors";var et=async n=>await pa({message:"Select an action:",theme:{prefix:z.cyan("\u2713 "),icon:{cursor:z.cyan("\u203A ")},style:{message:t=>z.bold(z.white(t)),highlight:t=>{let a=t.replace(/\x1b\[[0-9;]*m/g,"");return a.includes("Exit")?z.red(a):z.cyan(a)}}},choices:[{name:" Data Browser & Editor",value:"editor",description:"View, insert, update, and delete row data in your tables.",disabled:n.type==="unknown"},{name:" Run Raw SQL (REPL)",value:"repl",description:"Execute arbitrary SQL queries interactively.",disabled:n.type==="unknown"},{name:" Table Builder & Manager",value:"table",description:"Create new tables, or modify/drop existing tables.",disabled:n.type==="unknown"},new da,{name:n.type==="unknown"?" Setup Connection":" Connection Settings",value:n.type==="unknown"?"setup":"re-configure",description:n.type==="unknown"?"Setup the database connection manually.":"Re-configure the database connection."},{name:z.dim(" Exit"),value:"exit",description:"Exit the
|
|
148
|
+
Failed to detect database connection. Please enter valid database URL.`));break}return a}import{select as pa,Separator as da}from"@inquirer/prompts";import z from"picocolors";var et=async n=>await pa({message:"Select an action:",theme:{prefix:z.cyan("\u2713 "),icon:{cursor:z.cyan("\u203A ")},style:{message:t=>z.bold(z.white(t)),highlight:t=>{let a=t.replace(/\x1b\[[0-9;]*m/g,"");return a.includes("Exit")?z.red(a):z.cyan(a)}}},choices:[{name:" Data Browser & Editor",value:"editor",description:"View, insert, update, and delete row data in your tables.",disabled:n.type==="unknown"},{name:" Run Raw SQL (REPL)",value:"repl",description:"Execute arbitrary SQL queries interactively.",disabled:n.type==="unknown"},{name:" Table Builder & Manager",value:"table",description:"Create new tables, or modify/drop existing tables.",disabled:n.type==="unknown"},new da,{name:n.type==="unknown"?" Setup Connection":" Connection Settings",value:n.type==="unknown"?"setup":"re-configure",description:n.type==="unknown"?"Setup the database connection manually.":"Re-configure the database connection."},{name:z.dim(" Exit"),value:"exit",description:"Exit the Drixio CLI application."}]});C();ve();import B from"picocolors";async function tt(n){if(n.type==="unknown")return;let t=h(n),a=!0,{input:r}=await import("@inquirer/prompts");for(console.clear(),console.log(B.cyan(`
|
|
149
149
|
\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
150
|
`));a;)try{let e=(await r({message:B.green(`${n.type}>`)})).trim();if(e.toLowerCase()==="exit"||e.toLowerCase()==="quit"){a=!1;continue}if(e==="")continue;let s=await t.query(e);if(s.columns.length===0){console.log(B.yellow("Query executed successfully. (No output)"));continue}ee(s.columns,s.rows,{title:"Query Result",maxColWidth:50}),console.log(B.dim(`
|
|
151
151
|
(${s.rows.length} rows)`)),console.log()}catch(o){o.name==="ExitPromptError"?a=!1:console.log(B.red(`
|
|
152
152
|
Error: ${o.message}
|
|
153
153
|
`))}}import{parseArgs as to}from"util";async function Qt(){let n=process.argv.slice(2),t;n.length>0&&(n[0].startsWith("postgres://")||n[0].startsWith("postgresql://")||n[0].startsWith("mysql://")||n[0].startsWith("file:"))&&(t=n[0]);let{positionals:a,values:r}=to({args:n,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
|
-
|
|
155
|
-
`)),console.log(`${D.bold("Usage:")} npx
|
|
154
|
+
Drixio CLI - Modern Database Manager
|
|
155
|
+
`)),console.log(`${D.bold("Usage:")} npx drixio [command] [options]
|
|
156
156
|
`),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
157
|
${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,
|
|
159
|
-
No database connection found. Please run ${D.bold("
|
|
160
|
-
Thanks for using
|
|
161
|
-
Exit
|
|
158
|
+
If you don't provide a command, Drixio will launch the Interactive UI!`),process.exit(0));let o=t?void 0:a[0];if(o==="query"){let{runQueryCommand:i}=await Promise.resolve().then(()=>(ot(),at)),l=await A();await i(l,a.slice(1));return}if(o==="export"){let{runExportCommand:i}=await Promise.resolve().then(()=>(st(),nt)),l=await A();await i(l,a.slice(1),r);return}if(o==="studio"){let{runStudio:i}=await Promise.resolve().then(()=>(mt(),ct)),l=await A();await i(l);return}if(o==="backup"){let{runBackupCommand:i}=await Promise.resolve().then(()=>(pt(),ut)),l=await A();await i(l);return}if(o==="import"){let{runImportCommand:i}=await Promise.resolve().then(()=>(ft(),gt)),l=await A();await i(l,a.slice(1),r);return}if(o==="seed"){let{runSeedCommand:i}=await Promise.resolve().then(()=>(ht(),yt)),l=await A();await i(l,a.slice(1));return}if(o==="diagram"){let{runDiagramCommand:i}=await Promise.resolve().then(()=>(bt(),wt)),l=await A();await i(l);return}if(o==="exec"){let{runExecCommand:i}=await Promise.resolve().then(()=>(St(),$t)),l=await A();await i(l,a.slice(1));return}if(o==="generate-types"){let{runGenerateTypesCommand:i}=await Promise.resolve().then(()=>(Tt(),xt)),l=await A();await i(l);return}if(o==="init"){let{runInitCommand:i}=await Promise.resolve().then(()=>(vt(),Ct));await i(a.slice(1));return}if(o==="drop-db"){let{runDropDbCommand:i}=await Promise.resolve().then(()=>(qt(),At));await i(a.slice(1));return}let e=!0,s=await A(t);for(;e;)switch(console.clear(),_e(),Fe(s),await et(s)){case"editor":s.type==="unknown"?(console.log(D.yellow(`
|
|
159
|
+
No database connection found. Please run ${D.bold("drixio check")} first.`)),await c()):await Je(s);break;case"table":let{runTableManagerFlow:l}=await Promise.resolve().then(()=>(Vt(),jt));await l(s);break;case"repl":await tt(s);break;case"setup":case"re-configure":s=await Xe(s),await c();break;case"exit":e=!1,console.log(D.dim(`
|
|
160
|
+
Thanks for using Drixio. Goodbye!`));break}async function c(){let{input:i}=await import("@inquirer/prompts");await i({message:"Click Enter to continue..."})}}Qt().catch(n=>{n.name==="ExitPromptError"&&(console.log(`
|
|
161
|
+
Exit Drixio.`),process.exit(0)),console.error(`
|
|
162
162
|
Error: `,n),process.exit(1)});
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drixio",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "A lightweight interactive TUI database client",
|
|
5
5
|
"bin": {
|
|
6
|
-
"
|
|
6
|
+
"drixio": "dist/cli.js"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
9
|
"dist"
|
|
@@ -12,7 +12,17 @@
|
|
|
12
12
|
"database",
|
|
13
13
|
"tui",
|
|
14
14
|
"cli",
|
|
15
|
-
"
|
|
15
|
+
"drixio",
|
|
16
|
+
"postgres",
|
|
17
|
+
"sqlite",
|
|
18
|
+
"mysql",
|
|
19
|
+
"terminal",
|
|
20
|
+
"editor",
|
|
21
|
+
"developer",
|
|
22
|
+
"sql",
|
|
23
|
+
"data",
|
|
24
|
+
"db",
|
|
25
|
+
"ui"
|
|
16
26
|
],
|
|
17
27
|
"author": "TerKSDev",
|
|
18
28
|
"license": "MIT",
|