create-jinmankn-app 1.0.0

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.
Files changed (117) hide show
  1. package/bin/index.js +76 -0
  2. package/package.json +20 -0
  3. package/templates/blueprint/BLUEPRINT_REPRODUCTION_PROMPT.md +996 -0
  4. package/templates/blueprint/HOW_IT_WORKS.md +286 -0
  5. package/templates/blueprint/README.md +123 -0
  6. package/templates/blueprint/backend/config/db.js +12 -0
  7. package/templates/blueprint/backend/controllers/authController.js +90 -0
  8. package/templates/blueprint/backend/controllers/itemController.js +74 -0
  9. package/templates/blueprint/backend/middleware/auth.js +32 -0
  10. package/templates/blueprint/backend/middleware/errorHandler.js +23 -0
  11. package/templates/blueprint/backend/models/Item.js +26 -0
  12. package/templates/blueprint/backend/models/User.js +28 -0
  13. package/templates/blueprint/backend/package-lock.json +2190 -0
  14. package/templates/blueprint/backend/package.json +23 -0
  15. package/templates/blueprint/backend/routes/authRoutes.js +11 -0
  16. package/templates/blueprint/backend/routes/healthRoutes.js +9 -0
  17. package/templates/blueprint/backend/routes/itemRoutes.js +21 -0
  18. package/templates/blueprint/backend/server.js +29 -0
  19. package/templates/blueprint/frontend/.env.example +1 -0
  20. package/templates/blueprint/frontend/index.html +13 -0
  21. package/templates/blueprint/frontend/package-lock.json +2844 -0
  22. package/templates/blueprint/frontend/package.json +23 -0
  23. package/templates/blueprint/frontend/public/favicon.svg +4 -0
  24. package/templates/blueprint/frontend/src/App.jsx +78 -0
  25. package/templates/blueprint/frontend/src/assets/logo.svg +4 -0
  26. package/templates/blueprint/frontend/src/components/DashboardLayout.jsx +103 -0
  27. package/templates/blueprint/frontend/src/components/ProtectedRoute.jsx +18 -0
  28. package/templates/blueprint/frontend/src/index.css +1 -0
  29. package/templates/blueprint/frontend/src/main.jsx +13 -0
  30. package/templates/blueprint/frontend/src/pages/DashboardHome.jsx +74 -0
  31. package/templates/blueprint/frontend/src/pages/Items.jsx +243 -0
  32. package/templates/blueprint/frontend/src/pages/Login.jsx +101 -0
  33. package/templates/blueprint/frontend/src/pages/Profile.jsx +79 -0
  34. package/templates/blueprint/frontend/src/pages/Register.jsx +122 -0
  35. package/templates/blueprint/frontend/src/pages/Report.jsx +124 -0
  36. package/templates/blueprint/frontend/vite.config.js +10 -0
  37. package/templates/blueprint/package.json +13 -0
  38. package/templates/blueprint/scripts/pack-blueprint.ps1 +18 -0
  39. package/templates/chom/Backend/app.js +25 -0
  40. package/templates/chom/Backend/package-lock.json +1551 -0
  41. package/templates/chom/Backend/package.json +23 -0
  42. package/templates/chom/Backend/seedAdmin.js +21 -0
  43. package/templates/chom/Backend/src/controllers/payment.c.js +57 -0
  44. package/templates/chom/Backend/src/controllers/students.c.js +58 -0
  45. package/templates/chom/Backend/src/controllers/users.c.js +62 -0
  46. package/templates/chom/Backend/src/middleware/authentication.js +18 -0
  47. package/templates/chom/Backend/src/models/payment.m.js +13 -0
  48. package/templates/chom/Backend/src/models/students.m.js +10 -0
  49. package/templates/chom/Backend/src/models/users.m.js +11 -0
  50. package/templates/chom/Backend/src/routes/users.r.js +21 -0
  51. package/templates/chom/Frontend/README.md +16 -0
  52. package/templates/chom/Frontend/eslint.config.js +21 -0
  53. package/templates/chom/Frontend/index.html +13 -0
  54. package/templates/chom/Frontend/package-lock.json +3075 -0
  55. package/templates/chom/Frontend/package.json +31 -0
  56. package/templates/chom/Frontend/public/favicon.svg +1 -0
  57. package/templates/chom/Frontend/public/icons.svg +24 -0
  58. package/templates/chom/Frontend/src/App.css +189 -0
  59. package/templates/chom/Frontend/src/App.jsx +28 -0
  60. package/templates/chom/Frontend/src/api/api.jsx +27 -0
  61. package/templates/chom/Frontend/src/assets/hero.png +0 -0
  62. package/templates/chom/Frontend/src/assets/react.svg +1 -0
  63. package/templates/chom/Frontend/src/assets/vite.svg +1 -0
  64. package/templates/chom/Frontend/src/components/Navbar.jsx +21 -0
  65. package/templates/chom/Frontend/src/index.css +8 -0
  66. package/templates/chom/Frontend/src/main.jsx +10 -0
  67. package/templates/chom/Frontend/src/pages/Dashboard.jsx +21 -0
  68. package/templates/chom/Frontend/src/pages/Landing.jsx +39 -0
  69. package/templates/chom/Frontend/src/pages/Login.jsx +49 -0
  70. package/templates/chom/Frontend/src/pages/Overview.jsx +42 -0
  71. package/templates/chom/Frontend/src/pages/Register.jsx +76 -0
  72. package/templates/chom/Frontend/src/pages/Students.jsx +14 -0
  73. package/templates/chom/Frontend/vite.config.js +8 -0
  74. package/templates/chom/package.json +13 -0
  75. package/templates/hospital-faisal/backend/.env.example +9 -0
  76. package/templates/hospital-faisal/backend/config/db.js +96 -0
  77. package/templates/hospital-faisal/backend/controllers/appointmentController.js +164 -0
  78. package/templates/hospital-faisal/backend/controllers/authController.js +106 -0
  79. package/templates/hospital-faisal/backend/controllers/hospitalReportController.js +72 -0
  80. package/templates/hospital-faisal/backend/controllers/medicalReportController.js +105 -0
  81. package/templates/hospital-faisal/backend/controllers/patientController.js +98 -0
  82. package/templates/hospital-faisal/backend/database/schema.sql +47 -0
  83. package/templates/hospital-faisal/backend/middleware/auth.js +30 -0
  84. package/templates/hospital-faisal/backend/middleware/errorHandler.js +23 -0
  85. package/templates/hospital-faisal/backend/middleware/role.js +6 -0
  86. package/templates/hospital-faisal/backend/package-lock.json +2092 -0
  87. package/templates/hospital-faisal/backend/package.json +23 -0
  88. package/templates/hospital-faisal/backend/routes/appointmentRoutes.js +25 -0
  89. package/templates/hospital-faisal/backend/routes/authRoutes.js +12 -0
  90. package/templates/hospital-faisal/backend/routes/healthRoutes.js +9 -0
  91. package/templates/hospital-faisal/backend/routes/hospitalReportRoutes.js +10 -0
  92. package/templates/hospital-faisal/backend/routes/medicalReportRoutes.js +16 -0
  93. package/templates/hospital-faisal/backend/routes/patientRoutes.js +22 -0
  94. package/templates/hospital-faisal/backend/server.js +46 -0
  95. package/templates/hospital-faisal/frontend/.env.example +1 -0
  96. package/templates/hospital-faisal/frontend/index.html +10 -0
  97. package/templates/hospital-faisal/frontend/package-lock.json +2844 -0
  98. package/templates/hospital-faisal/frontend/package.json +23 -0
  99. package/templates/hospital-faisal/frontend/public/favicon.svg +4 -0
  100. package/templates/hospital-faisal/frontend/src/App.jsx +56 -0
  101. package/templates/hospital-faisal/frontend/src/api.js +20 -0
  102. package/templates/hospital-faisal/frontend/src/assets/logo.svg +4 -0
  103. package/templates/hospital-faisal/frontend/src/components/DashboardLayout.jsx +114 -0
  104. package/templates/hospital-faisal/frontend/src/components/ProtectedRoute.jsx +18 -0
  105. package/templates/hospital-faisal/frontend/src/components/RoleRoute.jsx +14 -0
  106. package/templates/hospital-faisal/frontend/src/index.css +1 -0
  107. package/templates/hospital-faisal/frontend/src/main.jsx +13 -0
  108. package/templates/hospital-faisal/frontend/src/pages/Appointments.jsx +305 -0
  109. package/templates/hospital-faisal/frontend/src/pages/DashboardHome.jsx +105 -0
  110. package/templates/hospital-faisal/frontend/src/pages/Login.jsx +98 -0
  111. package/templates/hospital-faisal/frontend/src/pages/MedicalReports.jsx +182 -0
  112. package/templates/hospital-faisal/frontend/src/pages/Patients.jsx +237 -0
  113. package/templates/hospital-faisal/frontend/src/pages/Profile.jsx +78 -0
  114. package/templates/hospital-faisal/frontend/src/pages/Register.jsx +133 -0
  115. package/templates/hospital-faisal/frontend/src/pages/Report.jsx +167 -0
  116. package/templates/hospital-faisal/frontend/vite.config.js +10 -0
  117. package/templates/hospital-faisal/package.json +13 -0
