diff --git a/.gitignore b/.gitignore index 8ac5504..58cad32 100644 --- a/.gitignore +++ b/.gitignore @@ -4,10 +4,12 @@ yarn-error.log node_modules cypress/screenshots test/app/.sapper -test/app/app/manifest +test/app/src/manifest +__sapper__ test/app/export test/app/build sapper runtime.js dist -!rollup.config.js \ No newline at end of file +!rollup.config.js +templates/*.js \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8717841..fe6dc02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,198 @@ # sapper changelog +## 0.24.3 + +* Add service-worker-index.html shell file for offline support ([#422](https://github.com/sveltejs/sapper/issues/422)) +* Don't cache .map files ([#534](https://github.com/sveltejs/sapper/issues/534)) + +## 0.24.2 + +* Support Rollup 1.0 ([#541](https://github.com/sveltejs/sapper/pull/541)) + +## 0.24.1 + +* Include CSS chunks in webpack build info to avoid duplication ([#529](https://github.com/sveltejs/sapper/pull/529)) +* Fix preload `as` for styles ([#530](https://github.com/sveltejs/sapper/pull/530)) + +## 0.24.0 + +* Handle external URLs in `this.redirect` ([#490](https://github.com/sveltejs/sapper/issues/490)) +* Strip leading `/` from basepath ([#495](https://github.com/sveltejs/sapper/issues/495)) +* Treat duplicate query string parameters as arrays ([#497](https://github.com/sveltejs/sapper/issues/497)) +* Don't buffer `stdout` and `stderr` ([#305](https://github.com/sveltejs/sapper/issues/305)) +* Posixify `build_dir` ([#498](https://github.com/sveltejs/sapper/pull/498)) +* Use `page[XY]Offset` instead of `scroll[XY]` ([#480](https://github.com/sveltejs/sapper/issues/480)) + +## 0.23.5 + +* Include lazily-imported CSS in main CSS chunk ([#492](https://github.com/sveltejs/sapper/pull/492)) +* Make search param decoding spec-compliant ([#493](https://github.com/sveltejs/sapper/pull/493)) +* Handle async route errors ([#488](https://github.com/sveltejs/sapper/pull/488)) + +## 0.23.4 + +* Ignore empty anchors when exporting ([#491](https://github.com/sveltejs/sapper/pull/491)) + +## 0.23.3 + +* Clear `error` and `status` on successful render ([#477](https://github.com/sveltejs/sapper/pull/477)) + +## 0.23.2 + +* Fix entry point CSS ([#471](https://github.com/sveltejs/sapper/pull/471)) + +## 0.23.1 + +* Scroll to deeplink that matches current URL ([#472](https://github.com/sveltejs/sapper/pull/472)) +* Scroll to deeplink on another page ([#341](https://github.com/sveltejs/sapper/issues/341)) + +## 0.23.0 + +* Overhaul internal APIs ([#468](https://github.com/sveltejs/sapper/pull/468)) +* Remove unused `sapper start` and `sapper upgrade` ([#468](https://github.com/sveltejs/sapper/pull/468)) +* Remove magic environment variables ([#469](https://github.com/sveltejs/sapper/pull/469)) +* Preserve SSI comments ([#470](https://github.com/sveltejs/sapper/pull/470)) + +## 0.22.10 + +* Handle `sapper-noscroll` attribute on `` elements ([#376](https://github.com/sveltejs/sapper/issues/376)) +* Fix CSS paths when using a base path ([#466](https://github.com/sveltejs/sapper/pull/466)) + +## 0.22.9 + +* Fix legacy builds ([#462](https://github.com/sveltejs/sapper/pull/462)) + +## 0.22.8 + +* Ensure CSS placeholders are overwritten ([#462](https://github.com/sveltejs/sapper/pull/462)) + +## 0.22.7 + +* Fix cookies ([#460](https://github.com/sveltejs/sapper/pull/460)) + +## 0.22.6 + +* Normalise chunk filenames on Windows ([#456](https://github.com/sveltejs/sapper/pull/456)) +* Load modules with credentials ([#458](https://github.com/sveltejs/sapper/pull/458)) + +## 0.22.5 + +* Fix `sapper dev`. Oops. + +## 0.22.4 + +* Ensure launcher does not overwrite a module ([#455](https://github.com/sveltejs/sapper/pull/455)) + +## 0.22.3 + +* Prevent server from accidentally importing dev client + +## 0.22.2 + +* Make paths in generated code relative to project + +## 0.22.1 + +* Fix `pkg.files` + +## 0.22.0 + +* Move generated files into `__sapper__` ([#453](https://github.com/sveltejs/sapper/pull/453)) +* Change default build and export directories to `__sapper__/build` and `__sapper__/export` ([#453](https://github.com/sveltejs/sapper/pull/453)) + +## 0.21.1 + +* Read template from build directory in production + +## 0.21.0 + +* Change project folder structure ([#432](https://github.com/sveltejs/sapper/issues/432)) +* Escape filenames ([#446](https://github.com/sveltejs/sapper/pull/446/)) + +## 0.20.4 + +* Fix legacy build CSS ([#439](https://github.com/sveltejs/sapper/issues/439)) +* Enable debugging in Chrome and VSCode ([#435](https://github.com/sveltejs/sapper/issues/435)) + +## 0.20.3 + +* Inject `nonce` attribute if `res.locals.nonce` is present ([#424](https://github.com/sveltejs/sapper/pull/424)) +* Prevent service worker caching ([#428](https://github.com/sveltejs/sapper/pull/428)) +* Consistent caching for HTML responses ([#429](https://github.com/sveltejs/sapper/pull/429)) + +## 0.20.2 + +* Add `immutable` cache control header for hashed assets ([#425](https://github.com/sveltejs/sapper/pull/425)) +* Handle value-less query string params ([#426](https://github.com/sveltejs/sapper/issues/426)) + +## 0.20.1 + +* Update shimport + +## 0.20.0 + +* Decode `req.params` and `req.query` ([#417](https://github.com/sveltejs/sapper/issues/417)) +* Decode URLs before writing files in `sapper export` ([#414](https://github.com/sveltejs/sapper/pull/414)) +* Generate server sourcemaps for Rollup apps in dev mode ([#418](https://github.com/sveltejs/sapper/pull/418)) + +## 0.19.3 + +* Better unicode route handling ([#347](https://github.com/sveltejs/sapper/issues/347)) + +## 0.19.2 + +* Ignore editor tmp files ([#220](https://github.com/sveltejs/sapper/issues/220)) +* Ignore clicks an `` element without `href` ([#235](https://github.com/sveltejs/sapper/issues/235)) +* Allow routes that are reserved JavaScript words ([#315](https://github.com/sveltejs/sapper/issues/315)) +* Print out webpack errors ([#403](https://github.com/sveltejs/sapper/issues/403)) + +## 0.19.1 + +* Don't include local origin in export redirects ([#409](https://github.com/sveltejs/sapper/pull/409)) + +## 0.19.0 + +* Extract styles out of JS into .css files, for Rollup apps ([#388](https://github.com/sveltejs/sapper/issues/388)) +* Fix `prefetchRoutes` ([#380](https://github.com/sveltejs/sapper/issues/380)) + +## 0.18.7 + +* Support differential bundling for Rollup apps via a `--legacy` flag ([#280](https://github.com/sveltejs/sapper/issues/280)) + +## 0.18.6 + +* Bundle missing dependency + +## 0.18.5 + +* Bugfix + +## 0.18.4 + +* Handle non-Sapper responses when exporting ([#382](https://github.com/sveltejs/sapper/issues/392)) +* Add `--dev-port` flag to `sapper dev` ([#381](https://github.com/sveltejs/sapper/issues/381)) + +## 0.18.3 + +* Fix service worker Rollup build config + +## 0.18.2 + +* Update `pkg.files` + +## 0.18.1 + +* Add live reloading ([#385](https://github.com/sveltejs/sapper/issues/385)) + +## 0.18.0 + +* Rollup support ([#379](https://github.com/sveltejs/sapper/pull/379)) +* Fail `export` if a page times out (configurable with `--timeout`) ([#378](https://github.com/sveltejs/sapper/pull/378)) + +## 0.17.1 + +* Print which file is causing build errors/warnings ([#371](https://github.com/sveltejs/sapper/pull/371)) + ## 0.17.0 * Use `cheap-watch` instead of `chokidar` ([#364](https://github.com/sveltejs/sapper/issues/364)) diff --git a/api.js b/api.js index 9746681..719e270 100644 --- a/api.js +++ b/api.js @@ -1 +1 @@ -module.exports = require('./dist/api.ts.js'); \ No newline at end of file +module.exports = require('./dist/api.js'); \ No newline at end of file diff --git a/components/default-layout.html b/components/default-layout.html deleted file mode 100644 index 8c0dcbb..0000000 --- a/components/default-layout.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/config/rollup.js b/config/rollup.js new file mode 100644 index 0000000..3b5c8be --- /dev/null +++ b/config/rollup.js @@ -0,0 +1 @@ +module.exports = require('../dist/rollup.js'); \ No newline at end of file diff --git a/config/webpack.js b/config/webpack.js new file mode 100644 index 0000000..15b21cf --- /dev/null +++ b/config/webpack.js @@ -0,0 +1 @@ +module.exports = require('../dist/webpack.js'); \ No newline at end of file diff --git a/cypress.json b/cypress.json deleted file mode 100644 index 7288d9f..0000000 --- a/cypress.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "baseUrl": "http://localhost:3000", - "videoRecording": false, - "fixturesFolder": "test/cypress/fixtures", - "integrationFolder": "test/cypress/integration", - "pluginsFile": false, - "screenshotsFolder": "test/cypress/screenshots", - "supportFile": "test/cypress/support/index.js" -} diff --git a/index.js b/index.js new file mode 100644 index 0000000..92381ab --- /dev/null +++ b/index.js @@ -0,0 +1 @@ +throw new Error(`As of Sapper 0.22, you should not import 'sapper' directly. See https://sapper.svelte.technology/guide#0-21-to-0-22 for more information`); \ No newline at end of file diff --git a/mocha.opts b/mocha.opts index 985f08b..c769c5c 100644 --- a/mocha.opts +++ b/mocha.opts @@ -2,4 +2,4 @@ --require ts-node/register --recursive test/unit/*/*.ts -test/common/test.js \ No newline at end of file +test/apps/*/test.ts \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4510112..571cef0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "sapper", - "version": "0.17.0", + "version": "0.24.3", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -10,6 +10,32 @@ "integrity": "sha1-MU+BaPUK5IoDLP2tX9tDb0ZKl6w=", "dev": true }, + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@polka/url": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-0.5.0.tgz", + "integrity": "sha512-oZLYFEAzUKyi3SKnXvj32ZCEGH6RDnao7COuCVhDydMS9NrCSVXhM79VaKyP5+Zc33m0QXEd2DN3UkU7OsHcfw==", + "dev": true + }, "@types/estree": { "version": "0.0.39", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", @@ -18,14 +44,14 @@ }, "@types/events": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==", "dev": true }, "@types/glob": { - "version": "5.0.35", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.35.tgz", - "integrity": "sha512-wc+VveszMLyMWFvXLkloixT4n0harUIVZjnpzztaZ0nKLuul7Z32iMt2fUFGAaZ4y1XWjFRMtCI5ewvyh4aIeg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", "dev": true, "requires": { "@types/events": "*", @@ -55,11 +81,20 @@ "dev": true }, "@types/node": { - "version": "10.7.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.7.1.tgz", - "integrity": "sha512-EGoI4ylB/lPOaqXqtzAyL8HcgOuCtH2hkEaLmkueOYufsTFWBn4VCvlCDC2HW8Q+9iF+QVC3sxjDKQYjHQeZ9w==", + "version": "10.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.0.tgz", + "integrity": "sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ==", "dev": true }, + "@types/puppeteer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@types/puppeteer/-/puppeteer-1.9.0.tgz", + "integrity": "sha512-ZP3wL4Lqpgu4xZbz/0vQhbIZnllNEawVW3oTpEXyJg+uhf/YQgL8oeTrfoUwj9JXE9UUe53eqmgLl29/d2gjqQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/rimraf": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/@types/rimraf/-/rimraf-2.0.2.tgz", @@ -71,278 +106,193 @@ } }, "@webassemblyjs/ast": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.5.13.tgz", - "integrity": "sha512-49nwvW/Hx9i+OYHg+mRhKZfAlqThr11Dqz8TsrvqGKMhdI2ijy3KBJOun2Z4770TPjrIJhR6KxChQIDaz8clDA==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.8.tgz", + "integrity": "sha512-dOrtdtEyB8sInpl75yLPNksY4sRl0j/+t6aHyB/YA+ab9hV3Fo7FmG12FHzP+2MvWVAJtDb+6eXR5EZbZJ+uVg==", "dev": true, "requires": { - "@webassemblyjs/helper-module-context": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/wast-parser": "1.5.13", - "debug": "^3.1.0", - "mamacro": "^0.0.3" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } + "@webassemblyjs/helper-module-context": "1.7.8", + "@webassemblyjs/helper-wasm-bytecode": "1.7.8", + "@webassemblyjs/wast-parser": "1.7.8" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.5.13.tgz", - "integrity": "sha512-vrvvB18Kh4uyghSKb0NTv+2WZx871WL2NzwMj61jcq2bXkyhRC+8Q0oD7JGVf0+5i/fKQYQSBCNMMsDMRVAMqA==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.8.tgz", + "integrity": "sha512-kn2zNKGsbql5i56VAgRYkpG+VazqHhQQZQycT2uXAazrAEDs23gy+Odkh5VblybjnwX2/BITkDtNmSO76hdIvQ==", "dev": true }, "@webassemblyjs/helper-api-error": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.5.13.tgz", - "integrity": "sha512-dBh2CWYqjaDlvMmRP/kudxpdh30uXjIbpkLj9HQe+qtYlwvYjPRjdQXrq1cTAAOUSMTtzqbXIxEdEZmyKfcwsg==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.8.tgz", + "integrity": "sha512-xUwxDXsd1dUKArJEP5wWM5zxgCSwZApSOJyP1XO7M8rNUChUDblcLQ4FpzTpWG2YeylMwMl1MlP5Ztryiz1x4g==", "dev": true }, "@webassemblyjs/helper-buffer": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.5.13.tgz", - "integrity": "sha512-v7igWf1mHcpJNbn4m7e77XOAWXCDT76Xe7Is1VQFXc4K5jRcFrl9D0NrqM4XifQ0bXiuTSkTKMYqDxu5MhNljA==", - "dev": true, - "requires": { - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.8.tgz", + "integrity": "sha512-WXiIMnuvuwlhWvVOm8xEXU9DnHaa3AgAU0ZPfvY8vO1cSsmYb2WbGbHnMLgs43vXnA7XAob9b56zuZaMkxpCBg==", + "dev": true }, "@webassemblyjs/helper-code-frame": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.5.13.tgz", - "integrity": "sha512-yN6ScQQDFCiAXnVctdVO/J5NQRbwyTbQzsGzEgXsAnrxhjp0xihh+nNHQTMrq5UhOqTb5LykpJAvEv9AT0jnAQ==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.8.tgz", + "integrity": "sha512-TLQxyD9qGOIdX5LPQOPo0Ernd88U5rHkFb8WAjeMIeA0sPjCHeVPaGqUGGIXjUcblUkjuDAc07bruCcNHUrHDA==", "dev": true, "requires": { - "@webassemblyjs/wast-printer": "1.5.13" + "@webassemblyjs/wast-printer": "1.7.8" } }, "@webassemblyjs/helper-fsm": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.5.13.tgz", - "integrity": "sha512-hSIKzbXjVMRvy3Jzhgu+vDd/aswJ+UMEnLRCkZDdknZO3Z9e6rp1DAs0tdLItjCFqkz9+0BeOPK/mk3eYvVzZg==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.8.tgz", + "integrity": "sha512-TjK0CnD8hAPkV5mbSp5aWl6SO1+H3WFcjWtixWoy8EMA99YnNzYhpc/WSYWhf7yrhpzkq5tZB0tvLK3Svr3IXA==", "dev": true }, "@webassemblyjs/helper-module-context": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.5.13.tgz", - "integrity": "sha512-zxJXULGPLB7r+k+wIlvGlXpT4CYppRz8fLUM/xobGHc9Z3T6qlmJD9ySJ2jknuktuuiR9AjnNpKYDECyaiX+QQ==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "mamacro": "^0.0.3" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.8.tgz", + "integrity": "sha512-uCutAKR7Nm0VsFixcvnB4HhAyHouNbj0Dx1p7eRjFjXGGZ+N7ftTaG1ZbWCasAEbtwGj54LP8+lkBZdTCPmLGg==", + "dev": true }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.5.13.tgz", - "integrity": "sha512-0n3SoNGLvbJIZPhtMFq0XmmnA/YmQBXaZKQZcW8maGKwLpVcgjNrxpFZHEOLKjXJYVN5Il8vSfG7nRX50Zn+aw==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.8.tgz", + "integrity": "sha512-AdCCE3BMW6V34WYaKUmPgVHa88t2Z14P4/0LjLwuGkI0X6pf7nzp0CehzVVk51cKm2ymVXjl9dCG+gR1yhITIQ==", "dev": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.5.13.tgz", - "integrity": "sha512-IJ/goicOZ5TT1axZFSnlAtz4m8KEjYr12BNOANAwGFPKXM4byEDaMNXYowHMG0yKV9a397eU/NlibFaLwr1fbw==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.8.tgz", + "integrity": "sha512-BkBhYQuzyl4hgTGOKo87Vdw6f9nj8HhI7WYpI0MCC5qFa5ahrAPOGgyETVdnRbv+Rjukl9MxxfDmVcVC435lDg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-buffer": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/wasm-gen": "1.5.13", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/helper-buffer": "1.7.8", + "@webassemblyjs/helper-wasm-bytecode": "1.7.8", + "@webassemblyjs/wasm-gen": "1.7.8" } }, "@webassemblyjs/ieee754": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.5.13.tgz", - "integrity": "sha512-TseswvXEPpG5TCBKoLx9tT7+/GMACjC1ruo09j46ULRZWYm8XHpDWaosOjTnI7kr4SRJFzA6MWoUkAB+YCGKKg==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.8.tgz", + "integrity": "sha512-tOarWChdG1a3y1yqCX0JMDKzrat5tQe4pV6K/TX19BcXsBLYxFQOL1DEDa5KG9syeyvCrvZ+i1+Mv1ExngvktQ==", "dev": true, "requires": { - "ieee754": "^1.1.11" + "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.5.13.tgz", - "integrity": "sha512-0NRMxrL+GG3eISGZBmLBLAVjphbN8Si15s7jzThaw1UE9e5BY1oH49/+MA1xBzxpf1OW5sf9OrPDOclk9wj2yg==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.8.tgz", + "integrity": "sha512-GCYeGPgUFWJiZuP4NICbcyUQNxNLJIf476Ei+K+jVuuebtLpfvwkvYT6iTUE7oZYehhkor4Zz2g7SJ/iZaPudQ==", "dev": true, "requires": { - "long": "4.0.0" - }, - "dependencies": { - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", - "dev": true - } + "@xtuc/long": "4.2.1" } }, "@webassemblyjs/utf8": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.5.13.tgz", - "integrity": "sha512-Ve1ilU2N48Ew0lVGB8FqY7V7hXjaC4+PeZM+vDYxEd+R2iQ0q+Wb3Rw8v0Ri0+rxhoz6gVGsnQNb4FjRiEH/Ng==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.8.tgz", + "integrity": "sha512-9X+f0VV+xNXW2ujfIRSXBJENGE6Qh7bNVKqu3yDjTFB3ar3nsThsGBBKdTG58aXOm2iUH6v28VIf88ymPXODHA==", "dev": true }, "@webassemblyjs/wasm-edit": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.5.13.tgz", - "integrity": "sha512-X7ZNW4+Hga4f2NmqENnHke2V/mGYK/xnybJSIXImt1ulxbCOEs/A+ZK/Km2jgihjyVxp/0z0hwIcxC6PrkWtgw==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.8.tgz", + "integrity": "sha512-6D3Hm2gFixrfyx9XjSON4ml1FZTugqpkIz5Awvrou8fnpyprVzcm4X8pyGRtA2Piixjl3DqmX/HB1xdWyE097A==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-buffer": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/helper-wasm-section": "1.5.13", - "@webassemblyjs/wasm-gen": "1.5.13", - "@webassemblyjs/wasm-opt": "1.5.13", - "@webassemblyjs/wasm-parser": "1.5.13", - "@webassemblyjs/wast-printer": "1.5.13", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/helper-buffer": "1.7.8", + "@webassemblyjs/helper-wasm-bytecode": "1.7.8", + "@webassemblyjs/helper-wasm-section": "1.7.8", + "@webassemblyjs/wasm-gen": "1.7.8", + "@webassemblyjs/wasm-opt": "1.7.8", + "@webassemblyjs/wasm-parser": "1.7.8", + "@webassemblyjs/wast-printer": "1.7.8" } }, "@webassemblyjs/wasm-gen": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.5.13.tgz", - "integrity": "sha512-yfv94Se8R73zmr8GAYzezFHc3lDwE/lBXQddSiIZEKZFuqy7yWtm3KMwA1uGbv5G1WphimJxboXHR80IgX1hQA==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.8.tgz", + "integrity": "sha512-a7O/wE6eBeVKKUYgpMK7NOHmMADD85rSXLe3CqrWRDwWff5y3cSVbzpN6Qv3z6C4hdkpq9qyij1Ga1kemOZGvQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/ieee754": "1.5.13", - "@webassemblyjs/leb128": "1.5.13", - "@webassemblyjs/utf8": "1.5.13" + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/helper-wasm-bytecode": "1.7.8", + "@webassemblyjs/ieee754": "1.7.8", + "@webassemblyjs/leb128": "1.7.8", + "@webassemblyjs/utf8": "1.7.8" } }, "@webassemblyjs/wasm-opt": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.5.13.tgz", - "integrity": "sha512-IkXSkgzVhQ0QYAdIayuCWMmXSYx0dHGU8Ah/AxJf1gBvstMWVnzJnBwLsXLyD87VSBIcsqkmZ28dVb0mOC3oBg==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.8.tgz", + "integrity": "sha512-3lbQ0PT81NHCdi1sR/7+SNpZadM4qYcTSr62nFFAA7e5lFwJr14M1Gi+A/Y3PgcDWOHYjsaNGPpPU0H03N6Blg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-buffer": "1.5.13", - "@webassemblyjs/wasm-gen": "1.5.13", - "@webassemblyjs/wasm-parser": "1.5.13", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/helper-buffer": "1.7.8", + "@webassemblyjs/wasm-gen": "1.7.8", + "@webassemblyjs/wasm-parser": "1.7.8" } }, "@webassemblyjs/wasm-parser": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.5.13.tgz", - "integrity": "sha512-XnYoIcu2iqq8/LrtmdnN3T+bRjqYFjRHqWbqK3osD/0r/Fcv4d9ecRzjVtC29ENEuNTK4mQ9yyxCBCbK8S/cpg==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.8.tgz", + "integrity": "sha512-rZ/zlhp9DHR/05zh1MbAjT2t624sjrPP/OkJCjXqzm7ynH+nIdNcn9Ixc+qzPMFXhIrk0rBoQ3to6sEIvHh9jQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-api-error": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/ieee754": "1.5.13", - "@webassemblyjs/leb128": "1.5.13", - "@webassemblyjs/utf8": "1.5.13" + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/helper-api-error": "1.7.8", + "@webassemblyjs/helper-wasm-bytecode": "1.7.8", + "@webassemblyjs/ieee754": "1.7.8", + "@webassemblyjs/leb128": "1.7.8", + "@webassemblyjs/utf8": "1.7.8" } }, "@webassemblyjs/wast-parser": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.5.13.tgz", - "integrity": "sha512-Lbz65T0LQ1LgzKiUytl34CwuhMNhaCLgrh0JW4rJBN6INnBB8NMwUfQM+FxTnLY9qJ+lHJL/gCM5xYhB9oWi4A==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.8.tgz", + "integrity": "sha512-Q/zrvtUvzWuSiJMcSp90fi6gp2nraiHXjTV2VgAluVdVapM4gy1MQn7akja2p6eSBDQpKJPJ6P4TxRkghRS5dg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/floating-point-hex-parser": "1.5.13", - "@webassemblyjs/helper-api-error": "1.5.13", - "@webassemblyjs/helper-code-frame": "1.5.13", - "@webassemblyjs/helper-fsm": "1.5.13", - "long": "^3.2.0", - "mamacro": "^0.0.3" + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/floating-point-hex-parser": "1.7.8", + "@webassemblyjs/helper-api-error": "1.7.8", + "@webassemblyjs/helper-code-frame": "1.7.8", + "@webassemblyjs/helper-fsm": "1.7.8", + "@xtuc/long": "4.2.1" } }, "@webassemblyjs/wast-printer": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.5.13.tgz", - "integrity": "sha512-QcwogrdqcBh8Z+eUF8SG+ag5iwQSXxQJELBEHmLkk790wgQgnIMmntT2sMAMw53GiFNckArf5X0bsCA44j3lWQ==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.8.tgz", + "integrity": "sha512-GllIthRtwTxRDAURRNXscu7Napzmdf1jt1gpiZiK/QN4fH0lSGs3OTmvdfsMNP7tqI4B3ZtfaaWRlNIQug6Xyg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/wast-parser": "1.5.13", - "long": "^3.2.0" + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/wast-parser": "1.7.8", + "@xtuc/long": "4.2.1" } }, - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true, - "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" - } + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", + "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==", + "dev": true }, "acorn": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", - "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", "dev": true }, "acorn-dynamic-import": { @@ -355,38 +305,61 @@ } }, "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", + "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", "dev": true, "requires": { - "acorn": "^3.0.4" + "acorn": "^5.0.3" + } + }, + "agadoo": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/agadoo/-/agadoo-1.0.1.tgz", + "integrity": "sha512-rEOSqXQ3ABoxmgvxqEvUfS7mcMJBqRhcMbmJq4j+EpCXN0P1cFHYQT66V7rYSu0C+3jialSk58yHTBqzY0m+Sw==", + "dev": true, + "requires": { + "rollup": "^0.64.1", + "rollup-plugin-virtual": "^1.0.1" }, "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true + "rollup": { + "version": "0.64.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.64.1.tgz", + "integrity": "sha512-+ThdVXrvonJdOTzyybMBipP0uz605Z8AnzWVY3rf+cSGnLO7uNkJBlN+9jXqWOomkvumXfm/esmBpA5d53qm7g==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "@types/node": "*" + } } } }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", "dev": true, "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", + "es6-promisify": "^5.0.0" + } + }, + "ajv": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz", + "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", "dev": true }, "ansi-escapes": { @@ -396,16 +369,19 @@ "dev": true }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "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" + } }, "anymatch": { "version": "2.0.0", @@ -415,6 +391,297 @@ "requires": { "micromatch": "^3.1.4", "normalize-path": "^2.1.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "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" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "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" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "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==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "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" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "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" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "aproba": { @@ -433,10 +700,13 @@ } }, "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } }, "arr-flatten": { "version": "1.1.0", @@ -456,18 +726,6 @@ "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", "dev": true }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, "array-map": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", @@ -496,9 +754,9 @@ "dev": true }, "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", "dev": true }, "arrify": { @@ -507,15 +765,6 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", @@ -553,12 +802,6 @@ } } }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -571,10 +814,10 @@ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", "dev": true }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", "dev": true }, "atob": { @@ -583,53 +826,6 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -688,6 +884,18 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, @@ -697,16 +905,6 @@ "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", "dev": true }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", @@ -714,15 +912,15 @@ "dev": true }, "binary-extensions": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", + "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", "dev": true }, "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", + "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==", "dev": true }, "bn.js": { @@ -731,32 +929,6 @@ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, - "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.1", - "http-errors": "~1.6.2", - "iconv-lite": "0.4.19", - "on-finished": "~2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "~1.6.15" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true - } - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -768,32 +940,14 @@ } }, "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "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" - } - } + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" } }, "brorand": { @@ -810,7 +964,7 @@ }, "browserify-aes": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { @@ -847,7 +1001,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { @@ -881,7 +1035,7 @@ }, "buffer": { "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { @@ -913,12 +1067,6 @@ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, "cacache": { "version": "10.0.4", "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", @@ -955,6 +1103,14 @@ "to-object-path": "^0.3.0", "union-value": "^1.0.0", "unset-value": "^1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "caller-path": { @@ -981,28 +1137,6 @@ "upper-case": "^1.1.1" } }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", @@ -1012,38 +1146,18 @@ "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" - }, - "dependencies": { - "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" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, "cheap-watch": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/cheap-watch/-/cheap-watch-0.3.0.tgz", - "integrity": "sha512-5i7VOOgjZgxOA51L+Y6hFYsSLt2llTmOv+/91QUZgQdOzxTBqnVn9k4XTQEP7TrNBF0aI0SmHezm1wjbjsAUrA==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cheap-watch/-/cheap-watch-1.0.0.tgz", + "integrity": "sha512-ZeqXFSLfd/NzLXyFDKfa48/14nytP43gBD2Go1L1WUYLXAkEqIo4TTmp89AEbnXVOk47//sB2/16UbVs3vfijA==", "dev": true }, "chokidar": { @@ -1065,12 +1179,110 @@ "path-is-absolute": "^1.0.0", "readdirp": "^2.0.0", "upath": "^1.0.5" + }, + "dependencies": { + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + } + }, + "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" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "chownr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "dev": true }, "chrome-trace-event": { @@ -1118,6 +1330,12 @@ "requires": { "is-descriptor": "^0.1.0" } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, @@ -1127,13 +1345,6 @@ "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", "requires": { "source-map": "~0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } } }, "cli-cursor": { @@ -1151,24 +1362,6 @@ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -1180,29 +1373,20 @@ } }, "color-convert": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", - "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { - "color-name": "1.1.1" + "color-name": "1.1.3" } }, "color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, "commander": { "version": "2.17.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", @@ -1214,42 +1398,12 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, - "compare-versions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-2.0.1.tgz", - "integrity": "sha1-Htwfk2h/2XoyXFn1XkWgfbEGrKY=", - "dev": true - }, "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", "dev": true }, - "compressible": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.14.tgz", - "integrity": "sha1-MmxfUH+7BV9UEWeCuWmoG2einac=", - "dev": true, - "requires": { - "mime-db": ">= 1.34.0 < 2" - } - }, - "compression": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", - "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.14", - "debug": "2.6.9", - "on-headers": "~1.0.1", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - } - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1289,30 +1443,12 @@ "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", "dev": true }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", "dev": true }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, "copy-concurrently": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", @@ -1351,7 +1487,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { @@ -1364,7 +1500,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { @@ -1377,12 +1513,14 @@ } }, "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "lru-cache": "^4.0.1", + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } @@ -1406,30 +1544,12 @@ "randomfill": "^1.0.3" } }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, "cyclist": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", "dev": true }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -1437,64 +1557,26 @@ "dev": true }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, - "deep-defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/deep-defaults/-/deep-defaults-1.0.4.tgz", - "integrity": "sha1-Gpdi4rbI1qTpkxuO5/+M3O4dF1A=", - "dev": true, - "requires": { - "lodash": "3.0.x" - }, - "dependencies": { - "lodash": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.0.1.tgz", - "integrity": "sha1-FNSQKKOLx0AkHRHi7NV+wG1zwZo=", - "dev": true - } - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -1502,14 +1584,6 @@ "dev": true, "requires": { "object-keys": "^1.0.12" - }, - "dependencies": { - "object-keys": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", - "dev": true - } } }, "define-property": { @@ -1550,6 +1624,18 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, @@ -1568,18 +1654,6 @@ "rimraf": "^2.2.8" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, "des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", @@ -1590,12 +1664,6 @@ "minimalistic-assert": "^1.0.0" } }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, "devalue": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/devalue/-/devalue-1.0.4.tgz", @@ -1610,7 +1678,7 @@ }, "diffie-hellman": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "requires": { @@ -1634,16 +1702,10 @@ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, "duplexify": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", - "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", + "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", "dev": true, "requires": { "end-of-stream": "^1.0.0", @@ -1652,67 +1714,6 @@ "stream-shift": "^1.0.0" } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "electron": { - "version": "1.8.7", - "resolved": "https://registry.npmjs.org/electron/-/electron-1.8.7.tgz", - "integrity": "sha512-q6dn8bspX8u8z6tNU4bEas6ZrdNavnrjJ6d/oz49Nb4zFIPrdh8p29AFjFlSAavypGwAVR/PhYOAGwzZSQSSVQ==", - "dev": true, - "requires": { - "@types/node": "^8.0.24", - "electron-download": "^3.0.1", - "extract-zip": "^1.0.3" - }, - "dependencies": { - "@types/node": { - "version": "8.10.26", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.26.tgz", - "integrity": "sha512-opk6bLLErLSwyVVJeSH5Ek7ZWOBSsN0JrvXTNVGLXLAXKB9xlTYajrplR44xVyMrmbut94H6uJ9jqzM/12jxkA==", - "dev": true - } - } - }, - "electron-download": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-3.3.0.tgz", - "integrity": "sha1-LP1U1pZsAZxNSa1l++Zcyc3vaMg=", - "dev": true, - "requires": { - "debug": "^2.2.0", - "fs-extra": "^0.30.0", - "home-path": "^1.0.1", - "minimist": "^1.2.0", - "nugget": "^2.0.0", - "path-exists": "^2.1.0", - "rc": "^1.1.2", - "semver": "^5.3.0", - "sumchecker": "^1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, "elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", @@ -1734,12 +1735,6 @@ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "dev": true }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -1760,29 +1755,6 @@ "tapable": "^1.0.0" } }, - "enqueue": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/enqueue/-/enqueue-1.0.2.tgz", - "integrity": "sha1-kBTpvOVw7pPKlubI5jrVTBkra8g=", - "dev": true, - "requires": { - "sliced": "0.0.5" - }, - "dependencies": { - "sliced": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz", - "integrity": "sha1-XtwETKTrb3gW1Qui/GPiXY/kcH8=", - "dev": true - } - } - }, - "ensure-posix-path": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ensure-posix-path/-/ensure-posix-path-1.0.2.tgz", - "integrity": "sha1-pls+QtC3HPxYXrd0+ZQ8jZuRsMI=", - "dev": true - }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -1815,27 +1787,30 @@ } }, "es-to-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", - "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "dev": true, "requires": { - "is-callable": "^1.1.1", + "is-callable": "^1.1.4", "is-date-object": "^1.0.1", - "is-symbol": "^1.0.1" + "is-symbol": "^1.0.2" } }, "es6-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", "dev": true }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } }, "escape-string-regexp": { "version": "1.0.5", @@ -1844,60 +1819,49 @@ "dev": true }, "eslint": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", - "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.7.0.tgz", + "integrity": "sha512-zYCeFQahsxffGl87U2aJ7DPyH8CbWgxBC213Y8+TCanhUTf2gEvfq3EKpHmEcozTLyPmGe9LZdMAwC/CpJBM5A==", "dev": true, "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", + "@babel/code-frame": "^7.0.0", + "ajv": "^6.5.3", "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", + "eslint-scope": "^4.0.0", + "eslint-utils": "^1.3.1", "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.4", - "esquery": "^1.0.0", + "espree": "^4.0.0", + "esquery": "^1.0.1", "esutils": "^2.0.2", "file-entry-cache": "^2.0.0", "functional-red-black-tree": "^1.0.1", "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", + "globals": "^11.7.0", + "ignore": "^4.0.6", "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", + "inquirer": "^6.1.0", + "is-resolvable": "^1.1.0", + "js-yaml": "^3.12.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", + "lodash": "^4.17.5", + "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", "optionator": "^0.8.2", "path-is-inside": "^1.0.2", "pluralize": "^7.0.0", "progress": "^2.0.0", - "regexpp": "^1.0.1", + "regexpp": "^2.0.1", "require-uncached": "^1.0.3", - "semver": "^5.3.0", + "semver": "^5.5.1", "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "4.0.2", - "text-table": "~0.2.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } + "strip-json-comments": "^2.0.1", + "table": "^5.0.2", + "text-table": "^0.2.0" } }, "eslint-import-resolver-node": { @@ -1908,6 +1872,23 @@ "requires": { "debug": "^2.6.9", "resolve": "^1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "eslint-module-utils": { @@ -1918,6 +1899,23 @@ "requires": { "debug": "^2.6.8", "pkg-dir": "^1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "eslint-plugin-import": { @@ -1938,6 +1936,15 @@ "resolve": "^1.6.0" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "doctrine": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", @@ -1947,19 +1954,31 @@ "esutils": "^2.0.2", "isarray": "^1.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, "eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", "dev": true, "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" } }, + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", + "dev": true + }, "eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -1967,13 +1986,13 @@ "dev": true }, "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", + "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", "dev": true, "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" + "acorn": "^5.6.0", + "acorn-jsx": "^4.1.1" } }, "esprima": { @@ -2018,30 +2037,9 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "event-stream": { - "version": "3.3.4", - "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true, - "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, "events": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz", "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", "dev": true }, @@ -2056,38 +2054,12 @@ } }, "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "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" - } - } + "is-posix-bracket": "^0.1.0" } }, "expand-range": { @@ -2097,102 +2069,8 @@ "dev": true, "requires": { "fill-range": "^2.1.0" - }, - "dependencies": { - "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dev": true, - "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } } }, - "express": { - "version": "4.16.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", - "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "array-flatten": "1.1.1", - "body-parser": "1.18.2", - "content-disposition": "0.5.2", - "content-type": "~1.0.4", - "cookie": "0.3.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.1.1", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.3", - "qs": "6.5.1", - "range-parser": "~1.2.0", - "safe-buffer": "5.1.1", - "send": "0.16.2", - "serve-static": "1.13.2", - "setprototypeof": "1.1.0", - "statuses": "~1.4.0", - "type-is": "~1.6.16", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", @@ -2215,79 +2093,23 @@ } }, "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", "dev": true, "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", "tmp": "^0.0.33" } }, "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "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" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "is-extglob": "^1.0.0" } }, "extract-zip": { @@ -2300,18 +2122,29 @@ "debug": "2.6.9", "mkdirp": "0.5.1", "yauzl": "2.4.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, "fast-json-stable-stringify": { @@ -2361,41 +2194,16 @@ "dev": true }, "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "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" - } - } - } - }, - "finalhandler": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.4.0", - "unpipe": "~1.0.0" + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" } }, "find-cache-dir": { @@ -2476,29 +2284,6 @@ "for-in": "^1.0.1" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "1.0.6", - "mime-types": "^2.1.12" - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true - }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -2508,18 +2293,6 @@ "map-cache": "^0.2.2" } }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -2530,19 +2303,6 @@ "readable-stream": "^2.0.0" } }, - "fs-extra": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", - "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -2574,27 +2334,27 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "resolved": false, "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "resolved": false, "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "resolved": false, "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "resolved": false, "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", "dev": true, "optional": true, @@ -2605,13 +2365,13 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "resolved": false, "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "resolved": false, "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { @@ -2621,39 +2381,39 @@ }, "chownr": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "resolved": false, "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "resolved": false, "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "resolved": false, "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "resolved": false, "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "resolved": false, "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "resolved": false, "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "optional": true, @@ -2663,28 +2423,28 @@ }, "deep-extend": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz", + "resolved": false, "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "resolved": false, "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "resolved": false, "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "resolved": false, "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, @@ -2694,14 +2454,14 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "resolved": false, "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "resolved": false, "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, @@ -2718,7 +2478,7 @@ }, "glob": { "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "resolved": false, "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "optional": true, @@ -2733,14 +2493,14 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "resolved": false, "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.21", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", + "resolved": false, "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", "dev": true, "optional": true, @@ -2750,7 +2510,7 @@ }, "ignore-walk": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "resolved": false, "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, @@ -2760,7 +2520,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "resolved": false, "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, @@ -2771,20 +2531,20 @@ }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "resolved": false, "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "ini": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "resolved": false, "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "resolved": false, "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { @@ -2793,14 +2553,14 @@ }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "resolved": false, "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "resolved": false, "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { @@ -2809,13 +2569,13 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": false, "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, "minipass": { "version": "2.2.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", + "resolved": false, "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", "dev": true, "requires": { @@ -2825,7 +2585,7 @@ }, "minizlib": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", + "resolved": false, "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", "dev": true, "optional": true, @@ -2835,7 +2595,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": false, "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { @@ -2844,14 +2604,14 @@ }, "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "resolved": false, "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true, "optional": true }, "needle": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.0.tgz", + "resolved": false, "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==", "dev": true, "optional": true, @@ -2863,7 +2623,7 @@ }, "node-pre-gyp": { "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz", + "resolved": false, "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==", "dev": true, "optional": true, @@ -2882,7 +2642,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "resolved": false, "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, @@ -2893,14 +2653,14 @@ }, "npm-bundled": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz", + "resolved": false, "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.1.10", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz", + "resolved": false, "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", "dev": true, "optional": true, @@ -2911,7 +2671,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "resolved": false, "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, @@ -2924,20 +2684,20 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "resolved": false, "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "resolved": false, "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "resolved": false, "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { @@ -2946,21 +2706,21 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": false, "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": false, "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "resolved": false, "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, @@ -2971,21 +2731,21 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": false, "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "resolved": false, "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true }, "rc": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz", + "resolved": false, "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", "dev": true, "optional": true, @@ -2998,7 +2758,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": false, "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true @@ -3007,7 +2767,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": false, "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, @@ -3023,7 +2783,7 @@ }, "rimraf": { "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "resolved": false, "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "optional": true, @@ -3033,48 +2793,48 @@ }, "safe-buffer": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "resolved": false, "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", "dev": true }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "resolved": false, "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "resolved": false, "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "resolved": false, "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "resolved": false, "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "resolved": false, "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "resolved": false, "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { @@ -3085,7 +2845,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "resolved": false, "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, @@ -3095,7 +2855,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": false, "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { @@ -3104,14 +2864,14 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "resolved": false, "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz", + "resolved": false, "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", "dev": true, "optional": true, @@ -3127,14 +2887,14 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "resolved": false, "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "resolved": false, "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", "dev": true, "optional": true, @@ -3144,13 +2904,13 @@ }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "resolved": false, "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "yallist": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "resolved": false, "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", "dev": true } @@ -3162,43 +2922,22 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "function-source": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/function-source/-/function-source-0.1.0.tgz", - "integrity": "sha1-2RBL8+RniLVUaMAr8bL6vPj8Ga8=", - "dev": true - }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -3217,59 +2956,21 @@ "requires": { "glob-parent": "^2.0.0", "is-glob": "^2.0.0" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } } }, "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } + "is-glob": "^2.0.0" } }, "globals": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", - "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz", + "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==", "dev": true }, "globalyzer": { @@ -3310,22 +3011,6 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", - "dev": true, - "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" - } - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -3335,21 +3020,18 @@ "function-bind": "^1.1.1" } }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -3359,6 +3041,14 @@ "get-value": "^2.0.6", "has-values": "^1.0.0", "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "has-values": { @@ -3371,6 +3061,26 @@ "kind-of": "^4.0.0" }, "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -3418,12 +3128,6 @@ "minimalistic-crypto-utils": "^1.0.1" } }, - "home-path": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/home-path/-/home-path-1.0.6.tgz", - "integrity": "sha512-wo+yjrdAtoXt43Vy92a+0IPCYViiyLAHyp0QVS4xL/tfvVz5sXIW1ubLZk3nhVkD92fQpUMKX+fzMjr5F489vw==", - "dev": true - }, "hosted-git-info": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", @@ -3444,39 +3148,37 @@ "uglify-js": "3.4.x" } }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "dev": true, + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" @@ -3495,9 +3197,9 @@ "dev": true }, "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, "imurmurhash": { @@ -3506,15 +3208,6 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", @@ -3537,40 +3230,27 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", + "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==", "dev": true, "requires": { "ansi-escapes": "^3.0.0", "chalk": "^2.0.0", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", - "external-editor": "^2.0.4", + "external-editor": "^3.0.0", "figures": "^2.0.0", - "lodash": "^4.3.0", + "lodash": "^4.17.10", "mute-stream": "0.0.7", "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", + "rxjs": "^6.1.0", "string-width": "^2.1.0", "strip-ansi": "^4.0.0", "through": "^2.3.6" } }, - "ipaddr.js": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", - "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=", - "dev": true - }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -3578,17 +3258,6 @@ "dev": true, "requires": { "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } } }, "is-arrayish": { @@ -3614,7 +3283,7 @@ }, "is-builtin-module": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { @@ -3634,17 +3303,6 @@ "dev": true, "requires": { "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } } }, "is-date-object": { @@ -3694,20 +3352,11 @@ "dev": true }, "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", "dev": true }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -3715,12 +3364,12 @@ "dev": true }, "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "is-extglob": "^1.0.0" } }, "is-module": { @@ -3730,23 +3379,12 @@ "dev": true }, "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } } }, "is-path-cwd": { @@ -3780,6 +3418,14 @@ "dev": true, "requires": { "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "is-posix-bracket": { @@ -3816,22 +3462,13 @@ "dev": true }, "is-symbol": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } }, "is-windows": { "version": "1.0.2", @@ -3852,21 +3489,18 @@ "dev": true }, "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } }, "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "js-yaml": { @@ -3879,35 +3513,16 @@ "esprima": "^4.0.0" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "json-stable-stringify-without-jsonify": { @@ -3916,70 +3531,31 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, "json5": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz", "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, - "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "keypress": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz", - "integrity": "sha1-SjGI1CkbZrT2XtuZ+AaqmuKTWSo=", - "dev": true - }, "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "graceful-fs": "^4.1.9" + "is-buffer": "^1.1.5" } }, "kleur": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-2.0.1.tgz", - "integrity": "sha512-Zq/jyANIJ2uX8UZjWlqLwbyhcxSXJtT/Y89lClyeZd3l++3ztL1I5SSCYrbcbwSunTjC88N3WuMk0kRDQD6gzA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-2.0.2.tgz", + "integrity": "sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==", "dev": true }, "levn": { @@ -3994,7 +3570,7 @@ }, "load-json-file": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { @@ -4005,9 +3581,9 @@ } }, "loader-runner": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", - "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz", + "integrity": "sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw==", "dev": true }, "loader-utils": { @@ -4040,9 +3616,9 @@ } }, "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "lodash.debounce": { @@ -4051,22 +3627,6 @@ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, - "long": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", - "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=", - "dev": true - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, "lower-case": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", @@ -4083,12 +3643,12 @@ } }, "magic-string": { - "version": "0.22.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", - "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz", + "integrity": "sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg==", "dev": true, "requires": { - "vlq": "^0.2.2" + "sourcemap-codec": "^1.4.1" } }, "make-dir": { @@ -4109,15 +3669,9 @@ } }, "make-error": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", - "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", - "dev": true - }, - "mamacro": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", - "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", "dev": true }, "map-cache": { @@ -4126,18 +3680,6 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -4147,15 +3689,6 @@ "object-visit": "^1.0.0" } }, - "matcher-collection": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/matcher-collection/-/matcher-collection-1.0.5.tgz", - "integrity": "sha512-nUCmzKipcJEwYsBVAFh5P+d7JBuhJaW1xs85Hara9xuMLqtCVUrW6DSC0JVIkluxEH2W45nPBM/wjHtBXa/tYA==", - "dev": true, - "requires": { - "minimatch": "^3.0.2" - } - }, "matchit": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/matchit/-/matchit-1.0.6.tgz", @@ -4172,21 +3705,16 @@ "dev": true }, "md5.js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", - "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dev": true, "requires": { "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" } }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -4203,117 +3731,25 @@ "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", "dev": true }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "dependencies": { - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - } - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" } }, "miller-rabin": { @@ -4327,26 +3763,11 @@ } }, "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", + "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", "dev": true }, - "mime-db": { - "version": "1.35.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", - "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==", - "dev": true - }, - "mime-types": { - "version": "2.1.19", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", - "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", - "dev": true, - "requires": { - "mime-db": "~1.35.0" - } - }, "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", @@ -4376,30 +3797,10 @@ }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, - "minstache": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minstache/-/minstache-1.2.0.tgz", - "integrity": "sha1-/xzEA6woRPaNvxjGYhKb5+sO/EE=", - "dev": true, - "requires": { - "commander": "1.0.4" - }, - "dependencies": { - "commander": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/commander/-/commander-1.0.4.tgz", - "integrity": "sha1-Xt6xruI8T7VBprcNaSq+8ZZpotM=", - "dev": true, - "requires": { - "keypress": "0.1.x" - } - } - } - }, "mississippi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", @@ -4416,24 +3817,6 @@ "pumpify": "^1.3.3", "stream-each": "^1.1.0", "through2": "^2.0.0" - }, - "dependencies": { - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } } }, "mixin-deep": { @@ -4459,7 +3842,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { @@ -4487,7 +3870,7 @@ "dependencies": { "commander": { "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", "dev": true }, @@ -4500,6 +3883,26 @@ "ms": "2.0.0" } }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", @@ -4532,20 +3935,11 @@ "dev": true }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, - "multiline": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/multiline/-/multiline-1.0.2.tgz", - "integrity": "sha1-abHyX/B00oKJBPJE3dBrfZbvbJM=", - "dev": true, - "requires": { - "strip-indent": "^1.0.0" - } - }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -4553,9 +3947,9 @@ "dev": true }, "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", "dev": true, "optional": true }, @@ -4576,6 +3970,26 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } } }, "natural-compare": { @@ -4584,46 +3998,18 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - }, "neo-async": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.2.tgz", - "integrity": "sha512-vdqTKI9GBIYcAEbFAcpKPErKINfPF5zIuz3/niBfq8WUZjpT2tytLlFVrBgWdOtqI4uaA/Rb6No0hux39XXDuw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", + "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", "dev": true }, "nice-try": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", - "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "nightmare": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/nightmare/-/nightmare-3.0.1.tgz", - "integrity": "sha512-WptvyPfp5mHRRYHzt6+4xazaR9cc437BuLJI6cLFnqwwgxgdtsFImfBVDeTUCPAeLrkp5VryX5jlw7Wwg+UnFQ==", - "dev": true, - "requires": { - "debug": "^2.2.0", - "deep-defaults": "^1.0.3", - "defaults": "^1.0.2", - "electron": "^1.8.4", - "enqueue": "^1.0.2", - "function-source": "^0.1.0", - "jsesc": "^0.5.0", - "minstache": "^1.2.0", - "mkdirp": "^0.5.1", - "multiline": "^1.0.2", - "once": "^1.3.3", - "rimraf": "^2.4.3", - "sliced": "1.0.1", - "split2": "^2.0.1" - } - }, "no-case": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", @@ -4667,6 +4053,14 @@ "url": "^0.11.0", "util": "^0.10.3", "vm-browserify": "0.0.4" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } } }, "normalize-package-data": { @@ -4691,44 +4085,22 @@ } }, "npm-run-all": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.3.tgz", - "integrity": "sha512-aOG0N3Eo/WW+q6sUIdzcV2COS8VnTZCmdji0VQIAZF3b+a3YWb0AD0vFIyjKec18A7beLGbaQ5jFTNI2bPt9Cg==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.4", + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", "memorystream": "^0.3.1", "minimatch": "^3.0.4", - "ps-tree": "^1.1.0", + "pidtree": "^0.3.0", "read-pkg": "^3.0.0", "shell-quote": "^1.6.1", "string.prototype.padend": "^3.0.0" }, "dependencies": { - "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" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -4779,51 +4151,6 @@ } } }, - "nugget": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/nugget/-/nugget-2.0.1.tgz", - "integrity": "sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=", - "dev": true, - "requires": { - "debug": "^2.1.3", - "minimist": "^1.1.0", - "pretty-bytes": "^1.0.2", - "progress-stream": "^1.1.0", - "request": "^2.45.0", - "single-line-log": "^1.1.2", - "throttleit": "0.0.2" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "pretty-bytes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", - "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.1.0" - } - } - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4849,22 +4176,13 @@ "requires": { "is-descriptor": "^0.1.0" } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } } } }, "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", "dev": true }, "object-visit": { @@ -4874,6 +4192,14 @@ "dev": true, "requires": { "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, "object.omit": { @@ -4893,23 +4219,16 @@ "dev": true, "requires": { "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", - "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", - "dev": true - }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5014,7 +4333,7 @@ }, "parse-asn1": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", "dev": true, "requires": { @@ -5035,23 +4354,6 @@ "is-dotfile": "^1.0.0", "is-extglob": "^1.0.0", "is-glob": "^2.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } } }, "parse-json": { @@ -5063,18 +4365,6 @@ "error-ex": "^1.2.0" } }, - "parse-ms": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-1.0.1.tgz", - "integrity": "sha1-VjRtR0nXjyNDDKDHE4UK75GqNh0=", - "dev": true - }, - "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", - "dev": true - }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -5126,12 +4416,6 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", @@ -5141,19 +4425,10 @@ "pify": "^2.0.0" } }, - "pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "requires": { - "through": "~2.3" - } - }, "pbkdf2": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", - "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", "dev": true, "requires": { "create-hash": "^1.1.2", @@ -5169,10 +4444,10 @@ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", "dev": true }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "pidtree": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.0.tgz", + "integrity": "sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==", "dev": true }, "pify": { @@ -5212,13 +4487,13 @@ "dev": true }, "polka": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/polka/-/polka-0.4.0.tgz", - "integrity": "sha1-RT/FE81TCgid1V2P89rql1LxYd8=", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/polka/-/polka-0.5.1.tgz", + "integrity": "sha512-de0VgqoAgGIJoa4mTj+e9KKIt5uRJOGyE37TbsoYEuDzI+cbJZ8nKBRCmiwv9DUMKrYhAMHW/di7/6/65zgZZQ==", "dev": true, "requires": { - "parseurl": "^1.3.2", - "trouter": "^1.1.0" + "@polka/url": "^0.5.0", + "trouter": "^2.0.1" } }, "port-authority": { @@ -5251,15 +4526,6 @@ "integrity": "sha512-wa5+qGVg9Yt7PB6rYm3kXlKzgzgivYTLRandezh43jjRqgyDyP+9YxfJpJiLs9yKD1WeU8/OvtToWpW7255FtA==", "dev": true }, - "pretty-ms": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-3.2.0.tgz", - "integrity": "sha512-ZypexbfVUGTFxb0v+m1bUyy92DHe5SyYlnyY0msyms5zd3RwyvNgyxZZsXXgoyzlxjx5MiqtXUdhUfvQbe0A2Q==", - "dev": true, - "requires": { - "parse-ms": "^1.0.0" - } - }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -5278,31 +4544,17 @@ "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", "dev": true }, - "progress-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", - "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", - "dev": true, - "requires": { - "speedometer": "~0.1.2", - "through2": "~0.2.3" - } - }, "promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, - "proxy-addr": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", - "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", - "dev": true, - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.8.0" - } + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", + "dev": true }, "prr": { "version": "1.0.1", @@ -5310,38 +4562,24 @@ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", "dev": true }, - "ps-tree": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz", - "integrity": "sha1-tCGyQUDWID8e08dplrRCewjowBQ=", - "dev": true, - "requires": { - "event-stream": "~3.3.0" - } - }, "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.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", - "dev": true - }, "public-encrypt": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", - "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", "dev": true, "requires": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1" + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" } }, "pump": { @@ -5366,16 +4604,37 @@ } }, "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", - "dev": true + "puppeteer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.9.0.tgz", + "integrity": "sha512-GH4PmhJf9wBRAPvtJkEJLAvdNNOofZortmBZSj8cGWYni98GUFqsf66blOEfJbo5B8l0KG5HR2d/W2MejnUrzg==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "extract-zip": "^1.6.6", + "https-proxy-agent": "^2.2.1", + "mime": "^2.0.3", + "progress": "^2.0.0", + "proxy-from-env": "^1.0.0", + "rimraf": "^2.6.1", + "ws": "^5.1.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } }, "querystring": { "version": "0.2.0", @@ -5389,12 +4648,6 @@ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true }, - "querystringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz", - "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==", - "dev": true - }, "randomatic": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", @@ -5411,6 +4664,12 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, @@ -5433,76 +4692,6 @@ "safe-buffer": "^5.1.0" } }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true - }, - "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "unpipe": "1.0.0" - }, - "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", - "dev": true, - "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": ">= 1.3.1 < 2" - } - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true - }, - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", - "dev": true - } - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -5537,7 +4726,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -5551,25 +4740,305 @@ } }, "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "readable-stream": "^2.0.2", - "set-immediate-shim": "^1.0.1" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "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" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "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" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "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==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "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" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "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" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "regex-cache": { @@ -5592,9 +5061,9 @@ } }, "regexpp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", - "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, "relateurl": { @@ -5620,51 +5089,6 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - } - } - }, "require-relative": { "version": "0.8.7", "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", @@ -5681,12 +5105,6 @@ "resolve-from": "^1.0.0" } }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, "resolve": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", @@ -5744,9 +5162,9 @@ } }, "rollup": { - "version": "0.59.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.59.4.tgz", - "integrity": "sha512-ISiMqq/aJa+57QxX2MRcvLESHdJ7wSavmr6U1euMr+6UgFe6KM+3QANrYy8LQofwhTC1I7BcAdlLnDiaODs1BA==", + "version": "0.66.6", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.66.6.tgz", + "integrity": "sha512-J7/SWanrcb83vfIHqa8+aVVGzy457GcjA6GVZEnD0x2u4OnOd0Q1pCrEoNe8yLwM6z6LZP02zBT2uW0yh5TqOw==", "dev": true, "requires": { "@types/estree": "0.0.39", @@ -5754,30 +5172,30 @@ } }, "rollup-plugin-commonjs": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.1.5.tgz", - "integrity": "sha512-Hy7KbvsSMNu6aCO2xabp8gBcWrTiS+EzfHkzWwZwMjrcAYuYfCLU7fP1nM4xM0FMye/13r8mzTkfb9AmDaZ1hQ==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.2.0.tgz", + "integrity": "sha512-0RM5U4Vd6iHjL6rLvr3lKBwnPsaVml+qxOGaaNUWN1lSq6S33KhITOfHmvxV3z2vy9Mk4t0g4rNlVaJJsNQPWA==", "dev": true, "requires": { - "estree-walker": "^0.5.1", - "magic-string": "^0.22.4", - "resolve": "^1.5.0", - "rollup-pluginutils": "^2.0.1" + "estree-walker": "^0.5.2", + "magic-string": "^0.25.1", + "resolve": "^1.8.1", + "rollup-pluginutils": "^2.3.3" } }, "rollup-plugin-json": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-3.0.0.tgz", - "integrity": "sha512-WUAV9/I/uFWvHhyRTqFb+3SIapjISFJS7R1xN/cXxWESrfYo9I8ncHI7AxJHflKRXhBVSv7revBVJh2wvhWh5w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-3.1.0.tgz", + "integrity": "sha512-BlYk5VspvGpjz7lAwArVzBXR60JK+4EKtPkCHouAWg39obk9S61hZYJDBfMK+oitPdoe11i69TlxKlMQNFC/Uw==", "dev": true, "requires": { - "rollup-pluginutils": "^2.2.0" + "rollup-pluginutils": "^2.3.1" } }, "rollup-plugin-node-resolve": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.3.0.tgz", - "integrity": "sha512-9zHGr3oUJq6G+X0oRMYlzid9fXicBdiydhwGChdyeNRGPcN/majtegApRKHLR5drboUvEWU+QeUmGTyEZQs3WA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.4.0.tgz", + "integrity": "sha512-PJcd85dxfSBWih84ozRtBkB731OjXk0KnzN0oGp7WOWcarAFkVa71cV5hTJg2qpVsV2U8EUwrzHP3tvy9vS3qg==", "dev": true, "requires": { "builtin-modules": "^2.0.0", @@ -5793,6 +5211,17 @@ } } }, + "rollup-plugin-replace": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-replace/-/rollup-plugin-replace-2.1.0.tgz", + "integrity": "sha512-SxrAIgpH/B5/W4SeULgreOemxcpEgKs2gcD42zXw50bhqGWmcnlXneVInQpAqzA/cIly4bJrOpeelmB9p4YXSQ==", + "dev": true, + "requires": { + "magic-string": "^0.25.1", + "minimatch": "^3.0.2", + "rollup-pluginutils": "^2.0.1" + } + }, "rollup-plugin-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/rollup-plugin-string/-/rollup-plugin-string-2.0.2.tgz", @@ -5810,7 +5239,7 @@ }, "rollup-pluginutils": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz", "integrity": "sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg=", "dev": true, "requires": { @@ -5820,142 +5249,41 @@ } } }, + "rollup-plugin-svelte": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-4.3.2.tgz", + "integrity": "sha512-aGFuB+hc9c5pmPCgnXiJCbRwrDw7sdPia+WBRKTMEwVv3ygiSOi5gIlGHIPRMvMisioOk0ns5Bu5Gz57JxEZTg==", + "dev": true, + "requires": { + "require-relative": "^0.8.7", + "rollup-pluginutils": "^2.3.0", + "sourcemap-codec": "^1.4.1" + } + }, "rollup-plugin-typescript": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-typescript/-/rollup-plugin-typescript-0.8.1.tgz", - "integrity": "sha1-L/fuzCHPa7K0P8J+W2iJUs5xkko=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-typescript/-/rollup-plugin-typescript-1.0.0.tgz", + "integrity": "sha512-d2KDNMJXgaaB//dDGd/YmyMiopt1Pz965Iu3zmEoL08YqNcKRBz26uHqqc47rFGfrJV5kFqifC9IYlh6dpSCLg==", "dev": true, "requires": { - "compare-versions": "2.0.1", - "object-assign": "^4.0.1", - "rollup-pluginutils": "^1.3.1", - "tippex": "^2.1.1", - "typescript": "^1.8.9" - }, - "dependencies": { - "estree-walker": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.2.1.tgz", - "integrity": "sha1-va/oCVOD2EFNXcLs9MkXO225QS4=", - "dev": true - }, - "rollup-pluginutils": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz", - "integrity": "sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg=", - "dev": true, - "requires": { - "estree-walker": "^0.2.1", - "minimatch": "^3.0.2" - } - }, - "typescript": { - "version": "1.8.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-1.8.10.tgz", - "integrity": "sha1-tHXW4N/wv1DyluXKbvn7tccyDx4=", - "dev": true - } + "resolve": "^1.8.1", + "rollup-pluginutils": "^2.3.1" } }, + "rollup-plugin-virtual": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-virtual/-/rollup-plugin-virtual-1.0.1.tgz", + "integrity": "sha512-HCTBpV8MwP5lNzZrHD2moVxHIToHU1EkzkKGVj6Z0DcgUfxrxrZmeQirQeLz2yhnkJqRjwiVywK9CS8jDYakrw==", + "dev": true + }, "rollup-pluginutils": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.3.1.tgz", - "integrity": "sha512-JZS8aJMHEHhqmY2QVPMXwKP6lsD1ShkrcGYjhAIvqKKdXQyPHw/9NF0tl3On/xOJ4ACkxfeG7AF+chfCN1NpBg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.3.3.tgz", + "integrity": "sha512-2XZwja7b6P5q4RZ5FhyX1+f46xi1Z3qBKigLRZ6VTZjwbN0K1IFGMlwm06Uu0Emcre2Z63l77nq/pzn+KxIEoA==", "dev": true, "requires": { "estree-walker": "^0.5.2", "micromatch": "^2.3.11" - }, - "dependencies": { - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - } - } } }, "run-async": { @@ -5976,19 +5304,13 @@ "aproba": "^1.1.1" } }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", "dev": true, "requires": { - "rx-lite": "*" + "tslib": "^1.9.0" } }, "sade": { @@ -6041,91 +5363,20 @@ "requires": { "ajv": "^6.1.0", "ajv-keywords": "^3.1.0" - }, - "dependencies": { - "ajv": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", - "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", - "dev": true - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - } } }, "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" - } - }, "serialize-javascript": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", "dev": true }, - "serve-static": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.2", - "send": "0.16.2" - } - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", @@ -6155,15 +5406,9 @@ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", "dev": true }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, "sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { @@ -6198,50 +5443,26 @@ "jsonify": "~0.0.0" } }, + "shimport": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/shimport/-/shimport-0.0.11.tgz", + "integrity": "sha512-wRlG/wMuV/czrzJEWBUPjydU/Ve0kTrTH8wHLRjuY6S2BDB+qDDXkTY/WrNc/7t5jnd0LPVO1sRIE7Ga6uXTpw==" + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, - "single-line-log": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz", - "integrity": "sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=", + "sirv": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-0.2.2.tgz", + "integrity": "sha512-X0UjfTc32MeK+rkhgdQK/blQ5ysC0CfLF9OH9d8x2RnpaD2D5BDLMeox79utmhxai4T+/VCahK5pDgAEnG/tNQ==", "dev": true, "requires": { - "string-width": "^1.0.1" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } + "@polka/url": "^0.5.0", + "mime": "^2.3.1", + "tiny-glob": "^0.2.0" } }, "slice-ansi": { @@ -6253,12 +5474,6 @@ "is-fullwidth-code-point": "^2.0.0" } }, - "sliced": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", - "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=", - "dev": true - }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -6275,6 +5490,15 @@ "use": "^3.1.0" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", @@ -6292,6 +5516,18 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "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 } } }, @@ -6343,6 +5579,18 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, @@ -6353,30 +5601,18 @@ "dev": true, "requires": { "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } } }, "source-list-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", "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 + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-resolve": { "version": "0.5.2", @@ -6392,19 +5628,12 @@ } }, "source-map-support": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.8.tgz", - "integrity": "sha512-WqAEWPdb78u25RfKzOF0swBpY0dKrNdjc4GvLwm7ScX/o9bj8Eh/YL8mcMhBHYDGl87UkkSXDOFnW4G7GhWhGg==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } } }, "source-map-url": { @@ -6413,10 +5642,15 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, + "sourcemap-codec": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.3.tgz", + "integrity": "sha512-vFrY/x/NdsD7Yc8mpTJXuao9S8lq08Z/kOITHz6b7YbfI9xL8Spe5EvSQUHOI7SbpY8bRPr0U3kKSsPuqEGSfA==" + }, "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -6424,9 +5658,9 @@ } }, "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, "spdx-expression-parse": { @@ -6440,26 +5674,11 @@ } }, "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", + "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==", "dev": true }, - "speedometer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", - "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=", - "dev": true - }, - "split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true, - "requires": { - "through": "2" - } - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -6469,56 +5688,12 @@ "extend-shallow": "^3.0.0" } }, - "split2": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", - "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", - "dev": true, - "requires": { - "through2": "^2.0.2" - }, - "dependencies": { - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "sshpk": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, "ssri": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", @@ -6549,12 +5724,6 @@ } } }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true - }, "stream-browserify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", @@ -6565,15 +5734,6 @@ "readable-stream": "^2.0.2" } }, - "stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "requires": { - "duplexer": "~0.1.1" - } - }, "stream-each": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", @@ -6595,14 +5755,6 @@ "readable-stream": "^2.3.6", "to-arraybuffer": "^1.0.0", "xtend": "^4.0.0" - }, - "dependencies": { - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } } }, "stream-shift": { @@ -6611,6 +5763,11 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, + "string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=" + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -6648,14 +5805,6 @@ "dev": true, "requires": { "ansi-regex": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - } } }, "strip-bom": { @@ -6664,41 +5813,25 @@ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } - }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, - "sumchecker": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-1.3.1.tgz", - "integrity": "sha1-ebs7RFbdBPGOvbwNcDodHa7FEF0=", + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "debug": "^2.2.0", - "es6-promise": "^4.0.5" + "has-flag": "^3.0.0" } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, "svelte": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-2.11.0.tgz", - "integrity": "sha512-lIgtxDkGzLNppVNRtn+t2GZzyumxQj6f/Ola+z7fT6bmisTUxKTFf3wUzOwNcYkQWNIOk2/NkzIa/UO4JQO/bg==", + "version": "2.13.5", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-2.13.5.tgz", + "integrity": "sha512-Mg4+vRwAT1IMR4FAH3cOmMaVVrJ35xUI1qsTW+WoJvRpeBDx7aLZUbgBXnctxdfEJQ4BuP2MCuhYKy8917Au1A==", "dev": true }, "svelte-dev-helper": { @@ -6708,33 +5841,32 @@ "dev": true }, "svelte-loader": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/svelte-loader/-/svelte-loader-2.10.1.tgz", - "integrity": "sha512-Kua8LHwjrHPEGgFUycPo4pg17vzcBu1ptm/2OR/mZfnR1tk1YRMhyoQGvS15Zr36VwRCPPgDYYVYT3peWVseAw==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/svelte-loader/-/svelte-loader-2.11.0.tgz", + "integrity": "sha512-+Q24lBhQ8KGB9flHNXjKqq9TJEIcT3VJlzsxhijqrJ9feK9bUG3TLDlosceoAXvOsjxuaHKN1ZveUbbX7J7zUQ==", "dev": true, "requires": { "loader-utils": "^1.1.0", - "svelte-dev-helper": "^1.1.7" + "require-relative": "^0.8.7", + "svelte-dev-helper": "^1.1.9" } }, "table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/table/-/table-5.1.0.tgz", + "integrity": "sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg==", "dev": true, "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", + "ajv": "^6.5.3", + "lodash": "^4.17.10", "slice-ansi": "1.0.0", "string-width": "^2.1.1" } }, "tapable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", - "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.0.tgz", + "integrity": "sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA==", "dev": true }, "text-table": { @@ -6743,52 +5875,20 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "throttleit": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", - "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", - "dev": true - }, "through": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, "through2": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", - "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "~1.1.9", - "xtend": "~2.1.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" } }, "timers-browserify": { @@ -6810,12 +5910,6 @@ "globrex": "^0.1.1" } }, - "tippex": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tippex/-/tippex-2.3.1.tgz", - "integrity": "sha1-ov1bcIfXy/sgyYBqbBYQjCwPr9o=", - "dev": true - }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -6838,17 +5932,6 @@ "dev": true, "requires": { "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } } }, "to-regex": { @@ -6871,28 +5954,23 @@ "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + } } }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, "trouter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/trouter/-/trouter-1.1.0.tgz", - "integrity": "sha512-EH5irPolH2hPRpgH77V8ZDS3T05oMFJ7Pcq0Vn5Dlzol4xKLhjOe4ftWnnDnHmTFzPUgUF//H6xyjv5dYAE6Kg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/trouter/-/trouter-2.0.1.tgz", + "integrity": "sha512-kr8SKKw94OI+xTGOkfsvwZQ8mWoikZDd2n8XZHjJVZUARZT+4/VV6cacRS6CLsH9bNm+HFIPU1Zx4CnNnb4qlQ==", "dev": true, "requires": { "matchit": "^1.0.0" @@ -6916,7 +5994,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -6933,22 +6011,6 @@ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true - }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -6958,16 +6020,6 @@ "prelude-ls": "~1.1.2" } }, - "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.18" - } - }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -6975,30 +6027,18 @@ "dev": true }, "typescript": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", - "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.3.tgz", + "integrity": "sha512-+81MUSyX+BaSo+u2RbozuQk/UWx6hfG0a5gHu4ANEM4sU96XbuIyAB+rWBW1u70c6a5QuZfuYICn3s2UjuHUpA==", "dev": true }, "uglify-js": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.7.tgz", - "integrity": "sha512-J0M2i1mQA+ze3EdN9SBi751DNdAXmeFLfJrd/MDIkRc3G3Gbb9OPVSx7GIQvVwfWxQARcYV2DTxIkMyDAk3o9Q==", + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", "requires": { - "commander": "~2.16.0", + "commander": "~2.17.1", "source-map": "~0.6.1" - }, - "dependencies": { - "commander": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz", - "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } } }, "uglifyjs-webpack-plugin": { @@ -7023,12 +6063,6 @@ "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", "dev": true }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, "uglify-es": { "version": "3.3.9", "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", @@ -7077,29 +6111,23 @@ } }, "unique-filename": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", - "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", "dev": true, "requires": { "unique-slug": "^2.0.0" } }, "unique-slug": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", - "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", + "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", "dev": true, "requires": { "imurmurhash": "^0.1.4" } }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -7137,6 +6165,12 @@ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true } } }, @@ -7158,14 +6192,6 @@ "dev": true, "requires": { "punycode": "^2.1.0" - }, - "dependencies": { - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - } } }, "urix": { @@ -7192,16 +6218,6 @@ } } }, - "url-parse": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz", - "integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==", - "dev": true, - "requires": { - "querystringify": "^2.0.0", - "requires-port": "^1.0.0" - } - }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -7223,18 +6239,6 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -7245,29 +6249,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "vlq": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", - "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", - "dev": true - }, "vm-browserify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", @@ -7277,16 +6258,6 @@ "indexof": "0.0.1" } }, - "walk-sync": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/walk-sync/-/walk-sync-0.3.3.tgz", - "integrity": "sha512-jQgTHmCazUngGqvHZFlr30u2VLKEKErBMLFe+fBl5mn4rh9aI/QVRog8PT1hv2vaOu4EBwigfmpRTyZrbnpRVA==", - "dev": true, - "requires": { - "ensure-posix-path": "^1.0.0", - "matcher-collection": "^1.0.0" - } - }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", @@ -7299,16 +6270,15 @@ } }, "webpack": { - "version": "4.16.5", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.16.5.tgz", - "integrity": "sha512-i5cHYHonzSc1zBuwB5MSzW4v9cScZFbprkHK8ZgzPDCRkQXGGpYzPmJhbus5bOrZ0tXTcQp+xyImRSvKb0b+Kw==", + "version": "4.20.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.20.2.tgz", + "integrity": "sha512-75WFUMblcWYcocjSLlXCb71QuGyH7egdBZu50FtBGl2Nso8CK3Ej+J7bTZz2FPFq5l6fzCisD9modB7t30ikuA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-module-context": "1.5.13", - "@webassemblyjs/wasm-edit": "1.5.13", - "@webassemblyjs/wasm-opt": "1.5.13", - "@webassemblyjs/wasm-parser": "1.5.13", + "@webassemblyjs/ast": "1.7.8", + "@webassemblyjs/helper-module-context": "1.7.8", + "@webassemblyjs/wasm-edit": "1.7.8", + "@webassemblyjs/wasm-parser": "1.7.8", "acorn": "^5.6.2", "acorn-dynamic-import": "^3.0.0", "ajv": "^6.1.0", @@ -7325,50 +6295,299 @@ "neo-async": "^2.5.0", "node-libs-browser": "^2.0.0", "schema-utils": "^0.4.4", - "tapable": "^1.0.0", + "tapable": "^1.1.0", "uglifyjs-webpack-plugin": "^1.2.4", "watchpack": "^1.5.0", - "webpack-sources": "^1.0.1" + "webpack-sources": "^1.3.0" }, "dependencies": { - "ajv": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", - "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", - "dev": true - }, - "eslint-scope": { + "arr-diff": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "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" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "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" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "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==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "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" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "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" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true } } @@ -7383,21 +6602,13 @@ } }, "webpack-sources": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", - "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", + "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", "dev": true, "requires": { "source-list-map": "^2.0.0", "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "which": { @@ -7439,15 +6650,21 @@ "mkdirp": "^0.5.1" } }, - "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", "dev": true, "requires": { - "object-keys": "~0.4.0" + "async-limiter": "~1.0.0" } }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", @@ -7476,9 +6693,9 @@ "dev": true }, "yootils": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/yootils/-/yootils-0.0.11.tgz", - "integrity": "sha512-RyIMvxBJ9JYGQXwJCq1Co4XvDgkfri7SNv0Gq4RZnlFpYDwMe3+xLDOjf9c4drHyisw88i+t9bB0h69962vAMA==", + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/yootils/-/yootils-0.0.14.tgz", + "integrity": "sha512-yWoA/a/4aVUp5nqfqdjbTdyXcR8d0OAbRQ8Ktu3ZsfQnArwLpS81oqZl3adIszX3p8NEhT0aNHARPsaTwBH/Qw==", "dev": true } } diff --git a/package.json b/package.json index b3951aa..d8878dc 100644 --- a/package.json +++ b/package.json @@ -1,81 +1,79 @@ { "name": "sapper", - "version": "0.17.0", + "version": "0.24.3", "description": "Military-grade apps, engineered by Svelte", - "main": "dist/middleware.ts.js", "bin": { "sapper": "./sapper" }, "files": [ "*.js", - "*.ts.js", - "runtime", "webpack", + "config", "sapper", - "components", - "dist" + "dist/*.js", + "templates/*.js" ], "directories": { "test": "test" }, "dependencies": { - "html-minifier": "^3.5.16", - "source-map-support": "^0.5.6", - "tslib": "^1.9.1" + "html-minifier": "^3.5.20", + "shimport": "0.0.11", + "source-map-support": "^0.5.9", + "sourcemap-codec": "^1.4.3", + "string-hash": "^1.1.3", + "tslib": "^1.9.3" }, "devDependencies": { - "@types/glob": "^5.0.34", "@types/mkdirp": "^0.5.2", "@types/mocha": "^5.2.5", - "@types/node": "^10.7.1", + "@types/node": "^10.12.0", + "@types/puppeteer": "^1.9.0", "@types/rimraf": "^2.0.2", - "cheap-watch": "^0.3.0", - "compression": "^1.7.1", + "agadoo": "^1.0.1", + "cheap-watch": "^1.0.0", "cookie": "^0.3.1", "devalue": "^1.0.4", - "eslint": "^4.13.1", - "eslint-plugin-import": "^2.12.0", - "express": "^4.16.3", - "kleur": "^2.0.1", + "eslint": "^5.7.0", + "eslint-plugin-import": "^2.14.0", + "kleur": "^2.0.2", "mkdirp": "^0.5.1", "mocha": "^5.2.0", - "nightmare": "^3.0.0", - "node-fetch": "^2.1.1", - "npm-run-all": "^4.1.3", - "polka": "^0.4.0", + "node-fetch": "^2.2.0", + "npm-run-all": "^4.1.5", + "polka": "^0.5.1", "port-authority": "^1.0.5", - "pretty-bytes": "^5.0.0", - "pretty-ms": "^3.1.0", + "pretty-bytes": "^5.1.0", + "puppeteer": "^1.9.0", "require-relative": "^0.8.7", "rimraf": "^2.6.2", - "rollup": "^0.59.2", - "rollup-plugin-commonjs": "^9.1.3", - "rollup-plugin-json": "^3.0.0", - "rollup-plugin-node-resolve": "^3.3.0", + "rollup": "^0.66.6", + "rollup-plugin-commonjs": "^9.2.0", + "rollup-plugin-json": "^3.1.0", + "rollup-plugin-node-resolve": "^3.4.0", + "rollup-plugin-replace": "^2.1.0", "rollup-plugin-string": "^2.0.2", - "rollup-plugin-typescript": "^0.8.1", + "rollup-plugin-svelte": "^4.3.2", + "rollup-plugin-typescript": "^1.0.0", "sade": "^1.4.1", "sander": "^0.6.0", - "serve-static": "^1.13.2", - "svelte": "^2.6.3", - "svelte-loader": "^2.9.0", - "tiny-glob": "^0.2.2", + "sirv": "^0.2.2", + "svelte": "^2.13.5", + "svelte-loader": "^2.11.0", "ts-node": "^7.0.1", - "typescript": "^2.8.3", - "url-parse": "^1.2.0", - "walk-sync": "^0.3.2", - "webpack": "^4.8.3", - "webpack-format-messages": "^2.0.1", - "yootils": "0.0.11" + "typescript": "^3.1.3", + "webpack": "^4.20.2", + "webpack-format-messages": "^2.0.3", + "yootils": "0.0.14" }, "scripts": { - "cy:open": "cypress open", "test": "mocha --opts mocha.opts", "pretest": "npm run build", "build": "rm -rf dist && rollup -c", + "prepare": "npm run build", "dev": "rollup -cw", "prepublishOnly": "npm test", - "update_mime_types": "curl http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types | grep -e \"^[^#]\" > src/middleware/mime-types.md" + "update_mime_types": "curl http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types | grep -e \"^[^#]\" > templates/src/server/middleware/mime-types.md" }, "repository": "https://github.com/sveltejs/sapper", "keywords": [ diff --git a/rollup.config.js b/rollup.config.js index 51f1499..7e13cd6 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -4,6 +4,7 @@ import json from 'rollup-plugin-json'; import resolve from 'rollup-plugin-node-resolve'; import commonjs from 'rollup-plugin-commonjs'; import pkg from './package.json'; +import { builtinModules } from 'module'; const external = [].concat( Object.keys(pkg.dependencies), @@ -11,28 +12,39 @@ const external = [].concat( 'sapper/core.js' ); -export default [ - { - input: `src/runtime/index.ts`, +function template(kind, external, target) { + return { + input: `templates/src/${kind}/index.ts`, output: { - file: `runtime.js`, + file: `templates/${kind}.js`, format: 'es' }, + external, plugins: [ + resolve(), + commonjs(), + string({ + include: '**/*.md' + }), typescript({ typescript: require('typescript'), - target: "ES2017" + target }) ] - }, + }; +} + +export default [ + template('client', ['__ROOT__', '__ERROR__'], 'ES2017'), + template('server', builtinModules, 'ES2015'), { input: [ `src/api.ts`, `src/cli.ts`, `src/core.ts`, - `src/middleware.ts`, - `src/webpack.ts` + `src/config/rollup.ts`, + `src/config/webpack.ts` ], output: { dir: 'dist', @@ -41,9 +53,6 @@ export default [ }, external, plugins: [ - string({ - include: '**/*.md' - }), json(), resolve(), commonjs(), @@ -51,7 +60,6 @@ export default [ typescript: require('typescript') }) ], - experimentalCodeSplitting: true, - experimentalDynamicImport: true + experimentalCodeSplitting: true } ]; \ No newline at end of file diff --git a/runtime/README.md b/runtime/README.md deleted file mode 100644 index 7b650d6..0000000 --- a/runtime/README.md +++ /dev/null @@ -1 +0,0 @@ -This directory exists for legacy reasons and should be deleted before releasing version 1. \ No newline at end of file diff --git a/runtime/app.js b/runtime/app.js deleted file mode 100644 index 43ebb81..0000000 --- a/runtime/app.js +++ /dev/null @@ -1,2 +0,0 @@ -console.error('sapper/runtime/app.js has been deprecated in favour of sapper/runtime.js'); -export * from '../runtime.js'; \ No newline at end of file diff --git a/sapper b/sapper index 72c1eca..e6f3430 100755 --- a/sapper +++ b/sapper @@ -1,2 +1,2 @@ #!/usr/bin/env node -require('./dist/cli.ts.js'); \ No newline at end of file +require('./dist/cli.js'); \ No newline at end of file diff --git a/sapper-dev-client.js b/sapper-dev-client.js index b717a25..e5c0035 100644 --- a/sapper-dev-client.js +++ b/sapper-dev-client.js @@ -1,6 +1,8 @@ let source; function check() { + if (typeof module === 'undefined') return; + if (module.hot.status() === 'idle') { module.hot.check(true).then(modules => { console.log(`[SAPPER] applied HMR update`); diff --git a/src/api.ts b/src/api.ts index b8cee72..d90cdfd 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,6 +1,4 @@ -import { dev } from './api/dev'; -import { build } from './api/build'; -import { exporter } from './api/export'; -import { find_page } from './api/find_page'; - -export { dev, build, exporter, find_page }; \ No newline at end of file +export { dev } from './api/dev'; +export { build } from './api/build'; +export { export } from './api/export'; +export { find_page } from './api/find_page'; \ No newline at end of file diff --git a/src/api/build.ts b/src/api/build.ts index 2330a8e..c8287d6 100644 --- a/src/api/build.ts +++ b/src/api/build.ts @@ -2,40 +2,58 @@ import * as fs from 'fs'; import * as path from 'path'; import mkdirp from 'mkdirp'; import rimraf from 'rimraf'; -import { EventEmitter } from 'events'; import minify_html from './utils/minify_html'; -import { create_compilers, create_main_manifests, create_routes, create_serviceworker_manifest } from '../core'; -import * as events from './interfaces'; +import { create_compilers, create_main_manifests, create_manifest_data, create_serviceworker_manifest } from '../core'; +import { copy_shimport } from './utils/copy_shimport'; +import read_template from '../core/read_template'; +import { CompileResult } from '../core/create_compilers/interfaces'; +import { noop } from './utils/noop'; +import validate_bundler from './utils/validate_bundler'; -export function build(opts: {}) { - const emitter = new EventEmitter(); +type Opts = { + cwd?: string; + src?: string; + routes?: string; + dest?: string; + output?: string; + static?: string; + legacy?: boolean; + bundler?: 'rollup' | 'webpack'; + oncompile?: ({ type, result }: { type: string, result: CompileResult }) => void; +}; - execute(emitter, opts).then( - () => { - emitter.emit('done', {}); // TODO do we need to pass back any info? - }, - error => { - emitter.emit('error', { - error - }); - } - ); +export async function build({ + cwd, + src = 'src', + routes = 'src/routes', + output = '__sapper__', + static: static_files = 'static', + dest = '__sapper__/build', - return emitter; -} + bundler, + legacy = false, + oncompile = noop +}: Opts = {}) { + bundler = validate_bundler(bundler); + + cwd = path.resolve(cwd); + src = path.resolve(cwd, src); + dest = path.resolve(cwd, dest); + routes = path.resolve(cwd, routes); + output = path.resolve(cwd, output); + static_files = path.resolve(cwd, static_files); + + if (legacy && bundler === 'webpack') { + throw new Error(`Legacy builds are not supported for projects using webpack`); + } -async function execute(emitter: EventEmitter, { - dest = 'build', - app = 'app', - webpack = 'webpack', - routes = 'routes' -} = {}) { - mkdirp.sync(dest); rimraf.sync(path.join(dest, '**/*')); + mkdirp.sync(`${dest}/client`); + copy_shimport(dest); - // minify app/template.html + // minify src/template.html // TODO compile this to a function? could be quicker than str.replace(...).replace(...).replace(...) - const template = fs.readFileSync(`${app}/template.html`, 'utf-8'); + const template = read_template(src); // remove this in a future version if (template.indexOf('%sapper.base%') === -1) { @@ -46,64 +64,74 @@ async function execute(emitter: EventEmitter, { fs.writeFileSync(`${dest}/template.html`, minify_html(template)); - const route_objects = create_routes(); + const manifest_data = create_manifest_data(routes); - // create app/manifest/client.js and app/manifest/server.js - create_main_manifests({ routes: route_objects }); - - const { client, server, serviceworker } = create_compilers({ webpack }); - - const client_stats = await compile(client); - emitter.emit('build', { - type: 'client', - // TODO duration/warnings - webpack_stats: client_stats + // create src/manifest/client.js and src/manifest/server.js + create_main_manifests({ + bundler, + manifest_data, + cwd, + src, + dest, + routes, + output, + dev: false }); - const client_info = client_stats.toJson(); - fs.writeFileSync(path.join(dest, 'client_assets.json'), JSON.stringify(client_info.assetsByChunkName)); + const { client, server, serviceworker } = await create_compilers(bundler, cwd, src, dest, true); - const server_stats = await compile(server); - emitter.emit('build', { + const client_result = await client.compile(); + oncompile({ + type: 'client', + result: client_result + }); + + const build_info = client_result.to_json(manifest_data, { src, routes, dest }); + + if (legacy) { + process.env.SAPPER_LEGACY_BUILD = 'true'; + const { client } = await create_compilers(bundler, cwd, src, dest, true); + + const client_result = await client.compile(); + + oncompile({ + type: 'client (legacy)', + result: client_result + }); + + client_result.to_json(manifest_data, { src, routes, dest }); + build_info.legacy_assets = client_result.assets; + delete process.env.SAPPER_LEGACY_BUILD; + } + + fs.writeFileSync(path.join(dest, 'build.json'), JSON.stringify(build_info)); + + const server_stats = await server.compile(); + oncompile({ type: 'server', - // TODO duration/warnings - webpack_stats: server_stats + result: server_stats }); let serviceworker_stats; if (serviceworker) { + + const client_files = client_result.chunks + .filter(chunk => !chunk.file.endsWith('.map')) // SW does not need to cache sourcemap files + .map(chunk => `client/${chunk.file}`); + create_serviceworker_manifest({ - routes: route_objects, - client_files: client_stats.toJson().assets.map((chunk: { name: string }) => `client/${chunk.name}`) + manifest_data, + output, + client_files, + static_files }); - serviceworker_stats = await compile(serviceworker); + serviceworker_stats = await serviceworker.compile(); - emitter.emit('build', { + oncompile({ type: 'serviceworker', - // TODO duration/warnings - webpack_stats: serviceworker_stats + result: serviceworker_stats }); } -} - -function compile(compiler: any) { - return new Promise((fulfil, reject) => { - compiler.run((err: Error, stats: any) => { - if (err) { - reject(err); - process.exit(1); - } - - if (stats.hasErrors()) { - console.error(stats.toString({ colors: true })); - reject(new Error(`Encountered errors while building app`)); - } - - else { - fulfil(stats); - } - }); - }); -} +} \ No newline at end of file diff --git a/src/api/dev.ts b/src/api/dev.ts index 68711c3..54fddc9 100644 --- a/src/api/dev.ts +++ b/src/api/dev.ts @@ -5,34 +5,59 @@ import * as child_process from 'child_process'; import * as ports from 'port-authority'; import mkdirp from 'mkdirp'; import rimraf from 'rimraf'; -import format_messages from 'webpack-format-messages'; -import { locations } from '../config'; import { EventEmitter } from 'events'; -import { create_routes, create_main_manifests, create_compilers, create_serviceworker_manifest } from '../core'; +import { create_manifest_data, create_main_manifests, create_compilers, create_serviceworker_manifest } from '../core'; +import { Compiler, Compilers } from '../core/create_compilers'; +import { CompileResult } from '../core/create_compilers/interfaces'; import Deferred from './utils/Deferred'; -import * as events from './interfaces'; +import validate_bundler from './utils/validate_bundler'; +import { copy_shimport } from './utils/copy_shimport'; +import { ManifestData, FatalEvent, ErrorEvent, ReadyEvent, InvalidEvent } from '../interfaces'; +import read_template from '../core/read_template'; +import { noop } from './utils/noop'; -export function dev(opts) { +type Opts = { + cwd?: string, + src?: string, + dest?: string, + routes?: string, + output?: string, + static?: string, + 'dev-port'?: number, + live?: boolean, + hot?: boolean, + 'devtools-port'?: number, + bundler?: 'rollup' | 'webpack', + port?: number +}; + +export function dev(opts: Opts) { return new Watcher(opts); } class Watcher extends EventEmitter { + bundler: 'rollup' | 'webpack'; dirs: { - app: string; + cwd: string; + src: string; dest: string; routes: string; - webpack: string; + output: string; + static: string; } port: number; closed: boolean; + dev_port: number; + live: boolean; + hot: boolean; + + devtools_port: number; + dev_server: DevServer; proc: child_process.ChildProcess; filewatchers: Array<{ close: () => void }>; - deferreds: { - client: Deferred; - server: Deferred; - }; + deferred: Deferred; crashed: boolean; restarting: boolean; @@ -44,24 +69,42 @@ class Watcher extends EventEmitter { } constructor({ - app = locations.app(), - dest = locations.dest(), - routes = locations.routes(), - webpack = 'webpack', + cwd = '.', + src = 'src', + routes = 'src/routes', + output = '__sapper__', + static: static_files = 'static', + dest = '__sapper__/dev', + 'dev-port': dev_port, + live, + hot, + 'devtools-port': devtools_port, + bundler, port = +process.env.PORT - }: { - app: string, - dest: string, - routes: string, - webpack: string, - port: number - }) { + }: Opts) { super(); - this.dirs = { app, dest, routes, webpack }; + cwd = path.resolve(cwd); + + this.bundler = validate_bundler(bundler); + this.dirs = { + cwd, + src: path.resolve(cwd, src), + dest: path.resolve(cwd, dest), + routes: path.resolve(cwd, routes), + output: path.resolve(cwd, output), + static: path.resolve(cwd, static_files) + }; + this.port = port; this.closed = false; + this.dev_port = dev_port; + this.live = live; + this.hot = hot; + + this.devtools_port = devtools_port; + this.filewatchers = []; this.current_build = { @@ -72,7 +115,7 @@ class Watcher extends EventEmitter { }; // remove this in a future version - const template = fs.readFileSync(path.join(app, 'template.html'), 'utf-8'); + const template = read_template(src); if (template.indexOf('%sapper.base%') === -1) { const error = new Error(`As of Sapper v0.10, your template.html file must include %sapper.base% in the `); error.code = `missing-sapper-base`; @@ -91,7 +134,7 @@ class Watcher extends EventEmitter { async init() { if (this.port) { if (!await ports.check(this.port)) { - this.emit('fatal', { + this.emit('fatal', { message: `Port ${this.port} is unavailable` }); return; @@ -100,27 +143,39 @@ class Watcher extends EventEmitter { this.port = await ports.find(3000); } - const { dest } = this.dirs; + const { cwd, src, dest, routes, output, static: static_files } = this.dirs; rimraf.sync(dest); - mkdirp.sync(dest); + mkdirp.sync(`${dest}/client`); + if (this.bundler === 'rollup') copy_shimport(dest); - const dev_port = await ports.find(10000); + if (!this.dev_port) this.dev_port = await ports.find(10000); + + // Chrome looks for debugging targets on ports 9222 and 9229 by default + if (!this.devtools_port) this.devtools_port = await ports.find(9222); + + let manifest_data: ManifestData; try { - const routes = create_routes(); - create_main_manifests({ routes, dev_port }); + manifest_data = create_manifest_data(routes); + create_main_manifests({ + bundler: this.bundler, + manifest_data, + dev: true, + dev_port: this.dev_port, + cwd, src, dest, routes, output + }); } catch (err) { - this.emit('fatal', { + this.emit('fatal', { message: err.message }); return; } - this.dev_server = new DevServer(dev_port); + this.dev_server = new DevServer(this.dev_port); this.filewatchers.push( watch_dir( - locations.routes(), + routes, ({ path: file, stats }) => { if (stats.isDirectory()) { return path.basename(file)[0] !== '_'; @@ -128,41 +183,40 @@ class Watcher extends EventEmitter { return true; }, () => { - const routes = create_routes(); - create_main_manifests({ routes, dev_port }); - try { - const routes = create_routes(); - create_main_manifests({ routes, dev_port }); + const new_manifest_data = create_manifest_data(routes); + create_main_manifests({ + bundler: this.bundler, + manifest_data, // TODO is this right? not new_manifest_data? + dev: true, + dev_port: this.dev_port, + cwd, src, dest, routes, output + }); + + manifest_data = new_manifest_data; } catch (err) { - this.emit('error', { + this.emit('error', { message: err.message }); } } ), - fs.watch(`${locations.app()}/template.html`, () => { + fs.watch(`${src}/template.html`, () => { this.dev_server.send({ action: 'reload' }); }) ); - this.deferreds = { - server: new Deferred(), - client: new Deferred() - }; + let deferred = new Deferred(); // TODO watch the configs themselves? - const compilers = create_compilers({ webpack: this.dirs.webpack }); - - let log = ''; + const compilers: Compilers = await create_compilers(this.bundler, cwd, src, dest, false); const emitFatal = () => { - this.emit('fatal', { - message: `Server crashed`, - log + this.emit('fatal', { + message: `Server crashed` }); this.crashed = true; @@ -174,34 +228,35 @@ class Watcher extends EventEmitter { invalid: filename => { this.restart(filename, 'server'); - this.deferreds.server = new Deferred(); }, - result: info => { - this.deferreds.client.promise.then(() => { + handle_result: (result: CompileResult) => { + deferred.promise.then(() => { const restart = () => { - log = ''; this.crashed = false; ports.wait(this.port) .then((() => { - this.emit('ready', { + this.emit('ready', { port: this.port, process: this.proc }); - this.deferreds.server.fulfil(); - - this.dev_server.send({ - status: 'completed' - }); + if (this.hot && this.bundler === 'webpack') { + this.dev_server.send({ + status: 'completed' + }); + } else { + this.dev_server.send({ + action: 'reload' + }); + } })) .catch(err => { if (this.crashed) return; - this.emit('fatal', { - message: `Server is not listening on port ${this.port}`, - log + this.emit('fatal', { + message: `Server is not listening on port ${this.port}` }); }); }; @@ -214,21 +269,28 @@ class Watcher extends EventEmitter { restart(); } - this.proc = child_process.fork(`${dest}/server.js`, [], { + // we need to give the child process its own DevTools port, + // otherwise Node will try to use the parent's (and fail) + const debugArgRegex = /--inspect(?:-brk|-port)?|--debug-port/; + const execArgv = process.execArgv.slice(); + if (execArgv.some((arg: string) => !!arg.match(debugArgRegex))) { + execArgv.push(`--inspect-port=${this.devtools_port}`); + } + + this.proc = child_process.fork(`${dest}/server/server.js`, [], { cwd: process.cwd(), env: Object.assign({ PORT: this.port }, process.env), - stdio: ['ipc'] + stdio: ['ipc'], + execArgv }); this.proc.stdout.on('data', chunk => { - log += chunk; this.emit('stdout', chunk); }); this.proc.stderr.on('data', chunk => { - log += chunk; this.emit('stderr', chunk); }); @@ -245,31 +307,37 @@ class Watcher extends EventEmitter { } }); - let first = true; - this.watch(compilers.client, { name: 'client', invalid: filename => { this.restart(filename, 'client'); - this.deferreds.client = new Deferred(); + deferred = new Deferred(); // TODO we should delete old assets. due to a webpack bug // i don't even begin to comprehend, this is apparently // quite difficult }, - result: info => { - fs.writeFileSync(path.join(dest, 'client_assets.json'), JSON.stringify(info.assetsByChunkName, null, ' ')); - this.deferreds.client.fulfil(); + handle_result: (result: CompileResult) => { + fs.writeFileSync( + path.join(dest, 'build.json'), - const client_files = info.assets.map((chunk: { name: string }) => `client/${chunk.name}`); + // TODO should be more explicit that to_json has effects + JSON.stringify(result.to_json(manifest_data, this.dirs), null, ' ') + ); + + const client_files = result.chunks.map(chunk => `client/${chunk.file}`); create_serviceworker_manifest({ - routes: create_routes(), - client_files + manifest_data, + output, + client_files, + static_files }); + deferred.fulfil(); + // we need to wait a beat before watching the service // worker, because of some webpack nonsense setTimeout(watch_serviceworker, 100); @@ -281,11 +349,7 @@ class Watcher extends EventEmitter { watch_serviceworker = noop; this.watch(compilers.serviceworker, { - name: 'service worker', - - result: info => { - fs.writeFileSync(path.join(dest, 'serviceworker_info.json'), JSON.stringify(info, null, ' ')); - } + name: 'service worker' }); } : noop; @@ -318,7 +382,7 @@ class Watcher extends EventEmitter { }; process.nextTick(() => { - this.emit('invalid', { + this.emit('invalid', { changed: Array.from(this.current_build.changed), invalid: { server: this.current_build.rebuilding.has('server'), @@ -332,82 +396,34 @@ class Watcher extends EventEmitter { } } - watch(compiler: any, { name, invalid = noop, result }: { + watch(compiler: Compiler, { name, invalid = noop, handle_result = noop }: { name: string, invalid?: (filename: string) => void; - result: (stats: any) => void; + handle_result?: (result: CompileResult) => void; }) { - compiler.hooks.invalid.tap('sapper', (filename: string) => { - invalid(filename); - }); + compiler.oninvalid(invalid); - compiler.watch({}, (err: Error, stats: any) => { + compiler.watch((err?: Error, result?: CompileResult) => { if (err) { - this.emit('error', { + this.emit('error', { type: name, message: err.message }); } else { - const messages = format_messages(stats); - const info = stats.toJson(); - this.emit('build', { type: name, - duration: info.time, - - errors: messages.errors.map((message: string) => { - const duplicate = this.current_build.unique_errors.has(message); - this.current_build.unique_errors.add(message); - - return mungeWebpackError(message, duplicate); - }), - - warnings: messages.warnings.map((message: string) => { - const duplicate = this.current_build.unique_warnings.has(message); - this.current_build.unique_warnings.add(message); - - return mungeWebpackError(message, duplicate); - }), + duration: result.duration, + errors: result.errors, + warnings: result.warnings }); - result(info); + handle_result(result); } }); } } -const locPattern = /\((\d+):(\d+)\)$/; - -function mungeWebpackError(message: string, duplicate: boolean) { - // TODO this is all a bit rube goldberg... - const lines = message.split('\n'); - - const file = lines.shift() - .replace('', '') // careful — there is a special character at the beginning of this string - .replace('', '') - .replace('./', ''); - - let line = null; - let column = null; - - const match = locPattern.exec(lines[0]); - if (match) { - lines[0] = lines[0].replace(locPattern, ''); - line = +match[1]; - column = +match[2]; - } - - return { - file, - line, - column, - message: lines.join('\n'), - originalMessage: message, - duplicate - }; -} - const INTERVAL = 10000; class DevServer { @@ -460,14 +476,12 @@ class DevServer { } } -function noop() {} - function watch_dir( dir: string, filter: ({ path, stats }: { path: string, stats: fs.Stats }) => boolean, callback: () => void ) { - let watch; + let watch: any; let closed = false; import('cheap-watch').then(CheapWatch => { @@ -475,7 +489,7 @@ function watch_dir( watch = new CheapWatch({ dir, filter, debounce: 50 }); - watch.on('+', ({ isNew }) => { + watch.on('+', ({ isNew }: { isNew: boolean }) => { if (isNew) callback(); }); diff --git a/src/api/export.ts b/src/api/export.ts index 3a900c4..5d80674 100644 --- a/src/api/export.ts +++ b/src/api/export.ts @@ -1,129 +1,150 @@ import * as child_process from 'child_process'; import * as path from 'path'; import * as sander from 'sander'; -import URL from 'url-parse'; +import * as url from 'url'; import fetch from 'node-fetch'; import * as yootils from 'yootils'; import * as ports from 'port-authority'; -import { EventEmitter } from 'events'; import clean_html from './utils/clean_html'; import minify_html from './utils/minify_html'; import Deferred from './utils/Deferred'; -import * as events from './interfaces'; +import { noop } from './utils/noop'; -export function exporter(opts: {}) { - const emitter = new EventEmitter(); +type Opts = { + build_dir?: string, + export_dir?: string, + cwd?: string, + static?: string, + basepath?: string, + timeout?: number | false, + oninfo?: ({ message }: { message: string }) => void; + onfile?: ({ file, size, status }: { file: string, size: number, status: number }) => void; +}; - execute(emitter, opts).then( - () => { - emitter.emit('done', {}); // TODO do we need to pass back any info? - }, - error => { - emitter.emit('error', { - error - }); - } - ); - - return emitter; +function resolve(from: string, to: string) { + return url.parse(url.resolve(from, to)); } -async function execute(emitter: EventEmitter, { - build = 'build', - dest = 'export', - basepath = '' -} = {}) { - const export_dir = path.join(dest, basepath); +type URL = url.UrlWithStringQuery; + +export { _export as export }; + +async function _export({ + cwd, + static: static_files = 'static', + build_dir = '__sapper__/build', + export_dir = '__sapper__/export', + basepath = '', + timeout = 5000, + oninfo = noop, + onfile = noop +}: Opts = {}) { + basepath = basepath.replace(/^\//, '') + + cwd = path.resolve(cwd); + static_files = path.resolve(cwd, static_files); + build_dir = path.resolve(cwd, build_dir); + export_dir = path.resolve(cwd, export_dir, basepath); // Prep output directory sander.rimrafSync(export_dir); - sander.copydirSync('assets').to(export_dir); - sander.copydirSync(build, 'client').to(export_dir, 'client'); + sander.copydirSync(static_files).to(export_dir); + sander.copydirSync(build_dir, 'client').to(export_dir, 'client'); - if (sander.existsSync(build, 'service-worker.js')) { - sander.copyFileSync(build, 'service-worker.js').to(export_dir, 'service-worker.js'); + if (sander.existsSync(build_dir, 'service-worker.js')) { + sander.copyFileSync(build_dir, 'service-worker.js').to(export_dir, 'service-worker.js'); } - if (sander.existsSync(build, 'service-worker.js.map')) { - sander.copyFileSync(build, 'service-worker.js.map').to(export_dir, 'service-worker.js.map'); + if (sander.existsSync(build_dir, 'service-worker.js.map')) { + sander.copyFileSync(build_dir, 'service-worker.js.map').to(export_dir, 'service-worker.js.map'); } const port = await ports.find(3000); - const origin = `http://localhost:${port}`; - const root = new URL(basepath || '', origin); + const protocol = 'http:'; + const host = `localhost:${port}`; + const origin = `${protocol}//${host}`; - emitter.emit('info', { + const root = resolve(origin, basepath); + if (!root.href.endsWith('/')) root.href += '/'; + + oninfo({ message: `Crawling ${root.href}` }); - const proc = child_process.fork(path.resolve(`${build}/server.js`), [], { - cwd: process.cwd(), + const proc = child_process.fork(path.resolve(`${build_dir}/server/server.js`), [], { + cwd, env: Object.assign({ PORT: port, NODE_ENV: 'production', - SAPPER_DEST: build, SAPPER_EXPORT: 'true' }, process.env) }); const seen = new Set(); const saved = new Set(); - const deferreds = new Map(); - function get_deferred(pathname: string) { - pathname = pathname.replace(root.pathname, ''); - - if (!deferreds.has(pathname)) { - deferreds.set(pathname, new Deferred()); - } - - return deferreds.get(pathname); - } - - proc.on('message', message => { - if (!message.__sapper__ || message.event !== 'file') return; - - const pathname = new URL(message.url, origin).pathname; - let file = pathname.slice(1); - let { body } = message; + function save(path: string, status: number, type: string, body: string) { + const { pathname } = resolve(origin, path); + let file = decodeURIComponent(pathname.slice(1)); if (saved.has(file)) return; saved.add(file); - const is_html = message.type === 'text/html'; + const is_html = type === 'text/html'; if (is_html) { - file = file === '' ? 'index.html' : `${file}/index.html`; + if (pathname !== '/service-worker-index.html') { + file = file === '' ? 'index.html' : `${file}/index.html`; + } body = minify_html(body); } - emitter.emit('file', { + onfile({ file, size: body.length, - status: message.status + status }); sander.writeFileSync(export_dir, file, body); + } - get_deferred(pathname).fulfil(); + proc.on('message', message => { + if (!message.__sapper__ || message.event !== 'file') return; + save(message.url, message.status, message.type, message.body); }); async function handle(url: URL) { - const pathname = (url.pathname.replace(root.pathname, '') || '/'); + let pathname = url.pathname; + if (pathname !== '/service-worker-index.html') { + pathname = pathname.replace(root.pathname, '') || '/' + } if (seen.has(pathname)) return; seen.add(pathname); - const deferred = get_deferred(pathname); + const timeout_deferred = new Deferred(); + const the_timeout = setTimeout(() => { + timeout_deferred.reject(new Error(`Timed out waiting for ${url.href}`)); + }, timeout); + + const r = await Promise.race([ + fetch(url.href, { + redirect: 'manual' + }), + timeout_deferred.promise + ]); + + clearTimeout(the_timeout); // prevent it hanging at the end + + let type = r.headers.get('Content-Type'); + let body = await r.text(); - const r = await fetch(url.href); const range = ~~(r.status / 100); if (range === 2) { - if (r.headers.get('Content-Type') === 'text/html') { - const body = await r.text(); + if (type === 'text/html' && pathname !== '/service-worker-index.html') { const urls: URL[] = []; const cleaned = clean_html(body); @@ -133,7 +154,7 @@ async function execute(emitter: EventEmitter, { const base_match = //m.exec(cleaned); const base_href = base_match && get_href(base_match[1]); - const base = new URL(base_href || '/', url.href); + const base = resolve(url.href, base_href); let match; let pattern = //gm; @@ -143,8 +164,9 @@ async function execute(emitter: EventEmitter, { const href = get_href(attrs); if (href) { - const url = new URL(href, base.href); - if (url.origin === origin) { + const url = resolve(base.href, href); + + if (url.protocol === protocol && url.host === host) { promise = q.add(() => handle(url)); } } @@ -154,18 +176,29 @@ async function execute(emitter: EventEmitter, { } } - await deferred.promise; + if (range === 3) { + const location = r.headers.get('Location'); + + type = 'text/html'; + body = ``; + + await handle(resolve(root.href, location)); + } + + save(pathname, r.status, type, body); } return ports.wait(port) - .then(() => { - // TODO all static routes - return handle(root); - }) - .then(() => proc.kill()); + .then(() => handle(root)) + .then(() => handle(resolve(root.href, 'service-worker-index.html'))) + .then(() => proc.kill()) + .catch(err => { + proc.kill(); + throw err; + }); } function get_href(attrs: string) { - const match = /href\s*=\s*(?:"(.+?)"|'(.+?)'|([^\s>]+))/.exec(attrs); + const match = /href\s*=\s*(?:"(.*?)"|'(.+?)'|([^\s>]+))/.exec(attrs); return match[1] || match[2] || match[3]; } \ No newline at end of file diff --git a/src/api/find_page.ts b/src/api/find_page.ts index bf843d0..6f7cac9 100644 --- a/src/api/find_page.ts +++ b/src/api/find_page.ts @@ -1,8 +1,7 @@ -import { locations } from '../config'; -import { create_routes } from '../core'; +import { create_manifest_data } from '../core'; -export function find_page(pathname: string, cwd = locations.routes()) { - const { pages } = create_routes(cwd); +export function find_page(pathname: string, cwd = 'src/routes') { + const { pages } = create_manifest_data(cwd); for (let i = 0; i < pages.length; i += 1) { const page = pages[i]; diff --git a/src/api/interfaces.ts b/src/api/interfaces.ts deleted file mode 100644 index e1ac627..0000000 --- a/src/api/interfaces.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as child_process from 'child_process'; - -export type ReadyEvent = { - port: number; - process: child_process.ChildProcess; -}; - -export type ErrorEvent = { - type: string; - message: string; -}; - -export type FatalEvent = { - message: string; - log?: string; -}; - -export type InvalidEvent = { - changed: string[]; - invalid: { - client: boolean; - server: boolean; - serviceworker: boolean; - } -}; - -export type BuildEvent = { - type: string; - errors: Array<{ message: string, duplicate: boolean }>; - warnings: Array<{ message: string, duplicate: boolean }>; - duration: number; - webpack_stats: any; -} - -export type FileEvent = { - file: string; - size: number; -} - -export type FailureEvent = { - -} - -export type DoneEvent = {} \ No newline at end of file diff --git a/src/api/utils/copy_shimport.ts b/src/api/utils/copy_shimport.ts new file mode 100644 index 0000000..dda43f1 --- /dev/null +++ b/src/api/utils/copy_shimport.ts @@ -0,0 +1,9 @@ +import * as fs from 'fs'; + +export function copy_shimport(dest: string) { + const shimport_version = require('shimport/package.json').version; + fs.writeFileSync( + `${dest}/client/shimport@${shimport_version}.js`, + fs.readFileSync(require.resolve('shimport/index.js')) + ); +} \ No newline at end of file diff --git a/src/api/utils/minify_html.ts b/src/api/utils/minify_html.ts index e628e8a..65f1486 100644 --- a/src/api/utils/minify_html.ts +++ b/src/api/utils/minify_html.ts @@ -7,6 +7,7 @@ export default function minify_html(html: string) { conservativeCollapse: true, decodeEntities: true, html5: true, + ignoreCustomComments: [/^#/], minifyCSS: true, minifyJS: false, removeAttributeQuotes: true, diff --git a/src/api/utils/noop.ts b/src/api/utils/noop.ts new file mode 100644 index 0000000..628cbae --- /dev/null +++ b/src/api/utils/noop.ts @@ -0,0 +1 @@ +export function noop() {} \ No newline at end of file diff --git a/src/api/utils/validate_bundler.ts b/src/api/utils/validate_bundler.ts new file mode 100644 index 0000000..d3df428 --- /dev/null +++ b/src/api/utils/validate_bundler.ts @@ -0,0 +1,38 @@ +import * as fs from 'fs'; + +export default function validate_bundler(bundler?: 'rollup' | 'webpack') { + if (!bundler) { + bundler = ( + fs.existsSync('rollup.config.js') ? 'rollup' : + fs.existsSync('webpack.config.js') ? 'webpack' : + null + ); + + if (!bundler) { + // TODO remove in a future version + deprecate_dir('rollup'); + deprecate_dir('webpack'); + + throw new Error(`Could not find rollup.config.js or webpack.config.js`); + } + } + + if (bundler !== 'rollup' && bundler !== 'webpack') { + throw new Error(`'${bundler}' is not a valid option for --bundler — must be either 'rollup' or 'webpack'`); + } + + return bundler; +} + +function deprecate_dir(bundler: 'rollup' | 'webpack') { + try { + const stats = fs.statSync(bundler); + if (!stats.isDirectory()) return; + } catch (err) { + // do nothing + return; + } + + // TODO link to docs, once those docs exist + throw new Error(`As of Sapper 0.21, build configuration should be placed in a single ${bundler}.config.js file`); +} \ No newline at end of file diff --git a/src/cli.ts b/src/cli.ts index 303f5d1..d3e8667 100755 --- a/src/cli.ts +++ b/src/cli.ts @@ -2,96 +2,284 @@ import * as fs from 'fs'; import * as path from 'path'; import sade from 'sade'; import colors from 'kleur'; -import prettyMs from 'pretty-ms'; import * as pkg from '../package.json'; +import { elapsed, repeat, left_pad, format_milliseconds } from './utils'; +import { InvalidEvent, ErrorEvent, FatalEvent, BuildEvent, ReadyEvent } from './interfaces'; const prog = sade('sapper').version(pkg.version); +if (process.argv[2] === 'start') { + // remove this in a future version + console.error(colors.bold.red(`'sapper start' has been removed`)); + console.error(`Use 'node [build_dir]' instead`); + process.exit(1); +} + +const start = Date.now(); + prog.command('dev') .describe('Start a development server') .option('-p, --port', 'Specify a port') .option('-o, --open', 'Open a browser window') - .action(async (opts: { port: number, open: boolean }) => { - const { dev } = await import('./cli/dev'); - dev(opts); + .option('--dev-port', 'Specify a port for development server') + .option('--hot', 'Use hot module replacement (requires webpack)', true) + .option('--live', 'Reload on changes if not using --hot', true) + .option('--bundler', 'Specify a bundler (rollup or webpack)') + .option('--cwd', 'Current working directory', '.') + .option('--src', 'Source directory', 'src') + .option('--routes', 'Routes directory', 'src/routes') + .option('--static', 'Static files directory', 'static') + .option('--output', 'Sapper output directory', '__sapper__') + .option('--build-dir', 'Development build directory', '__sapper__/dev') + .action(async (opts: { + port: number, + open: boolean, + 'dev-port': number, + live: boolean, + hot: boolean, + bundler?: 'rollup' | 'webpack', + cwd: string, + src: string, + routes: string, + static: string, + output: string, + 'build-dir': string + }) => { + const { dev } = await import('./api/dev'); + + try { + const watcher = dev({ + cwd: opts.cwd, + src: opts.src, + routes: opts.routes, + static: opts.static, + output: opts.output, + dest: opts['build-dir'], + port: opts.port, + 'dev-port': opts['dev-port'], + live: opts.live, + hot: opts.hot, + bundler: opts.bundler + }); + + let first = true; + + watcher.on('stdout', data => { + process.stdout.write(data); + }); + + watcher.on('stderr', data => { + process.stderr.write(data); + }); + + watcher.on('ready', async (event: ReadyEvent) => { + if (first) { + console.log(colors.bold.cyan(`> Listening on http://localhost:${event.port}`)); + if (opts.open) { + const { exec } = await import('child_process'); + exec(`open http://localhost:${event.port}`); + } + first = false; + } + }); + + watcher.on('invalid', (event: InvalidEvent) => { + const changed = event.changed.map(filename => path.relative(process.cwd(), filename)).join(', '); + console.log(`\n${colors.bold.cyan(changed)} changed. rebuilding...`); + }); + + watcher.on('error', (event: ErrorEvent) => { + console.log(colors.red(`✗ ${event.type}`)); + console.log(colors.red(event.message)); + }); + + watcher.on('fatal', (event: FatalEvent) => { + console.log(colors.bold.red(`> ${event.message}`)); + if (event.log) console.log(event.log); + }); + + watcher.on('build', (event: BuildEvent) => { + if (event.errors.length) { + console.log(colors.bold.red(`✗ ${event.type}`)); + + event.errors.filter(e => !e.duplicate).forEach(error => { + if (error.file) console.log(colors.bold(error.file)); + console.log(error.message); + }); + + const hidden = event.errors.filter(e => e.duplicate).length; + if (hidden > 0) { + console.log(`${hidden} duplicate ${hidden === 1 ? 'error' : 'errors'} hidden\n`); + } + } else if (event.warnings.length) { + console.log(colors.bold.yellow(`• ${event.type}`)); + + event.warnings.filter(e => !e.duplicate).forEach(warning => { + if (warning.file) console.log(colors.bold(warning.file)); + console.log(warning.message); + }); + + const hidden = event.warnings.filter(e => e.duplicate).length; + if (hidden > 0) { + console.log(`${hidden} duplicate ${hidden === 1 ? 'warning' : 'warnings'} hidden\n`); + } + } else { + console.log(`${colors.bold.green(`✔ ${event.type}`)} ${colors.gray(`(${format_milliseconds(event.duration)})`)}`); + } + }); + } catch (err) { + console.log(colors.bold.red(`> ${err.message}`)); + process.exit(1); + } }); prog.command('build [dest]') .describe('Create a production-ready version of your app') .option('-p, --port', 'Default of process.env.PORT', '3000') + .option('--bundler', 'Specify a bundler (rollup or webpack, blank for auto)') + .option('--legacy', 'Create separate legacy build') + .option('--cwd', 'Current working directory', '.') + .option('--src', 'Source directory', 'src') + .option('--routes', 'Routes directory', 'src/routes') + .option('--output', 'Sapper output directory', '__sapper__') .example(`build custom-dir -p 4567`) - .action(async (dest = 'build', opts: { port: string }) => { + .action(async (dest = '__sapper__/build', opts: { + port: string, + legacy: boolean, + bundler?: 'rollup' | 'webpack', + cwd: string, + src: string, + routes: string, + output: string + }) => { console.log(`> Building...`); - process.env.NODE_ENV = process.env.NODE_ENV || 'production'; - process.env.SAPPER_DEST = dest; - - const start = Date.now(); - try { - const { build } = await import('./cli/build'); - await build(); + await _build(opts.bundler, opts.legacy, opts.cwd, opts.src, opts.routes, opts.output, dest); const launcher = path.resolve(dest, 'index.js'); fs.writeFileSync(launcher, ` // generated by sapper build at ${new Date().toISOString()} process.env.NODE_ENV = process.env.NODE_ENV || 'production'; - process.env.SAPPER_DEST = __dirname; process.env.PORT = process.env.PORT || ${opts.port || 3000}; console.log('Starting server on port ' + process.env.PORT); - require('./server.js'); + require('./server/server.js'); `.replace(/^\t+/gm, '').trim()); console.error(`\n> Finished in ${elapsed(start)}. Type ${colors.bold.cyan(`node ${dest}`)} to run the app.`); } catch (err) { - console.error(err ? err.details || err.stack || err.message || err : 'Unknown error'); + console.log(`${colors.bold.red(`> ${err.message}`)}`); process.exit(1); } }); -prog.command('start [dir]') - .describe('Start your app') - .option('-p, --port', 'Specify a port') - .option('-o, --open', 'Open a browser window') - .action(async (dir = 'build', opts: { port: number, open: boolean }) => { - const { start } = await import('./cli/start'); - start(dir, opts); - }); - prog.command('export [dest]') .describe('Export your app as static files (if possible)') .option('--build', '(Re)build app before exporting', true) - .option('--build-dir', 'Specify a custom temporary build directory', '.sapper/prod') .option('--basepath', 'Specify a base path') - .action(async (dest = 'export', opts: { build: boolean, 'build-dir': string, basepath?: string }) => { - process.env.NODE_ENV = 'production'; - process.env.SAPPER_DEST = opts['build-dir']; - - const start = Date.now(); - + .option('--timeout', 'Milliseconds to wait for a page (--no-timeout to disable)', 5000) + .option('--legacy', 'Create separate legacy build') + .option('--bundler', 'Specify a bundler (rollup or webpack, blank for auto)') + .option('--cwd', 'Current working directory', '.') + .option('--src', 'Source directory', 'src') + .option('--routes', 'Routes directory', 'src/routes') + .option('--static', 'Static files directory', 'static') + .option('--output', 'Sapper output directory', '__sapper__') + .option('--build-dir', 'Intermediate build directory', '__sapper__/build') + .action(async (dest = '__sapper__/export', opts: { + build: boolean, + legacy: boolean, + bundler?: 'rollup' | 'webpack', + basepath?: string, + timeout: number | false, + cwd: string, + src: string, + routes: string, + static: string, + output: string, + 'build-dir': string, + }) => { try { if (opts.build) { console.log(`> Building...`); - const { build } = await import('./cli/build'); - await build(); + await _build(opts.bundler, opts.legacy, opts.cwd, opts.src, opts.routes, opts.output, opts['build-dir']); console.error(`\n> Built in ${elapsed(start)}`); } - const { exporter } = await import('./cli/export'); - await exporter(dest, opts); + const { export: _export } = await import('./api/export'); + const { default: pb } = await import('pretty-bytes'); + + await _export({ + cwd: opts.cwd, + static: opts.static, + build_dir: opts['build-dir'], + export_dir: dest, + basepath: opts.basepath, + timeout: opts.timeout, + + oninfo: event => { + console.log(colors.bold.cyan(`> ${event.message}`)); + }, + + onfile: event => { + const size_color = event.size > 150000 ? colors.bold.red : event.size > 50000 ? colors.bold.yellow : colors.bold.gray; + const size_label = size_color(left_pad(pb(event.size), 10)); + + const file_label = event.status === 200 + ? event.file + : colors.bold[event.status >= 400 ? 'red' : 'yellow'](`(${event.status}) ${event.file}`); + + console.log(`${size_label} ${file_label}`); + } + }); + console.error(`\n> Finished in ${elapsed(start)}. Type ${colors.bold.cyan(`npx serve ${dest}`)} to run the app.`); } catch (err) { - console.error(err ? err.details || err.stack || err.message || err : 'Unknown error'); + console.error(colors.bold.red(`> ${err.message}`)); process.exit(1); } }); -// TODO upgrade - prog.parse(process.argv); -function elapsed(start: number) { - return prettyMs(Date.now() - start); -} + +async function _build( + bundler: 'rollup' | 'webpack', + legacy: boolean, + cwd: string, + src: string, + routes: string, + output: string, + dest: string +) { + const { build } = await import('./api/build'); + + await build({ + bundler, + legacy, + cwd, + src, + routes, + dest, + + oncompile: event => { + let banner = `built ${event.type}`; + let c = colors.cyan; + + const { warnings } = event.result; + if (warnings.length > 0) { + banner += ` with ${warnings.length} ${warnings.length === 1 ? 'warning' : 'warnings'}`; + c = colors.yellow; + } + + console.log(); + console.log(c(`┌─${repeat('─', banner.length)}─┐`)); + console.log(c(`│ ${colors.bold(banner) } │`)); + console.log(c(`└─${repeat('─', banner.length)}─┘`)); + + console.log(event.result.print()); + } + }); +} \ No newline at end of file diff --git a/src/cli/build.ts b/src/cli/build.ts deleted file mode 100644 index b7bf87b..0000000 --- a/src/cli/build.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { build as _build } from '../api/build'; -import colors from 'kleur'; -import { locations } from '../config'; - -export function build() { - return new Promise((fulfil, reject) => { - try { - const emitter = _build({ - dest: locations.dest(), - app: locations.app(), - routes: locations.routes(), - webpack: 'webpack' - }); - - emitter.on('build', event => { - console.log(colors.inverse(`\nbuilt ${event.type}`)); - console.log(event.webpack_stats.toString({ colors: true })); - }); - - emitter.on('error', event => { - reject(event.error); - }); - - emitter.on('done', event => { - fulfil(); - }); - } catch (err) { - console.log(`${colors.bold.red(`> ${err.message}`)}`); - process.exit(1); - } - }); -} \ No newline at end of file diff --git a/src/cli/dev.ts b/src/cli/dev.ts deleted file mode 100644 index 17eab11..0000000 --- a/src/cli/dev.ts +++ /dev/null @@ -1,78 +0,0 @@ -import * as path from 'path'; -import colors from 'kleur'; -import * as child_process from 'child_process'; -import prettyMs from 'pretty-ms'; -import { dev as _dev } from '../api/dev'; -import * as events from '../api/interfaces'; - -export function dev(opts: { port: number, open: boolean }) { - try { - const watcher = _dev(opts); - - let first = true; - - watcher.on('ready', (event: events.ReadyEvent) => { - if (first) { - console.log(`${colors.bold.cyan(`> Listening on http://localhost:${event.port}`)}`); - if (opts.open) child_process.exec(`open http://localhost:${event.port}`); - first = false; - } - - // TODO clear screen? - - event.process.stdout.on('data', data => { - process.stdout.write(data); - }); - - event.process.stderr.on('data', data => { - process.stderr.write(data); - }); - }); - - watcher.on('invalid', (event: events.InvalidEvent) => { - const changed = event.changed.map(filename => path.relative(process.cwd(), filename)).join(', '); - console.log(`\n${colors.bold.cyan(changed)} changed. rebuilding...`); - }); - - watcher.on('error', (event: events.ErrorEvent) => { - console.log(`${colors.red(`✗ ${event.type}`)}`); - console.log(`${colors.red(event.message)}`); - }); - - watcher.on('fatal', (event: events.FatalEvent) => { - console.log(`${colors.bold.red(`> ${event.message}`)}`); - if (event.log) console.log(event.log); - }); - - watcher.on('build', (event: events.BuildEvent) => { - if (event.errors.length) { - console.log(`${colors.bold.red(`✗ ${event.type}`)}`); - - event.errors.filter(e => !e.duplicate).forEach(error => { - console.log(error.message); - }); - - const hidden = event.errors.filter(e => e.duplicate).length; - if (hidden > 0) { - console.log(`${hidden} duplicate ${hidden === 1 ? 'error' : 'errors'} hidden\n`); - } - } else if (event.warnings.length) { - console.log(`${colors.bold.yellow(`• ${event.type}`)}`); - - event.warnings.filter(e => !e.duplicate).forEach(warning => { - console.log(warning.message); - }); - - const hidden = event.warnings.filter(e => e.duplicate).length; - if (hidden > 0) { - console.log(`${hidden} duplicate ${hidden === 1 ? 'warning' : 'warnings'} hidden\n`); - } - } else { - console.log(`${colors.bold.green(`✔ ${event.type}`)} ${colors.gray(`(${prettyMs(event.duration)})`)}`); - } - }); - } catch (err) { - console.log(`${colors.bold.red(`> ${err.message}`)}`); - process.exit(1); - } -} \ No newline at end of file diff --git a/src/cli/export.ts b/src/cli/export.ts deleted file mode 100644 index 0a7737a..0000000 --- a/src/cli/export.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { exporter as _exporter } from '../api/export'; -import colors from 'kleur'; -import prettyBytes from 'pretty-bytes'; -import { locations } from '../config'; - -function left_pad(str: string, len: number) { - while (str.length < len) str = ` ${str}`; - return str; -} - -export function exporter(export_dir: string, { basepath = '' }) { - return new Promise((fulfil, reject) => { - try { - const emitter = _exporter({ - build: locations.dest(), - dest: export_dir, - basepath - }); - - emitter.on('file', event => { - const pb = prettyBytes(event.size); - const size_color = event.size > 150000 ? colors.bold.red : event.size > 50000 ? colors.bold.yellow : colors.bold.gray; - const size_label = size_color(left_pad(prettyBytes(event.size), 10)); - - const file_label = event.status === 200 - ? event.file - : colors.bold[event.status >= 400 ? 'red' : 'yellow'](`(${event.status}) ${event.file}`); - - console.log(`${size_label} ${file_label}`); - }); - - emitter.on('info', event => { - console.log(colors.bold.cyan(`> ${event.message}`)); - }); - - emitter.on('error', event => { - reject(event.error); - }); - - emitter.on('done', event => { - fulfil(); - }); - } catch (err) { - console.log(`${colors.bold.red(`> ${err.message}`)}`); - process.exit(1); - } - }); -} \ No newline at end of file diff --git a/src/cli/start.ts b/src/cli/start.ts deleted file mode 100644 index ba658ae..0000000 --- a/src/cli/start.ts +++ /dev/null @@ -1,39 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; -import * as child_process from 'child_process'; -import colors from 'kleur'; -import * as ports from 'port-authority'; - -export async function start(dir: string, opts: { port: number, open: boolean }) { - let port = opts.port || +process.env.PORT; - - const resolved = path.resolve(dir); - const server = path.resolve(dir, 'server.js'); - - if (!fs.existsSync(server)) { - console.log(`${colors.bold.red(`> ${dir}/server.js does not exist — type ${colors.bold.cyan(dir === 'build' ? `npx sapper build` : `npx sapper build ${dir}`)} to create it`)}`); - return; - } - - if (port) { - if (!await ports.check(port)) { - console.log(`${colors.bold.red(`> Port ${port} is unavailable`)}`); - return; - } - } else { - port = await ports.find(3000); - } - - child_process.fork(server, [], { - cwd: process.cwd(), - env: Object.assign({ - NODE_ENV: 'production', - PORT: port, - SAPPER_DEST: dir - }, process.env) - }); - - await ports.wait(port); - console.log(`${colors.bold.cyan(`> Listening on http://localhost:${port}`)}`); - if (opts.open) child_process.exec(`open http://localhost:${port}`); -} diff --git a/src/cli/upgrade.ts b/src/cli/upgrade.ts deleted file mode 100644 index 7d8b16b..0000000 --- a/src/cli/upgrade.ts +++ /dev/null @@ -1,53 +0,0 @@ -import * as fs from 'fs'; -import colors from 'kleur'; - -export default async function upgrade() { - const upgraded = [ - await upgrade_sapper_main() - ].filter(Boolean); - - if (upgraded.length === 0) { - console.log(`No changes!`); - } -} - -async function upgrade_sapper_main() { - const _2xx = read('templates/2xx.html'); - const _4xx = read('templates/4xx.html'); - const _5xx = read('templates/5xx.html'); - - const pattern = /` - }); - } - - return; - } - - if (preload_error) { - handle_error(req, res, preload_error.statusCode, preload_error.message); - return; - } - - const serialized = { - preloaded: `[${preloaded.map(data => try_serialize(data)).join(',')}]`, - store: store && try_serialize(store.get()) - }; - - const segments = req.path.split('/').filter(Boolean); - - const props: Props = { - path: req.path, - query: req.query, - params: {}, - child: null - }; - - if (error) { - props.error = error instanceof Error ? error : { message: error }; - props.status = status; - } - - const data = Object.assign({}, props, preloaded[0], { - params: {}, - child: { - segment: segments[0] - } - }); - - let level = data.child; - for (let i = 0; i < page.parts.length; i += 1) { - const part = page.parts[i]; - if (!part) continue; - - const get_params = part.params || (() => ({})); - - Object.assign(level, { - component: part.component, - props: Object.assign({}, props, { - params: get_params(match) - }, preloaded[i + 1]) - }); - - level.props.child = { - segment: segments[i + 1] - }; - level = level.props.child; - } - - const { html, head, css } = manifest.root.render(data, { - store - }); - - let scripts = [] - .concat(chunks.main) // chunks main might be an array. it might not! thanks, webpack - .filter(file => !file.match(/\.map$/)) - .map(file => ``) - .join(''); - - let inline_script = `__SAPPER__={${[ - error && `error:1`, - `baseUrl:"${req.baseUrl}"`, - serialized.preloaded && `preloaded:${serialized.preloaded}`, - serialized.store && `store:${serialized.store}` - ].filter(Boolean).join(',')}};`; - - const has_service_worker = fs.existsSync(path.join(locations.dest(), 'service-worker.js')); - if (has_service_worker) { - inline_script += `if ('serviceWorker' in navigator) navigator.serviceWorker.register('${req.baseUrl}/service-worker.js');`; - } - - const body = template() - .replace('%sapper.base%', () => ``) - .replace('%sapper.scripts%', () => `${scripts}`) - .replace('%sapper.html%', () => html) - .replace('%sapper.head%', () => `${head}`) - .replace('%sapper.styles%', () => (css && css.code ? `` : '')); - - res.statusCode = status; - res.end(body); - - if (process.send) { - process.send({ - __sapper__: true, - event: 'file', - url: req.url, - method: req.method, - status, - type: 'text/html', - body - }); - } - }).catch(err => { - if (error) { - // we encountered an error while rendering the error page — oops - res.statusCode = 500; - res.end(`
${escape_html(err.message)}
`); - } else { - handle_error(req, res, 500, err); - } - }); - } - - return function find_route(req: Req, res: ServerResponse, next: () => void) { - if (req[IGNORE]) return next(); - - if (!server_routes.some(route => route.pattern.test(req.path))) { - for (const page of pages) { - if (page.pattern.test(req.path)) { - handle_page(page, req, res); - return; - } - } - } - - handle_error(req, res, 404, 'Not found'); - }; -} - -function compose_handlers(handlers: Handler[]) { - return (req: Req, res: ServerResponse, next: () => void) => { - let i = 0; - function go() { - const handler = handlers[i]; - - if (handler) { - handler(req, res, () => { - i += 1; - go(); - }); - } else { - next(); - } - } - - go(); - }; -} - -function try_serialize(data: any) { - try { - return devalue(data); - } catch (err) { - return null; - } -} - -function escape_html(html: string) { - const chars: Record = { - '"' : 'quot', - "'": '#39', - '&': 'amp', - '<' : 'lt', - '>' : 'gt' - }; - - return html.replace(/["'&<>]/g, c => `&${chars[c]};`); -} diff --git a/src/runtime/index.ts b/src/runtime/index.ts deleted file mode 100644 index 8e74336..0000000 --- a/src/runtime/index.ts +++ /dev/null @@ -1,477 +0,0 @@ -import { detach, findAnchor, scroll_state, which } from './utils'; -import { Component, ComponentConstructor, Params, Query, Redirect, Manifest, RouteData, ScrollPosition, Store, Target } from './interfaces'; - -const initial_data = typeof window !== 'undefined' && window.__SAPPER__; - -export let root: Component; -let target: Node; -let store: Store; -let manifest: Manifest; -let segments: string[] = []; - -type RootProps = { - path: string; - params: Record; - query: Record; - child: Child; -}; - -type Child = { - segment?: string; - props?: any; - component?: Component; -}; - -const root_props: RootProps = { - path: null, - params: null, - query: null, - child: { - segment: null, - component: null, - props: {} - } -}; - -export { root as component }; // legacy reasons — drop in a future version - -const history = typeof window !== 'undefined' ? window.history : { - pushState: (state: any, title: string, href: string) => {}, - replaceState: (state: any, title: string, href: string) => {}, - scrollRestoration: '' -}; - -const scroll_history: Record = {}; -let uid = 1; -let cid: number; - -if ('scrollRestoration' in history) { - history.scrollRestoration = 'manual'; -} - -function select_route(url: URL): Target { - if (url.origin !== window.location.origin) return null; - if (!url.pathname.startsWith(initial_data.baseUrl)) return null; - - const path = url.pathname.slice(initial_data.baseUrl.length); - - // avoid accidental clashes between server routes and pages - if (manifest.ignore.some(pattern => pattern.test(path))) return; - - for (let i = 0; i < manifest.pages.length; i += 1) { - const page = manifest.pages[i]; - - const match = page.pattern.exec(path); - if (match) { - const query: Record = {}; - if (url.search.length > 0) { - url.search.slice(1).split('&').forEach(searchParam => { - const [, key, value] = /([^=]+)=(.*)/.exec(searchParam); - query[key] = value || true; - }); - } - return { url, path, page, match, query }; - } - } -} - -let current_token: {}; - -function render(data: any, nullable_depth: number, scroll: ScrollPosition, token: {}) { - if (current_token !== token) return; - - if (root) { - // first, clear out highest-level root component - let level = data.child; - for (let i = 0; i < nullable_depth; i += 1) { - if (i === nullable_depth) break; - level = level.props.child; - } - - const { component } = level; - level.component = null; - root.set({ child: data.child }); - - // then render new stuff - level.component = component; - root.set(data); - } else { - // first load — remove SSR'd contents - const start = document.querySelector('#sapper-head-start'); - const end = document.querySelector('#sapper-head-end'); - - if (start && end) { - while (start.nextSibling !== end) detach(start.nextSibling); - detach(start); - detach(end); - } - - Object.assign(data, root_data); - - root = new manifest.root({ - target, - data, - store, - hydrate: true - }); - } - - if (scroll) { - window.scrollTo(scroll.x, scroll.y); - } - - Object.assign(root_props, data); - ready = true; -} - -function changed(a: Record, b: Record) { - return JSON.stringify(a) !== JSON.stringify(b); -} - -let root_preload: Promise; -let root_data: any; - -function prepare_page(target: Target): Promise<{ - redirect?: Redirect; - data?: any; - nullable_depth?: number; -}> { - const { page, path, query } = target; - const new_segments = path.split('/').filter(Boolean); - let changed_from = 0; - - while ( - segments[changed_from] && - new_segments[changed_from] && - segments[changed_from] === new_segments[changed_from] - ) changed_from += 1; - - let redirect: Redirect = null; - let error: { statusCode: number, message: Error | string } = null; - - const preload_context = { - store, - fetch: (url: string, opts?: any) => window.fetch(url, opts), - redirect: (statusCode: number, location: string) => { - if (redirect && (redirect.statusCode !== statusCode || redirect.location !== location)) { - throw new Error(`Conflicting redirects`); - } - redirect = { statusCode, location }; - }, - error: (statusCode: number, message: Error | string) => { - error = { statusCode, message }; - } - }; - - if (!root_preload) { - root_preload = manifest.root.preload - ? initial_data.preloaded[0] || manifest.root.preload.call(preload_context, { - path, - query, - params: {} - }) - : {}; - } - - return Promise.all(page.parts.map(async (part, i) => { - if (i < changed_from) return null; - if (!part) return null; - - const { default: Component } = await part.component(); - const req = { - path, - query, - params: part.params ? part.params(target.match) : {} - }; - - const preloaded = ready || !initial_data.preloaded[i + 1] - ? Component.preload ? await Component.preload.call(preload_context, req) : {} - : initial_data.preloaded[i + 1]; - - return { Component, preloaded }; - })).catch(err => { - error = { statusCode: 500, message: err }; - return []; - }).then(async results => { - if (!root_data) root_data = await root_preload; - - if (redirect) { - return { redirect }; - } - - segments = new_segments; - - const get_params = page.parts[page.parts.length - 1].params || (() => ({})); - const params = get_params(target.match); - - if (error) { - const props = { - path, - query, - params, - error: typeof error.message === 'string' ? new Error(error.message) : error.message, - status: error.statusCode - }; - - return { - data: Object.assign({}, props, { - preloading: false, - child: { - component: manifest.error, - props - } - }) - }; - } - - const props = { path, query }; - const data = { - path, - preloading: false, - child: Object.assign({}, root_props.child, { - segment: segments[0] - }) - }; - if (changed(query, root_props.query)) data.query = query; - if (changed(params, root_props.params)) data.params = params; - - let level = data.child; - let nullable_depth = 0; - - for (let i = 0; i < page.parts.length; i += 1) { - const part = page.parts[i]; - if (!part) continue; - - const get_params = part.params || (() => ({})); - - if (i < changed_from) { - level.props.path = path; - level.props.query = query; - level.props.child = Object.assign({}, level.props.child); - - nullable_depth += 1; - } else { - level.component = results[i].Component; - level.props = Object.assign({}, level.props, props, { - params: get_params(target.match), - }, results[i].preloaded); - - level.props.child = {}; - } - - level = level.props.child; - level.segment = segments[i + 1]; - } - - return { data, nullable_depth }; - }); -} - -async function navigate(target: Target, id: number): Promise { - if (id) { - // popstate or initial navigation - cid = id; - } else { - // clicked on a link. preserve scroll state - scroll_history[cid] = scroll_state(); - - id = cid = ++uid; - scroll_history[cid] = { x: 0, y: 0 }; - } - - cid = id; - - if (root) { - root.set({ preloading: true }); - } - const loaded = prefetching && prefetching.href === target.url.href ? - prefetching.promise : - prepare_page(target); - - prefetching = null; - - const token = current_token = {}; - const { redirect, data, nullable_depth } = await loaded; - - if (redirect) { - await goto(redirect.location, { replaceState: true }); - } else { - render(data, nullable_depth, scroll_history[id], token); - if (document.activeElement) document.activeElement.blur(); - } -} - -function handle_click(event: MouseEvent) { - // Adapted from https://github.com/visionmedia/page.js - // MIT license https://github.com/visionmedia/page.js#license - if (which(event) !== 1) return; - if (event.metaKey || event.ctrlKey || event.shiftKey) return; - if (event.defaultPrevented) return; - - const a: HTMLAnchorElement | SVGAElement = findAnchor(event.target); - if (!a) return; - - // check if link is inside an svg - // in this case, both href and target are always inside an object - const svg = typeof a.href === 'object' && a.href.constructor.name === 'SVGAnimatedString'; - const href = String(svg ? (a).href.baseVal : a.href); - - if (href === window.location.href) { - event.preventDefault(); - return; - } - - // Ignore if tag has - // 1. 'download' attribute - // 2. rel='external' attribute - if (a.hasAttribute('download') || a.getAttribute('rel') === 'external') return; - - // Ignore if
has a target - if (svg ? (a).target.baseVal : a.target) return; - - const url = new URL(href); - - // Don't handle hash changes - if (url.pathname === window.location.pathname && url.search === window.location.search) return; - - const target = select_route(url); - if (target) { - navigate(target, null); - event.preventDefault(); - history.pushState({ id: cid }, '', url.href); - } -} - -function handle_popstate(event: PopStateEvent) { - scroll_history[cid] = scroll_state(); - - if (event.state) { - const url = new URL(window.location.href); - const target = select_route(url); - if (target) { - navigate(target, event.state.id); - } else { - window.location.href = window.location.href; - } - } else { - // hashchange - cid = ++uid; - history.replaceState({ id: cid }, '', window.location.href); - } -} - -let prefetching: { - href: string; - promise: Promise<{ redirect?: Redirect, data?: any, nullable_depth?: number }>; -} = null; - -export function prefetch(href: string) { - const target: Target = select_route(new URL(href, document.baseURI)); - - if (target && (!prefetching || href !== prefetching.href)) { - prefetching = { - href, - promise: prepare_page(target) - }; - } -} - -let mousemove_timeout: NodeJS.Timer; - -function handle_mousemove(event: MouseEvent) { - clearTimeout(mousemove_timeout); - mousemove_timeout = setTimeout(() => { - trigger_prefetch(event); - }, 20); -} - -function trigger_prefetch(event: MouseEvent | TouchEvent) { - const a: HTMLAnchorElement = findAnchor(event.target); - if (!a || a.rel !== 'prefetch') return; - - prefetch(a.href); -} - -let inited: boolean; -let ready = false; - -export function init(opts: { - App: ComponentConstructor, - target: Node, - manifest: Manifest, - store?: (data: any) => Store, - routes?: any // legacy -}) { - if (opts instanceof HTMLElement) { - throw new Error(`The signature of init(...) has changed — see https://sapper.svelte.technology/guide#0-11-to-0-12 for more information`); - } - - if (opts.routes) { - throw new Error(`As of Sapper 0.15, opts.routes should be opts.manifest`); - } - - target = opts.target; - manifest = opts.manifest; - - if (opts && opts.store) { - store = opts.store(initial_data.store); - } - - if (!inited) { // this check makes HMR possible - window.addEventListener('click', handle_click); - window.addEventListener('popstate', handle_popstate); - - // prefetch - window.addEventListener('touchstart', trigger_prefetch); - window.addEventListener('mousemove', handle_mousemove); - - inited = true; - } - - return Promise.resolve().then(() => { - const { hash, href } = window.location; - - const deep_linked = hash && document.getElementById(hash.slice(1)); - scroll_history[uid] = deep_linked ? - { x: 0, y: deep_linked.getBoundingClientRect().top } : - scroll_state(); - - history.replaceState({ id: uid }, '', href); - - if (!initial_data.error) { - const target = select_route(new URL(window.location.href)); - if (target) return navigate(target, uid); - } - }); -} - -export function goto(href: string, opts = { replaceState: false }) { - const target = select_route(new URL(href, document.baseURI)); - let promise; - - if (target) { - promise = navigate(target, null); - if (history) history[opts.replaceState ? 'replaceState' : 'pushState']({ id: cid }, '', href); - } else { - window.location.href = href; - promise = new Promise(f => {}); // never resolves - } - - return promise; -} - -export function prefetchRoutes(pathnames: string[]) { - if (!manifest) throw new Error(`You must call init() first`); - - return manifest.pages - .filter(route => { - if (!pathnames) return true; - return pathnames.some(pathname => route.pattern.test(pathname)); - }) - .reduce((promise: Promise, route) => { - return promise.then(route.load); - }, Promise.resolve()); -} - -// remove this in 0.9 -export { prefetchRoutes as preloadRoutes }; \ No newline at end of file diff --git a/src/runtime/utils.ts b/src/runtime/utils.ts deleted file mode 100644 index cec5f69..0000000 --- a/src/runtime/utils.ts +++ /dev/null @@ -1,19 +0,0 @@ -export function detach(node: Node) { - node.parentNode.removeChild(node); -} - -export function findAnchor(node: Node) { - while (node && node.nodeName.toUpperCase() !== 'A') node = node.parentNode; // SVG elements have a lowercase name - return node; -} - -export function which(event: MouseEvent) { - return event.which === null ? event.button : event.which; -} - -export function scroll_state() { - return { - x: window.scrollX, - y: window.scrollY - }; -} \ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..43bbad6 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,119 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +export function left_pad(str: string, len: number) { + while (str.length < len) str = ` ${str}`; + return str; +} + +export function repeat(str: string, i: number) { + let result = ''; + while (i--) result += str; + return result; +} + +export function format_milliseconds(ms: number) { + if (ms < 1000) return `${ms}ms`; + if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`; + + const minutes = ~~(ms / 60000); + const seconds = Math.round((ms % 60000) / 1000); + return `${minutes}m${seconds < 10 ? '0' : ''}${seconds}s`; +} + +export function elapsed(start: number) { + return format_milliseconds(Date.now() - start); +} + +export function walk(cwd: string, dir = cwd, files: string[] = []) { + fs.readdirSync(dir).forEach(file => { + const resolved = path.resolve(dir, file); + if (fs.statSync(resolved).isDirectory()) { + walk(cwd, resolved, files); + } else { + files.push(posixify(path.relative(cwd, resolved))); + } + }); + + return files; +} + +export function posixify(str: string) { + return str.replace(/\\/g, '/'); +} + +const previous_contents = new Map(); + +export function write_if_changed(file: string, code: string) { + if (code !== previous_contents.get(file)) { + previous_contents.set(file, code); + fs.writeFileSync(file, code); + fudge_mtime(file); + } +} + +export function stringify(string: string, includeQuotes: boolean = true) { + const quoted = JSON.stringify(string); + return includeQuotes ? quoted : quoted.slice(1, -1); +} + +export function fudge_mtime(file: string) { + // need to fudge the mtime so that webpack doesn't go doolally + const { atime, mtime } = fs.statSync(file); + fs.utimesSync( + file, + new Date(atime.getTime() - 999999), + new Date(mtime.getTime() - 999999) + ); +} + +export const reserved_words = new Set([ + 'arguments', + 'await', + 'break', + 'case', + 'catch', + 'class', + 'const', + 'continue', + 'debugger', + 'default', + 'delete', + 'do', + 'else', + 'enum', + 'eval', + 'export', + 'extends', + 'false', + 'finally', + 'for', + 'function', + 'if', + 'implements', + 'import', + 'in', + 'instanceof', + 'interface', + 'let', + 'new', + 'null', + 'package', + 'private', + 'protected', + 'public', + 'return', + 'static', + 'super', + 'switch', + 'this', + 'throw', + 'true', + 'try', + 'typeof', + 'var', + 'void', + 'while', + 'with', + 'yield', +]); \ No newline at end of file diff --git a/templates/src/client/app.ts b/templates/src/client/app.ts new file mode 100644 index 0000000..8461d3d --- /dev/null +++ b/templates/src/client/app.ts @@ -0,0 +1,389 @@ +import RootComponent from '__ROOT__'; +import ErrorComponent from '__ERROR__'; +import { + Target, + ScrollPosition, + Component, + Redirect, + ComponentLoader, + ComponentConstructor, + RootProps, + Page +} from './types'; +import goto from './goto'; + +const ignore = __IGNORE__; +export const components: ComponentLoader[] = __COMPONENTS__; +export const pages: Page[] = __PAGES__; + +let ready = false; +let root_component: Component; +let segments: string[] = []; +let current_token: {}; +let root_preload: Promise; +let root_data: any; + +const root_props: RootProps = { + path: null, + params: null, + query: null, + child: { + segment: null, + component: null, + props: {} + } +}; + +export let prefetching: { + href: string; + promise: Promise<{ redirect?: Redirect, data?: any, nullable_depth?: number }>; +} = null; +export function set_prefetching(href, promise) { + prefetching = { href, promise }; +} + +export let store; +export function set_store(fn) { + store = fn(initial_data.store); +} + +export let target: Node; +export function set_target(element) { + target = element; +} + +export let uid = 1; +export function set_uid(n) { + uid = n; +} + +export let cid: number; +export function set_cid(n) { + cid = n; +} + +export const initial_data = typeof __SAPPER__ !== 'undefined' && __SAPPER__; + +const _history = typeof history !== 'undefined' ? history : { + pushState: (state: any, title: string, href: string) => {}, + replaceState: (state: any, title: string, href: string) => {}, + scrollRestoration: '' +}; +export { _history as history }; + +export const scroll_history: Record = {}; + +export function select_route(url: URL): Target { + if (url.origin !== location.origin) return null; + if (!url.pathname.startsWith(initial_data.baseUrl)) return null; + + const path = url.pathname.slice(initial_data.baseUrl.length); + + // avoid accidental clashes between server routes and pages + if (ignore.some(pattern => pattern.test(path))) return; + + for (let i = 0; i < pages.length; i += 1) { + const page = pages[i]; + + const match = page.pattern.exec(path); + if (match) { + const query: Record = Object.create(null); + if (url.search.length > 0) { + url.search.slice(1).split('&').forEach(searchParam => { + let [, key, value] = /([^=]*)(?:=(.*))?/.exec(decodeURIComponent(searchParam)); + value = (value || '').replace(/\+/g, ' '); + if (typeof query[key] === 'string') query[key] = [query[key]]; + if (typeof query[key] === 'object') query[key].push(value); + else query[key] = value; + }); + } + return { url, path, page, match, query }; + } + } +} + +export function scroll_state() { + return { + x: pageXOffset, + y: pageYOffset + }; +} + +export function navigate(target: Target, id: number, noscroll?: boolean, hash?: string): Promise { + let scroll: ScrollPosition; + if (id) { + // popstate or initial navigation + cid = id; + } else { + const current_scroll = scroll_state(); + + // clicked on a link. preserve scroll state + scroll_history[cid] = current_scroll; + + id = cid = ++uid; + scroll_history[cid] = noscroll ? current_scroll : { x: 0, y: 0 }; + } + + cid = id; + + if (root_component) { + root_component.set({ preloading: true }); + } + const loaded = prefetching && prefetching.href === target.url.href ? + prefetching.promise : + prepare_page(target); + + prefetching = null; + + const token = current_token = {}; + + return loaded.then(({ redirect, data, nullable_depth }) => { + if (redirect) { + return goto(redirect.location, { replaceState: true }); + } + render(data, nullable_depth, scroll_history[id], noscroll, hash, token); + if (document.activeElement) document.activeElement.blur(); + }); +} + +function render(data: any, nullable_depth: number, scroll: ScrollPosition, noscroll: boolean, hash: string, token: {}) { + if (current_token !== token) return; + + if (root_component) { + // first, clear out highest-level root component + let level = data.child; + for (let i = 0; i < nullable_depth; i += 1) { + if (i === nullable_depth) break; + level = level.props.child; + } + + const { component } = level; + level.component = null; + root_component.set({ child: data.child }); + + // then render new stuff + level.component = component; + root_component.set(data); + } else { + // first load — remove SSR'd contents + const start = document.querySelector('#sapper-head-start'); + const end = document.querySelector('#sapper-head-end'); + + if (start && end) { + while (start.nextSibling !== end) detach(start.nextSibling); + detach(start); + detach(end); + } + + Object.assign(data, root_data); + + root_component = new RootComponent({ + target, + data, + store, + hydrate: true + }); + } + + if (!noscroll) { + if (hash) { + // scroll is an element id (from a hash), we need to compute y. + const deep_linked = document.querySelector(hash); + if (deep_linked) { + scroll = { + x: 0, + y: deep_linked.getBoundingClientRect().top + }; + } + } + + scroll_history[cid] = scroll; + if (scroll) scrollTo(scroll.x, scroll.y); + } + + Object.assign(root_props, data); + ready = true; +} + +export function prepare_page(target: Target): Promise<{ + redirect?: Redirect; + data?: any; + nullable_depth?: number; +}> { + const { page, path, query } = target; + const new_segments = path.split('/').filter(Boolean); + let changed_from = 0; + + while ( + segments[changed_from] && + new_segments[changed_from] && + segments[changed_from] === new_segments[changed_from] + ) changed_from += 1; + + let redirect: Redirect = null; + let error: { statusCode: number, message: Error | string } = null; + + const preload_context = { + store, + fetch: (url: string, opts?: any) => fetch(url, opts), + redirect: (statusCode: number, location: string) => { + if (redirect && (redirect.statusCode !== statusCode || redirect.location !== location)) { + throw new Error(`Conflicting redirects`); + } + redirect = { statusCode, location }; + }, + error: (statusCode: number, message: Error | string) => { + error = { statusCode, message }; + } + }; + + if (!root_preload) { + root_preload = RootComponent.preload + ? initial_data.preloaded[0] || RootComponent.preload.call(preload_context, { + path, + query, + params: {} + }) + : {}; + } + + return Promise.all(page.parts.map((part, i) => { + if (i < changed_from) return null; + if (!part) return null; + + return load_component(components[part.i]).then(Component => { + const req = { + path, + query, + params: part.params ? part.params(target.match) : {} + }; + + let preloaded; + if (ready || !initial_data.preloaded[i + 1]) { + preloaded = Component.preload + ? Component.preload.call(preload_context, req) + : {}; + } else { + preloaded = initial_data.preloaded[i + 1]; + } + + return Promise.resolve(preloaded).then(preloaded => { + return { Component, preloaded }; + }); + }); + })).catch(err => { + error = { statusCode: 500, message: err }; + return []; + }).then(results => { + if (root_data) { + return results; + } else { + return Promise.resolve(root_preload).then(value => { + root_data = value; + return results; + }); + } + }).then(results => { + if (redirect) { + return { redirect }; + } + + segments = new_segments; + + const get_params = page.parts[page.parts.length - 1].params || (() => ({})); + const params = get_params(target.match); + + if (error) { + const props = { + path, + query, + params, + error: typeof error.message === 'string' ? new Error(error.message) : error.message, + status: error.statusCode + }; + + return { + data: Object.assign({}, props, { + preloading: false, + child: { + component: ErrorComponent, + props + } + }) + }; + } + + const props = { path, query, error: null, status: null }; + const data = { + path, + preloading: false, + child: Object.assign({}, root_props.child, { + segment: segments[0] + }) + }; + if (changed(query, root_props.query)) data.query = query; + if (changed(params, root_props.params)) data.params = params; + + let level = data.child; + let nullable_depth = 0; + + for (let i = 0; i < page.parts.length; i += 1) { + const part = page.parts[i]; + if (!part) continue; + + const get_params = part.params || (() => ({})); + + if (i < changed_from) { + level.props.path = path; + level.props.query = query; + level.props.child = Object.assign({}, level.props.child); + + nullable_depth += 1; + } else { + level.component = results[i].Component; + level.props = Object.assign({}, level.props, props, { + params: get_params(target.match), + }, results[i].preloaded); + + level.props.child = {}; + } + + level = level.props.child; + level.segment = segments[i + 1]; + } + + return { data, nullable_depth }; + }); +} + +function load_css(chunk: string) { + const href = `client/${chunk}`; + if (document.querySelector(`link[href="${href}"]`)) return; + + return new Promise((fulfil, reject) => { + const link = document.createElement('link'); + link.rel = 'stylesheet'; + link.href = href; + + link.onload = () => fulfil(); + link.onerror = reject; + + document.head.appendChild(link); + }); +} + +export function load_component(component: ComponentLoader): Promise { + // TODO this is temporary — once placeholders are + // always rewritten, scratch the ternary + const promises: Array> = (typeof component.css === 'string' ? [] : component.css.map(load_css)); + promises.unshift(component.js()); + return Promise.all(promises).then(values => values[0].default); +} + +function detach(node: Node) { + node.parentNode.removeChild(node); +} + +function changed(a: Record, b: Record) { + return JSON.stringify(a) !== JSON.stringify(b); +} \ No newline at end of file diff --git a/templates/src/client/goto/index.ts b/templates/src/client/goto/index.ts new file mode 100644 index 0000000..29757ed --- /dev/null +++ b/templates/src/client/goto/index.ts @@ -0,0 +1,13 @@ +import { history, select_route, navigate, cid } from '../app'; + +export default function goto(href: string, opts = { replaceState: false }) { + const target = select_route(new URL(href, document.baseURI)); + + if (target) { + history[opts.replaceState ? 'replaceState' : 'pushState']({ id: cid }, '', href); + return navigate(target, null).then(() => {}); + } + + location.href = href; + return new Promise(f => {}); // never resolves +} \ No newline at end of file diff --git a/templates/src/client/index.ts b/templates/src/client/index.ts new file mode 100644 index 0000000..f171109 --- /dev/null +++ b/templates/src/client/index.ts @@ -0,0 +1,4 @@ +export { default as start } from './start/index'; +export { default as goto } from './goto/index'; +export { default as prefetch } from './prefetch/index'; +export { default as prefetchRoutes } from './prefetchRoutes/index'; \ No newline at end of file diff --git a/templates/src/client/prefetch/index.ts b/templates/src/client/prefetch/index.ts new file mode 100644 index 0000000..cd22c63 --- /dev/null +++ b/templates/src/client/prefetch/index.ts @@ -0,0 +1,14 @@ +import { select_route, prefetching, set_prefetching, prepare_page } from '../app'; +import { Target } from '../types'; + +export default function prefetch(href: string) { + const target: Target = select_route(new URL(href, document.baseURI)); + + if (target) { + if (!prefetching || href !== prefetching.href) { + set_prefetching(href, prepare_page(target)); + } + + return prefetching.promise; + } +} \ No newline at end of file diff --git a/templates/src/client/prefetchRoutes/index.ts b/templates/src/client/prefetchRoutes/index.ts new file mode 100644 index 0000000..b3c2f3c --- /dev/null +++ b/templates/src/client/prefetchRoutes/index.ts @@ -0,0 +1,12 @@ +import { components, pages, load_component } from "../app"; + +export default function prefetchRoutes(pathnames: string[]) { + return pages + .filter(route => { + if (!pathnames) return true; + return pathnames.some(pathname => route.pattern.test(pathname)); + }) + .reduce((promise: Promise, route) => promise.then(() => { + return Promise.all(route.parts.map(part => part && load_component(components[part.i]))); + }), Promise.resolve()); +} \ No newline at end of file diff --git a/templates/src/client/start/index.ts b/templates/src/client/start/index.ts new file mode 100644 index 0000000..99c01e9 --- /dev/null +++ b/templates/src/client/start/index.ts @@ -0,0 +1,134 @@ +import { + cid, + history, + initial_data, + navigate, + scroll_history, + scroll_state, + select_route, + set_store, + set_target, + uid, + set_uid, + set_cid +} from '../app'; +import prefetch from '../prefetch/index'; +import { Store, ScrollPosition } from '../types'; + +export default function start(opts: { + target: Node, + store?: (data: any) => Store +}) { + if ('scrollRestoration' in history) { + history.scrollRestoration = 'manual'; + } + + set_target(opts.target); + if (opts.store) set_store(opts.store); + + addEventListener('click', handle_click); + addEventListener('popstate', handle_popstate); + + // prefetch + addEventListener('touchstart', trigger_prefetch); + addEventListener('mousemove', handle_mousemove); + + return Promise.resolve().then(() => { + const { hash, href } = location; + + history.replaceState({ id: uid }, '', href); + + if (!initial_data.error) { + const target = select_route(new URL(location.href)); + if (target) return navigate(target, uid, false, hash); + } + }); +} + +let mousemove_timeout: NodeJS.Timer; + +function handle_mousemove(event: MouseEvent) { + clearTimeout(mousemove_timeout); + mousemove_timeout = setTimeout(() => { + trigger_prefetch(event); + }, 20); +} + +function trigger_prefetch(event: MouseEvent | TouchEvent) { + const a: HTMLAnchorElement = find_anchor(event.target); + if (!a || a.rel !== 'prefetch') return; + + prefetch(a.href); +} + +function handle_click(event: MouseEvent) { + // Adapted from https://github.com/visionmedia/page.js + // MIT license https://github.com/visionmedia/page.js#license + if (which(event) !== 1) return; + if (event.metaKey || event.ctrlKey || event.shiftKey) return; + if (event.defaultPrevented) return; + + const a: HTMLAnchorElement | SVGAElement = find_anchor(event.target); + if (!a) return; + + if (!a.href) return; + + // check if link is inside an svg + // in this case, both href and target are always inside an object + const svg = typeof a.href === 'object' && a.href.constructor.name === 'SVGAnimatedString'; + const href = String(svg ? (a).href.baseVal : a.href); + + if (href === location.href) { + if (!location.hash) event.preventDefault(); + return; + } + + // Ignore if tag has + // 1. 'download' attribute + // 2. rel='external' attribute + if (a.hasAttribute('download') || a.getAttribute('rel') === 'external') return; + + // Ignore if has a target + if (svg ? (a).target.baseVal : a.target) return; + + const url = new URL(href); + + // Don't handle hash changes + if (url.pathname === location.pathname && url.search === location.search) return; + + const target = select_route(url); + if (target) { + const noscroll = a.hasAttribute('sapper-noscroll'); + navigate(target, null, noscroll, url.hash); + event.preventDefault(); + history.pushState({ id: cid }, '', url.href); + } +} + +function which(event: MouseEvent) { + return event.which === null ? event.button : event.which; +} + +function find_anchor(node: Node) { + while (node && node.nodeName.toUpperCase() !== 'A') node = node.parentNode; // SVG elements have a lowercase name + return node; +} + +function handle_popstate(event: PopStateEvent) { + scroll_history[cid] = scroll_state(); + + if (event.state) { + const url = new URL(location.href); + const target = select_route(url); + if (target) { + navigate(target, event.state.id); + } else { + location.href = location.href; + } + } else { + // hashchange + set_uid(uid + 1); + set_cid(uid); + history.replaceState({ id: cid }, '', location.href); + } +} \ No newline at end of file diff --git a/src/runtime/interfaces.ts b/templates/src/client/types.ts similarity index 69% rename from src/runtime/interfaces.ts rename to templates/src/client/types.ts index 5fbc381..2a28582 100644 --- a/src/runtime/interfaces.ts +++ b/templates/src/client/types.ts @@ -1,10 +1,20 @@ -import { Store } from '../interfaces'; - -export { Store }; export type Params = Record; export type Query = Record; export type RouteData = { params: Params, query: Query, path: string }; +type Child = { + segment?: string; + props?: any; + component?: Component; +}; + +export type RootProps = { + path: string; + params: Record; + query: Record; + child: Child; +}; + export interface ComponentConstructor { new (options: { target: Node, data: any, store: Store, hydrate: boolean }): Component; preload: (props: { params: Params, query: Query }) => Promise; @@ -15,10 +25,15 @@ export interface Component { destroy: () => void; } +export type ComponentLoader = { + js: () => Promise<{ default: ComponentConstructor }>, + css: string[] +}; + export type Page = { pattern: RegExp; parts: Array<{ - component: () => Promise<{ default: ComponentConstructor }>; + i: number; params?: (match: RegExpExecArray) => Record; }>; }; @@ -40,10 +55,14 @@ export type Target = { path: string; page: Page; match: RegExpExecArray; - query: Record; + query: Record; }; export type Redirect = { statusCode: number; location: string; -}; \ No newline at end of file +}; + +export type Store = { + get: () => any; +} \ No newline at end of file diff --git a/templates/src/server/index.ts b/templates/src/server/index.ts new file mode 100644 index 0000000..f6706ca --- /dev/null +++ b/templates/src/server/index.ts @@ -0,0 +1 @@ +export { default as middleware } from './middleware/index'; \ No newline at end of file diff --git a/templates/src/server/middleware/get_page_handler.ts b/templates/src/server/middleware/get_page_handler.ts new file mode 100644 index 0000000..67405ba --- /dev/null +++ b/templates/src/server/middleware/get_page_handler.ts @@ -0,0 +1,359 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import cookie from 'cookie'; +import devalue from 'devalue'; +import fetch from 'node-fetch'; +import { URL, resolve } from 'url'; +import { build_dir, dev, src_dir, IGNORE } from '../placeholders'; +import { Manifest, Page, Props, Req, Res, Store } from './types'; + +export function get_page_handler( + manifest: Manifest, + store_getter: (req: Req, res: Res) => Store +) { + const get_build_info = dev + ? () => JSON.parse(fs.readFileSync(path.join(build_dir, 'build.json'), 'utf-8')) + : (assets => () => assets)(JSON.parse(fs.readFileSync(path.join(build_dir, 'build.json'), 'utf-8'))); + + const template = dev + ? () => read_template(src_dir) + : (str => () => str)(read_template(build_dir)); + + const has_service_worker = fs.existsSync(path.join(build_dir, 'service-worker.js')); + + const { server_routes, pages } = manifest; + const error_route = manifest.error; + + function handle_error(req: Req, res: Res, statusCode: number, error: Error | string) { + handle_page({ + pattern: null, + parts: [ + { name: null, component: error_route } + ] + }, req, res, statusCode, error || new Error('Unknown error in preload function')); + } + + async function handle_page(page: Page, req: Req, res: Res, status = 200, error: Error | string = null) { + const isSWIndexHtml = req.path === '/service-worker-index.html'; + const build_info: { + bundler: 'rollup' | 'webpack', + shimport: string | null, + assets: Record, + legacy_assets?: Record + } = get_build_info(); + + res.setHeader('Content-Type', 'text/html'); + res.setHeader('Cache-Control', dev ? 'no-cache' : 'max-age=600'); + + // preload main.js and current route + // TODO detect other stuff we can preload? images, CSS, fonts? + let preloaded_chunks = Array.isArray(build_info.assets.main) ? build_info.assets.main : [build_info.assets.main]; + if (!error && !isSWIndexHtml) { + page.parts.forEach(part => { + if (!part) return; + + // using concat because it could be a string or an array. thanks webpack! + preloaded_chunks = preloaded_chunks.concat(build_info.assets[part.name]); + }); + } + + if (build_info.bundler === 'rollup') { + // TODO add dependencies and CSS + const link = preloaded_chunks + .filter(file => file && !file.match(/\.map$/)) + .map(file => `<${req.baseUrl}/client/${file}>;rel="modulepreload"`) + .join(', '); + + res.setHeader('Link', link); + } else { + const link = preloaded_chunks + .filter(file => file && !file.match(/\.map$/)) + .map((file) => { + const as = /\.css$/.test(file) ? 'style' : 'script'; + return `<${req.baseUrl}/client/${file}>;rel="preload";as="${as}"`; + }) + .join(', '); + + res.setHeader('Link', link); + } + + const store = store_getter ? store_getter(req, res) : null; + + let redirect: { statusCode: number, location: string }; + let preload_error: { statusCode: number, message: Error | string }; + + const preload_context = { + redirect: (statusCode: number, location: string) => { + if (redirect && (redirect.statusCode !== statusCode || redirect.location !== location)) { + throw new Error(`Conflicting redirects`); + } + location = location.replace(/^\//g, ''); // leading slash (only) + redirect = { statusCode, location }; + }, + error: (statusCode: number, message: Error | string) => { + preload_error = { statusCode, message }; + }, + fetch: (url: string, opts?: any) => { + const parsed = new URL(url, `http://127.0.0.1:${process.env.PORT}${req.baseUrl ? req.baseUrl + '/' :''}`); + + if (opts) { + opts = Object.assign({}, opts); + + const include_cookies = ( + opts.credentials === 'include' || + opts.credentials === 'same-origin' && parsed.origin === `http://127.0.0.1:${process.env.PORT}` + ); + + if (include_cookies) { + if (!opts.headers) opts.headers = {}; + + const cookies = Object.assign( + {}, + cookie.parse(req.headers.cookie || ''), + cookie.parse(opts.headers.cookie || '') + ); + + const set_cookie = res.getHeader('Set-Cookie'); + (Array.isArray(set_cookie) ? set_cookie : [set_cookie]).forEach(str => { + const match = /([^=]+)=([^;]+)/.exec(str); + if (match) cookies[match[1]] = match[2]; + }); + + const str = Object.keys(cookies) + .map(key => `${key}=${cookies[key]}`) + .join('; '); + + opts.headers.cookie = str; + } + } + + return fetch(parsed.href, opts); + }, + store + }; + + let preloaded; + let match; + + try { + const root_preloaded = manifest.root.preload + ? manifest.root.preload.call(preload_context, { + path: req.path, + query: req.query, + params: {} + }) + : {}; + + match = error ? null : page.pattern.exec(req.path); + + let toPreload = [root_preloaded]; + if (!isSWIndexHtml) { + toPreload = toPreload.concat(page.parts.map(part => { + if (!part) return null; + + return part.component.preload + ? part.component.preload.call(preload_context, { + path: req.path, + query: req.query, + params: part.params ? part.params(match) : {} + }) + : {}; + })) + } + + preloaded = await Promise.all(toPreload); + } catch (err) { + preload_error = { statusCode: 500, message: err }; + preloaded = []; // appease TypeScript + } + + try { + if (redirect) { + const location = resolve(req.baseUrl || '/', redirect.location); + + res.statusCode = redirect.statusCode; + res.setHeader('Location', location); + res.end(); + + return; + } + + if (preload_error) { + handle_error(req, res, preload_error.statusCode, preload_error.message); + return; + } + + const serialized = { + preloaded: `[${preloaded.map(data => try_serialize(data)).join(',')}]`, + store: store && try_serialize(store.get()) + }; + + const segments = req.path.split('/').filter(Boolean); + + const props: Props = { + path: req.path, + query: req.query, + params: {}, + child: null + }; + + if (error) { + props.error = error instanceof Error ? error : { message: error }; + props.status = status; + } + + const data = Object.assign({}, props, preloaded[0], { + params: {}, + child: { + segment: segments[0] + } + }); + + let level = data.child; + if (isSWIndexHtml) { + level.props = Object.assign({}, props, { + params: {} + }) + } else { + for (let i = 0; i < page.parts.length; i += 1) { + const part = page.parts[i]; + if (!part) continue; + + const get_params = part.params || (() => ({})); + + Object.assign(level, { + component: part.component, + props: Object.assign({}, props, { + params: get_params(match) + }, preloaded[i + 1]) + }); + + level.props.child = { + segment: segments[i + 1] + }; + level = level.props.child; + } + } + + const { html, head, css } = manifest.root.render(data, { + store + }); + + let script = `__SAPPER__={${[ + error && `error:1`, + `baseUrl:"${req.baseUrl}"`, + serialized.preloaded && `preloaded:${serialized.preloaded}`, + serialized.store && `store:${serialized.store}` + ].filter(Boolean).join(',')}};`; + + if (has_service_worker) { + script += `if('serviceWorker' in navigator)navigator.serviceWorker.register('${req.baseUrl}/service-worker.js');`; + } + + const file = [].concat(build_info.assets.main).filter(file => file && /\.js$/.test(file))[0]; + const main = `${req.baseUrl}/client/${file}`; + + if (build_info.bundler === 'rollup') { + if (build_info.legacy_assets) { + const legacy_main = `${req.baseUrl}/client/legacy/${build_info.legacy_assets.main}`; + script += `(function(){try{eval("async function x(){}");var main="${main}"}catch(e){main="${legacy_main}"};var s=document.createElement("script");try{new Function("if(0)import('')")();s.src=main;s.type="module";s.crossOrigin="use-credentials";}catch(e){s.src="${req.baseUrl}/client/shimport@${build_info.shimport}.js";s.setAttribute("data-main",main);}document.head.appendChild(s);}());`; + } else { + script += `var s=document.createElement("script");try{new Function("if(0)import('')")();s.src="${main}";s.type="module";s.crossOrigin="use-credentials";}catch(e){s.src="${req.baseUrl}/client/shimport@${build_info.shimport}.js";s.setAttribute("data-main","${main}")}document.head.appendChild(s)`; + } + } else { + script += ``) + .replace('%sapper.html%', () => html) + .replace('%sapper.head%', () => `${head}`) + .replace('%sapper.styles%', () => styles); + + res.statusCode = status; + res.end(body); + } catch(err) { + if (error) { + // we encountered an error while rendering the error page — oops + res.statusCode = 500; + res.end(`
${escape_html(err.message)}
`); + } else { + handle_error(req, res, 500, err); + } + } + } + + return function find_route(req: Req, res: Res, next: () => void) { + if (req[IGNORE]) return next(); + + if (req.path === '/service-worker-index.html') { + const homePage = pages.find(page => page.pattern.test('/')); + handle_page(homePage, req, res); + return; + } + + if (!server_routes.some(route => route.pattern.test(req.path))) { + for (const page of pages) { + if (page.pattern.test(req.path)) { + handle_page(page, req, res); + return; + } + } + } + + handle_error(req, res, 404, 'Not found'); + }; +} + +function read_template(dir = build_dir) { + return fs.readFileSync(`${dir}/template.html`, 'utf-8'); +} + +function try_serialize(data: any) { + try { + return devalue(data); + } catch (err) { + return null; + } +} + +function escape_html(html: string) { + const chars: Record = { + '"' : 'quot', + "'": '#39', + '&': 'amp', + '<' : 'lt', + '>' : 'gt' + }; + + return html.replace(/["'&<>]/g, c => `&${chars[c]};`); +} diff --git a/templates/src/server/middleware/get_server_route_handler.ts b/templates/src/server/middleware/get_server_route_handler.ts new file mode 100644 index 0000000..1e2f3db --- /dev/null +++ b/templates/src/server/middleware/get_server_route_handler.ts @@ -0,0 +1,78 @@ +import { IGNORE } from '../placeholders'; +import { Req, Res, ServerRoute } from './types'; + +export function get_server_route_handler(routes: ServerRoute[]) { + async function handle_route(route: ServerRoute, req: Req, res: Res, next: () => void) { + req.params = route.params(route.pattern.exec(req.path)); + + const method = req.method.toLowerCase(); + // 'delete' cannot be exported from a module because it is a keyword, + // so check for 'del' instead + const method_export = method === 'delete' ? 'del' : method; + const handle_method = route.handlers[method_export]; + if (handle_method) { + if (process.env.SAPPER_EXPORT) { + const { write, end, setHeader } = res; + const chunks: any[] = []; + const headers: Record = {}; + + // intercept data so that it can be exported + res.write = function(chunk: any) { + chunks.push(Buffer.from(chunk)); + write.apply(res, arguments); + }; + + res.setHeader = function(name: string, value: string) { + headers[name.toLowerCase()] = value; + setHeader.apply(res, arguments); + }; + + res.end = function(chunk?: any) { + if (chunk) chunks.push(Buffer.from(chunk)); + end.apply(res, arguments); + + process.send({ + __sapper__: true, + event: 'file', + url: req.url, + method: req.method, + status: res.statusCode, + type: headers['content-type'], + body: Buffer.concat(chunks).toString() + }); + }; + } + + const handle_next = (err?: Error) => { + if (err) { + res.statusCode = 500; + res.end(err.message); + } else { + process.nextTick(next); + } + }; + + try { + await handle_method(req, res, handle_next); + } catch (err) { + handle_next(err); + } + } else { + // no matching handler for method + process.nextTick(next); + } + } + + return function find_route(req: Req, res: Res, next: () => void) { + if (req[IGNORE]) return next(); + + for (const route of routes) { + if (route.pattern.test(req.path)) { + handle_route(route, req, res, next); + return; + } + } + + next(); + }; +} \ No newline at end of file diff --git a/templates/src/server/middleware/index.ts b/templates/src/server/middleware/index.ts new file mode 100644 index 0000000..f06942c --- /dev/null +++ b/templates/src/server/middleware/index.ts @@ -0,0 +1,143 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { build_dir, dev, manifest, IGNORE } from '../placeholders'; +import { Handler, Req, Res, Store } from './types'; +import { get_server_route_handler } from './get_server_route_handler'; +import { get_page_handler } from './get_page_handler'; +import { lookup } from './mime'; + +export default function middleware(opts: { + store?: (req: Req, res: Res) => Store, + ignore?: any +} = {}) { + const { store, ignore } = opts; + + let emitted_basepath = false; + + return compose_handlers([ + ignore && ((req: Req, res: Res, next: () => void) => { + req[IGNORE] = should_ignore(req.path, ignore); + next(); + }), + + (req: Req, res: Res, next: () => void) => { + if (req[IGNORE]) return next(); + + if (req.baseUrl === undefined) { + let { originalUrl } = req; + if (req.url === '/' && originalUrl[originalUrl.length - 1] !== '/') { + originalUrl += '/'; + } + + req.baseUrl = originalUrl + ? originalUrl.slice(0, -req.url.length) + : ''; + } + + if (!emitted_basepath && process.send) { + process.send({ + __sapper__: true, + event: 'basepath', + basepath: req.baseUrl + }); + + emitted_basepath = true; + } + + if (req.path === undefined) { + req.path = req.url.replace(/\?.*/, ''); + } + + next(); + }, + + fs.existsSync(path.join(build_dir, 'index.html')) && serve({ + pathname: '/index.html', + cache_control: dev ? 'no-cache' : 'max-age=600' + }), + + fs.existsSync(path.join(build_dir, 'service-worker.js')) && serve({ + pathname: '/service-worker.js', + cache_control: 'no-cache, no-store, must-revalidate' + }), + + fs.existsSync(path.join(build_dir, 'service-worker.js.map')) && serve({ + pathname: '/service-worker.js.map', + cache_control: 'no-cache, no-store, must-revalidate' + }), + + serve({ + prefix: '/client/', + cache_control: dev ? 'no-cache' : 'max-age=31536000, immutable' + }), + + get_server_route_handler(manifest.server_routes), + + get_page_handler(manifest, store) + ].filter(Boolean)); +} + +export function compose_handlers(handlers: Handler[]) { + return (req: Req, res: Res, next: () => void) => { + let i = 0; + function go() { + const handler = handlers[i]; + + if (handler) { + handler(req, res, () => { + i += 1; + go(); + }); + } else { + next(); + } + } + + go(); + }; +} + +export function should_ignore(uri: string, val: any) { + if (Array.isArray(val)) return val.some(x => should_ignore(uri, x)); + if (val instanceof RegExp) return val.test(uri); + if (typeof val === 'function') return val(uri); + return uri.startsWith(val.charCodeAt(0) === 47 ? val : `/${val}`); +} + +export function serve({ prefix, pathname, cache_control }: { + prefix?: string, + pathname?: string, + cache_control: string +}) { + const filter = pathname + ? (req: Req) => req.path === pathname + : (req: Req) => req.path.startsWith(prefix); + + const cache: Map = new Map(); + + const read = dev + ? (file: string) => fs.readFileSync(path.resolve(build_dir, file)) + : (file: string) => (cache.has(file) ? cache : cache.set(file, fs.readFileSync(path.resolve(build_dir, file)))).get(file) + + return (req: Req, res: Res, next: () => void) => { + if (req[IGNORE]) return next(); + + if (filter(req)) { + const type = lookup(req.path); + + try { + const file = decodeURIComponent(req.path.slice(1)); + const data = read(file); + + res.setHeader('Content-Type', type); + res.setHeader('Cache-Control', cache_control); + res.end(data); + } catch (err) { + res.statusCode = 404; + res.end('not found'); + } + } else { + next(); + } + }; +} \ No newline at end of file diff --git a/src/middleware/mime-types.md b/templates/src/server/middleware/mime-types.md similarity index 100% rename from src/middleware/mime-types.md rename to templates/src/server/middleware/mime-types.md diff --git a/src/middleware/mime.ts b/templates/src/server/middleware/mime.ts similarity index 100% rename from src/middleware/mime.ts rename to templates/src/server/middleware/mime.ts diff --git a/templates/src/server/middleware/types.ts b/templates/src/server/middleware/types.ts new file mode 100644 index 0000000..6d7597f --- /dev/null +++ b/templates/src/server/middleware/types.ts @@ -0,0 +1,69 @@ +import { ClientRequest, ServerResponse } from 'http'; + +export type ServerRoute = { + pattern: RegExp; + handlers: Record; + params: (match: RegExpMatchArray) => Record; +}; + +export type Page = { + pattern: RegExp; + parts: Array<{ + name: string; + component: Component; + params?: (match: RegExpMatchArray) => Record; + }> +}; + +export type Manifest = { + server_routes: ServerRoute[]; + pages: Page[]; + root: Component; + error: Component; +} + +export type Handler = (req: Req, res: Res, next: () => void) => void; + +export type Store = { + get: () => any +}; + +export type Props = { + path: string; + query: Record; + params: Record; + error?: { message: string }; + status?: number; + child: { + segment: string; + component: Component; + props: Props; + }; + [key: string]: any; +}; + +export interface Req extends ClientRequest { + url: string; + baseUrl: string; + originalUrl: string; + method: string; + path: string; + params: Record; + query: Record; + headers: Record; +} + +export interface Res extends ServerResponse { + write: (data: any) => void; +} + +export { ServerResponse }; + +interface Component { + render: (data: any, opts: { store: Store }) => { + head: string; + css: { code: string, map: any }; + html: string + }, + preload: (data: any) => any | Promise +} \ No newline at end of file diff --git a/templates/src/server/placeholders.ts b/templates/src/server/placeholders.ts new file mode 100644 index 0000000..b95b5ea --- /dev/null +++ b/templates/src/server/placeholders.ts @@ -0,0 +1,11 @@ +import { Manifest } from './types'; + +export const manifest: Manifest = __MANIFEST__; + +export const build_dir = __BUILD__DIR__; + +export const src_dir = __SRC__DIR__; + +export const dev = __DEV__; + +export const IGNORE = '__SAPPER__IGNORE__'; \ No newline at end of file diff --git a/test/app/.gitignore b/test/app/.gitignore deleted file mode 100644 index 9f3fcfb..0000000 --- a/test/app/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -.DS_Store -node_modules -.sapper -yarn.lock -cypress/screenshots -templates/.* -dist diff --git a/test/app/README.md b/test/app/README.md deleted file mode 100644 index ea2230e..0000000 --- a/test/app/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# sapper-template - -The default [Sapper](https://github.com/sveltejs/sapper) template. To clone it and get started: - -```bash -npx degit sveltejs/sapper-template my-app -cd my-app -npm install # or yarn! -npm run dev -``` - -Open up [localhost:3000](http://localhost:3000) and start clicking around. - - -## Structure - -Sapper expects to find three directories in the root of your project — `assets`, `routes` and `templates`. - - -### assets - -The [assets](assets) directory contains any static assets that should be available. These are served using [serve-static](https://github.com/expressjs/serve-static). - -In your [service-worker.js](templates/service-worker.js) file, Sapper makes these files available as `__assets__` so that you can cache them (though you can choose not to, for example if you don't want to cache very large files). - - -### routes - -This is the heart of your Sapper app. There are two kinds of routes — *pages*, and *server routes*. - -**Pages** are Svelte components written in `.html` files. When a user first visits the application, they will be served a server-rendered version of the route in question, plus some JavaScript that 'hydrates' the page and initialises a client-side router. From that point forward, navigating to other pages is handled entirely on the client for a fast, app-like feel. (Sapper will preload and cache the code for these subsequent pages, so that navigation is instantaneous.) - -**Server routes** are modules written in `.js` files, that export functions corresponding to HTTP methods. Each function receives Express `request` and `response` objects as arguments, plus a `next` function. This is useful for creating a JSON API, for example. - -There are three simple rules for naming the files that define your routes: - -* A file called `routes/about.html` corresponds to the `/about` route. A file called `routes/blog/[slug].html` corresponds to the `/blog/:slug` route, in which case `params.slug` is available to the route -* The file `routes/index.html` (or `routes/index.js`) corresponds to the root of your app. `routes/about/index.html` is treated the same as `routes/about.html`. -* Files and directories with a leading underscore do *not* create routes. This allows you to colocate helper modules and components with the routes that depend on them — for example you could have a file called `routes/_helpers/datetime.js` and it would *not* create a `/_helpers/datetime` route - - -### templates - -This directory should contain the following files at a minimum: - -* [2xx.html](templates/2xx.html) — a template for the page to serve for valid requests -* [4xx.html](templates/4xx.html) — a template for 4xx-range errors (such as 404 Not Found) -* [5xx.html](templates/5xx.html) — a template for 5xx-range errors (such as 500 Internal Server Error) -* [main.js](templates/main.js) — this module initialises Sapper -* [service-worker.js](templates/service-worker.js) — your app's service worker - -Inside the HTML templates, Sapper will inject various values as indicated by `%sapper.xxxx%` tags. Inside JavaScript files, Sapper will replace strings like `__dev__` with the appropriate value. - -In lieu of documentation (bear with us), consult the files to see what variables are available and how they're used. - - -## Webpack config - -Sapper uses webpack to provide code-splitting, dynamic imports and hot module reloading, as well as compiling your Svelte components. As long as you don't do anything daft, you can edit the configuration files to add whatever loaders and plugins you'd like. - - -## Production mode and deployment - -To start a production version of your app, run `npm start`. This will disable hot module replacement, and activate the appropriate webpack plugins. - -You can deploy your application to any environment that supports Node 8 or above. As an example, to deploy to [Now](https://zeit.co/now), run these commands: - -```bash -npm install -g now -now -``` - - -## Bugs and feedback - -Sapper is in early development, and may have the odd rough edge here and there. Please be vocal over on the [Sapper issue tracker](https://github.com/sveltejs/sapper/issues). - - -## License - -[LIL](LICENSE) diff --git a/test/app/app/client.js b/test/app/app/client.js deleted file mode 100644 index 2ca0ebe..0000000 --- a/test/app/app/client.js +++ /dev/null @@ -1,13 +0,0 @@ -import { init, prefetchRoutes } from '../../../runtime.js'; -import { Store } from 'svelte/store.js'; -import { manifest } from './manifest/client.js'; - -window.init = () => { - return init({ - target: document.querySelector('#sapper'), - manifest, - store: data => new Store(data) - }); -}; - -window.prefetchRoutes = prefetchRoutes; \ No newline at end of file diff --git a/test/app/app/server.js b/test/app/app/server.js deleted file mode 100644 index f09d318..0000000 --- a/test/app/app/server.js +++ /dev/null @@ -1,121 +0,0 @@ -import fs from 'fs'; -import { resolve } from 'url'; -import express from 'express'; -import serve from 'serve-static'; -import sapper from '../../../dist/middleware.ts.js'; -import { Store } from 'svelte/store.js'; -import { manifest } from './manifest/server.js'; - -let pending; -let ended; - -process.on('message', message => { - if (message.action === 'start') { - if (pending) { - throw new Error(`Already capturing`); - } - - pending = new Set(); - ended = false; - process.send({ type: 'ready' }); - } - - if (message.action === 'end') { - ended = true; - if (pending.size === 0) { - process.send({ type: 'done' }); - pending = null; - } - } -}); - -const app = express(); - -const { PORT = 3000, BASEPATH = '' } = process.env; -const base = `http://localhost:${PORT}${BASEPATH}/`; - -// this allows us to do e.g. `fetch('/api/blog')` on the server -const fetch = require('node-fetch'); -global.fetch = (url, opts) => { - return fetch(resolve(base, url), opts); -}; - -const middlewares = [ - serve('assets'), - - // set test cookie - (req, res, next) => { - res.setHeader('Set-Cookie', 'test=woohoo!; Max-Age=3600'); - next(); - }, - - // emit messages so we can capture requests - (req, res, next) => { - if (!pending) return next(); - - pending.add(req.url); - - const { write, end } = res; - const chunks = []; - - res.write = function(chunk) { - chunks.push(new Buffer(chunk)); - write.apply(res, arguments); - }; - - res.end = function(chunk) { - if (chunk) chunks.push(new Buffer(chunk)); - end.apply(res, arguments); - - if (pending) pending.delete(req.url); - - process.send({ - method: req.method, - url: req.url, - status: res.statusCode, - headers: res._headers, - body: Buffer.concat(chunks).toString() - }); - - if (pending && pending.size === 0 && ended) { - process.send({ type: 'done' }); - } - }; - - next(); - }, - - // set up some values for the store - (req, res, next) => { - req.hello = 'hello'; - res.locals = { name: 'world' }; - next(); - }, - - sapper({ - manifest, - store: (req, res) => { - return new Store({ - title: `${req.hello} ${res.locals.name}` - }); - }, - ignore: [ - /foobar/i, - '/buzz', - 'fizz', - x => x === '/hello' - ] - }), -]; - -if (BASEPATH) { - app.use(BASEPATH, ...middlewares); -} else { - app.use(...middlewares); -} - -['foobar', 'buzz', 'fizzer', 'hello'].forEach(uri => { - app.get('/'+uri, (req, res) => res.end(uri)); -}); - -app.listen(PORT); diff --git a/test/app/app/template.html b/test/app/app/template.html deleted file mode 100644 index 0ea5e17..0000000 --- a/test/app/app/template.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - %sapper.base% - - - - - - - %sapper.styles% - - - %sapper.head% - - - -
%sapper.html%
- - - %sapper.scripts% - - \ No newline at end of file diff --git a/test/app/assets/favicon.png b/test/app/assets/favicon.png deleted file mode 100644 index f76753e..0000000 Binary files a/test/app/assets/favicon.png and /dev/null differ diff --git a/test/app/assets/global.css b/test/app/assets/global.css deleted file mode 100644 index 3831b79..0000000 --- a/test/app/assets/global.css +++ /dev/null @@ -1,45 +0,0 @@ -body { - margin: 0; - font-family: Roboto, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; - font-size: 14px; - line-height: 1.5; - color: #333; -} - -main { - position: relative; - max-width: 56em; - background-color: white; - padding: 2em; - margin: 0 auto; - box-sizing: border-box; -} - -h1, h2, h3, h4, h5, h6 { - margin: 0 0 0.5em 0; - font-weight: 400; - line-height: 1.2; -} - -h1 { - font-size: 2em; -} - -a { - color: inherit; -} - -code { - font-family: menlo, inconsolata, monospace; - font-size: calc(1em - 2px); - color: #555; - background-color: #f0f0f0; - padding: 0.2em 0.4em; - border-radius: 2px; -} - -@media (min-width: 400px) { - body { - font-size: 16px; - } -} \ No newline at end of file diff --git a/test/app/assets/great-success.png b/test/app/assets/great-success.png deleted file mode 100644 index c38720c..0000000 Binary files a/test/app/assets/great-success.png and /dev/null differ diff --git a/test/app/assets/manifest.json b/test/app/assets/manifest.json deleted file mode 100644 index 2b4ac3e..0000000 --- a/test/app/assets/manifest.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "background_color": "#ffffff", - "theme_color": "#aa1e1e", - "name": "TODO", - "short_name": "TODO", - "display": "minimal-ui", - "start_url": "/", - "icons": [ - { - "src": "svelte-logo-192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "svelte-logo-512.png", - "sizes": "512x512", - "type": "image/png" - } - ] -} diff --git a/test/app/assets/svelte-logo-192.png b/test/app/assets/svelte-logo-192.png deleted file mode 100644 index d12fc1a..0000000 Binary files a/test/app/assets/svelte-logo-192.png and /dev/null differ diff --git a/test/app/assets/svelte-logo-512.png b/test/app/assets/svelte-logo-512.png deleted file mode 100644 index 37e8198..0000000 Binary files a/test/app/assets/svelte-logo-512.png and /dev/null differ diff --git a/test/app/routes/_error.html b/test/app/routes/_error.html deleted file mode 100644 index 9974a17..0000000 --- a/test/app/routes/_error.html +++ /dev/null @@ -1,6 +0,0 @@ - - {status} - - -

{status}

-

{error.message}

\ No newline at end of file diff --git a/test/app/routes/about.html b/test/app/routes/about.html deleted file mode 100644 index 65ebb57..0000000 --- a/test/app/routes/about.html +++ /dev/null @@ -1,27 +0,0 @@ - - About - - -

About this site

- -

This is the 'about' page. There's not much here.

- - - - \ No newline at end of file diff --git a/test/app/routes/blog/[slug].html b/test/app/routes/blog/[slug].html deleted file mode 100644 index 7fdc8b4..0000000 --- a/test/app/routes/blog/[slug].html +++ /dev/null @@ -1,36 +0,0 @@ - - {post.title} - - -

{post.title}

- -
- {@html post.html} -
- - \ No newline at end of file diff --git a/test/app/routes/blog/[slug].json.js b/test/app/routes/blog/[slug].json.js deleted file mode 100644 index 61ebee8..0000000 --- a/test/app/routes/blog/[slug].json.js +++ /dev/null @@ -1,23 +0,0 @@ -import posts from './_posts.js'; - -const lookup = {}; -posts.forEach(post => { - lookup[post.slug] = JSON.stringify(post); -}); - -export function get(req, res, next) { - // the `slug` parameter is available because this file - // is called [slug].js - const { slug } = req.params; - - if (slug in lookup) { - res.writeHead(200, { - 'Content-Type': 'application/json', - 'Cache-Control': `no-cache` - }); - - res.end(lookup[slug]); - } else { - next(); - } -} \ No newline at end of file diff --git a/test/app/routes/blog/_posts.js b/test/app/routes/blog/_posts.js deleted file mode 100644 index d5e0dc2..0000000 --- a/test/app/routes/blog/_posts.js +++ /dev/null @@ -1,116 +0,0 @@ -// Ordinarily, you'd generate this data from markdown files in your -// repo, or fetch them from a database of some kind. But in order to -// avoid unnecessary dependencies in the starter template, and in the -// service of obviousness, we're just going to leave it here. - -// This file is called `_posts.js` rather than `posts.js`, because -// we don't want to create an `/api/blog/posts` route — the leading -// underscore tells Sapper not to do that. - -const posts = [ - { - title: 'What is Sapper?', - slug: 'what-is-sapper', - html: ` -

First, you have to know what Svelte is. Svelte is a UI framework with a bold new idea: rather than providing a library that you write code with (like React or Vue, for example), it's a compiler that turns your components into highly optimized vanilla JavaScript. If you haven't already read the introductory blog post, you should!

- -

Sapper is a Next.js-style framework (more on that here) built around Svelte. It makes it embarrassingly easy to create extremely high performance web apps. Out of the box, you get:

- - - -

It's implemented as Express middleware. Everything is set up and waiting for you to get started, but you keep complete control over the server, service worker, webpack config and everything else, so it's as flexible as you need it to be.

- ` - }, - - { - title: 'How to use Sapper', - slug: 'how-to-use-sapper', - html: ` -

Step one

-

Create a new project, using degit:

- -
npx degit sveltejs/sapper-template my-app
-			cd my-app
-			npm install # or yarn!
-			npm run dev
-			
- -

Step two

-

Go to localhost:3000. Open my-app in your editor. Edit the files in the routes directory or add new ones.

- -

Step three

-

...

- -

Step four

-

Resist overdone joke formats.

- ` - }, - - { - title: 'Why the name?', - slug: 'why-the-name', - html: ` -

In war, the soldiers who build bridges, repair roads, clear minefields and conduct demolitions — all under combat conditions — are known as sappers.

- -

For web developers, the stakes are generally lower than those for combat engineers. But we face our own hostile environment: underpowered devices, poor network connections, and the complexity inherent in front-end engineering. Sapper, which is short for Svelte app maker, is your courageous and dutiful ally.

- ` - }, - - { - title: 'How is Sapper different from Next.js?', - slug: 'how-is-sapper-different-from-next', - html: ` -

Next.js is a React framework from Zeit, and is the inspiration for Sapper. There are a few notable differences, however:

- - - ` - }, - - { - title: 'How can I get involved?', - slug: 'how-can-i-get-involved', - html: ` -

We're so glad you asked! Come on over to the Svelte and Sapper repos, and join us in the Gitter chatroom. Everyone is welcome, especially you!

- ` - }, - - { - title: 'A very long post with deep links', - slug: 'a-very-long-post', - html: ` -

One

-

I'll have a vodka rocks. (Mom, it's breakfast time.) And a piece of toast. Let me out that Queen. Fried cheese… with club sauce.

-

Her lawyers are claiming the seal is worth $250,000. And that's not even including Buster's Swatch. This was a big get for God. What, so the guy we are meeting with can't even grow his own hair? COME ON! She's always got to wedge herself in the middle of us so that she can control everything. Yeah. Mom's awesome. It's, like, Hey, you want to go down to the whirlpool? Yeah, I don't have a husband. I call it Swing City. The CIA should've just Googled for his hideout, evidently. There are dozens of us! DOZENS! Yeah, like I'm going to take a whiz through this $5,000 suit. COME ON.

- -

Two

-

Tobias Fünke costume. Heart attack never stopped old big bear.

-

Nellie is blowing them all AWAY. I will be a bigger and hairier mole than the one on your inner left thigh! I'll sacrifice anything for my children.

-

Up yours, granny! You couldn't handle it! Hey, Dad. Look at you. You're a year older…and a year closer to death. Buster: Oh yeah, I guess that's kind of funny. Bob Loblaw Law Blog. The guy runs a prison, he can have any piece of ass he wants.

- -

Three

-

I prematurely shot my wad on what was supposed to be a dry run, so now I'm afraid I have something of a mess on my hands. Dead Dove DO NOT EAT. Never once touched my per diem. I'd go to Craft Service, get some raw veggies, bacon, Cup-A-Soup…baby, I got a stew goin'. You're losing blood, aren't you? Gob: Probably, my socks are wet. Sure, let the little fruit do it. HUZZAH! Although George Michael had only got to second base, he'd gone in head first, like Pete Rose. I will pack your sweet pink mouth with so much ice cream you'll be the envy of every Jerry and Jane on the block!

-

Gosh Mom… after all these years, God's not going to take a call from you. Come on, this is a Bluth family celebration. It's no place for children.

-

And I wouldn't just lie there, if that's what you're thinking. That's not what I WAS thinking. Who? i just dont want him to point out my cracker ass in front of ann. When a man needs to prove to a woman that he's actually… When a man loves a woman… Heyyyyyy Uncle Father Oscar. [Stabbing Gob] White power! Gob: I'm white! Let me take off my assistant's skirt and put on my Barbra-Streisand-in-The-Prince-of-Tides ass-masking therapist pantsuit. In the mid '90s, Tobias formed a folk music band with Lindsay and Maebe which he called Dr. Funke's 100 Percent Natural Good Time Family Band Solution. The group was underwritten by the Natural Food Life Company, a division of Chem-Grow, an Allen Crayne acqusition, which was part of the Squimm Group. Their motto was simple: We keep you alive.

- -

Four

-

If you didn't have adult onset diabetes, I wouldn't mind giving you a little sugar. Everybody dance NOW. And the soup of the day is bread. Great, now I'm gonna smell to high heaven like a tuna melt!

-

That's how Tony Wonder lost a nut. She calls it a Mayonegg. Go ahead, touch the Cornballer. There's a new daddy in town. A discipline daddy.

- ` - } -]; - -posts.forEach(post => { - post.html = post.html.replace(/^\t{3}/gm, ''); -}); - -export default posts; \ No newline at end of file diff --git a/test/app/routes/blog/index.html b/test/app/routes/blog/index.html deleted file mode 100644 index 2e9f428..0000000 --- a/test/app/routes/blog/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - Blog - - -

Recent posts

- - - - \ No newline at end of file diff --git a/test/app/routes/blog/index.json.js b/test/app/routes/blog/index.json.js deleted file mode 100644 index 9d73d78..0000000 --- a/test/app/routes/blog/index.json.js +++ /dev/null @@ -1,17 +0,0 @@ -import posts from './_posts.js'; - -const contents = JSON.stringify(posts.map(post => { - return { - title: post.title, - slug: post.slug - }; -})); - -export function get(req, res) { - res.writeHead(200, { - 'Content-Type': 'application/json', - 'Cache-Control': `max-age=${30 * 60 * 1e3}` // cache for 30 minutes - }); - - res.end(contents); -} \ No newline at end of file diff --git a/test/app/routes/credentials/test.json.js b/test/app/routes/credentials/test.json.js deleted file mode 100644 index 3e7a549..0000000 --- a/test/app/routes/credentials/test.json.js +++ /dev/null @@ -1,28 +0,0 @@ -export function get(req, res) { - const cookies = req.headers.cookie - ? req.headers.cookie.split(/,\s+/).reduce((cookies, cookie) => { - const [pair] = cookie.split('; '); - const [name, value] = pair.split('='); - cookies[name] = value; - return cookies; - }, {}) - : {}; - - if (cookies.test) { - res.writeHead(200, { - 'Content-Type': 'application/json' - }); - - res.end(JSON.stringify({ - message: cookies.test - })); - } else { - res.writeHead(403, { - 'Content-Type': 'application/json' - }); - - res.end(JSON.stringify({ - message: 'unauthorized' - })); - } -} \ No newline at end of file diff --git a/test/app/routes/fünke.html b/test/app/routes/fünke.html deleted file mode 100644 index 088a7aa..0000000 --- a/test/app/routes/fünke.html +++ /dev/null @@ -1 +0,0 @@ -

I'm afraid I just blue myself

\ No newline at end of file diff --git a/test/app/routes/index.html b/test/app/routes/index.html deleted file mode 100644 index b695afe..0000000 --- a/test/app/routes/index.html +++ /dev/null @@ -1,27 +0,0 @@ - - Sapper project template - - -

Great success!

- -home -about -slow preload -redirect -redirect (root) -broken link -error link -credentials -blog - -
- - \ No newline at end of file diff --git a/test/app/routes/missing-index/ok.html b/test/app/routes/missing-index/ok.html deleted file mode 100644 index 7cc8f66..0000000 --- a/test/app/routes/missing-index/ok.html +++ /dev/null @@ -1 +0,0 @@ -

it works

\ No newline at end of file diff --git a/test/app/routes/throw-an-error.js b/test/app/routes/throw-an-error.js deleted file mode 100644 index 523f2bc..0000000 --- a/test/app/routes/throw-an-error.js +++ /dev/null @@ -1,3 +0,0 @@ -export function get() { - throw new Error('nope'); -} \ No newline at end of file diff --git a/test/app/webpack/client.config.js b/test/app/webpack/client.config.js deleted file mode 100644 index 9a17294..0000000 --- a/test/app/webpack/client.config.js +++ /dev/null @@ -1,34 +0,0 @@ -const config = require('../../../webpack/config.js'); -const webpack = require('webpack'); - -const mode = process.env.NODE_ENV; -const isDev = mode === 'development'; - -module.exports = { - entry: config.client.entry(), - output: config.client.output(), - resolve: { - extensions: ['.js', '.html'] - }, - module: { - rules: [ - { - test: /\.html$/, - exclude: /node_modules/, - use: { - loader: 'svelte-loader', - options: { - hydratable: true, - cascade: false, - store: true - } - } - } - ] - }, - mode, - plugins: [ - isDev && new webpack.HotModuleReplacementPlugin() - ].filter(Boolean), - devtool: isDev && 'inline-source-map' -}; \ No newline at end of file diff --git a/test/app/webpack/server.config.js b/test/app/webpack/server.config.js deleted file mode 100644 index 4f76856..0000000 --- a/test/app/webpack/server.config.js +++ /dev/null @@ -1,36 +0,0 @@ -const config = require('../../../webpack/config.js'); -const sapper_pkg = require('../../../package.json'); - -module.exports = { - entry: config.server.entry(), - output: config.server.output(), - target: 'node', - resolve: { - extensions: ['.js', '.html'] - }, - externals: [].concat( - Object.keys(sapper_pkg.dependencies), - Object.keys(sapper_pkg.devDependencies) - ), - module: { - rules: [ - { - test: /\.html$/, - exclude: /node_modules/, - use: { - loader: 'svelte-loader', - options: { - css: false, - cascade: false, - store: true, - generate: 'ssr' - } - } - } - ] - }, - mode: process.env.NODE_ENV, - performance: { - hints: false // it doesn't matter if server.js is large - } -}; \ No newline at end of file diff --git a/test/app/webpack/service-worker.config.js b/test/app/webpack/service-worker.config.js deleted file mode 100644 index f95b5f4..0000000 --- a/test/app/webpack/service-worker.config.js +++ /dev/null @@ -1,7 +0,0 @@ -const config = require('../../../webpack/config.js'); - -module.exports = { - entry: config.serviceworker.entry(), - output: config.serviceworker.output(), - mode: process.env.NODE_ENV -}; \ No newline at end of file diff --git a/test/apps/AppRunner.ts b/test/apps/AppRunner.ts new file mode 100644 index 0000000..84dd6b6 --- /dev/null +++ b/test/apps/AppRunner.ts @@ -0,0 +1,132 @@ +import * as path from 'path'; +import * as puppeteer from 'puppeteer'; +import * as ports from 'port-authority'; +import { fork, ChildProcess } from 'child_process'; + +declare const start: () => Promise; +declare const prefetchRoutes: () => Promise; +declare const prefetch: (href: string) => Promise; +declare const goto: (href: string) => Promise; + +type StartOpts = { + requestInterceptor?: (interceptedRequst: puppeteer.Request) => any +}; + +export class AppRunner { + cwd: string; + entry: string; + port: number; + proc: ChildProcess; + messages: any[]; + + browser: puppeteer.Browser; + page: puppeteer.Page; + + constructor(cwd: string, entry: string) { + this.cwd = cwd; + this.entry = path.join(cwd, entry); + this.messages = []; + } + + async start({ requestInterceptor }: StartOpts = {}) { + this.port = await ports.find(3000); + + this.proc = fork(this.entry, [], { + cwd: this.cwd, + env: { + PORT: String(this.port) + } + }); + + this.proc.on('message', message => { + if (!message.__sapper__) return; + this.messages.push(message); + }); + + this.browser = await puppeteer.launch({ args: ['--no-sandbox'] }); + + this.page = await this.browser.newPage(); + this.page.on('console', msg => { + const text = msg.text(); + + if (!text.startsWith('Failed to load resource')) { + console.log(text); + } + }); + + if (requestInterceptor) { + await this.page.setRequestInterception(true); + this.page.on('request', requestInterceptor); + } + + return { + page: this.page, + base: `http://localhost:${this.port}`, + + // helpers + start: () => this.page.evaluate(() => start()), + prefetchRoutes: () => this.page.evaluate(() => prefetchRoutes()), + prefetch: (href: string) => this.page.evaluate((href: string) => prefetch(href), href), + goto: (href: string) => this.page.evaluate((href: string) => goto(href), href), + title: () => this.page.$eval('h1', node => node.textContent) + }; + } + + capture(fn: () => any): Promise { + return new Promise((fulfil, reject) => { + const requests: string[] = []; + const pending: Set = new Set(); + let done = false; + + function handle_request(request: puppeteer.Request) { + const url = request.url(); + requests.push(url); + pending.add(url); + } + + function handle_requestfinished(request: puppeteer.Request) { + const url = request.url(); + pending.delete(url); + + if (done && pending.size === 0) { + cleanup(); + fulfil(requests); + } + } + + function handle_requestfailed(request: puppeteer.Request) { + cleanup(); + reject(new Error(`failed to fetch ${request.url()}`)) + } + + const cleanup = () => { + this.page.removeListener('request', handle_request); + this.page.removeListener('requestfinished', handle_requestfinished); + this.page.removeListener('requestfailed', handle_requestfailed); + }; + + this.page.on('request', handle_request); + this.page.on('requestfinished', handle_requestfinished); + this.page.on('requestfailed', handle_requestfailed); + + return Promise.resolve(fn()).then(() => { + if (pending.size === 0) { + cleanup(); + fulfil(requests); + } + + done = true; + }); + }); + } + + end() { + return Promise.all([ + this.browser.close(), + new Promise(fulfil => { + this.proc.once('exit', fulfil); + this.proc.kill(); + }) + ]); + } +} \ No newline at end of file diff --git a/test/apps/basics/rollup.config.js b/test/apps/basics/rollup.config.js new file mode 100644 index 0000000..943b676 --- /dev/null +++ b/test/apps/basics/rollup.config.js @@ -0,0 +1,64 @@ +import resolve from 'rollup-plugin-node-resolve'; +import replace from 'rollup-plugin-replace'; +import svelte from 'rollup-plugin-svelte'; + +const mode = process.env.NODE_ENV; +const dev = mode === 'development'; + +const config = require('../../../config/rollup.js'); + +export default { + client: { + input: config.client.input(), + output: config.client.output(), + plugins: [ + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + dev, + hydratable: true, + emitCss: true + }), + resolve() + ], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + server: { + input: config.server.input(), + output: config.server.output(), + plugins: [ + replace({ + 'process.browser': false, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + generate: 'ssr', + dev + }), + resolve({ + preferBuiltins: true + }) + ], + external: ['sirv', 'polka'], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + serviceworker: { + input: config.serviceworker.input(), + output: config.serviceworker.output(), + plugins: [ + resolve(), + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }) + ] + } +}; \ No newline at end of file diff --git a/test/apps/basics/src/client.js b/test/apps/basics/src/client.js new file mode 100644 index 0000000..0865a4a --- /dev/null +++ b/test/apps/basics/src/client.js @@ -0,0 +1,9 @@ +import * as sapper from '../__sapper__/client.js'; + +window.start = () => sapper.start({ + target: document.querySelector('#sapper') +}); + +window.prefetchRoutes = () => sapper.prefetchRoutes(); +window.prefetch = href => sapper.prefetch(href); +window.goto = href => sapper.goto(href); \ No newline at end of file diff --git a/test/apps/basics/src/routes/[slug].html b/test/apps/basics/src/routes/[slug].html new file mode 100644 index 0000000..ade66de --- /dev/null +++ b/test/apps/basics/src/routes/[slug].html @@ -0,0 +1 @@ +

{params.slug.toUpperCase()}

\ No newline at end of file diff --git a/test/apps/basics/src/routes/_error.html b/test/apps/basics/src/routes/_error.html new file mode 100644 index 0000000..4cd55d2 --- /dev/null +++ b/test/apps/basics/src/routes/_error.html @@ -0,0 +1,3 @@ +

{status}

+ +

{error.message}

\ No newline at end of file diff --git a/test/apps/basics/src/routes/a.html b/test/apps/basics/src/routes/a.html new file mode 100644 index 0000000..0e6757b --- /dev/null +++ b/test/apps/basics/src/routes/a.html @@ -0,0 +1 @@ +

a

\ No newline at end of file diff --git a/test/unit/create_routes/samples/basic/blog/[slug].html b/test/apps/basics/src/routes/ambiguous/[slug].html similarity index 100% rename from test/unit/create_routes/samples/basic/blog/[slug].html rename to test/apps/basics/src/routes/ambiguous/[slug].html diff --git a/test/apps/basics/src/routes/ambiguous/[slug].json.js b/test/apps/basics/src/routes/ambiguous/[slug].json.js new file mode 100644 index 0000000..adc3102 --- /dev/null +++ b/test/apps/basics/src/routes/ambiguous/[slug].json.js @@ -0,0 +1,3 @@ +export function get(req, res) { + res.end(req.params.slug); +} \ No newline at end of file diff --git a/test/apps/basics/src/routes/b/index.html b/test/apps/basics/src/routes/b/index.html new file mode 100644 index 0000000..d93079d --- /dev/null +++ b/test/apps/basics/src/routes/b/index.html @@ -0,0 +1,11 @@ +

{letter}

+ + \ No newline at end of file diff --git a/test/apps/basics/src/routes/b/index.json.js b/test/apps/basics/src/routes/b/index.json.js new file mode 100644 index 0000000..29b7ede --- /dev/null +++ b/test/apps/basics/src/routes/b/index.json.js @@ -0,0 +1,3 @@ +export function get(req, res) { + res.end(JSON.stringify('b')); +} \ No newline at end of file diff --git a/test/apps/basics/src/routes/const.html b/test/apps/basics/src/routes/const.html new file mode 100644 index 0000000..6975aae --- /dev/null +++ b/test/apps/basics/src/routes/const.html @@ -0,0 +1 @@ +

reserved words are okay as routes

\ No newline at end of file diff --git a/test/app/routes/api/delete/[id].js b/test/apps/basics/src/routes/delete-test/[id].json.js similarity index 100% rename from test/app/routes/api/delete/[id].js rename to test/apps/basics/src/routes/delete-test/[id].json.js diff --git a/test/app/routes/delete-test.html b/test/apps/basics/src/routes/delete-test/index.html similarity index 67% rename from test/app/routes/delete-test.html rename to test/apps/basics/src/routes/delete-test/index.html index 428ab3c..a5280cb 100644 --- a/test/app/routes/delete-test.html +++ b/test/apps/basics/src/routes/delete-test/index.html @@ -2,9 +2,13 @@ \ No newline at end of file diff --git a/test/apps/css/src/routes/foo.html b/test/apps/css/src/routes/foo.html new file mode 100644 index 0000000..3aeeeeb --- /dev/null +++ b/test/apps/css/src/routes/foo.html @@ -0,0 +1,7 @@ +

Foo

+ + \ No newline at end of file diff --git a/test/apps/css/src/routes/index.html b/test/apps/css/src/routes/index.html new file mode 100644 index 0000000..a9fd9fd --- /dev/null +++ b/test/apps/css/src/routes/index.html @@ -0,0 +1,10 @@ +

Great success!

+ +foo +bar + + \ No newline at end of file diff --git a/test/apps/css/src/server.js b/test/apps/css/src/server.js new file mode 100644 index 0000000..0e7741c --- /dev/null +++ b/test/apps/css/src/server.js @@ -0,0 +1,8 @@ +import polka from 'polka'; +import * as sapper from '../__sapper__/server.js'; + +const { PORT } = process.env; + +polka() + .use(sapper.middleware()) + .listen(PORT); diff --git a/test/apps/css/src/service-worker.js b/test/apps/css/src/service-worker.js new file mode 100644 index 0000000..9d2ac9d --- /dev/null +++ b/test/apps/css/src/service-worker.js @@ -0,0 +1,82 @@ +import { timestamp, files, shell, routes } from '../__sapper__/service-worker.js'; + +const ASSETS = `cache${timestamp}`; + +// `shell` is an array of all the files generated by webpack, +// `files` is an array of everything in the `static` directory +const to_cache = shell.concat(ASSETS); +const cached = new Set(to_cache); + +self.addEventListener('install', event => { + event.waitUntil( + caches + .open(ASSETS) + .then(cache => cache.addAll(to_cache)) + .then(() => { + self.skipWaiting(); + }) + ); +}); + +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(async keys => { + // delete old caches + for (const key of keys) { + if (key !== ASSETS) await caches.delete(key); + } + + self.clients.claim(); + }) + ); +}); + +self.addEventListener('fetch', event => { + if (event.request.method !== 'GET') return; + + const url = new URL(event.request.url); + + // don't try to handle e.g. data: URIs + if (!url.protocol.startsWith('http')) return; + + // ignore dev server requests + if (url.hostname === self.location.hostname && url.port !== self.location.port) return; + + // always serve assets and webpack-generated files from cache + if (url.host === self.location.host && cached.has(url.pathname)) { + event.respondWith(caches.match(event.request)); + return; + } + + // for pages, you might want to serve a shell `index.html` file, + // which Sapper has generated for you. It's not right for every + // app, but if it's right for yours then uncomment this section + /* + if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) { + event.respondWith(caches.match('/index.html')); + return; + } + */ + + if (event.request.cache === 'only-if-cached') return; + + // for everything else, try the network first, falling back to + // cache if the user is offline. (If the pages never change, you + // might prefer a cache-first approach to a network-first one.) + event.respondWith( + caches + .open(`offline${timestamp}`) + .then(async cache => { + try { + const response = await fetch(event.request); + cache.put(event.request, response.clone()); + return response; + } catch(err) { + const response = await cache.match(event.request); + if (response) return response; + + throw err; + } + }) + ); +}); diff --git a/test/apps/css/src/template.html b/test/apps/css/src/template.html new file mode 100644 index 0000000..0eb1f3b --- /dev/null +++ b/test/apps/css/src/template.html @@ -0,0 +1,14 @@ + + + + + + %sapper.base% + %sapper.styles% + %sapper.head% + + +
%sapper.html%
+ %sapper.scripts% + + diff --git a/test/apps/css/test.ts b/test/apps/css/test.ts new file mode 100644 index 0000000..c6539af --- /dev/null +++ b/test/apps/css/test.ts @@ -0,0 +1,78 @@ +import * as assert from 'assert'; +import * as puppeteer from 'puppeteer'; +import { build } from '../../../api'; +import { AppRunner } from '../AppRunner'; +import { wait } from '../../utils'; + +describe('css', function() { + this.timeout(10000); + + let runner: AppRunner; + let page: puppeteer.Page; + let base: string; + + // helpers + let start: () => Promise; + let prefetchRoutes: () => Promise; + let prefetch: (href: string) => Promise; + let goto: (href: string) => Promise; + let title: () => Promise; + + // hooks + before(async () => { + await build({ cwd: __dirname }); + + runner = new AppRunner(__dirname, '__sapper__/build/server/server.js'); + ({ base, page, start, prefetchRoutes, prefetch, goto, title } = await runner.start()); + }); + + after(() => runner.end()); + + it('includes critical CSS with server render', async () => { + await page.goto(base); + + assert.equal( + await page.evaluate(() => { + const h1 = document.querySelector('h1'); + return getComputedStyle(h1).color; + }), + 'rgb(255, 0, 0)' + ); + }); + + it('loads CSS when navigating client-side', async () => { + await page.goto(base); + + await start(); + await prefetchRoutes(); + + await page.click(`[href="foo"]`); + await wait(50); + + assert.equal( + await page.evaluate(() => { + const h1 = document.querySelector('h1'); + return getComputedStyle(h1).color; + }), + 'rgb(0, 0, 255)' + ); + }); + + it('loads CSS for a lazily-rendered component', async () => { + await page.goto(base); + + await start(); + await prefetchRoutes(); + + await page.click(`[href="bar"]`); + await wait(50); + + assert.equal( + await page.evaluate(() => { + const h1 = document.querySelector('h1'); + return getComputedStyle(h1).color; + }), + 'rgb(0, 128, 0)' + ); + }); +}); \ No newline at end of file diff --git a/test/apps/encoding/rollup.config.js b/test/apps/encoding/rollup.config.js new file mode 100644 index 0000000..943b676 --- /dev/null +++ b/test/apps/encoding/rollup.config.js @@ -0,0 +1,64 @@ +import resolve from 'rollup-plugin-node-resolve'; +import replace from 'rollup-plugin-replace'; +import svelte from 'rollup-plugin-svelte'; + +const mode = process.env.NODE_ENV; +const dev = mode === 'development'; + +const config = require('../../../config/rollup.js'); + +export default { + client: { + input: config.client.input(), + output: config.client.output(), + plugins: [ + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + dev, + hydratable: true, + emitCss: true + }), + resolve() + ], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + server: { + input: config.server.input(), + output: config.server.output(), + plugins: [ + replace({ + 'process.browser': false, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + generate: 'ssr', + dev + }), + resolve({ + preferBuiltins: true + }) + ], + external: ['sirv', 'polka'], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + serviceworker: { + input: config.serviceworker.input(), + output: config.serviceworker.output(), + plugins: [ + resolve(), + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }) + ] + } +}; \ No newline at end of file diff --git a/test/apps/encoding/src/client.js b/test/apps/encoding/src/client.js new file mode 100644 index 0000000..0865a4a --- /dev/null +++ b/test/apps/encoding/src/client.js @@ -0,0 +1,9 @@ +import * as sapper from '../__sapper__/client.js'; + +window.start = () => sapper.start({ + target: document.querySelector('#sapper') +}); + +window.prefetchRoutes = () => sapper.prefetchRoutes(); +window.prefetch = href => sapper.prefetch(href); +window.goto = href => sapper.goto(href); \ No newline at end of file diff --git a/test/apps/encoding/src/routes/_error.html b/test/apps/encoding/src/routes/_error.html new file mode 100644 index 0000000..4cd55d2 --- /dev/null +++ b/test/apps/encoding/src/routes/_error.html @@ -0,0 +1,3 @@ +

{status}

+ +

{error.message}

\ No newline at end of file diff --git a/test/apps/encoding/src/routes/echo/page/[slug].html b/test/apps/encoding/src/routes/echo/page/[slug].html new file mode 100644 index 0000000..2cdc03d --- /dev/null +++ b/test/apps/encoding/src/routes/echo/page/[slug].html @@ -0,0 +1,11 @@ +

{slug} {JSON.stringify(query)}

+ + \ No newline at end of file diff --git a/test/apps/encoding/src/routes/echo/server-route/[slug].js b/test/apps/encoding/src/routes/echo/server-route/[slug].js new file mode 100644 index 0000000..e0e9ef7 --- /dev/null +++ b/test/apps/encoding/src/routes/echo/server-route/[slug].js @@ -0,0 +1,15 @@ +export function get(req, res) { + res.writeHead(200, { + 'Content-Type': 'text/html' + }); + + res.end(` + + + + +

${req.params.slug}

+ + + `); +} \ No newline at end of file diff --git a/test/apps/encoding/src/routes/fünke.html b/test/apps/encoding/src/routes/fünke.html new file mode 100644 index 0000000..e1fba6c --- /dev/null +++ b/test/apps/encoding/src/routes/fünke.html @@ -0,0 +1,11 @@ +

{phrase}

+ + \ No newline at end of file diff --git a/test/apps/encoding/src/routes/fünke.json.js b/test/apps/encoding/src/routes/fünke.json.js new file mode 100644 index 0000000..a9ccd6e --- /dev/null +++ b/test/apps/encoding/src/routes/fünke.json.js @@ -0,0 +1,9 @@ +export function get(req, res) { + res.writeHead(200, { + 'Content-Type': 'application/json' + }); + + res.end(JSON.stringify( + "I'm afraid I just blue myself" + )); +} \ No newline at end of file diff --git a/test/apps/encoding/src/routes/index.html b/test/apps/encoding/src/routes/index.html new file mode 100644 index 0000000..198a277 --- /dev/null +++ b/test/apps/encoding/src/routes/index.html @@ -0,0 +1,3 @@ +

Great success!

+ +link \ No newline at end of file diff --git a/test/apps/encoding/src/server.js b/test/apps/encoding/src/server.js new file mode 100644 index 0000000..0e7741c --- /dev/null +++ b/test/apps/encoding/src/server.js @@ -0,0 +1,8 @@ +import polka from 'polka'; +import * as sapper from '../__sapper__/server.js'; + +const { PORT } = process.env; + +polka() + .use(sapper.middleware()) + .listen(PORT); diff --git a/test/apps/encoding/src/service-worker.js b/test/apps/encoding/src/service-worker.js new file mode 100644 index 0000000..9d2ac9d --- /dev/null +++ b/test/apps/encoding/src/service-worker.js @@ -0,0 +1,82 @@ +import { timestamp, files, shell, routes } from '../__sapper__/service-worker.js'; + +const ASSETS = `cache${timestamp}`; + +// `shell` is an array of all the files generated by webpack, +// `files` is an array of everything in the `static` directory +const to_cache = shell.concat(ASSETS); +const cached = new Set(to_cache); + +self.addEventListener('install', event => { + event.waitUntil( + caches + .open(ASSETS) + .then(cache => cache.addAll(to_cache)) + .then(() => { + self.skipWaiting(); + }) + ); +}); + +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(async keys => { + // delete old caches + for (const key of keys) { + if (key !== ASSETS) await caches.delete(key); + } + + self.clients.claim(); + }) + ); +}); + +self.addEventListener('fetch', event => { + if (event.request.method !== 'GET') return; + + const url = new URL(event.request.url); + + // don't try to handle e.g. data: URIs + if (!url.protocol.startsWith('http')) return; + + // ignore dev server requests + if (url.hostname === self.location.hostname && url.port !== self.location.port) return; + + // always serve assets and webpack-generated files from cache + if (url.host === self.location.host && cached.has(url.pathname)) { + event.respondWith(caches.match(event.request)); + return; + } + + // for pages, you might want to serve a shell `index.html` file, + // which Sapper has generated for you. It's not right for every + // app, but if it's right for yours then uncomment this section + /* + if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) { + event.respondWith(caches.match('/index.html')); + return; + } + */ + + if (event.request.cache === 'only-if-cached') return; + + // for everything else, try the network first, falling back to + // cache if the user is offline. (If the pages never change, you + // might prefer a cache-first approach to a network-first one.) + event.respondWith( + caches + .open(`offline${timestamp}`) + .then(async cache => { + try { + const response = await fetch(event.request); + cache.put(event.request, response.clone()); + return response; + } catch(err) { + const response = await cache.match(event.request); + if (response) return response; + + throw err; + } + }) + ); +}); diff --git a/test/apps/encoding/src/template.html b/test/apps/encoding/src/template.html new file mode 100644 index 0000000..0eb1f3b --- /dev/null +++ b/test/apps/encoding/src/template.html @@ -0,0 +1,14 @@ + + + + + + %sapper.base% + %sapper.styles% + %sapper.head% + + +
%sapper.html%
+ %sapper.scripts% + + diff --git a/test/apps/encoding/test.ts b/test/apps/encoding/test.ts new file mode 100644 index 0000000..c50559b --- /dev/null +++ b/test/apps/encoding/test.ts @@ -0,0 +1,68 @@ +import * as assert from 'assert'; +import * as puppeteer from 'puppeteer'; +import { build } from '../../../api'; +import { AppRunner } from '../AppRunner'; +import { wait } from '../../utils'; + +describe('encoding', function() { + this.timeout(10000); + + let runner: AppRunner; + let page: puppeteer.Page; + let base: string; + + // helpers + let start: () => Promise; + let prefetchRoutes: () => Promise; + + // hooks + before(async () => { + await build({ cwd: __dirname }); + + runner = new AppRunner(__dirname, '__sapper__/build/server/server.js'); + ({ base, page, start, prefetchRoutes } = await runner.start()); + }); + + after(() => runner.end()); + + it('encodes routes', async () => { + await page.goto(`${base}/fünke`); + + assert.equal( + await page.$eval('h1', node => node.textContent), + `I'm afraid I just blue myself` + ); + }); + + it('encodes req.params and req.query for server-rendered pages', async () => { + await page.goto(`${base}/echo/page/encöded?message=hëllö+wörld&föo=bar&=baz`); + + assert.equal( + await page.$eval('h1', node => node.textContent), + 'encöded {"message":"hëllö wörld","föo":"bar","":"baz"}' + ); + }); + + it('encodes req.params and req.query for client-rendered pages', async () => { + await page.goto(base); + await start(); + await prefetchRoutes(); + + await page.click('a[href="echo/page/encöded?message=hëllö+wörld&föo=bar&=baz"]'); + await wait(50); + + assert.equal( + await page.$eval('h1', node => node.textContent), + 'encöded {"message":"hëllö wörld","föo":"bar","":"baz"}' + ); + }); + + it('encodes req.params for server routes', async () => { + await page.goto(`${base}/echo/server-route/encöded`); + + assert.equal( + await page.$eval('h1', node => node.textContent), + 'encöded' + ); + }); +}); \ No newline at end of file diff --git a/test/apps/errors/rollup.config.js b/test/apps/errors/rollup.config.js new file mode 100644 index 0000000..943b676 --- /dev/null +++ b/test/apps/errors/rollup.config.js @@ -0,0 +1,64 @@ +import resolve from 'rollup-plugin-node-resolve'; +import replace from 'rollup-plugin-replace'; +import svelte from 'rollup-plugin-svelte'; + +const mode = process.env.NODE_ENV; +const dev = mode === 'development'; + +const config = require('../../../config/rollup.js'); + +export default { + client: { + input: config.client.input(), + output: config.client.output(), + plugins: [ + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + dev, + hydratable: true, + emitCss: true + }), + resolve() + ], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + server: { + input: config.server.input(), + output: config.server.output(), + plugins: [ + replace({ + 'process.browser': false, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + generate: 'ssr', + dev + }), + resolve({ + preferBuiltins: true + }) + ], + external: ['sirv', 'polka'], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + serviceworker: { + input: config.serviceworker.input(), + output: config.serviceworker.output(), + plugins: [ + resolve(), + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }) + ] + } +}; \ No newline at end of file diff --git a/test/apps/errors/src/client.js b/test/apps/errors/src/client.js new file mode 100644 index 0000000..0865a4a --- /dev/null +++ b/test/apps/errors/src/client.js @@ -0,0 +1,9 @@ +import * as sapper from '../__sapper__/client.js'; + +window.start = () => sapper.start({ + target: document.querySelector('#sapper') +}); + +window.prefetchRoutes = () => sapper.prefetchRoutes(); +window.prefetch = href => sapper.prefetch(href); +window.goto = href => sapper.goto(href); \ No newline at end of file diff --git a/test/apps/errors/src/routes/_error.html b/test/apps/errors/src/routes/_error.html new file mode 100644 index 0000000..4cd55d2 --- /dev/null +++ b/test/apps/errors/src/routes/_error.html @@ -0,0 +1,3 @@ +

{status}

+ +

{error.message}

\ No newline at end of file diff --git a/test/apps/errors/src/routes/async-throw.json.js b/test/apps/errors/src/routes/async-throw.json.js new file mode 100644 index 0000000..25158f7 --- /dev/null +++ b/test/apps/errors/src/routes/async-throw.json.js @@ -0,0 +1,3 @@ +export function get(req, res) { + return Promise.reject(new Error('oops')); +} \ No newline at end of file diff --git a/test/apps/errors/src/routes/blog/[slug].html b/test/apps/errors/src/routes/blog/[slug].html new file mode 100644 index 0000000..8a304d0 --- /dev/null +++ b/test/apps/errors/src/routes/blog/[slug].html @@ -0,0 +1,19 @@ +

{post.title}

+ + \ No newline at end of file diff --git a/test/apps/errors/src/routes/blog/[slug].json.js b/test/apps/errors/src/routes/blog/[slug].json.js new file mode 100644 index 0000000..5e2e2a7 --- /dev/null +++ b/test/apps/errors/src/routes/blog/[slug].json.js @@ -0,0 +1,9 @@ +export function get(req, res) { + res.writeHead(404, { + 'Content-Type': 'application/json' + }); + + res.end(JSON.stringify({ + message: 'not found' + })); +} \ No newline at end of file diff --git a/test/apps/errors/src/routes/enhance-your-calm.html b/test/apps/errors/src/routes/enhance-your-calm.html new file mode 100644 index 0000000..398584e --- /dev/null +++ b/test/apps/errors/src/routes/enhance-your-calm.html @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/test/apps/errors/src/routes/index.html b/test/apps/errors/src/routes/index.html new file mode 100644 index 0000000..a6b7896 --- /dev/null +++ b/test/apps/errors/src/routes/index.html @@ -0,0 +1,5 @@ +

root

+ +nope +blog/nope +throw \ No newline at end of file diff --git a/test/apps/errors/src/routes/no-error.html b/test/apps/errors/src/routes/no-error.html new file mode 100644 index 0000000..8dc116a --- /dev/null +++ b/test/apps/errors/src/routes/no-error.html @@ -0,0 +1,3 @@ +

{error ? error.message : 'No error here'}

+ +Enhance your calm \ No newline at end of file diff --git a/test/apps/errors/src/routes/nope.json.js b/test/apps/errors/src/routes/nope.json.js new file mode 100644 index 0000000..3813784 --- /dev/null +++ b/test/apps/errors/src/routes/nope.json.js @@ -0,0 +1,4 @@ +export function get(req, res) { + res.writeHead(500); + res.end('nope'); +} \ No newline at end of file diff --git a/test/apps/errors/src/routes/throw.html b/test/apps/errors/src/routes/throw.html new file mode 100644 index 0000000..16b4131 --- /dev/null +++ b/test/apps/errors/src/routes/throw.html @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/test/apps/errors/src/routes/throw.json.js b/test/apps/errors/src/routes/throw.json.js new file mode 100644 index 0000000..5247b57 --- /dev/null +++ b/test/apps/errors/src/routes/throw.json.js @@ -0,0 +1,3 @@ +export function get(req, res) { + throw new Error('oops'); +} \ No newline at end of file diff --git a/test/apps/errors/src/server.js b/test/apps/errors/src/server.js new file mode 100644 index 0000000..0e7741c --- /dev/null +++ b/test/apps/errors/src/server.js @@ -0,0 +1,8 @@ +import polka from 'polka'; +import * as sapper from '../__sapper__/server.js'; + +const { PORT } = process.env; + +polka() + .use(sapper.middleware()) + .listen(PORT); diff --git a/test/apps/errors/src/service-worker.js b/test/apps/errors/src/service-worker.js new file mode 100644 index 0000000..9d2ac9d --- /dev/null +++ b/test/apps/errors/src/service-worker.js @@ -0,0 +1,82 @@ +import { timestamp, files, shell, routes } from '../__sapper__/service-worker.js'; + +const ASSETS = `cache${timestamp}`; + +// `shell` is an array of all the files generated by webpack, +// `files` is an array of everything in the `static` directory +const to_cache = shell.concat(ASSETS); +const cached = new Set(to_cache); + +self.addEventListener('install', event => { + event.waitUntil( + caches + .open(ASSETS) + .then(cache => cache.addAll(to_cache)) + .then(() => { + self.skipWaiting(); + }) + ); +}); + +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(async keys => { + // delete old caches + for (const key of keys) { + if (key !== ASSETS) await caches.delete(key); + } + + self.clients.claim(); + }) + ); +}); + +self.addEventListener('fetch', event => { + if (event.request.method !== 'GET') return; + + const url = new URL(event.request.url); + + // don't try to handle e.g. data: URIs + if (!url.protocol.startsWith('http')) return; + + // ignore dev server requests + if (url.hostname === self.location.hostname && url.port !== self.location.port) return; + + // always serve assets and webpack-generated files from cache + if (url.host === self.location.host && cached.has(url.pathname)) { + event.respondWith(caches.match(event.request)); + return; + } + + // for pages, you might want to serve a shell `index.html` file, + // which Sapper has generated for you. It's not right for every + // app, but if it's right for yours then uncomment this section + /* + if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) { + event.respondWith(caches.match('/index.html')); + return; + } + */ + + if (event.request.cache === 'only-if-cached') return; + + // for everything else, try the network first, falling back to + // cache if the user is offline. (If the pages never change, you + // might prefer a cache-first approach to a network-first one.) + event.respondWith( + caches + .open(`offline${timestamp}`) + .then(async cache => { + try { + const response = await fetch(event.request); + cache.put(event.request, response.clone()); + return response; + } catch(err) { + const response = await cache.match(event.request); + if (response) return response; + + throw err; + } + }) + ); +}); diff --git a/test/apps/errors/src/template.html b/test/apps/errors/src/template.html new file mode 100644 index 0000000..0eb1f3b --- /dev/null +++ b/test/apps/errors/src/template.html @@ -0,0 +1,14 @@ + + + + + + %sapper.base% + %sapper.styles% + %sapper.head% + + +
%sapper.html%
+ %sapper.scripts% + + diff --git a/test/apps/errors/test.ts b/test/apps/errors/test.ts new file mode 100644 index 0000000..539587d --- /dev/null +++ b/test/apps/errors/test.ts @@ -0,0 +1,137 @@ +import * as assert from 'assert'; +import * as puppeteer from 'puppeteer'; +import { build } from '../../../api'; +import { AppRunner } from '../AppRunner'; +import { wait } from '../../utils'; + +describe('errors', function() { + this.timeout(10000); + + let runner: AppRunner; + let page: puppeteer.Page; + let base: string; + + // helpers + let start: () => Promise; + let prefetchRoutes: () => Promise; + let title: () => Promise; + + // hooks + before(async () => { + await build({ cwd: __dirname }); + + runner = new AppRunner(__dirname, '__sapper__/build/server/server.js'); + ({ base, page, start, prefetchRoutes, title } = await runner.start()); + }); + + after(() => runner.end()); + + it('handles missing route on server', async () => { + await page.goto(`${base}/nope`); + + assert.equal( + await page.$eval('h1', node => node.textContent), + '404' + ); + }); + + it('handles missing route on client', async () => { + await page.goto(base); + await start(); + + await page.click('[href="nope"]'); + await wait(50); + + assert.equal( + await page.$eval('h1', node => node.textContent), + '404' + ); + }); + + it('handles explicit 4xx on server', async () => { + await page.goto(`${base}/blog/nope`); + + assert.equal( + await page.$eval('h1', node => node.textContent), + '404' + ); + }); + + it('handles explicit 4xx on client', async () => { + await page.goto(base); + await start(); + await prefetchRoutes(); + + await page.click('[href="blog/nope"]'); + await wait(50); + + assert.equal( + await page.$eval('h1', node => node.textContent), + '404' + ); + }); + + it('handles error on server', async () => { + await page.goto(`${base}/throw`); + + assert.equal( + await page.$eval('h1', node => node.textContent), + '500' + ); + }); + + it('handles error on client', async () => { + await page.goto(base); + await start(); + await prefetchRoutes(); + + await page.click('[href="throw"]'); + await wait(50); + + assert.equal( + await page.$eval('h1', node => node.textContent), + '500' + ); + }); + + it('does not serve error page for explicit non-page errors', async () => { + await page.goto(`${base}/nope.json`); + + assert.equal( + await page.evaluate(() => document.body.textContent), + 'nope' + ); + }); + + it('does not serve error page for thrown non-page errors', async () => { + await page.goto(`${base}/throw.json`); + + assert.equal( + await page.evaluate(() => document.body.textContent), + 'oops' + ); + }); + + it('does not serve error page for async non-page error', async () => { + await page.goto(`${base}/async-throw.json`); + + assert.equal( + await page.evaluate(() => document.body.textContent), + 'oops' + ); + }); + + it('clears props.error on successful render', async () => { + await page.goto(`${base}/no-error`); + await start(); + await prefetchRoutes(); + + await page.click('[href="enhance-your-calm"]'); + await wait(50); + assert.equal(await title(), '420'); + + await page.goBack(); + await wait(50); + assert.equal(await title(), 'No error here'); + }); +}); \ No newline at end of file diff --git a/test/apps/export/rollup.config.js b/test/apps/export/rollup.config.js new file mode 100644 index 0000000..943b676 --- /dev/null +++ b/test/apps/export/rollup.config.js @@ -0,0 +1,64 @@ +import resolve from 'rollup-plugin-node-resolve'; +import replace from 'rollup-plugin-replace'; +import svelte from 'rollup-plugin-svelte'; + +const mode = process.env.NODE_ENV; +const dev = mode === 'development'; + +const config = require('../../../config/rollup.js'); + +export default { + client: { + input: config.client.input(), + output: config.client.output(), + plugins: [ + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + dev, + hydratable: true, + emitCss: true + }), + resolve() + ], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + server: { + input: config.server.input(), + output: config.server.output(), + plugins: [ + replace({ + 'process.browser': false, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + generate: 'ssr', + dev + }), + resolve({ + preferBuiltins: true + }) + ], + external: ['sirv', 'polka'], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + serviceworker: { + input: config.serviceworker.input(), + output: config.serviceworker.output(), + plugins: [ + resolve(), + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }) + ] + } +}; \ No newline at end of file diff --git a/test/apps/export/src/client.js b/test/apps/export/src/client.js new file mode 100644 index 0000000..0865a4a --- /dev/null +++ b/test/apps/export/src/client.js @@ -0,0 +1,9 @@ +import * as sapper from '../__sapper__/client.js'; + +window.start = () => sapper.start({ + target: document.querySelector('#sapper') +}); + +window.prefetchRoutes = () => sapper.prefetchRoutes(); +window.prefetch = href => sapper.prefetch(href); +window.goto = href => sapper.goto(href); \ No newline at end of file diff --git a/test/apps/export/src/routes/_error.html b/test/apps/export/src/routes/_error.html new file mode 100644 index 0000000..4cd55d2 --- /dev/null +++ b/test/apps/export/src/routes/_error.html @@ -0,0 +1,3 @@ +

{status}

+ +

{error.message}

\ No newline at end of file diff --git a/test/apps/export/src/routes/blog/[slug].html b/test/apps/export/src/routes/blog/[slug].html new file mode 100644 index 0000000..f44adaa --- /dev/null +++ b/test/apps/export/src/routes/blog/[slug].html @@ -0,0 +1,11 @@ +

{post.title}

+ + \ No newline at end of file diff --git a/test/apps/export/src/routes/blog/[slug].json.js b/test/apps/export/src/routes/blog/[slug].json.js new file mode 100644 index 0000000..66781ad --- /dev/null +++ b/test/apps/export/src/routes/blog/[slug].json.js @@ -0,0 +1,19 @@ +import posts from './_posts.js'; + +export function get(req, res) { + const post = posts.find(post => post.slug === req.params.slug); + + if (post) { + res.writeHead(200, { + 'Content-Type': 'application/json' + }); + + res.end(JSON.stringify(post)); + } else { + res.writeHead(404, { + 'Content-Type': 'application/json' + }); + + res.end(JSON.stringify({ message: 'not found' })); + } +} \ No newline at end of file diff --git a/test/apps/export/src/routes/blog/_posts.js b/test/apps/export/src/routes/blog/_posts.js new file mode 100644 index 0000000..d283aa6 --- /dev/null +++ b/test/apps/export/src/routes/blog/_posts.js @@ -0,0 +1,5 @@ +export default [ + { slug: 'foo', title: 'once upon a foo' }, + { slug: 'bar', title: 'a bar is born' }, + { slug: 'baz', title: 'bazzily ever after' } +]; \ No newline at end of file diff --git a/test/apps/export/src/routes/blog/index.html b/test/apps/export/src/routes/blog/index.html new file mode 100644 index 0000000..2eea681 --- /dev/null +++ b/test/apps/export/src/routes/blog/index.html @@ -0,0 +1,15 @@ +

blog

+ +{#each posts as post} +

{post.title}

+{/each} + + \ No newline at end of file diff --git a/test/apps/export/src/routes/blog/index.json.js b/test/apps/export/src/routes/blog/index.json.js new file mode 100644 index 0000000..0097f77 --- /dev/null +++ b/test/apps/export/src/routes/blog/index.json.js @@ -0,0 +1,9 @@ +import posts from './_posts.js'; + +export function get(req, res) { + res.writeHead(200, { + 'Content-Type': 'application/json' + }); + + res.end(JSON.stringify(posts)); +} \ No newline at end of file diff --git a/test/apps/export/src/routes/index.html b/test/apps/export/src/routes/index.html new file mode 100644 index 0000000..cdeb5a8 --- /dev/null +++ b/test/apps/export/src/routes/index.html @@ -0,0 +1,4 @@ +

Great success!

+ +blog +empty anchor \ No newline at end of file diff --git a/test/apps/export/src/server.js b/test/apps/export/src/server.js new file mode 100644 index 0000000..d5a668b --- /dev/null +++ b/test/apps/export/src/server.js @@ -0,0 +1,15 @@ +import sirv from 'sirv'; +import polka from 'polka'; +import * as sapper from '../__sapper__/server.js'; + +const { PORT, NODE_ENV } = process.env; +const dev = NODE_ENV === 'development'; + +polka() + .use( + sirv('static', { dev }), + sapper.middleware() + ) + .listen(PORT, err => { + if (err) console.log('error', err); + }); diff --git a/test/apps/export/src/service-worker.js b/test/apps/export/src/service-worker.js new file mode 100644 index 0000000..9d2ac9d --- /dev/null +++ b/test/apps/export/src/service-worker.js @@ -0,0 +1,82 @@ +import { timestamp, files, shell, routes } from '../__sapper__/service-worker.js'; + +const ASSETS = `cache${timestamp}`; + +// `shell` is an array of all the files generated by webpack, +// `files` is an array of everything in the `static` directory +const to_cache = shell.concat(ASSETS); +const cached = new Set(to_cache); + +self.addEventListener('install', event => { + event.waitUntil( + caches + .open(ASSETS) + .then(cache => cache.addAll(to_cache)) + .then(() => { + self.skipWaiting(); + }) + ); +}); + +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(async keys => { + // delete old caches + for (const key of keys) { + if (key !== ASSETS) await caches.delete(key); + } + + self.clients.claim(); + }) + ); +}); + +self.addEventListener('fetch', event => { + if (event.request.method !== 'GET') return; + + const url = new URL(event.request.url); + + // don't try to handle e.g. data: URIs + if (!url.protocol.startsWith('http')) return; + + // ignore dev server requests + if (url.hostname === self.location.hostname && url.port !== self.location.port) return; + + // always serve assets and webpack-generated files from cache + if (url.host === self.location.host && cached.has(url.pathname)) { + event.respondWith(caches.match(event.request)); + return; + } + + // for pages, you might want to serve a shell `index.html` file, + // which Sapper has generated for you. It's not right for every + // app, but if it's right for yours then uncomment this section + /* + if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) { + event.respondWith(caches.match('/index.html')); + return; + } + */ + + if (event.request.cache === 'only-if-cached') return; + + // for everything else, try the network first, falling back to + // cache if the user is offline. (If the pages never change, you + // might prefer a cache-first approach to a network-first one.) + event.respondWith( + caches + .open(`offline${timestamp}`) + .then(async cache => { + try { + const response = await fetch(event.request); + cache.put(event.request, response.clone()); + return response; + } catch(err) { + const response = await cache.match(event.request); + if (response) return response; + + throw err; + } + }) + ); +}); diff --git a/test/apps/export/src/template.html b/test/apps/export/src/template.html new file mode 100644 index 0000000..0eb1f3b --- /dev/null +++ b/test/apps/export/src/template.html @@ -0,0 +1,14 @@ + + + + + + %sapper.base% + %sapper.styles% + %sapper.head% + + +
%sapper.html%
+ %sapper.scripts% + + diff --git a/test/apps/export/static/global.css b/test/apps/export/static/global.css new file mode 100644 index 0000000..800f57a --- /dev/null +++ b/test/apps/export/static/global.css @@ -0,0 +1,3 @@ +body { + font-family: 'Comic Sans MS'; +} \ No newline at end of file diff --git a/test/apps/export/test.ts b/test/apps/export/test.ts new file mode 100644 index 0000000..897bc5f --- /dev/null +++ b/test/apps/export/test.ts @@ -0,0 +1,39 @@ +import * as assert from 'assert'; +import { walk } from '../../utils'; +import * as api from '../../../api'; + +describe('export', function() { + this.timeout(10000); + + // hooks + before(async () => { + await api.build({ cwd: __dirname }); + await api.export({ cwd: __dirname }); + }); + + it('crawls a site', () => { + const files = walk(`${__dirname}/__sapper__/export`); + + const client_assets = files.filter(file => file.startsWith('client/')); + const non_client_assets = files.filter(file => !file.startsWith('client/')).sort(); + + assert.ok(client_assets.length > 0); + + assert.deepEqual(non_client_assets, [ + 'blog.json', + 'blog/bar.json', + 'blog/bar/index.html', + 'blog/baz.json', + 'blog/baz/index.html', + 'blog/foo.json', + 'blog/foo/index.html', + 'blog/index.html', + 'global.css', + 'index.html', + 'service-worker-index.html', + 'service-worker.js' + ]); + }); + + // TODO test timeout, basepath +}); \ No newline at end of file diff --git a/test/apps/ignore/rollup.config.js b/test/apps/ignore/rollup.config.js new file mode 100644 index 0000000..943b676 --- /dev/null +++ b/test/apps/ignore/rollup.config.js @@ -0,0 +1,64 @@ +import resolve from 'rollup-plugin-node-resolve'; +import replace from 'rollup-plugin-replace'; +import svelte from 'rollup-plugin-svelte'; + +const mode = process.env.NODE_ENV; +const dev = mode === 'development'; + +const config = require('../../../config/rollup.js'); + +export default { + client: { + input: config.client.input(), + output: config.client.output(), + plugins: [ + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + dev, + hydratable: true, + emitCss: true + }), + resolve() + ], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + server: { + input: config.server.input(), + output: config.server.output(), + plugins: [ + replace({ + 'process.browser': false, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + generate: 'ssr', + dev + }), + resolve({ + preferBuiltins: true + }) + ], + external: ['sirv', 'polka'], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + serviceworker: { + input: config.serviceworker.input(), + output: config.serviceworker.output(), + plugins: [ + resolve(), + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }) + ] + } +}; \ No newline at end of file diff --git a/test/apps/ignore/src/client.js b/test/apps/ignore/src/client.js new file mode 100644 index 0000000..0865a4a --- /dev/null +++ b/test/apps/ignore/src/client.js @@ -0,0 +1,9 @@ +import * as sapper from '../__sapper__/client.js'; + +window.start = () => sapper.start({ + target: document.querySelector('#sapper') +}); + +window.prefetchRoutes = () => sapper.prefetchRoutes(); +window.prefetch = href => sapper.prefetch(href); +window.goto = href => sapper.goto(href); \ No newline at end of file diff --git a/test/apps/ignore/src/routes/[slug].html b/test/apps/ignore/src/routes/[slug].html new file mode 100644 index 0000000..ade66de --- /dev/null +++ b/test/apps/ignore/src/routes/[slug].html @@ -0,0 +1 @@ +

{params.slug.toUpperCase()}

\ No newline at end of file diff --git a/test/apps/ignore/src/routes/_error.html b/test/apps/ignore/src/routes/_error.html new file mode 100644 index 0000000..4cd55d2 --- /dev/null +++ b/test/apps/ignore/src/routes/_error.html @@ -0,0 +1,3 @@ +

{status}

+ +

{error.message}

\ No newline at end of file diff --git a/test/apps/ignore/src/routes/a.html b/test/apps/ignore/src/routes/a.html new file mode 100644 index 0000000..0e6757b --- /dev/null +++ b/test/apps/ignore/src/routes/a.html @@ -0,0 +1 @@ +

a

\ No newline at end of file diff --git a/test/apps/ignore/src/routes/b/index.html b/test/apps/ignore/src/routes/b/index.html new file mode 100644 index 0000000..d93079d --- /dev/null +++ b/test/apps/ignore/src/routes/b/index.html @@ -0,0 +1,11 @@ +

{letter}

+ + \ No newline at end of file diff --git a/test/apps/ignore/src/routes/b/index.json.js b/test/apps/ignore/src/routes/b/index.json.js new file mode 100644 index 0000000..29b7ede --- /dev/null +++ b/test/apps/ignore/src/routes/b/index.json.js @@ -0,0 +1,3 @@ +export function get(req, res) { + res.end(JSON.stringify('b')); +} \ No newline at end of file diff --git a/test/apps/ignore/src/routes/index.html b/test/apps/ignore/src/routes/index.html new file mode 100644 index 0000000..e08c0cb --- /dev/null +++ b/test/apps/ignore/src/routes/index.html @@ -0,0 +1,3 @@ +

Great success!

+ +a \ No newline at end of file diff --git a/test/apps/ignore/src/server.js b/test/apps/ignore/src/server.js new file mode 100644 index 0000000..f987e4a --- /dev/null +++ b/test/apps/ignore/src/server.js @@ -0,0 +1,19 @@ +import polka from 'polka'; +import * as sapper from '../__sapper__/server.js'; + +const { PORT } = process.env; + +const app = polka().use(sapper.middleware({ + ignore: [ + /foobar/i, + '/buzz', + 'fizz', + x => x === '/hello' + ] +})); + +['foobar', 'buzz', 'fizzer', 'hello'].forEach(uri => { + app.get('/'+uri, (req, res) => res.end(uri)); +}); + +app.listen(PORT); diff --git a/test/apps/ignore/src/service-worker.js b/test/apps/ignore/src/service-worker.js new file mode 100644 index 0000000..9d2ac9d --- /dev/null +++ b/test/apps/ignore/src/service-worker.js @@ -0,0 +1,82 @@ +import { timestamp, files, shell, routes } from '../__sapper__/service-worker.js'; + +const ASSETS = `cache${timestamp}`; + +// `shell` is an array of all the files generated by webpack, +// `files` is an array of everything in the `static` directory +const to_cache = shell.concat(ASSETS); +const cached = new Set(to_cache); + +self.addEventListener('install', event => { + event.waitUntil( + caches + .open(ASSETS) + .then(cache => cache.addAll(to_cache)) + .then(() => { + self.skipWaiting(); + }) + ); +}); + +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(async keys => { + // delete old caches + for (const key of keys) { + if (key !== ASSETS) await caches.delete(key); + } + + self.clients.claim(); + }) + ); +}); + +self.addEventListener('fetch', event => { + if (event.request.method !== 'GET') return; + + const url = new URL(event.request.url); + + // don't try to handle e.g. data: URIs + if (!url.protocol.startsWith('http')) return; + + // ignore dev server requests + if (url.hostname === self.location.hostname && url.port !== self.location.port) return; + + // always serve assets and webpack-generated files from cache + if (url.host === self.location.host && cached.has(url.pathname)) { + event.respondWith(caches.match(event.request)); + return; + } + + // for pages, you might want to serve a shell `index.html` file, + // which Sapper has generated for you. It's not right for every + // app, but if it's right for yours then uncomment this section + /* + if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) { + event.respondWith(caches.match('/index.html')); + return; + } + */ + + if (event.request.cache === 'only-if-cached') return; + + // for everything else, try the network first, falling back to + // cache if the user is offline. (If the pages never change, you + // might prefer a cache-first approach to a network-first one.) + event.respondWith( + caches + .open(`offline${timestamp}`) + .then(async cache => { + try { + const response = await fetch(event.request); + cache.put(event.request, response.clone()); + return response; + } catch(err) { + const response = await cache.match(event.request); + if (response) return response; + + throw err; + } + }) + ); +}); diff --git a/test/apps/ignore/src/template.html b/test/apps/ignore/src/template.html new file mode 100644 index 0000000..0eb1f3b --- /dev/null +++ b/test/apps/ignore/src/template.html @@ -0,0 +1,14 @@ + + + + + + %sapper.base% + %sapper.styles% + %sapper.head% + + +
%sapper.html%
+ %sapper.scripts% + + diff --git a/test/apps/ignore/test.ts b/test/apps/ignore/test.ts new file mode 100644 index 0000000..6ec8616 --- /dev/null +++ b/test/apps/ignore/test.ts @@ -0,0 +1,58 @@ +import * as assert from 'assert'; +import * as puppeteer from 'puppeteer'; +import { build } from '../../../api'; +import { AppRunner } from '../AppRunner'; + +describe('ignore', function() { + this.timeout(10000); + + let runner: AppRunner; + let page: puppeteer.Page; + let base: string; + + // hooks + before(async () => { + await build({ cwd: __dirname }); + + runner = new AppRunner(__dirname, '__sapper__/build/server/server.js'); + ({ base, page } = await runner.start()); + }); + + after(() => runner.end()); + + it('respects `options.ignore` values (RegExp)', async () => { + await page.goto(`${base}/foobar`); + + assert.equal( + await page.evaluate(() => document.documentElement.textContent), + 'foobar' + ); + }); + + it('respects `options.ignore` values (String #1)', async () => { + await page.goto(`${base}/buzz`); + + assert.equal( + await page.evaluate(() => document.documentElement.textContent), + 'buzz' + ); + }); + + it('respects `options.ignore` values (String #2)', async () => { + await page.goto(`${base}/fizzer`); + + assert.equal( + await page.evaluate(() => document.documentElement.textContent), + 'fizzer' + ); + }); + + it('respects `options.ignore` values (Function)', async () => { + await page.goto(`${base}/hello`); + + assert.equal( + await page.evaluate(() => document.documentElement.textContent), + 'hello' + ); + }); +}); \ No newline at end of file diff --git a/test/apps/layout/rollup.config.js b/test/apps/layout/rollup.config.js new file mode 100644 index 0000000..943b676 --- /dev/null +++ b/test/apps/layout/rollup.config.js @@ -0,0 +1,64 @@ +import resolve from 'rollup-plugin-node-resolve'; +import replace from 'rollup-plugin-replace'; +import svelte from 'rollup-plugin-svelte'; + +const mode = process.env.NODE_ENV; +const dev = mode === 'development'; + +const config = require('../../../config/rollup.js'); + +export default { + client: { + input: config.client.input(), + output: config.client.output(), + plugins: [ + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + dev, + hydratable: true, + emitCss: true + }), + resolve() + ], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + server: { + input: config.server.input(), + output: config.server.output(), + plugins: [ + replace({ + 'process.browser': false, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + generate: 'ssr', + dev + }), + resolve({ + preferBuiltins: true + }) + ], + external: ['sirv', 'polka'], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + serviceworker: { + input: config.serviceworker.input(), + output: config.serviceworker.output(), + plugins: [ + resolve(), + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }) + ] + } +}; \ No newline at end of file diff --git a/test/apps/layout/src/client.js b/test/apps/layout/src/client.js new file mode 100644 index 0000000..0865a4a --- /dev/null +++ b/test/apps/layout/src/client.js @@ -0,0 +1,9 @@ +import * as sapper from '../__sapper__/client.js'; + +window.start = () => sapper.start({ + target: document.querySelector('#sapper') +}); + +window.prefetchRoutes = () => sapper.prefetchRoutes(); +window.prefetch = href => sapper.prefetch(href); +window.goto = href => sapper.goto(href); \ No newline at end of file diff --git a/test/apps/layout/src/routes/[slug].html b/test/apps/layout/src/routes/[slug].html new file mode 100644 index 0000000..ade66de --- /dev/null +++ b/test/apps/layout/src/routes/[slug].html @@ -0,0 +1 @@ +

{params.slug.toUpperCase()}

\ No newline at end of file diff --git a/test/app/routes/[x]/[y]/[z].html b/test/apps/layout/src/routes/[x]/[y]/[z].html similarity index 87% rename from test/app/routes/[x]/[y]/[z].html rename to test/apps/layout/src/routes/[x]/[y]/[z].html index 787e413..018f001 100644 --- a/test/app/routes/[x]/[y]/[z].html +++ b/test/apps/layout/src/routes/[x]/[y]/[z].html @@ -1,5 +1,5 @@ z: {segment} {count} - +click me \ No newline at end of file diff --git a/test/app/routes/redirect-root.html b/test/apps/redirects/src/routes/redirect-to-root.html similarity index 70% rename from test/app/routes/redirect-root.html rename to test/apps/redirects/src/routes/redirect-to-root.html index ddd4b49..0fa438b 100644 --- a/test/app/routes/redirect-root.html +++ b/test/apps/redirects/src/routes/redirect-to-root.html @@ -1,7 +1,9 @@ +

unredirected

+ + \ No newline at end of file diff --git a/test/app/routes/redirect-to.html b/test/apps/redirects/src/routes/redirect-to.html similarity index 100% rename from test/app/routes/redirect-to.html rename to test/apps/redirects/src/routes/redirect-to.html diff --git a/test/apps/redirects/src/server.js b/test/apps/redirects/src/server.js new file mode 100644 index 0000000..0e7741c --- /dev/null +++ b/test/apps/redirects/src/server.js @@ -0,0 +1,8 @@ +import polka from 'polka'; +import * as sapper from '../__sapper__/server.js'; + +const { PORT } = process.env; + +polka() + .use(sapper.middleware()) + .listen(PORT); diff --git a/test/apps/redirects/src/service-worker.js b/test/apps/redirects/src/service-worker.js new file mode 100644 index 0000000..9d2ac9d --- /dev/null +++ b/test/apps/redirects/src/service-worker.js @@ -0,0 +1,82 @@ +import { timestamp, files, shell, routes } from '../__sapper__/service-worker.js'; + +const ASSETS = `cache${timestamp}`; + +// `shell` is an array of all the files generated by webpack, +// `files` is an array of everything in the `static` directory +const to_cache = shell.concat(ASSETS); +const cached = new Set(to_cache); + +self.addEventListener('install', event => { + event.waitUntil( + caches + .open(ASSETS) + .then(cache => cache.addAll(to_cache)) + .then(() => { + self.skipWaiting(); + }) + ); +}); + +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(async keys => { + // delete old caches + for (const key of keys) { + if (key !== ASSETS) await caches.delete(key); + } + + self.clients.claim(); + }) + ); +}); + +self.addEventListener('fetch', event => { + if (event.request.method !== 'GET') return; + + const url = new URL(event.request.url); + + // don't try to handle e.g. data: URIs + if (!url.protocol.startsWith('http')) return; + + // ignore dev server requests + if (url.hostname === self.location.hostname && url.port !== self.location.port) return; + + // always serve assets and webpack-generated files from cache + if (url.host === self.location.host && cached.has(url.pathname)) { + event.respondWith(caches.match(event.request)); + return; + } + + // for pages, you might want to serve a shell `index.html` file, + // which Sapper has generated for you. It's not right for every + // app, but if it's right for yours then uncomment this section + /* + if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) { + event.respondWith(caches.match('/index.html')); + return; + } + */ + + if (event.request.cache === 'only-if-cached') return; + + // for everything else, try the network first, falling back to + // cache if the user is offline. (If the pages never change, you + // might prefer a cache-first approach to a network-first one.) + event.respondWith( + caches + .open(`offline${timestamp}`) + .then(async cache => { + try { + const response = await fetch(event.request); + cache.put(event.request, response.clone()); + return response; + } catch(err) { + const response = await cache.match(event.request); + if (response) return response; + + throw err; + } + }) + ); +}); diff --git a/test/apps/redirects/src/template.html b/test/apps/redirects/src/template.html new file mode 100644 index 0000000..0eb1f3b --- /dev/null +++ b/test/apps/redirects/src/template.html @@ -0,0 +1,14 @@ + + + + + + %sapper.base% + %sapper.styles% + %sapper.head% + + +
%sapper.html%
+ %sapper.scripts% + + diff --git a/test/apps/redirects/test.ts b/test/apps/redirects/test.ts new file mode 100644 index 0000000..50d6507 --- /dev/null +++ b/test/apps/redirects/test.ts @@ -0,0 +1,139 @@ +import * as assert from 'assert'; +import * as puppeteer from 'puppeteer'; +import { build } from '../../../api'; +import { AppRunner } from '../AppRunner'; +import { wait } from '../../utils'; + +describe('redirects', function() { + this.timeout(10000); + + let runner: AppRunner; + let page: puppeteer.Page; + let base: string; + + // helpers + let start: () => Promise; + let prefetchRoutes: () => Promise; + let title: () => Promise; + + // hooks + before(async () => { + await build({ cwd: __dirname }); + + runner = new AppRunner(__dirname, '__sapper__/build/server/server.js'); + ({ base, page, start, prefetchRoutes, title } = await runner.start({ + requestInterceptor: (interceptedRequest) => { + if (/example\.com/.test(interceptedRequest.url())) { + interceptedRequest.respond({ + status: 200, + contentType: 'text/html', + body: `

external

` + }); + } else { + interceptedRequest.continue(); + } + } + })); + }); + + after(() => runner.end()); + + it('redirects on server', async () => { + await page.goto(`${base}/redirect-from`); + + assert.equal( + page.url(), + `${base}/redirect-to` + ); + + assert.equal( + await title(), + 'redirected' + ); + }); + + it('redirects in client', async () => { + await page.goto(base); + await start(); + await prefetchRoutes(); + + await page.click('[href="redirect-from"]'); + await wait(50); + + assert.equal( + page.url(), + `${base}/redirect-to` + ); + + assert.equal( + await title(), + 'redirected' + ); + }); + + it('redirects to root on server', async () => { + await page.goto(`${base}/redirect-to-root`); + + assert.equal( + page.url(), + `${base}/` + ); + + assert.equal( + await title(), + 'root' + ); + }); + + it('redirects to root in client', async () => { + await page.goto(base); + await start(); + await prefetchRoutes(); + + await page.click('[href="redirect-to-root"]'); + await wait(50); + + assert.equal( + page.url(), + `${base}/` + ); + + assert.equal( + await title(), + 'root' + ); + }); + + it('redirects to external URL on server', async () => { + await page.goto(`${base}/redirect-to-external`); + + assert.equal( + page.url(), + `https://example.com/` + ); + + assert.equal( + await title(), + 'external' + ); + }); + + it('redirects to external URL in client', async () => { + await page.goto(base); + await start(); + await prefetchRoutes(); + + await page.click('[href="redirect-to-external"]'); + await wait(50); + + assert.equal( + page.url(), + `https://example.com/` + ); + + assert.equal( + await title(), + 'external' + ); + }); +}); \ No newline at end of file diff --git a/test/apps/scroll/rollup.config.js b/test/apps/scroll/rollup.config.js new file mode 100644 index 0000000..943b676 --- /dev/null +++ b/test/apps/scroll/rollup.config.js @@ -0,0 +1,64 @@ +import resolve from 'rollup-plugin-node-resolve'; +import replace from 'rollup-plugin-replace'; +import svelte from 'rollup-plugin-svelte'; + +const mode = process.env.NODE_ENV; +const dev = mode === 'development'; + +const config = require('../../../config/rollup.js'); + +export default { + client: { + input: config.client.input(), + output: config.client.output(), + plugins: [ + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + dev, + hydratable: true, + emitCss: true + }), + resolve() + ], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + server: { + input: config.server.input(), + output: config.server.output(), + plugins: [ + replace({ + 'process.browser': false, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + generate: 'ssr', + dev + }), + resolve({ + preferBuiltins: true + }) + ], + external: ['sirv', 'polka'], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + serviceworker: { + input: config.serviceworker.input(), + output: config.serviceworker.output(), + plugins: [ + resolve(), + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }) + ] + } +}; \ No newline at end of file diff --git a/test/apps/scroll/src/client.js b/test/apps/scroll/src/client.js new file mode 100644 index 0000000..0865a4a --- /dev/null +++ b/test/apps/scroll/src/client.js @@ -0,0 +1,9 @@ +import * as sapper from '../__sapper__/client.js'; + +window.start = () => sapper.start({ + target: document.querySelector('#sapper') +}); + +window.prefetchRoutes = () => sapper.prefetchRoutes(); +window.prefetch = href => sapper.prefetch(href); +window.goto = href => sapper.goto(href); \ No newline at end of file diff --git a/test/apps/scroll/src/routes/_error.html b/test/apps/scroll/src/routes/_error.html new file mode 100644 index 0000000..4cd55d2 --- /dev/null +++ b/test/apps/scroll/src/routes/_error.html @@ -0,0 +1,3 @@ +

{status}

+ +

{error.message}

\ No newline at end of file diff --git a/test/apps/scroll/src/routes/another-tall-page.html b/test/apps/scroll/src/routes/another-tall-page.html new file mode 100644 index 0000000..d66879b --- /dev/null +++ b/test/apps/scroll/src/routes/another-tall-page.html @@ -0,0 +1,2 @@ +
+

element

\ No newline at end of file diff --git a/test/apps/scroll/src/routes/index.html b/test/apps/scroll/src/routes/index.html new file mode 100644 index 0000000..0cc4b72 --- /dev/null +++ b/test/apps/scroll/src/routes/index.html @@ -0,0 +1 @@ +

Great success!

\ No newline at end of file diff --git a/test/apps/scroll/src/routes/tall-page.html b/test/apps/scroll/src/routes/tall-page.html new file mode 100644 index 0000000..67db967 --- /dev/null +++ b/test/apps/scroll/src/routes/tall-page.html @@ -0,0 +1,24 @@ +scroll to foo +
+ +
+ link + link + {#if barLink} + link + {/if} +
+ + \ No newline at end of file diff --git a/test/apps/scroll/src/server.js b/test/apps/scroll/src/server.js new file mode 100644 index 0000000..0e7741c --- /dev/null +++ b/test/apps/scroll/src/server.js @@ -0,0 +1,8 @@ +import polka from 'polka'; +import * as sapper from '../__sapper__/server.js'; + +const { PORT } = process.env; + +polka() + .use(sapper.middleware()) + .listen(PORT); diff --git a/test/apps/scroll/src/service-worker.js b/test/apps/scroll/src/service-worker.js new file mode 100644 index 0000000..9d2ac9d --- /dev/null +++ b/test/apps/scroll/src/service-worker.js @@ -0,0 +1,82 @@ +import { timestamp, files, shell, routes } from '../__sapper__/service-worker.js'; + +const ASSETS = `cache${timestamp}`; + +// `shell` is an array of all the files generated by webpack, +// `files` is an array of everything in the `static` directory +const to_cache = shell.concat(ASSETS); +const cached = new Set(to_cache); + +self.addEventListener('install', event => { + event.waitUntil( + caches + .open(ASSETS) + .then(cache => cache.addAll(to_cache)) + .then(() => { + self.skipWaiting(); + }) + ); +}); + +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(async keys => { + // delete old caches + for (const key of keys) { + if (key !== ASSETS) await caches.delete(key); + } + + self.clients.claim(); + }) + ); +}); + +self.addEventListener('fetch', event => { + if (event.request.method !== 'GET') return; + + const url = new URL(event.request.url); + + // don't try to handle e.g. data: URIs + if (!url.protocol.startsWith('http')) return; + + // ignore dev server requests + if (url.hostname === self.location.hostname && url.port !== self.location.port) return; + + // always serve assets and webpack-generated files from cache + if (url.host === self.location.host && cached.has(url.pathname)) { + event.respondWith(caches.match(event.request)); + return; + } + + // for pages, you might want to serve a shell `index.html` file, + // which Sapper has generated for you. It's not right for every + // app, but if it's right for yours then uncomment this section + /* + if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) { + event.respondWith(caches.match('/index.html')); + return; + } + */ + + if (event.request.cache === 'only-if-cached') return; + + // for everything else, try the network first, falling back to + // cache if the user is offline. (If the pages never change, you + // might prefer a cache-first approach to a network-first one.) + event.respondWith( + caches + .open(`offline${timestamp}`) + .then(async cache => { + try { + const response = await fetch(event.request); + cache.put(event.request, response.clone()); + return response; + } catch(err) { + const response = await cache.match(event.request); + if (response) return response; + + throw err; + } + }) + ); +}); diff --git a/test/apps/scroll/src/template.html b/test/apps/scroll/src/template.html new file mode 100644 index 0000000..0eb1f3b --- /dev/null +++ b/test/apps/scroll/src/template.html @@ -0,0 +1,14 @@ + + + + + + %sapper.base% + %sapper.styles% + %sapper.head% + + +
%sapper.html%
+ %sapper.scripts% + + diff --git a/test/apps/scroll/test.ts b/test/apps/scroll/test.ts new file mode 100644 index 0000000..cd9209e --- /dev/null +++ b/test/apps/scroll/test.ts @@ -0,0 +1,91 @@ +import * as assert from 'assert'; +import * as puppeteer from 'puppeteer'; +import { build } from '../../../api'; +import { AppRunner } from '../AppRunner'; +import { wait } from '../../utils'; + +describe('scroll', function() { + this.timeout(10000); + + let runner: AppRunner; + let page: puppeteer.Page; + let base: string; + + // helpers + let start: () => Promise; + let prefetchRoutes: () => Promise; + + // hooks + before(async () => { + await build({ cwd: __dirname }); + + runner = new AppRunner(__dirname, '__sapper__/build/server/server.js'); + ({ base, page, start, prefetchRoutes } = await runner.start()); + }); + + after(() => runner.end()); + + it('scrolls to active deeplink', async () => { + await page.goto(`${base}/tall-page#foo`); + await start(); + + const scrollY = await page.evaluate(() => window.scrollY); + assert.ok(scrollY > 0, scrollY); + }); + + it('scrolls to any deeplink if it was already active', async () => { + await page.goto(`${base}/tall-page#foo`); + await start(); + + let scrollY = await page.evaluate(() => window.scrollY); + assert.ok(scrollY > 0, scrollY); + + scrollY = await page.evaluate(() => { + window.scrollTo(0, 0) + return window.scrollY + }); + assert.ok(scrollY === 0, scrollY); + + await page.click('[href="tall-page#foo"]'); + scrollY = await page.evaluate(() => window.scrollY); + assert.ok(scrollY > 0, scrollY); + }); + + it('resets scroll when a link is clicked', async () => { + await page.goto(`${base}/tall-page#foo`); + await start(); + await prefetchRoutes(); + + await page.click('[href="another-tall-page"]'); + await wait(50); + + assert.equal( + await page.evaluate(() => window.scrollY), + 0 + ); + }); + + it('preserves scroll when a link with sapper-noscroll is clicked', async () => { + await page.goto(`${base}/tall-page#foo`); + await start(); + await prefetchRoutes(); + + await page.click('[href="another-tall-page"][sapper-noscroll]'); + await wait(50); + + const scrollY = await page.evaluate(() => window.scrollY); + + assert.ok(scrollY > 0); + }); + + it('scrolls into a deeplink on a new page', async () => { + await page.goto(`${base}/tall-page#foo`); + await start(); + await prefetchRoutes(); + + await page.click('[href="another-tall-page#bar"]'); + await wait(50); + const scrollY = await page.evaluate(() => window.scrollY); + assert.ok(scrollY > 0); + }); +}); \ No newline at end of file diff --git a/test/apps/store/rollup.config.js b/test/apps/store/rollup.config.js new file mode 100644 index 0000000..943b676 --- /dev/null +++ b/test/apps/store/rollup.config.js @@ -0,0 +1,64 @@ +import resolve from 'rollup-plugin-node-resolve'; +import replace from 'rollup-plugin-replace'; +import svelte from 'rollup-plugin-svelte'; + +const mode = process.env.NODE_ENV; +const dev = mode === 'development'; + +const config = require('../../../config/rollup.js'); + +export default { + client: { + input: config.client.input(), + output: config.client.output(), + plugins: [ + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + dev, + hydratable: true, + emitCss: true + }), + resolve() + ], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + server: { + input: config.server.input(), + output: config.server.output(), + plugins: [ + replace({ + 'process.browser': false, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + generate: 'ssr', + dev + }), + resolve({ + preferBuiltins: true + }) + ], + external: ['sirv', 'polka'], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + serviceworker: { + input: config.serviceworker.input(), + output: config.serviceworker.output(), + plugins: [ + resolve(), + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }) + ] + } +}; \ No newline at end of file diff --git a/test/apps/store/src/client.js b/test/apps/store/src/client.js new file mode 100644 index 0000000..df66471 --- /dev/null +++ b/test/apps/store/src/client.js @@ -0,0 +1,11 @@ +import { Store } from 'svelte/store.js'; +import * as sapper from '../__sapper__/client.js'; + +window.start = () => sapper.start({ + target: document.querySelector('#sapper'), + store: data => new Store(data) +}); + +window.prefetchRoutes = () => sapper.prefetchRoutes(); +window.prefetch = href => sapper.prefetch(href); +window.goto = href => sapper.goto(href); \ No newline at end of file diff --git a/test/apps/store/src/routes/_error.html b/test/apps/store/src/routes/_error.html new file mode 100644 index 0000000..4cd55d2 --- /dev/null +++ b/test/apps/store/src/routes/_error.html @@ -0,0 +1,3 @@ +

{status}

+ +

{error.message}

\ No newline at end of file diff --git a/test/apps/store/src/routes/index.html b/test/apps/store/src/routes/index.html new file mode 100644 index 0000000..221c0f5 --- /dev/null +++ b/test/apps/store/src/routes/index.html @@ -0,0 +1,7 @@ +

Great success!

+ +a +ok +ok + +
\ No newline at end of file diff --git a/test/app/routes/store.html b/test/apps/store/src/routes/store.html similarity index 100% rename from test/app/routes/store.html rename to test/apps/store/src/routes/store.html diff --git a/test/apps/store/src/server.js b/test/apps/store/src/server.js new file mode 100644 index 0000000..c40e690 --- /dev/null +++ b/test/apps/store/src/server.js @@ -0,0 +1,22 @@ +import polka from 'polka'; +import { Store } from 'svelte/store.js'; +import * as sapper from '../__sapper__/server.js'; + +const { PORT } = process.env; + +polka() + .use((req, res, next) => { + req.hello = 'hello'; + res.locals = { name: 'world' }; + next(); + }) + .use( + sapper.middleware({ + store: (req, res) => { + return new Store({ + title: `${req.hello} ${res.locals.name}` + }); + } + }) + ) + .listen(PORT); diff --git a/test/apps/store/src/service-worker.js b/test/apps/store/src/service-worker.js new file mode 100644 index 0000000..9d2ac9d --- /dev/null +++ b/test/apps/store/src/service-worker.js @@ -0,0 +1,82 @@ +import { timestamp, files, shell, routes } from '../__sapper__/service-worker.js'; + +const ASSETS = `cache${timestamp}`; + +// `shell` is an array of all the files generated by webpack, +// `files` is an array of everything in the `static` directory +const to_cache = shell.concat(ASSETS); +const cached = new Set(to_cache); + +self.addEventListener('install', event => { + event.waitUntil( + caches + .open(ASSETS) + .then(cache => cache.addAll(to_cache)) + .then(() => { + self.skipWaiting(); + }) + ); +}); + +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(async keys => { + // delete old caches + for (const key of keys) { + if (key !== ASSETS) await caches.delete(key); + } + + self.clients.claim(); + }) + ); +}); + +self.addEventListener('fetch', event => { + if (event.request.method !== 'GET') return; + + const url = new URL(event.request.url); + + // don't try to handle e.g. data: URIs + if (!url.protocol.startsWith('http')) return; + + // ignore dev server requests + if (url.hostname === self.location.hostname && url.port !== self.location.port) return; + + // always serve assets and webpack-generated files from cache + if (url.host === self.location.host && cached.has(url.pathname)) { + event.respondWith(caches.match(event.request)); + return; + } + + // for pages, you might want to serve a shell `index.html` file, + // which Sapper has generated for you. It's not right for every + // app, but if it's right for yours then uncomment this section + /* + if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) { + event.respondWith(caches.match('/index.html')); + return; + } + */ + + if (event.request.cache === 'only-if-cached') return; + + // for everything else, try the network first, falling back to + // cache if the user is offline. (If the pages never change, you + // might prefer a cache-first approach to a network-first one.) + event.respondWith( + caches + .open(`offline${timestamp}`) + .then(async cache => { + try { + const response = await fetch(event.request); + cache.put(event.request, response.clone()); + return response; + } catch(err) { + const response = await cache.match(event.request); + if (response) return response; + + throw err; + } + }) + ); +}); diff --git a/test/apps/store/src/template.html b/test/apps/store/src/template.html new file mode 100644 index 0000000..0eb1f3b --- /dev/null +++ b/test/apps/store/src/template.html @@ -0,0 +1,14 @@ + + + + + + %sapper.base% + %sapper.styles% + %sapper.head% + + +
%sapper.html%
+ %sapper.scripts% + + diff --git a/test/apps/store/test.ts b/test/apps/store/test.ts new file mode 100644 index 0000000..a8eab1c --- /dev/null +++ b/test/apps/store/test.ts @@ -0,0 +1,36 @@ +import * as assert from 'assert'; +import * as puppeteer from 'puppeteer'; +import { build } from '../../../api'; +import { AppRunner } from '../AppRunner'; + +describe('store', function() { + this.timeout(10000); + + let runner: AppRunner; + let page: puppeteer.Page; + let base: string; + + // helpers + let start: () => Promise; + + // hooks + before(async () => { + await build({ cwd: __dirname }); + + runner = new AppRunner(__dirname, '__sapper__/build/server/server.js'); + ({ base, page, start } = await runner.start()); + }); + + after(() => runner.end()); + + const title = () => page.$eval('h1', node => node.textContent); + + it('renders store props', async () => { + await page.goto(`${base}/store`); + + assert.equal(await title(), 'hello world'); + + await start(); + assert.equal(await title(), 'hello world'); + }); +}); \ No newline at end of file diff --git a/test/apps/with-basepath/rollup.config.js b/test/apps/with-basepath/rollup.config.js new file mode 100644 index 0000000..943b676 --- /dev/null +++ b/test/apps/with-basepath/rollup.config.js @@ -0,0 +1,64 @@ +import resolve from 'rollup-plugin-node-resolve'; +import replace from 'rollup-plugin-replace'; +import svelte from 'rollup-plugin-svelte'; + +const mode = process.env.NODE_ENV; +const dev = mode === 'development'; + +const config = require('../../../config/rollup.js'); + +export default { + client: { + input: config.client.input(), + output: config.client.output(), + plugins: [ + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + dev, + hydratable: true, + emitCss: true + }), + resolve() + ], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + server: { + input: config.server.input(), + output: config.server.output(), + plugins: [ + replace({ + 'process.browser': false, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + generate: 'ssr', + dev + }), + resolve({ + preferBuiltins: true + }) + ], + external: ['sirv', 'polka'], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + serviceworker: { + input: config.serviceworker.input(), + output: config.serviceworker.output(), + plugins: [ + resolve(), + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }) + ] + } +}; \ No newline at end of file diff --git a/test/apps/with-basepath/src/client.js b/test/apps/with-basepath/src/client.js new file mode 100644 index 0000000..0865a4a --- /dev/null +++ b/test/apps/with-basepath/src/client.js @@ -0,0 +1,9 @@ +import * as sapper from '../__sapper__/client.js'; + +window.start = () => sapper.start({ + target: document.querySelector('#sapper') +}); + +window.prefetchRoutes = () => sapper.prefetchRoutes(); +window.prefetch = href => sapper.prefetch(href); +window.goto = href => sapper.goto(href); \ No newline at end of file diff --git a/test/apps/with-basepath/src/routes/_error.html b/test/apps/with-basepath/src/routes/_error.html new file mode 100644 index 0000000..4cd55d2 --- /dev/null +++ b/test/apps/with-basepath/src/routes/_error.html @@ -0,0 +1,3 @@ +

{status}

+ +

{error.message}

\ No newline at end of file diff --git a/test/apps/with-basepath/src/routes/index.html b/test/apps/with-basepath/src/routes/index.html new file mode 100644 index 0000000..0cc4b72 --- /dev/null +++ b/test/apps/with-basepath/src/routes/index.html @@ -0,0 +1 @@ +

Great success!

\ No newline at end of file diff --git a/test/apps/with-basepath/src/server.js b/test/apps/with-basepath/src/server.js new file mode 100644 index 0000000..b187dad --- /dev/null +++ b/test/apps/with-basepath/src/server.js @@ -0,0 +1,16 @@ +import sirv from 'sirv'; +import polka from 'polka'; +import * as sapper from '../__sapper__/server.js'; + +const { PORT, NODE_ENV } = process.env; +const dev = NODE_ENV === 'development'; + +polka() + .use( + 'custom-basepath', + sirv('static', { dev }), + sapper.middleware() + ) + .listen(PORT, err => { + if (err) console.log('error', err); + }); diff --git a/test/apps/with-basepath/src/service-worker.js b/test/apps/with-basepath/src/service-worker.js new file mode 100644 index 0000000..9d2ac9d --- /dev/null +++ b/test/apps/with-basepath/src/service-worker.js @@ -0,0 +1,82 @@ +import { timestamp, files, shell, routes } from '../__sapper__/service-worker.js'; + +const ASSETS = `cache${timestamp}`; + +// `shell` is an array of all the files generated by webpack, +// `files` is an array of everything in the `static` directory +const to_cache = shell.concat(ASSETS); +const cached = new Set(to_cache); + +self.addEventListener('install', event => { + event.waitUntil( + caches + .open(ASSETS) + .then(cache => cache.addAll(to_cache)) + .then(() => { + self.skipWaiting(); + }) + ); +}); + +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(async keys => { + // delete old caches + for (const key of keys) { + if (key !== ASSETS) await caches.delete(key); + } + + self.clients.claim(); + }) + ); +}); + +self.addEventListener('fetch', event => { + if (event.request.method !== 'GET') return; + + const url = new URL(event.request.url); + + // don't try to handle e.g. data: URIs + if (!url.protocol.startsWith('http')) return; + + // ignore dev server requests + if (url.hostname === self.location.hostname && url.port !== self.location.port) return; + + // always serve assets and webpack-generated files from cache + if (url.host === self.location.host && cached.has(url.pathname)) { + event.respondWith(caches.match(event.request)); + return; + } + + // for pages, you might want to serve a shell `index.html` file, + // which Sapper has generated for you. It's not right for every + // app, but if it's right for yours then uncomment this section + /* + if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) { + event.respondWith(caches.match('/index.html')); + return; + } + */ + + if (event.request.cache === 'only-if-cached') return; + + // for everything else, try the network first, falling back to + // cache if the user is offline. (If the pages never change, you + // might prefer a cache-first approach to a network-first one.) + event.respondWith( + caches + .open(`offline${timestamp}`) + .then(async cache => { + try { + const response = await fetch(event.request); + cache.put(event.request, response.clone()); + return response; + } catch(err) { + const response = await cache.match(event.request); + if (response) return response; + + throw err; + } + }) + ); +}); diff --git a/test/apps/with-basepath/src/template.html b/test/apps/with-basepath/src/template.html new file mode 100644 index 0000000..0eb1f3b --- /dev/null +++ b/test/apps/with-basepath/src/template.html @@ -0,0 +1,14 @@ + + + + + + %sapper.base% + %sapper.styles% + %sapper.head% + + +
%sapper.html%
+ %sapper.scripts% + + diff --git a/test/apps/with-basepath/static/global.css b/test/apps/with-basepath/static/global.css new file mode 100644 index 0000000..800f57a --- /dev/null +++ b/test/apps/with-basepath/static/global.css @@ -0,0 +1,3 @@ +body { + font-family: 'Comic Sans MS'; +} \ No newline at end of file diff --git a/test/apps/with-basepath/test.ts b/test/apps/with-basepath/test.ts new file mode 100644 index 0000000..5741d1b --- /dev/null +++ b/test/apps/with-basepath/test.ts @@ -0,0 +1,63 @@ +import * as assert from 'assert'; +import * as puppeteer from 'puppeteer'; +import * as api from '../../../api'; +import { walk } from '../../utils'; +import { AppRunner } from '../AppRunner'; + +describe('with-basepath', function() { + this.timeout(10000); + + let runner: AppRunner; + let page: puppeteer.Page; + let base: string; + + // hooks + before(async () => { + await api.build({ cwd: __dirname }); + + await api.export({ + cwd: __dirname, + basepath: '/custom-basepath' + }); + + runner = new AppRunner(__dirname, '__sapper__/build/server/server.js'); + ({ base, page } = await runner.start()); + }); + + after(() => runner.end()); + + it('serves /custom-basepath', async () => { + await page.goto(`${base}/custom-basepath`); + + assert.equal( + await page.$eval('h1', node => node.textContent), + 'Great success!' + ); + }); + + it('emits a basepath message', async () => { + await page.goto(`${base}/custom-basepath`); + + assert.deepEqual(runner.messages, [{ + __sapper__: true, + event: 'basepath', + basepath: '/custom-basepath' + }]); + }); + + it('crawls an exported site with basepath', () => { + const files = walk(`${__dirname}/__sapper__/export`); + + const client_assets = files.filter(file => file.startsWith('custom-basepath/client/')); + const non_client_assets = files.filter(file => !file.startsWith('custom-basepath/client/')).sort(); + + assert.ok(client_assets.length > 0); + + assert.deepEqual(non_client_assets, [ + 'custom-basepath/global.css', + 'custom-basepath/index.html', + 'custom-basepath/service-worker-index.html', + 'custom-basepath/service-worker.js' + ]); + }); +}); \ No newline at end of file diff --git a/test/apps/with-sourcemaps-webpack/src/client.js b/test/apps/with-sourcemaps-webpack/src/client.js new file mode 100644 index 0000000..0865a4a --- /dev/null +++ b/test/apps/with-sourcemaps-webpack/src/client.js @@ -0,0 +1,9 @@ +import * as sapper from '../__sapper__/client.js'; + +window.start = () => sapper.start({ + target: document.querySelector('#sapper') +}); + +window.prefetchRoutes = () => sapper.prefetchRoutes(); +window.prefetch = href => sapper.prefetch(href); +window.goto = href => sapper.goto(href); \ No newline at end of file diff --git a/test/apps/with-sourcemaps-webpack/src/routes/_error.html b/test/apps/with-sourcemaps-webpack/src/routes/_error.html new file mode 100644 index 0000000..4cd55d2 --- /dev/null +++ b/test/apps/with-sourcemaps-webpack/src/routes/_error.html @@ -0,0 +1,3 @@ +

{status}

+ +

{error.message}

\ No newline at end of file diff --git a/test/apps/with-sourcemaps-webpack/src/routes/index.html b/test/apps/with-sourcemaps-webpack/src/routes/index.html new file mode 100644 index 0000000..abaff72 --- /dev/null +++ b/test/apps/with-sourcemaps-webpack/src/routes/index.html @@ -0,0 +1,3 @@ +

Great success!

+ +

Woot!

\ No newline at end of file diff --git a/test/apps/with-sourcemaps-webpack/src/server.js b/test/apps/with-sourcemaps-webpack/src/server.js new file mode 100644 index 0000000..0e7741c --- /dev/null +++ b/test/apps/with-sourcemaps-webpack/src/server.js @@ -0,0 +1,8 @@ +import polka from 'polka'; +import * as sapper from '../__sapper__/server.js'; + +const { PORT } = process.env; + +polka() + .use(sapper.middleware()) + .listen(PORT); diff --git a/test/apps/with-sourcemaps-webpack/src/service-worker.js b/test/apps/with-sourcemaps-webpack/src/service-worker.js new file mode 100644 index 0000000..9d2ac9d --- /dev/null +++ b/test/apps/with-sourcemaps-webpack/src/service-worker.js @@ -0,0 +1,82 @@ +import { timestamp, files, shell, routes } from '../__sapper__/service-worker.js'; + +const ASSETS = `cache${timestamp}`; + +// `shell` is an array of all the files generated by webpack, +// `files` is an array of everything in the `static` directory +const to_cache = shell.concat(ASSETS); +const cached = new Set(to_cache); + +self.addEventListener('install', event => { + event.waitUntil( + caches + .open(ASSETS) + .then(cache => cache.addAll(to_cache)) + .then(() => { + self.skipWaiting(); + }) + ); +}); + +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(async keys => { + // delete old caches + for (const key of keys) { + if (key !== ASSETS) await caches.delete(key); + } + + self.clients.claim(); + }) + ); +}); + +self.addEventListener('fetch', event => { + if (event.request.method !== 'GET') return; + + const url = new URL(event.request.url); + + // don't try to handle e.g. data: URIs + if (!url.protocol.startsWith('http')) return; + + // ignore dev server requests + if (url.hostname === self.location.hostname && url.port !== self.location.port) return; + + // always serve assets and webpack-generated files from cache + if (url.host === self.location.host && cached.has(url.pathname)) { + event.respondWith(caches.match(event.request)); + return; + } + + // for pages, you might want to serve a shell `index.html` file, + // which Sapper has generated for you. It's not right for every + // app, but if it's right for yours then uncomment this section + /* + if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) { + event.respondWith(caches.match('/index.html')); + return; + } + */ + + if (event.request.cache === 'only-if-cached') return; + + // for everything else, try the network first, falling back to + // cache if the user is offline. (If the pages never change, you + // might prefer a cache-first approach to a network-first one.) + event.respondWith( + caches + .open(`offline${timestamp}`) + .then(async cache => { + try { + const response = await fetch(event.request); + cache.put(event.request, response.clone()); + return response; + } catch(err) { + const response = await cache.match(event.request); + if (response) return response; + + throw err; + } + }) + ); +}); diff --git a/test/apps/with-sourcemaps-webpack/src/template.html b/test/apps/with-sourcemaps-webpack/src/template.html new file mode 100644 index 0000000..0eb1f3b --- /dev/null +++ b/test/apps/with-sourcemaps-webpack/src/template.html @@ -0,0 +1,14 @@ + + + + + + %sapper.base% + %sapper.styles% + %sapper.head% + + +
%sapper.html%
+ %sapper.scripts% + + diff --git a/test/apps/with-sourcemaps-webpack/test.ts b/test/apps/with-sourcemaps-webpack/test.ts new file mode 100644 index 0000000..cb0a3ca --- /dev/null +++ b/test/apps/with-sourcemaps-webpack/test.ts @@ -0,0 +1,43 @@ +import * as puppeteer from 'puppeteer'; +import { build } from '../../../api'; +import * as assert from "assert"; +import { AppRunner } from '../AppRunner'; +import * as fs from "fs"; +import * as path from "path"; + +describe('with-sourcemaps-webpack', function() { + this.timeout(10000); + + let runner: AppRunner; + let page: puppeteer.Page; + let base: string; + + // helpers + let start: () => Promise; + let prefetchRoutes: () => Promise; + let prefetch: (href: string) => Promise; + let goto: (href: string) => Promise; + + // hooks + before(async () => { + await build({ cwd: __dirname, bundler: 'webpack' }); + + runner = new AppRunner(__dirname, '__sapper__/build/server/server.js'); + ({ base, page, start, prefetchRoutes, prefetch, goto } = await runner.start()); + }); + + it('does not put sourcemap files in service worker shell', async () => { + const serviceWorker = await import(`${__dirname}/__sapper__/service-worker.js`); + const shell: string[] = serviceWorker.shell; + + assert.equal(shell.filter(_ => _.endsWith('.map')).length, 0, + 'sourcemap files are not cached in SW'); + + const clientShellDir = path.resolve(`${__dirname}/__sapper__/build`, path.dirname(shell[0])); + const sourcemapFiles = fs.readdirSync(clientShellDir).filter(_ => _.endsWith('.map')); + assert.ok(sourcemapFiles.length > 0, 'sourcemap files exist'); + }); + + after(() => runner.end()); + +}); \ No newline at end of file diff --git a/test/apps/with-sourcemaps-webpack/webpack.config.js b/test/apps/with-sourcemaps-webpack/webpack.config.js new file mode 100644 index 0000000..40b612d --- /dev/null +++ b/test/apps/with-sourcemaps-webpack/webpack.config.js @@ -0,0 +1,73 @@ +const webpack = require('webpack'); +const config = require('../../../config/webpack.js'); + +const mode = process.env.NODE_ENV; +const dev = mode === 'development'; + +module.exports = { + client: { + entry: config.client.entry(), + output: config.client.output(), + resolve: { + extensions: ['.js', '.json', '.html'], + mainFields: ['svelte', 'module', 'browser', 'main'] + }, + module: { + rules: [ + { + test: /\.html$/, + use: { + loader: 'svelte-loader', + options: { + dev, + hydratable: true, + hotReload: true + } + } + } + ] + }, + mode, + plugins: [ + dev && new webpack.HotModuleReplacementPlugin(), + new webpack.DefinePlugin({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + ].filter(Boolean), + devtool: dev ? 'inline-source-map' : 'source-map' + }, + + server: { + entry: config.server.entry(), + output: config.server.output(), + target: 'node', + resolve: { + extensions: ['.js', '.json', '.html'], + mainFields: ['svelte', 'module', 'browser', 'main'] + }, + module: { + rules: [ + { + test: /\.html$/, + use: { + loader: 'svelte-loader', + options: { + css: false, + generate: 'ssr', + dev + } + } + } + ] + }, + mode: process.env.NODE_ENV + }, + + serviceworker: { + entry: config.serviceworker.entry(), + output: config.serviceworker.output(), + mode: process.env.NODE_ENV, + devtool: 'sourcemap' + } +}; diff --git a/test/apps/with-sourcemaps/rollup.config.js b/test/apps/with-sourcemaps/rollup.config.js new file mode 100644 index 0000000..c057e2e --- /dev/null +++ b/test/apps/with-sourcemaps/rollup.config.js @@ -0,0 +1,64 @@ +import resolve from 'rollup-plugin-node-resolve'; +import replace from 'rollup-plugin-replace'; +import svelte from 'rollup-plugin-svelte'; + +const mode = process.env.NODE_ENV; +const dev = mode === 'development'; + +const config = require('../../../config/rollup.js'); + +export default { + client: { + input: config.client.input(), + output: Object.assign({}, config.client.output(), { sourcemap: true }), + plugins: [ + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + dev, + hydratable: true, + emitCss: true + }), + resolve() + ], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + server: { + input: config.server.input(), + output: config.server.output(), + plugins: [ + replace({ + 'process.browser': false, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + generate: 'ssr', + dev + }), + resolve({ + preferBuiltins: true + }) + ], + external: ['sirv', 'polka'], + + // temporary, pending Rollup 1.0 + experimentalCodeSplitting: true + }, + + serviceworker: { + input: config.serviceworker.input(), + output: config.serviceworker.output(), + plugins: [ + resolve(), + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }) + ] + } +}; \ No newline at end of file diff --git a/test/apps/with-sourcemaps/src/client.js b/test/apps/with-sourcemaps/src/client.js new file mode 100644 index 0000000..0865a4a --- /dev/null +++ b/test/apps/with-sourcemaps/src/client.js @@ -0,0 +1,9 @@ +import * as sapper from '../__sapper__/client.js'; + +window.start = () => sapper.start({ + target: document.querySelector('#sapper') +}); + +window.prefetchRoutes = () => sapper.prefetchRoutes(); +window.prefetch = href => sapper.prefetch(href); +window.goto = href => sapper.goto(href); \ No newline at end of file diff --git a/test/apps/with-sourcemaps/src/routes/_error.html b/test/apps/with-sourcemaps/src/routes/_error.html new file mode 100644 index 0000000..4cd55d2 --- /dev/null +++ b/test/apps/with-sourcemaps/src/routes/_error.html @@ -0,0 +1,3 @@ +

{status}

+ +

{error.message}

\ No newline at end of file diff --git a/test/apps/with-sourcemaps/src/routes/index.html b/test/apps/with-sourcemaps/src/routes/index.html new file mode 100644 index 0000000..abaff72 --- /dev/null +++ b/test/apps/with-sourcemaps/src/routes/index.html @@ -0,0 +1,3 @@ +

Great success!

+ +

Woot!

\ No newline at end of file diff --git a/test/apps/with-sourcemaps/src/server.js b/test/apps/with-sourcemaps/src/server.js new file mode 100644 index 0000000..0e7741c --- /dev/null +++ b/test/apps/with-sourcemaps/src/server.js @@ -0,0 +1,8 @@ +import polka from 'polka'; +import * as sapper from '../__sapper__/server.js'; + +const { PORT } = process.env; + +polka() + .use(sapper.middleware()) + .listen(PORT); diff --git a/test/apps/with-sourcemaps/src/service-worker.js b/test/apps/with-sourcemaps/src/service-worker.js new file mode 100644 index 0000000..9d2ac9d --- /dev/null +++ b/test/apps/with-sourcemaps/src/service-worker.js @@ -0,0 +1,82 @@ +import { timestamp, files, shell, routes } from '../__sapper__/service-worker.js'; + +const ASSETS = `cache${timestamp}`; + +// `shell` is an array of all the files generated by webpack, +// `files` is an array of everything in the `static` directory +const to_cache = shell.concat(ASSETS); +const cached = new Set(to_cache); + +self.addEventListener('install', event => { + event.waitUntil( + caches + .open(ASSETS) + .then(cache => cache.addAll(to_cache)) + .then(() => { + self.skipWaiting(); + }) + ); +}); + +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(async keys => { + // delete old caches + for (const key of keys) { + if (key !== ASSETS) await caches.delete(key); + } + + self.clients.claim(); + }) + ); +}); + +self.addEventListener('fetch', event => { + if (event.request.method !== 'GET') return; + + const url = new URL(event.request.url); + + // don't try to handle e.g. data: URIs + if (!url.protocol.startsWith('http')) return; + + // ignore dev server requests + if (url.hostname === self.location.hostname && url.port !== self.location.port) return; + + // always serve assets and webpack-generated files from cache + if (url.host === self.location.host && cached.has(url.pathname)) { + event.respondWith(caches.match(event.request)); + return; + } + + // for pages, you might want to serve a shell `index.html` file, + // which Sapper has generated for you. It's not right for every + // app, but if it's right for yours then uncomment this section + /* + if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) { + event.respondWith(caches.match('/index.html')); + return; + } + */ + + if (event.request.cache === 'only-if-cached') return; + + // for everything else, try the network first, falling back to + // cache if the user is offline. (If the pages never change, you + // might prefer a cache-first approach to a network-first one.) + event.respondWith( + caches + .open(`offline${timestamp}`) + .then(async cache => { + try { + const response = await fetch(event.request); + cache.put(event.request, response.clone()); + return response; + } catch(err) { + const response = await cache.match(event.request); + if (response) return response; + + throw err; + } + }) + ); +}); diff --git a/test/apps/with-sourcemaps/src/template.html b/test/apps/with-sourcemaps/src/template.html new file mode 100644 index 0000000..0eb1f3b --- /dev/null +++ b/test/apps/with-sourcemaps/src/template.html @@ -0,0 +1,14 @@ + + + + + + %sapper.base% + %sapper.styles% + %sapper.head% + + +
%sapper.html%
+ %sapper.scripts% + + diff --git a/test/apps/with-sourcemaps/test.ts b/test/apps/with-sourcemaps/test.ts new file mode 100644 index 0000000..1b61c28 --- /dev/null +++ b/test/apps/with-sourcemaps/test.ts @@ -0,0 +1,43 @@ +import * as puppeteer from 'puppeteer'; +import { build } from '../../../api'; +import * as assert from "assert"; +import { AppRunner } from '../AppRunner'; +import * as fs from 'fs'; +import * as path from "path"; + +describe('with-sourcemaps', function() { + this.timeout(10000); + + let runner: AppRunner; + let page: puppeteer.Page; + let base: string; + + // helpers + let start: () => Promise; + let prefetchRoutes: () => Promise; + let prefetch: (href: string) => Promise; + let goto: (href: string) => Promise; + + // hooks + before(async () => { + await build({ cwd: __dirname }); + + runner = new AppRunner(__dirname, '__sapper__/build/server/server.js'); + ({ base, page, start, prefetchRoutes, prefetch, goto } = await runner.start()); + }); + + it('does not put sourcemap files in service worker shell', async () => { + const serviceWorker = await import(`${__dirname}/__sapper__/service-worker.js`); + const shell: string[] = serviceWorker.shell; + + assert.equal(shell.filter(_ => _.endsWith('.map')).length, 0, + 'sourcemap files are not cached in SW'); + + const clientShellDir = path.resolve(`${__dirname}/__sapper__/build`, path.dirname(shell[0])); + const sourcemapFiles = fs.readdirSync(clientShellDir).filter(_ => _.endsWith('.map')); + assert.ok(sourcemapFiles.length > 0, 'sourcemap files exist'); + }); + + after(() => runner.end()); + +}); \ No newline at end of file diff --git a/test/common/test.js b/test/common/test.js deleted file mode 100644 index 2db23ff..0000000 --- a/test/common/test.js +++ /dev/null @@ -1,790 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const assert = require('assert'); -const Nightmare = require('nightmare'); -const serve = require('serve-static'); -const walkSync = require('walk-sync'); -const fetch = require('node-fetch'); -const rimraf = require('rimraf'); -const ports = require('port-authority'); - -Nightmare.action('page', { - title(done) { - this.evaluate_now(() => document.querySelector('h1').textContent, done); - }, - - html(done) { - this.evaluate_now(() => document.documentElement.innerHTML, done); - }, - - text(done) { - this.evaluate_now(() => document.body.textContent, done); - } -}); - -Nightmare.action('init', function(done) { - this.evaluate_now(() => window.init(), done); -}); - -Nightmare.action('prefetchRoutes', function(done) { - this.evaluate_now(() => window.prefetchRoutes(), done); -}); - -const cli = path.resolve(__dirname, '../../sapper'); - -const wait = ms => new Promise(f => setTimeout(f, ms)); - -describe('sapper', function() { - process.chdir(path.resolve(__dirname, '../app')); - - // clean up after previous test runs - rimraf.sync('export'); - rimraf.sync('build'); - rimraf.sync('.sapper'); - rimraf.sync('start.js'); - - this.timeout(process.env.CI ? 30000 : 15000); - - // TODO reinstate dev tests - // run({ - // mode: 'development' - // }); - - run({ - mode: 'production' - }); - - run({ - mode: 'production', - basepath: '/custom-basepath' - }); - - testExport({}); - - testExport({ basepath: '/custom-basepath' }); -}); - -function testExport({ basepath = '' }) { - describe(basepath ? `export --basepath ${basepath}` : 'export', () => { - before(() => { - if (basepath) { - process.env.BASEPATH = basepath; - } - - return exec(`node ${cli} export ${basepath ? `--basepath ${basepath}` : ''}`); - }); - - it('export all pages', () => { - const dest = path.resolve(__dirname, '../app/export'); - - // Pages that should show up in the extraction directory. - const expectedPages = [ - 'index.html', - 'about/index.html', - 'slow-preload/index.html', - - 'blog/index.html', - 'blog/a-very-long-post/index.html', - 'blog/how-can-i-get-involved/index.html', - 'blog/how-is-sapper-different-from-next/index.html', - 'blog/how-to-use-sapper/index.html', - 'blog/what-is-sapper/index.html', - 'blog/why-the-name/index.html', - - 'blog.json', - 'blog/a-very-long-post.json', - 'blog/how-can-i-get-involved.json', - 'blog/how-is-sapper-different-from-next.json', - 'blog/how-to-use-sapper.json', - 'blog/what-is-sapper.json', - 'blog/why-the-name.json', - - 'favicon.png', - 'global.css', - 'great-success.png', - 'manifest.json', - 'service-worker.js', - 'svelte-logo-192.png', - 'svelte-logo-512.png', - ].map(file => { - return basepath ? `${basepath.replace(/^[\/\\]/, '')}/${file}` : file; - }); - - // Client scripts that should show up in the extraction directory. - const expectedClientRegexes = [ - /client\/[^/]+\/main(\.\d+)?\.js/, - /client\/[^/]+\/index(\.\d+)?\.js/, - /client\/[^/]+\/about(\.\d+)?\.js/, - /client\/[^/]+\/blog_\$slug(\.\d+)?\.js/, - /client\/[^/]+\/blog(\.\d+)?\.js/, - /client\/[^/]+\/slow\$45preload(\.\d+)?\.js/, - ]; - const allPages = walkSync(dest); - - expectedPages.forEach((expectedPage) => { - assert.ok(allPages.includes(expectedPage),`Could not find page matching ${expectedPage}`); - }); - - expectedClientRegexes.forEach((expectedRegex) => { - // Ensure each client page regular expression matches at least one - // generated page. - let matched = false; - for (const page of allPages) { - if (expectedRegex.test(page)) { - matched = true; - break; - } - } - assert.ok(matched, `Could not find client page matching ${expectedRegex}`); - }); - }); - }); -} - -function run({ mode, basepath = '' }) { - describe(`mode=${mode}`, function () { - let proc; - let capture; - - let base; - let captured_basepath; - - const nightmare = new Nightmare(); - - nightmare.on('console', (type, ...args) => { - console[type](...args); - }); - - nightmare.on('page', (type, ...args) => { - if (type === 'error') { - console.error(args[1]); - } else { - console.warn(type, args); - } - }); - - before(() => { - const promise = mode === 'production' - ? exec(`node ${cli} build -l`).then(() => ports.find(3000)) - : ports.find(3000).then(port => { - exec(`node ${cli} dev`); - return ports.wait(port).then(() => port); - }); - - return promise.then(port => { - base = `http://localhost:${port}`; - if (basepath) base += basepath; - - const dir = mode === 'production' ? 'build' : '.sapper'; - - if (mode === 'production') { - assert.ok(fs.existsSync('build/index.js')); - } - - proc = require('child_process').fork(`${dir}/server.js`, { - cwd: process.cwd(), - env: { - NODE_ENV: mode, - BASEPATH: basepath, - SAPPER_DEST: dir, - PORT: port - } - }); - - let handler; - - proc.on('message', message => { - if (message.__sapper__) { - if (message.event === 'basepath') { - captured_basepath = basepath; - } - return; - } - - if (handler) handler(message); - }); - - capture = fn => { - return new Promise((fulfil, reject) => { - const captured = []; - - let start = Date.now(); - - handler = message => { - if (message.type === 'ready') { - fn().then(() => { - proc.send({ - action: 'end' - }); - }, reject); - } - - else if (message.type === 'done') { - fulfil(captured); - handler = null; - } - - else { - captured.push(message); - } - }; - - proc.send({ - action: 'start' - }); - }); - }; - }); - }); - - after(() => { - // give a chance to clean up - return Promise.all([ - nightmare.end(), - new Promise(fulfil => { - proc.on('exit', fulfil); - proc.kill(); - }) - ]); - }); - - describe('basic functionality', () => { - it('serves /', () => { - return nightmare.goto(base).page.title().then(title => { - assert.equal(title, 'Great success!'); - }); - }); - - it('serves /?', () => { - return nightmare.goto(`${base}?`).page.title().then(title => { - assert.equal(title, 'Great success!'); - }); - }); - - it('serves static route', () => { - return nightmare.goto(`${base}/about`).page.title().then(title => { - assert.equal(title, 'About this site'); - }); - }); - - it('serves dynamic route', () => { - return nightmare.goto(`${base}/blog/what-is-sapper`).page.title().then(title => { - assert.equal(title, 'What is Sapper?'); - }); - }); - - it('navigates to a new page without reloading', () => { - return nightmare.goto(base).init().prefetchRoutes() - .then(() => { - return capture(() => nightmare.click('a[href="about"]')); - }) - .then(requests => { - assert.deepEqual(requests.map(r => r.url), []); - }) - .then(() => wait(100)) - .then(() => nightmare.path()) - .then(path => { - assert.equal(path, `${basepath}/about`); - return nightmare.title(); - }) - .then(title => { - assert.equal(title, 'About'); - }); - }); - - it('navigates programmatically', () => { - return nightmare - .goto(`${base}/about`) - .init() - .evaluate(() => window.goto('blog/what-is-sapper')) - .title() - .then(title => { - assert.equal(title, 'What is Sapper?'); - }); - }); - - it('prefetches programmatically', () => { - return capture(() => nightmare.goto(`${base}/about`).init()) - .then(() => { - return capture(() => { - return nightmare - .click('.prefetch') - .wait(200); - }); - }) - .then(requests => { - assert.ok(!!requests.find(r => r.url === `/blog/why-the-name.json`)); - }); - }); - - it('scrolls to active deeplink', () => { - return nightmare - .goto(`${base}/blog/a-very-long-post#four`) - .init() - .evaluate(() => window.scrollY) - .then(scrollY => { - assert.ok(scrollY > 0, scrollY); - }); - }); - - it.skip('reuses prefetch promise', () => { - return nightmare - .goto(`${base}/blog`) - .init() - .then(() => { - return capture(() => { - return nightmare - .evaluate(() => { - const a = document.querySelector('[href="blog/what-is-sapper"]'); - a.dispatchEvent(new MouseEvent('mousemove')); - }) - .wait(200); - }); - }) - .then(mouseover_requests => { - assert.ok(mouseover_requests.findIndex(r => r.url === `/blog/what-is-sapper.json`) !== -1); - - return capture(() => { - return nightmare - .click('[href="blog/what-is-sapper"]') - .wait(200); - }); - }) - .then(click_requests => { - assert.ok(click_requests.findIndex(r => r.url === `/blog/what-is-sapper.json`) === -1); - }); - }); - - it('cancels navigation if subsequent navigation occurs during preload', () => { - return nightmare - .goto(base) - .init() - .click('a[href="slow-preload"]') - .wait(100) - .click('a[href="about"]') - .wait(100) - .then(() => nightmare.path()) - .then(path => { - assert.equal(path, `${basepath}/about`); - return nightmare.title(); - }) - .then(title => { - assert.equal(title, 'About'); - return nightmare.evaluate(() => window.fulfil({})).wait(100); - }) - .then(() => nightmare.path()) - .then(path => { - assert.equal(path, `${basepath}/about`); - return nightmare.title(); - }) - .then(title => { - assert.equal(title, 'About'); - }); - }); - - it('calls a delete handler', () => { - return nightmare - .goto(`${base}/delete-test`) - .init() - .click('.del') - .wait(() => window.deleted) - .evaluate(() => window.deleted.id) - .then(id => { - assert.equal(id, 42); - }); - }); - - it('hydrates initial route', () => { - return nightmare.goto(base) - .wait('.hydrate-test') - .evaluate(() => { - window.el = document.querySelector('.hydrate-test'); - }) - .init() - .evaluate(() => { - return document.querySelector('.hydrate-test') === window.el; - }) - .then(matches => { - assert.ok(matches); - }); - }); - - it('redirects on server', () => { - return nightmare.goto(`${base}/redirect-from`) - .path() - .then(path => { - assert.equal(path, `${basepath}/redirect-to`); - }) - .then(() => nightmare.page.title()) - .then(title => { - assert.equal(title, 'redirected'); - }); - }); - - it('redirects in client', () => { - return nightmare.goto(base) - .wait('[href="redirect-from"]') - .click('[href="redirect-from"]') - .wait(200) - .path() - .then(path => { - assert.equal(path, `${basepath}/redirect-to`); - }) - .then(() => nightmare.page.title()) - .then(title => { - assert.equal(title, 'redirected'); - }); - }); - - it('redirects on server (root)', () => { - return nightmare.goto(`${base}/redirect-root`) - .path() - .then(path => { - assert.equal(path, `${basepath}/`); - }) - .then(() => nightmare.page.title()) - .then(title => { - assert.equal(title, 'Great success!'); - }); - }); - - it('redirects in client (root)', () => { - return nightmare.goto(base) - .wait('[href="redirect-root"]') - .click('[href="redirect-root"]') - .wait(200) - .path() - .then(path => { - assert.equal(path, `${basepath}/`); - }) - .then(() => nightmare.page.title()) - .then(title => { - assert.equal(title, 'Great success!'); - }); - }); - - it('handles 4xx error on server', () => { - return nightmare.goto(`${base}/blog/nope`) - .path() - .then(path => { - assert.equal(path, `${basepath}/blog/nope`); - }) - .then(() => nightmare.page.title()) - .then(title => { - assert.equal(title, '404') - }); - }); - - it('handles 4xx error in client', () => { - return nightmare.goto(base) - .init() - .click('[href="blog/nope"]') - .wait(200) - .path() - .then(path => { - assert.equal(path, `${basepath}/blog/nope`); - }) - .then(() => nightmare.page.title()) - .then(title => { - assert.equal(title, '404'); - }); - }); - - it('handles non-4xx error on server', () => { - return nightmare.goto(`${base}/blog/throw-an-error`) - .path() - .then(path => { - assert.equal(path, `${basepath}/blog/throw-an-error`); - }) - .then(() => nightmare.page.title()) - .then(title => { - assert.equal(title, '500') - }); - }); - - it('handles non-4xx error in client', () => { - return nightmare.goto(base) - .init() - .click('[href="blog/throw-an-error"]') - .wait(200) - .path() - .then(path => { - assert.equal(path, `${basepath}/blog/throw-an-error`); - }) - .then(() => nightmare.page.title()) - .then(title => { - assert.equal(title, '500'); - }); - }); - - // Ignores are meant for top-level escape. - // ~> Sapper **should** own the entire {basepath} when designated. - if (!basepath) { - it('respects `options.ignore` values (RegExp)', () => { - return nightmare.goto(`${base}/foobar`) - .evaluate(() => document.documentElement.textContent) - .then(text => { - assert.equal(text, 'foobar'); - }); - }); - - it('respects `options.ignore` values (String #1)', () => { - return nightmare.goto(`${base}/buzz`) - .evaluate(() => document.documentElement.textContent) - .then(text => { - assert.equal(text, 'buzz'); - }); - }); - - it('respects `options.ignore` values (String #2)', () => { - return nightmare.goto(`${base}/fizzer`) - .evaluate(() => document.documentElement.textContent) - .then(text => { - assert.equal(text, 'fizzer'); - }); - }); - - it('respects `options.ignore` values (Function)', () => { - return nightmare.goto(`${base}/hello`) - .evaluate(() => document.documentElement.textContent) - .then(text => { - assert.equal(text, 'hello'); - }); - }); - } - - it('does not attempt client-side navigation to server routes', () => { - return nightmare.goto(`${base}/blog/how-is-sapper-different-from-next`) - .init() - .click(`[href="blog/how-is-sapper-different-from-next.json"]`) - .wait(200) - .page.text() - .then(text => { - JSON.parse(text); - }); - }); - - it('does not serve error page for non-page errors', () => { - return nightmare.goto(`${base}/throw-an-error`) - .page.text() - .then(text => { - assert.equal(text, 'nope'); - }); - }); - - it('encodes routes', () => { - return nightmare.goto(`${base}/fünke`) - .page.title() - .then(title => { - assert.equal(title, `I'm afraid I just blue myself`); - }); - }); - - it('serializes Set objects returned from preload', () => { - return nightmare.goto(`${base}/preload-values/set`) - .page.title() - .then(title => { - assert.equal(title, 'true'); - return nightmare.init().page.title(); - }) - .then(title => { - assert.equal(title, 'true'); - }); - }); - - it('bails on custom classes returned from preload', () => { - return nightmare.goto(`${base}/preload-values/custom-class`) - .page.title() - .then(title => { - assert.equal(title, '42'); - return nightmare.init().page.title(); - }) - .then(title => { - assert.equal(title, '42'); - }); - }); - - it('renders store props', () => { - return nightmare.goto(`${base}/store`) - .page.title() - .then(title => { - assert.equal(title, 'hello world'); - return nightmare.init().page.title(); - }) - .then(title => { - assert.equal(title, 'hello world'); - }); - }); - - it('sends cookies when using this.fetch with credentials: "include"', () => { - return nightmare.goto(`${base}/credentials?creds=include`) - .page.title() - .then(title => { - assert.equal(title, 'woohoo!'); - }); - }); - - it('does not send cookies when using this.fetch without credentials', () => { - return nightmare.goto(`${base}/credentials`) - .page.title() - .then(title => { - assert.equal(title, 'unauthorized'); - }); - }); - - it('delegates to fetch on the client', () => { - return nightmare.goto(base).init() - .click('[href="credentials?creds=include"]') - .wait(100) - .page.title() - .then(title => { - assert.equal(title, 'woohoo!'); - }); - }); - - it('includes service worker', () => { - return nightmare.goto(base).page.html().then(html => { - assert.ok(html.indexOf('service-worker.js') !== -1); - }); - }); - - it('sets preloading true when appropriate', () => { - return nightmare - .goto(base) - .init() - .click('a[href="slow-preload"]') - .wait(100) - .evaluate(() => { - const progress = document.querySelector('progress'); - return !!progress; - }) - .then(hasProgressIndicator => { - assert.ok(hasProgressIndicator); - }) - .then(() => nightmare.evaluate(() => window.fulfil())) - .then(() => nightmare.evaluate(() => { - const progress = document.querySelector('progress'); - return !!progress; - })) - .then(hasProgressIndicator => { - assert.ok(!hasProgressIndicator); - }); - }); - - it('emits a basepath', () => { - assert.equal(captured_basepath, basepath); - }); - - // skipped because Nightmare doesn't seem to focus the correctly - it.skip('resets the active element after navigation', () => { - return nightmare - .goto(base) - .init() - .click('a[href="about"]') - .wait(100) - .evaluate(() => document.activeElement.nodeName) - .then(name => { - assert.equal(name, 'BODY'); - }); - }); - - it('replaces %sapper.xxx% tags safely', () => { - return nightmare - .goto(`${base}/unsafe-replacement`) - .init() - .page.html() - .then(html => { - assert.equal(html.indexOf('%sapper'), -1); - }); - }); - - it('only recreates components when necessary', () => { - return nightmare - .goto(`${base}/foo/bar/baz`) - .init() - .evaluate(() => document.querySelector('#sapper').textContent) - .then(text => { - assert.deepEqual(text.split('\n').filter(Boolean), [ - 'y: bar 1', - 'z: baz 1', - 'child segment: baz' - ]); - - return nightmare.click(`a`) - .then(() => wait(100)) - .then(() => { - return nightmare.evaluate(() => document.querySelector('#sapper').textContent); - }); - }) - .then(text => { - assert.deepEqual(text.split('\n').filter(Boolean), [ - 'y: bar 1', - 'z: qux 2', - 'child segment: qux' - ]); - }); - }); - - it('uses a fallback index component if none is provided', () => { - return nightmare.goto(`${base}/missing-index/ok`) - .page.title() - .then(title => { - assert.equal(title, 'it works'); - }); - }); - - it('runs preload in root component', () => { - return nightmare.goto(`${base}/preload-root`) - .page.title() - .then(title => { - assert.equal(title, 'root preload function ran: true'); - }); - }); - }); - - describe('headers', () => { - it('sets Content-Type and Link...preload headers', () => { - return capture(() => nightmare.goto(base)).then(requests => { - const { headers } = requests[0]; - - assert.equal( - headers['content-type'], - 'text/html' - ); - - const str = ['main', '.+?\\.\\d+'] - .map(file => { - return `<${basepath}/client/[^/]+/${file}\\.js>;rel="preload";as="script"`; - }) - .join(', '); - - const regex = new RegExp(str); - - assert.ok( - regex.test(headers['link']), - headers['link'] - ); - }); - }); - }); - }); -} - -function exec(cmd) { - return new Promise((fulfil, reject) => { - const parts = cmd.trim().split(' '); - const proc = require('child_process').spawn(parts.shift(), parts); - - proc.stdout.on('data', data => { - process.stdout.write(data); - }); - - proc.stderr.on('data', data => { - process.stderr.write(data); - }); - - proc.on('error', reject); - - proc.on('close', () => fulfil()); - }); -} diff --git a/test/unit/create_routes/index.ts b/test/unit/create_manifest_data/index.ts similarity index 69% rename from test/unit/create_routes/index.ts rename to test/unit/create_manifest_data/index.ts index 6c61bc3..d21a537 100644 --- a/test/unit/create_routes/index.ts +++ b/test/unit/create_manifest_data/index.ts @@ -1,10 +1,10 @@ import * as path from 'path'; import * as assert from 'assert'; -import create_routes from '../../../src/core/create_routes'; +import create_manifest_data from '../../../src/core/create_manifest_data'; -describe('create_routes', () => { +describe('manifest_data', () => { it('creates routes', () => { - const { components, pages, server_routes } = create_routes(path.join(__dirname, 'samples/basic')); + const { components, pages, server_routes } = create_manifest_data(path.join(__dirname, 'samples/basic')); const index = { name: 'index', file: 'index.html' }; const about = { name: 'about', file: 'about.html' }; @@ -53,14 +53,14 @@ describe('create_routes', () => { assert.deepEqual(server_routes, [ { name: 'route_blog_json', - pattern: /^\/blog.json\/?$/, + pattern: /^\/blog.json$/, file: 'blog/index.json.js', params: [] }, { name: 'route_blog_$slug_json', - pattern: /^\/blog\/([^\/]+?).json\/?$/, + pattern: /^\/blog\/([^\/]+?).json$/, file: 'blog/[slug].json.js', params: ['slug'] } @@ -68,7 +68,7 @@ describe('create_routes', () => { }); it('encodes invalid characters', () => { - const { components, pages } = create_routes(path.join(__dirname, 'samples/encoding')); + const { components, pages } = create_manifest_data(path.join(__dirname, 'samples/encoding')); // had to remove ? and " because windows @@ -90,7 +90,7 @@ describe('create_routes', () => { }); it('allows regex qualifiers', () => { - const { pages } = create_routes(path.join(__dirname, 'samples/qualifiers')); + const { pages } = create_manifest_data(path.join(__dirname, 'samples/qualifiers')); assert.deepEqual(pages.map(p => p.pattern), [ /^\/([0-9-a-z]{3,})\/?$/, @@ -100,7 +100,7 @@ describe('create_routes', () => { }); it('sorts routes correctly', () => { - const { pages } = create_routes(path.join(__dirname, 'samples/sorting')); + const { pages } = create_manifest_data(path.join(__dirname, 'samples/sorting')); assert.deepEqual(pages.map(p => p.parts.map(part => part && part.component.file)), [ ['index.html'], @@ -116,7 +116,7 @@ describe('create_routes', () => { }); it('ignores files and directories with leading underscores', () => { - const { server_routes } = create_routes(path.join(__dirname, 'samples/hidden-underscore')); + const { server_routes } = create_manifest_data(path.join(__dirname, 'samples/hidden-underscore')); assert.deepEqual(server_routes.map(r => r.file), [ 'index.js', @@ -125,7 +125,7 @@ describe('create_routes', () => { }); it('ignores files and directories with leading dots except .well-known', () => { - const { server_routes } = create_routes(path.join(__dirname, 'samples/hidden-dot')); + const { server_routes } = create_manifest_data(path.join(__dirname, 'samples/hidden-dot')); assert.deepEqual(server_routes.map(r => r.file), [ '.well-known/dnt-policy.txt.js' @@ -134,24 +134,35 @@ describe('create_routes', () => { it('fails on clashes', () => { assert.throws(() => { - const { pages } = create_routes(path.join(__dirname, 'samples/clash-pages')); + const { pages } = create_manifest_data(path.join(__dirname, 'samples/clash-pages')); }, /The \[bar\]\/index\.html and \[foo\]\.html pages clash/); assert.throws(() => { - const { server_routes } = create_routes(path.join(__dirname, 'samples/clash-routes')); + const { server_routes } = create_manifest_data(path.join(__dirname, 'samples/clash-routes')); console.log(server_routes); }, /The \[bar\]\/index\.js and \[foo\]\.js routes clash/); }); it('fails if dynamic params are not separated', () => { assert.throws(() => { - create_routes(path.join(__dirname, 'samples/invalid-params')); + create_manifest_data(path.join(__dirname, 'samples/invalid-params')); }, /Invalid route \[foo\]\[bar\]\.js — parameters must be separated/); }); it('errors when trying to use reserved characters in route regexp', () => { assert.throws(() => { - create_routes(path.join(__dirname, 'samples/invalid-qualifier')); + create_manifest_data(path.join(__dirname, 'samples/invalid-qualifier')); }, /Invalid route \[foo\(\[a-z\]\(\[0-9\]\)\)\].js — cannot use \(, \), \? or \: in route qualifiers/); }); + + it('ignores things that look like lockfiles' , () => { + const { server_routes } = create_manifest_data(path.join(__dirname, 'samples/lockfiles')); + + assert.deepEqual(server_routes, [{ + file: 'foo.js', + name: 'route_foo', + params: [], + pattern: /^\/foo$/ + }]); + }); }); \ No newline at end of file diff --git a/test/unit/create_routes/samples/basic/about.html b/test/unit/create_manifest_data/samples/basic/about.html similarity index 100% rename from test/unit/create_routes/samples/basic/about.html rename to test/unit/create_manifest_data/samples/basic/about.html diff --git a/test/unit/create_routes/samples/qualifiers/[slug].html b/test/unit/create_manifest_data/samples/basic/blog/[slug].html similarity index 100% rename from test/unit/create_routes/samples/qualifiers/[slug].html rename to test/unit/create_manifest_data/samples/basic/blog/[slug].html diff --git a/test/unit/create_routes/samples/basic/blog/[slug].json.js b/test/unit/create_manifest_data/samples/basic/blog/[slug].json.js similarity index 100% rename from test/unit/create_routes/samples/basic/blog/[slug].json.js rename to test/unit/create_manifest_data/samples/basic/blog/[slug].json.js diff --git a/test/unit/create_routes/samples/basic/blog/_default.html b/test/unit/create_manifest_data/samples/basic/blog/_default.html similarity index 100% rename from test/unit/create_routes/samples/basic/blog/_default.html rename to test/unit/create_manifest_data/samples/basic/blog/_default.html diff --git a/test/unit/create_routes/samples/basic/blog/index.html b/test/unit/create_manifest_data/samples/basic/blog/index.html similarity index 100% rename from test/unit/create_routes/samples/basic/blog/index.html rename to test/unit/create_manifest_data/samples/basic/blog/index.html diff --git a/test/unit/create_routes/samples/basic/blog/index.json.js b/test/unit/create_manifest_data/samples/basic/blog/index.json.js similarity index 100% rename from test/unit/create_routes/samples/basic/blog/index.json.js rename to test/unit/create_manifest_data/samples/basic/blog/index.json.js diff --git a/test/unit/create_routes/samples/basic/index.html b/test/unit/create_manifest_data/samples/basic/index.html similarity index 100% rename from test/unit/create_routes/samples/basic/index.html rename to test/unit/create_manifest_data/samples/basic/index.html diff --git a/test/unit/create_routes/samples/clash-pages/[bar]/index.html b/test/unit/create_manifest_data/samples/clash-pages/[bar]/index.html similarity index 100% rename from test/unit/create_routes/samples/clash-pages/[bar]/index.html rename to test/unit/create_manifest_data/samples/clash-pages/[bar]/index.html diff --git a/test/unit/create_routes/samples/clash-pages/[foo].html b/test/unit/create_manifest_data/samples/clash-pages/[foo].html similarity index 100% rename from test/unit/create_routes/samples/clash-pages/[foo].html rename to test/unit/create_manifest_data/samples/clash-pages/[foo].html diff --git a/test/unit/create_routes/samples/clash-pages/index.html b/test/unit/create_manifest_data/samples/clash-pages/index.html similarity index 100% rename from test/unit/create_routes/samples/clash-pages/index.html rename to test/unit/create_manifest_data/samples/clash-pages/index.html diff --git a/test/unit/create_routes/samples/clash-routes/[bar]/index.js b/test/unit/create_manifest_data/samples/clash-routes/[bar]/index.js similarity index 100% rename from test/unit/create_routes/samples/clash-routes/[bar]/index.js rename to test/unit/create_manifest_data/samples/clash-routes/[bar]/index.js diff --git a/test/unit/create_routes/samples/clash-routes/[foo].js b/test/unit/create_manifest_data/samples/clash-routes/[foo].js similarity index 100% rename from test/unit/create_routes/samples/clash-routes/[foo].js rename to test/unit/create_manifest_data/samples/clash-routes/[foo].js diff --git a/test/unit/create_routes/samples/clash-routes/index.html b/test/unit/create_manifest_data/samples/clash-routes/index.html similarity index 100% rename from test/unit/create_routes/samples/clash-routes/index.html rename to test/unit/create_manifest_data/samples/clash-routes/index.html diff --git a/test/unit/create_routes/samples/encoding/#.html b/test/unit/create_manifest_data/samples/encoding/#.html similarity index 100% rename from test/unit/create_routes/samples/encoding/#.html rename to test/unit/create_manifest_data/samples/encoding/#.html diff --git a/test/unit/create_routes/samples/hidden-dot/.unknown/foo.txt.js b/test/unit/create_manifest_data/samples/hidden-dot/.unknown/foo.txt.js similarity index 100% rename from test/unit/create_routes/samples/hidden-dot/.unknown/foo.txt.js rename to test/unit/create_manifest_data/samples/hidden-dot/.unknown/foo.txt.js diff --git a/test/unit/create_routes/samples/hidden-dot/.well-known/dnt-policy.txt.js b/test/unit/create_manifest_data/samples/hidden-dot/.well-known/dnt-policy.txt.js similarity index 100% rename from test/unit/create_routes/samples/hidden-dot/.well-known/dnt-policy.txt.js rename to test/unit/create_manifest_data/samples/hidden-dot/.well-known/dnt-policy.txt.js diff --git a/test/unit/create_routes/samples/hidden-underscore/_foo.js b/test/unit/create_manifest_data/samples/hidden-underscore/_foo.js similarity index 100% rename from test/unit/create_routes/samples/hidden-underscore/_foo.js rename to test/unit/create_manifest_data/samples/hidden-underscore/_foo.js diff --git a/test/unit/create_routes/samples/hidden-underscore/a/_b/c/d.js b/test/unit/create_manifest_data/samples/hidden-underscore/a/_b/c/d.js similarity index 100% rename from test/unit/create_routes/samples/hidden-underscore/a/_b/c/d.js rename to test/unit/create_manifest_data/samples/hidden-underscore/a/_b/c/d.js diff --git a/test/unit/create_routes/samples/hidden-underscore/e/f/g/h.js b/test/unit/create_manifest_data/samples/hidden-underscore/e/f/g/h.js similarity index 100% rename from test/unit/create_routes/samples/hidden-underscore/e/f/g/h.js rename to test/unit/create_manifest_data/samples/hidden-underscore/e/f/g/h.js diff --git a/test/unit/create_routes/samples/hidden-underscore/i/_j.js b/test/unit/create_manifest_data/samples/hidden-underscore/i/_j.js similarity index 100% rename from test/unit/create_routes/samples/hidden-underscore/i/_j.js rename to test/unit/create_manifest_data/samples/hidden-underscore/i/_j.js diff --git a/test/unit/create_routes/samples/hidden-underscore/index.html b/test/unit/create_manifest_data/samples/hidden-underscore/index.html similarity index 100% rename from test/unit/create_routes/samples/hidden-underscore/index.html rename to test/unit/create_manifest_data/samples/hidden-underscore/index.html diff --git a/test/unit/create_routes/samples/hidden-underscore/index.js b/test/unit/create_manifest_data/samples/hidden-underscore/index.js similarity index 100% rename from test/unit/create_routes/samples/hidden-underscore/index.js rename to test/unit/create_manifest_data/samples/hidden-underscore/index.js diff --git a/test/unit/create_routes/samples/invalid-params/[foo][bar].js b/test/unit/create_manifest_data/samples/invalid-params/[foo][bar].js similarity index 100% rename from test/unit/create_routes/samples/invalid-params/[foo][bar].js rename to test/unit/create_manifest_data/samples/invalid-params/[foo][bar].js diff --git a/test/unit/create_routes/samples/invalid-qualifier/[foo([a-z]([0-9]))].js b/test/unit/create_manifest_data/samples/invalid-qualifier/[foo([a-z]([0-9]))].js similarity index 100% rename from test/unit/create_routes/samples/invalid-qualifier/[foo([a-z]([0-9]))].js rename to test/unit/create_manifest_data/samples/invalid-qualifier/[foo([a-z]([0-9]))].js diff --git a/test/unit/create_routes/samples/qualifiers/[slug([0-9-a-z]{3,})].html b/test/unit/create_manifest_data/samples/lockfiles/foo.js similarity index 100% rename from test/unit/create_routes/samples/qualifiers/[slug([0-9-a-z]{3,})].html rename to test/unit/create_manifest_data/samples/lockfiles/foo.js diff --git a/test/unit/create_routes/samples/qualifiers/[slug([a-z]{2})].html b/test/unit/create_manifest_data/samples/lockfiles/foo.js_tmp similarity index 100% rename from test/unit/create_routes/samples/qualifiers/[slug([a-z]{2})].html rename to test/unit/create_manifest_data/samples/lockfiles/foo.js_tmp diff --git a/test/unit/create_routes/samples/sorting/[wildcard].html b/test/unit/create_manifest_data/samples/qualifiers/[slug([0-9-a-z]{3,})].html similarity index 100% rename from test/unit/create_routes/samples/sorting/[wildcard].html rename to test/unit/create_manifest_data/samples/qualifiers/[slug([0-9-a-z]{3,})].html diff --git a/test/unit/create_routes/samples/sorting/_layout.html b/test/unit/create_manifest_data/samples/qualifiers/[slug([a-z]{2})].html similarity index 100% rename from test/unit/create_routes/samples/sorting/_layout.html rename to test/unit/create_manifest_data/samples/qualifiers/[slug([a-z]{2})].html diff --git a/test/unit/create_routes/samples/sorting/about.html b/test/unit/create_manifest_data/samples/qualifiers/[slug].html similarity index 100% rename from test/unit/create_routes/samples/sorting/about.html rename to test/unit/create_manifest_data/samples/qualifiers/[slug].html diff --git a/test/unit/create_routes/samples/sorting/index.html b/test/unit/create_manifest_data/samples/sorting/[wildcard].html similarity index 100% rename from test/unit/create_routes/samples/sorting/index.html rename to test/unit/create_manifest_data/samples/sorting/[wildcard].html diff --git a/test/unit/create_routes/samples/sorting/post/[id([0-9-a-z]{3,})].html b/test/unit/create_manifest_data/samples/sorting/_layout.html similarity index 100% rename from test/unit/create_routes/samples/sorting/post/[id([0-9-a-z]{3,})].html rename to test/unit/create_manifest_data/samples/sorting/_layout.html diff --git a/test/unit/create_routes/samples/sorting/post/[id].html b/test/unit/create_manifest_data/samples/sorting/about.html similarity index 100% rename from test/unit/create_routes/samples/sorting/post/[id].html rename to test/unit/create_manifest_data/samples/sorting/about.html diff --git a/test/unit/create_routes/samples/sorting/post/index.html b/test/unit/create_manifest_data/samples/sorting/index.html similarity index 100% rename from test/unit/create_routes/samples/sorting/post/index.html rename to test/unit/create_manifest_data/samples/sorting/index.html diff --git a/test/unit/create_routes/samples/sorting/post/_default.html b/test/unit/create_manifest_data/samples/sorting/post/[id([0-9-a-z]{3,})].html similarity index 100% rename from test/unit/create_routes/samples/sorting/post/_default.html rename to test/unit/create_manifest_data/samples/sorting/post/[id([0-9-a-z]{3,})].html diff --git a/test/unit/create_routes/samples/sorting/post/bar.html b/test/unit/create_manifest_data/samples/sorting/post/[id].html similarity index 100% rename from test/unit/create_routes/samples/sorting/post/bar.html rename to test/unit/create_manifest_data/samples/sorting/post/[id].html diff --git a/test/unit/create_routes/samples/sorting/post/f[xx].html b/test/unit/create_manifest_data/samples/sorting/post/_default.html similarity index 100% rename from test/unit/create_routes/samples/sorting/post/f[xx].html rename to test/unit/create_manifest_data/samples/sorting/post/_default.html diff --git a/test/unit/create_routes/samples/sorting/post/foo.html b/test/unit/create_manifest_data/samples/sorting/post/bar.html similarity index 100% rename from test/unit/create_routes/samples/sorting/post/foo.html rename to test/unit/create_manifest_data/samples/sorting/post/bar.html diff --git a/test/unit/create_manifest_data/samples/sorting/post/f[xx].html b/test/unit/create_manifest_data/samples/sorting/post/f[xx].html new file mode 100644 index 0000000..e69de29 diff --git a/test/unit/create_manifest_data/samples/sorting/post/foo.html b/test/unit/create_manifest_data/samples/sorting/post/foo.html new file mode 100644 index 0000000..e69de29 diff --git a/test/unit/create_manifest_data/samples/sorting/post/index.html b/test/unit/create_manifest_data/samples/sorting/post/index.html new file mode 100644 index 0000000..e69de29 diff --git a/test/utils.ts b/test/utils.ts new file mode 100644 index 0000000..fa802fa --- /dev/null +++ b/test/utils.ts @@ -0,0 +1,23 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +export function wait(ms: number) { + return new Promise(fulfil => setTimeout(fulfil, ms)); +} + +export function walk(cwd: string, dir = cwd, files: string[] = []) { + fs.readdirSync(dir).forEach(file => { + const resolved = path.resolve(dir, file); + if (fs.statSync(resolved).isDirectory()) { + walk(cwd, resolved, files); + } else { + files.push(posixify(path.relative(cwd, resolved))); + } + }); + + return files; +} + +function posixify(str: string) { + return str.replace(/\\/g, '/'); +} \ No newline at end of file diff --git a/webpack.js b/webpack.js index bb688ff..96fb4ce 100644 --- a/webpack.js +++ b/webpack.js @@ -1,2 +1,2 @@ -// TODO write to this file, instead of webpack.ts.js -module.exports = require('./dist/webpack.ts.js'); \ No newline at end of file +console.error(`[DEPRECATION] As of Sapper 0.18, webpack config should be loaded from sapper/config/webpack.js`); +module.exports = require('./dist/webpack.js'); \ No newline at end of file diff --git a/webpack/config.js b/webpack/config.js index 6483555..388f348 100644 --- a/webpack/config.js +++ b/webpack/config.js @@ -1,2 +1,2 @@ -// TODO deprecate this file in favour of sapper/webpack.js -module.exports = require('../dist/webpack.ts.js'); \ No newline at end of file +console.error(`[DEPRECATION] As of Sapper 0.18, webpack config should be loaded from sapper/config/webpack.js`); +module.exports = require('../dist/webpack.js'); \ No newline at end of file