mwalajs 1.0.7 → 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/.env.backup-2025-12-04T08-55-09-593Z +5 -0
- package/app.mjs +4 -0
- package/bin/mwala copy.mjs +212 -0
- package/bin/mwala.mjs +244 -76
- package/config/createdatabase copy.mjs +362 -0
- package/config/createdatabase.mjs +0 -158
- package/package.json +1 -1
- package/public/images/hekima-mwala.jpg +0 -0
- package/public/images/hekima-mwala2.jpg +0 -0
- package/public/images/mwala3.jpg +0 -0
- package/public/images/mwalajs.jpg +0 -0
- package/public/images/mwalajs1.jpg +0 -0
- package/utils/dbUtils.mjs +150 -0
- package/views/about.ejs +271 -136
- package/views/index.ejs +325 -428
- package/views/mwalajs-framework-documentation.ejs +778 -0
- package/views/partials/footer.ejs +102 -0
- package/views/partials/header.ejs +160 -0
- package/views/steps copy.ejs +243 -0
- package/views/steps.ejs +208 -482
- package/views/welcome.ejs +242 -184
package/app.mjs
CHANGED
|
@@ -17,6 +17,10 @@ mwalajs.use('/', homeRoutes);
|
|
|
17
17
|
mwalajs.use('/steps', homeRoutes);
|
|
18
18
|
mwalajs.use('/about', homeRoutes);
|
|
19
19
|
mwalajs.use('/welcome', homeRoutes);
|
|
20
|
+
mwalajs.get('/mwalajs-framework-documentation', (req, res) => {
|
|
21
|
+
res.render('mwalajs-framework-documentation');
|
|
22
|
+
});
|
|
23
|
+
|
|
20
24
|
// Start server
|
|
21
25
|
const port = process.env.PORT || 2025;
|
|
22
26
|
mwalajs.listen(port, () => {
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
|
|
11
|
+
// Dynamically import modules using relative paths
|
|
12
|
+
const { getDbConnection } = await import(pathToFileURL(path.join(__dirname, '../config/createdatabase.mjs')).href);
|
|
13
|
+
const { createTable, dropTable, migrateAll, rollbackLastMigration } = await import(pathToFileURL(path.join(__dirname, '../runMigrations.mjs')).href);
|
|
14
|
+
const { setupMwalajs } = await import(pathToFileURL(path.join(__dirname, '../setupMwalajs.mjs')).href);
|
|
15
|
+
const { createProject } = await import(pathToFileURL(path.join(__dirname, '../createProject.mjs')).href);
|
|
16
|
+
|
|
17
|
+
const args = process.argv.slice(2);
|
|
18
|
+
const command = args[0];
|
|
19
|
+
|
|
20
|
+
if (!command || command === 'help' || command === 'h') {
|
|
21
|
+
console.log(`
|
|
22
|
+
MwalaJS CLI - List of Commands:
|
|
23
|
+
|
|
24
|
+
General Commands:
|
|
25
|
+
- mwala -v | mwala --version → Show the MwalaJS version.
|
|
26
|
+
- mwala help | mwala h → Show this help message.
|
|
27
|
+
|
|
28
|
+
Project Management:
|
|
29
|
+
- mwala create-project → Create a new MwalaJS project.
|
|
30
|
+
- mwala init → Initialize MwalaJS in the current project.
|
|
31
|
+
|
|
32
|
+
Running the Application:
|
|
33
|
+
- mwala serve | mwala app.mjs → Start the MwalaJS application.
|
|
34
|
+
|
|
35
|
+
Database Operations:
|
|
36
|
+
- mwala create-db → Create the database specified in the .env file.
|
|
37
|
+
- mwala create-table <name> → Create a specific database table.
|
|
38
|
+
- mwala drop-table <name> → Drop a specific database table.
|
|
39
|
+
- mwala migrate all → Run all pending migrations.
|
|
40
|
+
|
|
41
|
+
Code Generation:
|
|
42
|
+
- mwala generate model <name> → Create a new model.
|
|
43
|
+
- mwala generate controller <name> → Create a new controller.
|
|
44
|
+
- mwala generate route <name> → Create a new route.
|
|
45
|
+
- mwala generate view <name> → Create a new view file.
|
|
46
|
+
- mwala generate midware <name> → Create a new middleware.
|
|
47
|
+
|
|
48
|
+
Use "mwala <command>" to execute a command.
|
|
49
|
+
`);
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
switch (command) {
|
|
54
|
+
case 'version':
|
|
55
|
+
case '-v':
|
|
56
|
+
case 'v':
|
|
57
|
+
case '--version':
|
|
58
|
+
console.log('MwalaJS Version: 1.0.6');
|
|
59
|
+
process.exit(0);
|
|
60
|
+
|
|
61
|
+
case 'create-project':
|
|
62
|
+
createProject();
|
|
63
|
+
break;
|
|
64
|
+
|
|
65
|
+
case 'serve':
|
|
66
|
+
case 'app.mjs':
|
|
67
|
+
const { spawn } = require('child_process');
|
|
68
|
+
|
|
69
|
+
const child = spawn('node', ['app.mjs'], {
|
|
70
|
+
stdio: 'inherit',
|
|
71
|
+
cwd: process.cwd()
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Forward signals ili Ctrl+C ifike kwenye app.mjs moja kwa moja
|
|
75
|
+
process.on('SIGINT', () => {
|
|
76
|
+
child.kill('SIGINT');
|
|
77
|
+
process.exit(0);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
process.on('SIGTERM', () => {
|
|
81
|
+
child.kill('SIGTERM');
|
|
82
|
+
process.exit(0);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Subiri child aexit
|
|
86
|
+
child.on('exit', (code, signal) => {
|
|
87
|
+
if (code !== null) {
|
|
88
|
+
process.exit(code);
|
|
89
|
+
} else {
|
|
90
|
+
process.exit(0);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
child.on('error', (err) => {
|
|
95
|
+
console.error(`Failed to start the app: ${err.message}`);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
});
|
|
98
|
+
break;
|
|
99
|
+
|
|
100
|
+
// case 'serve':
|
|
101
|
+
// case 'app.mjs':
|
|
102
|
+
// try {
|
|
103
|
+
// execSync('node app.mjs', { stdio: 'inherit' });
|
|
104
|
+
// } catch (error) {
|
|
105
|
+
// console.error(` Failed to run the app: ${error.message}`);
|
|
106
|
+
// process.exit(1);
|
|
107
|
+
// }
|
|
108
|
+
// break;
|
|
109
|
+
|
|
110
|
+
case 'init':
|
|
111
|
+
setupMwalajs();
|
|
112
|
+
break;
|
|
113
|
+
|
|
114
|
+
case 'generate': {
|
|
115
|
+
const subCommand = args[1]?.toLowerCase();
|
|
116
|
+
const name = args[2];
|
|
117
|
+
|
|
118
|
+
if (!subCommand || !name) {
|
|
119
|
+
console.log(' Please specify both subCommand and name.');
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const paths = {
|
|
124
|
+
model: 'models',
|
|
125
|
+
controller: 'controllers',
|
|
126
|
+
route: 'routes',
|
|
127
|
+
view: 'views',
|
|
128
|
+
midware: 'middlewares'
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
if (!paths[subCommand]) {
|
|
132
|
+
console.log(` Invalid subCommand: ${subCommand}. Valid options are: ${Object.keys(paths).join(', ')}`);
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const filePath = path.join(process.cwd(), paths[subCommand], `${name}.mjs`);
|
|
137
|
+
|
|
138
|
+
if (fs.existsSync(filePath)) {
|
|
139
|
+
console.log(` ${name} ${subCommand} already exists.`);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
let content = '';
|
|
144
|
+
switch (subCommand) {
|
|
145
|
+
case 'model':
|
|
146
|
+
content = `export const ${name}Model = {};`;
|
|
147
|
+
break;
|
|
148
|
+
case 'controller':
|
|
149
|
+
content = `export const ${name}Controller = { get${name}Page: (req, res) => { res.render('${name}', { title: '${name} Page' }); } };`;
|
|
150
|
+
break;
|
|
151
|
+
case 'route':
|
|
152
|
+
content = `import mwalajs from 'mwalajs';\nimport { ${name}Controller } from '../controllers/${name}Controller.mjs';\nconst router = mwalajs.Router();\nrouter.get('/', ${name}Controller.get${name}Page);\nexport { router as ${name}Route };`;
|
|
153
|
+
break;
|
|
154
|
+
case 'view':
|
|
155
|
+
content = `<!DOCTYPE html>\n<html lang='en'>\n<head>\n <meta charset='UTF-8'>\n <title>${name} Page</title>\n</head>\n<body>\n <h1>${name} View Page</h1>\n</body>\n</html>`;
|
|
156
|
+
break;
|
|
157
|
+
case 'midware':
|
|
158
|
+
content = `export const ${name} = (req, res, next) => { next(); };`;
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
163
|
+
fs.writeFileSync(filePath, content);
|
|
164
|
+
console.log(` ${name} ${subCommand} created successfully in ${paths[subCommand]}/.`);
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
case 'create-db':
|
|
169
|
+
getDbConnection().then(() => console.log('Database created.')).catch(err => {
|
|
170
|
+
console.error(` Failed to create database: ${err.message}`);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
});
|
|
173
|
+
break;
|
|
174
|
+
|
|
175
|
+
case 'create-table':
|
|
176
|
+
if (!args[1]) {
|
|
177
|
+
console.error(' Please specify a table name.');
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
createTable(args[1]);
|
|
181
|
+
break;
|
|
182
|
+
|
|
183
|
+
case 'drop-table':
|
|
184
|
+
if (!args[1]) {
|
|
185
|
+
console.error(' Please specify a table name.');
|
|
186
|
+
process.exit(1);
|
|
187
|
+
}
|
|
188
|
+
dropTable(args[1]);
|
|
189
|
+
break;
|
|
190
|
+
|
|
191
|
+
case 'migrate':
|
|
192
|
+
if (args[1] === 'all') {
|
|
193
|
+
migrateAll();
|
|
194
|
+
} else {
|
|
195
|
+
console.error(' Invalid migration command. Use: mwala migrate all');
|
|
196
|
+
process.exit(1);
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
case 'rollback':
|
|
200
|
+
if (args[1] === 'all') {
|
|
201
|
+
|
|
202
|
+
rollbackLastMigration();
|
|
203
|
+
} else {
|
|
204
|
+
console.error(' Invalid migration command. Use: mwala roll-back all');
|
|
205
|
+
process.exit(1);
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
208
|
+
|
|
209
|
+
default:
|
|
210
|
+
console.error(` Unknown command: ${command}. Run "mwala help" to see available commands.`);
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|
package/bin/mwala.mjs
CHANGED
|
@@ -1,91 +1,146 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
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';
|
|
7
|
+
import readlineSync from 'readline-sync';
|
|
7
8
|
|
|
8
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
10
|
const __dirname = path.dirname(__filename);
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
const args = process.argv.slice(2);
|
|
13
|
+
const command = args[0];
|
|
14
|
+
|
|
15
|
+
// Dynamic imports
|
|
12
16
|
const { getDbConnection } = await import(pathToFileURL(path.join(__dirname, '../config/createdatabase.mjs')).href);
|
|
13
|
-
const { createTable, dropTable, migrateAll, rollbackLastMigration } = await import(pathToFileURL(path.join(__dirname, '../runMigrations.mjs')).href);
|
|
14
17
|
const { setupMwalajs } = await import(pathToFileURL(path.join(__dirname, '../setupMwalajs.mjs')).href);
|
|
15
|
-
const { createProject
|
|
18
|
+
const { createProject } = await import(pathToFileURL(path.join(__dirname, '../createProject.mjs')).href);
|
|
16
19
|
|
|
17
|
-
const
|
|
18
|
-
|
|
20
|
+
const {
|
|
21
|
+
listTables,
|
|
22
|
+
describeTable,
|
|
23
|
+
truncateTable,
|
|
24
|
+
renameTable,
|
|
25
|
+
backupDatabase,
|
|
26
|
+
restoreDatabase,
|
|
27
|
+
seedDatabase,
|
|
28
|
+
showDatabaseSize,
|
|
29
|
+
listIndexes,
|
|
30
|
+
dropAllTables,
|
|
31
|
+
copyTable,
|
|
32
|
+
exportTableToCsv,
|
|
33
|
+
importCsvToTable,
|
|
34
|
+
countRows,
|
|
35
|
+
vacuumDatabase,
|
|
36
|
+
analyzeTable,
|
|
37
|
+
reindexTable,
|
|
38
|
+
showConnections,
|
|
39
|
+
killConnections,
|
|
40
|
+
checkTableExists
|
|
41
|
+
} = await import(pathToFileURL(path.join(__dirname, '../utils/dbUtils.mjs')).href);
|
|
19
42
|
|
|
20
43
|
if (!command || command === 'help' || command === 'h') {
|
|
21
44
|
console.log(`
|
|
22
|
-
|
|
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)
|
|
23
59
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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>
|
|
27
66
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
67
|
+
Database Setup:
|
|
68
|
+
mwala create-db → Interactive DB setup & creation
|
|
69
|
+
mwala db:config → Reconfigure database (.env)
|
|
31
70
|
|
|
32
|
-
|
|
33
|
-
|
|
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
|
|
34
79
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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!
|
|
40
88
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
- mwala generate route <name> → Create a new route.
|
|
45
|
-
- mwala generate view <name> → Create a new view file.
|
|
46
|
-
- mwala generate midware <name> → Create a new middleware.
|
|
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
|
|
47
92
|
|
|
48
|
-
|
|
93
|
+
Migrations:
|
|
94
|
+
mwala migrate all → Run all migrations
|
|
95
|
+
mwala rollback last → Rollback last migration
|
|
96
|
+
|
|
97
|
+
Enjoy building with MwalaJS! 🚀
|
|
49
98
|
`);
|
|
50
99
|
process.exit(0);
|
|
51
100
|
}
|
|
52
101
|
|
|
102
|
+
// ====================== COMMAND SWITCH ======================
|
|
53
103
|
switch (command) {
|
|
54
|
-
case 'version':
|
|
55
104
|
case '-v':
|
|
56
|
-
case '
|
|
105
|
+
case 'version':
|
|
57
106
|
case '--version':
|
|
58
|
-
console.log('MwalaJS Version: 1.0
|
|
107
|
+
console.log('MwalaJS Version: 1.1.0');
|
|
59
108
|
process.exit(0);
|
|
60
109
|
|
|
61
110
|
case 'create-project':
|
|
62
111
|
createProject();
|
|
63
112
|
break;
|
|
64
113
|
|
|
65
|
-
case 'serve':
|
|
66
|
-
case 'app.mjs':
|
|
67
|
-
try {
|
|
68
|
-
execSync('node app.mjs', { stdio: 'inherit' });
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.error(` Failed to run the app: ${error.message}`);
|
|
71
|
-
process.exit(1);
|
|
72
|
-
}
|
|
73
|
-
break;
|
|
74
|
-
|
|
75
114
|
case 'init':
|
|
76
115
|
setupMwalajs();
|
|
77
116
|
break;
|
|
78
117
|
|
|
118
|
+
case 'serve':
|
|
119
|
+
const child = spawn('node', ['app.mjs'], {
|
|
120
|
+
stdio: 'inherit',
|
|
121
|
+
cwd: process.cwd()
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
process.on('SIGINT', () => child.kill('SIGINT'));
|
|
125
|
+
process.on('SIGTERM', () => child.kill('SIGTERM'));
|
|
126
|
+
|
|
127
|
+
child.on('exit', (code) => process.exit(code ?? 0));
|
|
128
|
+
child.on('error', (err) => {
|
|
129
|
+
console.error(`Failed to start app: ${err.message}`);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
});
|
|
132
|
+
break;
|
|
133
|
+
|
|
79
134
|
case 'generate': {
|
|
80
|
-
const
|
|
135
|
+
const type = args[1]?.toLowerCase();
|
|
81
136
|
const name = args[2];
|
|
82
137
|
|
|
83
|
-
if (!
|
|
84
|
-
console.
|
|
138
|
+
if (!type || !name) {
|
|
139
|
+
console.error('Usage: mwala generate <model|controller|route|view|midware> <name>');
|
|
85
140
|
process.exit(1);
|
|
86
141
|
}
|
|
87
142
|
|
|
88
|
-
const
|
|
143
|
+
const folders = {
|
|
89
144
|
model: 'models',
|
|
90
145
|
controller: 'controllers',
|
|
91
146
|
route: 'routes',
|
|
@@ -93,85 +148,198 @@ switch (command) {
|
|
|
93
148
|
midware: 'middlewares'
|
|
94
149
|
};
|
|
95
150
|
|
|
96
|
-
if (!
|
|
97
|
-
console.
|
|
151
|
+
if (!folders[type]) {
|
|
152
|
+
console.error(`Invalid type. Use: ${Object.keys(folders).join(', ')}`);
|
|
98
153
|
process.exit(1);
|
|
99
154
|
}
|
|
100
155
|
|
|
101
|
-
const filePath = path.join(process.cwd(),
|
|
156
|
+
const filePath = path.join(process.cwd(), folders[type], `${name}.mjs`);
|
|
102
157
|
|
|
103
158
|
if (fs.existsSync(filePath)) {
|
|
104
|
-
console.
|
|
159
|
+
console.error(`${name} ${type} already exists.`);
|
|
105
160
|
process.exit(1);
|
|
106
161
|
}
|
|
107
162
|
|
|
108
163
|
let content = '';
|
|
109
|
-
switch (
|
|
164
|
+
switch (type) {
|
|
110
165
|
case 'model':
|
|
111
|
-
content = `export const ${name}Model = {}
|
|
166
|
+
content = `export const ${name}Model = {};\n`;
|
|
112
167
|
break;
|
|
113
168
|
case 'controller':
|
|
114
|
-
content = `export const ${name}Controller = {
|
|
169
|
+
content = `export const ${name}Controller = {\n getPage: (req, res) => {\n res.render('${name}', { title: '${name}' });\n }\n};\n`;
|
|
115
170
|
break;
|
|
116
171
|
case 'route':
|
|
117
|
-
content = `import mwalajs from 'mwalajs';\nimport { ${name}Controller } from '../controllers/${name}
|
|
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`;
|
|
118
173
|
break;
|
|
119
174
|
case 'view':
|
|
120
|
-
content = `<!DOCTYPE html>\n<html lang=
|
|
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`;
|
|
121
176
|
break;
|
|
122
177
|
case 'midware':
|
|
123
|
-
content = `export const ${name} = (req, res, next) => {
|
|
178
|
+
content = `export const ${name} = (req, res, next) => {\n next();\n};\n`;
|
|
124
179
|
break;
|
|
125
180
|
}
|
|
126
181
|
|
|
127
182
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
128
183
|
fs.writeFileSync(filePath, content);
|
|
129
|
-
console.log(
|
|
184
|
+
console.log(`✅ ${name} ${type} created at ${folders[type]}/${name}.mjs`);
|
|
130
185
|
break;
|
|
131
186
|
}
|
|
132
187
|
|
|
188
|
+
// ==================== DATABASE COMMANDS ====================
|
|
189
|
+
|
|
133
190
|
case 'create-db':
|
|
134
|
-
getDbConnection()
|
|
135
|
-
console.
|
|
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
|
+
});
|
|
197
|
+
break;
|
|
198
|
+
|
|
199
|
+
case 'db:config':
|
|
200
|
+
getDbConnection();
|
|
201
|
+
break;
|
|
202
|
+
|
|
203
|
+
case 'db:table':
|
|
204
|
+
const action = args[1];
|
|
205
|
+
const tableName = args[2];
|
|
206
|
+
const extraArg = args[3];
|
|
207
|
+
|
|
208
|
+
if (!action) {
|
|
209
|
+
console.error('Usage: mwala db:table <list|describe|count|truncate|rename|copy|exists> [args]');
|
|
136
210
|
process.exit(1);
|
|
137
|
-
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
switch (action) {
|
|
214
|
+
case 'list':
|
|
215
|
+
listTables();
|
|
216
|
+
break;
|
|
217
|
+
case 'describe':
|
|
218
|
+
if (!tableName) {
|
|
219
|
+
console.error('Table name required');
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
describeTable(tableName);
|
|
223
|
+
break;
|
|
224
|
+
case 'count':
|
|
225
|
+
if (!tableName) {
|
|
226
|
+
console.error('Table name required');
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
countRows(tableName);
|
|
230
|
+
break;
|
|
231
|
+
case 'truncate':
|
|
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
|
+
}
|
|
239
|
+
break;
|
|
240
|
+
case 'rename':
|
|
241
|
+
if (!tableName || !extraArg) {
|
|
242
|
+
console.error('Usage: mwala db:table rename <oldName> <newName>');
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
renameTable(tableName, extraArg);
|
|
246
|
+
break;
|
|
247
|
+
case 'copy':
|
|
248
|
+
if (!tableName || !extraArg) {
|
|
249
|
+
console.error('Usage: mwala db:table copy <source> <destination>');
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
copyTable(tableName, extraArg);
|
|
253
|
+
break;
|
|
254
|
+
case 'exists':
|
|
255
|
+
if (!tableName) {
|
|
256
|
+
console.error('Table name required');
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
checkTableExists(tableName);
|
|
260
|
+
break;
|
|
261
|
+
default:
|
|
262
|
+
console.error(`Unknown db:table action: ${action}`);
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
break;
|
|
266
|
+
|
|
267
|
+
case 'db:backup':
|
|
268
|
+
backupDatabase();
|
|
138
269
|
break;
|
|
139
270
|
|
|
140
|
-
case '
|
|
271
|
+
case 'db:restore':
|
|
141
272
|
if (!args[1]) {
|
|
142
|
-
console.error('
|
|
273
|
+
console.error('Usage: mwala db:restore <backup-file.sql>');
|
|
143
274
|
process.exit(1);
|
|
144
275
|
}
|
|
145
|
-
|
|
276
|
+
restoreDatabase(args[1]);
|
|
277
|
+
break;
|
|
278
|
+
|
|
279
|
+
case 'db:size':
|
|
280
|
+
showDatabaseSize();
|
|
146
281
|
break;
|
|
147
282
|
|
|
148
|
-
case '
|
|
283
|
+
case 'db:indexes':
|
|
149
284
|
if (!args[1]) {
|
|
150
|
-
console.error('
|
|
285
|
+
console.error('Table name required');
|
|
151
286
|
process.exit(1);
|
|
152
287
|
}
|
|
153
|
-
|
|
288
|
+
listIndexes(args[1]);
|
|
289
|
+
break;
|
|
290
|
+
|
|
291
|
+
case 'db:vacuum':
|
|
292
|
+
vacuumDatabase();
|
|
154
293
|
break;
|
|
155
294
|
|
|
156
|
-
case '
|
|
157
|
-
|
|
158
|
-
|
|
295
|
+
case 'db:connections':
|
|
296
|
+
showConnections();
|
|
297
|
+
break;
|
|
298
|
+
|
|
299
|
+
case 'db:kill-connections':
|
|
300
|
+
if (readlineSync.keyInYN('⚠️ Kill all other database connections?')) {
|
|
301
|
+
killConnections();
|
|
159
302
|
} else {
|
|
160
|
-
console.
|
|
303
|
+
console.log('Cancelled.');
|
|
304
|
+
}
|
|
305
|
+
break;
|
|
306
|
+
|
|
307
|
+
case 'db:drop-all-tables':
|
|
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
|
+
}
|
|
314
|
+
}
|
|
315
|
+
break;
|
|
316
|
+
|
|
317
|
+
case 'db:export':
|
|
318
|
+
if (!args[1] || !args[2]) {
|
|
319
|
+
console.error('Usage: mwala db:export <table> <output.csv>');
|
|
161
320
|
process.exit(1);
|
|
162
321
|
}
|
|
322
|
+
exportTableToCsv(args[1], args[2]);
|
|
163
323
|
break;
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
} else {
|
|
169
|
-
console.error(' Invalid migration command. Use: mwala roll-back all');
|
|
324
|
+
|
|
325
|
+
case 'db:import':
|
|
326
|
+
if (!args[1] || !args[2]) {
|
|
327
|
+
console.error('Usage: mwala db:import <input.csv> <table>');
|
|
170
328
|
process.exit(1);
|
|
171
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]);
|
|
172
339
|
break;
|
|
173
340
|
|
|
174
341
|
default:
|
|
175
|
-
console.error(`
|
|
342
|
+
console.error(`Unknown command: ${command}`);
|
|
343
|
+
console.log('Run "mwala help" for available commands.');
|
|
176
344
|
process.exit(1);
|
|
177
|
-
}
|
|
345
|
+
}
|