mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Statefull modules should be injected from top
This commit is contained in:
		
							parent
							
								
									2355da231e
								
							
						
					
					
						commit
						b2e9f38965
					
				
							
								
								
									
										3
									
								
								app.js
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								app.js
									
									
									
									
									
								
							@ -31,7 +31,8 @@ module.exports = function(config) {
 | 
			
		||||
 | 
			
		||||
    app.use(cookieParser());
 | 
			
		||||
 | 
			
		||||
    routes.create(router);
 | 
			
		||||
    // Setup API routes
 | 
			
		||||
    routes.create(router, config);
 | 
			
		||||
 | 
			
		||||
    app.use(baseUriPath, router);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										29
									
								
								lib/databaseConfig.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								lib/databaseConfig.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
var nconf  = require('nconf');
 | 
			
		||||
var fs     = require('fs');
 | 
			
		||||
var ini    = require('ini');
 | 
			
		||||
var logger = require('./logger');
 | 
			
		||||
 | 
			
		||||
function getDatabaseIniUrl() {
 | 
			
		||||
    // Finn specific way of delivering env variables
 | 
			
		||||
    var databaseini = nconf.argv().get('databaseini');
 | 
			
		||||
    var config = ini.parse(fs.readFileSync(databaseini, 'utf-8'));
 | 
			
		||||
 | 
			
		||||
    logger.info('unleash started with databaseini: ' + databaseini);
 | 
			
		||||
 | 
			
		||||
    return config.DATABASE_URL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getDatabaseUrl() {
 | 
			
		||||
    if (process.env.DATABASE_URL) {
 | 
			
		||||
        logger.info('unleash started with DATABASE_URL');
 | 
			
		||||
        return process.env.DATABASE_URL;
 | 
			
		||||
    } else if (nconf.argv().get('databaseini') !== undefined) {
 | 
			
		||||
        return getDatabaseIniUrl();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    throw new Error('please set DATABASE_URL or pass --databaseini');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports =  {
 | 
			
		||||
    getDatabaseUrl: getDatabaseUrl
 | 
			
		||||
};
 | 
			
		||||
@ -1,52 +1,9 @@
 | 
			
		||||
var logger = require('../logger');
 | 
			
		||||
var nconf  = require('nconf');
 | 
			
		||||
var fs     = require('fs');
 | 
			
		||||
var ini    = require('ini');
 | 
			
		||||
var knex   = require('knex');
 | 
			
		||||
 | 
			
		||||
function isTestEnv() {
 | 
			
		||||
    return process.env.NODE_ENV === 'test';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getDatabaseIniUrl() {
 | 
			
		||||
    // Finn specific way of delivering env variables
 | 
			
		||||
    var databaseini = nconf.argv().get('databaseini');
 | 
			
		||||
    var config = ini.parse(fs.readFileSync(databaseini, 'utf-8'));
 | 
			
		||||
 | 
			
		||||
    logger.info('unleash started with databaseini: ' + databaseini);
 | 
			
		||||
 | 
			
		||||
    return config.DATABASE_URL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getTestDatabaseUrl() {
 | 
			
		||||
    if (process.env.TEST_DATABASE_URL) {
 | 
			
		||||
        logger.info('unleash started with TEST_DATABASE_URL');
 | 
			
		||||
        return process.env.TEST_DATABASE_URL;
 | 
			
		||||
    } else {
 | 
			
		||||
        throw new Error('please set TEST_DATABASE_URL');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getDatabaseUrl() {
 | 
			
		||||
    if (process.env.DATABASE_URL) {
 | 
			
		||||
        logger.info('unleash started with DATABASE_URL');
 | 
			
		||||
        return process.env.DATABASE_URL;
 | 
			
		||||
    } else if (nconf.argv().get('databaseini') !== undefined) {
 | 
			
		||||
        return getDatabaseIniUrl();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    throw new Error('please set DATABASE_URL or pass --databaseini');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function createDbPool() {
 | 
			
		||||
module.exports = function(databaseConnection) {
 | 
			
		||||
    return knex({
 | 
			
		||||
        client: 'pg',
 | 
			
		||||
        connection: isTestEnv() ? getTestDatabaseUrl() : getDatabaseUrl(),
 | 
			
		||||
        pool: { 
 | 
			
		||||
            min: 2, 
 | 
			
		||||
            max: 20
 | 
			
		||||
        }
 | 
			
		||||
        connection: databaseConnection,
 | 
			
		||||
        pool: { min: 2, max: 20 }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = createDbPool();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -1,43 +1,45 @@
 | 
			
		||||
var knex          = require('./dbPool');
 | 
			
		||||
var EVENT_COLUMNS = ['id', 'type', 'created_by', 'created_at', 'data'];
 | 
			
		||||
 | 
			
		||||
function storeEvent(event) {
 | 
			
		||||
    return knex('events').insert({
 | 
			
		||||
        type: event.type,
 | 
			
		||||
        created_by: event.createdBy, // eslint-disable-line
 | 
			
		||||
        data: event.data
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
module.exports = function(db) {
 | 
			
		||||
    function storeEvent(event) {
 | 
			
		||||
        return db('events').insert({
 | 
			
		||||
            type: event.type,
 | 
			
		||||
            created_by: event.createdBy, // eslint-disable-line
 | 
			
		||||
            data: event.data
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
function getEvents() {
 | 
			
		||||
    return knex
 | 
			
		||||
    function getEvents() {
 | 
			
		||||
        return db
 | 
			
		||||
            .select(EVENT_COLUMNS)
 | 
			
		||||
            .from('events')
 | 
			
		||||
            .orderBy('created_at', 'desc')
 | 
			
		||||
            .map(rowToEvent);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getEventsFilterByName(name) {
 | 
			
		||||
        return db
 | 
			
		||||
        .select(EVENT_COLUMNS)
 | 
			
		||||
        .from('events')
 | 
			
		||||
        .whereRaw("data ->> 'name' = ?", [name])
 | 
			
		||||
        .orderBy('created_at', 'desc')
 | 
			
		||||
        .map(rowToEvent);
 | 
			
		||||
}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
function getEventsFilterByName(name) {
 | 
			
		||||
    return knex
 | 
			
		||||
      .select(EVENT_COLUMNS)
 | 
			
		||||
      .from('events')
 | 
			
		||||
      .whereRaw("data ->> 'name' = ?", [name])
 | 
			
		||||
      .orderBy('created_at', 'desc')
 | 
			
		||||
      .map(rowToEvent);
 | 
			
		||||
}
 | 
			
		||||
    function rowToEvent(row) {
 | 
			
		||||
        return {
 | 
			
		||||
            id: row.id,
 | 
			
		||||
            type: row.type,
 | 
			
		||||
            createdBy: row.created_by,
 | 
			
		||||
            createdAt: row.created_at,
 | 
			
		||||
            data: row.data
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
function rowToEvent(row) {
 | 
			
		||||
    return {
 | 
			
		||||
        id: row.id,
 | 
			
		||||
        type: row.type,
 | 
			
		||||
        createdBy: row.created_by,
 | 
			
		||||
        createdAt: row.created_at,
 | 
			
		||||
        data: row.data
 | 
			
		||||
        store: storeEvent,
 | 
			
		||||
        getEvents: getEvents,
 | 
			
		||||
        getEventsFilterByName: getEventsFilterByName
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    store: storeEvent,
 | 
			
		||||
    getEvents: getEvents,
 | 
			
		||||
    getEventsFilterByName: getEventsFilterByName
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,118 +1,118 @@
 | 
			
		||||
var eventStore      = require('../eventStore');
 | 
			
		||||
var eventType       = require('../eventType');
 | 
			
		||||
var logger          = require('../logger');
 | 
			
		||||
var knex            = require('./dbPool');
 | 
			
		||||
var NotFoundError   = require('../error/NotFoundError');
 | 
			
		||||
var FEATURE_COLUMNS = ['name', 'description', 'enabled', 'strategy_name', 'parameters'];
 | 
			
		||||
 | 
			
		||||
eventStore.on(eventType.featureCreated, function (event) {
 | 
			
		||||
    return createFeature(event.data);
 | 
			
		||||
});
 | 
			
		||||
module.exports = function(db, eventStore) {
 | 
			
		||||
    eventStore.on(eventType.featureCreated, function (event) {
 | 
			
		||||
        return createFeature(event.data);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
eventStore.on(eventType.featureUpdated, function (event) {
 | 
			
		||||
    return updateFeature(event.data);
 | 
			
		||||
});
 | 
			
		||||
    eventStore.on(eventType.featureUpdated, function (event) {
 | 
			
		||||
        return updateFeature(event.data);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
eventStore.on(eventType.featureArchived, function (event) {
 | 
			
		||||
    return archiveFeature(event.data);
 | 
			
		||||
});
 | 
			
		||||
    eventStore.on(eventType.featureArchived, function (event) {
 | 
			
		||||
        return archiveFeature(event.data);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
eventStore.on(eventType.featureRevived, function (event) {
 | 
			
		||||
    return reviveFeature(event.data);
 | 
			
		||||
});
 | 
			
		||||
    eventStore.on(eventType.featureRevived, function (event) {
 | 
			
		||||
        return reviveFeature(event.data);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
function getFeatures() {
 | 
			
		||||
    return knex
 | 
			
		||||
        .select(FEATURE_COLUMNS)
 | 
			
		||||
        .from('features')
 | 
			
		||||
        .where({ archived: 0 })
 | 
			
		||||
        .orderBy('name', 'asc')
 | 
			
		||||
        .map(rowToFeature);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getFeature(name) {
 | 
			
		||||
    return knex
 | 
			
		||||
        .first(FEATURE_COLUMNS)
 | 
			
		||||
        .from('features')
 | 
			
		||||
        .where({ name: name })
 | 
			
		||||
        .then(rowToFeature);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getArchivedFeatures() {
 | 
			
		||||
    return knex
 | 
			
		||||
        .select(FEATURE_COLUMNS)
 | 
			
		||||
        .from('features')
 | 
			
		||||
        .where({ archived: 1 })
 | 
			
		||||
        .orderBy('name', 'asc')
 | 
			
		||||
        .map(rowToFeature);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function rowToFeature(row) {
 | 
			
		||||
    if (!row) {
 | 
			
		||||
        throw new NotFoundError('No feature toggle found');
 | 
			
		||||
    function getFeatures() {
 | 
			
		||||
        return db
 | 
			
		||||
            .select(FEATURE_COLUMNS)
 | 
			
		||||
            .from('features')
 | 
			
		||||
            .where({ archived: 0 })
 | 
			
		||||
            .orderBy('name', 'asc')
 | 
			
		||||
            .map(rowToFeature);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getFeature(name) {
 | 
			
		||||
        return db
 | 
			
		||||
            .first(FEATURE_COLUMNS)
 | 
			
		||||
            .from('features')
 | 
			
		||||
            .where({ name: name })
 | 
			
		||||
            .then(rowToFeature);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getArchivedFeatures() {
 | 
			
		||||
        return db
 | 
			
		||||
            .select(FEATURE_COLUMNS)
 | 
			
		||||
            .from('features')
 | 
			
		||||
            .where({ archived: 1 })
 | 
			
		||||
            .orderBy('name', 'asc')
 | 
			
		||||
            .map(rowToFeature);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    function rowToFeature(row) {
 | 
			
		||||
        if (!row) {
 | 
			
		||||
            throw new NotFoundError('No feature toggle found');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            name: row.name,
 | 
			
		||||
            description: row.description,
 | 
			
		||||
            enabled: row.enabled > 0,
 | 
			
		||||
            strategy: row.strategy_name, // eslint-disable-line
 | 
			
		||||
            parameters: row.parameters
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function eventDataToRow(data) {
 | 
			
		||||
        return {
 | 
			
		||||
            name: data.name,
 | 
			
		||||
            description: data.description,
 | 
			
		||||
            enabled: data.enabled ? 1 : 0,
 | 
			
		||||
            archived: data.archived ? 1 :0,
 | 
			
		||||
            strategy_name: data.strategy, // eslint-disable-line
 | 
			
		||||
            parameters: data.parameters
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function createFeature(data) {
 | 
			
		||||
        return db('features')
 | 
			
		||||
            .insert(eventDataToRow(data))
 | 
			
		||||
            .catch(function (err) {
 | 
			
		||||
                logger.error('Could not insert feature, error was: ', err);
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function updateFeature(data) {
 | 
			
		||||
        return db('features')
 | 
			
		||||
            .where({ name: data.name })
 | 
			
		||||
            .update(eventDataToRow(data))
 | 
			
		||||
            .catch(function (err) {
 | 
			
		||||
                logger.error('Could not update feature, error was: ', err);
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function archiveFeature(data) {
 | 
			
		||||
        return db('features')
 | 
			
		||||
            .where({ name: data.name })
 | 
			
		||||
            .update({ archived: 1 })
 | 
			
		||||
            .catch(function (err) {
 | 
			
		||||
                logger.error('Could not archive feature, error was: ', err);
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function reviveFeature(data) {
 | 
			
		||||
        return db('features')
 | 
			
		||||
            .where({ name: data.name })
 | 
			
		||||
            .update({ archived: 0, enabled: 0 })
 | 
			
		||||
            .catch(function (err) {
 | 
			
		||||
                logger.error('Could not archive feature, error was: ', err);
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        name: row.name,
 | 
			
		||||
        description: row.description,
 | 
			
		||||
        enabled: row.enabled > 0,
 | 
			
		||||
        strategy: row.strategy_name, // eslint-disable-line
 | 
			
		||||
        parameters: row.parameters
 | 
			
		||||
        getFeatures: getFeatures,
 | 
			
		||||
        getFeature: getFeature,
 | 
			
		||||
        getArchivedFeatures: getArchivedFeatures,
 | 
			
		||||
        _createFeature: createFeature, // visible for testing
 | 
			
		||||
        _updateFeature: updateFeature  // visible for testing
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function eventDataToRow(data) {
 | 
			
		||||
    return {
 | 
			
		||||
        name: data.name,
 | 
			
		||||
        description: data.description || '',
 | 
			
		||||
        enabled: data.enabled ? 1 : 0,
 | 
			
		||||
        archived: data.archived ? 1 :0,
 | 
			
		||||
        strategy_name: data.strategy || 'default', // eslint-disable-line
 | 
			
		||||
        parameters: data.parameters || {}
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function createFeature(data) {
 | 
			
		||||
    return knex('features')
 | 
			
		||||
        .insert(eventDataToRow(data))
 | 
			
		||||
        .catch(function (err) {
 | 
			
		||||
            logger.error('Could not insert feature, error was: ', err);
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function updateFeature(data) {
 | 
			
		||||
    return knex('features')
 | 
			
		||||
        .where({ name: data.name })
 | 
			
		||||
        .update(eventDataToRow(data))
 | 
			
		||||
        .catch(function (err) {
 | 
			
		||||
            logger.error('Could not update feature, error was: ', err);
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function archiveFeature(data) {
 | 
			
		||||
    return knex('features')
 | 
			
		||||
        .where({ name: data.name })
 | 
			
		||||
        .update({ archived: 1 })
 | 
			
		||||
        .catch(function (err) {
 | 
			
		||||
            logger.error('Could not archive feature, error was: ', err);
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function reviveFeature(data) {
 | 
			
		||||
    return knex('features')
 | 
			
		||||
        .where({ name: data.name })
 | 
			
		||||
        .update({ archived: 0, enabled: 0 })
 | 
			
		||||
        .catch(function (err) {
 | 
			
		||||
            logger.error('Could not archive feature, error was: ', err);
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    getFeatures: getFeatures,
 | 
			
		||||
    getFeature: getFeature,
 | 
			
		||||
    getArchivedFeatures: getArchivedFeatures,
 | 
			
		||||
    _createFeature: createFeature, // visible for testing
 | 
			
		||||
    _updateFeature: updateFeature  // visible for testing
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -1,70 +1,70 @@
 | 
			
		||||
var eventStore      = require('../eventStore');
 | 
			
		||||
var eventType       = require('../eventType');
 | 
			
		||||
var logger          = require('../logger');
 | 
			
		||||
var knex            = require('./dbPool');
 | 
			
		||||
var NotFoundError   = require('../error/NotFoundError');
 | 
			
		||||
var STRATEGY_COLUMNS = ['name', 'description', 'parameters_template'];
 | 
			
		||||
 | 
			
		||||
eventStore.on(eventType.strategyCreated, function (event) {
 | 
			
		||||
    return createStrategy(event.data);
 | 
			
		||||
});
 | 
			
		||||
module.exports = function(db, eventStore) {
 | 
			
		||||
    eventStore.on(eventType.strategyCreated, function (event) {
 | 
			
		||||
        return createStrategy(event.data);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
eventStore.on(eventType.strategyDeleted, function (event) {
 | 
			
		||||
    knex('strategies')
 | 
			
		||||
        .where('name', event.data.name)
 | 
			
		||||
        .del()
 | 
			
		||||
        .catch(function (err) {
 | 
			
		||||
            logger.error('Could not delete strategy, error was: ', err);
 | 
			
		||||
        });
 | 
			
		||||
});
 | 
			
		||||
    eventStore.on(eventType.strategyDeleted, function (event) {
 | 
			
		||||
        db('strategies')
 | 
			
		||||
            .where('name', event.data.name)
 | 
			
		||||
            .del()
 | 
			
		||||
            .catch(function (err) {
 | 
			
		||||
                logger.error('Could not delete strategy, error was: ', err);
 | 
			
		||||
            });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
function getStrategies() {
 | 
			
		||||
    return knex
 | 
			
		||||
        .select(STRATEGY_COLUMNS)
 | 
			
		||||
        .from('strategies')
 | 
			
		||||
        .orderBy('created_at', 'asc')
 | 
			
		||||
        .map(rowToStrategy);
 | 
			
		||||
}
 | 
			
		||||
    function getStrategies() {
 | 
			
		||||
        return db
 | 
			
		||||
            .select(STRATEGY_COLUMNS)
 | 
			
		||||
            .from('strategies')
 | 
			
		||||
            .orderBy('created_at', 'asc')
 | 
			
		||||
            .map(rowToStrategy);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
function getStrategy(name) {
 | 
			
		||||
    return knex
 | 
			
		||||
        .first(STRATEGY_COLUMNS)
 | 
			
		||||
        .from('strategies')
 | 
			
		||||
        .where({ name: name })
 | 
			
		||||
        .then(rowToStrategy);
 | 
			
		||||
}
 | 
			
		||||
    function getStrategy(name) {
 | 
			
		||||
        return db
 | 
			
		||||
            .first(STRATEGY_COLUMNS)
 | 
			
		||||
            .from('strategies')
 | 
			
		||||
            .where({ name: name })
 | 
			
		||||
            .then(rowToStrategy);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
function rowToStrategy(row) {
 | 
			
		||||
    if (!row) {
 | 
			
		||||
        throw new NotFoundError('No strategy found');
 | 
			
		||||
    function rowToStrategy(row) {
 | 
			
		||||
        if (!row) {
 | 
			
		||||
            throw new NotFoundError('No strategy found');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            name: row.name,
 | 
			
		||||
            description: row.description,
 | 
			
		||||
            parametersTemplate: row.parameters_template
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function eventDataToRow(data) {
 | 
			
		||||
        return {
 | 
			
		||||
            name: data.name,
 | 
			
		||||
            description: data.description,
 | 
			
		||||
            parameters_template: data.parametersTemplate // eslint-disable-line
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function createStrategy(data) {
 | 
			
		||||
        db('strategies')
 | 
			
		||||
            .insert(eventDataToRow(data))
 | 
			
		||||
            .catch(function (err) {
 | 
			
		||||
                logger.error('Could not insert strategy, error was: ', err);
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        name: row.name,
 | 
			
		||||
        description: row.description,
 | 
			
		||||
        parametersTemplate: row.parameters_template
 | 
			
		||||
        getStrategies: getStrategies,
 | 
			
		||||
        getStrategy: getStrategy,
 | 
			
		||||
        _createStrategy: createStrategy // visible for testing
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function eventDataToRow(data) {
 | 
			
		||||
    return {
 | 
			
		||||
        name: data.name,
 | 
			
		||||
        description: data.description,
 | 
			
		||||
        parameters_template: data.parametersTemplate || {} // eslint-disable-line
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function createStrategy(data) {
 | 
			
		||||
    knex('strategies')
 | 
			
		||||
        .insert(eventDataToRow(data))
 | 
			
		||||
        .catch(function (err) {
 | 
			
		||||
            logger.error('Could not insert strategy, error was: ', err);
 | 
			
		||||
        });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    getStrategies: getStrategies,
 | 
			
		||||
    getStrategy: getStrategy,
 | 
			
		||||
    _createStrategy: createStrategy // visible for testing
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,17 +1,17 @@
 | 
			
		||||
var util = require('util'),
 | 
			
		||||
    eventDb = require('./db/event'),
 | 
			
		||||
    EventEmitter = require('events').EventEmitter;
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var EventEmitter = require('events').EventEmitter;
 | 
			
		||||
 | 
			
		||||
function EventStore() {
 | 
			
		||||
function EventStore(eventDb) {
 | 
			
		||||
    this.eventDb = eventDb;
 | 
			
		||||
    EventEmitter.call(this);
 | 
			
		||||
}
 | 
			
		||||
util.inherits(EventStore, EventEmitter);
 | 
			
		||||
 | 
			
		||||
EventStore.prototype.create = function (event) {
 | 
			
		||||
    var that = this;
 | 
			
		||||
    return eventDb.store(event).then(function() {
 | 
			
		||||
        return that.emit(event.type, event);
 | 
			
		||||
    return this.eventDb.store(event).then(function() {
 | 
			
		||||
        that.emit(event.type, event);
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = new EventStore();
 | 
			
		||||
module.exports = EventStore;
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,8 @@
 | 
			
		||||
var eventDb     = require('../db/event');
 | 
			
		||||
var eventDiffer = require('../eventDiffer');
 | 
			
		||||
 | 
			
		||||
module.exports = function (app) {
 | 
			
		||||
module.exports = function (app, config) {
 | 
			
		||||
    var eventDb = config.eventDb;
 | 
			
		||||
 | 
			
		||||
    app.get('/events', function (req, res) {
 | 
			
		||||
        eventDb.getEvents().then(function (events) {
 | 
			
		||||
            eventDiffer.addDiffs(events);
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,12 @@
 | 
			
		||||
var logger              = require('../logger');
 | 
			
		||||
var eventStore          = require('../eventStore');
 | 
			
		||||
var eventType           = require('../eventType');
 | 
			
		||||
var featureDb           = require('../db/feature');
 | 
			
		||||
var ValidationError     = require('../error/ValidationError');
 | 
			
		||||
var validateRequest     = require('../error/validateRequest');
 | 
			
		||||
 | 
			
		||||
module.exports = function (app) {
 | 
			
		||||
module.exports = function (app, config) {
 | 
			
		||||
    var featureDb = config.featureDb;
 | 
			
		||||
    var eventStore = config.eventStore;
 | 
			
		||||
 | 
			
		||||
    app.get('/archive/features', function (req, res) {
 | 
			
		||||
        featureDb.getArchivedFeatures().then(function (archivedFeatures) {
 | 
			
		||||
            res.json({ 'features': archivedFeatures });
 | 
			
		||||
 | 
			
		||||
@ -1,15 +1,16 @@
 | 
			
		||||
var Promise             = require("bluebird");
 | 
			
		||||
var logger              = require('../logger');
 | 
			
		||||
var eventStore          = require('../eventStore');
 | 
			
		||||
var eventType           = require('../eventType');
 | 
			
		||||
var featureDb           = require('../db/feature');
 | 
			
		||||
var NameExistsError     = require('../error/NameExistsError');
 | 
			
		||||
var NotFoundError       = require('../error/NotFoundError');
 | 
			
		||||
var ValidationError     = require('../error/ValidationError');
 | 
			
		||||
var validateRequest     = require('../error/validateRequest');
 | 
			
		||||
var extractUser         = require('../extractUser');
 | 
			
		||||
 | 
			
		||||
module.exports = function (app) {
 | 
			
		||||
module.exports = function (app, config) {
 | 
			
		||||
    var featureDb = config.featureDb;
 | 
			
		||||
    var eventStore = config.eventStore;
 | 
			
		||||
 | 
			
		||||
    app.get('/features', function (req, res) {
 | 
			
		||||
        featureDb.getFeatures().then(function (features) {
 | 
			
		||||
            res.json({ features: features });
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,8 @@
 | 
			
		||||
var knex = require('../db/dbPool');
 | 
			
		||||
var logger = require('../logger');
 | 
			
		||||
 | 
			
		||||
module.exports = function (app) {
 | 
			
		||||
module.exports = function (app, config) {
 | 
			
		||||
    app.get('/health', function (req, res) {
 | 
			
		||||
        knex.select(1)
 | 
			
		||||
        config.db.select(1)
 | 
			
		||||
            .from('features')
 | 
			
		||||
            .then(function() {
 | 
			
		||||
                res.json({ health: 'GOOD' });
 | 
			
		||||
 | 
			
		||||
@ -2,10 +2,10 @@
 | 
			
		||||
 * TODO: we should also inject config and
 | 
			
		||||
 * services to the routes to ease testing.
 | 
			
		||||
**/
 | 
			
		||||
exports.create = function (app) {
 | 
			
		||||
    require('./event')(app);
 | 
			
		||||
    require('./feature')(app);
 | 
			
		||||
    require('./feature-archive')(app);
 | 
			
		||||
    require('./strategy')(app);
 | 
			
		||||
    require('./health-check')(app);
 | 
			
		||||
exports.create = function (app, config) {
 | 
			
		||||
    require('./event')(app, config);
 | 
			
		||||
    require('./feature')(app, config);
 | 
			
		||||
    require('./feature-archive')(app, config);
 | 
			
		||||
    require('./strategy')(app, config);
 | 
			
		||||
    require('./health-check')(app, config);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,5 @@
 | 
			
		||||
var Promise             = require("bluebird");
 | 
			
		||||
var eventStore          = require('../eventStore');
 | 
			
		||||
var eventType           = require('../eventType');
 | 
			
		||||
var strategyDb          = require('../db/strategy');
 | 
			
		||||
var logger              = require('../logger');
 | 
			
		||||
var NameExistsError     = require('../error/NameExistsError');
 | 
			
		||||
var ValidationError     = require('../error/ValidationError');
 | 
			
		||||
@ -9,7 +7,10 @@ var NotFoundError       = require('../error/NotFoundError');
 | 
			
		||||
var validateRequest     = require('../error/validateRequest');
 | 
			
		||||
var extractUser         = require('../extractUser');
 | 
			
		||||
 | 
			
		||||
module.exports = function (app) {
 | 
			
		||||
module.exports = function (app, config) {
 | 
			
		||||
    var strategyDb = config.strategyDb;
 | 
			
		||||
    var eventStore = config.eventStore;
 | 
			
		||||
 | 
			
		||||
    app.get('/strategies', function (req, res) {
 | 
			
		||||
        strategyDb.getStrategies().then(function (strategies) {
 | 
			
		||||
            res.json({ strategies: strategies });
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								server.js
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								server.js
									
									
									
									
									
								
							@ -1,8 +1,22 @@
 | 
			
		||||
var logger = require('./lib/logger');
 | 
			
		||||
var databaseUri = require('./lib/databaseConfig').getDatabaseUrl();
 | 
			
		||||
 | 
			
		||||
// Database dependecies (statefull)
 | 
			
		||||
var db = require('./lib/db/dbPool')(databaseUri);
 | 
			
		||||
var eventDb = require('./lib/db/event')(db);
 | 
			
		||||
var EventStore = require('./lib/eventStore');
 | 
			
		||||
var eventStore = new EventStore(eventDb);
 | 
			
		||||
var featureDb = require('./lib/db/feature')(db, eventStore);
 | 
			
		||||
var strategyDb = require('./lib/db/strategy')(db, eventStore);
 | 
			
		||||
 | 
			
		||||
var config = {
 | 
			
		||||
    baseUriPath: process.env.BASE_URI_PATH || '',
 | 
			
		||||
    port: process.env.HTTP_PORT || process.env.PORT || 4242
 | 
			
		||||
    port: process.env.HTTP_PORT || process.env.PORT || 4242,
 | 
			
		||||
    db: db,
 | 
			
		||||
    eventDb: eventDb,
 | 
			
		||||
    eventStore: eventStore,
 | 
			
		||||
    featureDb: featureDb,
 | 
			
		||||
    strategyDb: strategyDb
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var app = require('./app')(config);
 | 
			
		||||
@ -25,7 +39,6 @@ if (app.get('env') === 'development') {
 | 
			
		||||
    }));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
process.on('uncaughtException', function(err) {
 | 
			
		||||
    logger.error('Uncaught Exception:', err.message);
 | 
			
		||||
    logger.error(err.stack);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								test/databaseConfig.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								test/databaseConfig.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
function getDatabaseUri() {
 | 
			
		||||
    if (!process.env.TEST_DATABASE_URL) {
 | 
			
		||||
        throw new Error('please set TEST_DATABASE_URL');
 | 
			
		||||
    } else {
 | 
			
		||||
        return process.env.TEST_DATABASE_URL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
module.exports = {
 | 
			
		||||
    getDatabaseUri: getDatabaseUri
 | 
			
		||||
};
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
'use strict';
 | 
			
		||||
var logger = require('../lib/logger');
 | 
			
		||||
var assert     = require('assert');
 | 
			
		||||
var specHelper = require('./specHelper');
 | 
			
		||||
var request    = specHelper.request;
 | 
			
		||||
@ -32,6 +33,7 @@ describe('The features api', function () {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('cant get feature that dose not exist', function (done) {
 | 
			
		||||
        logger.setLevel('FATAL');
 | 
			
		||||
        request
 | 
			
		||||
            .get('/features/myfeature')
 | 
			
		||||
            .expect('Content-Type', /json/)
 | 
			
		||||
@ -47,6 +49,7 @@ describe('The features api', function () {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('creates new feature toggle with createdBy', function (done) {
 | 
			
		||||
        logger.setLevel('FATAL');
 | 
			
		||||
        request
 | 
			
		||||
            .post('/features')
 | 
			
		||||
            .send({ name: 'com.test.Username', enabled: false })
 | 
			
		||||
@ -63,6 +66,7 @@ describe('The features api', function () {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('require new feature toggle to have a name', function (done) {
 | 
			
		||||
        logger.setLevel('FATAL');
 | 
			
		||||
        request
 | 
			
		||||
            .post('/features')
 | 
			
		||||
            .send({ name: '' })
 | 
			
		||||
@ -71,6 +75,7 @@ describe('The features api', function () {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('can not change status of feature toggle that does not exist', function (done) {
 | 
			
		||||
        logger.setLevel('FATAL');
 | 
			
		||||
        request
 | 
			
		||||
            .put('/features/should-not-exist')
 | 
			
		||||
            .send({ name: 'should-not-exist', enabled: false })
 | 
			
		||||
@ -79,6 +84,7 @@ describe('The features api', function () {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('can change status of feature toggle that does exist', function (done) {
 | 
			
		||||
        logger.setLevel('FATAL');
 | 
			
		||||
        request
 | 
			
		||||
            .put('/features/featureY')
 | 
			
		||||
            .send({ name: 'featureY', enabled: true })
 | 
			
		||||
 | 
			
		||||
@ -3,10 +3,22 @@ process.env.NODE_ENV = 'test';
 | 
			
		||||
 | 
			
		||||
var Promise = require('bluebird');
 | 
			
		||||
var request = require('supertest');
 | 
			
		||||
var app = require('../app')({ baseUriPath: '' });
 | 
			
		||||
var knex = require('../lib/db/dbPool');
 | 
			
		||||
var featureDb = require('../lib/db/feature');
 | 
			
		||||
var strategyDb = require('../lib/db/strategy');
 | 
			
		||||
var databaseUri = require('./databaseConfig').getDatabaseUri();
 | 
			
		||||
var knex = require('../lib/db/dbPool')(databaseUri);
 | 
			
		||||
var eventDb = require('../lib/db/event')(knex);
 | 
			
		||||
var EventStore = require('../lib/eventStore');
 | 
			
		||||
var eventStore = new EventStore(eventDb);
 | 
			
		||||
var featureDb = require('../lib/db/feature')(knex, eventStore);
 | 
			
		||||
var strategyDb = require('../lib/db/strategy')(knex, eventStore);
 | 
			
		||||
 | 
			
		||||
var app = require('../app')({
 | 
			
		||||
    baseUriPath: '',
 | 
			
		||||
    db: knex,
 | 
			
		||||
    eventDb: eventDb,
 | 
			
		||||
    eventStore: eventStore,
 | 
			
		||||
    featureDb: featureDb,
 | 
			
		||||
    strategyDb: strategyDb
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Promise.promisifyAll(request);
 | 
			
		||||
request = request(app);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user