Skip to content

Commit 6940a12

Browse files
author
liuliquan
committed
feat: versioned responses via transformer
1 parent e9dade8 commit 6940a12

File tree

4 files changed

+97
-9
lines changed

4 files changed

+97
-9
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"axios-retry": "^3.4.0",
5050
"bluebird": "^3.5.1",
5151
"body-parser": "^1.15.1",
52+
"compare-versions": "^6.1.0",
5253
"config": "^3.0.1",
5354
"cors": "^2.8.5",
5455
"decimal.js": "^10.4.3",

src/common/transformer.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
const _ = require("lodash");
2+
const { compareVersions } = require("compare-versions");
3+
const challengeService = require("../services/ChallengeService");
4+
5+
function transformData(data, fieldsToDelete) {
6+
if (!fieldsToDelete || !fieldsToDelete.length) {
7+
return data;
8+
}
9+
10+
if (_.isArray(data)) {
11+
return data.map((item) => transformData(item, fieldsToDelete));
12+
} else if (_.isObject(data)) {
13+
const clonedData = { ...data };
14+
for (const field of fieldsToDelete) {
15+
delete clonedData[field];
16+
}
17+
if (clonedData.result) {
18+
clonedData.result = transformData(clonedData.result, fieldsToDelete);
19+
}
20+
return clonedData;
21+
}
22+
23+
return data;
24+
}
25+
26+
function transformServices() {
27+
_.each(services, (service, serviceName) => {
28+
const serviceConfig = servicesConfig[serviceName];
29+
if (!serviceConfig) {
30+
return;
31+
}
32+
33+
_.each(service, (method, methodName) => {
34+
service[methodName] = async function () {
35+
const args = Array.prototype.slice.call(arguments);
36+
const data = await method.apply(this, args.slice(1));
37+
38+
// No transform need for this method
39+
if (!serviceConfig.methods.includes(methodName)) {
40+
return data;
41+
}
42+
43+
// args[0] is request, get version header
44+
const apiVersion = args[0].headers["challenge-api-version"] || "1.0.0";
45+
46+
const fieldsToDelete = [];
47+
_.each(serviceConfig.fieldsVersion, (version, field) => {
48+
// If input version less than required version, delete fields from response
49+
if (compareVersions(apiVersion, version) < 0) {
50+
fieldsToDelete.push(field);
51+
}
52+
});
53+
54+
// Transform response data by deleting fields
55+
return transformData(data, fieldsToDelete);
56+
};
57+
service[methodName].params = ["req", ...method.params];
58+
});
59+
});
60+
}
61+
62+
// Define the version config for services
63+
const servicesConfig = {
64+
challengeService: {
65+
methods: ["searchChallenges", "getChallenge", "createChallenge", "updateChallenge"],
66+
fieldsVersion: {
67+
skills: "1.1.0",
68+
payments: "2.0.0",
69+
},
70+
},
71+
};
72+
73+
// Define the services to export
74+
const services = {
75+
challengeService,
76+
};
77+
78+
// Transform services before export
79+
transformServices();
80+
81+
module.exports = services;

src/controllers/ChallengeController.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Controller for challenge endpoints
33
*/
44
const HttpStatus = require("http-status-codes");
5-
const service = require("../services/ChallengeService");
5+
const { challengeService: service } = require("../common/transformer");
66
const helper = require("../common/helper");
77
const logger = require("../common/logger");
88

@@ -12,7 +12,7 @@ const logger = require("../common/logger");
1212
* @param {Object} res the response
1313
*/
1414
async function searchChallenges(req, res) {
15-
let result = await service.searchChallenges(req.authUser, {
15+
let result = await service.searchChallenges(req, req.authUser, {
1616
...req.query,
1717
...req.body,
1818
});
@@ -23,7 +23,7 @@ async function searchChallenges(req, res) {
2323
logger.debug(`Staring to get mm challengeId`);
2424
const legacyId = await helper.getProjectIdByRoundId(req.query.legacyId);
2525
logger.debug(`Get mm challengeId successfully ${legacyId}`);
26-
result = await service.searchChallenges(req.authUser, {
26+
result = await service.searchChallenges(req, req.authUser, {
2727
...req.query,
2828
...req.body,
2929
legacyId,
@@ -50,7 +50,7 @@ async function createChallenge(req, res) {
5050
logger.debug(
5151
`createChallenge User: ${JSON.stringify(req.authUser)} - Body: ${JSON.stringify(req.body)}`
5252
);
53-
const result = await service.createChallenge(req.authUser, req.body, req.userToken);
53+
const result = await service.createChallenge(req, req.authUser, req.body, req.userToken);
5454
res.status(HttpStatus.CREATED).send(result);
5555
}
5656

@@ -60,7 +60,7 @@ async function createChallenge(req, res) {
6060
* @param {Object} res the response
6161
*/
6262
async function sendNotifications(req, res) {
63-
const result = await service.sendNotifications(req.authUser, req.params.challengeId);
63+
const result = await service.sendNotifications(req, req.authUser, req.params.challengeId);
6464
res.status(HttpStatus.CREATED).send(result);
6565
}
6666

@@ -71,6 +71,7 @@ async function sendNotifications(req, res) {
7171
*/
7272
async function getChallenge(req, res) {
7373
const result = await service.getChallenge(
74+
req,
7475
req.authUser,
7576
req.params.challengeId,
7677
req.query.checkIfExists
@@ -84,7 +85,7 @@ async function getChallenge(req, res) {
8485
* @param {Object} res the response
8586
*/
8687
async function getChallengeStatistics(req, res) {
87-
const result = await service.getChallengeStatistics(req.authUser, req.params.challengeId);
88+
const result = await service.getChallengeStatistics(req, req.authUser, req.params.challengeId);
8889
res.send(result);
8990
}
9091

@@ -99,7 +100,7 @@ async function updateChallenge(req, res) {
99100
req.params.challengeId
100101
} - Body: ${JSON.stringify(req.body)}`
101102
);
102-
const result = await service.updateChallenge(req.authUser, req.params.challengeId, req.body);
103+
const result = await service.updateChallenge(req, req.authUser, req.params.challengeId, req.body);
103104
res.send(result);
104105
}
105106

@@ -112,7 +113,7 @@ async function deleteChallenge(req, res) {
112113
logger.debug(
113114
`deleteChallenge User: ${JSON.stringify(req.authUser)} - ChallengeID: ${req.params.challengeId}`
114115
);
115-
const result = await service.deleteChallenge(req.authUser, req.params.challengeId);
116+
const result = await service.deleteChallenge(req, req.authUser, req.params.challengeId);
116117
res.send(result);
117118
}
118119

@@ -122,7 +123,7 @@ async function deleteChallenge(req, res) {
122123
* @param {Object} res the response
123124
*/
124125
async function advancePhase(req, res) {
125-
res.send(await service.advancePhase(req.authUser, req.params.challengeId, req.body));
126+
res.send(await service.advancePhase(req, req.authUser, req.params.challengeId, req.body));
126127
}
127128

128129
module.exports = {

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,11 @@ commondir@^1.0.1:
978978
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
979979
integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==
980980

981+
compare-versions@^6.1.0:
982+
version "6.1.0"
983+
resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-6.1.0.tgz#3f2131e3ae93577df111dba133e6db876ffe127a"
984+
integrity sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==
985+
981986
component-emitter@^1.2.0, component-emitter@^1.3.0:
982987
version "1.3.0"
983988
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"

0 commit comments

Comments
 (0)