Skip to content

Commit 01ee0b1

Browse files
finished transition to knex for the database. Rewrote each controller call to add some consistency to how request data is managed.
1 parent 2cfd6e9 commit 01ee0b1

17 files changed

+731
-585
lines changed

package-lock.json

Lines changed: 197 additions & 65 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "koa-vue-notes-api",
3-
"version": "1.0.3",
3+
"version": "1.0.4",
44
"description": "A SPA using Koa as the backend and Vue as the frontend.",
55
"author": "John Datserakis",
66
"private": false,
@@ -9,7 +9,7 @@
99
"watch": "nodemon --exec npm run start",
1010
"test": "jest --forceExit",
1111
"build": "babel src -d build && npm run pretty",
12-
"pretty": "prettier --write --print-width 80 --single-quote --trailing-comma es5 --tab-width 4 'src/**/*.js' 'models/**/*.js' 'middleware/**/*.js' 'config/**/*.js'",
12+
"pretty": "prettier --write --print-width 80 --single-quote --trailing-comma es5 --tab-width 4 --no-semi 'src/**/*.js' 'models/**/*.js' 'middleware/**/*.js' 'config/**/*.js'",
1313
"start-production": "pm2 start ecosystem.json",
1414
"clean": "npm run clean:dist && npm run clean:tmp"
1515
},
@@ -27,10 +27,10 @@
2727
"joi": "^10.6.0",
2828
"jsonwebtoken": "^7.4.1",
2929
"kcors": "^2.0.0",
30+
"knex": "^0.13.0",
3031
"koa": "^2.0.0-alpha.3",
3132
"koa-bodyparser": "^3.0.0",
3233
"koa-json-error": "^3.1.2",
33-
"koa-jwt": "^3.2.2",
3434
"koa-ratelimit": "^4.0.0",
3535
"koa-router": "^7.0.1",
3636
"koa-useragent": "^1.0.0",

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ We use controllers to keep our router thin. The controller's responsibility is t
8383

8484
### db
8585

86-
Here is our database setup. Basically we create a pool variable and export it to be used throughout our app. Very simple. A note - we are using the `promise-mysql` library instead of the vanilla `node-mysql` library to take advantage of it promise features. This works really well as we're able to fully utilize the new async/await present in the latest versions of Node. It makes the code really nice and lean.
86+
Here is our database setup. This project uses Knex to manage migarations and execute queries. I initially wrote raw SQL queries for the program, but the need for a migrations maanager pushed me towards an ORM for the MySQL database. Knex is awesome - very powerful, easy to use and make queries, and the migarations are nice to have for sure - especially for testing.
8787

8888
### middleware
8989

src/controllers/NoteController.js

Lines changed: 67 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,144 @@
1-
import {} from 'dotenv/config';
2-
import pool from '../db/db';
3-
import joi from 'joi';
4-
import dateFormat from 'date-fns/format';
1+
import {} from 'dotenv/config'
2+
import joi from 'joi'
3+
import dateFormat from 'date-fns/format'
54

6-
import { User } from '../models/User';
7-
import { Note } from '../models/Note';
5+
import { User } from '../models/User'
6+
import { Note } from '../models/Note'
87

98
const noteSchema = joi.object({
109
id: joi.number().integer(),
1110
userId: joi.number().integer().required(),
1211
title: joi.string().required(),
1312
content: joi.string().required(),
1413
ipAddress: joi.string(),
15-
});
14+
})
1615

