-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
214 lines (176 loc) · 6.73 KB
/
server.js
File metadata and controls
214 lines (176 loc) · 6.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/**
* Things to do;
*
* git init
* npm init
* create .gitignore file and add node_modules/
* add "express": "^4.16.2" in package.json dependencies
* npm install
*
* NOTE: heroku install node_modules/ according to package.json file, no need to carry them
*
* ---------heroku deploy---------
* heroku create, makes new heroku app and adds a heroku git remote
* heroku rename xxx, rename the app it must be unique
*
* git status
* git add .
* git status
* git commit -am "Init repo"
* [git push, push to github assume that we create repo on github before]
* git push heroku master
* heroku logs
* git log
* git diff , then hit Q to come back command prompt
*
* heroku open, open url in default browser
*
* ---after some changes to deploy heroku---
* git status
* git commit -am "some message"
* git push heroku
*
* ---some tricky parts---
* git remote -v, see all apps
* "start": "node server.js" => to your scripts in package.json. Heroku simply doesn't know what file is the entry point to your app!
* if you want to heroku to use different node, you need to add;
* {
* Other package.json props...
* "engines": {
* "node": "x.x.x"
* }
*}
*
* Pushing to Git first then to Herou is simply a product of habit. You don't need to push to GitHub first (or even use it at all) to push and deploy to Heroku.
*
* ------create repo on github------
*
* go github.com and create "New repository" => name "Todo-api"
* git remote add origin https://github.com/serhatates/Todo-api.git
* git push -u origin master
*
*/
//
const express = require('express'),
app = express(),
bodyParser = require('body-parser'),
PORT = process.env.PORT || 3000; // if PORT env not define on heroku simply gonna set 3000
const _ = require('underscore');
let todos = [],
todoNextId = 1;
// const todos = [{
// id: 1,
// description: 'Meet gf for lunch',
// completed: false
// },
// {
// id: 2,
// description: 'Go to market',
// completed: false
// },
// {
// id: 3,
// description: 'Feed the cat',
// completed: true
// }];
// Notice the new error argument
app.use(function (error, req, res, next) {
// Check if the error is a SyntaxError
if (error instanceof SyntaxError) {
// Send back some custom error code and message
} else {
// No error? Continue on.
next();
}
});
/**
* Body parse let's you access JSON as a JavaScript object when using req.body.
* Without body parser, you'd have to manually parse the body to make it useful.
*
* Body parser will only parse the content if the Content-Type header is properly set.
*/
// app.use which lets us set up some middleware (app level)
app.use(bodyParser.json()); // now anytime req comes in express is going to parse it, and we re gonna be able to access via req.body
app.get('/', (req, res) => {
res.send('Todo API ROOT');
});
// GET /todos?completed=true&q=work
app.get('/todos', (req, res) => {
let queryParams = req.query,
filteredTodos = todos;
if (queryParams.hasOwnProperty('completed') && queryParams.completed === 'true') {
filteredTodos = _.where(todos, { completed: true }); // where method returns all matching items unlike findWhere
}
else if (queryParams.hasOwnProperty('completed') && queryParams.completed === 'false') {
filteredTodos = _.where(todos, { completed: false });
}
if (queryParams.hasOwnProperty('q') && queryParams.q.trim().length > 0) {
filteredTodos = _.filter(filteredTodos, todo => {
return todo.description.toLowerCase().indexOf(queryParams.q.toLowerCase()) > -1
});
}
// we can only pass text back and forth so need to convert json string
res.status(200).json(filteredTodos);
});
// GET /todos/:id => : represent var(id) that's gonna passed in, that's what exactly express uses to parse data coming in
app.get('/todos/:id', (req, res) => {
let todoId = parseInt(req.params.id, 10);
/* we gonna do it with underscore */
// let mathcedTodo = todos.find((todo, i, arr) => {
// return todo.id === todoId; // any req parameters always string!, ***parseInt(string, base);
// });
let mathcedTodo = _.findWhere(todos, { id: todoId });
// undefined is falsie you could use like that, object is truthy => if (undefined) falsie, if(object) truthy
if (typeof mathcedTodo === 'undefined')
return res.status(404).send();
res.status(200).json(mathcedTodo);
});
// POST /todos
// we need to load body-parser module and it's an express middleware
app.post('/todos', (req, res) => {
let body = _.pick(req.body, 'description', 'completed'); // only take these key value pairs
// body validation with underscore lib
if (!_.isBoolean(body.completed) || !_.isString(body.description) || body.description.trim().length === 0)
return res.status(400).send(); // 400 means req can't be completed because of bad data was povided, BAD REQUEST
body.description = body.description.trim();
body = Object.assign({ id: todoNextId++ }, body);
todos.push(body);
res.status(200).json(body);
});
// DELETE /todos:id
app.delete('/todos/:id', (req, res) => {
let todoId = parseInt(req.params.id, 10);
// let mathcedTodo = todos.find((todo, i, arr) => {
// return todo.id === todoId; // any req parameters always string!, ***parseInt(string, base);
// });
// todos = todos.filter((todo, i, arr) => {
// return todo !== mathcedTodo;
// });
let mathcedTodo = _.findWhere(todos, { id: todoId });
if (!mathcedTodo)
return res.status(404).json({ "error": "no todo found with that id" });
todos = _.without(todos, mathcedTodo);
res.status(200).json(mathcedTodo);
});
// PATCH /todos/:id
app.patch('/todos/:id', (req, res) => {
let todoId = parseInt(req.params.id, 10),
mathcedTodo = _.findWhere(todos, { id: todoId });
let body = _.pick(req.body, 'description', 'completed'),
validAttributes = {};
if (!mathcedTodo)
return res.status(404).json({ "error": "no todo found with that id" });
if (body.hasOwnProperty('completed') && _.isBoolean(body.completed))
validAttributes['completed'] = body.completed;
else if (body.hasOwnProperty('completed'))
return res.status(400).send();
if (body.hasOwnProperty('description') && _.isString(body.description) && body.description.trim().length > 0)
validAttributes['description'] = body.description;
else if (body.hasOwnProperty('description'))
return res.status(400).send();
_.extend(mathcedTodo, validAttributes); // manipulate the original object, no need to return it
res.status(200).json(mathcedTodo)
});
app.listen(PORT, () => {
console.log('Express listening on port: %i', PORT);
});