@@ -0,0 +1,286 @@
1
+ # Blueprint — How it works (plain language)
2
+
3
+ Read this when something feels confusing. You do **not** need to understand every line of code.
4
+
5
+ ---
6
+
7
+ ## 1. The whole project in one sentence
8
+
9
+ **Blueprint is two programs that talk to each other:**
10
+
11
+ | Part | Folder | What it does | Address |
12
+ |------|--------|--------------|---------|
13
+ | **Screen (frontend)** | `frontend/` | What you see in the browser — buttons, forms, dashboard | http://localhost:5173 |
14
+ | **Brain (backend)** | `backend/` | Saves users and items in the database, checks passwords | http://localhost:5000 |
15
+
16
+ Both must be running at the same time.
17
+
18
+ ### Images and icons (two folders)
19
+
20
+ | Folder | Path | Use for |
21
+ |--------|------|---------|
22
+ | **public** | `frontend/public/` | Favicon, files you reference as `/filename.png` in `index.html` |
23
+ | **assets** | `frontend/src/assets/` | Logos and images used inside React pages (import them at the top of a `.jsx` file) |
24
+
25
+ Examples in this project:
26
+
27
+ - `public/favicon.svg` — browser tab icon (linked in `index.html`)
28
+ - `src/assets/logo.svg` — sidebar logo (used in `DashboardLayout.jsx`)
29
+
30
+ To change the logo: replace `frontend/src/assets/logo.svg` with your own image (same name), or add `my-logo.png` and update the import in `DashboardLayout.jsx`.
31
+
32
+ ---
33
+
34
+ ## 2. How to start the app (every time)
35
+
36
+ **Step 1 — MongoDB**
37
+ MongoDB must be running on your computer (the database).
38
+
39
+ **Step 2 — Backend (Terminal 1)**
40
+
41
+ ```powershell
42
+ cd backend
43
+ npm run dev
44
+ ```
45
+
46
+ Wait until you see: `Server running on http://localhost:5000`
47
+
48
+ **Step 3 — Frontend (Terminal 2)**
49
+
50
+ ```powershell
51
+ cd frontend
52
+ npm run dev
53
+ ```
54
+
55
+ Open: **http://localhost:5173**
56
+
57
+ If the screen is blank or errors appear, check that **both** terminals are still running.
58
+
59
+ ---
60
+
61
+ ## 3. What happens when someone uses your app
62
+
63
+ ```
64
+ Register or Login
65
+
66
+ Backend checks email/password → sends back a "token" (like a temporary key)
67
+
68
+ Browser saves token in localStorage
69
+
70
+ User goes to /dashboard (sidebar + pages)
71
+
72
+ Each page asks the backend for data (items, profile, report)
73
+
74
+ Backend only returns THAT user's data (using the token)
75
+ ```
76
+
77
+ **localStorage** = a small storage area inside the browser. After login it holds:
78
+
79
+ - `token` — proves you are logged in
80
+ - `user` — your name and email (for display)
81
+
82
+ Log out = those are deleted.
83
+
84
+ ---
85
+
86
+ ## 4. Files you will actually touch
87
+
88
+ ### Safe to edit (words and links)
89
+
90
+ | File | What you change |
91
+ |------|-----------------|
92
+ | `frontend/src/components/DashboardLayout.jsx` | Sidebar link names and URLs (`<Link>` lines) |
93
+ | `frontend/src/pages/*.jsx` | Page titles, labels, text users see |
94
+ | `frontend/src/App.jsx` | Add a new route when you add a new page |
95
+ | `frontend/public/` | Favicon and other static files |
96
+ | `frontend/src/assets/` | Logos and images for pages |
97
+ | `README.md` | Project notes for yourself |
98
+
99
+ ### Edit only if you know why (or with AI help)
100
+
101
+ | File | What it does |
102
+ |------|----------------|
103
+ | `backend/.env` | Database address, secret key |
104
+ | `backend/models/Item.js` | What fields an "item" has in the database |
105
+ | `backend/controllers/itemController.js` | Logic for create/read/update/delete items |
106
+ | `frontend/src/pages/Items.jsx` | Form + list that talks to `/api/items` |
107
+
108
+ ### Usually leave alone
109
+
110
+ | File | Why |
111
+ |------|-----|
112
+ | `node_modules/` | Installed packages — huge, auto-generated |
113
+ | `backend/middleware/auth.js` | Checks the token — works as-is |
114
+ | `frontend/src/components/ProtectedRoute.jsx` | Blocks dashboard if not logged in |
115
+ | `frontend/src/main.jsx` | Starts the React app |
116
+
117
+ ---
118
+
119
+ ## 5. The parts that confuse people most
120
+
121
+ ### A) Page vs Route vs Link (three names, one idea)
122
+
123
+ Think of your app like a **building with rooms**:
124
+
125
+ | Idea | File | Example |
126
+ |------|------|---------|
127
+ | **Page** | `frontend/src/pages/Items.jsx` | The room content (form, list) |
128
+ | **Route** | `frontend/src/App.jsx` | The address: `/dashboard/items` opens Items page |
129
+ | **Link** | `DashboardLayout.jsx` | The menu button that sends you to that address |
130
+
131
+ **Rule:** If you add a menu link, you need **both**:
132
+
133
+ 1. A `<Link to="/dashboard/something">` in `DashboardLayout.jsx`
134
+ 2. A `<Route path="something" element={...} />` in `App.jsx`
135
+ 3. A page file in `frontend/src/pages/`
136
+
137
+ Miss step 2 or 3 → link goes nowhere or shows a blank page.
138
+
139
+ ---
140
+
141
+ ### B) What is `App.jsx`?
142
+
143
+ It is the **map of your website**. It does not show much on screen — it only decides:
144
+
145
+ - `/login` → Login page
146
+ - `/register` → Register page
147
+ - `/dashboard` → Dashboard layout (sidebar) with pages inside it
148
+
149
+ The dashboard "wraps" inner pages using `<Outlet />` inside `DashboardLayout.jsx`.
150
+ **Outlet** = hole where the current page (Items, Report, Profile) appears.
151
+
152
+ ---
153
+
154
+ ### C) What is `ProtectedRoute`?
155
+
156
+ A **bouncer** at the dashboard door.
157
+
158
+ - Has `token` in localStorage? → Let them in.
159
+ - No token? → Send to `/login`.
160
+
161
+ You rarely need to change this file.
162
+
163
+ ---
164
+
165
+ ### D) What is `axios.get` / `axios.post`?
166
+
167
+ The frontend **asking the backend a question** over the internet.
168
+
169
+ Example from Items page:
170
+
171
+ ```text
172
+ axios.get('http://localhost:5000/api/items', { headers: { Authorization: 'Bearer TOKEN' } })
173
+ ```
174
+
175
+ Means: "Hey backend, give me my items. Here is my login token."
176
+
177
+ - **get** = read data
178
+ - **post** = create new data
179
+ - **put** = update
180
+ - **delete** = remove
181
+
182
+ If the URL is wrong or the backend is off → red error on the page.
183
+
184
+ ---
185
+
186
+ ### E) Backend structure (simple)
187
+
188
+ ```
189
+ Request hits server.js
190
+
191
+ Routes (authRoutes, itemRoutes) — which URL?
192
+
193
+ Controller — what to do?
194
+
195
+ Model (User, Item) — read/write MongoDB
196
+
197
+ Response back to frontend
198
+ ```
199
+
200
+ | URL | Purpose |
201
+ |-----|---------|
202
+ | `/api/auth/register` | Create account |
203
+ | `/api/auth/login` | Sign in, get token |
204
+ | `/api/auth/me` | Who am I? |
205
+ | `/api/items` | List / create items |
206
+ | `/api/items/:id` | Update / delete one item |
207
+
208
+ ---
209
+
210
+ ## 6. Sidebar — how you already customize it
211
+
212
+ Open `DashboardLayout.jsx`. You will see:
213
+
214
+ ```jsx
215
+ <Link to="/dashboard/items">Items</Link>
216
+ ```
217
+
218
+ - Change **Items** → any label (e.g. `Products`)
219
+ - Change **to=** only if you also change the route in `App.jsx`
220
+
221
+ ---
222
+
223
+ ## 7. When something goes wrong
224
+
225
+ | Problem | Check |
226
+ |---------|--------|
227
+ | Blank page after login | Is `DashboardLayout` inside `App.jsx`? (not commented out) |
228
+ | Link does nothing | Route missing in `App.jsx`? |
229
+ | "Failed to load" / network error | Backend running? MongoDB running? |
230
+ | Login works but items empty | Normal if you have not created items yet |
231
+ | CORS or connection error | Backend on port 5000, frontend on 5173 |
232
+
233
+ ---
234
+
235
+ ## 8. How to use Cursor / AI without confusion
236
+
237
+ Copy this pattern when you ask for help:
238
+
239
+ > "In my Blueprint project, I want to [goal].
240
+ > Please change only [file names] and explain in simple words what you changed."
241
+
242
+ Examples:
243
+
244
+ - "Rename Items to Tasks in the sidebar and Items page title."
245
+ - "Add a Customers page like Items — tell me which files you touched."
246
+ - "Login works but Report is empty — what should I check?"
247
+
248
+ Ask **one thing at a time** — easier to follow.
249
+
250
+ ---
251
+
252
+ ## 9. Quick picture
253
+
254
+ ```
255
+ ┌─────────────────────────────────────────────────────────┐
256
+ │ BROWSER (frontend) │
257
+ │ Login → token saved → Dashboard (sidebar + pages) │
258
+ │ │ axios calls │
259
+ └───────┼─────────────────────────────────────────────────┘
260
+
261
+ ┌─────────────────────────────────────────────────────────┐
262
+ │ SERVER (backend) port 5000 │
263
+ │ auth + items APIs │
264
+ └───────┼─────────────────────────────────────────────────┘
265
+
266
+ ┌─────────────────────────────────────────────────────────┐
267
+ │ MongoDB (database file on your PC) │
268
+ │ users collection + items collection │
269
+ └─────────────────────────────────────────────────────────┘
270
+ ```
271
+
272
+ ---
273
+
274
+ ## 10. You are doing fine if you can answer these
275
+
276
+ - [ ] I know frontend = what I see, backend = saves data
277
+ - [ ] I know both terminals must run
278
+ - [ ] I know sidebar links live in `DashboardLayout.jsx`
279
+ - [ ] I know new pages need a file + a route in `App.jsx`
280
+ - [ ] I know login saves a `token` so the dashboard works
281
+
282
+ You do **not** need to memorize React or Node. Edit labels and links first; copy `Items.jsx` when you need a new list page.
283
+
284
+ ---
285
+
286
+ *Keep this file in your project folder. When confused, read section 5 for the topic that bothers you, or ask AI: "Explain section X from HOW_IT_WORKS.md for my Blueprint."*
@@ -0,0 +1,123 @@
1
+ # Blueprint
2
+
3
+ A reusable full-stack starter template with authentication, CRUD, and MongoDB. Copy or rename this folder to bootstrap any new project.
4
+
5
+ ## Stack
6
+
7
+ - **Backend:** Node.js, Express, Mongoose, JWT, bcrypt
8
+ - **Frontend:** React (Vite), Tailwind CSS, React Router, axios
9
+
10
+ ## Prerequisites
11
+
12
+ - [Node.js](https://nodejs.org/) (v18+ recommended)
13
+ - [MongoDB](https://www.mongodb.com/try/download/community) running locally (use [MongoDB Compass](https://www.mongodb.com/products/compass) to inspect `blueprint_db`)
14
+
15
+ ## Project structure
16
+
17
+ ```
18
+ blueprint/
19
+ ├── backend/ # API (port 5000)
20
+ ├── frontend/ # React app (port 5173)
21
+ │ ├── public/ # Favicon, static files (e.g. /favicon.svg)
22
+ │ └── src/
23
+ │ └── assets/ # Logos, images used in pages
24
+ └── README.md
25
+ ```
26
+
27
+ ## Setup
28
+
29
+ ### 1. MongoDB
30
+
31
+ Start MongoDB on your machine. The default connection string targets a local instance:
32
+
33
+ ```
34
+ mongodb://127.0.0.1:27017/blueprint_db
35
+ ```
36
+
37
+ ### 2. Backend
38
+
39
+ ```bash
40
+ cd backend
41
+ npm install
42
+ cp .env.example .env
43
+ ```
44
+
45
+ On Windows (PowerShell):
46
+
47
+ ```powershell
48
+ Copy-Item .env.example .env
49
+ ```
50
+
51
+ Edit `.env` and set a strong `JWT_SECRET`. Other defaults work for local development.
52
+
53
+ ```bash
54
+ npm run dev
55
+ ```
56
+
57
+ API base: **http://localhost:5000/api**
58
+
59
+ - Health: `GET /api/health`
60
+ - Auth: `POST /api/auth/register`, `POST /api/auth/login`, `GET /api/auth/me`
61
+ - Items (protected): `GET/POST /api/items`, `GET/PUT/DELETE /api/items/:id`
62
+
63
+ ### 3. Frontend
64
+
65
+ In a second terminal:
66
+
67
+ ```bash
68
+ cd frontend
69
+ npm install
70
+ cp .env.example .env
71
+ ```
72
+
73
+ Windows:
74
+
75
+ ```powershell
76
+ Copy-Item .env.example .env
77
+ ```
78
+
79
+ ```bash
80
+ npm run dev
81
+ ```
82
+
83
+ App URL: **http://localhost:5173**
84
+
85
+ ## Test flow
86
+
87
+ 1. Open **http://localhost:5173/register** and create an account (name, email, password).
88
+ 2. You are redirected to **/items** with a JWT stored in `localStorage`.
89
+ 3. Create, edit, and delete items on the Items page.
90
+ 4. Log out, then sign in again at **/login** — your items remain tied to your user only.
91
+
92
+ ## Renaming for a new project
93
+
94
+ 1. Rename the `blueprint` folder and update `package.json` `name` fields in `backend` and `frontend`.
95
+ 2. Change `MONGO_URI` database name in `backend/.env`.
96
+ 3. Duplicate `Item` model/routes/controllers as a pattern for new resources.
97
+ 4. Add new pages and routes in the frontend following `Items.jsx`.
98
+
99
+ ## Scripts
100
+
101
+ | Location | Command | Description |
102
+ |-----------|----------------|--------------------------|
103
+ | backend | `npm run dev` | API with nodemon |
104
+ | backend | `npm start` | API (production-style) |
105
+ | frontend | `npm run dev` | Vite dev server |
106
+ | frontend | `npm run build`| Production build |
107
+
108
+ ## Environment variables
109
+
110
+ **Backend (`backend/.env`)**
111
+
112
+ | Variable | Example |
113
+ |-------------|--------------------------------------|
114
+ | PORT | 5000 |
115
+ | MONGO_URI | mongodb://127.0.0.1:27017/blueprint_db |
116
+ | JWT_SECRET | (long random string) |
117
+ | CLIENT_URL | http://localhost:5173 |
118
+
119
+ **Frontend (`frontend/.env`)**
120
+
121
+ | Variable | Example |
122
+ |---------------|------------------------------|
123
+ | VITE_API_URL | http://localhost:5000/api |
@@ -0,0 +1,12 @@
1
+ const mongoose = require('mongoose');
2
+
3
+ const connectDB = async () => {
4
+ try {
5
+ await mongoose.connect('mongodb://localhost:27017/blueprint_db');
6
+ console.log('MongoDB connected');
7
+ } catch (error) {
8
+ console.error('MongoDB connection error:', error);
9
+ }
10
+ };
11
+
12
+ module.exports = connectDB;
@@ -0,0 +1,90 @@
1
+ const bcrypt = require('bcrypt');
2
+ const jwt = require('jsonwebtoken');
3
+ const User = require('../models/User');
4
+ const JWT_SECRET = 'change_this_to_a_long_random_secret';
5
+
6
+
7
+
8
+ function createToken(userId) {
9
+ return jwt.sign({ userId },JWT_SECRET, { expiresIn: '7d' });
10
+ }
11
+
12
+ function formatUser(user) {
13
+ return {
14
+ id: user._id,
15
+ name: user.name,
16
+ email: user.email,
17
+ };
18
+ }
19
+
20
+ exports.register = async (req, res) => {
21
+ try {
22
+ const { name, email, password } = req.body;
23
+
24
+ if (!name || !email || !password) {
25
+ return res.status(400).json({ message: 'Name, email, and password are required' });
26
+ }
27
+
28
+ if (password.length < 6) {
29
+ return res.status(400).json({ message: 'Password must be at least 6 characters' });
30
+ }
31
+
32
+ const existing = await User.findOne({ email: email.toLowerCase() });
33
+ if (existing) {
34
+ return res.status(409).json({ message: 'Email already registered' });
35
+ }
36
+
37
+ const hashedPassword = await bcrypt.hash(password, 10);
38
+ const user = await User.create({
39
+ name,
40
+ email: email.toLowerCase(),//to ensure the email is always lowercase
41
+ password: hashedPassword,
42
+ });
43
+
44
+ const token = createToken(user._id);
45
+
46
+ res.status(201).json({
47
+ token,
48
+ user: formatUser(user),
49
+ });
50
+ } catch (err) {
51
+ res.status(500).json({ message: err.message });
52
+ }
53
+ }
54
+
55
+ exports.login = async (req, res) => {
56
+ try {
57
+ const { email, password } = req.body;
58
+
59
+ if (!email || !password) {
60
+ return res.status(400).json({ message: 'Email and password are required' });
61
+ }
62
+
63
+ const user = await User.findOne({ email: email.toLowerCase() });
64
+ if (!user) {
65
+ return res.status(401).json({ message: 'Invalid email or password' });
66
+ }
67
+
68
+ const match = await bcrypt.compare(password, user.password);
69
+ if (!match) {
70
+ return res.status(401).json({ message: 'Invalid email or password' });
71
+ }
72
+
73
+ const token = createToken(user._id);
74
+
75
+ res.json({
76
+ token,
77
+ user: formatUser(user),
78
+ });
79
+ } catch (err) {
80
+ res.status(500).json({ message: err.message });
81
+ }
82
+ }
83
+
84
+ exports.getMe = async (req, res) => {
85
+ try {
86
+ res.json({ user: formatUser(req.user) });
87
+ } catch (err) {
88
+ res.status(500).json({ message: err.message });
89
+ }
90
+ };
@@ -0,0 +1,74 @@
1
+ const Item = require('../models/Item');
2
+
3
+ exports.getItems = async (req, res) => {
4
+ try {
5
+ const items = await Item.find({ user: req.user._id }).sort({ createdAt: -1 });
6
+ res.json({ items });
7
+ } catch (err) {
8
+ res.status(500).json({ message: err.message });
9
+ }
10
+ }
11
+
12
+ exports.getItem = async (req, res) => {
13
+ try {
14
+ const item = await Item.findOne({ _id: req.params.id, user: req.user._id });
15
+ if (!item) {
16
+ return res.status(404).json({ message: 'Item not found' });
17
+ }
18
+ res.json({ item });
19
+ } catch (err) {
20
+ res.status(500).json({ message: err.message });
21
+ }
22
+ }
23
+
24
+ exports.createItem = async (req, res) => {
25
+ try {
26
+ const { title, description } = req.body;
27
+
28
+ if (!title) {
29
+ return res.status(400).json({ message: 'Title is required' });
30
+ }
31
+
32
+ const item = await Item.create({
33
+ title,
34
+ description: description || '',
35
+ user: req.user._id,
36
+ });
37
+
38
+ res.status(201).json({ item });
39
+ } catch (err) {
40
+ res.status(500).json({ message: err.message });
41
+ }
42
+ }
43
+
44
+ exports.updateItem = async (req, res) => {
45
+ try {
46
+ const { title, description } = req.body;
47
+
48
+ const item = await Item.findOne({ _id: req.params.id, user: req.user._id });
49
+ if (!item) {
50
+ return res.status(404).json({ message: 'Item not found' });
51
+ }
52
+
53
+ if (title !== undefined) item.title = title;
54
+ if (description !== undefined) item.description = description;
55
+
56
+ await item.save();
57
+
58
+ res.json({ item });
59
+ } catch (err) {
60
+ res.status(500).json({ message: err.message });
61
+ }
62
+ }
63
+
64
+ exports.deleteItem = async (req, res) => {
65
+ try {
66
+ const item = await Item.findOneAndDelete({ _id: req.params.id, user: req.user._id });
67
+ if (!item) {
68
+ return res.status(404).json({ message: 'Item not found' });
69
+ }
70
+ res.json({ message: 'Item deleted' });
71
+ } catch (err) {
72
+ res.status(500).json({ message: err.message });
73
+ }
74
+ }
@@ -0,0 +1,32 @@
1
+ // this middleware is helping us to protect our routes so that only authenticated users can access the routes
2
+ //it is checking if the user is authenticated by checking the token in the header(the header is the part of the request that contains the token)
3
+ //if the user is not authenticated, it will return a 401 status code and a message that the user is not authorized
4
+ //if the user is authenticated, it will return the user object
5
+ //and the user object is the user that is authenticated
6
+
7
+ const jwt = require('jsonwebtoken');
8
+ const User = require('../models/User');
9
+ const JWT_SECRET = 'change_this_to_a_long_random_secret';
10
+
11
+ exports.protect = async (req, res, next) => {
12
+ try {
13
+ const header = req.headers.authorization;
14
+
15
+ if (!header || !header.startsWith('Bearer ')) {
16
+ return res.status(401).json({ message: 'Not authorized' });
17
+ }
18
+
19
+ const token = header.split(' ')[1];
20
+ const decoded = jwt.verify(token, JWT_SECRET);
21
+ const user = await User.findById(decoded.userId).select('-password');
22
+
23
+ if (!user) {
24
+ return res.status(401).json({ message: 'Not authorized' });
25
+ }
26
+
27
+ req.user = user;
28
+ next();
29
+ } catch (err) {
30
+ return res.status(401).json({ message: 'Not authorized' });
31
+ }
32
+ };
@@ -0,0 +1,23 @@
1
+
2
+
3
+ exports.notFound = (req, res) => {
4
+ res.status(404).json({ message: 'Route not found' });
5
+ }
6
+
7
+ exports.errorHandler = (err, req, res, next) => {
8
+ console.error(err);
9
+
10
+ if (err.name === 'ValidationError') {
11
+ const messages = Object.values(err.errors).map((e) => e.message);
12
+ return res.status(400).json({ message: messages.join(', ') });
13
+ }
14
+
15
+ if (err.name === 'CastError') {
16
+ return res.status(400).json({ message: 'Invalid ID' });
17
+ }
18
+
19
+ const status = err.statusCode || 500;
20
+ const message = err.message || 'Server error';
21
+
22
+ res.status(status).json({ message });
23
+ };
@@ -0,0 +1,26 @@
1
+ const mongoose = require('mongoose');
2
+
3
+ const itemSchema = new mongoose.Schema(
4
+ {
5
+ title: {
6
+ type: String,
7
+ required: true,
8
+ trim: true,
9
+ },
10
+ description: {
11
+ type: String,
12
+ default: '',
13
+ trim: true,
14
+ },
15
+ user: {
16
+ type: mongoose.Schema.Types.ObjectId,
17
+ ref: 'User',
18
+ required: true,
19
+ },
20
+ },
21
+ { timestamps: true }
22
+ );
23
+
24
+ const Item = mongoose.model('Item', itemSchema);
25
+
26
+ module.exports = Item;
@@ -0,0 +1,28 @@
1
+ const mongoose = require('mongoose');
2
+
3
+ const userSchema = new mongoose.Schema(
4
+ {
5
+ name: {
6
+ type: String,
7
+ required: true,
8
+ trim: true,
9
+ },
10
+ email: {
11
+ type: String,
12
+ required: true,
13
+ unique: true,
14
+ lowercase: true,
15
+ trim: true,
16
+ },
17
+ password: {
18
+ type: String,
19
+ required: true,
20
+ minlength: 6,
21
+ },
22
+ },
23
+ { timestamps: true }
24
+ );
25
+
26
+ const User = mongoose.model('User', userSchema);
27
+
28
+ module.exports = User;