Skip to content

Commit 05aa2f7

Browse files
authored
Xendit #7 - Refactoring Ride API (#7)
* Initial refactor for Ride module * Reduce coupling on Rider module
1 parent a0fe96c commit 05aa2f7

17 files changed

+1242
-337
lines changed

.eslintrc.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ module.exports = {
1919
"consistent-return": 0,
2020
"func-names": 0,
2121
"global-require": 0,
22-
"no-restricted-globals": 0
22+
"no-restricted-globals": 0,
23+
"no-underscore-dangle": 0,
24+
"prefer-arrow-callback": 0,
2325
}
2426
};

index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ const port = 8010;
33
const sqlite3 = require('sqlite3').verbose();
44

55
const db = new sqlite3.Database(':memory:');
6-
76
const buildSchemas = require('./src/schemas');
87

98
db.serialize(() => {
109
buildSchemas(db);
1110

1211
const app = require('./src/app')(db);
13-
1412
app.listen(port, () => console.log(`App started and listening on port ${port}`));
1513
});

package-lock.json

Lines changed: 141 additions & 0 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 & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
"body-parser": "^1.19.0",
2121
"express": "^4.16.4",
2222
"faker": "^5.1.0",
23+
"http-status-codes": "^2.1.4",
2324
"sqlite3": "^4.0.6",
2425
"swagger-ui-express": "^4.1.4",
26+
"validator": "^13.1.17",
2527
"winston": "^3.3.3"
2628
},
2729
"devDependencies": {
@@ -31,6 +33,7 @@
3133
"husky": "^4.3.0",
3234
"mocha": "^6.1.4",
3335
"nyc": "^15.1.0",
36+
"sinon": "^9.2.1",
3437
"supertest": "^4.0.2"
3538
},
3639
"husky": {

src/app.js

Lines changed: 14 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -10,143 +10,28 @@ const swaggerUI = require('swagger-ui-express');
1010
const swaggerFile = require('./resources/api-v1-swagger.json');
1111

1212
const { errorHandler } = require('./lib/errorHandler');
13+
const RideRepository = require('./modules/Ride/RideRepository');
14+
const RideController = require('./modules/Ride/RideController');
15+
const RideEntity = require('./modules/Ride/RideEntity');
16+
const { selectQuery, insertQuery } = require('./lib/databaseQuery');
1317

1418
module.exports = (db) => {
19+
// Manually inject instances
20+
const repository = new RideRepository(db, RideEntity, selectQuery, insertQuery);
21+
const controller = new RideController(repository);
22+
1523
app.get('/health', (req, res) => res.send('Healthy'));
1624

1725
app.use('/api-documentation/v1', swaggerUI.serve, swaggerUI.setup(swaggerFile));
1826

19-
app.post('/rides', jsonParser, (req, res, next) => {
20-
const startLatitude = Number(req.body.start_lat);
21-
const startLongitude = Number(req.body.start_long);
22-
const endLatitude = Number(req.body.end_lat);
23-
const endLongitude = Number(req.body.end_long);
24-
const riderName = req.body.rider_name;
25-
const driverName = req.body.driver_name;
26-
const driverVehicle = req.body.driver_vehicle;
27-
28-
if (
29-
startLatitude < -90
30-
|| startLatitude > 90
31-
|| startLongitude < -180
32-
|| startLongitude > 180
33-
) {
34-
return res.send({
35-
error_code: 'VALIDATION_ERROR',
36-
message: 'Start latitude and longitude must be between -90 - 90 and -180 to 180 degrees respectively',
37-
});
38-
}
39-
40-
if (endLatitude < -90 || endLatitude > 90 || endLongitude < -180 || endLongitude > 180) {
41-
return res.send({
42-
error_code: 'VALIDATION_ERROR',
43-
message: 'End latitude and longitude must be between -90 - 90 and -180 to 180 degrees respectively',
44-
});
45-
}
46-
47-
if (typeof riderName !== 'string' || riderName.length < 1) {
48-
return res.send({
49-
error_code: 'VALIDATION_ERROR',
50-
message: 'Rider name must be a non empty string',
51-
});
52-
}
53-
54-
if (typeof driverName !== 'string' || driverName.length < 1) {
55-
return res.send({
56-
error_code: 'VALIDATION_ERROR',
57-
message: 'Rider name must be a non empty string',
58-
});
59-
}
60-
61-
if (typeof driverVehicle !== 'string' || driverVehicle.length < 1) {
62-
return res.send({
63-
error_code: 'VALIDATION_ERROR',
64-
message: 'Rider name must be a non empty string',
65-
});
66-
}
67-
68-
const values = [
69-
req.body.start_lat,
70-
req.body.start_long,
71-
req.body.end_lat,
72-
req.body.end_long,
73-
req.body.rider_name,
74-
req.body.driver_name,
75-
req.body.driver_vehicle,
76-
];
77-
78-
db.run('INSERT INTO Rides(startLat, startLong, endLat, endLong, riderName, driverName, driverVehicle) VALUES (?, ?, ?, ?, ?, ?, ?)', values, function (insertErr) {
79-
if (insertErr) {
80-
return next(insertErr);
81-
}
82-
db.all('SELECT * FROM Rides WHERE rideID = ?', this.lastID, (selectErr, rows) => {
83-
if (selectErr) {
84-
return next(selectErr);
85-
}
86-
res.send(rows);
87-
});
88-
});
27+
app.post('/rides', jsonParser, function (req, res, next) {
28+
controller.postRide(req, res, next);
8929
});
90-
91-
app.get('/rides', (req, res, next) => {
92-
const { page = 1, limit = 10 } = req.query;
93-
if (isNaN(page) || page < 1 || isNaN(limit) || limit < 1) {
94-
return res.send({
95-
error_code: 'INVALID_PAGINATION_VALUES',
96-
message: 'Pagination values should be a number and not be less than 1',
97-
});
98-
}
99-
100-
const offset = (page - 1) * limit;
101-
const parsedPage = Number(page);
102-
const nextUrl = `/rides?page=${parsedPage + 1}&limit=${limit}`;
103-
const previousUrl = parsedPage === 1 ? null : `/rides?page=${parsedPage - 1}&limit=${limit}`;
104-
105-
db.all('SELECT * FROM Rides LIMIT ? OFFSET ?', [limit, offset], (err, rideEntities) => {
106-
if (err) {
107-
return next(err);
108-
}
109-
110-
if (rideEntities.length === 0) {
111-
return res.send({
112-
error_code: 'RIDES_NOT_FOUND_ERROR',
113-
message: 'Could not find any rides',
114-
});
115-
}
116-
117-
db.all('SELECT COUNT(*) as count FROM Rides', (countError, rows) => {
118-
if (countError) {
119-
return next(countError);
120-
}
121-
122-
const totalCount = rows[0].count;
123-
const hasNextPage = (page * limit) <= totalCount;
124-
const response = {
125-
next: hasNextPage ? nextUrl : null,
126-
previous: previousUrl,
127-
totalCount: rows[0].count,
128-
results: rideEntities,
129-
};
130-
res.send(response);
131-
});
132-
});
30+
app.get('/rides', function (req, res, next) {
31+
controller.getRides(req, res, next);
13332
});
134-
135-
app.get('/rides/:id', (req, res, next) => {
136-
db.all(`SELECT * FROM Rides WHERE rideID='${req.params.id}'`, (err, rows) => {
137-
if (err) {
138-
return next(err);
139-
}
140-
141-
if (rows.length === 0) {
142-
return res.send({
143-
error_code: 'RIDES_NOT_FOUND_ERROR',
144-
message: 'Could not find any rides',
145-
});
146-
}
147-
148-
res.send(rows);
149-
});
33+
app.get('/rides/:id', function (req, res, next) {
34+
controller.getRide(req, res, next);
15035
});
15136

15237
app.use(errorHandler);

0 commit comments

Comments
 (0)