create-aziz-app 2.0.2 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/create-aziz-app.js +161 -47
- package/package.json +11 -8
- package/template/app.html +1 -2
- package/app.js +0 -88
- package/template/pages/NewPage.jsx +0 -39
- /package/template/pages/{Test.jsx → test.jsx} +0 -0
package/bin/create-aziz-app.js
CHANGED
|
@@ -1,64 +1,178 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const fs
|
|
3
|
+
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
|
+
const readline = require("readline");
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
// Create readline interface
|
|
8
|
+
const rl = readline.createInterface({
|
|
9
|
+
input: process.stdin,
|
|
10
|
+
output: process.stdout
|
|
11
|
+
});
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
// Promisify question
|
|
14
|
+
function question(query) {
|
|
15
|
+
return new Promise(resolve => rl.question(query, resolve));
|
|
16
|
+
}
|
|
11
17
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
// Main function
|
|
19
|
+
async function main() {
|
|
20
|
+
console.log(`\n⚡ Welcome to Aziz App Creator!\n`);
|
|
21
|
+
console.log(`🎨 A React-like framework with state management, routing, and API routes\n`);
|
|
22
|
+
|
|
23
|
+
// Get project name
|
|
24
|
+
let projectName = process.argv[2];
|
|
25
|
+
if (!projectName) {
|
|
26
|
+
projectName = await question('📁 Project name (my-aziz-app): ');
|
|
27
|
+
projectName = projectName.trim() || 'my-aziz-app';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Validate project name
|
|
31
|
+
if (!/^[a-z0-9-_]+$/i.test(projectName)) {
|
|
32
|
+
console.error(`❌ Invalid project name. Use only letters, numbers, hyphens, and underscores.`);
|
|
33
|
+
rl.close();
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const targetDir = path.join(process.cwd(), projectName);
|
|
38
|
+
|
|
39
|
+
// Check if directory exists
|
|
40
|
+
if (fs.existsSync(targetDir)) {
|
|
41
|
+
const overwrite = await question(`⚠️ Folder "${projectName}" already exists. Overwrite? (y/N): `);
|
|
42
|
+
if (overwrite.toLowerCase() !== 'y' && overwrite.toLowerCase() !== 'yes') {
|
|
43
|
+
console.log('❌ Cancelled.');
|
|
44
|
+
rl.close();
|
|
45
|
+
process.exit(0);
|
|
46
|
+
}
|
|
47
|
+
// Remove existing directory
|
|
48
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Ask for port
|
|
52
|
+
let port = await question('🌐 Dev server port (3000): ');
|
|
53
|
+
port = port.trim() || '3000';
|
|
54
|
+
if (!/^\d+$/.test(port)) {
|
|
55
|
+
console.log('⚠️ Invalid port, using default 3000');
|
|
56
|
+
port = '3000';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Ask for features
|
|
60
|
+
console.log('\n✨ Features to include:');
|
|
61
|
+
const includeExamples = await question(' Include example pages? (Y/n): ');
|
|
62
|
+
const includeApiExamples = await question(' Include example API routes? (Y/n): ');
|
|
63
|
+
const includeDocs = await question(' Include documentation? (Y/n): ');
|
|
64
|
+
|
|
65
|
+
const features = {
|
|
66
|
+
examples: includeExamples.toLowerCase() !== 'n' && includeExamples.toLowerCase() !== 'no',
|
|
67
|
+
apiExamples: includeApiExamples.toLowerCase() !== 'n' && includeApiExamples.toLowerCase() !== 'no',
|
|
68
|
+
docs: includeDocs.toLowerCase() !== 'n' && includeDocs.toLowerCase() !== 'no'
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
console.log(`\n⚡ Creating "${projectName}"...\n`);
|
|
72
|
+
|
|
73
|
+
const templateDir = path.join(__dirname, "../template");
|
|
74
|
+
|
|
75
|
+
// Copy the template
|
|
76
|
+
copyDir(templateDir, targetDir, features);
|
|
77
|
+
|
|
78
|
+
// Update package.json with project name
|
|
79
|
+
updatePackageJson(targetDir, projectName);
|
|
80
|
+
|
|
81
|
+
// Update dev server port
|
|
82
|
+
updateDevServerPort(targetDir, port);
|
|
83
|
+
|
|
84
|
+
console.log(`✅ Done! Your project is ready.\n`);
|
|
85
|
+
console.log(`🎉 Welcome to Aziz App - A React-like Framework\n`);
|
|
86
|
+
console.log(`📁 Created project: ${projectName}\n`);
|
|
87
|
+
console.log(`👉 Get started:\n`);
|
|
88
|
+
console.log(` cd ${projectName}`);
|
|
89
|
+
console.log(` npm install`);
|
|
90
|
+
console.log(` npm run dev\n`);
|
|
91
|
+
console.log(`🌐 Dev server will run on: http://localhost:${port}/\n`);
|
|
92
|
+
console.log(`📂 Project structure:\n`);
|
|
93
|
+
console.log(` app.html ← Main HTML file`);
|
|
94
|
+
console.log(` modules/ ← Core system (router, state, API)`);
|
|
95
|
+
console.log(` pages/ ← Your pages (auto-imported)`);
|
|
96
|
+
console.log(` components/ ← Your components (auto-imported)`);
|
|
97
|
+
console.log(` api/ ← Your API routes (auto-imported)`);
|
|
98
|
+
console.log(` scripts/ ← Build tools`);
|
|
99
|
+
if (features.docs) {
|
|
100
|
+
console.log(` docs/ ← Documentation`);
|
|
101
|
+
}
|
|
102
|
+
console.log(`\n✨ Features:\n`);
|
|
103
|
+
console.log(` • State Management - useState() like React`);
|
|
104
|
+
console.log(` • File-based Routing - pages/About.jsx → #/about`);
|
|
105
|
+
console.log(` • API Routes - Next.js-like API system`);
|
|
106
|
+
console.log(` • Auto-Import - No manual script tags!`);
|
|
107
|
+
console.log(` • Live Reload - Instant browser refresh\n`);
|
|
108
|
+
console.log(`💡 Quick tips:\n`);
|
|
109
|
+
console.log(` • Create pages/MyPage.jsx → Auto-imported!`);
|
|
110
|
+
console.log(` • Create api/todos.js → Auto-imported!`);
|
|
111
|
+
console.log(` • Just save and browser refreshes automatically`);
|
|
112
|
+
if (features.docs) {
|
|
113
|
+
console.log(` • Read docs/ folder for detailed guides`);
|
|
114
|
+
}
|
|
115
|
+
console.log(`\n🚀 Ready to build something awesome!\n`);
|
|
116
|
+
|
|
117
|
+
rl.close();
|
|
15
118
|
}
|
|
16
119
|
|
|
17
|
-
//
|
|
18
|
-
copyDir(
|
|
19
|
-
|
|
20
|
-
console.log(`✅ Done! Your project is ready.\n`);
|
|
21
|
-
console.log(`🎉 Welcome to Aziz App - A React-like Framework\n`);
|
|
22
|
-
console.log(`📁 Created project: ${projectName}\n`);
|
|
23
|
-
console.log(`👉 Get started:\n`);
|
|
24
|
-
console.log(` cd ${projectName}`);
|
|
25
|
-
console.log(` npm run dev\n`);
|
|
26
|
-
console.log(`🌐 This will:`);
|
|
27
|
-
console.log(` • Start dev server on http://localhost:3000/`);
|
|
28
|
-
console.log(` • Watch for file changes`);
|
|
29
|
-
console.log(` • Auto-import new files`);
|
|
30
|
-
console.log(` • Live reload browser\n`);
|
|
31
|
-
console.log(`� Project structure:\n`);
|
|
32
|
-
console.log(` app.html ← Main HTML file`);
|
|
33
|
-
console.log(` modules/ ← Core system (router, state, API)`);
|
|
34
|
-
console.log(` pages/ ← Your pages (auto-imported)`);
|
|
35
|
-
console.log(` components/ ← Your components (auto-imported)`);
|
|
36
|
-
console.log(` api/ ← Your API routes (auto-imported)`);
|
|
37
|
-
console.log(` scripts/ ← Build tools`);
|
|
38
|
-
console.log(` docs/ ← Documentation\n`);
|
|
39
|
-
console.log(`✨ Features:\n`);
|
|
40
|
-
console.log(` • State Management - useState() like React`);
|
|
41
|
-
console.log(` • File-based Routing - pages/About.jsx → #/about`);
|
|
42
|
-
console.log(` • API Routes - Next.js-like API system`);
|
|
43
|
-
console.log(` • Auto-Import - No manual script tags!`);
|
|
44
|
-
console.log(` • Live Reload - Instant browser refresh\n`);
|
|
45
|
-
console.log(`💡 Quick tips:\n`);
|
|
46
|
-
console.log(` • Create pages/MyPage.jsx → Auto-imported!`);
|
|
47
|
-
console.log(` • Create api/todos.js → Auto-imported!`);
|
|
48
|
-
console.log(` • Just save and browser refreshes automatically`);
|
|
49
|
-
console.log(` • Read docs/ folder for detailed guides\n`);
|
|
50
|
-
console.log(`🚀 Ready to build something awesome!\n`);
|
|
51
|
-
|
|
52
|
-
// ---- Helper ----
|
|
53
|
-
function copyDir(src, dest) {
|
|
120
|
+
// Helper to copy directory with filters
|
|
121
|
+
function copyDir(src, dest, features) {
|
|
54
122
|
fs.mkdirSync(dest, { recursive: true });
|
|
123
|
+
|
|
55
124
|
for (let file of fs.readdirSync(src)) {
|
|
56
|
-
const srcPath
|
|
125
|
+
const srcPath = path.join(src, file);
|
|
57
126
|
const destPath = path.join(dest, file);
|
|
127
|
+
|
|
128
|
+
// Skip certain files based on features
|
|
129
|
+
if (!features.docs && file === 'docs') continue;
|
|
130
|
+
if (!features.examples && file === 'pages' && fs.statSync(srcPath).isDirectory()) {
|
|
131
|
+
// Copy only essential pages
|
|
132
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
133
|
+
fs.copyFileSync(path.join(srcPath, 'Home.jsx'), path.join(destPath, 'Home.jsx'));
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (!features.apiExamples && file === 'api' && fs.statSync(srcPath).isDirectory()) {
|
|
137
|
+
// Skip API examples
|
|
138
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
|
|
58
142
|
if (fs.statSync(srcPath).isDirectory()) {
|
|
59
|
-
copyDir(srcPath, destPath);
|
|
143
|
+
copyDir(srcPath, destPath, features);
|
|
60
144
|
} else {
|
|
61
145
|
fs.copyFileSync(srcPath, destPath);
|
|
62
146
|
}
|
|
63
147
|
}
|
|
64
148
|
}
|
|
149
|
+
|
|
150
|
+
// Update package.json with project name
|
|
151
|
+
function updatePackageJson(targetDir, projectName) {
|
|
152
|
+
const packageJsonPath = path.join(targetDir, 'package.json');
|
|
153
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
154
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
155
|
+
packageJson.name = projectName;
|
|
156
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Update dev server port
|
|
161
|
+
function updateDevServerPort(targetDir, port) {
|
|
162
|
+
const devServerPath = path.join(targetDir, 'scripts', 'dev-server.js');
|
|
163
|
+
if (fs.existsSync(devServerPath)) {
|
|
164
|
+
let content = fs.readFileSync(devServerPath, 'utf8');
|
|
165
|
+
content = content.replace(
|
|
166
|
+
'const PORT = process.env.PORT || 3000;',
|
|
167
|
+
`const PORT = process.env.PORT || ${port};`
|
|
168
|
+
);
|
|
169
|
+
fs.writeFileSync(devServerPath, content);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Run main function
|
|
174
|
+
main().catch(err => {
|
|
175
|
+
console.error('❌ Error:', err);
|
|
176
|
+
rl.close();
|
|
177
|
+
process.exit(1);
|
|
178
|
+
});
|
package/package.json
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-aziz-app",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.3",
|
|
4
|
+
"description": "A React-like framework with state management, routing, and API routes - Create apps with auto-import, live reload, and Next.js-like features",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
6
|
+
"react",
|
|
7
|
+
"framework",
|
|
8
|
+
"cli",
|
|
9
|
+
"create-app",
|
|
10
|
+
"routing",
|
|
11
|
+
"state-management",
|
|
12
|
+
"api-routes",
|
|
13
|
+
"live-reload"
|
|
10
14
|
],
|
|
11
|
-
"license": "
|
|
15
|
+
"license": "MIT",
|
|
12
16
|
"author": "Syed Muhammad Aziz Ahmed",
|
|
13
17
|
"type": "commonjs",
|
|
14
18
|
"files": [
|
|
@@ -18,7 +22,6 @@
|
|
|
18
22
|
"bin": {
|
|
19
23
|
"create-aziz-app": "bin/create-aziz-app.js"
|
|
20
24
|
},
|
|
21
|
-
"main": "app.js",
|
|
22
25
|
"scripts": {
|
|
23
26
|
"dev": "cd template && node scripts/dev-server.js",
|
|
24
27
|
"build": "cd template && node scripts/generate-imports.js",
|
package/template/app.html
CHANGED
|
@@ -146,8 +146,7 @@
|
|
|
146
146
|
<script type="text/babel" src="pages/ApiDemo.jsx"></script>
|
|
147
147
|
<script type="text/babel" src="pages/Contact.jsx"></script>
|
|
148
148
|
<script type="text/babel" src="pages/Home.jsx"></script>
|
|
149
|
-
<script type="text/babel" src="pages/
|
|
150
|
-
<script type="text/babel" src="pages/Test.jsx"></script>
|
|
149
|
+
<script type="text/babel" src="pages/test.jsx"></script>
|
|
151
150
|
|
|
152
151
|
<!-- Start the app -->
|
|
153
152
|
<script type="text/babel">
|
package/app.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/** @jsx h */
|
|
2
|
-
|
|
3
|
-
// ==============================
|
|
4
|
-
// h() — our own createElement
|
|
5
|
-
// Babel compiles JSX like <div class="x"> into h("div", { class: "x" }, ...children)
|
|
6
|
-
// This function turns that into a real DOM element
|
|
7
|
-
// ==============================
|
|
8
|
-
function h(tag, props, ...children) {
|
|
9
|
-
// If tag is a function (a component like Header), call it
|
|
10
|
-
if (typeof tag === "function") {
|
|
11
|
-
return tag(props, ...children);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// Create the real DOM element
|
|
15
|
-
const el = document.createElement(tag);
|
|
16
|
-
|
|
17
|
-
// Apply props (class, onClick, etc.)
|
|
18
|
-
if (props) {
|
|
19
|
-
for (let key in props) {
|
|
20
|
-
if (key.startsWith("on")) {
|
|
21
|
-
// onClick -> click event
|
|
22
|
-
const eventName = key.slice(2).toLowerCase();
|
|
23
|
-
el.addEventListener(eventName, props[key]);
|
|
24
|
-
} else if (key === "className") {
|
|
25
|
-
el.className = props[key];
|
|
26
|
-
} else {
|
|
27
|
-
el.setAttribute(key, props[key]);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Append children (text or elements)
|
|
33
|
-
for (let child of children) {
|
|
34
|
-
if (child === null || child === undefined) continue;
|
|
35
|
-
if (typeof child === "string" || typeof child === "number") {
|
|
36
|
-
el.appendChild(document.createTextNode(child));
|
|
37
|
-
} else {
|
|
38
|
-
el.appendChild(child);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return el;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
// ==============================
|
|
47
|
-
// STATE
|
|
48
|
-
// ==============================
|
|
49
|
-
let state = {
|
|
50
|
-
count: 0
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// ==============================
|
|
55
|
-
// RENDER
|
|
56
|
-
// ==============================
|
|
57
|
-
function render() {
|
|
58
|
-
const root = document.getElementById("root");
|
|
59
|
-
root.innerHTML = "";
|
|
60
|
-
root.appendChild(Header());
|
|
61
|
-
root.appendChild(Counter());
|
|
62
|
-
root.appendChild(Footer());
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// ==============================
|
|
67
|
-
// STATE UPDATER FUNCTIONS
|
|
68
|
-
// ==============================
|
|
69
|
-
function increment() {
|
|
70
|
-
state.count = state.count + 1;
|
|
71
|
-
render();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function decrement() {
|
|
75
|
-
state.count = state.count - 1;
|
|
76
|
-
render();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function reset() {
|
|
80
|
-
state.count = 0;
|
|
81
|
-
render();
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// ==============================
|
|
86
|
-
// FIRST RENDER
|
|
87
|
-
// ==============================
|
|
88
|
-
render();
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/** @jsx h */
|
|
2
|
-
|
|
3
|
-
// Register this page at route "home" → "#/"
|
|
4
|
-
registerPage("NewPage", NewPage);
|
|
5
|
-
|
|
6
|
-
function NewPage() {
|
|
7
|
-
return (
|
|
8
|
-
<div>
|
|
9
|
-
<h1>Welcome Home 👋</h1>
|
|
10
|
-
|
|
11
|
-
<div class="card">
|
|
12
|
-
<h2>Global State Counter</h2>
|
|
13
|
-
<p>This uses the global state. Click the buttons to update it.</p>
|
|
14
|
-
|
|
15
|
-
<div class="count-display">{state.count}</div>
|
|
16
|
-
|
|
17
|
-
<div class="counter-actions">
|
|
18
|
-
<button class="btn btn-danger" onClick={() => setState({ count: state.count - 1 })}>−</button>
|
|
19
|
-
<button class="btn btn-primary" onClick={() => setState({ count: state.count + 1 })}>+</button>
|
|
20
|
-
<button class="btn btn-grey" onClick={() => setState({ count: 0 })}>Reset</button>
|
|
21
|
-
</div>
|
|
22
|
-
</div>
|
|
23
|
-
|
|
24
|
-
<div class="card">
|
|
25
|
-
<h2>File-based Routing</h2>
|
|
26
|
-
<p>
|
|
27
|
-
Each file in <strong>pages/</strong> is a route — just like Next.js.
|
|
28
|
-
Add a new file, register it in app.js, and it's a new page.
|
|
29
|
-
</p>
|
|
30
|
-
<button class="btn btn-primary" onClick={() => navigate("test")}>
|
|
31
|
-
Go to Test Page →
|
|
32
|
-
</button>
|
|
33
|
-
<button class="btn btn-primary" onClick={() => navigate("about")}>
|
|
34
|
-
Go to About →
|
|
35
|
-
</button>
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
File without changes
|