unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
169 lines • 7.6 kB
JavaScript
import Controller from '../../routes/controller.js';
import { NONE, UPDATE_FEATURE_DEPENDENCY, } from '../../types/index.js';
import { createRequestSchema, createResponseSchema, emptyResponse, getStandardResponses, parentFeatureOptionsSchema, parentVariantOptionsSchema, } from '../../openapi/index.js';
const PATH = '/:projectId/features';
const PATH_FEATURE = `${PATH}/:child`;
const PATH_DEPENDENCIES = `${PATH_FEATURE}/dependencies`;
const PATH_DEPENDENCIES_CHECK = `/:projectId/dependencies`;
const PATH_PARENTS = `${PATH_FEATURE}/parents`;
const PATH_PARENT_VARIANTS = `${PATH}/:parent/parent-variants`;
const PATH_DEPENDENCY = `${PATH_FEATURE}/dependencies/:parent`;
export default class DependentFeaturesController extends Controller {
constructor(config, { transactionalDependentFeaturesService, openApiService, }) {
super(config);
this.dependentFeaturesService = transactionalDependentFeaturesService;
this.openApiService = openApiService;
this.flagResolver = config.flagResolver;
this.logger = config.getLogger('/dependent-features/dependent-features-controller.ts');
this.route({
method: 'post',
path: PATH_DEPENDENCIES,
handler: this.addFeatureDependency,
permission: UPDATE_FEATURE_DEPENDENCY,
middleware: [
openApiService.validPath({
tags: ['Dependencies'],
summary: 'Add a feature dependency.',
description: 'Add a dependency to a parent feature. Each environment will resolve corresponding dependency independently.',
operationId: 'addFeatureDependency',
requestBody: createRequestSchema('createDependentFeatureSchema'),
responses: {
200: emptyResponse,
...getStandardResponses(401, 403, 404),
},
}),
],
});
this.route({
method: 'delete',
path: PATH_DEPENDENCY,
handler: this.deleteFeatureDependency,
permission: UPDATE_FEATURE_DEPENDENCY,
acceptAnyContentType: true,
middleware: [
openApiService.validPath({
tags: ['Dependencies'],
summary: 'Deletes a feature dependency.',
description: 'Remove a dependency to a parent feature.',
operationId: 'deleteFeatureDependency',
responses: {
200: emptyResponse,
...getStandardResponses(401, 403, 404),
},
}),
],
});
this.route({
method: 'delete',
path: PATH_DEPENDENCIES,
handler: this.deleteFeatureDependencies,
permission: UPDATE_FEATURE_DEPENDENCY,
acceptAnyContentType: true,
middleware: [
openApiService.validPath({
tags: ['Dependencies'],
summary: 'Deletes feature dependencies.',
description: 'Remove dependencies to all parent features.',
operationId: 'deleteFeatureDependencies',
responses: {
200: emptyResponse,
...getStandardResponses(401, 403, 404),
},
}),
],
});
this.route({
method: 'get',
path: PATH_PARENTS,
handler: this.getPossibleParentFeatures,
permission: NONE,
middleware: [
openApiService.validPath({
tags: ['Dependencies'],
summary: 'List parent options.',
description: 'List available parents who have no transitive dependencies.',
operationId: 'listParentOptions',
responses: {
200: createResponseSchema('parentFeatureOptionsSchema'),
...getStandardResponses(401, 403, 404),
},
}),
],
});
this.route({
method: 'get',
path: PATH_PARENT_VARIANTS,
handler: this.getPossibleParentVariants,
permission: NONE,
middleware: [
openApiService.validPath({
tags: ['Dependencies'],
summary: 'List parent feature variants.',
description: 'List available parent variants across all strategy variants and feature environment variants.',
operationId: 'listParentVariantOptions',
responses: {
200: createResponseSchema('parentVariantOptionsSchema'),
...getStandardResponses(401, 403, 404),
},
}),
],
});
this.route({
method: 'get',
path: PATH_DEPENDENCIES_CHECK,
handler: this.checkDependenciesExist,
permission: NONE,
middleware: [
openApiService.validPath({
tags: ['Dependencies'],
summary: 'Check dependencies exist.',
description: 'Check if any dependencies exist in this Unleash instance',
operationId: 'checkDependenciesExist',
responses: {
200: createResponseSchema('dependenciesExistSchema'),
...getStandardResponses(401, 403),
},
}),
],
});
}
async addFeatureDependency(req, res) {
const { child, projectId } = req.params;
const { variants, enabled, feature } = req.body;
await this.dependentFeaturesService.transactional((service) => service.upsertFeatureDependency({ child, projectId }, {
variants,
enabled,
feature,
}, req.user, req.audit));
res.status(200).end();
}
async deleteFeatureDependency(req, res) {
const { child, parent, projectId } = req.params;
await this.dependentFeaturesService.transactional((service) => service.deleteFeatureDependency({
parent,
child,
}, projectId, req.user, req.audit));
res.status(200).end();
}
async deleteFeatureDependencies(req, res) {
const { child, projectId } = req.params;
await this.dependentFeaturesService.transactional((service) => service.deleteFeaturesDependencies([child], projectId, req.user, req.audit));
res.status(200).end();
}
async getPossibleParentFeatures(req, res) {
const { child } = req.params;
const options = await this.dependentFeaturesService.getPossibleParentFeatures(child);
this.openApiService.respondWithValidation(200, res, parentFeatureOptionsSchema.$id, options);
}
async getPossibleParentVariants(req, res) {
const { parent } = req.params;
const options = await this.dependentFeaturesService.getPossibleParentVariants(parent);
this.openApiService.respondWithValidation(200, res, parentVariantOptionsSchema.$id, options);
}
async checkDependenciesExist(req, res) {
const { child } = req.params;
const exist = await this.dependentFeaturesService.checkDependenciesExist();
res.send(exist);
}
}
//# sourceMappingURL=dependent-features-controller.js.map