'use strict'; const Promise = require('bluebird'); const logger = require('../logger'); const eventType = require('../eventType'); const NameExistsError = require('../error/NameExistsError'); const NotFoundError = require('../error/NotFoundError'); const ValidationError = require('../error/ValidationError'); const validateRequest = require('../error/validateRequest'); const extractUser = require('../extractUser'); module.exports = function (app, config) { const featureDb = config.featureDb; const eventStore = config.eventStore; app.get('/features', (req, res) => { featureDb.getFeatures().then(features => { res.json({ features }); }); }); app.get('/features/:featureName', (req, res) => { featureDb.getFeature(req.params.featureName) .then(feature => { res.json(feature); }) .catch(() => { res.status(404).json({ error: 'Could not find feature' }); }); }); app.post('/features', (req, res) => { req.checkBody('name', 'Name is required').notEmpty(); req.checkBody('name', 'Name must match format ^[a-zA-Z\\.\\-]+$').matches(/^[a-zA-Z\\.\\-]+$/i); validateRequest(req) .then(validateUniqueName) .then(() => eventStore.create({ type: eventType.featureCreated, createdBy: extractUser(req), data: req.body, })) .then(() => { res.status(201).end(); }) .catch(NameExistsError, () => { res.status(403).json([{ msg: `A feature named '${req.body.name}' already exists. It could be archived.`, }]).end(); }) .catch(ValidationError, () => { res.status(400).json(req.validationErrors()); }) .catch(err => { logger.error('Could not create feature toggle', err); res.status(500).end(); }); }); app.put('/features/:featureName', (req, res) => { const featureName = req.params.featureName; const userName = extractUser(req); const updatedFeature = req.body; updatedFeature.name = featureName; featureDb.getFeature(featureName) .then(() => eventStore.create({ type: eventType.featureUpdated, createdBy: userName, data: updatedFeature, })) .then(() => { res.status(200).end(); }) .catch(NotFoundError, () => { res.status(404).end(); }) .catch(err => { logger.error(`Could not update feature toggle=${featureName}`, err); res.status(500).end(); }); }); app.delete('/features/:featureName', (req, res) => { const featureName = req.params.featureName; const userName = extractUser(req); featureDb.getFeature(featureName) .then(() => eventStore.create({ type: eventType.featureArchived, createdBy: userName, data: { name: featureName, }, })) .then(() => { res.status(200).end(); }) .catch(NotFoundError, () => { res.status(404).end(); }) .catch(err => { logger.error(`Could not archive feature=${featureName}`, err); res.status(500).end(); }); }); function validateUniqueName(req) { return new Promise((resolve, reject) => { featureDb.getFeature(req.body.name) .then(() => { reject(new NameExistsError('Feature name already exist')); }, () => { resolve(req); }); }); } };