mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-04 00:18:01 +01:00
client applications
This commit is contained in:
parent
baf2c62f25
commit
80d3f5be1c
@ -54,7 +54,7 @@ module.exports = class UnleashClientMetrics {
|
|||||||
if (!toggles[seenToggleName]) {
|
if (!toggles[seenToggleName]) {
|
||||||
toggles[seenToggleName] = [];
|
toggles[seenToggleName] = [];
|
||||||
}
|
}
|
||||||
toggles[seenToggleName].push(appName);
|
toggles[seenToggleName].push({ appName });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return toggles;
|
return toggles;
|
||||||
|
74
lib/db/client-applications-store.js
Normal file
74
lib/db/client-applications-store.js
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const COLUMNS = ['app_name', 'created_at', 'updated_at', 'description', 'url', 'color', 'icon'];
|
||||||
|
const TABLE = 'client_applications';
|
||||||
|
|
||||||
|
const mapRow = (row) => ({
|
||||||
|
appName: row.app_name,
|
||||||
|
createdAt: row.created_at,
|
||||||
|
updatedAt: row.updated_at,
|
||||||
|
description: row.description,
|
||||||
|
url: row.url,
|
||||||
|
color: row.color,
|
||||||
|
icon: row.icon,
|
||||||
|
});
|
||||||
|
|
||||||
|
const remapRow = (input, old = {}) => ({
|
||||||
|
app_name: input.appName,
|
||||||
|
updated_at: input.updatedAt,
|
||||||
|
description: input.description || old.description,
|
||||||
|
url: input.url || old.url,
|
||||||
|
color: input.color || old.color,
|
||||||
|
icon: input.icon || old.icon,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
class ClientApplicationsDb {
|
||||||
|
constructor (db) {
|
||||||
|
this.db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRow (details, prev) {
|
||||||
|
details.updatedAt = 'now()';
|
||||||
|
return this.db(TABLE)
|
||||||
|
.where('app_name', details.appName)
|
||||||
|
.update(remapRow(details, prev));
|
||||||
|
}
|
||||||
|
|
||||||
|
insertNewRow (details) {
|
||||||
|
return this.db(TABLE).insert(remapRow(details));
|
||||||
|
}
|
||||||
|
|
||||||
|
upsert (data) {
|
||||||
|
if (!data) {
|
||||||
|
throw new Error('Missing data to add / update');
|
||||||
|
}
|
||||||
|
return this.db(TABLE)
|
||||||
|
.select(COLUMNS)
|
||||||
|
.where('app_name', data.appName)
|
||||||
|
.then(result => {
|
||||||
|
if (result && result[0]) {
|
||||||
|
return this.updateRow(data, result[0]);
|
||||||
|
} else {
|
||||||
|
return this.insertNewRow(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getApplicationMetaData (appName) {
|
||||||
|
if (appName) {
|
||||||
|
return this.db
|
||||||
|
.select(COLUMNS)
|
||||||
|
.where('app_name', appName)
|
||||||
|
.from(TABLE)
|
||||||
|
.map(mapRow);
|
||||||
|
}
|
||||||
|
return this.db
|
||||||
|
.select(COLUMNS)
|
||||||
|
.from(TABLE)
|
||||||
|
.orderBy('created_at', 'asc')
|
||||||
|
.map(mapRow);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = ClientApplicationsDb;
|
@ -8,6 +8,7 @@ const ClientInstanceStore = require('./client-instance-store');
|
|||||||
const ClientMetricsDb = require('./client-metrics-db');
|
const ClientMetricsDb = require('./client-metrics-db');
|
||||||
const ClientMetricsStore = require('./client-metrics-store');
|
const ClientMetricsStore = require('./client-metrics-store');
|
||||||
const ClientStrategyStore = require('./client-strategy-store');
|
const ClientStrategyStore = require('./client-strategy-store');
|
||||||
|
const ClientApplicationsStore = require('./client-applications-store');
|
||||||
|
|
||||||
module.exports.createStores = (config) => {
|
module.exports.createStores = (config) => {
|
||||||
const db = createDb(config);
|
const db = createDb(config);
|
||||||
@ -19,6 +20,7 @@ module.exports.createStores = (config) => {
|
|||||||
eventStore,
|
eventStore,
|
||||||
featureToggleStore: new FeatureToggleStore(db, eventStore),
|
featureToggleStore: new FeatureToggleStore(db, eventStore),
|
||||||
strategyStore: new StrategyStore(db, eventStore),
|
strategyStore: new StrategyStore(db, eventStore),
|
||||||
|
clientApplicationsStore: new ClientApplicationsStore(db),
|
||||||
clientInstanceStore: new ClientInstanceStore(db),
|
clientInstanceStore: new ClientInstanceStore(db),
|
||||||
clientMetricsStore: new ClientMetricsStore(clientMetricsDb),
|
clientMetricsStore: new ClientMetricsStore(clientMetricsDb),
|
||||||
clientStrategyStore: new ClientStrategyStore(db),
|
clientStrategyStore: new ClientStrategyStore(db),
|
||||||
|
@ -11,6 +11,7 @@ module.exports = function (app, config) {
|
|||||||
clientMetricsStore,
|
clientMetricsStore,
|
||||||
clientStrategyStore,
|
clientStrategyStore,
|
||||||
clientInstanceStore,
|
clientInstanceStore,
|
||||||
|
clientApplicationsStore,
|
||||||
} = config.stores;
|
} = config.stores;
|
||||||
|
|
||||||
const metrics = new ClientMetrics(clientMetricsStore);
|
const metrics = new ClientMetrics(clientMetricsStore);
|
||||||
@ -22,7 +23,19 @@ module.exports = function (app, config) {
|
|||||||
|
|
||||||
app.get('/client/seen-apps', (req, res) => {
|
app.get('/client/seen-apps', (req, res) => {
|
||||||
const seenApps = metrics.getSeenAppsPerToggle();
|
const seenApps = metrics.getSeenAppsPerToggle();
|
||||||
res.json(seenApps);
|
clientApplicationsStore.getApplicationMetaData()
|
||||||
|
.then(toLookup)
|
||||||
|
.then(metaData => {
|
||||||
|
Object.keys(seenApps).forEach(key => {
|
||||||
|
seenApps[key] = seenApps[key].map(entry => {
|
||||||
|
if (metaData[entry.appName]) {
|
||||||
|
entry.data = metaData[entry.appName];
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
res.json(seenApps);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/client/metrics/feature-toggles', (req, res) => {
|
app.get('/client/metrics/feature-toggles', (req, res) => {
|
||||||
@ -99,27 +112,43 @@ module.exports = function (app, config) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.post('/client/applications/:appName', (req, res) => {
|
||||||
|
const input = Object.assign({}, req.body, {
|
||||||
|
appName: req.params.appName,
|
||||||
|
});
|
||||||
|
clientApplicationsStore
|
||||||
|
.upsert(input)
|
||||||
|
.then(() => res.status(202).end())
|
||||||
|
.catch((e) => {
|
||||||
|
logger.error(e);
|
||||||
|
res.status(500).end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function toLookup (metaData) {
|
||||||
|
return metaData.reduce((result, entry) => {
|
||||||
|
result[entry.appName] = entry;
|
||||||
|
return result;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
app.get('/client/applications/', (req, res) => {
|
app.get('/client/applications/', (req, res) => {
|
||||||
const strategyName = req.query.strategyName;
|
const strategyName = req.query.strategyName;
|
||||||
let appsPromise;
|
Promise.all([
|
||||||
|
strategyName ? clientStrategyStore.getAppsForStrategy(strategyName) : clientStrategyStore.getApplications(),
|
||||||
if (strategyName) {
|
clientApplicationsStore.getApplicationMetaData().then(toLookup),
|
||||||
appsPromise = clientStrategyStore.getAppsForStrategy(strategyName);
|
])
|
||||||
} else {
|
.then(([apps, metaData]) => {
|
||||||
appsPromise = clientStrategyStore.getApplications();
|
const applications = apps.map(({ appName }) => ({
|
||||||
}
|
appName,
|
||||||
|
data: metaData[appName],
|
||||||
appsPromise
|
links: {
|
||||||
.then(apps => {
|
appDetails: `/api/client/applications/${appName}`,
|
||||||
const applications = apps.map(appName => ({
|
},
|
||||||
appName,
|
}));
|
||||||
links: {
|
res.json({ applications });
|
||||||
appDetails: `/api/client/applications/${appName}`,
|
})
|
||||||
},
|
.catch(err => catchLogAndSendErrorResponse(err, res));
|
||||||
}));
|
|
||||||
res.json({ applications });
|
|
||||||
})
|
|
||||||
.catch(err => catchLogAndSendErrorResponse(err, res));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/client/applications/:appName', (req, res) => {
|
app.get('/client/applications/:appName', (req, res) => {
|
||||||
@ -128,8 +157,11 @@ module.exports = function (app, config) {
|
|||||||
Promise.all([
|
Promise.all([
|
||||||
clientInstanceStore.getByAppName(appName),
|
clientInstanceStore.getByAppName(appName),
|
||||||
clientStrategyStore.getByAppName(appName),
|
clientStrategyStore.getByAppName(appName),
|
||||||
|
clientApplicationsStore.getApplicationMetaData(appName),
|
||||||
])
|
])
|
||||||
.then(([instances, strategies]) => res.json({ appName, instances, strategies, seenToggles }))
|
.then(([instances, strategies, [metaData]]) =>
|
||||||
|
res.json({ appName, instances, strategies, seenToggles, data: metaData })
|
||||||
|
)
|
||||||
.catch(err => catchLogAndSendErrorResponse(err, res));
|
.catch(err => catchLogAndSendErrorResponse(err, res));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
3
migrations/20161205203516-create-client-applications.js
Normal file
3
migrations/20161205203516-create-client-applications.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = require('../scripts/migration-runner').create('011-create-client-applications');
|
1
migrations/sql/011-create-client-applications.down.sql
Normal file
1
migrations/sql/011-create-client-applications.down.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
DROP TABLE client_applications;
|
9
migrations/sql/011-create-client-applications.up.sql
Normal file
9
migrations/sql/011-create-client-applications.up.sql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
CREATE TABLE client_applications (
|
||||||
|
app_name varchar(255) PRIMARY KEY NOT NULL,
|
||||||
|
created_at timestamp default now(),
|
||||||
|
updated_at timestamp default now(),
|
||||||
|
description varchar(255),
|
||||||
|
icon varchar(255),
|
||||||
|
url varchar(255),
|
||||||
|
color varchar(255)
|
||||||
|
);
|
Loading…
Reference in New Issue
Block a user