cpeak 2.2.0 → 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/README.md +4 -0
- package/lib/index.js +27 -22
- 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 +7 -3
- package/private.txt +351 -0
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Cpeak
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/cpeak)
|
|
4
|
+
|
|
3
5
|
Cpeak is a minimal and fast Node.js framework inspired by Express.js.
|
|
4
6
|
|
|
5
7
|
This project is designed to be improved until it's ready for use in complex production applications, aiming to be more performant and minimal than Express.js. This framework is intended for HTTP applications that primarily deal with JSON and file-based message bodies.
|
|
@@ -40,6 +42,8 @@ Ready to dive in? Install **Cpeak** via npm:
|
|
|
40
42
|
npm install cpeak
|
|
41
43
|
```
|
|
42
44
|
|
|
45
|
+
Cpeak is a **pure ESM** package, and to use it, your project needs to be an ESM as well. You can learn more about that [here](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).
|
|
46
|
+
|
|
43
47
|
### Hello World App:
|
|
44
48
|
|
|
45
49
|
```javascript
|
package/lib/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import http from "node:http";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
|
|
4
|
-
import { serveStatic, parseJSON } from "./
|
|
4
|
+
import { serveStatic, parseJSON } from "./utils/index.js";
|
|
5
5
|
|
|
6
6
|
class Cpeak {
|
|
7
7
|
constructor() {
|
|
@@ -37,29 +37,32 @@ class Cpeak {
|
|
|
37
37
|
// Get the url without the URL parameters
|
|
38
38
|
const urlWithoutParams = req.url.split("?")[0];
|
|
39
39
|
|
|
40
|
+
// Parse the URL parameters (like /users?key1=value1&key2=value2)
|
|
41
|
+
// We put this here to also parse them for all the middleware functions
|
|
42
|
+
const params = new URLSearchParams(req.url.split("?")[1]);
|
|
43
|
+
req.params = Object.fromEntries(params.entries());
|
|
44
|
+
|
|
40
45
|
// Run all the middleware functions before we run the corresponding route
|
|
41
46
|
const runMiddleware = (req, res, middleware, index) => {
|
|
42
47
|
// Out exit point...
|
|
43
48
|
if (index === middleware.length) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
});
|
|
49
|
+
const routes = this.routes[req.method.toLowerCase()];
|
|
50
|
+
if (routes && typeof routes[Symbol.iterator] === "function")
|
|
51
|
+
for (const route of routes) {
|
|
52
|
+
const match = urlWithoutParams.match(route.regex);
|
|
53
|
+
|
|
54
|
+
if (match) {
|
|
55
|
+
// Parse the URL variables from the matched route (like /users/:id)
|
|
56
|
+
const vars = this.#extractVars(route.path, match);
|
|
57
|
+
req.vars = vars;
|
|
58
|
+
|
|
59
|
+
// Call the route handler with the modified req and res objects
|
|
60
|
+
return route.cb(req, res, (error) => {
|
|
61
|
+
res.setHeader("Connection", "close");
|
|
62
|
+
this.handleErr(error, req, res);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
61
65
|
}
|
|
62
|
-
}
|
|
63
66
|
|
|
64
67
|
// If the requested route dose not exist, return 404
|
|
65
68
|
return res
|
|
@@ -92,9 +95,11 @@ class Cpeak {
|
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
listen(port, cb) {
|
|
95
|
-
this.server.listen(port,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
+
this.server.listen(port, cb);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
close(cb) {
|
|
102
|
+
this.server.close(cb);
|
|
98
103
|
}
|
|
99
104
|
|
|
100
105
|
// ------------------------------
|
|
@@ -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
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cpeak",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "A minimal and fast Node.js HTTP framework.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "
|
|
8
|
+
"test": "mocha test/**/*.js"
|
|
9
9
|
},
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
|
@@ -22,5 +22,9 @@
|
|
|
22
22
|
"nodejs",
|
|
23
23
|
"http",
|
|
24
24
|
"framework"
|
|
25
|
-
]
|
|
25
|
+
],
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"mocha": "^10.7.3",
|
|
28
|
+
"supertest": "^7.0.0"
|
|
29
|
+
}
|
|
26
30
|
}
|
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
|
+
```
|