From 44872f2a9c50ecd96b65e1035633066d76705b03 Mon Sep 17 00:00:00 2001 From: MaxGenash Date: Thu, 6 Aug 2020 18:55:11 +0300 Subject: [PATCH] fix: strf-8574, bump version of "@hapi/lab" to fix security issues --- bin/stencil-bundle.spec.js | 173 ++- bin/stencil-init.spec.js | 16 +- lib/build-config.spec.js | 61 +- lib/bundle-validator.spec.js | 112 +- lib/cycles.spec.js | 42 +- lib/json-lint.spec.js | 30 +- lib/regions.spec.js | 54 +- lib/stencil-download.utils.spec.js | 119 +- lib/stencil-push.spec.js | 54 +- lib/stencil-push.utils.spec.js | 33 +- lib/theme-api-client.spec.js | 23 +- lib/theme-config.spec.js | 147 +- lib/validator/schema-translations.spec.js | 22 +- package-lock.json | 1287 +++++++---------- package.json | 2 +- server/lib/utils.spec.js | 16 +- .../plugins/renderer/renderer.module.spec.js | 97 +- .../renderer/responses/raw-response.spec.js | 29 +- server/plugins/router/router.module.spec.js | 101 +- tasks/changelog/changelog-generator.spec.js | 68 +- tasks/changelog/command-executor.spec.js | 52 +- 21 files changed, 1090 insertions(+), 1448 deletions(-) diff --git a/bin/stencil-bundle.spec.js b/bin/stencil-bundle.spec.js index 6188f26e..8d00caf4 100644 --- a/bin/stencil-bundle.spec.js +++ b/bin/stencil-bundle.spec.js @@ -4,9 +4,10 @@ const Code = require('code'); const Fs = require('fs'); const Sinon = require('sinon'); const Path = require('path'); +const { promisify } = require('util'); const async = require('async'); const when = require('when'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); const lab = exports.lab = Lab.script(); const describe = lab.describe; const themePath = Path.join(process.cwd(), 'test/_mocks/themes/valid'); @@ -21,7 +22,7 @@ describe('Stencil Bundle', () => { let sandbox; let Bundle; - lab.beforeEach(done => { + lab.beforeEach(() => { sandbox = Sinon.createSandbox(); const themeConfigStub = getThemeConfigStub(); const rawConfig = { @@ -36,16 +37,13 @@ describe('Stencil Bundle', () => { Bundle = new StencilBundle(themePath, themeConfigStub, rawConfig, { marketplace: false, }); - - done(); }); - lab.afterEach(done => { + lab.afterEach(() => { sandbox.restore(); - done(); }); - it('should initialize bundling', done => { + it('should initialize bundling', () => { sandbox.stub(async, 'series').callsArgWith(1, new Error('error')); const throws = () => { Bundle.initBundle(); @@ -53,130 +51,121 @@ describe('Stencil Bundle', () => { expect(throws).to.throw(Error); expect(async.series.calledOnce).to.equal(true); - done(); }); - it('should assemble CSS files', done => { + it('should assemble CSS files', async () => { sandbox.stub(async, 'map').callsArgWith(2, null, ['this is dog']); - const callback = (err, result) => { - expect(result).to.equal({'theme.scss': 'this is dog'}); - - done(); - }; - const task = Bundle.getCssAssembleTask('scss'); + const result = await promisify(task.bind(Bundle))(); - task(callback); - + expect(result).to.equal({'theme.scss': 'this is dog'}); }); - it('should error on assemble CSS files', done => { - sandbox.stub(async, 'map').callsArgWith(2, 'error'); - - const callback = err => { - expect(err).to.equal('error'); - done(); - }; - - const task = Bundle.getCssAssembleTask('scss'); + it('should error on assemble CSS files', async () => { + sandbox.stub(async, 'map').callsArgWith(2, 'our_error'); + + let error; + try { + const task = Bundle.getCssAssembleTask('scss'); + await promisify(task.bind(Bundle))(); + } catch (err) { + error = err; + } + expect(error).to.equal('our_error'); + }); - task(callback); + it('should assembleTemplates', async () => { + const result = await promisify(Bundle.assembleTemplatesTask.bind(Bundle))(); + expect(result['pages/page']).to.include(['pages/page', 'components/a']); + expect(result['pages/page2']).to.include(['pages/page2', 'components/b']); }); - it('should assembleTemplates', done => { - Bundle.assembleTemplatesTask((err, result) => { - expect(err).to.be.null(); - expect(result['pages/page']).to.include(['pages/page', 'components/a']); - expect(result['pages/page2']).to.include(['pages/page2', 'components/b']); - done(); - }); - }); + it('should error when running assembleTemplates', async () => { + sandbox.stub(async, 'map').callsArgWith(2, 'our_error'); - it('should error when running assembleTemplates', done => { - sandbox.stub(async, 'map').callsArgWith(2, 'error'); + let error; + try { + await promisify(Bundle.assembleTemplatesTask.bind(Bundle))(); + } catch (err) { + error = err; + } - Bundle.assembleTemplatesTask(err => { - expect(err).to.equal('error'); - done(); - }); + expect(error).to.equal('our_error'); }); - it('should assemble the Schema', done => { - Bundle.assembleSchema((err, result) => { - expect(result).to.equal(themeSchema); - done(); - }); + it('should assemble the Schema', async () => { + const result = await promisify(Bundle.assembleSchema.bind(Bundle))(); + + expect(result).to.equal(themeSchema); }); - it('should assemble the Lang Files', done => { + it('should assemble the Lang Files', async () => { sandbox.stub(LangAssembler, 'assemble').callsArgWith(0, null); - const callback = () => { - expect(LangAssembler.assemble.calledOnce).to.equal(true); - done(); - }; - - Bundle.assembleLangTask(callback); + await promisify(Bundle.assembleLangTask.bind(Bundle))(); + expect(LangAssembler.assemble.calledOnce).to.equal(true); }); - it('should error on assembling the Lang Files', done => { - sandbox.stub(LangAssembler, 'assemble').callsArgWith(0, 'error'); + it('should error on assembling the Lang Files', async () => { + sandbox.stub(LangAssembler, 'assemble').callsArgWith(0, 'our_error'); - const callback = err => { - expect(LangAssembler.assemble.calledOnce).to.equal(true); - expect(err).to.equal('error'); - done(); - }; - - Bundle.assembleLangTask(callback); + let error; + try { + await promisify(Bundle.assembleLangTask.bind(Bundle))(); + } catch (err) { + error = err; + } + expect(LangAssembler.assemble.calledOnce).to.equal(true); + expect(error).to.equal('our_error'); }); - it('should bundle JSPM assets', done => { + it('should bundle JSPM assets', async () => { sandbox.stub(jspm, 'bundleSFX').returns(when()); - const callback = (err, result) => { - expect(result).to.equal(true); - done(); - }; - - Bundle.getJspmBundleTask(getThemeConfigStub().getRawConfig)(callback); + const jspmBundleTask = Bundle.getJspmBundleTask(getThemeConfigStub().getRawConfig); + const result = await promisify(jspmBundleTask.bind(Bundle))(); + expect(result).to.equal(true); }); - it('should fail to bundle JSPM assets', done => { - sandbox.stub(jspm, 'bundleSFX').returns(when.reject(false)); + it('should fail to bundle JSPM assets', async () => { + sandbox.stub(jspm, 'bundleSFX').returns(when.reject('SFX Bundle input error')); - const callback = err => { - expect(err).to.equal(false); - done(); - }; + let error; + try { + const jspmBundleTask = Bundle.getJspmBundleTask(getThemeConfigStub().getRawConfig); + await promisify(jspmBundleTask.bind(Bundle))(); + } catch (err) { + error = err; + } - Bundle.getJspmBundleTask(getThemeConfigStub().getRawConfig)(callback); + expect(error).to.equal('SFX Bundle input error'); }); - it('should generate a manifest of files.', done => { - Bundle.assembleTemplatesTask((err, templates) => { - const results = { templates }; - Bundle.generateManifest(results, (err, manifest) => { - expect(err).to.be.null(); - expect(manifest.templates).to.contain(['components/a', 'components/b']); - done(); - }); - }); + it('should generate a manifest of files.', async () => { + const templates = await promisify(Bundle.assembleTemplatesTask.bind(Bundle))(); + const manifest = await promisify(Bundle.generateManifest.bind(Bundle))({ templates }); + + expect(manifest.templates).to.contain(['components/a', 'components/b']); }); - it('should error while reading files to generate a manifest of files.', done => { + it('should error while reading files to generate a manifest of files.', async () => { Bundle.templatesPath = 'invalid/path'; - Bundle.generateManifest({}, err => { - expect(Fs.writeFile.calledOnce).to.equal(false); - expect(err instanceof Error).to.be.true(); - expect(err.message).to.contain('no such file or directory'); - done(); - }); + + let error; + try { + await promisify(Bundle.generateManifest.bind(Bundle))({}); + } catch (err) { + error = err; + } + + expect(Fs.writeFile.calledOnce).to.equal(false); + expect(error instanceof Error).to.be.true(); + expect(error.message).to.contain('no such file or directory'); }); function getThemeConfigStub() { diff --git a/bin/stencil-init.spec.js b/bin/stencil-init.spec.js index ebee0b84..ac83ce95 100644 --- a/bin/stencil-init.spec.js +++ b/bin/stencil-init.spec.js @@ -2,7 +2,7 @@ const Code = require('code'); const Sinon = require('sinon'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); const lab = exports.lab = Lab.script(); const describe = lab.describe; const Inquirer = require('inquirer'); @@ -13,21 +13,19 @@ const StencilInit = require('../lib/stencil-init'); describe('stencil init', () => { let sandbox; - lab.beforeEach(done => { + lab.beforeEach(() => { sandbox = Sinon.createSandbox(); sandbox.stub(console, 'log'); sandbox.stub(console, 'error'); - done(); }); - lab.afterEach(done => { + lab.afterEach(() => { sandbox.restore(); - done(); }); var inquirer = Sinon.spy(Inquirer, 'prompt'); - it('should call prompt', done => { + it('should call prompt', () => { const dotStencilFile = '../_mocks/bin/dotStencilFile.json'; const jspmAssembler = Sinon.stub(); const themeConfig = Sinon.spy(); @@ -35,11 +33,9 @@ describe('stencil init', () => { StencilInit(jspmAssembler, themeConfig, dotStencilFile); expect(inquirer.calledOnce).to.be.true(); - - done(); }); - it('should not call prompt with bad JSON from dotStencilFile', done => { + it('should not call prompt with bad JSON from dotStencilFile', () => { const dotStencilFile = '../_mocks/malformedSchema.json'; const jspmAssembler = Sinon.stub(); const themeConfig = Sinon.spy(); @@ -47,7 +43,5 @@ describe('stencil init', () => { StencilInit(jspmAssembler, themeConfig, dotStencilFile); expect(inquirer.calledOnce).to.be.false(); - - done(); }); }); diff --git a/lib/build-config.spec.js b/lib/build-config.spec.js index 022e302c..099084d1 100644 --- a/lib/build-config.spec.js +++ b/lib/build-config.spec.js @@ -1,8 +1,9 @@ 'use strict'; const Code = require('code'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); const sinon = require('sinon'); +const { promisify } = require('util'); const lab = exports.lab = Lab.script(); const describe = lab.describe; const expect = Code.expect; @@ -20,71 +21,77 @@ describe('stencilBuildConfig', () => { return require('./build-config'); } - lab.beforeEach(done => { + lab.beforeEach(() => { sandbox = sinon.createSandbox(); - done(); }); - lab.afterEach(done => { + lab.afterEach(() => { sandbox.restore(); - done(); }); - it('should return watchOptions', done => { + it('should return watchOptions', () => { const buildConfig = loadModule('valid-config'); expect(buildConfig.watchOptions).to.be.an.object(); expect(buildConfig.watchOptions.files).to.be.an.array(); expect(buildConfig.watchOptions.ignored).to.be.an.array(); - - done(); }); describe('production method', () => { - it('should call "done()" function when production bundle finishes', done => { + it('should resolve successfully for "valid-config"', async () => { const buildConfig = loadModule('valid-config'); + const initedBuildConfig = buildConfig.initWorker(); expect(buildConfig.production).to.be.a.function(); - buildConfig.initWorker().production(message => { - expect(message).to.be.undefined(); - done(); - }); + + await promisify(initedBuildConfig.production.bind(initedBuildConfig))(); }); - it('should call "done()" function when production bundle finishes (legacy-config)', done => { + it('should resolve successfully for "legacy-config"', async () => { const buildConfig = loadModule('legacy-config'); + const initedBuildConfig = buildConfig.initWorker(); expect(buildConfig.production).to.be.a.function(); - buildConfig.initWorker().production(message => { - expect(message).to.be.undefined(); - done(); - }); + + await promisify(initedBuildConfig.production.bind(initedBuildConfig))(); }); - it('should call done with "noworker" meesage', done => { + it('should reject with "worker terminated" message for "noworker-config"', async () => { const buildConfig = loadModule('noworker-config'); + const initedBuildConfig = buildConfig.initWorker(); expect(buildConfig.production).to.be.a.function(); - buildConfig.initWorker().production(message => { - expect(message).to.equal('worker terminated'); - done(); - }); + + let message; + try { + await promisify(initedBuildConfig.production.bind(initedBuildConfig))(); + } catch (err) { + message = err; + } + + expect(message).to.equal('worker terminated'); }); }); describe('development method', () => { - it('should reload the browser when a message "reload" is received from stencil.conf.js', done => { + it('should reload the browser when a message "reload" is received from stencil.conf.js (valid-config)', async () => { const buildConfig = loadModule('valid-config'); expect(buildConfig.development).to.be.a.function(); - buildConfig.initWorker().development({ reload: done }); + + await new Promise(done => + buildConfig.initWorker().development({ reload: done }), + ); }); - it('should reload the browser when "reload" method is called from stencil.conf.js (legacy-config)', done => { + it('should reload the browser when "reload" method is called from stencil.conf.js (legacy-config)', async () => { const buildConfig = loadModule('legacy-config'); expect(buildConfig.development).to.be.a.function(); - buildConfig.initWorker().development({ reload: done }); + + await new Promise(done => + buildConfig.initWorker().development({ reload: done }), + ); }); }); }); diff --git a/lib/bundle-validator.spec.js b/lib/bundle-validator.spec.js index e3d20923..09bb2bda 100644 --- a/lib/bundle-validator.spec.js +++ b/lib/bundle-validator.spec.js @@ -1,9 +1,10 @@ const Code = require('code'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); const lab = exports.lab = Lab.script(); const describe = lab.describe; const sinon = require('sinon'); const Path = require('path'); +const { promisify } = require('util'); const themePath = Path.join(process.cwd(), 'test/_mocks/themes/valid'); const ThemeConfig = require('./theme-config'); const BundleValidator = require('./bundle-validator'); @@ -11,46 +12,38 @@ const expect = Code.expect; const it = lab.it; describe('BundleValidator', function () { - var themeConfig; + let themeConfig; - lab.beforeEach(function(done) { + lab.beforeEach(function() { themeConfig = ThemeConfig.getInstance(themePath); themeConfig.getConfig(); - - done(); }); - it('should not run image validations for private themes', function (done) { - - var validator = new BundleValidator(themePath, themeConfig, true); - var sizeOfSpy = sinon.spy(validator, 'sizeOf'); + it('should not run image validations for private themes', async () => { + const validator = new BundleValidator(themePath, themeConfig, true); + const sizeOfSpy = sinon.spy(validator, 'sizeOf'); - validator.validateTheme(error => { + await promisify(validator.validateTheme.bind(validator))(); - expect(error).to.be.null(); - expect(sizeOfSpy.called).to.equal(false); + expect(sizeOfSpy.called).to.equal(false); - sizeOfSpy.restore(); - done(); - }); + sizeOfSpy.restore(); }); - it('should run image validations for marketplace themes', function (done) { - var validator = new BundleValidator(themePath, themeConfig, false); - var sizeOfSpy = sinon.spy(validator, 'sizeOf'); + it('should run image validations for marketplace themes', async () => { + const validator = new BundleValidator(themePath, themeConfig, false); + const sizeOfSpy = sinon.spy(validator, 'sizeOf'); + + await promisify(validator.validateTheme.bind(validator))(); - validator.validateTheme(error => { - expect(error).to.be.null(); - expect(sizeOfSpy.called).to.equal(true); + expect(sizeOfSpy.called).to.equal(true); - sizeOfSpy.restore(); - done(); - }); + sizeOfSpy.restore(); }); - it ('should validate returned objects exist in templates', function (done) { - var validResults = [ + it ('should validate returned objects exist in templates', async () => { + const validResults = [ {"page":"---\nfront_matter_options:\n setting_x:\n value: {{theme_settings.front_matter_value}}\n---\n\n\n\n{{{footer.scripts}}}\n{{#if theme_settings.display_that}}\n
{{> components/index}}
\n{{/if}}\n\n\n", "components/index":"

This is the index

\n", }, @@ -58,16 +51,15 @@ describe('BundleValidator', function () { "page2":"\n\n\n

{{theme_settings.customizable_title}}

\n{{{head.scripts}}}\n\n\n", }, ]; + const validator = new BundleValidator(themePath, themeConfig, false); + + const result = await promisify(validator.validateObjects.bind(validator))(validResults); - var validator = new BundleValidator(themePath, themeConfig, false); - validator.validateObjects(validResults, function (err, result) { - expect(result).to.equal(true); - done(); - }); + expect(result).to.equal(true); }); - it ('should validate returned objects when they have whitespace in the object name', function (done) { - var validResults = [ + it ('should validate returned objects when they have whitespace in the object name', async () => { + const validResults = [ {"page":"---\nfront_matter_options:\n setting_x:\n value: {{theme_settings.front_matter_value}}\n---\n\n\n\n{{{footer.scripts}}}\n{{#if theme_settings.display_that}}\n
{{> components/index}}
\n{{/if}}\n\n\n", "components/index":"

This is the index

\n", }, @@ -75,16 +67,15 @@ describe('BundleValidator', function () { "page2":"\n\n\n

{{theme_settings.customizable_title}}

\n{{{ head.scripts }}}\n\n\n", }, ]; + const validator = new BundleValidator(themePath, themeConfig, false); + + const result = await promisify(validator.validateObjects.bind(validator))(validResults); - var validator = new BundleValidator(themePath, themeConfig, false); - validator.validateObjects(validResults, function (err, result) { - expect(result).to.equal(true); - done(); - }); + expect(result).to.equal(true); }); - it ('should not validate returned objects exist in templates', function (done) { - var validResults = [ + it ('should not validate returned objects exist in templates', async () => { + const validResults = [ {"page":"---\nfront_matter_options:\n setting_x:\n value: {{theme_settings.front_matter_value}}\n---\n\n\n\n{{#if theme_settings.display_that}}\n
{{> components/index}}
\n{{/if}}\n\n\n", "components/index":"

This is the index

\n", }, @@ -92,34 +83,41 @@ describe('BundleValidator', function () { "page2":"\n\n\n

{{theme_settings.customizable_title}}

\n{{{head.scripts}}}\n\n\n", }, ]; + const validator = new BundleValidator(themePath, themeConfig, false); - var validator = new BundleValidator(themePath, themeConfig, false); - validator.validateObjects(validResults, function (err, result) { - expect(result).to.be.undefined(); - expect(err.message).to.equal('Missing required objects/properties: footer.scripts'); - done(); - }); + let error; + let result; + try { + result = await promisify(validator.validateObjects.bind(validator))(validResults); + } catch (err) { + error = err; + } + + expect(result).to.be.undefined(); + expect(error.message).to.equal('Missing required objects/properties: footer.scripts'); }); - it ('should validate theme schema successfully', function (done) { + it ('should validate theme schema successfully', async () => { const validator = new BundleValidator(themePath, themeConfig, false); - validator.validateTheme(error => { - expect(error).to.be.null(); - done(); - }); + + await promisify(validator.validateTheme.bind(validator))(); }); - it ('should validate theme schema and throw errors', function (done) { + it ('should validate theme schema and throw errors', async () => { const themePath = Path.join(process.cwd(), 'test/_mocks/themes/invalid-schema'); themeConfig = ThemeConfig.getInstance(themePath); themeConfig.getConfig(); const validator = new BundleValidator(themePath, themeConfig, false); - validator.validateTheme(error => { - expect(error instanceof Error).to.be.true(); - expect(error.message).to.contain('schema[0].settings[0] should have required property \'content\''); - done(); - }); + let error; + try { + await promisify(validator.validateTheme.bind(validator))(); + } catch (err) { + error = err; + } + + expect(error instanceof Error).to.be.true(); + expect(error.message).to.contain('schema[0].settings[0] should have required property \'content\''); }); }); diff --git a/lib/cycles.spec.js b/lib/cycles.spec.js index 0a959c5b..d4fb9d76 100644 --- a/lib/cycles.spec.js +++ b/lib/cycles.spec.js @@ -1,15 +1,17 @@ -var Code = require('code'), - Lab = require('lab'), - lab = exports.lab = Lab.script(), - describe = lab.describe, - Cycles = require('./cycles'), - expect = Code.expect, - it = lab.it; +const Code = require('code'); +const Lab = require('@hapi/lab'); -describe('Cycles', function () { +const Cycles = require('./cycles'); - var invaldResults = [ - {"page":"---\nfront_matter_options:\n setting_x:\n value: {{theme_settings.front_matter_value}}\n---\n\n\n\n{{#if theme_settings.display_that}}\n
{{> components/index}}
\n{{/if}}\n\n\n", +const expect = Code.expect; +const lab = exports.lab = Lab.script(); +const describe = lab.describe; +const it = lab.it; + +describe('Cycles', () => { + const invaldResults = [ + { + "page":"---\nfront_matter_options:\n setting_x:\n value: {{theme_settings.front_matter_value}}\n---\n\n\n\n{{#if theme_settings.display_that}}\n
{{> components/index}}
\n{{/if}}\n\n\n", "components/index":"

Oh Hai there

\n

\n

Test product {{dynamicComponent 'components/options'}}

\n

\n", "components/options/date":"

This is a dynamic component

\n

Test product {{> components/index}}

\n", }, @@ -26,8 +28,9 @@ describe('Cycles', function () { }, ]; - var validResults = [ - {"page":"---\nfront_matter_options:\n setting_x:\n value: {{theme_settings.front_matter_value}}\n---\n\n\n\n{{#if theme_settings.display_that}}\n
{{> components/index}}
\n{{/if}}\n\n\n", + const validResults = [ + { + "page":"---\nfront_matter_options:\n setting_x:\n value: {{theme_settings.front_matter_value}}\n---\n\n\n\n{{#if theme_settings.display_that}}\n
{{> components/index}}
\n{{/if}}\n\n\n", "components/index":"

This is the index

\n", }, { @@ -35,30 +38,27 @@ describe('Cycles', function () { }, ]; - it('should throw error when cycle is detected', function (done) { - var throws = function () { + it('should throw error when cycle is detected', () => { + const throws = function () { new Cycles(invaldResults).detect(); }; expect(throws).throw(Error, /Circular/); - done(); }); - it('should throw an error when non array passed in', function (done) { - var throws = function () { + it('should throw an error when non array passed in', () => { + const throws = function () { new Cycles('test'); }; expect(throws).throw(Error); - done(); }); - it('should not throw an error when checking for cycles', function (done) { - var throws = function () { + it('should not throw an error when checking for cycles', () => { + const throws = function () { new Cycles(validResults).detect(); }; expect(throws).to.not.throw(); - done(); }); }); diff --git a/lib/json-lint.spec.js b/lib/json-lint.spec.js index 9d5307af..8908e456 100644 --- a/lib/json-lint.spec.js +++ b/lib/json-lint.spec.js @@ -1,32 +1,30 @@ -var Code = require('code'), - Lab = require('lab'), - lab = exports.lab = Lab.script(), - describe = lab.describe, - jsonLint = require('./json-lint'), - expect = Code.expect, - it = lab.it; +const Code = require('code'); +const Lab = require('@hapi/lab'); +const lab = exports.lab = Lab.script(); +const describe = lab.describe; +const jsonLint = require('./json-lint'); +const expect = Code.expect; +const it = lab.it; describe('json-lint', function () { - var badJsonFilename = '/path/to/badfile.json', - badJson = '{"foo":"bar" "fizz": "buzz"}', - file = new RegExp(badJsonFilename); + const badJsonFilename = '/path/to/badfile.json'; + const badJson = '{"foo":"bar" "fizz": "buzz"}'; + const file = new RegExp(badJsonFilename); - it('should add file name to error', function (done) { - var throws = function () { + it('should add file name to error', () => { + const throws = function () { jsonLint.parse(badJson, badJsonFilename); }; expect(throws).throw(Error, file); - done(); }); - it('should not need a file name', function (done) { - var throws = function () { + it('should not need a file name', () => { + const throws = function () { jsonLint.parse(badJson); }; expect(throws).throw(Error, !file); - done(); }); }); diff --git a/lib/regions.spec.js b/lib/regions.spec.js index 2fbcfd9a..7f09171b 100644 --- a/lib/regions.spec.js +++ b/lib/regions.spec.js @@ -2,8 +2,9 @@ const Code = require('code'); const Fs = require('fs'); +const { promisify } = require('util'); const Sinon = require('sinon'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); const lab = exports.lab = Lab.script(); const describe = lab.describe; const expect = Code.expect; @@ -15,9 +16,9 @@ const themePath = `${process.cwd()}/test/_mocks/themes/regions`; describe('Stencil Bundle', () => { let sandbox; - let Bundle; + let bundle; - lab.beforeEach(done => { + lab.beforeEach(() => { sandbox = Sinon.createSandbox(); const themeConfigStub = { configExists: sandbox.stub().returns(true), @@ -32,36 +33,31 @@ describe('Stencil Bundle', () => { sandbox.stub(Fs, 'writeFile').callsArgWith(2, null); - Bundle = new StencilBundle(themePath, themeConfigStub, rawConfig, { + bundle = new StencilBundle(themePath, themeConfigStub, rawConfig, { marketplace: false, }); - - done(); }); - lab.afterEach(done => { + lab.afterEach(() => { sandbox.restore(); - done(); }); - it('should return all regions with the right order.', done => { - Bundle.assembleTemplatesTask((err, templates) => { - expect(err).to.be.null(); - const results = { templates }; - Bundle.generateManifest(results, (err, manifest) => { - expect(err).to.be.null(); - expect(manifest.regions['pages/page']).to.equal([ - { name: 'top_region' }, - { name: 'dynamic_a' }, - { name: 'dynamic_b' }, - { name: 'dynamic_c' }, - { name: 'middle_region' }, - { name: 'other' }, - { name: 'bottom_region' }, - ]); - done(); - }); - }); + it('should return all regions with the right order.', async () => { + const assembleTemplatesTask = promisify(bundle.assembleTemplatesTask.bind(bundle)); + const generateManifest = promisify(bundle.generateManifest.bind(bundle)); + + const templates = await assembleTemplatesTask(); + const manifest = await generateManifest({ templates }); + + expect(manifest.regions['pages/page']).to.equal([ + { name: 'top_region' }, + { name: 'dynamic_a' }, + { name: 'dynamic_b' }, + { name: 'dynamic_c' }, + { name: 'middle_region' }, + { name: 'other' }, + { name: 'bottom_region' }, + ]); }); }); @@ -87,10 +83,8 @@ describe('Regions', () => { }; for (let template in map) { - it(`should parse region for template ${template}`, done => { - expect(Regions.parseRegions(template)) - .to.equal(map[template]); - done(); + it(`should parse region for template ${template}`, () => { + expect(Regions.parseRegions(template)).to.equal(map[template]); }); } }); diff --git a/lib/stencil-download.utils.spec.js b/lib/stencil-download.utils.spec.js index 9f97cd16..7a46cafa 100644 --- a/lib/stencil-download.utils.spec.js +++ b/lib/stencil-download.utils.spec.js @@ -3,17 +3,17 @@ require('colors'); const fs = require('fs'); const Code = require('code'); const Path = require('path'); +const { promisify } = require('util'); const yauzl = require('yauzl'); const request = require("request"); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); const lab = exports.lab = Lab.script(); const describe = lab.describe; const expect = Code.expect; const it = lab.it; const sinon = require('sinon'); const tmp = require('tmp'); -const stencilDownload = require('./stencil-download.utils'); - +const { downloadThemeFiles } = require('./stencil-download.utils'); describe('ThemeDownloader', function () { let sandbox; @@ -23,7 +23,7 @@ describe('ThemeDownloader', function () { let fsWriteSub; let zipOpenSpy; - lab.beforeEach(function (done) { + lab.beforeEach(() => { sandbox = sinon.createSandbox(); options = {downloadUrl: archiveMockUrl}; @@ -51,41 +51,35 @@ describe('ThemeDownloader', function () { sandbox.stub(fs, 'createWriteStream').callsFake(tempPath => { fs.writeFileSync(tempPath, fs.readFileSync(options.downloadUrl)); }); - - done(); }); - lab.afterEach(done => { + lab.afterEach(() => { sandbox.restore(); - done(); }); describe("Verify till Zip opens", () => { - - lab.beforeEach(done => { + lab.beforeEach(() => { zipOpenSpy = sandbox.spy(yauzl, 'open'); zipOpenSpy(archiveMockUrl, {lazyEntries: true}, themeCallback); - done(); }); - lab.afterEach(done => { + lab.afterEach(() => { sandbox.restore(); - done(); }); - it('should verify that the tmp.file() is called', done => { + it('should verify that the tmp.file() is called', async () => { const tmpSpy = sandbox.spy(tmp); - themeCallback = () => { - expect(tmpSpy.file.called).to.be.true(); - done(); - }; - stencilDownload.downloadThemeFiles(options, themeCallback); + + const promise = promisify(downloadThemeFiles)(options); zipOpenSpy.lastCall.callback(); + await promise; + + expect(tmpSpy.file.called).to.be.true(); }); - it('should return a callback error', done => { + it('should return a callback error', async () => { const throwsSpy = sandbox.spy(request); - stencilDownload.downloadThemeFiles(null, themeCallback); + downloadThemeFiles(null, themeCallback); try { throwsSpy(); @@ -93,86 +87,63 @@ describe('ThemeDownloader', function () { } sandbox.assert.threw(throwsSpy); - done(); }); - it('should verify request is called with downloadUrl', done => { - themeCallback = () => { - sandbox.assert.calledOnce(request.Request); - done(); - - }; - stencilDownload.downloadThemeFiles(options, themeCallback); + it('should verify request is called with downloadUrl', async () => { + const promise = promisify(downloadThemeFiles)(options); zipOpenSpy.lastCall.callback(); + await promise; + sandbox.assert.calledOnce(request.Request); }); - it('should verify createWriteStream is also called within the request', done => { - themeCallback = () => { - sandbox.assert.calledOnce(fs.createWriteStream); - done(); - - }; - stencilDownload.downloadThemeFiles(options, themeCallback); - + it('should verify createWriteStream is also called within the request', async () => { + const promise = promisify(downloadThemeFiles)(options); zipOpenSpy.lastCall.callback(); - }); - - it('should verify that the yauzl zip module is called', done => { + await promise; - themeCallback = () => { - expect(yauzl.open.called).to.be.true(); - done(); - }; + sandbox.assert.calledOnce(fs.createWriteStream); + }); - stencilDownload.downloadThemeFiles(options, themeCallback); + it('should verify that the yauzl zip module is called', async () => { + const promise = promisify(downloadThemeFiles)(options); zipOpenSpy.lastCall.callback(); + await promise; + + expect(yauzl.open.called).to.be.true(); }); - it('should call the zip open callback with zipFile', done => { - const callback = (err, zip) => { - expect(zip.fileSize).to.be.greaterThan(100); - done(); - }; - zipOpenSpy(archiveMockUrl, {lazyEntries: true}, callback); + it('should call the zip open callback with zipFile', async () => { + const zip = await promisify(zipOpenSpy)(archiveMockUrl, {lazyEntries: true}); + + expect(zip.fileSize).to.be.greaterThan(100); }); }); - describe("Verify After zip opens", () => { - - lab.afterEach(done => { + lab.afterEach(() => { options = {downloadUrl: archiveMockUrl}; sandbox.restore(); - done(); }); - it('should write the two files inside the zip archive', done => { - themeCallback = () => { - expect(fsWriteSub.calledTwice).to.be.true(); + it('should write the two files inside the zip archive', async () => { + await promisify(downloadThemeFiles)(options); - done(); - }; - stencilDownload.downloadThemeFiles(options, themeCallback); + expect(fsWriteSub.calledTwice).to.be.true(); }); - it('should exclude config.json from files to write', done => { + it('should exclude config.json from files to write', async () => { options.exclude = ['config.json']; - themeCallback = () => { - expect(fsWriteSub.calledOnce).to.be.true(); - done(); - }; - stencilDownload.downloadThemeFiles(options, themeCallback); + await promisify(downloadThemeFiles)(options); + + expect(fsWriteSub.calledOnce).to.be.true(); }); - it('should write config.json only', done => { + it('should write config.json only', async () => { options.file = 'config.json'; - themeCallback = () => { - expect(fsWriteSub.calledOnce).to.be.true(); - done(); - }; - stencilDownload.downloadThemeFiles(options, themeCallback); - }); + await promisify(downloadThemeFiles)(options); + expect(fsWriteSub.calledOnce).to.be.true(); + }); }); }); diff --git a/lib/stencil-push.spec.js b/lib/stencil-push.spec.js index 4e20c00c..4324b4de 100644 --- a/lib/stencil-push.spec.js +++ b/lib/stencil-push.spec.js @@ -1,15 +1,18 @@ 'use strict'; const Code = require('code'); -const Lab = require('lab'); -const lab = exports.lab = Lab.script(); -const describe = lab.describe; -const expect = Code.expect; -const it = lab.it; +const Lab = require('@hapi/lab'); const sinon = require('sinon'); +const Wreck = require('wreck'); +const { promisify } = require('util'); + const StencilPush = require('./stencil-push'); const utils = require('./stencil-push.utils.js'); -const Wreck = require('wreck'); + +const expect = Code.expect; +const lab = exports.lab = Lab.script(); +const describe = lab.describe; +const it = lab.it; const mockDb = { _data: {}, get data() { @@ -23,7 +26,7 @@ const mockDb = { describe('stencil push', () => { let sandbox; - lab.beforeEach(done => { + lab.beforeEach(() => { mockDb.data = {}; sandbox = sinon.createSandbox(); @@ -53,39 +56,40 @@ describe('stencil push', () => { }); }; } - - done(); }); - lab.afterEach(done => { + lab.afterEach(() => { sandbox.restore(); - done(); }); - it('should throw an error if dotStencilFilePath is not provided', done => { + it('should throw an error if dotStencilFilePath is not provided', () => { const throws = () => { StencilPush(); }; expect(throws).to.throw('dotStencilFilePath is required!'); - done(); }); - it('should return an error if dotStencilFilePath does not map to a file', done => { - StencilPush({ - dotStencilFilePath: 'DNE', - }, err => { - expect(err).to.be.an.error(/ENOENT/); - done(); - }); + it('should return an error if dotStencilFilePath does not map to a file', async () => { + let error; + try { + await promisify(StencilPush)({ dotStencilFilePath: 'DNE' }); + } catch (err) { + error = err; + } + + expect(error).to.be.an.error(/ENOENT/); }); - it('should return an error if it fails to retrieve the store hash', done => { + it('should return an error if it fails to retrieve the store hash', async () => { const dotStencilFilePath = `${__dirname}/../test/_mocks/bin/dotStencilFile.json`; + let error; + try { + await promisify(StencilPush)({ dotStencilFilePath }); + } catch (err) { + error = err; + } - StencilPush({ dotStencilFilePath }, err => { - expect(err).to.be.an.error('Failed to retrieve store hash'); - done(); - }); + expect(error).to.be.an.error('Failed to retrieve store hash'); }); }); diff --git a/lib/stencil-push.utils.spec.js b/lib/stencil-push.utils.spec.js index 2aff914f..ac886bbf 100644 --- a/lib/stencil-push.utils.spec.js +++ b/lib/stencil-push.utils.spec.js @@ -1,15 +1,18 @@ 'use strict'; const Code = require('code'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); +const sinon = require('sinon'); +const Wreck = require('wreck'); +const { promisify } = require('util'); + +const mockConfig = require('../test/_mocks/bin/dotStencilFile.json'); +const { getStoreHash } = require('./stencil-push.utils'); + const lab = exports.lab = Lab.script(); const describe = lab.describe; -const expect = Code.expect; -const mockConfig = require('../test/_mocks/bin/dotStencilFile.json'); const it = lab.it; -const sinon = require('sinon'); -const Wreck = require('wreck'); -const utils = require('./stencil-push.utils'); +const expect = Code.expect; const mockDb = { _data: {}, get data() { @@ -21,20 +24,18 @@ const mockDb = { }; describe('stencil push utils', () => { - lab.beforeEach(done => { + lab.beforeEach(() => { this.wreckReqStub = sinon.stub(Wreck, 'request').callsFake((method, url, options, callback) => { callback(null, mockDb.data); }); this.wreckReadStub = sinon.stub(Wreck, 'read').callsFake((response, options, callback) => { callback(null, response); }); - done(); }); - lab.afterEach(done => { + lab.afterEach(() => { this.wreckReqStub.restore(); this.wreckReadStub.restore(); - done(); }); describe('.getStoreHash()', () => { @@ -43,13 +44,11 @@ describe('stencil push utils', () => { statusCode: 200, }; - it('should get the store hash', done => { - utils.getStoreHash({ config: mockConfig }, (err, result) => { - expect(err).to.be.null(); - expect(result.storeHash).to.be.equal(mockDb.data.store_hash); - expect(result.config.normalStoreUrl).to.be.equal(mockConfig.normalStoreUrl); - done(); - }); + it('should get the store hash', async () => { + const result = await promisify(getStoreHash)({ config: mockConfig }); + + expect(result.storeHash).to.be.equal(mockDb.data.store_hash); + expect(result.config.normalStoreUrl).to.be.equal(mockConfig.normalStoreUrl); }); }); }); diff --git a/lib/theme-api-client.spec.js b/lib/theme-api-client.spec.js index 7bf28c3a..ab79e7f1 100644 --- a/lib/theme-api-client.spec.js +++ b/lib/theme-api-client.spec.js @@ -1,7 +1,7 @@ 'use strict'; const Code = require('code'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); const lab = exports.lab = Lab.script(); const describe = lab.describe; const expect = Code.expect; @@ -13,42 +13,43 @@ describe('theme-api-client', () => { describe('printErrorMessages()', () => { let consoleLogStub; - lab.before(done => { + lab.before(() => { consoleLogStub = sinon.stub(console, 'log'); - done(); }); - lab.after(done => { + lab.after(() => { console.log.restore(); - done(); }); - it('should log unknown error and return if input is not an array', done => { + it('should log unknown error and return if input is not an array', () => { expect(themeApiClient.printErrorMessages("string")).to.be.equal(false); expect(consoleLogStub.calledOnce).to.be.equal(true); + consoleLogStub.resetHistory(); + expect(themeApiClient.printErrorMessages({ "key": "value" })).to.be.equal(false); expect(consoleLogStub.calledOnce).to.be.equal(true); + consoleLogStub.resetHistory(); + expect(themeApiClient.printErrorMessages(null)).to.be.equal(false); expect(consoleLogStub.calledOnce).to.be.equal(true); - done(); }); - it('should log error message for each error in the array', done => { + it('should log error message for each error in the array', () => { consoleLogStub.resetHistory(); const arrayInput = [{"message": "first_error"}, {"message": "2nd_error"}]; + expect(themeApiClient.printErrorMessages(arrayInput)).to.be.equal(true); expect(consoleLogStub.calledThrice).to.be.equal(true); - done(); }); - it('should skip non object elements in the input array', done => { + it('should skip non object elements in the input array', () => { consoleLogStub.resetHistory(); const arrayInput = [{"message": "first_error"}, "string", {"message": "2nd_error"}]; + expect(themeApiClient.printErrorMessages(arrayInput)).to.be.equal(true); expect(consoleLogStub.calledThrice).to.be.equal(true); - done(); }); }); }); diff --git a/lib/theme-config.spec.js b/lib/theme-config.spec.js index 942639dd..728d770c 100644 --- a/lib/theme-config.spec.js +++ b/lib/theme-config.spec.js @@ -1,17 +1,20 @@ 'use strict'; const Code = require('code'); -const Os = require('os'); -const Fs = require('fs'); const Hoek = require('hoek'); -const Lab = require('lab'); -const Path = require('path'); +const Lab = require('@hapi/lab'); const Sinon = require('sinon'); +const Path = require('path'); +const Os = require('os'); +const Fs = require('fs'); +const { promisify } = require('util'); + const ThemeConfig = require('./theme-config'); -const lab = exports.lab = Lab.script(); const themePath = Path.join(process.cwd(), 'test/_mocks/themes/valid'); const missingVariationsThemePath = Path.join(process.cwd(), 'test/_mocks/themes/missing-variation'); const bareBonesThemePath = Path.join(process.cwd(), 'test/_mocks/themes/bare-bones'); + +const lab = exports.lab = Lab.script(); const describe = lab.describe; const expect = Code.expect; const it = lab.it; @@ -19,20 +22,16 @@ const it = lab.it; describe('ThemeConfig', () => { let themeConfig; - lab.beforeEach(done => { + lab.beforeEach(async () => { themeConfig = ThemeConfig.getInstance(themePath).setVariationByName('First'); - - done(); }); describe('getInstance()', () => { - it ('should always return the same instance', done => { + it ('should always return the same instance', async () => { expect(themeConfig).to.equal(ThemeConfig.getInstance()); - - done(); }); - it ('should allow overwriting of configPath, schemaPath, and variationName by calling getInstance with params', done => { + it ('should allow overwriting of configPath, schemaPath, and variationName by calling getInstance with params', async () => { const isWindows = Os.platform() === 'win32'; const secondConfigPath = isWindows ? '\\fake\\config.json' : '/fake/config.json'; const secondSchemaPath = isWindows ? '\\fake\\schema.json' : '/fake/schema.json'; @@ -41,14 +40,12 @@ describe('ThemeConfig', () => { expect(secondThemeConfig.configPath).to.equal(secondConfigPath); expect(secondThemeConfig.schemaPath).to.equal(secondSchemaPath); expect(secondThemeConfig).to.equal(themeConfig); - - done(); }); }); describe('getConfig()', () => { - it('should return the correct config for the current variation', done => { - var config = ThemeConfig.getInstance().setVariationByName('Second').getConfig(), + it('should return the correct config for the current variation', async () => { + const config = ThemeConfig.getInstance().setVariationByName('Second').getConfig(), originalSettingsToCompare = { color: '#ffffff', font: 'Sans Something', @@ -71,51 +68,41 @@ describe('ThemeConfig', () => { expect(config.settings).to.equal(settingsToCompare); expect(config.images).to.equal(imagesToCompare); expect(ThemeConfig.getInstance().globalSettings).to.equal(originalSettingsToCompare); - - done(); }); - it('should throw an Error if there are no variations in config.json file', done => { - var themeConfig = ThemeConfig.getInstance(missingVariationsThemePath); + it('should throw an Error if there are no variations in config.json file', async () => { + const themeConfig = ThemeConfig.getInstance(missingVariationsThemePath); expect(themeConfig.getConfig).to.throw(Error); - - done(); }); - it('should grab the first variation if none is passed in', done => { - var themeConfig = ThemeConfig.getInstance(); + it('should grab the first variation if none is passed in', async () => { + const themeConfig = ThemeConfig.getInstance(); themeConfig.setVariationByName(null); // console.log(themeConfig.getConfig()); expect(themeConfig.getConfig().variationName).to.equal('First'); - - done(); }); - it('should grab a specific variation if passed in', done => { - var themeConfig = ThemeConfig.getInstance(); + it('should grab a specific variation if passed in', async () => { + const themeConfig = ThemeConfig.getInstance(); themeConfig.setVariationByName('Second'); expect(themeConfig.getConfig().variationName).to.equal('Second'); - - done(); }); - it('should throw an Error if the passed in variation name does not match any in the config.json', done => { - var themeConfig = ThemeConfig.getInstance(themePath); + it('should throw an Error if the passed in variation name does not match any in the config.json', async () => { + const themeConfig = ThemeConfig.getInstance(themePath); function setVariation() { themeConfig.setVariationByName('Does Not Exist'); } expect(setVariation).to.throw(Error); - - done(); }); - it('should set proper default values if they do not exist', done => { - var themeConfig = ThemeConfig.getInstance(bareBonesThemePath), + it('should set proper default values if they do not exist', async () => { + const themeConfig = ThemeConfig.getInstance(bareBonesThemePath), config = themeConfig.getConfig(); expect(config.settings).to.equal({}); @@ -123,18 +110,16 @@ describe('ThemeConfig', () => { expect(config.css_compiler).to.equal('scss'); expect(config.autoprefixer_cascade).to.equal(true); expect(config.autoprefixer_browsers).to.equal(['> 1%', 'last 2 versions', 'Firefox ESR']); - - done(); }); }); describe('updateConfig()', () => { - var config, + let config, newSettings, originalSettings, themeConfig; - lab.beforeEach(done => { + lab.beforeEach(async () => { themeConfig = ThemeConfig.getInstance(); config = themeConfig.getConfig(); originalSettings = Hoek.clone(config.settings); @@ -145,100 +130,80 @@ describe('ThemeConfig', () => { checkbox: true, radio: 'first', }; - - done(); }); - it('should update the currentConfig with the new changes', done => { + it('should update the currentConfig with the new changes', async () => { expect(originalSettings).not.to.equal(newSettings); themeConfig.updateConfig(newSettings); expect(themeConfig.getConfig().settings).not.to.equal(originalSettings); expect(themeConfig.getConfig().settings).to.equal(newSettings); - - done(); }); - it('should not write to config file if saveToFile is falsey', done => { + it('should not write to config file if saveToFile is falsey', async () => { Sinon.stub(Fs, 'writeFileSync'); themeConfig.updateConfig(newSettings); expect(Fs.writeFileSync.called).to.be.false(); Fs.writeFileSync.restore(); - - done(); }); - it('should write to config file if saveToFile is truthy', done => { + it('should write to config file if saveToFile is truthy', async () => { Sinon.stub(Fs, 'writeFileSync'); themeConfig.updateConfig(newSettings, true); expect(Fs.writeFileSync.called).to.be.true(); Fs.writeFileSync.restore(); - - done(); }); - it('should just modify the variations section of the file', done => { - var configPath = Path.join(themePath, 'config.json'); - var initialConfig = JSON.parse(Fs.readFileSync(configPath, {encoding: 'utf-8'})); - - Sinon.stub(Fs, 'writeFileSync').callsFake(testSave); - - function testSave(path, newConfig) { - newConfig = JSON.parse(newConfig); + it('should just modify the variations section of the file', async () => { + const configPath = Path.join(themePath, 'config.json'); + const initialConfig = JSON.parse(Fs.readFileSync(configPath, {encoding: 'utf-8'})); - expect(newConfig).not.to.equal(initialConfig); + const testSavePromise = new Promise(resolve => + Sinon.stub(Fs, 'writeFileSync').callsFake((...args) => resolve(args)), + ); + themeConfig.updateConfig(newSettings, true); + let [, newConfig] = await testSavePromise; - delete newConfig.variations; - delete initialConfig.variations; + newConfig = JSON.parse(newConfig); - expect(newConfig).to.equal(initialConfig); + expect(newConfig).not.to.equal(initialConfig); - done(); - } + delete newConfig.variations; + delete initialConfig.variations; - themeConfig.updateConfig(newSettings, true); + expect(newConfig).to.equal(initialConfig); Fs.writeFileSync.restore(); }); }); describe('getSchema()', () => { + it('should return the correct schema', async () => { + const themeConfig = ThemeConfig.getInstance(); + const originalSchema = require(Path.join(themePath, 'schema.json')); - it('should return the correct schema', done => { - - var themeConfig = ThemeConfig.getInstance(); - var originalSchema = require(Path.join(themePath, 'schema.json')); + const schema = await promisify(themeConfig.getSchema.bind(themeConfig))(); - themeConfig.getSchema((err, schema) => { + expect(schema).to.be.an.array(); - expect(err).to.be.null(); + expect(schema[0]).to.equal(originalSchema[0]); + expect(schema).to.have.length(2); - expect(schema).to.be.an.array(); - - expect(schema[0]).to.equal(originalSchema[0]); - expect(schema).to.have.length(2); - - expect(schema[1].settings[0].force_reload).to.true(); - expect(schema[1].settings[1].force_reload).to.true(); - expect(schema[1].settings[2].force_reload).to.true(); - - done(); - }); + expect(schema[1].settings[0].force_reload).to.true(); + expect(schema[1].settings[1].force_reload).to.true(); + expect(schema[1].settings[2].force_reload).to.true(); }); - it('should return an empty schema', done => { - - var themeConfig = ThemeConfig.getInstance(bareBonesThemePath); + it('should return an empty schema', async () => { + const themeConfig = ThemeConfig.getInstance(bareBonesThemePath); - themeConfig.getSchema((err, schema) => { - expect(schema).to.be.an.array(); - expect(schema).to.have.length(0); + const schema = await promisify(themeConfig.getSchema.bind(themeConfig))(); - done(); - }); + expect(schema).to.be.an.array(); + expect(schema).to.have.length(0); }); }); }); diff --git a/lib/validator/schema-translations.spec.js b/lib/validator/schema-translations.spec.js index 1dbade8b..7b4d00f4 100644 --- a/lib/validator/schema-translations.spec.js +++ b/lib/validator/schema-translations.spec.js @@ -1,6 +1,6 @@ const Paths = require('path'); const Code = require('code'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); const lab = exports.lab = Lab.script(); const describe = lab.describe; const it = lab.it; @@ -16,52 +16,42 @@ const validatorSchemaTranslations = () => { }; describe('ValidatorSchemaTranslations', () => { - it('should return translations', function (done) { + it('should return translations', () => { const instance = validatorSchemaTranslations(); instance.setTranslations(schemaTranslations); expect(instance.getTranslations()).equals(schemaTranslations); - - done(); }); - it('should return translations keys', function (done) { + it('should return translations keys', () => { const instance = validatorSchemaTranslations(); instance.setSchema(schema); expect(instance.getSchemaKeys()).equals(['i18n.Test']); - - done(); }); - it('should return validation schema', function (done) { + it('should return validation schema', () => { const instance = validatorSchemaTranslations(); expect(instance.getValidationSchema()).equals(validationsTranslations); - - done(); }); - it('should return i18n keys array without duplicates', function (done) { + it('should return i18n keys array without duplicates', () => { const instance = validatorSchemaTranslations(); instance.setSchemaKeys('i18n.Global'); instance.setSchemaKeys('i18n.Global'); expect(instance.getSchemaKeys()).equals(['i18n.Global']); - - done(); }); - it('should return empty i18n keys array if specify empty string', function (done) { + it('should return empty i18n keys array if specify empty string', () => { const instance = validatorSchemaTranslations(); instance.setSchemaKeys(''); expect(instance.getSchemaKeys()).equals([]); - - done(); }); }); diff --git a/package-lock.json b/package-lock.json index 35bb2202..8a58b690 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1936,11 +1936,71 @@ "@hapi/hoek": "8.x.x" } }, + "@hapi/bossy": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@hapi/bossy/-/bossy-4.1.3.tgz", + "integrity": "sha512-a3+tEnP2OeN1rm3Bqpo8rO11RAIAOIre4pmjzABkAQp23Y0qv/bD2txkdTl9Gajxo6YNYsgy9dlyQcCUczx8JQ==", + "dev": true, + "requires": { + "@hapi/boom": "7.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/joi": "16.x.x" + }, + "dependencies": { + "@hapi/boom": { + "version": "7.4.11", + "resolved": "https://registry.npmjs.org/@hapi/boom/-/boom-7.4.11.tgz", + "integrity": "sha512-VSU/Cnj1DXouukYxxkes4nNJonCnlogHvIff1v1RVoN4xzkKhMXX+GRmb3NyH1iar10I9WFPDv2JPwfH3GaV0A==", + "dev": true, + "requires": { + "@hapi/hoek": "8.x.x" + } + }, + "@hapi/joi": { + "version": "16.1.8", + "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-16.1.8.tgz", + "integrity": "sha512-wAsVvTPe+FwSrsAurNt5vkg3zo+TblvC5Bb1zMVK6SJzZqw9UrJnexxR+76cpePmtUZKHAPxcQ2Bf7oVHyahhg==", + "dev": true, + "requires": { + "@hapi/address": "^2.1.2", + "@hapi/formula": "^1.2.0", + "@hapi/hoek": "^8.2.4", + "@hapi/pinpoint": "^1.0.2", + "@hapi/topo": "^3.1.3" + } + } + } + }, "@hapi/bourne": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-1.3.2.tgz", "integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==" }, + "@hapi/eslint-config-hapi": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/@hapi/eslint-config-hapi/-/eslint-config-hapi-12.3.0.tgz", + "integrity": "sha512-P3ZdC97vYUAVgV6fBuAEXh2Ol04R+Zp5LMNmJ9SAF69u8wT7v6vCgdX/SqZiXEzEKQ9YFpuh+m28wNj5aJ1tDg==", + "dev": true + }, + "@hapi/eslint-plugin-hapi": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@hapi/eslint-plugin-hapi/-/eslint-plugin-hapi-4.3.5.tgz", + "integrity": "sha512-2o6eJrE6qH0orR0kDB3B+lyQ1Swq7SrZ+ZubvE5UGmXBrHOYmWV/RhuvCU0mmSwRn0vyU3sK41doEqya7G3lIA==", + "dev": true, + "requires": { + "@hapi/rule-capitalize-modules": "1.x.x", + "@hapi/rule-for-loop": "1.x.x", + "@hapi/rule-no-arrowception": "1.x.x", + "@hapi/rule-no-var": "1.x.x", + "@hapi/rule-scope-start": "2.x.x" + } + }, + "@hapi/formula": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-1.2.0.tgz", + "integrity": "sha512-UFbtbGPjstz0eWHb+ga/GM3Z9EzqKXFWIbSOFURU0A/Gku0Bky4bCk9/h//K2Xr3IrCfjFNhMm4jyZ5dbCewGA==", + "dev": true + }, "@hapi/hoek": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz", @@ -1964,6 +2024,150 @@ } } }, + "@hapi/lab": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@hapi/lab/-/lab-21.0.0.tgz", + "integrity": "sha512-csYjq2DE+JzKPW+BaqEfDzbHJC5LIC+M1eYUljm0+zD7xoaKUXFPEWqlP4JSbJ4e16wRNY8Uid3UshxC+rUByw==", + "dev": true, + "requires": { + "@hapi/bossy": "4.x.x", + "@hapi/eslint-config-hapi": "12.x.x", + "@hapi/eslint-plugin-hapi": "4.x.x", + "@hapi/hoek": "8.x.x", + "diff": "4.x.x", + "eslint": "6.x.x", + "espree": "6.x.x", + "find-rc": "4.x.x", + "globby": "10.x.x", + "handlebars": "4.x.x", + "mkdirp": "0.5.x", + "seedrandom": "3.x.x", + "source-map": "0.7.x", + "source-map-support": "0.5.x", + "supports-color": "7.x.x", + "typescript": "3.6.x", + "will-call": "1.x.x" + }, + "dependencies": { + "handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, + "@hapi/pinpoint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-1.0.2.tgz", + "integrity": "sha512-dtXC/WkZBfC5vxscazuiJ6iq4j9oNx1SHknmIr8hofarpKUZKmlUVYVIhNVzIEgK5Wrc4GMHL5lZtt1uS2flmQ==", + "dev": true + }, + "@hapi/rule-capitalize-modules": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@hapi/rule-capitalize-modules/-/rule-capitalize-modules-1.2.1.tgz", + "integrity": "sha512-XduBSQQehgY/PJX/Ud2H5UdVyNVEC3QiU00vOHWvpn+kbH1co2dmzpu2JEGGxKmdGHjm8jdDkrlqVxGFXHAuhQ==", + "dev": true + }, + "@hapi/rule-for-loop": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@hapi/rule-for-loop/-/rule-for-loop-1.2.1.tgz", + "integrity": "sha512-9Y2yjNpmhntryViPTb6JlTCqma9fF+H0lCtjvlWA0La/ckxPSzXfwh9kgroyjQ3mJiwKDUYboqC4/BK6L5DFUg==", + "dev": true + }, + "@hapi/rule-no-arrowception": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@hapi/rule-no-arrowception/-/rule-no-arrowception-1.1.2.tgz", + "integrity": "sha512-NV6IpfcUpI6w/6oR2oBFaBUoOGC3j3xzfXq7ZciBnmOyReqwuSiyvwLb9SeSomei/n1LHaVdnIXJnMD9IAma2Q==", + "dev": true + }, + "@hapi/rule-no-var": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@hapi/rule-no-var/-/rule-no-var-1.1.4.tgz", + "integrity": "sha512-u0gtMRd9uxlmmew3H5pBZJe1D64dTz5yhPWU3UcurOwZGTbGYU2PAUpjxE0TOaeCRDW+tL5Y/9f7637P2vqQSA==", + "dev": true + }, + "@hapi/rule-scope-start": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@hapi/rule-scope-start/-/rule-scope-start-2.2.0.tgz", + "integrity": "sha512-n0adld0osaYNXlus/64dCN0GlkMvmwuJfkpM0OtrA2U7x2Iu1XoHV6Lmne3C+9gM8X/xLUviYLoTCOC7IW8RYg==", + "dev": true + }, "@hapi/topo": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.6.tgz", @@ -2722,6 +2926,32 @@ } } }, + "@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + } + }, "@octokit/auth-token": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.2.tgz", @@ -2934,6 +3164,16 @@ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, "@types/graceful-fs": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.3.tgz", @@ -2968,6 +3208,12 @@ "@types/istanbul-lib-report": "*" } }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, "@types/minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", @@ -3106,12 +3352,6 @@ "uri-js": "^4.2.2" } }, - "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", - "dev": true - }, "alce": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/alce/-/alce-1.2.0.tgz", @@ -3783,6 +4023,12 @@ } } }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", @@ -4921,24 +5167,6 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, - "bossy": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/bossy/-/bossy-3.0.4.tgz", - "integrity": "sha1-+a6fJugbQaMY9O4Ng2huSlwlB7k=", - "dev": true, - "requires": { - "hoek": "4.x.x", - "joi": "10.x.x" - }, - "dependencies": { - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", - "dev": true - } - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -5396,23 +5624,6 @@ "unset-value": "^1.0.0" } }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - }, - "dependencies": { - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - } - } - }, "callsite": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", @@ -5632,12 +5843,6 @@ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -7520,12 +7725,35 @@ "resolved": "https://registry.npmjs.org/dev-ip/-/dev-ip-1.0.1.tgz", "integrity": "sha1-p2o+0YVb56ASu4rBbLgPPADcKPA=" }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, "diff-sequences": { "version": "26.0.0", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.0.0.tgz", "integrity": "sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg==", "dev": true }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + }, + "dependencies": { + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + } + } + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -8163,25 +8391,6 @@ } } }, - "eslint-config-hapi": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-hapi/-/eslint-config-hapi-10.1.0.tgz", - "integrity": "sha512-tAUedyvZla1qKt6jhOx7mj5tYDVCwdSyImpEK7wk/A/atKUjg18aHUK6Q6qWWM6rq21I1F/A8JAhIpkk0SvFMQ==", - "dev": true - }, - "eslint-plugin-hapi": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-hapi/-/eslint-plugin-hapi-4.1.0.tgz", - "integrity": "sha512-z1yUoSWArx6pXaC0FoWRFpqjbHn8QWonJiTVhJmiC14jOAT7FZKdKWCkhM4jQrgrkEK9YEv3p2HuzSf5dtWmuQ==", - "dev": true, - "requires": { - "hapi-capitalize-modules": "1.x.x", - "hapi-for-you": "1.x.x", - "hapi-no-var": "1.x.x", - "hapi-scope-start": "2.x.x", - "no-arrowception": "1.x.x" - } - }, "eslint-scope": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", @@ -8533,59 +8742,145 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" - }, - "fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", "dev": true, "requires": { - "bser": "2.1.1" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "requires": { - "pend": "~1.2.0" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "requires": { - "flat-cache": "^2.0.1" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "fastq": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", + "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "requires": { + "flat-cache": "^2.0.1" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" }, "fill-range": { @@ -8670,6 +8965,12 @@ } } }, + "find-rc": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/find-rc/-/find-rc-4.0.1.tgz", + "integrity": "sha512-YEox27Ie95/zoqkxm6BYSPguJsvYz9d9G1YuaNKhxjSgZbjMC9q5blmvbL4+Ail8yacQIE0OObhDb+ZwvfJafw==", + "dev": true + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -10493,6 +10794,59 @@ "type-fest": "^0.8.1" } }, + "globby": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + } + } + }, "globule": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", @@ -11977,30 +12331,6 @@ } } }, - "hapi-capitalize-modules": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/hapi-capitalize-modules/-/hapi-capitalize-modules-1.1.6.tgz", - "integrity": "sha1-eZEXFBXhXmqjIx5k3ac8gUZmUxg=", - "dev": true - }, - "hapi-for-you": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hapi-for-you/-/hapi-for-you-1.0.0.tgz", - "integrity": "sha1-02L77o172pwseAHiB+WlzRoLans=", - "dev": true - }, - "hapi-no-var": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hapi-no-var/-/hapi-no-var-1.0.1.tgz", - "integrity": "sha512-kk2xyyTzI+eQ/oA1rO4eVdCpYsrPHVERHa6+mTHD08XXFLaAkkaEs6reMg1VyqGh2o5xPt//DO4EhCacLx/cRA==", - "dev": true - }, - "hapi-scope-start": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/hapi-scope-start/-/hapi-scope-start-2.1.1.tgz", - "integrity": "sha1-dJWnJv5yt7yo3izcwdh82M5qtPI=", - "dev": true - }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -12892,12 +13222,6 @@ "is-unc-path": "^1.0.0" } }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -15105,47 +15429,6 @@ } } }, - "joi": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-10.6.0.tgz", - "integrity": "sha512-hBF3LcqyAid+9X/pwg+eXjD2QBZI5eXnBFJYaAkH4SK3mp9QSRiiQnDYlmlz5pccMvnLcJRS4whhDOTCkmsAdQ==", - "dev": true, - "requires": { - "hoek": "4.x.x", - "isemail": "2.x.x", - "items": "2.x.x", - "topo": "2.x.x" - }, - "dependencies": { - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", - "dev": true - }, - "isemail": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-2.2.1.tgz", - "integrity": "sha1-A1PT2aYpUQgMJiwqoKQrjqjp4qY=", - "dev": true - }, - "items": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/items/-/items-2.1.2.tgz", - "integrity": "sha512-kezcEqgB97BGeZZYtX/MA8AG410ptURstvnz5RAgyFZ8wQFPMxHY8GpTq+/ZHKT3frSlIthUq7EvLt9xn3TvXg==", - "dev": true - }, - "topo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", - "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", - "dev": true, - "requires": { - "hoek": "4.x.x" - } - } - } - }, "js-base64": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.2.tgz", @@ -15251,15 +15534,6 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -15283,12 +15557,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, "jsonlint": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.3.tgz", @@ -15507,543 +15775,10 @@ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true }, - "lab": { - "version": "14.3.4", - "resolved": "https://registry.npmjs.org/lab/-/lab-14.3.4.tgz", - "integrity": "sha512-IFnuYVRd6CtnFTFgUbjPCFrrCIked5BvGH/dX+/h+6pi3IrQrK21JsKy/J1CshEm6sMe980+oswtK8lZCusHSA==", - "dev": true, - "requires": { - "bossy": "3.x.x", - "code": "4.1.x", - "diff": "3.5.x", - "eslint": "4.19.x", - "eslint-config-hapi": "10.x.x", - "eslint-plugin-hapi": "4.x.x", - "espree": "3.5.x", - "find-rc": "3.0.x", - "handlebars": "4.x.x", - "hoek": "4.x.x", - "items": "2.x.x", - "json-stable-stringify": "1.x.x", - "json-stringify-safe": "5.x.x", - "mkdirp": "0.5.x", - "seedrandom": "2.4.x", - "source-map": "0.6.x", - "source-map-support": "0.4.x", - "supports-color": "4.4.x" - }, - "dependencies": { - "acorn": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", - "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", - "dev": true - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "eslint": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", - "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", - "dev": true, - "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", - "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.4", - "esquery": "^1.0.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", - "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "regexpp": "^1.0.1", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", - "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "4.0.2", - "text-table": "~0.2.0" - } - }, - "eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, - "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true, - "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - } - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } - }, - "find-rc": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/find-rc/-/find-rc-3.0.1.tgz", - "integrity": "sha1-VKQXg3DxC8k3H6jRssKAmir6DM4=", - "dev": true - }, - "flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", - "dev": true, - "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", - "dev": true, - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", - "dev": true - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "items": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/items/-/items-2.1.2.tgz", - "integrity": "sha512-kezcEqgB97BGeZZYtX/MA8AG410ptURstvnz5RAgyFZ8wQFPMxHY8GpTq+/ZHKT3frSlIthUq7EvLt9xn3TvXg==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "regexpp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", - "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", - "dev": true - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - }, - "dependencies": { - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - } - } - }, - "table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", - "dev": true, - "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - } - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - } - } - }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", "dev": true, "requires": { "default-resolution": "^2.0.0", @@ -16990,6 +16725,12 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, "messageformat": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/messageformat/-/messageformat-0.2.2.tgz", @@ -17333,12 +17074,6 @@ "path-to-regexp": "^1.7.0" } }, - "no-arrowception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/no-arrowception/-/no-arrowception-1.0.0.tgz", - "integrity": "sha1-W/PpXrnEG1c4SoBTM9qjtzTuMno=", - "dev": true - }, "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", @@ -18107,12 +17842,6 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", @@ -18293,12 +18022,6 @@ } } }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", - "dev": true - }, "portscanner": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.1.1.tgz", @@ -19214,24 +18937,6 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - } - } - }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -19355,6 +19060,12 @@ "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -19415,6 +19126,12 @@ "is-promise": "^2.1.0" } }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true + }, "rx": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", @@ -19890,9 +19607,9 @@ } }, "seedrandom": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.4.tgz", - "integrity": "sha512-9A+PDmgm+2du77B5i0Ip2cxOqqHjgNxnBgglxLcX78A2D6c2rTo61z4jnVABpF4cKeDMDG+cmXXvdnqse2VqMA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", "dev": true }, "semver": { @@ -21499,6 +21216,12 @@ "kind-of": "^3.1.0" } }, + "typescript": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.5.tgz", + "integrity": "sha512-BEjlc0Z06ORZKbtcxGrIvvwYs5hAnuo6TKdNFL55frVDlB+na3z5bsLhFaIxmT+dPWgBIjMo6aNnTOgHHmHgiQ==", + "dev": true + }, "ua-parser-js": { "version": "0.7.21", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz", @@ -21919,6 +21642,12 @@ "string-width": "^1.0.2 || 2" } }, + "will-call": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/will-call/-/will-call-1.0.1.tgz", + "integrity": "sha512-1hEeV8SfBYhNRc/bNXeQfyUBX8Dl9SCYME3qXh99iZP9wJcnhnlBsoBw8Y0lXVZ3YuPsoxImTzBiol1ouNR/hg==", + "dev": true + }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", diff --git a/package.json b/package.json index ad6c9249..bec45589 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "devDependencies": { "@commitlint/cli": "^9.1.2", "@commitlint/config-conventional": "^7.1.2", + "@hapi/lab": "^21.0.0", "babel-core": "^6.8.0", "babel-loader": "^6.2.4", "babel-preset-es2015": "^6.6.0", @@ -93,7 +94,6 @@ "gulp-util": "^3.0.8", "husky": "^4.2.1", "jest": "^26.1.0", - "lab": "^14.3.3", "npm-which": "^3.0.1", "object-to-spawn-args": "^1.1.1", "sinon": "^8.1.1" diff --git a/server/lib/utils.spec.js b/server/lib/utils.spec.js index bcfe0fbd..ff672cdf 100644 --- a/server/lib/utils.spec.js +++ b/server/lib/utils.spec.js @@ -1,31 +1,29 @@ const Code = require('code'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); + +const Utils = require('./utils'); + const lab = exports.lab = Lab.script(); const describe = lab.describe; const expect = Code.expect; const it = lab.it; describe('Utils', () => { - const Utils = require('./utils'); - describe('uuid2int', () => { - it('should return an int value presentation', done => { + it('should return an int value presentation', () => { expect(Utils.uuid2int('00000000-0000-0000-0000-000000000001')).to.equal(1); expect(Utils.uuid2int('00000000-0000-0000-0000-000000000102')).to.equal(102); - done(); }); - it('should throw an error if an invalid uuid is used', done => { + it('should throw an error if an invalid uuid is used', () => { expect(() => Utils.uuid2int('00002')).to.throw(Error); - done(); }); }); describe('int2uuid', () => { - it('should return an uuid value presentation', done => { + it('should return an uuid value presentation', () => { expect(Utils.int2uuid(1)).to.equal('00000000-0000-0000-0000-000000000001'); expect(Utils.int2uuid(505)).to.equal('00000000-0000-0000-0000-000000000505'); - done(); }); }); }); diff --git a/server/plugins/renderer/renderer.module.spec.js b/server/plugins/renderer/renderer.module.spec.js index 2ea0a3d2..56163ac2 100644 --- a/server/plugins/renderer/renderer.module.spec.js +++ b/server/plugins/renderer/renderer.module.spec.js @@ -1,21 +1,24 @@ 'use strict'; const Code = require('code'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); const sinon = require('sinon'); const Wreck = require('wreck'); -const StencilCLI = require('../../index'); +const Path = require('path'); +const { promisify } = require('util'); + +const createStencilCLIServer = require('../../index'); + const lab = exports.lab = Lab.script(); const expect = Code.expect; const it = lab.it; -const Path = require('path'); lab.describe('Renderer Plugin', () => { let server; let wreckRequestStub; let wreckReadStub; - lab.before(done => { + lab.before(async () => { const options = { dotStencilFile: { storeUrl: "https://store-abc123.mybigcommerce.com", @@ -28,74 +31,65 @@ lab.describe('Renderer Plugin', () => { themePath: Path.join(process.cwd(), 'test/_mocks/themes/valid'), }; - StencilCLI(options, (err , srv) => { - server = srv; - - // Don't log errors during the test - server.ext('onPostHandler', (request, reply) => { - if (request.response.isBoom) { - return reply().code(500); - } - - reply.continue(); - }); + server = await promisify(createStencilCLIServer)(options); - done(); + // Don't log errors during the test + server.ext('onPostHandler', (request, reply) => { + if (request.response.isBoom) { + return reply().code(500); + } + reply.continue(); }); }); - lab.beforeEach(done => { + lab.beforeEach(() => { wreckRequestStub = sinon.stub(Wreck, 'request'); wreckReadStub = sinon.stub(Wreck, 'read'); - - done(); }); - lab.afterEach(done => { + lab.afterEach(async () => { wreckRequestStub.restore(); wreckReadStub.restore(); + }); - server.stop(done); + lab.after(async () => { + await promisify(server.stop.bind(server))(); }); - it('should handle fatal errors in the BCApp request', done => { - var options = { + it('should handle fatal errors in the BCApp request', async () => { + const options = { method: "GET", url: "/test", }; wreckRequestStub.callsArgWith(3, new Error('failure')); - server.inject(options, response => { - expect(response.statusCode).to.equal(500); + const response = await new Promise(resolve => + server.inject(options, resolve), + ); - done(); - }); + expect(response.statusCode).to.equal(500); }); - it('should handle responses of a 500 in the BCApp request', done => { - var options = { + it('should handle responses of a 500 in the BCApp request', async () => { + const options = { method: "GET", url: "/", }; + wreckRequestStub.callsArgWith(3, null, { statusCode: 500 }); - wreckRequestStub.callsArgWith(3, null, { - statusCode: 500, - }); - - server.inject(options, response => { - expect(response.statusCode).to.equal(500); + const response = await new Promise(resolve => + server.inject(options, resolve), + ); - done(); - }); + expect(response.statusCode).to.equal(500); }); - it('should handle redirects in the BCApp request', done => { - var options = { + it('should handle redirects in the BCApp request', async () => { + const options = { method: "GET", url: "/", }; - wreckRequestStub.callsArgWith(3, null, { statusCode: 301, headers: { @@ -103,20 +97,19 @@ lab.describe('Renderer Plugin', () => { }, }); - server.inject(options, response => { - expect(response.statusCode).to.equal(301); - expect(response.headers.location).to.equal('http://www.example.com/'); + const response = await new Promise(resolve => + server.inject(options, resolve), + ); - done(); - }); + expect(response.statusCode).to.equal(301); + expect(response.headers.location).to.equal('http://www.example.com/'); }); - it('should handle unauthorized in the Stapler Request', done => { - var options = { + it('should handle unauthorized in the Stapler Request', async () => { + const options = { method: "GET", url: "/", }; - wreckRequestStub.callsArgWith(3, null, { statusCode: 401, headers: { @@ -124,10 +117,10 @@ lab.describe('Renderer Plugin', () => { }, }); - server.inject(options, response => { - expect(response.statusCode).to.equal(401); + const response = await new Promise(resolve => + server.inject(options, resolve), + ); - done(); - }); + expect(response.statusCode).to.equal(401); }); }); diff --git a/server/plugins/renderer/responses/raw-response.spec.js b/server/plugins/renderer/responses/raw-response.spec.js index 7419dfb3..73903464 100644 --- a/server/plugins/renderer/responses/raw-response.spec.js +++ b/server/plugins/renderer/responses/raw-response.spec.js @@ -1,7 +1,7 @@ 'use strict'; const Code = require('code'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); const sinon = require('sinon'); const RawResponse = require('./raw-response'); const Utils = require('../../../lib/utils'); @@ -17,11 +17,11 @@ lab.describe('RawResponse', () => { }; const statusCode = 200; - var request; - var response; - var reply; + let request; + let response; + let reply; - lab.beforeEach(done => { + lab.beforeEach(() => { request = { url: {path: '/'}, app: {themeConfig: {variationIndex: 1}}, @@ -33,40 +33,33 @@ lab.describe('RawResponse', () => { }; reply = sinon.stub().returns(response); - done(); }); lab.describe('respond()', () => { - it('should respond', done => { - var rawResponse = new RawResponse(data, headers, statusCode); + it('should respond', () => { + const rawResponse = new RawResponse(data, headers, statusCode); rawResponse.respond(request, reply); expect(reply.called).to.be.true(); - - done(); }); - it('should append checkout css if is the checkout page', done => { + it('should append checkout css if is the checkout page', () => { request.url.path = '/checkout.php?blah=blah'; - var rawResponse = new RawResponse(data, headers, statusCode); + const rawResponse = new RawResponse(data, headers, statusCode); rawResponse.respond(request, reply); expect(reply.lastCall.args[0]).to.contain(` { - var rawResponse = new RawResponse(data, headers, statusCode); + it('should not append transfer-encoding header', () => { + const rawResponse = new RawResponse(data, headers, statusCode); rawResponse.respond(request, reply); expect(response.header.neverCalledWith('transfer-encoding')).to.be.true(); expect(response.header.calledWith('content-type')).to.be.true(); - - done(); }); }); }); diff --git a/server/plugins/router/router.module.spec.js b/server/plugins/router/router.module.spec.js index bae39905..79002416 100644 --- a/server/plugins/router/router.module.spec.js +++ b/server/plugins/router/router.module.spec.js @@ -1,14 +1,17 @@ const Code = require('code'); const Hapi = require('hapi'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); +const { promisify } = require('util'); + +const router = require('./router.module'); + +const expect = Code.expect; const lab = exports.lab = Lab.script(); const describe = lab.describe; -const expect = Code.expect; const it = lab.it; -const router = require('./router.module'); describe('Router', () => { - var server = new Hapi.Server(); + const server = new Hapi.Server(); const RendererPluginMock = { register: function(server, options, next) { server.expose('implementation', (request, reply) => reply('RendererHandlerFired')); @@ -39,71 +42,79 @@ describe('Router', () => { port: 3000, }); - lab.before(done => { - server.register([ + lab.before(async () => { + await promisify(server.register.bind(server))([ RendererPluginMock, ThemeAssetsMock, router, - ], err => { - expect(err).to.equal(undefined); - server.start(done); - }); + ]); + + await promisify(server.start.bind(server))(); }); - lab.after(done => { - server.stop(done); + lab.after(async () => { + await promisify(server.stop.bind(server))(); }); - it('should call the Renderer handler', done => { - server.inject({ + it('should call the Renderer handler', async () => { + const options = { method: 'GET', url: '/test', - }, response => { - expect(response.statusCode).to.equal(200); - expect(response.payload).to.equal('RendererHandlerFired'); + }; + + const response = await new Promise(resolve => + server.inject(options, resolve), + ); - done(); - }); + expect(response.statusCode).to.equal(200); + expect(response.payload).to.equal('RendererHandlerFired'); }); - it('should call the CSS handler', done => { - server.inject({ + it('should call the CSS handler', async () => { + const options = { method: 'GET', url: '/stencil/123/css/file.css', - }, response => { - expect(response.statusCode).to.equal(200); - expect(response.payload).to.equal('CssHandlerFired'); + }; + + const response = await new Promise(resolve => + server.inject(options, resolve), + ); - done(); - }); + expect(response.statusCode).to.equal(200); + expect(response.payload).to.equal('CssHandlerFired'); }); - it('should call the assets handler', done => { - server.inject({ + it('should call the assets handler', async () => { + const options = { method: 'GET', url: '/stencil/123/js/file.js', - }, response => { - expect(response.statusCode).to.equal(200); - expect(response.payload).to.equal('assetHandlerFired'); + }; - done(); - }); + const response = await new Promise(resolve => + server.inject(options, resolve), + ); + + expect(response.statusCode).to.equal(200); + expect(response.payload).to.equal('assetHandlerFired'); }); - it('should inject host and origin headers for GraphQL requests', done => { - server.inject({ + it('should inject host and origin headers for GraphQL requests', async () => { + const options = { method: 'POST', url: '/graphql', headers: { 'authorization': 'abc123' }, - }, response => { - expect(response.request.payload.headers).to.include( - { - authorization: 'abc123', - origin: 'https://store-abc123.mybigcommerce.com', - host: 'store-abc123.mybigcommerce.com', - }, - ); - done(); - }); + }; + + const response = await new Promise(resolve => + server.inject(options, resolve), + ); + + expect(response.request.payload.headers).to.include( + { + authorization: 'abc123', + origin: 'https://store-abc123.mybigcommerce.com', + host: 'store-abc123.mybigcommerce.com', + }, + ); }); }); diff --git a/tasks/changelog/changelog-generator.spec.js b/tasks/changelog/changelog-generator.spec.js index 29822bae..409557f1 100644 --- a/tasks/changelog/changelog-generator.spec.js +++ b/tasks/changelog/changelog-generator.spec.js @@ -1,13 +1,14 @@ const ChangelogGenerator = require('./changelog-generator'); const CommandExecutor = require('./command-executor'); const Code = require('code'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); const lab = exports.lab = Lab.script(); const describe = lab.describe; const sinon = require('sinon'); const expect = Code.expect; const it = lab.it; const path = require('path'); +const { promisify } = require('util'); describe('ChangelogGenerator', () => { let changelogGenerator; @@ -15,7 +16,7 @@ describe('ChangelogGenerator', () => { let fs; let executeCommandSpy; - lab.beforeEach( done => { + lab.beforeEach( () => { fs = { statSync: function() { return true; }, }; @@ -24,30 +25,36 @@ describe('ChangelogGenerator', () => { executeCommandSpy = sinon.spy(commandExecutor, "executeCommand"); changelogGenerator = new ChangelogGenerator(fs, '/src', commandExecutor); - - done(); }); - it('executes `conventional-changelog` command', done => { - changelogGenerator.generateChangelog({}, () => { - expect(executeCommandSpy.secondCall.calledWith( - 'conventional-changelog', - [], - { - config: path.join(__dirname, 'default-config.js'), - infile: path.join('/src', 'CHANGELOG.md'), - sameFile: true, - }, - )).to.equal(true); + it('executes `conventional-changelog` command', async() => { + try { + await promisify(changelogGenerator.generateChangelog.bind(changelogGenerator))({}); + + // The generator will throw an error since '/src' doesn't exist, but we don't care, + // just need to make sure that executeCommandSpy was called properly + } catch (err) {} - done(); - }); + expect(executeCommandSpy.secondCall.calledWith( + 'conventional-changelog', + [], + { + config: path.join(__dirname, 'default-config.js'), + infile: path.join('/src', 'CHANGELOG.md'), + sameFile: true, + }, + )).to.equal(true); }); - it('executes `conventional-changelog` command with a preset if it is provided', done => { - changelogGenerator.generateChangelog({ preset: 'angular' }, () => { + it('executes `conventional-changelog` command with a preset if it is provided', async() => { + try { + await promisify(changelogGenerator.generateChangelog.bind(changelogGenerator))({ preset: 'angular' }); - expect(executeCommandSpy.secondCall.calledWith( + // The generator will throw an error since '/src' doesn't exist, but we don't care, + // just need to make sure that executeCommandSpy was called properly + } catch (err) {} + + expect(executeCommandSpy.secondCall.calledWith( 'conventional-changelog', [], { @@ -56,16 +63,18 @@ describe('ChangelogGenerator', () => { preset: 'angular', sameFile: true, }, - )).to.equal(true); - - done(); - }); + )).to.equal(true); }); - it('executes `conventional-changelog` command from scratch if CHANGELOG does not exist', done => { - var changelogGeneratorWithoutFs = new ChangelogGenerator({}, '/src', commandExecutor); + it('executes `conventional-changelog` command from scratch if CHANGELOG does not exist', async() => { + const changelogGeneratorWithoutFs = new ChangelogGenerator({}, '/src', commandExecutor); + + try { + await promisify(changelogGeneratorWithoutFs.generateChangelog.bind(changelogGeneratorWithoutFs))({}); - changelogGeneratorWithoutFs.generateChangelog({}, () => { + // The generator will throw an error since '/src' doesn't exist, but we don't care, + // just need to make sure that executeCommandSpy was called properly + } catch (err) {} expect(executeCommandSpy.secondCall.calledWith( 'conventional-changelog', @@ -76,9 +85,6 @@ describe('ChangelogGenerator', () => { releaseCount: 0, sameFile: true, }, - )).to.equal(true); - - done(); - }); + )).to.equal(true); }); }); diff --git a/tasks/changelog/command-executor.spec.js b/tasks/changelog/command-executor.spec.js index f0029ea3..017a9159 100644 --- a/tasks/changelog/command-executor.spec.js +++ b/tasks/changelog/command-executor.spec.js @@ -1,6 +1,7 @@ const CommandExecutor = require('./command-executor'); +const { promisify } = require('util'); const Code = require('code'); -const Lab = require('lab'); +const Lab = require('@hapi/lab'); const lab = exports.lab = Lab.script(); const describe = lab.describe; const sinon = require('sinon'); @@ -15,51 +16,52 @@ describe('CommandExecutor', () => { let spawn; let doneCallBack; - it('spawns a new process to run the given command', done => { + it('spawns a new process to run the given command', async () => { childProcess = require('child_process'); spawnSpy = sinon.spy(childProcess, "spawn"); commandExecutor = new CommandExecutor(childProcess); + const executeCommand = promisify(commandExecutor.executeCommand.bind(commandExecutor)); - commandExecutor.executeCommand('jest', ['xyz.js'], { config: 'config.js' }, () => { - expect(spawnSpy.calledWith( - require('npm-which')(__dirname).sync('jest'), - ['--config', 'config.js', 'xyz.js'], - { stdio: 'inherit' }, - )).to.equal(true); + try { + await executeCommand('jest', ['xyz.js'], { config: 'config.js' }); - done(); - }); + // The executor will throw an error since '/xyz.js' doesn't exist, but we don't care, + // just need to make sure that spawnSpy was called properly + } catch (err) {} + + expect(spawnSpy.calledWith( + require('npm-which')(__dirname).sync('jest'), + ['--config', 'config.js', 'xyz.js'], + { stdio: 'inherit' }, + )).to.equal(true); }); - it('returns undefined if the process exits with a successful exit code', done => { + it('resolves successfully if the process exits with a successful exit code', async () => { processMock = { on: function(event, callback) { return callback(0); }, }; - spawn = function() { return processMock; }; - - doneCallBack = sinon.fake(); commandExecutor = new CommandExecutor({ spawn }); - commandExecutor.executeCommand('jest', ['xyz.js'], { config: 'config.js' }, doneCallBack); + const executeCommand = promisify(commandExecutor.executeCommand.bind(commandExecutor)); - expect(doneCallBack.calledWith(undefined)).to.equal(true); - - done(); + await executeCommand('jest', ['xyz.js'], { config: 'config.js' }); }); - it('returns error if the process exits with an unsuccessful exit code', done => { + it('throws an error if the process exits with an unsuccessful exit code', async () => { processMock = { on: function(event, callback) { return callback(1); }, }; - spawn = function() { return processMock; }; - - doneCallBack = sinon.fake(); commandExecutor = new CommandExecutor({ spawn }); - commandExecutor.executeCommand('jest', ['xyz.js'], { config: 'config.js' }, doneCallBack); + const executeCommand = promisify(commandExecutor.executeCommand.bind(commandExecutor)); - expect(doneCallBack.calledWith(undefined)).to.equal(false); + let error; + try { + await executeCommand('jest', ['xyz.js'], {config: 'config.js'}, doneCallBack); + } catch (err) { + error = err; + } - done(); + expect(error).to.be.an.error(); }); });