mwalajs 1.0.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/.env +5 -0
- package/LICENSE +21 -0
- package/README.md +542 -0
- package/app.mjs +23 -0
- package/bin/backupnewclean.js +162 -0
- package/bin/mwala.mjs +176 -0
- package/config/createTablesetdb.mjs +38 -0
- package/config/createdatabase.mjs +157 -0
- package/config/serverConfig.mjs +1 -0
- package/controllers/fileController.mjs +15 -0
- package/controllers/homeController.mjs +28 -0
- package/createProject.mjs +120 -0
- package/migrations/20250308115724_create_users.mjs +45 -0
- package/migrations/20250724111240_create_transactions.mjs +19 -0
- package/migrations/migration_log.json +1 -0
- package/models/exampleModel.mjs +5 -0
- package/mwala +5 -0
- package/mwala.cmd +2 -0
- package/mwalajs/index.js +109 -0
- package/mwalajs/index.mjs +121 -0
- package/mwalajs/package-lock.json +836 -0
- package/mwalajs/package.json +16 -0
- package/package.json +58 -0
- package/public/styles.css +115 -0
- package/routes/homeRoutes.mjs +12 -0
- package/runMigrations.mjs +137 -0
- package/setupMwalajs.mjs +58 -0
- package/ujasi/README.md +542 -0
- package/ujasi/app.mjs +33 -0
- package/ujasi/bin/backupnewclean.js +162 -0
- package/ujasi/bin/mwala.mjs +176 -0
- package/ujasi/config/createTablesetdb.mjs +38 -0
- package/ujasi/config/createdatabase.mjs +156 -0
- package/ujasi/config/serverConfig.mjs +1 -0
- package/ujasi/controllers/fileController.mjs +15 -0
- package/ujasi/controllers/homeController.mjs +28 -0
- package/ujasi/models/exampleModel.mjs +5 -0
- package/ujasi/mwalajs/index.js +109 -0
- package/ujasi/mwalajs/index.mjs +121 -0
- package/ujasi/mwalajs/package-lock.json +836 -0
- package/ujasi/mwalajs/package.json +16 -0
- package/ujasi/package-lock.json +8546 -0
- package/ujasi/package.json +58 -0
- package/ujasi/public/styles.css +115 -0
- package/ujasi/routes/homeRoutes.mjs +12 -0
- package/ujasi/runMigrations.mjs +137 -0
- package/ujasi/setupMwalajs.mjs +58 -0
- package/ujasi/views/about.ejs +159 -0
- package/ujasi/views/index.ejs +227 -0
- package/ujasi/views/sitemap.xml +1 -0
- package/ujasi/views/steps.ejs +514 -0
- package/ujasi/views/welcome.ejs +257 -0
- package/views/about.ejs +159 -0
- package/views/index.ejs +227 -0
- package/views/sitemap.xml +1 -0
- package/views/steps.ejs +514 -0
- package/views/welcome.ejs +257 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mwalajs",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"description": "",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"express": "^4.21.2"
|
|
15
|
+
}
|
|
16
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mwalajs",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "MwalaJS Framework CLI Tool",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "app.mjs",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node app.mjs",
|
|
9
|
+
"cli": "node bin/mwala.mjs"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"mwala": "./bin/mwala.mjs"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"dotenv": "^16.4.7",
|
|
16
|
+
"ejs": "^3.1.10",
|
|
17
|
+
"express": "^4.21.2",
|
|
18
|
+
"mongodb": "^6.14.2",
|
|
19
|
+
"mongoose": "^8.12.1",
|
|
20
|
+
"mpath": "^0.9.0",
|
|
21
|
+
"multer": "^1.4.2",
|
|
22
|
+
"mysql2": "^3.13.0",
|
|
23
|
+
"pg": "^8.13.3",
|
|
24
|
+
"pg-hstore": "^2.3.4",
|
|
25
|
+
"readline-sync": "^1.4.10",
|
|
26
|
+
"sequelize": "^6.37.6",
|
|
27
|
+
"sqlite3": "^5.1.7"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@vercel/ncc": "^0.38.3",
|
|
31
|
+
"nexe": "^5.0.0-beta.4",
|
|
32
|
+
"pkg": "^5.8.1"
|
|
33
|
+
},
|
|
34
|
+
"pkg": {
|
|
35
|
+
"assets": [
|
|
36
|
+
"views/**/*",
|
|
37
|
+
"public/**/*",
|
|
38
|
+
"config/**/*.mjs",
|
|
39
|
+
"runMigrations.mjs",
|
|
40
|
+
"setupMwalajs.mjs",
|
|
41
|
+
"createProject.mjs",
|
|
42
|
+
".env",
|
|
43
|
+
"README.md",
|
|
44
|
+
"package.json"
|
|
45
|
+
],
|
|
46
|
+
"targets": [
|
|
47
|
+
"node18-win-x64",
|
|
48
|
+
"node18-linux-x64",
|
|
49
|
+
"node18-macos-x64"
|
|
50
|
+
],
|
|
51
|
+
"outputPath": "dist"
|
|
52
|
+
},
|
|
53
|
+
"author": "HEKIMA AMBALILE MWALA",
|
|
54
|
+
"license": "MIT",
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=18.0.0"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
|
|
2
|
+
body {
|
|
3
|
+
font-family: Arial, sans-serif;
|
|
4
|
+
padding: 20px;
|
|
5
|
+
background-color: #f9f9f9;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
h1 {
|
|
9
|
+
text-align: center;
|
|
10
|
+
color: #333;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
form {
|
|
14
|
+
width: 300px;
|
|
15
|
+
margin: 0 auto;
|
|
16
|
+
padding: 20px;
|
|
17
|
+
background-color: #fff;
|
|
18
|
+
border-radius: 8px;
|
|
19
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
input[type="file"] {
|
|
23
|
+
width: 100%;
|
|
24
|
+
margin-bottom: 10px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
button {
|
|
28
|
+
width: 100%;
|
|
29
|
+
padding: 10px;
|
|
30
|
+
background-color: #4CAF50;
|
|
31
|
+
color: white;
|
|
32
|
+
border: none;
|
|
33
|
+
border-radius: 4px;
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
button:hover {
|
|
38
|
+
background-color: #45a049;
|
|
39
|
+
}
|
|
40
|
+
/* General Styles */
|
|
41
|
+
body {
|
|
42
|
+
font-family: Arial, sans-serif;
|
|
43
|
+
line-height: 1.6;
|
|
44
|
+
background-color: #f8f9fa;
|
|
45
|
+
color: #333;
|
|
46
|
+
margin: 0;
|
|
47
|
+
padding: 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* Header */
|
|
51
|
+
header {
|
|
52
|
+
background-color: #007bff;
|
|
53
|
+
color: white;
|
|
54
|
+
text-align: center;
|
|
55
|
+
padding: 20px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
h1 {
|
|
59
|
+
font-size: 2.2em;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
p {
|
|
63
|
+
margin: 10px 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Sections */
|
|
67
|
+
section {
|
|
68
|
+
max-width: 800px;
|
|
69
|
+
margin: 20px auto;
|
|
70
|
+
padding: 20px;
|
|
71
|
+
background: white;
|
|
72
|
+
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
|
|
73
|
+
border-radius: 8px;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
h2 {
|
|
77
|
+
color: #007bff;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
ul {
|
|
81
|
+
list-style: none;
|
|
82
|
+
padding: 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
ul li {
|
|
86
|
+
background: url('checkmark.png') left center no-repeat;
|
|
87
|
+
background-size: 18px;
|
|
88
|
+
padding-left: 30px;
|
|
89
|
+
margin-bottom: 8px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* Download Button */
|
|
93
|
+
.btn {
|
|
94
|
+
display: inline-block;
|
|
95
|
+
padding: 12px 20px;
|
|
96
|
+
color: white;
|
|
97
|
+
background-color: #007bff;
|
|
98
|
+
text-decoration: none;
|
|
99
|
+
border-radius: 5px;
|
|
100
|
+
font-size: 1.1em;
|
|
101
|
+
transition: 0.3s;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.btn:hover {
|
|
105
|
+
background-color: #0056b3;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Footer */
|
|
109
|
+
footer {
|
|
110
|
+
text-align: center;
|
|
111
|
+
padding: 15px;
|
|
112
|
+
background: #333;
|
|
113
|
+
color: white;
|
|
114
|
+
margin-top: 20px;
|
|
115
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import mwalajs from 'mwalajs';
|
|
2
|
+
import { homeController,Steps,welcome,about } from '../controllers/homeController.mjs';
|
|
3
|
+
|
|
4
|
+
const router = mwalajs.Router(); // Corrected Router usage
|
|
5
|
+
|
|
6
|
+
router.get('/', homeController.getHomePage);
|
|
7
|
+
router.get('/steps',Steps.getSteps);
|
|
8
|
+
router.get('/welcome',welcome.getwelcome);
|
|
9
|
+
router.get('/about',about.getabout);
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
export { router as homeRoutes };
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import readline from 'readline';
|
|
4
|
+
import { sequelize } from './config/createTablesetdb.mjs';
|
|
5
|
+
import { DataTypes } from 'sequelize';
|
|
6
|
+
|
|
7
|
+
// Define directory for migrations
|
|
8
|
+
const migrationsDir = path.join(process.cwd(), 'migrations');
|
|
9
|
+
const migrationLog = path.join(migrationsDir, 'migration_log.json');
|
|
10
|
+
|
|
11
|
+
// Ensure migrations folder exists
|
|
12
|
+
if (!fs.existsSync(migrationsDir)) {
|
|
13
|
+
fs.mkdirSync(migrationsDir, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (!fs.existsSync(migrationLog)) {
|
|
17
|
+
fs.writeFileSync(migrationLog, JSON.stringify([]));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const tableExists = async (tableName) => {
|
|
21
|
+
const tables = await sequelize.getQueryInterface().showAllTables();
|
|
22
|
+
return tables.includes(tableName);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const createTable = async (tableName) => {
|
|
26
|
+
if (await tableExists(tableName)) {
|
|
27
|
+
console.log(` Table "${tableName}" already exists.`);
|
|
28
|
+
const userResponse = await askUser(`Do you want to drop and recreate "${tableName}"? (yes/no): `);
|
|
29
|
+
if (userResponse.toLowerCase() !== 'yes') {
|
|
30
|
+
console.log(` Operation canceled.`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
await dropTable(tableName);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const timestamp = new Date().toISOString().replace(/[-T:]/g, '').split('.')[0];
|
|
37
|
+
const migrationFile = path.join(migrationsDir, `${timestamp}_create_${tableName}.mjs`);
|
|
38
|
+
|
|
39
|
+
const migrationTemplate = `
|
|
40
|
+
import { sequelize } from '../config/createTablesetdb.mjs';
|
|
41
|
+
import { DataTypes } from 'sequelize';
|
|
42
|
+
|
|
43
|
+
export const up = async () => {
|
|
44
|
+
await sequelize.getQueryInterface().createTable('${tableName}', {
|
|
45
|
+
id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true, allowNull: false },
|
|
46
|
+
name: { type: DataTypes.STRING, allowNull: false },
|
|
47
|
+
email: { type: DataTypes.STRING, allowNull: false, unique: true },
|
|
48
|
+
password: { type: DataTypes.STRING, allowNull: false },
|
|
49
|
+
age: { type: DataTypes.INTEGER, allowNull: true },
|
|
50
|
+
address: { type: DataTypes.STRING, allowNull: true },
|
|
51
|
+
createdAt: { type: DataTypes.DATE, allowNull: false, defaultValue: new Date() },
|
|
52
|
+
updatedAt: { type: DataTypes.DATE, allowNull: false, defaultValue: new Date() }
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const down = async () => {
|
|
57
|
+
await sequelize.getQueryInterface().dropTable('${tableName}');
|
|
58
|
+
};
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
fs.writeFileSync(migrationFile, migrationTemplate.trim());
|
|
62
|
+
console.log(` Migration file created: ${migrationFile}`);
|
|
63
|
+
console.log(` Run "mwala migrate all" to apply migrations.`);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const dropTable = async (tableName) => {
|
|
67
|
+
if (!(await tableExists(tableName))) {
|
|
68
|
+
console.log(` Table "${tableName}" does not exist.`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
await sequelize.getQueryInterface().dropTable(tableName);
|
|
73
|
+
console.log(` Table "${tableName}" dropped successfully.`);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error(` Failed to drop table "${tableName}": ${error.message}`);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const migrateAll = async () => {
|
|
80
|
+
const files = fs.readdirSync(migrationsDir).filter(file => file.endsWith('.mjs')).sort();
|
|
81
|
+
const executedMigrations = JSON.parse(fs.readFileSync(migrationLog));
|
|
82
|
+
console.log(` Found ${files.length} migration(s) to run.`);
|
|
83
|
+
|
|
84
|
+
for (const file of files) {
|
|
85
|
+
if (executedMigrations.includes(file)) continue;
|
|
86
|
+
console.log(` Running migration: ${file}`);
|
|
87
|
+
try {
|
|
88
|
+
const migration = await import(`file://${path.join(migrationsDir, file)}`);
|
|
89
|
+
await migration.up();
|
|
90
|
+
executedMigrations.push(file);
|
|
91
|
+
fs.writeFileSync(migrationLog, JSON.stringify(executedMigrations));
|
|
92
|
+
console.log(` Migration ${file} completed.`);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error(` Migration failed: ${error.message}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const rollbackLastMigration = async () => {
|
|
100
|
+
const executedMigrations = JSON.parse(fs.readFileSync(migrationLog));
|
|
101
|
+
if (executedMigrations.length === 0) {
|
|
102
|
+
console.log(' No migrations to rollback.');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const lastMigration = executedMigrations.pop();
|
|
106
|
+
console.log(` Rolling back migration: ${lastMigration}`);
|
|
107
|
+
try {
|
|
108
|
+
const migration = await import(`file://${path.join(migrationsDir, lastMigration)}`);
|
|
109
|
+
await migration.down();
|
|
110
|
+
fs.writeFileSync(migrationLog, JSON.stringify(executedMigrations));
|
|
111
|
+
console.log(` Rolled back: ${lastMigration}`);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
console.error(` Rollback failed: ${error.message}`);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export const listTables = async () => {
|
|
118
|
+
try {
|
|
119
|
+
const tables = await sequelize.getQueryInterface().showAllTables();
|
|
120
|
+
console.log(` Existing tables: ${tables.length > 0 ? tables.join(', ') : 'No tables found.'}`);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error(` Failed to fetch tables: ${error.message}`);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const askUser = (question) => {
|
|
127
|
+
return new Promise((resolve) => {
|
|
128
|
+
const rl = readline.createInterface({
|
|
129
|
+
input: process.stdin,
|
|
130
|
+
output: process.stdout
|
|
131
|
+
});
|
|
132
|
+
rl.question(question, (answer) => {
|
|
133
|
+
rl.close();
|
|
134
|
+
resolve(answer);
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
};
|
package/setupMwalajs.mjs
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Function to install express in mwalajs and copy the folder into node_modules.
|
|
9
|
+
*/
|
|
10
|
+
async function setupMwalajs() {
|
|
11
|
+
const projectDir = process.cwd(); // Get project root directory
|
|
12
|
+
const mwalajsDir = path.join(projectDir, 'mwalajs'); // mwalajs folder
|
|
13
|
+
const nodeModulesDir = path.join(projectDir, 'node_modules'); // node_modules
|
|
14
|
+
const targetMwalajs = path.join(nodeModulesDir, 'mwalajs'); // Destination folder inside node_modules
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
console.log(" Detecting Operating System...");
|
|
18
|
+
const userOS = os.platform(); // Get user OS (win32, linux, darwin)
|
|
19
|
+
console.log(` Running on: ${userOS === "win32" ? "Windows" : userOS === "darwin" ? "MacOS" : "Linux"}`);
|
|
20
|
+
|
|
21
|
+
// Check if mwalajs exists
|
|
22
|
+
if (!fs.existsSync(mwalajsDir)) {
|
|
23
|
+
console.error(" Error: 'mwalajs' folder not found! Please ensure it exists.");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
console.log(" Installing 'dependencies' inside 'mwalajs'...");
|
|
28
|
+
execSync('npm install express --prefix mwalajs', { stdio: 'inherit' });
|
|
29
|
+
|
|
30
|
+
// Ensure node_modules exists
|
|
31
|
+
if (!fs.existsSync(nodeModulesDir)) {
|
|
32
|
+
fs.mkdirSync(nodeModulesDir);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Delete existing mwalajs in node_modules if present
|
|
36
|
+
if (fs.existsSync(targetMwalajs)) {
|
|
37
|
+
console.log(" Removing old 'mwalajs' from node_modules...");
|
|
38
|
+
fs.removeSync(targetMwalajs);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
console.log(" Copying 'mwalajs' to 'node_modules'...");
|
|
42
|
+
fs.copySync(mwalajsDir, targetMwalajs, { overwrite: true });
|
|
43
|
+
|
|
44
|
+
console.log(` Successfully installed 'dependencies' and moved 'mwalajs' to:`);
|
|
45
|
+
console.log(` ${targetMwalajs}`);
|
|
46
|
+
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error(" Error:", error.message);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Export the function so it can be used anywhere
|
|
53
|
+
export { setupMwalajs };
|
|
54
|
+
|
|
55
|
+
// Prevent auto-execution unless explicitly called (ES Module Fix)
|
|
56
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
57
|
+
setupMwalajs();
|
|
58
|
+
}
|