1716
class NoteController {
1817
async index(ctx) {
18+
const query = ctx.query
19+
1920
//Attach logged in user
20-
const user = new User(ctx.state.user[0]);
21-
ctx.query.userId = user.id;
21+
const user = new User(ctx.state.user)
22+
query.userId = user.id
2223

2324
//Init a new note object
24-
const note = new Note();
25+
const note = new Note()
2526

2627
//Let's check that the sort options were set. Sort can be empty
27-
if (!ctx.query.order || !ctx.query.page || !ctx.query.limit) {
28-
ctx.throw(400, 'INVALID_ROUTE_OPTIONS');
28+
if (!query.order || !query.page || !query.limit) {
29+
ctx.throw(400, 'INVALID_ROUTE_OPTIONS')
2930
}
3031

32+
//Get paginated list of notes
3133
try {
32-
let result = await note.all(ctx.query);
33-
ctx.body = result;
34+
let result = await note.all(query)
35+
ctx.body = result
3436
} catch (error) {
35-
console.log(error);
36-
ctx.throw(400, 'INVALID_DATA');
37+
console.log(error)
38+
ctx.throw(400, 'INVALID_DATA' + error)
3739
}
3840
}
3941

4042
async show(ctx) {
41-
//Make sure they've chosen an id to show
42-
if (!ctx.params.id) ctx.throw(400, 'INVALID_DATA');
43+
const params = ctx.params
44+
if (!params.id) ctx.throw(400, 'INVALID_DATA')
4345

4446
//Initialize note
45-
const note = new Note();
47+
const note = new Note()
4648

4749
try {
4850
//Find and show note
49-
await note.find(ctx.params);
50-
ctx.body = note;
51+
await note.find(params.id)
52+
ctx.body = note
5153
} catch (error) {
52-
console.log(error);
53-
ctx.throw(400, 'INVALID_DATA');
54+
console.log(error)
55+
ctx.throw(400, 'INVALID_DATA')
5456
}
5557
}
5658

5759
async create(ctx) {
60+
const request = ctx.request.body
61+
5862
//Attach logged in user
59-
const user = new User(ctx.state.user[0]);
60-
ctx.request.body.userId = user.id;
63+
const user = new User(ctx.state.user)
64+
request.userId = user.id
6165

6266
//Add ip
63-
ctx.request.body.ipAddress = ctx.ip;
67+
request.ipAddress = ctx.ip
6468

6569
//Create a new note object using the request params
66-
const note = new Note(ctx.request.body);
70+
const note = new Note(request)
6771

6872
//Validate the newly created note
69-
const validator = joi.validate(note, noteSchema);
70-
if (validator.error) ctx.throw(400, validator.error.details[0].message);
73+
const validator = joi.validate(note, noteSchema)
74+
if (validator.error) ctx.throw(400, validator.error.details[0].message)
7175

7276
try {
73-
let result = await note.store();
74-
ctx.body = { message: 'SUCCESS', id: result.insertId };
77+
let result = await note.store()
78+
ctx.body = { message: 'SUCCESS', id: result }
7579
} catch (error) {
76-
console.log(error);
77-
ctx.throw(400, 'INVALID_DATA');
80+
console.log(error)
81+
ctx.throw(400, 'INVALID_DATA')
7882
}
7983
}
8084

8185
async update(ctx) {
86+
const params = ctx.params
87+
const request = ctx.request.body
88+
8289
//Make sure they've specified a note
83-
if (!ctx.params.id) ctx.throw(400, 'INVALID_DATA');
90+
if (!params.id) ctx.throw(400, 'INVALID_DATA')
8491

85-
//Find that note
86-
const note = new Note();
87-
await note.find(ctx.params);
88-
if (!note) ctx.throw(400, 'INVALID_DATA');
92+
//Find and set that note
93+
const note = new Note()
94+
await note.find(params.id)
95+
if (!note) ctx.throw(400, 'INVALID_DATA')
8996

9097
//Grab the user //If it's not their note - error out
91-
const user = new User(ctx.state.user[0]);
92-
if (note.userId !== user.id) ctx.throw(400, 'INVALID_DATA');
98+
const user = new User(ctx.state.user)
99+
if (note.userId !== user.id) ctx.throw(400, 'INVALID_DATA')
93100

94101
//Add the updated date value
95-
note.updatedAt = dateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss');
102+
note.updatedAt = dateFormat(new Date(), 'YYYY-MM-DD HH:mm:ss')
96103

97104
//Add the ip
98-
ctx.request.body.ipAddress = ctx.ip;
105+
request.ipAddress = ctx.ip
99106

100107
//Replace the note data with the new updated note data
101108
Object.keys(ctx.request.body).forEach(function(parameter, index) {
102-
note[parameter] = ctx.request.body[parameter];
103-
});
109+
note[parameter] = request[parameter]
110+
})
104111

105112
try {
106-
await note.save();
107-
ctx.body = { message: 'SUCCESS' };
113+
await note.save()
114+
ctx.body = { message: 'SUCCESS' }
108115
} catch (error) {
109-
console.log(error);
110-
ctx.throw(400, 'INVALID_DATA');
116+
console.log(error)
117+
ctx.throw(400, 'INVALID_DATA')
111118
}
112119
}
113120

114121
async delete(ctx) {
115-
if (!ctx.params.id) ctx.throw(400, 'INVALID_DATA');
122+
const params = ctx.params
123+
if (!params.id) ctx.throw(400, 'INVALID_DATA')
116124

117125
//Find that note
118-
const note = new Note();
119-
await note.find(ctx.params);
120-
if (!note) ctx.throw(400, 'INVALID_DATA');
126+
const note = new Note()
127+
await note.find(params.id)
128+
if (!note) ctx.throw(400, 'INVALID_DATA')
121129

122130
//Grab the user //If it's not their note - error out
123-
const user = new User(ctx.state.user[0]);
124-
if (note.userId !== user.id) ctx.throw(400, 'INVALID_DATA');
131+
const user = new User(ctx.state.user)
132+
if (note.userId !== user.id) ctx.throw(400, 'INVALID_DATA')
125133

126134
try {
127-
await note.destroy();
128-
ctx.body = { message: 'SUCCESS' };
135+
await note.destroy()
136+
ctx.body = { message: 'SUCCESS' }
129137
} catch (error) {
130-
console.log(error);
131-
ctx.throw(400, 'INVALID_DATA');
138+
console.log(error)
139+
ctx.throw(400, 'INVALID_DATA')
132140
}
133141
}
134142
}
135143

136-
export default NoteController;
144+
export default NoteController

0 commit comments

Comments
 (0)