mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-28 00:17:12 +01:00
fix: use airbnb lint rules directly (#583)
This drops usage of finn-eslint rules as they are no longer maintained.
This commit is contained in:
parent
42da450a86
commit
d01c9d2dac
21
.eslintrc
21
.eslintrc
@ -1,13 +1,20 @@
|
||||
{
|
||||
"extends": [
|
||||
"finn",
|
||||
"finn/node",
|
||||
"finn-prettier"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "2017"
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": ["airbnb-base", "prettier"],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "2018"
|
||||
},
|
||||
"plugins": ["prettier"],
|
||||
"root": true,
|
||||
"rules": {
|
||||
"class-methods-use-this": [0],
|
||||
"prettier/prettier": ["error"],
|
||||
"func-names": "off",
|
||||
"strict": [0, "global"],
|
||||
"no-underscore-dangle": "off",
|
||||
"no-plusplus": "off",
|
||||
"no-param-reassign": "error",
|
||||
"no-return-await": "error",
|
||||
"max-nested-callbacks": "off",
|
||||
|
@ -1,12 +1,12 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict';
|
||||
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
const serverImpl = require('../lib/server-impl.js');
|
||||
const fs = require('fs');
|
||||
|
||||
const argv = require('yargs')
|
||||
const { argv } = require('yargs')
|
||||
.usage('$0 [options]')
|
||||
.env(true)
|
||||
.option('port', {
|
||||
@ -43,7 +43,9 @@ const argv = require('yargs')
|
||||
default: 'public',
|
||||
demand: false,
|
||||
type: 'string',
|
||||
}).argv;
|
||||
});
|
||||
|
||||
const serverImpl = require('../lib/server-impl.js');
|
||||
|
||||
if (argv.databaseUrlFile) {
|
||||
argv.databaseUrl = fs.readFileSync(argv.databaseUrlFile, 'utf8');
|
||||
@ -54,8 +56,10 @@ serverImpl
|
||||
.start(argv)
|
||||
.then(instance => {
|
||||
const address = instance.server.address();
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
`Unleash started on http://${address.address}:${address.port}`
|
||||
`Unleash started on http://${address.address}:${address.port}`,
|
||||
);
|
||||
})
|
||||
// eslint-disable-next-line no-console
|
||||
.catch(console.err);
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* eslint-disable import/no-unresolved */
|
||||
|
||||
'use strict';
|
||||
|
||||
const auth = require('basic-auth');
|
||||
@ -11,13 +13,13 @@ function basicAuthentication(app) {
|
||||
// you will need to do some verification of credentials here.
|
||||
const user = new User({ email: `${credentials.name}@domain.com` });
|
||||
req.user = user;
|
||||
next();
|
||||
} else {
|
||||
return res
|
||||
.status('401')
|
||||
.set({ 'WWW-Authenticate': 'Basic realm="example"' })
|
||||
.end('access denied');
|
||||
return next();
|
||||
}
|
||||
|
||||
return res
|
||||
.status('401')
|
||||
.set({ 'WWW-Authenticate': 'Basic realm="example"' })
|
||||
.end('access denied');
|
||||
});
|
||||
|
||||
app.use((req, res, next) => {
|
||||
|
@ -12,7 +12,8 @@ unleash
|
||||
preRouterHook: basicAuth,
|
||||
})
|
||||
.then(server => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
`Unleash started on http://localhost:${server.app.get('port')}`
|
||||
`Unleash started on http://localhost:${server.app.get('port')}`,
|
||||
);
|
||||
});
|
||||
|
@ -21,7 +21,8 @@ unleash
|
||||
},
|
||||
})
|
||||
.then(server => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
`Unleash started on http://localhost:${server.app.get('port')}`
|
||||
`Unleash started on http://localhost:${server.app.get('port')}`,
|
||||
);
|
||||
});
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
@ -17,13 +19,13 @@
|
||||
* - GOOGLE_CALLBACK_URL
|
||||
*/
|
||||
|
||||
// const { User, AuthenticationRequired } = require('unleash-server');
|
||||
const { User, AuthenticationRequired } = require('../lib/server-impl.js');
|
||||
|
||||
const passport = require('@passport-next/passport');
|
||||
const GoogleOAuth2Strategy = require('@passport-next/passport-google-oauth2')
|
||||
.Strategy;
|
||||
|
||||
// const { User, AuthenticationRequired } = require('unleash-server');
|
||||
const { User, AuthenticationRequired } = require('../lib/server-impl.js');
|
||||
|
||||
passport.use(
|
||||
new GoogleOAuth2Strategy(
|
||||
{
|
||||
@ -38,10 +40,10 @@ passport.use(
|
||||
new User({
|
||||
name: profile.displayName,
|
||||
email: profile.emails[0].value,
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
function enableGoogleOauth(app) {
|
||||
@ -52,7 +54,7 @@ function enableGoogleOauth(app) {
|
||||
passport.deserializeUser((user, done) => done(null, user));
|
||||
app.get(
|
||||
'/api/admin/login',
|
||||
passport.authenticate('google', { scope: ['email'] })
|
||||
passport.authenticate('google', { scope: ['email'] }),
|
||||
);
|
||||
|
||||
app.get(
|
||||
@ -63,26 +65,25 @@ function enableGoogleOauth(app) {
|
||||
(req, res) => {
|
||||
// Successful authentication, redirect to your app.
|
||||
res.redirect('/');
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
app.use('/api/admin/', (req, res, next) => {
|
||||
if (req.user) {
|
||||
next();
|
||||
} else {
|
||||
// Instruct unleash-frontend to pop-up auth dialog
|
||||
return res
|
||||
.status('401')
|
||||
.json(
|
||||
new AuthenticationRequired({
|
||||
path: '/api/admin/login',
|
||||
type: 'custom',
|
||||
message: `You have to identify yourself in order to use Unleash.
|
||||
Click the button and follow the instructions.`,
|
||||
})
|
||||
)
|
||||
.end();
|
||||
return next();
|
||||
}
|
||||
// Instruct unleash-frontend to pop-up auth dialog
|
||||
return res
|
||||
.status('401')
|
||||
.json(
|
||||
new AuthenticationRequired({
|
||||
path: '/api/admin/login',
|
||||
type: 'custom',
|
||||
message: `You have to identify yourself in order to use Unleash.
|
||||
Click the button and follow the instructions.`,
|
||||
}),
|
||||
)
|
||||
.end();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,8 @@ unleash
|
||||
preRouterHook: enableGoogleOauth,
|
||||
})
|
||||
.then(server => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
`Unleash started on http://localhost:${server.app.get('port')}`
|
||||
`Unleash started on http://localhost:${server.app.get('port')}`,
|
||||
);
|
||||
});
|
||||
|
@ -1,3 +1,6 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
/* eslint-disable import/no-unresolved */
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
@ -14,12 +17,12 @@
|
||||
* - AUTH_CLIENT_ID
|
||||
*/
|
||||
|
||||
// const { User, AuthenticationRequired } = require('unleash-server');
|
||||
const { User, AuthenticationRequired } = require('../lib/server-impl.js');
|
||||
|
||||
const KeycloakStrategy = require('@exlinc/keycloak-passport');
|
||||
const passport = require('passport');
|
||||
|
||||
// const { User, AuthenticationRequired } = require('unleash-server');
|
||||
const { User, AuthenticationRequired } = require('../lib/server-impl.js');
|
||||
|
||||
const host = process.env.AUTH_HOST;
|
||||
const realm = process.env.AUTH_REALM;
|
||||
const clientID = process.env.AUTH_CLIENT_ID;
|
||||
@ -45,10 +48,10 @@ passport.use(
|
||||
new User({
|
||||
name: profile.fullName,
|
||||
email: profile.email,
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
function enableKeycloakOauth(app) {
|
||||
@ -65,26 +68,25 @@ function enableKeycloakOauth(app) {
|
||||
passport.authenticate('keycloak'),
|
||||
(req, res) => {
|
||||
res.redirect(`${contextPath}/`);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
app.use('/api/admin/', (req, res, next) => {
|
||||
if (req.user) {
|
||||
next();
|
||||
} else {
|
||||
// Instruct unleash-frontend to pop-up auth dialog
|
||||
return res
|
||||
.status('401')
|
||||
.json(
|
||||
new AuthenticationRequired({
|
||||
path: `${contextPath}/api/admin/login`,
|
||||
type: 'custom',
|
||||
message: `You have to identify yourself in order to use Unleash.
|
||||
Click the button and follow the instructions.`,
|
||||
})
|
||||
)
|
||||
.end();
|
||||
return next();
|
||||
}
|
||||
// Instruct unleash-frontend to pop-up auth dialog
|
||||
return res
|
||||
.status('401')
|
||||
.json(
|
||||
new AuthenticationRequired({
|
||||
path: `${contextPath}/api/admin/login`,
|
||||
type: 'custom',
|
||||
message: `You have to identify yourself in order to use Unleash.
|
||||
Click the button and follow the instructions.`,
|
||||
}),
|
||||
)
|
||||
.end();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,8 @@ unleash
|
||||
preRouterHook: enableKeycloak,
|
||||
})
|
||||
.then(server => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
`Unleash started on http://localhost:${server.app.get('port')}`
|
||||
`Unleash started on http://localhost:${server.app.get('port')}`,
|
||||
);
|
||||
});
|
||||
|
@ -4,9 +4,9 @@ const express = require('express');
|
||||
const compression = require('compression');
|
||||
const favicon = require('serve-favicon');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const IndexRouter = require('./routes');
|
||||
const path = require('path');
|
||||
const errorHandler = require('errorhandler');
|
||||
const IndexRouter = require('./routes');
|
||||
const unleashSession = require('./middleware/session');
|
||||
const responseTime = require('./middleware/response-time');
|
||||
const requestLogger = require('./middleware/request-logger');
|
||||
|
@ -4,6 +4,7 @@ const test = require('ava');
|
||||
const express = require('express');
|
||||
const proxyquire = require('proxyquire');
|
||||
const getLogger = require('../test/fixtures/no-logger');
|
||||
|
||||
const getApp = proxyquire('./app', {
|
||||
'./routes': class Index {
|
||||
router() {
|
||||
|
@ -1,11 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const UnleashClientMetrics = require('./index');
|
||||
const moment = require('moment');
|
||||
const lolex = require('lolex');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const UnleashClientMetrics = require('./index');
|
||||
|
||||
const appName = 'appName';
|
||||
const instanceId = 'instanceId';
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
|
||||
'use strict';
|
||||
|
||||
const Projection = require('./projection.js');
|
||||
@ -25,7 +27,7 @@ module.exports = class UnleashClientMetrics {
|
||||
Object.keys(toggles).forEach(toggleName => {
|
||||
this.lastHourProjection.substract(
|
||||
toggleName,
|
||||
this.createCountObject(toggles[toggleName])
|
||||
this.createCountObject(toggles[toggleName]),
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -33,7 +35,7 @@ module.exports = class UnleashClientMetrics {
|
||||
Object.keys(toggles).forEach(toggleName => {
|
||||
this.lastMinuteProjection.substract(
|
||||
toggleName,
|
||||
this.createCountObject(toggles[toggleName])
|
||||
this.createCountObject(toggles[toggleName]),
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -49,6 +51,7 @@ module.exports = class UnleashClientMetrics {
|
||||
});
|
||||
return apps;
|
||||
}
|
||||
|
||||
getSeenTogglesByAppName(appName) {
|
||||
return this.apps[appName]
|
||||
? Object.keys(this.apps[appName].seenToggles)
|
||||
@ -64,7 +67,7 @@ module.exports = class UnleashClientMetrics {
|
||||
toggles[seenToggleName] = [];
|
||||
}
|
||||
toggles[seenToggleName].push({ appName });
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
return toggles;
|
||||
@ -92,8 +95,8 @@ module.exports = class UnleashClientMetrics {
|
||||
}
|
||||
|
||||
createCountObject(entry) {
|
||||
let yes = typeof entry.yes == 'number' ? entry.yes : 0;
|
||||
let no = typeof entry.no == 'number' ? entry.no : 0;
|
||||
let yes = typeof entry.yes === 'number' ? entry.yes : 0;
|
||||
let no = typeof entry.no === 'number' ? entry.no : 0;
|
||||
|
||||
if (entry.variants) {
|
||||
Object.entries(entry.variants).forEach(([key, value]) => {
|
||||
|
@ -1,3 +1,6 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
/* eslint-disable max-classes-per-file */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
|
@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const List = require('./list');
|
||||
const moment = require('moment');
|
||||
const List = require('./list');
|
||||
|
||||
// this list must have entries with sorted ttl range
|
||||
module.exports = class TTLList extends EventEmitter {
|
||||
@ -47,7 +47,7 @@ module.exports = class TTLList extends EventEmitter {
|
||||
timedCheck() {
|
||||
const now = moment();
|
||||
this.list.reverseRemoveUntilTrue(({ value }) =>
|
||||
now.isBefore(value.ttl)
|
||||
now.isBefore(value.ttl),
|
||||
);
|
||||
this.startTimer();
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const TTLList = require('./ttl-list');
|
||||
const moment = require('moment');
|
||||
const lolex = require('lolex');
|
||||
const TTLList = require('./ttl-list');
|
||||
|
||||
test.cb('should emit expire', t => {
|
||||
const clock = lolex.install();
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* eslint camelcase:off */
|
||||
|
||||
'use strict';
|
||||
|
||||
const metricsHelper = require('../metrics-helper');
|
||||
@ -44,6 +45,7 @@ class ClientApplicationsDb {
|
||||
}
|
||||
|
||||
updateRow(details, prev) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
details.updatedAt = 'now()';
|
||||
return this.db(TABLE)
|
||||
.where('app_name', details.appName)
|
||||
@ -52,7 +54,7 @@ class ClientApplicationsDb {
|
||||
metricsHelper.wrapTimer(this.eventBus, DB_TIME, {
|
||||
store: 'applications',
|
||||
action: 'updateRow',
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@ -70,15 +72,14 @@ class ClientApplicationsDb {
|
||||
.then(result => {
|
||||
if (result && result[0]) {
|
||||
return this.updateRow(data, result[0]);
|
||||
} else {
|
||||
return this.insertNewRow(data);
|
||||
}
|
||||
return this.insertNewRow(data);
|
||||
})
|
||||
.then(
|
||||
metricsHelper.wrapTimer(this.eventBus, DB_TIME, {
|
||||
store: 'applications',
|
||||
action: 'upsert',
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@ -92,7 +93,7 @@ class ClientApplicationsDb {
|
||||
metricsHelper.wrapTimer(this.eventBus, DB_TIME, {
|
||||
store: 'applications',
|
||||
action: 'getAll',
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@ -120,7 +121,7 @@ class ClientApplicationsDb {
|
||||
.from(TABLE)
|
||||
.map(mapRow)
|
||||
.then(apps =>
|
||||
apps.filter(app => app.strategies.includes(strategyName))
|
||||
apps.filter(app => app.strategies.includes(strategyName)),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* eslint camelcase: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
const metricsHelper = require('../metrics-helper');
|
||||
@ -40,7 +41,7 @@ class ClientInstanceStore {
|
||||
.whereRaw("created_at < now() - interval '2 days'")
|
||||
.del()
|
||||
.then(
|
||||
res => res > 0 && this.logger.info(`Deleted ${res} instances`)
|
||||
res => res > 0 && this.logger.info(`Deleted ${res} instances`),
|
||||
);
|
||||
}
|
||||
|
||||
@ -73,15 +74,14 @@ class ClientInstanceStore {
|
||||
.then(rows => {
|
||||
if (rows[0].count > 0) {
|
||||
return this.updateRow(details);
|
||||
} else {
|
||||
return this.insertNewRow(details);
|
||||
}
|
||||
return this.insertNewRow(details);
|
||||
})
|
||||
.then(
|
||||
metricsHelper.wrapTimer(this.eventBus, DB_TIME, {
|
||||
store: 'instance',
|
||||
action: 'insert',
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@ class ClientInstanceStore {
|
||||
metricsHelper.wrapTimer(this.eventBus, DB_TIME, {
|
||||
store: 'instance',
|
||||
action: 'getAll',
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ class ClientMetricsStore extends EventEmitter {
|
||||
metricsHelper.wrapTimer(this.eventBus, DB_TIME, {
|
||||
store: 'metrics',
|
||||
action: 'insert',
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
const test = require('ava');
|
||||
const { EventEmitter } = require('events');
|
||||
const ClientMetricStore = require('./client-metrics-store');
|
||||
const lolex = require('lolex');
|
||||
const ClientMetricStore = require('./client-metrics-store');
|
||||
const getLogger = require('../../test/fixtures/no-logger');
|
||||
|
||||
function getMockDb() {
|
||||
@ -42,7 +42,7 @@ test.cb('should call database on startup', t => {
|
||||
test.cb('should start poller even if inital database fetch fails', t => {
|
||||
const clock = lolex.install();
|
||||
const mock = getMockDb();
|
||||
mock.getMetricsLastHour = () => Promise.reject('oops');
|
||||
mock.getMetricsLastHour = () => Promise.reject(new Error('oops'));
|
||||
const ee = new EventEmitter();
|
||||
const store = new ClientMetricStore(mock, ee, getLogger, 100);
|
||||
|
||||
|
@ -30,10 +30,10 @@ class ContextFieldStore {
|
||||
this._createFromConfig(customContextFields);
|
||||
|
||||
eventStore.on(CONTEXT_FIELD_CREATED, event =>
|
||||
this._createContextField(event.data)
|
||||
this._createContextField(event.data),
|
||||
);
|
||||
eventStore.on(CONTEXT_FIELD_UPDATED, event =>
|
||||
this._updateContextField(event.data)
|
||||
this._updateContextField(event.data),
|
||||
);
|
||||
eventStore.on(CONTEXT_FIELD_DELETED, event => {
|
||||
this._deleteContextField(event.data);
|
||||
@ -44,7 +44,7 @@ class ContextFieldStore {
|
||||
if (customContextFields) {
|
||||
this.logger.info(
|
||||
'Create custom context fields',
|
||||
customContextFields
|
||||
customContextFields,
|
||||
);
|
||||
const conextFields = await this.getAll();
|
||||
customContextFields
|
||||
@ -86,11 +86,13 @@ class ContextFieldStore {
|
||||
}
|
||||
|
||||
_createContextField(contextField) {
|
||||
console.log('insert', contextField);
|
||||
return this.db(TABLE)
|
||||
.insert(this.fieldToRow(contextField))
|
||||
.catch(err =>
|
||||
this.logger.error('Could not insert contextField, error: ', err)
|
||||
this.logger.error(
|
||||
'Could not insert contextField, error: ',
|
||||
err,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -101,8 +103,8 @@ class ContextFieldStore {
|
||||
.catch(err =>
|
||||
this.logger.error(
|
||||
'Could not update context field, error: ',
|
||||
err
|
||||
)
|
||||
err,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -113,7 +115,7 @@ class ContextFieldStore {
|
||||
.catch(err => {
|
||||
this.logger.error(
|
||||
'Could not delete context field, error: ',
|
||||
err
|
||||
err,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { DROP_FEATURES } = require('../event-type');
|
||||
const { EventEmitter } = require('events');
|
||||
const { DROP_FEATURES } = require('../event-type');
|
||||
|
||||
const EVENT_COLUMNS = ['id', 'type', 'created_by', 'created_at', 'data'];
|
||||
|
||||
@ -42,7 +42,7 @@ class EventStore extends EventEmitter {
|
||||
this.db
|
||||
.select(this.db.raw('coalesce(max(id),0) as id'))
|
||||
.from('events')
|
||||
.where({ type: DROP_FEATURES })
|
||||
.where({ type: DROP_FEATURES }),
|
||||
)
|
||||
.orderBy('created_at', 'desc')
|
||||
.map(this.rowToEvent);
|
||||
|
@ -9,6 +9,7 @@ const {
|
||||
DROP_FEATURES,
|
||||
} = require('../event-type');
|
||||
const NotFoundError = require('../error/notfound-error');
|
||||
|
||||
const FEATURE_COLUMNS = [
|
||||
'name',
|
||||
'description',
|
||||
@ -24,16 +25,16 @@ class FeatureToggleStore {
|
||||
this.db = db;
|
||||
this.getLogger = getLogger('client-toggle-store.js');
|
||||
eventStore.on(FEATURE_CREATED, event =>
|
||||
this._createFeature(event.data)
|
||||
this._createFeature(event.data),
|
||||
);
|
||||
eventStore.on(FEATURE_UPDATED, event =>
|
||||
this._updateFeature(event.data)
|
||||
this._updateFeature(event.data),
|
||||
);
|
||||
eventStore.on(FEATURE_ARCHIVED, event =>
|
||||
this._archiveFeature(event.data)
|
||||
this._archiveFeature(event.data),
|
||||
);
|
||||
eventStore.on(FEATURE_REVIVED, event =>
|
||||
this._reviveFeature(event.data)
|
||||
this._reviveFeature(event.data),
|
||||
);
|
||||
eventStore.on(FEATURE_IMPORT, event => this._importFeature(event.data));
|
||||
eventStore.on(DROP_FEATURES, () => this._dropFeatures());
|
||||
@ -119,7 +120,7 @@ class FeatureToggleStore {
|
||||
return this.db(TABLE)
|
||||
.insert(this.eventDataToRow(data))
|
||||
.catch(err =>
|
||||
this.logger.error('Could not insert feature, error: ', err)
|
||||
this.logger.error('Could not insert feature, error: ', err),
|
||||
);
|
||||
}
|
||||
|
||||
@ -128,7 +129,7 @@ class FeatureToggleStore {
|
||||
.where({ name: data.name })
|
||||
.update(this.eventDataToRow(data))
|
||||
.catch(err =>
|
||||
this.logger.error('Could not update feature, error: ', err)
|
||||
this.logger.error('Could not update feature, error: ', err),
|
||||
);
|
||||
}
|
||||
|
||||
@ -146,7 +147,7 @@ class FeatureToggleStore {
|
||||
.where({ name })
|
||||
.update({ archived: 0, enabled: 0 })
|
||||
.catch(err =>
|
||||
this.logger.error('Could not archive feature, error: ', err)
|
||||
this.logger.error('Could not archive feature, error: ', err),
|
||||
);
|
||||
}
|
||||
|
||||
@ -156,10 +157,10 @@ class FeatureToggleStore {
|
||||
.where({ name: rowData.name })
|
||||
.update(rowData)
|
||||
.then(result =>
|
||||
result === 0 ? this.db(TABLE).insert(rowData) : result
|
||||
result === 0 ? this.db(TABLE).insert(rowData) : result,
|
||||
)
|
||||
.catch(err =>
|
||||
this.logger.error('Could not import feature, error: ', err)
|
||||
this.logger.error('Could not import feature, error: ', err),
|
||||
);
|
||||
}
|
||||
|
||||
@ -167,7 +168,7 @@ class FeatureToggleStore {
|
||||
return this.db(TABLE)
|
||||
.delete()
|
||||
.catch(err =>
|
||||
this.logger.error('Could not drop features, error: ', err)
|
||||
this.logger.error('Could not drop features, error: ', err),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ const ContextFieldStore = require('./context-field-store');
|
||||
const SettingStore = require('./setting-store');
|
||||
|
||||
module.exports.createStores = (config, eventBus) => {
|
||||
const getLogger = config.getLogger;
|
||||
const { getLogger } = config;
|
||||
const db = createDb(config);
|
||||
const eventStore = new EventStore(db, getLogger);
|
||||
const clientMetricsDb = new ClientMetricsDb(db, getLogger);
|
||||
@ -25,19 +25,19 @@ module.exports.createStores = (config, eventBus) => {
|
||||
clientApplicationsStore: new ClientApplicationsStore(
|
||||
db,
|
||||
eventBus,
|
||||
getLogger
|
||||
getLogger,
|
||||
),
|
||||
clientInstanceStore: new ClientInstanceStore(db, eventBus, getLogger),
|
||||
clientMetricsStore: new ClientMetricsStore(
|
||||
clientMetricsDb,
|
||||
eventBus,
|
||||
getLogger
|
||||
getLogger,
|
||||
),
|
||||
contextFieldStore: new ContextFieldStore(
|
||||
db,
|
||||
config.customContextFields,
|
||||
eventStore,
|
||||
getLogger
|
||||
getLogger,
|
||||
),
|
||||
settingStore: new SettingStore(db, getLogger),
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* eslint camelcase: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
const TABLE = 'settings';
|
||||
@ -29,9 +30,8 @@ class SettingStore {
|
||||
.then(rows => {
|
||||
if (rows[0].count > 0) {
|
||||
return this.updateRow(name, content);
|
||||
} else {
|
||||
return this.insertNewRow(name, content);
|
||||
}
|
||||
return this.insertNewRow(name, content);
|
||||
});
|
||||
}
|
||||
|
||||
@ -43,9 +43,8 @@ class SettingStore {
|
||||
|
||||
if (result.length > 0) {
|
||||
return result[0].content;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ const {
|
||||
DROP_STRATEGIES,
|
||||
} = require('../event-type');
|
||||
const NotFoundError = require('../error/notfound-error');
|
||||
|
||||
const STRATEGY_COLUMNS = ['name', 'description', 'parameters', 'built_in'];
|
||||
const TABLE = 'strategies';
|
||||
|
||||
@ -16,16 +17,16 @@ class StrategyStore {
|
||||
this.db = db;
|
||||
this.logger = getLogger('strategy-store.js');
|
||||
eventStore.on(STRATEGY_CREATED, event =>
|
||||
this._createStrategy(event.data)
|
||||
this._createStrategy(event.data),
|
||||
);
|
||||
eventStore.on(STRATEGY_UPDATED, event =>
|
||||
this._updateStrategy(event.data)
|
||||
this._updateStrategy(event.data),
|
||||
);
|
||||
eventStore.on(STRATEGY_DELETED, event =>
|
||||
this._deleteStrategy(event.data)
|
||||
this._deleteStrategy(event.data),
|
||||
);
|
||||
eventStore.on(STRATEGY_IMPORT, event =>
|
||||
this._importStrategy(event.data)
|
||||
this._importStrategy(event.data),
|
||||
);
|
||||
eventStore.on(DROP_STRATEGIES, () => this._dropStrategies());
|
||||
}
|
||||
@ -90,7 +91,7 @@ class StrategyStore {
|
||||
this.db(TABLE)
|
||||
.insert(this.eventDataToRow(data))
|
||||
.catch(err =>
|
||||
this.logger.error('Could not insert strategy, error: ', err)
|
||||
this.logger.error('Could not insert strategy, error: ', err),
|
||||
);
|
||||
}
|
||||
|
||||
@ -99,7 +100,7 @@ class StrategyStore {
|
||||
.where({ name: data.name })
|
||||
.update(this.eventDataToRow(data))
|
||||
.catch(err =>
|
||||
this.logger.error('Could not update strategy, error: ', err)
|
||||
this.logger.error('Could not update strategy, error: ', err),
|
||||
);
|
||||
}
|
||||
|
||||
@ -118,10 +119,10 @@ class StrategyStore {
|
||||
.where({ name: rowData.name, built_in: 0 }) // eslint-disable-line
|
||||
.update(rowData)
|
||||
.then(result =>
|
||||
result === 0 ? this.db(TABLE).insert(rowData) : result
|
||||
result === 0 ? this.db(TABLE).insert(rowData) : result,
|
||||
)
|
||||
.catch(err =>
|
||||
this.logger.error('Could not import strategy, error: ', err)
|
||||
this.logger.error('Could not import strategy, error: ', err),
|
||||
);
|
||||
}
|
||||
|
||||
@ -130,7 +131,7 @@ class StrategyStore {
|
||||
.where({ built_in: 0 }) // eslint-disable-line
|
||||
.delete()
|
||||
.catch(err =>
|
||||
this.logger.error('Could not drop strategies, error: ', err)
|
||||
this.logger.error('Could not drop strategies, error: ', err),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { diff } = require('deep-diff');
|
||||
const {
|
||||
STRATEGY_CREATED,
|
||||
STRATEGY_DELETED,
|
||||
@ -16,7 +19,6 @@ const {
|
||||
CONTEXT_FIELD_UPDATED,
|
||||
CONTEXT_FIELD_DELETED,
|
||||
} = require('./event-type');
|
||||
const diff = require('deep-diff').diff;
|
||||
|
||||
const strategyTypes = [
|
||||
STRATEGY_CREATED,
|
||||
@ -44,9 +46,11 @@ const contextTypes = [
|
||||
function baseTypeFor(event) {
|
||||
if (featureTypes.indexOf(event.type) !== -1) {
|
||||
return 'features';
|
||||
} else if (strategyTypes.indexOf(event.type) !== -1) {
|
||||
}
|
||||
if (strategyTypes.indexOf(event.type) !== -1) {
|
||||
return 'strategies';
|
||||
} else if (contextTypes.indexOf(event.type) !== -1) {
|
||||
}
|
||||
if (contextTypes.indexOf(event.type) !== -1) {
|
||||
return 'context';
|
||||
}
|
||||
throw new Error(`unknown event type: ${JSON.stringify(event)}`);
|
||||
@ -91,6 +95,7 @@ function eachConsecutiveEvent(events, callback) {
|
||||
}
|
||||
|
||||
function addDiffs(events) {
|
||||
// TODO: no-param-reassign
|
||||
eachConsecutiveEvent(events, (left, right) => {
|
||||
if (right) {
|
||||
left.diffs = diff(right.data, left.data);
|
||||
|
@ -44,7 +44,7 @@ test('diffs a feature-update event', t => {
|
||||
|
||||
eventDiffer.addDiffs(events);
|
||||
|
||||
const diffs = events[0].diffs;
|
||||
const { diffs } = events[0];
|
||||
t.true(diffs[0].kind === 'E');
|
||||
t.true(diffs[0].path[0] === 'enabled');
|
||||
t.true(diffs[0].kind === 'E');
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
const test = require('ava');
|
||||
const { EventEmitter } = require('events');
|
||||
|
||||
const eventStore = new EventEmitter();
|
||||
const { addEventHook } = require('./event-hook');
|
||||
const {
|
||||
@ -28,5 +29,5 @@ test.before(() => {
|
||||
eventStore.emit(feature, data);
|
||||
t.true(o[feature] === data);
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -2,31 +2,6 @@
|
||||
|
||||
const log4js = require('log4js');
|
||||
|
||||
let loggerProvider = getDefaultLogProvider();
|
||||
|
||||
module.exports.defaultLogProvider = loggerProvider;
|
||||
|
||||
function validateLogProvider(provider) {
|
||||
validate(typeof provider == 'function', 'Provider needs to be a function');
|
||||
|
||||
const logger = provider('unleash:logger');
|
||||
validate(typeof logger.debug == 'function', 'Logger must implement debug');
|
||||
validate(typeof logger.info == 'function', 'Logger must implement info');
|
||||
validate(typeof logger.warn == 'function', 'Logger must implement warn');
|
||||
validate(typeof logger.error == 'function', 'Logger must implement error');
|
||||
}
|
||||
exports.validateLogProvider = validateLogProvider;
|
||||
|
||||
// Deprecated
|
||||
exports.setLoggerProvider = function setLoggerProvider(provider) {
|
||||
validateLogProvider(provider);
|
||||
|
||||
loggerProvider = provider;
|
||||
const logger = provider('unleash:logger');
|
||||
logger.info(`Your way of configuring a logProvider is depreacted.
|
||||
See https://unleash.github.io/docs/getting_started for details`);
|
||||
};
|
||||
|
||||
function getDefaultLogProvider() {
|
||||
let level;
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
@ -49,8 +24,34 @@ function getDefaultLogProvider() {
|
||||
return log4js.getLogger;
|
||||
}
|
||||
|
||||
let loggerProvider = getDefaultLogProvider();
|
||||
|
||||
function validate(isValid, msg) {
|
||||
if (!isValid) {
|
||||
throw new TypeError(msg);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.defaultLogProvider = loggerProvider;
|
||||
|
||||
function validateLogProvider(provider) {
|
||||
validate(typeof provider === 'function', 'Provider needs to be a function');
|
||||
|
||||
const logger = provider('unleash:logger');
|
||||
validate(typeof logger.debug === 'function', 'Logger must implement debug');
|
||||
validate(typeof logger.info === 'function', 'Logger must implement info');
|
||||
validate(typeof logger.warn === 'function', 'Logger must implement warn');
|
||||
validate(typeof logger.error === 'function', 'Logger must implement error');
|
||||
}
|
||||
|
||||
exports.validateLogProvider = validateLogProvider;
|
||||
|
||||
// Deprecated
|
||||
exports.setLoggerProvider = function setLoggerProvider(provider) {
|
||||
validateLogProvider(provider);
|
||||
|
||||
loggerProvider = provider;
|
||||
const logger = provider('unleash:logger');
|
||||
logger.info(`Your way of configuring a logProvider is depreacted.
|
||||
See https://unleash.github.io/docs/getting_started for details`);
|
||||
};
|
||||
|
@ -18,7 +18,7 @@ test('should require custom logger to implement info', t => {
|
||||
() => {
|
||||
logger.setLoggerProvider(provider)();
|
||||
},
|
||||
{ instanceOf: TypeError }
|
||||
{ instanceOf: TypeError },
|
||||
);
|
||||
t.is(error.message, 'Logger must implement info');
|
||||
});
|
||||
@ -34,7 +34,7 @@ test('should require custom logger to implement error', t => {
|
||||
() => {
|
||||
logger.setLoggerProvider(provider)();
|
||||
},
|
||||
{ instanceOf: TypeError }
|
||||
{ instanceOf: TypeError },
|
||||
);
|
||||
t.is(error.message, 'Logger must implement error');
|
||||
});
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
|
||||
'use strict';
|
||||
|
||||
const timer = require('./timer');
|
||||
|
@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const client = require('prom-client');
|
||||
const events = require('./events');
|
||||
const {
|
||||
FEATURE_CREATED,
|
||||
@ -8,6 +9,7 @@ const {
|
||||
FEATURE_REVIVED,
|
||||
} = require('./event-type');
|
||||
const { version } = require('./routes/api-def');
|
||||
|
||||
const THREE_HOURS = 3 * 60 * 60 * 1000;
|
||||
|
||||
exports.startMonitoring = (
|
||||
@ -15,14 +17,12 @@ exports.startMonitoring = (
|
||||
eventBus,
|
||||
eventStore,
|
||||
clientMetricsStore,
|
||||
featureToggleStore
|
||||
featureToggleStore,
|
||||
) => {
|
||||
if (!enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
const client = require('prom-client');
|
||||
|
||||
client.collectDefaultMetrics();
|
||||
|
||||
const requestDuration = new client.Summary({
|
||||
@ -84,6 +84,7 @@ exports.startMonitoring = (
|
||||
});
|
||||
|
||||
clientMetricsStore.on('metrics', m => {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const [feature, { yes, no }] of Object.entries(m.bucket.toggles)) {
|
||||
featureToggleUsageTotal.labels(feature, true, m.appName).inc(yes);
|
||||
featureToggleUsageTotal.labels(feature, false, m.appName).inc(no);
|
||||
|
@ -2,13 +2,14 @@
|
||||
|
||||
const test = require('ava');
|
||||
const { EventEmitter } = require('events');
|
||||
|
||||
const eventBus = new EventEmitter();
|
||||
const eventStore = new EventEmitter();
|
||||
const clientMetricsStore = new EventEmitter();
|
||||
const { register: prometheusRegister } = require('prom-client');
|
||||
const { REQUEST_TIME, DB_TIME } = require('./events');
|
||||
const { FEATURE_UPDATED } = require('./event-type');
|
||||
const { startMonitoring } = require('./metrics');
|
||||
const { register: prometheusRegister } = require('prom-client');
|
||||
|
||||
test.before(() => {
|
||||
const featureToggleStore = {
|
||||
@ -19,7 +20,7 @@ test.before(() => {
|
||||
eventBus,
|
||||
eventStore,
|
||||
clientMetricsStore,
|
||||
featureToggleStore
|
||||
featureToggleStore,
|
||||
);
|
||||
});
|
||||
|
||||
@ -34,7 +35,7 @@ test('should collect metrics for requests', t => {
|
||||
const metrics = prometheusRegister.metrics();
|
||||
t.regex(
|
||||
metrics,
|
||||
/http_request_duration_milliseconds{quantile="0\.99",path="somePath",method="GET",status="200"} 1337/
|
||||
/http_request_duration_milliseconds{quantile="0\.99",path="somePath",method="GET",status="200"} 1337/,
|
||||
);
|
||||
});
|
||||
|
||||
@ -62,7 +63,7 @@ test('should collect metrics for client metric reports', t => {
|
||||
const metrics = prometheusRegister.metrics();
|
||||
t.regex(
|
||||
metrics,
|
||||
/feature_toggle_usage_total{toggle="TestToggle",active="true",appName="undefined"} 10\nfeature_toggle_usage_total{toggle="TestToggle",active="false",appName="undefined"} 5/
|
||||
/feature_toggle_usage_total{toggle="TestToggle",active="true",appName="undefined"} 10\nfeature_toggle_usage_total{toggle="TestToggle",active="false",appName="undefined"} 5/,
|
||||
);
|
||||
});
|
||||
|
||||
@ -76,7 +77,7 @@ test('should collect metrics for db query timings', t => {
|
||||
const metrics = prometheusRegister.metrics();
|
||||
t.regex(
|
||||
metrics,
|
||||
/db_query_duration_seconds{quantile="0\.99",store="foo",action="bar"} 0.1337/
|
||||
/db_query_duration_seconds{quantile="0\.99",store="foo",action="bar"} 0.1337/,
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -11,7 +11,7 @@ test('should add dummy user object to all requests', t => {
|
||||
const app = express();
|
||||
noAuthentication('', app);
|
||||
app.get('/api/admin/test', (req, res) => {
|
||||
const user = Object.assign({}, req.user);
|
||||
const user = { ...req.user };
|
||||
|
||||
return res
|
||||
.status(200)
|
||||
|
@ -22,7 +22,7 @@ module.exports = function(config, permission) {
|
||||
new MissingPermission({
|
||||
permission,
|
||||
message: `You require ${permission} to perform this action`,
|
||||
})
|
||||
}),
|
||||
)
|
||||
.end();
|
||||
};
|
||||
|
@ -1,13 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../test/fixtures/store');
|
||||
const checkPermission = require('./permission-checker');
|
||||
const supertest = require('supertest');
|
||||
const getApp = require('../app');
|
||||
const getLogger = require('../../test/fixtures/no-logger');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
function getSetup(preRouterHook) {
|
||||
@ -28,7 +28,7 @@ function getSetup(preRouterHook) {
|
||||
res.status(200)
|
||||
.json({ message: 'OK' })
|
||||
.end();
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
});
|
||||
|
@ -21,20 +21,19 @@ function unsecureAuthentication(basePath = '', app) {
|
||||
|
||||
app.use(`${basePath}/api/admin/`, (req, res, next) => {
|
||||
if (req.user) {
|
||||
next();
|
||||
} else {
|
||||
return res
|
||||
.status('401')
|
||||
.json(
|
||||
new AuthenticationRequired({
|
||||
path: `${basePath}/api/admin/login`,
|
||||
type: 'unsecure',
|
||||
message:
|
||||
'You have to indentify yourself in order to use Unleash.',
|
||||
})
|
||||
)
|
||||
.end();
|
||||
return next();
|
||||
}
|
||||
return res
|
||||
.status('401')
|
||||
.json(
|
||||
new AuthenticationRequired({
|
||||
path: `${basePath}/api/admin/login`,
|
||||
type: 'unsecure',
|
||||
message:
|
||||
'You have to indentify yourself in order to use Unleash.',
|
||||
}),
|
||||
)
|
||||
.end();
|
||||
});
|
||||
|
||||
app.use((req, res, next) => {
|
||||
|
@ -8,6 +8,16 @@ const { defaultLogProvider, validateLogProvider } = require('./logger');
|
||||
|
||||
const THIRTY_DAYS = 30 * 24 * 60 * 60 * 1000;
|
||||
|
||||
function defaultDatabaseUrl() {
|
||||
if (process.env.DATABASE_URL_FILE) {
|
||||
return readFileSync(process.env.DATABASE_URL_FILE, 'utf8');
|
||||
}
|
||||
if (process.env.DATABASE_URL) {
|
||||
return process.env.DATABASE_URL;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function defaultOptions() {
|
||||
return {
|
||||
databaseUrl: defaultDatabaseUrl(),
|
||||
@ -41,16 +51,6 @@ function defaultOptions() {
|
||||
};
|
||||
}
|
||||
|
||||
function defaultDatabaseUrl() {
|
||||
if (process.env.DATABASE_URL_FILE) {
|
||||
return readFileSync(process.env.DATABASE_URL_FILE, 'utf8');
|
||||
} else if (process.env.DATABASE_URL) {
|
||||
return process.env.DATABASE_URL;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createOptions: (opts = {}) => {
|
||||
const options = merge(defaultOptions(), opts);
|
||||
@ -62,7 +62,7 @@ module.exports = {
|
||||
|
||||
if (!options.db.host) {
|
||||
throw new Error(
|
||||
`Unleash requires database details to start. See https://unleash.github.io/docs/getting_started`
|
||||
`Unleash requires database details to start. See https://unleash.github.io/docs/getting_started`,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const fs = require('fs');
|
||||
const { createOptions } = require('./options');
|
||||
|
||||
delete process.env.DATABASE_URL;
|
||||
|
||||
test('should require DATABASE_URI', t => {
|
||||
const { createOptions } = require('./options');
|
||||
|
||||
t.throws(() => {
|
||||
createOptions({});
|
||||
});
|
||||
@ -17,7 +18,6 @@ test('should use DATABASE_URL from env', t => {
|
||||
const databaseUrl = 'postgres://u:p@localhost:5432/name';
|
||||
delete process.env.NODE_ENV;
|
||||
process.env.DATABASE_URL = databaseUrl;
|
||||
const { createOptions } = require('./options');
|
||||
|
||||
const options = createOptions({});
|
||||
|
||||
@ -30,7 +30,6 @@ test('should use DATABASE_URL_FILE from env', t => {
|
||||
fs.writeFileSync(path, databaseUrl, { mode: 0o755 });
|
||||
delete process.env.NODE_ENV;
|
||||
process.env.DATABASE_URL_FILE = path;
|
||||
const { createOptions } = require('./options');
|
||||
|
||||
const options = createOptions({});
|
||||
|
||||
@ -39,7 +38,6 @@ test('should use DATABASE_URL_FILE from env', t => {
|
||||
|
||||
test('should use databaseUrl from options', t => {
|
||||
const databaseUrl = 'postgres://u:p@localhost:5432/name';
|
||||
const { createOptions } = require('./options');
|
||||
|
||||
const options = createOptions({ databaseUrl });
|
||||
|
||||
@ -50,7 +48,6 @@ test('should not override provided options', t => {
|
||||
process.env.DATABASE_URL = 'postgres://test:5432/name';
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
const { createOptions } = require('./options');
|
||||
const options = createOptions({
|
||||
databaseUrl: 'postgres://test:5432/name',
|
||||
port: 1111,
|
||||
@ -61,7 +58,6 @@ test('should not override provided options', t => {
|
||||
});
|
||||
|
||||
test('should add listen options from host and port', t => {
|
||||
const { createOptions } = require('./options');
|
||||
const options = createOptions({
|
||||
databaseUrl: 'postgres://test:5432/name',
|
||||
port: 1111,
|
||||
@ -72,7 +68,6 @@ test('should add listen options from host and port', t => {
|
||||
});
|
||||
|
||||
test('should use pipe to path', t => {
|
||||
const { createOptions } = require('./options');
|
||||
const options = createOptions({
|
||||
databaseUrl: 'postgres://test:5432/name',
|
||||
port: 1111,
|
||||
@ -86,7 +81,6 @@ test('should use pipe to path', t => {
|
||||
test('should prefer databaseUrl from options', t => {
|
||||
process.env.DATABASE_URL = 'postgres://test:5432/name';
|
||||
const databaseUrl = 'postgres://u:p@localhost:5432/options';
|
||||
const { createOptions } = require('./options');
|
||||
|
||||
const options = createOptions({ databaseUrl });
|
||||
|
||||
@ -96,7 +90,6 @@ test('should prefer databaseUrl from options', t => {
|
||||
test('should expand databaseUrl from options', t => {
|
||||
process.env.DATABASE_URL = 'postgres://test:5432/name';
|
||||
const databaseUrl = 'postgres://u:p@localhost:5432/options';
|
||||
const { createOptions } = require('./options');
|
||||
|
||||
const options = createOptions({ databaseUrl });
|
||||
|
||||
@ -113,7 +106,6 @@ test('should expand databaseUrl from options', t => {
|
||||
test('should validate getLogger', t => {
|
||||
const databaseUrl = 'postgres://u:p@localhost:5432/options';
|
||||
const getLogger = () => {};
|
||||
const { createOptions } = require('./options');
|
||||
|
||||
t.throws(() => {
|
||||
createOptions({ databaseUrl, getLogger });
|
||||
@ -128,7 +120,6 @@ test('should accept custome log-provider', t => {
|
||||
warn: console.log,
|
||||
error: console.log,
|
||||
});
|
||||
const { createOptions } = require('./options');
|
||||
const options = createOptions({ databaseUrl, getLogger });
|
||||
|
||||
t.deepEqual(options.getLogger, getLogger);
|
||||
@ -145,7 +136,6 @@ test('should prefer custom db connection options', t => {
|
||||
ssl: false,
|
||||
driver: 'postgres',
|
||||
};
|
||||
const { createOptions } = require('./options');
|
||||
const options = createOptions({ databaseUrl, db });
|
||||
|
||||
t.deepEqual(options.db, db);
|
||||
@ -154,7 +144,6 @@ test('should prefer custom db connection options', t => {
|
||||
test('should baseUriPath', t => {
|
||||
const databaseUrl = 'postgres://u:p@localhost:5432/options';
|
||||
const baseUriPath = 'some';
|
||||
const { createOptions } = require('./options');
|
||||
const options = createOptions({ databaseUrl, baseUriPath });
|
||||
|
||||
t.deepEqual(options.baseUriPath, baseUriPath);
|
||||
|
@ -31,7 +31,7 @@ class ArchiveController extends Controller {
|
||||
createdBy: userName,
|
||||
data: { name: req.params.name },
|
||||
});
|
||||
res.status(200).end();
|
||||
return res.status(200).end();
|
||||
} catch (error) {
|
||||
this.logger.error('Server failed executing request', error);
|
||||
return res.status(500).end();
|
||||
|
@ -1,14 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const store = require('./../../../test/fixtures/store');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../../test/fixtures/store');
|
||||
const permissions = require('../../../test/fixtures/permissions');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const supertest = require('supertest');
|
||||
const getApp = require('../../app');
|
||||
const { UPDATE_FEATURE } = require('../../permissions');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
function getSetup() {
|
||||
|
@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const store = require('./../../../test/fixtures/store');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../../test/fixtures/store');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const getApp = require('../../app');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
const uiConfig = {
|
||||
|
@ -32,12 +32,12 @@ class ContextController extends Controller {
|
||||
this.put(
|
||||
'/:contextField',
|
||||
this.updateContextField,
|
||||
UPDATE_CONTEXT_FIELD
|
||||
UPDATE_CONTEXT_FIELD,
|
||||
);
|
||||
this.delete(
|
||||
'/:contextField',
|
||||
this.deleteContextField,
|
||||
DELETE_CONTEXT_FIELD
|
||||
DELETE_CONTEXT_FIELD,
|
||||
);
|
||||
this.post('/validate', this.validate);
|
||||
}
|
||||
@ -60,7 +60,7 @@ class ContextController extends Controller {
|
||||
}
|
||||
|
||||
async createContextField(req, res) {
|
||||
const name = req.body.name;
|
||||
const { name } = req.body;
|
||||
const userName = extractUser(req);
|
||||
|
||||
try {
|
||||
@ -130,7 +130,7 @@ class ContextController extends Controller {
|
||||
}
|
||||
|
||||
async validate(req, res) {
|
||||
const name = req.body.name;
|
||||
const { name } = req.body;
|
||||
|
||||
try {
|
||||
await nameSchema.validateAsync({ name });
|
||||
|
@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const store = require('./../../../test/fixtures/store');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../../test/fixtures/store');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const getApp = require('../../app');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
function getSetup() {
|
||||
|
@ -3,6 +3,7 @@
|
||||
const Controller = require('../controller');
|
||||
|
||||
const eventDiffer = require('../../event-differ');
|
||||
|
||||
const version = 1;
|
||||
|
||||
class EventController extends Controller {
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
const test = require('ava');
|
||||
|
||||
const store = require('./../../../test/fixtures/store');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../../test/fixtures/store');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
|
||||
const supertest = require('supertest');
|
||||
const getApp = require('../../app');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
function getSetup() {
|
||||
|
@ -41,7 +41,7 @@ const variantsSchema = joi.object().keys({
|
||||
contextName: joi.string().required(),
|
||||
values: joi.array().items(joi.string()),
|
||||
})
|
||||
.optional()
|
||||
.optional(),
|
||||
),
|
||||
});
|
||||
|
||||
|
@ -91,7 +91,7 @@ test('variant overrides must have corect shape', async t => {
|
||||
} catch (error) {
|
||||
t.is(
|
||||
error.details[0].message,
|
||||
'"variants[0].overrides" must be an array'
|
||||
'"variants[0].overrides" must be an array',
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -16,6 +16,7 @@ const {
|
||||
CREATE_FEATURE,
|
||||
} = require('../../permissions');
|
||||
const { featureShema, nameSchema } = require('./feature-schema');
|
||||
|
||||
const version = 1;
|
||||
|
||||
class FeatureController extends Controller {
|
||||
@ -52,7 +53,7 @@ class FeatureController extends Controller {
|
||||
}
|
||||
|
||||
async validate(req, res) {
|
||||
const name = req.body.name;
|
||||
const { name } = req.body;
|
||||
|
||||
try {
|
||||
await nameSchema.validateAsync({ name });
|
||||
@ -99,7 +100,7 @@ class FeatureController extends Controller {
|
||||
}
|
||||
|
||||
async updateToggle(req, res) {
|
||||
const featureName = req.params.featureName;
|
||||
const { featureName } = req.params;
|
||||
const userName = extractUser(req);
|
||||
const updatedFeature = req.body;
|
||||
|
||||
@ -140,12 +141,12 @@ class FeatureController extends Controller {
|
||||
}
|
||||
|
||||
async _toggle(enabled, req, res) {
|
||||
const featureName = req.params.featureName;
|
||||
const { featureName } = req.params;
|
||||
const userName = extractUser(req);
|
||||
|
||||
try {
|
||||
const feature = await this.featureToggleStore.getFeature(
|
||||
featureName
|
||||
featureName,
|
||||
);
|
||||
|
||||
feature.enabled = enabled;
|
||||
@ -161,7 +162,7 @@ class FeatureController extends Controller {
|
||||
}
|
||||
|
||||
async deleteToggle(req, res) {
|
||||
const featureName = req.params.featureName;
|
||||
const { featureName } = req.params;
|
||||
const userName = extractUser(req);
|
||||
|
||||
try {
|
||||
|
@ -1,14 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const store = require('./../../../test/fixtures/store');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../../test/fixtures/store');
|
||||
const permissions = require('../../../test/fixtures/permissions');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const supertest = require('supertest');
|
||||
const getApp = require('../../app');
|
||||
const { UPDATE_FEATURE, CREATE_FEATURE } = require('../../permissions');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
function getSetup() {
|
||||
@ -135,7 +135,7 @@ test('should not be allowed to reuse active toggle name', t => {
|
||||
.expect(res => {
|
||||
t.true(
|
||||
res.body.details[0].message ===
|
||||
'A toggle with that name already exist'
|
||||
'A toggle with that name already exist',
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -156,7 +156,7 @@ test('should not be allowed to reuse archived toggle name', t => {
|
||||
.expect(res => {
|
||||
t.true(
|
||||
res.body.details[0].message ===
|
||||
'An archived toggle with that name already exist'
|
||||
'An archived toggle with that name already exist',
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -201,8 +201,8 @@ test('valid feature names should pass validation', t => {
|
||||
strategies: [{ name: 'default' }],
|
||||
})
|
||||
.set('Content-Type', 'application/json')
|
||||
.expect(201)
|
||||
)
|
||||
.expect(201),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@ -229,8 +229,8 @@ test('invalid feature names should not pass validation', t => {
|
||||
strategies: [{ name: 'default' }],
|
||||
})
|
||||
.set('Content-Type', 'application/json')
|
||||
.expect(400)
|
||||
)
|
||||
.expect(400),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@ -253,7 +253,7 @@ test('invalid feature names should have error msg', t => {
|
||||
.expect(400)
|
||||
.expect(res => {
|
||||
t.true(
|
||||
res.body.details[0].message === '"name" must be URL friendly'
|
||||
res.body.details[0].message === '"name" must be URL friendly',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -30,7 +30,7 @@ class MetricsController extends Controller {
|
||||
this.post(
|
||||
'/applications/:appName',
|
||||
this.createApplication,
|
||||
UPDATE_APPLICATION
|
||||
UPDATE_APPLICATION,
|
||||
);
|
||||
this.get('/applications/', this.getApplications);
|
||||
this.get('/applications/:appName', this.getApplication);
|
||||
@ -45,6 +45,7 @@ class MetricsController extends Controller {
|
||||
const seenApps = this.metrics.getSeenAppsPerToggle();
|
||||
const applications = await this.clientApplicationsStore.getApplications();
|
||||
const metaData = applications.reduce((result, entry) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
result[entry.appName] = entry;
|
||||
return result;
|
||||
}, {});
|
||||
@ -52,7 +53,7 @@ class MetricsController extends Controller {
|
||||
Object.keys(seenApps).forEach(key => {
|
||||
seenApps[key] = seenApps[key].map(entry => {
|
||||
if (metaData[entry.appName]) {
|
||||
return Object.assign({}, entry, metaData[entry.appName]);
|
||||
return { ...entry, ...metaData[entry.appName] };
|
||||
}
|
||||
return entry;
|
||||
});
|
||||
@ -65,7 +66,7 @@ class MetricsController extends Controller {
|
||||
}
|
||||
|
||||
getFeatureToggle(req, res) {
|
||||
const name = req.params.name;
|
||||
const { name } = req.params;
|
||||
const data = this.metrics.getTogglesMetrics();
|
||||
const lastHour = data.lastHour[name] || {};
|
||||
const lastMinute = data.lastMinute[name] || {};
|
||||
@ -76,9 +77,7 @@ class MetricsController extends Controller {
|
||||
}
|
||||
|
||||
async createApplication(req, res) {
|
||||
const input = Object.assign({}, req.body, {
|
||||
appName: req.params.appName,
|
||||
});
|
||||
const input = { ...req.body, appName: req.params.appName };
|
||||
const { value: applicationData, error } = schema.validate(input);
|
||||
|
||||
if (error) {
|
||||
@ -88,17 +87,17 @@ class MetricsController extends Controller {
|
||||
|
||||
try {
|
||||
await this.clientApplicationsStore.upsert(applicationData);
|
||||
res.status(202).end();
|
||||
return res.status(202).end();
|
||||
} catch (err) {
|
||||
this.logger.error(err);
|
||||
res.status(500).end();
|
||||
return res.status(500).end();
|
||||
}
|
||||
}
|
||||
|
||||
async getApplications(req, res) {
|
||||
try {
|
||||
const applications = await this.clientApplicationsStore.getApplications(
|
||||
req.query
|
||||
req.query,
|
||||
);
|
||||
res.json({ applications });
|
||||
} catch (err) {
|
||||
@ -108,7 +107,7 @@ class MetricsController extends Controller {
|
||||
}
|
||||
|
||||
async getApplication(req, res) {
|
||||
const appName = req.params.appName;
|
||||
const { appName } = req.params;
|
||||
const seenToggles = this.metrics.getSeenTogglesByAppName(appName);
|
||||
|
||||
try {
|
||||
@ -133,12 +132,12 @@ class MetricsController extends Controller {
|
||||
icon: application.icon,
|
||||
strategies: application.strategies.map(name => {
|
||||
const found = strategies.find(f => f.name === name);
|
||||
return found ? found : { name, notFound: true };
|
||||
return found || { name, notFound: true };
|
||||
}),
|
||||
instances,
|
||||
seenToggles: seenToggles.map(name => {
|
||||
const found = features.find(f => f.name === name);
|
||||
return found ? found : { name, notFound: true };
|
||||
return found || { name, notFound: true };
|
||||
}),
|
||||
links: {
|
||||
self: `/api/applications/${application.appName}`,
|
||||
|
@ -1,14 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const store = require('./../../../test/fixtures/store');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../../test/fixtures/store');
|
||||
const permissions = require('../../../test/fixtures/permissions');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const supertest = require('supertest');
|
||||
const getApp = require('../../app');
|
||||
const { UPDATE_APPLICATION } = require('../../permissions');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
function getSetup() {
|
||||
|
@ -1,13 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const Controller = require('../controller');
|
||||
const { ADMIN } = require('../../permissions');
|
||||
const extractUser = require('../../extract-user');
|
||||
const { handleErrors } = require('./util');
|
||||
const mime = require('mime');
|
||||
const YAML = require('js-yaml');
|
||||
const moment = require('moment');
|
||||
const multer = require('multer');
|
||||
const Controller = require('../controller');
|
||||
const { ADMIN } = require('../../permissions');
|
||||
const extractUser = require('../../extract-user');
|
||||
const { handleErrors } = require('./util');
|
||||
|
||||
const upload = multer({ limits: { fileSize: 5242880 } });
|
||||
|
||||
class StateController extends Controller {
|
||||
|
@ -24,7 +24,7 @@ const strategySchema = joi.object().keys({
|
||||
.allow('')
|
||||
.optional(),
|
||||
required: joi.boolean(),
|
||||
})
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
|
@ -12,6 +12,7 @@ const {
|
||||
CREATE_STRATEGY,
|
||||
UPDATE_STRATEGY,
|
||||
} = require('../../permissions');
|
||||
|
||||
const version = 1;
|
||||
|
||||
class StrategyController extends Controller {
|
||||
@ -35,7 +36,7 @@ class StrategyController extends Controller {
|
||||
|
||||
async getStrategy(req, res) {
|
||||
try {
|
||||
const name = req.params.name;
|
||||
const { name } = req.params;
|
||||
const strategy = await this.strategyStore.getStrategy(name);
|
||||
res.json(strategy).end();
|
||||
} catch (err) {
|
||||
@ -104,9 +105,9 @@ class StrategyController extends Controller {
|
||||
.then(() =>
|
||||
reject(
|
||||
new NameExistsError(
|
||||
`Strategy with name ${data.name} already exist!`
|
||||
)
|
||||
)
|
||||
`Strategy with name ${data.name} already exist!`,
|
||||
),
|
||||
),
|
||||
)
|
||||
.catch(() => resolve(data));
|
||||
});
|
||||
|
@ -1,10 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const store = require('./../../../test/fixtures/store');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../../test/fixtures/store');
|
||||
const permissions = require('../../../test/fixtures/permissions');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const supertest = require('supertest');
|
||||
const getApp = require('../../app');
|
||||
const {
|
||||
DELETE_STRATEGY,
|
||||
@ -12,7 +13,6 @@ const {
|
||||
UPDATE_STRATEGY,
|
||||
} = require('../../permissions');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
function getSetup() {
|
||||
@ -75,7 +75,7 @@ test('require parameters array when creating a new stratey', t => {
|
||||
.expect(res => {
|
||||
t.deepEqual(
|
||||
res.body.details[0].message,
|
||||
'"parameters" is required'
|
||||
'"parameters" is required',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -11,7 +11,7 @@ class UserController extends Controller {
|
||||
|
||||
getUser(req, res) {
|
||||
if (req.user) {
|
||||
const user = Object.assign({}, req.user);
|
||||
const user = { ...req.user };
|
||||
if (!this.config.extendedPermissions) {
|
||||
delete user.permissions;
|
||||
} else if (!Array.isArray(user.permissions)) {
|
||||
@ -21,9 +21,8 @@ class UserController extends Controller {
|
||||
.status(200)
|
||||
.json(user)
|
||||
.end();
|
||||
} else {
|
||||
return res.status(404).end();
|
||||
}
|
||||
return res.status(404).end();
|
||||
}
|
||||
|
||||
// Depcreated, use "/logout" instead. Will be removed in later release.
|
||||
|
@ -1,13 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const store = require('./../../../test/fixtures/store');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../../test/fixtures/store');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const getApp = require('../../app');
|
||||
const User = require('../../user');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
const currentUser = new User({ email: 'test@mail.com' });
|
||||
|
@ -14,6 +14,7 @@ const customJoi = joi.extend(j => ({
|
||||
// Generate an error, state and options need to be passed
|
||||
return { value, errors: helpers.error('isUrlFriendly.base') };
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
}));
|
||||
|
||||
@ -30,6 +31,7 @@ const handleErrors = (res, logger, error) => {
|
||||
return res.status(404).end();
|
||||
case 'NameExistsError':
|
||||
case 'ValidationError':
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
error.isJoi = true;
|
||||
return res
|
||||
.status(400)
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
// export module version
|
||||
require('pkginfo')(module, 'version');
|
||||
const version = module.exports.version;
|
||||
|
||||
const { version } = module.exports;
|
||||
const clientApiDef = require('./client-api/api-def.json');
|
||||
const adminApiDef = require('./admin-api/api-def.json');
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const store = require('./../../test/fixtures/store');
|
||||
const getLogger = require('../../test/fixtures/no-logger');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../test/fixtures/store');
|
||||
const getLogger = require('../../test/fixtures/no-logger');
|
||||
const getApp = require('../app');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
test('should use enable prometheus', t => {
|
||||
|
@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const store = require('./../../../test/fixtures/store');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../../test/fixtures/store');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const getApp = require('../../app');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
function getSetup() {
|
||||
|
@ -10,8 +10,8 @@ class ClientApi extends Controller {
|
||||
constructor(config) {
|
||||
super();
|
||||
|
||||
const stores = config.stores;
|
||||
const getLogger = config.getLogger;
|
||||
const { stores } = config;
|
||||
const { getLogger } = config;
|
||||
|
||||
this.get('/', this.index);
|
||||
this.use('/features', new FeatureController(stores, getLogger).router);
|
||||
|
@ -31,10 +31,10 @@ class ClientMetricsController extends Controller {
|
||||
instanceId: value.instanceId,
|
||||
clientIp,
|
||||
});
|
||||
res.status(202).end();
|
||||
return res.status(202).end();
|
||||
} catch (e) {
|
||||
this.logger.error('failed to store metrics', e);
|
||||
res.status(500).end();
|
||||
return res.status(500).end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,12 @@
|
||||
|
||||
const test = require('ava');
|
||||
const supertest = require('supertest');
|
||||
const store = require('./../../../test/fixtures/store');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../../test/fixtures/store');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const getApp = require('../../app');
|
||||
const { clientMetricsSchema } = require('./metrics-schema');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
function getSetup() {
|
||||
|
@ -29,7 +29,7 @@ class RegisterController extends Controller {
|
||||
await this.clientInstanceStore.insert(value);
|
||||
const { appName, instanceId } = value;
|
||||
this.logger.info(
|
||||
`New client registration: appName=${appName}, instanceId=${instanceId}`
|
||||
`New client registration: appName=${appName}, instanceId=${instanceId}`,
|
||||
);
|
||||
return res.status(202).end();
|
||||
} catch (err) {
|
||||
|
@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const store = require('./../../../test/fixtures/store');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../../test/fixtures/store');
|
||||
const getLogger = require('../../../test/fixtures/no-logger');
|
||||
const getApp = require('../../app');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
function getSetup() {
|
||||
|
@ -16,7 +16,7 @@ class Controller {
|
||||
this.app.get(
|
||||
path,
|
||||
checkPermission(this.config, permission),
|
||||
handler.bind(this)
|
||||
handler.bind(this),
|
||||
);
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ class Controller {
|
||||
this.app.post(
|
||||
path,
|
||||
checkPermission(this.config, permission),
|
||||
handler.bind(this)
|
||||
handler.bind(this),
|
||||
);
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ class Controller {
|
||||
this.app.put(
|
||||
path,
|
||||
checkPermission(this.config, permission),
|
||||
handler.bind(this)
|
||||
handler.bind(this),
|
||||
);
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ class Controller {
|
||||
this.app.delete(
|
||||
path,
|
||||
checkPermission(this.config, permission),
|
||||
handler.bind(this)
|
||||
handler.bind(this),
|
||||
);
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ class Controller {
|
||||
path,
|
||||
checkPermission(this.config, permission),
|
||||
filehandler,
|
||||
handler.bind(this)
|
||||
handler.bind(this),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const store = require('./../../test/fixtures/store');
|
||||
const getLogger = require('../../test/fixtures/no-logger');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../test/fixtures/store');
|
||||
const getLogger = require('../../test/fixtures/no-logger');
|
||||
const getApp = require('../app');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
function getSetup() {
|
||||
const stores = store.createStores();
|
||||
const db = stores.db;
|
||||
const { db } = stores;
|
||||
const app = getApp({
|
||||
baseUriPath: '',
|
||||
stores,
|
||||
|
@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const test = require('ava');
|
||||
const store = require('./../../test/fixtures/store');
|
||||
const getLogger = require('../../test/fixtures/no-logger');
|
||||
const supertest = require('supertest');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../test/fixtures/store');
|
||||
const getLogger = require('../../test/fixtures/no-logger');
|
||||
const getApp = require('../app');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
function getSetup() {
|
||||
@ -40,7 +40,7 @@ test('api defintion', t => {
|
||||
t.true(admin.uri === '/api/admin');
|
||||
t.true(client.uri === '/api/client');
|
||||
t.true(
|
||||
admin.links['feature-toggles'].uri === '/api/admin/features'
|
||||
admin.links['feature-toggles'].uri === '/api/admin/features',
|
||||
);
|
||||
t.true(client.links.metrics.uri === '/api/client/metrics');
|
||||
});
|
||||
@ -56,7 +56,7 @@ test('admin api defintion', t => {
|
||||
.expect(res => {
|
||||
t.truthy(res.body);
|
||||
t.true(
|
||||
res.body.links['feature-toggles'].uri === '/api/admin/features'
|
||||
res.body.links['feature-toggles'].uri === '/api/admin/features',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -2,12 +2,12 @@
|
||||
|
||||
const test = require('ava');
|
||||
const supertest = require('supertest');
|
||||
const store = require('./../../test/fixtures/store');
|
||||
const { EventEmitter } = require('events');
|
||||
const store = require('../../test/fixtures/store');
|
||||
const getLogger = require('../../test/fixtures/no-logger');
|
||||
const getApp = require('../app');
|
||||
const User = require('../user');
|
||||
|
||||
const { EventEmitter } = require('events');
|
||||
const eventBus = new EventEmitter();
|
||||
|
||||
const currentUser = new User({ email: 'test@mail.com' });
|
||||
|
@ -20,15 +20,14 @@ async function createApp(options) {
|
||||
const stores = createStores(options, eventBus);
|
||||
const secret = await stores.settingStore.get('unleash.secret');
|
||||
|
||||
const config = Object.assign(
|
||||
{
|
||||
stores,
|
||||
eventBus,
|
||||
secret,
|
||||
logFactory: options.getLogger, // TODO: remove in v4.x
|
||||
},
|
||||
options
|
||||
);
|
||||
const config = {
|
||||
stores,
|
||||
eventBus,
|
||||
secret,
|
||||
logFactory: options.getLogger, // TODO: remove in v4.x
|
||||
|
||||
...options,
|
||||
};
|
||||
|
||||
const app = getApp(config);
|
||||
startMonitoring(
|
||||
@ -36,7 +35,7 @@ async function createApp(options) {
|
||||
eventBus,
|
||||
stores.eventStore,
|
||||
stores.clientMetricsStore,
|
||||
stores.featureToggleStore
|
||||
stores.featureToggleStore,
|
||||
);
|
||||
|
||||
if (typeof config.eventHook === 'function') {
|
||||
@ -54,7 +53,7 @@ async function createApp(options) {
|
||||
}
|
||||
|
||||
const server = app.listen(options.listen, () =>
|
||||
logger.info('Unleash has started.', server.address())
|
||||
logger.info('Unleash has started.', server.address()),
|
||||
);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -65,7 +64,7 @@ async function createApp(options) {
|
||||
server,
|
||||
eventBus,
|
||||
stateService,
|
||||
})
|
||||
}),
|
||||
);
|
||||
server.on('error', reject);
|
||||
});
|
||||
|
@ -41,7 +41,7 @@ const serverImpl = proxyquire('./server-impl', {
|
||||
return o;
|
||||
},
|
||||
},
|
||||
'../migrator'() {
|
||||
'../migrator': function() {
|
||||
return Promise.resolve();
|
||||
},
|
||||
});
|
||||
|
@ -3,9 +3,9 @@
|
||||
const joi = require('@hapi/joi');
|
||||
const fs = require('fs');
|
||||
const mime = require('mime');
|
||||
const YAML = require('js-yaml');
|
||||
const { featureShema } = require('./routes/admin-api/feature-schema');
|
||||
const strategySchema = require('./routes/admin-api/strategy-schema');
|
||||
const YAML = require('js-yaml');
|
||||
const {
|
||||
FEATURE_IMPORT,
|
||||
DROP_FEATURES,
|
||||
@ -27,7 +27,7 @@ const dataSchema = joi.object().keys({
|
||||
|
||||
function readFile(file) {
|
||||
return new Promise((resolve, reject) =>
|
||||
fs.readFile(file, (err, v) => (err ? reject(err) : resolve(v)))
|
||||
fs.readFile(file, (err, v) => (err ? reject(err) : resolve(v))),
|
||||
);
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ class StateService {
|
||||
|
||||
if (importData.features) {
|
||||
this.logger.info(
|
||||
`Importing ${importData.features.length} features`
|
||||
`Importing ${importData.features.length} features`,
|
||||
);
|
||||
if (dropBeforeImport) {
|
||||
this.logger.info(`Dropping existing features`);
|
||||
@ -72,14 +72,14 @@ class StateService {
|
||||
type: FEATURE_IMPORT,
|
||||
createdBy: userName,
|
||||
data: feature,
|
||||
})
|
||||
)
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (importData.strategies) {
|
||||
this.logger.info(
|
||||
`Importing ${importData.strategies.length} strategies`
|
||||
`Importing ${importData.strategies.length} strategies`,
|
||||
);
|
||||
if (dropBeforeImport) {
|
||||
this.logger.info(`Dropping existing strategies`);
|
||||
@ -95,8 +95,8 @@ class StateService {
|
||||
type: STRATEGY_IMPORT,
|
||||
createdBy: userName,
|
||||
data: strategy,
|
||||
})
|
||||
)
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
const test = require('ava');
|
||||
|
||||
const store = require('./../test/fixtures/store');
|
||||
const getLogger = require('./../test/fixtures/no-logger');
|
||||
const store = require('../test/fixtures/store');
|
||||
const getLogger = require('../test/fixtures/no-logger');
|
||||
|
||||
const StateService = require('./state-service');
|
||||
const {
|
||||
|
@ -8,7 +8,7 @@ function timeout(fn, ms) {
|
||||
setTimeout(() => {
|
||||
fn();
|
||||
resolve();
|
||||
}, ms)
|
||||
}, ms),
|
||||
);
|
||||
}
|
||||
|
||||
@ -28,5 +28,5 @@ test('timer should track the time', async t => {
|
||||
if (diff > 0.019 && diff < 0.05) {
|
||||
return t.pass();
|
||||
}
|
||||
t.fail();
|
||||
return t.fail();
|
||||
});
|
||||
|
@ -10,7 +10,7 @@ module.exports = class User {
|
||||
Joi.string()
|
||||
.email()
|
||||
.required(),
|
||||
'Email'
|
||||
'Email',
|
||||
);
|
||||
this.email = email;
|
||||
this.name = name;
|
||||
|
@ -9,7 +9,7 @@ test('should create user', t => {
|
||||
t.is(user.email, 'some@email.com');
|
||||
t.is(
|
||||
user.imageUrl,
|
||||
'https://gravatar.com/avatar/d8ffeba65ee5baf57e4901690edc8e1b?size=42&default=retro'
|
||||
'https://gravatar.com/avatar/d8ffeba65ee5baf57e4901690edc8e1b?size=42&default=retro',
|
||||
);
|
||||
});
|
||||
|
||||
@ -18,7 +18,7 @@ test('should require email', t => {
|
||||
() => {
|
||||
const user = new User(); // eslint-disable-line
|
||||
},
|
||||
{ instanceOf: Error }
|
||||
{ instanceOf: Error },
|
||||
);
|
||||
|
||||
t.is(error.message, 'Email "value" is required');
|
||||
|
@ -25,7 +25,7 @@ CREATE TABLE events (
|
||||
data json
|
||||
);
|
||||
`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
||||
@ -36,6 +36,6 @@ DROP TABLE events;
|
||||
DROP TABLE features;
|
||||
DROP TABLE strategies;
|
||||
`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
@ -3,13 +3,13 @@
|
||||
exports.up = function(db, callback) {
|
||||
db.runSql(
|
||||
'ALTER TABLE strategies ADD "parameters_template" json;',
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
||||
exports.down = function(db, callback) {
|
||||
db.runSql(
|
||||
'ALTER TABLE strategies DROP COLUMN "parameters_template";',
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ exports.up = function(db, callback) {
|
||||
INSERT INTO strategies(name, description)
|
||||
VALUES ('default', 'Default on/off strategy.');
|
||||
`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
||||
@ -14,6 +14,6 @@ exports.down = function(db, callback) {
|
||||
db.runSql(
|
||||
`
|
||||
DELETE FROM strategies where name='default';`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ exports.up = function(db, callback) {
|
||||
INSERT INTO events(type, created_by, data)
|
||||
VALUES ('strategy-created', 'migration', '{"name":"default","description":"Default on or off Strategy."}');
|
||||
`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
||||
@ -14,6 +14,6 @@ exports.down = function(db, callback) {
|
||||
db.runSql(
|
||||
`
|
||||
delete from events where type='strategy-created' and data->>'name' = 'default';`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ exports.up = function(db, callback) {
|
||||
UPDATE events SET type='feature-revived' WHERE type='feature-revive';
|
||||
UPDATE events SET type='feature-archived' WHERE type='feature-archive';
|
||||
`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
||||
@ -16,6 +16,6 @@ exports.down = function(db, callback) {
|
||||
UPDATE events SET type='feature-revive' WHERE type='feature-revived';
|
||||
UPDATE events SET type='feature-archive' WHERE type='feature-archived';
|
||||
`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
@ -16,7 +16,7 @@ WHERE f.name = features.name;
|
||||
ALTER TABLE features DROP COLUMN "strategy_name";
|
||||
ALTER TABLE features DROP COLUMN "parameters";
|
||||
`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
||||
@ -37,6 +37,6 @@ WHERE f.name = features.name;
|
||||
--drop new column
|
||||
ALTER TABLE features DROP COLUMN "strategies";
|
||||
`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
@ -8,7 +8,7 @@ CREATE TABLE client_metrics (
|
||||
created_at timestamp default now(),
|
||||
metrics json
|
||||
);`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -10,7 +10,7 @@ exports.up = function(db, callback) {
|
||||
last_seen timestamp default now(),
|
||||
created_at timestamp default now()
|
||||
);`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* eslint camelcase: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
exports.up = function(db, cb) {
|
||||
@ -20,7 +21,7 @@ exports.up = function(db, cb) {
|
||||
url: { type: 'string', length: 255 },
|
||||
color: { type: 'string', length: 255 },
|
||||
},
|
||||
cb
|
||||
cb,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* eslint camelcase: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
@ -25,12 +26,12 @@ exports.up = function(db, callback) {
|
||||
strategy => `
|
||||
UPDATE strategies
|
||||
SET parameters='${JSON.stringify(strategy.parameters)}'
|
||||
WHERE name='${strategy.name}';`
|
||||
WHERE name='${strategy.name}';`,
|
||||
)
|
||||
.join('\n');
|
||||
|
||||
db.runSql(updateSQL, cb);
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
@ -40,7 +41,7 @@ exports.up = function(db, callback) {
|
||||
populateNewData.bind(db),
|
||||
db.removeColumn.bind(db, 'strategies', 'parameters_template'),
|
||||
],
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
||||
@ -60,9 +61,9 @@ exports.down = function(db, callback) {
|
||||
strategy => `
|
||||
UPDATE strategies
|
||||
SET parameters_template='${JSON.stringify(
|
||||
strategy.parameters_template
|
||||
strategy.parameters_template,
|
||||
)}'
|
||||
WHERE name='${strategy.name}';`
|
||||
WHERE name='${strategy.name}';`,
|
||||
)
|
||||
.join('\n');
|
||||
|
||||
@ -78,6 +79,6 @@ exports.down = function(db, callback) {
|
||||
populateOldData.bind(db),
|
||||
db.removeColumn.bind(db, 'strategies', 'parameters'),
|
||||
],
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
@ -11,10 +11,10 @@ exports.up = function(db, cb) {
|
||||
}),
|
||||
db.runSql.bind(
|
||||
db,
|
||||
"UPDATE strategies SET built_in=1 where name='default'"
|
||||
"UPDATE strategies SET built_in=1 where name='default'",
|
||||
),
|
||||
],
|
||||
cb
|
||||
cb,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const strategies = require('./default-strategies.json');
|
||||
const async = require('async');
|
||||
const strategies = require('./default-strategies.json');
|
||||
|
||||
function insertStrategySQL(strategy) {
|
||||
return `
|
||||
INSERT INTO strategies (name, description, parameters, built_in)
|
||||
SELECT '${strategy.name}', '${strategy.description}', '${JSON.stringify(
|
||||
strategy.parameters
|
||||
strategy.parameters,
|
||||
)}', 1
|
||||
WHERE
|
||||
NOT EXISTS (
|
||||
@ -50,7 +50,7 @@ exports.up = function(db, callback) {
|
||||
db.runSql.bind(db, insertEventsSQL(s)),
|
||||
db.runSql.bind(db, insertStrategySQL(s)),
|
||||
],
|
||||
cb
|
||||
cb,
|
||||
);
|
||||
});
|
||||
async.series(insertStrategies, callback);
|
||||
@ -65,7 +65,7 @@ exports.down = function(db, callback) {
|
||||
db.runSql.bind(db, removeEventsSQL(s)),
|
||||
db.runSql.bind(db, removeStrategySQL(s)),
|
||||
],
|
||||
cb
|
||||
cb,
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -13,7 +13,7 @@ ALTER TABLE client_instances ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZO
|
||||
ALTER TABLE client_instances ALTER COLUMN last_seen TYPE TIMESTAMP WITH TIME ZONE;
|
||||
ALTER TABLE client_metrics ALTER COLUMN created_at TYPE TIMESTAMP WITH TIME ZONE;
|
||||
`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -3,13 +3,13 @@
|
||||
exports.up = function(db, callback) {
|
||||
db.runSql(
|
||||
'ALTER TABLE client_instances ADD "sdk_version" varchar(255);',
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
||||
exports.down = function(db, callback) {
|
||||
db.runSql(
|
||||
'ALTER TABLE client_instances DROP COLUMN "sdk_version";',
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ exports.up = function(db, callback) {
|
||||
ALTER TABLE features ADD "variants" json;
|
||||
ALTER TABLE features ALTER COLUMN "variants" SET DEFAULT '[]';
|
||||
`,
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const flexibleRollout = require('./flexible-rollout-strategy.json');
|
||||
const async = require('async');
|
||||
const flexibleRollout = require('./flexible-rollout-strategy.json');
|
||||
|
||||
function insertStrategySQL(strategy) {
|
||||
return `
|
||||
INSERT INTO strategies (name, description, parameters, built_in)
|
||||
SELECT '${strategy.name}', '${strategy.description}', '${JSON.stringify(
|
||||
strategy.parameters
|
||||
strategy.parameters,
|
||||
)}', 1
|
||||
WHERE
|
||||
NOT EXISTS (
|
||||
@ -49,7 +49,7 @@ exports.up = function(db, callback) {
|
||||
db.runSql.bind(db, insertEventsSQL(flexibleRollout)),
|
||||
db.runSql.bind(db, insertStrategySQL(flexibleRollout)),
|
||||
],
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
||||
@ -59,6 +59,6 @@ exports.down = function(db, callback) {
|
||||
db.runSql.bind(db, removeEventsSQL(flexibleRollout)),
|
||||
db.runSql.bind(db, removeStrategySQL(flexibleRollout)),
|
||||
],
|
||||
callback
|
||||
callback,
|
||||
);
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* eslint camelcase: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
const async = require('async');
|
||||
@ -25,10 +26,10 @@ exports.up = function(db, cb) {
|
||||
INSERT INTO context_fields(name, description, sort_order) VALUES('environment', 'Allows you to constrain on application environment', 0);
|
||||
INSERT INTO context_fields(name, description, sort_order) VALUES('userId', 'Allows you to constrain on userId', 1);
|
||||
INSERT INTO context_fields(name, description, sort_order) VALUES('appName', 'Allows you to constrain on application name', 2);
|
||||
`
|
||||
`,
|
||||
),
|
||||
],
|
||||
cb
|
||||
cb,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* eslint camelcase: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
exports.up = function(db, cb) {
|
||||
@ -13,7 +14,7 @@ exports.up = function(db, cb) {
|
||||
},
|
||||
content: { type: 'json' },
|
||||
},
|
||||
cb
|
||||
cb,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* eslint camelcase: "off" */
|
||||
|
||||
'use strict';
|
||||
|
||||
const crypto = require('crypto');
|
||||
@ -12,7 +13,7 @@ exports.up = function(db, cb) {
|
||||
`
|
||||
INSERT INTO settings(name, content)
|
||||
VALUES('${settingsName}', '${JSON.stringify(secret)}')`,
|
||||
cb
|
||||
cb,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,7 @@ require('db-migrate-shared').log.setLogLevel('error');
|
||||
const { getInstance } = require('db-migrate');
|
||||
|
||||
function migrateDb({ db, databaseSchema = 'public' }) {
|
||||
const custom = Object.assign({}, db, { schema: databaseSchema });
|
||||
const custom = { ...db, schema: databaseSchema };
|
||||
const dbmigrate = getInstance(true, {
|
||||
cwd: __dirname,
|
||||
config: { custom },
|
||||
|
@ -69,6 +69,7 @@
|
||||
"cookie-session": "^2.0.0-beta.3",
|
||||
"db-migrate": "^0.11.6",
|
||||
"db-migrate-pg": "^1.0.0",
|
||||
"db-migrate-shared": "^1.2.0",
|
||||
"deep-diff": "^1.0.2",
|
||||
"deepmerge": "^4.2.2",
|
||||
"errorhandler": "^1.5.1",
|
||||
@ -96,15 +97,17 @@
|
||||
"ava": "^3.7.0",
|
||||
"coveralls": "^3.0.6",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-finn": "^3.0.1",
|
||||
"eslint-config-finn-prettier": "^3.0.2",
|
||||
"eslint-config-airbnb-base": "^14.1.0",
|
||||
"eslint-config-prettier": "^6.10.1",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"husky": "^4.2.3",
|
||||
"lint-staged": "^10.0.7",
|
||||
"lolex": "^6.0.0",
|
||||
"nyc": "^15.0.0",
|
||||
"passport": "^0.4.1",
|
||||
"passport-google-auth": "^1.0.2",
|
||||
"prettier": "^1.18.2",
|
||||
"prettier": "^1.19.1",
|
||||
"proxyquire": "^2.1.3",
|
||||
"superagent": "^5.1.0",
|
||||
"supertest": "^4.0.2",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user