mwalajs 1.0.8 → 1.0.9

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/bin/mwala.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { execSync } from 'child_process';
3
+ import { spawn } from 'child_process';
4
4
  import fs from 'fs';
5
5
  import path from 'path';
6
6
  import { fileURLToPath, pathToFileURL } from 'url';
@@ -9,19 +9,20 @@ import readlineSync from 'readline-sync';
9
9
  const __filename = fileURLToPath(import.meta.url);
10
10
  const __dirname = path.dirname(__filename);
11
11
 
12
+ const args = process.argv.slice(2);
13
+ const command = args[0];
14
+
12
15
  // Dynamic imports
13
16
  const { getDbConnection } = await import(pathToFileURL(path.join(__dirname, '../config/createdatabase.mjs')).href);
14
- const { createTable, dropTable, migrateAll, rollbackLastMigration } = await import(pathToFileURL(path.join(__dirname, '../runMigrations.mjs')).href);
15
17
  const { setupMwalajs } = await import(pathToFileURL(path.join(__dirname, '../setupMwalajs.mjs')).href);
16
18
  const { createProject } = await import(pathToFileURL(path.join(__dirname, '../createProject.mjs')).href);
17
19
 
18
- // Import new DB helpers (we'll define these later)
19
- const {
20
- listTables,
21
- describeTable,
22
- truncateTable,
23
- renameTable,
24
- backupDatabase,
20
+ const {
21
+ listTables,
22
+ describeTable,
23
+ truncateTable,
24
+ renameTable,
25
+ backupDatabase,
25
26
  restoreDatabase,
26
27
  seedDatabase,
27
28
  showDatabaseSize,
@@ -37,88 +38,74 @@ const {
37
38
  showConnections,
38
39
  killConnections,
39
40
  checkTableExists
40
- } = await import(pathToFileURL(path.join(__dirname, '../dbUtils.mjs')).href);
41
-
42
- const args = process.argv.slice(2);
43
- const command = args[0];
41
+ } = await import(pathToFileURL(path.join(__dirname, '../utils/dbUtils.mjs')).href);
44
42
 
45
43
  if (!command || command === 'help' || command === 'h') {
46
44
  console.log(`
47
- ╔══════════════════════════════════════════════════╗
48
- MwalaJS CLI v1.1.0
49
- ╚══════════════════════════════════════════════════╝
50
-
51
- General Commands:
52
- - mwala -v | --version → Show version
53
- - mwala help | h → Show this help
54
-
55
- Project Management:
56
- - mwala create-project → Create new project
57
- - mwala init → Initialize MwalaJS
58
-
59
- Run Application:
60
- - mwala serve | app.mjs → Start server
61
-
62
- Code Generation:
63
- - mwala generate model <name>
64
- - mwala generate controller <name>
65
- - mwala generate route <name>
66
- - mwala generate view <name>
67
- - mwala generate midware <name>
68
-
69
- ════════════════════════════════════════════════════
70
- DATABASE COMMANDS
71
- ════════════════════════════════════════════════════
72
-
73
- Setup & Config:
74
- - mwala create-db Create/connect database (interactive)
75
- - mwala db:config Reconfigure .env database settings
76
-
77
- Table Management:
78
- - mwala db:table list List all tables
79
- - mwala db:table create <name> Create table
80
- - mwala db:table drop <name> Drop table
81
- - mwala db:table truncate <name> → Truncate table
82
- - mwala db:table rename <old> <new> Rename table
83
- - mwala db:table copy <src> <dest> Copy table structure + data
84
- - mwala db:table exists <name> Check if table exists
85
- - mwala db:table describe <name> Show table structure
86
- - mwala db:table count <name> Count rows in table
87
-
88
- Migrations:
89
- - mwala migrate all Run all pending migrations
90
- - mwala rollback last → Rollback last migration
91
- - mwala rollback all Rollback all migrations
92
-
93
- Data & Backup:
94
- - mwala db:seed <file.js> → Run seed file
95
- - mwala db:backup → Backup database
96
- - mwala db:restore <file.sql> Restore from backup
97
- - mwala db:export <table> <file.csv> Export table to CSV
98
- - mwala db:import <file.csv> <table> → Import CSV into table
99
-
100
- Maintenance & Stats:
101
- - mwala db:size → Show database size
102
- - mwala db:indexes <table> → List indexes on table
103
- - mwala db:analyze <table> → Analyze table (PostgreSQL)
104
- - mwala db:reindex <table> → Rebuild indexes
105
- - mwala db:vacuum → Vacuum database (SQLite/PostgreSQL)
106
- - mwala db:connections → Show active connections
107
- - mwala db:kill-connections → Kill all other connections (admin)
108
- - mwala db:drop-all-tables → ⚠️ Drop ALL tables (dangerous!)
109
-
110
- Use: mwala <command> [options]
45
+ ╔══════════════════════════════════════════════════════════╗
46
+ MwalaJS CLI v1.1.0
47
+ ╚══════════════════════════════════════════════════════════╝
48
+
49
+ General:
50
+ mwala -v | --version → Show version
51
+ mwala help | h → Show this help
52
+
53
+ Project:
54
+ mwala create-project → Create new project
55
+ mwala init → Initialize MwalaJS
56
+
57
+ Run:
58
+ mwala serve Start the server (runs app.mjs)
59
+
60
+ Generate:
61
+ mwala generate model <name>
62
+ mwala generate controller <name>
63
+ mwala generate route <name>
64
+ mwala generate view <name>
65
+ mwala generate midware <name>
66
+
67
+ Database Setup:
68
+ mwala create-db → Interactive DB setup & creation
69
+ mwala db:config → Reconfigure database (.env)
70
+
71
+ Database Commands:
72
+ mwala db:table list List all tables
73
+ mwala db:table describe <name> Show table structure
74
+ mwala db:table count <name> → Count rows
75
+ mwala db:table truncate <name> → Empty table
76
+ mwala db:table rename <old> <new> Rename table
77
+ mwala db:table copy <src> <dest> Copy table
78
+ mwala db:table exists <name> Check if exists
79
+
80
+ mwala db:backup Backup database
81
+ mwala db:restore <file.sql> Restore from backup
82
+ mwala db:size Show database size
83
+ mwala db:indexes <table> List indexes
84
+ mwala db:vacuum Optimize (SQLite/PostgreSQL)
85
+ mwala db:connections → Show active connections
86
+ mwala db:kill-connections → Kill other connections (admin)
87
+ mwala db:drop-all-tables ⚠️ DROP ALL TABLES!
88
+
89
+ mwala db:export <table> <file.csv> Export to CSV
90
+ mwala db:import <file.csv> <table> → Import from CSV
91
+ mwala db:seed <seedFile.mjs> → Run seed file
92
+
93
+ Migrations:
94
+ mwala migrate all Run all migrations
95
+ mwala rollback last Rollback last migration
96
+
97
+ Enjoy building with MwalaJS! 🚀
111
98
  `);
112
99
  process.exit(0);
113
100
  }
114
101
 
102
+ // ====================== COMMAND SWITCH ======================
115
103
  switch (command) {
116
-
117
- case 'version':
118
104
  case '-v':
105
+ case 'version':
119
106
  case '--version':
120
107
  console.log('MwalaJS Version: 1.1.0');
121
- break;
108
+ process.exit(0);
122
109
 
123
110
  case 'create-project':
124
111
  createProject();
@@ -129,143 +116,178 @@ switch (command) {
129
116
  break;
130
117
 
131
118
  case 'serve':
132
- case 'app.mjs':
133
- const { spawn } = require('child_process');
134
- const child = spawn('node', ['app.mjs'], { stdio: 'inherit', cwd: process.cwd() });
119
+ const child = spawn('node', ['app.mjs'], {
120
+ stdio: 'inherit',
121
+ cwd: process.cwd()
122
+ });
135
123
 
136
124
  process.on('SIGINT', () => child.kill('SIGINT'));
137
125
  process.on('SIGTERM', () => child.kill('SIGTERM'));
138
126
 
139
- child.on('exit', (code) => process.exit(code || 0));
127
+ child.on('exit', (code) => process.exit(code ?? 0));
140
128
  child.on('error', (err) => {
141
129
  console.error(`Failed to start app: ${err.message}`);
142
130
  process.exit(1);
143
131
  });
144
132
  break;
145
133
 
146
- case 'generate':
147
- // ... (your existing generate logic remains unchanged)
148
- // (kept same as before for brevity)
134
+ case 'generate': {
135
+ const type = args[1]?.toLowerCase();
136
+ const name = args[2];
137
+
138
+ if (!type || !name) {
139
+ console.error('Usage: mwala generate <model|controller|route|view|midware> <name>');
140
+ process.exit(1);
141
+ }
142
+
143
+ const folders = {
144
+ model: 'models',
145
+ controller: 'controllers',
146
+ route: 'routes',
147
+ view: 'views',
148
+ midware: 'middlewares'
149
+ };
150
+
151
+ if (!folders[type]) {
152
+ console.error(`Invalid type. Use: ${Object.keys(folders).join(', ')}`);
153
+ process.exit(1);
154
+ }
155
+
156
+ const filePath = path.join(process.cwd(), folders[type], `${name}.mjs`);
157
+
158
+ if (fs.existsSync(filePath)) {
159
+ console.error(`${name} ${type} already exists.`);
160
+ process.exit(1);
161
+ }
162
+
163
+ let content = '';
164
+ switch (type) {
165
+ case 'model':
166
+ content = `export const ${name}Model = {};\n`;
167
+ break;
168
+ case 'controller':
169
+ content = `export const ${name}Controller = {\n getPage: (req, res) => {\n res.render('${name}', { title: '${name}' });\n }\n};\n`;
170
+ break;
171
+ case 'route':
172
+ content = `import mwalajs from 'mwalajs';\nimport { ${name}Controller } from '../controllers/${name}.mjs';\n\nconst router = mwalajs.Router();\nrouter.get('/', ${name}Controller.getPage);\nexport { router as ${name}Route };\n`;
173
+ break;
174
+ case 'view':
175
+ content = `<!DOCTYPE html>\n<html lang="en">\n<head>\n <meta charset="UTF-8">\n <title>${name}</title>\n</head>\n<body>\n <h1>Welcome to ${name} Page</h1>\n</body>\n</html>\n`;
176
+ break;
177
+ case 'midware':
178
+ content = `export const ${name} = (req, res, next) => {\n next();\n};\n`;
179
+ break;
180
+ }
181
+
182
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
183
+ fs.writeFileSync(filePath, content);
184
+ console.log(`✅ ${name} ${type} created at ${folders[type]}/${name}.mjs`);
149
185
  break;
186
+ }
150
187
 
151
- // ====================== DATABASE COMMANDS ======================
188
+ // ==================== DATABASE COMMANDS ====================
152
189
 
153
190
  case 'create-db':
154
- getDbConnection().then(() => console.log('✅ Database ready.')).catch(err => {
155
- console.error(`❌ Failed: ${err.message}`);
156
- process.exit(1);
157
- });
191
+ getDbConnection()
192
+ .then(() => console.log('✅ Database configured and connected successfully!'))
193
+ .catch(err => {
194
+ console.error('❌ Database setup failed:', err.message);
195
+ process.exit(1);
196
+ });
158
197
  break;
159
198
 
160
199
  case 'db:config':
161
- getDbConnection(); // Re-runs interactive setup
200
+ getDbConnection();
162
201
  break;
163
202
 
164
203
  case 'db:table':
165
- const sub = args[1];
204
+ const action = args[1];
166
205
  const tableName = args[2];
167
- const extra = args[3];
206
+ const extraArg = args[3];
168
207
 
169
- if (!sub) {
170
- console.log('Usage: mwala db:table <list|create|drop|truncate|rename|copy|exists|describe|count> [args]');
208
+ if (!action) {
209
+ console.error('Usage: mwala db:table <list|describe|count|truncate|rename|copy|exists> [args]');
171
210
  process.exit(1);
172
211
  }
173
212
 
174
- switch (sub) {
213
+ switch (action) {
175
214
  case 'list':
176
215
  listTables();
177
216
  break;
178
- case 'create':
179
- if (!tableName) return console.error('Table name required');
180
- createTable(tableName);
217
+ case 'describe':
218
+ if (!tableName) {
219
+ console.error('Table name required');
220
+ process.exit(1);
221
+ }
222
+ describeTable(tableName);
181
223
  break;
182
- case 'drop':
183
- if (!tableName) return console.error('Table name required');
184
- dropTable(tableName);
224
+ case 'count':
225
+ if (!tableName) {
226
+ console.error('Table name required');
227
+ process.exit(1);
228
+ }
229
+ countRows(tableName);
185
230
  break;
186
231
  case 'truncate':
187
- if (!tableName) return console.error('Table name required');
188
- truncateTable(tableName);
232
+ if (!tableName) {
233
+ console.error('Table name required');
234
+ process.exit(1);
235
+ }
236
+ if (readlineSync.keyInYN(`Truncate ${tableName}? This cannot be undone.`)) {
237
+ truncateTable(tableName);
238
+ }
189
239
  break;
190
240
  case 'rename':
191
- if (!tableName || !extra) return console.error('Usage: rename <old> <new>');
192
- renameTable(tableName, extra);
241
+ if (!tableName || !extraArg) {
242
+ console.error('Usage: mwala db:table rename <oldName> <newName>');
243
+ process.exit(1);
244
+ }
245
+ renameTable(tableName, extraArg);
193
246
  break;
194
247
  case 'copy':
195
- if (!tableName || !extra) return console.error('Usage: copy <source> <destination>');
196
- copyTable(tableName, extra);
248
+ if (!tableName || !extraArg) {
249
+ console.error('Usage: mwala db:table copy <source> <destination>');
250
+ process.exit(1);
251
+ }
252
+ copyTable(tableName, extraArg);
197
253
  break;
198
254
  case 'exists':
199
- if (!tableName) return console.error('Table name required');
255
+ if (!tableName) {
256
+ console.error('Table name required');
257
+ process.exit(1);
258
+ }
200
259
  checkTableExists(tableName);
201
260
  break;
202
- case 'describe':
203
- if (!tableName) return console.error('Table name required');
204
- describeTable(tableName);
205
- break;
206
- case 'count':
207
- if (!tableName) return console.error('Table name required');
208
- countRows(tableName);
209
- break;
210
261
  default:
211
- console.log('Invalid db:table subcommand');
262
+ console.error(`Unknown db:table action: ${action}`);
263
+ process.exit(1);
212
264
  }
213
265
  break;
214
266
 
215
- case 'migrate':
216
- if (args[1] === 'all') migrateAll();
217
- else console.error('Use: mwala migrate all');
218
- break;
219
-
220
- case 'rollback':
221
- if (args[1] === 'last') rollbackLastMigration();
222
- else if (args[1] === 'all') dropAllTables(); // or full rollback
223
- else console.error('Use: mwala rollback last');
224
- break;
225
-
226
- case 'db:seed':
227
- if (!args[1]) return console.error('Seed file required');
228
- seedDatabase(args[1]);
229
- break;
230
-
231
267
  case 'db:backup':
232
268
  backupDatabase();
233
269
  break;
234
270
 
235
271
  case 'db:restore':
236
- if (!args[1]) return console.error('Backup file required');
272
+ if (!args[1]) {
273
+ console.error('Usage: mwala db:restore <backup-file.sql>');
274
+ process.exit(1);
275
+ }
237
276
  restoreDatabase(args[1]);
238
277
  break;
239
278
 
240
- case 'db:export':
241
- if (!args[1] || !args[2]) return console.error('Usage: db:export <table> <file.csv>');
242
- exportTableToCsv(args[1], args[2]);
243
- break;
244
-
245
- case 'db:import':
246
- if (!args[1] || !args[2]) return console.error('Usage: db:import <file.csv> <table>');
247
- importCsvToTable(args[1], args[2]);
248
- break;
249
-
250
279
  case 'db:size':
251
280
  showDatabaseSize();
252
281
  break;
253
282
 
254
283
  case 'db:indexes':
255
- if (!args[1]) return console.error('Table name required');
284
+ if (!args[1]) {
285
+ console.error('Table name required');
286
+ process.exit(1);
287
+ }
256
288
  listIndexes(args[1]);
257
289
  break;
258
290
 
259
- case 'db:analyze':
260
- if (!args[1]) return console.error('Table name required');
261
- analyzeTable(args[1]);
262
- break;
263
-
264
- case 'db:reindex':
265
- if (!args[1]) return console.error('Table name required');
266
- reindexTable(args[1]);
267
- break;
268
-
269
291
  case 'db:vacuum':
270
292
  vacuumDatabase();
271
293
  break;
@@ -275,18 +297,49 @@ switch (command) {
275
297
  break;
276
298
 
277
299
  case 'db:kill-connections':
278
- if (readlineSync.keyInYN('⚠️ Kill all other connections?')) {
300
+ if (readlineSync.keyInYN('⚠️ Kill all other database connections?')) {
279
301
  killConnections();
302
+ } else {
303
+ console.log('Cancelled.');
280
304
  }
281
305
  break;
282
306
 
283
307
  case 'db:drop-all-tables':
284
- if (readlineSync.keyInYN('⚠️⚠️ This will DROP ALL TABLES! Continue?')) {
285
- dropAllTables();
308
+ if (readlineSync.keyInYN('⚠️⚠️⚠️ DROP ALL TABLES PERMANENTLY? Type YES to confirm:')) {
309
+ if (readlineSync.question('Type database name to confirm: ') === process.env.DB_NAME) {
310
+ dropAllTables();
311
+ } else {
312
+ console.log('Database name mismatch. Aborted.');
313
+ }
286
314
  }
287
315
  break;
288
316
 
317
+ case 'db:export':
318
+ if (!args[1] || !args[2]) {
319
+ console.error('Usage: mwala db:export <table> <output.csv>');
320
+ process.exit(1);
321
+ }
322
+ exportTableToCsv(args[1], args[2]);
323
+ break;
324
+
325
+ case 'db:import':
326
+ if (!args[1] || !args[2]) {
327
+ console.error('Usage: mwala db:import <input.csv> <table>');
328
+ process.exit(1);
329
+ }
330
+ importCsvToTable(args[1], args[2]);
331
+ break;
332
+
333
+ case 'db:seed':
334
+ if (!args[1]) {
335
+ console.error('Usage: mwala db:seed <seedFile.mjs>');
336
+ process.exit(1);
337
+ }
338
+ seedDatabase(args[1]);
339
+ break;
340
+
289
341
  default:
290
- console.error(`Unknown command: ${command}\nRun "mwala help" for list.`);
342
+ console.error(`Unknown command: ${command}`);
343
+ console.log('Run "mwala help" for available commands.');
291
344
  process.exit(1);
292
345
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mwalajs",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "MwalaJS Framework CLI Tool and Web Framework for Backend and Frontend Development.",
5
5
  "type": "module",
6
6
  "main": "app.mjs",
package/utils/dbUtils.mjs CHANGED
@@ -1,124 +1,150 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
+ import { execSync } from 'child_process';
3
4
  import dotenv from 'dotenv';
4
5
  import mysql from 'mysql2/promise';
5
6
  import { Client } from 'pg';
6
7
  import { MongoClient } from 'mongodb';
7
8
  import sqlite3 from 'sqlite3';
8
- import { execSync } from 'child_process';
9
9
  import readlineSync from 'readline-sync';
10
10
 
11
11
  dotenv.config();
12
12
 
13
- const { DB_TYPE, DB_HOST, DB_USER, DB_PASSWORD, DB_NAME } = process.env;
13
+ const { DB_TYPE, DB_HOST = 'localhost', DB_USER, DB_PASSWORD, DB_NAME } = process.env;
14
14
 
15
- let connection = null;
15
+ let conn = null;
16
16
 
17
- const getConnection = async () => {
18
- if (connection) return connection;
17
+ const getConn = async () => {
18
+ if (conn) return conn;
19
19
 
20
- switch (DB_TYPE) {
21
- case 'mysql':
22
- connection = await mysql.createConnection({
23
- host: DB_HOST, user: DB_USER, password: DB_PASSWORD, database: DB_NAME
20
+ try {
21
+ if (DB_TYPE === 'mysql') {
22
+ conn = await mysql.createConnection({
23
+ host: DB_HOST,
24
+ user: DB_USER,
25
+ password: DB_PASSWORD,
26
+ database: DB_NAME
27
+ });
28
+ } else if (DB_TYPE === 'postgresql') {
29
+ conn = new Client({
30
+ host: DB_HOST,
31
+ user: DB_USER,
32
+ password: DB_PASSWORD,
33
+ database: DB_NAME
24
34
  });
25
- break;
26
- case 'postgresql':
27
- connection = new Client({ host: DB_HOST, user: DB_USER, password: DB_PASSWORD, database: DB_NAME });
28
- await connection.connect();
29
- break;
30
- case 'mongodb':
31
- connection = await MongoClient.connect(`mongodb://${DB_HOST}:27017/${DB_NAME}`);
32
- break;
33
- case 'sqlite':
34
- connection = new sqlite3.Database(`./${DB_NAME}.sqlite`);
35
- break;
35
+ await conn.connect();
36
+ } else if (DB_TYPE === 'sqlite') {
37
+ conn = new sqlite3.Database(`./${DB_NAME}.sqlite`);
38
+ } else if (DB_TYPE === 'mongodb') {
39
+ conn = await MongoClient.connect(`mongodb://${DB_HOST}:27017`);
40
+ conn = conn.db(DB_NAME);
41
+ }
42
+ } catch (err) {
43
+ console.error('Connection failed:', err.message);
44
+ process.exit(1);
36
45
  }
37
- return connection;
46
+
47
+ return conn;
38
48
  };
39
49
 
40
50
  export const listTables = async () => {
41
- const conn = await getConnection();
51
+ const connection = await getConn();
42
52
  if (DB_TYPE === 'mysql') {
43
- const [rows] = await conn.query('SHOW TABLES');
44
- console.log('Tables:', rows.map(r => Object.values(r)[0]));
53
+ const [rows] = await connection.query('SHOW TABLES');
54
+ console.log('Tables:\n', rows.map(r => Object.values(r)[0]).join('\n'));
45
55
  } else if (DB_TYPE === 'postgresql') {
46
- const res = await conn.query(`SELECT tablename FROM pg_tables WHERE schemaname = 'public'`);
47
- console.log('Tables:', res.rows.map(r => r.tablename));
56
+ const res = await connection.query("SELECT tablename FROM pg_tables WHERE schemaname = 'public'");
57
+ console.log('Tables:\n', res.rows.map(r => r.tablename).join('\n'));
48
58
  } else if (DB_TYPE === 'sqlite') {
49
- conn.all("SELECT name FROM sqlite_master WHERE type='table'", (err, rows) => {
50
- console.log('Tables:', rows.map(r => r.name));
59
+ connection.all("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'", (_, rows) => {
60
+ console.log('Tables:\n', rows.map(r => r.name).join('\n'));
51
61
  });
52
62
  }
53
63
  };
54
64
 
55
65
  export const describeTable = async (table) => {
56
- const conn = await getConnection();
66
+ const connection = await getConn();
57
67
  if (DB_TYPE === 'mysql') {
58
- const [rows] = await conn.query(`DESCRIBE \`${table}\``);
68
+ const [rows] = await connection.query(`DESCRIBE \`${table}\``);
59
69
  console.table(rows);
60
70
  } else if (DB_TYPE === 'postgresql') {
61
- const res = await conn.query(`
62
- SELECT column_name, data_type, is_nullable
63
- FROM information_schema.columns
64
- WHERE table_name = $1`, [table]);
71
+ const res = await connection.query(`
72
+ SELECT column_name, data_type, is_nullable, column_default
73
+ FROM information_schema.columns WHERE table_name = $1
74
+ `, [table]);
65
75
  console.table(res.rows);
66
76
  }
67
77
  };
68
78
 
79
+ export const countRows = async (table) => {
80
+ const connection = await getConn();
81
+ const [res] = await connection.query(`SELECT COUNT(*) AS count FROM \`${table}\``);
82
+ console.log(`Rows in ${table}: ${res[0].count}`);
83
+ };
84
+
69
85
  export const truncateTable = async (table) => {
70
- const conn = await getConnection();
71
- await conn.query(`TRUNCATE TABLE \`${table}\` RESTART IDENTITY CASCADE`);
72
- console.log(`Truncated ${table}`);
86
+ const connection = await getConn();
87
+ await connection.query(`TRUNCATE TABLE \`${table}\` RESTART IDENTITY CASCADE`);
88
+ console.log(`✅ ${table} truncated`);
73
89
  };
74
90
 
75
91
  export const renameTable = async (oldName, newName) => {
76
- const conn = await getConnection();
77
- await conn.query(`RENAME TABLE \`${oldName}\` TO \`${newName}\``);
92
+ const connection = await getConn();
93
+ await connection.query(`ALTER TABLE \`${oldName}\` RENAME TO \`${newName}\``);
78
94
  console.log(`Renamed ${oldName} → ${newName}`);
79
95
  };
80
96
 
81
97
  export const backupDatabase = () => {
82
- const timestamp = new Date().toISOString().slice(0,19).replace(/:/g, '-');
83
- const backupFile = `backup-${DB_NAME}-${timestamp}.sql`;
84
-
85
- if (DB_TYPE === 'mysql') {
86
- execSync(`mysqldump -h ${DB_HOST} -u ${DB_USER} -p${DB_PASSWORD} ${DB_NAME} > ${backupFile}`);
87
- } else if (DB_TYPE === 'postgresql') {
88
- execSync(`pg_dump -h ${DB_HOST} -U ${DB_USER} ${DB_NAME} > ${backupFile}`);
98
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
99
+ const file = `backup-${DB_NAME}-${timestamp}.sql`;
100
+
101
+ try {
102
+ if (DB_TYPE === 'mysql') {
103
+ execSync(`mysqldump -h ${DB_HOST} -u ${DB_USER} -p${DB_PASSWORD} ${DB_NAME} > ${file}`);
104
+ } else if (DB_TYPE === 'postgresql') {
105
+ process.env.PGPASSWORD = DB_PASSWORD;
106
+ execSync(`pg_dump -h ${DB_HOST} -U ${DB_USER} ${DB_NAME} > ${file}`);
107
+ }
108
+ console.log(`✅ Backup saved: ${file}`);
109
+ } catch (err) {
110
+ console.error('Backup failed:', err.message);
89
111
  }
90
- console.log(`Backup saved: ${backupFile}`);
91
112
  };
92
113
 
93
114
  export const restoreDatabase = (file) => {
94
- if (!fs.existsSync(file)) return console.error('File not found');
95
-
96
- if (DB_TYPE === 'mysql') {
97
- execSync(`mysql -h ${DB_HOST} -u ${DB_USER} -p${DB_PASSWORD} ${DB_NAME} < ${file}`);
98
- } else if (DB_TYPE === 'postgresql') {
99
- execSync(`psql -h ${DB_HOST} -U ${DB_USER} -d ${DB_NAME} -f ${file}`);
115
+ if (!fs.existsSync(file)) {
116
+ console.error('Backup file not found');
117
+ return;
118
+ }
119
+ try {
120
+ if (DB_TYPE === 'mysql') {
121
+ execSync(`mysql -h ${DB_HOST} -u ${DB_USER} -p${DB_PASSWORD} ${DB_NAME} < ${file}`);
122
+ } else if (DB_TYPE === 'postgresql') {
123
+ process.env.PGPASSWORD = DB_PASSWORD;
124
+ execSync(`psql -h ${DB_HOST} -U ${DB_USER} -d ${DB_NAME} -f ${file}`);
125
+ }
126
+ console.log('✅ Database restored');
127
+ } catch (err) {
128
+ console.error('Restore failed:', err.message);
100
129
  }
101
- console.log('Database restored');
102
- };
103
-
104
- // Add more functions similarly: exportTableToCsv, countRows, etc.
105
- // (You can expand this file further as needed)
106
-
107
- export const showDatabaseSize = () => {
108
- console.log(`Size estimation not implemented for ${DB_TYPE} yet.`);
109
130
  };
110
131
 
111
- // Placeholder for other commands...
112
- export const seedDatabase = (file) => console.log(`Seeding from ${file} not yet implemented`);
132
+ export const showDatabaseSize = () => console.log(`Size info not implemented for ${DB_TYPE} yet`);
113
133
  export const listIndexes = () => console.log('Indexes list coming soon');
114
- export const vacuumDatabase = () => console.log('VACUUM executed');
115
- export const dropAllTables = () => console.log('All tables dropped (dangerous!)');
116
- export const copyTable = () => console.log('Table copied');
117
- export const exportTableToCsv = () => console.log('Exported to CSV');
118
- export const importCsvToTable = () => console.log('Imported CSV');
119
- export const countRows = () => console.log('Row count shown');
120
- export const analyzeTable = () => console.log('Table analyzed');
121
- export const reindexTable = () => console.log('Indexes rebuilt');
122
- export const showConnections = () => console.log('Active connections listed');
123
- export const killConnections = () => console.log('Connections killed');
124
- export const checkTableExists = () => console.log('Table existence checked');
134
+ export const vacuumDatabase = () => console.log('VACUUM/optimize not implemented yet');
135
+ export const showConnections = () => console.log('Connections list not implemented');
136
+ export const killConnections = () => console.log('Kill connections not implemented');
137
+ export const dropAllTables = () => console.log('Drop all tables not implemented (too dangerous without confirmation logic)');
138
+ export const copyTable = () => console.log('Copy table not implemented');
139
+ export const exportTableToCsv = () => console.log('CSV export not implemented');
140
+ export const importCsvToTable = () => console.log('CSV import not implemented');
141
+ export const seedDatabase = (file) => {
142
+ if (fs.existsSync(file)) {
143
+ import(pathToFileURL(path.resolve(file)).href).then(mod => {
144
+ console.log('Seed executed');
145
+ });
146
+ } else {
147
+ console.error('Seed file not found');
148
+ }
149
+ };
150
+ export const checkTableExists = () => console.log('Check exists not implemented');