diff --git a/.travis.yml b/.travis.yml index 3d7db5c3..97bba51f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,7 @@ +os: + - linux + - osx + language: node_js dist: bionic @@ -18,8 +22,8 @@ branches: - /^[0-9]+\.[0-9]+\.[0-9]+.*/ before_install: - - sudo cp ./ssl/skyux-ca.crt /usr/local/share/ca-certificates/skyux-ca.crt - - sudo update-ca-certificates + - npm i -g @skyux-sdk/cli + - skyux certs install script: "npm run lint && npm run $TEST_COMMAND" diff --git a/CHANGELOG.md b/CHANGELOG.md index 39ff2807..34e79b00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 3.11.0 (2019-10-28) + +- Updated the local server to use the self-signed certificate implementation introduced in `@skyux-sdk/cli@3.2.0`. See the [SSL documentation](https://developer.blackbaud.com/skyux/learn/get-started/prereqs/ssl-certificate). [#168](https://github.com/blackbaud/skyux-sdk-builder/pull/168) + # 3.10.0 (2019-09-30) - Upgraded `help-client` to `2.1.0`. [#161](https://github.com/blackbaud/skyux-sdk-builder/pull/161) Thanks, [@Blackbaud-ColbyWhite](https://github.com/Blackbaud-ColbyWhite)! diff --git a/appveyor.yml b/appveyor.yml index ec76e7e7..f9169ef2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,6 +9,8 @@ environment: install: - choco install googlechrome --ignore-checksums - ps: Install-Product node $env:nodejs_version + - npm i -g @skyux-sdk/cli + - skyux certs install - npm install test_script: diff --git a/cli/e2e.js b/cli/e2e.js index 36241295..7cc3c473 100644 --- a/cli/e2e.js +++ b/cli/e2e.js @@ -183,7 +183,7 @@ function e2e(command, argv, skyPagesConfig, webpack) { return killServers(0); } - server.start() + server.start(argv) .then((port) => { argv.assets = 'https://localhost:' + port; diff --git a/cli/utils/cert-resolver.js b/cli/utils/cert-resolver.js new file mode 100644 index 00000000..2b479fca --- /dev/null +++ b/cli/utils/cert-resolver.js @@ -0,0 +1,33 @@ +/*jslint node: true */ +'use strict'; + +const fs = require('fs-extra'); +const logger = require('@blackbaud/skyux-logger'); + +function error(prop, code) { + logger.error(`Unable to resolve certificate property ${prop} (code ${code}).`); + logger.error('Please install the latest SKY UX CLI and run `skyux certs install`.'); +} + +function read(argv, prop) { + if (!argv[prop]) { + error(prop, 0); + } else if (!fs.pathExistsSync(argv[prop])) { + error(prop, 1); + } else { + return fs.readFileSync(argv[prop]); + } +} + +function readCert(argv) { + return read(argv, 'sslCert'); +} + +function readKey(argv) { + return read(argv, 'sslKey'); +} + +module.exports = { + readCert, + readKey +}; diff --git a/cli/utils/karma-utils.js b/cli/utils/karma-utils.js index f984a2f6..df79c015 100644 --- a/cli/utils/karma-utils.js +++ b/cli/utils/karma-utils.js @@ -83,7 +83,7 @@ function run(command, argv, specsPattern) { }); } - server.start(); + server.start(argv); }); } diff --git a/cli/utils/run-build.js b/cli/utils/run-build.js index ae1ef4d2..49609c1b 100644 --- a/cli/utils/run-build.js +++ b/cli/utils/run-build.js @@ -149,7 +149,7 @@ function cleanupDist() { function buildServe(argv, skyPagesConfig, webpack, isAot) { const base = skyPagesConfigUtil.getAppBase(skyPagesConfig); return server - .start(base) + .start(argv, base) .then(port => { argv.assets = argv.assets || `https://localhost:${port}`; return buildCompiler(argv, skyPagesConfig, webpack, isAot) diff --git a/cli/utils/server.js b/cli/utils/server.js index 92541d9e..4f0292f8 100644 --- a/cli/utils/server.js +++ b/cli/utils/server.js @@ -1,13 +1,13 @@ /*jslint node: true */ 'use strict'; -const fs = require('fs'); const path = require('path'); const portfinder = require('portfinder'); const express = require('express'); const https = require('https'); const cors = require('cors'); const logger = require('@blackbaud/skyux-logger'); +const certResolver = require('./cert-resolver'); const app = express(); @@ -17,7 +17,7 @@ let server; * Starts the httpServer * @name start */ -function start(root, distPath) { +function start(argv, root, distPath) { return new Promise((resolve, reject) => { const dist = path.resolve(process.cwd(), distPath || 'dist'); @@ -33,8 +33,8 @@ function start(root, distPath) { } const options = { - cert: fs.readFileSync(path.resolve(__dirname, '../../ssl/server.crt')), - key: fs.readFileSync(path.resolve(__dirname, '../../ssl/server.key')) + cert: certResolver.readCert(argv), + key: certResolver.readKey(argv) }; server = https.createServer(options, app); diff --git a/config/webpack/serve.webpack.config.js b/config/webpack/serve.webpack.config.js index 5fca2488..7d8dc2f4 100644 --- a/config/webpack/serve.webpack.config.js +++ b/config/webpack/serve.webpack.config.js @@ -1,7 +1,6 @@ /*jslint node: true */ 'use strict'; -const fs = require('fs'); const path = require('path'); const webpackMerge = require('webpack-merge'); const NamedModulesPlugin = require('webpack/lib/NamedModulesPlugin'); @@ -10,6 +9,7 @@ const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlug const skyPagesConfigUtil = require('../sky-pages/sky-pages.config'); const browser = require('../../cli/utils/browser'); +const certResolver = require('../../cli/utils/cert-resolver'); const tsLoaderUtil = require('./ts-loader-rule'); @@ -73,8 +73,8 @@ function getWebpackConfig(argv, skyPagesConfig) { index: skyPagesConfigUtil.getAppBase(skyPagesConfig) }, https: { - key: fs.readFileSync(path.join(__dirname, '../../ssl/server.key')), - cert: fs.readFileSync(path.join(__dirname, '../../ssl/server.crt')) + cert: certResolver.readCert(argv), + key: certResolver.readKey(argv) }, publicPath: skyPagesConfigUtil.getAppBase(skyPagesConfig) }, diff --git a/e2e/shared/common.js b/e2e/shared/common.js index d2f64401..f4a1f9b3 100644 --- a/e2e/shared/common.js +++ b/e2e/shared/common.js @@ -1,7 +1,8 @@ /*jshint node: true*/ -/*global browser, element, by*/ +/*global browser*/ 'use strict'; +const os = require('os'); const fs = require('fs-extra'); const path = require('path'); const rimraf = require('rimraf'); @@ -18,11 +19,15 @@ const skyuxConfigPath = path.resolve(process.cwd(), tmp, 'skyuxconfig.json'); const appExtrasPath = path.resolve(process.cwd(), tmp, 'src/app/app-extras.module.ts'); const cliPath = `../e2e/shared/cli`; +// This is normally provided by the CLI. +const sslCert = path.resolve(`${os.homedir()}/.skyux/certs/skyux-server.crt`); +const sslKey = path.resolve(`${os.homedir()}/.skyux/certs/skyux-server.key`); + let skyuxConfigOriginal; let appExtrasOriginal; let webpackServer; -let _exitCode; -let _port; +let spyExitCode; +let spyPort; /** * Stops the server. @@ -40,7 +45,7 @@ function afterAll() { if (appExtrasOriginal) { resetAppExtras(); } -}; +} /** * Adds event listeners to serve and resolves a promise. @@ -53,7 +58,7 @@ function bindServe() { webpackServer.stdout.on('data', data => { const dataAsString = log(data); if (dataAsString.indexOf('Compiled successfully.') > -1) { - resolve(_port); + resolve(spyPort); } if (dataAsString.indexOf('Failed to compile.') > -1) { reject(dataAsString); @@ -91,7 +96,7 @@ function exec(cmd, args, opts) { * Returns the last exit code. */ function getExitCode() { - return _exitCode; + return spyExitCode; } /** @@ -113,12 +118,12 @@ function prepareBuild(config) { function serve(exitCode) { // Save our exitCode for testing - _exitCode = exitCode; + spyExitCode = exitCode; // Reset skyuxconfig.json resetConfig(); - return server.start('unused-root', tmp) + return server.start({ sslCert, sslKey }, 'unused-root', tmp) .then(port => browser.get(`https://localhost:${port}/dist/`)); } @@ -140,15 +145,15 @@ function prepareServe() { if (webpackServer) { return bindServe(); - } else { - return new Promise((resolve, reject) => { - portfinder.getPortPromise() - .then(writeConfigServe) - .then(bindServe) - .then(resolve) - .catch(err => reject(err)); - }); } + + return new Promise((resolve, reject) => { + portfinder.getPortPromise() + .then(writeConfigServe) + .then(bindServe) + .then(resolve) + .catch(err => reject(err)); + }); } /** @@ -189,7 +194,7 @@ function writeConfig(json) { */ function writeConfigServe(port) { return new Promise(resolve => { - _port = port; + spyPort = port; const skyuxConfigWithPort = merge(true, skyuxConfigOriginal, { app: { port: port @@ -197,7 +202,19 @@ function writeConfigServe(port) { }); writeConfig(skyuxConfigWithPort); - const args = [cliPath, `serve`, `-l`, `none`, `--logFormat`, `none`]; + + const args = [ + cliPath, + `serve`, + `-l`, + `none`, + `--logFormat`, + `none`, + `--sslCert`, + sslCert, + `--sslKey`, + sslKey + ]; webpackServer = childProcessSpawn(`node`, args, cwdOpts); resetConfig(); resolve(); @@ -227,7 +244,7 @@ function writeAppFile(filePath, content) { */ function verifyAppFolder(folderPath) { const resolvedFolderPath = path.join(path.resolve(tmp), 'src', 'app', folderPath); - return new Promise((resolve, reject) => { + return new Promise((resolve) => { if (!fs.existsSync(resolvedFolderPath)) { fs.mkdirSync(resolvedFolderPath); } @@ -273,5 +290,7 @@ module.exports = { writeAppFile: writeAppFile, removeAppFolderItem: removeAppFolderItem, verifyAppFolder: verifyAppFolder, - writeAppExtras: writeAppExtras + writeAppExtras: writeAppExtras, + sslCert, + sslKey }; diff --git a/e2e/skyux-e2e.e2e-spec.js b/e2e/skyux-e2e.e2e-spec.js index 630d0567..59a9799d 100644 --- a/e2e/skyux-e2e.e2e-spec.js +++ b/e2e/skyux-e2e.e2e-spec.js @@ -4,7 +4,18 @@ const common = require('./shared/common'); function validateTestRun(done) { - common.exec(`node`, [common.cliPath, `e2e`, `--logFormat`, `none`], common.cwdOpts) + const args = [ + common.cliPath, + `e2e`, + `--logFormat`, + `none`, + `--sslCert`, + common.sslCert, + `--sslKey`, + common.sslKey + ]; + + common.exec(`node`, args, common.cwdOpts) .then(exit => { expect(exit).toEqual(0); done(); diff --git a/package-lock.json b/package-lock.json index 13d60920..0162d382 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@skyux-sdk/builder", - "version": "3.10.0", + "version": "3.11.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -505,9 +505,9 @@ "dev": true }, "@blackbaud/skyux-lib-help": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@blackbaud/skyux-lib-help/-/skyux-lib-help-3.1.1.tgz", - "integrity": "sha512-LPIa5NRvWlqbU+OVw8+afps9owMSHVJHbql7QB/Xi4nj5i0o+56Og+RvJJOI+WEGPjpEjgLsb7zrDI1DzKMvIQ==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@blackbaud/skyux-lib-help/-/skyux-lib-help-3.1.2.tgz", + "integrity": "sha512-075GV77Dplg3p4JzytaoFJvrLe+DA6UfNq0knr0TL6WKYAaN0p/JRicZDGmPHXDf19oDgnUbbVJ6eLjWlU2mjA==" }, "@blackbaud/skyux-logger": { "version": "1.1.1", @@ -531,6 +531,16 @@ "webpack-sources": "1.3.0" }, "dependencies": { + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, "rxjs": { "version": "6.3.3", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", @@ -780,9 +790,9 @@ } }, "@types/jasmine": { - "version": "3.3.16", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.3.16.tgz", - "integrity": "sha512-Nveep4zKGby8uIvG2AEUyYOwZS8uVeHK9TgbuWYSawUDDdIgfhCKz28QzamTo//Jk7Ztt9PO3f+vzlB6a4GV1Q==" + "version": "3.4.6", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.4.6.tgz", + "integrity": "sha512-hpQHs+lmZ0uuCrGyqypdI1Ho7jRFolOBT6OkNdZPFziLSSEKvWu+VxWU6bGdNEA/hoV4jV8pdDeNx8EWlmfNAw==" }, "@types/minimatch": { "version": "3.0.3", @@ -790,9 +800,9 @@ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, "@types/node": { - "version": "12.6.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.4.tgz", - "integrity": "sha512-ZKrDzI6KhrqtLpccI1YxMh4d+qzNnftNtp6iL9c4mLTNgzguFu7VR7pXH/C/MfzikMeoXjvISL9mlIGNGGDXDg==" + "version": "12.12.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.9.tgz", + "integrity": "sha512-kV3w4KeLsRBW+O2rKhktBwENNJuqAUQHS3kf4ia2wIaF/MN6U7ANgTsx7tGremcA0Pk3Yh0Hl0iKiLPuBdIgmw==" }, "@types/q": { "version": "1.0.7", @@ -3391,13 +3401,24 @@ } }, "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz", + "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==", "requires": { "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", + "memory-fs": "^0.5.0", "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } } }, "ent": { @@ -3898,9 +3919,9 @@ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, "eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", + "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==" }, "events": { "version": "3.0.0", @@ -5691,11 +5712,11 @@ "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=" }, "http-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", + "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", "requires": { - "eventemitter3": "^3.0.0", + "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" } @@ -5746,9 +5767,9 @@ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" }, "https-proxy-agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", - "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.3.tgz", + "integrity": "sha512-Ytgnz23gm2DVftnzqRRz2dOXZbGd2uiajSw/95bPp6v53zPRspQjLm/AfBgqbJ2qfeRXWIOMVLpp86+/5yX39Q==", "requires": { "agent-base": "^4.3.0", "debug": "^3.1.0" @@ -5962,6 +5983,11 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==" + }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -6554,12 +6580,19 @@ } }, "jasmine": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.4.0.tgz", - "integrity": "sha512-sR9b4n+fnBFDEd7VS2el2DeHgKcPiMVn44rtKFumq9q7P/t8WrxsVIZPob4UDdgcDNCwyDqwxCt4k9TDRmjPoQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.5.0.tgz", + "integrity": "sha512-DYypSryORqzsGoMazemIHUfMkXM7I7easFaxAvNM3Mr6Xz3Fy36TupTrAOxZWN8MVKEU5xECv22J4tUQf3uBzQ==", "requires": { - "glob": "^7.1.3", - "jasmine-core": "~3.4.0" + "glob": "^7.1.4", + "jasmine-core": "~3.5.0" + }, + "dependencies": { + "jasmine-core": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.5.0.tgz", + "integrity": "sha512-nCeAiw37MIMA9w9IXso7bRaLl+c/ef3wnxsoSAlYrzS+Ot0zTG6nU8G/cIfGkqpkjX2wNaIW9RFG0TwIFnG6bA==" + } } }, "jasmine-core": { @@ -6699,9 +6732,9 @@ "dev": true }, "karma": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/karma/-/karma-4.2.0.tgz", - "integrity": "sha512-fmCuxN1rwJxTdZfOXK5LjlmS4Ana/OvzNMpkyLL/TLE8hmgSkpVpMYQ7RTVa8TNKRVQDZNl5W1oF5cfKfgIMlA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/karma/-/karma-4.4.1.tgz", + "integrity": "sha512-L5SIaXEYqzrh6b1wqYC42tNsFMx2PWuxky84pK9coK09MvmL7mxii3G3bZBh/0rvD27lqDd0le9jyhzvwif73A==", "requires": { "bluebird": "^3.3.0", "body-parser": "^1.16.1", @@ -6709,7 +6742,6 @@ "chokidar": "^3.0.0", "colors": "^1.1.0", "connect": "^3.6.0", - "core-js": "^3.1.3", "di": "^0.0.1", "dom-serialize": "^2.2.0", "flatted": "^2.0.0", @@ -6717,7 +6749,7 @@ "graceful-fs": "^4.1.2", "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", - "lodash": "^4.17.11", + "lodash": "^4.17.14", "log4js": "^4.0.0", "mime": "^2.3.1", "minimatch": "^3.0.2", @@ -6733,9 +6765,9 @@ }, "dependencies": { "anymatch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.0.tgz", - "integrity": "sha512-Ozz7l4ixzI7Oxj2+cw+p0tVUt27BpaJ+1+q1TCeANWxHpvyn2+Un+YamBdfKu0uh8xLodGhoa1v7595NhKDAuA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -6755,18 +6787,18 @@ } }, "chokidar": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.1.1.tgz", - "integrity": "sha512-df4o16uZmMHzVQwECZRHwfguOt5ixpuQVaZHjYMvYisgKhE+JXwcj/Tcr3+3bu/XeOJQ9ycYmzu7Mv8XrGxJDQ==", - "requires": { - "anymatch": "^3.1.0", - "braces": "^3.0.2", - "fsevents": "^2.0.6", - "glob-parent": "^5.0.0", - "is-binary-path": "^2.1.0", - "is-glob": "^4.0.1", - "normalize-path": "^3.0.0", - "readdirp": "^3.1.1" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" } }, "colors": { @@ -6774,11 +6806,6 @@ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" }, - "core-js": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz", - "integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==" - }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -6788,9 +6815,9 @@ } }, "fsevents": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz", - "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", "optional": true }, "glob-parent": { @@ -6825,9 +6852,9 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "readdirp": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.1.2.tgz", - "integrity": "sha512-8rhl0xs2cxfVsqzreYCvs8EwBfn/DhVdqtoLmw19uI3SC5avYX9teCurlErfpPXGmYtMHReGaP2RsLnFvz/lnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", "requires": { "picomatch": "^2.0.4" } @@ -6848,9 +6875,9 @@ } }, "karma-chrome-launcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.0.0.tgz", - "integrity": "sha512-u/PnVgDOP97AUe/gJeABlC6Wa6aQ83MZsm0JgsJQ5bGQ9XcXON/7b2aRhl59A62Zom+q3PFveBkczc7E1RT7TA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz", + "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==", "requires": { "which": "^1.2.1" } @@ -7098,11 +7125,6 @@ "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" }, - "lodash.tail": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", - "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=" - }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -8619,9 +8641,9 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "picomatch": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", - "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", + "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==" }, "pify": { "version": "2.3.0", @@ -8660,9 +8682,9 @@ } }, "portfinder": { - "version": "1.0.21", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.21.tgz", - "integrity": "sha512-ESabpDCzmBS3ekHbmpAIiESq3udRsCBGiBZLsC+HgBKv2ezb0R4oG+7RnYEVZ/ZCfhel5Tx3UzdNWA0Lox2QCA==", + "version": "1.0.24", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.24.tgz", + "integrity": "sha512-ekRl7zD2qxYndYflwiryJwMioBI7LI7rVXg3EnLK3sjkouT5eOuhS3gS255XxBksa30VG8UPZYZCdgfGOfkSUg==", "requires": { "async": "^1.5.2", "debug": "^2.2.0", @@ -9542,54 +9564,38 @@ } }, "sass-loader": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz", - "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.3.1.tgz", + "integrity": "sha512-tuU7+zm0pTCynKYHpdqaPpe+MMTQ76I9TPZ7i4/5dZsigE350shQWe5EZNl5dBidM49TPET75tNqRbcsUZWeNA==", "requires": { - "clone-deep": "^2.0.1", + "clone-deep": "^4.0.1", "loader-utils": "^1.0.1", - "lodash.tail": "^4.1.1", "neo-async": "^2.5.0", - "pify": "^3.0.0", - "semver": "^5.5.0" + "pify": "^4.0.1", + "semver": "^6.3.0" }, "dependencies": { "clone-deep": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz", - "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "requires": { - "for-own": "^1.0.0", "is-plain-object": "^2.0.4", - "kind-of": "^6.0.0", - "shallow-clone": "^1.0.0" + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" } }, "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, "shallow-clone": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", - "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "requires": { - "is-extendable": "^0.1.1", - "kind-of": "^5.0.0", - "mixin-object": "^2.0.1" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } + "kind-of": "^6.0.2" } } } @@ -10780,9 +10786,9 @@ } }, "sockjs-client": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz", - "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.4.0.tgz", + "integrity": "sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==", "requires": { "debug": "^3.2.5", "eventsource": "^1.0.7", @@ -11210,22 +11216,21 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "style-loader": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", - "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.0.0.tgz", + "integrity": "sha512-B0dOCFwv7/eY31a5PCieNwMgMhVGFe9w+rh7s/Bx8kfFkrth9zfTZquoYvdw8URgiqxObQKcpW51Ugz1HjfdZw==", "requires": { - "loader-utils": "^1.1.0", - "schema-utils": "^1.0.0" + "loader-utils": "^1.2.3", + "schema-utils": "^2.0.1" }, "dependencies": { "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.4.1.tgz", + "integrity": "sha512-RqYLpkPZX5Oc3fw/kHHHyP56fg5Y+XBpIpV8nCg0znIALfq3OH+Ea9Hfeac9BAMwG5IICltiZ0vxFvJQONfA5w==", "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1" } } } @@ -12114,33 +12119,33 @@ } }, "webpack": { - "version": "4.35.3", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.35.3.tgz", - "integrity": "sha512-xggQPwr9ILlXzz61lHzjvgoqGU08v5+Wnut19Uv3GaTtzN4xBTcwnobodrXE142EL1tOiS5WVEButooGzcQzTA==", + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.1.tgz", + "integrity": "sha512-ak7u4tUu/U63sCVxA571IuPZO/Q0pZ9cEXKg+R/woxkDzVovq57uB6L2Hlg/pC8LCU+TWpvtcYwsstivQwMJmw==", "requires": { "@webassemblyjs/ast": "1.8.5", "@webassemblyjs/helper-module-context": "1.8.5", "@webassemblyjs/wasm-edit": "1.8.5", "@webassemblyjs/wasm-parser": "1.8.5", - "acorn": "^6.2.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", + "acorn": "^6.2.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", + "eslint-scope": "^4.0.3", "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", "schema-utils": "^1.0.0", - "tapable": "^1.1.0", - "terser-webpack-plugin": "^1.1.0", - "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.1", + "watchpack": "^1.6.0", + "webpack-sources": "^1.4.1" }, "dependencies": { "schema-utils": { @@ -12152,13 +12157,27 @@ "ajv-errors": "^1.0.0", "ajv-keywords": "^3.1.0" } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } } } }, "webpack-cli": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.6.tgz", - "integrity": "sha512-0vEa83M7kJtxK/jUhlpZ27WHIOndz5mghWL2O53kiDoA9DIxSKnfqB92LoqEn77cT4f3H2cZm1BMEat/6AZz3A==", + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.9.tgz", + "integrity": "sha512-xwnSxWl8nZtBl/AFJCOn9pG7s5CYUYdZxmmukv+fAHLcBIHM36dImfpQg3WfShZXeArkWlf6QRw24Klcsv8a5A==", "requires": { "chalk": "2.4.2", "cross-spawn": "6.0.5", @@ -12193,6 +12212,16 @@ "wrap-ansi": "^5.1.0" } }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -12300,12 +12329,13 @@ } }, "webpack-dev-middleware": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz", - "integrity": "sha512-qvDesR1QZRIAZHOE3iQ4CXLZZSQ1lAUsSpnQmlB1PBfoN/xdRjmge3Dok0W4IdaVLJOGJy3sGI4sZHwjRU0PCA==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", + "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", "requires": { "memory-fs": "^0.4.1", - "mime": "^2.4.2", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", "range-parser": "^1.2.1", "webpack-log": "^2.0.0" }, @@ -12327,40 +12357,42 @@ } }, "webpack-dev-server": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.7.2.tgz", - "integrity": "sha512-mjWtrKJW2T9SsjJ4/dxDC2fkFVUw8jlpemDERqV0ZJIkjjjamR2AbQlr3oz+j4JLhYCHImHnXZK5H06P2wvUew==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.8.2.tgz", + "integrity": "sha512-0xxogS7n5jHDQWy0WST0q6Ykp7UGj4YvWh+HVN71JoE7BwPxMZrwgraBvmdEMbDVMBzF0u+mEzn8TQzBm5NYJQ==", "requires": { "ansi-html": "0.0.7", "bonjour": "^3.5.0", - "chokidar": "^2.1.6", + "chokidar": "^2.1.8", "compression": "^1.7.4", "connect-history-api-fallback": "^1.6.0", "debug": "^4.1.1", "del": "^4.1.1", "express": "^4.17.1", "html-entities": "^1.2.1", - "http-proxy-middleware": "^0.19.1", + "http-proxy-middleware": "0.19.1", "import-local": "^2.0.0", "internal-ip": "^4.3.0", "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", "killable": "^1.0.1", - "loglevel": "^1.6.3", + "loglevel": "^1.6.4", "opn": "^5.5.0", "p-retry": "^3.0.1", - "portfinder": "^1.0.20", + "portfinder": "^1.0.24", "schema-utils": "^1.0.0", - "selfsigned": "^1.10.4", - "semver": "^6.1.1", + "selfsigned": "^1.10.7", + "semver": "^6.3.0", "serve-index": "^1.9.1", "sockjs": "0.3.19", - "sockjs-client": "1.3.0", - "spdy": "^4.0.0", + "sockjs-client": "1.4.0", + "spdy": "^4.0.1", "strip-ansi": "^3.0.1", "supports-color": "^6.1.0", "url": "^0.11.0", - "webpack-dev-middleware": "^3.7.0", + "webpack-dev-middleware": "^3.7.2", "webpack-log": "^2.0.0", + "ws": "^6.2.1", "yargs": "12.0.5" }, "dependencies": { @@ -12369,6 +12401,11 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -12534,6 +12571,31 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, + "portfinder": { + "version": "1.0.24", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.24.tgz", + "integrity": "sha512-ekRl7zD2qxYndYflwiryJwMioBI7LI7rVXg3EnLK3sjkouT5eOuhS3gS255XxBksa30VG8UPZYZCdgfGOfkSUg==", + "requires": { + "async": "^1.5.2", + "debug": "^2.2.0", + "mkdirp": "0.5.x" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -12595,6 +12657,14 @@ } } }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "requires": { + "async-limiter": "~1.0.0" + } + }, "yargs": { "version": "12.0.5", "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", @@ -12637,11 +12707,11 @@ } }, "webpack-merge": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", - "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", "requires": { - "lodash": "^4.17.5" + "lodash": "^4.17.15" } }, "webpack-sources": { diff --git a/package.json b/package.json index f74bc0f1..5e12098d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@skyux-sdk/builder", - "version": "3.10.0", + "version": "3.11.0", "description": "Builds the output of a SKY UX application.", "main": "index.js", "scripts": { @@ -54,18 +54,18 @@ "ts-node": "^8.0.1", "tslint": "^5.12.1", "typescript": "^3.2.4", - "zone.js": "^0.8.28" + "zone.js": "~0.8.28" }, "dependencies": { "@angular-devkit/build-optimizer": "0.13.9", "@blackbaud/help-client": "2.1.0", - "@blackbaud/skyux-lib-help": "3.1.1", + "@blackbaud/skyux-lib-help": "3.1.2", "@blackbaud/skyux-logger": "1.1.1", "@ngtools/webpack": "7.3.9", "@pact-foundation/karma-pact": "2.2.0", "@pact-foundation/pact-node": "9.0.0", - "@types/jasmine": "3.3.16", - "@types/node": "12.6.4", + "@types/jasmine": "3.4.6", + "@types/node": "12.12.9", "ajv": "6.10.2", "angular2-template-loader": "0.6.2", "async": "2.6.3", @@ -73,21 +73,21 @@ "chromedriver-version-matcher": "^1.0.0-alpha.2", "cors": "2.8.5", "cross-spawn": "6.0.5", - "enhanced-resolve": "4.1.0", + "enhanced-resolve": "4.1.1", "express": "4.17.1", "fs-extra": "7.0.1", "glob": "7.1.4", "hash-file": "3.0.0", "html-webpack-plugin": "3.2.0", - "http-proxy": "1.17.0", + "http-proxy": "1.18.0", "istanbul": "0.4.5", "istanbul-api": "2.1.7", "istanbul-instrumenter-loader": "3.0.1", "istanbul-reports": "2.2.6", - "jasmine": "3.4.0", + "jasmine": "3.5.0", "jasmine-spec-reporter": "4.2.1", - "karma": "4.2.0", - "karma-chrome-launcher": "3.0.0", + "karma": "4.4.1", + "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "2.1.0", "karma-jasmine": "2.0.1", "karma-mocha-reporter": "2.2.5", @@ -100,26 +100,26 @@ "node-sass": "4.12.0", "node-sass-tilde-importer": "1.0.2", "open": "6.4.0", - "portfinder": "1.0.21", + "portfinder": "1.0.24", "protractor": "5.4.2", "raw-loader": "1.0.0", "reflect-metadata": "0.1.13", "rimraf": "2.6.3", - "sass-loader": "7.1.0", + "sass-loader": "7.3.1", "selenium-standalone": "6.16.0", "simple-progress-webpack-plugin": "1.1.2", "source-map-inline-loader": "1.0.0", "source-map-loader": "0.2.4", - "style-loader": "0.23.1", + "style-loader": "1.0.0", "tsickle": "0.34.2", "tslint-jasmine-rules": "1.6.0", "url": "0.11.0", "util": "0.12.1", - "webpack": "4.35.3", - "webpack-cli": "3.3.6", - "webpack-dev-middleware": "3.7.0", - "webpack-dev-server": "3.7.2", - "webpack-merge": "4.2.1" + "webpack": "4.41.1", + "webpack-cli": "3.3.9", + "webpack-dev-middleware": "3.7.2", + "webpack-dev-server": "3.8.2", + "webpack-merge": "4.2.2" }, "devDependencies": { "@angular/animations": "7.2.15", diff --git a/test/cli-utils-cert-resolver.spec.js b/test/cli-utils-cert-resolver.spec.js new file mode 100644 index 00000000..67be7c90 --- /dev/null +++ b/test/cli-utils-cert-resolver.spec.js @@ -0,0 +1,79 @@ +/*jshint jasmine: true, node: true */ +'use strict'; + +const mock = require('mock-require'); +const logger = require('@blackbaud/skyux-logger'); + +describe('utils/cert-resolver.js', () => { + + beforeEach(() => { + spyOn(logger, 'error'); + spyOn(logger, 'info'); + }); + + function spyOnFS() { + const spyFS = jasmine.createSpyObj('fs', ['pathExistsSync', 'readFileSync']); + mock('fs-extra', spyFS); + return spyFS; + } + + function getLib() { + return mock.reRequire('../cli/utils/cert-resolver'); + } + + it('should expose getCert and getKey methods', () => { + const lib = getLib(); + expect(lib.readCert).toBeDefined(); + expect(lib.readKey).toBeDefined(); + }); + + it('should handle sslCert and sslKey not passed in', () => { + const lib = getLib(); + lib.readCert({}); + lib.readKey({}); + + expect(logger.error).toHaveBeenCalledWith( + `Unable to resolve certificate property sslCert (code 0).` + ); + expect(logger.error).toHaveBeenCalledWith( + `Unable to resolve certificate property sslKey (code 0).` + ); + expect(logger.error).toHaveBeenCalledWith( + 'Please install the latest SKY UX CLI and run `skyux certs install`.' + ); + }); + + it('should handle sslCert and sslKey not existing', () => { + const spyFS = spyOnFS(); + const lib = getLib(); + + spyFS.pathExistsSync.and.returnValue(false); + + lib.readCert({ sslCert: 'asdf' }); + lib.readKey({ sslKey: 'asdf' }); + + expect(logger.error).toHaveBeenCalledWith( + `Unable to resolve certificate property sslCert (code 1).` + ); + expect(logger.error).toHaveBeenCalledWith( + `Unable to resolve certificate property sslKey (code 1).` + ); + expect(logger.error).toHaveBeenCalledWith( + 'Please install the latest SKY UX CLI and run `skyux certs install`.' + ); + }); + + it('should return contents of sslCert and sslKey', () => { + const spyFS = spyOnFS(); + const lib = getLib(); + + spyFS.pathExistsSync.and.returnValue(true); + spyFS.readFileSync.and.callFake(p => `${p}-content`); + + const cert = lib.readCert({ sslCert: 'custom-cert' }); + const key = lib.readKey({ sslKey: 'custom-key' }); + + expect(cert).toBe('custom-cert-content'); + expect(key).toBe('custom-key-content'); + }); +}); diff --git a/test/cli-utils-server.spec.js b/test/cli-utils-server.spec.js index 41391256..26ba75a9 100644 --- a/test/cli-utils-server.spec.js +++ b/test/cli-utils-server.spec.js @@ -12,6 +12,7 @@ describe('server utils', () => { let customServerError; let customPortError; let customPortNumber; + let spyCertResolver; beforeEach(() => { spyOn(logger, 'info'); @@ -50,6 +51,9 @@ describe('server utils', () => { } }); + spyCertResolver = jasmine.createSpyObj('certResolver', ['readCert', 'readKey']); + mock('../cli/utils/cert-resolver', spyCertResolver); + return mock.reRequire('../cli/utils/server'); } @@ -62,7 +66,7 @@ describe('server utils', () => { it('should accept a root', () => { const server = bind(); const root = 'custom-root'; - server.start(root).then(() =>{ + server.start({}, root).then(() =>{ }); }); @@ -73,7 +77,7 @@ describe('server utils', () => { server.stop(); expect(closeCalled).toBe(false); - server.start().then(() => { + server.start({}).then(() => { logger.info.calls.reset(); server.stop(); expect(closeCalled).toBe(true); @@ -87,7 +91,7 @@ describe('server utils', () => { customServerError = 'custom-error'; const server = bind(); - server.start().catch(err => { + server.start({}).catch(err => { expect(err).toBe(customServerError); done(); }); @@ -97,7 +101,7 @@ describe('server utils', () => { customPortNumber = 1234; const server = bind(); - server.start().then(port => { + server.start({}).then(port => { expect(port).toBe(customPortNumber); done(); }); @@ -108,7 +112,7 @@ describe('server utils', () => { customPortError = 'custom-portfinder-error'; const server = bind(); - server.start().catch(err => { + server.start({}).catch(err => { expect(err).toBe(customPortError); done(); }); @@ -120,10 +124,21 @@ describe('server utils', () => { const customDistPath = 'custom-dist'; const server = bind(); - server.start('custom-root', customDistPath) + server.start({}, 'custom-root', customDistPath) .then(() => { expect(path.resolve).toHaveBeenCalledWith(process.cwd(), customDistPath); done(); }); }); + + it('should pass argv to cert-resolver and call the readCert and readKey methods', (done) => { + const argv = { custom: true }; + const server = bind(); + + server.start(argv).then(() => { + expect(spyCertResolver.readCert).toHaveBeenCalledWith(argv); + expect(spyCertResolver.readKey).toHaveBeenCalledWith(argv); + done(); + }); + }); }); diff --git a/test/config-webpack-serve.spec.js b/test/config-webpack-serve.spec.js index 96adb328..478db1ae 100644 --- a/test/config-webpack-serve.spec.js +++ b/test/config-webpack-serve.spec.js @@ -6,6 +6,13 @@ const runtimeUtils = require('../utils/runtime-test-utils'); describe('config webpack serve', () => { + let spyCertResolver; + + beforeEach(() => { + spyCertResolver = jasmine.createSpyObj('certResolver', ['readCert', 'readKey']); + mock('../cli/utils/cert-resolver', spyCertResolver); + }); + it('should expose a getWebpackConfig method', () => { const lib = require('../config/webpack/serve.webpack.config'); expect(typeof lib.getWebpackConfig).toEqual('function'); @@ -55,4 +62,13 @@ describe('config webpack serve', () => { }); + it('should pass argv to cert-resolver and call the readCert and readKey methods', () => { + const lib = mock.reRequire('../config/webpack/serve.webpack.config'); + const argv = { custom: true }; + + lib.getWebpackConfig(argv, runtimeUtils.getDefault()); + expect(spyCertResolver.readCert).toHaveBeenCalledWith(argv); + expect(spyCertResolver.readKey).toHaveBeenCalledWith(argv); + }); + });