create-aziz-app 2.0.12 → 2.0.14
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 +3 -2
- package/template/README.md +18 -24
- package/template/api/createUser.js +69 -0
- package/template/api/getUser.js +60 -0
- package/template/api/getUserWithDB.js +65 -0
- package/template/api/hello.js +19 -6
- package/template/api/loginUser.js +61 -0
- package/template/api/users.js +132 -37
- package/template/components/Navbar.jsx +7 -6
- package/template/docs/NEXTJS-APP-ROUTER.md +536 -0
- package/template/docs/NEXTJS-COMPARISON.md +473 -0
- package/template/lib/db.js +67 -0
- package/template/models/User.js +102 -0
- package/template/modules/next-response.js +58 -0
- package/template/modules/state.js +225 -31
- package/template/pages/HooksDemo.jsx +194 -0
- package/template/scripts/dev-server.js +108 -47
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-aziz-app",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.14",
|
|
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": "
|
|
16
|
+
"license": "AZIZ",
|
|
16
17
|
"author": "Syed Muhammad Aziz Ahmed",
|
|
17
18
|
"type": "commonjs",
|
|
18
19
|
"files": [
|
package/template/README.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
# Aziz App -
|
|
1
|
+
# Aziz App - Lightweight Next.js Clone
|
|
2
2
|
|
|
3
|
-
A
|
|
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,33 +101,23 @@ function ProfilePage() {
|
|
|
96
101
|
|
|
97
102
|
## ✨ Features
|
|
98
103
|
|
|
99
|
-
###
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
function HomePage() { } // → #/home
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
console.log('Mounted!');
|
|
111
|
+
}, []);
|
|
118
112
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
123
|
// api/todos.js - Runs on SERVER (Node.js)!
|
|
@@ -152,15 +147,14 @@ The CLI will automatically set up your chosen framework!
|
|
|
152
147
|
|
|
153
148
|
## 📚 Documentation
|
|
154
149
|
|
|
150
|
+
- **[Next.js Comparison](docs/NEXTJS-COMPARISON.md)** - How it compares to Next.js
|
|
155
151
|
- **[Getting Started](docs/GETTING-STARTED.md)** - Complete setup guide
|
|
156
152
|
- **[Auto-Registration](docs/AUTO-REGISTRATION.md)** - How pages auto-register
|
|
157
153
|
- **[API Routes](docs/API-ROUTES.md)** - Server-side API endpoints (like Next.js!)
|
|
158
|
-
- **[API Guide](docs/API-GUIDE.md)** - Legacy API guide
|
|
159
154
|
- **[Auto-Import](docs/AUTO-IMPORT.md)** - Auto-import system details
|
|
160
155
|
- **[Dev Server](docs/DEV-SERVER.md)** - Live reload and development
|
|
161
156
|
- **[How It Works](docs/HOW-IT-WORKS.md)** - System architecture
|
|
162
157
|
- **[Troubleshooting](docs/TROUBLESHOOTING.md)** - Fix common issues
|
|
163
|
-
- **[Quick Start](docs/QUICK-START.md)** - Quick examples
|
|
164
158
|
|
|
165
159
|
## 🛠️ Commands
|
|
166
160
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// API Route: /api/createUser
|
|
2
|
+
// Next.js App Router style
|
|
3
|
+
|
|
4
|
+
const { NextResponse } = require('../modules/next-response');
|
|
5
|
+
|
|
6
|
+
// Mock database
|
|
7
|
+
let users = [
|
|
8
|
+
{ _id: '1', name: 'Aziz Ahmed', email: 'aziz@example.com', role: 'admin', phone: '123-456-7890' }
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
// POST handler
|
|
12
|
+
async function POST(request) {
|
|
13
|
+
try {
|
|
14
|
+
// Parse request body
|
|
15
|
+
const body = await request.json();
|
|
16
|
+
const { name, email, password, role, phone } = body;
|
|
17
|
+
|
|
18
|
+
// Validation
|
|
19
|
+
if (!name || !email || !password) {
|
|
20
|
+
return NextResponse.json(
|
|
21
|
+
{
|
|
22
|
+
error: 'Validation failed',
|
|
23
|
+
message: 'Name, email, and password are required'
|
|
24
|
+
},
|
|
25
|
+
{ status: 400 }
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Check if email already exists
|
|
30
|
+
if (users.find(u => u.email === email)) {
|
|
31
|
+
return NextResponse.json(
|
|
32
|
+
{ error: 'User with this email already exists' },
|
|
33
|
+
{ status: 409 }
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Create new user
|
|
38
|
+
const newUser = {
|
|
39
|
+
_id: String(users.length + 1),
|
|
40
|
+
name,
|
|
41
|
+
email,
|
|
42
|
+
password, // In production, hash this with bcrypt!
|
|
43
|
+
role: role || 'user',
|
|
44
|
+
phone: phone || '',
|
|
45
|
+
createdAt: new Date().toISOString()
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
users.push(newUser);
|
|
49
|
+
|
|
50
|
+
// Return user data (without password)
|
|
51
|
+
const { password: _, ...userData } = newUser;
|
|
52
|
+
|
|
53
|
+
return NextResponse.json(
|
|
54
|
+
{
|
|
55
|
+
message: 'User created successfully',
|
|
56
|
+
user: userData
|
|
57
|
+
},
|
|
58
|
+
{ status: 201 }
|
|
59
|
+
);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error('Create user error:', error);
|
|
62
|
+
return NextResponse.json(
|
|
63
|
+
{ error: 'Failed to create user' },
|
|
64
|
+
{ status: 500 }
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = { POST };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// API Route: /api/getUser
|
|
2
|
+
// Next.js App Router style with NextResponse
|
|
3
|
+
|
|
4
|
+
const { NextResponse } = require('../modules/next-response');
|
|
5
|
+
|
|
6
|
+
// Mock database
|
|
7
|
+
const users = [
|
|
8
|
+
{ _id: '1', name: 'Aziz Ahmed', email: 'aziz@example.com', role: 'admin', phone: '123-456-7890' },
|
|
9
|
+
{ _id: '2', name: 'John Doe', email: 'john@example.com', role: 'user', phone: '098-765-4321' },
|
|
10
|
+
{ _id: '3', name: 'Jane Smith', email: 'jane@example.com', role: 'user', phone: '555-123-4567' }
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
// GET handler - Next.js App Router style
|
|
14
|
+
async function GET(request) {
|
|
15
|
+
try {
|
|
16
|
+
// Parse URL and get search params
|
|
17
|
+
const { searchParams } = new URL(request.url);
|
|
18
|
+
const email = searchParams.get('email');
|
|
19
|
+
const id = searchParams.get('id');
|
|
20
|
+
|
|
21
|
+
// Find by email
|
|
22
|
+
if (email) {
|
|
23
|
+
const user = users.find(u => u.email === email);
|
|
24
|
+
if (!user) {
|
|
25
|
+
return NextResponse.json(
|
|
26
|
+
{ error: 'User not found' },
|
|
27
|
+
{ status: 404 }
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
return NextResponse.json(user);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Find by ID
|
|
34
|
+
if (id) {
|
|
35
|
+
const user = users.find(u => u._id === id);
|
|
36
|
+
if (!user) {
|
|
37
|
+
return NextResponse.json(
|
|
38
|
+
{ error: 'User not found' },
|
|
39
|
+
{ status: 404 }
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
return NextResponse.json(user);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// No params provided
|
|
46
|
+
return NextResponse.json(
|
|
47
|
+
{ error: 'Email or ID required' },
|
|
48
|
+
{ status: 400 }
|
|
49
|
+
);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error('Error fetching user:', error);
|
|
52
|
+
return NextResponse.json(
|
|
53
|
+
{ error: 'Failed to fetch user' },
|
|
54
|
+
{ status: 500 }
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Export the handler
|
|
60
|
+
module.exports = { GET };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// API Route: /api/getUserWithDB
|
|
2
|
+
// Complete Next.js App Router style with DB and Model
|
|
3
|
+
|
|
4
|
+
const { NextResponse } = require('../modules/next-response');
|
|
5
|
+
const connectDB = require('../lib/db');
|
|
6
|
+
const User = require('../models/User');
|
|
7
|
+
|
|
8
|
+
// GET handler - Exactly like Next.js!
|
|
9
|
+
async function GET(request) {
|
|
10
|
+
try {
|
|
11
|
+
// Connect to database
|
|
12
|
+
await connectDB();
|
|
13
|
+
|
|
14
|
+
// Parse URL and get search params
|
|
15
|
+
const { searchParams } = new URL(request.url);
|
|
16
|
+
const email = searchParams.get('email');
|
|
17
|
+
const id = searchParams.get('id');
|
|
18
|
+
|
|
19
|
+
// Find by email
|
|
20
|
+
if (email) {
|
|
21
|
+
const user = await User.findOne({ email });
|
|
22
|
+
|
|
23
|
+
if (!user) {
|
|
24
|
+
return NextResponse.json(
|
|
25
|
+
{ error: 'User not found' },
|
|
26
|
+
{ status: 404 }
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Return user without sensitive fields
|
|
31
|
+
const { password, ...userData } = user;
|
|
32
|
+
return NextResponse.json(userData);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Find by ID
|
|
36
|
+
if (id) {
|
|
37
|
+
const user = await User.findById(id);
|
|
38
|
+
|
|
39
|
+
if (!user) {
|
|
40
|
+
return NextResponse.json(
|
|
41
|
+
{ error: 'User not found' },
|
|
42
|
+
{ status: 404 }
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Return user without sensitive fields
|
|
47
|
+
const { password, ...userData } = user;
|
|
48
|
+
return NextResponse.json(userData);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// No params - return error
|
|
52
|
+
return NextResponse.json(
|
|
53
|
+
{ error: 'Email or ID required' },
|
|
54
|
+
{ status: 400 }
|
|
55
|
+
);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('Error fetching user:', error);
|
|
58
|
+
return NextResponse.json(
|
|
59
|
+
{ error: 'Failed to fetch user' },
|
|
60
|
+
{ status: 500 }
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
module.exports = { GET };
|
package/template/api/hello.js
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
// API Route: /api/hello
|
|
2
|
-
//
|
|
2
|
+
// Simple Next.js-style API route
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
export default async function handler(req, res) {
|
|
5
|
+
const { method, query } = req;
|
|
6
|
+
|
|
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';
|
|
7
16
|
|
|
8
17
|
return res.status(200).json({
|
|
9
18
|
message: `Hello, ${name}!`,
|
|
10
19
|
timestamp: new Date().toISOString(),
|
|
11
|
-
method:
|
|
20
|
+
method: method,
|
|
21
|
+
query: query
|
|
12
22
|
});
|
|
13
|
-
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// CommonJS export for Node.js compatibility
|
|
26
|
+
module.exports = handler;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// API Route: /api/loginUser
|
|
2
|
+
// Next.js App Router style
|
|
3
|
+
|
|
4
|
+
const { NextResponse } = require('../modules/next-response');
|
|
5
|
+
|
|
6
|
+
// Mock database
|
|
7
|
+
const users = [
|
|
8
|
+
{ _id: '1', name: 'Aziz Ahmed', email: 'aziz@example.com', password: 'admin123', role: 'admin' },
|
|
9
|
+
{ _id: '2', name: 'John Doe', email: 'john@example.com', password: 'user123', role: 'user' }
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
// POST handler
|
|
13
|
+
async function POST(request) {
|
|
14
|
+
try {
|
|
15
|
+
// Parse request body
|
|
16
|
+
const body = await request.json();
|
|
17
|
+
const { email, password } = body;
|
|
18
|
+
|
|
19
|
+
// Validation
|
|
20
|
+
if (!email || !password) {
|
|
21
|
+
return NextResponse.json(
|
|
22
|
+
{ error: 'Email and password are required' },
|
|
23
|
+
{ status: 400 }
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Find user
|
|
28
|
+
const user = users.find(u => u.email === email);
|
|
29
|
+
|
|
30
|
+
if (!user) {
|
|
31
|
+
return NextResponse.json(
|
|
32
|
+
{ error: 'Invalid credentials' },
|
|
33
|
+
{ status: 401 }
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Check password (in production, use bcrypt!)
|
|
38
|
+
if (user.password !== password) {
|
|
39
|
+
return NextResponse.json(
|
|
40
|
+
{ error: 'Invalid credentials' },
|
|
41
|
+
{ status: 401 }
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Return user data (without password)
|
|
46
|
+
const { password: _, ...userData } = user;
|
|
47
|
+
|
|
48
|
+
return NextResponse.json({
|
|
49
|
+
...userData,
|
|
50
|
+
message: 'Login successful'
|
|
51
|
+
});
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error('Login error:', error);
|
|
54
|
+
return NextResponse.json(
|
|
55
|
+
{ error: 'Failed to login' },
|
|
56
|
+
{ status: 500 }
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = { POST };
|
package/template/api/users.js
CHANGED
|
@@ -1,60 +1,155 @@
|
|
|
1
1
|
// API Route: /api/users
|
|
2
|
-
//
|
|
2
|
+
// Next.js-style API route handler
|
|
3
3
|
|
|
4
|
-
// Mock database (in
|
|
5
|
-
|
|
6
|
-
{ id: 1, name: 'Aziz Ahmed', email: 'aziz@example.com' },
|
|
7
|
-
{ id: 2, name: 'John Doe', email: 'john@example.com' },
|
|
8
|
-
{ 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() }
|
|
9
9
|
];
|
|
10
10
|
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
// Next.js-style default export
|
|
12
|
+
export default async function handler(req, res) {
|
|
13
|
+
const { method, query, body } = req;
|
|
14
|
+
|
|
15
|
+
switch (method) {
|
|
15
16
|
case 'GET':
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
+
});
|
|
23
26
|
}
|
|
27
|
+
return res.status(200).json(user);
|
|
24
28
|
}
|
|
25
|
-
|
|
29
|
+
|
|
30
|
+
// Return all users
|
|
31
|
+
return res.status(200).json({
|
|
32
|
+
users,
|
|
33
|
+
total: users.length,
|
|
34
|
+
timestamp: new Date().toISOString()
|
|
35
|
+
});
|
|
26
36
|
|
|
27
37
|
case 'POST':
|
|
28
|
-
// Create
|
|
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
|
|
29
69
|
const newUser = {
|
|
30
|
-
id: users.length + 1,
|
|
31
|
-
name
|
|
32
|
-
email
|
|
70
|
+
id: users.length > 0 ? Math.max(...users.map(u => u.id)) + 1 : 1,
|
|
71
|
+
name,
|
|
72
|
+
email,
|
|
73
|
+
createdAt: new Date().toISOString()
|
|
33
74
|
};
|
|
75
|
+
|
|
34
76
|
users.push(newUser);
|
|
35
|
-
|
|
77
|
+
|
|
78
|
+
return res.status(201).json({
|
|
79
|
+
message: 'User created successfully',
|
|
80
|
+
user: newUser
|
|
81
|
+
});
|
|
36
82
|
|
|
37
83
|
case 'PUT':
|
|
38
|
-
// Update
|
|
39
|
-
const userId =
|
|
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
|
+
|
|
40
94
|
const userIndex = users.findIndex(u => u.id === parseInt(userId));
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return res.status(
|
|
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
|
+
});
|
|
44
101
|
}
|
|
45
|
-
|
|
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
|
+
});
|
|
46
115
|
|
|
47
116
|
case 'DELETE':
|
|
48
|
-
// Delete
|
|
49
|
-
const deleteId =
|
|
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
|
+
|
|
50
127
|
const deleteIndex = users.findIndex(u => u.id === parseInt(deleteId));
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return res.status(
|
|
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
|
+
});
|
|
54
134
|
}
|
|
55
|
-
|
|
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
|
+
});
|
|
56
142
|
|
|
57
143
|
default:
|
|
58
|
-
|
|
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
|
+
});
|
|
59
151
|
}
|
|
60
|
-
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// CommonJS export for Node.js compatibility
|
|
155
|
+
module.exports = handler;
|
|
@@ -5,12 +5,13 @@ function Navbar() {
|
|
|
5
5
|
|
|
6
6
|
return (
|
|
7
7
|
<nav>
|
|
8
|
-
<span class="brand" onClick={() => navigate("home")}>⚡
|
|
9
|
-
<a href="#/home"
|
|
10
|
-
<a href="#/about"
|
|
11
|
-
<a href="#/
|
|
12
|
-
<a href="#/
|
|
13
|
-
<a href="#/api-demo"
|
|
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
|
}
|