Skip to content

Commit 435675d

Browse files
add: get feature flag by ID api
1 parent c83575b commit 435675d

File tree

5 files changed

+143
-29
lines changed

5 files changed

+143
-29
lines changed

controllers/featureFlags.ts

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,48 @@
11
import { CustomRequest, CustomResponse } from "../types/global";
22
import featureFlagService from "../services/featureFlagService";
3-
import { FeatureFlag } from "../types/featureFlags";
3+
import { FeatureFlag, UpdateFeatureFlagRequestBody } from "../types/featureFlags";
44

55
export const getAllFeatureFlags = async (req: CustomRequest, res: CustomResponse) => {
66
try {
77
const serviceResponse = await featureFlagService.getAllFeatureFlags();
88

9-
if (serviceResponse.data) {
10-
return res.status(serviceResponse.status || 200).json({
11-
message: "Feature flags retrieved successfully",
12-
data: serviceResponse.data,
9+
if (!serviceResponse) {
10+
return res.status(500).json({
11+
error: "Failed to fetch feature flags"
1312
});
14-
} else if (serviceResponse.error) {
15-
return res.status(serviceResponse.status || 500).json({
16-
error: serviceResponse.error.message || "Internal server error",
17-
});
18-
} else {
19-
return res.status(500).json({ error: "Unknown error occurred" });
2013
}
14+
15+
return res.status(200).json({
16+
message: "Feature flags retrieved successfully",
17+
data: serviceResponse
18+
});
19+
2120
} catch (err) {
2221
logger.error(`Error in fetching feature flags: ${err}`);
2322
return res.boom.badImplementation('Internal server error');
2423
}
2524
};
2625

26+
27+
export const getFeatureFlagById = async (req: CustomRequest, res: CustomResponse) => {
28+
try {
29+
const { flagId } = req.params;
30+
const serviceResponse = await featureFlagService.getFeatureFlagById(flagId);
31+
32+
if (!serviceResponse) {
33+
return res.status(404).json({ error: "Feature flag not found" });
34+
}
35+
36+
return res.status(200).json({
37+
message: "Feature flag retrieved successfully",
38+
data: serviceResponse
39+
});
40+
} catch (err) {
41+
logger.error(`Error in fetching feature flag: ${err}`);
42+
return res.boom.badImplementation('Internal server error');
43+
}
44+
};
45+
2746
export const createFeatureFlag = async (req: CustomRequest, res: CustomResponse) => {
2847
try {
2948
const flagData: Partial<FeatureFlag> = req.body as Partial<FeatureFlag>;
@@ -53,9 +72,24 @@ export const createFeatureFlag = async (req: CustomRequest, res: CustomResponse)
5372
export const updateFeatureFlag = async (req: CustomRequest, res: CustomResponse) => {
5473
try {
5574
const { flagId } = req.params;
56-
const updateData: Partial<FeatureFlag> = req.body;
57-
const response = await featureFlagService.updateFeatureFlag(flagId, updateData);
58-
res.json(response);
75+
console.log("Mehulllll", flagId)
76+
const updateData: UpdateFeatureFlagRequestBody = {
77+
Status: req.body.Status,
78+
UserId: req.body.UserId,
79+
};
80+
81+
const serviceResponse = await featureFlagService.updateFeatureFlag(flagId, updateData);
82+
83+
if (serviceResponse.status >= 400) {
84+
return res.status(serviceResponse.status).json({
85+
error: serviceResponse.error?.message || "An error occurred while updating the feature flag",
86+
});
87+
}
88+
89+
return res.status(serviceResponse.status).json({
90+
message: "Feature flag updated successfully",
91+
data: serviceResponse.data,
92+
});
5993
} catch (err) {
6094
logger.error(`Error in updating feature flag: ${err}`);
6195
return res.boom.badImplementation('Internal server error');
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import Joi from 'joi';
2+
import { Request, Response, NextFunction } from 'express';
3+
import { CustomResponse } from '../../types/global';
4+
5+
const updateFeatureFlagSchema = Joi.object({
6+
Status: Joi.string()
7+
.valid('ENABLED', 'DISABLED')
8+
.required()
9+
.messages({
10+
'string.valid': 'Allowed values of Status are ENABLED, DISABLED',
11+
'any.required': 'Status is required'
12+
}),
13+
UserId: Joi.string()
14+
.required()
15+
.messages({
16+
'any.required': 'UserId is required'
17+
})
18+
});
19+
20+
export const validateUpdateFeatureFlag = async (req: Request, res: CustomResponse, next: NextFunction) => {
21+
try {
22+
await updateFeatureFlagSchema.validateAsync(req.body);
23+
next();
24+
} catch (error) {
25+
logger.error(`Error validating update feature flag payload: ${error.message}`);
26+
res.boom.badRequest(error.message);
27+
}
28+
};

routes/featureFlag.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import express from "express";
22
const router = express.Router();
33
import authenticate from "../middlewares/authenticate";
44
const authorizeRoles = require("../middlewares/authorizeRoles");
5-
import { getAllFeatureFlags, createFeatureFlag, updateFeatureFlag } from "../controllers/featureFlags";
5+
import { createFeatureFlag, getAllFeatureFlags, getFeatureFlagById, updateFeatureFlag} from "../controllers/featureFlags";
66
const { SUPERUSER } = require("../constants/roles");
7+
import { validateUpdateFeatureFlag } from '../middlewares/validators/featureFlag';
78

89
router.get("/getAllFeatureFlags", authenticate, getAllFeatureFlags);
9-
router.post('/createFeatureFlag', authenticate, authorizeRoles(SUPERUSER), createFeatureFlag);
10-
router.patch('/updateFeatureFlag/:flagId', authenticate, authorizeRoles(SUPERUSER), updateFeatureFlag);
10+
router.get("/getFeatureFlag/:flagId", authenticate, getFeatureFlagById);
11+
router.post('/createFeatureFlag', authenticate, authorizeRoles([SUPERUSER]), createFeatureFlag);
12+
router.patch('/updateFeatureFlag/:flagId', authenticate, authorizeRoles([SUPERUSER]), validateUpdateFeatureFlag, updateFeatureFlag);
1113

1214
module.exports = router;

services/featureFlagService.ts

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import config from "config";
2-
import { FeatureFlag, FeatureFlagResponse, FeatureFlagService } from "../types/featureFlags";
2+
import { FeatureFlag, FeatureFlagResponse, FeatureFlagService, UpdateFeatureFlagRequestBody } from "../types/featureFlags";
33

44
const FEATURE_FLAG_BASE_URL = config.get<string>("services.featureFlag.baseUrl");
55
const FEATURE_FLAG_API_KEY = config.get<string>("services.featureFlag.apiKey");
@@ -17,11 +17,17 @@ const getAllFeatureFlags = async (): Promise<FeatureFlagResponse> => {
1717
method: "GET",
1818
headers: generateHeaders(),
1919
});
20+
21+
if (!response.ok) {
22+
logger.error(`Failed to fetch feature flags. Status: ${response.status}`);
23+
throw new Error(`HTTP error! status: ${response.status}`);
24+
}
25+
2026
const data = await response.json();
2127
return data;
2228
} catch (err) {
2329
logger.error("Error in fetching feature flags", err);
24-
return { status: 500, error: { message: "Internal error while connecting to the feature flag service" } };
30+
return { status: 500, error: { message: "Internal error while connecting to the feature flag service" } };
2531
}
2632
};
2733

@@ -51,29 +57,67 @@ const createFeatureFlag = async (flagData: any): Promise<{ status: number; data?
5157
}
5258
};
5359

54-
5560
const updateFeatureFlag = async (
56-
flagId: string,
57-
updateData: Partial<FeatureFlag>
61+
flagId: string,
62+
updateData: UpdateFeatureFlagRequestBody
5863
): Promise<FeatureFlagResponse> => {
64+
try {
65+
const response = await fetch(`http://127.0.0.1:3000/feature-flags/${flagId}`, {
66+
method: "PATCH",
67+
headers: generateHeaders(),
68+
body: JSON.stringify(updateData),
69+
});
70+
console.log("Mehulllll", response)
71+
if (!response.ok) {
72+
const error = await response.json();
73+
return {
74+
status: response.status,
75+
error: error || { message: `HTTP error! status: ${response.status}` }
76+
};
77+
}
78+
79+
const data = await response.json();
80+
return { status: response.status, data };
81+
} catch (err) {
82+
logger.error("Error in updating feature flag", err);
83+
return {
84+
status: 500,
85+
error: { message: "Internal error while connecting to the feature flag service" }
86+
};
87+
}
88+
};
89+
90+
const getFeatureFlagById = async (flagId: string): Promise<FeatureFlagResponse> => {
5991
try {
6092
const response = await fetch(`${FEATURE_FLAG_BASE_URL}/feature-flags/${flagId}`, {
61-
method: "PUT",
93+
method: "GET",
6294
headers: generateHeaders(),
63-
body: JSON.stringify(updateData),
6495
});
96+
97+
if (!response.ok) {
98+
logger.error(`Failed to fetch feature flag. Status: ${response.status}`);
99+
return {
100+
status: response.status,
101+
error: { message: `HTTP error! status: ${response.status}` }
102+
};
103+
}
104+
65105
const data = await response.json();
66-
return data;
106+
return { status: response.status, data };
67107
} catch (err) {
68-
logger.error("Error in updating feature flag", err);
69-
throw err;
108+
logger.error("Error in fetching feature flag by ID", err);
109+
return {
110+
status: 500,
111+
error: { message: "Internal error while connecting to the feature flag service" }
112+
};
70113
}
71114
};
72115

73116
const featureFlagService: FeatureFlagService = {
74117
getAllFeatureFlags,
75118
createFeatureFlag,
76119
updateFeatureFlag,
120+
getFeatureFlagById,
77121
};
78122

79123
export default featureFlagService;

types/featureFlags.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,11 @@ export interface FeatureFlagResponse {
2020
export interface FeatureFlagService {
2121
getAllFeatureFlags(): Promise<FeatureFlagResponse>;
2222
createFeatureFlag(flagData: Partial<FeatureFlag>): Promise<FeatureFlagResponse>;
23-
updateFeatureFlag(flagId: string, updateData: Partial<FeatureFlag>): Promise<FeatureFlagResponse>;
24-
}
23+
updateFeatureFlag(flagId: string, updateData: UpdateFeatureFlagRequestBody): Promise<FeatureFlagResponse>;
24+
getFeatureFlagById: (flagId: string) => Promise<FeatureFlagResponse>;
25+
}
26+
27+
export interface UpdateFeatureFlagRequestBody {
28+
Status: string;
29+
UserId: string;
30+
}

0 commit comments

Comments
 (0)