create-aziz-app 2.0.11 → 2.0.13

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/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "create-aziz-app",
3
- "version": "2.0.11",
3
+ "version": "2.0.13",
4
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
6
  "react",
7
+ "full-stack",
7
8
  "framework",
8
9
  "cli",
9
10
  "create-app",
@@ -12,7 +13,7 @@
12
13
  "api-routes",
13
14
  "live-reload"
14
15
  ],
15
- "license": "MIT",
16
+ "license": "AZIZ",
16
17
  "author": "Syed Muhammad Aziz Ahmed",
17
18
  "type": "commonjs",
18
19
  "files": [
@@ -1,6 +1,11 @@
1
- # Aziz App - React-like Framework
1
+ # Aziz App - Lightweight Next.js Clone
2
2
 
3
- A simple, clean React-like framework with state management, routing, and API routes.
3
+ A **lightweight Next.js clone** with React hooks, API routes, and file-based routing. All the benefits of Next.js, but **6x smaller** with **zero dependencies**!
4
+
5
+ ```
6
+ Next.js: ~400KB + 20 dependencies
7
+ Aziz App: ~50KB + 0 dependencies
8
+ ```
4
9
 
5
10
  ## 📁 Project Structure
6
11
 
@@ -96,39 +101,31 @@ function ProfilePage() {
96
101
 
97
102
  ## ✨ Features
98
103
 
99
- ### Auto-Registration ⚡
100
- ```javascript
101
- // Just name your function with "Page" suffix
102
- function AboutPage() {
103
- return <div><h1>About</h1></div>;
104
- }
105
- // Automatically becomes route "#/about"
106
- ```
107
-
108
- ### State Management
104
+ ### React Hooks (Identical to Next.js!)
109
105
  ```javascript
110
106
  const [count, setCount] = useState(0);
111
107
  const [name, setName] = useState('');
112
- ```
113
108
 
114
- ### Routing
115
- ```javascript
116
- // Auto-registers based on function name
117
- function HomePage() { } // → #/home
109
+ useEffect(() => {
110
+ console.log('Mounted!');
111
+ }, []);
118
112
 
119
- // Or manually register for custom names
120
- registerPage("user-profile", UserProfilePage);
121
-
122
- // Navigate
123
- navigate("about");
113
+ const memoized = useMemo(() => expensive(), [dep]);
114
+ const callback = useCallback(() => action(), [dep]);
115
+ const ref = useRef(null);
116
+ const [state, dispatch] = useReducer(reducer, initial);
124
117
  ```
125
118
 
119
+ **All hooks work exactly like React/Next.js!**
120
+
126
121
  ### API Routes
127
122
  ```javascript
128
- // api/todos.js
129
- registerApiRoute('todos', async (req, res) => {
130
- return res.status(200).json({ todos: [] });
131
- });
123
+ // api/todos.js - Runs on SERVER (Node.js)!
124
+ module.exports = async function handler(req, res) {
125
+ if (req.method === 'GET') {
126
+ return res.status(200).json({ todos: [] });
127
+ }
128
+ };
132
129
 
133
130
  // Use in components
134
131
  const response = await fetchApi('/api/todos');
@@ -150,13 +147,14 @@ The CLI will automatically set up your chosen framework!
150
147
 
151
148
  ## 📚 Documentation
152
149
 
150
+ - **[Next.js Comparison](docs/NEXTJS-COMPARISON.md)** - How it compares to Next.js
153
151
  - **[Getting Started](docs/GETTING-STARTED.md)** - Complete setup guide
154
152
  - **[Auto-Registration](docs/AUTO-REGISTRATION.md)** - How pages auto-register
155
- - **[API Guide](docs/API-GUIDE.md)** - How to create API routes
153
+ - **[API Routes](docs/API-ROUTES.md)** - Server-side API endpoints (like Next.js!)
156
154
  - **[Auto-Import](docs/AUTO-IMPORT.md)** - Auto-import system details
157
155
  - **[Dev Server](docs/DEV-SERVER.md)** - Live reload and development
156
+ - **[How It Works](docs/HOW-IT-WORKS.md)** - System architecture
158
157
  - **[Troubleshooting](docs/TROUBLESHOOTING.md)** - Fix common issues
159
- - **[Quick Start](docs/QUICK-START.md)** - Quick examples
160
158
 
161
159
  ## 🛠️ Commands
162
160
 
@@ -1,14 +1,26 @@
1
- /** @jsx h */
1
+ // API Route: /api/hello
2
+ // Simple Next.js-style API route
2
3
 
3
- // Example API route: /api/hello
4
- // Simple hello world API endpoint
4
+ export default async function handler(req, res) {
5
+ const { method, query } = req;
5
6
 
6
- registerApiRoute('hello', async (req, res) => {
7
- const name = req.query.name || 'World';
7
+ if (method !== 'GET') {
8
+ res.setHeader('Allow', ['GET']);
9
+ return res.status(405).json({
10
+ error: 'Method not allowed',
11
+ message: `Method ${method} is not allowed. Use GET instead.`
12
+ });
13
+ }
14
+
15
+ const name = query.name || 'World';
8
16
 
9
17
  return res.status(200).json({
10
18
  message: `Hello, ${name}!`,
11
19
  timestamp: new Date().toISOString(),
12
- method: req.method
20
+ method: method,
21
+ query: query
13
22
  });
14
- });
23
+ }
24
+
25
+ // CommonJS export for Node.js compatibility
26
+ module.exports = handler;
@@ -1,62 +1,155 @@
1
- /** @jsx h */
1
+ // API Route: /api/users
2
+ // Next.js-style API route handler
2
3
 
3
- // Example API route: /api/users
4
- // This simulates a backend API endpoint
5
-
6
- // Mock database
7
- const users = [
8
- { id: 1, name: 'Aziz Ahmed', email: 'aziz@example.com' },
9
- { id: 2, name: 'John Doe', email: 'john@example.com' },
10
- { id: 3, name: 'Jane Smith', email: 'jane@example.com' }
4
+ // Mock database (in production, use a real database)
5
+ let users = [
6
+ { id: 1, name: 'Aziz Ahmed', email: 'aziz@example.com', createdAt: new Date().toISOString() },
7
+ { id: 2, name: 'John Doe', email: 'john@example.com', createdAt: new Date().toISOString() },
8
+ { id: 3, name: 'Jane Smith', email: 'jane@example.com', createdAt: new Date().toISOString() }
11
9
  ];
12
10
 
13
- // Register the API route
14
- registerApiRoute('users', async (req, res) => {
15
- // Handle different HTTP methods
16
- switch (req.method) {
11
+ // Next.js-style default export
12
+ export default async function handler(req, res) {
13
+ const { method, query, body } = req;
14
+
15
+ switch (method) {
17
16
  case 'GET':
18
- // Get all users or a specific user
19
- if (req.query.id) {
20
- const user = users.find(u => u.id === parseInt(req.query.id));
21
- if (user) {
22
- return res.status(200).json(user);
23
- } else {
24
- return res.status(404).json({ error: 'User not found' });
17
+ // GET /api/users - Get all users
18
+ // GET /api/users?id=1 - Get specific user
19
+ if (query.id) {
20
+ const user = users.find(u => u.id === parseInt(query.id));
21
+ if (!user) {
22
+ return res.status(404).json({
23
+ error: 'User not found',
24
+ message: `No user found with id ${query.id}`
25
+ });
25
26
  }
27
+ return res.status(200).json(user);
26
28
  }
27
- return res.status(200).json(users);
29
+
30
+ // Return all users
31
+ return res.status(200).json({
32
+ users,
33
+ total: users.length,
34
+ timestamp: new Date().toISOString()
35
+ });
28
36
 
29
37
  case 'POST':
30
- // Create a new user
38
+ // POST /api/users - Create new user
39
+ const { name, email } = body;
40
+
41
+ // Validation
42
+ if (!name || !email) {
43
+ return res.status(400).json({
44
+ error: 'Validation error',
45
+ message: 'Name and email are required',
46
+ fields: {
47
+ name: !name ? 'Name is required' : null,
48
+ email: !email ? 'Email is required' : null
49
+ }
50
+ });
51
+ }
52
+
53
+ if (!email.includes('@')) {
54
+ return res.status(400).json({
55
+ error: 'Validation error',
56
+ message: 'Invalid email format'
57
+ });
58
+ }
59
+
60
+ // Check if email already exists
61
+ if (users.find(u => u.email === email)) {
62
+ return res.status(409).json({
63
+ error: 'Conflict',
64
+ message: 'User with this email already exists'
65
+ });
66
+ }
67
+
68
+ // Create new user
31
69
  const newUser = {
32
- id: users.length + 1,
33
- name: req.body.name,
34
- email: req.body.email
70
+ id: users.length > 0 ? Math.max(...users.map(u => u.id)) + 1 : 1,
71
+ name,
72
+ email,
73
+ createdAt: new Date().toISOString()
35
74
  };
75
+
36
76
  users.push(newUser);
37
- return res.status(201).json(newUser);
77
+
78
+ return res.status(201).json({
79
+ message: 'User created successfully',
80
+ user: newUser
81
+ });
38
82
 
39
83
  case 'PUT':
40
- // Update a user
41
- const userId = req.query.id || req.body.id;
84
+ // PUT /api/users?id=1 - Update user
85
+ const userId = query.id || body.id;
86
+
87
+ if (!userId) {
88
+ return res.status(400).json({
89
+ error: 'Bad request',
90
+ message: 'User ID is required'
91
+ });
92
+ }
93
+
42
94
  const userIndex = users.findIndex(u => u.id === parseInt(userId));
43
- if (userIndex !== -1) {
44
- users[userIndex] = { ...users[userIndex], ...req.body };
45
- return res.status(200).json(users[userIndex]);
95
+
96
+ if (userIndex === -1) {
97
+ return res.status(404).json({
98
+ error: 'User not found',
99
+ message: `No user found with id ${userId}`
100
+ });
46
101
  }
47
- return res.status(404).json({ error: 'User not found' });
102
+
103
+ // Update user
104
+ users[userIndex] = {
105
+ ...users[userIndex],
106
+ ...body,
107
+ id: users[userIndex].id, // Prevent ID change
108
+ updatedAt: new Date().toISOString()
109
+ };
110
+
111
+ return res.status(200).json({
112
+ message: 'User updated successfully',
113
+ user: users[userIndex]
114
+ });
48
115
 
49
116
  case 'DELETE':
50
- // Delete a user
51
- const deleteId = req.query.id;
117
+ // DELETE /api/users?id=1 - Delete user
118
+ const deleteId = query.id;
119
+
120
+ if (!deleteId) {
121
+ return res.status(400).json({
122
+ error: 'Bad request',
123
+ message: 'User ID is required'
124
+ });
125
+ }
126
+
52
127
  const deleteIndex = users.findIndex(u => u.id === parseInt(deleteId));
53
- if (deleteIndex !== -1) {
54
- const deleted = users.splice(deleteIndex, 1);
55
- return res.status(200).json({ message: 'User deleted', user: deleted[0] });
128
+
129
+ if (deleteIndex === -1) {
130
+ return res.status(404).json({
131
+ error: 'User not found',
132
+ message: `No user found with id ${deleteId}`
133
+ });
56
134
  }
57
- return res.status(404).json({ error: 'User not found' });
135
+
136
+ const deletedUser = users.splice(deleteIndex, 1)[0];
137
+
138
+ return res.status(200).json({
139
+ message: 'User deleted successfully',
140
+ user: deletedUser
141
+ });
58
142
 
59
143
  default:
60
- return res.status(405).json({ error: 'Method not allowed' });
144
+ // Method not allowed
145
+ res.setHeader('Allow', ['GET', 'POST', 'PUT', 'DELETE']);
146
+ return res.status(405).json({
147
+ error: 'Method not allowed',
148
+ message: `Method ${method} is not allowed for this endpoint`,
149
+ allowedMethods: ['GET', 'POST', 'PUT', 'DELETE']
150
+ });
61
151
  }
62
- });
152
+ }
153
+
154
+ // CommonJS export for Node.js compatibility
155
+ module.exports = handler;
package/template/app.html CHANGED
@@ -28,31 +28,27 @@
28
28
  <!-- Footer is always visible -->
29
29
  <div id="footer"></div>
30
30
 
31
- <!-- Load core modules -->
32
- <script type="text/babel" src="modules/router.js"></script>
33
- <script type="text/babel" src="modules/state.js"></script>
34
- <script type="text/babel" src="modules/api.js"></script>
35
-
36
- <!-- Load API routes -->
37
- <script type="text/babel" src="api/hello.js"></script>
38
- <script type="text/babel" src="api/users.js"></script>
39
-
40
- <!-- Load shared components -->
41
- <script type="text/babel" src="components/Counter.jsx"></script>
42
- <script type="text/babel" src="components/Footer.jsx"></script>
43
- <script type="text/babel" src="components/Navbar.jsx"></script>
44
-
45
- <!-- Load pages -->
46
- <script type="text/babel" src="pages/About.jsx"></script>
47
- <script type="text/babel" src="pages/ApiDemo.jsx"></script>
48
- <script type="text/babel" src="pages/Contact.jsx"></script>
49
- <script type="text/babel" src="pages/Example.jsx"></script>
50
- <script type="text/babel" src="pages/Home.jsx"></script>
51
- <script type="text/babel" src="pages/test.jsx"></script>
52
-
53
- <!-- Start the app -->
54
- <script type="text/babel">
55
- startApp();
31
+ <!-- Load core modules -->
32
+ <script type="text/babel" src="modules/router.js"></script>
33
+ <script type="text/babel" src="modules/state.js"></script>
34
+ <script type="text/babel" src="modules/api.js"></script>
35
+
36
+ <!-- Load shared components -->
37
+ <script type="text/babel" src="components/Counter.jsx"></script>
38
+ <script type="text/babel" src="components/Footer.jsx"></script>
39
+ <script type="text/babel" src="components/Navbar.jsx"></script>
40
+
41
+ <!-- Load pages -->
42
+ <script type="text/babel" src="pages/About.jsx"></script>
43
+ <script type="text/babel" src="pages/ApiDemo.jsx"></script>
44
+ <script type="text/babel" src="pages/Contact.jsx"></script>
45
+ <script type="text/babel" src="pages/Example.jsx"></script>
46
+ <script type="text/babel" src="pages/Home.jsx"></script>
47
+ <script type="text/babel" src="pages/test.jsx"></script>
48
+
49
+ <!-- Start the app -->
50
+ <script type="text/babel">
51
+ startApp();
56
52
  </script>
57
53
 
58
54
  </body>
@@ -5,12 +5,13 @@ function Navbar() {
5
5
 
6
6
  return (
7
7
  <nav>
8
- <span class="brand" onClick={() => navigate("home")}>⚡ AzizJS</span>
9
- <a href="#/home" class={path === "home" ? "active" : ""}>Home</a>
10
- <a href="#/about" class={path === "about" ? "active" : ""}>About</a>
11
- <a href="#/contact" class={path === "contact" ? "active" : ""}>Contact</a>
12
- <a href="#/test" class={path === "test" ? "active" : ""}>Test</a>
13
- <a href="#/api-demo" class={path === "api-demo" ? "active" : ""}>API Demo</a>
8
+ <span class="brand" onClick={() => navigate("home")}>⚡ AzizApp</span>
9
+ <a href="#/home" class={path === "home" ? "active" : ""}>Home</a>
10
+ <a href="#/about" class={path === "about" ? "active" : ""}>About</a>
11
+ <a href="#/test" class={path === "test" ? "active" : ""}>Test</a>
12
+ <a href="#/hooks-demo" class={path === "hooks-demo" ? "active" : ""}>Hooks</a>
13
+ <a href="#/api-demo" class={path === "api-demo" ? "active" : ""}>API Demo</a>
14
+ <a href="#/contact" class={path === "contact" ? "active" : ""}>Contact</a>
14
15
  </nav>
15
16
  );
16
17
  }