diff --git a/.eslintignore b/.eslintignore index a6467301..714d8401 100644 --- a/.eslintignore +++ b/.eslintignore @@ -9,6 +9,7 @@ sauce_connect.log* yarn-error.log node_modules /handlebars-release.tgz +.nyc_output # Generated files lib/handlebars/compiler/parser.js diff --git a/.eslintrc.js b/.eslintrc.js index 0abcd580..2ac72935 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -17,7 +17,6 @@ module.exports = { // Best Practices // //----------------// 'default-case': 'warn', - 'dot-notation': ['error', { allowKeywords: false }], 'guard-for-in': 'warn', 'no-alert': 'error', 'no-caller': 'error', diff --git a/.gitignore b/.gitignore index 8922abaf..59019b37 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ sauce_connect.log* /yarn.lock node_modules /handlebars-release.tgz +.nyc_output # Generated files lib/handlebars/compiler/parser.js diff --git a/.istanbul.yml b/.istanbul.yml deleted file mode 100644 index 960643ef..00000000 --- a/.istanbul.yml +++ /dev/null @@ -1,2 +0,0 @@ -instrumentation: - excludes: ['**/spec/**', '**/handlebars/compiler/parser.js'] diff --git a/.prettierignore b/.prettierignore index b6bc4621..72462066 100644 --- a/.prettierignore +++ b/.prettierignore @@ -9,6 +9,7 @@ sauce_connect.log* yarn-error.log node_modules /handlebars-release.tgz +.nyc_output # Generated files lib/handlebars/compiler/parser.js diff --git a/Gruntfile.js b/Gruntfile.js index 298551b1..2a0fea65 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -211,6 +211,8 @@ module.exports = function(grunt) { 'copy:components' ]); + this.registerTask('test', ['test:bin', 'test:cov']); + grunt.registerTask('bench', ['metrics']); if (process.env.SAUCE_USERNAME) { @@ -225,7 +227,7 @@ module.exports = function(grunt) { 'bgShell:integrationTests', 'sauce', 'metrics', - 'publish:latest' + 'publish-to-aws' ]); grunt.registerTask('on-file-change', ['build', 'concat:tests', 'test']); diff --git a/nyc.config.js b/nyc.config.js new file mode 100644 index 00000000..f516eb2b --- /dev/null +++ b/nyc.config.js @@ -0,0 +1,9 @@ +module.exports = { + 'check-coverage': true, + branches: 100, + lines: 100, + functions: 100, + statements: 100, + exclude: ['**/spec/**', '**/handlebars/compiler/parser.js'], + reporter: 'html' +}; diff --git a/package-lock.json b/package-lock.json index d1638f30..c6c7bb05 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,67 @@ "@babel/highlight": "^7.0.0" } }, + "@babel/generator": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", + "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", + "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.7.4", + "@babel/template": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", + "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", + "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "dev": true, + "requires": { + "@babel/types": "^7.7.4" + } + }, "@babel/highlight": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", @@ -61,6 +122,12 @@ } } }, + "@babel/parser": { + "version": "7.7.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.5.tgz", + "integrity": "sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig==", + "dev": true + }, "@babel/runtime": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz", @@ -70,6 +137,88 @@ "regenerator-runtime": "^0.13.2" } }, + "@babel/template": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", + "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4" + } + }, + "@babel/traverse": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", + "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.7.4", + "@babel/helper-function-name": "^7.7.4", + "@babel/helper-split-export-declaration": "^7.7.4", + "@babel/parser": "^7.7.4", + "@babel/types": "^7.7.4", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "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 + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", + "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, "@knappi/grunt-saucelabs": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/@knappi/grunt-saucelabs/-/grunt-saucelabs-9.0.2.tgz", @@ -398,6 +547,21 @@ "normalize-path": "^2.0.0" } }, + "append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true, + "requires": { + "default-require-extensions": "^2.0.0" + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -681,6 +845,15 @@ "try-resolve": "^1.0.0" }, "dependencies": { + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "^1.0.0" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -1125,6 +1298,18 @@ } } }, + "caching-transform": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", + "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "dev": true, + "requires": { + "hasha": "^3.0.0", + "make-dir": "^2.0.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.4.2" + } + }, "caller-callsite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", @@ -1475,6 +1660,12 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, "commoner": { "version": "0.10.8", "resolved": "https://registry.npmjs.org/commoner/-/commoner-0.10.8.tgz", @@ -1897,6 +2088,27 @@ } } }, + "cp-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", + "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "make-dir": "^2.0.0", + "nested-error-stacks": "^2.0.0", + "pify": "^4.0.1", + "safe-buffer": "^5.0.1" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -2003,6 +2215,23 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "dev": true, + "requires": { + "strip-bom": "^3.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -2392,13 +2621,24 @@ "request": "^2.88.0", "strip-json-comments": "^2.0.1", "tslint": "^5.14.0", - "typescript": "^3.8.0-dev.20191203" + "typescript": "^3.8.0-dev.20191214" }, "dependencies": { + "fs-extra": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", + "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "typescript": { - "version": "3.8.0-dev.20191203", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.0-dev.20191203.tgz", - "integrity": "sha512-ZPMH02RdXSYkYr5JsxksisQsRlJ22w5yXn97vzIgp3ehFnMo/3O1fReQV99iEN4keTLD9IiGGxO0h2u6aKfJUQ==", + "version": "3.8.0-dev.20191214", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.0-dev.20191214.tgz", + "integrity": "sha512-JOZy5zal8B7INcewbvXY5hxf7lCflgWs8twStnVmRoHY70OC6ar7A+MpozX9jsxaycSSErBZ5YCPOjIt9/SDFA==", "dev": true } } @@ -2531,6 +2771,12 @@ "is-arrayish": "^0.2.1" } }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, "es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", @@ -2559,64 +2805,39 @@ "dev": true }, "escodegen": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.7.1.tgz", - "integrity": "sha1-MOz89mypjcZ80v0WKr626vqM5vw=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.3.3.tgz", + "integrity": "sha1-8CQBb1qI4Eb9EgBQVek5gC5sXyM=", "dev": true, "requires": { - "esprima": "^1.2.2", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.5.0", - "source-map": "~0.2.0" + "esprima": "~1.1.1", + "estraverse": "~1.5.0", + "esutils": "~1.0.0", + "source-map": "~0.1.33" }, "dependencies": { "esprima": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz", - "integrity": "sha1-CZNQL+r2aBODJXVvMPmlH+7sEek=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz", + "integrity": "sha1-W28VR/TRAuZw4UDFCb5ncdautUk=", "dev": true }, "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", + "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=", "dev": true }, - "fast-levenshtein": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.0.7.tgz", - "integrity": "sha1-AXjc3uAjuSkFGTrwlZ6KdjnP3Lk=", + "esutils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", + "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=", "dev": true }, - "levn": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.2.5.tgz", - "integrity": "sha1-uo0znQykphDjo/FFucr0iAcVUFQ=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.0", - "type-check": "~0.3.1" - } - }, - "optionator": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.5.0.tgz", - "integrity": "sha1-t1qJlaLUF98ltuTjhi9QqohlE2g=", - "dev": true, - "requires": { - "deep-is": "~0.1.2", - "fast-levenshtein": "~1.0.0", - "levn": "~0.2.5", - "prelude-ls": "~1.1.1", - "type-check": "~0.3.1", - "wordwrap": "~0.0.2" - } - }, "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, "optional": true, "requires": { @@ -3346,16 +3567,6 @@ "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", "dev": true }, - "fileset": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fileset/-/fileset-0.2.1.tgz", - "integrity": "sha1-WI74lzxmI7KnbfRlEFaWuWqsgGc=", - "dev": true, - "requires": { - "glob": "5.x", - "minimatch": "2.x" - } - }, "fill-range": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", @@ -3384,6 +3595,37 @@ "unpipe": "~1.0.0" } }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", @@ -3491,6 +3733,28 @@ "for-in": "^1.0.1" } }, + "foreground-child": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", + "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "dev": true, + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + } + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -3530,14 +3794,22 @@ "dev": true }, "fs-extra": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz", - "integrity": "sha1-irwSj3lG4xATXdyTuYvdtBDno0s=", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", + "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + } } }, "fs-readdir-recursive": { @@ -4376,9 +4648,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, "minimatch": { @@ -4405,9 +4677,9 @@ "dev": true }, "grunt": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.3.tgz", - "integrity": "sha512-/JzmZNPfKorlCrrmxWqQO4JVodO+DVd5XX4DkocL/1WlLlKVLE9+SdEIempOAxDhWPysLle6afvn/hg7Ck2k9g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.4.tgz", + "integrity": "sha512-PYsMOrOC+MsdGEkFVwMaMyc6Ob7pKmq+deg1Sjr+vvMWp35sztfwKE7qoN51V+UEtHsyNuMcGdgMLFkBHvMxHQ==", "dev": true, "requires": { "coffeescript": "~1.10.0", @@ -4421,7 +4693,7 @@ "grunt-legacy-log": "~2.0.0", "grunt-legacy-util": "~1.1.1", "iconv-lite": "~0.4.13", - "js-yaml": "~3.5.2", + "js-yaml": "~3.13.0", "minimatch": "~3.0.2", "mkdirp": "~0.5.1", "nopt": "~3.0.6", @@ -4461,15 +4733,6 @@ "resolve": "~1.1.0" } }, - "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" - } - }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", @@ -4602,9 +4865,9 @@ "dev": true }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, "source-map": { @@ -4667,9 +4930,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true } } @@ -4693,9 +4956,9 @@ }, "dependencies": { "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true } } @@ -4731,9 +4994,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, "supports-color": { @@ -4763,9 +5026,9 @@ }, "dependencies": { "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true } } @@ -4780,9 +5043,9 @@ }, "dependencies": { "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true } } @@ -4797,18 +5060,6 @@ "concat-stream": "^1.4.1" } }, - "handlebars": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", - "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==", - "dev": true, - "requires": { - "neo-async": "^2.6.0", - "optimist": "^0.6.1", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4" - } - }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -4926,6 +5177,15 @@ } } }, + "hasha": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", + "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", + "dev": true, + "requires": { + "is-stream": "^1.0.1" + } + }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", @@ -5028,9 +5288,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true } } @@ -5059,9 +5319,9 @@ "dev": true }, "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.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, "requires": { "agent-base": "^4.3.0", @@ -5737,100 +5997,119 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, - "istanbul": { - "version": "github:kpdecker/istanbul#dd1228d2f0a6e8506cbb5dba398a8297b1dbaf22", - "from": "github:kpdecker/istanbul", + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", + "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", "dev": true, "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "convert-source-map": "^1.1.1", - "escodegen": "1.7.x", - "esprima": "2.5.x", - "fileset": "0.2.x", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "source-map": "^0.4.4", - "source-map-support": "^0.3.2", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" + "append-transform": "^1.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" }, "dependencies": { - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true - }, - "esprima": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.5.0.tgz", - "integrity": "sha1-84ekb9NEwbGjm6+MIL+0O20AWMw=", - "dev": true - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "source-map-support": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.3.3.tgz", - "integrity": "sha1-NJAJd9W6PwfHdX7nLnO7GptTdU8=", - "dev": true, - "requires": { - "source-map": "0.1.32" - }, - "dependencies": { - "source-map": { - "version": "0.1.32", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz", - "integrity": "sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" } }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true } } }, + "istanbul-reports": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", + "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "dev": true, + "requires": { + "handlebars": "^4.1.2" + }, + "dependencies": { + "handlebars": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", + "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + } + } + } + }, "jison": { "version": "0.4.16", "resolved": "https://registry.npmjs.org/jison/-/jison-0.4.16.tgz", @@ -5847,45 +6126,11 @@ "nomnom": "1.5.2" }, "dependencies": { - "escodegen": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.3.3.tgz", - "integrity": "sha1-8CQBb1qI4Eb9EgBQVek5gC5sXyM=", - "dev": true, - "requires": { - "esprima": "~1.1.1", - "estraverse": "~1.5.0", - "esutils": "~1.0.0", - "source-map": "~0.1.33" - } - }, "esprima": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.1.1.tgz", "integrity": "sha1-W28VR/TRAuZw4UDFCb5ncdautUk=", "dev": true - }, - "estraverse": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", - "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=", - "dev": true - }, - "esutils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", - "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=", - "dev": true - }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } } } }, @@ -5912,19 +6157,19 @@ "dev": true }, "js-yaml": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz", - "integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74=", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { - "argparse": "^1.0.2", - "esprima": "^2.6.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, "dependencies": { "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true } } @@ -6801,6 +7046,12 @@ "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", "dev": true }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -6907,6 +7158,34 @@ "signal-exit": "^3.0.0" } }, + "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" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } + } + }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -7054,6 +7333,15 @@ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", "dev": true }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + } + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -7121,12 +7409,12 @@ "dev": true }, "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "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.0.0" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -7136,9 +7424,9 @@ "dev": true }, "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { "for-in": "^1.0.2", @@ -7341,6 +7629,12 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==" }, + "nested-error-stacks": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", + "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", + "dev": true + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -7511,6 +7805,204 @@ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, + "nyc": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", + "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", + "dev": true, + "requires": { + "archy": "^1.0.0", + "caching-transform": "^3.0.2", + "convert-source-map": "^1.6.0", + "cp-file": "^6.2.0", + "find-cache-dir": "^2.1.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-hook": "^2.0.7", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.4", + "js-yaml": "^3.13.1", + "make-dir": "^2.1.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.2.3", + "uuid": "^3.3.2", + "yargs": "^13.2.2", + "yargs-parser": "^13.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "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" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "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" + } + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "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" + } + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -7841,6 +8333,18 @@ "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=", "dev": true }, + "package-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", + "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^3.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } + }, "pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", @@ -8156,6 +8660,12 @@ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, "psl": { "version": "1.1.31", "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", @@ -8712,6 +9222,15 @@ "jsesc": "~0.5.0" } }, + "release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "requires": { + "es6-error": "^4.0.1" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -9060,9 +9579,9 @@ "dev": true }, "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -9407,6 +9926,20 @@ "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", "dev": true }, + "spawn-wrap": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", + "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", + "dev": true, + "requires": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } + }, "spdx-correct": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", @@ -9733,6 +10266,122 @@ "integrity": "sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=", "dev": true }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "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" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "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" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -10117,44 +10766,21 @@ } }, "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } + "set-value": "^2.0.1" } }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true }, "unpipe": { @@ -10651,6 +11277,17 @@ "mkdirp": "^0.5.1" } }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, "xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", @@ -10678,6 +11315,12 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, "yargs": { "version": "3.32.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", diff --git a/package.json b/package.json index 199f8c1b..162fe70a 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,8 @@ "eslint-config-prettier": "^6.7.0", "eslint-plugin-compat": "^3.3.0", "eslint-plugin-es5": "^1.4.1", - "grunt": "^1.0.3", + "fs-extra": "^8.1.0", + "grunt": "^1.0.4", "grunt-babel": "^5.0.0", "grunt-bg-shell": "^2.3.3", "grunt-cli": "^1", @@ -57,12 +58,12 @@ "grunt-contrib-watch": "^1.1.0", "grunt-webpack": "^1.0.8", "husky": "^3.1.0", - "istanbul": "kpdecker/istanbul", "jison": "0.4.16", "lint-staged": "^9.5.0", "mocha": "^5", "mock-stdin": "^0.3.0", "mustache": "^2.1.3", + "nyc": "^14.1.1", "prettier": "^1.19.1", "semver": "^5.0.1", "sinon": "^7.5.0", @@ -86,7 +87,7 @@ "lint": "eslint --max-warnings 0 . ", "dtslint": "dtslint types", "test": "grunt", - "extensive-tests-and-publish-to-aws": "grunt --stack extensive-tests-and-publish-to-aws", + "extensive-tests-and-publish-to-aws": "npx mocha tasks/task-tests/ && grunt --stack extensive-tests-and-publish-to-aws", "integration-test": "grunt integration-tests", "--- combined tasks ---": "", "check-before-pull-request": "concurrently --kill-others-on-fail npm:lint npm:dtslint npm:check-format npm:test" diff --git a/spec/builtins.js b/spec/builtins.js index d6bc2986..c74092e1 100644 --- a/spec/builtins.js +++ b/spec/builtins.js @@ -710,6 +710,23 @@ describe('builtin helpers', function() { shouldCompileTo(string, hash, ''); equals(true, called); }); + + it('should pass zero log arguments', function() { + var string = '{{log}}'; + var hash = { blah: 'whee' }; + var called; + + console.info = console.log = function() { + expect(arguments.length).to.equal(0); + called = true; + console.log = $log; + }; + + expectTemplate(string) + .withInput(hash) + .toCompileTo(''); + expect(called).to.be.true(); + }); /* eslint-enable no-console */ }); diff --git a/tasks/.eslintrc b/tasks/.eslintrc deleted file mode 100644 index 34615029..00000000 --- a/tasks/.eslintrc +++ /dev/null @@ -1,16 +0,0 @@ -{ - "globals": { - "require": true - }, - "rules": { - // Disabling for tests, for now. - "no-path-concat": 0, - - "no-var": 0, - "no-shadow": 0, - "handle-callback-err": 0, - "no-console": 0, - "no-process-env": 0, - "dot-notation": [2, {"allowKeywords": true}] - } -} \ No newline at end of file diff --git a/tasks/.eslintrc.js b/tasks/.eslintrc.js new file mode 100644 index 00000000..642a9ab0 --- /dev/null +++ b/tasks/.eslintrc.js @@ -0,0 +1,14 @@ +module.exports = { + extends: ['../.eslintrc.js'], + parserOptions: { + sourceType: 'module', + ecmaVersion: 2017, + ecmaFeatures: {} + }, + rules: { + 'no-process-env': 'off', + 'prefer-const': 'warn', + 'compat/compat': 'off', + 'dot-notation': ['error', { allowKeywords: true }] + } +}; diff --git a/tasks/metrics.js b/tasks/metrics.js index f903ceb7..acc3cece 100644 --- a/tasks/metrics.js +++ b/tasks/metrics.js @@ -1,26 +1,29 @@ -var _ = require('underscore'), - async = require('neo-async'), - metrics = require('../bench'); +const metrics = require('../bench'); +const { createRegisterAsyncTaskFn } = require('./util/async-grunt-task'); module.exports = function(grunt) { - grunt.registerTask('metrics', function() { - var done = this.async(), - execName = grunt.option('name'), - events = {}; + const registerAsyncTask = createRegisterAsyncTaskFn(grunt); - async.each( - _.keys(metrics), - function(name, complete) { - if (/^_/.test(name) || (execName && name !== execName)) { - return complete(); - } + registerAsyncTask('metrics', function() { + const onlyExecuteName = grunt.option('name'); + const events = {}; + const promises = Object.keys(metrics).map(async name => { + if (/^_/.test(name)) { + return; + } + if (onlyExecuteName != null && name !== onlyExecuteName) { + return; + } + + return new Promise(resolve => { metrics[name](grunt, function(data) { events[name] = data; - complete(); + resolve(); }); - }, - done - ); + }); + }); + + return Promise.all(promises); }); }; diff --git a/tasks/parser.js b/tasks/parser.js index 0adba111..252b8c26 100644 --- a/tasks/parser.js +++ b/tasks/parser.js @@ -1,39 +1,33 @@ -var childProcess = require('child_process'); +const { execFileWithInheritedOutput } = require('./util/exec-file'); +const { createRegisterAsyncTaskFn } = require('./util/async-grunt-task'); + +const OUTPUT_FILE = 'lib/handlebars/compiler/parser.js'; module.exports = function(grunt) { - grunt.registerTask('parser', 'Generate jison parser.', function() { - var done = this.async(); + const registerAsyncTask = createRegisterAsyncTaskFn(grunt); - var cmd = './node_modules/.bin/jison'; - - if (process.platform === 'win32') { - cmd = 'node_modules\\.bin\\jison.cmd'; - } - - var child = childProcess.spawn( - cmd, - ['-m', 'js', 'src/handlebars.yy', 'src/handlebars.l'], - { stdio: 'inherit' } - ); - child.on('exit', function(code) { - if (code != 0) { - grunt.fatal('Jison failure: ' + code); - done(); - return; - } - - var src = [ - 'src/parser-prefix.js', - 'handlebars.js', - 'src/parser-suffix.js' - ] - .map(grunt.file.read) - .join(''); - grunt.file.delete('handlebars.js'); - - grunt.file.write('lib/handlebars/compiler/parser.js', src); - grunt.log.writeln('Parser "lib/handlebars/compiler/parser.js" created.'); - done(); - }); + registerAsyncTask('parser', async () => { + await runJison(); + combineWithPrefixAndSuffix(); + grunt.log.writeln(`Parser "${OUTPUT_FILE}" created.`); }); + + async function runJison() { + await execFileWithInheritedOutput('jison', [ + '-m', + 'js', + 'src/handlebars.yy', + 'src/handlebars.l' + ]); + } + + function combineWithPrefixAndSuffix() { + const combinedParserSourceCode = + grunt.file.read('src/parser-prefix.js') + + grunt.file.read('handlebars.js') + + grunt.file.read('src/parser-suffix.js'); + + grunt.file.write(OUTPUT_FILE, combinedParserSourceCode); + grunt.file.delete('handlebars.js'); + } }; diff --git a/tasks/publish-to-aws.js b/tasks/publish-to-aws.js new file mode 100644 index 00000000..b551e1c9 --- /dev/null +++ b/tasks/publish-to-aws.js @@ -0,0 +1,102 @@ +const AWS = require('aws-sdk'); +const git = require('./util/git'); +const { createRegisterAsyncTaskFn } = require('./util/async-grunt-task'); +const semver = require('semver'); + +module.exports = function(grunt) { + const registerAsyncTask = createRegisterAsyncTaskFn(grunt); + + registerAsyncTask('publish-to-aws', async () => { + grunt.log.writeln('remotes: ' + (await git.remotes())); + grunt.log.writeln('branches: ' + (await git.branches())); + + const commitInfo = await git.commitInfo(); + grunt.log.writeln('tag: ', commitInfo.tagName); + + const suffixes = []; + + // Publish the master as "latest" and with the commit-id + if (commitInfo.isMaster) { + suffixes.push('-latest'); + suffixes.push('-' + commitInfo.headSha); + } + + // Publish tags by their tag-name + if (commitInfo.tagName != null && semver.valid(commitInfo.tagName)) { + suffixes.push('-' + commitInfo.tagName); + } + + if (suffixes.length > 0) { + initSDK(); + grunt.log.writeln( + 'publishing file-suffixes: ' + JSON.stringify(suffixes) + ); + await publish(suffixes); + } + }); + + function initSDK() { + const bucket = process.env.S3_BUCKET_NAME, + key = process.env.S3_ACCESS_KEY_ID, + secret = process.env.S3_SECRET_ACCESS_KEY; + + if (!bucket || !key || !secret) { + throw new Error('Missing S3 config values'); + } + + AWS.config.update({ accessKeyId: key, secretAccessKey: secret }); + } + + async function publish(suffixes) { + const publishPromises = suffixes.map(suffix => publishSuffix(suffix)); + return Promise.all(publishPromises); + } + + async function publishSuffix(suffix) { + const filenames = [ + 'handlebars.js', + 'handlebars.min.js', + 'handlebars.runtime.js', + 'handlebars.runtime.min.js' + ]; + const publishPromises = filenames.map(filename => { + const nameInBucket = getNameInBucket(filename, suffix); + const localFile = getLocalFile(filename); + uploadToBucket(localFile, nameInBucket); + grunt.log.writeln( + `Published ${localFile} to build server (${nameInBucket})` + ); + }); + return Promise.all(publishPromises); + } + + async function uploadToBucket(localFile, nameInBucket) { + const bucket = process.env.S3_BUCKET_NAME; + const uploadParams = { + Bucket: bucket, + Key: nameInBucket, + Body: grunt.file.read(localFile) + }; + return s3PutObject(uploadParams); + } +}; + +function s3PutObject(uploadParams) { + const s3 = new AWS.S3(); + return new Promise((resolve, reject) => { + s3.putObject(uploadParams, err => { + if (err != null) { + return reject(err); + } + resolve(); + }); + }); +} + +function getNameInBucket(filename, suffix) { + return filename.replace(/\.js$/, suffix + '.js'); +} + +function getLocalFile(filename) { + return 'dist/' + filename; +} diff --git a/tasks/publish.js b/tasks/publish.js deleted file mode 100644 index b22c9b8e..00000000 --- a/tasks/publish.js +++ /dev/null @@ -1,106 +0,0 @@ -var _ = require('underscore'), - async = require('neo-async'), - AWS = require('aws-sdk'), - git = require('./util/git'), - semver = require('semver'); - -module.exports = function(grunt) { - grunt.registerTask('publish:latest', function() { - var done = this.async(); - - git.debug(function(remotes, branches) { - grunt.log.writeln('remotes: ' + remotes); - grunt.log.writeln('branches: ' + branches); - - git.commitInfo(function(err, info) { - grunt.log.writeln('tag: ' + info.tagName); - - var files = []; - - // Publish the master as "latest" and with the commit-id - if (info.isMaster) { - files.push('-latest'); - files.push('-' + info.head); - } - - // Publish tags by their tag-name - if (info.tagName && semver.valid(info.tagName)) { - files.push('-' + info.tagName); - } - - if (files.length > 0) { - initSDK(); - grunt.log.writeln('publishing files: ' + JSON.stringify(files)); - publish(fileMap(files), done); - } else { - // Silently ignore for branches - done(); - } - }); - }); - }); - grunt.registerTask('publish:version', function() { - var done = this.async(); - initSDK(); - - git.commitInfo(function(err, info) { - if (!info.tagName) { - throw new Error('The current commit must be tagged'); - } - publish(fileMap(['-' + info.tagName]), done); - }); - }); - - function initSDK() { - var bucket = process.env.S3_BUCKET_NAME, - key = process.env.S3_ACCESS_KEY_ID, - secret = process.env.S3_SECRET_ACCESS_KEY; - - if (!bucket || !key || !secret) { - throw new Error('Missing S3 config values'); - } - - AWS.config.update({ accessKeyId: key, secretAccessKey: secret }); - } - function publish(files, callback) { - var s3 = new AWS.S3(), - bucket = process.env.S3_BUCKET_NAME; - - async.each( - _.keys(files), - function(file, callback) { - var params = { - Bucket: bucket, - Key: file, - Body: grunt.file.read(files[file]) - }; - s3.putObject(params, function(err) { - if (err) { - throw err; - } else { - grunt.log.writeln('Published ' + file + ' to build server.'); - callback(); - } - }); - }, - callback - ); - } - function fileMap(suffixes) { - var map = {}; - _.each( - [ - 'handlebars.js', - 'handlebars.min.js', - 'handlebars.runtime.js', - 'handlebars.runtime.min.js' - ], - function(file) { - _.each(suffixes, function(suffix) { - map[file.replace(/\.js$/, suffix + '.js')] = 'dist/' + file; - }); - } - ); - return map; - } -}; diff --git a/tasks/task-tests/.eslintrc.js b/tasks/task-tests/.eslintrc.js new file mode 100644 index 00000000..604aeb2c --- /dev/null +++ b/tasks/task-tests/.eslintrc.js @@ -0,0 +1,9 @@ +module.exports = { + extends: '../../.eslintrc.js', + env: { + mocha: true + }, + parserOptions: { + ecmaVersion: 2018 + } +}; diff --git a/tasks/task-tests/README.md b/tasks/task-tests/README.md new file mode 100644 index 00000000..f4a88806 --- /dev/null +++ b/tasks/task-tests/README.md @@ -0,0 +1 @@ +Use `mocha tasks/task-tests` to run these tests diff --git a/tasks/task-tests/git.test.js b/tasks/task-tests/git.test.js new file mode 100644 index 00000000..89546a8b --- /dev/null +++ b/tasks/task-tests/git.test.js @@ -0,0 +1,121 @@ +const os = require('os'); +const path = require('path'); +const fs = require('fs-extra'); +const chai = require('chai'); +chai.use(require('dirty-chai')); + +const git = require('../util/git'); + +const expect = chai.expect; + +const tmpBaseDir = path.join(os.tmpdir(), 'handlebars-task-tests'); +const tmpDir = path.join(tmpBaseDir, Date.now().toString(36)); +const remoteDir = path.join(tmpDir, 'remote-repo'); +const cloneDir = path.join(tmpDir, 'clone-repo'); +const oldCwd = process.cwd(); + +describe('utils/git', function() { + beforeEach(async function() { + await fs.remove(tmpDir); + await createRepositoryThatActsAsRemote(); + process.chdir(tmpDir); + await git.git('clone', 'remote-repo', 'clone-repo'); + process.chdir(cloneDir); + }); + + async function createRepositoryThatActsAsRemote() { + await fs.mkdirp(remoteDir); + process.chdir(remoteDir); + + await git.git('init'); + await fs.writeFile('testfile.txt', 'Testfile'); + await git.add('testfile.txt'); + await git.commit('commit message'); + } + + afterEach(function() { + process.chdir(oldCwd); + }); + + describe('the "remotes"-function', function() { + it('should list all remotes', async function() { + await git.git('remote', 'set-url', 'origin', 'https://test.org/test'); + await git.git('remote', 'add', 'second-remote', 'https://test.org/test2'); + + const result = await git.remotes(); + + expect(result.trim().split('\n')).to.deep.equal([ + 'origin\thttps://test.org/test (fetch)', + 'origin\thttps://test.org/test (push)', + 'second-remote\thttps://test.org/test2 (fetch)', + 'second-remote\thttps://test.org/test2 (push)' + ]); + }); + }); + + describe('the "branches"-function', function() { + it('should list all branches', async function() { + await git.git('branch', 'test'); + await git.git('branch', 'test2'); + + const result = await git.branches(); + expect(result.trim().split('\n')).to.deep.equal([ + '* master', + ' test', + ' test2', + ' remotes/origin/HEAD -> origin/master', + ' remotes/origin/master' + ]); + }); + }); + + describe('the "commitInfo"-function', function() { + it('should list head and master sha', async function() { + const result = await git.commitInfo(); + expect(result.masterSha).to.equal(result.headSha); + expect(result.masterSha).to.match(/^[0-9a-f]+$/); + expect(result.headSha).to.match(/^[0-9a-f]+$/); + }); + + it('should have "isMaster=true" if the master branch is checked out', async function() { + const result = await git.commitInfo(); + expect(result.isMaster).to.be.true(); + }); + + it('should have "isMaster=true" if the current commit is the last commit of the master branch', async function() { + await git.git('checkout', '-b', 'new-branch'); + + const result = await git.commitInfo(); + expect(result.isMaster).to.be.true(); + }); + + it('should have "isMaster=false" if the current commit is NOT the last commit of the master branch', async function() { + await git.git('checkout', '-b', 'new-branch'); + fs.writeFile('new-file.txt', 'new-file'); + await git.add('new-file.txt'); + await git.commit('added new file'); + + const result = await git.commitInfo(); + expect(result.isMaster).to.be.false(); + }); + + it('should show the current tag', async function() { + await git.git('tag', 'test-tag'); + const result = await git.commitInfo(); + expect(result.tagName).to.be.equal('test-tag'); + }); + + it('should show a version tag rather than standard tags', async function() { + await git.git('tag', 'test-tag'); + await git.git('tag', 'v1.2'); + await git.git('tag', 'test-tag2'); + const result = await git.commitInfo(); + expect(result.tagName).to.be.equal('v1.2'); + }); + + it('should show no tag if there is no tag', async function() { + const result = await git.commitInfo(); + expect(result.tagName).to.be.null(); + }); + }); +}); diff --git a/tasks/task-tests/mocha.opts b/tasks/task-tests/mocha.opts new file mode 100644 index 00000000..e69de29b diff --git a/tasks/test-bin.js b/tasks/test-bin.js new file mode 100644 index 00000000..8873c9f0 --- /dev/null +++ b/tasks/test-bin.js @@ -0,0 +1,45 @@ +const childProcess = require('child_process'), + fs = require('fs'), + os = require('os'), + expect = require('chai').expect; + +module.exports = function(grunt) { + grunt.registerTask('test:bin', function() { + const stdout = executeBinHandlebars( + '-a', + 'spec/artifacts/empty.handlebars' + ); + + const expectedOutput = fs.readFileSync( + './spec/expected/empty.amd.js', + 'utf-8' + ); + + const normalizedOutput = normalizeCrlf(stdout); + const normalizedExpectedOutput = normalizeCrlf(expectedOutput); + + expect(normalizedOutput).to.equal(normalizedExpectedOutput); + }); +}; + +// helper functions + +function executeBinHandlebars(...args) { + if (os.platform() === 'win32') { + // On Windows, the executable handlebars.js file cannot be run directly + const nodeJs = process.argv[0]; + return execFilesSyncUtf8(nodeJs, ['./bin/handlebars'].concat(args)); + } + return execFilesSyncUtf8('./bin/handlebars', args); +} + +function execFilesSyncUtf8(command, args) { + return childProcess.execFileSync(command, args, { encoding: 'utf-8' }); +} + +function normalizeCrlf(string) { + if (typeof string === 'string') { + return string.replace(/\r\n/g, '\n'); + } + return string; +} diff --git a/tasks/test-mocha.js b/tasks/test-mocha.js new file mode 100644 index 00000000..b412c8c0 --- /dev/null +++ b/tasks/test-mocha.js @@ -0,0 +1,22 @@ +const { execNodeJsScriptWithInheritedOutput } = require('./util/exec-file'); +const { createRegisterAsyncTaskFn } = require('./util/async-grunt-task'); +const nodeJs = process.argv0; + +module.exports = function(grunt) { + const registerAsyncTask = createRegisterAsyncTaskFn(grunt); + + registerAsyncTask('test:mocha', async () => + execNodeJsScriptWithInheritedOutput('./spec/env/runner') + ); + + registerAsyncTask('test:cov', async () => + execNodeJsScriptWithInheritedOutput('node_modules/nyc/bin/nyc', [ + nodeJs, + './spec/env/runner.js' + ]) + ); + + registerAsyncTask('test:min', async () => + execNodeJsScriptWithInheritedOutput('./spec/env/runner', ['--min']) + ); +}; diff --git a/tasks/test.js b/tasks/test.js deleted file mode 100644 index 94fc8c25..00000000 --- a/tasks/test.js +++ /dev/null @@ -1,107 +0,0 @@ -var childProcess = require('child_process'), - fs = require('fs'), - os = require('os'); - -module.exports = function(grunt) { - grunt.registerTask('test:bin', function() { - var done = this.async(); - - var cmd = './bin/handlebars'; - var args = ['-a', 'spec/artifacts/empty.handlebars']; - - // On Windows, the executable handlebars.js file cannot be run directly - if (os.platform() === 'win32') { - args.unshift(cmd); - cmd = process.argv[0]; - } - childProcess.execFile(cmd, args, function(err, stdout) { - if (err) { - throw err; - } - - var expected = fs - .readFileSync('./spec/expected/empty.amd.js') - .toString() - .replace(/\r\n/g, '\n'); - - if (stdout.toString() !== expected) { - throw new Error( - 'Expected binary output differed:\n\n"' + - stdout + - '"\n\n"' + - expected + - '"' - ); - } - - done(); - }); - }); - grunt.registerTask('test:mocha', function() { - var done = this.async(); - - var runner = childProcess.fork('./spec/env/runner', [], { - stdio: 'inherit' - }); - runner.on('close', function(code) { - if (code !== 0) { - grunt.fatal(code + ' tests failed'); - } - done(); - }); - }); - grunt.registerTask('test:cov', function() { - var done = this.async(); - - var runner = childProcess.fork( - 'node_modules/istanbul/lib/cli.js', - ['cover', '--source-map', '--', './spec/env/runner.js'], - { stdio: 'inherit' } - ); - runner.on('close', function(code) { - if (code != 0) { - grunt.fatal(code + ' tests failed'); - } - done(); - }); - }); - grunt.registerTask('test:min', function() { - var done = this.async(); - - var runner = childProcess.fork('./spec/env/runner', ['--min'], { - stdio: 'inherit' - }); - runner.on('close', function(code) { - if (code !== 0) { - grunt.fatal(code + ' tests failed'); - } - done(); - }); - }); - - grunt.registerTask('test:check-cov', function() { - var done = this.async(); - - var runner = childProcess.fork( - 'node_modules/istanbul/lib/cli.js', - [ - 'check-coverage', - '--statements', - '100', - '--functions', - '100', - '--branches', - '100', - '--lines 100' - ], - { stdio: 'inherit' } - ); - runner.on('close', function(code) { - if (code != 0) { - grunt.fatal('Coverage check failed: ' + code); - } - done(); - }); - }); - grunt.registerTask('test', ['test:bin', 'test:cov', 'test:check-cov']); -}; diff --git a/tasks/util/async-grunt-task.js b/tasks/util/async-grunt-task.js new file mode 100644 index 00000000..20360570 --- /dev/null +++ b/tasks/util/async-grunt-task.js @@ -0,0 +1,13 @@ +module.exports = { createRegisterAsyncTaskFn }; + +function createRegisterAsyncTaskFn(grunt) { + return function registerAsyncTask(name, asyncFunction) { + grunt.registerTask(name, function() { + asyncFunction() + .catch(error => { + grunt.fatal(error); + }) + .finally(this.async()); + }); + }; +} diff --git a/tasks/util/exec-file.js b/tasks/util/exec-file.js new file mode 100644 index 00000000..66fd8e92 --- /dev/null +++ b/tasks/util/exec-file.js @@ -0,0 +1,51 @@ +const childProcess = require('child_process'); +const fs = require('fs'); +const path = require('path'); + +module.exports = { + execNodeJsScriptWithInheritedOutput, + execFileWithInheritedOutput +}; + +async function execNodeJsScriptWithInheritedOutput(command, args) { + return new Promise((resolve, reject) => { + const child = childProcess.fork(command, args, { stdio: 'inherit' }); + child.on('close', code => { + if (code !== 0) { + reject(new Error(`Child process failed with exit-code ${code}`)); + } + resolve(); + }); + }); +} + +async function execFileWithInheritedOutput(command, args) { + return new Promise((resolve, reject) => { + const resolvedCommand = preferLocalDependencies(command); + const child = childProcess.spawn(resolvedCommand, args, { + stdio: 'inherit' + }); + child.on('exit', code => { + if (code !== 0) { + reject(new Error(`Child process failed with exit-code ${code}`)); + } + resolve(); + }); + }); +} + +function preferLocalDependencies(command) { + const localCandidate = resolveLocalCandidate(command); + + if (fs.existsSync(localCandidate)) { + return localCandidate; + } + return command; +} + +function resolveLocalCandidate(command) { + if (process.platform === 'win32') { + return path.join('node_modules', '.bin', command + '.cmd'); + } + return path.join('node_modules', '.bin', command); +} diff --git a/tasks/util/git.js b/tasks/util/git.js index 5418bf03..46c9cbe7 100644 --- a/tasks/util/git.js +++ b/tasks/util/git.js @@ -1,115 +1,73 @@ -var childProcess = require('child_process'); +const childProcess = require('child_process'); module.exports = { - debug: function(callback) { - childProcess.exec('git remote -v', {}, function(err, remotes) { - if (err) { - throw new Error('git.remote: ' + err.message); - } - - childProcess.exec('git branch -a', {}, function(err, branches) { - if (err) { - throw new Error('git.branch: ' + err.message); - } - - callback(remotes, branches); - }); - }); + async remotes() { + return git('remote', '-v'); }, - clean: function(callback) { - childProcess.exec('git diff-index --name-only HEAD --', {}, function( - err, - stdout - ) { - callback(undefined, !err && !stdout); - }); + async branches() { + return git('branch', '-a'); }, - - commitInfo: function(callback) { - module.exports.head(function(err, headSha) { - module.exports.master(function(err, masterSha) { - module.exports.tagName(function(err, tagName) { - callback(undefined, { - head: headSha, - master: masterSha, - tagName: tagName, - isMaster: headSha === masterSha - }); - }); - }); - }); + async commitInfo() { + const headSha = await getHeadSha(); + const masterSha = await getMasterSha(); + return { + headSha, + masterSha, + tagName: await getTagName(), + isMaster: headSha === masterSha + }; }, - - head: function(callback) { - childProcess.exec('git rev-parse --short HEAD', {}, function(err, stdout) { - if (err) { - throw new Error('git.head: ' + err.message); - } - - callback(undefined, stdout.trim()); - }); + async add(path) { + return git('add', '-f', path); }, - master: function(callback) { - childProcess.exec('git rev-parse --short origin/master', {}, function( - err, - stdout - ) { - // This will error if master was not checked out but in this case we know we are not master - // so we can ignore. - if (err && !/Needed a single revision/.test(err.message)) { - throw new Error('git.master: ' + err.message); - } - - callback(undefined, stdout.trim()); - }); + async commit(message) { + return git('commit', '--message', message); }, - - add: function(path, callback) { - childProcess.exec('git add -f ' + path, {}, function(err) { - if (err) { - throw new Error('git.add: ' + err.message); - } - - callback(); - }); - }, - commit: function(name, callback) { - childProcess.exec('git commit --message=' + name, {}, function(err) { - if (err) { - throw new Error('git.commit: ' + err.message); - } - - callback(); - }); - }, - tag: function(name, callback) { - childProcess.exec('git tag -a --message=' + name + ' ' + name, {}, function( - err - ) { - if (err) { - throw new Error('git.tag: ' + err.message); - } - - callback(); - }); - }, - tagName: function(callback) { - childProcess.exec('git describe --tags', {}, function(err, stdout) { - if (err) { - throw new Error('git.tagName: ' + err.message); - } - - var tags = stdout.trim().split(/\n/); - tags = tags.filter(function(info) { - info = info.split('-'); - return info.length == 1; - }); - - var versionTags = tags.filter(function(info) { - return /^v/.test(info[0]); - }); - - callback(undefined, versionTags[0] || tags[0]); - }); - } + git // visible for testing }; + +async function getHeadSha() { + const stdout = await git('rev-parse', '--short', 'HEAD'); + return stdout.trim(); +} + +async function getMasterSha() { + try { + const stdout = await git('rev-parse', '--short', 'origin/master'); + return stdout.trim(); + } catch (error) { + if (/Needed a single revision/.test(error.message)) { + // Master was not checked out but in this case, so we know we are not master. We can ignore this + return ''; + } + throw error; + } +} + +async function getTagName() { + const stdout = await git('tag', '-l', '--points-at', 'HEAD'); + const trimmedStdout = stdout.trim(); + if (trimmedStdout === '') { + return null; // there is no tag + } + + const tags = trimmedStdout.split(/\n|\r\n/); + const versionTags = tags.filter(tag => /^v/.test(tag)); + if (versionTags[0] != null) { + return versionTags[0]; + } + return tags[0]; +} + +async function git(...args) { + return new Promise((resolve, reject) => + childProcess.execFile('git', args, (err, stdout) => { + if (err != null) { + return reject( + new Error(`"git ${args.join(' ')}" caused error: ${err.message}`) + ); + } + resolve(stdout); + }) + ); +} diff --git a/tasks/version.js b/tasks/version.js index 05c05fa0..ba89d1fd 100644 --- a/tasks/version.js +++ b/tasks/version.js @@ -1,68 +1,62 @@ -var async = require('neo-async'), - git = require('./util/git'), - semver = require('semver'); +const git = require('./util/git'); +const semver = require('semver'); +const { createRegisterAsyncTaskFn } = require('./util/async-grunt-task'); module.exports = function(grunt) { - grunt.registerTask( - 'version', - 'Updates the current release version', - function() { - var done = this.async(), - pkg = grunt.config('pkg'), - version = grunt.option('ver'); + const registerAsyncTask = createRegisterAsyncTaskFn(grunt); - if (!semver.valid(version)) { - throw new Error( - 'Must provide a version number (Ex: --ver=1.0.0):\n\t' + - version + - '\n\n' - ); - } - - pkg.version = version; - grunt.config('pkg', pkg); - - grunt.log.writeln('Updating to version ' + version); - - async.each( - [ - [ - 'lib/handlebars/base.js', - /const VERSION = ['"](.*)['"];/, - "const VERSION = '" + version + "';" - ], - [ - 'components/bower.json', - /"version":.*/, - '"version": "' + version + '",' - ], - [ - 'components/package.json', - /"version":.*/, - '"version": "' + version + '",' - ], - [ - 'components/handlebars.js.nuspec', - /.*<\/version>/, - '' + version + '' - ] - ], - function(args, callback) { - replace.apply(undefined, args); - grunt.log.writeln(' - ' + args[0]); - git.add(args[0], callback); - }, - function() { - grunt.task.run(['default']); - done(); - } + registerAsyncTask('version', async () => { + const pkg = grunt.config('pkg'); + const version = grunt.option('ver'); + if (!semver.valid(version)) { + throw new Error( + 'Must provide a version number (Ex: --ver=1.0.0):\n\t' + + version + + '\n\n' ); } - ); + pkg.version = version; + grunt.config('pkg', pkg); - function replace(path, regex, value) { - var content = grunt.file.read(path); + const replaceSpec = [ + { + path: 'lib/handlebars/base.js', + regex: /const VERSION = ['"](.*)['"];/, + replacement: `const VERSION = '${version}';` + }, + { + path: 'components/bower.json', + regex: /"version":.*/, + replacement: `"version": "${version}",` + }, + { + path: 'components/package.json', + regex: /"version":.*/, + replacement: `"version": "${version}",` + }, + { + path: 'components/handlebars.js.nuspec', + regex: /.*<\/version>/, + replacement: `${version}` + } + ]; + + await Promise.all( + replaceSpec.map(replaceSpec => + replaceAndAdd( + replaceSpec.path, + replaceSpec.regex, + replaceSpec.replacement + ) + ) + ); + grunt.task.run(['default']); + }); + + async function replaceAndAdd(path, regex, value) { + let content = grunt.file.read(path); content = content.replace(regex, value); grunt.file.write(path, content); + await git.add(path); } };