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.
@@ -1,64 +1,178 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const fs = require("fs");
3
+ const fs = require("fs");
4
4
  const path = require("path");
5
+ const readline = require("readline");
5
6
 
6
- const projectName = process.argv[2] || "my-aziz-app";
7
- const targetDir = path.join(process.cwd(), projectName);
8
- const templateDir = path.join(__dirname, "../template");
7
+ // Create readline interface
8
+ const rl = readline.createInterface({
9
+ input: process.stdin,
10
+ output: process.stdout
11
+ });
9
12
 
10
- console.log(`\n⚡ Creating "${projectName}"...\n`);
13
+ // Promisify question
14
+ function question(query) {
15
+ return new Promise(resolve => rl.question(query, resolve));
16
+ }
11
17
 
12
- if (fs.existsSync(targetDir)) {
13
- console.error(`❌ Folder "${projectName}" already exists. Choose a different name.`);
14
- process.exit(1);
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
- // Copy the entire template folder into the new project
18
- copyDir(templateDir, targetDir);
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 = path.join(src, file);
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.2",
4
- "description": "so close to react ~~ just joking",
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
- "html",
7
- "css",
8
- "js",
9
- "react like"
6
+ "react",
7
+ "framework",
8
+ "cli",
9
+ "create-app",
10
+ "routing",
11
+ "state-management",
12
+ "api-routes",
13
+ "live-reload"
10
14
  ],
11
- "license": "Aziz",
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/NewPage.jsx"></script>
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