From d01c9d2dac635d4abbe6b75ff379b0e8543a1ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20Conradi=20=C3=98sthus?= Date: Tue, 14 Apr 2020 22:29:11 +0200 Subject: [PATCH] fix: use airbnb lint rules directly (#583) This drops usage of finn-eslint rules as they are no longer maintained. --- .eslintrc | 21 +- bin/unleash.js | 12 +- examples/basic-auth-hook.js | 14 +- examples/basic-auth-unleash.js | 3 +- examples/client-auth-unleash.js | 3 +- examples/google-auth-hook.js | 45 +- examples/google-auth-unleash.js | 3 +- examples/keycloak-auth-hook.js | 44 +- examples/keycloak-auth-unleash.js | 3 +- lib/app.js | 2 +- lib/app.test.js | 1 + lib/client-metrics/client-metrics.test.js | 2 +- lib/client-metrics/index.js | 13 +- lib/client-metrics/list.js | 3 + lib/client-metrics/ttl-list.js | 4 +- lib/client-metrics/ttl-list.test.js | 2 +- lib/db/client-applications-store.js | 13 +- lib/db/client-instance-store.js | 10 +- lib/db/client-metrics-store.js | 2 +- lib/db/client-metrics-store.test.js | 4 +- lib/db/context-field-store.js | 18 +- lib/db/event-store.js | 4 +- lib/db/feature-toggle-store.js | 21 +- lib/db/index.js | 8 +- lib/db/setting-store.js | 7 +- lib/db/strategy-store.js | 19 +- lib/event-differ.js | 11 +- lib/event-differ.test.js | 2 +- lib/event-hook.test.js | 3 +- lib/logger.js | 51 +-- lib/logger.test.js | 4 +- lib/metrics-helper.js | 2 + lib/metrics.js | 7 +- lib/metrics.test.js | 11 +- lib/middleware/no-authentication.test.js | 2 +- lib/middleware/permission-checker.js | 2 +- lib/middleware/permission-checker.test.js | 6 +- lib/middleware/simple-authentication.js | 25 +- lib/options.js | 22 +- lib/options.test.js | 17 +- lib/routes/admin-api/archive.js | 2 +- lib/routes/admin-api/archive.test.js | 6 +- lib/routes/admin-api/config.test.js | 6 +- lib/routes/admin-api/context.js | 8 +- lib/routes/admin-api/context.test.js | 6 +- lib/routes/admin-api/event.js | 1 + lib/routes/admin-api/events.test.js | 6 +- lib/routes/admin-api/feature-schema.js | 2 +- lib/routes/admin-api/feature-schema.test.js | 2 +- lib/routes/admin-api/feature.js | 11 +- lib/routes/admin-api/feature.test.js | 20 +- lib/routes/admin-api/metrics.js | 23 +- lib/routes/admin-api/metrics.test.js | 6 +- lib/routes/admin-api/state.js | 9 +- lib/routes/admin-api/strategy-schema.js | 2 +- lib/routes/admin-api/strategy.js | 9 +- lib/routes/admin-api/strategy.test.js | 8 +- lib/routes/admin-api/user.js | 5 +- lib/routes/admin-api/user.test.js | 6 +- lib/routes/admin-api/util.js | 2 + lib/routes/api-def.js | 3 +- lib/routes/backstage.test.js | 6 +- lib/routes/client-api/feature.test.js | 6 +- lib/routes/client-api/index.js | 4 +- lib/routes/client-api/metrics.js | 4 +- lib/routes/client-api/metrics.test.js | 4 +- lib/routes/client-api/register.js | 2 +- lib/routes/client-api/register.test.js | 6 +- lib/routes/controller.js | 10 +- lib/routes/health-check.test.js | 8 +- lib/routes/index.test.js | 10 +- lib/routes/logout.test.js | 4 +- lib/server-impl.js | 23 +- lib/server-impl.test.js | 2 +- lib/state-service.js | 16 +- lib/state-service.test.js | 4 +- lib/timer.test.js | 4 +- lib/user.js | 2 +- lib/user.test.js | 4 +- migrations/20141020151056-initial-schema.js | 4 +- ...5-add-parameters-template-to-strategies.js | 4 +- .../20141117202209-insert-default-strategy.js | 4 +- .../20141118071458-default-strategy-event.js | 4 +- .../20150210152531-006-rename-eventtype.js | 4 +- ...160618193924-add-strategies-to-features.js | 4 +- migrations/20161027134128-create-metrics.js | 2 +- .../20161104074441-create-client-instances.js | 2 +- ...161205203516-create-client-applications.js | 3 +- ...9-better-strategy-parameter-definitions.js | 13 +- .../20170211085502-built-in-strategies.js | 4 +- .../20170211090541-add-default-strategies.js | 8 +- .../20170306233934-timestamp-with-tz.js | 2 +- ...541-add-sdk-version-to-client-instances.js | 4 +- ...20190123204125-add-variants-to-features.js | 2 +- ...0191023184858-flexible-rollout-strategy.js | 8 +- .../20200102184820-create-context-fields.js | 5 +- migrations/20200227202711-settings.js | 3 +- migrations/20200329191251-settings-secret.js | 3 +- migrator.js | 2 +- package.json | 9 +- test/e2e/api/admin/context.e2e.test.js | 2 +- .../e2e/api/admin/feature-archive.e2e.test.js | 4 +- test/e2e/api/admin/feature.auth.e2e.test.js | 2 +- .../api/admin/feature.custom-auth.e2e.test.js | 10 +- test/e2e/api/admin/feature.e2e.test.js | 4 +- test/e2e/api/admin/metrics.e2e.test.js | 2 +- test/e2e/api/admin/strategy.e2e.test.js | 2 +- test/e2e/api/client/metrics.e2e.test.js | 2 +- test/e2e/helpers/database-init.js | 25 +- test/e2e/helpers/test-helper.js | 2 +- test/fixtures/fake-context-store.js | 3 +- test/fixtures/fake-feature-toggle-store.js | 11 +- test/fixtures/fake-metrics-store.js | 1 + test/fixtures/fake-strategies-store.js | 3 +- test/fixtures/no-logger.js | 2 + yarn.lock | 385 ++++++++++++++++-- 116 files changed, 809 insertions(+), 453 deletions(-) diff --git a/.eslintrc b/.eslintrc index 5add26ae43..8006a8d315 100644 --- a/.eslintrc +++ b/.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", diff --git a/bin/unleash.js b/bin/unleash.js index eeab1271f6..710c211153 100755 --- a/bin/unleash.js +++ b/bin/unleash.js @@ -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); diff --git a/examples/basic-auth-hook.js b/examples/basic-auth-hook.js index 7d09b27278..09f078d42a 100644 --- a/examples/basic-auth-hook.js +++ b/examples/basic-auth-hook.js @@ -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) => { diff --git a/examples/basic-auth-unleash.js b/examples/basic-auth-unleash.js index 84c15f7c4a..61b08e8fba 100644 --- a/examples/basic-auth-unleash.js +++ b/examples/basic-auth-unleash.js @@ -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')}`, ); }); diff --git a/examples/client-auth-unleash.js b/examples/client-auth-unleash.js index 237decdb48..2c7d6c597e 100644 --- a/examples/client-auth-unleash.js +++ b/examples/client-auth-unleash.js @@ -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')}`, ); }); diff --git a/examples/google-auth-hook.js b/examples/google-auth-hook.js index aa1228a602..4203606e09 100644 --- a/examples/google-auth-hook.js +++ b/examples/google-auth-hook.js @@ -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(); }); } diff --git a/examples/google-auth-unleash.js b/examples/google-auth-unleash.js index 12d0c2b157..122891f222 100644 --- a/examples/google-auth-unleash.js +++ b/examples/google-auth-unleash.js @@ -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')}`, ); }); diff --git a/examples/keycloak-auth-hook.js b/examples/keycloak-auth-hook.js index 29f28c6391..2cc0e02bfa 100644 --- a/examples/keycloak-auth-hook.js +++ b/examples/keycloak-auth-hook.js @@ -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(); }); } diff --git a/examples/keycloak-auth-unleash.js b/examples/keycloak-auth-unleash.js index 5ac6b14005..28e5597317 100644 --- a/examples/keycloak-auth-unleash.js +++ b/examples/keycloak-auth-unleash.js @@ -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')}`, ); }); diff --git a/lib/app.js b/lib/app.js index 72358b7e88..28c45b23d4 100644 --- a/lib/app.js +++ b/lib/app.js @@ -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'); diff --git a/lib/app.test.js b/lib/app.test.js index ce75c44e69..f81e346169 100644 --- a/lib/app.test.js +++ b/lib/app.test.js @@ -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() { diff --git a/lib/client-metrics/client-metrics.test.js b/lib/client-metrics/client-metrics.test.js index 90698eee51..be58a42369 100644 --- a/lib/client-metrics/client-metrics.test.js +++ b/lib/client-metrics/client-metrics.test.js @@ -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'; diff --git a/lib/client-metrics/index.js b/lib/client-metrics/index.js index 903f0a5b67..67869c22ec 100644 --- a/lib/client-metrics/index.js +++ b/lib/client-metrics/index.js @@ -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]) => { diff --git a/lib/client-metrics/list.js b/lib/client-metrics/list.js index 80f2150ec6..e0829352de 100644 --- a/lib/client-metrics/list.js +++ b/lib/client-metrics/list.js @@ -1,3 +1,6 @@ +/* eslint-disable no-param-reassign */ +/* eslint-disable max-classes-per-file */ + 'use strict'; const { EventEmitter } = require('events'); diff --git a/lib/client-metrics/ttl-list.js b/lib/client-metrics/ttl-list.js index 34333d1a39..c996f92f65 100644 --- a/lib/client-metrics/ttl-list.js +++ b/lib/client-metrics/ttl-list.js @@ -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(); } diff --git a/lib/client-metrics/ttl-list.test.js b/lib/client-metrics/ttl-list.test.js index 140c358ecb..8e4512e58b 100644 --- a/lib/client-metrics/ttl-list.test.js +++ b/lib/client-metrics/ttl-list.test.js @@ -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(); diff --git a/lib/db/client-applications-store.js b/lib/db/client-applications-store.js index a366978f92..9317b191b9 100644 --- a/lib/db/client-applications-store.js +++ b/lib/db/client-applications-store.js @@ -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)), ); } diff --git a/lib/db/client-instance-store.js b/lib/db/client-instance-store.js index 8b77cc1f9d..4b288b82b3 100644 --- a/lib/db/client-instance-store.js +++ b/lib/db/client-instance-store.js @@ -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', - }) + }), ); } diff --git a/lib/db/client-metrics-store.js b/lib/db/client-metrics-store.js index 9e83e256cf..ae95b67bb9 100644 --- a/lib/db/client-metrics-store.js +++ b/lib/db/client-metrics-store.js @@ -52,7 +52,7 @@ class ClientMetricsStore extends EventEmitter { metricsHelper.wrapTimer(this.eventBus, DB_TIME, { store: 'metrics', action: 'insert', - }) + }), ); } diff --git a/lib/db/client-metrics-store.test.js b/lib/db/client-metrics-store.test.js index 3b7bad1461..6e3548c03c 100644 --- a/lib/db/client-metrics-store.test.js +++ b/lib/db/client-metrics-store.test.js @@ -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); diff --git a/lib/db/context-field-store.js b/lib/db/context-field-store.js index c3686d5f9e..8214d2e023 100644 --- a/lib/db/context-field-store.js +++ b/lib/db/context-field-store.js @@ -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, ); }); } diff --git a/lib/db/event-store.js b/lib/db/event-store.js index a150ecdf84..e03ad0d06d 100644 --- a/lib/db/event-store.js +++ b/lib/db/event-store.js @@ -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); diff --git a/lib/db/feature-toggle-store.js b/lib/db/feature-toggle-store.js index 31d5d0727b..6e0407146b 100644 --- a/lib/db/feature-toggle-store.js +++ b/lib/db/feature-toggle-store.js @@ -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), ); } } diff --git a/lib/db/index.js b/lib/db/index.js index c1d0f33808..13714826b7 100644 --- a/lib/db/index.js +++ b/lib/db/index.js @@ -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), }; diff --git a/lib/db/setting-store.js b/lib/db/setting-store.js index db07b9da70..d02a27a646 100644 --- a/lib/db/setting-store.js +++ b/lib/db/setting-store.js @@ -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; } } diff --git a/lib/db/strategy-store.js b/lib/db/strategy-store.js index 578bd02a05..34fe58ddf7 100644 --- a/lib/db/strategy-store.js +++ b/lib/db/strategy-store.js @@ -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), ); } } diff --git a/lib/event-differ.js b/lib/event-differ.js index 27f8613721..3ff18bc338 100644 --- a/lib/event-differ.js +++ b/lib/event-differ.js @@ -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); diff --git a/lib/event-differ.test.js b/lib/event-differ.test.js index 4a372c4196..dcdb37c357 100644 --- a/lib/event-differ.test.js +++ b/lib/event-differ.test.js @@ -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'); diff --git a/lib/event-hook.test.js b/lib/event-hook.test.js index ed75d43fbd..036cc82171 100644 --- a/lib/event-hook.test.js +++ b/lib/event-hook.test.js @@ -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); }); - } + }, ); diff --git a/lib/logger.js b/lib/logger.js index a4758aaf7f..493b38432a 100644 --- a/lib/logger.js +++ b/lib/logger.js @@ -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`); +}; diff --git a/lib/logger.test.js b/lib/logger.test.js index 585dd1191f..fe5212a9a5 100644 --- a/lib/logger.test.js +++ b/lib/logger.test.js @@ -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'); }); diff --git a/lib/metrics-helper.js b/lib/metrics-helper.js index 6ac9541ef0..22f0291838 100644 --- a/lib/metrics-helper.js +++ b/lib/metrics-helper.js @@ -1,3 +1,5 @@ +/* eslint-disable no-param-reassign */ + 'use strict'; const timer = require('./timer'); diff --git a/lib/metrics.js b/lib/metrics.js index 78f77e44c5..d370d0ace3 100644 --- a/lib/metrics.js +++ b/lib/metrics.js @@ -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); diff --git a/lib/metrics.test.js b/lib/metrics.test.js index d5c03d8583..290668a5fe 100644 --- a/lib/metrics.test.js +++ b/lib/metrics.test.js @@ -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/, ); }); diff --git a/lib/middleware/no-authentication.test.js b/lib/middleware/no-authentication.test.js index 6dc1886c87..5ceef1c9ae 100644 --- a/lib/middleware/no-authentication.test.js +++ b/lib/middleware/no-authentication.test.js @@ -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) diff --git a/lib/middleware/permission-checker.js b/lib/middleware/permission-checker.js index 5f982f5f99..9c67a752f7 100644 --- a/lib/middleware/permission-checker.js +++ b/lib/middleware/permission-checker.js @@ -22,7 +22,7 @@ module.exports = function(config, permission) { new MissingPermission({ permission, message: `You require ${permission} to perform this action`, - }) + }), ) .end(); }; diff --git a/lib/middleware/permission-checker.test.js b/lib/middleware/permission-checker.test.js index 11e4145ab2..23691bc67e 100644 --- a/lib/middleware/permission-checker.test.js +++ b/lib/middleware/permission-checker.test.js @@ -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(); - } + }, ); }, }); diff --git a/lib/middleware/simple-authentication.js b/lib/middleware/simple-authentication.js index 0a5cc79fc1..db921c3b2a 100644 --- a/lib/middleware/simple-authentication.js +++ b/lib/middleware/simple-authentication.js @@ -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) => { diff --git a/lib/options.js b/lib/options.js index f46c0a50bf..ad53b8ef89 100644 --- a/lib/options.js +++ b/lib/options.js @@ -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`, ); } diff --git a/lib/options.test.js b/lib/options.test.js index 474126f0a0..846b01560c 100644 --- a/lib/options.test.js +++ b/lib/options.test.js @@ -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); diff --git a/lib/routes/admin-api/archive.js b/lib/routes/admin-api/archive.js index 202270fc45..4831c501dd 100644 --- a/lib/routes/admin-api/archive.js +++ b/lib/routes/admin-api/archive.js @@ -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(); diff --git a/lib/routes/admin-api/archive.test.js b/lib/routes/admin-api/archive.test.js index 0219f3ccd8..9bc6108dad 100644 --- a/lib/routes/admin-api/archive.test.js +++ b/lib/routes/admin-api/archive.test.js @@ -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() { diff --git a/lib/routes/admin-api/config.test.js b/lib/routes/admin-api/config.test.js index 7038000cc0..1b84d0de8e 100644 --- a/lib/routes/admin-api/config.test.js +++ b/lib/routes/admin-api/config.test.js @@ -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 = { diff --git a/lib/routes/admin-api/context.js b/lib/routes/admin-api/context.js index 2d95911731..bf2fa9a478 100644 --- a/lib/routes/admin-api/context.js +++ b/lib/routes/admin-api/context.js @@ -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 }); diff --git a/lib/routes/admin-api/context.test.js b/lib/routes/admin-api/context.test.js index 988a09568d..98ec5b3648 100644 --- a/lib/routes/admin-api/context.test.js +++ b/lib/routes/admin-api/context.test.js @@ -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() { diff --git a/lib/routes/admin-api/event.js b/lib/routes/admin-api/event.js index 963306564c..12f058a268 100644 --- a/lib/routes/admin-api/event.js +++ b/lib/routes/admin-api/event.js @@ -3,6 +3,7 @@ const Controller = require('../controller'); const eventDiffer = require('../../event-differ'); + const version = 1; class EventController extends Controller { diff --git a/lib/routes/admin-api/events.test.js b/lib/routes/admin-api/events.test.js index ff01752fee..687f18e924 100644 --- a/lib/routes/admin-api/events.test.js +++ b/lib/routes/admin-api/events.test.js @@ -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() { diff --git a/lib/routes/admin-api/feature-schema.js b/lib/routes/admin-api/feature-schema.js index 0176c46e10..e474bb75cf 100644 --- a/lib/routes/admin-api/feature-schema.js +++ b/lib/routes/admin-api/feature-schema.js @@ -41,7 +41,7 @@ const variantsSchema = joi.object().keys({ contextName: joi.string().required(), values: joi.array().items(joi.string()), }) - .optional() + .optional(), ), }); diff --git a/lib/routes/admin-api/feature-schema.test.js b/lib/routes/admin-api/feature-schema.test.js index 3701624adb..df587f9f38 100644 --- a/lib/routes/admin-api/feature-schema.test.js +++ b/lib/routes/admin-api/feature-schema.test.js @@ -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', ); } }); diff --git a/lib/routes/admin-api/feature.js b/lib/routes/admin-api/feature.js index fc1def07b7..e52fab4c4b 100644 --- a/lib/routes/admin-api/feature.js +++ b/lib/routes/admin-api/feature.js @@ -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 { diff --git a/lib/routes/admin-api/feature.test.js b/lib/routes/admin-api/feature.test.js index 8268e3e326..c913a24108 100644 --- a/lib/routes/admin-api/feature.test.js +++ b/lib/routes/admin-api/feature.test.js @@ -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', ); }); }); diff --git a/lib/routes/admin-api/metrics.js b/lib/routes/admin-api/metrics.js index d4c04b0efe..05149e9873 100644 --- a/lib/routes/admin-api/metrics.js +++ b/lib/routes/admin-api/metrics.js @@ -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}`, diff --git a/lib/routes/admin-api/metrics.test.js b/lib/routes/admin-api/metrics.test.js index 08bb6603da..f5326b9e71 100644 --- a/lib/routes/admin-api/metrics.test.js +++ b/lib/routes/admin-api/metrics.test.js @@ -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() { diff --git a/lib/routes/admin-api/state.js b/lib/routes/admin-api/state.js index 55221aa48c..3d42bd605a 100644 --- a/lib/routes/admin-api/state.js +++ b/lib/routes/admin-api/state.js @@ -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 { diff --git a/lib/routes/admin-api/strategy-schema.js b/lib/routes/admin-api/strategy-schema.js index c7052be919..90feea36d9 100644 --- a/lib/routes/admin-api/strategy-schema.js +++ b/lib/routes/admin-api/strategy-schema.js @@ -24,7 +24,7 @@ const strategySchema = joi.object().keys({ .allow('') .optional(), required: joi.boolean(), - }) + }), ), }); diff --git a/lib/routes/admin-api/strategy.js b/lib/routes/admin-api/strategy.js index 6fce18c8bc..8777e764e2 100644 --- a/lib/routes/admin-api/strategy.js +++ b/lib/routes/admin-api/strategy.js @@ -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)); }); diff --git a/lib/routes/admin-api/strategy.test.js b/lib/routes/admin-api/strategy.test.js index ae591d26d8..d67f964325 100644 --- a/lib/routes/admin-api/strategy.test.js +++ b/lib/routes/admin-api/strategy.test.js @@ -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', ); }); }); diff --git a/lib/routes/admin-api/user.js b/lib/routes/admin-api/user.js index d66c3018bc..02ade85c3f 100644 --- a/lib/routes/admin-api/user.js +++ b/lib/routes/admin-api/user.js @@ -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. diff --git a/lib/routes/admin-api/user.test.js b/lib/routes/admin-api/user.test.js index 116759428f..f05eef122f 100644 --- a/lib/routes/admin-api/user.test.js +++ b/lib/routes/admin-api/user.test.js @@ -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' }); diff --git a/lib/routes/admin-api/util.js b/lib/routes/admin-api/util.js index 2c8964792f..08787ae6d6 100644 --- a/lib/routes/admin-api/util.js +++ b/lib/routes/admin-api/util.js @@ -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) diff --git a/lib/routes/api-def.js b/lib/routes/api-def.js index 6f138b02c2..7f1c60f32e 100644 --- a/lib/routes/api-def.js +++ b/lib/routes/api-def.js @@ -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'); diff --git a/lib/routes/backstage.test.js b/lib/routes/backstage.test.js index eaf434f7ad..e385380077 100644 --- a/lib/routes/backstage.test.js +++ b/lib/routes/backstage.test.js @@ -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 => { diff --git a/lib/routes/client-api/feature.test.js b/lib/routes/client-api/feature.test.js index 34d0af154b..8047e7e889 100644 --- a/lib/routes/client-api/feature.test.js +++ b/lib/routes/client-api/feature.test.js @@ -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() { diff --git a/lib/routes/client-api/index.js b/lib/routes/client-api/index.js index 362e58e3a9..72b22b9eac 100644 --- a/lib/routes/client-api/index.js +++ b/lib/routes/client-api/index.js @@ -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); diff --git a/lib/routes/client-api/metrics.js b/lib/routes/client-api/metrics.js index 6b53650358..6e5303e79d 100644 --- a/lib/routes/client-api/metrics.js +++ b/lib/routes/client-api/metrics.js @@ -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(); } } } diff --git a/lib/routes/client-api/metrics.test.js b/lib/routes/client-api/metrics.test.js index 9d06913707..0e176c8a79 100644 --- a/lib/routes/client-api/metrics.test.js +++ b/lib/routes/client-api/metrics.test.js @@ -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() { diff --git a/lib/routes/client-api/register.js b/lib/routes/client-api/register.js index 788dcf53f6..9bc10ad3b3 100644 --- a/lib/routes/client-api/register.js +++ b/lib/routes/client-api/register.js @@ -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) { diff --git a/lib/routes/client-api/register.test.js b/lib/routes/client-api/register.test.js index 163db88517..130305b17b 100644 --- a/lib/routes/client-api/register.test.js +++ b/lib/routes/client-api/register.test.js @@ -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() { diff --git a/lib/routes/controller.js b/lib/routes/controller.js index 81d3330d94..6bfa1a3de5 100644 --- a/lib/routes/controller.js +++ b/lib/routes/controller.js @@ -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), ); } diff --git a/lib/routes/health-check.test.js b/lib/routes/health-check.test.js index 74ab3d5bf9..4d889fc9e2 100644 --- a/lib/routes/health-check.test.js +++ b/lib/routes/health-check.test.js @@ -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, diff --git a/lib/routes/index.test.js b/lib/routes/index.test.js index b74f2f25d0..5262c4b6a5 100644 --- a/lib/routes/index.test.js +++ b/lib/routes/index.test.js @@ -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', ); }); }); diff --git a/lib/routes/logout.test.js b/lib/routes/logout.test.js index 4cc6da822c..109d6b9f1a 100644 --- a/lib/routes/logout.test.js +++ b/lib/routes/logout.test.js @@ -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' }); diff --git a/lib/server-impl.js b/lib/server-impl.js index e6e1414d33..cd7aefb47b 100644 --- a/lib/server-impl.js +++ b/lib/server-impl.js @@ -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); }); diff --git a/lib/server-impl.test.js b/lib/server-impl.test.js index ebcf06af88..5f259f9965 100644 --- a/lib/server-impl.test.js +++ b/lib/server-impl.test.js @@ -41,7 +41,7 @@ const serverImpl = proxyquire('./server-impl', { return o; }, }, - '../migrator'() { + '../migrator': function() { return Promise.resolve(); }, }); diff --git a/lib/state-service.js b/lib/state-service.js index f19de4f138..afbe6d6d01 100644 --- a/lib/state-service.js +++ b/lib/state-service.js @@ -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, - }) - ) + }), + ), ); } } diff --git a/lib/state-service.test.js b/lib/state-service.test.js index 306af816c8..24507b7ab9 100644 --- a/lib/state-service.test.js +++ b/lib/state-service.test.js @@ -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 { diff --git a/lib/timer.test.js b/lib/timer.test.js index 94c3e7a3a0..65c24d4b53 100644 --- a/lib/timer.test.js +++ b/lib/timer.test.js @@ -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(); }); diff --git a/lib/user.js b/lib/user.js index 6865083ec7..114ace9ab7 100644 --- a/lib/user.js +++ b/lib/user.js @@ -10,7 +10,7 @@ module.exports = class User { Joi.string() .email() .required(), - 'Email' + 'Email', ); this.email = email; this.name = name; diff --git a/lib/user.test.js b/lib/user.test.js index ca24124a9a..213d0f57df 100644 --- a/lib/user.test.js +++ b/lib/user.test.js @@ -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'); diff --git a/migrations/20141020151056-initial-schema.js b/migrations/20141020151056-initial-schema.js index 9da702afff..ca035cad02 100644 --- a/migrations/20141020151056-initial-schema.js +++ b/migrations/20141020151056-initial-schema.js @@ -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, ); }; diff --git a/migrations/20141117200435-add-parameters-template-to-strategies.js b/migrations/20141117200435-add-parameters-template-to-strategies.js index 6c478a5b39..05924341d5 100644 --- a/migrations/20141117200435-add-parameters-template-to-strategies.js +++ b/migrations/20141117200435-add-parameters-template-to-strategies.js @@ -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, ); }; diff --git a/migrations/20141117202209-insert-default-strategy.js b/migrations/20141117202209-insert-default-strategy.js index bbd52e444b..0687d75b07 100644 --- a/migrations/20141117202209-insert-default-strategy.js +++ b/migrations/20141117202209-insert-default-strategy.js @@ -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, ); }; diff --git a/migrations/20141118071458-default-strategy-event.js b/migrations/20141118071458-default-strategy-event.js index 070bd11c4b..007b5314ee 100644 --- a/migrations/20141118071458-default-strategy-event.js +++ b/migrations/20141118071458-default-strategy-event.js @@ -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, ); }; diff --git a/migrations/20150210152531-006-rename-eventtype.js b/migrations/20150210152531-006-rename-eventtype.js index d05f135a81..79ddb195e8 100644 --- a/migrations/20150210152531-006-rename-eventtype.js +++ b/migrations/20150210152531-006-rename-eventtype.js @@ -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, ); }; diff --git a/migrations/20160618193924-add-strategies-to-features.js b/migrations/20160618193924-add-strategies-to-features.js index 632ae4b4d1..3dff4ed569 100644 --- a/migrations/20160618193924-add-strategies-to-features.js +++ b/migrations/20160618193924-add-strategies-to-features.js @@ -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, ); }; diff --git a/migrations/20161027134128-create-metrics.js b/migrations/20161027134128-create-metrics.js index fbd4415cbe..65423c08d7 100644 --- a/migrations/20161027134128-create-metrics.js +++ b/migrations/20161027134128-create-metrics.js @@ -8,7 +8,7 @@ CREATE TABLE client_metrics ( created_at timestamp default now(), metrics json );`, - callback + callback, ); }; diff --git a/migrations/20161104074441-create-client-instances.js b/migrations/20161104074441-create-client-instances.js index 91ad0bd273..4446f096c8 100644 --- a/migrations/20161104074441-create-client-instances.js +++ b/migrations/20161104074441-create-client-instances.js @@ -10,7 +10,7 @@ exports.up = function(db, callback) { last_seen timestamp default now(), created_at timestamp default now() );`, - callback + callback, ); }; diff --git a/migrations/20161205203516-create-client-applications.js b/migrations/20161205203516-create-client-applications.js index 03e5994bcd..14e7b7962c 100644 --- a/migrations/20161205203516-create-client-applications.js +++ b/migrations/20161205203516-create-client-applications.js @@ -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, ); }; diff --git a/migrations/20161212101749-better-strategy-parameter-definitions.js b/migrations/20161212101749-better-strategy-parameter-definitions.js index ee8d201f4b..02112fc811 100644 --- a/migrations/20161212101749-better-strategy-parameter-definitions.js +++ b/migrations/20161212101749-better-strategy-parameter-definitions.js @@ -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, ); }; diff --git a/migrations/20170211085502-built-in-strategies.js b/migrations/20170211085502-built-in-strategies.js index a3e1f31e29..32972776ef 100644 --- a/migrations/20170211085502-built-in-strategies.js +++ b/migrations/20170211085502-built-in-strategies.js @@ -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, ); }; diff --git a/migrations/20170211090541-add-default-strategies.js b/migrations/20170211090541-add-default-strategies.js index b7a63610ed..ee04ceb587 100644 --- a/migrations/20170211090541-add-default-strategies.js +++ b/migrations/20170211090541-add-default-strategies.js @@ -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, ); }); diff --git a/migrations/20170306233934-timestamp-with-tz.js b/migrations/20170306233934-timestamp-with-tz.js index b153b14933..4fec7b7254 100644 --- a/migrations/20170306233934-timestamp-with-tz.js +++ b/migrations/20170306233934-timestamp-with-tz.js @@ -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, ); }; diff --git a/migrations/20170628205541-add-sdk-version-to-client-instances.js b/migrations/20170628205541-add-sdk-version-to-client-instances.js index 527a9e2cca..5b91435dcf 100644 --- a/migrations/20170628205541-add-sdk-version-to-client-instances.js +++ b/migrations/20170628205541-add-sdk-version-to-client-instances.js @@ -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, ); }; diff --git a/migrations/20190123204125-add-variants-to-features.js b/migrations/20190123204125-add-variants-to-features.js index 933de85e52..594bdc258e 100644 --- a/migrations/20190123204125-add-variants-to-features.js +++ b/migrations/20190123204125-add-variants-to-features.js @@ -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, ); }; diff --git a/migrations/20191023184858-flexible-rollout-strategy.js b/migrations/20191023184858-flexible-rollout-strategy.js index 7615944763..67d0197c67 100644 --- a/migrations/20191023184858-flexible-rollout-strategy.js +++ b/migrations/20191023184858-flexible-rollout-strategy.js @@ -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, ); }; diff --git a/migrations/20200102184820-create-context-fields.js b/migrations/20200102184820-create-context-fields.js index 49d3abf168..caa5ac92ce 100644 --- a/migrations/20200102184820-create-context-fields.js +++ b/migrations/20200102184820-create-context-fields.js @@ -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, ); }; diff --git a/migrations/20200227202711-settings.js b/migrations/20200227202711-settings.js index f41f4abf96..2fce551934 100644 --- a/migrations/20200227202711-settings.js +++ b/migrations/20200227202711-settings.js @@ -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, ); }; diff --git a/migrations/20200329191251-settings-secret.js b/migrations/20200329191251-settings-secret.js index 069ae2c792..032e7da479 100644 --- a/migrations/20200329191251-settings-secret.js +++ b/migrations/20200329191251-settings-secret.js @@ -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, ); }; diff --git a/migrator.js b/migrator.js index 4eaf116c5b..ef3d0e6921 100644 --- a/migrator.js +++ b/migrator.js @@ -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 }, diff --git a/package.json b/package.json index 8d02a536d8..a94a1230e0 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/test/e2e/api/admin/context.e2e.test.js b/test/e2e/api/admin/context.e2e.test.js index 94854224e0..8a9648bb16 100644 --- a/test/e2e/api/admin/context.e2e.test.js +++ b/test/e2e/api/admin/context.e2e.test.js @@ -104,7 +104,7 @@ test.serial( .send({ name: 'userId' }) .set('Content-Type', 'application/json') .expect(400); - } + }, ); test.serial('should delete context field', async t => { diff --git a/test/e2e/api/admin/feature-archive.e2e.test.js b/test/e2e/api/admin/feature-archive.e2e.test.js index 70bbc3709e..6e619fc734 100644 --- a/test/e2e/api/admin/feature-archive.e2e.test.js +++ b/test/e2e/api/admin/feature-archive.e2e.test.js @@ -1,7 +1,7 @@ 'use strict'; const test = require('ava'); -const { setupApp } = require('./../../helpers/test-helper'); +const { setupApp } = require('../../helpers/test-helper'); const dbInit = require('../../helpers/database-init'); const getLogger = require('../../../fixtures/no-logger'); @@ -47,7 +47,7 @@ test.serial( .get('/api/admin/features/featureArchivedZ') .set('Content-Type', 'application/json') .expect(404); - } + }, ); test.serial('must set name when reviving toggle', async t => { diff --git a/test/e2e/api/admin/feature.auth.e2e.test.js b/test/e2e/api/admin/feature.auth.e2e.test.js index 499b9a70cd..8e14c3be18 100644 --- a/test/e2e/api/admin/feature.auth.e2e.test.js +++ b/test/e2e/api/admin/feature.auth.e2e.test.js @@ -1,7 +1,7 @@ 'use strict'; const test = require('ava'); -const { setupAppWithAuth } = require('./../../helpers/test-helper'); +const { setupAppWithAuth } = require('../../helpers/test-helper'); const dbInit = require('../../helpers/database-init'); const getLogger = require('../../../fixtures/no-logger'); diff --git a/test/e2e/api/admin/feature.custom-auth.e2e.test.js b/test/e2e/api/admin/feature.custom-auth.e2e.test.js index 8c21156584..6007995113 100644 --- a/test/e2e/api/admin/feature.custom-auth.e2e.test.js +++ b/test/e2e/api/admin/feature.custom-auth.e2e.test.js @@ -1,9 +1,9 @@ 'use strict'; const test = require('ava'); -const { setupAppWithCustomAuth } = require('./../../helpers/test-helper'); -const AuthenticationRequired = require('./../../../../lib/authentication-required'); -const User = require('./../../../../lib/user'); +const { setupAppWithCustomAuth } = require('../../helpers/test-helper'); +const AuthenticationRequired = require('../../../../lib/authentication-required'); +const User = require('../../../../lib/user'); const dbInit = require('../../helpers/database-init'); const getLogger = require('../../../fixtures/no-logger'); @@ -30,9 +30,9 @@ test.serial('should require authenticated user', async t => { path: '/api/admin/login', type: 'custom', message: `You have to identify yourself.`, - }) + }), ) - .end() + .end(), ); }; const request = await setupAppWithCustomAuth(stores, preHook); diff --git a/test/e2e/api/admin/feature.e2e.test.js b/test/e2e/api/admin/feature.e2e.test.js index d3412981a2..29bdfa53d0 100644 --- a/test/e2e/api/admin/feature.e2e.test.js +++ b/test/e2e/api/admin/feature.e2e.test.js @@ -120,7 +120,7 @@ test.serial( .send({ name: 'should-not-exist', enabled: false }) .set('Content-Type', 'application/json') .expect(404); - } + }, ); test.serial('can change status of feature toggle that does exist', async t => { @@ -207,7 +207,7 @@ test.serial( }) .set('Content-Type', 'application/json') .expect(200); - } + }, ); test.serial('should not be possible to create archived toggle', async t => { diff --git a/test/e2e/api/admin/metrics.e2e.test.js b/test/e2e/api/admin/metrics.e2e.test.js index 9109103c66..f8691f066b 100644 --- a/test/e2e/api/admin/metrics.e2e.test.js +++ b/test/e2e/api/admin/metrics.e2e.test.js @@ -56,7 +56,7 @@ test.serial('should allow client to register multiple times', async t => { request .post('/api/client/register') .send(clientRegistration) - .expect(202) + .expect(202), ); }); diff --git a/test/e2e/api/admin/strategy.e2e.test.js b/test/e2e/api/admin/strategy.e2e.test.js index f166520367..077efdb74f 100644 --- a/test/e2e/api/admin/strategy.e2e.test.js +++ b/test/e2e/api/admin/strategy.e2e.test.js @@ -27,7 +27,7 @@ test.serial('gets all strategies', async t => { .expect(res => { t.true( res.body.strategies.length === 2, - 'expected to have two strategies' + 'expected to have two strategies', ); }); }); diff --git a/test/e2e/api/client/metrics.e2e.test.js b/test/e2e/api/client/metrics.e2e.test.js index 7496738303..6ddaab0dfa 100644 --- a/test/e2e/api/client/metrics.e2e.test.js +++ b/test/e2e/api/client/metrics.e2e.test.js @@ -2,7 +2,7 @@ const test = require('ava'); -const { setupApp } = require('./../../helpers/test-helper'); +const { setupApp } = require('../../helpers/test-helper'); const metricsExample = require('../../../examples/client-metrics.json'); const dbInit = require('../../helpers/database-init'); const getLogger = require('../../../fixtures/no-logger'); diff --git a/test/e2e/helpers/database-init.js b/test/e2e/helpers/database-init.js index cae9ed6cb8..7f3b14d070 100644 --- a/test/e2e/helpers/database-init.js +++ b/test/e2e/helpers/database-init.js @@ -4,6 +4,7 @@ const { EventEmitter } = require('events'); const migrator = require('../../../migrator'); const { createStores } = require('../../../lib/db'); const { createDb } = require('../../../lib/db/db-pool'); +const dbConfig = require('./database-config'); const dbState = require('./database.json'); @@ -25,17 +26,6 @@ async function resetDatabase(stores) { ]); } -async function setupDatabase(stores) { - const updates = []; - updates.push(...createStrategies(stores.strategyStore)); - updates.push(...createContextFields(stores.contextFieldStore)); - updates.push(...createFeatures(stores.featureToggleStore)); - updates.push(...createClientInstance(stores.clientInstanceStore)); - updates.push(...createApplications(stores.clientApplicationsStore)); - - await Promise.all(updates); -} - function createStrategies(store) { return dbState.strategies.map(s => store._createStrategy(s)); } @@ -56,9 +46,20 @@ function createFeatures(store) { return dbState.features.map(f => store._createFeature(f)); } +async function setupDatabase(stores) { + const updates = []; + updates.push(...createStrategies(stores.strategyStore)); + updates.push(...createContextFields(stores.contextFieldStore)); + updates.push(...createFeatures(stores.featureToggleStore)); + updates.push(...createClientInstance(stores.clientInstanceStore)); + updates.push(...createApplications(stores.clientApplicationsStore)); + + await Promise.all(updates); +} + module.exports = async function init(databaseSchema = 'test', getLogger) { const options = { - db: require('./database-config').getDb(), + db: dbConfig.getDb(), databaseSchema, minPool: 1, maxPool: 1, diff --git a/test/e2e/helpers/test-helper.js b/test/e2e/helpers/test-helper.js index ab43d484d7..22beeed54d 100644 --- a/test/e2e/helpers/test-helper.js +++ b/test/e2e/helpers/test-helper.js @@ -4,11 +4,11 @@ process.env.NODE_ENV = 'test'; const supertest = require('supertest'); +const { EventEmitter } = require('events'); const getApp = require('../../../lib/app'); const getLogger = require('../../fixtures/no-logger'); const StateService = require('../../../lib/state-service'); -const { EventEmitter } = require('events'); const eventBus = new EventEmitter(); function createApp(stores, adminAuthentication = 'none', preHook) { diff --git a/test/fixtures/fake-context-store.js b/test/fixtures/fake-context-store.js index 67f3ec7c83..851d1e6f46 100644 --- a/test/fixtures/fake-context-store.js +++ b/test/fixtures/fake-context-store.js @@ -15,9 +15,8 @@ module.exports = () => { const field = _contextFields.find(c => c.name === name); if (field) { return Promise.resolve(field); - } else { - return Promise.reject(NotFoundError); } + return Promise.reject(NotFoundError); }, create: contextField => _contextFields.push(contextField), }; diff --git a/test/fixtures/fake-feature-toggle-store.js b/test/fixtures/fake-feature-toggle-store.js index fdd4946f15..ee4c581eb7 100644 --- a/test/fixtures/fake-feature-toggle-store.js +++ b/test/fixtures/fake-feature-toggle-store.js @@ -8,20 +8,19 @@ module.exports = () => { const toggle = _features.find(f => f.name === name); if (toggle) { return Promise.resolve(toggle); - } else { - return Promise.reject(); } + return Promise.reject(); }, hasFeature: name => { const toggle = _features.find(f => f.name === name); const archived = _archive.find(f => f.name === name); if (toggle) { return Promise.resolve({ name, archived: false }); - } else if (archived) { - return Promise.resolve({ name, archived: true }); - } else { - return Promise.reject(); } + if (archived) { + return Promise.resolve({ name, archived: true }); + } + return Promise.reject(); }, getFeatures: () => Promise.resolve(_features), addFeature: feature => _features.push(feature), diff --git a/test/fixtures/fake-metrics-store.js b/test/fixtures/fake-metrics-store.js index 37832b6839..423f80dcde 100644 --- a/test/fixtures/fake-metrics-store.js +++ b/test/fixtures/fake-metrics-store.js @@ -6,6 +6,7 @@ class FakeMetricsStore extends EventEmitter { getMetricsLastHour() { return Promise.resolve([]); } + insert() { return Promise.resolve(); } diff --git a/test/fixtures/fake-strategies-store.js b/test/fixtures/fake-strategies-store.js index 29ed68a118..09a8ae97f7 100644 --- a/test/fixtures/fake-strategies-store.js +++ b/test/fixtures/fake-strategies-store.js @@ -13,9 +13,8 @@ module.exports = () => { const strategy = _strategies.find(s => s.name === name); if (strategy) { return Promise.resolve(strategy); - } else { - return Promise.reject(new NotFoundError('Not found!')); } + return Promise.reject(new NotFoundError('Not found!')); }, addStrategy: strat => _strategies.push(strat), }; diff --git a/test/fixtures/no-logger.js b/test/fixtures/no-logger.js index 37b6c0c7fb..d5dc9231fe 100644 --- a/test/fixtures/no-logger.js +++ b/test/fixtures/no-logger.js @@ -1,3 +1,5 @@ +/* eslint-disable no-console */ + 'use strict'; module.exports = function noLoggerProvider() { diff --git a/yarn.lock b/yarn.lock index 88c8caa271..96784866de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -497,6 +497,15 @@ array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" +array-includes@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" + integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0" + is-string "^1.0.5" + array-slice@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4" @@ -509,6 +518,14 @@ array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" +array.prototype.flat@^1.2.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b" + integrity sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + arrgv@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/arrgv/-/arrgv-1.0.2.tgz#025ed55a6a433cad9b604f8112fc4292715a6ec0" @@ -1116,6 +1133,16 @@ configstore@^5.0.1: write-file-atomic "^3.0.0" xdg-basedir "^4.0.0" +confusing-browser-globals@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd" + integrity sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw== + +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= + content-disposition@0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -1288,6 +1315,7 @@ db-migrate-pg@^1.0.0: db-migrate-shared@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/db-migrate-shared/-/db-migrate-shared-1.2.0.tgz#6125be1b3a5e661229fc75d50c85f6c3ffadbede" + integrity sha512-65k86bVeHaMxb2L0Gw3y5V+CgZSRwhVQMwDMydmw5MvIpHHwD6SmBciqIwHsZfzJ9yzV/yYhdRefRM6FV5/siw== db-migrate@^0.11.6: version "0.11.6" @@ -1310,7 +1338,7 @@ db-migrate@^0.11.6: semver "^5.3.0" tunnel-ssh "^4.0.0" -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: @@ -1390,6 +1418,13 @@ defer-to-connect@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.0.2.tgz#4bae758a314b034ae33902b5aac25a8dd6a8633e" +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" @@ -1453,6 +1488,14 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -1523,7 +1566,7 @@ equal-length@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/equal-length/-/equal-length-1.0.1.tgz#21ca112d48ab24b4e1e7ffc0e5339d31fdfc274c" -error-ex@^1.3.1: +error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" dependencies: @@ -1537,6 +1580,32 @@ errorhandler@^1.5.1: accepts "~1.3.7" escape-html "~1.0.3" +es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: + version "1.17.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.5.tgz#d8c9d1d66c8981fb9200e2251d799eee92774ae9" + integrity sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + es6-error@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" @@ -1558,35 +1627,62 @@ escape-string-regexp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" -eslint-config-finn-prettier@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/eslint-config-finn-prettier/-/eslint-config-finn-prettier-3.0.2.tgz#4f21015d9a0d561feda55c2015935910a24f4808" +eslint-config-airbnb-base@^14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.1.0.tgz#2ba4592dd6843258221d9bff2b6831bd77c874e4" + integrity sha512-+XCcfGyCnbzOnktDVhwsCAx+9DmrzEmuwxyHUJpw+kqBVT744OUBrB09khgFKlK1lshVww6qXGsYPZpavoNjJw== dependencies: - eslint-config-prettier "^3.0.1" - eslint-plugin-prettier "^2.6.2" + confusing-browser-globals "^1.0.9" + object.assign "^4.1.0" + object.entries "^1.1.1" -eslint-config-finn@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/eslint-config-finn/-/eslint-config-finn-3.0.1.tgz#edec7dce85ff0f385dc57171e4ce7b92cd3f3a94" - dependencies: - eslint-config-schibsted "^4.0.0" - -eslint-config-prettier@^3.0.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-3.6.0.tgz#8ca3ffac4bd6eeef623a0651f9d754900e3ec217" +eslint-config-prettier@^6.10.1: + version "6.10.1" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.10.1.tgz#129ef9ec575d5ddc0e269667bf09defcd898642a" + integrity sha512-svTy6zh1ecQojvpbJSgH3aei/Rt7C6i090l5f2WQ4aB05lYHeZIR1qL4wZyyILTbtmnbHP5Yn8MrsOJMGa8RkQ== dependencies: get-stdin "^6.0.0" -eslint-config-schibsted@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-config-schibsted/-/eslint-config-schibsted-4.0.0.tgz#7c0dacdc18d56a2dac006923917ef40df29438ed" - -eslint-plugin-prettier@^2.6.2: - version "2.7.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.7.0.tgz#b4312dcf2c1d965379d7f9d5b5f8aaadc6a45904" +eslint-import-resolver-node@^0.3.2: + version "0.3.3" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz#dbaa52b6b2816b50bc6711af75422de808e98404" + integrity sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg== dependencies: - fast-diff "^1.1.1" - jest-docblock "^21.0.0" + debug "^2.6.9" + resolve "^1.13.1" + +eslint-module-utils@^2.4.1: + version "2.6.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6" + integrity sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA== + dependencies: + debug "^2.6.9" + pkg-dir "^2.0.0" + +eslint-plugin-import@^2.20.2: + version "2.20.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz#91fc3807ce08be4837141272c8b99073906e588d" + integrity sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg== + dependencies: + array-includes "^3.0.3" + array.prototype.flat "^1.2.1" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.2" + eslint-module-utils "^2.4.1" + has "^1.0.3" + minimatch "^3.0.4" + object.values "^1.1.0" + read-pkg-up "^2.0.0" + resolve "^1.12.0" + +eslint-plugin-prettier@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.3.tgz#ae116a0fc0e598fdae48743a4430903de5b4e6ca" + integrity sha512-+HG5jmu/dN3ZV3T6eCD7a4BlAySdN7mLIbJYo0z1cFQuI+r2DiTJEFeF68ots93PsnrMxbzIZ2S/ieX+mkrBeQ== + dependencies: + prettier-linter-helpers "^1.0.0" eslint-scope@^5.0.0: version "5.0.0" @@ -1819,7 +1915,7 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= -fast-diff@^1.1.1, fast-diff@^1.1.2: +fast-diff@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" @@ -1945,6 +2041,13 @@ find-cache-dir@^3.2.0: make-dir "^3.0.0" pkg-dir "^4.1.0" +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -2093,6 +2196,11 @@ fsevents@~2.1.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" @@ -2336,6 +2444,11 @@ has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" +has-symbols@^1.0.0, has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -2367,6 +2480,13 @@ has-yarn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + hasha@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.0.0.tgz#fdc3785caea03df29535fc8adb512c3d3a709004" @@ -2604,6 +2724,11 @@ is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" +is-callable@^1.1.4, is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -2622,6 +2747,11 @@ is-data-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-date-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== + is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" @@ -2757,6 +2887,13 @@ is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" +is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== + dependencies: + has "^1.0.3" + is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" @@ -2775,6 +2912,18 @@ is-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== + +is-symbol@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -2797,7 +2946,7 @@ isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" -isarray@1.0.0, isarray@~1.0.0: +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -2888,10 +3037,6 @@ istanbul-reports@^3.0.0: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jest-docblock@^21.0.0: - version "21.2.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" - js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" @@ -3140,6 +3285,16 @@ listr@^0.14.3: p-map "^2.0.0" rxjs "^6.3.3" +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + load-json-file@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-5.3.0.tgz#4d3c1e01fa1c03ea78a60ac7af932c9ce53403f3" @@ -3150,6 +3305,14 @@ load-json-file@^5.2.0: strip-bom "^3.0.0" type-fest "^0.3.0" +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -3536,7 +3699,7 @@ node-preload@^0.2.0: dependencies: process-on-spawn "^1.0.0" -normalize-package-data@^2.5.0: +normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -3620,12 +3783,32 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-inspect@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" + integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" dependencies: isobject "^3.0.0" +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + object.defaults@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" @@ -3635,6 +3818,16 @@ object.defaults@^1.1.0: for-own "^1.0.0" isobject "^3.0.0" +object.entries@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.1.tgz#ee1cf04153de02bb093fec33683900f57ce5399b" + integrity sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + object.map@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" @@ -3648,6 +3841,16 @@ object.pick@^1.2.0, object.pick@^1.3.0: dependencies: isobject "^3.0.1" +object.values@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + on-finished@^2.3.0, on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -3730,6 +3933,13 @@ p-finally@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + p-limit@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.1.0.tgz#1d5a0d20fb12707c758a655f6bbc4386b5930d68" @@ -3742,6 +3952,13 @@ p-limit@^2.2.0: dependencies: p-try "^2.0.0" +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -3772,6 +3989,11 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + p-try@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" @@ -3822,6 +4044,13 @@ parse-filepath@^1.0.1: map-cache "^0.2.0" path-root "^0.1.1" +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -3921,6 +4150,13 @@ path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= + dependencies: + pify "^2.0.0" + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -4023,6 +4259,11 @@ picomatch@^2.0.7, picomatch@^2.2.1, picomatch@^2.2.2: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + pify@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" @@ -4034,6 +4275,13 @@ pkg-conf@^3.1.0: find-up "^3.0.0" load-json-file "^5.2.0" +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" + pkg-dir@^4.1.0, pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -4097,10 +4345,17 @@ prepend-http@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" -prettier@^1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" - integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== pretty-ms@^6.0.1: version "6.0.1" @@ -4230,6 +4485,23 @@ rc@^1.1.6, rc@^1.2.8: minimist "^1.2.0" strip-json-comments "~2.0.1" +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + read-pkg@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" @@ -4403,6 +4675,13 @@ resolve@^1.11.1: dependencies: path-parse "^1.0.6" +resolve@^1.12.0, resolve@^1.13.1: + version "1.15.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" + integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== + dependencies: + path-parse "^1.0.6" + response-time@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/response-time/-/response-time-2.3.2.tgz#ffa71bab952d62f7c1d49b7434355fbc68dffc5a" @@ -4876,6 +5155,40 @@ string-width@^4.1.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^5.2.0" +string.prototype.trimend@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" + integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.trimleft@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz#4408aa2e5d6ddd0c9a80739b087fbc067c03b3cc" + integrity sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.trimstart "^1.0.0" + +string.prototype.trimright@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz#c76f1cef30f21bbad8afeb8db1511496cfb0f2a3" + integrity sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.trimend "^1.0.0" + +string.prototype.trimstart@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" + integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"