dj-express 1.0.1
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/.gitattributes +2 -0
- package/README.md +136 -0
- package/example.js +98 -0
- package/index.js +242 -0
- package/package.json +18 -0
package/.gitattributes
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Mini Express
|
|
2
|
+
|
|
3
|
+
A minimal Express.js implementation for beginners to understand how Express works internally.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
node example.js
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## How Express Works (Internally)
|
|
12
|
+
|
|
13
|
+
### 1. Routes are just an Array
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
const routes = [];
|
|
17
|
+
|
|
18
|
+
app.get = (path, handler) => {
|
|
19
|
+
routes.push({ method: "GET", path, handler });
|
|
20
|
+
};
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
When you call `app.get("/users", handler)`, it simply adds to an array!
|
|
24
|
+
|
|
25
|
+
### 2. Middlewares are also an Array
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
const middlewares = [];
|
|
29
|
+
|
|
30
|
+
app.use = (middleware) => {
|
|
31
|
+
middlewares.push(middleware);
|
|
32
|
+
};
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 3. The `next()` Function (Magic!)
|
|
36
|
+
|
|
37
|
+
```javascript
|
|
38
|
+
let i = 0;
|
|
39
|
+
|
|
40
|
+
function next() {
|
|
41
|
+
const middleware = middlewares[i++];
|
|
42
|
+
if (middleware) {
|
|
43
|
+
middleware(req, res, next);
|
|
44
|
+
} else {
|
|
45
|
+
handleRoute();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`next()` simply calls the next function in the array!
|
|
51
|
+
|
|
52
|
+
### 4. `res.send()` is just a wrapper
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
res.send = (data) => {
|
|
56
|
+
if (typeof data === "object") {
|
|
57
|
+
res.setHeader("Content-Type", "application/json");
|
|
58
|
+
res.end(JSON.stringify(data));
|
|
59
|
+
} else {
|
|
60
|
+
res.end(data);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 5. Body Parsing (Reading POST data)
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
req.on("data", (chunk) => (body += chunk));
|
|
69
|
+
req.on("end", () => {
|
|
70
|
+
req.body = JSON.parse(body);
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Node.js sends data in chunks, we collect them and parse.
|
|
75
|
+
|
|
76
|
+
## Usage
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
const { createApp } = require("./index");
|
|
80
|
+
|
|
81
|
+
const app = createApp();
|
|
82
|
+
|
|
83
|
+
// Middleware
|
|
84
|
+
app.use((req, res, next) => {
|
|
85
|
+
console.log(req.method, req.url);
|
|
86
|
+
next();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Routes
|
|
90
|
+
app.get("/", (req, res) => {
|
|
91
|
+
res.json({ message: "Hello!" });
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
app.get("/users/:id", (req, res) => {
|
|
95
|
+
res.json({ userId: req.params.id });
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
app.post("/data", (req, res) => {
|
|
99
|
+
res.json(req.body);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
app.listen(3000);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Test Commands
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# GET request
|
|
109
|
+
curl http://localhost:3000/
|
|
110
|
+
|
|
111
|
+
# Route params
|
|
112
|
+
curl http://localhost:3000/users/123
|
|
113
|
+
|
|
114
|
+
# Query params
|
|
115
|
+
curl "http://localhost:3000/search?q=express"
|
|
116
|
+
|
|
117
|
+
# POST with body
|
|
118
|
+
curl -X POST -H "Content-Type: application/json" -d '{"name":"John"}' http://localhost:3000/data
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Features
|
|
122
|
+
|
|
123
|
+
| Feature | How it works |
|
|
124
|
+
| -------------- | ------------------------------------------------ |
|
|
125
|
+
| Routing | Routes stored in array, matched by path & method |
|
|
126
|
+
| Middleware | Array of functions, `next()` calls the next one |
|
|
127
|
+
| `req.params` | Extracted from `/users/:id` pattern |
|
|
128
|
+
| `req.query` | Parsed from `?key=value` |
|
|
129
|
+
| `req.body` | Parsed from POST request body |
|
|
130
|
+
| `res.send()` | Auto-detects JSON vs text |
|
|
131
|
+
| `res.json()` | Sends JSON response |
|
|
132
|
+
| `res.status()` | Sets status code |
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
MIT
|
package/example.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mini Express - Example Usage
|
|
3
|
+
*
|
|
4
|
+
* Run: node example.js
|
|
5
|
+
* Test: curl http://localhost:3000/
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { createApp } = require("./index");
|
|
9
|
+
|
|
10
|
+
const app = createApp();
|
|
11
|
+
|
|
12
|
+
// ============================================
|
|
13
|
+
// MIDDLEWARE EXAMPLES
|
|
14
|
+
// ============================================
|
|
15
|
+
|
|
16
|
+
// Middleware 1: Logger - Har request log karta hai
|
|
17
|
+
app.use((req, res, next) => {
|
|
18
|
+
console.log(`[${new Date().toLocaleTimeString()}] ${req.method} ${req.url}`);
|
|
19
|
+
next(); // IMPORTANT: next() call karna zaroori hai!
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Middleware 2: Custom header add karta hai
|
|
23
|
+
app.use((req, res, next) => {
|
|
24
|
+
res.setHeader("X-Powered-By", "Mini-Express");
|
|
25
|
+
next();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// ============================================
|
|
29
|
+
// ROUTE EXAMPLES
|
|
30
|
+
// ============================================
|
|
31
|
+
|
|
32
|
+
// GET / - Home page
|
|
33
|
+
app.get("/", (req, res) => {
|
|
34
|
+
res.send({ message: "Welcome to Mini Express! 🚀" });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// GET /hello - Simple text response
|
|
38
|
+
app.get("/hello", (req, res) => {
|
|
39
|
+
res.send("<h1>Hello World!</h1>");
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// GET /users/:id - Route params example
|
|
43
|
+
// Try: curl http://localhost:3000/users/123
|
|
44
|
+
app.get("/users/:id", (req, res) => {
|
|
45
|
+
res.json({
|
|
46
|
+
message: "User found!",
|
|
47
|
+
userId: req.params.id,
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// GET /search?q=something - Query params example
|
|
52
|
+
// Try: curl "http://localhost:3000/search?q=express&limit=10"
|
|
53
|
+
app.get("/search", (req, res) => {
|
|
54
|
+
res.json({
|
|
55
|
+
message: "Search results",
|
|
56
|
+
query: req.query,
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// POST /data - Body parsing example
|
|
61
|
+
// Try: curl -X POST -H "Content-Type: application/json" -d '{"name":"John"}' http://localhost:3000/data
|
|
62
|
+
app.post("/data", (req, res) => {
|
|
63
|
+
res.status(201).json({
|
|
64
|
+
message: "Data received!",
|
|
65
|
+
data: req.body,
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// GET /posts/:postId/comments/:commentId - Multiple params
|
|
70
|
+
// Try: curl http://localhost:3000/posts/1/comments/42
|
|
71
|
+
app.get("/posts/:postId/comments/:commentId", (req, res) => {
|
|
72
|
+
res.json({
|
|
73
|
+
postId: req.params.postId,
|
|
74
|
+
commentId: req.params.commentId,
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// ============================================
|
|
79
|
+
// START SERVER
|
|
80
|
+
// ============================================
|
|
81
|
+
|
|
82
|
+
const PORT = 3000;
|
|
83
|
+
|
|
84
|
+
app.listen(PORT, () => {
|
|
85
|
+
console.log(`
|
|
86
|
+
╔═══════════════════════════════════════════════╗
|
|
87
|
+
║ Mini Express Server Running! ║
|
|
88
|
+
║ http://localhost:${PORT} ║
|
|
89
|
+
╠═══════════════════════════════════════════════╣
|
|
90
|
+
║ Try these URLs: ║
|
|
91
|
+
║ • GET / ║
|
|
92
|
+
║ • GET /hello ║
|
|
93
|
+
║ • GET /users/123 ║
|
|
94
|
+
║ • GET /search?q=express ║
|
|
95
|
+
║ • POST /data (with JSON body) ║
|
|
96
|
+
╚═══════════════════════════════════════════════╝
|
|
97
|
+
`);
|
|
98
|
+
});
|
package/index.js
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mini Express - A minimal Express.js implementation
|
|
3
|
+
*
|
|
4
|
+
* This shows how Express works internally.
|
|
5
|
+
* Express is not magic - it's just JavaScript!
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ============================================
|
|
9
|
+
// STEP 1: CREATE APP FUNCTION
|
|
10
|
+
// ============================================
|
|
11
|
+
// Express ka createApp() ek function return karta hai
|
|
12
|
+
// jo http.createServer() ke saath use hota hai
|
|
13
|
+
|
|
14
|
+
function createApp() {
|
|
15
|
+
// ============================================
|
|
16
|
+
// STEP 2: ROUTES STORAGE
|
|
17
|
+
// ============================================
|
|
18
|
+
// Routes ek simple array mein store hote hain
|
|
19
|
+
// Jab app.get() ya app.post() call hota hai, route yahan add hota hai
|
|
20
|
+
|
|
21
|
+
const routes = [];
|
|
22
|
+
|
|
23
|
+
// ============================================
|
|
24
|
+
// STEP 3: MIDDLEWARE STORAGE
|
|
25
|
+
// ============================================
|
|
26
|
+
// Middlewares bhi ek array mein store hote hain
|
|
27
|
+
// Jab app.use() call hota hai, middleware yahan add hota hai
|
|
28
|
+
|
|
29
|
+
const middlewares = [];
|
|
30
|
+
|
|
31
|
+
// ============================================
|
|
32
|
+
// STEP 4: MAIN REQUEST HANDLER
|
|
33
|
+
// ============================================
|
|
34
|
+
// Ye function har HTTP request pe call hota hai
|
|
35
|
+
// http.createServer(app) - yahan 'app' ye function hai
|
|
36
|
+
|
|
37
|
+
const app = (req, res) => {
|
|
38
|
+
// ============================================
|
|
39
|
+
// STEP 5: ENHANCE RESPONSE OBJECT
|
|
40
|
+
// ============================================
|
|
41
|
+
// Express mein res.send(), res.json() kaise kaam karta hai
|
|
42
|
+
|
|
43
|
+
// res.send() - Automatically detect karta hai data type
|
|
44
|
+
res.send = (data) => {
|
|
45
|
+
if (typeof data === "object") {
|
|
46
|
+
res.setHeader("Content-Type", "application/json");
|
|
47
|
+
res.end(JSON.stringify(data));
|
|
48
|
+
} else {
|
|
49
|
+
res.setHeader("Content-Type", "text/html");
|
|
50
|
+
res.end(data);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// res.json() - Directly JSON bhejta hai
|
|
55
|
+
res.json = (data) => {
|
|
56
|
+
res.setHeader("Content-Type", "application/json");
|
|
57
|
+
res.end(JSON.stringify(data));
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// res.status() - Status code set karta hai
|
|
61
|
+
res.status = (code) => {
|
|
62
|
+
res.statusCode = code;
|
|
63
|
+
return res; // Chaining ke liye
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// ============================================
|
|
67
|
+
// STEP 6: BODY PARSING (POST DATA)
|
|
68
|
+
// ============================================
|
|
69
|
+
// Node.js mein body directly nahi milta
|
|
70
|
+
// Hume stream se data read karna padta hai
|
|
71
|
+
|
|
72
|
+
function parseBody(callback) {
|
|
73
|
+
let body = "";
|
|
74
|
+
|
|
75
|
+
// Data chunks aate hain
|
|
76
|
+
req.on("data", (chunk) => {
|
|
77
|
+
body += chunk;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Jab poora data aa jaye
|
|
81
|
+
req.on("end", () => {
|
|
82
|
+
try {
|
|
83
|
+
req.body = JSON.parse(body);
|
|
84
|
+
} catch {
|
|
85
|
+
req.body = {};
|
|
86
|
+
}
|
|
87
|
+
callback();
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ============================================
|
|
92
|
+
// STEP 7: ROUTE MATCHING
|
|
93
|
+
// ============================================
|
|
94
|
+
// URL ke according sahi route dhundhta hai
|
|
95
|
+
|
|
96
|
+
function handleRoute() {
|
|
97
|
+
const { url, method } = req;
|
|
98
|
+
|
|
99
|
+
// Parse URL (query string alag karo)
|
|
100
|
+
const [path, queryString] = url.split("?");
|
|
101
|
+
|
|
102
|
+
// Query params parse karo (?name=John&age=25)
|
|
103
|
+
req.query = {};
|
|
104
|
+
if (queryString) {
|
|
105
|
+
queryString.split("&").forEach((param) => {
|
|
106
|
+
const [key, value] = param.split("=");
|
|
107
|
+
req.query[key] = decodeURIComponent(value || "");
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Route dhundho
|
|
112
|
+
for (const route of routes) {
|
|
113
|
+
const match = matchRoute(route.path, path);
|
|
114
|
+
|
|
115
|
+
if (match && route.method === method) {
|
|
116
|
+
req.params = match.params; // URL params (/users/:id)
|
|
117
|
+
route.handler(req, res);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Koi route match nahi hua
|
|
123
|
+
res.status(404).send("404 Not Found");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ============================================
|
|
127
|
+
// STEP 8: MIDDLEWARE CHAIN (CORE MAGIC!)
|
|
128
|
+
// ============================================
|
|
129
|
+
// Ye Express ka sabse important concept hai
|
|
130
|
+
// next() call karne pe agle middleware pe jaata hai
|
|
131
|
+
|
|
132
|
+
let middlewareIndex = 0;
|
|
133
|
+
|
|
134
|
+
function next() {
|
|
135
|
+
// Current middleware lo
|
|
136
|
+
const middleware = middlewares[middlewareIndex++];
|
|
137
|
+
|
|
138
|
+
if (middleware) {
|
|
139
|
+
// Middleware execute karo, next pass karo
|
|
140
|
+
middleware(req, res, next);
|
|
141
|
+
} else {
|
|
142
|
+
// Koi middleware nahi bacha, route handle karo
|
|
143
|
+
handleRoute();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ============================================
|
|
148
|
+
// STEP 9: START THE CHAIN
|
|
149
|
+
// ============================================
|
|
150
|
+
// Pehle body parse karo (POST ke liye)
|
|
151
|
+
// Phir middleware chain start karo
|
|
152
|
+
|
|
153
|
+
parseBody(() => {
|
|
154
|
+
next();
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// ============================================
|
|
159
|
+
// STEP 10: ROUTE REGISTRATION METHODS
|
|
160
|
+
// ============================================
|
|
161
|
+
// app.get(), app.post() kaise kaam karte hain
|
|
162
|
+
// Ye simply routes array mein push karte hain
|
|
163
|
+
|
|
164
|
+
app.get = (path, handler) => {
|
|
165
|
+
routes.push({ method: "GET", path, handler });
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
app.post = (path, handler) => {
|
|
169
|
+
routes.push({ method: "POST", path, handler });
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
app.put = (path, handler) => {
|
|
173
|
+
routes.push({ method: "PUT", path, handler });
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
app.delete = (path, handler) => {
|
|
177
|
+
routes.push({ method: "DELETE", path, handler });
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// ============================================
|
|
181
|
+
// STEP 11: MIDDLEWARE REGISTRATION
|
|
182
|
+
// ============================================
|
|
183
|
+
// app.use() kaise kaam karta hai
|
|
184
|
+
// Ye simply middlewares array mein push karta hai
|
|
185
|
+
|
|
186
|
+
app.use = (middleware) => {
|
|
187
|
+
middlewares.push(middleware);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// ============================================
|
|
191
|
+
// STEP 12: LISTEN METHOD
|
|
192
|
+
// ============================================
|
|
193
|
+
// app.listen() - Express style server start
|
|
194
|
+
|
|
195
|
+
app.listen = (port, callback) => {
|
|
196
|
+
const http = require("http");
|
|
197
|
+
const server = http.createServer(app);
|
|
198
|
+
server.listen(port, callback);
|
|
199
|
+
return server;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
return app;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ============================================
|
|
206
|
+
// HELPER: ROUTE MATCHING WITH PARAMS
|
|
207
|
+
// ============================================
|
|
208
|
+
// /users/:id ko /users/123 se match karta hai
|
|
209
|
+
// aur { id: "123" } return karta hai
|
|
210
|
+
|
|
211
|
+
function matchRoute(routePath, actualPath) {
|
|
212
|
+
const routeParts = routePath.split("/");
|
|
213
|
+
const actualParts = actualPath.split("/");
|
|
214
|
+
|
|
215
|
+
// Length match nahi ho thi toh false
|
|
216
|
+
if (routeParts.length !== actualParts.length) {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const params = {};
|
|
221
|
+
|
|
222
|
+
for (let i = 0; i < routeParts.length; i++) {
|
|
223
|
+
const routePart = routeParts[i];
|
|
224
|
+
const actualPart = actualParts[i];
|
|
225
|
+
|
|
226
|
+
// :param pattern check karo
|
|
227
|
+
if (routePart.startsWith(":")) {
|
|
228
|
+
const paramName = routePart.slice(1); // ":" hatao
|
|
229
|
+
params[paramName] = actualPart;
|
|
230
|
+
} else if (routePart !== actualPart) {
|
|
231
|
+
// Match nahi hua
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return { params };
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// ============================================
|
|
240
|
+
// EXPORT
|
|
241
|
+
// ============================================
|
|
242
|
+
module.exports = { createApp };
|
package/package.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dj-express",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "A minimal Express.js implementation for beginners - learn how Express works internally",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node example.js"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"express",
|
|
11
|
+
"http",
|
|
12
|
+
"server",
|
|
13
|
+
"educational",
|
|
14
|
+
"learning"
|
|
15
|
+
],
|
|
16
|
+
"author": "",
|
|
17
|
+
"license": "MIT"
|
|
18
|
+
}
|