cpeak 2.2.1 → 2.2.2
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/lib/index.js +1 -1
- package/lib/utils/index.js +4 -0
- package/lib/utils/parseJSON.js +20 -0
- package/lib/{util.js → utils/serveStatic.js} +1 -20
- package/package.json +1 -1
- package/private.txt +351 -0
- package/test/errors.test.js +0 -40
- package/test/files/audio.m4a +0 -0
- package/test/files/styles.css +0 -9
- package/test/files/test.txt +0 -1
- package/test/files.test.js +0 -35
- package/test/middleware.test.js +0 -68
- package/test/parseJSON.test.js +0 -43
- package/test/router.test.js +0 -85
- package/test/serveStatic.test.js +0 -53
package/lib/index.js
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Parsing JSON
|
|
2
|
+
const parseJSON = (req, res, next) => {
|
|
3
|
+
// This is only good for bodies that their size is less than the highWaterMark value
|
|
4
|
+
if (req.headers["content-type"] === "application/json") {
|
|
5
|
+
let body = "";
|
|
6
|
+
req.on("data", (chunk) => {
|
|
7
|
+
body += chunk.toString("utf-8");
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
req.on("end", () => {
|
|
11
|
+
body = JSON.parse(body);
|
|
12
|
+
req.body = body;
|
|
13
|
+
return next();
|
|
14
|
+
});
|
|
15
|
+
} else {
|
|
16
|
+
next();
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export { parseJSON };
|
|
@@ -74,23 +74,4 @@ const serveStatic = (folderPath, newMimeTypes) => {
|
|
|
74
74
|
};
|
|
75
75
|
};
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
const parseJSON = (req, res, next) => {
|
|
79
|
-
// This is only good for bodies that their size is less than the highWaterMark value
|
|
80
|
-
if (req.headers["content-type"] === "application/json") {
|
|
81
|
-
let body = "";
|
|
82
|
-
req.on("data", (chunk) => {
|
|
83
|
-
body += chunk.toString("utf-8");
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
req.on("end", () => {
|
|
87
|
-
body = JSON.parse(body);
|
|
88
|
-
req.body = body;
|
|
89
|
-
return next();
|
|
90
|
-
});
|
|
91
|
-
} else {
|
|
92
|
-
next();
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
export { serveStatic, parseJSON };
|
|
77
|
+
export { serveStatic };
|
package/package.json
CHANGED
package/private.txt
ADDED
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
NPM publish
|
|
2
|
+
|
|
3
|
+
after making a regular comment:
|
|
4
|
+
1- update package.json version number
|
|
5
|
+
2- git commit -am '2.2.0'
|
|
6
|
+
3- git tag v2.2.0
|
|
7
|
+
4- npm publish
|
|
8
|
+
5- git push
|
|
9
|
+
6- git push --tags
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
https://www.freecodecamp.org/news/how-to-create-and-publish-your-first-npm-package/
|
|
13
|
+
|
|
14
|
+
https://cloudfour.com/thinks/how-to-publish-an-updated-version-of-an-npm-package/
|
|
15
|
+
|
|
16
|
+
git push --tags
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
A minimal and fast Node.js framework aiming to become one of the best. Every step of the development is explained and documented for educational purposes.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
For documentation refer to here: [cododev.ca/cpeak]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
rm -rf nodemodules && npm i
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
README Backup:
|
|
38
|
+
# Cpeak
|
|
39
|
+
|
|
40
|
+
Cpeak is a minimal and fast Node.js framework inspired by Express.js.
|
|
41
|
+
|
|
42
|
+
This project is meant to be improved to be ready for use in complex production applications, and be more performant and minimal than Express.js. This frameworks is for HTTP applications that just deal with with JSON and file-based message bodies.
|
|
43
|
+
|
|
44
|
+
This is an educational project that was started as part of the [Understanding Node.js: Core Concepts](https://www.udemy.com/course/understanding-nodejs-core-concepts/?referralCode=0BC21AC4DD6958AE6A95) course, and if you want to learn how to build a framework like this, and also get to a point to be bale to build things like these yourself, checkout out this course!
|
|
45
|
+
|
|
46
|
+
## Why Cpeak?
|
|
47
|
+
|
|
48
|
+
- **Minimalism**: No unnecessary bloat, with zero dependencies. Just the core essentials you need to build fast and reliable applications.
|
|
49
|
+
- **Performance**: Engineered to be fast, **Cpeak** won't sacrifice speed for excessive customizability.
|
|
50
|
+
- **Educational**: Every new change that is made in the project, will be explained in great detail in this YouTube Playlist (playlist will be added soon). Follow this project, and let's see what it takes to build an industry leading product!
|
|
51
|
+
- **Expess.js Compatible**: You can easily refactor from Cpeak to Express.js and vice versa. Many NPM packages that work with Express.js will also work with Cpeak.
|
|
52
|
+
|
|
53
|
+
## Getting Starter
|
|
54
|
+
|
|
55
|
+
Ready to dive in? Install **Cpeak** via npm:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install cpeak
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
#### Hello World App:
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
import cpeak from "cpeak";
|
|
65
|
+
|
|
66
|
+
const server = new cpeak();
|
|
67
|
+
|
|
68
|
+
server.route("get", "/", (req, res) => {
|
|
69
|
+
res.json({ message: "Hi there!" });
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
server.listen(3000, () => {
|
|
73
|
+
console.log("Server has started on port 3000");
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Documentation
|
|
78
|
+
|
|
79
|
+
#### Including
|
|
80
|
+
|
|
81
|
+
Include the framework like this:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
import cpeak from "cpeak";
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Because of the minimalistic philosophy, you will not add in unnecessary objects to your memory as soon as you include the framework. If at any point you want to use a particular utility function (like pareJSON and serveStatic), include that like the line below, and only at that point in will be moved to your memory:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
import cpeak, { serveStatic, parseJSON } from "cpeak";
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### Initializing
|
|
94
|
+
|
|
95
|
+
Initialize the Cpeak server like this:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
const server = new cpeak();
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Now you can use this server object to start listening, add route logic, add middleware functions, and also handle errors.
|
|
102
|
+
|
|
103
|
+
#### Middleware
|
|
104
|
+
|
|
105
|
+
If you add a middleware function, that function will run before your route logic kicks in. Here you can customize the request object, return an error, or do anything else that you want to do prior to your route logics like authentication.
|
|
106
|
+
|
|
107
|
+
After calling next, the next middleware functions is going to run if there's any, otherwise the route logic is going to run.
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
server.beforeEach((req, res, next) => {
|
|
111
|
+
if (req.headers.authentication) {
|
|
112
|
+
// Your authentication logic...
|
|
113
|
+
req.userId = "<something>";
|
|
114
|
+
req.custom = "This is some string";
|
|
115
|
+
next();
|
|
116
|
+
} else {
|
|
117
|
+
// Return an error and close the request...
|
|
118
|
+
return res.status(401).json({ error: "Unauthorized" });
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
server.beforeEach((req, res, next) => {
|
|
123
|
+
console.log(
|
|
124
|
+
"The custom was added from the previous middleware: ",
|
|
125
|
+
req.custom
|
|
126
|
+
);
|
|
127
|
+
next();
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### Route Handling
|
|
132
|
+
|
|
133
|
+
You can add in new routes like this:
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
server.route("patch", "/the-path-you-want", (req, res) => {
|
|
137
|
+
// your route logic
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The req and res object types are the same with the Node.js HTTP module (http.IncomingMessage and http.ServerResponse). You can read more about them in the [official Node.js documentation](https://nodejs.org/docs/latest/api/http.html).
|
|
142
|
+
|
|
143
|
+
#### URL Variables & Parameters
|
|
144
|
+
|
|
145
|
+
Because in HTTP these are called URL parameters: `/path?key1=value1&key2=value2&foo=900`, here in Cpeak we also call them params short for HTTP URL parameters.
|
|
146
|
+
We can also do custom path management, and we call them vars short for URL variables.
|
|
147
|
+
|
|
148
|
+
Here's how we can read both:
|
|
149
|
+
|
|
150
|
+
```javascript
|
|
151
|
+
// Imaging request URL is example.com/test/my-title/more-text?filter=newest
|
|
152
|
+
server.route("patch", "/test/:title/more-text", (req, res) => {
|
|
153
|
+
const title = req.vars.title;
|
|
154
|
+
const filter = req.params.get("filter");
|
|
155
|
+
|
|
156
|
+
console.log(title); // my-title
|
|
157
|
+
console.log(filter); // newest
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### Sending Files
|
|
162
|
+
|
|
163
|
+
You can send a file as a Node.js Stream anywhere in your route or middleware logic like this:
|
|
164
|
+
|
|
165
|
+
```javascript
|
|
166
|
+
server.route("get", "/testing", (req, res) => {
|
|
167
|
+
return res.status(200).sendFile("<file-path>", "<mime-type>");
|
|
168
|
+
|
|
169
|
+
// Example:
|
|
170
|
+
// return res.status(200).sendFile("./images/sun.jpeg", "image/jpeg");
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The file binary content will be in the HTTP response body content. Make sure you specify a correct path relative to your CWD (use the path module for better compatibility) and also the correct HTTP mime type for that file.
|
|
175
|
+
|
|
176
|
+
#### Error Handling
|
|
177
|
+
|
|
178
|
+
If anywhere in you route functions, you want to return an error, it's better to pass to the handleErr function like this:
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
server.route("get", "/api/document/:title", (req, res, handleErr) => {
|
|
182
|
+
const title = req.vars.title;
|
|
183
|
+
|
|
184
|
+
// Handling errors
|
|
185
|
+
if (title.length > 500)
|
|
186
|
+
return handleErr({ status: 400, message: "Title too long." });
|
|
187
|
+
|
|
188
|
+
// The rest of your logic...
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
And then handle all the errors like here in the handleErr callback:
|
|
193
|
+
|
|
194
|
+
```javascript
|
|
195
|
+
server.handleErr((error, req, res) => {
|
|
196
|
+
if (error && error.status) {
|
|
197
|
+
res.status(error.status).json({ error: error.message });
|
|
198
|
+
} else {
|
|
199
|
+
// Log the unexpected errors somewhere so you can keep track of them...
|
|
200
|
+
console.error(error);
|
|
201
|
+
res.status(500).json({
|
|
202
|
+
error: "Sorry, something unexpected happened from our side.",
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The error object is the object that you passed to the handleErr function before in your routes.
|
|
209
|
+
|
|
210
|
+
#### Listening
|
|
211
|
+
|
|
212
|
+
Start listening on a specific port like this:
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
server.listen(3000, () => {
|
|
216
|
+
console.log("Server has started on port 3000");
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Util Functions
|
|
221
|
+
|
|
222
|
+
There are utility functions that you can include and use as middleware functions. These are meant to make it easier for you to make HTTP applications. In the future, many more will be added, and you only move them to your memory once you include them. No need to have many NPM dependencies for simple applications!
|
|
223
|
+
|
|
224
|
+
The list of utility functions as of now:
|
|
225
|
+
|
|
226
|
+
- serveStatic
|
|
227
|
+
- parseJSON
|
|
228
|
+
|
|
229
|
+
Including any one of them is like this:
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
import cpeak, { utilName } from "cpeak";
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
#### serveStatic
|
|
236
|
+
|
|
237
|
+
With this middleware function, you can automatically set a folder in your project to be served by Cpeak. Here's how to set it up:
|
|
238
|
+
|
|
239
|
+
```javascript
|
|
240
|
+
server.beforeEach(
|
|
241
|
+
serveStatic("./public", {
|
|
242
|
+
mp3: "audio/mpeg",
|
|
243
|
+
})
|
|
244
|
+
);
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
If you have file types in your public folder that are not one of the followings, make sure to add the MIME types manually as the second argument in the function as an object where each property key is the file extension, and each value is the correct MIME type for that. You can see all the available MIME types from [iana website](https://www.iana.org/assignments/media-types/media-types.xhtml) .
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
html: "text/html",
|
|
251
|
+
css: "text/css",
|
|
252
|
+
js: "application/javascript",
|
|
253
|
+
jpg: "image/jpeg",
|
|
254
|
+
jpeg: "image/jpeg",
|
|
255
|
+
png: "image/png",
|
|
256
|
+
svg: "image/svg+xml",
|
|
257
|
+
txt: "text/plain",
|
|
258
|
+
eot: "application/vnd.ms-fontobject",
|
|
259
|
+
otf: "font/otf",
|
|
260
|
+
ttf: "font/ttf",
|
|
261
|
+
woff: "font/woff",
|
|
262
|
+
woff2: "font/woff2"
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### parseJSON
|
|
266
|
+
|
|
267
|
+
With this middleware function, you can easily read and send JSON in HTTP message bodies in route and middleware functions. Fire it up like this:
|
|
268
|
+
|
|
269
|
+
```javascript
|
|
270
|
+
server.beforeEach(parseJSON);
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Read and send JSON from HTTP messages like this:
|
|
274
|
+
|
|
275
|
+
```javascript
|
|
276
|
+
server.route("put", "/api/user", (req, res) => {
|
|
277
|
+
// Reading JSON from the HTTP request:
|
|
278
|
+
const email = req.body.email;
|
|
279
|
+
|
|
280
|
+
// rest of your logic...
|
|
281
|
+
|
|
282
|
+
// Sending JSON in the HTTP response:
|
|
283
|
+
res.status(201).json({ message: "Something was created..." });
|
|
284
|
+
});
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Complete Example
|
|
288
|
+
|
|
289
|
+
Here you can see all the features the Cpeak offers, in one small piece of code:
|
|
290
|
+
|
|
291
|
+
```javascript
|
|
292
|
+
import cpeak, { serveStatic, parseJSON } from "cpeak";
|
|
293
|
+
|
|
294
|
+
const server = new cpeak();
|
|
295
|
+
|
|
296
|
+
server.beforeEach(
|
|
297
|
+
serveStatic("./public", {
|
|
298
|
+
mp3: "audio/mpeg",
|
|
299
|
+
})
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
// For parsing JSON body
|
|
303
|
+
server.beforeEach(parseJSON);
|
|
304
|
+
|
|
305
|
+
// Adding custom middleware functions
|
|
306
|
+
server.beforeEach((req, res, next) => {
|
|
307
|
+
req.custom = "This is some string";
|
|
308
|
+
next();
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// Adding route handlers
|
|
312
|
+
server.route("get", "/api/document/:title", (req, res, handleErr) => {
|
|
313
|
+
// Reading URL variables
|
|
314
|
+
const title = req.vars.title;
|
|
315
|
+
|
|
316
|
+
// Reading URL parameters (like /users?filter=active)
|
|
317
|
+
const filter = req.params.get("filter");
|
|
318
|
+
|
|
319
|
+
// Reading JSON request body
|
|
320
|
+
const anything = req.body.anything;
|
|
321
|
+
|
|
322
|
+
// Handling errors
|
|
323
|
+
if (anything === "not-expected-thing")
|
|
324
|
+
return handleErr({ status: 401, message: "Invalid property." });
|
|
325
|
+
|
|
326
|
+
// Sending a JSON response
|
|
327
|
+
res.status(200).json({ message: "This is a test response" });
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
// Sending a file response
|
|
331
|
+
server.route("get", "/file", (req, res) => {
|
|
332
|
+
// Make sure to specify a correct path and MIME type...
|
|
333
|
+
res.status(200).sendFile("<path-to-file-relative-to-cwd>", "<mime-type>");
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
// Handle all the errors that could happen in the routes
|
|
337
|
+
server.handleErr((error, req, res) => {
|
|
338
|
+
if (error && error.status) {
|
|
339
|
+
res.status(error.status).json({ error: error.message });
|
|
340
|
+
} else {
|
|
341
|
+
console.error(error);
|
|
342
|
+
res.status(500).json({
|
|
343
|
+
error: "Sorry, something unexpected happened from our side.",
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
server.listen(3000, () => {
|
|
349
|
+
console.log("Server has started on port 3000");
|
|
350
|
+
});
|
|
351
|
+
```
|
package/test/errors.test.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert";
|
|
2
|
-
import supertest from "supertest";
|
|
3
|
-
import cpeak from "../lib/index.js";
|
|
4
|
-
|
|
5
|
-
const PORT = 7543;
|
|
6
|
-
const request = supertest(`http://localhost:${PORT}`);
|
|
7
|
-
|
|
8
|
-
describe("Error handling with handleErr", function () {
|
|
9
|
-
let server;
|
|
10
|
-
|
|
11
|
-
before(function (done) {
|
|
12
|
-
server = new cpeak();
|
|
13
|
-
|
|
14
|
-
server.route("patch", "/foo/:bar", (req, res, handleErr) => {
|
|
15
|
-
const bar = req.vars.bar;
|
|
16
|
-
|
|
17
|
-
if (bar === "random") {
|
|
18
|
-
return handleErr({ status: 403, message: "an error msg" });
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return res.status(200).json({ bar });
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
server.handleErr((error, req, res) => {
|
|
25
|
-
return res.status(error.status).json({ error: error.message });
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
server.listen(PORT, done);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
after(function (done) {
|
|
32
|
-
server.close(done);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("should get an error using the handleErr function from a router", async function () {
|
|
36
|
-
const res = await request.patch("/foo/random");
|
|
37
|
-
assert.strictEqual(res.status, 403);
|
|
38
|
-
assert.deepStrictEqual(res.body, { error: "an error msg" });
|
|
39
|
-
});
|
|
40
|
-
});
|
package/test/files/audio.m4a
DELETED
|
Binary file
|
package/test/files/styles.css
DELETED
package/test/files/test.txt
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
This is a test file.
|
package/test/files.test.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert";
|
|
2
|
-
import supertest from "supertest";
|
|
3
|
-
import fs from "node:fs/promises";
|
|
4
|
-
import cpeak from "../lib/index.js";
|
|
5
|
-
|
|
6
|
-
const PORT = 7543;
|
|
7
|
-
const request = supertest(`http://localhost:${PORT}`);
|
|
8
|
-
|
|
9
|
-
describe("Returning files with sendFile", function () {
|
|
10
|
-
let server;
|
|
11
|
-
|
|
12
|
-
before(function (done) {
|
|
13
|
-
server = new cpeak();
|
|
14
|
-
|
|
15
|
-
server.route("get", "/file", (req, res) => {
|
|
16
|
-
res.status(200).sendFile("./test/files/test.txt", "text/plain");
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
server.listen(PORT, done);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
after(function (done) {
|
|
23
|
-
server.close(done);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("should get a file as the response with the correct MIME type", async function () {
|
|
27
|
-
const res = await request.get("/file");
|
|
28
|
-
|
|
29
|
-
const fileContent = await fs.readFile("./test/files/test.txt", "utf-8");
|
|
30
|
-
|
|
31
|
-
assert.strictEqual(res.status, 200);
|
|
32
|
-
assert.strictEqual(res.headers["content-type"], "text/plain");
|
|
33
|
-
assert.strictEqual(res.text, fileContent);
|
|
34
|
-
});
|
|
35
|
-
});
|
package/test/middleware.test.js
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert";
|
|
2
|
-
import supertest from "supertest";
|
|
3
|
-
import cpeak from "../lib/index.js";
|
|
4
|
-
|
|
5
|
-
const PORT = 7543;
|
|
6
|
-
const request = supertest(`http://localhost:${PORT}`);
|
|
7
|
-
|
|
8
|
-
describe("Middleware functions", function () {
|
|
9
|
-
let server;
|
|
10
|
-
|
|
11
|
-
before(function (done) {
|
|
12
|
-
server = new cpeak();
|
|
13
|
-
|
|
14
|
-
server.beforeEach((req, res, next) => {
|
|
15
|
-
const value = req.params.value;
|
|
16
|
-
|
|
17
|
-
if (value === "random")
|
|
18
|
-
return res.status(400).json({ error: "an error msg" });
|
|
19
|
-
|
|
20
|
-
next();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
server.beforeEach((req, res, next) => {
|
|
24
|
-
req.foo = "text";
|
|
25
|
-
next();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
server.beforeEach((req, res, next) => {
|
|
29
|
-
res.unauthorized = () => {
|
|
30
|
-
res.statusCode = 401;
|
|
31
|
-
return res;
|
|
32
|
-
};
|
|
33
|
-
next();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
server.route("get", "/bar", (req, res) => {
|
|
37
|
-
res.status(200).json({ message: req.foo });
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
server.route("get", "/bar-more", (req, res) => {
|
|
41
|
-
res.unauthorized().json({});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
server.listen(PORT, done);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
after(function (done) {
|
|
48
|
-
server.close(done);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it("should modify the req object with a new property", async function () {
|
|
52
|
-
const res = await request.get("/bar");
|
|
53
|
-
assert.strictEqual(res.status, 200);
|
|
54
|
-
assert.strictEqual(res.body.message, "text");
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("should modify the res object with a new method", async function () {
|
|
58
|
-
const res = await request.get("/bar-more");
|
|
59
|
-
assert.strictEqual(res.status, 401);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("should exit the middleware and route chain if a middleware wants to", async function () {
|
|
63
|
-
const res = await request.get("/bar?value=random");
|
|
64
|
-
assert.strictEqual(res.status, 400);
|
|
65
|
-
assert.strictEqual(res.body.message, undefined);
|
|
66
|
-
assert.deepStrictEqual(res.body, { error: "an error msg" });
|
|
67
|
-
});
|
|
68
|
-
});
|
package/test/parseJSON.test.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert";
|
|
2
|
-
import supertest from "supertest";
|
|
3
|
-
import cpeak, { parseJSON } from "../lib/index.js";
|
|
4
|
-
|
|
5
|
-
const PORT = 7543;
|
|
6
|
-
const request = supertest(`http://localhost:${PORT}`);
|
|
7
|
-
|
|
8
|
-
describe("Parsing request bodies with parseJSON", function () {
|
|
9
|
-
let server;
|
|
10
|
-
|
|
11
|
-
before(function (done) {
|
|
12
|
-
server = new cpeak();
|
|
13
|
-
|
|
14
|
-
server.beforeEach(parseJSON);
|
|
15
|
-
|
|
16
|
-
server.route("post", "/do-something", (req, res) => {
|
|
17
|
-
res.status(205).json({ receivedData: req.body });
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
server.listen(PORT, done);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
after(function (done) {
|
|
24
|
-
server.close(done);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("should return the same data that was sent in request body as JSON", async function () {
|
|
28
|
-
const obj = {
|
|
29
|
-
key1: "value1",
|
|
30
|
-
key2: 42,
|
|
31
|
-
key3: {
|
|
32
|
-
nestedKey1: "nestedValue1",
|
|
33
|
-
nestedKey2: ["arrayValue1", "arrayValue2", 1000],
|
|
34
|
-
},
|
|
35
|
-
key4: true,
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const res = await request.post("/do-something").send(obj);
|
|
39
|
-
|
|
40
|
-
assert.strictEqual(res.status, 205);
|
|
41
|
-
assert.deepStrictEqual(res.body.receivedData, obj);
|
|
42
|
-
});
|
|
43
|
-
});
|
package/test/router.test.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert";
|
|
2
|
-
import supertest from "supertest";
|
|
3
|
-
import cpeak from "../lib/index.js";
|
|
4
|
-
|
|
5
|
-
const PORT = 7543;
|
|
6
|
-
const request = supertest(`http://localhost:${PORT}`);
|
|
7
|
-
|
|
8
|
-
describe("General route logic & URL variables and parameters", function () {
|
|
9
|
-
let server;
|
|
10
|
-
|
|
11
|
-
before(function (done) {
|
|
12
|
-
server = new cpeak();
|
|
13
|
-
|
|
14
|
-
server.route("get", "/hello", (req, res) => {
|
|
15
|
-
res.status(200).json({ message: "Hello, World!" });
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
server.route("get", "/document/:title/more/:another/final", (req, res) => {
|
|
19
|
-
const title = req.vars.title;
|
|
20
|
-
const another = req.vars.another;
|
|
21
|
-
const params = req.params;
|
|
22
|
-
|
|
23
|
-
res.status(200).json({ title, another, params });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
server.listen(PORT, done);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
after(function (done) {
|
|
30
|
-
server.close(done);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it("should return a simple response with no variables and parameters", async function () {
|
|
34
|
-
const res = await request.get("/hello");
|
|
35
|
-
assert.strictEqual(res.status, 200);
|
|
36
|
-
assert.deepStrictEqual(res.body, { message: "Hello, World!" });
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("should return a 404 for unknown routes", async function () {
|
|
40
|
-
const res = await request.get("/unknown");
|
|
41
|
-
assert.strictEqual(res.status, 404);
|
|
42
|
-
assert.deepStrictEqual(res.body, {
|
|
43
|
-
error: "Cannot GET /unknown",
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("should return a 404 for not handled methods", async function () {
|
|
48
|
-
const res = await request.patch("/random");
|
|
49
|
-
assert.strictEqual(res.status, 404);
|
|
50
|
-
assert.deepStrictEqual(res.body, {
|
|
51
|
-
error: "Cannot PATCH /random",
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("should return the correct URL variables and parameters", async function () {
|
|
56
|
-
const expectedResponseBody = {
|
|
57
|
-
title: "some-title",
|
|
58
|
-
another: "thisISsome__more-text",
|
|
59
|
-
params: {
|
|
60
|
-
filter: "comments-date",
|
|
61
|
-
page: "2",
|
|
62
|
-
sortBy: "date-desc",
|
|
63
|
-
tags: JSON.stringify(["nodejs", "express", "url-params"]),
|
|
64
|
-
author: JSON.stringify({ name: "John Doe", id: 123 }),
|
|
65
|
-
isPublished: "true",
|
|
66
|
-
metadata: JSON.stringify({ version: "1.0.0", language: "en" }),
|
|
67
|
-
},
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const res = await request
|
|
71
|
-
.get("/document/some-title/more/thisISsome__more-text/final")
|
|
72
|
-
.query({
|
|
73
|
-
filter: "comments-date",
|
|
74
|
-
page: 2,
|
|
75
|
-
sortBy: "date-desc",
|
|
76
|
-
tags: JSON.stringify(["nodejs", "express", "url-params"]),
|
|
77
|
-
author: JSON.stringify({ name: "John Doe", id: 123 }),
|
|
78
|
-
isPublished: true,
|
|
79
|
-
metadata: JSON.stringify({ version: "1.0.0", language: "en" }),
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
assert.strictEqual(res.status, 200);
|
|
83
|
-
assert.deepStrictEqual(res.body, expectedResponseBody);
|
|
84
|
-
});
|
|
85
|
-
});
|
package/test/serveStatic.test.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert";
|
|
2
|
-
import supertest from "supertest";
|
|
3
|
-
import fs from "node:fs/promises";
|
|
4
|
-
import cpeak, { serveStatic } from "../lib/index.js";
|
|
5
|
-
|
|
6
|
-
const PORT = 7543;
|
|
7
|
-
const request = supertest(`http://localhost:${PORT}`);
|
|
8
|
-
|
|
9
|
-
describe("Serving static files with serveStatic", function () {
|
|
10
|
-
let server;
|
|
11
|
-
|
|
12
|
-
before(function (done) {
|
|
13
|
-
server = new cpeak();
|
|
14
|
-
|
|
15
|
-
server.beforeEach(serveStatic("./test/files", { m4a: "audio/mp4" }));
|
|
16
|
-
|
|
17
|
-
server.listen(PORT, done);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
after(function (done) {
|
|
21
|
-
server.close(done);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it("should return the correct file with the correct MIME type", async function () {
|
|
25
|
-
const textRes = await request.get("/test.txt");
|
|
26
|
-
const cssRes = await request.get("/styles.css");
|
|
27
|
-
|
|
28
|
-
const fileTextContent = await fs.readFile("./test/files/test.txt", "utf-8");
|
|
29
|
-
const fileCssContent = await fs.readFile(
|
|
30
|
-
"./test/files/styles.css",
|
|
31
|
-
"utf-8"
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
assert.strictEqual(textRes.status, 200);
|
|
35
|
-
assert.strictEqual(textRes.headers["content-type"], "text/plain");
|
|
36
|
-
assert.strictEqual(textRes.text, fileTextContent);
|
|
37
|
-
|
|
38
|
-
assert.strictEqual(cssRes.status, 200);
|
|
39
|
-
assert.strictEqual(cssRes.headers["content-type"], "text/css");
|
|
40
|
-
assert.strictEqual(cssRes.text, fileCssContent);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("should return the correct file with the specified MIME type by the developer", async function () {
|
|
44
|
-
const res = await request.get("/audio.m4a");
|
|
45
|
-
|
|
46
|
-
// read the file as binary
|
|
47
|
-
const fileBuffer = await fs.readFile("./test/files/audio.m4a");
|
|
48
|
-
|
|
49
|
-
assert.strictEqual(res.status, 200);
|
|
50
|
-
assert.strictEqual(res.headers["content-type"], "audio/mp4");
|
|
51
|
-
assert.deepStrictEqual(res.body, fileBuffer);
|
|
52
|
-
});
|
|
53
|
-
});
|