From 9cc325281b6be24599b5afb36e2d5e2b1cc90d08 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 23 Mar 2019 18:52:59 -0600 Subject: [PATCH 001/404] Configure typescript --- .eslintrc.json | 6 - .vscode/launch.json | 21 +- package-lock.json | 2271 ++++++++++++++++++++++++------------------- package.json | 62 +- tsconfig.json | 12 + 5 files changed, 1370 insertions(+), 1002 deletions(-) delete mode 100644 .eslintrc.json create mode 100644 tsconfig.json diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 8ebb2e5e..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "standard", - "env": { - "mocha": true - } -} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index f9db6af3..f2888c29 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,24 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "type": "node", + "request": "launch", + "name": "TS - Mocha Tests", + "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", + "args": [ + "--require", + "ts-node/register", + "-u", + "tdd", + "--timeout", + "999999", + "--colors", + "--recursive", + "${workspaceFolder}/src/**/*.ts" + ], + "internalConsoleOptions": "openOnSessionStart" + }, { "type": "node", "request": "launch", @@ -36,6 +54,7 @@ "request": "attach", "name": "Attach to Process", "port": 5858 - } + }, + ] } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 24f43896..a2e7f042 100644 --- a/package-lock.json +++ b/package-lock.json @@ -192,12 +192,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -268,12 +262,6 @@ "to-fast-properties": "^2.0.0" } }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -303,12 +291,6 @@ "to-fast-properties": "^2.0.0" } }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -484,12 +466,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -619,12 +595,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -808,12 +778,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -877,12 +841,6 @@ "to-fast-properties": "^2.0.0" } }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -911,12 +869,6 @@ "to-fast-properties": "^2.0.0" } }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -946,12 +898,6 @@ "to-fast-properties": "^2.0.0" } }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -1058,12 +1004,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1101,12 +1041,6 @@ "to-fast-properties": "^2.0.0" } }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -1128,14 +1062,6 @@ "dev": true, "requires": { "lodash": "^4.17.5" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - } } }, "@babel/helper-remap-async-to-generator": { @@ -1307,12 +1233,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -1504,12 +1424,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -1619,12 +1533,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1819,12 +1727,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -2015,12 +1917,6 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -2222,12 +2118,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -2340,17 +2230,17 @@ "dev": true }, "regexpu-core": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz", - "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", + "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", "dev": true, "requires": { "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^7.0.0", + "regenerate-unicode-properties": "^8.0.2", "regjsgen": "^0.5.0", "regjsparser": "^0.6.0", "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.0.2" + "unicode-match-property-value-ecmascript": "^1.1.0" } }, "regjsgen": { @@ -2515,14 +2405,6 @@ "requires": { "@babel/helper-plugin-utils": "7.0.0-beta.47", "lodash": "^4.17.5" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - } } }, "@babel/plugin-transform-classes": { @@ -2651,12 +2533,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -2716,17 +2592,17 @@ "dev": true }, "regexpu-core": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz", - "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", + "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", "dev": true, "requires": { "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^7.0.0", + "regenerate-unicode-properties": "^8.0.2", "regjsgen": "^0.5.0", "regjsparser": "^0.6.0", "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.0.2" + "unicode-match-property-value-ecmascript": "^1.1.0" } }, "regjsgen": { @@ -2879,12 +2755,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -3002,12 +2872,6 @@ "to-fast-properties": "^2.0.0" } }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -3117,17 +2981,17 @@ "dev": true }, "regexpu-core": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.4.0.tgz", - "integrity": "sha512-eDDWElbwwI3K0Lo6CqbQbA6FwgtCz4kYTarrri1okfkRLZAqstU+B3voZBCjg8Fl6iq0gXrJG6MvRgLthfvgOA==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", + "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", "dev": true, "requires": { "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^7.0.0", + "regenerate-unicode-properties": "^8.0.2", "regjsgen": "^0.5.0", "regjsparser": "^0.6.0", "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.0.2" + "unicode-match-property-value-ecmascript": "^1.1.0" } }, "regjsgen": { @@ -3610,10 +3474,22 @@ } } }, + "@types/chai": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", + "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", + "dev": true + }, + "@types/mocha": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.6.tgz", + "integrity": "sha512-1axi39YdtBI7z957vdqXI4Ac25e7YihYQtJa+Clnxg1zTJEaIRbndt71O3sP4GAMgiAm0pY26/b9BrY4MR/PMw==", + "dev": true + }, "@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==", + "version": "11.11.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", + "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==", "dev": true }, "@types/socket.io": { @@ -3625,6 +3501,59 @@ "@types/node": "*" } }, + "@typescript-eslint/eslint-plugin": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.5.0.tgz", + "integrity": "sha512-TZ5HRDFz6CswqBUviPX8EfS+iOoGbclYroZKT3GWGYiGScX0qo6QjHc5uuM7JN920voP2zgCkHgF5SDEVlCtjQ==", + "dev": true, + "requires": { + "@typescript-eslint/parser": "1.5.0", + "@typescript-eslint/typescript-estree": "1.5.0", + "requireindex": "^1.2.0", + "tsutils": "^3.7.0" + } + }, + "@typescript-eslint/parser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.5.0.tgz", + "integrity": "sha512-pRWTnJrnxuT0ragdY26hZL+bxqDd4liMlftpH2CBlMPryOIOb1J+MdZuw6R4tIu6bWVdwbHKPTs+Q34LuGvfGw==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "1.5.0", + "eslint-scope": "^4.0.0", + "eslint-visitor-keys": "^1.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } + } + }, + "@typescript-eslint/typescript-estree": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.5.0.tgz", + "integrity": "sha512-XqR14d4BcYgxcrpxIwcee7UEjncl9emKc/MgkeUfIk2u85KlsGYyaxC7Zxjmb17JtWERk/NaO+KnBsqgpIXzwA==", + "dev": true, + "requires": { + "lodash.unescape": "4.0.1", + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + } + } + }, "@vue/babel-preset-app": { "version": "3.0.0-beta.11", "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-3.0.0-beta.11.tgz", @@ -3642,9 +3571,9 @@ } }, "@vue/component-compiler-utils": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-2.5.2.tgz", - "integrity": "sha512-3exq9O89GXo9E+CGKzgURCbasG15FtFMs8QRrCUVWGaKue4Egpw41MHb3Avtikv1VykKfBq3FvAnf9Nx3sdVJg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-2.6.0.tgz", + "integrity": "sha512-IHjxt7LsOFYc0DkTncB7OXJL7UzwOLPPQCfEUNyxL2qt+tF12THV+EO33O1G2Uk4feMSWua3iD39Itszx0f0bw==", "dev": true, "requires": { "consolidate": "^0.15.1", @@ -3655,7 +3584,7 @@ "postcss-selector-parser": "^5.0.0", "prettier": "1.16.3", "source-map": "~0.6.1", - "vue-template-es2015-compiler": "^1.8.2" + "vue-template-es2015-compiler": "^1.9.0" }, "dependencies": { "ansi-styles": { @@ -3723,6 +3652,12 @@ "uniq": "^1.0.1" } }, + "prettier": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.3.tgz", + "integrity": "sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -3740,179 +3675,211 @@ } } }, + "@vue/eslint-config-prettier": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-4.0.1.tgz", + "integrity": "sha512-rJEDXPb61Hfgg8GllO3XXFP98bcIxdNNHSrNcxP/vBSukOolgOwQyZJ5f5z/c7ViPyh5/IDlC4qBnhx/0n+I4g==", + "dev": true, + "requires": { + "eslint-config-prettier": "^3.3.0", + "eslint-plugin-prettier": "^3.0.0", + "prettier": "^1.15.2" + }, + "dependencies": { + "eslint-config-prettier": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-3.6.0.tgz", + "integrity": "sha512-ixJ4U3uTLXwJts4rmSVW/lMXjlGwCijhBJHk8iVqKKSifeI0qgFEfWl8L63isfc8Od7EiBALF6BX3jKLluf/jQ==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } + } + } + }, + "@vue/eslint-config-typescript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-4.0.0.tgz", + "integrity": "sha512-uSMAMgw4xDgVdZQhpbtJRo8nMV4oOy3Ht8olfOo7xvYFYLMF2JZ1tDRKd9/NSusxA72O2Vma+HzmyzDHg9evcQ==", + "dev": true, + "requires": { + "@typescript-eslint/eslint-plugin": "^1.1.0", + "@typescript-eslint/parser": "^1.1.0" + } + }, "@webassemblyjs/ast": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.3.tgz", - "integrity": "sha512-xy3m06+Iu4D32+6soz6zLnwznigXJRuFNTovBX2M4GqVqLb0dnyWLbPnpcXvUSdEN+9DVyDeaq2jyH1eIL2LZQ==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", "dev": true, "requires": { - "@webassemblyjs/helper-module-context": "1.8.3", - "@webassemblyjs/helper-wasm-bytecode": "1.8.3", - "@webassemblyjs/wast-parser": "1.8.3" + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.3.tgz", - "integrity": "sha512-vq1TISG4sts4f0lDwMUM0f3kpe0on+G3YyV5P0IySHFeaLKRYZ++n2fCFfG4TcCMYkqFeTUYFxm75L3ddlk2xA==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", "dev": true }, "@webassemblyjs/helper-api-error": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.3.tgz", - "integrity": "sha512-BmWEynI4FnZbjk8CaYZXwcv9a6gIiu+rllRRouQUo73hglanXD3AGFJE7Q4JZCoVE0p5/jeX6kf5eKa3D4JxwQ==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", "dev": true }, "@webassemblyjs/helper-buffer": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.3.tgz", - "integrity": "sha512-iVIMhWnNHoFB94+/2l7LpswfCsXeMRnWfExKtqsZ/E2NxZyUx9nTeKK/MEMKTQNEpyfznIUX06OchBHQ+VKi/Q==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", "dev": true }, "@webassemblyjs/helper-code-frame": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.3.tgz", - "integrity": "sha512-K1UxoJML7GKr1QXR+BG7eXqQkvu+eEeTjlSl5wUFQ6W6vaOc5OwSxTcb3oE9x/3+w4NHhrIKD4JXXCZmLdL2cg==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", "dev": true, "requires": { - "@webassemblyjs/wast-printer": "1.8.3" + "@webassemblyjs/wast-printer": "1.8.5" } }, "@webassemblyjs/helper-fsm": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.3.tgz", - "integrity": "sha512-387zipfrGyO77/qm7/SDUiZBjQ5KGk4qkrVIyuoubmRNIiqn3g+6ijY8BhnlGqsCCQX5bYKOnttJobT5xoyviA==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", "dev": true }, "@webassemblyjs/helper-module-context": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.3.tgz", - "integrity": "sha512-lPLFdQfaRssfnGEJit5Sk785kbBPPPK4ZS6rR5W/8hlUO/5v3F+rN8XuUcMj/Ny9iZiyKhhuinWGTUuYL4VKeQ==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.3", + "@webassemblyjs/ast": "1.8.5", "mamacro": "^0.0.3" } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.3.tgz", - "integrity": "sha512-R1nJW7bjyJLjsJQR5t3K/9LJ0QWuZezl8fGa49DZq4IVaejgvkbNlKEQxLYTC579zgT4IIIVHb5JA59uBPHXyw==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", "dev": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.3.tgz", - "integrity": "sha512-P6F7D61SJY73Yz+fs49Q3+OzlYAZP86OfSpaSY448KzUy65NdfzDmo2NPVte+Rw4562MxEAacvq/mnDuvRWOcg==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.3", - "@webassemblyjs/helper-buffer": "1.8.3", - "@webassemblyjs/helper-wasm-bytecode": "1.8.3", - "@webassemblyjs/wasm-gen": "1.8.3" + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" } }, "@webassemblyjs/ieee754": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.3.tgz", - "integrity": "sha512-UD4HuLU99hjIvWz1pD68b52qsepWQlYCxDYVFJQfHh3BHyeAyAlBJ+QzLR1nnS5J6hAzjki3I3AoJeobNNSZlg==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.3.tgz", - "integrity": "sha512-XXd3s1BmkC1gpGABuCRLqCGOD6D2L+Ma2BpwpjrQEHeQATKWAQtxAyU9Z14/z8Ryx6IG+L4/NDkIGHrccEhRUg==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", "dev": true, "requires": { "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.3.tgz", - "integrity": "sha512-Wv/WH9Zo5h5ZMyfCNpUrjFsLZ3X1amdfEuwdb7MLdG3cPAjRS6yc6ElULlpjLiiBTuzvmLhr3ENsuGyJ3wyCgg==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", "dev": true }, "@webassemblyjs/wasm-edit": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.3.tgz", - "integrity": "sha512-nB19eUx3Yhi1Vvv3yev5r+bqQixZprMtaoCs1brg9Efyl8Hto3tGaUoZ0Yb4Umn/gQCyoEGFfUxPLp1/8+Jvnw==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.3", - "@webassemblyjs/helper-buffer": "1.8.3", - "@webassemblyjs/helper-wasm-bytecode": "1.8.3", - "@webassemblyjs/helper-wasm-section": "1.8.3", - "@webassemblyjs/wasm-gen": "1.8.3", - "@webassemblyjs/wasm-opt": "1.8.3", - "@webassemblyjs/wasm-parser": "1.8.3", - "@webassemblyjs/wast-printer": "1.8.3" + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" } }, "@webassemblyjs/wasm-gen": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.3.tgz", - "integrity": "sha512-sDNmu2nLBJZ/huSzlJvd9IK8B1EjCsOl7VeMV9VJPmxKYgTJ47lbkSP+KAXMgZWGcArxmcrznqm7FrAPQ7vVGg==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.3", - "@webassemblyjs/helper-wasm-bytecode": "1.8.3", - "@webassemblyjs/ieee754": "1.8.3", - "@webassemblyjs/leb128": "1.8.3", - "@webassemblyjs/utf8": "1.8.3" + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" } }, "@webassemblyjs/wasm-opt": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.3.tgz", - "integrity": "sha512-j8lmQVFR+FR4/645VNgV4R/Jz8i50eaPAj93GZyd3EIJondVshE/D9pivpSDIXyaZt+IkCodlzOoZUE4LnQbeA==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.3", - "@webassemblyjs/helper-buffer": "1.8.3", - "@webassemblyjs/wasm-gen": "1.8.3", - "@webassemblyjs/wasm-parser": "1.8.3" + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" } }, "@webassemblyjs/wasm-parser": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.3.tgz", - "integrity": "sha512-NBI3SNNtRoy4T/KBsRZCAWUzE9lI94RH2nneLwa1KKIrt/2zzcTavWg6oY05ArCbb/PZDk3OUi63CD1RYtN65w==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.3", - "@webassemblyjs/helper-api-error": "1.8.3", - "@webassemblyjs/helper-wasm-bytecode": "1.8.3", - "@webassemblyjs/ieee754": "1.8.3", - "@webassemblyjs/leb128": "1.8.3", - "@webassemblyjs/utf8": "1.8.3" + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" } }, "@webassemblyjs/wast-parser": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.3.tgz", - "integrity": "sha512-gZPst4CNcmGtKC1eYQmgCx6gwQvxk4h/nPjfPBbRoD+Raw3Hs+BS3yhrfgyRKtlYP+BJ8LcY9iFODEQofl2qbg==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.3", - "@webassemblyjs/floating-point-hex-parser": "1.8.3", - "@webassemblyjs/helper-api-error": "1.8.3", - "@webassemblyjs/helper-code-frame": "1.8.3", - "@webassemblyjs/helper-fsm": "1.8.3", + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", "@xtuc/long": "4.2.2" } }, "@webassemblyjs/wast-printer": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.3.tgz", - "integrity": "sha512-DTA6kpXuHK4PHu16yAD9QVuT1WZQRT7079oIFFmFSjqjLWGXS909I/7kiLTn931mcj7wGsaUNungjwNQ2lGQ3Q==", + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.3", - "@webassemblyjs/wast-parser": "1.8.3", + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", "@xtuc/long": "4.2.2" } }, @@ -4178,13 +4145,13 @@ "dev": true }, "algoliasearch": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-3.32.0.tgz", - "integrity": "sha512-C8oQnPTf0wPuyD2jSZwtBAPvz+lHOE7zRIPpgXGBuNt6ZNcC4omsbytG26318rT77a8h4759vmIp6n9p8iw4NA==", + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-3.32.1.tgz", + "integrity": "sha512-NaaHMboU9tKwrU3aim7LlzSDqKb+1TGaC+Lx3NOttSnuMHbPpaf+7LtJL4KlosbRWEwqb9t5wSYMVDrPTH2dNA==", "dev": true, "requires": { "agentkeepalive": "^2.2.0", - "debug": "^2.6.8", + "debug": "^2.6.9", "envify": "^4.0.0", "es6-promise": "^4.1.0", "events": "^1.1.0", @@ -4283,9 +4250,9 @@ } }, "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", "dev": true }, "ansi-escapes": { @@ -4324,9 +4291,9 @@ } }, "app-root-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.1.0.tgz", - "integrity": "sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.2.0.tgz", + "integrity": "sha512-qbXcJgmuLGNwO7FH2WrtoJpA0mpcm0ZFQZPm6RV7ZLfA0QR3bQFpoij33x74+u3Zn58JDy5Jc/Z/LXKxTvh1Rw==", "dev": true }, "append-transform": { @@ -4350,6 +4317,12 @@ "integrity": "sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg==", "dev": true }, + "arg": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", + "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==", + "dev": true + }, "argparse": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", @@ -4482,6 +4455,12 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -4691,9 +4670,9 @@ } }, "babel-generator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", - "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "dev": true, "requires": { "babel-messages": "^6.23.0", @@ -4702,8 +4681,16 @@ "detect-indent": "^4.0.0", "jsesc": "^1.3.0", "lodash": "^4.17.4", - "source-map": "^0.5.6", + "source-map": "^0.5.7", "trim-right": "^1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, "babel-helper-bindify-decorators": { @@ -5851,27 +5838,6 @@ "requires": { "locate-path": "^2.0.0" } - }, - "istanbul-lib-coverage": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", - "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", - "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true, - "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.1", - "semver": "^5.3.0" - } } } }, @@ -6088,9 +6054,9 @@ } }, "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", - "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", "dev": true, "requires": { "babel-plugin-transform-strict-mode": "^6.24.1", @@ -7027,6 +6993,14 @@ "dev": true, "requires": { "callsites": "^0.2.0" + }, + "dependencies": { + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + } } }, "callsite": { @@ -7036,9 +7010,9 @@ "dev": true }, "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", + "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==", "dev": true }, "camel-case": { @@ -7260,15 +7234,15 @@ } }, "caniuse-db": { - "version": "1.0.30000938", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000938.tgz", - "integrity": "sha512-1lbcoAGPQFUYOdY7sxpsl8ZDBfn5cyn80XuYnZwk7N4Qp7Behw7uxZCH5jjH2qWTV2WM6hgjvDVpP/uV3M/l9g==", + "version": "1.0.30000951", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000951.tgz", + "integrity": "sha512-Nb8bgexT3HDxPMFOLcT5kol/dHsXpPiiFLU079+msbSBTsq9zZaCpzqDb122+9B9woZnTG5Z8lt+3adIaxKj2A==", "dev": true }, "caniuse-lite": { - "version": "1.0.30000938", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000938.tgz", - "integrity": "sha512-ekW8NQ3/FvokviDxhdKLZZAx7PptXNwxKgXtnR5y+PR3hckwuP3yJ1Ir+4/c97dsHNqtAyfKUGdw8P4EYzBNgw==", + "version": "1.0.30000951", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000951.tgz", + "integrity": "sha512-eRhP+nQ6YUkIcNQ6hnvdhMkdc7n3zadog0KXNRxAZTT2kHjUb1yGn71OrPhSn8MOvlX97g5CR97kGVj8fMsXWg==", "dev": true }, "capture-stack-trace": { @@ -7331,9 +7305,9 @@ } }, "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 }, "check-error": { @@ -7778,12 +7752,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -8679,9 +8647,9 @@ "dev": true }, "domhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", - "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", "dev": true, "requires": { "domelementtype": "1" @@ -8750,9 +8718,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.113", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz", - "integrity": "sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g==", + "version": "1.3.119", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.119.tgz", + "integrity": "sha512-3mtqcAWa4HgG+Djh/oNXlPH0cOH6MmtwxN1nHSaReb9P0Vn51qYPqYwLeoSuAX9loU1wrOBhFbiX3CkeIxPfgg==", "dev": true }, "elliptic": { @@ -8770,6 +8738,12 @@ "minimalistic-crypto-utils": "^1.0.0" } }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", @@ -8805,18 +8779,6 @@ "ws": "~6.1.0" }, "dependencies": { - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", - "dev": true - }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", - "dev": true - }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -8825,19 +8787,6 @@ "requires": { "ms": "2.0.0" } - }, - "engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } } } }, @@ -8961,14 +8910,14 @@ } }, "es5-ext": { - "version": "0.10.47", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.47.tgz", - "integrity": "sha512-/1TItLfj+TTfWoeRcDn/0FbGV6SNo4R+On2GGVucPU/j3BWnXE2Co8h8CTo4Tu34gFJtnmwS9xiScKs4EjZhdw==", + "version": "0.10.49", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.49.tgz", + "integrity": "sha512-3NMEhi57E31qdzmYp2jwRArIUsj1HI/RxbQ4bgnSB+AIKIxsAmTiK83bYMifIcpWvEc3P1X30DhUKOqEtF/kvg==", "dev": true, "requires": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.1", - "next-tick": "1" + "next-tick": "^1.0.0" } }, "es6-iterator": { @@ -8989,9 +8938,9 @@ "dev": true }, "es6-promise": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", - "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", + "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==", "dev": true }, "es6-promisify": { @@ -9063,51 +9012,61 @@ } }, "eslint": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.4.0.tgz", - "integrity": "sha512-UIpL91XGex3qtL6qwyCQJar2j3osKxK9e3ano3OcGEIRM4oWIpCkDg9x95AXEC2wMs7PnxzOkPZ2gq+tsMS9yg==", + "version": "5.15.3", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.15.3.tgz", + "integrity": "sha512-vMGi0PjCHSokZxE0NLp2VneGw5sio7SSiDNgIUn2tC0XkWJRNOIoHIg3CliLVfXnJsiHxGAYrkw0PieAu8+KYQ==", "dev": true, "requires": { - "ajv": "^6.5.0", - "babel-code-frame": "^6.26.0", + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", "chalk": "^2.1.0", "cross-spawn": "^6.0.5", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^4.0.0", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", "eslint-utils": "^1.3.1", "eslint-visitor-keys": "^1.0.0", - "espree": "^4.0.0", + "espree": "^5.0.1", "esquery": "^1.0.1", "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", + "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob": "^7.1.2", "globals": "^11.7.0", - "ignore": "^4.0.2", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^5.2.0", - "is-resolvable": "^1.1.0", - "js-yaml": "^3.11.0", + "inquirer": "^6.2.2", + "js-yaml": "^3.12.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", - "lodash": "^4.17.5", + "lodash": "^4.17.11", "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": "^2.0.0", - "require-uncached": "^1.0.3", - "semver": "^5.5.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", "strip-ansi": "^4.0.0", "strip-json-comments": "^2.0.1", - "table": "^4.0.3", + "table": "^5.2.3", "text-table": "^0.2.0" }, "dependencies": { + "ajv": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", + "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" + } + }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", @@ -9134,19 +9093,19 @@ "supports-color": "^5.3.0" } }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { - "ms": "^2.1.1" + "esutils": "^2.0.2" } }, "eslint-scope": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "dev": true, "requires": { "esrecurse": "^4.1.0", @@ -9154,9 +9113,9 @@ } }, "globals": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.10.0.tgz", - "integrity": "sha512-0GZF1RiPKU97IHUO5TORo9w1PwrH/NBPl+fS7oMLdaTRiYmYbwK4NWoZWrAdd0/abG9R2BU+OiwyQpTpE6pdfQ==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", "dev": true }, "has-flag": { @@ -9165,26 +9124,20 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "js-yaml": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", - "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "import-fresh": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", + "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" } }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, "semver": { @@ -9193,6 +9146,45 @@ "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -9210,9 +9202,30 @@ "requires": { "has-flag": "^3.0.0" } + }, + "table": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", + "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", + "dev": true, + "requires": { + "ajv": "^6.9.1", + "lodash": "^4.17.11", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } } } }, + "eslint-config-prettier": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-4.1.0.tgz", + "integrity": "sha512-zILwX9/Ocz4SV2vX7ox85AsrAgXV3f2o2gpIicdMIOra48WYqgUnWNH/cR/iHtmD2Vb3dLSC3LiEJnS05Gkw7w==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } + }, "eslint-config-standard": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz", @@ -9422,6 +9435,15 @@ } } }, + "eslint-plugin-prettier": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.1.tgz", + "integrity": "sha512-/PMttrarPAY78PLvV3xfWibMOdMDl57hmlQ2XqFeA37wd+CJ7WSxV7txqjVPHi/AAFKd2lX0ZqfsOc/i5yFCSQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, "eslint-plugin-promise": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz", @@ -9447,6 +9469,15 @@ "integrity": "sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA==", "dev": true }, + "eslint-plugin-vue": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-5.2.2.tgz", + "integrity": "sha512-CtGWH7IB0DA6BZOwcV9w9q3Ri6Yuo8qMjx05SmOGJ6X6E0Yo3y9E/gQ5tuNxg2dEt30tRnBoFTbvtmW9iEoyHA==", + "dev": true, + "requires": { + "vue-eslint-parser": "^5.0.0" + } + }, "eslint-scope": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", @@ -9470,14 +9501,22 @@ "dev": true }, "espree": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", - "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", "dev": true, "requires": { - "acorn": "^6.0.2", + "acorn": "^6.0.7", "acorn-jsx": "^5.0.0", "eslint-visitor-keys": "^1.0.0" + }, + "dependencies": { + "acorn": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", + "dev": true + } } }, "esprima": { @@ -9680,14 +9719,25 @@ } }, "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" + }, + "dependencies": { + "iconv-lite": { + "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" + } + } } }, "extglob": { @@ -9716,6 +9766,12 @@ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "fast-glob": { "version": "2.2.6", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.6.tgz", @@ -10263,13 +10319,12 @@ } }, "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", "dev": true, "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "flat-cache": "^2.0.1" } }, "file-loader": { @@ -10299,14 +10354,14 @@ } }, "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "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": "^1.1.3", + "randomatic": "^3.0.0", "repeat-element": "^1.1.2", "repeat-string": "^1.5.2" } @@ -10391,15 +10446,14 @@ } }, "flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", "dev": true, "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" }, "dependencies": { "glob": { @@ -10427,6 +10481,12 @@ } } }, + "flatted": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "dev": true + }, "flatten": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", @@ -10476,22 +10536,28 @@ } }, "follow-redirects": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.2.4.tgz", - "integrity": "sha512-Suw6KewLV2hReSyEOeql+UUkBVyiBm3ok1VPrVFRZnQInWpdoZbbiG5i8aJVSjTr0yQ4Ava0Sh6/joCg1Brdqw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", + "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", "dev": true, "requires": { - "debug": "^2.4.5" + "debug": "^3.2.6" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "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 } } }, @@ -11757,16 +11823,6 @@ "strip-bom-string": "^1.0.0" }, "dependencies": { - "js-yaml": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", - "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", @@ -12065,61 +12121,58 @@ "dev": true }, "uglify-js": { - "version": "3.4.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", + "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", "dev": true, "requires": { - "commander": "~2.17.1", + "commander": "~2.19.0", "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + } } } } }, "htmlparser2": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", - "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", "dev": true, "requires": { - "domelementtype": "1", - "domhandler": "2.1", - "domutils": "1.1", - "readable-stream": "1.0" + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" }, "dependencies": { - "domutils": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", - "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", + "readable-stream": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", + "integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", "dev": true, "requires": { - "domelementtype": "1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, - "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.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "string_decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", + "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "safe-buffer": "~5.1.0" } - }, - "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 } } }, @@ -12426,26 +12479,32 @@ "dev": true }, "inquirer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", - "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz", + "integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", - "external-editor": "^2.1.0", + "external-editor": "^3.0.3", "figures": "^2.0.0", - "lodash": "^4.3.0", + "lodash": "^4.17.11", "mute-stream": "0.0.7", "run-async": "^2.2.0", - "rxjs": "^5.5.2", + "rxjs": "^6.4.0", "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", + "strip-ansi": "^5.0.0", "through": "^2.3.6" }, "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", @@ -12492,15 +12551,34 @@ "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } } }, "supports-color": { @@ -12916,119 +12994,129 @@ } }, "istanbul-api": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.1.11.tgz", - "integrity": "sha1-/MC0YeKzvaceMFFVE4I4doJX2d4=", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", + "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", "dev": true, "requires": { "async": "^2.1.4", "fileset": "^2.0.2", - "istanbul-lib-coverage": "^1.1.1", - "istanbul-lib-hook": "^1.0.7", - "istanbul-lib-instrument": "^1.7.4", - "istanbul-lib-report": "^1.1.1", - "istanbul-lib-source-maps": "^1.2.1", - "istanbul-reports": "^1.1.1", + "istanbul-lib-coverage": "^1.2.1", + "istanbul-lib-hook": "^1.2.2", + "istanbul-lib-instrument": "^1.10.2", + "istanbul-lib-report": "^1.1.5", + "istanbul-lib-source-maps": "^1.2.6", + "istanbul-reports": "^1.5.1", "js-yaml": "^3.7.0", "mkdirp": "^0.5.1", "once": "^1.4.0" }, "dependencies": { "async": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", - "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.14.0" + "lodash": "^4.17.11" } - } - } - }, - "istanbul-lib-coverage": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz", - "integrity": "sha512-0+1vDkmzxqJIn5rcoEqapSB4DmPxE31EtI2dF2aCkV5esN9EWHxZ0dwgDClivMXJqE7zaYQxq30hj5L0nlTN5Q==", - "dev": true - }, - "istanbul-lib-hook": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz", - "integrity": "sha512-3U2HB9y1ZV9UmFlE12Fx+nPtFqIymzrqCksrXujm3NVbAZIJg/RfYgO1XiIa0mbmxTjWpVEVlkIZJ25xVIAfkQ==", - "dev": true, - "requires": { - "append-transform": "^0.4.0" - } - }, - "istanbul-lib-instrument": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.4.tgz", - "integrity": "sha1-6f2SDkdn89Ge3HZeLWs/XMvQ7qg=", - "dev": true, - "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.17.4", - "istanbul-lib-coverage": "^1.1.1", - "semver": "^5.3.0" - } - }, - "istanbul-lib-report": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", - "integrity": "sha512-tvF+YmCmH4thnez6JFX06ujIA19WPa9YUiwjc1uALF2cv5dmE3It8b5I8Ob7FHJ70H9Y5yF+TDkVa/mcADuw1Q==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^1.1.1", - "mkdirp": "^0.5.1", - "path-parse": "^1.0.5", - "supports-color": "^3.1.2" - }, - "dependencies": { - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "ms": "^2.1.1" } - } - } - }, - "istanbul-lib-source-maps": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz", - "integrity": "sha512-mukVvSXCn9JQvdJl8wP/iPhqig0MRtuWuD4ZNKo6vB2Ik//AmhAKe3QnPN02dmkRe3lTudFk3rzoHhwU4hb94w==", - "dev": true, - "requires": { - "debug": "^2.6.3", - "istanbul-lib-coverage": "^1.1.1", - "mkdirp": "^0.5.1", - "rimraf": "^2.6.1", - "source-map": "^0.5.3" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + }, + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", + "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", "dev": true, "requires": { - "ms": "2.0.0" + "append-transform": "^0.4.0" + } + }, + "istanbul-lib-report": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", + "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "path-parse": "^1.0.5", + "supports-color": "^3.1.2" + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", + "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" + } + }, + "istanbul-reports": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", + "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", + "dev": true, + "requires": { + "handlebars": "^4.0.3" + } + }, + "ms": { + "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 + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" } } } }, - "istanbul-reports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.1.tgz", - "integrity": "sha512-P8G873A0kW24XRlxHVGhMJBhQ8gWAec+dae7ZxOBzxT4w+a9ATSPvRVK3LB1RAJ9S8bg2tOyWHAGW40Zd2dKfw==", + "istanbul-lib-instrument": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", "dev": true, "requires": { - "handlebars": "^4.0.3" + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + }, + "dependencies": { + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + } } }, "javascript-stringify": { @@ -13061,9 +13149,9 @@ "dev": true }, "js-yaml": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz", - "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz", + "integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -13407,14 +13495,6 @@ "requires": { "lodash": "^4.17.5", "webpack-sources": "^1.1.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - } } }, "latest-version": { @@ -13441,12 +13521,12 @@ }, "dependencies": { "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "debug": { @@ -13457,12 +13537,6 @@ "requires": { "ms": "2.0.0" } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true } } }, @@ -13609,26 +13683,6 @@ "ms": "2.0.0" } }, - "follow-redirects": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", - "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", - "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" - } - } - } - }, "yargs": { "version": "6.6.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", @@ -13671,9 +13725,9 @@ } }, "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "lodash._reinterpolate": { @@ -13805,6 +13859,12 @@ "resolved": "https://registry.npmjs.org/lodash.trim/-/lodash.trim-4.5.1.tgz", "integrity": "sha1-NkJefukL5KpeJ7zruFt9EepHqlc=" }, + "lodash.unescape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", + "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", + "dev": true + }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -13985,6 +14045,12 @@ } } }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, "mamacro": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", @@ -14091,6 +14157,12 @@ "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", "dev": true }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -14321,18 +14393,18 @@ "dev": true }, "mime-db": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==", "dev": true }, "mime-types": { - "version": "2.1.21", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", "dev": true, "requires": { - "mime-db": "~1.37.0" + "mime-db": "~1.38.0" } }, "mimic-fn": { @@ -14865,8 +14937,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-component": { "version": "0.0.3", @@ -15008,9 +15079,9 @@ "dev": true }, "opn": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", - "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", "dev": true, "requires": { "is-wsl": "^1.1.0" @@ -15124,9 +15195,9 @@ } }, "p-try": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", + "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", "dev": true }, "package-json": { @@ -15142,9 +15213,9 @@ } }, "pako": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.8.tgz", - "integrity": "sha512-6i0HVbUfcKaTv+EG8ZTr75az7GFXcLYk9UyLEg7Notv/Ma+z/UG3TCoz6GiNeOrn1E/e63I0X/Hpw18jHOTUnA==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", + "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, "parallel-transform": { @@ -15167,6 +15238,15 @@ "no-case": "^2.2.0" } }, + "parent-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.0.tgz", + "integrity": "sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "parse-asn1": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", @@ -16495,11 +16575,20 @@ "dev": true }, "prettier": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.3.tgz", - "integrity": "sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw==", + "version": "1.16.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz", + "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==", "dev": true }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "pretty-bytes": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", @@ -16733,43 +16822,27 @@ "dev": true }, "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", "dev": true, "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.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" - }, - "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" - } - } - } + "version": "4.0.0", + "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": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, @@ -16904,12 +16977,20 @@ } }, "reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/reduce/-/reduce-1.0.1.tgz", - "integrity": "sha1-FPouX/H8VgcDoCDLtfuqtpFWWAQ=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/reduce/-/reduce-1.0.2.tgz", + "integrity": "sha512-xX7Fxke/oHO5IfZSk77lvPa/7bjMh9BuCk4OOoX5XTXrM7s0Z+MkPfSDfz0q7r91BhhGSs8gii/VEN/7zhCPpQ==", "dev": true, "requires": { - "object-keys": "~1.0.0" + "object-keys": "^1.1.0" + }, + "dependencies": { + "object-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", + "dev": true + } } }, "reduce-css-calc": { @@ -16955,9 +17036,9 @@ "dev": true }, "regenerate-unicode-properties": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz", - "integrity": "sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.2.tgz", + "integrity": "sha512-SbA/iNrBUf6Pv2zU8Ekv1Qbhv92yxL4hiDa2siuxs4KKn4oOoMDHXjAf7+Nz9qinUQ46B1LcWEi/PhJfPWpZWQ==", "dev": true, "requires": { "regenerate": "^1.4.0" @@ -17032,9 +17113,9 @@ "dev": true }, "registry-auth-token": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", - "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", + "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", "dev": true, "requires": { "rc": "^1.1.6", @@ -17092,14 +17173,14 @@ "dev": true }, "renderkid": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.2.tgz", - "integrity": "sha512-FsygIxevi1jSiPY9h7vZmBFUbAOcbYm9UwyiLNdVsLRs/5We9Ob5NMPbGYUTWiLq5L+ezlVdE0A8bbME5CWTpg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.3.tgz", + "integrity": "sha512-z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA==", "dev": true, "requires": { "css-select": "^1.1.0", - "dom-converter": "~0.2", - "htmlparser2": "~3.3.0", + "dom-converter": "^0.2", + "htmlparser2": "^3.3.0", "strip-ansi": "^3.0.0", "utila": "^0.4.0" } @@ -17187,8 +17268,22 @@ "requires": { "caller-path": "^0.1.0", "resolve-from": "^1.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + } } }, + "requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true + }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -17222,9 +17317,9 @@ } }, "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "resolve-path": { @@ -17319,12 +17414,12 @@ } }, "rxjs": { - "version": "5.5.12", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", - "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", "dev": true, "requires": { - "symbol-observable": "1.0.1" + "tslib": "^1.9.0" } }, "safe-buffer": { @@ -17794,169 +17889,6 @@ "socket.io-adapter": "~1.1.0", "socket.io-client": "2.2.0", "socket.io-parser": "~3.3.0" - }, - "dependencies": { - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", - "dev": true - }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", - "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 - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "engine.io-client": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.1.tgz", - "integrity": "sha512-q66JBFuQcy7CSlfAz9L3jH+v7DTT3i6ZEadYcVj2pOs8/0uJHLxKX3WBkGTvULJMdz0tUCyJag0aKT/dpXL9BQ==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - }, - "ms": { - "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 - }, - "socket.io-client": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz", - "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.3.1", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - }, - "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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "socket.io-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", - "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "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" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", - "dev": true - } } }, "socket.io-adapter": { @@ -18169,6 +18101,271 @@ "eslint-plugin-react": "~7.11.1", "eslint-plugin-standard": "~4.0.0", "standard-engine": "~9.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 + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "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" + } + }, + "eslint": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.4.0.tgz", + "integrity": "sha512-UIpL91XGex3qtL6qwyCQJar2j3osKxK9e3ano3OcGEIRM4oWIpCkDg9x95AXEC2wMs7PnxzOkPZ2gq+tsMS9yg==", + "dev": true, + "requires": { + "ajv": "^6.5.0", + "babel-code-frame": "^6.26.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^4.0.0", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^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.7.0", + "ignore": "^4.0.2", + "imurmurhash": "^0.1.4", + "inquirer": "^5.2.0", + "is-resolvable": "^1.1.0", + "js-yaml": "^3.11.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "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": "^2.0.0", + "require-uncached": "^1.0.3", + "semver": "^5.5.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^4.0.3", + "text-table": "^0.2.0" + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", + "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", + "dev": true, + "requires": { + "acorn": "^6.0.2", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, + "globals": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "inquirer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "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.1.0", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^5.5.2", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "ms": { + "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 + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "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", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "rxjs": { + "version": "5.5.12", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", + "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", + "dev": true, + "requires": { + "symbol-observable": "1.0.1" + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + } } }, "standard-engine": { @@ -18228,9 +18425,9 @@ } }, "steal": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/steal/-/steal-2.1.13.tgz", - "integrity": "sha512-bOYp8E0BqaBnJMKSXGqxt/rIjoxvD5wBjRbpP6/gKGfPwNkRFyCFLdoLTmCAd0+kOmbY/+3QEAX3aMQL+wfZcA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/steal/-/steal-2.2.0.tgz", + "integrity": "sha512-aX2uTCktgSYP0ByPLCDZ9o27LzV+HUJ46930tGSBpEa6v7jKxuHM11OjivGqymBX2DlCFj34UqYAsXkWqZJzOg==", "dev": true, "requires": { "assert": "~1.4.1", @@ -18365,6 +18562,22 @@ } } }, + "steal-typescript": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/steal-typescript/-/steal-typescript-0.5.0.tgz", + "integrity": "sha1-XxINuwU2hiVF4hx5KqK3vJsWwNs=", + "requires": { + "object-assign": "^4.1.0", + "typescript": "^2.1.4" + }, + "dependencies": { + "typescript": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", + "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==" + } + } + }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -18611,12 +18824,6 @@ "readable-stream": "^2.3.5" }, "dependencies": { - "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 - }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -18846,20 +19053,20 @@ } }, "terser": { - "version": "3.16.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.16.1.tgz", - "integrity": "sha512-JDJjgleBROeek2iBcSNzOHLKsB/MdDf+E/BOAJ0Tk9r7p9/fVobfv7LMJ/g/k3v9SXdmjZnIlFd5nfn/Rt0Xow==", + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", + "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", "dev": true, "requires": { - "commander": "~2.17.1", + "commander": "^2.19.0", "source-map": "~0.6.1", - "source-map-support": "~0.5.9" + "source-map-support": "~0.5.10" }, "dependencies": { "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", "dev": true }, "source-map": { @@ -18869,9 +19076,9 @@ "dev": true }, "source-map-support": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", - "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.11.tgz", + "integrity": "sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -18881,9 +19088,9 @@ } }, "terser-webpack-plugin": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.2.tgz", - "integrity": "sha512-1DMkTk286BzmfylAvLXwpJrI7dWa5BnFmscV/2dCr8+c56egFcbaeFAl7+sujAjdmpLam21XRdhA4oifLyiWWg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz", + "integrity": "sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA==", "dev": true, "requires": { "cacache": "^11.0.2", @@ -18919,13 +19126,13 @@ } }, "find-cache-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", - "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "dev": true, "requires": { "commondir": "^1.0.1", - "make-dir": "^1.0.0", + "make-dir": "^2.0.0", "pkg-dir": "^3.0.0" } }, @@ -18977,6 +19184,16 @@ "yallist": "^3.0.2" } }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, "mississippi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", @@ -18996,9 +19213,9 @@ } }, "p-limit": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", - "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -19019,6 +19236,12 @@ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", @@ -19058,6 +19281,12 @@ "ajv-keywords": "^3.1.0" } }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -19101,9 +19330,9 @@ } }, "testee": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/testee/-/testee-0.8.1.tgz", - "integrity": "sha512-lJ2HHDgPiU06NTYfMr5to7GZwO74plk5PugkfvY8W+pJzbkSCrhO2ruAzBTBX8kzPXO+EPpKv1Jx1lFVJ6aztQ==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/testee/-/testee-0.9.0.tgz", + "integrity": "sha512-vyP8iPx7aJNewQfpyKasgmzcTqNR52WwdWkQQ+CMhlkqA9rqvxy551yks4mAEdYcmHfYW663kLjB5UkFiK++0g==", "dev": true, "requires": { "babel-core": "^6.24.0", @@ -19135,14 +19364,6 @@ "dev": true, "requires": { "ms": "^2.1.1" - }, - "dependencies": { - "ms": { - "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 - } } }, "diff": { @@ -19212,12 +19433,6 @@ "wordwrap": "^1.0.0" } }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "mocha": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", @@ -19265,6 +19480,12 @@ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -19276,6 +19497,12 @@ } } }, + "ms": { + "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 + }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", @@ -19547,12 +19774,52 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, + "ts-node": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.0.3.tgz", + "integrity": "sha512-2qayBA4vdtVRuDo11DEFSsD/SFsBXQBRZZhbRGSIkmYmVkWjULn/GGMdG10KVqkaGndljfaTD8dKjWgcejO8YA==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "source-map-support": "^0.5.6", + "yn": "^3.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.11.tgz", + "integrity": "sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", "dev": true }, + "tsutils": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.9.1.tgz", + "integrity": "sha512-hrxVtLtPqQr//p8/msPT1X1UYXUjizqSit5d9AQ5k38TcV38NyecL5xODNxa73cLe/5sdiJ+w1FqzDhRBA/anA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "tty-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", @@ -19622,6 +19889,12 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typescript": { + "version": "3.3.4000", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.4000.tgz", + "integrity": "sha512-jjOcCZvpkl2+z7JFn0yBOoLQyLoIkNZAs/fYJkUG6VKy6zLPHJGfQJYFHzibB6GJaF/8QrcECtlQ5cpvRHSMEA==", + "dev": true + }, "uberproto": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/uberproto/-/uberproto-1.2.0.tgz", @@ -19676,15 +19949,15 @@ } }, "unicode-match-property-value-ecmascript": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz", - "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", + "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", "dev": true }, "unicode-property-aliases-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz", - "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", + "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", "dev": true }, "union-value": { @@ -19869,7 +20142,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", - "dev": true + "dev": true, + "optional": true }, "update-notifier": { "version": "2.5.0", @@ -20154,16 +20428,53 @@ "integrity": "sha512-pxY3ZHlXNJMFQbkjEgGVMaMMkSV1ONpz+4qB55kZuJzyJOhn6MSy/YZdzhdnumegNzVTL/Dn3Pp4UrVBYt1j/g==", "dev": true }, + "vue-eslint-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-5.0.0.tgz", + "integrity": "sha512-JlHVZwBBTNVvzmifwjpZYn0oPWH2SgWv5dojlZBsrhablDu95VFD+hriB1rQGwbD+bms6g+rAFhQHk6+NyiS6g==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "eslint-scope": "^4.0.0", + "eslint-visitor-keys": "^1.0.0", + "espree": "^4.1.0", + "esquery": "^1.0.1", + "lodash": "^4.17.11" + }, + "dependencies": { + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", + "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", + "dev": true, + "requires": { + "acorn": "^6.0.2", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + } + } + }, "vue-hot-reload-api": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.2.tgz", - "integrity": "sha512-NpznMQoe/DzMG7nJjPkJKT7FdEn9xXfnntG7POfTmqnSaza97ylaBf1luZDh4IgV+vgUoR//id5pf8Ru+Ym+0g==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.3.tgz", + "integrity": "sha512-KmvZVtmM26BQOMK1rwUZsrqxEGeKiYSZGA7SNWE6uExx8UX/cj9hq2MRV/wWC3Cq6AoeDGk57rL9YMFRel/q+g==", "dev": true }, "vue-loader": { - "version": "15.6.3", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.6.3.tgz", - "integrity": "sha512-4rgz4hk5pEzz/BNiXPG9UpgFqFPHldO6l9X7/HB2NxOYTbn/dmQDw/UjW+/rnBoRCGqyTazGNNqXVp5Htb0Mfg==", + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.7.0.tgz", + "integrity": "sha512-x+NZ4RIthQOxcFclEcs8sXGEWqnZHodL2J9Vq+hUz+TDZzBaDIh1j3d9M2IUlTjtrHTZy4uMuRdTi8BGws7jLA==", "dev": true, "requires": { "@vue/component-compiler-utils": "^2.5.1", @@ -20180,9 +20491,9 @@ "dev": true }, "vue-server-renderer": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/vue-server-renderer/-/vue-server-renderer-2.6.6.tgz", - "integrity": "sha512-dJ4IrIilS3nhxpOrR12+IKGu9Meg8L0t/W/e/UNSXKyh9EkwDqFPK0nZTfGPudXzr9FMQfg2hK6p2RMydPRU2Q==", + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/vue-server-renderer/-/vue-server-renderer-2.6.10.tgz", + "integrity": "sha512-UYoCEutBpKzL2fKCwx8zlRtRtwxbPZXKTqbl2iIF4yRZUNO/ovrHyDAJDljft0kd+K0tZhN53XRHkgvCZoIhug==", "dev": true, "requires": { "chalk": "^1.1.3", @@ -20206,9 +20517,9 @@ } }, "vue-template-compiler": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.6.tgz", - "integrity": "sha512-OakxDGyrmMQViCjkakQFbDZlG0NibiOzpLauOfyCUVRQc9yPmTqpiz9nF0VeA+dFkXegetw0E5x65BFhhLXO0A==", + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz", + "integrity": "sha512-jVZkw4/I/HT5ZMvRnhv78okGusqe0+qH2A0Em0Cp8aq78+NK9TII263CDVz2QXZsIT+yyV/gZc/j/vlwa+Epyg==", "dev": true, "requires": { "de-indent": "^1.0.2", @@ -20216,15 +20527,15 @@ } }, "vue-template-es2015-compiler": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.8.2.tgz", - "integrity": "sha512-cliV19VHLJqFUYbz/XeWXe5CO6guzwd0yrrqqp0bmjlMP3ZZULY7fu8RTC4+3lmHwo6ESVDHFDsvjB15hcR5IA==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", + "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "dev": true }, "vuepress": { - "version": "0.14.9", - "resolved": "https://registry.npmjs.org/vuepress/-/vuepress-0.14.9.tgz", - "integrity": "sha512-fsbAmo5TG39q2frEhNYFu7IwuFkYpuTe2BinwdU7BjXyjdApzkWza8n2SPMsBYakAgba5JIwNEZR8bkvnVUhXQ==", + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vuepress/-/vuepress-0.14.10.tgz", + "integrity": "sha512-upD0br3AUmZQ+kNJMg135jW36JjYAdShl6XYwDmVMw4XbtcLDSMGWTLqLCQN3PTIs/7TgiJ3cLWNL1ps63gyUQ==", "dev": true, "requires": { "@babel/core": "7.0.0-beta.47", @@ -20368,9 +20679,9 @@ } }, "chokidar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.2.tgz", - "integrity": "sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", + "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -20384,7 +20695,7 @@ "normalize-path": "^3.0.0", "path-is-absolute": "^1.0.0", "readdirp": "^2.2.1", - "upath": "^1.1.0" + "upath": "^1.1.1" } }, "commander": { @@ -21179,16 +21490,6 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "js-yaml": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", - "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", @@ -21217,9 +21518,9 @@ } }, "nan": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", - "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.1.tgz", + "integrity": "sha512-I6YB/YEuDeUZMmhscXKxGgZlFnhsn5y0hgOZBadkzfTRrZBtJDZeg6eQf7PYMIEclwmorTKK8GztsyOUSVBREA==", "dev": true, "optional": true }, @@ -21254,6 +21555,12 @@ "requires": { "has-flag": "^3.0.0" } + }, + "upath": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", + "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", + "dev": true } } }, @@ -21372,9 +21679,9 @@ } }, "chokidar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.2.tgz", - "integrity": "sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", + "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", "dev": true, "requires": { "anymatch": "^2.0.0", @@ -21388,7 +21695,7 @@ "normalize-path": "^3.0.0", "path-is-absolute": "^1.0.0", "readdirp": "^2.2.1", - "upath": "^1.1.0" + "upath": "^1.1.1" } }, "debug": { @@ -22199,9 +22506,9 @@ } }, "nan": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", - "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.1.tgz", + "integrity": "sha512-I6YB/YEuDeUZMmhscXKxGgZlFnhsn5y0hgOZBadkzfTRrZBtJDZeg6eQf7PYMIEclwmorTKK8GztsyOUSVBREA==", "dev": true, "optional": true }, @@ -22221,19 +22528,25 @@ "micromatch": "^3.1.10", "readable-stream": "^2.0.2" } + }, + "upath": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", + "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", + "dev": true } } }, "webpack": { - "version": "4.29.5", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.29.5.tgz", - "integrity": "sha512-DuWlYUT982c7XVHodrLO9quFbNpVq5FNxLrMUfYUTlgKW0+yPimynYf1kttSQpEneAL1FH3P3OLNgkyImx8qIQ==", + "version": "4.29.6", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.29.6.tgz", + "integrity": "sha512-MwBwpiE1BQpMDkbnUUaW6K8RFZjljJHArC6tWQJoFm0oQtfoSebtg4Y7/QHnJ/SddtjYLHaKGX64CFjG5rehJw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.8.3", - "@webassemblyjs/helper-module-context": "1.8.3", - "@webassemblyjs/wasm-edit": "1.8.3", - "@webassemblyjs/wasm-parser": "1.8.3", + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", "acorn": "^6.0.5", "acorn-dynamic-import": "^4.0.0", "ajv": "^6.1.0", @@ -22307,9 +22620,9 @@ } }, "eslint-scope": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "dev": true, "requires": { "esrecurse": "^4.1.0", @@ -22573,12 +22886,12 @@ } }, "webpack-dev-middleware": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.5.2.tgz", - "integrity": "sha512-nPmshdt1ckcwWjI0Ubrdp8KroeuprW6xFKYqk0u3MflNMBXvHPnMATsC7/L/enwav2zvLCfj/Usr47qnF3KQyA==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.6.1.tgz", + "integrity": "sha512-XQmemun8QJexMEvNFbD2BIg4eSKrmSIMrTfnl2nql2Sc6OGAYFyb8rwuYrCjl/IiEYYuyTEiimMscu7EXji/Dw==", "dev": true, "requires": { - "memory-fs": "~0.4.1", + "memory-fs": "^0.4.1", "mime": "^2.3.1", "range-parser": "^1.0.3", "webpack-log": "^2.0.0" @@ -22699,14 +23012,6 @@ "dev": true, "requires": { "lodash": "^4.17.5" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - } } }, "webpack-serve": { @@ -22798,12 +23103,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -22908,12 +23207,6 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -23201,9 +23494,9 @@ "dev": true }, "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", "dev": true, "requires": { "mkdirp": "^0.5.1" @@ -23313,6 +23606,12 @@ "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==", "dev": true }, + "yn": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.0.0.tgz", + "integrity": "sha512-+Wo/p5VRfxUgBUGy2j/6KX2mj9AYJWOHuhMjMcbBFc3y54o9/4buK1ksBvuiK01C3kby8DH9lSmJdSxw+4G/2Q==", + "dev": true + }, "zepto": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/zepto/-/zepto-1.2.0.tgz", diff --git a/package.json b/package.json index 714734dc..90e0a4ce 100644 --- a/package.json +++ b/package.json @@ -38,17 +38,47 @@ "lint": "standard --fix", "coverage": "istanbul cover node_modules/mocha/bin/_mocha -- --opts mocha.opts", "test": "npm run lint && npm run test-node && npm run testee", + "test-ts": "mocha --require ts-node/register src/**/*.test.ts", "test-node": "mocha --opts mocha.opts", "testee": "testee test/index.html --browsers firefox", "start": "npm run compile && node example/app", "docs:dev": "vuepress dev docs", "docs:build": "vuepress build docs" }, - "standard": { - "sourceType": "module", - "env": [ - "mocha" - ] + "prettier": { + "fix": true, + "singleQuote": true, + "semi": false, + "trailingComma": "none", + "tabWidth": 2 + }, + "eslintConfig": { + "root": true, + "env": { + "node": true, + "mocha": true + }, + "extends": [ + "plugin:@typescript-eslint/recommended", + "prettier/@typescript-eslint", + "plugin:prettier/recommended" + ], + "rules": { + "prettier/prettier": [ + "warn", + { + "fix": true, + "singleQuote": true, + "semi": false, + "trailingComma": "none" + } + ] + }, + "parserOptions": { + "parser": "@typescript-eslint/parser", + "ecmaVersion": 2018, + "sourceType": "module" + } }, "steal": { "map": { @@ -82,7 +112,8 @@ "lodash.omit": "^4.5.0", "lodash.trim": "^4.5.1", "serialize-error": "^3.0.0", - "sift": "^7.0.1" + "sift": "^7.0.1", + "steal-typescript": "^0.5.0" }, "devDependencies": { "@feathersjs/authentication-client": "^1.0.10", @@ -91,6 +122,12 @@ "@feathersjs/feathers": "^3.3.1", "@feathersjs/rest-client": "^1.4.7", "@feathersjs/socketio-client": "^1.2.1", + "@types/chai": "^4.1.7", + "@types/mocha": "^5.2.6", + "@typescript-eslint/eslint-plugin": "^1.5.0", + "@typescript-eslint/parser": "^1.5.0", + "@vue/eslint-config-prettier": "^4.0.1", + "@vue/eslint-config-typescript": "^4.0.0", "axios": "^0.18.0", "babel-cli": "^6.26.0", "babel-core": "^6.26.3", @@ -101,17 +138,24 @@ "body-parser": "^1.18.3", "can-fixture-socket": "^2.0.0", "chai": "^4.2.0", + "eslint": "^5.15.3", + "eslint-config-prettier": "^4.1.0", + "eslint-plugin-prettier": "^3.0.1", + "eslint-plugin-vue": "^5.2.2", "feathers-memory": "^3.0.1", "istanbul": "^1.1.0-alpha.1", "mocha": "^5.2.0", + "prettier": "^1.16.4", "shx": "^0.3.2", "socket.io-client": "^2.2.0", "standard": "^12.0.1", - "steal": "^2.1.13", + "steal": "^2.2.0", "steal-mocha": "^2.0.1", - "testee": "^0.8.1", + "testee": "^0.9.0", + "ts-node": "^8.0.3", + "typescript": "^3.3.4000", "vue": "^2.5.22", - "vuepress": "^0.14.9", + "vuepress": "^0.14.10", "vuex": "^3.0.1" } } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..03d0466c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "**/*.test.js" + ] +} \ No newline at end of file From d40cd987a6636de24e9bcf9519893cd5e47d4edc Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 23 Mar 2019 18:53:31 -0600 Subject: [PATCH 002/404] Beginning of new Model class --- src/service-module/model/model.js | 115 ++++++++++++++++ src/service-module/model/model.test.js | 17 +++ src/service-module/model/model.test.ts | 27 ++++ src/service-module/model/model.tests.html | 11 ++ src/service-module/model/model.ts | 156 ++++++++++++++++++++++ 5 files changed, 326 insertions(+) create mode 100644 src/service-module/model/model.js create mode 100644 src/service-module/model/model.test.js create mode 100644 src/service-module/model/model.test.ts create mode 100644 src/service-module/model/model.tests.html create mode 100644 src/service-module/model/model.ts diff --git a/src/service-module/model/model.js b/src/service-module/model/model.js new file mode 100644 index 00000000..59679971 --- /dev/null +++ b/src/service-module/model/model.js @@ -0,0 +1,115 @@ +"use strict"; +exports.__esModule = true; +var fast_copy_1 = require("fast-copy"); +var lodash_isplainobject_1 = require("lodash.isplainobject"); +var lodash_merge_1 = require("lodash.merge"); +function makeModel(options) { + if (options === void 0) { options = { idField: 'id', preferUpdate: false }; } + var _a; + var idField = options.idField, preferUpdate = options.preferUpdate; + return _a = /** @class */ (function () { + function FeathersVuexModel() { + } + FeathersVuexModel.getFromStore = function (id) { }; + FeathersVuexModel.getId = function (record) { + return record[FeathersVuexModel.idField]; + }; + FeathersVuexModel.prototype.clone = function () { + if (this.isClone) { + throw new Error('You cannot clone a copy'); + } + var id = this[FeathersVuexModel.idField]; + return this._clone(id); + }; + FeathersVuexModel.prototype._clone = function (id) { }; + FeathersVuexModel.prototype.reset = function () { + if (this.isClone) { + var id = this[FeathersVuexModel.idField]; + this._reset(id); + } + else { + throw new Error('You cannot reset a non-copy'); + } + }; + FeathersVuexModel.prototype._reset = function (id) { }; + FeathersVuexModel.prototype.commit = function () { + if (this.isClone) { + var id = this[FeathersVuexModel.idField]; + return this._commit(id); + } + else { + throw new Error('You cannnot call commit on a non-copy'); + } + }; + FeathersVuexModel.prototype._commit = function (id) { }; + FeathersVuexModel.prototype.save = function (params) { + if (this[idField]) { + return preferUpdate + ? this.update(params) + : this.patch(params); + } + else { + return this.create(params); + } + }; + FeathersVuexModel.prototype.create = function (params) { + var data = Object.assign({}, this); + if (data[idField] === null) { + delete data[idField]; + } + return store.dispatch(namespace + "/create", [data, params]); + // return this._create(data, params) + }; + FeathersVuexModel.prototype._create = function (data, params) { }; + FeathersVuexModel.prototype.patch = function (params) { + if (!this[idField]) { + var error = new Error("Missing " + idField + " property. You must create the data before you can patch with this data"); + return Promise.reject(error); + } + // return this._patch(this[idField], this, params) + }; + FeathersVuexModel.prototype._patch = function (idField) { }; + FeathersVuexModel.prototype.update = function (params) { + if (!this[idField]) { + var error = new Error("Missing " + idField + " property. You must create the data before you can update with this data"); + return Promise.reject(error); + } + // return this._update(this[idField], this, params) + }; + FeathersVuexModel.prototype._update = function () { }; + FeathersVuexModel.prototype.remove = function (params) { + // return this._remove(this[idField], params) + }; + FeathersVuexModel.prototype._remove = function () { }; + FeathersVuexModel.prototype.toJSON = function () { + return lodash_merge_1["default"]({}, this); + }; + return FeathersVuexModel; + }()), + // static copiesById: Object + _a.idField = idField, + _a.preferUpdate = preferUpdate, + _a; +} +function createRelatedInstance(_a) { + var item = _a.item, Model = _a.Model, idField = _a.idField, store = _a.store; + // Create store instances (if data contains an idField) + var model = new Model(item); + var id = model[idField]; + var storedModel = store.state[model.constructor.namespace].keyedById[id]; + return { model: model, storedModel: storedModel }; +} +function cloneWithAccessors(obj) { + var clone = {}; + var props = Object.getOwnPropertyNames(obj); + props.forEach(function (key) { + var desc = Object.getOwnPropertyDescriptor(obj, key); + // Do not allow sharing of deeply-nested objects between instances + if (lodash_isplainobject_1["default"](desc.value)) { + desc.value = fast_copy_1["default"](desc.value); + } + Object.defineProperty(clone, key, desc); + }); + return clone; +} +exports["default"] = makeModel; diff --git a/src/service-module/model/model.test.js b/src/service-module/model/model.test.js new file mode 100644 index 00000000..dd4c17e9 --- /dev/null +++ b/src/service-module/model/model.test.js @@ -0,0 +1,17 @@ +"use strict"; +exports.__esModule = true; +var chai_1 = require("chai"); +// import Vuex from 'vuex' +// import { makeTodos } from '../../../test/fixtures/todos' +// import { +// feathersRestClient as feathersClient, feathersSocketioClient, makeFeathersRestClient +// } from '../fixtures/feathers-client' +var model_1 = require("./model"); +describe('makeModel', function () { + it('can make a FeathersVuexModel', function () { + var FeathersVuexModel = model_1["default"]({ + idField: '_id' + }); + chai_1.assert(FeathersVuexModel); + }); +}); diff --git a/src/service-module/model/model.test.ts b/src/service-module/model/model.test.ts new file mode 100644 index 00000000..68086534 --- /dev/null +++ b/src/service-module/model/model.test.ts @@ -0,0 +1,27 @@ +import { assert } from 'chai' +// import Vuex from 'vuex' + +// import { makeTodos } from '../../../test/fixtures/todos' +// import { +// feathersRestClient as feathersClient, feathersSocketioClient, makeFeathersRestClient +// } from '../fixtures/feathers-client' +import makeModel from './model' + +describe('makeModel', function() { + it('creating FeathersVuexModel', function() { + const FeathersVuexModel = makeModel({ + store: {} + }) + + assert(FeathersVuexModel.idField === 'id') + }) + + it('customizing FeathersVuexModel', function() { + const FeathersVuexModel = makeModel({ + idField: '_id', + store: {} + }) + + assert(FeathersVuexModel.idField === '_id') + }) +}) diff --git a/src/service-module/model/model.tests.html b/src/service-module/model/model.tests.html new file mode 100644 index 00000000..6d676d85 --- /dev/null +++ b/src/service-module/model/model.tests.html @@ -0,0 +1,11 @@ + + + + Model tests (Feathers-Vuex) + + + + + + + \ No newline at end of file diff --git a/src/service-module/model/model.ts b/src/service-module/model/model.ts new file mode 100644 index 00000000..28684012 --- /dev/null +++ b/src/service-module/model/model.ts @@ -0,0 +1,156 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import fastCopy from 'fast-copy' +import isPlainObject from 'lodash.isplainobject' +import merge from 'lodash.merge' +// import { updateOriginal } from '../../utils' + +const defaults = { + idField: 'id', + preferUpdate: false, + instanceDefaults: {} +} + +interface FeathersVuexModelOptions { + idField?: string + preferUpdate?: boolean + nameStyle?: string + store: any +} + +function makeModel(options: FeathersVuexModelOptions) { + options = Object.assign({}, defaults, options) + const { idField, preferUpdate } = options + + return class FeathersVuexModel { + protected isClone: boolean + + // static copiesById: Object + public static idField: string = idField + // static instanceDefaults: Object + private static globalModels: Record + public static modelName: string + public static namespace: string + public static options: FeathersVuexModelOptions + public static preferUpdate: boolean = preferUpdate + public static store: Record + + public static getFromStore(id: string) {} + public static getId(record: Record): string { + return record[FeathersVuexModel.idField] + } + + public constructor() {} + + public clone() { + if (this.isClone) { + throw new Error('You cannot clone a copy') + } + const id = this[FeathersVuexModel.idField] + + return this._clone(id) + } + public _clone(id) {} + + public reset() { + if (this.isClone) { + const id = this[FeathersVuexModel.idField] + this._reset(id) + } else { + throw new Error('You cannot reset a non-copy') + } + } + public _reset(id: string) {} + + public commit() { + if (this.isClone) { + const id = this[FeathersVuexModel.idField] + return this._commit(id) + } else { + throw new Error('You cannnot call commit on a non-copy') + } + } + public _commit(id) {} + + public save(params) { + if (this[idField]) { + return preferUpdate ? this.update(params) : this.patch(params) + } else { + return this.create(params) + } + } + + public create(params) { + const data = Object.assign({}, this) + if (data[idField] === null) { + delete data[idField] + } + // return store.dispatch(`${namespace}/create`, [data, params]) + // return this._create(data, params) + } + public _create(data, params) {} + + public patch(params) { + if (!this[idField]) { + const error = new Error( + `Missing ${idField} property. You must create the data before you can patch with this data` + ) + return Promise.reject(error) + } + // return this._patch(this[idField], this, params) + } + public _patch(idField: string) {} + + public update(params) { + if (!this[idField]) { + const error = new Error( + `Missing ${idField} property. You must create the data before you can update with this data` + ) + return Promise.reject(error) + } + // return this._update(this[idField], this, params) + } + public _update() {} + + public remove(params) { + // return this._remove(this[idField], params) + } + public _remove() {} + + public toJSON() { + return merge({}, this) + } + } +} + +function createRelatedInstance({ item, Model, idField, store }) { + // Create store instances (if data contains an idField) + const model = new Model(item) + const id = model[idField] + const storedModel = store.state[model.constructor.namespace].keyedById[id] + + return { model, storedModel } +} + +function cloneWithAccessors(obj) { + const clone = {} + + const props = Object.getOwnPropertyNames(obj) + props.forEach(key => { + const desc = Object.getOwnPropertyDescriptor(obj, key) + + // Do not allow sharing of deeply-nested objects between instances + if (isPlainObject(desc.value)) { + desc.value = fastCopy(desc.value) + } + + Object.defineProperty(clone, key, desc) + }) + + return clone +} + +export default makeModel From 8bfd07a0a64b2a8890c9659ebdd4261cc9011874 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 23 Mar 2019 19:00:56 -0600 Subject: [PATCH 003/404] lint cleanup --- src/service-module/service-module.js | 92 +++++++++++++++++++--------- 1 file changed, 63 insertions(+), 29 deletions(-) diff --git a/src/service-module/service-module.js b/src/service-module/service-module.js index 9095ea55..97ce3131 100644 --- a/src/service-module/service-module.js +++ b/src/service-module/service-module.js @@ -28,36 +28,54 @@ const defaults = { actions: {} // for custom actions } -export default function servicePluginInit (feathersClient, globalOptions = {}, globalModels = {}) { +export default function servicePluginInit( + feathersClient, + globalOptions = {}, + globalModels = {} +) { globalModels.byServicePath = globalModels.byServicePath || {} if (!feathersClient || !feathersClient.service) { - throw new Error('You must provide a Feathers Client instance to feathers-vuex') + throw new Error( + 'You must provide a Feathers Client instance to feathers-vuex' + ) } globalOptions = Object.assign({}, defaults, globalOptions) - const serviceModule = function serviceModule (servicePath, options = {}) { + const serviceModule = function serviceModule(servicePath, options = {}) { if (!feathersClient || !feathersClient.service) { - throw new Error('You must provide a service path or object to create a feathers-vuex service module') + throw new Error( + 'You must provide a service path or object to create a feathers-vuex service module' + ) } options = Object.assign({}, globalOptions, options) const { debug, apiPrefix } = options if (typeof servicePath !== 'string') { - throw new Error('The first argument to setup a feathers-vuex service must be a string') + throw new Error( + 'The first argument to setup a feathers-vuex service must be a string' + ) } const service = feathersClient.service(servicePath) if (!service) { - throw new Error('No service was found. Please configure a transport plugin on the Feathers Client. Make sure you use the client version of the transport, like `feathers-socketio/client` or `feathers-rest/client`.') + throw new Error( + 'No service was found. Please configure a transport plugin on the Feathers Client. Make sure you use the client version of the transport, like `feathers-socketio/client` or `feathers-rest/client`.' + ) } - const paginate = service.hasOwnProperty('paginate') && service.paginate.hasOwnProperty('default') + const paginate = + service.hasOwnProperty('paginate') && + service.paginate.hasOwnProperty('default') const stateOptions = Object.assign(options, { paginate }) const defaultState = makeState(servicePath, stateOptions) const defaultGetters = makeGetters(servicePath) - const defaultMutations = makeMutations(servicePath, { debug, globalModels, apiPrefix }) + const defaultMutations = makeMutations(servicePath, { + debug, + globalModels, + apiPrefix + }) const defaultActions = makeActions(service, { debug }) const module = { namespaced: true, @@ -69,14 +87,14 @@ export default function servicePluginInit (feathersClient, globalOptions = {}, g return module } - const serviceModel = function serviceModel (options) { + const serviceModel = function serviceModel(options) { options = Object.assign({}, globalOptions, options, { globalModels }) const Model = makeModel(options) return Model } - const servicePlugin = function servicePlugin (module, Model, options = {}) { + const servicePlugin = function servicePlugin(module, Model, options = {}) { options = Object.assign({}, globalOptions, options) const { servicePath } = module.state const { nameStyle, apiPrefix } = options @@ -88,7 +106,7 @@ export default function servicePluginInit (feathersClient, globalOptions = {}, g } let namespace = options.namespace || nameStyles[nameStyle](servicePath) - return function setupStore (store) { + return function setupStore(store) { service.FeathersVuexModel = Model // Add servicePath to Model so it can be accessed Object.defineProperties(Model, { @@ -104,7 +122,12 @@ export default function servicePluginInit (feathersClient, globalOptions = {}, g }) // Add Model to the globalModels object, so it's available in the Vue plugin - const modelInfo = registerModel(Model, globalModels, apiPrefix, servicePath) + const modelInfo = registerModel( + Model, + globalModels, + apiPrefix, + servicePath + ) module.state.modelName = modelInfo.path store.registerModule(namespace, module) @@ -114,17 +137,17 @@ export default function servicePluginInit (feathersClient, globalOptions = {}, g value: modelInfo.name }, find: { - value (params) { + value(params) { return store.dispatch(`${namespace}/find`, params) } }, findInStore: { - value (params) { + value(params) { return store.getters[`${namespace}/find`](params) } }, get: { - value (id, params) { + value(id, params) { if (params) { return store.dispatch(`${namespace}/get`, [id, params]) } else { @@ -133,9 +156,9 @@ export default function servicePluginInit (feathersClient, globalOptions = {}, g } }, getFromStore: { - value (id, params) { + value(id, params) { if (params) { - return store.getters[`${namespace}/get`]([ id, params ]) + return store.getters[`${namespace}/get`]([id, params]) } else { return store.getters[`${namespace}/get`](id) } @@ -146,7 +169,7 @@ export default function servicePluginInit (feathersClient, globalOptions = {}, g // Upgrade the Model's API methods to use the store.actions Object.defineProperties(Model.prototype, { _clone: { - value (id) { + value(id) { store.commit(`${namespace}/createCopy`, id) if (store.state[namespace].keepCopiesInStore) { @@ -157,34 +180,34 @@ export default function servicePluginInit (feathersClient, globalOptions = {}, g } }, _commit: { - value (id) { + value(id) { store.commit(`${namespace}/commitCopy`, id) return this._clone(id) } }, _reset: { - value (id) { + value(id) { store.commit(`${namespace}/rejectCopy`, id) } }, _create: { - value (data, params) { + value(data, params) { return store.dispatch(`${namespace}/create`, [data, params]) } }, _patch: { - value (id, data, params) { + value(id, data, params) { return store.dispatch(`${namespace}/patch`, [id, data, params]) } }, _update: { - value (id, data, params) { + value(id, data, params) { return store.dispatch(`${namespace}/update`, [id, data, params]) } }, _remove: { - value (id, params) { + value(id, params) { return store.dispatch(`${namespace}/remove`, [id, params]) } } @@ -192,15 +215,26 @@ export default function servicePluginInit (feathersClient, globalOptions = {}, g if (options.enableEvents) { // Listen to socket events when available. - service.on('created', item => store.commit(`${namespace}/addItem`, item)) - service.on('updated', item => store.commit(`${namespace}/updateItem`, item)) - service.on('patched', item => store.commit(`${namespace}/updateItem`, item)) - service.on('removed', item => store.commit(`${namespace}/removeItem`, item)) + service.on('created', item => + store.commit(`${namespace}/addItem`, item) + ) + service.on('updated', item => + store.commit(`${namespace}/updateItem`, item) + ) + service.on('patched', item => + store.commit(`${namespace}/updateItem`, item) + ) + service.on('removed', item => + store.commit(`${namespace}/removeItem`, item) + ) } } } - const createServicePlugin = function createServicePlugin (servicePath, options = {}) { + const createServicePlugin = function createServicePlugin( + servicePath, + options = {} + ) { const module = serviceModule(servicePath, options) const Model = serviceModel(options) From b654994ce90300a9a47e2a24ed903a83503729d9 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 01:59:11 -0600 Subject: [PATCH 004/404] Design new API, begins tests --- package-lock.json | 6 +- package.json | 2 +- .../model/model.global-models.ts | 3 + src/service-module/model/model.js | 115 ---- .../model/model.make-service-module.ts | 70 ++ .../model/model.service-module.ts | 237 +++++++ src/service-module/model/model.test.js | 17 - src/service-module/model/model.test.ts | 42 +- src/service-module/model/model.ts | 25 +- src/service-module/model/notes.md | 37 + src/service-module/new-api/add-model.ts | 22 + src/service-module/new-api/global-models.ts | 10 + src/service-module/new-api/index.ts | 33 + src/service-module/new-api/make-model.ts | 45 ++ .../new-api/make-service-module.ts | 16 + .../new-api/make-service-plugin.test.ts | 98 +++ .../new-api/make-service-plugin.ts | 30 + src/service-module/new-api/model.test.ts | 68 ++ src/service-module/new-api/model.ts | 0 src/{utils.js => utils.ts} | 250 ++++--- test/service-module/service-module.test.js | 643 +++++++++++------- tsconfig.json | 4 +- 22 files changed, 1284 insertions(+), 489 deletions(-) create mode 100644 src/service-module/model/model.global-models.ts delete mode 100644 src/service-module/model/model.js create mode 100644 src/service-module/model/model.make-service-module.ts create mode 100644 src/service-module/model/model.service-module.ts delete mode 100644 src/service-module/model/model.test.js create mode 100644 src/service-module/model/notes.md create mode 100644 src/service-module/new-api/add-model.ts create mode 100644 src/service-module/new-api/global-models.ts create mode 100644 src/service-module/new-api/index.ts create mode 100644 src/service-module/new-api/make-model.ts create mode 100644 src/service-module/new-api/make-service-module.ts create mode 100644 src/service-module/new-api/make-service-plugin.test.ts create mode 100644 src/service-module/new-api/make-service-plugin.ts create mode 100644 src/service-module/new-api/model.test.ts create mode 100644 src/service-module/new-api/model.ts rename src/{utils.js => utils.ts} (62%) diff --git a/package-lock.json b/package-lock.json index a2e7f042..5ba32ff5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20423,9 +20423,9 @@ } }, "vue": { - "version": "2.5.22", - "resolved": "https://registry.npmjs.org/vue/-/vue-2.5.22.tgz", - "integrity": "sha512-pxY3ZHlXNJMFQbkjEgGVMaMMkSV1ONpz+4qB55kZuJzyJOhn6MSy/YZdzhdnumegNzVTL/Dn3Pp4UrVBYt1j/g==", + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.10.tgz", + "integrity": "sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==", "dev": true }, "vue-eslint-parser": { diff --git a/package.json b/package.json index 90e0a4ce..72f696e2 100644 --- a/package.json +++ b/package.json @@ -154,7 +154,7 @@ "testee": "^0.9.0", "ts-node": "^8.0.3", "typescript": "^3.3.4000", - "vue": "^2.5.22", + "vue": "^2.6.10", "vuepress": "^0.14.10", "vuex": "^3.0.1" } diff --git a/src/service-module/model/model.global-models.ts b/src/service-module/model/model.global-models.ts new file mode 100644 index 00000000..2930db75 --- /dev/null +++ b/src/service-module/model/model.global-models.ts @@ -0,0 +1,3 @@ +export default { + byServicePath: {} +} diff --git a/src/service-module/model/model.js b/src/service-module/model/model.js deleted file mode 100644 index 59679971..00000000 --- a/src/service-module/model/model.js +++ /dev/null @@ -1,115 +0,0 @@ -"use strict"; -exports.__esModule = true; -var fast_copy_1 = require("fast-copy"); -var lodash_isplainobject_1 = require("lodash.isplainobject"); -var lodash_merge_1 = require("lodash.merge"); -function makeModel(options) { - if (options === void 0) { options = { idField: 'id', preferUpdate: false }; } - var _a; - var idField = options.idField, preferUpdate = options.preferUpdate; - return _a = /** @class */ (function () { - function FeathersVuexModel() { - } - FeathersVuexModel.getFromStore = function (id) { }; - FeathersVuexModel.getId = function (record) { - return record[FeathersVuexModel.idField]; - }; - FeathersVuexModel.prototype.clone = function () { - if (this.isClone) { - throw new Error('You cannot clone a copy'); - } - var id = this[FeathersVuexModel.idField]; - return this._clone(id); - }; - FeathersVuexModel.prototype._clone = function (id) { }; - FeathersVuexModel.prototype.reset = function () { - if (this.isClone) { - var id = this[FeathersVuexModel.idField]; - this._reset(id); - } - else { - throw new Error('You cannot reset a non-copy'); - } - }; - FeathersVuexModel.prototype._reset = function (id) { }; - FeathersVuexModel.prototype.commit = function () { - if (this.isClone) { - var id = this[FeathersVuexModel.idField]; - return this._commit(id); - } - else { - throw new Error('You cannnot call commit on a non-copy'); - } - }; - FeathersVuexModel.prototype._commit = function (id) { }; - FeathersVuexModel.prototype.save = function (params) { - if (this[idField]) { - return preferUpdate - ? this.update(params) - : this.patch(params); - } - else { - return this.create(params); - } - }; - FeathersVuexModel.prototype.create = function (params) { - var data = Object.assign({}, this); - if (data[idField] === null) { - delete data[idField]; - } - return store.dispatch(namespace + "/create", [data, params]); - // return this._create(data, params) - }; - FeathersVuexModel.prototype._create = function (data, params) { }; - FeathersVuexModel.prototype.patch = function (params) { - if (!this[idField]) { - var error = new Error("Missing " + idField + " property. You must create the data before you can patch with this data"); - return Promise.reject(error); - } - // return this._patch(this[idField], this, params) - }; - FeathersVuexModel.prototype._patch = function (idField) { }; - FeathersVuexModel.prototype.update = function (params) { - if (!this[idField]) { - var error = new Error("Missing " + idField + " property. You must create the data before you can update with this data"); - return Promise.reject(error); - } - // return this._update(this[idField], this, params) - }; - FeathersVuexModel.prototype._update = function () { }; - FeathersVuexModel.prototype.remove = function (params) { - // return this._remove(this[idField], params) - }; - FeathersVuexModel.prototype._remove = function () { }; - FeathersVuexModel.prototype.toJSON = function () { - return lodash_merge_1["default"]({}, this); - }; - return FeathersVuexModel; - }()), - // static copiesById: Object - _a.idField = idField, - _a.preferUpdate = preferUpdate, - _a; -} -function createRelatedInstance(_a) { - var item = _a.item, Model = _a.Model, idField = _a.idField, store = _a.store; - // Create store instances (if data contains an idField) - var model = new Model(item); - var id = model[idField]; - var storedModel = store.state[model.constructor.namespace].keyedById[id]; - return { model: model, storedModel: storedModel }; -} -function cloneWithAccessors(obj) { - var clone = {}; - var props = Object.getOwnPropertyNames(obj); - props.forEach(function (key) { - var desc = Object.getOwnPropertyDescriptor(obj, key); - // Do not allow sharing of deeply-nested objects between instances - if (lodash_isplainobject_1["default"](desc.value)) { - desc.value = fast_copy_1["default"](desc.value); - } - Object.defineProperty(clone, key, desc); - }); - return clone; -} -exports["default"] = makeModel; diff --git a/src/service-module/model/model.make-service-module.ts b/src/service-module/model/model.make-service-module.ts new file mode 100644 index 00000000..99376dce --- /dev/null +++ b/src/service-module/model/model.make-service-module.ts @@ -0,0 +1,70 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +// import { Module } from 'vuex' +import globalModels from './model.global-models' +function makeState(servicePath, stateOptions) {} +function makeGetters(servicePath) {} +function makeMutations(servicePath, options) {} +function makeActions(servicePath, options) {} +// import makeState from '../state' +// import makeGetters from '../getters' +// import makeMutations from '../mutations' +// import makeActions from '../actions' + +function makeServiceModule( + servicePath: string, + options = { + state: {}, + mutations: {}, + actions: {}, + getters: {} + } +) { + // const { debug, apiPrefix } = options + + if (typeof servicePath !== 'string') { + throw new Error( + 'The first argument to setup a feathers-vuex service must be a string' + ) + } + + // test variables + const service = { + paginate: {} + } + const debug = false + const apiPrefix = '' + + // const service = feathersClient.service(servicePath) + if (!service) { + throw new Error( + 'No service was found. Please configure a transport plugin on the Feathers Client. Make sure you use the client version of the transport, like `feathers-socketio/client` or `feathers-rest/client`.' + ) + } + const paginate = + service.hasOwnProperty('paginate') && + service.paginate.hasOwnProperty('default') + const stateOptions = Object.assign(options, { paginate }) + + const defaultState = makeState(servicePath, stateOptions) + const defaultGetters = makeGetters(servicePath) + const defaultMutations = makeMutations(servicePath, { + debug, + globalModels, + apiPrefix + }) + const defaultActions = makeActions(service, { debug }) + const module = { + namespaced: true, + state: Object.assign({}, defaultState, options.state), + getters: Object.assign({}, defaultGetters, options.getters), + mutations: Object.assign({}, defaultMutations, options.mutations), + actions: Object.assign({}, defaultActions, options.actions) + } + return module +} + +export default makeServiceModule diff --git a/src/service-module/model/model.service-module.ts b/src/service-module/model/model.service-module.ts new file mode 100644 index 00000000..54fcc4e9 --- /dev/null +++ b/src/service-module/model/model.service-module.ts @@ -0,0 +1,237 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { getShortName, getNameFromPath, registerModel } from '../../utils' +import makeServiceModule from './model.make-service-module' +import makeModel from './model' + +interface GlobalModels { + byServicePath?: Record +} + +const modelOptions = { + idField: 'id', // The field in each record that will contain the id + instanceDefaults: {}, // The default values for the instance when `const instance =new Model()` + modelName: '', // The location of this service's Model in the Vue plugin (globalModels object). Added in the servicePlugin method + preferUpdate: false // When true, calling model.save() will do an update instead of a patch. +} +const moduleOptions = { + state: {}, // for custom state + getters: {}, // for custom getters + mutations: {}, // for custom mutations + actions: {}, // for custom actions + paramsForServer: [], // Custom query operators that are ignored in the find getter, but will pass through to the server. + whitelist: [], // Custom query operators that will be allowed in the find getter. + keepCopiesInStore: false, // Set to true to store cloned copies in the store instead of on the Model. + skipRequestIfExists: false, // For get action, if the record already exists in store, skip the remote request + autoRemove: false, // Automatically remove records missing from responses (only use with feathers-rest) + diffOnPatch: false, // Only send changed data on patch + replaceItems: false, // Instad of merging in changes in the store, replace the entire record. + addOnUpsert: false // Add new records pushed by 'updated/patched' socketio events into store, instead of discarding them +} +const defaults = { + idField: 'id', // The field in each record that will contain the id + nameStyle: 'short', // Determines the source of the module name. 'short', 'path', or 'explicit' + enableEvents: true, // Listens to socket.io events when available + apiPrefix: '', // Setting to 'api1/' will prefix the store moduleName, unless `namespace` is used, then this is ignored. + debug: false // Set to true to enable logging messages. +} + +export default function servicePluginInit( + feathersClient, + globalOptions = {}, + globalModels: GlobalModels = {} +) { + globalModels.byServicePath = globalModels.byServicePath || {} + if (!feathersClient || !feathersClient.service) { + throw new Error( + 'You must provide a Feathers Client instance to feathers-vuex' + ) + } + + globalOptions = Object.assign({}, defaults, globalOptions) + + const options = {} + + const allOptions = Object.assign({}, globalOptions, moduleOptions, options) + + const serviceModule = makeServiceModule('service', allOptions) + + const serviceModel = function serviceModel(options) { + options = Object.assign({}, globalOptions, options, { globalModels }) + const Model = makeModel(options) + + return Model + } + + const servicePlugin = function servicePlugin( + module, + Model, + options = { + nameStyle: 'short', + apiPrefix: '', + namespace: '', + enableEvents: true + } + ) { + options = Object.assign({}, globalOptions, options) + const { servicePath } = module.state + const { nameStyle, apiPrefix } = options + const service = feathersClient.service(servicePath) + + const nameStyles = { + short: getShortName, + path: getNameFromPath + } + let namespace = options.namespace || nameStyles[nameStyle](servicePath) + + return function setupStore(store) { + service.FeathersVuexModel = Model + // Add servicePath to Model so it can be accessed + Object.defineProperties(Model, { + servicePath: { + value: servicePath + }, + namespace: { + value: namespace + }, + store: { + value: store + } + }) + + // Add Model to the globalModels object, so it's available in the Vue plugin + const modelInfo = registerModel( + Model, + globalModels, + apiPrefix, + servicePath + ) + + module.state.modelName = modelInfo.path + store.registerModule(namespace, module) + + Object.defineProperties(Model, { + className: { + value: modelInfo.name + }, + find: { + value(params) { + return store.dispatch(`${namespace}/find`, params) + } + }, + findInStore: { + value(params) { + return store.getters[`${namespace}/find`](params) + } + }, + get: { + value(id, params) { + if (params) { + return store.dispatch(`${namespace}/get`, [id, params]) + } else { + return store.dispatch(`${namespace}/get`, id) + } + } + }, + getFromStore: { + value(id, params) { + if (params) { + return store.getters[`${namespace}/get`]([id, params]) + } else { + return store.getters[`${namespace}/get`](id) + } + } + } + }) + + // Upgrade the Model's API methods to use the store.actions + Object.defineProperties(Model.prototype, { + _clone: { + value(id) { + store.commit(`${namespace}/createCopy`, id) + + if (store.state[namespace].keepCopiesInStore) { + return store.getters[`${namespace}/getCopyById`](id) + } else { + return Model.copiesById[id] + } + } + }, + _commit: { + value(id) { + store.commit(`${namespace}/commitCopy`, id) + + return this._clone(id) + } + }, + _reset: { + value(id) { + store.commit(`${namespace}/rejectCopy`, id) + } + }, + _create: { + value(data, params) { + return store.dispatch(`${namespace}/create`, [data, params]) + } + }, + _patch: { + value(id, data, params) { + return store.dispatch(`${namespace}/patch`, [id, data, params]) + } + }, + _update: { + value(id, data, params) { + return store.dispatch(`${namespace}/update`, [id, data, params]) + } + }, + _remove: { + value(id, params) { + return store.dispatch(`${namespace}/remove`, [id, params]) + } + } + }) + + if (options.enableEvents) { + // Listen to socket events when available. + service.on('created', item => + store.commit(`${namespace}/addItem`, item) + ) + service.on('updated', item => + store.commit(`${namespace}/updateItem`, item) + ) + service.on('patched', item => + store.commit(`${namespace}/updateItem`, item) + ) + service.on('removed', item => + store.commit(`${namespace}/removeItem`, item) + ) + } + } + } + + const createServicePlugin = function createServicePlugin( + servicePath, + options = { + state: {}, + mutations: {}, + actions: {}, + getters: {} + } + ) { + const module = makeServiceModule(servicePath, options) + const Model = serviceModel(options) + + return servicePlugin(module, Model /*options*/) + } + + Object.assign(createServicePlugin, { + serviceModule, + serviceModel, + servicePlugin + }) + + return createServicePlugin +} diff --git a/src/service-module/model/model.test.js b/src/service-module/model/model.test.js deleted file mode 100644 index dd4c17e9..00000000 --- a/src/service-module/model/model.test.js +++ /dev/null @@ -1,17 +0,0 @@ -"use strict"; -exports.__esModule = true; -var chai_1 = require("chai"); -// import Vuex from 'vuex' -// import { makeTodos } from '../../../test/fixtures/todos' -// import { -// feathersRestClient as feathersClient, feathersSocketioClient, makeFeathersRestClient -// } from '../fixtures/feathers-client' -var model_1 = require("./model"); -describe('makeModel', function () { - it('can make a FeathersVuexModel', function () { - var FeathersVuexModel = model_1["default"]({ - idField: '_id' - }); - chai_1.assert(FeathersVuexModel); - }); -}); diff --git a/src/service-module/model/model.test.ts b/src/service-module/model/model.test.ts index 68086534..19fd9577 100644 --- a/src/service-module/model/model.test.ts +++ b/src/service-module/model/model.test.ts @@ -1,13 +1,41 @@ import { assert } from 'chai' -// import Vuex from 'vuex' - -// import { makeTodos } from '../../../test/fixtures/todos' -// import { -// feathersRestClient as feathersClient, feathersSocketioClient, makeFeathersRestClient -// } from '../fixtures/feathers-client' +import Vuex from 'vuex' +import servicePluginInit from './model.service-module' +import { + makeFeathersRestClient, + feathersRestClient as feathersClient, + feathersSocketioClient +} from '../../../test/fixtures/feathers-client' import makeModel from './model' -describe('makeModel', function() { +const globalModels = {} +const service = servicePluginInit(feathersClient, {}, globalModels) + +describe.skip('makeModel', function() { + it('registers a vuex plugin and Model for the service', () => { + const serviceName = 'todos' + const feathersService = feathersClient.service(serviceName) + const store = new Vuex.Store({ + plugins: [service(serviceName)] + }) + assert( + globalModels.hasOwnProperty('Todo'), + 'the Model was added to the globalModels' + ) + // assert( + // feathersService.FeathersVuexModel === globalModels.Todo, + // 'the Model is also found at service.FeathersVuexModel' + // ) + + // const todo = new globalModels.Todo({ + // description: 'Do the dishes', + // isComplete: false + // }) + // assert(todo instanceof globalModels.Todo, 'Model can be instantiated.') + + // assert(store.state[serviceName]) + }) + it('creating FeathersVuexModel', function() { const FeathersVuexModel = makeModel({ store: {} diff --git a/src/service-module/model/model.ts b/src/service-module/model/model.ts index 28684012..9e4452e4 100644 --- a/src/service-module/model/model.ts +++ b/src/service-module/model/model.ts @@ -6,10 +6,12 @@ eslint import fastCopy from 'fast-copy' import isPlainObject from 'lodash.isplainobject' import merge from 'lodash.merge' +import { getShortName, getNameFromPath } from '../../utils' // import { updateOriginal } from '../../utils' const defaults = { idField: 'id', + nameStyle: 'short', preferUpdate: false, instanceDefaults: {} } @@ -18,12 +20,20 @@ interface FeathersVuexModelOptions { idField?: string preferUpdate?: boolean nameStyle?: string + namespace?: string store: any } function makeModel(options: FeathersVuexModelOptions) { options = Object.assign({}, defaults, options) - const { idField, preferUpdate } = options + const { idField, preferUpdate, nameStyle, store } = options + let { namespace } = options + const nameStyles = { + short: getShortName, + path: getNameFromPath + } + const servicePath = 'test' + namespace = namespace || nameStyles[nameStyle](servicePath) return class FeathersVuexModel { protected isClone: boolean @@ -31,14 +41,15 @@ function makeModel(options: FeathersVuexModelOptions) { // static copiesById: Object public static idField: string = idField // static instanceDefaults: Object - private static globalModels: Record - public static modelName: string - public static namespace: string - public static options: FeathersVuexModelOptions + // public static modelName: string + // public static options: FeathersVuexModelOptions public static preferUpdate: boolean = preferUpdate - public static store: Record + private static globalModels: Record + protected static nameStyle = nameStyle + public static namespace: string = namespace + public static store: any = store - public static getFromStore(id: string) {} + // public static getFromStore(id: string) {} public static getId(record: Record): string { return record[FeathersVuexModel.idField] } diff --git a/src/service-module/model/notes.md b/src/service-module/model/notes.md new file mode 100644 index 00000000..db953da3 --- /dev/null +++ b/src/service-module/model/notes.md @@ -0,0 +1,37 @@ +# API Notes + +```ts +import feathers from './feathers-client' +import Vuex from 'vuex' +import feathersVuex from 'feathers-vuex' + +const { makeServicePlugin, BaseModel, addModel } = feathersVuex(feathers, { + idField: '_id', + serverAlias: 'default' +}) + +// @service('todos') +class Todo extends BaseModel { + servicePath: 'todos' + store: any + firstName: string + constructor(data) { + this.firstName = data.firstName + } +} + +addModel(Todo) + +const servicePath = 'todos' +const todos = makeServicePlugin({ + servicePath, + Model: Todo, + service: feathers.service(servicePath) +}) + +const store = new Vuex.Store({ + plugins: [ + todos + ] +}) +``` \ No newline at end of file diff --git a/src/service-module/new-api/add-model.ts b/src/service-module/new-api/add-model.ts new file mode 100644 index 00000000..2e8a1f5a --- /dev/null +++ b/src/service-module/new-api/add-model.ts @@ -0,0 +1,22 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import globalModels from './global-models' + +/** + * prepareAddModel wraps options in a closure around addModel + * @param options + */ +export default function prepareAddModel(options) { + const { serverAlias } = options + + return function addModel(Model) { + globalModels[serverAlias] = globalModels[serverAlias] || {} + if (globalModels[serverAlias][Model.name]) { + console.error(`Overwriting Model: models[${serverAlias}][${Model.name}].`) + } + globalModels[serverAlias][Model.name] = Model + } +} diff --git a/src/service-module/new-api/global-models.ts b/src/service-module/new-api/global-models.ts new file mode 100644 index 00000000..7cd22d22 --- /dev/null +++ b/src/service-module/new-api/global-models.ts @@ -0,0 +1,10 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +const globalModels: { [k: string]: Record } = { + byServicePath: {} +} + +export default globalModels diff --git a/src/service-module/new-api/index.ts b/src/service-module/new-api/index.ts new file mode 100644 index 00000000..722871e5 --- /dev/null +++ b/src/service-module/new-api/index.ts @@ -0,0 +1,33 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import prepareMakeServicePlugin from './make-service-plugin' +import makeModel from './make-model' +import prepareAddModel from './add-model' +import models from './global-models' + +export interface FeathersVuexOptions { + idField?: string + nameStyle?: string + serverAlias: string +} +const defaultOptions = { + idField: 'id', + nameStyle: 'short' +} + +export default function feathersVuex(feathers, options: FeathersVuexOptions) { + options = Object.assign({}, defaultOptions, options) + const BaseModel = makeModel(options) + const makeServicePlugin = prepareMakeServicePlugin(options) + const addModel = prepareAddModel(options) + + return { + makeServicePlugin, + BaseModel, + addModel, + models + } +} diff --git a/src/service-module/new-api/make-model.ts b/src/service-module/new-api/make-model.ts new file mode 100644 index 00000000..f9ac2bc1 --- /dev/null +++ b/src/service-module/new-api/make-model.ts @@ -0,0 +1,45 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import globalModels from './global-models' +import Vue from 'vue' + +export default function makeModel(options) { + abstract class FeathersVuexModel { + abstract servicePath: string + public static idField: string = options.idField + public static models = globalModels // Can access other Models here + public static copiesById = {} + public static serverAlias: string = options.serverAlias + public static store: Record + protected isClone: boolean + + public _data: Record + public constructor(data) { + this._data = Vue.observable(data) + } + + public static getId(record: Record): string { + return record[FeathersVuexModel.idField] + } + + public clone() { + const { store, copiesById } = FeathersVuexModel + if (this.isClone) { + throw new Error('You cannot clone a copy') + } + const id = this[FeathersVuexModel.idField] + + store.commit(`${options.namespace}/createCopy`, id) + + if (store.state[options.namespace].keepCopiesInStore) { + return store.getters[`${options.namespace}/getCopyById`](id) + } else { + return copiesById[id] + } + } + } + return FeathersVuexModel +} diff --git a/src/service-module/new-api/make-service-module.ts b/src/service-module/new-api/make-service-module.ts new file mode 100644 index 00000000..ce0a801b --- /dev/null +++ b/src/service-module/new-api/make-service-module.ts @@ -0,0 +1,16 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +export default function makeServiceModule(service, options) { + return { + namespaced: true, + state: { + options + }, + getters: {}, + mutations: {}, + actions: {} + } +} diff --git a/src/service-module/new-api/make-service-plugin.test.ts b/src/service-module/new-api/make-service-plugin.test.ts new file mode 100644 index 00000000..2668dfd5 --- /dev/null +++ b/src/service-module/new-api/make-service-plugin.test.ts @@ -0,0 +1,98 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { assert } from 'chai' +import Vue from 'vue' +import Vuex, { StoreOptions } from 'vuex' +import { feathersRestClient as feathers } from '../../../test/fixtures/feathers-client' +import feathersVuex from './index' + +Vue.use(Vuex) + +describe('makeServicePlugin', function() { + it('regisers the vuex module with options', function() { + const serverAlias = 'default' + const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { + serverAlias + }) + + const servicePath = 'todos' + class Todo extends BaseModel { + public servicePath = servicePath + } + const todosPlugin = makeServicePlugin({ + servicePath, + Model: Todo, + service: feathers.service(servicePath) + }) + interface RootState { + todos: { options: {} } + } + const store = new Vuex.Store({ plugins: [todosPlugin] }) + + const expected = { + idField: 'id', + namespace: 'todos', + nameStyle: 'short', + serverAlias: 'default' + } + + assert.deepEqual( + store.state.todos.options, + expected, + 'The module was registered.' + ) + }) + + it('sets up Model.store', function() { + const serverAlias = 'default' + const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { + serverAlias + }) + + const servicePath = 'todos' + class Todo extends BaseModel { + public servicePath = servicePath + } + const todosPlugin = makeServicePlugin({ + servicePath, + Model: Todo, + service: feathers.service(servicePath) + }) + const store = new Vuex.Store({ plugins: [todosPlugin] }) + + assert(Todo.store === store, 'the store is on the Model!') + }) +}) + +it('allows accessing other models', function() { + const serverAlias = 'default' + const { makeServicePlugin, BaseModel, addModel, models } = feathersVuex( + feathers, + { idField: '_id', serverAlias } + ) + + const servicePath = 'todos' + class Todo extends BaseModel { + public servicePath = servicePath + public static store: Record + public constructor(data) { + super(data) + } + } + addModel(Todo) + const todosPlugin = makeServicePlugin({ + servicePath, + Model: Todo, + service: feathers.service(servicePath) + }) + + const store = new Vuex.Store({ + plugins: [todosPlugin] + }) + + assert(models[serverAlias][Todo.name] === Todo) + assert(Todo.store === store) +}) diff --git a/src/service-module/new-api/make-service-plugin.ts b/src/service-module/new-api/make-service-plugin.ts new file mode 100644 index 00000000..5a55aa52 --- /dev/null +++ b/src/service-module/new-api/make-service-plugin.ts @@ -0,0 +1,30 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import makeServiceModule from './make-service-module' +import { makeNamespace } from '../../utils' + +/** + * prepare only wraps the makeServicePlugin to provide the globalOptions. + * @param globalOptions + */ +export default function prepareMakeServicePlugin(globalOptions) { + /** + * Make a Vuex plugin for the provided service. It also attaches the vuex + * store to the provided Model instance. + */ + return function makeServicePlugin(required, options?) { + options = Object.assign({}, globalOptions, options) + const { servicePath, Model, service } = required + const { namespace, nameStyle } = options + + return store => { + options.namespace = makeNamespace(servicePath, { nameStyle, namespace }) + const module = makeServiceModule(service, options) + store.registerModule(options.namespace, module) + Model.store = store + } + } +} diff --git a/src/service-module/new-api/model.test.ts b/src/service-module/new-api/model.test.ts new file mode 100644 index 00000000..bc804687 --- /dev/null +++ b/src/service-module/new-api/model.test.ts @@ -0,0 +1,68 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { assert } from 'chai' +import Vue from 'vue' +import Vuex from 'vuex' +import { feathersRestClient as feathers } from '../../../test/fixtures/feathers-client' +import feathersVuex from './index' + +Vue.use(Vuex) + +describe.only('makeModel', function() { + it('propertly sets up the BaseModel', function() { + const serverAlias = 'default' + const { BaseModel } = feathersVuex(feathers, { + serverAlias + }) + + assert(BaseModel.name === 'FeathersVuexModel', 'name in place') + assert( + BaseModel.serverAlias === 'default', + 'serverAlias in place on BaseModel' + ) + assert(!BaseModel.store, 'no store by default') + assert(BaseModel.models, 'models are available') + assert(BaseModel.idField === 'id', 'default idField is id') + assert(typeof BaseModel.getId === 'function', 'have the getId method') + }) + + // it('default values', function() { + // const serverAlias = 'default' + // const { BaseModel } = feathersVuex(feathers, { + // serverAlias + // }) + // }) +}) + +it('allows accessing other models', function() { + const serverAlias = 'default' + const { makeServicePlugin, BaseModel, addModel, models } = feathersVuex( + feathers, + { idField: '_id', serverAlias } + ) + + const servicePath = 'todos' + class Todo extends BaseModel { + public servicePath = servicePath + public static store: Record + public constructor(data) { + super(data) + } + } + addModel(Todo) + const todosPlugin = makeServicePlugin({ + servicePath, + Model: Todo, + service: feathers.service(servicePath) + }) + + const store = new Vuex.Store({ + plugins: [todosPlugin] + }) + + assert(models[serverAlias][Todo.name] === Todo) + assert(Todo.store === store) +}) diff --git a/src/service-module/new-api/model.ts b/src/service-module/new-api/model.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/utils.js b/src/utils.ts similarity index 62% rename from src/utils.js rename to src/utils.ts index 7a577e11..87ff56c4 100644 --- a/src/utils.js +++ b/src/utils.ts @@ -1,21 +1,62 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ import _trim from 'lodash.trim' import decode from 'jwt-decode' import inflection from 'inflection' -import deepDiff from 'deep-diff' +import { diff } from 'deep-diff' import Vue from 'vue' import isObject from 'lodash.isobject' -const { diff } = deepDiff +export function stripSlashes(location) { + return Array.isArray(location) + ? location.map(l => _trim(l, '/')) + : _trim(location, '/') +} + +// From feathers-plus/feathers-hooks-common +export function setByDot(obj, path, value, ifDelete?) { + if (ifDelete) { + console.log( + 'DEPRECATED. Use deleteByDot instead of setByDot(obj,path,value,true). (setByDot)' + ) + } + + if (path.indexOf('.') === -1) { + obj[path] = value + + if (value === undefined && ifDelete) { + delete obj[path] + } + + return + } + + const parts = path.split('.') + const lastIndex = parts.length - 1 + return parts.reduce((obj1, part, i) => { + if (i !== lastIndex) { + if (!obj1.hasOwnProperty(part) || typeof obj1[part] !== 'object') { + obj1[part] = {} + } + return obj1[part] + } -export function stripSlashes (location) { - return Array.isArray(location) ? location.map(l => _trim(l, '/')) : _trim(location, '/') + obj1[part] = value + if (value === undefined && ifDelete) { + delete obj1[part] + } + return obj1 + }, obj) } -export function upperCaseFirst (string) { +export function upperCaseFirst(string) { return string.charAt(0).toUpperCase() + string.slice(1) } -export function getShortName (service) { +export function getShortName(service) { let namespace = stripSlashes(service) if (Array.isArray(namespace)) { namespace = namespace.slice(-1) @@ -25,12 +66,39 @@ export function getShortName (service) { return namespace } -export function getNameFromPath (service) { +export function getNameFromPath(service) { return stripSlashes(service) } +// Reads and returns the contents of a cookie with the provided name. +export function readCookie(cookies, name) { + if (!cookies) { + return undefined + } + var nameEQ = name + '=' + var ca = cookies.split(';') + for (var i = 0; i < ca.length; i++) { + var c = ca[i] + while (c.charAt(0) === ' ') { + c = c.substring(1, c.length) + } + if (c.indexOf(nameEQ) === 0) { + return c.substring(nameEQ.length, c.length) + } + } + return null +} + +// Pass a decoded payload and it will return a boolean based on if it hasn't expired. +export function payloadIsValid(payload) { + return payload && payload.exp * 1000 > new Date().getTime() +} + // from https://github.com/iliakan/detect-node -export const isNode = Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]' +export const isNode = + Object.prototype.toString.call( + typeof process !== 'undefined' ? process : 0 + ) === '[object process]' export const isBrowser = !isNode @@ -41,14 +109,34 @@ const authDefaults = { cookieName: 'feathers-jwt' } -export const initAuth = function initAuth (options) { - const { commit, req, moduleName, cookieName, feathersClient } = Object.assign({}, authDefaults, options) +export function getValidPayloadFromToken(token) { + if (token) { + try { + var payload = decode(token) + return payloadIsValid(payload) ? payload : undefined + } catch (error) { + return undefined + } + } + return undefined +} + +export const initAuth = function initAuth(options) { + const { commit, req, moduleName, cookieName, feathersClient } = Object.assign( + {}, + authDefaults, + options + ) if (typeof commit !== 'function') { - throw new Error('You must pass the `commit` function in the `initAuth` function options.') + throw new Error( + 'You must pass the `commit` function in the `initAuth` function options.' + ) } if (!req) { - throw new Error('You must pass the `req` object in the `initAuth` function options.') + throw new Error( + 'You must pass the `req` object in the `initAuth` function options.' + ) } const accessToken = readCookie(req.headers.cookie, cookieName) @@ -64,66 +152,21 @@ export const initAuth = function initAuth (options) { return Promise.resolve(payload) } -export function getValidPayloadFromToken (token) { - if (token) { - try { - var payload = decode(token) - return payloadIsValid(payload) ? payload : undefined - } catch (error) { - return undefined - } - } - return undefined -} - -// Pass a decoded payload and it will return a boolean based on if it hasn't expired. -export function payloadIsValid (payload) { - return payload && payload.exp * 1000 > new Date().getTime() -} - -// Reads and returns the contents of a cookie with the provided name. -export function readCookie (cookies, name) { - if (!cookies) { - return undefined - } - var nameEQ = name + '=' - var ca = cookies.split(';') - for (var i = 0; i < ca.length; i++) { - var c = ca[i] - while (c.charAt(0) === ' ') { - c = c.substring(1, c.length) - } - if (c.indexOf(nameEQ) === 0) { - return c.substring(nameEQ.length, c.length) - } - } - return null -} - -export function checkId (id, item, debug) { +export function checkId(id, item, debug) { if (id === undefined || id === null) { if (debug) { - console.error('No id found for item. Do you need to customize the `idField`?', item) + console.error( + 'No id found for item. Do you need to customize the `idField`?', + item + ) } return false } return true } -export function registerModel (Model, globalModels, apiPrefix, servicePath) { - const modelName = getModelName(Model) - let path = apiPrefix ? `${apiPrefix}.${modelName}` : modelName - - setByDot(globalModels, path, Model) - globalModels.byServicePath[servicePath] = Model - return { - path, - name: modelName - } -} - // Creates a Model class name from the last part of the servicePath -export function getModelName (Model) { +export function getModelName(Model) { // If the Model.name has been customized, use it. if (Model.modelName) { return Model.modelName @@ -138,7 +181,19 @@ export function getModelName (Model) { return name } -export function getServicePrefix (servicePath) { +export function registerModel(Model, globalModels, apiPrefix, servicePath) { + const modelName = getModelName(Model) + let path = apiPrefix ? `${apiPrefix}.${modelName}` : modelName + + setByDot(globalModels, path, Model) + globalModels.byServicePath[servicePath] = Model + return { + path, + name: modelName + } +} + +export function getServicePrefix(servicePath) { const parts = servicePath.split('/') let name = parts[parts.length - 1] // name = inflection.underscore(name) @@ -147,7 +202,7 @@ export function getServicePrefix (servicePath) { return name } -export function getServiceCapitalization (servicePath) { +export function getServiceCapitalization(servicePath) { const parts = servicePath.split('/') let name = parts[parts.length - 1] // name = inflection.underscore(name) @@ -156,48 +211,11 @@ export function getServiceCapitalization (servicePath) { return name } -// From feathers-plus/feathers-hooks-common -export function setByDot (obj, path, value, ifDelete) { - if (ifDelete) { - console.log('DEPRECATED. Use deleteByDot instead of setByDot(obj,path,value,true). (setByDot)') - } - - if (path.indexOf('.') === -1) { - obj[path] = value - - if (value === undefined && ifDelete) { - delete obj[path] - } - - return - } - - const parts = path.split('.') - const lastIndex = parts.length - 1 - return parts.reduce( - (obj1, part, i) => { - if (i !== lastIndex) { - if (!obj1.hasOwnProperty(part) || typeof obj1[part] !== 'object') { - obj1[part] = {} - } - return obj1[part] - } - - obj1[part] = value - if (value === undefined && ifDelete) { - delete obj1[part] - } - return obj1 - }, - obj - ) -} - -export function diffFunctions () { +export function diffFunctions() { return diff } -export function updateOriginal (newData, existingItem) { +export function updateOriginal(newData, existingItem) { Object.keys(newData).forEach(key => { const newProp = newData[key] const oldProp = existingItem[key] @@ -210,15 +228,22 @@ export function updateOriginal (newData, existingItem) { // If the old item doesn't already have this property, update it if (!existingItem.hasOwnProperty(key)) { shouldCopyProp = true - // If the old prop is null or undefined, and the new prop is neither - } else if ((oldProp === null || oldProp === undefined) && (newProp !== null && newProp !== undefined)) { + // If the old prop is null or undefined, and the new prop is neither + } else if ( + (oldProp === null || oldProp === undefined) && + (newProp !== null && newProp !== undefined) + ) { shouldCopyProp = true - // If both old and new are arrays + // If both old and new are arrays } else if (Array.isArray(oldProp) && Array.isArray(newProp)) { shouldCopyProp = true } else if (isObject(oldProp)) { shouldCopyProp = true - } else if (oldProp !== newProp && !Array.isArray(oldProp) && !Array.isArray(newProp)) { + } else if ( + oldProp !== newProp && + !Array.isArray(oldProp) && + !Array.isArray(newProp) + ) { shouldCopyProp = true } @@ -231,3 +256,12 @@ export function updateOriginal (newData, existingItem) { } }) } + +export function makeNamespace(servicePath, options) { + const { namespace, nameStyle } = options + const nameStyles = { + short: getShortName, + path: getNameFromPath + } + return namespace || nameStyles[nameStyle](servicePath) +} diff --git a/test/service-module/service-module.test.js b/test/service-module/service-module.test.js index ab5b905d..4b797331 100644 --- a/test/service-module/service-module.test.js +++ b/test/service-module/service-module.test.js @@ -1,6 +1,10 @@ import assert from 'chai/chai' import setupVuexService from '~/src/service-module/service-module' -import { makeFeathersRestClient, feathersRestClient as feathersClient, feathersSocketioClient } from '../fixtures/feathers-client' +import { + makeFeathersRestClient, + feathersRestClient as feathersClient, + feathersSocketioClient +} from '../fixtures/feathers-client' import { stripSlashes } from '../../src/utils' import memory from 'feathers-memory' import { makeTodos } from '../fixtures/todos' @@ -16,8 +20,14 @@ describe('Service Module', () => { const store = new Vuex.Store({ plugins: [service(serviceName)] }) - assert(globalModels.hasOwnProperty('Todo'), 'the Model was added to the globalModels') - assert(feathersService.FeathersVuexModel === globalModels.Todo, 'the Model is also found at service.FeathersVuexModel') + assert( + globalModels.hasOwnProperty('Todo'), + 'the Model was added to the globalModels' + ) + assert( + feathersService.FeathersVuexModel === globalModels.Todo, + 'the Model is also found at service.FeathersVuexModel' + ) const todo = new globalModels.Todo({ description: 'Do the dishes', @@ -28,19 +38,22 @@ describe('Service Module', () => { assert(store.state[serviceName]) }) - describe('Models', function () { - beforeEach(function () { + describe('Models', function() { + beforeEach(function() { const serviceName = 'todos' const store = new Vuex.Store({ plugins: [service(serviceName)] }) assert(store) - assert(globalModels.hasOwnProperty('Todo'), 'the Model was added to the globalModels') - const owners = this.owners = [ + assert( + globalModels.hasOwnProperty('Todo'), + 'the Model was added to the globalModels' + ) + const owners = (this.owners = [ { id: 1, name: 'Marshall' }, { id: 2, name: 'Mariah' }, { id: 3, name: 'Leah' } - ] + ]) const data = { id: 1, description: 'Do the dishes', @@ -55,31 +68,40 @@ describe('Service Module', () => { this.todoClone = todo.clone() }) - it('allows creating model clones', function () { + it('allows creating model clones', function() { const { todoClone } = this assert(todoClone.isClone, 'created a todo clone with isClone attribute') - assert(todoClone instanceof globalModels.Todo, 'the copy is an instance of the same class') + assert( + todoClone instanceof globalModels.Todo, + 'the copy is an instance of the same class' + ) }) - it('allows modifying clones without affecting the original', function () { + it('allows modifying clones without affecting the original', function() { const { todo, todoClone } = this todoClone.description = 'Do something else' - assert(todo.description === 'Do the dishes', 'the original todo remained intact') + assert( + todo.description === 'Do the dishes', + 'the original todo remained intact' + ) }) - it('allows commiting changes back to the original in the store', function () { + it('allows commiting changes back to the original in the store', function() { const { todo, todoClone } = this todoClone.description = 'Do something else' todoClone.commit() - assert(todo.description === 'Do something else', 'the original todo was updated') + assert( + todo.description === 'Do something else', + 'the original todo was updated' + ) }) - it('performs a shallow merge when commiting back to the original record', function () { + it('performs a shallow merge when commiting back to the original record', function() { const { todo, todoClone, owners } = this todoClone.owners = [ @@ -90,10 +112,14 @@ describe('Service Module', () => { todoClone.commit() - assert.deepEqual(todo.owners, [ owners[0], owners[1] ], 'ownerIds were updated properly') + assert.deepEqual( + todo.owners, + [owners[0], owners[1]], + 'ownerIds were updated properly' + ) }) - it(`changes the original record if you don't use the return value of commit()`, function () { + it(`changes the original record if you don't use the return value of commit()`, function() { const { todo, todoClone, owners } = this assert.deepEqual(todo.owners, owners, 'original todo remained unchanged') @@ -101,10 +127,14 @@ describe('Service Module', () => { todoClone.commit() todoClone.owners[0].name = 'Ted' - assert.deepEqual(todo.owners[0].name, 'Ted', 'nested object in original todo was changed') + assert.deepEqual( + todo.owners[0].name, + 'Ted', + 'nested object in original todo was changed' + ) }) - it(`doesn't change the original record if you use modify return value of a commit`, function () { + it(`doesn't change the original record if you use modify return value of a commit`, function() { let { todo, todoClone, owners } = this assert.deepEqual(todo.owners, owners, 'original todo remained unchanged') @@ -112,20 +142,30 @@ describe('Service Module', () => { todoClone = todoClone.commit() todoClone.owners[0].name = 'Ted' - assert.deepEqual(todo.owners[0].name, 'Marshall', 'nested object in original todo was NOT changed') + assert.deepEqual( + todo.owners[0].name, + 'Marshall', + 'nested object in original todo was NOT changed' + ) }) - it('allows reseting copy changes back to match the original', function () { + it('allows reseting copy changes back to match the original', function() { const { todo, todoClone } = this todoClone.description = 'Do something else' todoClone.reset() - assert(todo.description === 'Do the dishes', 'the original todo was untouched') - assert(todoClone.description === 'Do the dishes', 'the clone was reset to match the original') + assert( + todo.description === 'Do the dishes', + 'the original todo was untouched' + ) + assert( + todoClone.description === 'Do the dishes', + 'the clone was reset to match the original' + ) }) - it('adds additional properties to model instances when more data arrives for the same id', function () { + it('adds additional properties to model instances when more data arrives for the same id', function() { const { todo, owners } = this const newData = { id: 1, @@ -138,10 +178,13 @@ describe('Service Module', () => { assert(newTodo === todo, 'the records are the same') assert(newTodo.test === true, 'the new attribute was added') - assert(todo.test === true, 'the new attribute was also added to the original') + assert( + todo.test === true, + 'the new attribute was also added to the original' + ) }) - it('ignores when new data with matching id has fewer props than current record', function () { + it('ignores when new data with matching id has fewer props than current record', function() { const { todo, owners } = this const newData = { id: 1, @@ -150,11 +193,17 @@ describe('Service Module', () => { const newTodo = new todo.constructor(newData) assert(newTodo === todo, 'the records are the same') - assert(todo.description === 'Do the dishes', 'the existing attributes remained in place') - assert(todo.isComplete === false, 'the existing attributes remained in place') + assert( + todo.description === 'Do the dishes', + 'the existing attributes remained in place' + ) + assert( + todo.isComplete === false, + 'the existing attributes remained in place' + ) }) - it('updates the new record when non-null, non-undefined values do not match', function () { + it('updates the new record when non-null, non-undefined values do not match', function() { const { todo, owners } = this const newData = { id: 1, @@ -165,18 +214,21 @@ describe('Service Module', () => { const newTodo = new todo.constructor(newData) assert(newTodo === todo, 'the records are the same') - assert(todo.description === 'Do the mopping', 'non-matching string was updated') + assert( + todo.description === 'Do the mopping', + 'non-matching string was updated' + ) assert(todo.isComplete === true, 'non-matching boolean was updated') }) }) - describe('Models - Default Values', function () { - beforeEach(function () { - const taskDefaults = this.taskDefaults = { + describe('Models - Default Values', function() { + beforeEach(function() { + const taskDefaults = (this.taskDefaults = { id: null, description: '', isComplete: false - } + }) this.store = new Vuex.Store({ plugins: [ service('todos'), @@ -185,12 +237,12 @@ describe('Service Module', () => { firstName: '', lastName: '', location: { - coordinates: [ -111.549668, 39.014 ] + coordinates: [-111.549668, 39.014] }, - get fullName () { + get fullName() { return `${this.firstName} ${this.lastName}` }, - todos ({ store }) { + todos({ store }) { console.log(Object.keys(store)) } } @@ -200,10 +252,10 @@ describe('Service Module', () => { instanceDefaults: taskDefaults }), service('groups', { - instanceDefaults (data, { store, Model, Models }) { + instanceDefaults(data, { store, Model, Models }) { return { name: '', - get todos () { + get todos() { return Models.Todo.findInStore({ query: {} }).data } } @@ -219,14 +271,14 @@ describe('Service Module', () => { // store.commit('todos/addItem', data) - it('models default to an empty object', function () { + it('models default to an empty object', function() { const { Todo } = this const todo = new Todo() assert.deepEqual(todo, {}, 'default model is an empty object') }) - it('setCurrent works on model instances with getters', function () { + it('setCurrent works on model instances with getters', function() { const { Person, store } = this const person = new Person({ id: 1, @@ -235,61 +287,93 @@ describe('Service Module', () => { }) store.commit('people/setCurrent', person) - assert(store.state.people.copy.fullName === 'Al fred', 'setCurrent preserved the getter accessor prop') + assert( + store.state.people.copy.fullName === 'Al fred', + 'setCurrent preserved the getter accessor prop' + ) }) - it('stores clones in Model.copiesById by default', function () { + it('stores clones in Model.copiesById by default', function() { const { Todo } = this const todo = new Todo({ id: 1, description: 'Do something' }) - assert.deepEqual(Todo.copiesById, {}, 'Model.copiesById should start out empty') + assert.deepEqual( + Todo.copiesById, + {}, + 'Model.copiesById should start out empty' + ) const todoClone = todo.clone() - assert(Todo.copiesById[1], 'should have a copy stored on Model.copiesById') + assert( + Todo.copiesById[1], + 'should have a copy stored on Model.copiesById' + ) todoClone.description = 'Do something else' todoClone.commit() - assert.equal(todo.description, 'Do something else', 'the original should have been updated') + assert.equal( + todo.description, + 'Do something else', + 'the original should have been updated' + ) }) - it('allows customizing the default values for a model', function () { + it('allows customizing the default values for a model', function() { const { Task, taskDefaults } = this const task = new Task() - assert.deepEqual(task, taskDefaults, 'the instance had the customized values') + assert.deepEqual( + task, + taskDefaults, + 'the instance had the customized values' + ) }) - it('allows model classes to be customized with es5 getters', function () { + it('allows model classes to be customized with es5 getters', function() { const { Person } = this const person = new Person({ firstName: 'Marshall', lastName: 'Thompson' }) - assert.equal(person.fullName, `Marshall Thompson`, 'the es5 getter returned the correct value') + assert.equal( + person.fullName, + `Marshall Thompson`, + 'the es5 getter returned the correct value' + ) }) - it('instanceDefaults can be a function that receives the store', function () { + it('instanceDefaults can be a function that receives the store', function() { const { Group } = this const group = new Group({ name: 'test' }) - assert(Array.isArray(group.todos), 'instanceDefaults correctly assigned as function') + assert( + Array.isArray(group.todos), + 'instanceDefaults correctly assigned as function' + ) }) - it('does not allow sharing of deeply nested objects between instances', function () { + it('does not allow sharing of deeply nested objects between instances', function() { const { Person } = this - const person1 = new Person({ firstName: 'Marshall', lastName: 'Thompson' }) + const person1 = new Person({ + firstName: 'Marshall', + lastName: 'Thompson' + }) const person2 = new Person({ firstName: 'Austin', lastName: 'Thompson' }) person1.location.coordinates[0] = 5 - assert.equal(person2.location.coordinates[0], -111.549668, 'the value was not shared') + assert.equal( + person2.location.coordinates[0], + -111.549668, + 'the value was not shared' + ) }) - it('keeps the options on the Model', function () { + it('keeps the options on the Model', function() { const { Task, taskDefaults } = this const options = { actions: {}, @@ -315,12 +399,16 @@ describe('Service Module', () => { state: {} } - assert.deepEqual(Task.options, options, 'The Model.options object should be in place') + assert.deepEqual( + Task.options, + options, + 'The Model.options object should be in place' + ) }) }) - describe('Models - Methods', function () { - beforeEach(function () { + describe('Models - Methods', function() { + beforeEach(function() { this.store = new Vuex.Store({ strict: true, plugins: [ @@ -335,51 +423,54 @@ describe('Service Module', () => { this.Task = globalModels.Task }) - it('Model.find', function () { + it('Model.find', function() { const { Todo } = this assert(typeof Todo.find === 'function') }) - it('Model.findInStore', function () { + it('Model.findInStore', function() { const { Todo } = this assert(typeof Todo.findInStore === 'function') }) - it('Model.get', function () { + it('Model.get', function() { const { Todo } = this assert(typeof Todo.get === 'function') }) - it('Model.getFromStore', function () { + it('Model.getFromStore', function() { const { Todo } = this assert(typeof Todo.getFromStore === 'function') }) - it('instance.save calls create with correct arguments', function () { + it('instance.save calls create with correct arguments', function() { const { Todo } = this const todo = new Todo({ test: true }) Object.defineProperty(todo, 'create', { - value (params) { + value(params) { assert(arguments.length === 1, 'should have only called with params') - assert(params === undefined, 'no params should have been passed this time') + assert( + params === undefined, + 'no params should have been passed this time' + ) } }) todo.save() }) - it('instance.save passes params to create', function () { + it('instance.save passes params to create', function() { const { Todo } = this const todo = new Todo({ test: true }) let called = false Object.defineProperty(todo, 'create', { - value (params) { + value(params) { assert(arguments.length === 1, 'should have only called with params') assert(params.test, 'should have received params') called = true @@ -390,13 +481,13 @@ describe('Service Module', () => { assert(called, 'create should have been called') }) - it('instance.save passes params to patch', function () { + it('instance.save passes params to patch', function() { const { Todo } = this const todo = new Todo({ id: 1, test: true }) let called = false Object.defineProperty(todo, 'patch', { - value (params) { + value(params) { assert(arguments.length === 1, 'should have only called with params') assert(params.test, 'should have received params') called = true @@ -407,13 +498,13 @@ describe('Service Module', () => { assert(called, 'patch should have been called') }) - it('instance.save passes params to update', function () { + it('instance.save passes params to update', function() { const { Task } = this const task = new Task({ id: 1, test: true }) let called = false Object.defineProperty(task, 'update', { - value (params) { + value(params) { assert(arguments.length === 1, 'should have only called with params') assert(params.test, 'should have received params') called = true @@ -424,12 +515,12 @@ describe('Service Module', () => { assert(called, 'update should have been called') }) - it('instance.toJSON', function () { + it('instance.toJSON', function() { const { Task } = this const task = new Task({ id: 1, test: true }) Object.defineProperty(task, 'getter', { - get () { + get() { return `got'er` } }) @@ -442,8 +533,8 @@ describe('Service Module', () => { }) }) - describe('Models - modelName', function () { - beforeEach(function () { + describe('Models - modelName', function() { + beforeEach(function() { this.store = new Vuex.Store({ strict: true, plugins: [ @@ -457,14 +548,14 @@ describe('Service Module', () => { this.HotspotMedia = globalModels.HotspotMedia }) - it('allows passing a custom Model name', function () { + it('allows passing a custom Model name', function() { assert(!this.HotspotMedium, `the model wasn't in the default location`) assert(this.HotspotMedia, 'the model is named correctly.') }) }) - describe('Models - Dates', function () { - beforeEach(function () { + describe('Models - Dates', function() { + beforeEach(function() { this.store = new Vuex.Store({ strict: true, plugins: [ @@ -481,7 +572,7 @@ describe('Service Module', () => { this.Todo = globalModels.Todo }) - it('converts keys that contain the Date constructor into date instances', function () { + it('converts keys that contain the Date constructor into date instances', function() { const { Todo } = this const createdAt = '2018-05-01T04:42:24.136Z' const todo = new Todo({ @@ -490,14 +581,23 @@ describe('Service Module', () => { createdAt }) - assert(typeof todo.createdAt === 'object', 'todo.createdAt is an instance of object') - assert(todo.createdAt.constructor.name === 'Date', 'todo.createdAt is an instance of date') - assert(todo.createdAt.toString() === new Date(createdAt).toString(), 'the correct date was used') + assert( + typeof todo.createdAt === 'object', + 'todo.createdAt is an instance of object' + ) + assert( + todo.createdAt.constructor.name === 'Date', + 'todo.createdAt is an instance of date' + ) + assert( + todo.createdAt.toString() === new Date(createdAt).toString(), + 'the correct date was used' + ) }) }) - describe('Models - Relationships', function () { - beforeEach(function () { + describe('Models - Relationships', function() { + beforeEach(function() { this.store = new Vuex.Store({ strict: true, plugins: [ @@ -509,7 +609,7 @@ describe('Service Module', () => { } }), service('todos', { - instanceDefaults (data) { + instanceDefaults(data) { const priority = data.priority || 'normal' const defaultsByPriority = { normal: { @@ -528,17 +628,17 @@ describe('Service Module', () => { } }), service('items', { - instanceDefaults (data, { store, Model, Models }) { + instanceDefaults(data, { store, Model, Models }) { return { test: false, todo: 'Todo', - get todos () { + get todos() { return Models.Todo.findInStore({ query: {} }).data } } }, mutations: { - toggleTestBoolean (state, item) { + toggleTestBoolean(state, item) { item.test = !item.test } } @@ -550,7 +650,7 @@ describe('Service Module', () => { this.Item = globalModels.Item }) - it('can setup relationships through es5 getters in instanceDefaults', function () { + it('can setup relationships through es5 getters in instanceDefaults', function() { const { Item, Todo } = this const todo = new Todo({ id: 5, description: 'hey' }) const item = new Item({}) @@ -559,7 +659,7 @@ describe('Service Module', () => { assert(item.todos[0] === todo, 'The todo was returned through the getter') }) - it('can have different instanceDefaults based on new instance data', function () { + it('can have different instanceDefaults based on new instance data', function() { const { Todo } = this const normalTodo = new Todo({ description: 'Normal' @@ -569,11 +669,17 @@ describe('Service Module', () => { priority: 'high' }) - assert(!normalTodo.hasOwnProperty('isHighPriority'), 'Normal todos do not have an isHighPriority default attribute') - assert(highPriorityTodo.isHighPriority, 'High priority todos have a unique attribute') + assert( + !normalTodo.hasOwnProperty('isHighPriority'), + 'Normal todos do not have an isHighPriority default attribute' + ) + assert( + highPriorityTodo.isHighPriority, + 'High priority todos have a unique attribute' + ) }) - it('converts keys that match Model names into Model instances', function () { + it('converts keys that match Model names into Model instances', function() { const { Todo, store } = this const todo = new Todo({ task: { @@ -582,11 +688,18 @@ describe('Service Module', () => { } }) - assert(todo.task.constructor.className === 'Task', 'task is an instance of Task') - assert.deepEqual(store.state.tasks.keyedById, {}, 'nothing was added to the store') + assert( + todo.task.constructor.className === 'Task', + 'task is an instance of Task' + ) + assert.deepEqual( + store.state.tasks.keyedById, + {}, + 'nothing was added to the store' + ) }) - it('adds model instances containing an id to the store', function () { + it('adds model instances containing an id to the store', function() { const { Todo, store } = this const todo = new Todo({ @@ -597,10 +710,14 @@ describe('Service Module', () => { } }) - assert.deepEqual(store.state.tasks.keyedById[1], todo.task, 'task was added to the store') + assert.deepEqual( + store.state.tasks.keyedById[1], + todo.task, + 'task was added to the store' + ) }) - it('works with multiple keys that match Model names', function () { + it('works with multiple keys that match Model names', function() { const { Todo, store } = this const todo = new Todo({ @@ -615,11 +732,19 @@ describe('Service Module', () => { } }) - assert.deepEqual(store.state.tasks.keyedById[1], todo.task, 'task was added to the store') - assert.deepEqual(store.state.items.keyedById[2], todo.item, 'item was added to the store') + assert.deepEqual( + store.state.tasks.keyedById[1], + todo.task, + 'task was added to the store' + ) + assert.deepEqual( + store.state.items.keyedById[2], + todo.item, + 'item was added to the store' + ) }) - it('handles nested relationships', function () { + it('handles nested relationships', function() { const { Todo } = this const todo = new Todo({ @@ -637,10 +762,13 @@ describe('Service Module', () => { } }) - assert(todo.item.todo.constructor.className === 'Todo', 'the nested todo is an instance of Todo') + assert( + todo.item.todo.constructor.className === 'Todo', + 'the nested todo is an instance of Todo' + ) }) - it('handles recursive nested relationships', function () { + it('handles recursive nested relationships', function() { const { Todo, store } = this const todo = new Todo({ @@ -656,13 +784,21 @@ describe('Service Module', () => { } }) - assert.deepEqual(store.state.todos.keyedById[1], todo, 'todo was added to the store') - assert.deepEqual(store.state.items.keyedById[2], todo.item, 'item was added to the store') + assert.deepEqual( + store.state.todos.keyedById[1], + todo, + 'todo was added to the store' + ) + assert.deepEqual( + store.state.items.keyedById[2], + todo.item, + 'item was added to the store' + ) assert(todo.item, 'todo still has an item') assert(todo.item.todo, 'todo still nested in itself') }) - it('updates related data', function () { + it('updates related data', function() { const { Todo, store } = this const todo = new Todo({ @@ -684,12 +820,20 @@ describe('Service Module', () => { store.commit('items/toggleTestBoolean', storedItem) // todo.item.test = false - assert.equal(todo.item.test, false, 'the nested todo.item.test should be false') - assert.equal(storedTodo.item.test, false, 'the nested item.test should be false') + assert.equal( + todo.item.test, + false, + 'the nested todo.item.test should be false' + ) + assert.equal( + storedTodo.item.test, + false, + 'the nested item.test should be false' + ) assert.equal(storedItem.test, false, 'item.test should be false') }) - it(`allows creating more than once relational instance`, function () { + it(`allows creating more than once relational instance`, function() { const { Todo, store } = this const todo1 = new Todo({ @@ -712,13 +856,25 @@ describe('Service Module', () => { const storedTodo = store.state.todos.keyedById['todo-2'] const storedItem = store.state.items.keyedById['item-3'] - assert.equal(todo1.item.test, true, 'the nested todo.item.test should be true') - assert.equal(todo2.item.test, true, 'the nested todo.item.test should be true') - assert.equal(storedTodo.item.test, true, 'the nested item.test should be true') + assert.equal( + todo1.item.test, + true, + 'the nested todo.item.test should be true' + ) + assert.equal( + todo2.item.test, + true, + 'the nested todo.item.test should be true' + ) + assert.equal( + storedTodo.item.test, + true, + 'the nested item.test should be true' + ) assert.equal(storedItem.test, true, 'item.test should be true') }) - it(`handles arrays of related data`, function () { + it(`handles arrays of related data`, function() { const { Todo, store } = this const todo1 = new Todo({ @@ -728,7 +884,8 @@ describe('Service Module', () => { { id: 'item-1', test: true - }, { + }, + { id: 'item-2', test: true } @@ -741,7 +898,8 @@ describe('Service Module', () => { { id: 'item-3', test: true - }, { + }, + { id: 'item-4', test: true } @@ -770,10 +928,7 @@ describe('Service Module', () => { describe('Setting Up', () => { it('service stores have global defaults', () => { const store = new Vuex.Store({ - plugins: [ - service('tasks'), - service('/v2/todos') - ] + plugins: [service('tasks'), service('/v2/todos')] }) const { state } = store @@ -782,47 +937,48 @@ describe('Service Module', () => { assert(state.todos, 'uses `short` nameStyle by default') }) - it('can customize the idField for each service', function () { + it('can customize the idField for each service', function() { const idField = '_id' const store = new Vuex.Store({ - plugins: [ - service('tests', { idField }) - ] + plugins: [service('tests', { idField })] }) - assert(store.state.tests.idField === idField, 'the idField was properly set') + assert( + store.state.tests.idField === idField, + 'the idField was properly set' + ) }) - it('allows enabling autoRemove', function () { + it('allows enabling autoRemove', function() { const autoRemove = true const store = new Vuex.Store({ - plugins: [ - service('tests', { autoRemove }) - ] + plugins: [service('tests', { autoRemove })] }) - assert(store.state.tests.autoRemove === autoRemove, 'the autoRemove was enabled') + assert( + store.state.tests.autoRemove === autoRemove, + 'the autoRemove was enabled' + ) }) it('can switch to path name as namespace', () => { const nameStyle = 'path' const serviceName = '/v1/tests' const store = new Vuex.Store({ - plugins: [ - service(serviceName, { nameStyle }) - ] + plugins: [service(serviceName, { nameStyle })] }) const namespace = stripSlashes(serviceName) - assert(store.state[namespace], 'the full path name was used as a namespace') + assert( + store.state[namespace], + 'the full path name was used as a namespace' + ) }) it('can explicitly provide a namespace', () => { const namespace = 'blah' const store = new Vuex.Store({ - plugins: [ - service('/v1/tests', { namespace }) - ] + plugins: [service('/v1/tests', { namespace })] }) assert(store.state.blah, 'the namespace option was used as the namespace') }) @@ -831,16 +987,14 @@ describe('Service Module', () => { const namespace = 'blah' const nameStyle = 'path' const store = new Vuex.Store({ - plugins: [ - service('/v1/tests', { namespace, nameStyle }) - ] + plugins: [service('/v1/tests', { namespace, nameStyle })] }) assert(store.state.blah, 'the namespace option was used as the namespace') }) }) describe('Basics', () => { - beforeEach(function () { + beforeEach(function() { this.feathersClient = makeFeathersRestClient() this.feathersClient.use('todos', memory({ store: makeTodos() })) this.service = setupVuexService(this.feathersClient) @@ -848,9 +1002,7 @@ describe('Service Module', () => { it('populates default store', () => { const store = new Vuex.Store({ - plugins: [ - service('todos') - ] + plugins: [service('todos')] }) const todoState = store.state.todos const expectedState = { @@ -888,34 +1040,40 @@ describe('Service Module', () => { whitelist: [] } - assert.deepEqual(todoState, expectedState, 'the expected state was returned') + assert.deepEqual( + todoState, + expectedState, + 'the expected state was returned' + ) }) - it('throws an error if first arg is not a string', function () { + it('throws an error if first arg is not a string', function() { const { service } = this try { - new Vuex.Store({ // eslint-disable-line no-new - plugins: [ - service({}) - ] + new Vuex.Store({ + // eslint-disable-line no-new + plugins: [service({})] }) } catch (error) { - assert(error.message === 'The first argument to setup a feathers-vuex service must be a string', 'threw an error') + assert( + error.message === + 'The first argument to setup a feathers-vuex service must be a string', + 'threw an error' + ) } }) - it(`populates items on find`, function (done) { + it(`populates items on find`, function(done) { const store = new Vuex.Store({ - plugins: [ - this.service('todos', { idField: '_id' }) - ] + plugins: [this.service('todos', { idField: '_id' })] }) const todoState = store.state.todos assert(todoState.ids.length === 0) - store.dispatch('todos/find', { query: {} }) + store + .dispatch('todos/find', { query: {} }) .then(todos => { assert(todoState.ids.length === 3) done() @@ -926,27 +1084,31 @@ describe('Service Module', () => { }) }) - describe('Auto-remove items', function () { - beforeEach(function () { + describe('Auto-remove items', function() { + beforeEach(function() { this.feathersClient = makeFeathersRestClient() - this.feathersClient.use('todos', memory({ - store: makeTodos() - })) - this.feathersClient.use('tasks', memory({ - store: makeTodos(), - paginate: { - default: 10, - max: 50 - } - })) + this.feathersClient.use( + 'todos', + memory({ + store: makeTodos() + }) + ) + this.feathersClient.use( + 'tasks', + memory({ + store: makeTodos(), + paginate: { + default: 10, + max: 50 + } + }) + ) this.service = setupVuexService(this.feathersClient) }) - it(`removes missing items when pagination is off`, function (done) { + it(`removes missing items when pagination is off`, function(done) { const store = new Vuex.Store({ - plugins: [ - this.service('todos', { idField: '_id', autoRemove: true }) - ] + plugins: [this.service('todos', { idField: '_id', autoRemove: true })] }) const todoState = store.state.todos @@ -954,18 +1116,25 @@ describe('Service Module', () => { assert(todoState.ids.length === 0) // Load some data into the store - store.dispatch('todos/find', { query: {} }) + store + .dispatch('todos/find', { query: {} }) .then(todos => { // Remove the third item from the service delete this.feathersClient.service('todos').store[3] // We went around using the store actions, so there will still be three items. - assert(todoState.ids.length === 3, 'there are still three items in the store') + assert( + todoState.ids.length === 3, + 'there are still three items in the store' + ) // Perform the same query again return store.dispatch('todos/find', { query: {} }) }) .then(todos => { - assert(todoState.ids.length === 2, 'there are now two items in the store') + assert( + todoState.ids.length === 2, + 'there are now two items in the store' + ) done() }) .catch(error => { @@ -974,11 +1143,9 @@ describe('Service Module', () => { }) }) - it(`does not remove missing items when pagination is on`, function (done) { + it(`does not remove missing items when pagination is on`, function(done) { const store = new Vuex.Store({ - plugins: [ - this.service('tasks', { idField: '_id', autoRemove: true }) - ] + plugins: [this.service('tasks', { idField: '_id', autoRemove: true })] }) const taskState = store.state.tasks @@ -986,19 +1153,26 @@ describe('Service Module', () => { assert(taskState.ids.length === 0) // Load some data into the store - store.dispatch('tasks/find', { query: {} }) + store + .dispatch('tasks/find', { query: {} }) .then(todos => { // Remove the third item from the service delete this.feathersClient.service('tasks').store[3] // We went around using the store actions, so there will still be three items. - assert(taskState.ids.length === 3, 'there are still three items in the store') + assert( + taskState.ids.length === 3, + 'there are still three items in the store' + ) // Perform the same query again return store.dispatch('tasks/find', { query: {} }) }) .then(todos => { assert(todos.hasOwnProperty('total'), 'pagination is on') - assert(taskState.ids.length === 3, 'there are still three items in the store') + assert( + taskState.ids.length === 3, + 'there are still three items in the store' + ) done() }) .catch(error => { @@ -1007,7 +1181,7 @@ describe('Service Module', () => { }) }) - it(`does not remove missing items when autoRemove is off`, function (done) { + it(`does not remove missing items when autoRemove is off`, function(done) { const store = new Vuex.Store({ plugins: [ this.service('todos', { idField: '_id', autoRemove: false }) @@ -1018,18 +1192,25 @@ describe('Service Module', () => { assert(todoState.ids.length === 0) // Load some data into the store - store.dispatch('todos/find', { query: {} }) + store + .dispatch('todos/find', { query: {} }) .then(todos => { // Remove the third item from the service delete this.feathersClient.service('todos').store[3] // We went around using the store actions, so there will still be three items. - assert(todoState.ids.length === 3, 'there are still three items in the store') + assert( + todoState.ids.length === 3, + 'there are still three items in the store' + ) // Perform the same query again return store.dispatch('todos/find', { query: {} }) }) .then(todos => { - assert(todoState.ids.length === 3, 'there are still three items in the store') + assert( + todoState.ids.length === 3, + 'there are still three items in the store' + ) done() }) .catch(error => { @@ -1040,8 +1221,8 @@ describe('Service Module', () => { }) }) - describe('Customizing Service Stores', function () { - it('allows adding custom state', function () { + describe('Customizing Service Stores', function() { + it('allows adding custom state', function() { const customState = { test: true, test2: { @@ -1049,67 +1230,65 @@ describe('Service Module', () => { } } const store = new Vuex.Store({ - plugins: [ - service('todos', { state: customState }) - ] + plugins: [service('todos', { state: customState })] }) assert(store.state.todos.test === true, 'added custom state') assert(store.state.todos.test2.test === true, 'added custom state') }) - it('allows custom mutations', function () { + it('allows custom mutations', function() { const state = { test: true } const customMutations = { - setTestToFalse (state) { + setTestToFalse(state) { state.test = false } } const store = new Vuex.Store({ - plugins: [ - service('todos', { state, mutations: customMutations }) - ] + plugins: [service('todos', { state, mutations: customMutations })] }) store.commit('todos/setTestToFalse') - assert(store.state.todos.test === false, 'the custom state was modified by the custom mutation') + assert( + store.state.todos.test === false, + 'the custom state was modified by the custom mutation' + ) }) - it('allows custom getters', function () { + it('allows custom getters', function() { const customGetters = { - oneTwoThree (state) { + oneTwoThree(state) { return 123 } } const store = new Vuex.Store({ - plugins: [ - service('todos', { getters: customGetters }) - ] + plugins: [service('todos', { getters: customGetters })] }) - assert(store.getters['todos/oneTwoThree'] === 123, 'the custom getter was available') + assert( + store.getters['todos/oneTwoThree'] === 123, + 'the custom getter was available' + ) }) - it('allows adding custom actions', function () { + it('allows adding custom actions', function() { const config = { state: { isTrue: false }, mutations: { - setToTrue (state) { + setToTrue(state) { state.isTrue = true } }, actions: { - trigger (context) { + trigger(context) { context.commit('setToTrue') } } } const store = new Vuex.Store({ - plugins: [ - service('todos', config) - ] + plugins: [service('todos', config)] }) store.dispatch('todos/trigger') @@ -1117,69 +1296,73 @@ describe('Service Module', () => { }) }) - describe.skip('Updates the Store on Events', function () { + describe.skip('Updates the Store on Events', function() { const socketService = setupVuexService(feathersSocketioClient) - it('created', function (done) { + it('created', function(done) { const store = new Vuex.Store({ - plugins: [ - socketService('things') - ] + plugins: [socketService('things')] }) feathersSocketioClient.service('things').on('created', item => { - assert(store.state.things.keyedById[0].test, 'the item received from the socket event was added to the store') + assert( + store.state.things.keyedById[0].test, + 'the item received from the socket event was added to the store' + ) done() }) feathersSocketioClient.service('things').create({ test: true }) }) - it('patched', function (done) { + it('patched', function(done) { const store = new Vuex.Store({ - plugins: [ - socketService('things') - ] + plugins: [socketService('things')] }) store.commit('things/addItem', { id: 1, test: false }) feathersSocketioClient.service('things').on('patched', item => { - assert(store.state.things.keyedById[1].test, 'the item received from the socket event was updated in the store') + assert( + store.state.things.keyedById[1].test, + 'the item received from the socket event was updated in the store' + ) done() }) feathersSocketioClient.service('things').patch(1, { test: true }) }) - it('updated', function (done) { + it('updated', function(done) { const store = new Vuex.Store({ - plugins: [ - socketService('things') - ] + plugins: [socketService('things')] }) store.commit('things/addItem', { id: 1, test: false }) feathersSocketioClient.service('things').on('updated', item => { - assert(store.state.things.keyedById[1].test, 'the item received from the socket event was updated in the store') + assert( + store.state.things.keyedById[1].test, + 'the item received from the socket event was updated in the store' + ) done() }) feathersSocketioClient.service('things').update(1, { test: true }) }) - it('removed', function (done) { + it('removed', function(done) { const store = new Vuex.Store({ - plugins: [ - socketService('things') - ] + plugins: [socketService('things')] }) store.commit('things/addItem', { id: 1, test: false }) feathersSocketioClient.service('things').on('removed', item => { - assert(!store.state.things.keyedById[1], 'the item received from the socket event was removed from the store') + assert( + !store.state.things.keyedById[1], + 'the item received from the socket event was removed from the store' + ) done() }) diff --git a/tsconfig.json b/tsconfig.json index 03d0466c..0056a28e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,8 @@ { "compilerOptions": { - + "allowJs": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true }, "include": [ "src/**/*" From 9a615d4d0dbd5c582a448816baeb57bd9abebadd Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 11:06:20 -0600 Subject: [PATCH 005/404] Define types for options --- src/service-module/model/model.ts | 148 ++++++++-------- src/service-module/model/notes.md | 8 +- src/service-module/new-api/make-model.ts | 163 +++++++++++++++++- .../new-api/make-service-plugin.ts | 14 +- src/service-module/new-api/model.test.ts | 3 + src/service-module/new-api/types.ts | 17 ++ src/service-module/service-module.js | 81 --------- 7 files changed, 263 insertions(+), 171 deletions(-) create mode 100644 src/service-module/new-api/types.ts diff --git a/src/service-module/model/model.ts b/src/service-module/model/model.ts index 9e4452e4..8ebc8469 100644 --- a/src/service-module/model/model.ts +++ b/src/service-module/model/model.ts @@ -56,80 +56,80 @@ function makeModel(options: FeathersVuexModelOptions) { public constructor() {} - public clone() { - if (this.isClone) { - throw new Error('You cannot clone a copy') - } - const id = this[FeathersVuexModel.idField] - - return this._clone(id) - } - public _clone(id) {} - - public reset() { - if (this.isClone) { - const id = this[FeathersVuexModel.idField] - this._reset(id) - } else { - throw new Error('You cannot reset a non-copy') - } - } - public _reset(id: string) {} - - public commit() { - if (this.isClone) { - const id = this[FeathersVuexModel.idField] - return this._commit(id) - } else { - throw new Error('You cannnot call commit on a non-copy') - } - } - public _commit(id) {} - - public save(params) { - if (this[idField]) { - return preferUpdate ? this.update(params) : this.patch(params) - } else { - return this.create(params) - } - } - - public create(params) { - const data = Object.assign({}, this) - if (data[idField] === null) { - delete data[idField] - } - // return store.dispatch(`${namespace}/create`, [data, params]) - // return this._create(data, params) - } - public _create(data, params) {} - - public patch(params) { - if (!this[idField]) { - const error = new Error( - `Missing ${idField} property. You must create the data before you can patch with this data` - ) - return Promise.reject(error) - } - // return this._patch(this[idField], this, params) - } - public _patch(idField: string) {} - - public update(params) { - if (!this[idField]) { - const error = new Error( - `Missing ${idField} property. You must create the data before you can update with this data` - ) - return Promise.reject(error) - } - // return this._update(this[idField], this, params) - } - public _update() {} - - public remove(params) { - // return this._remove(this[idField], params) - } - public _remove() {} + // public clone() { + // if (this.isClone) { + // throw new Error('You cannot clone a copy') + // } + // const id = this[FeathersVuexModel.idField] + + // return this._clone(id) + // } + // public _clone(id) {} + + // public reset() { + // if (this.isClone) { + // const id = this[FeathersVuexModel.idField] + // this._reset(id) + // } else { + // throw new Error('You cannot reset a non-copy') + // } + // } + // public _reset(id: string) {} + + // public commit() { + // if (this.isClone) { + // const id = this[FeathersVuexModel.idField] + // return this._commit(id) + // } else { + // throw new Error('You cannnot call commit on a non-copy') + // } + // } + // public _commit(id) {} + + // public save(params) { + // if (this[idField]) { + // return preferUpdate ? this.update(params) : this.patch(params) + // } else { + // return this.create(params) + // } + // } + + // public create(params) { + // const data = Object.assign({}, this) + // if (data[idField] === null) { + // delete data[idField] + // } + // // return store.dispatch(`${namespace}/create`, [data, params]) + // // return this._create(data, params) + // } + // public _create(data, params) {} + + // public patch(params) { + // if (!this[idField]) { + // const error = new Error( + // `Missing ${idField} property. You must create the data before you can patch with this data` + // ) + // return Promise.reject(error) + // } + // // return this._patch(this[idField], this, params) + // } + // public _patch(idField: string) {} + + // public update(params) { + // if (!this[idField]) { + // const error = new Error( + // `Missing ${idField} property. You must create the data before you can update with this data` + // ) + // return Promise.reject(error) + // } + // // return this._update(this[idField], this, params) + // } + // public _update() {} + + // public remove(params) { + // // return this._remove(this[idField], params) + // } + // public _remove() {} public toJSON() { return merge({}, this) diff --git a/src/service-module/model/notes.md b/src/service-module/model/notes.md index db953da3..e872c1ef 100644 --- a/src/service-module/model/notes.md +++ b/src/service-module/model/notes.md @@ -5,9 +5,9 @@ import feathers from './feathers-client' import Vuex from 'vuex' import feathersVuex from 'feathers-vuex' -const { makeServicePlugin, BaseModel, addModel } = feathersVuex(feathers, { +const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { idField: '_id', - serverAlias: 'default' + serverAlias: 'myApiServer' }) // @service('todos') @@ -20,8 +20,6 @@ class Todo extends BaseModel { } } -addModel(Todo) - const servicePath = 'todos' const todos = makeServicePlugin({ servicePath, @@ -34,4 +32,4 @@ const store = new Vuex.Store({ todos ] }) -``` \ No newline at end of file +``` diff --git a/src/service-module/new-api/make-model.ts b/src/service-module/new-api/make-model.ts index f9ac2bc1..745a0fac 100644 --- a/src/service-module/new-api/make-model.ts +++ b/src/service-module/new-api/make-model.ts @@ -3,17 +3,27 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ +import { GlobalOptions } from './types' import globalModels from './global-models' +import { getNamespace } from '../../utils' import Vue from 'vue' -export default function makeModel(options) { +/** + * + * @param options + */ +export default function makeModel(options: GlobalOptions) { abstract class FeathersVuexModel { abstract servicePath: string + + // Monkey patched onto the Model class in `makeServicePlugin()` + public static namespace: string + public static store: Record + public static idField: string = options.idField public static models = globalModels // Can access other Models here public static copiesById = {} public static serverAlias: string = options.serverAlias - public static store: Record protected isClone: boolean public _data: Record @@ -25,13 +35,57 @@ export default function makeModel(options) { return record[FeathersVuexModel.idField] } + public static getNamespace() { + // return ( + // FeathersVuexModel.namespace || + // getNamespace(FeathersVuexModel.servicePath, options.nameStyle) + // ) + } + + public static find(params) { + return FeathersVuexModel.store.dispatch( + `${options.namespace}/find`, + params + ) + } + + public static findInStore(params) { + return FeathersVuexModel.store.getters[`${options.namespace}/find`]( + params + ) + } + + public static get(id, params) { + const { store } = FeathersVuexModel + if (params) { + return store.dispatch(`${options.namespace}/get`, [id, params]) + } else { + return store.dispatch(`${options.namespace}/get`, id) + } + } + + public static getFromStore(id, params) { + const { store } = FeathersVuexModel + if (params) { + return store.getters[`${options.namespace}/get`]([id, params]) + } else { + return store.getters[`${options.namespace}/get`](id) + } + } + + /** + * Use the `createCopy` mutation to clone the current record. Return the + * clone + */ public clone() { - const { store, copiesById } = FeathersVuexModel if (this.isClone) { throw new Error('You cannot clone a copy') } const id = this[FeathersVuexModel.idField] - + this._clone(id) + } + private _clone(id) { + const { store, copiesById } = FeathersVuexModel store.commit(`${options.namespace}/createCopy`, id) if (store.state[options.namespace].keepCopiesInStore) { @@ -40,6 +94,107 @@ export default function makeModel(options) { return copiesById[id] } } + + /** + * Reset a clone to match the instance in the store. + */ + public reset() { + if (this.isClone) { + const id = this[FeathersVuexModel.idField] + FeathersVuexModel.store.commit(`${options.namespace}/rejectCopy`, id) + } else { + throw new Error('You cannot reset a non-copy') + } + } + + /** + * Update a store instance to match a clone. + */ + public commit() { + if (this.isClone) { + const id = this[FeathersVuexModel.idField] + FeathersVuexModel.store.commit(`${options.namespace}/commitCopy`, id) + + return this._clone(id) + } else { + throw new Error('You cannnot call commit on a non-copy') + } + } + + /** + * A shortcut to either call create or patch/update + * @param params + */ + public save(params) { + if (this[options.idField]) { + return options.preferUpdate ? this.update(params) : this.patch(params) + } else { + return this.create(params) + } + } + /** + * Calls service create with the current instance data + * @param params + */ + public create(params) { + const { store } = FeathersVuexModel + const data = Object.assign({}, this) + if (data[options.idField] === null) { + delete data[options.idField] + } + return store.dispatch(`${options.namespace}/create`, [data, params]) + } + + /** + * Calls service patch with the current instance data + * @param params + */ + public patch(params) { + if (!this[options.idField]) { + const error = new Error( + `Missing ${ + options.idField + } property. You must create the data before you can patch with this data` + ) + return Promise.reject(error) + } + return FeathersVuexModel.store.dispatch(`${options.namespace}/patch`, [ + this[options.idField], + this, + params + ]) + } + + /** + * Calls service update with the current instance data + * @param params + */ + public update(params) { + if (!this[options.idField]) { + const error = new Error( + `Missing ${ + options.idField + } property. You must create the data before you can update with this data` + ) + return Promise.reject(error) + } + return FeathersVuexModel.store.dispatch(`${options.namespace}/update`, [ + this[options.idField], + this, + params + ]) + } + + /** + * Calls service remove with the current instance id + * @param params + */ + public remove(params) { + return FeathersVuexModel.store.dispatch(`${options.namespace}/remove`, [ + this[options.idField], + params + ]) + } } return FeathersVuexModel } diff --git a/src/service-module/new-api/make-service-plugin.ts b/src/service-module/new-api/make-service-plugin.ts index 5a55aa52..aa573e9b 100644 --- a/src/service-module/new-api/make-service-plugin.ts +++ b/src/service-module/new-api/make-service-plugin.ts @@ -3,25 +3,25 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ +import { GlobalOptions, MakeServicePluginOptions } from './types' import makeServiceModule from './make-service-module' -import { makeNamespace } from '../../utils' +import { getNamespace } from '../../utils' /** * prepare only wraps the makeServicePlugin to provide the globalOptions. * @param globalOptions */ -export default function prepareMakeServicePlugin(globalOptions) { +export default function prepareMakeServicePlugin(globalOptions: GlobalOptions) { /** * Make a Vuex plugin for the provided service. It also attaches the vuex * store to the provided Model instance. */ - return function makeServicePlugin(required, options?) { - options = Object.assign({}, globalOptions, options) - const { servicePath, Model, service } = required - const { namespace, nameStyle } = options + return function makeServicePlugin(config) { + const options = Object.assign({}, globalOptions, config) + const { servicePath, Model, service, namespace, nameStyle } = options return store => { - options.namespace = makeNamespace(servicePath, { nameStyle, namespace }) + options.namespace = namespace || getNamespace(servicePath, nameStyle) const module = makeServiceModule(service, options) store.registerModule(options.namespace, module) Model.store = store diff --git a/src/service-module/new-api/model.test.ts b/src/service-module/new-api/model.test.ts index bc804687..e62996c1 100644 --- a/src/service-module/new-api/model.test.ts +++ b/src/service-module/new-api/model.test.ts @@ -52,7 +52,10 @@ it('allows accessing other models', function() { super(data) } } + + // TODO: move this into makeServicePlugin addModel(Todo) + const todosPlugin = makeServicePlugin({ servicePath, Model: Todo, diff --git a/src/service-module/new-api/types.ts b/src/service-module/new-api/types.ts new file mode 100644 index 00000000..f505acf2 --- /dev/null +++ b/src/service-module/new-api/types.ts @@ -0,0 +1,17 @@ +/* +eslint +@typescript-eslint/no-explicit-any: 0 +*/ +export interface GlobalOptions { + serverAlias: string + idField?: string +} + +export interface MakeServicePluginOptions { + servicePath: string + Model: any + service: any + namespace?: string +} + +export interface MakeModelOptions extends GlobalOptions {} diff --git a/src/service-module/service-module.js b/src/service-module/service-module.js index 97ce3131..6fb089b1 100644 --- a/src/service-module/service-module.js +++ b/src/service-module/service-module.js @@ -132,87 +132,6 @@ export default function servicePluginInit( module.state.modelName = modelInfo.path store.registerModule(namespace, module) - Object.defineProperties(Model, { - className: { - value: modelInfo.name - }, - find: { - value(params) { - return store.dispatch(`${namespace}/find`, params) - } - }, - findInStore: { - value(params) { - return store.getters[`${namespace}/find`](params) - } - }, - get: { - value(id, params) { - if (params) { - return store.dispatch(`${namespace}/get`, [id, params]) - } else { - return store.dispatch(`${namespace}/get`, id) - } - } - }, - getFromStore: { - value(id, params) { - if (params) { - return store.getters[`${namespace}/get`]([id, params]) - } else { - return store.getters[`${namespace}/get`](id) - } - } - } - }) - - // Upgrade the Model's API methods to use the store.actions - Object.defineProperties(Model.prototype, { - _clone: { - value(id) { - store.commit(`${namespace}/createCopy`, id) - - if (store.state[namespace].keepCopiesInStore) { - return store.getters[`${namespace}/getCopyById`](id) - } else { - return Model.copiesById[id] - } - } - }, - _commit: { - value(id) { - store.commit(`${namespace}/commitCopy`, id) - - return this._clone(id) - } - }, - _reset: { - value(id) { - store.commit(`${namespace}/rejectCopy`, id) - } - }, - _create: { - value(data, params) { - return store.dispatch(`${namespace}/create`, [data, params]) - } - }, - _patch: { - value(id, data, params) { - return store.dispatch(`${namespace}/patch`, [id, data, params]) - } - }, - _update: { - value(id, data, params) { - return store.dispatch(`${namespace}/update`, [id, data, params]) - } - }, - _remove: { - value(id, params) { - return store.dispatch(`${namespace}/remove`, [id, params]) - } - } - }) - if (options.enableEvents) { // Listen to socket events when available. service.on('created', item => From fac6929df19bce94e89c09216e2063291b89793a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 14:39:50 -0600 Subject: [PATCH 006/404] Test BaseModel, including multiple APIs --- .../model/model.global-models.ts | 3 - ...odule.ts => model.make-service-module.old} | 2 +- ...ice-module.ts => model.service-module.old} | 2 +- src/service-module/model/model.test.ts | 55 ----- src/service-module/model/model.tests.html | 11 - src/service-module/model/model.ts | 167 --------------- src/service-module/new-api/add-model.ts | 3 +- src/service-module/new-api/index.ts | 8 +- src/service-module/new-api/make-model.ts | 99 +++++---- .../new-api/make-service-plugin.test.ts | 7 - .../new-api/make-service-plugin.ts | 35 ++- src/service-module/new-api/model.test.ts | 200 ++++++++++++++---- .../{model => new-api}/notes.md | 6 - src/service-module/new-api/types.ts | 12 +- src/utils.ts | 12 +- test/fixtures/feathers-client.js | 12 +- tsconfig.json | 3 +- 17 files changed, 264 insertions(+), 373 deletions(-) delete mode 100644 src/service-module/model/model.global-models.ts rename src/service-module/model/{model.make-service-module.ts => model.make-service-module.old} (97%) rename src/service-module/model/{model.service-module.ts => model.service-module.old} (99%) delete mode 100644 src/service-module/model/model.test.ts delete mode 100644 src/service-module/model/model.tests.html delete mode 100644 src/service-module/model/model.ts rename src/service-module/{model => new-api}/notes.md (82%) diff --git a/src/service-module/model/model.global-models.ts b/src/service-module/model/model.global-models.ts deleted file mode 100644 index 2930db75..00000000 --- a/src/service-module/model/model.global-models.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default { - byServicePath: {} -} diff --git a/src/service-module/model/model.make-service-module.ts b/src/service-module/model/model.make-service-module.old similarity index 97% rename from src/service-module/model/model.make-service-module.ts rename to src/service-module/model/model.make-service-module.old index 99376dce..aa3f3094 100644 --- a/src/service-module/model/model.make-service-module.ts +++ b/src/service-module/model/model.make-service-module.old @@ -4,7 +4,7 @@ eslint @typescript-eslint/no-explicit-any: 0 */ // import { Module } from 'vuex' -import globalModels from './model.global-models' +const globalModels = {} function makeState(servicePath, stateOptions) {} function makeGetters(servicePath) {} function makeMutations(servicePath, options) {} diff --git a/src/service-module/model/model.service-module.ts b/src/service-module/model/model.service-module.old similarity index 99% rename from src/service-module/model/model.service-module.ts rename to src/service-module/model/model.service-module.old index 54fcc4e9..6fd60b14 100644 --- a/src/service-module/model/model.service-module.ts +++ b/src/service-module/model/model.service-module.old @@ -5,8 +5,8 @@ eslint */ import { getShortName, getNameFromPath, registerModel } from '../../utils' import makeServiceModule from './model.make-service-module' -import makeModel from './model' +function makeModel(options) {} interface GlobalModels { byServicePath?: Record } diff --git a/src/service-module/model/model.test.ts b/src/service-module/model/model.test.ts deleted file mode 100644 index 19fd9577..00000000 --- a/src/service-module/model/model.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { assert } from 'chai' -import Vuex from 'vuex' -import servicePluginInit from './model.service-module' -import { - makeFeathersRestClient, - feathersRestClient as feathersClient, - feathersSocketioClient -} from '../../../test/fixtures/feathers-client' -import makeModel from './model' - -const globalModels = {} -const service = servicePluginInit(feathersClient, {}, globalModels) - -describe.skip('makeModel', function() { - it('registers a vuex plugin and Model for the service', () => { - const serviceName = 'todos' - const feathersService = feathersClient.service(serviceName) - const store = new Vuex.Store({ - plugins: [service(serviceName)] - }) - assert( - globalModels.hasOwnProperty('Todo'), - 'the Model was added to the globalModels' - ) - // assert( - // feathersService.FeathersVuexModel === globalModels.Todo, - // 'the Model is also found at service.FeathersVuexModel' - // ) - - // const todo = new globalModels.Todo({ - // description: 'Do the dishes', - // isComplete: false - // }) - // assert(todo instanceof globalModels.Todo, 'Model can be instantiated.') - - // assert(store.state[serviceName]) - }) - - it('creating FeathersVuexModel', function() { - const FeathersVuexModel = makeModel({ - store: {} - }) - - assert(FeathersVuexModel.idField === 'id') - }) - - it('customizing FeathersVuexModel', function() { - const FeathersVuexModel = makeModel({ - idField: '_id', - store: {} - }) - - assert(FeathersVuexModel.idField === '_id') - }) -}) diff --git a/src/service-module/model/model.tests.html b/src/service-module/model/model.tests.html deleted file mode 100644 index 6d676d85..00000000 --- a/src/service-module/model/model.tests.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - Model tests (Feathers-Vuex) - - - - - - - \ No newline at end of file diff --git a/src/service-module/model/model.ts b/src/service-module/model/model.ts deleted file mode 100644 index 8ebc8469..00000000 --- a/src/service-module/model/model.ts +++ /dev/null @@ -1,167 +0,0 @@ -/* -eslint -@typescript-eslint/explicit-function-return-type: 0, -@typescript-eslint/no-explicit-any: 0 -*/ -import fastCopy from 'fast-copy' -import isPlainObject from 'lodash.isplainobject' -import merge from 'lodash.merge' -import { getShortName, getNameFromPath } from '../../utils' -// import { updateOriginal } from '../../utils' - -const defaults = { - idField: 'id', - nameStyle: 'short', - preferUpdate: false, - instanceDefaults: {} -} - -interface FeathersVuexModelOptions { - idField?: string - preferUpdate?: boolean - nameStyle?: string - namespace?: string - store: any -} - -function makeModel(options: FeathersVuexModelOptions) { - options = Object.assign({}, defaults, options) - const { idField, preferUpdate, nameStyle, store } = options - let { namespace } = options - const nameStyles = { - short: getShortName, - path: getNameFromPath - } - const servicePath = 'test' - namespace = namespace || nameStyles[nameStyle](servicePath) - - return class FeathersVuexModel { - protected isClone: boolean - - // static copiesById: Object - public static idField: string = idField - // static instanceDefaults: Object - // public static modelName: string - // public static options: FeathersVuexModelOptions - public static preferUpdate: boolean = preferUpdate - private static globalModels: Record - protected static nameStyle = nameStyle - public static namespace: string = namespace - public static store: any = store - - // public static getFromStore(id: string) {} - public static getId(record: Record): string { - return record[FeathersVuexModel.idField] - } - - public constructor() {} - - // public clone() { - // if (this.isClone) { - // throw new Error('You cannot clone a copy') - // } - // const id = this[FeathersVuexModel.idField] - - // return this._clone(id) - // } - // public _clone(id) {} - - // public reset() { - // if (this.isClone) { - // const id = this[FeathersVuexModel.idField] - // this._reset(id) - // } else { - // throw new Error('You cannot reset a non-copy') - // } - // } - // public _reset(id: string) {} - - // public commit() { - // if (this.isClone) { - // const id = this[FeathersVuexModel.idField] - // return this._commit(id) - // } else { - // throw new Error('You cannnot call commit on a non-copy') - // } - // } - // public _commit(id) {} - - // public save(params) { - // if (this[idField]) { - // return preferUpdate ? this.update(params) : this.patch(params) - // } else { - // return this.create(params) - // } - // } - - // public create(params) { - // const data = Object.assign({}, this) - // if (data[idField] === null) { - // delete data[idField] - // } - // // return store.dispatch(`${namespace}/create`, [data, params]) - // // return this._create(data, params) - // } - // public _create(data, params) {} - - // public patch(params) { - // if (!this[idField]) { - // const error = new Error( - // `Missing ${idField} property. You must create the data before you can patch with this data` - // ) - // return Promise.reject(error) - // } - // // return this._patch(this[idField], this, params) - // } - // public _patch(idField: string) {} - - // public update(params) { - // if (!this[idField]) { - // const error = new Error( - // `Missing ${idField} property. You must create the data before you can update with this data` - // ) - // return Promise.reject(error) - // } - // // return this._update(this[idField], this, params) - // } - // public _update() {} - - // public remove(params) { - // // return this._remove(this[idField], params) - // } - // public _remove() {} - - public toJSON() { - return merge({}, this) - } - } -} - -function createRelatedInstance({ item, Model, idField, store }) { - // Create store instances (if data contains an idField) - const model = new Model(item) - const id = model[idField] - const storedModel = store.state[model.constructor.namespace].keyedById[id] - - return { model, storedModel } -} - -function cloneWithAccessors(obj) { - const clone = {} - - const props = Object.getOwnPropertyNames(obj) - props.forEach(key => { - const desc = Object.getOwnPropertyDescriptor(obj, key) - - // Do not allow sharing of deeply-nested objects between instances - if (isPlainObject(desc.value)) { - desc.value = fastCopy(desc.value) - } - - Object.defineProperty(clone, key, desc) - }) - - return clone -} - -export default makeModel diff --git a/src/service-module/new-api/add-model.ts b/src/service-module/new-api/add-model.ts index 2e8a1f5a..4bffe830 100644 --- a/src/service-module/new-api/add-model.ts +++ b/src/service-module/new-api/add-model.ts @@ -3,13 +3,14 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ +import { FeathersVuexOptions } from './types' import globalModels from './global-models' /** * prepareAddModel wraps options in a closure around addModel * @param options */ -export default function prepareAddModel(options) { +export function prepareAddModel(options: FeathersVuexOptions) { const { serverAlias } = options return function addModel(Model) { diff --git a/src/service-module/new-api/index.ts b/src/service-module/new-api/index.ts index 722871e5..8d505892 100644 --- a/src/service-module/new-api/index.ts +++ b/src/service-module/new-api/index.ts @@ -3,16 +3,12 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ +import { FeathersVuexOptions } from './types' import prepareMakeServicePlugin from './make-service-plugin' import makeModel from './make-model' -import prepareAddModel from './add-model' +import { prepareAddModel } from './add-model' import models from './global-models' -export interface FeathersVuexOptions { - idField?: string - nameStyle?: string - serverAlias: string -} const defaultOptions = { idField: 'id', nameStyle: 'short' diff --git a/src/service-module/new-api/make-model.ts b/src/service-module/new-api/make-model.ts index 745a0fac..b0678851 100644 --- a/src/service-module/new-api/make-model.ts +++ b/src/service-module/new-api/make-model.ts @@ -3,79 +3,76 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import { GlobalOptions } from './types' +import { FeathersVuexOptions } from './types' import globalModels from './global-models' -import { getNamespace } from '../../utils' import Vue from 'vue' /** * * @param options */ -export default function makeModel(options: GlobalOptions) { +export default function makeModel(options: FeathersVuexOptions) { abstract class FeathersVuexModel { - abstract servicePath: string - // Monkey patched onto the Model class in `makeServicePlugin()` - public static namespace: string public static store: Record + public static namespace: string + public static servicePath: string public static idField: string = options.idField - public static models = globalModels // Can access other Models here - public static copiesById = {} + public static preferUpdate: boolean = options.preferUpdate public static serverAlias: string = options.serverAlias + + public static readonly models = globalModels // Can access other Models here + public static readonly copiesById = {} + protected isClone: boolean - public _data: Record + public data: Record public constructor(data) { - this._data = Vue.observable(data) + Object.assign(this, data) + this.data = Vue.observable(data) } public static getId(record: Record): string { return record[FeathersVuexModel.idField] } - public static getNamespace() { - // return ( - // FeathersVuexModel.namespace || - // getNamespace(FeathersVuexModel.servicePath, options.nameStyle) - // ) - } - public static find(params) { return FeathersVuexModel.store.dispatch( - `${options.namespace}/find`, + `${FeathersVuexModel.namespace}/find`, params ) } public static findInStore(params) { - return FeathersVuexModel.store.getters[`${options.namespace}/find`]( - params - ) + return FeathersVuexModel.store.getters[ + `${FeathersVuexModel.namespace}/find` + ](params) } public static get(id, params) { const { store } = FeathersVuexModel if (params) { - return store.dispatch(`${options.namespace}/get`, [id, params]) + return store.dispatch(`${FeathersVuexModel.namespace}/get`, [ + id, + params + ]) } else { - return store.dispatch(`${options.namespace}/get`, id) + return store.dispatch(`${FeathersVuexModel.namespace}/get`, id) } } public static getFromStore(id, params) { const { store } = FeathersVuexModel if (params) { - return store.getters[`${options.namespace}/get`]([id, params]) + return store.getters[`${FeathersVuexModel.namespace}/get`]([id, params]) } else { - return store.getters[`${options.namespace}/get`](id) + return store.getters[`${FeathersVuexModel.namespace}/get`](id) } } /** - * Use the `createCopy` mutation to clone the current record. Return the - * clone + * clone the current record using the `createCopy` mutation */ public clone() { if (this.isClone) { @@ -84,12 +81,13 @@ export default function makeModel(options: GlobalOptions) { const id = this[FeathersVuexModel.idField] this._clone(id) } + private _clone(id) { const { store, copiesById } = FeathersVuexModel - store.commit(`${options.namespace}/createCopy`, id) + store.commit(`${FeathersVuexModel.namespace}/createCopy`, id) - if (store.state[options.namespace].keepCopiesInStore) { - return store.getters[`${options.namespace}/getCopyById`](id) + if (store.state[FeathersVuexModel.namespace].keepCopiesInStore) { + return store.getters[`${FeathersVuexModel.namespace}/getCopyById`](id) } else { return copiesById[id] } @@ -101,7 +99,10 @@ export default function makeModel(options: GlobalOptions) { public reset() { if (this.isClone) { const id = this[FeathersVuexModel.idField] - FeathersVuexModel.store.commit(`${options.namespace}/rejectCopy`, id) + FeathersVuexModel.store.commit( + `${FeathersVuexModel.namespace}/rejectCopy`, + id + ) } else { throw new Error('You cannot reset a non-copy') } @@ -113,7 +114,10 @@ export default function makeModel(options: GlobalOptions) { public commit() { if (this.isClone) { const id = this[FeathersVuexModel.idField] - FeathersVuexModel.store.commit(`${options.namespace}/commitCopy`, id) + FeathersVuexModel.store.commit( + `${FeathersVuexModel.namespace}/commitCopy`, + id + ) return this._clone(id) } else { @@ -142,7 +146,10 @@ export default function makeModel(options: GlobalOptions) { if (data[options.idField] === null) { delete data[options.idField] } - return store.dispatch(`${options.namespace}/create`, [data, params]) + return store.dispatch(`${FeathersVuexModel.namespace}/create`, [ + data, + params + ]) } /** @@ -158,11 +165,10 @@ export default function makeModel(options: GlobalOptions) { ) return Promise.reject(error) } - return FeathersVuexModel.store.dispatch(`${options.namespace}/patch`, [ - this[options.idField], - this, - params - ]) + return FeathersVuexModel.store.dispatch( + `${FeathersVuexModel.namespace}/patch`, + [this[options.idField], this, params] + ) } /** @@ -178,11 +184,10 @@ export default function makeModel(options: GlobalOptions) { ) return Promise.reject(error) } - return FeathersVuexModel.store.dispatch(`${options.namespace}/update`, [ - this[options.idField], - this, - params - ]) + return FeathersVuexModel.store.dispatch( + `${FeathersVuexModel.namespace}/update`, + [this[options.idField], this, params] + ) } /** @@ -190,10 +195,10 @@ export default function makeModel(options: GlobalOptions) { * @param params */ public remove(params) { - return FeathersVuexModel.store.dispatch(`${options.namespace}/remove`, [ - this[options.idField], - params - ]) + return FeathersVuexModel.store.dispatch( + `${FeathersVuexModel.namespace}/remove`, + [this[options.idField], params] + ) } } return FeathersVuexModel diff --git a/src/service-module/new-api/make-service-plugin.test.ts b/src/service-module/new-api/make-service-plugin.test.ts index 2668dfd5..986eb035 100644 --- a/src/service-module/new-api/make-service-plugin.test.ts +++ b/src/service-module/new-api/make-service-plugin.test.ts @@ -23,7 +23,6 @@ describe('makeServicePlugin', function() { public servicePath = servicePath } const todosPlugin = makeServicePlugin({ - servicePath, Model: Todo, service: feathers.service(servicePath) }) @@ -57,7 +56,6 @@ describe('makeServicePlugin', function() { public servicePath = servicePath } const todosPlugin = makeServicePlugin({ - servicePath, Model: Todo, service: feathers.service(servicePath) }) @@ -77,14 +75,9 @@ it('allows accessing other models', function() { const servicePath = 'todos' class Todo extends BaseModel { public servicePath = servicePath - public static store: Record - public constructor(data) { - super(data) - } } addModel(Todo) const todosPlugin = makeServicePlugin({ - servicePath, Model: Todo, service: feathers.service(servicePath) }) diff --git a/src/service-module/new-api/make-service-plugin.ts b/src/service-module/new-api/make-service-plugin.ts index aa573e9b..8b7fc5a3 100644 --- a/src/service-module/new-api/make-service-plugin.ts +++ b/src/service-module/new-api/make-service-plugin.ts @@ -3,28 +3,43 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import { GlobalOptions, MakeServicePluginOptions } from './types' +import { FeathersVuexOptions, MakeServicePluginOptions } from './types' import makeServiceModule from './make-service-module' -import { getNamespace } from '../../utils' +import { prepareAddModel } from './add-model' +import { makeNamespace, getServicePath } from '../../utils' /** * prepare only wraps the makeServicePlugin to provide the globalOptions. * @param globalOptions */ -export default function prepareMakeServicePlugin(globalOptions: GlobalOptions) { +export default function prepareMakeServicePlugin( + globalOptions: FeathersVuexOptions +) { + const addModel = prepareAddModel(globalOptions) /** - * Make a Vuex plugin for the provided service. It also attaches the vuex - * store to the provided Model instance. + * (1) Make a Vuex plugin for the provided service. + * (2) Attach the vuex store to the Model. */ - return function makeServicePlugin(config) { + return function makeServicePlugin(config: MakeServicePluginOptions) { const options = Object.assign({}, globalOptions, config) - const { servicePath, Model, service, namespace, nameStyle } = options + const { Model, service, namespace, nameStyle } = options + + // Make sure we get a service path from either the service or the options + let { servicePath } = options + if (!servicePath) { + servicePath = getServicePath(service, Model.name) + } + options.servicePath = servicePath return store => { - options.namespace = namespace || getNamespace(servicePath, nameStyle) + // (1^) Create and register the Vuex module + const vuexNamespace = makeNamespace(namespace, servicePath, nameStyle) const module = makeServiceModule(service, options) - store.registerModule(options.namespace, module) - Model.store = store + store.registerModule(vuexNamespace, module) + + // (2^) Monkey patch the Model and add to globalModels + Object.assign(Model, { store, namespace: vuexNamespace, servicePath }) + addModel(Model) } } } diff --git a/src/service-module/new-api/model.test.ts b/src/service-module/new-api/model.test.ts index e62996c1..52bd01c3 100644 --- a/src/service-module/new-api/model.test.ts +++ b/src/service-module/new-api/model.test.ts @@ -6,66 +6,176 @@ eslint import { assert } from 'chai' import Vue from 'vue' import Vuex from 'vuex' -import { feathersRestClient as feathers } from '../../../test/fixtures/feathers-client' +import { + feathersRestClient as feathers, + makeFeathersRestClient +} from '../../../test/fixtures/feathers-client' import feathersVuex from './index' Vue.use(Vuex) describe.only('makeModel', function() { - it('propertly sets up the BaseModel', function() { - const serverAlias = 'default' + it('properly sets up the BaseModel', function() { + const alias = 'default' + const { BaseModel } = feathersVuex(feathers, { serverAlias: alias }) + const { + name, + store, + namespace, + idField, + preferUpdate, + serverAlias, + models, + copiesById + } = BaseModel + + assert(name === 'FeathersVuexModel', 'name in place') + + // Monkey patched onto the Model class in `makeServicePlugin()` + assert(!store, 'no store by default') + assert(!namespace, 'no namespace by default') + + assert(idField === 'id', 'default idField is id') + assert(!preferUpdate, 'prefer fetch by default') + + // Readonly props + assert(serverAlias === 'default', 'serverAlias') + assert(models, 'models are available') + assert.equal(Object.keys(copiesById).length, 0, 'copiesById is empty') + + // Static Methods + const staticMethods = [ + 'getId', + 'find', + 'findInStore', + 'get', + 'getFromStore' + ] + staticMethods.forEach(method => { + assert(typeof BaseModel[method] === 'function', `has ${method} method`) + }) + + // Prototype Methods + const prototypeMethods = [ + 'clone', + 'reset', + 'commit', + 'save', + 'create', + 'patch', + 'update', + 'remove' + ] + prototypeMethods.forEach(method => { + assert( + typeof BaseModel.prototype[method] === 'function', + `has ${method} method` + ) + }) + }) + + it('allows customization through the FeathersVuexOptions', function() { const { BaseModel } = feathersVuex(feathers, { - serverAlias + serverAlias: 'myApi', + idField: '_id', + preferUpdate: true }) + const { idField, preferUpdate, serverAlias } = BaseModel - assert(BaseModel.name === 'FeathersVuexModel', 'name in place') - assert( - BaseModel.serverAlias === 'default', - 'serverAlias in place on BaseModel' - ) - assert(!BaseModel.store, 'no store by default') - assert(BaseModel.models, 'models are available') - assert(BaseModel.idField === 'id', 'default idField is id') - assert(typeof BaseModel.getId === 'function', 'have the getId method') + assert(idField === '_id', 'idField was set') + assert(preferUpdate, 'turned on preferUpdate') + assert(serverAlias === 'myApi', 'serverAlias was set') }) - // it('default values', function() { - // const serverAlias = 'default' - // const { BaseModel } = feathersVuex(feathers, { - // serverAlias - // }) - // }) -}) + it('receives store after Vuex plugin is registered', function() { + const { BaseModel, makeServicePlugin } = feathersVuex(feathers, { + serverAlias: 'myApi' + }) + const plugin = makeServicePlugin({ + service: feathers.service('todos'), + Model: BaseModel + }) + new Vuex.Store({ + plugins: [plugin] + }) + const { store, namespace } = BaseModel + + assert(store, 'store is in place') + assert.equal(namespace, 'todos', 'namespace is in place') + }) + + it('allows access to other models after Vuex plugins are registered', function() { + const serverAlias = 'default' + const { makeServicePlugin, BaseModel, models } = feathersVuex(feathers, { + idField: '_id', + serverAlias + }) -it('allows accessing other models', function() { - const serverAlias = 'default' - const { makeServicePlugin, BaseModel, addModel, models } = feathersVuex( - feathers, - { idField: '_id', serverAlias } - ) - - const servicePath = 'todos' - class Todo extends BaseModel { - public servicePath = servicePath - public static store: Record - public constructor(data) { - super(data) + // Create a Todo Model & Plugin + class Todo extends BaseModel { + public test: boolean = true } - } + const todosPlugin = makeServicePlugin({ + Model: Todo, + service: feathers.service('todos') + }) - // TODO: move this into makeServicePlugin - addModel(Todo) + // Create a Task Model & Plugin + class Task extends BaseModel { + public test: boolean = true + } + const tasksPlugin = makeServicePlugin({ + Model: Task, + service: feathers.service('tasks') + }) - const todosPlugin = makeServicePlugin({ - servicePath, - Model: Todo, - service: feathers.service(servicePath) - }) + // Register the plugins + new Vuex.Store({ + plugins: [todosPlugin, tasksPlugin] + }) - const store = new Vuex.Store({ - plugins: [todosPlugin] + assert(models[serverAlias][Todo.name] === Todo) + assert.equal(Todo.models, models, 'models available at Model.models') + assert.equal(Task.models, models, 'models available at Model.models') }) - assert(models[serverAlias][Todo.name] === Todo) - assert(Todo.store === store) + it.only('works with multiple, independent Feathers servers', function() { + // Create a Todo Model & Plugin on myApi + const feathersMyApi = makeFeathersRestClient('https://api.my-api.com') + const myApi = feathersVuex(feathersMyApi, { + idField: '_id', + serverAlias: 'myApi' + }) + class Todo extends myApi.BaseModel { + public test: boolean = true + } + const todosPlugin = myApi.makeServicePlugin({ + Model: Todo, + service: feathersMyApi.service('todos') + }) + + // Create a Task Model & Plugin on theirApi + const feathersTheirApi = makeFeathersRestClient('https://api.their-api.com') + const theirApi = feathersVuex(feathersTheirApi, { + serverAlias: 'theirApi' + }) + class Task extends theirApi.BaseModel { + public test: boolean = true + } + const tasksPlugin = theirApi.makeServicePlugin({ + Model: Task, + service: feathersTheirApi.service('tasks') + }) + + // Register the plugins + new Vuex.Store({ + plugins: [todosPlugin, tasksPlugin] + }) + const { models } = myApi + + assert(models.myApi.Todo === Todo) + assert(!models.theirApi.Todo, `Todo stayed out of the 'theirApi' namespace`) + assert(models.theirApi.Task === Task) + assert(!models.myApi.Task, `Task stayed out of the 'myApi' namespace`) + }) }) diff --git a/src/service-module/model/notes.md b/src/service-module/new-api/notes.md similarity index 82% rename from src/service-module/model/notes.md rename to src/service-module/new-api/notes.md index e872c1ef..f10b62f9 100644 --- a/src/service-module/model/notes.md +++ b/src/service-module/new-api/notes.md @@ -13,16 +13,10 @@ const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { // @service('todos') class Todo extends BaseModel { servicePath: 'todos' - store: any - firstName: string - constructor(data) { - this.firstName = data.firstName - } } const servicePath = 'todos' const todos = makeServicePlugin({ - servicePath, Model: Todo, service: feathers.service(servicePath) }) diff --git a/src/service-module/new-api/types.ts b/src/service-module/new-api/types.ts index f505acf2..4972843f 100644 --- a/src/service-module/new-api/types.ts +++ b/src/service-module/new-api/types.ts @@ -2,16 +2,20 @@ eslint @typescript-eslint/no-explicit-any: 0 */ -export interface GlobalOptions { +export interface FeathersVuexOptions { serverAlias: string idField?: string + nameStyle?: string + preferUpdate?: boolean } export interface MakeServicePluginOptions { - servicePath: string Model: any service: any namespace?: string + servicePath?: string + state?: {} + getters?: {} + mutations?: {} + actions?: {} } - -export interface MakeModelOptions extends GlobalOptions {} diff --git a/src/utils.ts b/src/utils.ts index 87ff56c4..8b9932bc 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -257,11 +257,19 @@ export function updateOriginal(newData, existingItem) { }) } -export function makeNamespace(servicePath, options) { - const { namespace, nameStyle } = options +export function makeNamespace(namespace, servicePath, nameStyle) { const nameStyles = { short: getShortName, path: getNameFromPath } return namespace || nameStyles[nameStyle](servicePath) } + +export function getServicePath(service: any, modelName: string) { + if (!service.name) { + throw new Error( + `Service for model named ${modelName} is missing a path or name property. The feathers adapter needs to be updated with a PR to expose this property. You can work around this by passing a 'servicePath' attribute in the options: makeServicePlugin({servicePath: '/path/to/my/service'})` + ) + } + return service.path || service.name +} diff --git a/test/fixtures/feathers-client.js b/test/fixtures/feathers-client.js index 76956fe3..6047ac1f 100644 --- a/test/fixtures/feathers-client.js +++ b/test/fixtures/feathers-client.js @@ -11,24 +11,24 @@ const baseUrl = 'http://localhost:3030' // These are fixtures used in the service-modulet.test.js under socket events. let id = 0 -mockServer.on('things::create', function (data) { +mockServer.on('things::create', function(data) { data.id = id id++ mockServer.emit('things created', data) }) -mockServer.on('things::patch', function (id, data) { +mockServer.on('things::patch', function(id, data) { Object.assign(data, { id, test: true }) mockServer.emit('things patched', data) }) -mockServer.on('things::update', function (id, data) { +mockServer.on('things::update', function(id, data) { Object.assign(data, { id, test: true }) mockServer.emit('things updated', data) }) -mockServer.on('things::remove', function (id, data) { +mockServer.on('things::remove', function(id, data) { mockServer.emit('things removed', { id, test: true }) }) -export function makeFeathersSocketClient () { +export function makeFeathersSocketClient(baseUrl) { const socket = io(baseUrl) return feathers() @@ -36,7 +36,7 @@ export function makeFeathersSocketClient () { .configure(auth()) } -export function makeFeathersRestClient () { +export function makeFeathersRestClient(baseUrl) { return feathers() .configure(rest(baseUrl).axios(axios)) .configure(auth()) diff --git a/tsconfig.json b/tsconfig.json index 0056a28e..9dca8f43 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,8 @@ "compilerOptions": { "allowJs": true, "allowSyntheticDefaultImports": true, - "esModuleInterop": true + "esModuleInterop": true, + "outDir": "dist" }, "include": [ "src/**/*" From f72f1759e502564bf06924e16e689c29c891254a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 14:59:06 -0600 Subject: [PATCH 007/404] make-service-plugin tests --- package-lock.json | 3 +-- package.json | 1 + src/service-module/new-api/add-model.ts | 2 +- .../new-api/make-service-module.ts | 5 ++++- .../new-api/make-service-plugin.test.ts | 19 +++++++++++-------- src/service-module/new-api/model.test.ts | 4 ++-- src/service-module/new-api/types.ts | 1 + test/fixtures/feathers-client.js | 2 +- 8 files changed, 22 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5ba32ff5..47f96ced 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13826,8 +13826,7 @@ "lodash.pick": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", - "dev": true + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" }, "lodash.template": { "version": "4.4.0", diff --git a/package.json b/package.json index 72f696e2..7f46d214 100644 --- a/package.json +++ b/package.json @@ -110,6 +110,7 @@ "lodash.isplainobject": "^4.0.6", "lodash.merge": "^4.6.1", "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", "lodash.trim": "^4.5.1", "serialize-error": "^3.0.0", "sift": "^7.0.1", diff --git a/src/service-module/new-api/add-model.ts b/src/service-module/new-api/add-model.ts index 4bffe830..08e45623 100644 --- a/src/service-module/new-api/add-model.ts +++ b/src/service-module/new-api/add-model.ts @@ -15,7 +15,7 @@ export function prepareAddModel(options: FeathersVuexOptions) { return function addModel(Model) { globalModels[serverAlias] = globalModels[serverAlias] || {} - if (globalModels[serverAlias][Model.name]) { + if (globalModels[serverAlias][Model.name] && options.debug) { console.error(`Overwriting Model: models[${serverAlias}][${Model.name}].`) } globalModels[serverAlias][Model.name] = Model diff --git a/src/service-module/new-api/make-service-module.ts b/src/service-module/new-api/make-service-module.ts index ce0a801b..8cda7e90 100644 --- a/src/service-module/new-api/make-service-module.ts +++ b/src/service-module/new-api/make-service-module.ts @@ -3,11 +3,14 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ +import omit from 'lodash.omit' + export default function makeServiceModule(service, options) { + const stateOptions = omit(options, ['Model', 'service']) return { namespaced: true, state: { - options + options: stateOptions }, getters: {}, mutations: {}, diff --git a/src/service-module/new-api/make-service-plugin.test.ts b/src/service-module/new-api/make-service-plugin.test.ts index 986eb035..1448d986 100644 --- a/src/service-module/new-api/make-service-plugin.test.ts +++ b/src/service-module/new-api/make-service-plugin.test.ts @@ -5,9 +5,10 @@ eslint */ import { assert } from 'chai' import Vue from 'vue' -import Vuex, { StoreOptions } from 'vuex' +// import Vuex, { StoreOptions } from 'vuex' import { feathersRestClient as feathers } from '../../../test/fixtures/feathers-client' import feathersVuex from './index' +import _pick from 'lodash.pick' Vue.use(Vuex) @@ -31,18 +32,20 @@ describe('makeServicePlugin', function() { } const store = new Vuex.Store({ plugins: [todosPlugin] }) + const received = _pick(store.state.todos.options, [ + 'idField', + 'nameStyle', + 'serverAlias', + 'servicePath' + ]) const expected = { idField: 'id', - namespace: 'todos', nameStyle: 'short', - serverAlias: 'default' + serverAlias: 'default', + servicePath: 'todos' } - assert.deepEqual( - store.state.todos.options, - expected, - 'The module was registered.' - ) + assert.deepEqual(received, expected, 'The module was registered.') }) it('sets up Model.store', function() { diff --git a/src/service-module/new-api/model.test.ts b/src/service-module/new-api/model.test.ts index 52bd01c3..9f4e52b3 100644 --- a/src/service-module/new-api/model.test.ts +++ b/src/service-module/new-api/model.test.ts @@ -14,7 +14,7 @@ import feathersVuex from './index' Vue.use(Vuex) -describe.only('makeModel', function() { +describe('makeModel / BaseModel', function() { it('properly sets up the BaseModel', function() { const alias = 'default' const { BaseModel } = feathersVuex(feathers, { serverAlias: alias }) @@ -139,7 +139,7 @@ describe.only('makeModel', function() { assert.equal(Task.models, models, 'models available at Model.models') }) - it.only('works with multiple, independent Feathers servers', function() { + it('works with multiple, independent Feathers servers', function() { // Create a Todo Model & Plugin on myApi const feathersMyApi = makeFeathersRestClient('https://api.my-api.com') const myApi = feathersVuex(feathersMyApi, { diff --git a/src/service-module/new-api/types.ts b/src/service-module/new-api/types.ts index 4972843f..3142da82 100644 --- a/src/service-module/new-api/types.ts +++ b/src/service-module/new-api/types.ts @@ -7,6 +7,7 @@ export interface FeathersVuexOptions { idField?: string nameStyle?: string preferUpdate?: boolean + debug?: boolean } export interface MakeServicePluginOptions { diff --git a/test/fixtures/feathers-client.js b/test/fixtures/feathers-client.js index 6047ac1f..88a83536 100644 --- a/test/fixtures/feathers-client.js +++ b/test/fixtures/feathers-client.js @@ -24,7 +24,7 @@ mockServer.on('things::update', function(id, data) { Object.assign(data, { id, test: true }) mockServer.emit('things updated', data) }) -mockServer.on('things::remove', function(id, data) { +mockServer.on('things::remove', function(id) { mockServer.emit('things removed', { id, test: true }) }) From 218a8e1fc39fcfd749e31920e5498b7359f8d2e1 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 15:08:29 -0600 Subject: [PATCH 008/404] Clean up default options (up to this point) --- src/service-module/new-api/index.ts | 7 ++- .../new-api/make-service-plugin.test.ts | 44 +++++++++---------- .../new-api/make-service-plugin.ts | 11 ++++- 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/service-module/new-api/index.ts b/src/service-module/new-api/index.ts index 8d505892..88dd3fed 100644 --- a/src/service-module/new-api/index.ts +++ b/src/service-module/new-api/index.ts @@ -9,9 +9,12 @@ import makeModel from './make-model' import { prepareAddModel } from './add-model' import models from './global-models' -const defaultOptions = { +const defaultOptions: FeathersVuexOptions = { idField: 'id', - nameStyle: 'short' + debug: false, + nameStyle: 'short', + preferUpdate: false, + serverAlias: '' } export default function feathersVuex(feathers, options: FeathersVuexOptions) { diff --git a/src/service-module/new-api/make-service-plugin.test.ts b/src/service-module/new-api/make-service-plugin.test.ts index 1448d986..e6dcceae 100644 --- a/src/service-module/new-api/make-service-plugin.test.ts +++ b/src/service-module/new-api/make-service-plugin.test.ts @@ -5,7 +5,7 @@ eslint */ import { assert } from 'chai' import Vue from 'vue' -// import Vuex, { StoreOptions } from 'vuex' +import Vuex, { StoreOptions } from 'vuex' import { feathersRestClient as feathers } from '../../../test/fixtures/feathers-client' import feathersVuex from './index' import _pick from 'lodash.pick' @@ -66,29 +66,29 @@ describe('makeServicePlugin', function() { assert(Todo.store === store, 'the store is on the Model!') }) -}) -it('allows accessing other models', function() { - const serverAlias = 'default' - const { makeServicePlugin, BaseModel, addModel, models } = feathersVuex( - feathers, - { idField: '_id', serverAlias } - ) + it('allows accessing other models', function() { + const serverAlias = 'default' + const { makeServicePlugin, BaseModel, addModel, models } = feathersVuex( + feathers, + { idField: '_id', serverAlias } + ) - const servicePath = 'todos' - class Todo extends BaseModel { - public servicePath = servicePath - } - addModel(Todo) - const todosPlugin = makeServicePlugin({ - Model: Todo, - service: feathers.service(servicePath) - }) + const servicePath = 'todos' + class Todo extends BaseModel { + public servicePath = servicePath + } + addModel(Todo) + const todosPlugin = makeServicePlugin({ + Model: Todo, + service: feathers.service(servicePath) + }) - const store = new Vuex.Store({ - plugins: [todosPlugin] - }) + const store = new Vuex.Store({ + plugins: [todosPlugin] + }) - assert(models[serverAlias][Todo.name] === Todo) - assert(Todo.store === store) + assert(models[serverAlias][Todo.name] === Todo) + assert(Todo.store === store) + }) }) diff --git a/src/service-module/new-api/make-service-plugin.ts b/src/service-module/new-api/make-service-plugin.ts index 8b7fc5a3..6f4cdff1 100644 --- a/src/service-module/new-api/make-service-plugin.ts +++ b/src/service-module/new-api/make-service-plugin.ts @@ -8,6 +8,15 @@ import makeServiceModule from './make-service-module' import { prepareAddModel } from './add-model' import { makeNamespace, getServicePath } from '../../utils' +const defaults = { + namespace: '', + servicePath: '', + state: {}, + getters: {}, + mutations: {}, + actions: {} +} + /** * prepare only wraps the makeServicePlugin to provide the globalOptions. * @param globalOptions @@ -21,7 +30,7 @@ export default function prepareMakeServicePlugin( * (2) Attach the vuex store to the Model. */ return function makeServicePlugin(config: MakeServicePluginOptions) { - const options = Object.assign({}, globalOptions, config) + const options = Object.assign({}, defaults, globalOptions, config) const { Model, service, namespace, nameStyle } = options // Make sure we get a service path from either the service or the options From 451fdf2d51294568ce6e4a0d04e257d2c29ac93f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 15:34:27 -0600 Subject: [PATCH 009/404] Enable real-time events --- .../new-api/make-service-plugin.ts | 18 ++++++++++++++++++ src/service-module/new-api/types.ts | 1 + src/service-module/service-module.js | 16 ---------------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/service-module/new-api/make-service-plugin.ts b/src/service-module/new-api/make-service-plugin.ts index 6f4cdff1..41f7ec09 100644 --- a/src/service-module/new-api/make-service-plugin.ts +++ b/src/service-module/new-api/make-service-plugin.ts @@ -28,6 +28,7 @@ export default function prepareMakeServicePlugin( /** * (1) Make a Vuex plugin for the provided service. * (2) Attach the vuex store to the Model. + * (3) Setup real-time events */ return function makeServicePlugin(config: MakeServicePluginOptions) { const options = Object.assign({}, defaults, globalOptions, config) @@ -49,6 +50,23 @@ export default function prepareMakeServicePlugin( // (2^) Monkey patch the Model and add to globalModels Object.assign(Model, { store, namespace: vuexNamespace, servicePath }) addModel(Model) + + // (3^) Setup real-time events + if (options.enableEvents) { + // Listen to socket events when available. + service.on('created', item => + store.commit(`${namespace}/addItem`, item) + ) + service.on('updated', item => + store.commit(`${namespace}/updateItem`, item) + ) + service.on('patched', item => + store.commit(`${namespace}/updateItem`, item) + ) + service.on('removed', item => + store.commit(`${namespace}/removeItem`, item) + ) + } } } } diff --git a/src/service-module/new-api/types.ts b/src/service-module/new-api/types.ts index 3142da82..ccb6ad7f 100644 --- a/src/service-module/new-api/types.ts +++ b/src/service-module/new-api/types.ts @@ -14,6 +14,7 @@ export interface MakeServicePluginOptions { Model: any service: any namespace?: string + enableEvents?: boolean servicePath?: string state?: {} getters?: {} diff --git a/src/service-module/service-module.js b/src/service-module/service-module.js index 6fb089b1..de9f39ba 100644 --- a/src/service-module/service-module.js +++ b/src/service-module/service-module.js @@ -131,22 +131,6 @@ export default function servicePluginInit( module.state.modelName = modelInfo.path store.registerModule(namespace, module) - - if (options.enableEvents) { - // Listen to socket events when available. - service.on('created', item => - store.commit(`${namespace}/addItem`, item) - ) - service.on('updated', item => - store.commit(`${namespace}/updateItem`, item) - ) - service.on('patched', item => - store.commit(`${namespace}/updateItem`, item) - ) - service.on('removed', item => - store.commit(`${namespace}/removeItem`, item) - ) - } } } From cdeb74ea1417640a548980faf8002f444739c32a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 15:43:51 -0600 Subject: [PATCH 010/404] Setup service.FeathersVuexModel --- .../new-api/make-service-plugin.test.ts | 9 +++--- .../new-api/make-service-plugin.ts | 2 ++ src/service-module/new-api/model.test.ts | 5 ++-- src/service-module/service-module.js | 30 ------------------- 4 files changed, 9 insertions(+), 37 deletions(-) diff --git a/src/service-module/new-api/make-service-plugin.test.ts b/src/service-module/new-api/make-service-plugin.test.ts index e6dcceae..66c07fc5 100644 --- a/src/service-module/new-api/make-service-plugin.test.ts +++ b/src/service-module/new-api/make-service-plugin.test.ts @@ -48,23 +48,22 @@ describe('makeServicePlugin', function() { assert.deepEqual(received, expected, 'The module was registered.') }) - it('sets up Model.store', function() { + it('sets up Model.store && service.FeathersVuexModel', function() { const serverAlias = 'default' const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { serverAlias }) const servicePath = 'todos' + const service = feathers.service(servicePath) class Todo extends BaseModel { public servicePath = servicePath } - const todosPlugin = makeServicePlugin({ - Model: Todo, - service: feathers.service(servicePath) - }) + const todosPlugin = makeServicePlugin({ Model: Todo, service }) const store = new Vuex.Store({ plugins: [todosPlugin] }) assert(Todo.store === store, 'the store is on the Model!') + assert.equal(service.FeathersVuexModel, Todo, 'Model accessible on service') }) it('allows accessing other models', function() { diff --git a/src/service-module/new-api/make-service-plugin.ts b/src/service-module/new-api/make-service-plugin.ts index 41f7ec09..73e866a4 100644 --- a/src/service-module/new-api/make-service-plugin.ts +++ b/src/service-module/new-api/make-service-plugin.ts @@ -41,6 +41,8 @@ export default function prepareMakeServicePlugin( } options.servicePath = servicePath + service.FeathersVuexModel = Model + return store => { // (1^) Create and register the Vuex module const vuexNamespace = makeNamespace(namespace, servicePath, nameStyle) diff --git a/src/service-module/new-api/model.test.ts b/src/service-module/new-api/model.test.ts index 9f4e52b3..88bf27e3 100644 --- a/src/service-module/new-api/model.test.ts +++ b/src/service-module/new-api/model.test.ts @@ -87,7 +87,7 @@ describe('makeModel / BaseModel', function() { assert(serverAlias === 'myApi', 'serverAlias was set') }) - it('receives store after Vuex plugin is registered', function() { + it('receives store & other props after Vuex plugin is registered', function() { const { BaseModel, makeServicePlugin } = feathersVuex(feathers, { serverAlias: 'myApi' }) @@ -98,10 +98,11 @@ describe('makeModel / BaseModel', function() { new Vuex.Store({ plugins: [plugin] }) - const { store, namespace } = BaseModel + const { store, namespace, servicePath } = BaseModel assert(store, 'store is in place') assert.equal(namespace, 'todos', 'namespace is in place') + assert.equal(servicePath, 'todos', 'servicePath is in place') }) it('allows access to other models after Vuex plugins are registered', function() { diff --git a/src/service-module/service-module.js b/src/service-module/service-module.js index de9f39ba..76797470 100644 --- a/src/service-module/service-module.js +++ b/src/service-module/service-module.js @@ -107,20 +107,6 @@ export default function servicePluginInit( let namespace = options.namespace || nameStyles[nameStyle](servicePath) return function setupStore(store) { - service.FeathersVuexModel = Model - // Add servicePath to Model so it can be accessed - Object.defineProperties(Model, { - servicePath: { - value: servicePath - }, - namespace: { - value: namespace - }, - store: { - value: store - } - }) - // Add Model to the globalModels object, so it's available in the Vue plugin const modelInfo = registerModel( Model, @@ -134,21 +120,5 @@ export default function servicePluginInit( } } - const createServicePlugin = function createServicePlugin( - servicePath, - options = {} - ) { - const module = serviceModule(servicePath, options) - const Model = serviceModel(options) - - return servicePlugin(module, Model, options) - } - - Object.assign(createServicePlugin, { - serviceModule, - serviceModel, - servicePlugin - }) - return createServicePlugin } From e2409a4e230c31d77ac7adf5d7a24d858e05769c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 16:16:25 -0600 Subject: [PATCH 011/404] Test correct options --- .../new-api/make-service-plugin.test.ts | 17 ++++++++++------- .../new-api/make-service-plugin.ts | 6 +++--- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/service-module/new-api/make-service-plugin.test.ts b/src/service-module/new-api/make-service-plugin.test.ts index 66c07fc5..70b02447 100644 --- a/src/service-module/new-api/make-service-plugin.test.ts +++ b/src/service-module/new-api/make-service-plugin.test.ts @@ -32,17 +32,20 @@ describe('makeServicePlugin', function() { } const store = new Vuex.Store({ plugins: [todosPlugin] }) - const received = _pick(store.state.todos.options, [ - 'idField', - 'nameStyle', - 'serverAlias', - 'servicePath' - ]) + const keys = Object.keys(store.state.todos.options) + const received = _pick(store.state.todos.options, keys) const expected = { + actions: {}, + debug: false, + getters: {}, idField: 'id', + mutations: {}, nameStyle: 'short', + namespace: 'todos', + preferUpdate: false, serverAlias: 'default', - servicePath: 'todos' + servicePath: 'todos', + state: {} } assert.deepEqual(received, expected, 'The module was registered.') diff --git a/src/service-module/new-api/make-service-plugin.ts b/src/service-module/new-api/make-service-plugin.ts index 73e866a4..8e24bdb6 100644 --- a/src/service-module/new-api/make-service-plugin.ts +++ b/src/service-module/new-api/make-service-plugin.ts @@ -45,12 +45,12 @@ export default function prepareMakeServicePlugin( return store => { // (1^) Create and register the Vuex module - const vuexNamespace = makeNamespace(namespace, servicePath, nameStyle) + options.namespace = makeNamespace(namespace, servicePath, nameStyle) const module = makeServiceModule(service, options) - store.registerModule(vuexNamespace, module) + store.registerModule(options.namespace, module) // (2^) Monkey patch the Model and add to globalModels - Object.assign(Model, { store, namespace: vuexNamespace, servicePath }) + Object.assign(Model, { store, namespace: options.namespace, servicePath }) addModel(Model) // (3^) Setup real-time events From cbe7bd3fb1ac9198c6d6b7316b2102fc6dccb926 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 16:20:29 -0600 Subject: [PATCH 012/404] Add modelName to state.options --- .../new-api/make-service-module.ts | 5 +++++ .../new-api/make-service-plugin.test.ts | 1 + src/service-module/service-module.js | 16 ---------------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/service-module/new-api/make-service-module.ts b/src/service-module/new-api/make-service-module.ts index 8cda7e90..8d91cbab 100644 --- a/src/service-module/new-api/make-service-module.ts +++ b/src/service-module/new-api/make-service-module.ts @@ -7,6 +7,11 @@ import omit from 'lodash.omit' export default function makeServiceModule(service, options) { const stateOptions = omit(options, ['Model', 'service']) + + Object.assign(stateOptions, { + modelName: options.Model.name + }) + return { namespaced: true, state: { diff --git a/src/service-module/new-api/make-service-plugin.test.ts b/src/service-module/new-api/make-service-plugin.test.ts index 70b02447..5a2a5708 100644 --- a/src/service-module/new-api/make-service-plugin.test.ts +++ b/src/service-module/new-api/make-service-plugin.test.ts @@ -39,6 +39,7 @@ describe('makeServicePlugin', function() { debug: false, getters: {}, idField: 'id', + modelName: 'Todo', mutations: {}, nameStyle: 'short', namespace: 'todos', diff --git a/src/service-module/service-module.js b/src/service-module/service-module.js index 76797470..32494b2e 100644 --- a/src/service-module/service-module.js +++ b/src/service-module/service-module.js @@ -97,23 +97,7 @@ export default function servicePluginInit( const servicePlugin = function servicePlugin(module, Model, options = {}) { options = Object.assign({}, globalOptions, options) const { servicePath } = module.state - const { nameStyle, apiPrefix } = options - const service = feathersClient.service(servicePath) - - const nameStyles = { - short: getShortName, - path: getNameFromPath - } - let namespace = options.namespace || nameStyles[nameStyle](servicePath) - return function setupStore(store) { - // Add Model to the globalModels object, so it's available in the Vue plugin - const modelInfo = registerModel( - Model, - globalModels, - apiPrefix, - servicePath - ) module.state.modelName = modelInfo.path store.registerModule(namespace, module) From dee4c0a286cdb8cebcaa98353e81ff48e2f5be84 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 16:28:02 -0600 Subject: [PATCH 013/404] Remove nonState options from state --- src/service-module/new-api/index.ts | 3 ++- src/service-module/new-api/make-service-module.ts | 14 ++++++++++++-- .../new-api/make-service-plugin.test.ts | 7 ++----- src/service-module/new-api/types.ts | 1 + src/service-module/service-module.js | 9 ++------- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/service-module/new-api/index.ts b/src/service-module/new-api/index.ts index 88dd3fed..b5d28e64 100644 --- a/src/service-module/new-api/index.ts +++ b/src/service-module/new-api/index.ts @@ -10,7 +10,8 @@ import { prepareAddModel } from './add-model' import models from './global-models' const defaultOptions: FeathersVuexOptions = { - idField: 'id', + autoRemove: false, // Automatically remove records missing from responses (only use with feathers-rest) + idField: 'id', // The field in each record that will contain the id debug: false, nameStyle: 'short', preferUpdate: false, diff --git a/src/service-module/new-api/make-service-module.ts b/src/service-module/new-api/make-service-module.ts index 8d91cbab..0eecd5dd 100644 --- a/src/service-module/new-api/make-service-module.ts +++ b/src/service-module/new-api/make-service-module.ts @@ -3,10 +3,20 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import omit from 'lodash.omit' +import _omit from 'lodash.omit' +import _pick from 'lodash.pick' export default function makeServiceModule(service, options) { - const stateOptions = omit(options, ['Model', 'service']) + const nonStateProps = [ + 'Model', + 'service', + 'state', + 'getters', + 'mutations', + 'actions' + ] + const stateOptions = _omit(options, nonStateProps) + const nonStateOptions = _pick(options, nonStateProps) Object.assign(stateOptions, { modelName: options.Model.name diff --git a/src/service-module/new-api/make-service-plugin.test.ts b/src/service-module/new-api/make-service-plugin.test.ts index 5a2a5708..10fa3bb8 100644 --- a/src/service-module/new-api/make-service-plugin.test.ts +++ b/src/service-module/new-api/make-service-plugin.test.ts @@ -35,18 +35,15 @@ describe('makeServicePlugin', function() { const keys = Object.keys(store.state.todos.options) const received = _pick(store.state.todos.options, keys) const expected = { - actions: {}, + autoRemove: false, debug: false, - getters: {}, idField: 'id', modelName: 'Todo', - mutations: {}, nameStyle: 'short', namespace: 'todos', preferUpdate: false, serverAlias: 'default', - servicePath: 'todos', - state: {} + servicePath: 'todos' } assert.deepEqual(received, expected, 'The module was registered.') diff --git a/src/service-module/new-api/types.ts b/src/service-module/new-api/types.ts index ccb6ad7f..06e11174 100644 --- a/src/service-module/new-api/types.ts +++ b/src/service-module/new-api/types.ts @@ -4,6 +4,7 @@ eslint */ export interface FeathersVuexOptions { serverAlias: string + autoRemove?: boolean idField?: string nameStyle?: string preferUpdate?: boolean diff --git a/src/service-module/service-module.js b/src/service-module/service-module.js index 32494b2e..3f6d2c44 100644 --- a/src/service-module/service-module.js +++ b/src/service-module/service-module.js @@ -1,4 +1,3 @@ -import { getShortName, getNameFromPath, registerModel } from '../utils' import makeState from './state' import makeGetters from './getters' import makeMutations from './mutations' @@ -6,8 +5,6 @@ import makeActions from './actions' import makeModel from './model' const defaults = { - idField: 'id', // The field in each record that will contain the id - autoRemove: false, // Automatically remove records missing from responses (only use with feathers-rest) nameStyle: 'short', // Determines the source of the module name. 'short', 'path', or 'explicit' enableEvents: true, // Listens to socket.io events when available addOnUpsert: false, // Add new records pushed by 'updated/patched' socketio events into store, instead of discarding them @@ -98,10 +95,8 @@ export default function servicePluginInit( options = Object.assign({}, globalOptions, options) const { servicePath } = module.state - - module.state.modelName = modelInfo.path - store.registerModule(namespace, module) - } + module.state.modelName = modelInfo.path + store.registerModule(namespace, module) } return createServicePlugin From e362e41c9bbec5c3c00e566c3647f74cb8e51bd0 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 16:49:13 -0600 Subject: [PATCH 014/404] Add and test more options --- src/service-module/new-api/index.ts | 21 ++++++++++++--- .../new-api/make-service-plugin.test.ts | 10 ++++++- .../new-api/make-service-plugin.ts | 11 ++++---- src/service-module/new-api/types.ts | 14 ++++++++-- src/service-module/service-module.js | 26 +++---------------- 5 files changed, 47 insertions(+), 35 deletions(-) diff --git a/src/service-module/new-api/index.ts b/src/service-module/new-api/index.ts index b5d28e64..9c52ee30 100644 --- a/src/service-module/new-api/index.ts +++ b/src/service-module/new-api/index.ts @@ -11,14 +11,27 @@ import models from './global-models' const defaultOptions: FeathersVuexOptions = { autoRemove: false, // Automatically remove records missing from responses (only use with feathers-rest) + addOnUpsert: false, // Add new records pushed by 'updated/patched' socketio events into store, instead of discarding them + diffOnPatch: true, // Only send changed data on patch. Sends the full object if set to false. + enableEvents: true, // Listens to socket.io events when available idField: 'id', // The field in each record that will contain the id - debug: false, - nameStyle: 'short', - preferUpdate: false, - serverAlias: '' + debug: false, // Set to true to enable logging messages. + keepCopiesInStore: false, // Set to true to store cloned copies in the store instead of on the Model. + nameStyle: 'short', // Determines the source of the module name. 'short', 'path', or 'explicit' + paramsForServer: [], // Custom query operators that are ignored in the find getter, but will pass through to the server. + preferUpdate: false, // When true, calling model.save() will do an update instead of a patch. + replaceItems: false, // Instad of merging in changes in the store, replace the entire record. + serverAlias: '', + skipRequestIfExists: false, // For get action, if the record already exists in store, skip the remote request + whitelist: [] // Custom query operators that will be allowed in the find getter. } export default function feathersVuex(feathers, options: FeathersVuexOptions) { + if (!feathers || !feathers.service) { + throw new Error( + 'You must provide a service path or object to create a feathers-vuex service module' + ) + } options = Object.assign({}, defaultOptions, options) const BaseModel = makeModel(options) const makeServicePlugin = prepareMakeServicePlugin(options) diff --git a/src/service-module/new-api/make-service-plugin.test.ts b/src/service-module/new-api/make-service-plugin.test.ts index 10fa3bb8..e7408725 100644 --- a/src/service-module/new-api/make-service-plugin.test.ts +++ b/src/service-module/new-api/make-service-plugin.test.ts @@ -35,15 +35,23 @@ describe('makeServicePlugin', function() { const keys = Object.keys(store.state.todos.options) const received = _pick(store.state.todos.options, keys) const expected = { + addOnUpsert: false, autoRemove: false, debug: false, + diffOnPatch: true, + enableEvents: true, idField: 'id', + keepCopiesInStore: false, modelName: 'Todo', nameStyle: 'short', namespace: 'todos', + paramsForServer: [], preferUpdate: false, + replaceItems: false, serverAlias: 'default', - servicePath: 'todos' + servicePath: 'todos', + skipRequestIfExists: false, + whitelist: [] } assert.deepEqual(received, expected, 'The module was registered.') diff --git a/src/service-module/new-api/make-service-plugin.ts b/src/service-module/new-api/make-service-plugin.ts index 8e24bdb6..fae775ff 100644 --- a/src/service-module/new-api/make-service-plugin.ts +++ b/src/service-module/new-api/make-service-plugin.ts @@ -9,12 +9,13 @@ import { prepareAddModel } from './add-model' import { makeNamespace, getServicePath } from '../../utils' const defaults = { - namespace: '', + namespace: '', // The namespace for the Vuex module. Will generally be derived from the service.path, service.name, when available. Otherwise, it must be provided here, explicitly. + nameStyle: 'short', // Determines the source of the module name. 'short', 'path', or 'explicit' servicePath: '', - state: {}, - getters: {}, - mutations: {}, - actions: {} + state: {}, // for custom state + getters: {}, // for custom getters + mutations: {}, // for custom mutations + actions: {} // for custom actions } /** diff --git a/src/service-module/new-api/types.ts b/src/service-module/new-api/types.ts index 06e11174..442e6a27 100644 --- a/src/service-module/new-api/types.ts +++ b/src/service-module/new-api/types.ts @@ -4,18 +4,28 @@ eslint */ export interface FeathersVuexOptions { serverAlias: string + addOnUpsert?: boolean autoRemove?: boolean + debug?: boolean + diffOnPatch?: boolean + enableEvents?: boolean idField?: string + keepCopiesInStore?: boolean nameStyle?: string + paramsForServer?: string[] preferUpdate?: boolean - debug?: boolean + replaceItems?: boolean + skipRequestIfExists?: boolean + whitelist?: string[] } export interface MakeServicePluginOptions { Model: any service: any - namespace?: string + addOnUpsert?: boolean + diffOnPatch?: boolean enableEvents?: boolean + namespace?: string servicePath?: string state?: {} getters?: {} diff --git a/src/service-module/service-module.js b/src/service-module/service-module.js index 3f6d2c44..d42554db 100644 --- a/src/service-module/service-module.js +++ b/src/service-module/service-module.js @@ -4,25 +4,11 @@ import makeMutations from './mutations' import makeActions from './actions' import makeModel from './model' -const defaults = { - nameStyle: 'short', // Determines the source of the module name. 'short', 'path', or 'explicit' - enableEvents: true, // Listens to socket.io events when available - addOnUpsert: false, // Add new records pushed by 'updated/patched' socketio events into store, instead of discarding them - diffOnPatch: false, // Only send changed data on patch - skipRequestIfExists: false, // For get action, if the record already exists in store, skip the remote request - preferUpdate: false, // When true, calling model.save() will do an update instead of a patch. +const differencesToDocument = { apiPrefix: '', // Setting to 'api1/' will prefix the store moduleName, unless `namespace` is used, then this is ignored. - debug: false, // Set to true to enable logging messages. - modelName: '', // The location of this service's Model in the Vue plugin (globalModels object). Added in the servicePlugin method + modelName: '', // The location of this service's Model in the Vue plugin (globalModels object). Added in the servicePlugin method : NOW DERIVED FROM Model.name instanceDefaults: {}, // The default values for the instance when `const instance =new Model()` - replaceItems: false, // Instad of merging in changes in the store, replace the entire record. - keepCopiesInStore: false, // Set to true to store cloned copies in the store instead of on the Model. - paramsForServer: [], // Custom query operators that are ignored in the find getter, but will pass through to the server. - whitelist: [], // Custom query operators that will be allowed in the find getter. - state: {}, // for custom state - getters: {}, // for custom getters - mutations: {}, // for custom mutations - actions: {} // for custom actions + diffOnPatch: true // This is now true by default } export default function servicePluginInit( @@ -40,12 +26,6 @@ export default function servicePluginInit( globalOptions = Object.assign({}, defaults, globalOptions) const serviceModule = function serviceModule(servicePath, options = {}) { - if (!feathersClient || !feathersClient.service) { - throw new Error( - 'You must provide a service path or object to create a feathers-vuex service module' - ) - } - options = Object.assign({}, globalOptions, options) const { debug, apiPrefix } = options From 93286c15676da4507981fd771969e3b8e1d10872 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 16:54:56 -0600 Subject: [PATCH 015/404] Throw error if no feathers client is passed --- src/service-module/new-api/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/new-api/index.ts b/src/service-module/new-api/index.ts index 9c52ee30..3153feec 100644 --- a/src/service-module/new-api/index.ts +++ b/src/service-module/new-api/index.ts @@ -29,7 +29,7 @@ const defaultOptions: FeathersVuexOptions = { export default function feathersVuex(feathers, options: FeathersVuexOptions) { if (!feathers || !feathers.service) { throw new Error( - 'You must provide a service path or object to create a feathers-vuex service module' + 'The first argument to feathersVuex must be a feathers client.' ) } options = Object.assign({}, defaultOptions, options) From d0224400f6ebe4dbae7b2a7b7130a1cc9d0df7c8 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 17:40:51 -0600 Subject: [PATCH 016/404] Add models[serverAlias]byServicePath --- src/service-module/new-api/add-model.ts | 5 ++++- src/service-module/new-api/global-models.ts | 4 +--- src/service-module/new-api/model.test.ts | 11 +++++++++++ src/service-module/service-module.js | 14 ++------------ 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/service-module/new-api/add-model.ts b/src/service-module/new-api/add-model.ts index 08e45623..a766882a 100644 --- a/src/service-module/new-api/add-model.ts +++ b/src/service-module/new-api/add-model.ts @@ -14,10 +14,13 @@ export function prepareAddModel(options: FeathersVuexOptions) { const { serverAlias } = options return function addModel(Model) { - globalModels[serverAlias] = globalModels[serverAlias] || {} + globalModels[serverAlias] = globalModels[serverAlias] || { + byServicePath: {} + } if (globalModels[serverAlias][Model.name] && options.debug) { console.error(`Overwriting Model: models[${serverAlias}][${Model.name}].`) } globalModels[serverAlias][Model.name] = Model + globalModels[serverAlias].byServicePath[Model.servicePath] = Model } } diff --git a/src/service-module/new-api/global-models.ts b/src/service-module/new-api/global-models.ts index 7cd22d22..657069d5 100644 --- a/src/service-module/new-api/global-models.ts +++ b/src/service-module/new-api/global-models.ts @@ -3,8 +3,6 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -const globalModels: { [k: string]: Record } = { - byServicePath: {} -} +const globalModels: { [k: string]: Record } = {} export default globalModels diff --git a/src/service-module/new-api/model.test.ts b/src/service-module/new-api/model.test.ts index 88bf27e3..73c9e771 100644 --- a/src/service-module/new-api/model.test.ts +++ b/src/service-module/new-api/model.test.ts @@ -178,5 +178,16 @@ describe('makeModel / BaseModel', function() { assert(!models.theirApi.Todo, `Todo stayed out of the 'theirApi' namespace`) assert(models.theirApi.Task === Task) assert(!models.myApi.Task, `Task stayed out of the 'myApi' namespace`) + + assert.equal( + models.myApi.byServicePath[Todo.servicePath], + Todo, + 'also registered in models.byServicePath' + ) + assert.equal( + models.theirApi.byServicePath[Task.servicePath], + Task, + 'also registered in models.byServicePath' + ) }) }) diff --git a/src/service-module/service-module.js b/src/service-module/service-module.js index d42554db..ebcf2378 100644 --- a/src/service-module/service-module.js +++ b/src/service-module/service-module.js @@ -8,7 +8,8 @@ const differencesToDocument = { apiPrefix: '', // Setting to 'api1/' will prefix the store moduleName, unless `namespace` is used, then this is ignored. modelName: '', // The location of this service's Model in the Vue plugin (globalModels object). Added in the servicePlugin method : NOW DERIVED FROM Model.name instanceDefaults: {}, // The default values for the instance when `const instance =new Model()` - diffOnPatch: true // This is now true by default + diffOnPatch: true, // This is now true by default + 'service-setup-outside': true // You no longer just pass a servicePath, but instead an entire service object. } export default function servicePluginInit( @@ -16,7 +17,6 @@ export default function servicePluginInit( globalOptions = {}, globalModels = {} ) { - globalModels.byServicePath = globalModels.byServicePath || {} if (!feathersClient || !feathersClient.service) { throw new Error( 'You must provide a Feathers Client instance to feathers-vuex' @@ -26,16 +26,6 @@ export default function servicePluginInit( globalOptions = Object.assign({}, defaults, globalOptions) const serviceModule = function serviceModule(servicePath, options = {}) { - options = Object.assign({}, globalOptions, options) - const { debug, apiPrefix } = options - - if (typeof servicePath !== 'string') { - throw new Error( - 'The first argument to setup a feathers-vuex service must be a string' - ) - } - - const service = feathersClient.service(servicePath) if (!service) { throw new Error( 'No service was found. Please configure a transport plugin on the Feathers Client. Make sure you use the client version of the transport, like `feathers-socketio/client` or `feathers-rest/client`.' From 879363d2182eeec35e6eb96bec73d9f0db8ae282 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 19:20:20 -0600 Subject: [PATCH 017/404] Throw if no service is provided --- src/service-module/new-api/make-service-plugin.ts | 6 ++++++ src/service-module/service-module.js | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/service-module/new-api/make-service-plugin.ts b/src/service-module/new-api/make-service-plugin.ts index fae775ff..943e99b8 100644 --- a/src/service-module/new-api/make-service-plugin.ts +++ b/src/service-module/new-api/make-service-plugin.ts @@ -35,6 +35,12 @@ export default function prepareMakeServicePlugin( const options = Object.assign({}, defaults, globalOptions, config) const { Model, service, namespace, nameStyle } = options + if (!service) { + throw new Error( + 'No service was provided. If you passed one in, check that you have configured a transport plugin on the Feathers Client. Make sure you use the client version of the transport`.' + ) + } + // Make sure we get a service path from either the service or the options let { servicePath } = options if (!servicePath) { diff --git a/src/service-module/service-module.js b/src/service-module/service-module.js index ebcf2378..61cd7fd5 100644 --- a/src/service-module/service-module.js +++ b/src/service-module/service-module.js @@ -26,11 +26,6 @@ export default function servicePluginInit( globalOptions = Object.assign({}, defaults, globalOptions) const serviceModule = function serviceModule(servicePath, options = {}) { - if (!service) { - throw new Error( - 'No service was found. Please configure a transport plugin on the Feathers Client. Make sure you use the client version of the transport, like `feathers-socketio/client` or `feathers-rest/client`.' - ) - } const paginate = service.hasOwnProperty('paginate') && service.paginate.hasOwnProperty('default') From 9bbc1366c748df463d19c30ddf62721037d2d1dc Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 21:33:22 -0600 Subject: [PATCH 018/404] Reorganize and add more docs --- .vscode/launch.json | 2 +- notes.md => notes.old.md | 0 package.json | 2 +- .../{auth-module.js => auth-module.ts} | 16 +- src/index.js | 32 --- src/{service-module/new-api => }/index.ts | 38 ++- .../add-model.ts => global-models.ts} | 6 +- .../{new-api => }/make-model.ts | 2 +- src/service-module/make-service-module.ts | 46 ++++ .../{new-api => }/make-service-plugin.ts | 4 +- src/service-module/{model.js => model.old.js} | 0 src/service-module/{new-api => }/model.ts | 0 .../model/model.make-service-module.old | 70 ------ .../model/model.service-module.old | 237 ------------------ .../{actions.js => module.actions.ts} | 67 +++-- .../{getters.js => module.getters.ts} | 26 +- .../{mutations.js => module.mutations.ts} | 143 ++++++----- .../{state.js => module.state.ts} | 7 +- src/service-module/new-api/global-models.ts | 8 - .../new-api/make-service-module.ts | 34 --- src/service-module/new-api/notes.md | 29 --- src/service-module/notes.md | 205 +++++++++++++++ src/service-module/service-module.js | 68 ----- src/service-module/{new-api => }/types.ts | 0 .../{vue-plugin.js => vue-plugin.ts} | 10 +- .../make-service-plugin.test.ts | 13 +- .../service-module/model-base.test.ts | 4 +- tsconfig.json | 2 +- 28 files changed, 473 insertions(+), 598 deletions(-) rename notes.md => notes.old.md (100%) rename src/auth-module/{auth-module.js => auth-module.ts} (74%) delete mode 100644 src/index.js rename src/{service-module/new-api => }/index.ts (66%) rename src/service-module/{new-api/add-model.ts => global-models.ts} (82%) rename src/service-module/{new-api => }/make-model.ts (99%) create mode 100644 src/service-module/make-service-module.ts rename src/service-module/{new-api => }/make-service-plugin.ts (96%) rename src/service-module/{model.js => model.old.js} (100%) rename src/service-module/{new-api => }/model.ts (100%) delete mode 100644 src/service-module/model/model.make-service-module.old delete mode 100644 src/service-module/model/model.service-module.old rename src/service-module/{actions.js => module.actions.ts} (82%) rename src/service-module/{getters.js => module.getters.ts} (74%) rename src/service-module/{mutations.js => module.mutations.ts} (74%) rename src/service-module/{state.js => module.state.ts} (84%) delete mode 100644 src/service-module/new-api/global-models.ts delete mode 100644 src/service-module/new-api/make-service-module.ts delete mode 100644 src/service-module/new-api/notes.md create mode 100644 src/service-module/notes.md delete mode 100644 src/service-module/service-module.js rename src/service-module/{new-api => }/types.ts (100%) rename src/vue-plugin/{vue-plugin.js => vue-plugin.ts} (62%) rename {src/service-module/new-api => test/service-module}/make-service-plugin.test.ts (90%) rename src/service-module/new-api/model.test.ts => test/service-module/model-base.test.ts (98%) diff --git a/.vscode/launch.json b/.vscode/launch.json index f2888c29..f5636140 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -18,7 +18,7 @@ "999999", "--colors", "--recursive", - "${workspaceFolder}/src/**/*.ts" + "${workspaceFolder}/test/**/*.ts" ], "internalConsoleOptions": "openOnSessionStart" }, diff --git a/notes.md b/notes.old.md similarity index 100% rename from notes.md rename to notes.old.md diff --git a/package.json b/package.json index 7f46d214..ac465027 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "lint": "standard --fix", "coverage": "istanbul cover node_modules/mocha/bin/_mocha -- --opts mocha.opts", "test": "npm run lint && npm run test-node && npm run testee", - "test-ts": "mocha --require ts-node/register src/**/*.test.ts", + "test-ts": "mocha --require ts-node/register test/**/*.test.ts]", "test-node": "mocha --opts mocha.opts", "testee": "testee test/index.html --browsers firefox", "start": "npm run compile && node example/app", diff --git a/src/auth-module/auth-module.js b/src/auth-module/auth-module.ts similarity index 74% rename from src/auth-module/auth-module.js rename to src/auth-module/auth-module.ts index 9f9b4832..dcabb0a2 100644 --- a/src/auth-module/auth-module.js +++ b/src/auth-module/auth-module.ts @@ -1,7 +1,13 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ import setupState from './state' import setupGetters from './getters' import setupMutations from './mutations' import setupActions from './actions' +import { globalModels } from '../service-module/global-models' const defaults = { namespace: 'auth', @@ -12,16 +18,18 @@ const defaults = { actions: {} // for custom actions } -export default function authPluginInit (feathersClient, globalOptions = {}, globalModels = {}) { +export default function authPluginInit(feathersClient) { if (!feathersClient || !feathersClient.service) { throw new Error('You must pass a Feathers Client instance to feathers-vuex') } - return function createAuthModule (options) { + return function createAuthModule(options) { options = Object.assign({}, defaults, options) if (!feathersClient.authenticate) { - throw new Error('You must register the @feathersjs/authentication-client plugin before using the feathers-vuex auth module') + throw new Error( + 'You must register the @feathersjs/authentication-client plugin before using the feathers-vuex auth module' + ) } const defaultState = setupState(options) @@ -29,7 +37,7 @@ export default function authPluginInit (feathersClient, globalOptions = {}, glob const defaultMutations = setupMutations(feathersClient) const defaultActions = setupActions(feathersClient, globalModels) - return function setupStore (store) { + return function setupStore(store) { const { namespace } = options store.registerModule(namespace, { diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 0fac8a0c..00000000 --- a/src/index.js +++ /dev/null @@ -1,32 +0,0 @@ -import setupServiceModule from './service-module/service-module' -import setupAuthModule from './auth-module/auth-module' -import setupVuePlugin from './vue-plugin/vue-plugin' -import FeathersVuexFind from './FeathersVuexFind' -import FeathersVuexGet from './FeathersVuexGet' -import makeFindMixin from './make-find-mixin' -import makeGetMixin from './make-get-mixin' -import { initAuth } from './utils' - -const globalDefaults = { - idField: 'id', // The field in each record that will contain the id - autoRemove: false, // automatically remove records missing from responses (only use with feathers-rest) - nameStyle: 'short', // Determines the source of the module name. 'short', 'path', or 'explicit' - apiPrefix: '' // Setting to 'api1/' will prefix the store moduleName, unless `namespace` is used, then this is ignored. -} -const globalModels = { - byServicePath: {} -} - -export { initAuth, FeathersVuexFind, FeathersVuexGet, makeFindMixin, makeGetMixin } - -export default function (feathersClient, globalOptions = {}) { - globalOptions = Object.assign({}, globalDefaults, globalOptions) - - return { - service: setupServiceModule(feathersClient, globalOptions, globalModels), - auth: setupAuthModule(feathersClient, globalOptions, globalModels), - FeathersVuex: setupVuePlugin(globalModels), - FeathersVuexFind, - FeathersVuexGet - } -} diff --git a/src/service-module/new-api/index.ts b/src/index.ts similarity index 66% rename from src/service-module/new-api/index.ts rename to src/index.ts index 3153feec..1b303081 100644 --- a/src/service-module/new-api/index.ts +++ b/src/index.ts @@ -3,11 +3,18 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import { FeathersVuexOptions } from './types' -import prepareMakeServicePlugin from './make-service-plugin' -import makeModel from './make-model' -import { prepareAddModel } from './add-model' -import models from './global-models' +import setupAuthModule from './auth-module/auth-module' +import FeathersVuexFind from './FeathersVuexFind' +import FeathersVuexGet from './FeathersVuexGet' +import makeFindMixin from './make-find-mixin' +import makeGetMixin from './make-get-mixin' +import { globalModels } from './service-module/global-models' +import makeModel from './service-module/make-model' +import prepareMakeServicePlugin from './service-module/make-service-plugin' + +import { FeathersVuexOptions } from './service-module/types' +import { initAuth } from './utils' +import setupVuePlugin from './vue-plugin/vue-plugin' const defaultOptions: FeathersVuexOptions = { autoRemove: false, // Automatically remove records missing from responses (only use with feathers-rest) @@ -33,14 +40,29 @@ export default function feathersVuex(feathers, options: FeathersVuexOptions) { ) } options = Object.assign({}, defaultOptions, options) + + if (!options.serverAlias) { + throw new Error( + `You must provide a 'serverAlias' in the options to feathersVuex` + ) + } + const BaseModel = makeModel(options) const makeServicePlugin = prepareMakeServicePlugin(options) - const addModel = prepareAddModel(options) return { makeServicePlugin, BaseModel, - addModel, - models + makeAuthPlugin: setupAuthModule(feathers), + FeathersVuex: setupVuePlugin(), + models: globalModels } } + +export { + initAuth, + FeathersVuexFind, + FeathersVuexGet, + makeFindMixin, + makeGetMixin +} diff --git a/src/service-module/new-api/add-model.ts b/src/service-module/global-models.ts similarity index 82% rename from src/service-module/new-api/add-model.ts rename to src/service-module/global-models.ts index a766882a..9aea82fe 100644 --- a/src/service-module/new-api/add-model.ts +++ b/src/service-module/global-models.ts @@ -4,7 +4,11 @@ eslint @typescript-eslint/no-explicit-any: 0 */ import { FeathersVuexOptions } from './types' -import globalModels from './global-models' + +/** + * A global object that holds references to all Model Classes in the application. + */ +export const globalModels: { [k: string]: Record } = {} /** * prepareAddModel wraps options in a closure around addModel diff --git a/src/service-module/new-api/make-model.ts b/src/service-module/make-model.ts similarity index 99% rename from src/service-module/new-api/make-model.ts rename to src/service-module/make-model.ts index b0678851..a979b1d8 100644 --- a/src/service-module/new-api/make-model.ts +++ b/src/service-module/make-model.ts @@ -4,7 +4,7 @@ eslint @typescript-eslint/no-explicit-any: 0 */ import { FeathersVuexOptions } from './types' -import globalModels from './global-models' +import { globalModels } from './global-models' import Vue from 'vue' /** diff --git a/src/service-module/make-service-module.ts b/src/service-module/make-service-module.ts new file mode 100644 index 00000000..23c584dd --- /dev/null +++ b/src/service-module/make-service-module.ts @@ -0,0 +1,46 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import _omit from 'lodash.omit' +import _pick from 'lodash.pick' + +import makeDefaultState from './module.state' +import makeGetters from './module.getters' +import makeMutations from './module.mutations' +import makeActions from './module.actions' + +export default function makeServiceModule(service, options) { + const nonStateProps = [ + 'Model', + 'service', + 'state', + 'getters', + 'mutations', + 'actions' + ] + const stateOptions = _omit(options, nonStateProps) + const nonStateOptions = _pick(options, nonStateProps) + + const defaultState = makeDefaultState(stateOptions.servicePath, stateOptions) + const defaultGetters = makeGetters() + const defaultMutations = makeMutations(stateOptions.servicePath, options) + const defaultActions = makeActions(service, options) + + Object.assign(stateOptions, { + modelName: options.Model.name + }) + + return { + namespaced: true, + state: Object.assign( + { options: stateOptions }, + defaultState, + nonStateOptions.state + ), + getters: Object.assign({}, defaultGetters, options.getters), + mutations: Object.assign({}, defaultMutations, options.mutations), + actions: Object.assign({}, defaultActions, options.actions) + } +} diff --git a/src/service-module/new-api/make-service-plugin.ts b/src/service-module/make-service-plugin.ts similarity index 96% rename from src/service-module/new-api/make-service-plugin.ts rename to src/service-module/make-service-plugin.ts index 943e99b8..c1bb57b0 100644 --- a/src/service-module/new-api/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -5,8 +5,8 @@ eslint */ import { FeathersVuexOptions, MakeServicePluginOptions } from './types' import makeServiceModule from './make-service-module' -import { prepareAddModel } from './add-model' -import { makeNamespace, getServicePath } from '../../utils' +import { prepareAddModel } from './global-models' +import { makeNamespace, getServicePath } from '../utils' const defaults = { namespace: '', // The namespace for the Vuex module. Will generally be derived from the service.path, service.name, when available. Otherwise, it must be provided here, explicitly. diff --git a/src/service-module/model.js b/src/service-module/model.old.js similarity index 100% rename from src/service-module/model.js rename to src/service-module/model.old.js diff --git a/src/service-module/new-api/model.ts b/src/service-module/model.ts similarity index 100% rename from src/service-module/new-api/model.ts rename to src/service-module/model.ts diff --git a/src/service-module/model/model.make-service-module.old b/src/service-module/model/model.make-service-module.old deleted file mode 100644 index aa3f3094..00000000 --- a/src/service-module/model/model.make-service-module.old +++ /dev/null @@ -1,70 +0,0 @@ -/* -eslint -@typescript-eslint/explicit-function-return-type: 0, -@typescript-eslint/no-explicit-any: 0 -*/ -// import { Module } from 'vuex' -const globalModels = {} -function makeState(servicePath, stateOptions) {} -function makeGetters(servicePath) {} -function makeMutations(servicePath, options) {} -function makeActions(servicePath, options) {} -// import makeState from '../state' -// import makeGetters from '../getters' -// import makeMutations from '../mutations' -// import makeActions from '../actions' - -function makeServiceModule( - servicePath: string, - options = { - state: {}, - mutations: {}, - actions: {}, - getters: {} - } -) { - // const { debug, apiPrefix } = options - - if (typeof servicePath !== 'string') { - throw new Error( - 'The first argument to setup a feathers-vuex service must be a string' - ) - } - - // test variables - const service = { - paginate: {} - } - const debug = false - const apiPrefix = '' - - // const service = feathersClient.service(servicePath) - if (!service) { - throw new Error( - 'No service was found. Please configure a transport plugin on the Feathers Client. Make sure you use the client version of the transport, like `feathers-socketio/client` or `feathers-rest/client`.' - ) - } - const paginate = - service.hasOwnProperty('paginate') && - service.paginate.hasOwnProperty('default') - const stateOptions = Object.assign(options, { paginate }) - - const defaultState = makeState(servicePath, stateOptions) - const defaultGetters = makeGetters(servicePath) - const defaultMutations = makeMutations(servicePath, { - debug, - globalModels, - apiPrefix - }) - const defaultActions = makeActions(service, { debug }) - const module = { - namespaced: true, - state: Object.assign({}, defaultState, options.state), - getters: Object.assign({}, defaultGetters, options.getters), - mutations: Object.assign({}, defaultMutations, options.mutations), - actions: Object.assign({}, defaultActions, options.actions) - } - return module -} - -export default makeServiceModule diff --git a/src/service-module/model/model.service-module.old b/src/service-module/model/model.service-module.old deleted file mode 100644 index 6fd60b14..00000000 --- a/src/service-module/model/model.service-module.old +++ /dev/null @@ -1,237 +0,0 @@ -/* -eslint -@typescript-eslint/explicit-function-return-type: 0, -@typescript-eslint/no-explicit-any: 0 -*/ -import { getShortName, getNameFromPath, registerModel } from '../../utils' -import makeServiceModule from './model.make-service-module' - -function makeModel(options) {} -interface GlobalModels { - byServicePath?: Record -} - -const modelOptions = { - idField: 'id', // The field in each record that will contain the id - instanceDefaults: {}, // The default values for the instance when `const instance =new Model()` - modelName: '', // The location of this service's Model in the Vue plugin (globalModels object). Added in the servicePlugin method - preferUpdate: false // When true, calling model.save() will do an update instead of a patch. -} -const moduleOptions = { - state: {}, // for custom state - getters: {}, // for custom getters - mutations: {}, // for custom mutations - actions: {}, // for custom actions - paramsForServer: [], // Custom query operators that are ignored in the find getter, but will pass through to the server. - whitelist: [], // Custom query operators that will be allowed in the find getter. - keepCopiesInStore: false, // Set to true to store cloned copies in the store instead of on the Model. - skipRequestIfExists: false, // For get action, if the record already exists in store, skip the remote request - autoRemove: false, // Automatically remove records missing from responses (only use with feathers-rest) - diffOnPatch: false, // Only send changed data on patch - replaceItems: false, // Instad of merging in changes in the store, replace the entire record. - addOnUpsert: false // Add new records pushed by 'updated/patched' socketio events into store, instead of discarding them -} -const defaults = { - idField: 'id', // The field in each record that will contain the id - nameStyle: 'short', // Determines the source of the module name. 'short', 'path', or 'explicit' - enableEvents: true, // Listens to socket.io events when available - apiPrefix: '', // Setting to 'api1/' will prefix the store moduleName, unless `namespace` is used, then this is ignored. - debug: false // Set to true to enable logging messages. -} - -export default function servicePluginInit( - feathersClient, - globalOptions = {}, - globalModels: GlobalModels = {} -) { - globalModels.byServicePath = globalModels.byServicePath || {} - if (!feathersClient || !feathersClient.service) { - throw new Error( - 'You must provide a Feathers Client instance to feathers-vuex' - ) - } - - globalOptions = Object.assign({}, defaults, globalOptions) - - const options = {} - - const allOptions = Object.assign({}, globalOptions, moduleOptions, options) - - const serviceModule = makeServiceModule('service', allOptions) - - const serviceModel = function serviceModel(options) { - options = Object.assign({}, globalOptions, options, { globalModels }) - const Model = makeModel(options) - - return Model - } - - const servicePlugin = function servicePlugin( - module, - Model, - options = { - nameStyle: 'short', - apiPrefix: '', - namespace: '', - enableEvents: true - } - ) { - options = Object.assign({}, globalOptions, options) - const { servicePath } = module.state - const { nameStyle, apiPrefix } = options - const service = feathersClient.service(servicePath) - - const nameStyles = { - short: getShortName, - path: getNameFromPath - } - let namespace = options.namespace || nameStyles[nameStyle](servicePath) - - return function setupStore(store) { - service.FeathersVuexModel = Model - // Add servicePath to Model so it can be accessed - Object.defineProperties(Model, { - servicePath: { - value: servicePath - }, - namespace: { - value: namespace - }, - store: { - value: store - } - }) - - // Add Model to the globalModels object, so it's available in the Vue plugin - const modelInfo = registerModel( - Model, - globalModels, - apiPrefix, - servicePath - ) - - module.state.modelName = modelInfo.path - store.registerModule(namespace, module) - - Object.defineProperties(Model, { - className: { - value: modelInfo.name - }, - find: { - value(params) { - return store.dispatch(`${namespace}/find`, params) - } - }, - findInStore: { - value(params) { - return store.getters[`${namespace}/find`](params) - } - }, - get: { - value(id, params) { - if (params) { - return store.dispatch(`${namespace}/get`, [id, params]) - } else { - return store.dispatch(`${namespace}/get`, id) - } - } - }, - getFromStore: { - value(id, params) { - if (params) { - return store.getters[`${namespace}/get`]([id, params]) - } else { - return store.getters[`${namespace}/get`](id) - } - } - } - }) - - // Upgrade the Model's API methods to use the store.actions - Object.defineProperties(Model.prototype, { - _clone: { - value(id) { - store.commit(`${namespace}/createCopy`, id) - - if (store.state[namespace].keepCopiesInStore) { - return store.getters[`${namespace}/getCopyById`](id) - } else { - return Model.copiesById[id] - } - } - }, - _commit: { - value(id) { - store.commit(`${namespace}/commitCopy`, id) - - return this._clone(id) - } - }, - _reset: { - value(id) { - store.commit(`${namespace}/rejectCopy`, id) - } - }, - _create: { - value(data, params) { - return store.dispatch(`${namespace}/create`, [data, params]) - } - }, - _patch: { - value(id, data, params) { - return store.dispatch(`${namespace}/patch`, [id, data, params]) - } - }, - _update: { - value(id, data, params) { - return store.dispatch(`${namespace}/update`, [id, data, params]) - } - }, - _remove: { - value(id, params) { - return store.dispatch(`${namespace}/remove`, [id, params]) - } - } - }) - - if (options.enableEvents) { - // Listen to socket events when available. - service.on('created', item => - store.commit(`${namespace}/addItem`, item) - ) - service.on('updated', item => - store.commit(`${namespace}/updateItem`, item) - ) - service.on('patched', item => - store.commit(`${namespace}/updateItem`, item) - ) - service.on('removed', item => - store.commit(`${namespace}/removeItem`, item) - ) - } - } - } - - const createServicePlugin = function createServicePlugin( - servicePath, - options = { - state: {}, - mutations: {}, - actions: {}, - getters: {} - } - ) { - const module = makeServiceModule(servicePath, options) - const Model = serviceModel(options) - - return servicePlugin(module, Model /*options*/) - } - - Object.assign(createServicePlugin, { - serviceModule, - serviceModel, - servicePlugin - }) - - return createServicePlugin -} diff --git a/src/service-module/actions.js b/src/service-module/module.actions.ts similarity index 82% rename from src/service-module/actions.js rename to src/service-module/module.actions.ts index 935a049d..44ae3a36 100644 --- a/src/service-module/actions.js +++ b/src/service-module/module.actions.ts @@ -1,8 +1,14 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ import { checkId, diffFunctions } from '../utils' -export default function makeServiceActions (service, { debug }) { +export default function makeServiceActions(service, { debug }) { const serviceActions = { - find ({ commit, dispatch, getters, state }, params = {}) { + find({ commit, dispatch, state }, params) { + params = params || {} const { idField } = state const handleResponse = response => { const { qid = 'default', query } = params @@ -45,13 +51,16 @@ export default function makeServiceActions (service, { debug }) { commit('setFindPending') - return service.find(params).then(handleResponse).catch(handleError) + return service + .find(params) + .then(handleResponse) + .catch(handleError) }, // Two query syntaxes are supported, since actions only receive one argument. // 1. Just pass the id: `get(1)` // 2. Pass arguments as an array: `get([null, params])` - get ({ state, getters, commit, dispatch }, args) { + get({ state, getters, commit, dispatch }, args) { const { idField } = state let id let params @@ -72,9 +81,10 @@ export default function makeServiceActions (service, { debug }) { skipRequestIfExists = state.skipRequestIfExists } - function getFromRemote () { + function getFromRemote() { commit('setGetPending') - return service.get(id, params) + return service + .get(id, params) .then(item => { const id = item[idField] @@ -105,7 +115,7 @@ export default function makeServiceActions (service, { debug }) { return getFromRemote() }, - create ({ commit, dispatch, state }, dataOrArray) { + create({ commit, dispatch, state }, dataOrArray) { const { idField } = state let data let params @@ -121,7 +131,8 @@ export default function makeServiceActions (service, { debug }) { commit('setCreatePending') - return service.create(data, params) + return service + .create(data, params) .then(response => { if (Array.isArray(response)) { dispatch('addOrUpdateList', response) @@ -151,12 +162,13 @@ export default function makeServiceActions (service, { debug }) { }) }, - update ({ commit, dispatch, state }, [id, data, params]) { + update({ commit, dispatch, state }, [id, data, params]) { const { idField } = state commit('setUpdatePending') - return service.update(id, data, params) + return service + .update(id, data, params) .then(item => { const id = item[idField] dispatch('addOrUpdate', item) @@ -170,7 +182,7 @@ export default function makeServiceActions (service, { debug }) { }) }, - patch ({ commit, dispatch, state }, [id, data, params]) { + patch({ commit, dispatch, state }, [id, data, params]) { const { idField, diffOnPatch } = state commit('setPatchPending') @@ -179,7 +191,7 @@ export default function makeServiceActions (service, { debug }) { const { observableDiff, applyChange } = diffFunctions() let diff = {} - observableDiff(state.copy, data, function (d) { + observableDiff(state.copy, data, function(d) { if (d.path && d.path.length) { // Apply all changes except to the id property... if (d.path[d.path.length - 1] !== idField) { @@ -191,7 +203,8 @@ export default function makeServiceActions (service, { debug }) { data = diff } - return service.patch(id, data, params) + return service + .patch(id, data, params) .then(item => { const id = item[idField] @@ -206,7 +219,7 @@ export default function makeServiceActions (service, { debug }) { }) }, - remove ({ commit, dispatch }, idOrArray) { + remove({ commit }, idOrArray) { let id let params @@ -221,7 +234,8 @@ export default function makeServiceActions (service, { debug }) { commit('setRemovePending') - return service.remove(id, params) + return service + .remove(id, params) .then(item => { commit('removeItem', id) commit('unsetRemovePending') @@ -236,8 +250,8 @@ export default function makeServiceActions (service, { debug }) { } const actions = { - afterFind ({ commit, dispatch, getters, state }, response) {}, - addOrUpdateList ({ state, commit }, response) { + afterFind() {}, + addOrUpdateList({ state, commit }, response) { const list = response.data || response const isPaginated = response.hasOwnProperty('total') const toAdd = [] @@ -245,7 +259,7 @@ export default function makeServiceActions (service, { debug }) { const toRemove = [] const { idField, autoRemove } = state - list.forEach((item, index) => { + list.forEach(item => { let id = item[idField] let existingItem = state.keyedById[id] @@ -259,7 +273,10 @@ export default function makeServiceActions (service, { debug }) { if (!isPaginated && autoRemove) { // Find IDs from the state which are not in the list state.ids.forEach(id => { - if (id !== state.currentId && !list.some(item => item[idField] === id)) { + if ( + id !== state.currentId && + !list.some(item => item[idField] === id) + ) { toRemove.push(state.keyedById[id]) } }) @@ -268,21 +285,27 @@ export default function makeServiceActions (service, { debug }) { if (service.FeathersVuexModel) { toAdd.forEach((item, index) => { - toAdd[index] = new service.FeathersVuexModel(item, { skipCommit: true }) + toAdd[index] = new service.FeathersVuexModel(item, { + skipCommit: true + }) }) } commit('addItems', toAdd) commit('updateItems', toUpdate) }, - addOrUpdate ({ state, commit }, item) { + addOrUpdate({ state, commit }, item) { const { idField } = state let id = item[idField] let existingItem = state.keyedById[id] const isIdOk = checkId(id, item, debug) - if (service.FeathersVuexModel && !existingItem && !item.isFeathersVuexInstance) { + if ( + service.FeathersVuexModel && + !existingItem && + !item.isFeathersVuexInstance + ) { item = new service.FeathersVuexModel(item) } diff --git a/src/service-module/getters.js b/src/service-module/module.getters.ts similarity index 74% rename from src/service-module/getters.js rename to src/service-module/module.getters.ts index dbf6fb4f..22aa1910 100644 --- a/src/service-module/getters.js +++ b/src/service-module/module.getters.ts @@ -1,3 +1,8 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ import sift from 'sift' import commons from '@feathersjs/commons' import dbCommons from '@feathersjs/adapter-commons' @@ -5,20 +10,23 @@ import omit from 'lodash.omit' const { _ } = commons const { filterQuery, sorter, select } = dbCommons -const FILTERS = [ '$sort', '$limit', '$skip', '$select' ] -const OPERATORS = [ '$in', '$nin', '$lt', '$lte', '$gt', '$gte', '$ne', '$or' ] -const additionalOperators = [ '$elemMatch' ] +const FILTERS = ['$sort', '$limit', '$skip', '$select'] +const OPERATORS = ['$in', '$nin', '$lt', '$lte', '$gt', '$gte', '$ne', '$or'] +const additionalOperators = ['$elemMatch'] const defaultOps = FILTERS.concat(OPERATORS).concat(additionalOperators) -export default function makeServiceGetters (servicePath) { +export default function makeServiceGetters() { return { - list (state) { + list(state) { return state.ids.map(id => state.keyedById[id]) }, - find: state => (params = {}) => { + find: state => params => { + params = params || {} const { paramsForServer, whitelist } = state const q = omit(params.query || {}, paramsForServer) - const customOperators = Object.keys(q).filter(k => k[0] === '$' && !defaultOps.includes(k)) + const customOperators = Object.keys(q).filter( + k => k[0] === '$' && !defaultOps.includes(k) + ) const cleanQuery = omit(q, customOperators) const { query, filters } = filterQuery(cleanQuery, { @@ -55,10 +63,10 @@ export default function makeServiceGetters (servicePath) { get: ({ keyedById, idField }) => (id, params = {}) => { return keyedById[id] ? select(params, idField)(keyedById[id]) : undefined }, - current (state) { + current(state) { return state.currentId ? state.keyedById[state.currentId] : null }, - getCopy (state) { + getCopy(state) { return state.copy ? state.copy : null }, getCopyById: state => id => { diff --git a/src/service-module/mutations.js b/src/service-module/module.mutations.ts similarity index 74% rename from src/service-module/mutations.js rename to src/service-module/module.mutations.ts index 143697d5..43f675ad 100644 --- a/src/service-module/mutations.js +++ b/src/service-module/module.mutations.ts @@ -1,13 +1,21 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ import Vue from 'vue' import _merge from 'lodash.merge' import serializeError from 'serialize-error' import isObject from 'lodash.isobject' import { checkId, updateOriginal } from '../utils' -export default function makeServiceMutations (servicePath, { debug, globalModels }) { +export default function makeServiceMutations( + servicePath, + { debug, globalModels } +) { globalModels = globalModels || { byServicePath: {} } - function addItems (state, items) { + function addItems(state, items) { const { idField } = state const Model = globalModels.byServicePath[servicePath] @@ -34,7 +42,7 @@ export default function makeServiceMutations (servicePath, { debug, globalModels state.keyedById = newKeyedById } - function updateItems (state, items) { + function updateItems(state, items) { const { idField, replaceItems, addOnUpsert } = state const Model = globalModels.byServicePath[servicePath] @@ -51,12 +59,12 @@ export default function makeServiceMutations (servicePath, { debug, globalModels item = new Model(item) } Vue.set(state.keyedById, id, item) - // Merge in changes + // Merge in changes } else { updateOriginal(item, state.keyedById[id]) } - // if addOnUpsert then add the record into the state, else discard it. + // if addOnUpsert then add the record into the state, else discard it. } else if (addOnUpsert) { state.ids.push(id) Vue.set(state.keyedById, id, item) @@ -67,23 +75,25 @@ export default function makeServiceMutations (servicePath, { debug, globalModels } return { - addItem (state, item) { + addItem(state, item) { addItems(state, [item]) }, - addItems (state, items) { + addItems(state, items) { addItems(state, items) }, - updateItem (state, item) { + updateItem(state, item) { updateItems(state, [item]) }, - updateItems (state, items) { + updateItems(state, items) { if (!Array.isArray(items)) { - throw new Error('You must provide an array to the `updateItems` mutation.') + throw new Error( + 'You must provide an array to the `updateItems` mutation.' + ) } updateItems(state, items) }, - removeItem (state, item) { + removeItem(state, item) { const { idField } = state const idToBeRemoved = isObject(item) ? item[idField] : item const { currentId } = state @@ -101,15 +111,19 @@ export default function makeServiceMutations (servicePath, { debug, globalModels } }, - removeItems (state, items) { + removeItems(state, items) { const { idField, currentId } = state if (!Array.isArray(items)) { - throw new Error('You must provide an array to the `removeItems` mutation.') + throw new Error( + 'You must provide an array to the `removeItems` mutation.' + ) } // Make sure we have an array of ids. Assume all are the same. const containsObjects = items[0] && isObject(items[0]) - const idsToRemove = containsObjects ? items.map(item => item[idField]) : items + const idsToRemove = containsObjects + ? items.map(item => item[idField]) + : items const mapOfIdsToRemove = idsToRemove.reduce((map, id) => { map[id] = true return map @@ -126,15 +140,17 @@ export default function makeServiceMutations (servicePath, { debug, globalModels return map }, {}) // Remove highest indexes first, so the indexes don't change - const indexesInReverseOrder = Object.keys(mapOfIndexesToRemove).sort((a, b) => { - if (a < b) { - return 1 - } else if (a > b) { - return -1 - } else { - return 0 + const indexesInReverseOrder = Object.keys(mapOfIndexesToRemove).sort( + (a, b) => { + if (a < b) { + return 1 + } else if (a > b) { + return -1 + } else { + return 0 + } } - }) + ) indexesInReverseOrder.forEach(indexInIdsArray => { Vue.delete(state.ids, indexInIdsArray) }) @@ -145,14 +161,14 @@ export default function makeServiceMutations (servicePath, { debug, globalModels } }, - clearAll (state) { + clearAll(state) { state.ids = [] state.currentId = null state.copy = null state.keyedById = {} }, - clearList (state) { + clearList(state) { let currentId = state.currentId let current = state.keyedById[currentId] @@ -167,7 +183,7 @@ export default function makeServiceMutations (servicePath, { debug, globalModels } }, - setCurrent (state, itemOrId) { + setCurrent(state, itemOrId) { const { idField } = state const Model = globalModels.byServicePath[servicePath] let id @@ -185,20 +201,20 @@ export default function makeServiceMutations (servicePath, { debug, globalModels state.copy = new Model(item, { isClone: true }) }, - clearCurrent (state) { + clearCurrent(state) { state.currentId = null state.copy = null }, // Removes the copy from copiesById - clearCopy (state, id) { + clearCopy(state, id) { const newCopiesById = Object.assign({}, state.copiesById) delete newCopiesById[id] state.copiesById = newCopiesById }, // Creates a copy of the record with the passed-in id, stores it in copiesById - createCopy (state, id) { + createCopy(state, id) { const current = state.keyedById[id] const Model = globalModels.byServicePath[servicePath] const copyData = _merge({}, current) @@ -212,9 +228,11 @@ export default function makeServiceMutations (servicePath, { debug, globalModels }, // Resets the copy to match the original record, locally - rejectCopy (state, id) { + rejectCopy(state, id) { const isIdOk = checkId(id, undefined, debug) - const current = isIdOk ? state.keyedById[id] : state.keyedById[state.currentId] + const current = isIdOk + ? state.keyedById[id] + : state.keyedById[state.currentId] const Model = globalModels.byServicePath[servicePath] let copy @@ -228,9 +246,11 @@ export default function makeServiceMutations (servicePath, { debug, globalModels }, // Deep assigns copy to original record, locally - commitCopy (state, id) { + commitCopy(state, id) { const isIdOk = checkId(id, undefined, debug) - const current = isIdOk ? state.keyedById[id] : state.keyedById[state.currentId] + const current = isIdOk + ? state.keyedById[id] + : state.keyedById[state.currentId] const Model = globalModels.byServicePath[servicePath] let copy @@ -247,87 +267,94 @@ export default function makeServiceMutations (servicePath, { debug, globalModels // Stores pagination data on state.pagination based on the query identifier (qid) // The qid must be manually assigned to `params.qid` - updatePaginationForQuery (state, { qid, response, query }) { + updatePaginationForQuery(state, { qid, response, query }) { const { data, limit, skip, total } = response const { idField } = state const ids = data.map(item => { return item[idField] }) const queriedAt = new Date().getTime() - Vue.set(state.pagination, qid, { limit, skip, total, ids, query, queriedAt }) + Vue.set(state.pagination, qid, { + limit, + skip, + total, + ids, + query, + queriedAt + }) }, - setFindPending (state) { + setFindPending(state) { state.isFindPending = true }, - unsetFindPending (state) { + unsetFindPending(state) { state.isFindPending = false }, - setGetPending (state) { + setGetPending(state) { state.isGetPending = true }, - unsetGetPending (state) { + unsetGetPending(state) { state.isGetPending = false }, - setCreatePending (state) { + setCreatePending(state) { state.isCreatePending = true }, - unsetCreatePending (state) { + unsetCreatePending(state) { state.isCreatePending = false }, - setUpdatePending (state) { + setUpdatePending(state) { state.isUpdatePending = true }, - unsetUpdatePending (state) { + unsetUpdatePending(state) { state.isUpdatePending = false }, - setPatchPending (state) { + setPatchPending(state) { state.isPatchPending = true }, - unsetPatchPending (state) { + unsetPatchPending(state) { state.isPatchPending = false }, - setRemovePending (state) { + setRemovePending(state) { state.isRemovePending = true }, - unsetRemovePending (state) { + unsetRemovePending(state) { state.isRemovePending = false }, - setFindError (state, payload) { + setFindError(state, payload) { state.errorOnFind = Object.assign({}, serializeError(payload)) }, - clearFindError (state) { + clearFindError(state) { state.errorOnFind = null }, - setGetError (state, payload) { + setGetError(state, payload) { state.errorOnGet = Object.assign({}, serializeError(payload)) }, - clearGetError (state) { + clearGetError(state) { state.errorOnGet = null }, - setCreateError (state, payload) { + setCreateError(state, payload) { state.errorOnCreate = Object.assign({}, serializeError(payload)) }, - clearCreateError (state) { + clearCreateError(state) { state.errorOnCreate = null }, - setUpdateError (state, payload) { + setUpdateError(state, payload) { state.errorOnUpdate = Object.assign({}, serializeError(payload)) }, - clearUpdateError (state) { + clearUpdateError(state) { state.errorOnUpdate = null }, - setPatchError (state, payload) { + setPatchError(state, payload) { state.errorOnPatch = Object.assign({}, serializeError(payload)) }, - clearPatchError (state) { + clearPatchError(state) { state.errorOnPatch = null }, - setRemoveError (state, payload) { + setRemoveError(state, payload) { state.errorOnRemove = Object.assign({}, serializeError(payload)) }, - clearRemoveError (state) { + clearRemoveError(state) { state.errorOnRemove = null } } diff --git a/src/service-module/state.js b/src/service-module/module.state.ts similarity index 84% rename from src/service-module/state.js rename to src/service-module/module.state.ts index 6dcd3ca0..edad2ba3 100644 --- a/src/service-module/state.js +++ b/src/service-module/module.state.ts @@ -1,4 +1,9 @@ -export default function makeDefaultState (servicePath, options) { +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +export default function makeDefaultState(servicePath, options) { const { idField, autoRemove, diff --git a/src/service-module/new-api/global-models.ts b/src/service-module/new-api/global-models.ts deleted file mode 100644 index 657069d5..00000000 --- a/src/service-module/new-api/global-models.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* -eslint -@typescript-eslint/explicit-function-return-type: 0, -@typescript-eslint/no-explicit-any: 0 -*/ -const globalModels: { [k: string]: Record } = {} - -export default globalModels diff --git a/src/service-module/new-api/make-service-module.ts b/src/service-module/new-api/make-service-module.ts deleted file mode 100644 index 0eecd5dd..00000000 --- a/src/service-module/new-api/make-service-module.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* -eslint -@typescript-eslint/explicit-function-return-type: 0, -@typescript-eslint/no-explicit-any: 0 -*/ -import _omit from 'lodash.omit' -import _pick from 'lodash.pick' - -export default function makeServiceModule(service, options) { - const nonStateProps = [ - 'Model', - 'service', - 'state', - 'getters', - 'mutations', - 'actions' - ] - const stateOptions = _omit(options, nonStateProps) - const nonStateOptions = _pick(options, nonStateProps) - - Object.assign(stateOptions, { - modelName: options.Model.name - }) - - return { - namespaced: true, - state: { - options: stateOptions - }, - getters: {}, - mutations: {}, - actions: {} - } -} diff --git a/src/service-module/new-api/notes.md b/src/service-module/new-api/notes.md deleted file mode 100644 index f10b62f9..00000000 --- a/src/service-module/new-api/notes.md +++ /dev/null @@ -1,29 +0,0 @@ -# API Notes - -```ts -import feathers from './feathers-client' -import Vuex from 'vuex' -import feathersVuex from 'feathers-vuex' - -const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { - idField: '_id', - serverAlias: 'myApiServer' -}) - -// @service('todos') -class Todo extends BaseModel { - servicePath: 'todos' -} - -const servicePath = 'todos' -const todos = makeServicePlugin({ - Model: Todo, - service: feathers.service(servicePath) -}) - -const store = new Vuex.Store({ - plugins: [ - todos - ] -}) -``` diff --git a/src/service-module/notes.md b/src/service-module/notes.md new file mode 100644 index 00000000..5f378aca --- /dev/null +++ b/src/service-module/notes.md @@ -0,0 +1,205 @@ +# Differences in Feathers-Vuex 2.0 + +The biggest change in Feathers-Vuex 2.0 is that it has been refactored with TypeScript! + +> I will admit that I was less than excited to try out TypeScript. It definitely introduces a bigger learning curve. I'm not a fan of large barriers to entry, especially when it comes to software development. I thought "It's hard enough already!". And I still feel that's accurate, but it's not an excuse to stay away from TypeScript. I see now that it's actually one of the reasons to use TypeScript. +> +> It only took me a couple of hours to learn some of the basics of TypeScript. Most of the time was spent configuring Visual Studio Code in a way that I liked. For those interested in what I picked, check out [this article](https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project). Thank you, Robert Cooper for such a great setup. +> As I started devloping with TypeScript, I really appreciated how it started to rewire how I thought about code organization. The cdde is much cleaner, especially the service plugin. Some huge benefits came from this refactor. +> +> 1. The FeathersVuex Model class is now fully extendable. This introduces a new level of flexibility. +> 1. Test coverage has improved. The newly-organized code is much easier to test in smaller units. +> 1. Greater compatibility for communicating with multiple FeathersJS servers. The organized code made it easy to see where to add support for this. +> +> TypeScript users will likely notice plenty of room for more accurate types. I'm just getting started with this stuff. Please feel free to make PRs. I'm really excited to see what we can make out of this. + +```js +const differencesToDocument = { + instanceDefaults: {}, // The default values for the instance when `const instance =new Model()` +} +``` + +## Changes to Initialization + +1. To assist in connecting with multiple FeathersJS API servers, a new `serverAlias` option is now required. This requires a simple addition to the initial options. +2. The returned object has also changed. The `service` method has been renamed to `makeServicePlugin`. +3. The `auth` method is now called `makeAuthPlugin` +4. You get back the actual FeathersVuexModel / BaseModel. Feel free to extend it and make it fit your awesome apps! +5. You no longer pass a `servicePath` to create a service-plugin. Instead, pass the actual Feathers service. +6. Since you can customize the Model, you also pass the model into the `makeServicePlugin` method. + +```js +import feathers from './feathers-client' +import Vuex from 'vuex' +import feathersVuex from 'feathers-vuex' + +const { + BaseModel, + makeServicePlugin, // (2^) + makeAuthPlugin, // (3^) + FeathersVuex, + models // (4^) +} = feathersVuex(feathers, { + idField: '_id', + serverAlias: 'myApiServer' // (1^) +}) + +class Todo extends BaseModel { + // customize the model as you see fit! +} + +const todosPlugin = makeServicePlugin({ + Model: Todo, // (6^) + service: feathers.service('todos') // (5^) +}) + +const store = new Vuex.Store({ + plugins: [ + todosPlugin + ] +}) +``` + +## FeathersVuex Vue plugin changes + +The Vue plugin is registered in exactly the same way. The difference comes when you try to find the Model classes in the `$FeathersVuex` object. Instead of finding models directly on the `$FeathersVuex` object, they are namespaced by the `serverAlias` you provided. This allows cleaner support for multiple APIs. Supposing you had this code in a component, previously... + +```js +created () { + // The old way + const { Todo } = this.$FeathersVuex +} +``` + +Modify it to include the new `serverAlias`. Suppose you set a `serverAlias` of `myApi`, you'd put this in the new version: + +```js +created () { + // The new way includes the `serverAlias` of '.myApi' + const { Todo } = this.$FeathersVuex.myApi +} +``` + +## Changes to service module state + +The options are no longer at the root level of the service module state. You'll find them all in the options key: + +```js +const state = { + // ... + options: { + addOnUpsert: false, + autoRemove: false, + debug: false, + diffOnPatch: true, + enableEvents: true, + idField: 'id', + keepCopiesInStore: false, + modelName: 'Todo', + nameStyle: 'short', + namespace: 'todos', + paramsForServer: [], + preferUpdate: false, + replaceItems: false, + serverAlias: 'default', + servicePath: 'todos', + skipRequestIfExists: false, + whitelist: [] + }, + // ... +} +``` + +## The `diffOnPatch` option is turned on by default + +In Feathers-Vuex 2.0, the `diffOnPatch` option is enabled, by default. This means that only the necessary data is sent to the API server. Set `diffOnPatch: false` in the options to revert back to the old way. + +## The `modelName` option has been removed + +Previous versions of Feathers-Vuex only supported a single FeathersVuexModel class, which was difficult to customize. This limitation required internal use of using inflections or passing a `modelName`. Version 2.0, with its full support for extending the FeathersVuexModel/BaseModel class no longer requires this option. Just name your class something new: + +```js +const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { serverAlias: 'myApi' }) + +class Todo extends BaseModel { + public static exampleProp: string = 'Hello, World! (notice the comma, folks!)' +} + +const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathers.service(servicePath) + }) + ] +}) +``` + +## The 'apiPrefix' option has been removed + +Feathers-Vuex now includes full support for communicating with multiple FeathersJS APIs. The `apiPrefix` option was a poorly implemented, hacky first attempt at this same feature. It was buggy. Since it didn't work as intended, it has been removed. See this example test for working with multiple APIs: + +```js +import { assert } from 'chai' +import Vue from 'vue' +import Vuex from 'vuex' +import { + feathersRestClient as feathers, + makeFeathersRestClient +} from '../../test/fixtures/feathers-client' +import feathersVuex from './index' + +it('works with multiple, independent Feathers servers', function() { + // Connect to myApi, create a Todo Model & Plugin + const feathersMyApi = makeFeathersRestClient('https://api.my-api.com') + const myApi = feathersVuex(feathersMyApi, { + idField: '_id', + serverAlias: 'myApi' + }) + class Todo extends myApi.BaseModel { + public test: boolean = true + } + const todosPlugin = myApi.makeServicePlugin({ + Model: Todo, + service: feathersMyApi.service('todos') + }) + + // Create a Task Model & Plugin on theirApi + const feathersTheirApi = makeFeathersRestClient('https://api.their-api.com') + const theirApi = feathersVuex(feathersTheirApi, { + serverAlias: 'theirApi' + }) + class Task extends theirApi.BaseModel { + public test: boolean = true + } + const tasksPlugin = theirApi.makeServicePlugin({ + Model: Task, + service: feathersTheirApi.service('tasks') + }) + + // Register the plugins + new Vuex.Store({ + plugins: [todosPlugin, tasksPlugin] + }) + const { models } = myApi + + assert(models.myApi.Todo === Todo) + assert(!models.theirApi.Todo, `Todo stayed out of the 'theirApi' namespace`) + assert(models.theirApi.Task === Task) + assert(!models.myApi.Task, `Task stayed out of the 'myApi' namespace`) + + assert.equal( + models.myApi.byServicePath[Todo.servicePath], + Todo, + 'also registered in models.byServicePath' + ) + assert.equal( + models.theirApi.byServicePath[Task.servicePath], + Task, + 'also registered in models.byServicePath' + ) +``` + +## Services are no longer set up internally + +You no longer just pass a servicePath, but instead an entire service object. \ No newline at end of file diff --git a/src/service-module/service-module.js b/src/service-module/service-module.js deleted file mode 100644 index 61cd7fd5..00000000 --- a/src/service-module/service-module.js +++ /dev/null @@ -1,68 +0,0 @@ -import makeState from './state' -import makeGetters from './getters' -import makeMutations from './mutations' -import makeActions from './actions' -import makeModel from './model' - -const differencesToDocument = { - apiPrefix: '', // Setting to 'api1/' will prefix the store moduleName, unless `namespace` is used, then this is ignored. - modelName: '', // The location of this service's Model in the Vue plugin (globalModels object). Added in the servicePlugin method : NOW DERIVED FROM Model.name - instanceDefaults: {}, // The default values for the instance when `const instance =new Model()` - diffOnPatch: true, // This is now true by default - 'service-setup-outside': true // You no longer just pass a servicePath, but instead an entire service object. -} - -export default function servicePluginInit( - feathersClient, - globalOptions = {}, - globalModels = {} -) { - if (!feathersClient || !feathersClient.service) { - throw new Error( - 'You must provide a Feathers Client instance to feathers-vuex' - ) - } - - globalOptions = Object.assign({}, defaults, globalOptions) - - const serviceModule = function serviceModule(servicePath, options = {}) { - const paginate = - service.hasOwnProperty('paginate') && - service.paginate.hasOwnProperty('default') - const stateOptions = Object.assign(options, { paginate }) - - const defaultState = makeState(servicePath, stateOptions) - const defaultGetters = makeGetters(servicePath) - const defaultMutations = makeMutations(servicePath, { - debug, - globalModels, - apiPrefix - }) - const defaultActions = makeActions(service, { debug }) - const module = { - namespaced: true, - state: Object.assign({}, defaultState, options.state), - getters: Object.assign({}, defaultGetters, options.getters), - mutations: Object.assign({}, defaultMutations, options.mutations), - actions: Object.assign({}, defaultActions, options.actions) - } - return module - } - - const serviceModel = function serviceModel(options) { - options = Object.assign({}, globalOptions, options, { globalModels }) - const Model = makeModel(options) - - return Model - } - - const servicePlugin = function servicePlugin(module, Model, options = {}) { - options = Object.assign({}, globalOptions, options) - const { servicePath } = module.state - - module.state.modelName = modelInfo.path - store.registerModule(namespace, module) - } - - return createServicePlugin -} diff --git a/src/service-module/new-api/types.ts b/src/service-module/types.ts similarity index 100% rename from src/service-module/new-api/types.ts rename to src/service-module/types.ts diff --git a/src/vue-plugin/vue-plugin.js b/src/vue-plugin/vue-plugin.ts similarity index 62% rename from src/vue-plugin/vue-plugin.js rename to src/vue-plugin/vue-plugin.ts index b3daa394..afc93331 100644 --- a/src/vue-plugin/vue-plugin.js +++ b/src/vue-plugin/vue-plugin.ts @@ -1,9 +1,15 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ import FeathersVuexFind from '../FeathersVuexFind' import FeathersVuexGet from '../FeathersVuexGet' +import { globalModels } from '../service-module/global-models' -export default function setupVuePlugin (globalModels) { +export default function setupVuePlugin() { return { - install (Vue, options = {}) { + install(Vue, options = { components: true }) { const shouldSetupComponents = options.components !== false Vue.$FeathersVuex = globalModels diff --git a/src/service-module/new-api/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts similarity index 90% rename from src/service-module/new-api/make-service-plugin.test.ts rename to test/service-module/make-service-plugin.test.ts index e7408725..0bf4fc0a 100644 --- a/src/service-module/new-api/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -6,8 +6,8 @@ eslint import { assert } from 'chai' import Vue from 'vue' import Vuex, { StoreOptions } from 'vuex' -import { feathersRestClient as feathers } from '../../../test/fixtures/feathers-client' -import feathersVuex from './index' +import { feathersRestClient as feathers } from '../../test/fixtures/feathers-client' +import feathersVuex from '../../src/index' import _pick from 'lodash.pick' Vue.use(Vuex) @@ -77,16 +77,15 @@ describe('makeServicePlugin', function() { it('allows accessing other models', function() { const serverAlias = 'default' - const { makeServicePlugin, BaseModel, addModel, models } = feathersVuex( - feathers, - { idField: '_id', serverAlias } - ) + const { makeServicePlugin, BaseModel, models } = feathersVuex(feathers, { + idField: '_id', + serverAlias + }) const servicePath = 'todos' class Todo extends BaseModel { public servicePath = servicePath } - addModel(Todo) const todosPlugin = makeServicePlugin({ Model: Todo, service: feathers.service(servicePath) diff --git a/src/service-module/new-api/model.test.ts b/test/service-module/model-base.test.ts similarity index 98% rename from src/service-module/new-api/model.test.ts rename to test/service-module/model-base.test.ts index 73c9e771..03f1f3d8 100644 --- a/src/service-module/new-api/model.test.ts +++ b/test/service-module/model-base.test.ts @@ -9,8 +9,8 @@ import Vuex from 'vuex' import { feathersRestClient as feathers, makeFeathersRestClient -} from '../../../test/fixtures/feathers-client' -import feathersVuex from './index' +} from '../fixtures/feathers-client' +import feathersVuex from '../../src/index' Vue.use(Vuex) diff --git a/tsconfig.json b/tsconfig.json index 9dca8f43..7ae2605f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "outDir": "dist" }, "include": [ - "src/**/*" + "src/**/*", "test/**/*" ], "exclude": [ "node_modules", From a527a4643908832496c55de2e48bc6c9f4f1303a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 21:40:50 -0600 Subject: [PATCH 019/404] Lint cleanup --- src/FeathersVuexFind.js | 54 ++++++++------ src/FeathersVuexGet.js | 71 +++++++++++++------ .../make-service-plugin.test.ts | 2 +- 3 files changed, 85 insertions(+), 42 deletions(-) diff --git a/src/FeathersVuexFind.js b/src/FeathersVuexFind.js index 3a0b4b34..731cf714 100644 --- a/src/FeathersVuexFind.js +++ b/src/FeathersVuexFind.js @@ -9,7 +9,7 @@ export default { default: null }, queryWhen: { - type: [ Boolean, Function ], + type: [Boolean, Function], default: true }, // If a separate query is desired to fetch data, use fetchQuery @@ -18,8 +18,8 @@ export default { type: Object }, watch: { - type: [ String, Array ], - default () { + type: [String, Array], + default() { return [] } }, @@ -29,13 +29,13 @@ export default { }, editScope: { type: Function, - default (scope) { + default(scope) { return scope } }, qid: { type: String, - default () { + default() { return randomString(10) } } @@ -44,15 +44,15 @@ export default { isFindPending: false }), computed: { - items () { + items() { const { query, service, $store } = this return query ? $store.getters[`${service}/find`]({ query }).data : [] }, - pagination () { + pagination() { return this.$store.state[this.service].pagination[this.qid] }, - scope () { + scope() { const { items, isFindPending, pagination } = this const defaultScope = { isFindPending, pagination, items } @@ -60,10 +60,14 @@ export default { } }, methods: { - findData () { + findData() { const query = this.fetchQuery || this.query - if (typeof this.queryWhen === 'function' ? this.queryWhen(this.query) : this.queryWhen) { + if ( + typeof this.queryWhen === 'function' + ? this.queryWhen(this.query) + : this.queryWhen + ) { this.isFindPending = true if (query) { @@ -72,33 +76,42 @@ export default { if (this.qid) { params.qid = params.qid || this.qid } - return this.$store.dispatch(`${this.service}/find`, params) + return this.$store + .dispatch(`${this.service}/find`, params) .then(() => { this.isFindPending = false }) } } }, - fetchData () { + fetchData() { if (!this.local) { if (this.query) { return this.findData() } else { // TODO: access debug boolean from from the store config, somehow. - console.log(`No query and no id provided, so no data will be fetched.`) + console.log( + `No query and no id provided, so no data will be fetched.` + ) } } } }, - created () { + created() { if (!this.$FeathersVuex) { - throw new Error(`You must first Vue.use the FeathersVuex plugin before using the 'feathers-vuex-find' component.`) + throw new Error( + `You must first Vue.use the FeathersVuex plugin before using the 'feathers-vuex-find' component.` + ) } if (!this.$store.state[this.service]) { - throw new Error(`The '${this.service}' plugin cannot be found. Did you register the service with feathers-vuex?`) + throw new Error( + `The '${ + this.service + }' plugin cannot be found. Did you register the service with feathers-vuex?` + ) } - const watch = Array.isArray(this.watch) ? this.watch : [ this.watch ] + const watch = Array.isArray(this.watch) ? this.watch : [this.watch] if (this.fetchQuery || this.query) { watch.forEach(prop => { @@ -116,14 +129,15 @@ export default { this.fetchData() } }, - render () { + render() { return this.$scopedSlots.default(this.scope) } } -function randomString (length) { +function randomString(length) { let text = '' - let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' + let possible = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' for (let i = 0; i < length; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)) diff --git a/src/FeathersVuexGet.js b/src/FeathersVuexGet.js index 9a689834..76e1c9d2 100644 --- a/src/FeathersVuexGet.js +++ b/src/FeathersVuexGet.js @@ -9,12 +9,12 @@ export default { default: null }, queryWhen: { - type: [ Boolean, Function ], + type: [Boolean, Function], default: true }, // For get requests id: { - type: [ Number, String ], + type: [Number, String], default: null }, // If a separate query is desired to fetch data, use fetchQuery @@ -23,8 +23,8 @@ export default { type: Object }, watch: { - type: [ String, Array ], - default () { + type: [String, Array], + default() { return [] } }, @@ -34,7 +34,7 @@ export default { }, editScope: { type: Function, - default (scope) { + default(scope) { return scope } } @@ -44,16 +44,20 @@ export default { isGetPending: false }), computed: { - item () { + item() { const getArgs = this.getArgs(this.query) if (this.id) { - return this.$store.getters[`${this.service}/get`](getArgs.length === 1 ? this.id : getArgs) || null + return ( + this.$store.getters[`${this.service}/get`]( + getArgs.length === 1 ? this.id : getArgs + ) || null + ) } else { return null } }, - scope () { + scope() { const { item, isGetPending } = this const defaultScope = { item, isGetPending } @@ -61,7 +65,7 @@ export default { } }, methods: { - getArgs (queryToUse) { + getArgs(queryToUse) { const query = queryToUse || this.fetchQuery || this.query const getArgs = [this.id] @@ -71,41 +75,66 @@ export default { return getArgs }, - getData () { + getData() { const getArgs = this.getArgs() - if (typeof this.queryWhen === 'function' ? this.queryWhen(...getArgs) : this.queryWhen) { + if ( + typeof this.queryWhen === 'function' + ? this.queryWhen(...getArgs) + : this.queryWhen + ) { this.isGetPending = true if (this.id) { - return this.$store.dispatch(`${this.service}/get`, getArgs.length === 1 ? this.id : getArgs) + return this.$store + .dispatch( + `${this.service}/get`, + getArgs.length === 1 ? this.id : getArgs + ) .then(() => { this.isGetPending = false }) } } }, - fetchData () { + fetchData() { if (!this.local) { - if (this.id !== null && this.id !== undefined && !this.query && !this.fetchQuery) { + if ( + this.id !== null && + this.id !== undefined && + !this.query && + !this.fetchQuery + ) { return this.getData() } else { - console.log(`No query and no id provided, so no data will be fetched.`) + console.log( + `No query and no id provided, so no data will be fetched.` + ) } } } }, - created () { + created() { if (!this.$FeathersVuex) { - throw new Error(`You must first Vue.use the FeathersVuex plugin before using the 'feathers-vuex-get' component.`) + throw new Error( + `You must first Vue.use the FeathersVuex plugin before using the 'feathers-vuex-get' component.` + ) } if (!this.$store.state[this.service]) { - throw new Error(`The '${this.service}' plugin cannot be found. Did you register the service with feathers-vuex?`) + throw new Error( + `The '${ + this.service + }' plugin cannot be found. Did you register the service with feathers-vuex?` + ) } - const watch = Array.isArray(this.watch) ? this.watch : [ this.watch ] + const watch = Array.isArray(this.watch) ? this.watch : [this.watch] - if (this.fetchQuery || this.query || (this.id !== null && this.id !== undefined)) { + if ( + this.fetchQuery || + this.query || + (this.id !== null && this.id !== undefined) + ) { watch.forEach(prop => { if (typeof prop !== 'string') { throw new Error(`Values in the 'watch' array must be strings.`) @@ -121,7 +150,7 @@ export default { this.fetchData() } }, - render () { + render() { return this.$scopedSlots.default(this.scope) } } diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index 0bf4fc0a..9fb18861 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -5,7 +5,7 @@ eslint */ import { assert } from 'chai' import Vue from 'vue' -import Vuex, { StoreOptions } from 'vuex' +import Vuex from 'vuex' import { feathersRestClient as feathers } from '../../test/fixtures/feathers-client' import feathersVuex from '../../src/index' import _pick from 'lodash.pick' From 23768374b9af34bb1425c5d75752529d795318e5 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 21:41:04 -0600 Subject: [PATCH 020/404] Update notes --- src/service-module/notes.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 5f378aca..448b1166 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -5,7 +5,10 @@ The biggest change in Feathers-Vuex 2.0 is that it has been refactored with Type > I will admit that I was less than excited to try out TypeScript. It definitely introduces a bigger learning curve. I'm not a fan of large barriers to entry, especially when it comes to software development. I thought "It's hard enough already!". And I still feel that's accurate, but it's not an excuse to stay away from TypeScript. I see now that it's actually one of the reasons to use TypeScript. > > It only took me a couple of hours to learn some of the basics of TypeScript. Most of the time was spent configuring Visual Studio Code in a way that I liked. For those interested in what I picked, check out [this article](https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project). Thank you, Robert Cooper for such a great setup. -> As I started devloping with TypeScript, I really appreciated how it started to rewire how I thought about code organization. The cdde is much cleaner, especially the service plugin. Some huge benefits came from this refactor. +> +> As I started devloping with TypeScript, I really appreciated how it started to rewire how I thought about code organization. The cdde is much cleaner, especially the service plugin. When adding Model support in Feathers-Vuex 1.0, I ran into a difficult race condition. The Models need the store to first be initialized. But the store actions/mutations need the Models to first be initialized. In version 1.0 this resulted in a 115-line monkey patch! With TypeScript's assistance, I was able to see how to reduce it to a clean, two-line monkey patch. Much better! +> +> Some huge benefits came from this refactor. > > 1. The FeathersVuex Model class is now fully extendable. This introduces a new level of flexibility. > 1. Test coverage has improved. The newly-organized code is much easier to test in smaller units. From d9ca88f4d8888e8ea4a288b0d06a78d41875189c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 21:42:54 -0600 Subject: [PATCH 021/404] Move randomString util to utils file --- src/FeathersVuexFind.js | 14 ++------------ src/utils.ts | 12 ++++++++++++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/FeathersVuexFind.js b/src/FeathersVuexFind.js index 731cf714..007e1924 100644 --- a/src/FeathersVuexFind.js +++ b/src/FeathersVuexFind.js @@ -1,3 +1,5 @@ +import { randomString } from './utils' + export default { props: { service: { @@ -133,15 +135,3 @@ export default { return this.$scopedSlots.default(this.scope) } } - -function randomString(length) { - let text = '' - let possible = - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' - - for (let i = 0; i < length; i++) { - text += possible.charAt(Math.floor(Math.random() * possible.length)) - } - - return text -} diff --git a/src/utils.ts b/src/utils.ts index 8b9932bc..b6067729 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -273,3 +273,15 @@ export function getServicePath(service: any, modelName: string) { } return service.path || service.name } + +export function randomString(length) { + let text = '' + let possible = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' + + for (let i = 0; i < length; i++) { + text += possible.charAt(Math.floor(Math.random() * possible.length)) + } + + return text +} From 7781e438288fc9a30a7153b8a769844d9f7ff28a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 21:45:28 -0600 Subject: [PATCH 022/404] Switch extension on Components to .ts --- src/{FeathersVuexFind.js => FeathersVuexFind.ts} | 5 +---- src/{FeathersVuexGet.js => FeathersVuexGet.ts} | 0 2 files changed, 1 insertion(+), 4 deletions(-) rename src/{FeathersVuexFind.js => FeathersVuexFind.ts} (96%) rename src/{FeathersVuexGet.js => FeathersVuexGet.ts} (100%) diff --git a/src/FeathersVuexFind.js b/src/FeathersVuexFind.ts similarity index 96% rename from src/FeathersVuexFind.js rename to src/FeathersVuexFind.ts index 007e1924..c95cf79d 100644 --- a/src/FeathersVuexFind.js +++ b/src/FeathersVuexFind.ts @@ -73,11 +73,8 @@ export default { this.isFindPending = true if (query) { - const params = { query } + const params = { query, qid: this.qid || 'default' } - if (this.qid) { - params.qid = params.qid || this.qid - } return this.$store .dispatch(`${this.service}/find`, params) .then(() => { diff --git a/src/FeathersVuexGet.js b/src/FeathersVuexGet.ts similarity index 100% rename from src/FeathersVuexGet.js rename to src/FeathersVuexGet.ts From 8121601bc88d7865256ee7c9605e7cee1ddde742 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 21:47:22 -0600 Subject: [PATCH 023/404] Switch mixins to .ts --- ...{make-find-mixin.js => make-find-mixin.ts} | 99 +++++++++++++------ src/{make-get-mixin.js => make-get-mixin.ts} | 96 ++++++++++++------ 2 files changed, 136 insertions(+), 59 deletions(-) rename src/{make-find-mixin.js => make-find-mixin.ts} (68%) rename src/{make-get-mixin.js => make-get-mixin.ts} (66%) diff --git a/src/make-find-mixin.js b/src/make-find-mixin.ts similarity index 68% rename from src/make-find-mixin.js rename to src/make-find-mixin.ts index c5fa0211..edb1b9a2 100644 --- a/src/make-find-mixin.js +++ b/src/make-find-mixin.ts @@ -1,7 +1,21 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ import { getServicePrefix, getServiceCapitalization } from './utils' -export default function makeFindMixin (options) { - const { service, params, fetchQuery, queryWhen = () => true, local = false, qid = 'default', items, debug } = options +export default function makeFindMixin(options) { + const { + service, + params, + fetchQuery, + queryWhen = () => true, + local = false, + qid = 'default', + items, + debug + } = options let { name, watch = [] } = options if (typeof watch === 'string') { @@ -10,8 +24,13 @@ export default function makeFindMixin (options) { watch = ['params'] } - if (!service || (typeof service !== 'string' && typeof service !== 'function')) { - throw new Error(`The 'service' option is required in the FeathersVuex make-find-mixin and must be a string.`) + if ( + !service || + (typeof service !== 'string' && typeof service !== 'function') + ) { + throw new Error( + `The 'service' option is required in the FeathersVuex make-find-mixin and must be a string.` + ) } if (typeof service === 'function' && !name) { name = 'service' @@ -42,23 +61,27 @@ export default function makeFindMixin (options) { } const mixin = { - data () { + data() { return data }, computed: { - [ITEMS] () { - return this[PARAMS] ? this.$store.getters[`${this[SERVICE_NAME]}/find`](this[PARAMS]).data : [] + [ITEMS]() { + return this[PARAMS] + ? this.$store.getters[`${this[SERVICE_NAME]}/find`](this[PARAMS]).data + : [] }, - [ITEMS_FETCHED] () { + [ITEMS_FETCHED]() { if (this[FETCH_PARAMS]) { - return this.$store.getters[`${this[SERVICE_NAME]}/find`](this[FETCH_PARAMS]).data + return this.$store.getters[`${this[SERVICE_NAME]}/find`]( + this[FETCH_PARAMS] + ).data } else { return this[ITEMS] } } }, methods: { - [FIND_ACTION] (params) { + [FIND_ACTION](params) { let paramsToUse if (params) { paramsToUse = params @@ -69,7 +92,11 @@ export default function makeFindMixin (options) { } if (!this[LOCAL]) { - if (typeof this[QUERY_WHEN] === 'function' ? this[QUERY_WHEN](paramsToUse) : this[QUERY_WHEN]) { + if ( + typeof this[QUERY_WHEN] === 'function' + ? this[QUERY_WHEN](paramsToUse) + : this[QUERY_WHEN] + ) { this[IS_FIND_PENDING] = true if (paramsToUse) { @@ -79,7 +106,8 @@ export default function makeFindMixin (options) { paramsToUse.qid = qid } - return this.$store.dispatch(`${this[SERVICE_NAME]}/find`, paramsToUse) + return this.$store + .dispatch(`${this[SERVICE_NAME]}/find`, paramsToUse) .then(response => { this[IS_FIND_PENDING] = false return response @@ -89,8 +117,11 @@ export default function makeFindMixin (options) { } } }, - created () { - debug && console.log(`running 'created' hook in makeFindMixin for service "${service}" (using name ${nameToUse}")`) + created() { + debug && + console.log( + `running 'created' hook in makeFindMixin for service "${service}" (using name ${nameToUse}")` + ) debug && console.log(PARAMS, this[PARAMS]) debug && console.log(FETCH_PARAMS, this[FETCH_PARAMS]) @@ -116,35 +147,43 @@ export default function makeFindMixin (options) { if (!local) { // TODO: Add this message to the logging: // "Pass { local: true } to disable this warning and only do local queries." - console.log(`No "${PARAMS}" or "${FETCH_PARAMS}" attribute was found in the makeFindMixin for the "${service}" service (using name "${nameToUse}"). No queries will be made.`) + console.log( + `No "${PARAMS}" or "${FETCH_PARAMS}" attribute was found in the makeFindMixin for the "${service}" service (using name "${nameToUse}"). No queries will be made.` + ) } } } } if (qid) { - mixin.computed[PAGINATION] = function () { + mixin.computed[PAGINATION] = function() { return this.$store.state[this[SERVICE_NAME]].pagination[qid] } } - setupAttribute(SERVICE_NAME, service, 'computed', true) - setupAttribute(PARAMS, params) - setupAttribute(FETCH_PARAMS, fetchQuery) - setupAttribute(QUERY_WHEN, queryWhen, 'methods') - setupAttribute(LOCAL, local) + function hasSomeAttribute(vm, ...attributes) { + return attributes.some(a => { + return vm.hasOwnProperty(a) || Object.getPrototypeOf(vm).hasOwnProperty(a) + }) + } - function setupAttribute (NAME, value, computedOrMethods = 'computed', returnTheValue = false) { + function setupAttribute( + NAME, + value, + computedOrMethods = 'computed', + returnTheValue = false + ) { if (typeof value === 'boolean') { data[NAME] = !!value } else if (typeof value === 'string') { - mixin.computed[NAME] = function () { + mixin.computed[NAME] = function() { // If the specified computed prop wasn't found, display an error. if (returnTheValue) { - } else { if (!hasSomeAttribute(this, value, NAME)) { - throw new Error(`Value for ${NAME} was not found on the component at '${value}'.`) + throw new Error( + `Value for ${NAME} was not found on the component at '${value}'.` + ) } } return returnTheValue ? value : this[value] @@ -154,11 +193,11 @@ export default function makeFindMixin (options) { } } - function hasSomeAttribute (vm, ...attributes) { - return attributes.some(a => { - return vm.hasOwnProperty(a) || Object.getPrototypeOf(vm).hasOwnProperty(a) - }) - } + setupAttribute(SERVICE_NAME, service, 'computed', true) + setupAttribute(PARAMS, params) + setupAttribute(FETCH_PARAMS, fetchQuery) + setupAttribute(QUERY_WHEN, queryWhen, 'methods') + setupAttribute(LOCAL, local) return mixin } diff --git a/src/make-get-mixin.js b/src/make-get-mixin.ts similarity index 66% rename from src/make-get-mixin.js rename to src/make-get-mixin.ts index b3629fb9..5f428483 100644 --- a/src/make-get-mixin.js +++ b/src/make-get-mixin.ts @@ -1,7 +1,22 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ import inflection from 'inflection' -export default function makeFindMixin (options) { - const { service, params, fetchParams, queryWhen, id, local = false, qid = 'default', item, debug } = options +export default function makeFindMixin(options) { + const { + service, + params, + fetchParams, + queryWhen, + id, + local = false, + qid = 'default', + item, + debug + } = options let { name, watch = [] } = options if (typeof watch === 'string') { @@ -10,8 +25,13 @@ export default function makeFindMixin (options) { watch = ['query'] } - if (!service || (typeof service !== 'string' && typeof service !== 'function')) { - throw new Error(`The 'service' option is required in the FeathersVuex make-find-mixin and must be a string.`) + if ( + !service || + (typeof service !== 'string' && typeof service !== 'function') + ) { + throw new Error( + `The 'service' option is required in the FeathersVuex make-find-mixin and must be a string.` + ) } if (typeof service === 'function' && !name) { name = 'service' @@ -42,19 +62,21 @@ export default function makeFindMixin (options) { } const mixin = { - data () { + data() { return data }, computed: { - [ITEM] () { - return this[ID] ? this.$store.getters[`${this[SERVICE_NAME]}/get`](this[ID]) : null + [ITEM]() { + return this[ID] + ? this.$store.getters[`${this[SERVICE_NAME]}/get`](this[ID]) + : null }, - [QUERY_WHEN] () { + [QUERY_WHEN]() { return true } }, methods: { - [GET_ACTION] (id, params) { + [GET_ACTION](id, params) { const paramsToUse = params || this[FETCH_PARAMS] || this[PARAMS] const idToUse = id || this[ID] @@ -63,7 +85,8 @@ export default function makeFindMixin (options) { this[IS_GET_PENDING] = true if (idToUse) { - return this.$store.dispatch(`${this[SERVICE_NAME]}/get`, [ idToUse, paramsToUse ]) + return this.$store + .dispatch(`${this[SERVICE_NAME]}/get`, [idToUse, paramsToUse]) .then(response => { this[IS_GET_PENDING] = false return response @@ -73,15 +96,22 @@ export default function makeFindMixin (options) { } } }, - created () { - debug && console.log(`running 'created' hook in makeGetMixin for service "${service}" (using name ${nameToUse}")`) + created() { + debug && + console.log( + `running 'created' hook in makeGetMixin for service "${service}" (using name ${nameToUse}")` + ) debug && console.log(ID, this[ID]) debug && console.log(PARAMS, this[PARAMS]) debug && console.log(FETCH_PARAMS, this[FETCH_PARAMS]) const pType = Object.getPrototypeOf(this) - if (pType.hasOwnProperty(ID) || pType.hasOwnProperty(PARAMS) || pType.hasOwnProperty(FETCH_PARAMS)) { + if ( + pType.hasOwnProperty(ID) || + pType.hasOwnProperty(PARAMS) || + pType.hasOwnProperty(FETCH_PARAMS) + ) { if (!watch.includes(ID)) { watch.push(ID) } @@ -102,29 +132,36 @@ export default function makeFindMixin (options) { return this[GET_ACTION]() } else { - console.log(`No "${ID}", "${PARAMS}" or "${FETCH_PARAMS}" attribute was found in the makeGetMixin for the "${service}" service (using name "${nameToUse}"). No queries will be made.`) + console.log( + `No "${ID}", "${PARAMS}" or "${FETCH_PARAMS}" attribute was found in the makeGetMixin for the "${service}" service (using name "${nameToUse}"). No queries will be made.` + ) } } } - setupAttribute(SERVICE_NAME, service, 'computed', true) - setupAttribute(ID, id) - setupAttribute(PARAMS, params) - setupAttribute(FETCH_PARAMS, fetchParams) - setupAttribute(QUERY_WHEN, queryWhen, 'computed') - setupAttribute(LOCAL, local) + function hasSomeAttribute(vm, ...attributes) { + return attributes.some(a => { + return vm.hasOwnProperty(a) || Object.getPrototypeOf(vm).hasOwnProperty(a) + }) + } - function setupAttribute (NAME, value, computedOrMethods = 'computed', returnTheValue = false) { + function setupAttribute( + NAME, + value, + computedOrMethods = 'computed', + returnTheValue = false + ) { if (typeof value === 'boolean') { data[NAME] = !!value } else if (typeof value === 'string') { - mixin.computed[NAME] = function () { + mixin.computed[NAME] = function() { // If the specified computed prop wasn't found, display an error. if (returnTheValue) { - } else { if (!hasSomeAttribute(this, value, NAME)) { - throw new Error(`Value for ${NAME} was not found on the component at '${value}'.`) + throw new Error( + `Value for ${NAME} was not found on the component at '${value}'.` + ) } } return returnTheValue ? value : this[value] @@ -134,11 +171,12 @@ export default function makeFindMixin (options) { } } - function hasSomeAttribute (vm, ...attributes) { - return attributes.some(a => { - return vm.hasOwnProperty(a) || Object.getPrototypeOf(vm).hasOwnProperty(a) - }) - } + setupAttribute(SERVICE_NAME, service, 'computed', true) + setupAttribute(ID, id) + setupAttribute(PARAMS, params) + setupAttribute(FETCH_PARAMS, fetchParams) + setupAttribute(QUERY_WHEN, queryWhen, 'computed') + setupAttribute(LOCAL, local) return mixin } From 868507f5e1b7a736aaf4be58bbb2ce1780765222 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 21:50:29 -0600 Subject: [PATCH 024/404] Switch auth module to .ts files --- src/auth-module/{actions.js => actions.ts} | 48 ++++++++++++------- src/auth-module/auth-module.ts | 5 +- src/auth-module/getters.js | 5 -- src/auth-module/getters.ts | 10 ++++ .../{mutations.js => mutations.ts} | 31 +++++++----- src/auth-module/{state.js => state.ts} | 7 ++- 6 files changed, 67 insertions(+), 39 deletions(-) rename src/auth-module/{actions.js => actions.ts} (55%) delete mode 100644 src/auth-module/getters.js create mode 100644 src/auth-module/getters.ts rename src/auth-module/{mutations.js => mutations.ts} (56%) rename src/auth-module/{state.js => state.ts} (71%) diff --git a/src/auth-module/actions.js b/src/auth-module/actions.ts similarity index 55% rename from src/auth-module/actions.js rename to src/auth-module/actions.ts index 1354d0fb..022e18dc 100644 --- a/src/auth-module/actions.js +++ b/src/auth-module/actions.ts @@ -1,35 +1,47 @@ -export default function makeAuthActions (feathersClient, globalModels) { +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +export default function makeAuthActions(feathersClient) { return { - authenticate (store, data) { + authenticate(store, data) { const { commit, state, dispatch } = store commit('setAuthenticatePending') if (state.errorOnAuthenticate) { commit('clearAuthenticateError') } - return feathersClient.authenticate(data) + return feathersClient + .authenticate(data) .then(response => { if (response.accessToken) { commit('setAccessToken', response.accessToken) // Decode the token and set the payload, but return the response - return feathersClient.passport.verifyJWT(response.accessToken) + return feathersClient.passport + .verifyJWT(response.accessToken) .then(payload => { commit('setPayload', payload) // Populate the user if the userService was provided - if (state.userService && payload.hasOwnProperty(state.entityIdField)) { - return dispatch('populateUser', payload[state.entityIdField]) - .then(() => { - commit('unsetAuthenticatePending') - return response - }) + if ( + state.userService && + payload.hasOwnProperty(state.entityIdField) + ) { + return dispatch( + 'populateUser', + payload[state.entityIdField] + ).then(() => { + commit('unsetAuthenticatePending') + return response + }) } else { commit('unsetAuthenticatePending') } return response }) - // If there was not an accessToken in the response, allow the response to pass through to handle two-factor-auth + // If there was not an accessToken in the response, allow the response to pass through to handle two-factor-auth } else { return response } @@ -41,17 +53,19 @@ export default function makeAuthActions (feathersClient, globalModels) { }) }, - populateUser ({ commit, state, rootState, dispatch }, userId) { - return dispatch(`${state.userService}/get`, userId, { root: true }) - .then(user => { + populateUser({ commit, state, rootState, dispatch }, userId) { + return dispatch(`${state.userService}/get`, userId, { root: true }).then( + user => { commit('setUser', user) return user - }) + } + ) }, - logout ({ commit }) { + logout({ commit }) { commit('setLogoutPending') - return feathersClient.logout() + return feathersClient + .logout() .then(response => { commit('logout') commit('unsetLogoutPending') diff --git a/src/auth-module/auth-module.ts b/src/auth-module/auth-module.ts index dcabb0a2..d55c9956 100644 --- a/src/auth-module/auth-module.ts +++ b/src/auth-module/auth-module.ts @@ -7,7 +7,6 @@ import setupState from './state' import setupGetters from './getters' import setupMutations from './mutations' import setupActions from './actions' -import { globalModels } from '../service-module/global-models' const defaults = { namespace: 'auth', @@ -34,8 +33,8 @@ export default function authPluginInit(feathersClient) { const defaultState = setupState(options) const defaultGetters = setupGetters() - const defaultMutations = setupMutations(feathersClient) - const defaultActions = setupActions(feathersClient, globalModels) + const defaultMutations = setupMutations() + const defaultActions = setupActions(feathersClient) return function setupStore(store) { const { namespace } = options diff --git a/src/auth-module/getters.js b/src/auth-module/getters.js deleted file mode 100644 index e292c25b..00000000 --- a/src/auth-module/getters.js +++ /dev/null @@ -1,5 +0,0 @@ -export default function makeAuthGetters () { - return { - // Auth specific "Getters" will go here - } -} diff --git a/src/auth-module/getters.ts b/src/auth-module/getters.ts new file mode 100644 index 00000000..631d0940 --- /dev/null +++ b/src/auth-module/getters.ts @@ -0,0 +1,10 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +export default function makeAuthGetters() { + return { + // Auth specific "Getters" will go here + } +} diff --git a/src/auth-module/mutations.js b/src/auth-module/mutations.ts similarity index 56% rename from src/auth-module/mutations.js rename to src/auth-module/mutations.ts index 5ac84bd6..8123eb68 100644 --- a/src/auth-module/mutations.js +++ b/src/auth-module/mutations.ts @@ -1,44 +1,49 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ import serializeError from 'serialize-error' -export default function makeAuthMutations (feathers) { +export default function makeAuthMutations() { return { - setAccessToken (state, payload) { + setAccessToken(state, payload) { state.accessToken = payload }, - setPayload (state, payload) { + setPayload(state, payload) { state.payload = payload }, - setUser (state, payload) { + setUser(state, payload) { state.user = payload }, - setAuthenticatePending (state) { + setAuthenticatePending(state) { state.isAuthenticatePending = true }, - unsetAuthenticatePending (state) { + unsetAuthenticatePending(state) { state.isAuthenticatePending = false }, - setLogoutPending (state) { + setLogoutPending(state) { state.isLogoutPending = true }, - unsetLogoutPending (state) { + unsetLogoutPending(state) { state.isLogoutPending = false }, - setAuthenticateError (state, error) { + setAuthenticateError(state, error) { state.errorOnAuthenticate = Object.assign({}, serializeError(error)) }, - clearAuthenticateError (state) { + clearAuthenticateError(state) { state.errorOnAuthenticate = null }, - setLogoutError (state, error) { + setLogoutError(state, error) { state.errorOnLogout = Object.assign({}, serializeError(error)) }, - clearLogoutError (state) { + clearLogoutError(state) { state.errorOnLogout = null }, - logout (state) { + logout(state) { state.payload = null state.accessToken = null if (state.user) { diff --git a/src/auth-module/state.js b/src/auth-module/state.ts similarity index 71% rename from src/auth-module/state.js rename to src/auth-module/state.ts index 8906c31b..47dd8468 100644 --- a/src/auth-module/state.js +++ b/src/auth-module/state.ts @@ -1,4 +1,9 @@ -export default function setupAuthState ({ userService }) { +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +export default function setupAuthState({ userService }) { const state = { accessToken: null, // The JWT payload: null, // The JWT payload From b87be92d35c98aaecb84ee1583fd8d771560ccec Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 21:51:56 -0600 Subject: [PATCH 025/404] Remove unused variable --- src/auth-module/actions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/auth-module/actions.ts b/src/auth-module/actions.ts index 022e18dc..23eda9eb 100644 --- a/src/auth-module/actions.ts +++ b/src/auth-module/actions.ts @@ -53,7 +53,7 @@ export default function makeAuthActions(feathersClient) { }) }, - populateUser({ commit, state, rootState, dispatch }, userId) { + populateUser({ commit, state, dispatch }, userId) { return dispatch(`${state.userService}/get`, userId, { root: true }).then( user => { commit('setUser', user) From 0d2e7aaf66274504e957ead30ac0f9bd3396c3bf Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 22:08:56 -0600 Subject: [PATCH 026/404] Separate out auth response handler Closes #170 --- src/auth-module/actions.ts | 64 ++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/src/auth-module/actions.ts b/src/auth-module/actions.ts index 23eda9eb..4f3de751 100644 --- a/src/auth-module/actions.ts +++ b/src/auth-module/actions.ts @@ -15,36 +15,7 @@ export default function makeAuthActions(feathersClient) { return feathersClient .authenticate(data) .then(response => { - if (response.accessToken) { - commit('setAccessToken', response.accessToken) - - // Decode the token and set the payload, but return the response - return feathersClient.passport - .verifyJWT(response.accessToken) - .then(payload => { - commit('setPayload', payload) - - // Populate the user if the userService was provided - if ( - state.userService && - payload.hasOwnProperty(state.entityIdField) - ) { - return dispatch( - 'populateUser', - payload[state.entityIdField] - ).then(() => { - commit('unsetAuthenticatePending') - return response - }) - } else { - commit('unsetAuthenticatePending') - } - return response - }) - // If there was not an accessToken in the response, allow the response to pass through to handle two-factor-auth - } else { - return response - } + return dispatch('responseHandler', response) }) .catch(error => { commit('setAuthenticateError', error) @@ -53,6 +24,39 @@ export default function makeAuthActions(feathersClient) { }) }, + responseHandler({ commit, state, dispatch }, response) { + if (response.accessToken) { + commit('setAccessToken', response.accessToken) + + // Decode the token and set the payload, but return the response + return feathersClient.passport + .verifyJWT(response.accessToken) + .then(payload => { + commit('setPayload', payload) + + // Populate the user if the userService was provided + if ( + state.userService && + payload.hasOwnProperty(state.entityIdField) + ) { + return dispatch( + 'populateUser', + payload[state.entityIdField] + ).then(() => { + commit('unsetAuthenticatePending') + return response + }) + } else { + commit('unsetAuthenticatePending') + } + return response + }) + // If there was not an accessToken in the response, allow the response to pass through to handle two-factor-auth + } else { + return response + } + }, + populateUser({ commit, state, dispatch }, userId) { return dispatch(`${state.userService}/get`, userId, { root: true }).then( user => { From af172e96db3d2491860f681bf035f531a97fe486 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 22:54:00 -0600 Subject: [PATCH 027/404] change actions.test to .ts --- src/service-module/types.ts | 1 + test/service-module/actions.test.js | 784 ------------------- test/service-module/actions.test.ts | 1125 +++++++++++++++++++++++++++ 3 files changed, 1126 insertions(+), 784 deletions(-) delete mode 100644 test/service-module/actions.test.js create mode 100644 test/service-module/actions.test.ts diff --git a/src/service-module/types.ts b/src/service-module/types.ts index 442e6a27..0ea37143 100644 --- a/src/service-module/types.ts +++ b/src/service-module/types.ts @@ -25,6 +25,7 @@ export interface MakeServicePluginOptions { addOnUpsert?: boolean diffOnPatch?: boolean enableEvents?: boolean + idField?: string namespace?: string servicePath?: string state?: {} diff --git a/test/service-module/actions.test.js b/test/service-module/actions.test.js deleted file mode 100644 index c7b86f85..00000000 --- a/test/service-module/actions.test.js +++ /dev/null @@ -1,784 +0,0 @@ -import assert from 'chai/chai' -import setupVuexService from '~/src/service-module/service-module' -import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' -import Vuex, { mapActions } from 'vuex' -import memory from 'feathers-memory' - -const service = setupVuexService(feathersClient) -const makeStore = () => { - return { - 0: { id: 0, description: 'Do the first' }, - 1: { id: 1, description: 'Do the second' }, - 2: { id: 2, description: 'Do the third' }, - 3: { id: 3, description: 'Do the fourth' }, - 4: { id: 4, description: 'Do the fifth' }, - 5: { id: 5, description: 'Do the sixth' }, - 6: { id: 6, description: 'Do the seventh' }, - 7: { id: 7, description: 'Do the eighth' }, - 8: { id: 8, description: 'Do the ninth' }, - 9: { id: 9, description: 'Do the tenth' } - } -} - -const assertRejected = (promise, done, callback) => { - // resolve handler - promise.then( - () => done(new Error('expected promise to be rejected')), - // reject handler - () => { - try { - callback() - done() - } catch (e) { - done(e) - } - }) -} - -describe('Service Module - Actions', () => { - beforeEach(function () { - this.todoService = feathersClient.use('todos', memory({ - store: makeStore() - })) - - this.taskService = feathersClient.use('tasks', memory({ - store: makeStore(), - paginate: { - default: 10, - max: 50 - } - })) - - this.noIdService = feathersClient.use('no-ids', memory({ - store: makeStore(), - paginate: { - default: 10, - max: 50 - } - })) - - this.brokenService = feathersClient.use('broken', { - find (params) { return Promise.reject(new Error('find error')) }, - get (id, params) { return Promise.reject(new Error('get error')) }, - create (data, params) { return Promise.reject(new Error('create error')) }, - update (id, data, params) { return Promise.reject(new Error('update error')) }, - patch (id, data, params) { return Promise.reject(new Error('patch error')) }, - remove (id, params) { return Promise.reject(new Error('remove error')) }, - setup (app, path) {} - }) - }) - - describe('Find', () => { - describe('without pagination', () => { - it('Find without pagination', (done) => { - const store = new Vuex.Store({ - plugins: [service('todos')] - }) - const todoState = store.state.todos - const actions = mapActions('todos', ['find']) - - assert(todoState.ids.length === 0, 'no ids before find') - assert(todoState.errorOnFind === null, 'no error before find') - assert(todoState.isFindPending === false, 'isFindPending is false') - assert(todoState.idField === 'id', 'idField is `id`') - - actions.find.call({ $store: store }, {}) - .then(response => { - assert(todoState.ids.length === 10, 'three ids populated') - assert(todoState.errorOnFind === null, 'errorOnFind still null') - assert(todoState.isFindPending === false, 'isFindPending is false') - let expectedKeyedById = makeStore() - assert.deepEqual(todoState.keyedById, expectedKeyedById, 'keyedById matches') - - assert(typeof todoState.keyedById[1].save === 'function', 'added FeathersVuexModel class methods to the data') - - done() - }) - - // Make sure proper state changes occurred before response - assert(todoState.ids.length === 0) - assert(todoState.errorOnFind === null) - assert(todoState.isFindPending === true) - assert.deepEqual(todoState.keyedById, {}) - }) - - it('find with limit', (done) => { - const store = new Vuex.Store({ - plugins: [service('todos')] - }) - const actions = mapActions('todos', ['find']) - - actions.find.call({ $store: store }, { query: { $limit: 1 } }) - .then(response => { - assert(response.length === 1, 'only one record was returned') - assert.deepEqual(response[0], { id: 0, description: 'Do the first' }, 'the first record was returned') - done() - }) - }) - - it('find with skip', (done) => { - const store = new Vuex.Store({ - plugins: [service('todos')] - }) - const actions = mapActions('todos', ['find']) - - actions.find.call({ $store: store }, { query: { $skip: 9 } }) - .then(response => { - assert(response.length === 1, 'one record was returned') - assert.deepEqual(response[0], { id: 9, description: 'Do the tenth' }, 'the tenth record was returned') - done() - }) - }) - - it('Find with limit and skip', (done) => { - const store = new Vuex.Store({ - plugins: [service('todos')] - }) - const actions = mapActions('todos', ['find']) - - actions.find.call({ $store: store }, { query: { $limit: 1, $skip: 8 } }) - .then(response => { - assert(response.length === 1, 'one record was returned') - assert.deepEqual(response[0], { id: 8, description: 'Do the ninth' }, 'the ninth record was returned') - done() - }) - }) - }) - - describe('with pagination', () => { - it('find with limit', (done) => { - const store = new Vuex.Store({ - plugins: [service('tasks')] - }) - const actions = mapActions('tasks', ['find']) - - actions.find.call({ $store: store }, { query: { $limit: 1 } }) - .then(response => { - assert(response.data.length === 1, 'only one record was returned') - assert.deepEqual(response.data[0], { id: 0, description: 'Do the first' }, 'the first record was returned') - assert(response.limit === 1, 'limit was correct') - assert(response.skip === 0, 'skip was correct') - assert(response.total === 10, 'total was correct') - done() - }) - }) - - it('find with skip', (done) => { - const store = new Vuex.Store({ - plugins: [service('tasks')] - }) - const actions = mapActions('tasks', ['find']) - - actions.find.call({ $store: store }, { query: { $skip: 9 } }) - .then(response => { - assert(response.data.length === 1, 'only one record was returned') - assert.deepEqual(response.data[0], { id: 9, description: 'Do the tenth' }, 'the tenth record was returned') - assert(response.limit === 10, 'limit was correct') - assert(response.skip === 9, 'skip was correct') - assert(response.total === 10, 'total was correct') - done() - }) - }) - - it('find with limit and skip', (done) => { - const store = new Vuex.Store({ - plugins: [service('tasks')] - }) - const actions = mapActions('tasks', ['find']) - - actions.find.call({ $store: store }, { query: { $limit: 1, $skip: 8 } }) - .then(response => { - assert(response.data.length === 1, 'only one record was returned') - assert.deepEqual(response.data[0], { id: 8, description: 'Do the ninth' }, 'the ninth record was returned') - assert(response.limit === 1, 'limit was correct') - assert(response.skip === 8, 'skip was correct') - assert(response.total === 10, 'total was correct') - done() - }) - }) - - it('adds default pagination data to the store', (done) => { - const store = new Vuex.Store({ - plugins: [service('tasks')] - }) - const actions = mapActions('tasks', ['find']) - - actions.find.call({ $store: store }, { query: {} }) - .then(response => { - const { ids, limit, skip, total } = store.state.tasks.pagination.default - assert(ids.length === 10, 'ten ids were returned in this page') - assert(limit === 10, 'limit matches the default pagination limit on the server') - assert(skip === 0, 'skip was correct') - assert(total === 10, 'total was correct') - done() - }) - }) - - it('can provide a query identifier to store pagination', (done) => { - const store = new Vuex.Store({ - plugins: [service('tasks')] - }) - const actions = mapActions('tasks', ['find']) - const qid = 'component-name' - - actions.find.call({ $store: store }, { query: {}, qid }) - .then(response => { - const { ids, limit, skip, total } = store.state.tasks.pagination[qid] - assert(ids.length === 10, 'ten ids were returned in this page') - assert(limit === 10, 'limit matches the default pagination limit on the server') - assert(skip === 0, 'skip was correct') - assert(total === 10, 'total was correct') - done() - }) - }) - - it('updates properly with limit and skip', (done) => { - const store = new Vuex.Store({ - plugins: [service('tasks')] - }) - const actions = mapActions('tasks', ['find']) - const qid = 'component-name' - - actions.find.call({ $store: store }, { query: { $limit: 5, $skip: 2 }, qid }) - .then(response => { - const { ids, limit, skip, total } = store.state.tasks.pagination[qid] - assert(ids.length === 5, 'ten ids were returned in this page') - assert(limit === 5, 'limit matches the default pagination limit on the server') - assert(skip === 2, 'skip was correct') - assert(total === 10, 'total was correct') - done() - }) - }) - - it('works with multiple queries and identifiers', (done) => { - const store = new Vuex.Store({ - plugins: [service('tasks')] - }) - const actions = mapActions('tasks', ['find']) - const qids = [ - 'component-query-zero', - 'component-query-one' - ] - - actions.find.call({ $store: store }, { query: {}, qid: qids[0] }) - .then(response => actions.find.call({ $store: store }, { query: {}, qid: qids[1] })) - .then(response => { - qids.forEach(qid => { - const { ids, limit, skip, total } = store.state.tasks.pagination[qid] - assert(ids.length === 10, 'ten ids were returned in this page') - assert(limit === 10, 'limit matches the default pagination limit on the server') - assert(skip === 0, 'skip was correct') - assert(total === 10, 'total was correct') - }) - - done() - }) - }) - - it(`allows non-id'd data to pass through`, (done) => { - const store = new Vuex.Store({ - plugins: [ - service('no-ids', { - idField: '_id' - }) - ] - }) - const actions = mapActions('no-ids', ['find']) - - actions.find.call({ $store: store }, { query: {} }) - .then(response => { - assert(response.data.length === 10, 'records were still returned') - assert(store.state['no-ids'].ids.length === 0, 'no records were stored in the state') - - done() - }) - }) - - it(`runs the afterFind action`, (done) => { - const store = new Vuex.Store({ - plugins: [ - service('no-ids', { - idField: '_id', - actions: { - afterFind ({ commit, dispatch, getters, state }, response) { - assert(response.data.length === 10, 'records were still returned') - assert(store.state['no-ids'].ids.length === 0, 'no records were stored in the state') - - done() - } - } - }) - ] - }) - const actions = mapActions('no-ids', ['find']) - - actions.find.call({ $store: store }, { query: {} }) - }) - }) - - it('updates errorOnFind state on service failure', (done) => { - const store = new Vuex.Store({ - plugins: [service('broken')] - }) - const brokenState = store.state.broken - const actions = mapActions('broken', ['find']) - - assertRejected(actions.find.call({ $store: store }, {}), done, () => { - assert(brokenState.errorOnFind.message === 'find error', 'errorOnFind was set') - assert(brokenState.isFindPending === false, 'pending state was cleared') - assert(brokenState.ids.length === 0) - }) - - // Make sure proper state changes occurred before response - assert(brokenState.ids.length === 0) - assert(brokenState.errorOnFind === null) - assert(brokenState.isFindPending === true) - }) - }) - - describe('Get', function () { - it('updates store list state on service success', (done) => { - const store = new Vuex.Store({ - plugins: [service('todos')] - }) - const todoState = store.state.todos - const actions = mapActions('todos', ['get']) - - assert(todoState.ids.length === 0) - assert(todoState.errorOnGet === null) - assert(todoState.isGetPending === false) - assert(todoState.idField === 'id') - - actions.get.call({ $store: store }, 0) - .then(response => { - assert(todoState.ids.length === 1, 'only one item is in the store') - assert(todoState.errorOnGet === null, 'there was no errorOnGet') - assert(todoState.isGetPending === false, 'isGetPending is set to false') - assert(todoState.currentId === 0, 'the currentId was set') - - let expectedKeyedById = { - 0: { id: 0, description: 'Do the first' } - } - assert.deepEqual(todoState.keyedById, expectedKeyedById) - - // Make a request with the array syntax that allows passing params - actions.get.call({ $store: store }, [1, {}]) - .then(response2 => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the first' }, - 1: { id: 1, description: 'Do the second' } - } - assert(response2.description === 'Do the second') - assert.deepEqual(todoState.keyedById, expectedKeyedById) - - // Make a request to an existing record and return the existing data first, then update `keyedById` - todoState.keyedById = { - 0: { id: 0, description: 'Do the FIRST' }, // twist the data to see difference - 1: { id: 1, description: 'Do the second' } - } - actions.get.call({ $store: store }, [0, {}]) - .then(response3 => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the FIRST' }, - 1: { id: 1, description: 'Do the second' } - } - assert(response3.description === 'Do the FIRST') - assert.deepEqual(todoState.keyedById, expectedKeyedById) - - // Wait for the remote data to arriive - setTimeout(() => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the first' }, - 1: { id: 1, description: 'Do the second' } - } - assert.deepEqual(todoState.keyedById, expectedKeyedById) - done() - }, 100) - }) - }) - }) - - // Make sure proper state changes occurred before response - assert(todoState.ids.length === 0) - assert(todoState.errorOnCreate === null) - assert(todoState.isGetPending === true) - assert.deepEqual(todoState.keyedById, {}) - }) - - it('does not set currentId when setCurrentOnGet is false', (done) => { - const store = new Vuex.Store({ - plugins: [service('todos')] - }) - const todoState = store.state.todos - const actions = mapActions('todos', ['get']) - - todoState.setCurrentOnGet = false - - assert(todoState.ids.length === 0) - assert(todoState.errorOnGet === null) - assert(todoState.isGetPending === false) - assert(todoState.idField === 'id') - - actions.get.call({ $store: store }, 0) - .then(response => { - assert(todoState.ids.length === 1, 'only one item is in the store') - assert(todoState.errorOnGet === null, 'there was no errorOnGet') - assert(todoState.isGetPending === false, 'isGetPending is set to false') - assert(todoState.currentId === null, 'the currentId was set') - - let expectedKeyedById = { - 0: { id: 0, description: 'Do the first' } - } - assert.deepEqual(todoState.keyedById, expectedKeyedById) - - // Make a request with the array syntax that allows passing params - actions.get.call({ $store: store }, [1, {}]) - .then(response2 => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the first' }, - 1: { id: 1, description: 'Do the second' } - } - assert(response2.description === 'Do the second') - assert.deepEqual(todoState.keyedById, expectedKeyedById) - - // Make a request to an existing record and return the existing data first, then update `keyedById` - todoState.keyedById = { - 0: { id: 0, description: 'Do the FIRST' }, // twist the data to see difference - 1: { id: 1, description: 'Do the second' } - } - actions.get.call({ $store: store }, [0, {}]) - .then(response3 => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the FIRST' }, - 1: { id: 1, description: 'Do the second' } - } - assert(response3.description === 'Do the FIRST') - assert.deepEqual(todoState.keyedById, expectedKeyedById) - - // Wait for the remote data to arriive - setTimeout(() => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the first' }, - 1: { id: 1, description: 'Do the second' } - } - assert.deepEqual(todoState.keyedById, expectedKeyedById) - done() - }, 100) - }) - }) - }) - - // Make sure proper state changes occurred before response - assert(todoState.ids.length === 0) - assert(todoState.errorOnCreate === null) - assert(todoState.isGetPending === true) - assert.deepEqual(todoState.keyedById, {}) - }) - - it('does not make remote call when skipRequestIfExists=true', (done) => { - const store = new Vuex.Store({ - plugins: [service('todos')] - }) - const todoState = store.state.todos - const actions = mapActions('todos', ['get']) - - assert(todoState.ids.length === 0) - assert(todoState.errorOnGet === null) - assert(todoState.isGetPending === false) - assert(todoState.idField === 'id') - - actions.get.call({ $store: store }, 0) - .then(response => { - assert(todoState.ids.length === 1, 'only one item is in the store') - assert(todoState.errorOnGet === null, 'there was no errorOnGet') - assert(todoState.isGetPending === false, 'isGetPending is set to false') - let expectedKeyedById = { - 0: { id: 0, description: 'Do the first' } - } - assert.deepEqual(todoState.keyedById, expectedKeyedById) - - // Make a request with the array syntax that allows passing params - actions.get.call({ $store: store }, [1, {}]) - .then(response2 => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the first' }, - 1: { id: 1, description: 'Do the second' } - } - assert(response2.description === 'Do the second') - assert.deepEqual(todoState.keyedById, expectedKeyedById) - - // Make a request to an existing record and return the existing data first, then update `keyedById` - todoState.keyedById = { - 0: { id: 0, description: 'Do the FIRST' }, // twist the data to see difference - 1: { id: 1, description: 'Do the second' } - } - actions.get.call({ $store: store }, [0, { skipRequestIfExists: true }]) - .then(response3 => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the FIRST' }, - 1: { id: 1, description: 'Do the second' } - } - assert(response3.description === 'Do the FIRST') - assert.deepEqual(todoState.keyedById, expectedKeyedById) - - // The remote data will never arriive - setTimeout(() => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the FIRST' }, - 1: { id: 1, description: 'Do the second' } - } - assert.deepEqual(todoState.keyedById, expectedKeyedById) - done() - }, 100) - }) - }) - }) - - // Make sure proper state changes occurred before response - assert(todoState.ids.length === 0) - assert(todoState.errorOnCreate === null) - assert(todoState.isGetPending === true) - assert.deepEqual(todoState.keyedById, {}) - }) - - it('updates errorOnGet state on service failure', (done) => { - const store = new Vuex.Store({ - plugins: [service('broken')] - }) - const brokenState = store.state.broken - const actions = mapActions('broken', ['get']) - - assertRejected(actions.get.call({ $store: store }, {}), done, () => { - assert(brokenState.errorOnGet.message === 'get error', 'errorOnGet was set') - assert(brokenState.isGetPending === false, 'pending state was cleared') - assert(brokenState.ids.length === 0) - }) - - // Make sure proper state changes occurred before response - assert(brokenState.ids.length === 0) - assert(brokenState.errorOnGet === null) - assert(brokenState.isGetPending === true) - }) - }) - - describe('Create', function () { - it('updates store list state on service success', (done) => { - const store = new Vuex.Store({ - plugins: [service('todos')] - }) - const todoState = store.state.todos - const actions = mapActions('todos', ['create']) - - actions.create.call({ $store: store }, { description: 'Do the second' }) - .then(response => { - assert(todoState.ids.length === 1) - assert(todoState.errorOnCreate === null) - assert(todoState.isCreatePending === false) - assert.deepEqual(todoState.keyedById[response.id], response) - done() - }) - - // Make sure proper state changes occurred before response - assert(todoState.ids.length === 0) - assert(todoState.errorOnCreate === null) - assert(todoState.isCreatePending === true) - assert(todoState.idField === 'id') - assert.deepEqual(todoState.keyedById, {}) - }) - - it('updates errorOnCreate state on service failure', (done) => { - const store = new Vuex.Store({ - plugins: [service('broken')] - }) - const brokenState = store.state.broken - const actions = mapActions('broken', ['create']) - - assertRejected(actions.create.call({ $store: store }, {}), done, () => { - assert(brokenState.errorOnCreate.message === 'create error', 'errorOnCreate was set') - assert(brokenState.isCreatePending === false, 'pending state was cleared') - assert(brokenState.ids.length === 0) - }) - - // Make sure proper state changes occurred before response - assert(brokenState.ids.length === 0) - assert(brokenState.errorOnCreate === null) - assert(brokenState.isCreatePending === true) - }) - }) - - describe('Update', () => { - it('updates store list state on service success', (done) => { - const store = new Vuex.Store({ - plugins: [service('todos')] - }) - const todoState = store.state.todos - const actions = mapActions('todos', ['create', 'update']) - - actions.create.call({ $store: store }, { description: 'Do the second' }) - .then(response => { - actions.update.call({ $store: store }, [0, { id: 0, description: 'Do da dishuz' }]) - .then(responseFromUpdate => { - assert(todoState.ids.length === 1) - assert(todoState.errorOnUpdate === null) - assert(todoState.isUpdatePending === false) - assert.deepEqual(todoState.keyedById[responseFromUpdate.id], responseFromUpdate) - done() - }) - - // Make sure proper state changes occurred before response - assert(todoState.ids.length === 1) - assert(todoState.errorOnUpdate === null) - assert(todoState.isUpdatePending === true) - assert(todoState.idField === 'id') - }) - .catch(error => { - assert(!error, error) - }) - }) - - it('updates errorOnUpdate state on service failure', (done) => { - const store = new Vuex.Store({ - plugins: [service('broken')] - }) - const brokenState = store.state.broken - const actions = mapActions('broken', ['update']) - - assertRejected(actions.update.call({ $store: store }, [0, { id: 0 }]), done, () => { - assert(brokenState.errorOnUpdate.message === 'update error', 'errorOnUpdate was set') - assert(brokenState.isUpdatePending === false, 'pending state was cleared') - assert(brokenState.ids.length === 0) - }) - - // Make sure proper state changes occurred before response - assert(brokenState.ids.length === 0) - assert(brokenState.errorOnUpdate === null) - assert(brokenState.isUpdatePending === true) - }) - }) - - describe('Patch', () => { - it('updates only the changed properties', (done) => { - const store = new Vuex.Store({ - plugins: [service('todos')] - }) - const todoState = store.state.todos - const actions = mapActions('todos', ['create', 'patch']) - - const dataUnchanged = { unchanged: true, deep: { changed: false, unchanged: true } } - const dataChanged = { unchanged: true, deep: { changed: true, unchanged: true } } - - actions.create.call({ $store: store }, Object.assign({ description: 'Do the second' }, dataUnchanged)) - .then(response => { - actions.patch.call({ $store: store }, [0, Object.assign({ description: 'Write a Vue app' }, dataChanged)]) - .then(responseFromPatch => { - assert(todoState.ids.length === 1) - assert(todoState.errorOnPatch === null) - assert(todoState.isPatchPending === false) - assert.deepEqual(todoState.keyedById[responseFromPatch.id], responseFromPatch) - done() - }) - - // Make sure proper state changes occurred before response - assert(todoState.ids.length === 1) - assert(todoState.errorOnPatch === null) - assert(todoState.isPatchPending === true) - assert(todoState.idField === 'id') - }) - }) - - it('updates store state on service success', (done) => { - const store = new Vuex.Store({ - plugins: [service('todos')] - }) - const todoState = store.state.todos - const actions = mapActions('todos', ['create', 'patch']) - - actions.create.call({ $store: store }, { description: 'Do the second' }) - .then(response => { - actions.patch.call({ $store: store }, [0, { description: 'Write a Vue app' }]) - .then(responseFromPatch => { - assert(todoState.ids.length === 1) - assert(todoState.errorOnPatch === null) - assert(todoState.isPatchPending === false) - assert.deepEqual(todoState.keyedById[responseFromPatch.id], responseFromPatch) - done() - }) - - // Make sure proper state changes occurred before response - assert(todoState.ids.length === 1) - assert(todoState.errorOnPatch === null) - assert(todoState.isPatchPending === true) - assert(todoState.idField === 'id') - }) - }) - - it('updates errorOnPatch state on service failure', (done) => { - const store = new Vuex.Store({ - plugins: [service('broken')] - }) - const brokenState = store.state.broken - const actions = mapActions('broken', ['patch']) - - assertRejected(actions.patch.call({ $store: store }, [0, { id: 0 }]), done, () => { - assert(brokenState.errorOnPatch.message === 'patch error', 'errorOnPatch was set') - assert(brokenState.isPatchPending === false, 'pending state was cleared') - assert(brokenState.ids.length === 0) - }) - - // Make sure proper state changes occurred before response - assert(brokenState.ids.length === 0) - assert(brokenState.errorOnPatch === null) - assert(brokenState.isPatchPending === true) - }) - }) - - describe('Remove', () => { - it('updates store state on service success', (done) => { - const store = new Vuex.Store({ - plugins: [service('todos')] - }) - const todoState = store.state.todos - const actions = mapActions('todos', ['create', 'remove']) - - actions.create.call({ $store: store }, { description: 'Do the second' }) - .then(response => { - actions.remove.call({ $store: store }, 0) - .then(responseFromRemove => { - assert(todoState.ids.length === 0) - assert(todoState.errorOnRemove === null) - assert(todoState.isRemovePending === false) - assert.deepEqual(todoState.keyedById, {}) - done() - }) - .catch(error => { - console.log(error) - }) - - // Make sure proper state changes occurred before response - assert(todoState.ids.length === 1) - assert(todoState.errorOnRemove === null) - assert(todoState.isRemovePending === true) - assert(todoState.idField === 'id') - }) - }) - - it('updates errorOnRemove state on service failure', (done) => { - const store = new Vuex.Store({ - plugins: [service('broken')] - }) - const brokenState = store.state.broken - const actions = mapActions('broken', ['remove']) - - assertRejected(actions.remove.call({ $store: store }, 0), done, () => { - assert(brokenState.errorOnRemove.message === 'remove error', 'errorOnRemove was set') - assert(brokenState.isRemovePending === false, 'pending state was cleared') - assert(brokenState.ids.length === 0) - }) - - // Make sure proper state changes occurred before response - assert(brokenState.ids.length === 0) - assert(brokenState.errorOnRemove === null) - assert(brokenState.isRemovePending === true) - }) - }) -}) diff --git a/test/service-module/actions.test.ts b/test/service-module/actions.test.ts new file mode 100644 index 00000000..05679e2f --- /dev/null +++ b/test/service-module/actions.test.ts @@ -0,0 +1,1125 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import assert from 'chai/chai' +import feathersVuex from '../../src/index' +import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' +import Vuex, { mapActions } from 'vuex' +import memory from 'feathers-memory' + +interface PaginationState { + ids: any + limit: number + skip: number + ip: number + total: number +} +interface ServiceState { + options: {} + ids: string[] + errorOnFind: any + errorOnGet: any + errorOnCreate: any + errorOnPatch: any + errorOnUpdate: any + errorOnRemove: any + currentId: number + isFindPending: boolean + isGetPending: boolean + isCreatePending: boolean + isPatchPending: boolean + isUpdatePending: boolean + isRemovePending: boolean + setCurrentOnGet: boolean + idField: string + keyedById: {} + pagination?: { + default: PaginationState + } +} +interface RootState { + todos: ServiceState + tasks: ServiceState + broken: ServiceState +} +interface NumberedList { + 0?: {} + 1?: {} +} + +const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'default' +}) +class Todo extends BaseModel { + public static test: boolean = true +} +class Task extends BaseModel { + public static test: boolean = true +} +class NoId extends BaseModel { + public static test: boolean = true +} +class Broken extends BaseModel { + public static test: boolean = true +} +const makeStore = () => { + return { + 0: { id: 0, description: 'Do the first' }, + 1: { id: 1, description: 'Do the second' }, + 2: { id: 2, description: 'Do the third' }, + 3: { id: 3, description: 'Do the fourth' }, + 4: { id: 4, description: 'Do the fifth' }, + 5: { id: 5, description: 'Do the sixth' }, + 6: { id: 6, description: 'Do the seventh' }, + 7: { id: 7, description: 'Do the eighth' }, + 8: { id: 8, description: 'Do the ninth' }, + 9: { id: 9, description: 'Do the tenth' } + } +} + +const assertRejected = (promise, done, callback) => { + // resolve handler + promise.then( + () => done(new Error('expected promise to be rejected')), + // reject handler + () => { + try { + callback() + done() + } catch (e) { + done(e) + } + } + ) +} + +describe('Service Module - Actions', () => { + beforeEach(function() { + this.todoService = feathersClient.use( + 'todos', + memory({ + store: makeStore() + }) + ) + + this.taskService = feathersClient.use( + 'tasks', + memory({ + store: makeStore(), + paginate: { + default: 10, + max: 50 + } + }) + ) + + this.noIdService = feathersClient.use( + 'no-ids', + memory({ + store: makeStore(), + paginate: { + default: 10, + max: 50 + } + }) + ) + + this.brokenService = feathersClient.use('broken', { + find() { + return Promise.reject(new Error('find error')) + }, + get() { + return Promise.reject(new Error('get error')) + }, + create() { + return Promise.reject(new Error('create error')) + }, + update() { + return Promise.reject(new Error('update error')) + }, + patch() { + return Promise.reject(new Error('patch error')) + }, + remove() { + return Promise.reject(new Error('remove error')) + }, + setup() {} + }) + }) + + describe('Find', () => { + describe('without pagination', () => { + it('Find without pagination', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.makeServicePlugin({ + Model: Todo, + service: feathersClient.service('todos') + }) + }) + ] + }) + const todoState = store.state.todos + const actions = mapActions('todos', ['find']) + + assert(todoState.ids.length === 0, 'no ids before find') + assert(todoState.errorOnFind === null, 'no error before find') + assert(todoState.isFindPending === false, 'isFindPending is false') + assert(todoState.idField === 'id', 'idField is `id`') + + actions.find.call({ $store: store }, {}).then(() => { + assert(todoState.ids.length === 10, 'three ids populated') + assert(todoState.errorOnFind === null, 'errorOnFind still null') + assert(todoState.isFindPending === false, 'isFindPending is false') + let expectedKeyedById: NumberedList = makeStore() + assert.deepEqual( + todoState.keyedById, + expectedKeyedById, + 'keyedById matches' + ) + + assert( + typeof todoState.keyedById[1].save === 'function', + 'added FeathersVuexModel class methods to the data' + ) + + done() + }) + + // Make sure proper state changes occurred before response + assert(todoState.ids.length === 0) + assert(todoState.errorOnFind === null) + assert(todoState.isFindPending === true) + assert.deepEqual(todoState.keyedById, {}) + }) + + it('find with limit', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('todos') + }) + ] + }) + const actions = mapActions('todos', ['find']) + + actions.find + .call({ $store: store }, { query: { $limit: 1 } }) + .then(response => { + assert(response.length === 1, 'only one record was returned') + assert.deepEqual( + response[0], + { id: 0, description: 'Do the first' }, + 'the first record was returned' + ) + done() + }) + }) + + it('find with skip', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('todos') + }) + ] + }) + const actions = mapActions('todos', ['find']) + + actions.find + .call({ $store: store }, { query: { $skip: 9 } }) + .then(response => { + assert(response.length === 1, 'one record was returned') + assert.deepEqual( + response[0], + { id: 9, description: 'Do the tenth' }, + 'the tenth record was returned' + ) + done() + }) + }) + + it('Find with limit and skip', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('todos') + }) + ] + }) + const actions = mapActions('todos', ['find']) + + actions.find + .call({ $store: store }, { query: { $limit: 1, $skip: 8 } }) + .then(response => { + assert(response.length === 1, 'one record was returned') + assert.deepEqual( + response[0], + { id: 8, description: 'Do the ninth' }, + 'the ninth record was returned' + ) + done() + }) + }) + }) + + describe('with pagination', () => { + it('find with limit', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Task, + service: feathersClient.service('tasks') + }) + ] + }) + const actions = mapActions('tasks', ['find']) + + actions.find + .call({ $store: store }, { query: { $limit: 1 } }) + .then(response => { + assert(response.data.length === 1, 'only one record was returned') + assert.deepEqual( + response.data[0], + { id: 0, description: 'Do the first' }, + 'the first record was returned' + ) + assert(response.limit === 1, 'limit was correct') + assert(response.skip === 0, 'skip was correct') + assert(response.total === 10, 'total was correct') + done() + }) + }) + + it('find with skip', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Task, + service: feathersClient.service('tasks') + }) + ] + }) + const actions = mapActions('tasks', ['find']) + + actions.find + .call({ $store: store }, { query: { $skip: 9 } }) + .then(response => { + assert(response.data.length === 1, 'only one record was returned') + assert.deepEqual( + response.data[0], + { id: 9, description: 'Do the tenth' }, + 'the tenth record was returned' + ) + assert(response.limit === 10, 'limit was correct') + assert(response.skip === 9, 'skip was correct') + assert(response.total === 10, 'total was correct') + done() + }) + }) + + it('find with limit and skip', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Task, + service: feathersClient.service('tasks') + }) + ] + }) + const actions = mapActions('tasks', ['find']) + + actions.find + .call({ $store: store }, { query: { $limit: 1, $skip: 8 } }) + .then(response => { + assert(response.data.length === 1, 'only one record was returned') + assert.deepEqual( + response.data[0], + { id: 8, description: 'Do the ninth' }, + 'the ninth record was returned' + ) + assert(response.limit === 1, 'limit was correct') + assert(response.skip === 8, 'skip was correct') + assert(response.total === 10, 'total was correct') + done() + }) + }) + + it('adds default pagination data to the store', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Task, + service: feathersClient.service('tasks') + }) + ] + }) + const actions = mapActions('tasks', ['find']) + + actions.find.call({ $store: store }, { query: {} }).then(() => { + const { + ids, + limit, + skip, + total + } = store.state.tasks.pagination.default + assert(ids.length === 10, 'ten ids were returned in this page') + assert( + limit === 10, + 'limit matches the default pagination limit on the server' + ) + assert(skip === 0, 'skip was correct') + assert(total === 10, 'total was correct') + done() + }) + }) + + it('can provide a query identifier to store pagination', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Task, + service: feathersClient.service('tasks') + }) + ] + }) + const actions = mapActions('tasks', ['find']) + const qid = 'component-name' + + actions.find.call({ $store: store }, { query: {}, qid }).then(() => { + const { ids, limit, skip, total } = store.state.tasks.pagination[qid] + assert(ids.length === 10, 'ten ids were returned in this page') + assert( + limit === 10, + 'limit matches the default pagination limit on the server' + ) + assert(skip === 0, 'skip was correct') + assert(total === 10, 'total was correct') + done() + }) + }) + + it('updates properly with limit and skip', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Task, + service: feathersClient.service('tasks') + }) + ] + }) + const actions = mapActions('tasks', ['find']) + const qid = 'component-name' + + actions.find + .call({ $store: store }, { query: { $limit: 5, $skip: 2 }, qid }) + .then(() => { + const { ids, limit, skip, total } = store.state.tasks.pagination[ + qid + ] + assert(ids.length === 5, 'ten ids were returned in this page') + assert( + limit === 5, + 'limit matches the default pagination limit on the server' + ) + assert(skip === 2, 'skip was correct') + assert(total === 10, 'total was correct') + done() + }) + }) + + it('works with multiple queries and identifiers', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Task, + service: feathersClient.service('tasks') + }) + ] + }) + const actions = mapActions('tasks', ['find']) + const qids = ['component-query-zero', 'component-query-one'] + + actions.find + .call({ $store: store }, { query: {}, qid: qids[0] }) + .then(() => + actions.find.call({ $store: store }, { query: {}, qid: qids[1] }) + ) + .then(() => { + qids.forEach(qid => { + const { ids, limit, skip, total } = store.state.tasks.pagination[ + qid + ] + assert(ids.length === 10, 'ten ids were returned in this page') + assert( + limit === 10, + 'limit matches the default pagination limit on the server' + ) + assert(skip === 0, 'skip was correct') + assert(total === 10, 'total was correct') + }) + + done() + }) + }) + + it(`allows non-id'd data to pass through`, done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: NoId, + service: feathersClient.service('no-ids'), + idField: '_id' + }) + ] + }) + const actions = mapActions('no-ids', ['find']) + + actions.find.call({ $store: store }, { query: {} }).then(response => { + assert(response.data.length === 10, 'records were still returned') + assert( + store.state['no-ids'].ids.length === 0, + 'no records were stored in the state' + ) + + done() + }) + }) + + it(`runs the afterFind action`, done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: NoId, + service: feathersClient.service('no-ids'), + idField: '_id', + actions: { + afterFind({}, response) { + assert( + response.data.length === 10, + 'records were still returned' + ) + assert( + store.state['no-ids'].ids.length === 0, + 'no records were stored in the state' + ) + + done() + } + } + }) + ] + }) + const actions = mapActions('no-ids', ['find']) + + actions.find.call({ $store: store }, { query: {} }) + }) + }) + + it('updates errorOnFind state on service failure', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Broken, + service: feathersClient.service('broken') + }) + ] + }) + const brokenState = store.state.broken + const actions = mapActions('broken', ['find']) + + assertRejected(actions.find.call({ $store: store }, {}), done, () => { + assert( + brokenState.errorOnFind.message === 'find error', + 'errorOnFind was set' + ) + assert(brokenState.isFindPending === false, 'pending state was cleared') + assert(brokenState.ids.length === 0) + }) + + // Make sure proper state changes occurred before response + assert(brokenState.ids.length === 0) + assert(brokenState.errorOnFind === null) + assert(brokenState.isFindPending === true) + }) + }) + + describe('Get', function() { + it('updates store list state on service success', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('todos') + }) + ] + }) + const todoState = store.state.todos + const actions = mapActions('todos', ['get']) + + assert(todoState.ids.length === 0) + assert(todoState.errorOnGet === null) + assert(todoState.isGetPending === false) + assert(todoState.idField === 'id') + + actions.get.call({ $store: store }, 0).then(() => { + assert(todoState.ids.length === 1, 'only one item is in the store') + assert(todoState.errorOnGet === null, 'there was no errorOnGet') + assert(todoState.isGetPending === false, 'isGetPending is set to false') + assert(todoState.currentId === 0, 'the currentId was set') + + let expectedKeyedById: NumberedList = { + 0: { id: 0, description: 'Do the first' } + } + assert.deepEqual(todoState.keyedById, expectedKeyedById) + + // Make a request with the array syntax that allows passing params + actions.get.call({ $store: store }, [1, {}]).then(response2 => { + expectedKeyedById = { + 0: { id: 0, description: 'Do the first' }, + 1: { id: 1, description: 'Do the second' } + } + assert(response2.description === 'Do the second') + assert.deepEqual(todoState.keyedById, expectedKeyedById) + + // Make a request to an existing record and return the existing data first, then update `keyedById` + todoState.keyedById = { + 0: { id: 0, description: 'Do the FIRST' }, // twist the data to see difference + 1: { id: 1, description: 'Do the second' } + } + actions.get.call({ $store: store }, [0, {}]).then(response3 => { + expectedKeyedById = { + 0: { id: 0, description: 'Do the FIRST' }, + 1: { id: 1, description: 'Do the second' } + } + assert(response3.description === 'Do the FIRST') + assert.deepEqual(todoState.keyedById, expectedKeyedById) + + // Wait for the remote data to arriive + setTimeout(() => { + expectedKeyedById = { + 0: { id: 0, description: 'Do the first' }, + 1: { id: 1, description: 'Do the second' } + } + assert.deepEqual(todoState.keyedById, expectedKeyedById) + done() + }, 100) + }) + }) + }) + + // Make sure proper state changes occurred before response + assert(todoState.ids.length === 0) + assert(todoState.errorOnCreate === null) + assert(todoState.isGetPending === true) + assert.deepEqual(todoState.keyedById, {}) + }) + + it('does not set currentId when setCurrentOnGet is false', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('todos') + }) + ] + }) + const todoState = store.state.todos + const actions = mapActions('todos', ['get']) + + todoState.setCurrentOnGet = false + + assert(todoState.ids.length === 0) + assert(todoState.errorOnGet === null) + assert(todoState.isGetPending === false) + assert(todoState.idField === 'id') + + actions.get.call({ $store: store }, 0).then(() => { + assert(todoState.ids.length === 1, 'only one item is in the store') + assert(todoState.errorOnGet === null, 'there was no errorOnGet') + assert(todoState.isGetPending === false, 'isGetPending is set to false') + assert(todoState.currentId === null, 'the currentId was set') + + let expectedKeyedById: NumberedList = { + 0: { id: 0, description: 'Do the first' } + } + assert.deepEqual(todoState.keyedById, expectedKeyedById) + + // Make a request with the array syntax that allows passing params + actions.get.call({ $store: store }, [1, {}]).then(response2 => { + expectedKeyedById = { + 0: { id: 0, description: 'Do the first' }, + 1: { id: 1, description: 'Do the second' } + } + assert(response2.description === 'Do the second') + assert.deepEqual(todoState.keyedById, expectedKeyedById) + + // Make a request to an existing record and return the existing data first, then update `keyedById` + todoState.keyedById = { + 0: { id: 0, description: 'Do the FIRST' }, // twist the data to see difference + 1: { id: 1, description: 'Do the second' } + } + actions.get.call({ $store: store }, [0, {}]).then(response3 => { + expectedKeyedById = { + 0: { id: 0, description: 'Do the FIRST' }, + 1: { id: 1, description: 'Do the second' } + } + assert(response3.description === 'Do the FIRST') + assert.deepEqual(todoState.keyedById, expectedKeyedById) + + // Wait for the remote data to arriive + setTimeout(() => { + expectedKeyedById = { + 0: { id: 0, description: 'Do the first' }, + 1: { id: 1, description: 'Do the second' } + } + assert.deepEqual(todoState.keyedById, expectedKeyedById) + done() + }, 100) + }) + }) + }) + + // Make sure proper state changes occurred before response + assert(todoState.ids.length === 0) + assert(todoState.errorOnCreate === null) + assert(todoState.isGetPending === true) + assert.deepEqual(todoState.keyedById, {}) + }) + + it('does not make remote call when skipRequestIfExists=true', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('todos') + }) + ] + }) + const todoState = store.state.todos + const actions = mapActions('todos', ['get']) + + assert(todoState.ids.length === 0) + assert(todoState.errorOnGet === null) + assert(todoState.isGetPending === false) + assert(todoState.idField === 'id') + + actions.get.call({ $store: store }, 0).then(() => { + assert(todoState.ids.length === 1, 'only one item is in the store') + assert(todoState.errorOnGet === null, 'there was no errorOnGet') + assert(todoState.isGetPending === false, 'isGetPending is set to false') + let expectedKeyedById: NumberedList = { + 0: { id: 0, description: 'Do the first' } + } + assert.deepEqual(todoState.keyedById, expectedKeyedById) + + // Make a request with the array syntax that allows passing params + actions.get.call({ $store: store }, [1, {}]).then(response2 => { + expectedKeyedById = { + 0: { id: 0, description: 'Do the first' }, + 1: { id: 1, description: 'Do the second' } + } + assert(response2.description === 'Do the second') + assert.deepEqual(todoState.keyedById, expectedKeyedById) + + // Make a request to an existing record and return the existing data first, then update `keyedById` + todoState.keyedById = { + 0: { id: 0, description: 'Do the FIRST' }, // twist the data to see difference + 1: { id: 1, description: 'Do the second' } + } + actions.get + .call({ $store: store }, [0, { skipRequestIfExists: true }]) + .then(response3 => { + expectedKeyedById = { + 0: { id: 0, description: 'Do the FIRST' }, + 1: { id: 1, description: 'Do the second' } + } + assert(response3.description === 'Do the FIRST') + assert.deepEqual(todoState.keyedById, expectedKeyedById) + + // The remote data will never arriive + setTimeout(() => { + expectedKeyedById = { + 0: { id: 0, description: 'Do the FIRST' }, + 1: { id: 1, description: 'Do the second' } + } + assert.deepEqual(todoState.keyedById, expectedKeyedById) + done() + }, 100) + }) + }) + }) + + // Make sure proper state changes occurred before response + assert(todoState.ids.length === 0) + assert(todoState.errorOnCreate === null) + assert(todoState.isGetPending === true) + assert.deepEqual(todoState.keyedById, {}) + }) + + it('updates errorOnGet state on service failure', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Broken, + service: feathersClient.service('broken') + }) + ] + }) + const brokenState = store.state.broken + const actions = mapActions('broken', ['get']) + + assertRejected(actions.get.call({ $store: store }, {}), done, () => { + assert( + brokenState.errorOnGet.message === 'get error', + 'errorOnGet was set' + ) + assert(brokenState.isGetPending === false, 'pending state was cleared') + assert(brokenState.ids.length === 0) + }) + + // Make sure proper state changes occurred before response + assert(brokenState.ids.length === 0) + assert(brokenState.errorOnGet === null) + assert(brokenState.isGetPending === true) + }) + }) + + describe('Create', function() { + it('updates store list state on service success', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('todos') + }) + ] + }) + const todoState = store.state.todos + const actions = mapActions('todos', ['create']) + + actions.create + .call({ $store: store }, { description: 'Do the second' }) + .then(response => { + assert(todoState.ids.length === 1) + assert(todoState.errorOnCreate === null) + assert(todoState.isCreatePending === false) + assert.deepEqual(todoState.keyedById[response.id], response) + done() + }) + + // Make sure proper state changes occurred before response + assert(todoState.ids.length === 0) + assert(todoState.errorOnCreate === null) + assert(todoState.isCreatePending === true) + assert(todoState.idField === 'id') + assert.deepEqual(todoState.keyedById, {}) + }) + + it('updates errorOnCreate state on service failure', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Broken, + service: feathersClient.service('broken') + }) + ] + }) + const brokenState = store.state.broken + const actions = mapActions('broken', ['create']) + + assertRejected(actions.create.call({ $store: store }, {}), done, () => { + assert( + brokenState.errorOnCreate.message === 'create error', + 'errorOnCreate was set' + ) + assert( + brokenState.isCreatePending === false, + 'pending state was cleared' + ) + assert(brokenState.ids.length === 0) + }) + + // Make sure proper state changes occurred before response + assert(brokenState.ids.length === 0) + assert(brokenState.errorOnCreate === null) + assert(brokenState.isCreatePending === true) + }) + }) + + describe('Update', () => { + it('updates store list state on service success', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('todos') + }) + ] + }) + const todoState = store.state.todos + const actions = mapActions('todos', ['create', 'update']) + + actions.create + .call({ $store: store }, { description: 'Do the second' }) + .then(() => { + actions.update + .call({ $store: store }, [ + 0, + { id: 0, description: 'Do da dishuz' } + ]) + .then(responseFromUpdate => { + assert(todoState.ids.length === 1) + assert(todoState.errorOnUpdate === null) + assert(todoState.isUpdatePending === false) + assert.deepEqual( + todoState.keyedById[responseFromUpdate.id], + responseFromUpdate + ) + done() + }) + + // Make sure proper state changes occurred before response + assert(todoState.ids.length === 1) + assert(todoState.errorOnUpdate === null) + assert(todoState.isUpdatePending === true) + assert(todoState.idField === 'id') + }) + .catch(error => { + assert(!error, error) + }) + }) + + it('updates errorOnUpdate state on service failure', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Broken, + service: feathersClient.service('broken') + }) + ] + }) + const brokenState = store.state.broken + const actions = mapActions('broken', ['update']) + + assertRejected( + actions.update.call({ $store: store }, [0, { id: 0 }]), + done, + () => { + assert( + brokenState.errorOnUpdate.message === 'update error', + 'errorOnUpdate was set' + ) + assert( + brokenState.isUpdatePending === false, + 'pending state was cleared' + ) + assert(brokenState.ids.length === 0) + } + ) + + // Make sure proper state changes occurred before response + assert(brokenState.ids.length === 0) + assert(brokenState.errorOnUpdate === null) + assert(brokenState.isUpdatePending === true) + }) + }) + + describe('Patch', () => { + it('updates only the changed properties', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('todos') + }) + ] + }) + const todoState = store.state.todos + const actions = mapActions('todos', ['create', 'patch']) + + const dataUnchanged = { + unchanged: true, + deep: { changed: false, unchanged: true } + } + const dataChanged = { + unchanged: true, + deep: { changed: true, unchanged: true } + } + + actions.create + .call( + { $store: store }, + Object.assign({ description: 'Do the second' }, dataUnchanged) + ) + .then(() => { + actions.patch + .call({ $store: store }, [ + 0, + Object.assign({ description: 'Write a Vue app' }, dataChanged) + ]) + .then(responseFromPatch => { + assert(todoState.ids.length === 1) + assert(todoState.errorOnPatch === null) + assert(todoState.isPatchPending === false) + assert.deepEqual( + todoState.keyedById[responseFromPatch.id], + responseFromPatch + ) + done() + }) + + // Make sure proper state changes occurred before response + assert(todoState.ids.length === 1) + assert(todoState.errorOnPatch === null) + assert(todoState.isPatchPending === true) + assert(todoState.idField === 'id') + }) + }) + + it('updates store state on service success', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('todos') + }) + ] + }) + const todoState = store.state.todos + const actions = mapActions('todos', ['create', 'patch']) + + actions.create + .call({ $store: store }, { description: 'Do the second' }) + .then(() => { + actions.patch + .call({ $store: store }, [0, { description: 'Write a Vue app' }]) + .then(responseFromPatch => { + assert(todoState.ids.length === 1) + assert(todoState.errorOnPatch === null) + assert(todoState.isPatchPending === false) + assert.deepEqual( + todoState.keyedById[responseFromPatch.id], + responseFromPatch + ) + done() + }) + + // Make sure proper state changes occurred before response + assert(todoState.ids.length === 1) + assert(todoState.errorOnPatch === null) + assert(todoState.isPatchPending === true) + assert(todoState.idField === 'id') + }) + }) + + it('updates errorOnPatch state on service failure', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Broken, + service: feathersClient.service('broken') + }) + ] + }) + const brokenState = store.state.broken + const actions = mapActions('broken', ['patch']) + + assertRejected( + actions.patch.call({ $store: store }, [0, { id: 0 }]), + done, + () => { + assert( + brokenState.errorOnPatch.message === 'patch error', + 'errorOnPatch was set' + ) + assert( + brokenState.isPatchPending === false, + 'pending state was cleared' + ) + assert(brokenState.ids.length === 0) + } + ) + + // Make sure proper state changes occurred before response + assert(brokenState.ids.length === 0) + assert(brokenState.errorOnPatch === null) + assert(brokenState.isPatchPending === true) + }) + }) + + describe('Remove', () => { + it('updates store state on service success', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('todos') + }) + ] + }) + const todoState = store.state.todos + const actions = mapActions('todos', ['create', 'remove']) + + actions.create + .call({ $store: store }, { description: 'Do the second' }) + .then(() => { + actions.remove + .call({ $store: store }, 0) + .then(() => { + assert(todoState.ids.length === 0) + assert(todoState.errorOnRemove === null) + assert(todoState.isRemovePending === false) + assert.deepEqual(todoState.keyedById, {}) + done() + }) + .catch(error => { + console.log(error) + }) + + // Make sure proper state changes occurred before response + assert(todoState.ids.length === 1) + assert(todoState.errorOnRemove === null) + assert(todoState.isRemovePending === true) + assert(todoState.idField === 'id') + }) + }) + + it('updates errorOnRemove state on service failure', done => { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Broken, + service: feathersClient.service('broken') + }) + ] + }) + const brokenState = store.state.broken + const actions = mapActions('broken', ['remove']) + + assertRejected(actions.remove.call({ $store: store }, 0), done, () => { + assert( + brokenState.errorOnRemove.message === 'remove error', + 'errorOnRemove was set' + ) + assert( + brokenState.isRemovePending === false, + 'pending state was cleared' + ) + assert(brokenState.ids.length === 0) + }) + + // Make sure proper state changes occurred before response + assert(brokenState.ids.length === 0) + assert(brokenState.errorOnRemove === null) + assert(brokenState.isRemovePending === true) + }) + }) +}) From b585284a87456f20027da498a2b1c25380b0ce45 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 23:04:41 -0600 Subject: [PATCH 028/404] Fix test --- test/service-module/actions.test.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/test/service-module/actions.test.ts b/test/service-module/actions.test.ts index 05679e2f..532dbb33 100644 --- a/test/service-module/actions.test.ts +++ b/test/service-module/actions.test.ts @@ -3,7 +3,7 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import assert from 'chai/chai' +import { assert } from 'chai' import feathersVuex from '../../src/index' import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' import Vuex, { mapActions } from 'vuex' @@ -151,15 +151,13 @@ describe('Service Module - Actions', () => { describe('Find', () => { describe('without pagination', () => { - it('Find without pagination', done => { + it.only('Find without pagination', done => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'todos', Model: Todo, - service: feathersClient.makeServicePlugin({ - Model: Todo, - service: feathersClient.service('todos') - }) + service: feathersClient.service('todos') }) ] }) @@ -176,8 +174,11 @@ describe('Service Module - Actions', () => { assert(todoState.errorOnFind === null, 'errorOnFind still null') assert(todoState.isFindPending === false, 'isFindPending is false') let expectedKeyedById: NumberedList = makeStore() + const currentKeyedById = JSON.parse( + JSON.stringify(todoState.keyedById) + ) assert.deepEqual( - todoState.keyedById, + currentKeyedById, expectedKeyedById, 'keyedById matches' ) From fbe65cc3ae09f6816500e13e56bbc12999e56dd5 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 24 Mar 2019 23:04:56 -0600 Subject: [PATCH 029/404] Setup individual properties as Vue.observables --- src/service-module/make-model.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index a979b1d8..99d58bc1 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -30,7 +30,9 @@ export default function makeModel(options: FeathersVuexOptions) { public data: Record public constructor(data) { Object.assign(this, data) - this.data = Vue.observable(data) + Object.keys(this).forEach(key => { + this[key] = Vue.observable(this[key]) + }) } public static getId(record: Record): string { From 5f2cdf32a3d0ee632f2cb65e7d7871a0a6020462 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 25 Mar 2019 00:03:52 -0600 Subject: [PATCH 030/404] Get service actions passing --- src/service-module/module.mutations.ts | 26 ++-- test/service-module/actions.test.ts | 112 ++++++++++++++---- .../make-service-plugin.test.ts | 6 +- test/service-module/model-base.test.ts | 3 + 4 files changed, 111 insertions(+), 36 deletions(-) diff --git a/src/service-module/module.mutations.ts b/src/service-module/module.mutations.ts index 43f675ad..9152c746 100644 --- a/src/service-module/module.mutations.ts +++ b/src/service-module/module.mutations.ts @@ -8,16 +8,13 @@ import _merge from 'lodash.merge' import serializeError from 'serialize-error' import isObject from 'lodash.isobject' import { checkId, updateOriginal } from '../utils' +import { globalModels } from './global-models' -export default function makeServiceMutations( - servicePath, - { debug, globalModels } -) { - globalModels = globalModels || { byServicePath: {} } - +export default function makeServiceMutations(servicePath, { debug }) { function addItems(state, items) { const { idField } = state - const Model = globalModels.byServicePath[servicePath] + const Model = + globalModels[state.options.serverAlias].byServicePath[servicePath] let newKeyedById = { ...state.keyedById } @@ -44,7 +41,8 @@ export default function makeServiceMutations( function updateItems(state, items) { const { idField, replaceItems, addOnUpsert } = state - const Model = globalModels.byServicePath[servicePath] + const Model = + globalModels[state.options.serverAlias].byServicePath[servicePath] for (let item of items) { let id = item[idField] @@ -185,7 +183,8 @@ export default function makeServiceMutations( setCurrent(state, itemOrId) { const { idField } = state - const Model = globalModels.byServicePath[servicePath] + const Model = + globalModels[state.options.serverAlias].byServicePath[servicePath] let id let item @@ -216,7 +215,8 @@ export default function makeServiceMutations( // Creates a copy of the record with the passed-in id, stores it in copiesById createCopy(state, id) { const current = state.keyedById[id] - const Model = globalModels.byServicePath[servicePath] + const Model = + globalModels[state.options.serverAlias].byServicePath[servicePath] const copyData = _merge({}, current) const copy = new Model(copyData, { isClone: true }) @@ -233,7 +233,8 @@ export default function makeServiceMutations( const current = isIdOk ? state.keyedById[id] : state.keyedById[state.currentId] - const Model = globalModels.byServicePath[servicePath] + const Model = + globalModels[state.options.serverAlias].byServicePath[servicePath] let copy if (state.keepCopiesInStore || !Model) { @@ -251,7 +252,8 @@ export default function makeServiceMutations( const current = isIdOk ? state.keyedById[id] : state.keyedById[state.currentId] - const Model = globalModels.byServicePath[servicePath] + const Model = + globalModels[state.options.serverAlias].byServicePath[servicePath] let copy if (state.keepCopiesInStore || !Model) { diff --git a/test/service-module/actions.test.ts b/test/service-module/actions.test.ts index 532dbb33..20a8659d 100644 --- a/test/service-module/actions.test.ts +++ b/test/service-module/actions.test.ts @@ -151,7 +151,7 @@ describe('Service Module - Actions', () => { describe('Find', () => { describe('without pagination', () => { - it.only('Find without pagination', done => { + it('Find without pagination', done => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -202,6 +202,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'todos', Model: Todo, service: feathersClient.service('todos') }) @@ -212,9 +213,10 @@ describe('Service Module - Actions', () => { actions.find .call({ $store: store }, { query: { $limit: 1 } }) .then(response => { + const returnedRecord = JSON.parse(JSON.stringify(response[0])) assert(response.length === 1, 'only one record was returned') assert.deepEqual( - response[0], + returnedRecord, { id: 0, description: 'Do the first' }, 'the first record was returned' ) @@ -226,6 +228,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'todos', Model: Todo, service: feathersClient.service('todos') }) @@ -236,9 +239,10 @@ describe('Service Module - Actions', () => { actions.find .call({ $store: store }, { query: { $skip: 9 } }) .then(response => { + const returnedRecord = JSON.parse(JSON.stringify(response[0])) assert(response.length === 1, 'one record was returned') assert.deepEqual( - response[0], + returnedRecord, { id: 9, description: 'Do the tenth' }, 'the tenth record was returned' ) @@ -250,6 +254,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'todos', Model: Todo, service: feathersClient.service('todos') }) @@ -260,9 +265,10 @@ describe('Service Module - Actions', () => { actions.find .call({ $store: store }, { query: { $limit: 1, $skip: 8 } }) .then(response => { + const returnedRecord = JSON.parse(JSON.stringify(response[0])) assert(response.length === 1, 'one record was returned') assert.deepEqual( - response[0], + returnedRecord, { id: 8, description: 'Do the ninth' }, 'the ninth record was returned' ) @@ -276,6 +282,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'tasks', Model: Task, service: feathersClient.service('tasks') }) @@ -286,9 +293,10 @@ describe('Service Module - Actions', () => { actions.find .call({ $store: store }, { query: { $limit: 1 } }) .then(response => { + const returnedRecord = JSON.parse(JSON.stringify(response.data[0])) assert(response.data.length === 1, 'only one record was returned') assert.deepEqual( - response.data[0], + returnedRecord, { id: 0, description: 'Do the first' }, 'the first record was returned' ) @@ -303,6 +311,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'tasks', Model: Task, service: feathersClient.service('tasks') }) @@ -313,9 +322,10 @@ describe('Service Module - Actions', () => { actions.find .call({ $store: store }, { query: { $skip: 9 } }) .then(response => { + const returnedRecord = JSON.parse(JSON.stringify(response.data[0])) assert(response.data.length === 1, 'only one record was returned') assert.deepEqual( - response.data[0], + returnedRecord, { id: 9, description: 'Do the tenth' }, 'the tenth record was returned' ) @@ -330,6 +340,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'tasks', Model: Task, service: feathersClient.service('tasks') }) @@ -340,9 +351,10 @@ describe('Service Module - Actions', () => { actions.find .call({ $store: store }, { query: { $limit: 1, $skip: 8 } }) .then(response => { + const returnedRecord = JSON.parse(JSON.stringify(response.data[0])) assert(response.data.length === 1, 'only one record was returned') assert.deepEqual( - response.data[0], + returnedRecord, { id: 8, description: 'Do the ninth' }, 'the ninth record was returned' ) @@ -357,6 +369,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'tasks', Model: Task, service: feathersClient.service('tasks') }) @@ -386,6 +399,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'tasks', Model: Task, service: feathersClient.service('tasks') }) @@ -411,6 +425,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'tasks', Model: Task, service: feathersClient.service('tasks') }) @@ -440,6 +455,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'tasks', Model: Task, service: feathersClient.service('tasks') }) @@ -475,6 +491,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'no-ids', Model: NoId, service: feathersClient.service('no-ids'), idField: '_id' @@ -498,6 +515,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'no-ids', Model: NoId, service: feathersClient.service('no-ids'), idField: '_id', @@ -528,6 +546,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'broken', Model: Broken, service: feathersClient.service('broken') }) @@ -557,6 +576,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'todos', Model: Todo, service: feathersClient.service('todos') }) @@ -579,7 +599,10 @@ describe('Service Module - Actions', () => { let expectedKeyedById: NumberedList = { 0: { id: 0, description: 'Do the first' } } - assert.deepEqual(todoState.keyedById, expectedKeyedById) + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) // Make a request with the array syntax that allows passing params actions.get.call({ $store: store }, [1, {}]).then(response2 => { @@ -588,7 +611,10 @@ describe('Service Module - Actions', () => { 1: { id: 1, description: 'Do the second' } } assert(response2.description === 'Do the second') - assert.deepEqual(todoState.keyedById, expectedKeyedById) + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) // Make a request to an existing record and return the existing data first, then update `keyedById` todoState.keyedById = { @@ -601,7 +627,10 @@ describe('Service Module - Actions', () => { 1: { id: 1, description: 'Do the second' } } assert(response3.description === 'Do the FIRST') - assert.deepEqual(todoState.keyedById, expectedKeyedById) + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) // Wait for the remote data to arriive setTimeout(() => { @@ -609,7 +638,10 @@ describe('Service Module - Actions', () => { 0: { id: 0, description: 'Do the first' }, 1: { id: 1, description: 'Do the second' } } - assert.deepEqual(todoState.keyedById, expectedKeyedById) + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) done() }, 100) }) @@ -627,6 +659,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'todos', Model: Todo, service: feathersClient.service('todos') }) @@ -651,7 +684,10 @@ describe('Service Module - Actions', () => { let expectedKeyedById: NumberedList = { 0: { id: 0, description: 'Do the first' } } - assert.deepEqual(todoState.keyedById, expectedKeyedById) + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) // Make a request with the array syntax that allows passing params actions.get.call({ $store: store }, [1, {}]).then(response2 => { @@ -660,7 +696,10 @@ describe('Service Module - Actions', () => { 1: { id: 1, description: 'Do the second' } } assert(response2.description === 'Do the second') - assert.deepEqual(todoState.keyedById, expectedKeyedById) + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) // Make a request to an existing record and return the existing data first, then update `keyedById` todoState.keyedById = { @@ -673,7 +712,10 @@ describe('Service Module - Actions', () => { 1: { id: 1, description: 'Do the second' } } assert(response3.description === 'Do the FIRST') - assert.deepEqual(todoState.keyedById, expectedKeyedById) + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) // Wait for the remote data to arriive setTimeout(() => { @@ -681,7 +723,10 @@ describe('Service Module - Actions', () => { 0: { id: 0, description: 'Do the first' }, 1: { id: 1, description: 'Do the second' } } - assert.deepEqual(todoState.keyedById, expectedKeyedById) + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) done() }, 100) }) @@ -692,13 +737,14 @@ describe('Service Module - Actions', () => { assert(todoState.ids.length === 0) assert(todoState.errorOnCreate === null) assert(todoState.isGetPending === true) - assert.deepEqual(todoState.keyedById, {}) + assert.deepEqual(JSON.parse(JSON.stringify(todoState.keyedById)), {}) }) it('does not make remote call when skipRequestIfExists=true', done => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'todos', Model: Todo, service: feathersClient.service('todos') }) @@ -719,7 +765,10 @@ describe('Service Module - Actions', () => { let expectedKeyedById: NumberedList = { 0: { id: 0, description: 'Do the first' } } - assert.deepEqual(todoState.keyedById, expectedKeyedById) + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) // Make a request with the array syntax that allows passing params actions.get.call({ $store: store }, [1, {}]).then(response2 => { @@ -728,7 +777,10 @@ describe('Service Module - Actions', () => { 1: { id: 1, description: 'Do the second' } } assert(response2.description === 'Do the second') - assert.deepEqual(todoState.keyedById, expectedKeyedById) + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) // Make a request to an existing record and return the existing data first, then update `keyedById` todoState.keyedById = { @@ -743,7 +795,10 @@ describe('Service Module - Actions', () => { 1: { id: 1, description: 'Do the second' } } assert(response3.description === 'Do the FIRST') - assert.deepEqual(todoState.keyedById, expectedKeyedById) + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) // The remote data will never arriive setTimeout(() => { @@ -751,7 +806,10 @@ describe('Service Module - Actions', () => { 0: { id: 0, description: 'Do the FIRST' }, 1: { id: 1, description: 'Do the second' } } - assert.deepEqual(todoState.keyedById, expectedKeyedById) + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) done() }, 100) }) @@ -762,13 +820,14 @@ describe('Service Module - Actions', () => { assert(todoState.ids.length === 0) assert(todoState.errorOnCreate === null) assert(todoState.isGetPending === true) - assert.deepEqual(todoState.keyedById, {}) + assert.deepEqual(JSON.parse(JSON.stringify(todoState.keyedById)), {}) }) it('updates errorOnGet state on service failure', done => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'broken', Model: Broken, service: feathersClient.service('broken') }) @@ -798,6 +857,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'todos', Model: Todo, service: feathersClient.service('todos') }) @@ -821,13 +881,14 @@ describe('Service Module - Actions', () => { assert(todoState.errorOnCreate === null) assert(todoState.isCreatePending === true) assert(todoState.idField === 'id') - assert.deepEqual(todoState.keyedById, {}) + assert.deepEqual(JSON.parse(JSON.stringify(todoState.keyedById)), {}) }) it('updates errorOnCreate state on service failure', done => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'broken', Model: Broken, service: feathersClient.service('broken') }) @@ -860,6 +921,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'todos', Model: Todo, service: feathersClient.service('todos') }) @@ -902,6 +964,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'broken', Model: Broken, service: feathersClient.service('broken') }) @@ -938,6 +1001,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'todos', Model: Todo, service: feathersClient.service('todos') }) @@ -989,6 +1053,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'todos', Model: Todo, service: feathersClient.service('todos') }) @@ -1025,6 +1090,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'broken', Model: Broken, service: feathersClient.service('broken') }) @@ -1061,6 +1127,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'todos', Model: Todo, service: feathersClient.service('todos') }) @@ -1097,6 +1164,7 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ + servicePath: 'broken', Model: Broken, service: feathersClient.service('broken') }) diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index 9fb18861..652d6897 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -13,7 +13,7 @@ import _pick from 'lodash.pick' Vue.use(Vuex) describe('makeServicePlugin', function() { - it('regisers the vuex module with options', function() { + it('registers the vuex module with options', function() { const serverAlias = 'default' const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { serverAlias @@ -24,6 +24,7 @@ describe('makeServicePlugin', function() { public servicePath = servicePath } const todosPlugin = makeServicePlugin({ + servicePath, Model: Todo, service: feathers.service(servicePath) }) @@ -68,7 +69,7 @@ describe('makeServicePlugin', function() { class Todo extends BaseModel { public servicePath = servicePath } - const todosPlugin = makeServicePlugin({ Model: Todo, service }) + const todosPlugin = makeServicePlugin({ servicePath, Model: Todo, service }) const store = new Vuex.Store({ plugins: [todosPlugin] }) assert(Todo.store === store, 'the store is on the Model!') @@ -87,6 +88,7 @@ describe('makeServicePlugin', function() { public servicePath = servicePath } const todosPlugin = makeServicePlugin({ + servicePath, Model: Todo, service: feathers.service(servicePath) }) diff --git a/test/service-module/model-base.test.ts b/test/service-module/model-base.test.ts index 03f1f3d8..9c564a97 100644 --- a/test/service-module/model-base.test.ts +++ b/test/service-module/model-base.test.ts @@ -92,6 +92,7 @@ describe('makeModel / BaseModel', function() { serverAlias: 'myApi' }) const plugin = makeServicePlugin({ + servicePath: 'todos', service: feathers.service('todos'), Model: BaseModel }) @@ -117,6 +118,7 @@ describe('makeModel / BaseModel', function() { public test: boolean = true } const todosPlugin = makeServicePlugin({ + servicePath: 'todos', Model: Todo, service: feathers.service('todos') }) @@ -126,6 +128,7 @@ describe('makeModel / BaseModel', function() { public test: boolean = true } const tasksPlugin = makeServicePlugin({ + servicePath: 'tasks', Model: Task, service: feathers.service('tasks') }) From 9b7d343653f09cf826ee26a346565fa85387affb Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 25 Mar 2019 00:49:31 -0600 Subject: [PATCH 031/404] Remove current and setCurrent --- docs/service-module.md | 59 +++++++++++-- package-lock.json | 3 +- package.json | 1 + src/service-module/make-service-module.ts | 6 +- src/service-module/module.actions.ts | 10 --- src/service-module/module.mutations.ts | 37 ++------ src/service-module/module.state.ts | 8 +- test/service-module/actions.test.ts | 86 ------------------- .../make-service-plugin.test.ts | 22 ++++- ...getters.test.js => module.getters.test.ts} | 66 +++++++------- test/service-module/service-module.test.js | 2 - 11 files changed, 117 insertions(+), 183 deletions(-) rename test/service-module/{getters.test.js => module.getters.test.ts} (80%) diff --git a/docs/service-module.md b/docs/service-module.md index cc3aba89..db0ed41b 100644 --- a/docs/service-module.md +++ b/docs/service-module.md @@ -1,5 +1,8 @@ + + --- title: Service Module API + --- The `Service Module` creates plugins which can be used to connect a Feathers service to the Vuex store. Once you create the plugin, you must register it in the `plugins` section of your store setup: @@ -47,21 +50,20 @@ export default new Vuex.Store({ Once the service plugin has been registered with Vuex, the FeathersClient Service will have a new `service.FeathersVuexModel` property. This provides access to the service's [Model class](./model-classes.md). ## Service State + Each service comes loaded with the following default state: + ```js { ids: [], keyedById: {}, // A hash map, keyed by id of each item currentId: undefined, // The id of the item marked as current - copy: undefined, // A deep copy of the current item idField: 'id', servicePath: 'v1/todos' // The full service path autoRemove: false, // Indicates that this service will not automatically remove results missing from subsequent requests. replaceItems: false, // When set to true, updates and patches will replace the record in the store instead of merging changes paginate: false, // Indicates if pagination is enabled on the Feathers service. - setCurrentOnGet: true, // Automatically sets the `current` property to the record retrieved from get requests - setCurrentOnCreate: true, // Automatically sets the `current` property to the record returned from a create paramsForServer: [], // Custom query operators that are ignored in the find getter, but will pass through to the server. whitelist: [], // Custom query operators that will be allowed in the find getter. @@ -87,17 +89,16 @@ The following attributes are available in each service module's state: - `ids {Array}` - an array of plain ids representing the ids that belong to each object in the `keyedById` map. - `keyedById {Object}` - a hash map keyed by the id of each item. - `currentId {Number|String}` - the id of the item marked as current. -- `copy {Object}` - a deep copy of the current item at the moment it was marked as current. You can make changes to the copy without modifying the `current`. You can then use the `commitCopy` mutation to save the changes as the `current` or `rejectCopy` to revert `copy` to once again match `current`. You may prefer to use the new [clone API]() for [managing multiple copies with model instances](./common-patterns.md#Multiple-Copies). +- `copy {Object}` - a deep copy of the current item at the moment it was marked as current. You can make changes to the copy without modifying the `current`. You can then use the `commitCopy` mutation to save the changes as the `current` or `rejectCopy` to revert `copy` to once again match `current`. You may prefer to use the new [clone API](./common-patterns.md#Multiple-Copies) for [managing multiple copies with model instances](./common-patterns.md#Multiple-Copies). - `servicePath {String}` - the full service path, even if you alias the namespace to something else. - `modelName {String}` - the key in the $FeathersVuex plugin where the model will be found. - `autoRemove {Boolean` - indicates that this service will not automatically remove results missing from subsequent requests. Only use with feathers-rest. Default is false. - `replaceItems {Boolean}` - When set to true, updates and patches will replace the record in the store instead of merging changes. Default is false - `idField {String}` - the name of the field that holds each item's id. *Default: `'id'`* - `paginate {Boolean}` - Indicates if the service has pagination turned on. -- `setCurrentOnGet {Boolean}` - Automatically sets the `current` property to the record retrieved from get requests. Default is true -- `setCurrentOnCreate {Boolean}` - Automatically sets the `current` property to the record returned from create. Default is true The following state attributes allow you to bind to the pending state of requests: + - `isFindPending {Boolean}` - `true` if there's a pending `find` request. `false` if not. - `isGetPending {Boolean}` - `true` if there's a pending `get` request. `false` if not. - `isCreatePending {Boolean}` - `true` if there's a pending `create` request. `false` if not. @@ -106,6 +107,7 @@ The following state attributes allow you to bind to the pending state of request - `isRemovePending {Boolean}` - `true` if there's a pending `remove` request. `false` if not. The following state attribute will be populated with any request error, serialized as a plain object: + - `errorOnFind {Error}` - `errorOnGet {Error}` - `errorOnCreate {Error}` @@ -114,7 +116,9 @@ The following state attribute will be populated with any request error, serializ - `errorOnRemo {Error}` ## Service Getters + Service modules include the following getters: + - `list {Array}` - an array of items. The array form of `keyedById` Read only. - `find(params) {Function}` - a helper function that allows you to use the [Feathers Adapter Common API](https://docs.feathersjs.com/api/databases/common) and [Query API](https://docs.feathersjs.com/api/databases/querying) to pull data from the store. This allows you to treat the store just like a local Feathers database adapter (but without hooks). - `params {Object}` - an object with a `query` object and an optional `paginate` boolean property. The `query` is in the FeathersJS query format. You can set `params.paginate` to `false` to disable pagination for a single request. @@ -125,53 +129,70 @@ Service modules include the following getters: - `getCopy {Object}` - An alias to the `state.copy`. ## Service Mutations + The following mutations are included in each service module. > **Note:** you would typically not call these directly, but instead with `store.commit('removeItem', 'itemId')`. Using vuex's mapMutations on a Vue component can simplify that to `this.removeItem('itemId')` ### `addItem(state, item)` + Adds a single item to the `keyedById` map. + - `item {Object}` - The item to be added to the store. ### `addItems(state, items)` + Adds an array of items to the `keyedById` map. + - `items {Array}` - the items to be added to the store. ### `updateItem(state, item)` + Updates an item in the store to match the passed in `item`. + - `item {Object}` the item, including `id`, to replace the currently-stored item. ### `updateItems(state, items)` + Updates multiple items in the store to match the passed in array of items. + - `items {Array}` - An array of items. ### `removeItem(state, item)` + Removes a single item. `item` can be + - `item {Number|String|Object}` - The item or id of the item to be deleted. ### `removeItems(state, items)` + Removes the passed in items or ids from the store. -- `items {Array}` - An array of ids or of objects with ids that will be removed from the data store. -### `setCurrent(state, item)` -- `item {Number|String|Object}` - the object with id to be set as the current item, or the id of the object in the store that should become the `current` item. Setting the `current` item or id also create the deep-cloned `copy`. +- `items {Array}` - An array of ids or of objects with ids that will be removed from the data store. ### `commitCopy(state)` + Saves changes from the `copy` to the `current` item. ### `rejectCopy(state)` + Re-copies the data from `current` to `copy`, restoring the original copy. ### `clearCurrent(state)` + Clears the `current` item, which also clears the copy. ### `clearList(state)` + Clears the `list`, excepting the `current` item. ### `clearAll(state)` + Clears all data from `ids`, `keyedById`, and `currentId` ### Mutations for Managing Pending State + The following mutations are called automatically by the service actions, and will rarely, if ever, need to be used manually. + - `setFindPending(state)` - sets `isFindPending` to `true` - `unsetFindPending(state)` - sets `isFindPending` to `false` - `setGetPending(state)` - sets `isGetPending` to `true` @@ -186,7 +207,9 @@ The following mutations are called automatically by the service actions, and wil - `unsetRemovePending(state)` - sets `isRemovePending` to `false` ### Mutations for Managing Errors + The following mutations are called automatically by the service actions, and will rarely need to be used manually. + - `setFindError(state, error)` - `clearFindError(state)` - `setGetError(state, error)` @@ -201,6 +224,7 @@ The following mutations are called automatically by the service actions, and wil - `clearRemoveError(state)` ## Service Actions + An action is included for each of the Feathers service interface methods. These actions will affect changes in both the Feathers API server and the Vuex store. All of the [Feathers Service Methods](https://docs.feathersjs.com/api/databases/common#service-methods) are supported. Because Vuex only supports providing a single argument to actions, there is a slight change in syntax that works well. If you need to pass multiple arguments to a service method, pass an array to the action with the order of the array elements matching the order of the arguments. See each method for examples. @@ -208,7 +232,9 @@ All of the [Feathers Service Methods](https://docs.feathersjs.com/api/databases/ > Note: If you use the Feathers service methods, directly, the store will not change. Only the actions will cause store changes. ### `find(params)` + Query an array of records from the server & add to the Vuex store. + - `params {Object}` - An object containing a `query` object and an optional `paginate` boolean. You can set `params.paginate` to `false` to disable pagination for a single request. ```js @@ -223,7 +249,9 @@ See the section about pagination, below, for more information that is applicable The `afterFind` action is called by the `find` action after a successful response is added to the store. It is called with the current response. By default, it is a no-op (it literally does nothing), and is just a placeholder for you to use when necessary. See the sections on [customizing the default store](#Customizing-a-Service’s-Default-Store) and [Handling custom server responses](./common-patterns.md#Handling-custom-server-responses) for example usage. ### `get(id)` or `get([id, params])` + Query a single record from the server & add to Vuex store + - `id {Number|String}` - the `id` of the record being requested from the API server. - `params {Object}` - An object containing a `query` object. @@ -238,7 +266,9 @@ store.dispatch('todos/get', [1, params]) Make sure your returned records have a unique field that matches the `idField` option for the service plugin. ### `create(data)` + Create one or multiple records. + - `data {Object|Array}` - if an object is provided, a single record will be created. If an array of objects is provided, multiple records will be created. ```js @@ -249,7 +279,9 @@ store.dispatch('todos/create', newTodo) Make sure your returned records have a unique field that matches the `idField` option for the service plugin. ### `update(paramArray)` + Update (overwrite) a record. + - `paramArray {Array}` - array containing the three parameters update takes. - `id {Number|String}` - the `id` of the existing record being requested from the API server. - `data {Object}` - the data that will overwrite the existing record @@ -280,7 +312,9 @@ export default { Make sure your returned records have a unique field that matches the `idField` option for the service plugin. ### `patch(paramArray)` + Patch (merge in changes) one or more records + - `paramArray {Array}` - array containing the three parameters patch takes. - `id {Number|String}` - the `id` of the existing record being requested from the API server. - `data {Object}` - the data that will be merged into the existing record @@ -295,7 +329,9 @@ store.dispatch('todos/patch', [1, data, params]) Make sure your returned records have a unique field that matches the `idField` option for the service plugin. ### `remove(id)` + Remove/delete the record with the given `id`. + - `id {Number|String}` - the `id` of the existing record being requested from the API server. ```js @@ -305,6 +341,7 @@ store.dispatch('todos/remove', 1) Make sure your returned records have a unique field that matches the `idField` option for the service plugin. ## Querying with Find & Pagination + Both the `find` action and the `find` getter support pagination. There are differences in how they work. ### The `find` action @@ -314,6 +351,7 @@ The `find` action queries data from the remote server. It returns a promise tha `feathers-vuex@1.0.0` can store pagination data on a per-query basis. The `pagination` store attribute maps queries to their most-recent pagination data. It's an empty object by default, but after performing a single query (with pagination in the response), it will have a `default` property. This property stores pagination information for the query. Here's what it will look like: **`params = { query: {} }`** + ```js { pagination: { @@ -332,6 +370,7 @@ The `find` action queries data from the remote server. It returns a promise tha It's possible that you'll want to store pagination information for more than one query. This might be for different components making queries against the same service, for example. You can use the `params.qid` (query identifier) property to assign a name to the query. If you set a `qid` of `mainListView`, for example, the pagination for this query will show up under `pagination.mainListView`. The `pagination.default` property will be used any time a `params.qid` is not provided. Here's an example of what this might look like: **`params = { query: { $limit: 1 }, qid: 'mainListView' }`** + ```js // Data in the store { @@ -349,6 +388,7 @@ It's possible that you'll want to store pagination information for more than one ``` > Note: The `find` action no longer returns reactive lists. The list data will still be reactive, but new matches that arrive from the server do NOT get automatically added to lists. There are two solutions to this: + - Use the `find` action to pull in data from the server. Use the `find` getter to pull a reactive list from the store. - Configure the `feathers-reactive` plugin with RxJS on your Feathers Client instance. [Read the docs for implementation details.](https://github.com/feathers-plus/feathers-reactive) @@ -357,6 +397,7 @@ It's possible that you'll want to store pagination information for more than one The `find` getter queries data from the local store using the same Feathers query syntax as on the server. It is synchronous and returns the results of the query with pagination. Pagination cannot be disabled. It accepts a params object with a `query` attribute. It does not use any other special attributes. The returned object looks just like a paginated result that you would receive from the server: **`params = { query: {} }`** + ```js // The returned results object { diff --git a/package-lock.json b/package-lock.json index 47f96ced..7fdfd075 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13727,8 +13727,7 @@ "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" }, "lodash._reinterpolate": { "version": "3.0.0", diff --git a/package.json b/package.json index ac465027..ed2b851b 100644 --- a/package.json +++ b/package.json @@ -106,6 +106,7 @@ "fast-copy": "^1.2.3", "inflection": "^1.12.0", "jwt-decode": "^2.2.0", + "lodash": "^4.17.11", "lodash.isobject": "^3.0.2", "lodash.isplainobject": "^4.0.6", "lodash.merge": "^4.6.1", diff --git a/src/service-module/make-service-module.ts b/src/service-module/make-service-module.ts index 23c584dd..418ef429 100644 --- a/src/service-module/make-service-module.ts +++ b/src/service-module/make-service-module.ts @@ -34,11 +34,7 @@ export default function makeServiceModule(service, options) { return { namespaced: true, - state: Object.assign( - { options: stateOptions }, - defaultState, - nonStateOptions.state - ), + state: Object.assign(stateOptions, defaultState, nonStateOptions.state), getters: Object.assign({}, defaultGetters, options.getters), mutations: Object.assign({}, defaultMutations, options.mutations), actions: Object.assign({}, defaultActions, options.actions) diff --git a/src/service-module/module.actions.ts b/src/service-module/module.actions.ts index 44ae3a36..227da87a 100644 --- a/src/service-module/module.actions.ts +++ b/src/service-module/module.actions.ts @@ -90,9 +90,6 @@ export default function makeServiceActions(service, { debug }) { dispatch('addOrUpdate', item) - if (state.setCurrentOnGet) { - commit('setCurrent', item) - } commit('unsetGetPending') return state.keyedById[id] }) @@ -106,9 +103,6 @@ export default function makeServiceActions(service, { debug }) { // If the records is already in store, return it const existedItem = getters.get(id, params) if (existedItem) { - if (state.setCurrentOnGet) { - commit('setCurrent', existedItem) - } if (!skipRequestIfExists) getFromRemote() return Promise.resolve(existedItem) } @@ -146,10 +140,6 @@ export default function makeServiceActions(service, { debug }) { dispatch('addOrUpdate', response) - if (state.setCurrentOnCreate) { - commit('setCurrent', response) - } - response = state.keyedById[id] } commit('unsetCreatePending') diff --git a/src/service-module/module.mutations.ts b/src/service-module/module.mutations.ts index 9152c746..c140a0dd 100644 --- a/src/service-module/module.mutations.ts +++ b/src/service-module/module.mutations.ts @@ -9,12 +9,15 @@ import serializeError from 'serialize-error' import isObject from 'lodash.isobject' import { checkId, updateOriginal } from '../utils' import { globalModels } from './global-models' +import { get } from 'lodash' export default function makeServiceMutations(servicePath, { debug }) { function addItems(state, items) { const { idField } = state - const Model = - globalModels[state.options.serverAlias].byServicePath[servicePath] + const Model = get( + globalModels, + `[${state.serverAlias}].byServicePath[${servicePath}]` + ) let newKeyedById = { ...state.keyedById } @@ -41,8 +44,10 @@ export default function makeServiceMutations(servicePath, { debug }) { function updateItems(state, items) { const { idField, replaceItems, addOnUpsert } = state - const Model = - globalModels[state.options.serverAlias].byServicePath[servicePath] + const Model = get( + globalModels, + `[${state.serverAlias}].byServicePath[${servicePath}]` + ) for (let item of items) { let id = item[idField] @@ -181,30 +186,6 @@ export default function makeServiceMutations(servicePath, { debug }) { } }, - setCurrent(state, itemOrId) { - const { idField } = state - const Model = - globalModels[state.options.serverAlias].byServicePath[servicePath] - let id - let item - - if (isObject(itemOrId)) { - id = itemOrId[idField] - item = itemOrId - } else { - id = itemOrId - item = state.keyedById[id] - } - state.currentId = id - - state.copy = new Model(item, { isClone: true }) - }, - - clearCurrent(state) { - state.currentId = null - state.copy = null - }, - // Removes the copy from copiesById clearCopy(state, id) { const newCopiesById = Object.assign({}, state.copiesById) diff --git a/src/service-module/module.state.ts b/src/service-module/module.state.ts index edad2ba3..d4a4a1a6 100644 --- a/src/service-module/module.state.ts +++ b/src/service-module/module.state.ts @@ -10,6 +10,7 @@ export default function makeDefaultState(servicePath, options) { enableEvents, addOnUpsert, diffOnPatch, + serverAlias, skipRequestIfExists, preferUpdate, replaceItems, @@ -21,10 +22,6 @@ export default function makeDefaultState(servicePath, options) { ids: [], keyedById: {}, copiesById: {}, - currentId: null, - copy: null, - setCurrentOnGet: true, - setCurrentOnCreate: true, idField, servicePath, autoRemove, @@ -34,9 +31,10 @@ export default function makeDefaultState(servicePath, options) { skipRequestIfExists, preferUpdate, replaceItems, - pagination: {}, + serverAlias, paramsForServer, whitelist, + pagination: {}, isFindPending: false, isGetPending: false, diff --git a/test/service-module/actions.test.ts b/test/service-module/actions.test.ts index 20a8659d..b193ddf7 100644 --- a/test/service-module/actions.test.ts +++ b/test/service-module/actions.test.ts @@ -32,7 +32,6 @@ interface ServiceState { isPatchPending: boolean isUpdatePending: boolean isRemovePending: boolean - setCurrentOnGet: boolean idField: string keyedById: {} pagination?: { @@ -655,91 +654,6 @@ describe('Service Module - Actions', () => { assert.deepEqual(todoState.keyedById, {}) }) - it('does not set currentId when setCurrentOnGet is false', done => { - const store = new Vuex.Store({ - plugins: [ - makeServicePlugin({ - servicePath: 'todos', - Model: Todo, - service: feathersClient.service('todos') - }) - ] - }) - const todoState = store.state.todos - const actions = mapActions('todos', ['get']) - - todoState.setCurrentOnGet = false - - assert(todoState.ids.length === 0) - assert(todoState.errorOnGet === null) - assert(todoState.isGetPending === false) - assert(todoState.idField === 'id') - - actions.get.call({ $store: store }, 0).then(() => { - assert(todoState.ids.length === 1, 'only one item is in the store') - assert(todoState.errorOnGet === null, 'there was no errorOnGet') - assert(todoState.isGetPending === false, 'isGetPending is set to false') - assert(todoState.currentId === null, 'the currentId was set') - - let expectedKeyedById: NumberedList = { - 0: { id: 0, description: 'Do the first' } - } - assert.deepEqual( - JSON.parse(JSON.stringify(todoState.keyedById)), - expectedKeyedById - ) - - // Make a request with the array syntax that allows passing params - actions.get.call({ $store: store }, [1, {}]).then(response2 => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the first' }, - 1: { id: 1, description: 'Do the second' } - } - assert(response2.description === 'Do the second') - assert.deepEqual( - JSON.parse(JSON.stringify(todoState.keyedById)), - expectedKeyedById - ) - - // Make a request to an existing record and return the existing data first, then update `keyedById` - todoState.keyedById = { - 0: { id: 0, description: 'Do the FIRST' }, // twist the data to see difference - 1: { id: 1, description: 'Do the second' } - } - actions.get.call({ $store: store }, [0, {}]).then(response3 => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the FIRST' }, - 1: { id: 1, description: 'Do the second' } - } - assert(response3.description === 'Do the FIRST') - assert.deepEqual( - JSON.parse(JSON.stringify(todoState.keyedById)), - expectedKeyedById - ) - - // Wait for the remote data to arriive - setTimeout(() => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the first' }, - 1: { id: 1, description: 'Do the second' } - } - assert.deepEqual( - JSON.parse(JSON.stringify(todoState.keyedById)), - expectedKeyedById - ) - done() - }, 100) - }) - }) - }) - - // Make sure proper state changes occurred before response - assert(todoState.ids.length === 0) - assert(todoState.errorOnCreate === null) - assert(todoState.isGetPending === true) - assert.deepEqual(JSON.parse(JSON.stringify(todoState.keyedById)), {}) - }) - it('does not make remote call when skipRequestIfExists=true', done => { const store = new Vuex.Store({ plugins: [ diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index 652d6897..76d2b9a2 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -13,7 +13,7 @@ import _pick from 'lodash.pick' Vue.use(Vuex) describe('makeServicePlugin', function() { - it('registers the vuex module with options', function() { + it.only('registers the vuex module with options', function() { const serverAlias = 'default' const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { serverAlias @@ -33,19 +33,35 @@ describe('makeServicePlugin', function() { } const store = new Vuex.Store({ plugins: [todosPlugin] }) - const keys = Object.keys(store.state.todos.options) - const received = _pick(store.state.todos.options, keys) + const keys = Object.keys(store.state.todos) + const received = _pick(store.state.todos, keys) const expected = { addOnUpsert: false, autoRemove: false, debug: false, + copiesById: {}, diffOnPatch: true, enableEvents: true, + errorOnCreate: null, + errorOnFind: null, + errorOnGet: null, + errorOnPatch: null, + errorOnRemove: null, + errorOnUpdate: null, idField: 'id', + ids: [], + isCreatePending: false, + isFindPending: false, + isGetPending: false, + isPatchPending: false, + isRemovePending: false, + isUpdatePending: false, keepCopiesInStore: false, + keyedById: {}, modelName: 'Todo', nameStyle: 'short', namespace: 'todos', + pagination: {}, paramsForServer: [], preferUpdate: false, replaceItems: false, diff --git a/test/service-module/getters.test.js b/test/service-module/module.getters.test.ts similarity index 80% rename from test/service-module/getters.test.js rename to test/service-module/module.getters.test.ts index fed2d88a..452e534d 100644 --- a/test/service-module/getters.test.js +++ b/test/service-module/module.getters.test.ts @@ -1,18 +1,24 @@ -import assert from 'chai/chai' -import makeServiceGetters from '~/src/service-module/getters' -import makeServiceMutations from '~/src/service-module/mutations' -import makeServiceState from '~/src/service-module/state' +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { assert } from 'chai' +import makeServiceGetters from '../../src/service-module/module.getters' +import makeServiceMutations from '../../src/service-module/module.mutations' +import makeServiceState from '../../src/service-module/module.state' const options = { idField: '_id', - autoRemove: false + autoRemove: false, + serverAlias: 'default' } -const { find, list } = makeServiceGetters('todos', options) -const { addItems } = makeServiceMutations('todos', options) +const { find, list } = makeServiceGetters() +const { addItems } = makeServiceMutations('todos', { debug: false }) -describe('Service Module - Getters', function () { - beforeEach(function () { +describe('Service Module - Getters', function() { + beforeEach(function() { const state = makeServiceState('todos', options) this.items = [ { _id: 1, otherField: true, test: true }, @@ -21,31 +27,27 @@ describe('Service Module - Getters', function () { name: 'Marshall', otherField: true, test: true, - movies: [ - { actors: [ 'Jerry the Mouse' ] } - ] + movies: [{ actors: ['Jerry the Mouse'] }] }, { _id: 3, otherField: true, test: false, - movies: [ - { actors: [ 'Tom Hanks', 'Tom Cruise', 'Tomcat' ] } - ] + movies: [{ actors: ['Tom Hanks', 'Tom Cruise', 'Tomcat'] }] } ] addItems(state, this.items) this.state = state }) - it('list', function () { + it('list', function() { const { state, items } = this const results = list(state) assert.deepEqual(results, items, 'the list was correct') }) - it('find', function () { + it('find', function() { const { state, items } = this const params = { query: {} } const results = find(state)(params) @@ -56,7 +58,7 @@ describe('Service Module - Getters', function () { assert(results.total === 3, 'total was correct') }) - it('find with query', function () { + it('find with query', function() { const { state } = this const params = { query: { test: false } } const results = find(state)(params) @@ -68,7 +70,7 @@ describe('Service Module - Getters', function () { assert(results.total === 1, 'total was correct') }) - it('find with custom operator', function () { + it('find with custom operator', function() { const { state } = this const params = { query: { test: false, $populateQuery: 'test' } } const results = find(state)(params) @@ -80,9 +82,9 @@ describe('Service Module - Getters', function () { assert(results.total === 1, 'total was correct') }) - it('find with paramsForServer option', function () { + it('find with paramsForServer option', function() { const { state } = this - state.paramsForServer = [ '_$client' ] + state.paramsForServer = ['_$client'] const params = { query: { test: false, _$client: 'test' } } const results = find(state)(params) @@ -93,28 +95,26 @@ describe('Service Module - Getters', function () { assert(results.total === 1, 'total was correct') }) - it('find with non-whitelisted custom operator fails', function () { + it('find with non-whitelisted custom operator fails', function() { const { state } = this const params = { query: { $client: 'test' } } - let results = [] try { - results = find(state)(params) + var results = find(state)(params) } catch (error) { assert(error) } - assert(!results.length) + assert(!results[0]) }) - it('find with whitelisted custom operators', function () { + it('find with whitelisted custom operators', function() { const { state } = this state.whitelist = ['$regex', '$options'] const query = { name: { $regex: 'marsh', $options: 'igm' } } const params = { query } - let results = [] try { - results = find(state)(params) + var results = find(state)(params) } catch (error) { assert(!error, 'should not have failed with whitelisted custom operator') } @@ -125,7 +125,7 @@ describe('Service Module - Getters', function () { assert(results.total === 1, 'total was correct') }) - it('find works with $elemMatch', function () { + it('find works with $elemMatch', function() { const { state } = this const query = { movies: { @@ -142,7 +142,7 @@ describe('Service Module - Getters', function () { assert(results.total === 1, 'total was correct') }) - it('find with limit', function () { + it('find with limit', function() { const { state } = this const params = { query: { $limit: 1 } } const results = find(state)(params) @@ -154,7 +154,7 @@ describe('Service Module - Getters', function () { assert(results.total === 3, 'total was correct') }) - it('find with skip', function () { + it('find with skip', function() { const { state } = this const params = { query: { $skip: 1 } } const results = find(state)(params) @@ -167,7 +167,7 @@ describe('Service Module - Getters', function () { assert(results.total === 3, 'total was correct') }) - it('find with limit and skip', function () { + it('find with limit and skip', function() { const { state } = this const params = { query: { $limit: 1, $skip: 1 } } const results = find(state)(params) @@ -179,7 +179,7 @@ describe('Service Module - Getters', function () { assert(results.total === 3, 'total was correct') }) - it('find with select', function () { + it('find with select', function() { const { state } = this const params = { query: { $select: ['otherField'] } } const results = find(state)(params) diff --git a/test/service-module/service-module.test.js b/test/service-module/service-module.test.js index 4b797331..b9caafc5 100644 --- a/test/service-module/service-module.test.js +++ b/test/service-module/service-module.test.js @@ -1029,8 +1029,6 @@ describe('Service Module', () => { modelName: 'Todo', addOnUpsert: false, diffOnPatch: false, - setCurrentOnGet: true, - setCurrentOnCreate: true, skipRequestIfExists: false, preferUpdate: false, replaceItems: false, From 3cf44539b0d81544b8992001fe96676780ee6e4b Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 25 Mar 2019 19:50:31 -0600 Subject: [PATCH 032/404] More TypeScript, Simplify mutations --- docs/service-module.md | 14 + .../{actions.ts => auth-module.actions.ts} | 0 .../{getters.ts => auth-module.getters.ts} | 0 ...{mutations.ts => auth-module.mutations.ts} | 0 .../{state.ts => auth-module.state.ts} | 0 src/service-module/make-service-plugin.ts | 8 +- src/service-module/notes.md | 30 +- ...e.actions.ts => service-module.actions.ts} | 48 +-- ...e.getters.ts => service-module.getters.ts} | 0 ...tations.ts => service-module.mutations.ts} | 84 +--- ...odule.state.ts => service-module.state.ts} | 6 + test/service-module/actions.test.ts | 4 +- .../make-service-plugin.test.ts | 2 +- test/service-module/mutations.test.js | 385 ++++++------------ 14 files changed, 227 insertions(+), 354 deletions(-) rename src/auth-module/{actions.ts => auth-module.actions.ts} (100%) rename src/auth-module/{getters.ts => auth-module.getters.ts} (100%) rename src/auth-module/{mutations.ts => auth-module.mutations.ts} (100%) rename src/auth-module/{state.ts => auth-module.state.ts} (100%) rename src/service-module/{module.actions.ts => service-module.actions.ts} (87%) rename src/service-module/{module.getters.ts => service-module.getters.ts} (100%) rename src/service-module/{module.mutations.ts => service-module.mutations.ts} (79%) rename src/service-module/{module.state.ts => service-module.state.ts} (91%) diff --git a/docs/service-module.md b/docs/service-module.md index db0ed41b..c02857d5 100644 --- a/docs/service-module.md +++ b/docs/service-module.md @@ -193,6 +193,8 @@ Clears all data from `ids`, `keyedById`, and `currentId` The following mutations are called automatically by the service actions, and will rarely, if ever, need to be used manually. +Before Feathers-Vuex 2.0, these were the available mutations: + - `setFindPending(state)` - sets `isFindPending` to `true` - `unsetFindPending(state)` - sets `isFindPending` to `false` - `setGetPending(state)` - sets `isGetPending` to `true` @@ -206,10 +208,17 @@ The following mutations are called automatically by the service actions, and wil - `setRemovePending(state)` - sets `isRemovePending` to `true` - `unsetRemovePending(state)` - sets `isRemovePending` to `false` +In Feathers-Vuex 2.0, these have changed to only two mutations: + +- `setPending(state, method)` - sets the `is${method}Pending` attribute to true +- `unsetPending(state, method)` - sets the `is${method}Pending` attribute to false + ### Mutations for Managing Errors The following mutations are called automatically by the service actions, and will rarely need to be used manually. +Before Feathers-Vuex 2.0, these were the available mutations: + - `setFindError(state, error)` - `clearFindError(state)` - `setGetError(state, error)` @@ -223,6 +232,11 @@ The following mutations are called automatically by the service actions, and wil - `setRemoveError(state, error)` - `clearRemoveError(state)` +In Feathers-Vuex 2.0, these have changed to only two mutations: + +- `setError(state, { method, error })` - sets the `errorOn${method}` attribute to the error +- `clearError(state, method)` - sets the `errorOn${method}` attribute to `null` + ## Service Actions An action is included for each of the Feathers service interface methods. These actions will affect changes in both the Feathers API server and the Vuex store. diff --git a/src/auth-module/actions.ts b/src/auth-module/auth-module.actions.ts similarity index 100% rename from src/auth-module/actions.ts rename to src/auth-module/auth-module.actions.ts diff --git a/src/auth-module/getters.ts b/src/auth-module/auth-module.getters.ts similarity index 100% rename from src/auth-module/getters.ts rename to src/auth-module/auth-module.getters.ts diff --git a/src/auth-module/mutations.ts b/src/auth-module/auth-module.mutations.ts similarity index 100% rename from src/auth-module/mutations.ts rename to src/auth-module/auth-module.mutations.ts diff --git a/src/auth-module/state.ts b/src/auth-module/auth-module.state.ts similarity index 100% rename from src/auth-module/state.ts rename to src/auth-module/auth-module.state.ts diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index c1bb57b0..ec06e24e 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -64,16 +64,16 @@ export default function prepareMakeServicePlugin( if (options.enableEvents) { // Listen to socket events when available. service.on('created', item => - store.commit(`${namespace}/addItem`, item) + store.commit(`${options.namespace}/addItem`, item) ) service.on('updated', item => - store.commit(`${namespace}/updateItem`, item) + store.commit(`${options.namespace}/updateItem`, item) ) service.on('patched', item => - store.commit(`${namespace}/updateItem`, item) + store.commit(`${options.namespace}/updateItem`, item) ) service.on('removed', item => - store.commit(`${namespace}/removeItem`, item) + store.commit(`${options.namespace}/removeItem`, item) ) } } diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 448b1166..178275af 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -205,4 +205,32 @@ it('works with multiple, independent Feathers servers', function() { ## Services are no longer set up internally -You no longer just pass a servicePath, but instead an entire service object. \ No newline at end of file +You no longer just pass a servicePath, but instead an entire service object. + +## Simplified Pending Mutations + +Previously, there was a mutation for every single variety of method and set/unset pending. (`setFindPending`, `unsetFindPending`, etc.). There were a total of twelve methods for this simple operation. They are now combined into two methods: `setPending(method)` and `unsetPending(method)`. Here's the difference. + +```js +// The old way +commit('setFindPending') +commit('unsetFindPending') + +// The new way +commit('setPending', 'find') +commit('unsetPending', 'find') +``` + +## Simplified Error Mutations + +The "error" mutations have been simplified similar to the "pending" mutations: + +```js +// The old way +commit('setFindError', error) +commit('clearFindError') + +// The new way +commit('setError', { method: 'find', error }) +commit('clearError', 'find') +``` diff --git a/src/service-module/module.actions.ts b/src/service-module/service-module.actions.ts similarity index 87% rename from src/service-module/module.actions.ts rename to src/service-module/service-module.actions.ts index 227da87a..8514ca07 100644 --- a/src/service-module/module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -14,7 +14,7 @@ export default function makeServiceActions(service, { debug }) { const { qid = 'default', query } = params dispatch('addOrUpdateList', response) - commit('unsetFindPending') + commit('unsetPending', 'find') const mapItemFromState = item => { const id = item[idField] @@ -44,12 +44,12 @@ export default function makeServiceActions(service, { debug }) { return response } const handleError = error => { - commit('setFindError', error) - commit('unsetFindPending') + commit('setError', { method: 'find', error }) + commit('unsetPending', 'find') return Promise.reject(error) } - commit('setFindPending') + commit('setPending', 'find') return service .find(params) @@ -82,7 +82,7 @@ export default function makeServiceActions(service, { debug }) { } function getFromRemote() { - commit('setGetPending') + commit('setPending', 'get') return service .get(id, params) .then(item => { @@ -90,12 +90,12 @@ export default function makeServiceActions(service, { debug }) { dispatch('addOrUpdate', item) - commit('unsetGetPending') + commit('unsetPending', 'get') return state.keyedById[id] }) .catch(error => { - commit('setGetError', error) - commit('unsetGetPending') + commit('setError', { method: 'get', error }) + commit('unsetPending', 'get') return Promise.reject(error) }) } @@ -123,7 +123,7 @@ export default function makeServiceActions(service, { debug }) { params = params || {} - commit('setCreatePending') + commit('setPending', 'create') return service .create(data, params) @@ -142,12 +142,12 @@ export default function makeServiceActions(service, { debug }) { response = state.keyedById[id] } - commit('unsetCreatePending') + commit('unsetPending', 'create') return response }) .catch(error => { - commit('setCreateError', error) - commit('unsetCreatePending') + commit('setError', { method: 'create', error }) + commit('unsetPending', 'create') return Promise.reject(error) }) }, @@ -155,19 +155,19 @@ export default function makeServiceActions(service, { debug }) { update({ commit, dispatch, state }, [id, data, params]) { const { idField } = state - commit('setUpdatePending') + commit('setPending', 'update') return service .update(id, data, params) .then(item => { const id = item[idField] dispatch('addOrUpdate', item) - commit('unsetUpdatePending') + commit('unsetPending', 'update') return state.keyedById[id] }) .catch(error => { - commit('setUpdateError', error) - commit('unsetUpdatePending') + commit('setError', { method: 'update', error }) + commit('unsetPending', 'update') return Promise.reject(error) }) }, @@ -175,7 +175,7 @@ export default function makeServiceActions(service, { debug }) { patch({ commit, dispatch, state }, [id, data, params]) { const { idField, diffOnPatch } = state - commit('setPatchPending') + commit('setPending', 'patch') if (diffOnPatch) { const { observableDiff, applyChange } = diffFunctions() @@ -199,12 +199,12 @@ export default function makeServiceActions(service, { debug }) { const id = item[idField] dispatch('addOrUpdate', item) - commit('unsetPatchPending') + commit('unsetPending', 'patch') return state.keyedById[id] }) .catch(error => { - commit('setPatchError', error) - commit('unsetPatchPending') + commit('setError', { method: 'patch', error }) + commit('unsetPending', 'patch') return Promise.reject(error) }) }, @@ -222,18 +222,18 @@ export default function makeServiceActions(service, { debug }) { params = params || {} - commit('setRemovePending') + commit('setPending', 'remove') return service .remove(id, params) .then(item => { commit('removeItem', id) - commit('unsetRemovePending') + commit('unsetPending', 'remove') return item }) .catch(error => { - commit('setRemoveError', error) - commit('unsetRemovePending') + commit('setError', { method: 'remove', error}) + commit('unsetPending', 'remove') return Promise.reject(error) }) } diff --git a/src/service-module/module.getters.ts b/src/service-module/service-module.getters.ts similarity index 100% rename from src/service-module/module.getters.ts rename to src/service-module/service-module.getters.ts diff --git a/src/service-module/module.mutations.ts b/src/service-module/service-module.mutations.ts similarity index 79% rename from src/service-module/module.mutations.ts rename to src/service-module/service-module.mutations.ts index c140a0dd..71aff85b 100644 --- a/src/service-module/module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -267,78 +267,26 @@ export default function makeServiceMutations(servicePath, { debug }) { }) }, - setFindPending(state) { - state.isFindPending = true + setPending(state, method: string): void { + const uppercaseMethod = method.charAt(0).toUpperCase() + method.slice(1) + state[`is${uppercaseMethod}Pending`] = true }, - unsetFindPending(state) { - state.isFindPending = false - }, - setGetPending(state) { - state.isGetPending = true - }, - unsetGetPending(state) { - state.isGetPending = false - }, - setCreatePending(state) { - state.isCreatePending = true - }, - unsetCreatePending(state) { - state.isCreatePending = false - }, - setUpdatePending(state) { - state.isUpdatePending = true - }, - unsetUpdatePending(state) { - state.isUpdatePending = false - }, - setPatchPending(state) { - state.isPatchPending = true - }, - unsetPatchPending(state) { - state.isPatchPending = false - }, - setRemovePending(state) { - state.isRemovePending = true - }, - unsetRemovePending(state) { - state.isRemovePending = false + unsetPending(state, method: string): void { + const uppercaseMethod = method.charAt(0).toUpperCase() + method.slice(1) + state[`is${uppercaseMethod}Pending`] = false }, - setFindError(state, payload) { - state.errorOnFind = Object.assign({}, serializeError(payload)) - }, - clearFindError(state) { - state.errorOnFind = null - }, - setGetError(state, payload) { - state.errorOnGet = Object.assign({}, serializeError(payload)) - }, - clearGetError(state) { - state.errorOnGet = null - }, - setCreateError(state, payload) { - state.errorOnCreate = Object.assign({}, serializeError(payload)) - }, - clearCreateError(state) { - state.errorOnCreate = null - }, - setUpdateError(state, payload) { - state.errorOnUpdate = Object.assign({}, serializeError(payload)) - }, - clearUpdateError(state) { - state.errorOnUpdate = null - }, - setPatchError(state, payload) { - state.errorOnPatch = Object.assign({}, serializeError(payload)) - }, - clearPatchError(state) { - state.errorOnPatch = null - }, - setRemoveError(state, payload) { - state.errorOnRemove = Object.assign({}, serializeError(payload)) + setError(state, payload: { method: string; error: Error }): void { + const { method, error } = payload + const uppercaseMethod = method.charAt(0).toUpperCase() + method.slice(1) + state[`errorOn${uppercaseMethod}`] = Object.assign( + {}, + serializeError(error) + ) }, - clearRemoveError(state) { - state.errorOnRemove = null + clearError(state, method: string): void { + const uppercaseMethod = method.charAt(0).toUpperCase() + method.slice(1) + state[`errorOn${uppercaseMethod}`] = null } } } diff --git a/src/service-module/module.state.ts b/src/service-module/service-module.state.ts similarity index 91% rename from src/service-module/module.state.ts rename to src/service-module/service-module.state.ts index d4a4a1a6..1fb60e7d 100644 --- a/src/service-module/module.state.ts +++ b/src/service-module/service-module.state.ts @@ -35,6 +35,12 @@ export default function makeDefaultState(servicePath, options) { paramsForServer, whitelist, pagination: {}, + realtimeLocks: { + create: {}, + patch: {}, + update: {}, + remove: {} + }, isFindPending: false, isGetPending: false, diff --git a/test/service-module/actions.test.ts b/test/service-module/actions.test.ts index b193ddf7..d1e82bf2 100644 --- a/test/service-module/actions.test.ts +++ b/test/service-module/actions.test.ts @@ -25,7 +25,6 @@ interface ServiceState { errorOnPatch: any errorOnUpdate: any errorOnRemove: any - currentId: number isFindPending: boolean isGetPending: boolean isCreatePending: boolean @@ -94,7 +93,7 @@ const assertRejected = (promise, done, callback) => { ) } -describe('Service Module - Actions', () => { +describe.only('Service Module - Actions', () => { beforeEach(function() { this.todoService = feathersClient.use( 'todos', @@ -593,7 +592,6 @@ describe('Service Module - Actions', () => { assert(todoState.ids.length === 1, 'only one item is in the store') assert(todoState.errorOnGet === null, 'there was no errorOnGet') assert(todoState.isGetPending === false, 'isGetPending is set to false') - assert(todoState.currentId === 0, 'the currentId was set') let expectedKeyedById: NumberedList = { 0: { id: 0, description: 'Do the first' } diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index 76d2b9a2..d1aa901d 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -13,7 +13,7 @@ import _pick from 'lodash.pick' Vue.use(Vuex) describe('makeServicePlugin', function() { - it.only('registers the vuex module with options', function() { + it('registers the vuex module with options', function() { const serverAlias = 'default' const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { serverAlias diff --git a/test/service-module/mutations.test.js b/test/service-module/mutations.test.js index 060c36d1..b0bdaed7 100644 --- a/test/service-module/mutations.test.js +++ b/test/service-module/mutations.test.js @@ -25,7 +25,7 @@ const options = { globalModels: { Todo: todoModel, byServicePath: { - 'todos': todoModel + todos: todoModel } } } @@ -44,39 +44,19 @@ const { rejectCopy, commitCopy, updatePaginationForQuery, - setFindPending, - unsetFindPending, - setGetPending, - unsetGetPending, - setCreatePending, - unsetCreatePending, - setUpdatePending, - unsetUpdatePending, - setPatchPending, - unsetPatchPending, - setRemovePending, - unsetRemovePending, - setFindError, - clearFindError, - setGetError, - clearGetError, - setCreateError, - clearCreateError, - setUpdateError, - clearUpdateError, - setPatchError, - clearPatchError, - setRemoveError, - clearRemoveError + setPending, + unsetPending, + setError, + clearError } = makeServiceMutations('todos', options) -describe('Service Module - Mutations', function () { - beforeEach(function () { +describe('Service Module - Mutations', function() { + beforeEach(function() { this.state = makeServiceState('todos', options) this.state.keepCopiesInStore = true }) - it('addItem', function () { + it('addItem', function() { const state = this.state const item1 = { _id: 1, @@ -107,7 +87,7 @@ describe('Service Module - Mutations', function () { assert(state.keyedById[2].test) }) - it('addItems', function () { + it('addItems', function() { const state = this.state const item1 = { _id: 1, @@ -126,8 +106,8 @@ describe('Service Module - Mutations', function () { assert(state.keyedById[2].test) }) - describe('updateItem', function () { - it('updates existing item when addOnUpsert=true', function () { + describe('updateItem', function() { + it('updates existing item when addOnUpsert=true', function() { const state = this.state state.addOnUpsert = true const item1 = { @@ -146,7 +126,7 @@ describe('Service Module - Mutations', function () { assert(state.keyedById[1].test === false) }) - it('updates existing item when addOnUpsert=false', function () { + it('updates existing item when addOnUpsert=false', function() { const state = this.state state.addOnUpsert = false const item1 = { @@ -165,7 +145,7 @@ describe('Service Module - Mutations', function () { assert(state.keyedById[1].test === false) }) - it('adds non-existing item when addOnUpsert=true', function () { + it('adds non-existing item when addOnUpsert=true', function() { const state = this.state state.addOnUpsert = true @@ -175,11 +155,14 @@ describe('Service Module - Mutations', function () { } updateItem(state, item1updated) - assert.deepEqual([state.addOnUpsert, state.ids, state.keyedById], [true, [1], { 1: { _id: 1, test: false } }]) + assert.deepEqual( + [state.addOnUpsert, state.ids, state.keyedById], + [true, [1], { 1: { _id: 1, test: false } }] + ) // assert(state.keyedById[1].test === false) }) - it('discards non-existing item when addOnUpsert=false', function () { + it('discards non-existing item when addOnUpsert=false', function() { const state = this.state state.addOnUpsert = false @@ -193,12 +176,12 @@ describe('Service Module - Mutations', function () { }) }) - describe('Vue event bindings', function () { - it('does not break when attempting to overwrite a getter', function (done) { + describe('Vue event bindings', function() { + it('does not break when attempting to overwrite a getter', function(done) { const state = this.state const item1 = { _id: 1, - get getter () { + get getter() { return 'Release the flying monkies!' } } @@ -210,7 +193,7 @@ describe('Service Module - Mutations', function () { item: state.keyedById[1] }, watch: { - 'item.getter' (val) { + 'item.getter'(val) { throw new Error('this should never happen') } } @@ -228,12 +211,12 @@ describe('Service Module - Mutations', function () { done() }) - it('correctly emits events for existing array properties', function (done) { + it('correctly emits events for existing array properties', function(done) { const state = this.state const item1 = { _id: 1, test: true, - users: [ 'Marshall', 'Mariah' ] + users: ['Marshall', 'Mariah'] } const items = [item1] addItems(state, items) @@ -243,7 +226,7 @@ describe('Service Module - Mutations', function () { item: state.keyedById[1] }, watch: { - 'item.users' (val) { + 'item.users'(val) { assert(this.item.users.length === 3) done() } @@ -255,12 +238,12 @@ describe('Service Module - Mutations', function () { const updatedItem = { _id: 1, test: false, - users: [ 'Marshall', 'Mariah', 'Scooby Doo' ] + users: ['Marshall', 'Mariah', 'Scooby Doo'] } updateItem(state, updatedItem) }) - it('correctly emits events for new array properties', function (done) { + it('correctly emits events for new array properties', function(done) { const state = this.state const item1 = { _id: 1, @@ -274,7 +257,7 @@ describe('Service Module - Mutations', function () { item: state.keyedById[1] }, watch: { - 'item.users' (val) { + 'item.users'(val) { assert(this.item.users.length === 3) done() } @@ -286,12 +269,12 @@ describe('Service Module - Mutations', function () { const updatedItem = { _id: 1, test: false, - users: [ 'Marshall', 'Mariah', 'Scooby Doo' ] + users: ['Marshall', 'Mariah', 'Scooby Doo'] } updateItem(state, updatedItem) }) - it('correctly emits events for existing object properties', function (done) { + it('correctly emits events for existing object properties', function(done) { const state = this.state const item1 = { _id: 1, @@ -305,7 +288,7 @@ describe('Service Module - Mutations', function () { item: state.keyedById[1] }, watch: { - 'item.obj' (val) { + 'item.obj'(val) { assert(this.item.obj.test === false) done() } @@ -321,7 +304,7 @@ describe('Service Module - Mutations', function () { updateItem(state, updatedItem) }) - it('correctly emits events for new object properties', function (done) { + it('correctly emits events for new object properties', function(done) { const state = this.state const item1 = { _id: 1 @@ -334,7 +317,7 @@ describe('Service Module - Mutations', function () { item: state.keyedById[1] }, watch: { - 'item.obj' (val) { + 'item.obj'(val) { assert(this.item.obj.test === false) done() } @@ -350,7 +333,7 @@ describe('Service Module - Mutations', function () { updateItem(state, updatedItem) }) - it('correctly emits events for existing boolean properties', function (done) { + it('correctly emits events for existing boolean properties', function(done) { const state = this.state const item1 = { _id: 1, @@ -364,7 +347,7 @@ describe('Service Module - Mutations', function () { item: state.keyedById[1] }, watch: { - 'item.isValid' (val) { + 'item.isValid'(val) { assert(this.item.isValid === false) done() } @@ -380,7 +363,7 @@ describe('Service Module - Mutations', function () { updateItem(state, updatedItem) }) - it('correctly emits events for new boolean properties', function (done) { + it('correctly emits events for new boolean properties', function(done) { const state = this.state const item1 = { _id: 1 @@ -393,7 +376,7 @@ describe('Service Module - Mutations', function () { item: state.keyedById[1] }, watch: { - 'item.isValid' (val) { + 'item.isValid'(val) { assert(this.item.isValid === false) done() } @@ -409,7 +392,7 @@ describe('Service Module - Mutations', function () { updateItem(state, updatedItem) }) - it('correctly emits events for existing string properties', function (done) { + it('correctly emits events for existing string properties', function(done) { const state = this.state const item1 = { _id: 1, @@ -423,7 +406,7 @@ describe('Service Module - Mutations', function () { item: state.keyedById[1] }, watch: { - 'item.name' (val) { + 'item.name'(val) { assert(this.item.name === 'Xavier') done() } @@ -439,7 +422,7 @@ describe('Service Module - Mutations', function () { updateItem(state, updatedItem) }) - it('correctly emits events for new string properties', function (done) { + it('correctly emits events for new string properties', function(done) { const state = this.state const item1 = { _id: 1 @@ -452,7 +435,7 @@ describe('Service Module - Mutations', function () { item: state.keyedById[1] }, watch: { - 'item.name' (val) { + 'item.name'(val) { assert(this.item.name === 'Xavier') done() } @@ -468,7 +451,7 @@ describe('Service Module - Mutations', function () { updateItem(state, updatedItem) }) - it('correctly emits events for existing null properties', function (done) { + it('correctly emits events for existing null properties', function(done) { const state = this.state const item1 = { _id: 1, @@ -482,7 +465,7 @@ describe('Service Module - Mutations', function () { item: state.keyedById[1] }, watch: { - 'item.name' (val) { + 'item.name'(val) { assert(this.item.name === 'Xavier') done() } @@ -498,7 +481,7 @@ describe('Service Module - Mutations', function () { updateItem(state, updatedItem) }) - it('correctly emits events for properties set to null', function (done) { + it('correctly emits events for properties set to null', function(done) { const state = this.state const item1 = { _id: 1, @@ -512,7 +495,7 @@ describe('Service Module - Mutations', function () { item: state.keyedById[1] }, watch: { - 'item.name' (val) { + 'item.name'(val) { assert(this.item.name === null) done() } @@ -528,7 +511,7 @@ describe('Service Module - Mutations', function () { updateItem(state, updatedItem) }) - it('correctly emits events for existing number properties', function (done) { + it('correctly emits events for existing number properties', function(done) { const state = this.state const item1 = { _id: 1, @@ -542,7 +525,7 @@ describe('Service Module - Mutations', function () { item: state.keyedById[1] }, watch: { - 'item.age' (val) { + 'item.age'(val) { assert(this.item.age === 50) done() } @@ -558,7 +541,7 @@ describe('Service Module - Mutations', function () { updateItem(state, updatedItem) }) - it('correctly emits events for new number properties', function (done) { + it('correctly emits events for new number properties', function(done) { const state = this.state const item1 = { _id: 1 @@ -571,7 +554,7 @@ describe('Service Module - Mutations', function () { item: state.keyedById[1] }, watch: { - 'item.age' (val) { + 'item.age'(val) { assert(this.item.age === 50) done() } @@ -588,7 +571,7 @@ describe('Service Module - Mutations', function () { }) }) - it('updateItems', function () { + it('updateItems', function() { const state = this.state const item1 = { _id: 1, @@ -616,7 +599,7 @@ describe('Service Module - Mutations', function () { assert(state.keyedById[2].test === false) }) - it('removeItem', function () { + it('removeItem', function() { const state = this.state addItem(state, { _id: 1, test: true }) @@ -626,7 +609,7 @@ describe('Service Module - Mutations', function () { assert(Object.keys(state.keyedById).length === 0) }) - it('removeItems with array of ids', function () { + it('removeItems with array of ids', function() { const state = this.state const items = [ { _id: 1, test: true }, @@ -639,10 +622,13 @@ describe('Service Module - Mutations', function () { removeItems(state, itemsToRemove) assert(state.ids.length === 2, 'should have 2 ids left') - assert(Object.keys(state.keyedById).length === 2, 'should have 2 items left') + assert( + Object.keys(state.keyedById).length === 2, + 'should have 2 items left' + ) }) - it('removeItems with array of items', function () { + it('removeItems with array of items', function() { const state = this.state const items = [ { _id: 1, test: true }, @@ -651,17 +637,17 @@ describe('Service Module - Mutations', function () { { _id: 4, test: true } ] addItems(state, items) - const itemsToRemove = [ - { _id: 1, test: true }, - { _id: 2, test: true } - ] + const itemsToRemove = [{ _id: 1, test: true }, { _id: 2, test: true }] removeItems(state, itemsToRemove) assert(state.ids.length === 2, 'should have 2 ids left') - assert(Object.keys(state.keyedById).length === 2, 'should have 2 items left') + assert( + Object.keys(state.keyedById).length === 2, + 'should have 2 items left' + ) }) - it('clearAll', function () { + it('clearAll', function() { const state = this.state const item1 = { _id: 1, @@ -679,7 +665,7 @@ describe('Service Module - Mutations', function () { assert(Object.keys(state.keyedById).length === 0) }) - it('clearList', function () { + it('clearList', function() { const state = this.state const item1 = { _id: 1, @@ -701,7 +687,7 @@ describe('Service Module - Mutations', function () { assert(state.keyedById[2].test, 'the item is still in keyedById') }) - it('setCurrent', function () { + it('setCurrent', function() { const state = this.state const item1 = { _id: 1, @@ -724,7 +710,7 @@ describe('Service Module - Mutations', function () { assert.deepEqual(state.copy, item1) }) - it('clearCurrent', function () { + it('clearCurrent', function() { const state = this.state const item1 = { _id: 1, @@ -743,7 +729,7 @@ describe('Service Module - Mutations', function () { assert(state.copy === null) }) - it('copy works', function () { + it('copy works', function() { const state = this.state const item1 = { _id: 1, @@ -756,7 +742,7 @@ describe('Service Module - Mutations', function () { assert(state.copy.test === false, 'the copy was updated successfully.') }) - it('rejectCopy', function () { + it('rejectCopy', function() { const state = this.state const item1 = { _id: 1, @@ -768,13 +754,16 @@ describe('Service Module - Mutations', function () { const copy = state.copy state.copy.test = false - assert(original.test === true, `the original item didn't change when copy was changed`) + assert( + original.test === true, + `the original item didn't change when copy was changed` + ) rejectCopy(state) assert(copy.test === true, 'the copy was reset') }) - it('commitCopy', function () { + it('commitCopy', function() { const state = this.state const item1 = { _id: 1, @@ -789,10 +778,13 @@ describe('Service Module - Mutations', function () { commitCopy(state) assert(copy.test === false, `the copy wasn't changed after commitCopy`) - assert(original.test === false, 'the original item was updated after commitCopy') + assert( + original.test === false, + 'the original item was updated after commitCopy' + ) }) - it('updatePaginationForQuery', function () { + it('updatePaginationForQuery', function() { const state = this.state const qid = 'query-identifier' const query = { limit: 2 } @@ -813,193 +805,80 @@ describe('Service Module - Mutations', function () { assert.deepEqual(pageData.query, query, 'the query was stored') }) - describe('Pending', function () { - it('setFindPending', function () { - const state = this.state - assert(!state.isFindPending) - setFindPending(state) - assert(state.isFindPending) - }) - - it('setFindPending', function () { - const state = this.state - setFindPending(state) - unsetFindPending(state) - assert(!state.isFindPending) - }) - - it('setGetPending', function () { + describe('Pending', function() { + it('setPending', function() { const state = this.state - assert(!state.isGetPending) - setGetPending(state) - assert(state.isGetPending) - }) - - it('setGetPending', function () { - const state = this.state - setGetPending(state) - unsetGetPending(state) - assert(!state.isGetPending) - }) + const methods = ['find', 'get', 'create', 'update', 'patch', 'remove'] - it('setCreatePending', function () { - const state = this.state - assert(!state.isCreatePending) - setCreatePending(state) - assert(state.isCreatePending) - }) - - it('setCreatePending', function () { - const state = this.state - setCreatePending(state) - unsetCreatePending(state) - assert(!state.isCreatePending) - }) - - it('setUpdatePending', function () { - const state = this.state - assert(!state.isUpdatePending) - setUpdatePending(state) - assert(state.isUpdatePending) - }) - - it('setUpdatePending', function () { - const state = this.state - setUpdatePending(state) - unsetUpdatePending(state) - assert(!state.isUpdatePending) - }) - - it('setPatchPending', function () { - const state = this.state - assert(!state.isPatchPending) - setPatchPending(state) - assert(state.isPatchPending) - }) - - it('setPatchPending', function () { - const state = this.state - setPatchPending(state) - unsetPatchPending(state) - assert(!state.isPatchPending) + methods.forEach(method => { + const uppercaseMethod = method.charAt(0).toUpperCase() + method.slice(1) + assert(!state[`is${uppercaseMethod}Pending`]) + setPending(state, method) + assert(state[`is${uppercaseMethod}Pending`]) + }) }) - it('setRemovePending', function () { + it('unsetPending', function() { const state = this.state - assert(!state.isRemovePending) - setRemovePending(state) - assert(state.isRemovePending) - }) + const methods = ['find', 'get', 'create', 'update', 'patch', 'remove'] - it('setRemovePending', function () { - const state = this.state - setRemovePending(state) - unsetRemovePending(state) - assert(!state.isRemovePending) + methods.forEach(method => { + const uppercaseMethod = method.charAt(0).toUpperCase() + method.slice(1) + assert(!state[`is${uppercaseMethod}Pending`]) + unsetPending(state, method) + assert(state[`is${uppercaseMethod}Pending`]) + }) }) }) - describe('Errors', function () { - it('setFindError', function () { - const state = this.state - setFindError(state, new Error('This is a test')) - assert(state.errorOnFind.message) - assert(state.errorOnFind.name) - assert(state.errorOnFind.stack) - }) - - it('setFindError with feathers-errors', function () { - const state = this.state - setFindError(state, new errors.NotAuthenticated('You are not logged in')) - assert(state.errorOnFind.className) - assert(state.errorOnFind.code) - assert(state.errorOnFind.hasOwnProperty('errors')) - assert(state.errorOnFind.hasOwnProperty('data')) - assert(state.errorOnFind.message) - assert(state.errorOnFind.name) - assert(state.errorOnFind.stack) - }) - - it('clearFindError', function () { - const state = this.state - setFindError(state, new Error('This is a test')) - clearFindError(state) - assert(!state.errorOnFind, 'errorOnFind was cleared') - }) - - it('setGetError', function () { - const state = this.state - setGetError(state, new Error('This is a test')) - assert(state.errorOnGet.message) - assert(state.errorOnGet.name) - assert(state.errorOnGet.stack) - }) - - it('clearGetError', function () { - const state = this.state - setGetError(state, new Error('This is a test')) - clearGetError(state) - assert(!state.errorOnGet, 'errorOnGet was cleared') - }) - - it('setCreateError', function () { - const state = this.state - setCreateError(state, new Error('This is a test')) - assert(state.errorOnCreate.message) - assert(state.errorOnCreate.name) - assert(state.errorOnCreate.stack) - }) - - it('clearCreateError', function () { + describe('Errors', function() { + it('setError', function() { const state = this.state - setCreateError(state, new Error('This is a test')) - clearCreateError(state) - assert(!state.errorOnCreate, 'errorOnCreate was cleared') - }) + const methods = ['find', 'get', 'create', 'update', 'patch', 'remove'] - it('setUpdateError', function () { - const state = this.state - setUpdateError(state, new Error('This is a test')) - assert(state.errorOnUpdate.message) - assert(state.errorOnUpdate.name) - assert(state.errorOnUpdate.stack) + methods.forEach(method => { + const uppercaseMethod = method.charAt(0).toUpperCase() + method.slice(1) + setError(state, { method, error: new Error('This is a test') }) + assert(state[`errorOn${uppercaseMethod}`].message) + assert(state[`errorOn${uppercaseMethod}`].name) + assert(state[`errorOn${uppercaseMethod}`].stack) + }) }) - it('clearUpdateError', function () { + it('setError with feathers-errors', function() { const state = this.state - setUpdateError(state, new Error('This is a test')) - clearUpdateError(state) - assert(!state.errorOnUpdate, 'errorOnUpdate was cleared') - }) + const methods = ['find', 'get', 'create', 'update', 'patch', 'remove'] - it('setPatchError', function () { - const state = this.state - setPatchError(state, new Error('This is a test')) - assert(state.errorOnPatch.message) - assert(state.errorOnPatch.name) - assert(state.errorOnPatch.stack) + methods.forEach(method => { + const uppercaseMethod = method.charAt(0).toUpperCase() + method.slice(1) + setError(state, { + method, + error: new errors.NotAuthenticated('You are not logged in') + }) + assert(state[`errorOn${uppercaseMethod}`].className) + assert(state[`errorOn${uppercaseMethod}`].code) + assert(state[`errorOn${uppercaseMethod}`].hasOwnProperty('errors')) + assert(state[`errorOn${uppercaseMethod}`].hasOwnProperty('data')) + assert(state[`errorOn${uppercaseMethod}`].message) + assert(state[`errorOn${uppercaseMethod}`].name) + assert(state[`errorOn${uppercaseMethod}`].stack) + }) }) - it('clearPatchError', function () { + it('clearError', function() { const state = this.state - setPatchError(state, new Error('This is a test')) - clearPatchError(state) - assert(!state.errorOnPatch, 'errorOnPatch was cleared') - }) + const methods = ['find', 'get', 'create', 'update', 'patch', 'remove'] - it('setRemoveError', function () { - const state = this.state - setRemoveError(state, new Error('This is a test')) - assert(state.errorOnRemove.message) - assert(state.errorOnRemove.name) - assert(state.errorOnRemove.stack) - }) + methods.forEach(method => { + const uppercaseMethod = method.charAt(0).toUpperCase() + method.slice(1) - it('clearRemoveError', function () { - const state = this.state - setRemoveError(state, new Error('This is a test')) - clearRemoveError(state) - assert(!state.errorOnRemove, 'errorOnRemove was cleared') + setError(state, { method, error: new Error('This is a test') }) + clearError(state, method) + assert( + state[`errorOn${uppercaseMethod}`] === null, + `errorOn${uppercaseMethod} was cleared` + ) + }) }) }) }) From 0659efa1285bd6d130e4fc0879955fdc14d1b6dc Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 25 Mar 2019 20:01:08 -0600 Subject: [PATCH 033/404] Lint cleanup --- .../service-module.mutations.ts | 6 ++-- test/service-module/mutations.test.js | 30 +++++++++---------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 71aff85b..005cf34e 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -248,8 +248,10 @@ export default function makeServiceMutations(servicePath, { debug }) { // Object.assign(current, copy) }, - // Stores pagination data on state.pagination based on the query identifier (qid) - // The qid must be manually assigned to `params.qid` + /** + * Stores pagination data on state.pagination based on the query identifier + * (qid) The qid must be manually assigned to `params.qid` + */ updatePaginationForQuery(state, { qid, response, query }) { const { data, limit, skip, total } = response const { idField } = state diff --git a/test/service-module/mutations.test.js b/test/service-module/mutations.test.js index b0bdaed7..f7001bf0 100644 --- a/test/service-module/mutations.test.js +++ b/test/service-module/mutations.test.js @@ -182,7 +182,7 @@ describe('Service Module - Mutations', function() { const item1 = { _id: 1, get getter() { - return 'Release the flying monkies!' + return 'Release the flying monkeys!' } } const items = [item1] @@ -193,7 +193,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.getter'(val) { + 'item.getter'() { throw new Error('this should never happen') } } @@ -207,7 +207,7 @@ describe('Service Module - Mutations', function() { } updateItem(state, updatedItem) - assert(state.keyedById[1].getter === 'Release the flying monkies!') + assert(state.keyedById[1].getter === 'Release the flying monkeys!') done() }) @@ -226,7 +226,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.users'(val) { + 'item.users'() { assert(this.item.users.length === 3) done() } @@ -257,7 +257,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.users'(val) { + 'item.users'() { assert(this.item.users.length === 3) done() } @@ -288,7 +288,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.obj'(val) { + 'item.obj'() { assert(this.item.obj.test === false) done() } @@ -317,7 +317,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.obj'(val) { + 'item.obj'() { assert(this.item.obj.test === false) done() } @@ -347,7 +347,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.isValid'(val) { + 'item.isValid'() { assert(this.item.isValid === false) done() } @@ -376,7 +376,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.isValid'(val) { + 'item.isValid'() { assert(this.item.isValid === false) done() } @@ -406,7 +406,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.name'(val) { + 'item.name'() { assert(this.item.name === 'Xavier') done() } @@ -435,7 +435,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.name'(val) { + 'item.name'() { assert(this.item.name === 'Xavier') done() } @@ -465,7 +465,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.name'(val) { + 'item.name'() { assert(this.item.name === 'Xavier') done() } @@ -495,7 +495,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.name'(val) { + 'item.name'() { assert(this.item.name === null) done() } @@ -525,7 +525,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.age'(val) { + 'item.age'() { assert(this.item.age === 50) done() } @@ -554,7 +554,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.age'(val) { + 'item.age'() { assert(this.item.age === 50) done() } From 399eb67b5549e0f01f2590168d084ce50b234040 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 25 Mar 2019 20:10:37 -0600 Subject: [PATCH 034/404] Lint cleanup --- src/auth-module/auth-module.ts | 8 +- src/service-module/make-service-module.ts | 8 +- src/service-module/service-module.actions.ts | 2 +- test/auth-module/actions.test.js | 77 ++++++++++---------- test/service-module/module.getters.test.ts | 6 +- 5 files changed, 50 insertions(+), 51 deletions(-) diff --git a/src/auth-module/auth-module.ts b/src/auth-module/auth-module.ts index d55c9956..9e77acfb 100644 --- a/src/auth-module/auth-module.ts +++ b/src/auth-module/auth-module.ts @@ -3,10 +3,10 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import setupState from './state' -import setupGetters from './getters' -import setupMutations from './mutations' -import setupActions from './actions' +import setupState from './auth-module.state' +import setupGetters from './auth-module.getters' +import setupMutations from './auth-module.mutations' +import setupActions from './auth-module.actions' const defaults = { namespace: 'auth', diff --git a/src/service-module/make-service-module.ts b/src/service-module/make-service-module.ts index 418ef429..ca284da4 100644 --- a/src/service-module/make-service-module.ts +++ b/src/service-module/make-service-module.ts @@ -6,10 +6,10 @@ eslint import _omit from 'lodash.omit' import _pick from 'lodash.pick' -import makeDefaultState from './module.state' -import makeGetters from './module.getters' -import makeMutations from './module.mutations' -import makeActions from './module.actions' +import makeDefaultState from './service-module.state' +import makeGetters from './service-module.getters' +import makeMutations from './service-module.mutations' +import makeActions from './service-module.actions' export default function makeServiceModule(service, options) { const nonStateProps = [ diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 8514ca07..f1a11904 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -232,7 +232,7 @@ export default function makeServiceActions(service, { debug }) { return item }) .catch(error => { - commit('setError', { method: 'remove', error}) + commit('setError', { method: 'remove', error }) commit('unsetPending', 'remove') return Promise.reject(error) }) diff --git a/test/auth-module/actions.test.js b/test/auth-module/actions.test.js index b645f7d7..0b34e24b 100644 --- a/test/auth-module/actions.test.js +++ b/test/auth-module/actions.test.js @@ -11,15 +11,16 @@ const globalModels = {} const auth = setupVuexAuth(feathersClient, options, globalModels) const service = setupVuexService(feathersClient, options, globalModels) -const accessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjAsImV4cCI6OTk5OTk5OTk5OTk5OX0.zmvEm8w142xGI7CbUsnvVGZk_hrVE1KEjzDt80LSW50' +const accessToken = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjAsImV4cCI6OTk5OTk5OTk5OTk5OX0.zmvEm8w142xGI7CbUsnvVGZk_hrVE1KEjzDt80LSW50' describe('Auth Module - Actions', () => { - it('Authenticate', (done) => { + it('Authenticate', done => { const store = new Vuex.Store({ plugins: [auth()] }) feathersClient.use('authentication', { - create (data) { + create(data) { return Promise.resolve({ accessToken }) } }) @@ -35,20 +36,19 @@ describe('Auth Module - Actions', () => { assert(authState.payload === null) const request = { strategy: 'local', email: 'test', password: 'test' } - actions.authenticate.call({ $store: store }, request) - .then(response => { - assert(authState.accessToken === response.accessToken) - assert(authState.errorOnAuthenticate === null) - assert(authState.errorOnLogout === null) - assert(authState.isAuthenticatePending === false) - assert(authState.isLogoutPending === false) - let expectedPayload = { - userId: 0, - exp: 9999999999999 - } - assert.deepEqual(authState.payload, expectedPayload) - done() - }) + actions.authenticate.call({ $store: store }, request).then(response => { + assert(authState.accessToken === response.accessToken) + assert(authState.errorOnAuthenticate === null) + assert(authState.errorOnLogout === null) + assert(authState.isAuthenticatePending === false) + assert(authState.isLogoutPending === false) + let expectedPayload = { + userId: 0, + exp: 9999999999999 + } + assert.deepEqual(authState.payload, expectedPayload) + done() + }) // Make sure proper state changes occurred before response assert(authState.accessToken === null) @@ -59,12 +59,12 @@ describe('Auth Module - Actions', () => { assert(authState.payload === null) }) - it('Logout', (done) => { + it('Logout', done => { const store = new Vuex.Store({ plugins: [auth()] }) feathersClient.use('authentication', { - create (data) { + create(data) { return Promise.resolve({ accessToken }) } }) @@ -73,33 +73,31 @@ describe('Auth Module - Actions', () => { const actions = mapActions('auth', ['authenticate', 'logout']) const request = { strategy: 'local', email: 'test', password: 'test' } - actions.authenticate.call({ $store: store }, request) - .then(authResponse => { - actions.logout.call({ $store: store }) - .then(response => { - assert(authState.accessToken === null) - assert(authState.errorOnAuthenticate === null) - assert(authState.errorOnLogout === null) - assert(authState.isAuthenticatePending === false) - assert(authState.isLogoutPending === false) - assert(authState.payload === null) - done() - }) + actions.authenticate.call({ $store: store }, request).then(authResponse => { + actions.logout.call({ $store: store }).then(response => { + assert(authState.accessToken === null) + assert(authState.errorOnAuthenticate === null) + assert(authState.errorOnLogout === null) + assert(authState.isAuthenticatePending === false) + assert(authState.isLogoutPending === false) + assert(authState.payload === null) + done() }) + }) }) - it('Authenticate with userService config option', (done) => { + it('Authenticate with userService config option', done => { feathersClient.use('authentication', { - create (data) { + create(data) { return Promise.resolve({ accessToken }) } }) - feathersClient.use('users', memory({ store: { 0: { id: 0, email: 'test@test.com' } } })) + feathersClient.use( + 'users', + memory({ store: { 0: { id: 0, email: 'test@test.com' } } }) + ) const store = new Vuex.Store({ - plugins: [ - auth({ userService: 'users' }), - service('users') - ] + plugins: [auth({ userService: 'users' }), service('users')] }) const authState = store.state.auth @@ -108,7 +106,8 @@ describe('Auth Module - Actions', () => { assert(authState.user === null) const request = { strategy: 'local', email: 'test', password: 'test' } - actions.authenticate.call({ $store: store }, request) + actions.authenticate + .call({ $store: store }, request) .then(response => { let expectedUser = { id: 0, diff --git a/test/service-module/module.getters.test.ts b/test/service-module/module.getters.test.ts index 452e534d..a2d7024a 100644 --- a/test/service-module/module.getters.test.ts +++ b/test/service-module/module.getters.test.ts @@ -4,9 +4,9 @@ eslint @typescript-eslint/no-explicit-any: 0 */ import { assert } from 'chai' -import makeServiceGetters from '../../src/service-module/module.getters' -import makeServiceMutations from '../../src/service-module/module.mutations' -import makeServiceState from '../../src/service-module/module.state' +import makeServiceGetters from '../../src/service-module/service-module.getters' +import makeServiceMutations from '../../src/service-module/service-module.mutations' +import makeServiceState from '../../src/service-module/service-module.state' const options = { idField: '_id', From 79ddfa3ad70908278c753e481c1cb7ca594ac0fe Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 25 Mar 2019 20:10:47 -0600 Subject: [PATCH 035/404] Add realtimeLocksById to state --- src/service-module/service-module.state.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/service-module/service-module.state.ts b/src/service-module/service-module.state.ts index 1fb60e7d..74d98fa9 100644 --- a/src/service-module/service-module.state.ts +++ b/src/service-module/service-module.state.ts @@ -35,12 +35,6 @@ export default function makeDefaultState(servicePath, options) { paramsForServer, whitelist, pagination: {}, - realtimeLocks: { - create: {}, - patch: {}, - update: {}, - remove: {} - }, isFindPending: false, isGetPending: false, @@ -57,5 +51,16 @@ export default function makeDefaultState(servicePath, options) { errorOnRemove: null } + if (enableEvents) { + Object.assign(state, { + realtimeLocksById: { + create: {}, + patch: {}, + update: {}, + remove: {} + } + }) + } + return state } From 9ddeb87d32703d756fef6a2a88f5cbf2bb2556ea Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 25 Mar 2019 23:05:35 -0600 Subject: [PATCH 036/404] Remove event locks --- src/service-module/service-module.state.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/service-module/service-module.state.ts b/src/service-module/service-module.state.ts index 74d98fa9..d4a4a1a6 100644 --- a/src/service-module/service-module.state.ts +++ b/src/service-module/service-module.state.ts @@ -51,16 +51,5 @@ export default function makeDefaultState(servicePath, options) { errorOnRemove: null } - if (enableEvents) { - Object.assign(state, { - realtimeLocksById: { - create: {}, - patch: {}, - update: {}, - remove: {} - } - }) - } - return state } From d0cbc9e433616268ba3066fa221819cc78284d4c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 13:18:29 -0600 Subject: [PATCH 037/404] Get mutation tests passing, document API changes --- docs/model-classes.md | 2 +- docs/service-module.md | 8 +- src/service-module/make-model.ts | 8 +- src/service-module/make-service-module.ts | 2 +- src/service-module/model.old.js | 107 ++-- src/service-module/notes.md | 8 + .../service-module.mutations.ts | 118 ++-- src/utils.ts | 48 +- test/service-module/module.getters.test.ts | 10 +- ...test.ts => service-module.actions.test.ts} | 2 +- ...st.js => service-module.mutations.test.ts} | 569 ++++++++---------- test/service-module/service-module.test.js | 15 - test/test-utils.ts | 14 + tsconfig.json | 4 +- 14 files changed, 448 insertions(+), 467 deletions(-) rename test/service-module/{actions.test.ts => service-module.actions.test.ts} (99%) rename test/service-module/{mutations.test.js => service-module.mutations.test.ts} (62%) create mode 100644 test/test-utils.ts diff --git a/docs/model-classes.md b/docs/model-classes.md index cd462b32..d8fe87cb 100644 --- a/docs/model-classes.md +++ b/docs/model-classes.md @@ -96,7 +96,7 @@ Now that we have Model instances, let's take a look at the functionality they pr *Remember, if a record already has an attribute with any of these method names, it will be overwritten with the method.* -These methods give access to many of the store `actions` and `mutations`. Using Model instances, you no longer have to use `mapActions` for `create`, `patch`, `update`, or `remove`. You also no longer have to use `mapMutations` for `createCopy`, `commitCopy`, or `rejectCopy`. +These methods give access to many of the store `actions` and `mutations`. Using Model instances, you no longer have to use `mapActions` for `create`, `patch`, `update`, or `remove`. You also no longer have to use `mapMutations` for `createCopy`, `commitCopy`, or `resetCopy`. ```js store.dispatch('todos/find', { query: {} }) diff --git a/docs/service-module.md b/docs/service-module.md index c02857d5..8d042b27 100644 --- a/docs/service-module.md +++ b/docs/service-module.md @@ -89,7 +89,7 @@ The following attributes are available in each service module's state: - `ids {Array}` - an array of plain ids representing the ids that belong to each object in the `keyedById` map. - `keyedById {Object}` - a hash map keyed by the id of each item. - `currentId {Number|String}` - the id of the item marked as current. -- `copy {Object}` - a deep copy of the current item at the moment it was marked as current. You can make changes to the copy without modifying the `current`. You can then use the `commitCopy` mutation to save the changes as the `current` or `rejectCopy` to revert `copy` to once again match `current`. You may prefer to use the new [clone API](./common-patterns.md#Multiple-Copies) for [managing multiple copies with model instances](./common-patterns.md#Multiple-Copies). +- `copy {Object}` - a deep copy of the current item at the moment it was marked as current. You can make changes to the copy without modifying the `current`. You can then use the `commitCopy` mutation to save the changes as the `current` or `resetCopy` to revert `copy` to once again match `current`. You may prefer to use the new [clone API](./common-patterns.md#Multiple-Copies) for [managing multiple copies with model instances](./common-patterns.md#Multiple-Copies). - `servicePath {String}` - the full service path, even if you alias the namespace to something else. - `modelName {String}` - the key in the $FeathersVuex plugin where the model will be found. - `autoRemove {Boolean` - indicates that this service will not automatically remove results missing from subsequent requests. Only use with feathers-rest. Default is false. @@ -173,16 +173,20 @@ Removes the passed in items or ids from the store. Saves changes from the `copy` to the `current` item. -### `rejectCopy(state)` +### `resetCopy(state)` Re-copies the data from `current` to `copy`, restoring the original copy. ### `clearCurrent(state)` +> Removed in 2.0 + Clears the `current` item, which also clears the copy. ### `clearList(state)` +> Removed in 2.0 + Clears the `list`, excepting the `current` item. ### `clearAll(state)` diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 99d58bc1..62c76116 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -6,6 +6,7 @@ eslint import { FeathersVuexOptions } from './types' import { globalModels } from './global-models' import Vue from 'vue' +import { mergeWithAccessors } from '../utils' /** * @@ -29,10 +30,7 @@ export default function makeModel(options: FeathersVuexOptions) { public data: Record public constructor(data) { - Object.assign(this, data) - Object.keys(this).forEach(key => { - this[key] = Vue.observable(this[key]) - }) + mergeWithAccessors(this, data) } public static getId(record: Record): string { @@ -102,7 +100,7 @@ export default function makeModel(options: FeathersVuexOptions) { if (this.isClone) { const id = this[FeathersVuexModel.idField] FeathersVuexModel.store.commit( - `${FeathersVuexModel.namespace}/rejectCopy`, + `${FeathersVuexModel.namespace}/resetCopy`, id ) } else { diff --git a/src/service-module/make-service-module.ts b/src/service-module/make-service-module.ts index ca284da4..46010bf7 100644 --- a/src/service-module/make-service-module.ts +++ b/src/service-module/make-service-module.ts @@ -25,7 +25,7 @@ export default function makeServiceModule(service, options) { const defaultState = makeDefaultState(stateOptions.servicePath, stateOptions) const defaultGetters = makeGetters() - const defaultMutations = makeMutations(stateOptions.servicePath, options) + const defaultMutations = makeMutations() const defaultActions = makeActions(service, options) Object.assign(stateOptions, { diff --git a/src/service-module/model.old.js b/src/service-module/model.old.js index df6a314e..4cca170b 100644 --- a/src/service-module/model.old.js +++ b/src/service-module/model.old.js @@ -1,7 +1,4 @@ -import fastCopy from 'fast-copy' -import isPlainObject from 'lodash.isplainobject' -import merge from 'lodash.merge' -import { updateOriginal } from '../utils' +import { updateOriginal, cloneWithAccessors } from '../utils' const defaults = { idField: 'id', @@ -9,15 +6,16 @@ const defaults = { instanceDefaults: {} } -export default function (options) { +export default function(options) { options = Object.assign({}, defaults, options) const { idField, preferUpdate, globalModels, modelName } = options const instanceDefaults = options.instanceDefaults || {} class FeathersVuexModel { - constructor (data = {}, options = {}) { + constructor(data = {}, options = {}) { const { store, namespace } = this.constructor - const existingItem = data[idField] && FeathersVuexModel.getFromStore(data[idField]) + const existingItem = + data[idField] && FeathersVuexModel.getFromStore(data[idField]) const _relationships = {} let fnDefaults @@ -36,9 +34,15 @@ export default function (options) { // Don't modify the original instanceDefaults. Clone it with accessors intact if (typeof instanceDefaults === 'function') { - fnDefaults = instanceDefaults(data, { store, Model: this.constructor, Models: globalModels }) + fnDefaults = instanceDefaults(data, { + store, + Model: this.constructor, + Models: globalModels + }) } - const _instanceDefaults = cloneWithAccessors(fnDefaults || instanceDefaults) + const _instanceDefaults = cloneWithAccessors( + fnDefaults || instanceDefaults + ) Object.keys(_instanceDefaults).forEach(key => { // Prevent getters and setters from firing before the instance is constructed @@ -78,19 +82,29 @@ export default function (options) { if (Model === Date) { related[index] = new Date(item) } else { - const { model, storedModel } = createRelatedInstance({ item, Model, idField, store }) + const { model, storedModel } = createRelatedInstance({ + item, + Model, + idField, + store + }) // Replace the original array index with a reference to the model related[index] = storedModel || model } }) - // Handle objects + // Handle objects } else { if (Model === Date) { data[prop] = new Date(data[prop]) } else { - const { model, storedModel } = createRelatedInstance({ item: related, Model, idField, store }) + const { model, storedModel } = createRelatedInstance({ + item: related, + Model, + idField, + store + }) // Replace the data's prop value with a reference to the model data[prop] = storedModel || model @@ -111,7 +125,8 @@ export default function (options) { dataProps.forEach(key => { const desc = Object.getOwnPropertyDescriptor(data, key) const propertyExists = this.hasOwnProperty(key) - const isComputed = desc.get || desc.set || typeof desc.value === 'function' + const isComputed = + desc.get || desc.set || typeof desc.value === 'function' if (propertyExists && isComputed) { return } @@ -124,7 +139,7 @@ export default function (options) { } } - clone () { + clone() { if (this.isClone) { throw new Error('You cannot clone a copy') } @@ -132,9 +147,8 @@ export default function (options) { return this._clone(id) } - _clone (id) {} - reset () { + reset() { if (this.isClone) { const id = this[idField] this._reset(id) @@ -142,9 +156,8 @@ export default function (options) { throw new Error('You cannot reset a non-copy') } } - _reset () {} - commit () { + commit() { if (this.isClone) { const id = this[idField] return this._commit(id) @@ -152,51 +165,50 @@ export default function (options) { throw new Error('You cannnot call commit on a non-copy') } } - _commit (id) {} - save (params) { + save(params) { if (this[idField]) { - return preferUpdate - ? this.update(params) - : this.patch(params) + return preferUpdate ? this.update(params) : this.patch(params) } else { return this.create(params) } } - create (params) { + create(params) { const data = Object.assign({}, this) if (data[idField] === null) { delete data[idField] } return this._create(data, params) } - _create (data, params) {} - patch (params) { + patch(params) { if (!this[idField]) { - const error = new Error(`Missing ${idField} property. You must create the data before you can patch with this data`, this) + const error = new Error( + `Missing ${idField} property. You must create the data before you can patch with this data`, + this + ) return Promise.reject(error) } return this._patch(this[idField], this, params) } - _patch () {} - update (params) { + update(params) { if (!this[idField]) { - const error = new Error(`Missing ${idField} property. You must create the data before you can update with this data`, this) + const error = new Error( + `Missing ${idField} property. You must create the data before you can update with this data`, + this + ) return Promise.reject(error) } return this._update(this[idField], this, params) } - _update () {} - remove (params) { + remove(params) { return this._remove(this[idField], params) } - _remove () {} - toJSON () { + toJSON() { return merge({}, this) } } @@ -209,30 +221,3 @@ export default function (options) { return FeathersVuexModel } - -function createRelatedInstance ({ item, Model, idField, store }) { - // Create store instances (if data contains an idField) - const model = new Model(item) - const id = model[idField] - const storedModel = store.state[model.constructor.namespace].keyedById[id] - - return { model, storedModel } -} - -function cloneWithAccessors (obj) { - const clone = {} - - const props = Object.getOwnPropertyNames(obj) - props.forEach(key => { - const desc = Object.getOwnPropertyDescriptor(obj, key) - - // Do not allow sharing of deeply-nested objects between instances - if (isPlainObject(desc.value)) { - desc.value = fastCopy(desc.value) - } - - Object.defineProperty(clone, key, desc) - }) - - return clone -} diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 178275af..cfc5fcf8 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -113,6 +113,14 @@ const state = { } ``` +## The "currentItem" workflow is no longer supported + +The `setCurrent` mutation and `currentId` state encouraged use of a very limiting API. It's much more common for apps to require more than one current record. The `createCopy`, `resetCopy` (formerly called `rejectCopy`), `commitCopy`, and `clearCopy` mutations (since v1.x) provide a more flexible solution for implementing the same functionality. As a result of this, following have been removed from the modules: + +- state: `currentID` +- getters: `current` +- mutations: `setCurrent`, `clearList`, `copy` + ## The `diffOnPatch` option is turned on by default In Feathers-Vuex 2.0, the `diffOnPatch` option is enabled, by default. This means that only the necessary data is sent to the API server. Set `diffOnPatch: false` in the options to revert back to the old way. diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 005cf34e..f4895d4f 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -4,17 +4,16 @@ eslint @typescript-eslint/no-explicit-any: 0 */ import Vue from 'vue' -import _merge from 'lodash.merge' import serializeError from 'serialize-error' import isObject from 'lodash.isobject' -import { checkId, updateOriginal } from '../utils' +import { checkId, updateOriginal, mergeWithAccessors } from '../utils' import { globalModels } from './global-models' -import { get } from 'lodash' +import { get as _get } from 'lodash' -export default function makeServiceMutations(servicePath, { debug }) { +export default function makeServiceMutations() { function addItems(state, items) { - const { idField } = state - const Model = get( + const { idField, debug, servicePath } = state + const Model = _get( globalModels, `[${state.serverAlias}].byServicePath[${servicePath}]` ) @@ -43,8 +42,8 @@ export default function makeServiceMutations(servicePath, { debug }) { } function updateItems(state, items) { - const { idField, replaceItems, addOnUpsert } = state - const Model = get( + const { idField, replaceItems, addOnUpsert, debug, servicePath } = state + const Model = _get( globalModels, `[${state.serverAlias}].byServicePath[${servicePath}]` ) @@ -97,25 +96,19 @@ export default function makeServiceMutations(servicePath, { debug }) { }, removeItem(state, item) { - const { idField } = state + const { idField, debug } = state const idToBeRemoved = isObject(item) ? item[idField] : item - const { currentId } = state const isIdOk = checkId(idToBeRemoved, item, debug) const index = state.ids.findIndex(i => i === idToBeRemoved) if (isIdOk && index !== null && index !== undefined) { Vue.delete(state.ids, index) Vue.delete(state.keyedById, idToBeRemoved) - - if (currentId === idToBeRemoved) { - state.currentId = null - state.copy = null - } } }, removeItems(state, items) { - const { idField, currentId } = state + const { idField } = state if (!Array.isArray(items)) { throw new Error( @@ -157,35 +150,13 @@ export default function makeServiceMutations(servicePath, { debug }) { indexesInReverseOrder.forEach(indexInIdsArray => { Vue.delete(state.ids, indexInIdsArray) }) - - if (currentId && mapOfIdsToRemove[currentId]) { - state.currentId = null - state.copy = null - } }, clearAll(state) { state.ids = [] - state.currentId = null - state.copy = null state.keyedById = {} }, - clearList(state) { - let currentId = state.currentId - let current = state.keyedById[currentId] - - if (currentId && current) { - state.keyedById = { - [currentId]: current - } - state.ids = [currentId] - } else { - state.keyedById = {} - state.ids = [] - } - }, - // Removes the copy from copiesById clearCopy(state, id) { const newCopiesById = Object.assign({}, state.copiesById) @@ -195,56 +166,57 @@ export default function makeServiceMutations(servicePath, { debug }) { // Creates a copy of the record with the passed-in id, stores it in copiesById createCopy(state, id) { + const { servicePath, keepCopiesInStore } = state const current = state.keyedById[id] - const Model = - globalModels[state.options.serverAlias].byServicePath[servicePath] - const copyData = _merge({}, current) - const copy = new Model(copyData, { isClone: true }) - - if (state.keepCopiesInStore) { - state.copiesById[id] = copy + const Model = _get( + globalModels, + `[${state.serverAlias}].byServicePath[${servicePath}]` + ) + const copyData = mergeWithAccessors({}, current) + if (Model) { + var model = new Model(copyData, { isClone: true }) + } + if (keepCopiesInStore) { + state.copiesById[id] = model || copyData } else { - Model.copiesById[id] = copy + Model.copiesById[id] = model || copyData } }, // Resets the copy to match the original record, locally - rejectCopy(state, id) { - const isIdOk = checkId(id, undefined, debug) - const current = isIdOk - ? state.keyedById[id] - : state.keyedById[state.currentId] - const Model = - globalModels[state.options.serverAlias].byServicePath[servicePath] - let copy + resetCopy(state, id) { + const { debug, servicePath, keepCopiesInStore } = state + checkId(id, undefined, debug) + const Model = _get( + globalModels, + `[${state.serverAlias}].byServicePath[${servicePath}]` + ) + const copy = keepCopiesInStore + ? state.copiesById[id] + : Model && _get(Model, `copiesById[${id}]`) - if (state.keepCopiesInStore || !Model) { - copy = isIdOk ? state.copiesById[id] : state.copy - } else { - copy = Model.copiesById[id] + if (copy) { + mergeWithAccessors(copy, state.keyedById[id]) } - - _merge(copy, current) }, // Deep assigns copy to original record, locally commitCopy(state, id) { - const isIdOk = checkId(id, undefined, debug) - const current = isIdOk - ? state.keyedById[id] - : state.keyedById[state.currentId] - const Model = - globalModels[state.options.serverAlias].byServicePath[servicePath] - let copy + const { debug, servicePath, keepCopiesInStore } = state + checkId(id, undefined, debug) + const Model = _get( + globalModels, + `[${state.serverAlias}].byServicePath[${servicePath}]` + ) + const copy = keepCopiesInStore + ? state.copiesById[id] + : Model && _get(Model, `copiesById[${id}]`) - if (state.keepCopiesInStore || !Model) { - copy = isIdOk ? state.copiesById[id] : state.copy - } else { - copy = Model.copiesById[id] + if (copy) { + mergeWithAccessors(state.keyedById[id], copy) } - updateOriginal(copy, current) - + // updateOriginal(copy, current) // Object.assign(current, copy) }, diff --git a/src/utils.ts b/src/utils.ts index b6067729..53a29020 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -8,7 +8,8 @@ import decode from 'jwt-decode' import inflection from 'inflection' import { diff } from 'deep-diff' import Vue from 'vue' -import isObject from 'lodash.isobject' +import fastCopy from 'fast-copy' +import { isPlainObject as _isPlainObject, isObject as _isObject } from 'lodash' export function stripSlashes(location) { return Array.isArray(location) @@ -237,7 +238,7 @@ export function updateOriginal(newData, existingItem) { // If both old and new are arrays } else if (Array.isArray(oldProp) && Array.isArray(newProp)) { shouldCopyProp = true - } else if (isObject(oldProp)) { + } else if (_isObject(oldProp)) { shouldCopyProp = true } else if ( oldProp !== newProp && @@ -285,3 +286,46 @@ export function randomString(length) { return text } + +export function createRelatedInstance({ item, Model, idField, store }) { + // Create store instances (if data contains an idField) + const model = new Model(item) + const id = model[idField] + const storedModel = store.state[model.constructor.namespace].keyedById[id] + + return { model, storedModel } +} + +export function mergeWithAccessors(dest, source) { + const props = Object.getOwnPropertyNames(source) + props.forEach(key => { + const desc = Object.getOwnPropertyDescriptor(source, key) + + // Do not allow sharing of deeply-nested objects between instances + // This may break accessors on nested data. + if (_isPlainObject(desc.value)) { + desc.value = fastCopy(desc.value) + } + + Object.defineProperty(dest, key, desc) + }) + return dest +} + +export function cloneWithAccessors(obj) { + const clone = {} + + const props = Object.getOwnPropertyNames(obj) + props.forEach(key => { + const desc = Object.getOwnPropertyDescriptor(obj, key) + + // Do not allow sharing of deeply-nested objects between instances + if (_isPlainObject(desc.value)) { + desc.value = fastCopy(desc.value) + } + + Object.defineProperty(clone, key, desc) + }) + + return clone +} diff --git a/test/service-module/module.getters.test.ts b/test/service-module/module.getters.test.ts index a2d7024a..1ac8e622 100644 --- a/test/service-module/module.getters.test.ts +++ b/test/service-module/module.getters.test.ts @@ -15,11 +15,11 @@ const options = { } const { find, list } = makeServiceGetters() -const { addItems } = makeServiceMutations('todos', { debug: false }) +const { addItems } = makeServiceMutations() describe('Service Module - Getters', function() { beforeEach(function() { - const state = makeServiceState('todos', options) + const state = makeServiceState('getter-todos', options) this.items = [ { _id: 1, otherField: true, test: true }, { @@ -44,7 +44,11 @@ describe('Service Module - Getters', function() { const { state, items } = this const results = list(state) - assert.deepEqual(results, items, 'the list was correct') + results.forEach((record, index) => { + const item = items[index] + + assert.deepEqual(record, item, 'item in correct order') + }) }) it('find', function() { diff --git a/test/service-module/actions.test.ts b/test/service-module/service-module.actions.test.ts similarity index 99% rename from test/service-module/actions.test.ts rename to test/service-module/service-module.actions.test.ts index d1e82bf2..7ae8b410 100644 --- a/test/service-module/actions.test.ts +++ b/test/service-module/service-module.actions.test.ts @@ -93,7 +93,7 @@ const assertRejected = (promise, done, callback) => { ) } -describe.only('Service Module - Actions', () => { +describe('Service Module - Actions', () => { beforeEach(function() { this.todoService = feathersClient.use( 'todos', diff --git a/test/service-module/mutations.test.js b/test/service-module/service-module.mutations.test.ts similarity index 62% rename from test/service-module/mutations.test.js rename to test/service-module/service-module.mutations.test.ts index f7001bf0..ea318c88 100644 --- a/test/service-module/mutations.test.js +++ b/test/service-module/service-module.mutations.test.ts @@ -1,7 +1,13 @@ -import assert from 'chai/chai' -import makeServiceMutations from '~/src/service-module/mutations' -import makeServiceState from '~/src/service-module/state' -import makeServiceModuleMaker from '~/src/service-module/service-module' +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { assert } from 'chai' +import { assertGetter } from '../test-utils' +import makeServiceMutations from '../../src/service-module/service-module.mutations' +import makeServiceState from '../../src/service-module/service-module.state' +import feathersVuex from '../../src/index' import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' import errors from '@feathersjs/errors' import Vue from 'vue' @@ -9,25 +15,17 @@ import Vuex from 'vuex' Vue.use(Vuex) -const makeServiceModule = makeServiceModuleMaker(feathersClient) -const { serviceModel } = makeServiceModule -const todoModel = serviceModel({}) -// const store = new Vuex.Store({ -// plugins: [ -// todoModule -// ] -// }) -// store.test = true +const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'myApi' +}) +class Todo extends BaseModel { + public static test: boolean = true +} const options = { idField: '_id', autoRemove: false, - globalModels: { - Todo: todoModel, - byServicePath: { - todos: todoModel - } - } + serverAlias: 'myApi' } const { @@ -38,72 +36,166 @@ const { removeItem, removeItems, clearAll, - clearList, - setCurrent, - clearCurrent, - rejectCopy, + createCopy, + resetCopy, commitCopy, updatePaginationForQuery, setPending, unsetPending, setError, clearError -} = makeServiceMutations('todos', options) +} = makeServiceMutations() describe('Service Module - Mutations', function() { beforeEach(function() { - this.state = makeServiceState('todos', options) + this.state = makeServiceState('mutation-todos', options) this.state.keepCopiesInStore = true }) - it('addItem', function() { - const state = this.state - const item1 = { - _id: 1, - test: true - } - const item2 = { - _id: 2, - test: true - } - - addItem(state, item1) - assert(state.ids.length === 1) - assert(state.ids[0] === 1) - assert(state.keyedById[1].test) - - // Add item 2 - addItem(state, item2) - assert(state.ids.length === 2) - assert(state.ids[1] === 2) - assert(state.keyedById[2].test) - - // Re-add item 1 - addItem(state, item1) - assert(state.ids.length === 2, 'still only two items in the ids array') - assert(state.ids[0] === 1) - assert(state.keyedById[1].test) - assert(state.ids[1] === 2) - assert(state.keyedById[2].test) - }) + describe('Create, Update, Remove', function() { + it('addItem', function() { + const state = this.state + const item1 = { + _id: 1, + test: true + } + const item2 = { + _id: 2, + test: true + } + + addItem(state, item1) + assert(state.ids.length === 1) + assert(state.ids[0] === 1) + assert(state.keyedById[1].test) + + // Add item 2 + addItem(state, item2) + assert(state.ids.length === 2) + assert(state.ids[1] === 2) + assert(state.keyedById[2].test) + + // Re-add item 1 + addItem(state, item1) + assert(state.ids.length === 2, 'still only two items in the ids array') + assert(state.ids[0] === 1) + assert(state.keyedById[1].test) + assert(state.ids[1] === 2) + assert(state.keyedById[2].test) + }) + + it('addItems', function() { + const state = this.state + const item1 = { + _id: 1, + test: true + } + const item2 = { + _id: 2, + test: true + } + const items = [item1, item2] + addItems(state, items) + assert(state.ids.length === 2, 'still only two items in the ids array') + assert(state.ids[0] === 1) + assert(state.keyedById[1].test) + assert(state.ids[1] === 2) + assert(state.keyedById[2].test) + }) + + it('updateItems', function() { + const state = this.state + const item1 = { + _id: 1, + test: true + } + const item2 = { + _id: 2, + test: true + } + const items = [item1, item2] + addItems(state, items) + + const item1updated = { + _id: 1, + test: false + } + const item2updated = { + _id: 2, + test: false + } + const itemsToUpdate = [item1updated, item2updated] + updateItems(state, itemsToUpdate) + + assert(state.keyedById[1].test === false) + assert(state.keyedById[2].test === false) + }) + + it('removeItem', function() { + const state = this.state + + addItem(state, { _id: 1, test: true }) + removeItem(state, 1) + + assert(state.ids.length === 0) + assert(Object.keys(state.keyedById).length === 0) + }) + + it('removeItems with array of ids', function() { + const state = this.state + const items = [ + { _id: 1, test: true }, + { _id: 2, test: true }, + { _id: 3, test: true }, + { _id: 4, test: true } + ] + addItems(state, items) + const itemsToRemove = [1, 2] + removeItems(state, itemsToRemove) - it('addItems', function() { - const state = this.state - const item1 = { - _id: 1, - test: true - } - const item2 = { - _id: 2, - test: true - } - const items = [item1, item2] - addItems(state, items) - assert(state.ids.length === 2, 'still only two items in the ids array') - assert(state.ids[0] === 1) - assert(state.keyedById[1].test) - assert(state.ids[1] === 2) - assert(state.keyedById[2].test) + assert(state.ids.length === 2, 'should have 2 ids left') + assert( + Object.keys(state.keyedById).length === 2, + 'should have 2 items left' + ) + }) + + it('removeItems with array of items', function() { + const state = this.state + const items = [ + { _id: 1, test: true }, + { _id: 2, test: true }, + { _id: 3, test: true }, + { _id: 4, test: true } + ] + addItems(state, items) + const itemsToRemove = [{ _id: 1, test: true }, { _id: 2, test: true }] + removeItems(state, itemsToRemove) + + assert(state.ids.length === 2, 'should have 2 ids left') + assert( + Object.keys(state.keyedById).length === 2, + 'should have 2 items left' + ) + }) + + it('clearAll', function() { + const state = this.state + const item1 = { + _id: 1, + test: true + } + const item2 = { + _id: 2, + test: true + } + const items = [item1, item2] + addItems(state, items) + + clearAll(state) + assert(state.ids.length === 0) + assert(Object.keys(state.keyedById).length === 0) + }) }) describe('updateItem', function() { @@ -185,15 +277,21 @@ describe('Service Module - Mutations', function() { return 'Release the flying monkeys!' } } + assertGetter(item1, 'getter', 'Release the flying monkeys!') const items = [item1] + addItems(state, items) + // Prove the getter is still in place in the store + assertGetter(state.keyedById[1], 'getter', 'Release the flying monkeys!') + const vm = new Vue({ data: { item: state.keyedById[1] }, watch: { - 'item.getter'() { + 'item.getter'(val) { + console.log(state.keyedById) throw new Error('this should never happen') } } @@ -571,262 +669,129 @@ describe('Service Module - Mutations', function() { }) }) - it('updateItems', function() { - const state = this.state - const item1 = { - _id: 1, - test: true - } - const item2 = { - _id: 2, - test: true - } - const items = [item1, item2] - addItems(state, items) - - const item1updated = { - _id: 1, - test: false - } - const item2updated = { - _id: 2, - test: false - } - const itemsToUpdate = [item1updated, item2updated] - updateItems(state, itemsToUpdate) - - assert(state.keyedById[1].test === false) - assert(state.keyedById[2].test === false) - }) + describe('Copy & Commit', function() { + it('createCopy', function() { + const { state } = this + const item1 = { + _id: 1, + test: true, + get getter() { + return 'Life is a Joy!' + }, + set setter(val) { + this.test = val + } + } + addItem(state, item1) + const original = state.keyedById[1] - it('removeItem', function() { - const state = this.state + createCopy(state, item1._id) - addItem(state, { _id: 1, test: true }) - removeItem(state, 1) + const copy = state.copiesById[item1._id] - assert(state.ids.length === 0) - assert(Object.keys(state.keyedById).length === 0) - }) + copy.setter = false + assert(copy.getter === 'Life is a Joy!', `getter was preserved`) + assert(copy.test === false, `copy was changed through setter`) + assert(original.test === true, `original item intact after copy changed`) + }) - it('removeItems with array of ids', function() { - const state = this.state - const items = [ - { _id: 1, test: true }, - { _id: 2, test: true }, - { _id: 3, test: true }, - { _id: 4, test: true } - ] - addItems(state, items) - const itemsToRemove = [1, 2] - removeItems(state, itemsToRemove) - - assert(state.ids.length === 2, 'should have 2 ids left') - assert( - Object.keys(state.keyedById).length === 2, - 'should have 2 items left' - ) - }) + it('resetCopy', function() { + const { state } = this + const item1 = { + _id: 1, + test: true, + get getter() { + return 'Life is a Joy!' + }, + set setter(val) { + this.test = val + } + } + addItem(state, item1) - it('removeItems with array of items', function() { - const state = this.state - const items = [ - { _id: 1, test: true }, - { _id: 2, test: true }, - { _id: 3, test: true }, - { _id: 4, test: true } - ] - addItems(state, items) - const itemsToRemove = [{ _id: 1, test: true }, { _id: 2, test: true }] - removeItems(state, itemsToRemove) - - assert(state.ids.length === 2, 'should have 2 ids left') - assert( - Object.keys(state.keyedById).length === 2, - 'should have 2 items left' - ) - }) + // Create a copy and modify it. + createCopy(state, item1._id) + const copy = state.copiesById[item1._id] + copy.test = false - it('clearAll', function() { - const state = this.state - const item1 = { - _id: 1, - test: true - } - const item2 = { - _id: 2, - test: true - } - const items = [item1, item2] - addItems(state, items) - - clearAll(state) - assert(state.ids.length === 0) - assert(Object.keys(state.keyedById).length === 0) - }) + // Call resetCopy and check that it's back to the original value + resetCopy(state, item1._id) + assert(copy.test === true, 'the copy was reset') - it('clearList', function() { - const state = this.state - const item1 = { - _id: 1, - test: true - } - const item2 = { - _id: 2, - test: true - } - - const items = [item1, item2] - addItems(state, items) - setCurrent(state, item2) - - clearList(state) - assert(state.ids.length === 1, 'only one id was left in the list') - assert(state.ids[0] === 2, 'the remaining id is for the current item') - assert(state.keyedById[1] === undefined, 'item1 is removed from keyedById') - assert(state.keyedById[2].test, 'the item is still in keyedById') - }) + // Make sure accessors stayed intact + assertGetter(copy, 'getter', 'Life is a Joy!') + copy.setter = false + assert(copy.test === false, 'the setter is intact') + }) - it('setCurrent', function() { - const state = this.state - const item1 = { - _id: 1, - test: true - } - const item2 = { - _id: 2, - test: true - } - const items = [item1, item2] - addItems(state, items) - setCurrent(state, item2) - - assert(state.currentId === 2) - assert.deepEqual(state.copy, item2) - - setCurrent(state, item1._id) - - assert(state.currentId === 1) - assert.deepEqual(state.copy, item1) - }) + it('commitCopy', function() { + const state = this.state + const item1 = { + _id: 1, + test: true, + get getter() { + return 'Life is a Joy!' + }, + set setter(val) { + this.test = val + } + } + addItem(state, item1) + const original = state.keyedById[item1._id] - it('clearCurrent', function() { - const state = this.state - const item1 = { - _id: 1, - test: true - } - const item2 = { - _id: 2, - test: true - } - const items = [item1, item2] - addItems(state, items) - setCurrent(state, item2) - clearCurrent(state) - - assert(state.currentId === null) - assert(state.copy === null) - }) + // Create a copy and modify it. + createCopy(state, item1._id) + const copy = state.copiesById[item1._id] + copy.test = false - it('copy works', function() { - const state = this.state - const item1 = { - _id: 1, - test: true - } - addItem(state, item1) - setCurrent(state, item1) - assert(state.copy.test === true, 'the copy is in place') - state.copy.test = false - assert(state.copy.test === false, 'the copy was updated successfully.') + commitCopy(state, item1._id) + assert(copy.test === false, `the copy wasn't changed after commitCopy`) + assert(original.test === false, 'original item updated after commitCopy') + }) }) - it('rejectCopy', function() { - const state = this.state - const item1 = { - _id: 1, - test: true - } - addItem(state, item1) - setCurrent(state, item1) - const original = state.keyedById[1] - const copy = state.copy - - state.copy.test = false - assert( - original.test === true, - `the original item didn't change when copy was changed` - ) - - rejectCopy(state) - assert(copy.test === true, 'the copy was reset') - }) + describe('Pagination', function() { + it('updatePaginationForQuery', function() { + const state = this.state + const qid = 'query-identifier' + const query = { limit: 2 } + const response = { + data: [{ _id: 1, test: true }], + limit: 2, + skip: 0, + total: 1 + } - it('commitCopy', function() { - const state = this.state - const item1 = { - _id: 1, - test: true - } - addItem(state, item1) - setCurrent(state, item1) - const original = state.keyedById[1] - const copy = state.copy - - copy.test = false - - commitCopy(state) - assert(copy.test === false, `the copy wasn't changed after commitCopy`) - assert( - original.test === false, - 'the original item was updated after commitCopy' - ) - }) + updatePaginationForQuery(state, { qid, response, query }) - it('updatePaginationForQuery', function() { - const state = this.state - const qid = 'query-identifier' - const query = { limit: 2 } - const response = { - data: [{ _id: 1, test: true }], - limit: 2, - skip: 0, - total: 1 - } - - updatePaginationForQuery(state, { qid, response, query }) - - const pageData = state.pagination[qid] - assert(pageData.ids.length === 1, `the _id was added to the pagination ids`) - assert(pageData.limit === 2, 'the limit was correct') - assert(pageData.skip === 0, 'the skip was correct') - assert(pageData.total === 1, 'the total was correct') - assert.deepEqual(pageData.query, query, 'the query was stored') + const pageData = state.pagination[qid] + assert( + pageData.ids.length === 1, + `the _id was added to the pagination ids` + ) + assert(pageData.limit === 2, 'the limit was correct') + assert(pageData.skip === 0, 'the skip was correct') + assert(pageData.total === 1, 'the total was correct') + assert.deepEqual(pageData.query, query, 'the query was stored') + }) }) describe('Pending', function() { - it('setPending', function() { + it('setPending && unsetPending', function() { const state = this.state const methods = ['find', 'get', 'create', 'update', 'patch', 'remove'] methods.forEach(method => { const uppercaseMethod = method.charAt(0).toUpperCase() + method.slice(1) assert(!state[`is${uppercaseMethod}Pending`]) + + // Set pending & check setPending(state, method) assert(state[`is${uppercaseMethod}Pending`]) - }) - }) - it('unsetPending', function() { - const state = this.state - const methods = ['find', 'get', 'create', 'update', 'patch', 'remove'] - - methods.forEach(method => { - const uppercaseMethod = method.charAt(0).toUpperCase() + method.slice(1) - assert(!state[`is${uppercaseMethod}Pending`]) + // Unset pending & check unsetPending(state, method) - assert(state[`is${uppercaseMethod}Pending`]) + assert(!state[`!is${uppercaseMethod}Pending`]) }) }) }) diff --git a/test/service-module/service-module.test.js b/test/service-module/service-module.test.js index b9caafc5..64e9da25 100644 --- a/test/service-module/service-module.test.js +++ b/test/service-module/service-module.test.js @@ -278,21 +278,6 @@ describe('Service Module', () => { assert.deepEqual(todo, {}, 'default model is an empty object') }) - it('setCurrent works on model instances with getters', function() { - const { Person, store } = this - const person = new Person({ - id: 1, - firstName: 'Al', - lastName: 'fred' - }) - store.commit('people/setCurrent', person) - - assert( - store.state.people.copy.fullName === 'Al fred', - 'setCurrent preserved the getter accessor prop' - ) - }) - it('stores clones in Model.copiesById by default', function() { const { Todo } = this const todo = new Todo({ id: 1, description: 'Do something' }) diff --git a/test/test-utils.ts b/test/test-utils.ts new file mode 100644 index 00000000..eb6022aa --- /dev/null +++ b/test/test-utils.ts @@ -0,0 +1,14 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { assert } from 'chai' + +export function assertGetter(item, prop, value) { + assert( + typeof Object.getOwnPropertyDescriptor(item, prop).get === 'function', + 'getter in place' + ) + assert.equal(item[prop], value, 'returned value matches') +} diff --git a/tsconfig.json b/tsconfig.json index 7ae2605f..6f22f643 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,9 @@ "allowJs": true, "allowSyntheticDefaultImports": true, "esModuleInterop": true, - "outDir": "dist" + "outDir": "dist", + "moduleResolution": "node", + "target": "ES6" }, "include": [ "src/**/*", "test/**/*" From 9d197911f17818e4fac0b199810cb6c8ce66a6fa Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 13:21:07 -0600 Subject: [PATCH 038/404] Lint cleanup --- src/service-module/service-module.mutations.ts | 5 +---- test/service-module/service-module.mutations.test.ts | 11 +---------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index f4895d4f..532a86c5 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -179,7 +179,7 @@ export default function makeServiceMutations() { if (keepCopiesInStore) { state.copiesById[id] = model || copyData } else { - Model.copiesById[id] = model || copyData + Model.copiesById[id] = Vue.observable(model || copyData) } }, @@ -215,9 +215,6 @@ export default function makeServiceMutations() { if (copy) { mergeWithAccessors(state.keyedById[id], copy) } - - // updateOriginal(copy, current) - // Object.assign(current, copy) }, /** diff --git a/test/service-module/service-module.mutations.test.ts b/test/service-module/service-module.mutations.test.ts index ea318c88..972e0701 100644 --- a/test/service-module/service-module.mutations.test.ts +++ b/test/service-module/service-module.mutations.test.ts @@ -7,21 +7,12 @@ import { assert } from 'chai' import { assertGetter } from '../test-utils' import makeServiceMutations from '../../src/service-module/service-module.mutations' import makeServiceState from '../../src/service-module/service-module.state' -import feathersVuex from '../../src/index' -import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' import errors from '@feathersjs/errors' import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) -const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { - serverAlias: 'myApi' -}) -class Todo extends BaseModel { - public static test: boolean = true -} - const options = { idField: '_id', autoRemove: false, @@ -290,7 +281,7 @@ describe('Service Module - Mutations', function() { item: state.keyedById[1] }, watch: { - 'item.getter'(val) { + 'item.getter'() { console.log(state.keyedById) throw new Error('this should never happen') } From d595b339593e85f2d884bd4c38ca94081a90e4a4 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 13:33:03 -0600 Subject: [PATCH 039/404] Add test for clearCopy mutation --- src/service-module/service-module.mutations.ts | 14 +++++++------- .../service-module.mutations.test.ts | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 532a86c5..d41db656 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -157,13 +157,6 @@ export default function makeServiceMutations() { state.keyedById = {} }, - // Removes the copy from copiesById - clearCopy(state, id) { - const newCopiesById = Object.assign({}, state.copiesById) - delete newCopiesById[id] - state.copiesById = newCopiesById - }, - // Creates a copy of the record with the passed-in id, stores it in copiesById createCopy(state, id) { const { servicePath, keepCopiesInStore } = state @@ -217,6 +210,13 @@ export default function makeServiceMutations() { } }, + // Removes the copy from copiesById + clearCopy(state, id) { + const newCopiesById = Object.assign({}, state.copiesById) + delete newCopiesById[id] + state.copiesById = newCopiesById + }, + /** * Stores pagination data on state.pagination based on the query identifier * (qid) The qid must be manually assigned to `params.qid` diff --git a/test/service-module/service-module.mutations.test.ts b/test/service-module/service-module.mutations.test.ts index 972e0701..73e7d1b4 100644 --- a/test/service-module/service-module.mutations.test.ts +++ b/test/service-module/service-module.mutations.test.ts @@ -30,6 +30,7 @@ const { createCopy, resetCopy, commitCopy, + clearCopy, updatePaginationForQuery, setPending, unsetPending, @@ -739,6 +740,21 @@ describe('Service Module - Mutations', function() { assert(copy.test === false, `the copy wasn't changed after commitCopy`) assert(original.test === false, 'original item updated after commitCopy') }) + + it('clearCopy', function() { + const state = this.state + const item1 = { + _id: 1, + test: true + } + addItem(state, item1) + + // Create a copy then clear it. + createCopy(state, item1._id) + assert(state.copiesById[item1._id], `the copy is there!`) + clearCopy(state, item1._id) + assert(!state.copiesById[item1._id], `the copy is gone!`) + }) }) describe('Pagination', function() { From 838b6c5a893f43ec38b8018110c998da045a8e1a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 13:47:27 -0600 Subject: [PATCH 040/404] Get utils tests passing --- src/auth-module/types.ts | 12 +++++ test/utils.test.js | 71 -------------------------- test/utils.test.ts | 105 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+), 71 deletions(-) create mode 100644 src/auth-module/types.ts delete mode 100644 test/utils.test.js create mode 100644 test/utils.test.ts diff --git a/src/auth-module/types.ts b/src/auth-module/types.ts new file mode 100644 index 00000000..a1b2c3d5 --- /dev/null +++ b/src/auth-module/types.ts @@ -0,0 +1,12 @@ +export interface AuthState { + accessToken: string + payload: {} + entityIdField: string + + isAuthenticatePending: boolean + isLogoutPending: boolean + + errorOnAuthenticate: Error + errorOnLogout: Error + user: {} +} diff --git a/test/utils.test.js b/test/utils.test.js deleted file mode 100644 index a75f5384..00000000 --- a/test/utils.test.js +++ /dev/null @@ -1,71 +0,0 @@ -import assert from 'chai/chai' -import { initAuth, getServicePrefix, getServiceCapitalization } from '../src/utils' -import feathersNuxt from '../src/index' -import { feathersSocketioClient as feathersClient } from './fixtures/feathers-client' -import Vue from 'vue' -import Vuex from 'vuex' - -Vue.use(Vuex) - -const { service, auth } = feathersNuxt(feathersClient) - -describe('Utils', function () { - it('properly populates auth', function () { - const store = new Vuex.Store({ - plugins: [ - service('todos'), - auth() - ] - }) - const accessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZXhwIjoiOTk5OTk5OTk5OTkiLCJuYW1lIjoiSm9obiBEb2UiLCJhZG1pbiI6dHJ1ZX0.lUlEd3xH-TnlNRbKM3jnDVTNoIg10zgzaS6QyFZE-6g' - const req = { - headers: { - cookie: 'feathers-jwt=' + accessToken - } - } - return initAuth({ - commit: store.commit, - req, - moduleName: 'auth', - cookieName: 'feathers-jwt' - }) - .then(payload => { - assert(store.state.auth.accessToken === accessToken, 'the token was in place') - assert(store.state.auth.payload, 'the payload was set') - return feathersClient.passport.getJWT() - }) - .then((token) => { - assert.isDefined(token, 'the feathers client storage was set') - }) - }) - - describe('Inflections', function () { - it('properly inflects the service prefix', function () { - const decisionTable = [ - ['todos', 'todos'], - ['TODOS', 'tODOS'], - ['environment-Panos', 'environmentPanos'], - ['env-panos', 'envPanos'], - ['envPanos', 'envPanos'], - ['api/v1/env-panos', 'envPanos'] - ] - decisionTable.forEach(([ path, prefix ]) => { - assert(getServicePrefix(path) === prefix, `The service prefix for path "${path}" was "${getServicePrefix(path)}", expected "${prefix}"`) - }) - }) - - it('properly inflects the service capitalization', function () { - const decisionTable = [ - ['todos', 'Todos'], - ['TODOS', 'TODOS'], - ['environment-Panos', 'EnvironmentPanos'], - ['env-panos', 'EnvPanos'], - ['envPanos', 'EnvPanos'], - ['api/v1/env-panos', 'EnvPanos'] - ] - decisionTable.forEach(([ path, prefix ]) => { - assert(getServiceCapitalization(path) === prefix, `The service prefix for path "${path}" was "${getServiceCapitalization(path)}", expected "${prefix}"`) - }) - }) - }) -}) diff --git a/test/utils.test.ts b/test/utils.test.ts new file mode 100644 index 00000000..07c91e6d --- /dev/null +++ b/test/utils.test.ts @@ -0,0 +1,105 @@ +import { assert } from 'chai' +import { AuthState } from '../src/auth-module/types' +import { + initAuth, + getServicePrefix, + getServiceCapitalization +} from '../src/utils' +import feathersVuex from '../src/index' +import { feathersSocketioClient as feathersClient } from './fixtures/feathers-client' +import Vue from 'vue' +import Vuex from 'vuex' + +Vue.use(Vuex) + +const { makeServicePlugin, makeAuthPlugin, BaseModel } = feathersVuex( + feathersClient, + { serverAlias: 'utils' } +) + +class User extends BaseModel { + public static test: boolean = true +} + +interface RootState { + auth: AuthState +} + +describe('Utils', function() { + it('properly populates auth', function() { + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: User, + servicePath: 'users', + service: feathersClient.service('users') + }), + makeAuthPlugin({}) + ] + }) + const accessToken = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZXhwIjoiOTk5OTk5OTk5OTkiLCJuYW1lIjoiSm9obiBEb2UiLCJhZG1pbiI6dHJ1ZX0.lUlEd3xH-TnlNRbKM3jnDVTNoIg10zgzaS6QyFZE-6g' + const req = { + headers: { + cookie: 'feathers-jwt=' + accessToken + } + } + return initAuth({ + commit: store.commit, + req, + moduleName: 'auth', + cookieName: 'feathers-jwt' + }) + .then(() => { + assert( + store.state.auth.accessToken === accessToken, + 'the token was in place' + ) + assert(store.state.auth.payload, 'the payload was set') + return feathersClient.passport.getJWT() + }) + .then(token => { + assert.isDefined(token, 'the feathers client storage was set') + }) + }) + + describe('Inflections', function() { + it('properly inflects the service prefix', function() { + const decisionTable = [ + ['todos', 'todos'], + ['TODOS', 'tODOS'], + ['environment-Panos', 'environmentPanos'], + ['env-panos', 'envPanos'], + ['envPanos', 'envPanos'], + ['api/v1/env-panos', 'envPanos'] + ] + decisionTable.forEach(([path, prefix]) => { + assert( + getServicePrefix(path) === prefix, + `The service prefix for path "${path}" was "${getServicePrefix( + path + )}", expected "${prefix}"` + ) + }) + }) + + it('properly inflects the service capitalization', function() { + const decisionTable = [ + ['todos', 'Todos'], + ['TODOS', 'TODOS'], + ['environment-Panos', 'EnvironmentPanos'], + ['env-panos', 'EnvPanos'], + ['envPanos', 'EnvPanos'], + ['api/v1/env-panos', 'EnvPanos'] + ] + decisionTable.forEach(([path, prefix]) => { + assert( + getServiceCapitalization(path) === prefix, + `The service prefix for path "${path}" was "${getServiceCapitalization( + path + )}", expected "${prefix}"` + ) + }) + }) + }) +}) From 78e00126109128ed2b0670fbaa8fe04ea1f2f5a0 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 20:31:13 -0600 Subject: [PATCH 041/404] Use more unique service names to prevent interference with other tests --- .../service-module.actions.test.ts | 159 +++++++++--------- 1 file changed, 79 insertions(+), 80 deletions(-) diff --git a/test/service-module/service-module.actions.test.ts b/test/service-module/service-module.actions.test.ts index 7ae8b410..e08d2819 100644 --- a/test/service-module/service-module.actions.test.ts +++ b/test/service-module/service-module.actions.test.ts @@ -38,8 +38,8 @@ interface ServiceState { } } interface RootState { - todos: ServiceState - tasks: ServiceState + 'my-todos': ServiceState + 'my-tasks': ServiceState broken: ServiceState } interface NumberedList { @@ -96,14 +96,14 @@ const assertRejected = (promise, done, callback) => { describe('Service Module - Actions', () => { beforeEach(function() { this.todoService = feathersClient.use( - 'todos', + 'my-todos', memory({ store: makeStore() }) ) this.taskService = feathersClient.use( - 'tasks', + 'my-tasks', memory({ store: makeStore(), paginate: { @@ -153,21 +153,21 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'todos', + servicePath: 'my-todos', Model: Todo, - service: feathersClient.service('todos') + service: feathersClient.service('my-todos') }) ] }) - const todoState = store.state.todos - const actions = mapActions('todos', ['find']) + const todoState = store.state['my-todos'] + const actions = mapActions('my-todos', ['find']) assert(todoState.ids.length === 0, 'no ids before find') assert(todoState.errorOnFind === null, 'no error before find') assert(todoState.isFindPending === false, 'isFindPending is false') assert(todoState.idField === 'id', 'idField is `id`') - actions.find.call({ $store: store }, {}).then(() => { + actions.find.call({ $store: store }, {}).then(response => { assert(todoState.ids.length === 10, 'three ids populated') assert(todoState.errorOnFind === null, 'errorOnFind still null') assert(todoState.isFindPending === false, 'isFindPending is false') @@ -200,13 +200,13 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'todos', + servicePath: 'my-todos', Model: Todo, - service: feathersClient.service('todos') + service: feathersClient.service('my-todos') }) ] }) - const actions = mapActions('todos', ['find']) + const actions = mapActions('my-todos', ['find']) actions.find .call({ $store: store }, { query: { $limit: 1 } }) @@ -226,13 +226,13 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'todos', + servicePath: 'my-todos', Model: Todo, - service: feathersClient.service('todos') + service: feathersClient.service('my-todos') }) ] }) - const actions = mapActions('todos', ['find']) + const actions = mapActions('my-todos', ['find']) actions.find .call({ $store: store }, { query: { $skip: 9 } }) @@ -252,13 +252,13 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'todos', + servicePath: 'my-todos', Model: Todo, - service: feathersClient.service('todos') + service: feathersClient.service('my-todos') }) ] }) - const actions = mapActions('todos', ['find']) + const actions = mapActions('my-todos', ['find']) actions.find .call({ $store: store }, { query: { $limit: 1, $skip: 8 } }) @@ -280,13 +280,13 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'tasks', + servicePath: 'my-tasks', Model: Task, - service: feathersClient.service('tasks') + service: feathersClient.service('my-tasks') }) ] }) - const actions = mapActions('tasks', ['find']) + const actions = mapActions('my-tasks', ['find']) actions.find .call({ $store: store }, { query: { $limit: 1 } }) @@ -309,13 +309,13 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'tasks', + servicePath: 'my-tasks', Model: Task, - service: feathersClient.service('tasks') + service: feathersClient.service('my-tasks') }) ] }) - const actions = mapActions('tasks', ['find']) + const actions = mapActions('my-tasks', ['find']) actions.find .call({ $store: store }, { query: { $skip: 9 } }) @@ -338,13 +338,13 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'tasks', + servicePath: 'my-tasks', Model: Task, - service: feathersClient.service('tasks') + service: feathersClient.service('my-tasks') }) ] }) - const actions = mapActions('tasks', ['find']) + const actions = mapActions('my-tasks', ['find']) actions.find .call({ $store: store }, { query: { $limit: 1, $skip: 8 } }) @@ -367,21 +367,18 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'tasks', + servicePath: 'my-tasks', Model: Task, - service: feathersClient.service('tasks') + service: feathersClient.service('my-tasks') }) ] }) - const actions = mapActions('tasks', ['find']) + const actions = mapActions('my-tasks', ['find']) actions.find.call({ $store: store }, { query: {} }).then(() => { - const { - ids, - limit, - skip, - total - } = store.state.tasks.pagination.default + const { ids, limit, skip, total } = store.state[ + 'my-tasks' + ].pagination.default assert(ids.length === 10, 'ten ids were returned in this page') assert( limit === 10, @@ -397,17 +394,19 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'tasks', + servicePath: 'my-tasks', Model: Task, - service: feathersClient.service('tasks') + service: feathersClient.service('my-tasks') }) ] }) - const actions = mapActions('tasks', ['find']) + const actions = mapActions('my-tasks', ['find']) const qid = 'component-name' actions.find.call({ $store: store }, { query: {}, qid }).then(() => { - const { ids, limit, skip, total } = store.state.tasks.pagination[qid] + const { ids, limit, skip, total } = store.state[ + 'my-tasks' + ].pagination[qid] assert(ids.length === 10, 'ten ids were returned in this page') assert( limit === 10, @@ -423,21 +422,21 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'tasks', + servicePath: 'my-tasks', Model: Task, - service: feathersClient.service('tasks') + service: feathersClient.service('my-tasks') }) ] }) - const actions = mapActions('tasks', ['find']) + const actions = mapActions('my-tasks', ['find']) const qid = 'component-name' actions.find .call({ $store: store }, { query: { $limit: 5, $skip: 2 }, qid }) .then(() => { - const { ids, limit, skip, total } = store.state.tasks.pagination[ - qid - ] + const { ids, limit, skip, total } = store.state[ + 'my-tasks' + ].pagination[qid] assert(ids.length === 5, 'ten ids were returned in this page') assert( limit === 5, @@ -453,13 +452,13 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'tasks', + servicePath: 'my-tasks', Model: Task, - service: feathersClient.service('tasks') + service: feathersClient.service('my-tasks') }) ] }) - const actions = mapActions('tasks', ['find']) + const actions = mapActions('my-tasks', ['find']) const qids = ['component-query-zero', 'component-query-one'] actions.find @@ -469,9 +468,9 @@ describe('Service Module - Actions', () => { ) .then(() => { qids.forEach(qid => { - const { ids, limit, skip, total } = store.state.tasks.pagination[ - qid - ] + const { ids, limit, skip, total } = store.state[ + 'my-tasks' + ].pagination[qid] assert(ids.length === 10, 'ten ids were returned in this page') assert( limit === 10, @@ -574,14 +573,14 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'todos', + servicePath: 'my-todos', Model: Todo, - service: feathersClient.service('todos') + service: feathersClient.service('my-todos') }) ] }) - const todoState = store.state.todos - const actions = mapActions('todos', ['get']) + const todoState = store.state['my-todos'] + const actions = mapActions('my-todos', ['get']) assert(todoState.ids.length === 0) assert(todoState.errorOnGet === null) @@ -656,14 +655,14 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'todos', + servicePath: 'my-todos', Model: Todo, - service: feathersClient.service('todos') + service: feathersClient.service('my-todos') }) ] }) - const todoState = store.state.todos - const actions = mapActions('todos', ['get']) + const todoState = store.state['my-todos'] + const actions = mapActions('my-todos', ['get']) assert(todoState.ids.length === 0) assert(todoState.errorOnGet === null) @@ -769,14 +768,14 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'todos', + servicePath: 'my-todos', Model: Todo, - service: feathersClient.service('todos') + service: feathersClient.service('my-todos') }) ] }) - const todoState = store.state.todos - const actions = mapActions('todos', ['create']) + const todoState = store.state['my-todos'] + const actions = mapActions('my-todos', ['create']) actions.create .call({ $store: store }, { description: 'Do the second' }) @@ -833,14 +832,14 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'todos', + servicePath: 'my-todos', Model: Todo, - service: feathersClient.service('todos') + service: feathersClient.service('my-todos') }) ] }) - const todoState = store.state.todos - const actions = mapActions('todos', ['create', 'update']) + const todoState = store.state['my-todos'] + const actions = mapActions('my-todos', ['create', 'update']) actions.create .call({ $store: store }, { description: 'Do the second' }) @@ -913,14 +912,14 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'todos', + servicePath: 'my-todos', Model: Todo, - service: feathersClient.service('todos') + service: feathersClient.service('my-todos') }) ] }) - const todoState = store.state.todos - const actions = mapActions('todos', ['create', 'patch']) + const todoState = store.state['my-todos'] + const actions = mapActions('my-todos', ['create', 'patch']) const dataUnchanged = { unchanged: true, @@ -965,14 +964,14 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'todos', + servicePath: 'my-todos', Model: Todo, - service: feathersClient.service('todos') + service: feathersClient.service('my-todos') }) ] }) - const todoState = store.state.todos - const actions = mapActions('todos', ['create', 'patch']) + const todoState = store.state['my-todos'] + const actions = mapActions('my-todos', ['create', 'patch']) actions.create .call({ $store: store }, { description: 'Do the second' }) @@ -1039,14 +1038,14 @@ describe('Service Module - Actions', () => { const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - servicePath: 'todos', + servicePath: 'my-todos', Model: Todo, - service: feathersClient.service('todos') + service: feathersClient.service('my-todos') }) ] }) - const todoState = store.state.todos - const actions = mapActions('todos', ['create', 'remove']) + const todoState = store.state['my-todos'] + const actions = mapActions('my-todos', ['create', 'remove']) actions.create .call({ $store: store }, { description: 'Do the second' }) From f7d80dc3a7ff6ab3c61a6c18e5a3db87ae35076a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 20:31:33 -0600 Subject: [PATCH 042/404] Make sure events are emitted on commitCopy --- src/utils.ts | 36 +++++++++++--- .../service-module.mutations.test.ts | 47 +++++++++++++++++++ 2 files changed, 76 insertions(+), 7 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 53a29020..f64e9a47 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -297,17 +297,39 @@ export function createRelatedInstance({ item, Model, idField, store }) { } export function mergeWithAccessors(dest, source) { - const props = Object.getOwnPropertyNames(source) - props.forEach(key => { + const sourceProps = Object.getOwnPropertyNames(source) + const destProps = Object.getOwnPropertyNames(dest) + const sourceIsVueObservable = sourceProps.includes('__ob__') + const destIsVueObservable = destProps.includes('__ob__') + sourceProps.forEach(key => { const desc = Object.getOwnPropertyDescriptor(source, key) - // Do not allow sharing of deeply-nested objects between instances - // This may break accessors on nested data. - if (_isPlainObject(desc.value)) { - desc.value = fastCopy(desc.value) + // If we're dealing with a Vue Observable, just assign the values. + if (destIsVueObservable) { + dest[key] = source[key] + return + } + + // Handle defining accessors + if (typeof desc.get === 'function' || typeof desc.set === 'function') { + if (destIsVueObservable) { + dest[key] = desc.value + } else { + Object.defineProperty(dest, key, desc) + } + return } - Object.defineProperty(dest, key, desc) + // Assign values + if (key !== '__ob__') { + // Do not allow sharing of deeply-nested objects between instances + // Probably breaks accessors on nested data. Use recursion if this is an issue + if (_isPlainObject(desc.value)) { + desc.value = fastCopy(desc.value) + } + // Vue.set(dest, key, desc.value) + dest[key] = desc.value + } }) return dest } diff --git a/test/service-module/service-module.mutations.test.ts b/test/service-module/service-module.mutations.test.ts index 73e7d1b4..a3c1a5e0 100644 --- a/test/service-module/service-module.mutations.test.ts +++ b/test/service-module/service-module.mutations.test.ts @@ -659,6 +659,53 @@ describe('Service Module - Mutations', function() { } updateItem(state, updatedItem) }) + + it('correctly emits events after commitCopy', function(done) { + const state = this.state + const item1 = { + _id: 1, + obj: { test: true }, + get getter() { + return this.obj.test + }, + set setter(val) { + this.obj.test = val + } + } + const items = [item1] + + addItems(state, items) + const item = state.keyedById[item1._id] + + createCopy(state, item._id) + const copy = state.copiesById[item1._id] + + const vm = new Vue({ + data: { + item, + copy + }, + watch: { + 'item.obj': { + handler() { + assert(this.item.obj.test === false) + done() + }, + deep: true + } + } + }) + + assert(vm.item, 'vm has item') + assert(vm.copy, 'vm has copy') + + // Modify copy and commit + vm.copy.setter = false + commitCopy(state, item1._id) + + assert(item.obj.test === false, 'deep obj should be false') + assert(vm.item.obj.test === false, 'deep obj should be false') + }) }) describe('Copy & Commit', function() { From c6ec7404f3489174fa9f8feb556d7c9734604462 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 20:45:17 -0600 Subject: [PATCH 043/404] Add test for resetCopy --- .../service-module.mutations.test.ts | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/test/service-module/service-module.mutations.test.ts b/test/service-module/service-module.mutations.test.ts index a3c1a5e0..eb7ba272 100644 --- a/test/service-module/service-module.mutations.test.ts +++ b/test/service-module/service-module.mutations.test.ts @@ -706,6 +706,53 @@ describe('Service Module - Mutations', function() { assert(item.obj.test === false, 'deep obj should be false') assert(vm.item.obj.test === false, 'deep obj should be false') }) + + it('correctly emits events after resetCopy', function(done) { + const state = this.state + const item1 = { + _id: 1, + obj: { test: true }, + get getter() { + return this.obj.test + }, + set setter(val) { + this.obj.test = val + } + } + const items = [item1] + + addItems(state, items) + const item = state.keyedById[item1._id] + + // createCopy and modify, but don't commit + createCopy(state, item._id) + const copy = state.copiesById[item1._id] + copy.setter = false + + const vm = new Vue({ + data: { + item, + copy + }, + watch: { + 'copy.obj': { + handler() { + assert(this.copy.obj.test === true) + done() + }, + deep: true + } + } + }) + + assert(vm.item, 'vm has item') + assert(vm.copy, 'vm has copy') + + resetCopy(state, item1._id) + + assert(item.obj.test === true, 'deep obj should be true') + assert(vm.item.obj.test === true, 'deep obj should be true') + }) }) describe('Copy & Commit', function() { From 8a62944fdd8b59afc6845b0065a3a44e34e37bbf Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 21:05:39 -0600 Subject: [PATCH 044/404] Clean up service mutations --- src/service-module/service-module.mutations.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index d41db656..3dd3c5b4 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -80,9 +80,7 @@ export default function makeServiceMutations() { addItem(state, item) { addItems(state, [item]) }, - addItems(state, items) { - addItems(state, items) - }, + addItems, updateItem(state, item) { updateItems(state, [item]) }, From dc89a2ef22fbbdf41ed5a9017001aa12c5b3f65b Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 21:05:55 -0600 Subject: [PATCH 045/404] Add misconfigured client tests --- .../misconfigured-client.test.js | 19 ------------ .../misconfigured-client.test.ts | 31 +++++++++++++++++++ 2 files changed, 31 insertions(+), 19 deletions(-) delete mode 100644 test/service-module/misconfigured-client.test.js create mode 100644 test/service-module/misconfigured-client.test.ts diff --git a/test/service-module/misconfigured-client.test.js b/test/service-module/misconfigured-client.test.js deleted file mode 100644 index d4e7cad0..00000000 --- a/test/service-module/misconfigured-client.test.js +++ /dev/null @@ -1,19 +0,0 @@ -import assert from 'chai/chai' -import feathersVuex from '~/src/service-module/service-module' -import feathers from '@feathersjs/client' -import auth from '@feathersjs/authentication-client' - -const feathersClient = feathers() - .configure(auth()) - -describe('Service Module - Bad Client Setup', () => { - it('throws an error when no client transport plugin is registered', () => { - const service = feathersVuex(feathersClient) - - try { - service('todos') - } catch (error) { - assert(error.message.includes('No service was found. Please configure a transport plugin on the Feathers Client'), 'got an error with a misconfigured client') - } - }) -}) diff --git a/test/service-module/misconfigured-client.test.ts b/test/service-module/misconfigured-client.test.ts new file mode 100644 index 00000000..2a1b1d87 --- /dev/null +++ b/test/service-module/misconfigured-client.test.ts @@ -0,0 +1,31 @@ +import { assert } from 'chai' +import feathersVuex from '../../src/index' +import feathers from '@feathersjs/client' +import auth from '@feathersjs/authentication-client' + +const feathersClient = feathers().configure(auth()) + +describe('Service Module - Bad Client Setup', () => { + it('throws an error when no client transport plugin is registered', () => { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'misconfigured' + }) + class MisconfiguredTask extends BaseModel { + public static test: boolean = true + } + + try { + makeServicePlugin({ + Model: MisconfiguredTask, + service: feathersClient.service('misconfigured-todos') + }) + } catch (error) { + assert( + error.message.includes( + 'No service was provided. If you passed one in, check that you have configured a transport plugin on the Feathers Client. Make sure you use the client version of the transport`.' + ), + 'got an error with a misconfigured client' + ) + } + }) +}) From 30a5b2b53e87d474962ffac00dff5ba37ebec216 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 22:35:48 -0600 Subject: [PATCH 046/404] Simplify & test FeathersVuex Vue Plugin --- package-lock.json | 564 +++++++++++++++++++++++++++++++---- package.json | 3 + src/index.ts | 12 +- src/vue-plugin/vue-plugin.ts | 18 +- test/make-find-mixin.test.js | 58 ---- test/make-find-mixin.test.ts | 67 +++++ test/vue-plugin.test.ts | 41 +++ 7 files changed, 630 insertions(+), 133 deletions(-) delete mode 100644 test/make-find-mixin.test.js create mode 100644 test/make-find-mixin.test.ts create mode 100644 test/vue-plugin.test.ts diff --git a/package-lock.json b/package-lock.json index 7fdfd075..5a17b69a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3707,6 +3707,16 @@ "@typescript-eslint/parser": "^1.1.0" } }, + "@vue/test-utils": { + "version": "1.0.0-beta.29", + "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-1.0.0-beta.29.tgz", + "integrity": "sha512-yX4sxEIHh4M9yAbLA/ikpEnGKMNBCnoX98xE1RwxfhQVcn0MaXNSj1Qmac+ZydTj6VBSEVukchBogXBTwc+9iA==", + "dev": true, + "requires": { + "dom-event-types": "^1.0.0", + "lodash": "^4.17.4" + } + }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", @@ -4065,6 +4075,12 @@ "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg=", "dev": true }, + "abab": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", + "dev": true + }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -4093,12 +4109,28 @@ "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", "dev": true }, + "acorn-globals": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", + "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + } + }, "acorn-jsx": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", "dev": true }, + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "dev": true + }, "after": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", @@ -4189,6 +4221,7 @@ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, + "optional": true, "requires": { "kind-of": "^3.0.2", "longest": "^1.0.1", @@ -4353,6 +4386,12 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -4911,13 +4950,15 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "dev": true, + "optional": true }, "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, + "optional": true, "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -4936,6 +4977,7 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, + "optional": true, "requires": { "is-extendable": "^0.1.0" } @@ -5119,6 +5161,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, + "optional": true, "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -5131,6 +5174,7 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, + "optional": true, "requires": { "is-extendable": "^0.1.0" } @@ -5157,7 +5201,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -5178,12 +5223,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5198,17 +5245,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -5325,7 +5375,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -5337,6 +5388,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5351,6 +5403,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5358,12 +5411,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -5382,6 +5437,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -5462,7 +5518,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -5474,6 +5531,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -5559,7 +5617,8 @@ "safe-buffer": { "version": "5.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -5595,6 +5654,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5614,6 +5674,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -5657,12 +5718,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -5725,7 +5788,8 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "dev": true, + "optional": true }, "is-glob": { "version": "4.0.0", @@ -5742,6 +5806,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, + "optional": true, "requires": { "kind-of": "^3.0.2" }, @@ -5751,6 +5816,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, + "optional": true, "requires": { "is-buffer": "^1.1.5" } @@ -5761,13 +5827,15 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "dev": true, + "optional": 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 + "dev": true, + "optional": true }, "micromatch": { "version": "3.1.10", @@ -6691,6 +6759,12 @@ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, "browser-stdout": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", @@ -8253,6 +8327,21 @@ "source-map": "^0.5.3" } }, + "cssom": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", + "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==", + "dev": true + }, + "cssstyle": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.1.tgz", + "integrity": "sha512-7DYm8qe+gPx/h77QlCyFmX80+fGaE/6A/Ekl0zaszYOubvySO2saYFdQ78P29D0UsULxFKCetDGNaNRUdSF+2A==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -8286,6 +8375,17 @@ "assert-plus": "^1.0.0" } }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + } + }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -8618,6 +8718,12 @@ "utila": "~0.4" } }, + "dom-event-types": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dom-event-types/-/dom-event-types-1.0.0.tgz", + "integrity": "sha512-2G2Vwi2zXTHBGqXHsJ4+ak/iP0N8Ar+G8a7LiD2oup5o4sQWytwqqrZu/O6hIMV0KMID2PL69OhpshLO0n7UJQ==", + "dev": true + }, "dom-serializer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", @@ -8646,6 +8752,15 @@ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", "dev": true }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, "domhandler": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", @@ -10701,7 +10816,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.1.1", @@ -10752,7 +10868,8 @@ "balanced-match": { "version": "0.4.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "bcrypt-pbkdf": { "version": "1.0.1", @@ -10767,6 +10884,7 @@ "version": "0.0.9", "bundled": true, "dev": true, + "optional": true, "requires": { "inherits": "~2.0.0" } @@ -10775,6 +10893,7 @@ "version": "2.10.1", "bundled": true, "dev": true, + "optional": true, "requires": { "hoek": "2.x.x" } @@ -10783,6 +10902,7 @@ "version": "1.1.7", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^0.4.1", "concat-map": "0.0.1" @@ -10791,7 +10911,8 @@ "buffer-shims": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "caseless": { "version": "0.12.0", @@ -10808,12 +10929,14 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "combined-stream": { "version": "1.0.5", "bundled": true, "dev": true, + "optional": true, "requires": { "delayed-stream": "~1.0.0" } @@ -10821,17 +10944,20 @@ "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "cryptiles": { "version": "2.0.5", @@ -10877,7 +11003,8 @@ "delayed-stream": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "delegates": { "version": "1.0.0", @@ -10903,7 +11030,8 @@ "extsprintf": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "forever-agent": { "version": "0.6.1", @@ -10925,12 +11053,14 @@ "fs.realpath": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "fstream": { "version": "1.0.11", "bundled": true, "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -10986,6 +11116,7 @@ "version": "7.1.2", "bundled": true, "dev": true, + "optional": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -10998,7 +11129,8 @@ "graceful-fs": { "version": "4.1.11", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "har-schema": { "version": "1.0.5", @@ -11037,7 +11169,8 @@ "hoek": { "version": "2.16.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "http-signature": { "version": "1.1.1", @@ -11054,6 +11187,7 @@ "version": "1.0.6", "bundled": true, "dev": true, + "optional": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -11062,7 +11196,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.4", @@ -11074,6 +11209,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -11087,7 +11223,8 @@ "isarray": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "isstream": { "version": "0.1.2", @@ -11160,12 +11297,14 @@ "mime-db": { "version": "1.27.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "mime-types": { "version": "2.1.15", "bundled": true, "dev": true, + "optional": true, "requires": { "mime-db": "~1.27.0" } @@ -11174,6 +11313,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -11181,12 +11321,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "mkdirp": { "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -11239,7 +11381,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "oauth-sign": { "version": "0.8.2", @@ -11257,6 +11400,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -11286,7 +11430,8 @@ "path-is-absolute": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "performance-now": { "version": "0.2.0", @@ -11297,7 +11442,8 @@ "process-nextick-args": { "version": "1.0.7", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "punycode": { "version": "1.4.1", @@ -11335,6 +11481,7 @@ "version": "2.2.9", "bundled": true, "dev": true, + "optional": true, "requires": { "buffer-shims": "~1.0.0", "core-util-is": "~1.0.0", @@ -11379,6 +11526,7 @@ "version": "2.6.1", "bundled": true, "dev": true, + "optional": true, "requires": { "glob": "^7.0.5" } @@ -11386,7 +11534,8 @@ "safe-buffer": { "version": "5.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "semver": { "version": "5.3.0", @@ -11444,6 +11593,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -11454,6 +11604,7 @@ "version": "1.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.0.1" } @@ -11468,6 +11619,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -11482,6 +11634,7 @@ "version": "2.2.1", "bundled": true, "dev": true, + "optional": true, "requires": { "block-stream": "*", "fstream": "^1.0.2", @@ -11537,7 +11690,8 @@ "util-deprecate": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "uuid": { "version": "3.0.1", @@ -11566,7 +11720,8 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -12087,6 +12242,15 @@ "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", "dev": true }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, "html-minifier": { "version": "3.5.21", "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", @@ -13164,6 +13328,90 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, + "jsdom": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-14.0.0.tgz", + "integrity": "sha512-/VkyPmdtbwqpJSkwDx3YyJ3U1oawYNB/h5z8vTUZGAzjtu2OHTeFRfnJqyMHsJ5Cyes23trOmvUpM1GfHH1leA==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^6.0.4", + "acorn-globals": "^4.3.0", + "array-equal": "^1.0.0", + "cssom": "^0.3.4", + "cssstyle": "^1.1.1", + "data-urls": "^1.1.0", + "domexception": "^1.0.1", + "escodegen": "^1.11.0", + "html-encoding-sniffer": "^1.0.2", + "nwsapi": "^2.0.9", + "parse5": "5.1.0", + "pn": "^1.1.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.5", + "saxes": "^3.1.5", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.5.0", + "w3c-hr-time": "^1.0.1", + "w3c-xmlserializer": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^7.0.0", + "ws": "^6.1.2", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "escodegen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "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 + }, + "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, + "optional": true + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + } + } + }, + "jsdom-global": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-3.0.2.tgz", + "integrity": "sha1-a9KZwTsMRiay2iwDk81DhdYGrLk=", + "dev": true + }, "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", @@ -13827,6 +14075,12 @@ "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, "lodash.template": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", @@ -13983,7 +14237,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true + "dev": true, + "optional": true }, "loose-envify": { "version": "1.3.1", @@ -14926,6 +15181,12 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "nwsapi": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.1.tgz", + "integrity": "sha512-T5GaA1J/d34AC8mkrFD2O0DR17kwJ702ZOtJOsS8RpbsQZVOC2/xYFb1i/cw+xdM54JIlMuojjDOYct8GIWtwg==", + "dev": true + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -15279,6 +15540,12 @@ "error-ex": "^1.2.0" } }, + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "dev": true + }, "parseqs": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", @@ -15543,6 +15810,12 @@ "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, "portfinder": { "version": "1.0.20", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz", @@ -17240,6 +17513,26 @@ } } }, + "request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "request-promise-native": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", + "dev": true, + "requires": { + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -17447,6 +17740,15 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, + "saxes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.9.tgz", + "integrity": "sha512-FZeKhJglhJHk7eWG5YM0z46VHmI3KJpMBAQm3xa9meDvd+wevB5GuBB0wc0exPInZiBBHqi00DbS8AcvCGCFMw==", + "dev": true, + "requires": { + "xmlchars": "^1.3.1" + } + }, "schema-utils": { "version": "0.4.7", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", @@ -18576,6 +18878,12 @@ } } }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -18914,6 +19222,12 @@ "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", "dev": true }, + "symbol-tree": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", + "dev": true + }, "table": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", @@ -19754,6 +20068,23 @@ } } }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "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 + } + } + }, "traverse": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", @@ -20882,7 +21213,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -20903,12 +21235,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -20923,17 +21257,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -21050,7 +21387,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -21062,6 +21400,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -21076,6 +21415,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -21083,12 +21423,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -21107,6 +21449,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -21187,7 +21530,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -21199,6 +21543,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -21284,7 +21629,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -21320,6 +21666,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -21339,6 +21686,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -21382,12 +21730,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -21603,6 +21953,26 @@ "integrity": "sha512-wLoqz0B7DSZtgbWL1ShIBBCjv22GV5U+vcBFox658g6V0s4wZV9P4YjCNyoHSyIBpj1f29JBoNQIqD82cR4O3w==", "dev": true }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "w3c-xmlserializer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", + "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", + "dev": true, + "requires": { + "domexception": "^1.0.1", + "webidl-conversions": "^4.0.2", + "xml-name-validator": "^3.0.0" + } + }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", @@ -21876,7 +22246,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -21897,12 +22268,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -21917,17 +22290,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -22044,7 +22420,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -22056,6 +22433,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -22070,6 +22448,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -22077,12 +22456,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -22101,6 +22482,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -22181,7 +22563,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -22193,6 +22576,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -22278,7 +22662,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -22314,6 +22699,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -22333,6 +22719,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -22376,12 +22763,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -22535,6 +22924,12 @@ } } }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, "webpack": { "version": "4.29.6", "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.29.6.tgz", @@ -23227,6 +23622,43 @@ } } }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + }, + "dependencies": { + "iconv-lite": { + "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" + } + } + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "when": { "version": "3.6.4", "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz", @@ -23526,12 +23958,24 @@ "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", "dev": true }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, "xmlbuilder": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=", "dev": true }, + "xmlchars": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-1.3.1.tgz", + "integrity": "sha512-tGkGJkN8XqCod7OT+EvGYK5Z4SfDQGD30zAa58OcnAa0RRWgzUEK72tkXhsX1FZd+rgnhRxFtmO+ihkp8LHSkw==", + "dev": true + }, "xmldom": { "version": "0.1.27", "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", diff --git a/package.json b/package.json index ed2b851b..febff351 100644 --- a/package.json +++ b/package.json @@ -130,6 +130,7 @@ "@typescript-eslint/parser": "^1.5.0", "@vue/eslint-config-prettier": "^4.0.1", "@vue/eslint-config-typescript": "^4.0.0", + "@vue/test-utils": "^1.0.0-beta.29", "axios": "^0.18.0", "babel-cli": "^6.26.0", "babel-core": "^6.26.3", @@ -146,6 +147,8 @@ "eslint-plugin-vue": "^5.2.2", "feathers-memory": "^3.0.1", "istanbul": "^1.1.0-alpha.1", + "jsdom": "^14.0.0", + "jsdom-global": "^3.0.2", "mocha": "^5.2.0", "prettier": "^1.16.4", "shx": "^0.3.2", diff --git a/src/index.ts b/src/index.ts index 1b303081..3be1b73a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,13 +8,13 @@ import FeathersVuexFind from './FeathersVuexFind' import FeathersVuexGet from './FeathersVuexGet' import makeFindMixin from './make-find-mixin' import makeGetMixin from './make-get-mixin' -import { globalModels } from './service-module/global-models' +import { globalModels as models } from './service-module/global-models' import makeModel from './service-module/make-model' import prepareMakeServicePlugin from './service-module/make-service-plugin' import { FeathersVuexOptions } from './service-module/types' import { initAuth } from './utils' -import setupVuePlugin from './vue-plugin/vue-plugin' +import { FeathersVuex } from './vue-plugin/vue-plugin' const defaultOptions: FeathersVuexOptions = { autoRemove: false, // Automatically remove records missing from responses (only use with feathers-rest) @@ -54,8 +54,8 @@ export default function feathersVuex(feathers, options: FeathersVuexOptions) { makeServicePlugin, BaseModel, makeAuthPlugin: setupAuthModule(feathers), - FeathersVuex: setupVuePlugin(), - models: globalModels + FeathersVuex, + models } } @@ -63,6 +63,8 @@ export { initAuth, FeathersVuexFind, FeathersVuexGet, + FeathersVuex, makeFindMixin, - makeGetMixin + makeGetMixin, + models } diff --git a/src/vue-plugin/vue-plugin.ts b/src/vue-plugin/vue-plugin.ts index afc93331..71c6705a 100644 --- a/src/vue-plugin/vue-plugin.ts +++ b/src/vue-plugin/vue-plugin.ts @@ -7,18 +7,16 @@ import FeathersVuexFind from '../FeathersVuexFind' import FeathersVuexGet from '../FeathersVuexGet' import { globalModels } from '../service-module/global-models' -export default function setupVuePlugin() { - return { - install(Vue, options = { components: true }) { - const shouldSetupComponents = options.components !== false +export const FeathersVuex = { + install(Vue, options = { components: true }) { + const shouldSetupComponents = options.components !== false - Vue.$FeathersVuex = globalModels - Vue.prototype.$FeathersVuex = globalModels + Vue.$FeathersVuex = globalModels + Vue.prototype.$FeathersVuex = globalModels - if (shouldSetupComponents) { - Vue.component('feathers-vuex-find', FeathersVuexFind) - Vue.component('feathers-vuex-get', FeathersVuexGet) - } + if (shouldSetupComponents) { + Vue.component('feathers-vuex-find', FeathersVuexFind) + Vue.component('feathers-vuex-get', FeathersVuexGet) } } } diff --git a/test/make-find-mixin.test.js b/test/make-find-mixin.test.js deleted file mode 100644 index 9a080232..00000000 --- a/test/make-find-mixin.test.js +++ /dev/null @@ -1,58 +0,0 @@ -import assert from 'chai/chai' -import setupVuexService from '~/src/service-module/service-module' -import setupVuePlugin from '../src/vue-plugin/vue-plugin.js' -import { feathersRestClient as feathersClient } from './fixtures/feathers-client' -import makeFindMixin from '../src/make-find-mixin' -import Vue from 'vue/dist/vue' -import Vuex from 'vuex' - -const globalModels = {} -const vuePlugin = setupVuePlugin(globalModels) -const service = setupVuexService(feathersClient, {}, globalModels) - -Vue.use(Vuex) -Vue.use(vuePlugin) - -describe('Find Mixin', function () { - const serviceName = 'todos' - const store = new Vuex.Store({ - plugins: [service(serviceName)] - }) - - it('correctly forms mixin data', function () { - const todosMixin = makeFindMixin({ service: 'todos' }) - - const vm = new Vue({ - name: 'todos-component', - mixins: [ - todosMixin - ], - store, - template: `
` - }).$mount() - - assert.deepEqual(vm.todos, [], 'todos prop was empty array') - assert(vm.hasOwnProperty('todosPaginationData'), 'pagination data prop was present, even if undefined') - assert(vm.todosServiceName === 'todos', 'service name was correct') - assert(vm.isFindTodosPending === false, 'loading boolean is in place') - assert(typeof vm.findTodos === 'function', 'the find action is in place') - assert(vm.todosLocal === false, 'local boolean is false by default') - assert(vm.todosQid === 'default', 'the default query identifier is in place') - assert(vm.todosQueryWhen() === true, 'the default queryWhen is true') - // assert(vm.todosWatch.length === 0, 'the default watch is an empty array') - assert(vm.todosParams === undefined, 'no params are in place by default, must be specified by the user') - assert(vm.todosFetchParams === undefined, 'no fetch params are in place by default, must be specified by the user') - }) - - it('registers a vuex plugin and Model for the service', () => { - assert(globalModels.hasOwnProperty('Todo'), 'the Model was added to the globalModels') - - const todo = new globalModels.Todo({ - description: 'Do the dishes', - isComplete: false - }) - assert(todo instanceof globalModels.Todo, 'Model can be instantiated.') - - assert(store.state[serviceName]) - }) -}) diff --git a/test/make-find-mixin.test.ts b/test/make-find-mixin.test.ts new file mode 100644 index 00000000..b9082d91 --- /dev/null +++ b/test/make-find-mixin.test.ts @@ -0,0 +1,67 @@ +import jsdom from 'jsdom-global' +import { assert } from 'chai' +import feathersVuex, { FeathersVuex, models } from '../src/index' +import { feathersRestClient as feathersClient } from './fixtures/feathers-client' +import makeFindMixin from '../src/make-find-mixin' +import Vue from 'vue/dist/vue' +import Vuex from 'vuex' + +jsdom() + +const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'make-find-mixin' +}) + +class FindModel extends BaseModel { + public static test: boolean = true +} + +Vue.use(Vuex) +Vue.use(FeathersVuex) + +describe('Find Mixin', function() { + const serviceName = 'todos' + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: FindModel, + service: feathersClient.service(serviceName) + }) + ] + }) + + it('correctly forms mixin data', function() { + const todosMixin = makeFindMixin({ service: 'todos' }) + + const vm = new Vue({ + name: 'todos-component', + mixins: [todosMixin], + store, + template: `
` + }).$mount() + + assert.deepEqual(vm.todos, [], 'todos prop was empty array') + assert( + vm.hasOwnProperty('todosPaginationData'), + 'pagination data prop was present, even if undefined' + ) + assert(vm.todosServiceName === 'todos', 'service name was correct') + assert(vm.isFindTodosPending === false, 'loading boolean is in place') + assert(typeof vm.findTodos === 'function', 'the find action is in place') + assert(vm.todosLocal === false, 'local boolean is false by default') + assert( + vm.todosQid === 'default', + 'the default query identifier is in place' + ) + assert(vm.todosQueryWhen() === true, 'the default queryWhen is true') + // assert(vm.todosWatch.length === 0, 'the default watch is an empty array') + assert( + vm.todosParams === undefined, + 'no params are in place by default, must be specified by the user' + ) + assert( + vm.todosFetchParams === undefined, + 'no fetch params are in place by default, must be specified by the user' + ) + }) +}) diff --git a/test/vue-plugin.test.ts b/test/vue-plugin.test.ts new file mode 100644 index 00000000..3b275ef7 --- /dev/null +++ b/test/vue-plugin.test.ts @@ -0,0 +1,41 @@ +import { assert } from 'chai' +import feathersVuex, { FeathersVuex } from '../src/index' +import { feathersRestClient as feathersClient } from './fixtures/feathers-client' +import Vue from 'vue/dist/vue' +import Vuex from 'vuex' + +Vue.use(Vuex) +Vue.use(FeathersVuex) + +const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'make-find-mixin' +}) +class FindModel extends BaseModel { + public static test: boolean = true +} + +const serviceName = 'todos' +const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: FindModel, + service: feathersClient.service(serviceName) + }) + ] +}) + +interface VueWithFeathers { + $FeathersVuex: {} +} + +describe('Vue Plugin', function() { + it('Adds the `$FeathersVuex` object to components', function() { + const vm = new Vue({ + name: 'todos-component', + store, + template: `
` + }).$mount() + + assert(vm.$FeathersVuex, 'registeredPlugin correctly') + }) +}) From 7919ae63a18c568c03f838c1f5c4dc3824e59259 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 22:37:25 -0600 Subject: [PATCH 047/404] Add tests for Node Env detection utils --- test/node.test.js | 17 ----------------- test/utils.test.ts | 11 +++++++++++ 2 files changed, 11 insertions(+), 17 deletions(-) delete mode 100644 test/node.test.js diff --git a/test/node.test.js b/test/node.test.js deleted file mode 100644 index 4854ba7a..00000000 --- a/test/node.test.js +++ /dev/null @@ -1,17 +0,0 @@ - -import chai from 'chai/chai' -import { isNode, isBrowser } from '../src/utils' - -const assert = chai.assert - -describe('feathers-vuex', () => { - describe('Utils', () => { - it('sets isNode to true', () => { - assert(isNode, 'isNode was true') - }) - - it('sets isBrowser to false', () => { - assert(!isBrowser, 'isBrowser was false') - }) - }) -}) diff --git a/test/utils.test.ts b/test/utils.test.ts index 07c91e6d..44ebe61b 100644 --- a/test/utils.test.ts +++ b/test/utils.test.ts @@ -1,5 +1,6 @@ import { assert } from 'chai' import { AuthState } from '../src/auth-module/types' +import { isNode, isBrowser } from '../src/utils' import { initAuth, getServicePrefix, @@ -102,4 +103,14 @@ describe('Utils', function() { }) }) }) + + describe('Environments', () => { + it('sets isNode to true', () => { + assert(isNode, 'isNode was true') + }) + + it('sets isBrowser to false', () => { + assert(!isBrowser, 'isBrowser was false') + }) + }) }) From 006d32f1ff04198c10eb158e38e1e99ed8483dc5 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 22:46:37 -0600 Subject: [PATCH 048/404] Add test for exports --- test/index.test.js | 62 ---------------------------------------------- test/index.test.ts | 40 ++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 62 deletions(-) delete mode 100644 test/index.test.js create mode 100644 test/index.test.ts diff --git a/test/index.test.js b/test/index.test.js deleted file mode 100644 index 4de92934..00000000 --- a/test/index.test.js +++ /dev/null @@ -1,62 +0,0 @@ -import './service-module/service-module.test.js' -import './service-module/misconfigured-client.test.js' -import './service-module/actions.test.js' -import './service-module/getters.test.js' -import './service-module/mutations.test.js' -import './auth-module/auth-module.test.js' -import './auth-module/actions.test.js' -import './make-find-mixin.test.js' -import './utils.test.js' - -import assert from 'chai/chai' -import 'steal-mocha' -import feathersVuex from '../src/index' -import { feathersSocketioClient as feathersClient } from './fixtures/feathers-client' -import Vue from 'vue' -import Vuex from 'vuex' - -Vue.use(Vuex) - -describe('feathers-vuex', () => { - it('is CommonJS compatible', () => { - assert(typeof feathersVuex === 'function') - }) - - it('basic functionality', () => { - assert(typeof feathersVuex === 'function', 'It worked') - }) - - it('requires a Feathers Client instance', () => { - try { - feathersVuex() - } catch (error) { - assert(error.message === 'You must provide a Feathers Client instance to feathers-vuex') - } - }) - - it('includes the service and auth plugins', function () { - const { service, auth, FeathersVuex, FeathersVuexFind, FeathersVuexGet } = feathersVuex(feathersClient) - - assert(typeof service === 'function', 'service util in place') - assert(typeof auth === 'function', 'auth util in place') - assert(typeof FeathersVuex.install === 'function', 'vue plugin is in place') - assert(typeof FeathersVuexFind === 'object', 'FeathersVuexFind component is in place') - assert(typeof FeathersVuexGet === 'object', 'FeathersVuexGet component is in place') - }) - - it('can globally set the options', () => { - const options = { - idField: '___idField', - autoRemove: true - } - const { service } = feathersVuex(feathersClient, options) - const store = new Vuex.Store({ - plugins: [ - service('todos') - ] - }) - const { idField, autoRemove } = store.state.todos - assert(idField === options.idField, 'idField was set correctly') - assert(autoRemove === options.autoRemove, 'autoRemove was set correctly') - }) -}) diff --git a/test/index.test.ts b/test/index.test.ts new file mode 100644 index 00000000..c497a67c --- /dev/null +++ b/test/index.test.ts @@ -0,0 +1,40 @@ +import { assert } from 'chai' +import * as feathersVuex from '../src/index' +import { feathersSocketioClient as feathersClient } from './fixtures/feathers-client' +import Vue from 'vue' +import Vuex from 'vuex' + +Vue.use(Vuex) + +describe('feathers-vuex', () => { + it('has correct exports', () => { + assert(typeof feathersVuex.default === 'function') + assert( + typeof feathersVuex.FeathersVuex.install === 'function', + 'has Vue Plugin' + ) + assert(feathersVuex.FeathersVuexFind) + assert(feathersVuex.FeathersVuexGet) + assert(feathersVuex.initAuth) + assert(feathersVuex.makeFindMixin) + assert(feathersVuex.makeGetMixin) + assert(feathersVuex.models) + }) + + it('requires a Feathers Client instance', () => { + try { + console.log(Object.keys(feathersVuex)) + feathersVuex.default( + {}, + { + serverAlias: 'index-test' + } + ) + } catch (error) { + assert( + error.message === + 'The first argument to feathersVuex must be a feathers client.' + ) + } + }) +}) From b7a5664fb1a1688742fa1f7e67ff80f1852173fb Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 22:46:56 -0600 Subject: [PATCH 049/404] Remove old test file --- test/index.html | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 test/index.html diff --git a/test/index.html b/test/index.html deleted file mode 100644 index f49d9876..00000000 --- a/test/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - Feathers-Vuex tests - - - - - - - \ No newline at end of file From d555176159814066be92416d57d78122874a8ecf Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 23:36:57 -0600 Subject: [PATCH 050/404] Clean up console.log --- test/index.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/index.test.ts b/test/index.test.ts index c497a67c..109c66e9 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -23,7 +23,6 @@ describe('feathers-vuex', () => { it('requires a Feathers Client instance', () => { try { - console.log(Object.keys(feathersVuex)) feathersVuex.default( {}, { From f716b8df6d6a9ff0c043adc33d8f3f00bc8802ab Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 26 Mar 2019 23:37:46 -0600 Subject: [PATCH 051/404] Lint cleanup --- test/index.test.ts | 1 - test/make-find-mixin.test.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/test/index.test.ts b/test/index.test.ts index 109c66e9..715aedf8 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -1,6 +1,5 @@ import { assert } from 'chai' import * as feathersVuex from '../src/index' -import { feathersSocketioClient as feathersClient } from './fixtures/feathers-client' import Vue from 'vue' import Vuex from 'vuex' diff --git a/test/make-find-mixin.test.ts b/test/make-find-mixin.test.ts index b9082d91..3b78cc87 100644 --- a/test/make-find-mixin.test.ts +++ b/test/make-find-mixin.test.ts @@ -1,6 +1,6 @@ import jsdom from 'jsdom-global' import { assert } from 'chai' -import feathersVuex, { FeathersVuex, models } from '../src/index' +import feathersVuex, { FeathersVuex } from '../src/index' import { feathersRestClient as feathersClient } from './fixtures/feathers-client' import makeFindMixin from '../src/make-find-mixin' import Vue from 'vue/dist/vue' From 243b043c3dafa20a9502f6bf0b1d18c065a57580 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 18:49:39 -0600 Subject: [PATCH 052/404] Allow clearing globalModels with public API --- src/service-module/global-models.ts | 12 ++++++++++++ test/service-module/model-base.test.ts | 7 ++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/service-module/global-models.ts b/src/service-module/global-models.ts index 9aea82fe..faba1d21 100644 --- a/src/service-module/global-models.ts +++ b/src/service-module/global-models.ts @@ -28,3 +28,15 @@ export function prepareAddModel(options: FeathersVuexOptions) { globalModels[serverAlias].byServicePath[Model.servicePath] = Model } } + +export function clearModels() { + Object.keys(globalModels).forEach(key => { + const serverAliasObj = globalModels[key] + + Object.keys(serverAliasObj).forEach(key => { + delete globalModels[key] + }) + + delete globalModels[key] + }) +} diff --git a/test/service-module/model-base.test.ts b/test/service-module/model-base.test.ts index 9c564a97..81cad14c 100644 --- a/test/service-module/model-base.test.ts +++ b/test/service-module/model-base.test.ts @@ -6,6 +6,7 @@ eslint import { assert } from 'chai' import Vue from 'vue' import Vuex from 'vuex' +import { clearModels } from '../../src/service-module/global-models' import { feathersRestClient as feathers, makeFeathersRestClient @@ -15,6 +16,10 @@ import feathersVuex from '../../src/index' Vue.use(Vuex) describe('makeModel / BaseModel', function() { + before(() => { + clearModels() + }) + it('properly sets up the BaseModel', function() { const alias = 'default' const { BaseModel } = feathersVuex(feathers, { serverAlias: alias }) @@ -29,7 +34,7 @@ describe('makeModel / BaseModel', function() { copiesById } = BaseModel - assert(name === 'FeathersVuexModel', 'name in place') + assert(name === 'BaseModel', 'name in place') // Monkey patched onto the Model class in `makeServicePlugin()` assert(!store, 'no store by default') From c7801b813384dca72db6e8b9d39353f9065d3cdb Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 18:50:12 -0600 Subject: [PATCH 053/404] Allow one BaseModel per serverAlias --- src/service-module/make-model.ts | 121 +++++++++++++++++-------------- 1 file changed, 66 insertions(+), 55 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 62c76116..1cf6d6a2 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -4,16 +4,32 @@ eslint @typescript-eslint/no-explicit-any: 0 */ import { FeathersVuexOptions } from './types' -import { globalModels } from './global-models' -import Vue from 'vue' +import { globalModels, prepareAddModel } from './global-models' import { mergeWithAccessors } from '../utils' +import { get as _get } from 'lodash' + +interface BaseConstructor { + store: {} +} +interface BaseModelConstructorOptions { + isClone?: boolean +} /** * * @param options */ export default function makeModel(options: FeathersVuexOptions) { - abstract class FeathersVuexModel { + const addModel = prepareAddModel(options) + const { serverAlias } = options + + // If this serverAlias already has a BaseModel, nreturn it + const ExistingBaseModel = _get(globalModels, `[${serverAlias}].BaseModel`) + if (ExistingBaseModel) { + return ExistingBaseModel + } + + abstract class BaseModel { // Monkey patched onto the Model class in `makeServicePlugin()` public static store: Record public static namespace: string @@ -29,45 +45,45 @@ export default function makeModel(options: FeathersVuexOptions) { protected isClone: boolean public data: Record - public constructor(data) { + public constructor(data, options: BaseModelConstructorOptions = {}) { + if (options.isClone) { + Object.defineProperty(this, 'isClone', { + value: true, + enumerable: false, + writable: false + }) + } + mergeWithAccessors(this, data) } public static getId(record: Record): string { - return record[FeathersVuexModel.idField] + return record[BaseModel.idField] } public static find(params) { - return FeathersVuexModel.store.dispatch( - `${FeathersVuexModel.namespace}/find`, - params - ) + return BaseModel.store.dispatch(`${BaseModel.namespace}/find`, params) } public static findInStore(params) { - return FeathersVuexModel.store.getters[ - `${FeathersVuexModel.namespace}/find` - ](params) + return BaseModel.store.getters[`${BaseModel.namespace}/find`](params) } public static get(id, params) { - const { store } = FeathersVuexModel + const { store } = BaseModel if (params) { - return store.dispatch(`${FeathersVuexModel.namespace}/get`, [ - id, - params - ]) + return store.dispatch(`${BaseModel.namespace}/get`, [id, params]) } else { - return store.dispatch(`${FeathersVuexModel.namespace}/get`, id) + return store.dispatch(`${BaseModel.namespace}/get`, id) } } public static getFromStore(id, params) { - const { store } = FeathersVuexModel + const { store } = BaseModel if (params) { - return store.getters[`${FeathersVuexModel.namespace}/get`]([id, params]) + return store.getters[`${BaseModel.namespace}/get`]([id, params]) } else { - return store.getters[`${FeathersVuexModel.namespace}/get`](id) + return store.getters[`${BaseModel.namespace}/get`](id) } } @@ -78,16 +94,17 @@ export default function makeModel(options: FeathersVuexOptions) { if (this.isClone) { throw new Error('You cannot clone a copy') } - const id = this[FeathersVuexModel.idField] - this._clone(id) + const id = this[BaseModel.idField] + return this._clone(id) } private _clone(id) { - const { store, copiesById } = FeathersVuexModel - store.commit(`${FeathersVuexModel.namespace}/createCopy`, id) + const { store, copiesById, namespace } = BaseModel + // const { store } = this.constructor + store.commit(`${namespace}/createCopy`, id) - if (store.state[FeathersVuexModel.namespace].keepCopiesInStore) { - return store.getters[`${FeathersVuexModel.namespace}/getCopyById`](id) + if (store.state[namespace].keepCopiesInStore) { + return store.getters[`${namespace}/getCopyById`](id) } else { return copiesById[id] } @@ -98,11 +115,8 @@ export default function makeModel(options: FeathersVuexOptions) { */ public reset() { if (this.isClone) { - const id = this[FeathersVuexModel.idField] - FeathersVuexModel.store.commit( - `${FeathersVuexModel.namespace}/resetCopy`, - id - ) + const id = this[BaseModel.idField] + BaseModel.store.commit(`${BaseModel.namespace}/resetCopy`, id) } else { throw new Error('You cannot reset a non-copy') } @@ -113,11 +127,8 @@ export default function makeModel(options: FeathersVuexOptions) { */ public commit() { if (this.isClone) { - const id = this[FeathersVuexModel.idField] - FeathersVuexModel.store.commit( - `${FeathersVuexModel.namespace}/commitCopy`, - id - ) + const id = this[BaseModel.idField] + BaseModel.store.commit(`${BaseModel.namespace}/commitCopy`, id) return this._clone(id) } else { @@ -141,15 +152,12 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public create(params) { - const { store } = FeathersVuexModel + const { store } = BaseModel const data = Object.assign({}, this) if (data[options.idField] === null) { delete data[options.idField] } - return store.dispatch(`${FeathersVuexModel.namespace}/create`, [ - data, - params - ]) + return store.dispatch(`${BaseModel.namespace}/create`, [data, params]) } /** @@ -165,10 +173,11 @@ export default function makeModel(options: FeathersVuexOptions) { ) return Promise.reject(error) } - return FeathersVuexModel.store.dispatch( - `${FeathersVuexModel.namespace}/patch`, - [this[options.idField], this, params] - ) + return BaseModel.store.dispatch(`${BaseModel.namespace}/patch`, [ + this[options.idField], + this, + params + ]) } /** @@ -184,10 +193,11 @@ export default function makeModel(options: FeathersVuexOptions) { ) return Promise.reject(error) } - return FeathersVuexModel.store.dispatch( - `${FeathersVuexModel.namespace}/update`, - [this[options.idField], this, params] - ) + return BaseModel.store.dispatch(`${BaseModel.namespace}/update`, [ + this[options.idField], + this, + params + ]) } /** @@ -195,11 +205,12 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public remove(params) { - return FeathersVuexModel.store.dispatch( - `${FeathersVuexModel.namespace}/remove`, - [this[options.idField], params] - ) + return BaseModel.store.dispatch(`${BaseModel.namespace}/remove`, [ + this[options.idField], + params + ]) } } - return FeathersVuexModel + addModel(BaseModel) + return BaseModel } From ba82d87b1afbb8d93bc21b9ef6df9b9e147c04aa Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 18:50:46 -0600 Subject: [PATCH 054/404] Monkey patch the BaseModel and the passed-in one --- src/service-module/make-service-plugin.ts | 24 +++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index ec06e24e..52a6d2ed 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -5,7 +5,7 @@ eslint */ import { FeathersVuexOptions, MakeServicePluginOptions } from './types' import makeServiceModule from './make-service-module' -import { prepareAddModel } from './global-models' +import { globalModels, prepareAddModel } from './global-models' import { makeNamespace, getServicePath } from '../utils' const defaults = { @@ -28,7 +28,8 @@ export default function prepareMakeServicePlugin( const addModel = prepareAddModel(globalOptions) /** * (1) Make a Vuex plugin for the provided service. - * (2) Attach the vuex store to the Model. + * (2a) Attach the vuex store to the BaseModel. + * (2b) If the Model does not extend the BaseModel, monkey patch it, too * (3) Setup real-time events */ return function makeServicePlugin(config: MakeServicePluginOptions) { @@ -56,8 +57,23 @@ export default function prepareMakeServicePlugin( const module = makeServiceModule(service, options) store.registerModule(options.namespace, module) - // (2^) Monkey patch the Model and add to globalModels - Object.assign(Model, { store, namespace: options.namespace, servicePath }) + // (2a^) Monkey patch the BaseModel in globalModels + const { BaseModel } = globalModels[options.serverAlias] + if (!BaseModel.store) { + Object.assign(BaseModel, { + store, + namespace: options.namespace, + servicePath + }) + } + // (2b^) Monkey patch the Model(s) and add to globalModels + if (!(Model.prototype instanceof BaseModel)) { + Object.assign(Model, { + store, + namespace: options.namespace, + servicePath + }) + } addModel(Model) // (3^) Setup real-time events From 449346c169c231874f89010034e9b6d1d0489660 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 18:53:22 -0600 Subject: [PATCH 055/404] Add nameStyle and preferUpdate to interface --- src/service-module/types.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/service-module/types.ts b/src/service-module/types.ts index 0ea37143..3d2134e6 100644 --- a/src/service-module/types.ts +++ b/src/service-module/types.ts @@ -26,7 +26,9 @@ export interface MakeServicePluginOptions { diffOnPatch?: boolean enableEvents?: boolean idField?: string + nameStyle?: string namespace?: string + preferUpdate?: boolean servicePath?: string state?: {} getters?: {} From d141505fe9037a5687efd658be7dcac96821c9dc Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 18:53:42 -0600 Subject: [PATCH 056/404] Use assign for Vue objects in mergeWithAccessors --- src/utils.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/utils.ts b/src/utils.ts index f64e9a47..83bff8c6 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -266,6 +266,12 @@ export function makeNamespace(namespace, servicePath, nameStyle) { return namespace || nameStyles[nameStyle](servicePath) } +/** + * Gets the service path or name from the service. The modelname is provided + * to allow easier discovery if there's a problem. + * @param service + * @param modelName + */ export function getServicePath(service: any, modelName: string) { if (!service.name) { throw new Error( @@ -305,7 +311,7 @@ export function mergeWithAccessors(dest, source) { const desc = Object.getOwnPropertyDescriptor(source, key) // If we're dealing with a Vue Observable, just assign the values. - if (destIsVueObservable) { + if (destIsVueObservable || sourceIsVueObservable) { dest[key] = source[key] return } From d4ab733b84b310ca0bc2eeb4c4e5e3b3b20b4499 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 19:26:30 -0600 Subject: [PATCH 057/404] Clear models before each test --- test/service-module/make-service-plugin.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index d1aa901d..52434c4b 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -6,6 +6,7 @@ eslint import { assert } from 'chai' import Vue from 'vue' import Vuex from 'vuex' +import { clearModels } from '../../src/service-module/global-models' import { feathersRestClient as feathers } from '../../test/fixtures/feathers-client' import feathersVuex from '../../src/index' import _pick from 'lodash.pick' @@ -13,6 +14,10 @@ import _pick from 'lodash.pick' Vue.use(Vuex) describe('makeServicePlugin', function() { + beforeEach(() => { + clearModels() + }) + it('registers the vuex module with options', function() { const serverAlias = 'default' const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { From 29a8ae3ac8b67e19fde8fe146e849711138dffc6 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 19:26:48 -0600 Subject: [PATCH 058/404] Move types to separate file --- .../service-module.actions.test.ts | 29 +------------- test/service-module/types.ts | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 28 deletions(-) create mode 100644 test/service-module/types.ts diff --git a/test/service-module/service-module.actions.test.ts b/test/service-module/service-module.actions.test.ts index e08d2819..219302ab 100644 --- a/test/service-module/service-module.actions.test.ts +++ b/test/service-module/service-module.actions.test.ts @@ -3,40 +3,13 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ +import { ServiceState } from './types' import { assert } from 'chai' import feathersVuex from '../../src/index' import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' import Vuex, { mapActions } from 'vuex' import memory from 'feathers-memory' -interface PaginationState { - ids: any - limit: number - skip: number - ip: number - total: number -} -interface ServiceState { - options: {} - ids: string[] - errorOnFind: any - errorOnGet: any - errorOnCreate: any - errorOnPatch: any - errorOnUpdate: any - errorOnRemove: any - isFindPending: boolean - isGetPending: boolean - isCreatePending: boolean - isPatchPending: boolean - isUpdatePending: boolean - isRemovePending: boolean - idField: string - keyedById: {} - pagination?: { - default: PaginationState - } -} interface RootState { 'my-todos': ServiceState 'my-tasks': ServiceState diff --git a/test/service-module/types.ts b/test/service-module/types.ts new file mode 100644 index 00000000..84e102e0 --- /dev/null +++ b/test/service-module/types.ts @@ -0,0 +1,38 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +// TODO: use this in the src +export interface ServiceState { + options: {} + ids: string[] + autoRemove: boolean + errorOnFind: any + errorOnGet: any + errorOnCreate: any + errorOnPatch: any + errorOnUpdate: any + errorOnRemove: any + isFindPending: boolean + isGetPending: boolean + isCreatePending: boolean + isPatchPending: boolean + isUpdatePending: boolean + isRemovePending: boolean + idField: string + keyedById: {} + namespace: string + nameStyle: string // Should be enum of 'short' or 'path' + pagination?: { + default: PaginationState + } +} + +export interface PaginationState { + ids: any + limit: number + skip: number + ip: number + total: number +} From 388a495d60f3a98444ed833150d63915fe2b5fa8 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 19:27:06 -0600 Subject: [PATCH 059/404] Fix auth test after clearing models --- test/utils.test.ts | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/test/utils.test.ts b/test/utils.test.ts index 44ebe61b..c21fa024 100644 --- a/test/utils.test.ts +++ b/test/utils.test.ts @@ -13,29 +13,37 @@ import Vuex from 'vuex' Vue.use(Vuex) -const { makeServicePlugin, makeAuthPlugin, BaseModel } = feathersVuex( - feathersClient, - { serverAlias: 'utils' } -) - -class User extends BaseModel { - public static test: boolean = true -} - interface RootState { auth: AuthState } describe('Utils', function() { + before(function() { + const { makeServicePlugin, makeAuthPlugin, BaseModel } = feathersVuex( + feathersClient, + { serverAlias: 'utils' } + ) + + class User extends BaseModel { + public static test: boolean = true + } + + Object.assign(this, { + makeServicePlugin, + makeAuthPlugin, + BaseModel, + User + }) + }) it('properly populates auth', function() { const store = new Vuex.Store({ plugins: [ - makeServicePlugin({ - Model: User, + this.makeServicePlugin({ + Model: this.User, servicePath: 'users', service: feathersClient.service('users') }), - makeAuthPlugin({}) + this.makeAuthPlugin({}) ] }) const accessToken = From fd44c023a7f88312d9eba0caace3f9e3c6b978ef Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 19:27:22 -0600 Subject: [PATCH 060/404] Begin switch to .ts for largest test file: service-module.test.js --- ...-module.test.js => service-module.test.ts} | 779 ++++++++++++------ 1 file changed, 510 insertions(+), 269 deletions(-) rename test/service-module/{service-module.test.js => service-module.test.ts} (62%) diff --git a/test/service-module/service-module.test.js b/test/service-module/service-module.test.ts similarity index 62% rename from test/service-module/service-module.test.js rename to test/service-module/service-module.test.ts index 64e9da25..5390a12a 100644 --- a/test/service-module/service-module.test.js +++ b/test/service-module/service-module.test.ts @@ -1,5 +1,13 @@ -import assert from 'chai/chai' -import setupVuexService from '~/src/service-module/service-module' +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { ServiceState } from './types' +import { assert } from 'chai/chai' +import feathersVuex, { models } from '../../src/index' +import { clearModels } from '../../src/service-module/global-models' + import { makeFeathersRestClient, feathersRestClient as feathersClient, @@ -10,44 +18,111 @@ import memory from 'feathers-memory' import { makeTodos } from '../fixtures/todos' import Vuex from 'vuex' -const globalModels = {} -const service = setupVuexService(feathersClient, {}, globalModels) +interface Options { + idField: string +} +interface TodoState extends ServiceState { + test: any + test2: { + test: boolean + } + isTrue: boolean +} +interface RootState { + todos: TodoState + tasks: ServiceState + tests: ServiceState + blah: ServiceState + things: ServiceState +} + +const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'service-module' +}) + +class ServiceTodo extends BaseModel { + public id + public description: string +} +class HotspotMedia extends BaseModel { + public id + public description: string +} +class Media extends BaseModel { + public id + public description: string +} +class Person extends BaseModel { + public static test: boolean = true +} +class Item extends BaseModel { + public static test: boolean = true +} +class Task extends BaseModel { + public static test: boolean = true +} +class Car extends BaseModel { + public static test: boolean = true +} +class Group extends BaseModel { + public static test: boolean = true +} +class Test extends BaseModel { + public static test: boolean = true +} +class Thing extends BaseModel { + public static test: boolean = true +} + +describe.skip('Service Module', () => { + before(() => { + clearModels() + }) -describe('Service Module', () => { it('registers a vuex plugin and Model for the service', () => { - const serviceName = 'todos' + const serviceName = 'service-todos' const feathersService = feathersClient.service(serviceName) - const store = new Vuex.Store({ - plugins: [service(serviceName)] + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: ServiceTodo, + service: feathersClient.service(serviceName) + }) + ] }) assert( - globalModels.hasOwnProperty('Todo'), - 'the Model was added to the globalModels' + models['service-module'].hasOwnProperty('ServiceTodo'), + 'the Model was added to the models' ) assert( - feathersService.FeathersVuexModel === globalModels.Todo, + feathersService.FeathersVuexModel === ServiceTodo, 'the Model is also found at service.FeathersVuexModel' ) - const todo = new globalModels.Todo({ - description: 'Do the dishes', - isComplete: false - }) - assert(todo instanceof globalModels.Todo, 'Model can be instantiated.') + // const serviceTodo = new ServiceTodo({ + // description: 'Do the dishes', + // isComplete: false + // }) + // assert(serviceTodo instanceof ServiceTodo, 'Model can be instantiated.') + // assert(serviceTodo instanceof BaseModel, 'Model can be instantiated.') assert(store.state[serviceName]) }) describe('Models', function() { beforeEach(function() { - const serviceName = 'todos' - const store = new Vuex.Store({ - plugins: [service(serviceName)] + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: ServiceTodo, + service: feathersClient.service('service-todos') + }) + ] }) assert(store) assert( - globalModels.hasOwnProperty('Todo'), - 'the Model was added to the globalModels' + models['service-module'].hasOwnProperty('ServiceTodo'), + 'the Model was added to the models' ) const owners = (this.owners = [ { id: 1, name: 'Marshall' }, @@ -60,113 +135,128 @@ describe('Service Module', () => { isComplete: false, owners } - store.commit('todos/addItem', data) + store.commit('service-todos/addItem', data) - const todo = store.state.todos.keyedById[1] + const serviceTodo = store.state['service-todos'].keyedById[1] - this.todo = todo - this.todoClone = todo.clone() + this.serviceTodo = serviceTodo }) it('allows creating model clones', function() { - const { todoClone } = this + const serviceTodoClone = this.serviceTodo.clone() - assert(todoClone.isClone, 'created a todo clone with isClone attribute') assert( - todoClone instanceof globalModels.Todo, + serviceTodoClone.isClone, + 'created a todo clone with isClone attribute' + ) + assert( + serviceTodoClone instanceof ServiceTodo, 'the copy is an instance of the same class' ) }) it('allows modifying clones without affecting the original', function() { - const { todo, todoClone } = this + const { serviceTodo } = this + const serviceTodoClone = serviceTodo.clone() - todoClone.description = 'Do something else' + serviceTodoClone.description = 'Do something else' assert( - todo.description === 'Do the dishes', + serviceTodo.description === 'Do the dishes', 'the original todo remained intact' ) }) it('allows commiting changes back to the original in the store', function() { - const { todo, todoClone } = this + const { module, moduleClone } = this - todoClone.description = 'Do something else' - todoClone.commit() + moduleClone.description = 'Do something else' + moduleClone.commit() assert( - todo.description === 'Do something else', + module.description === 'Do something else', 'the original todo was updated' ) }) it('performs a shallow merge when commiting back to the original record', function() { - const { todo, todoClone, owners } = this + const { module, moduleClone, owners } = this - todoClone.owners = [ + moduleClone.owners = [ { id: 1, name: 'Marshall' }, { id: 2, name: 'Mariah' } ] - assert.deepEqual(todo.owners, owners, 'original todo remained unchanged') + assert.deepEqual( + module.owners, + owners, + 'original todo remained unchanged' + ) - todoClone.commit() + moduleClone.commit() assert.deepEqual( - todo.owners, + module.owners, [owners[0], owners[1]], 'ownerIds were updated properly' ) }) it(`changes the original record if you don't use the return value of commit()`, function() { - const { todo, todoClone, owners } = this + const { module, moduleClone, owners } = this - assert.deepEqual(todo.owners, owners, 'original todo remained unchanged') + assert.deepEqual( + module.owners, + owners, + 'original todo remained unchanged' + ) - todoClone.commit() - todoClone.owners[0].name = 'Ted' + moduleClone.commit() + moduleClone.owners[0].name = 'Ted' assert.deepEqual( - todo.owners[0].name, + module.owners[0].name, 'Ted', 'nested object in original todo was changed' ) }) it(`doesn't change the original record if you use modify return value of a commit`, function() { - let { todo, todoClone, owners } = this + let { module, moduleClone, owners } = this - assert.deepEqual(todo.owners, owners, 'original todo remained unchanged') + assert.deepEqual( + module.owners, + owners, + 'original todo remained unchanged' + ) - todoClone = todoClone.commit() - todoClone.owners[0].name = 'Ted' + moduleClone = moduleClone.commit() + moduleClone.owners[0].name = 'Ted' assert.deepEqual( - todo.owners[0].name, + module.owners[0].name, 'Marshall', 'nested object in original todo was NOT changed' ) }) it('allows reseting copy changes back to match the original', function() { - const { todo, todoClone } = this + const { module, moduleClone } = this - todoClone.description = 'Do something else' - todoClone.reset() + moduleClone.description = 'Do something else' + moduleClone.reset() assert( - todo.description === 'Do the dishes', + module.description === 'Do the dishes', 'the original todo was untouched' ) assert( - todoClone.description === 'Do the dishes', + moduleClone.description === 'Do the dishes', 'the clone was reset to match the original' ) }) it('adds additional properties to model instances when more data arrives for the same id', function() { - const { todo, owners } = this + const { module, owners } = this const newData = { id: 1, description: 'Do the dishes', @@ -174,51 +264,51 @@ describe('Service Module', () => { owners, test: true } - const newTodo = new todo.constructor(newData) + const newTodo = new module.constructor(newData) - assert(newTodo === todo, 'the records are the same') + assert(newTodo === module, 'the records are the same') assert(newTodo.test === true, 'the new attribute was added') assert( - todo.test === true, + module.test === true, 'the new attribute was also added to the original' ) }) it('ignores when new data with matching id has fewer props than current record', function() { - const { todo, owners } = this + const { module, owners } = this const newData = { id: 1, owners } - const newTodo = new todo.constructor(newData) + const newTodo = new module.constructor(newData) - assert(newTodo === todo, 'the records are the same') + assert(newTodo === module, 'the records are the same') assert( - todo.description === 'Do the dishes', + module.description === 'Do the dishes', 'the existing attributes remained in place' ) assert( - todo.isComplete === false, + module.isComplete === false, 'the existing attributes remained in place' ) }) it('updates the new record when non-null, non-undefined values do not match', function() { - const { todo, owners } = this + const { module, owners } = this const newData = { id: 1, description: 'Do the mopping', isComplete: true, owners } - const newTodo = new todo.constructor(newData) + const newTodo = new module.constructor(newData) - assert(newTodo === todo, 'the records are the same') + assert(newTodo === module, 'the records are the same') assert( - todo.description === 'Do the mopping', + module.description === 'Do the mopping', 'non-matching string was updated' ) - assert(todo.isComplete === true, 'non-matching boolean was updated') + assert(module.isComplete === true, 'non-matching boolean was updated') }) }) @@ -229,80 +319,92 @@ describe('Service Module', () => { description: '', isComplete: false }) - this.store = new Vuex.Store({ + + // TODO: Do Something with this! + const instanceDefaultsForPerson = { + firstName: '', + lastName: '', + location: { + coordinates: [-111.549668, 39.014] + }, + get fullName() { + return `${this.firstName} ${this.lastName}` + }, + todos({ store }) { + console.log(Object.keys(store)) + } + } + const instanceDefaultsForCars = { + keepCopiesInStore: true, + instanceDefaults: taskDefaults + } + const instanceDefaultsForGroups = function instanceDefaults() { + return { + name: '', + get todos() { + return models.Todo.findInStore({ query: {} }).data + } + } + } + this.store = new Vuex.Store({ plugins: [ - service('todos'), - service('people', { - instanceDefaults: { - firstName: '', - lastName: '', - location: { - coordinates: [-111.549668, 39.014] - }, - get fullName() { - return `${this.firstName} ${this.lastName}` - }, - todos({ store }) { - console.log(Object.keys(store)) - } - } + makeServicePlugin({ + Model: ServiceTodo, + service: feathersClient.service('service-todos') }), - service('tasks', { - keepCopiesInStore: true, - instanceDefaults: taskDefaults + makeServicePlugin({ + Model: Person, + service: feathersClient.service('people') }), - service('groups', { - instanceDefaults(data, { store, Model, Models }) { - return { - name: '', - get todos() { - return Models.Todo.findInStore({ query: {} }).data - } - } - } + makeServicePlugin({ + Model: Car, + service: feathersClient.service('cars') + }), + makeServicePlugin({ + Model: Group, + service: feathersClient.service('groups') }) ] }) - this.Todo = globalModels.Todo - this.Task = globalModels.Task - this.Person = globalModels.Person - this.Group = globalModels.Group + this.Todo = ServiceTodo + this.Task = models.Task + this.Person = models.Person + this.Group = models.Group }) // store.commit('todos/addItem', data) it('models default to an empty object', function() { const { Todo } = this - const todo = new Todo() + const module = new Todo() - assert.deepEqual(todo, {}, 'default model is an empty object') + assert.deepEqual(module, {}, 'default model is an empty object') }) - it('stores clones in Model.copiesById by default', function() { - const { Todo } = this - const todo = new Todo({ id: 1, description: 'Do something' }) + // it('stores clones in Model.copiesById by default', function() { + // const module = new ServiceTodo({ id: 1, description: 'Do something' }) - assert.deepEqual( - Todo.copiesById, - {}, - 'Model.copiesById should start out empty' - ) + // assert.deepEqual( + // ServiceTodo.copiesById, + // {}, + // 'Model.copiesById should start out empty' + // ) - const todoClone = todo.clone() - assert( - Todo.copiesById[1], - 'should have a copy stored on Model.copiesById' - ) + // const moduleClone = module.clone() + // assert( + // ServiceTodo.copiesById[1], + // 'should have a copy stored on Model.copiesById' + // ) - todoClone.description = 'Do something else' - todoClone.commit() + // // moduleClone.description = 'Do something else' + // // moduleClone.commit() - assert.equal( - todo.description, - 'Do something else', - 'the original should have been updated' - ) - }) + // assert.equal( + // module.description, + // 'Do something else', + // 'the original should have been updated' + // ) + // }) it('allows customizing the default values for a model', function() { const { Task, taskDefaults } = this @@ -370,7 +472,7 @@ describe('Service Module', () => { diffOnPatch: false, skipRequestIfExists: false, getters: {}, - globalModels, + models, idField: 'id', instanceDefaults: taskDefaults, keepCopiesInStore: true, @@ -394,18 +496,26 @@ describe('Service Module', () => { describe('Models - Methods', function() { beforeEach(function() { - this.store = new Vuex.Store({ + this.store = new Vuex.Store({ strict: true, plugins: [ - service('tasks', { + makeServicePlugin({ + Model: Task, + service: feathersClient.service('tasks'), preferUpdate: true }), - service('todos'), - service('items') + makeServicePlugin({ + Model: ServiceTodo, + service: feathersClient.service('service-todos') + }), + makeServicePlugin({ + Model: Item, + service: feathersClient.service('items') + }) ] }) - this.Todo = globalModels.Todo - this.Task = globalModels.Task + this.Todo = ServiceTodo + this.Task = models.Task }) it('Model.find', function() { @@ -434,9 +544,9 @@ describe('Service Module', () => { it('instance.save calls create with correct arguments', function() { const { Todo } = this - const todo = new Todo({ test: true }) + const module = new Todo({ test: true }) - Object.defineProperty(todo, 'create', { + Object.defineProperty(module, 'create', { value(params) { assert(arguments.length === 1, 'should have only called with params') assert( @@ -446,15 +556,15 @@ describe('Service Module', () => { } }) - todo.save() + module.save() }) it('instance.save passes params to create', function() { const { Todo } = this - const todo = new Todo({ test: true }) + const module = new Todo({ test: true }) let called = false - Object.defineProperty(todo, 'create', { + Object.defineProperty(module, 'create', { value(params) { assert(arguments.length === 1, 'should have only called with params') assert(params.test, 'should have received params') @@ -462,16 +572,16 @@ describe('Service Module', () => { } }) - todo.save({ test: true }) + module.save({ test: true }) assert(called, 'create should have been called') }) it('instance.save passes params to patch', function() { const { Todo } = this - const todo = new Todo({ id: 1, test: true }) + const module = new Todo({ id: 1, test: true }) let called = false - Object.defineProperty(todo, 'patch', { + Object.defineProperty(module, 'patch', { value(params) { assert(arguments.length === 1, 'should have only called with params') assert(params.test, 'should have received params') @@ -479,7 +589,7 @@ describe('Service Module', () => { } }) - todo.save({ test: true }) + module.save({ test: true }) assert(called, 'patch should have been called') }) @@ -520,17 +630,25 @@ describe('Service Module', () => { describe('Models - modelName', function() { beforeEach(function() { - this.store = new Vuex.Store({ + this.store = new Vuex.Store({ strict: true, plugins: [ - service('media'), - service('hotspot-media', { - modelName: 'HotspotMedia' + makeServicePlugin({ + Model: HotspotMedia, + service: feathersClient.service('hotspot-media') + }), + makeServicePlugin({ + Model: Media, + service: feathersClient.service('media') + }), + makeServicePlugin({ + Model: HotspotMedia, + service: feathersClient.service('hotspot-media') }) ] }) - this.Medium = globalModels.Medium - this.HotspotMedia = globalModels.HotspotMedia + this.Medium = models.Medium + this.HotspotMedia = models.HotspotMedia }) it('allows passing a custom Model name', function() { @@ -541,41 +659,43 @@ describe('Service Module', () => { describe('Models - Dates', function() { beforeEach(function() { - this.store = new Vuex.Store({ + const instanceDefaults = { + id: null, + description: '', + isComplete: false, + createdAt: Date + } + this.store = new Vuex.Store({ strict: true, plugins: [ - service('todos', { - instanceDefaults: { - id: null, - description: '', - isComplete: false, - createdAt: Date - } + makeServicePlugin({ + Model: ServiceTodo, + service: feathersClient.service('service-todos') }) ] }) - this.Todo = globalModels.Todo + this.Todo = ServiceTodo }) it('converts keys that contain the Date constructor into date instances', function() { const { Todo } = this const createdAt = '2018-05-01T04:42:24.136Z' - const todo = new Todo({ + const module = new Todo({ description: 'Go on a date.', isComplete: true, createdAt }) assert( - typeof todo.createdAt === 'object', - 'todo.createdAt is an instance of object' + typeof module.createdAt === 'object', + 'module.createdAt is an instance of object' ) assert( - todo.createdAt.constructor.name === 'Date', - 'todo.createdAt is an instance of date' + module.createdAt.constructor.name === 'Date', + 'module.createdAt is an instance of date' ) assert( - todo.createdAt.toString() === new Date(createdAt).toString(), + module.createdAt.toString() === new Date(createdAt).toString(), 'the correct date was used' ) }) @@ -583,45 +703,57 @@ describe('Service Module', () => { describe('Models - Relationships', function() { beforeEach(function() { - this.store = new Vuex.Store({ - strict: true, - plugins: [ - service('tasks', { - instanceDefaults: { - id: null, + class Task extends BaseModel { + public static instanceDefaults: { + id: null + description: '' + isComplete: false + } + } + class ServiceTodo extends BaseModel { + public static instanceDefaults(data) { + const priority = data.priority || 'normal' + const defaultsByPriority = { + normal: { description: '', - isComplete: false + isComplete: false, + task: 'Task', + item: 'Item', + priority: '' + }, + high: { + isHighPriority: true, + priority: '' } - }), - service('todos', { - instanceDefaults(data) { - const priority = data.priority || 'normal' - const defaultsByPriority = { - normal: { - description: '', - isComplete: false, - task: 'Task', - item: 'Item', - priority: '' - }, - high: { - isHighPriority: true, - priority: '' - } - } - return defaultsByPriority[priority] + } + return defaultsByPriority[priority] + } + } + class Item extends BaseModel { + public static instanceDefaults({ Models }) { + return { + test: false, + todo: 'Todo', + get todos() { + return Models.Todo.findInStore({ query: {} }).data } + } + } + } + this.store = new Vuex.Store({ + strict: true, + plugins: [ + makeServicePlugin({ + Model: Task, + service: feathersClient.service('tasks') }), - service('items', { - instanceDefaults(data, { store, Model, Models }) { - return { - test: false, - todo: 'Todo', - get todos() { - return Models.Todo.findInStore({ query: {} }).data - } - } - }, + makeServicePlugin({ + Model: ServiceTodo, + service: feathersClient.service('service-todos') + }), + makeServicePlugin({ + Model: Item, + service: feathersClient.service('items'), mutations: { toggleTestBoolean(state, item) { item.test = !item.test @@ -630,18 +762,21 @@ describe('Service Module', () => { }) ] }) - this.Todo = globalModels.Todo - this.Task = globalModels.Task - this.Item = globalModels.Item + this.Todo = ServiceTodo + this.Task = models.Task + this.Item = models.Item }) it('can setup relationships through es5 getters in instanceDefaults', function() { const { Item, Todo } = this - const todo = new Todo({ id: 5, description: 'hey' }) + const module = new Todo({ id: 5, description: 'hey' }) const item = new Item({}) assert(Array.isArray(item.todos), 'Received an array of todos') - assert(item.todos[0] === todo, 'The todo was returned through the getter') + assert( + item.todos[0] === module, + 'The todo was returned through the getter' + ) }) it('can have different instanceDefaults based on new instance data', function() { @@ -666,7 +801,7 @@ describe('Service Module', () => { it('converts keys that match Model names into Model instances', function() { const { Todo, store } = this - const todo = new Todo({ + const module = new Todo({ task: { description: 'test', isComplete: true @@ -674,7 +809,7 @@ describe('Service Module', () => { }) assert( - todo.task.constructor.className === 'Task', + module.task.constructor.className === 'Task', 'task is an instance of Task' ) assert.deepEqual( @@ -687,7 +822,7 @@ describe('Service Module', () => { it('adds model instances containing an id to the store', function() { const { Todo, store } = this - const todo = new Todo({ + const module = new Todo({ task: { id: 1, description: 'test', @@ -697,7 +832,7 @@ describe('Service Module', () => { assert.deepEqual( store.state.tasks.keyedById[1], - todo.task, + module.task, 'task was added to the store' ) }) @@ -705,7 +840,7 @@ describe('Service Module', () => { it('works with multiple keys that match Model names', function() { const { Todo, store } = this - const todo = new Todo({ + const module = new Todo({ task: { id: 1, description: 'test', @@ -719,12 +854,12 @@ describe('Service Module', () => { assert.deepEqual( store.state.tasks.keyedById[1], - todo.task, + module.task, 'task was added to the store' ) assert.deepEqual( store.state.items.keyedById[2], - todo.item, + module.item, 'item was added to the store' ) }) @@ -732,7 +867,7 @@ describe('Service Module', () => { it('handles nested relationships', function() { const { Todo } = this - const todo = new Todo({ + const module = new Todo({ task: { id: 1, description: 'test', @@ -748,7 +883,7 @@ describe('Service Module', () => { }) assert( - todo.item.todo.constructor.className === 'Todo', + module.item.module.constructor.className === 'Todo', 'the nested todo is an instance of Todo' ) }) @@ -756,7 +891,7 @@ describe('Service Module', () => { it('handles recursive nested relationships', function() { const { Todo, store } = this - const todo = new Todo({ + const module = new Todo({ id: 1, description: 'todo description', item: { @@ -771,22 +906,22 @@ describe('Service Module', () => { assert.deepEqual( store.state.todos.keyedById[1], - todo, + module, 'todo was added to the store' ) assert.deepEqual( store.state.items.keyedById[2], - todo.item, + module.item, 'item was added to the store' ) - assert(todo.item, 'todo still has an item') - assert(todo.item.todo, 'todo still nested in itself') + assert(module.item, 'todo still has an item') + assert(module.item.module, 'todo still nested in itself') }) it('updates related data', function() { const { Todo, store } = this - const todo = new Todo({ + const module = new Todo({ id: 'todo-1', description: 'todo description', item: { @@ -803,12 +938,12 @@ describe('Service Module', () => { const storedItem = store.state.items.keyedById['item-2'] store.commit('items/toggleTestBoolean', storedItem) - // todo.item.test = false + // module.item.test = false assert.equal( - todo.item.test, + module.item.test, false, - 'the nested todo.item.test should be false' + 'the nested module.item.test should be false' ) assert.equal( storedTodo.item.test, @@ -844,12 +979,12 @@ describe('Service Module', () => { assert.equal( todo1.item.test, true, - 'the nested todo.item.test should be true' + 'the nested module.item.test should be true' ) assert.equal( todo2.item.test, true, - 'the nested todo.item.test should be true' + 'the nested module.item.test should be true' ) assert.equal( storedTodo.item.test, @@ -912,8 +1047,20 @@ describe('Service Module', () => { describe('Setting Up', () => { it('service stores have global defaults', () => { - const store = new Vuex.Store({ - plugins: [service('tasks'), service('/v2/todos')] + class Todo extends BaseModel { + public static test: boolean = true + } + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Task, + service: feathersClient.service('tasks') + }), + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('/v2/todos') + }) + ] }) const { state } = store @@ -924,8 +1071,14 @@ describe('Service Module', () => { it('can customize the idField for each service', function() { const idField = '_id' - const store = new Vuex.Store({ - plugins: [service('tests', { idField })] + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + idField, + Model: Test, + service: feathersClient.service('tests') + }) + ] }) assert( @@ -936,8 +1089,13 @@ describe('Service Module', () => { it('allows enabling autoRemove', function() { const autoRemove = true - const store = new Vuex.Store({ - plugins: [service('tests', { autoRemove })] + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Test, + service: feathersClient.service('tests') + }) + ] }) assert( @@ -949,8 +1107,14 @@ describe('Service Module', () => { it('can switch to path name as namespace', () => { const nameStyle = 'path' const serviceName = '/v1/tests' - const store = new Vuex.Store({ - plugins: [service(serviceName, { nameStyle })] + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Test, + service: feathersClient.service(serviceName), + nameStyle + }) + ] }) const namespace = stripSlashes(serviceName) @@ -962,8 +1126,14 @@ describe('Service Module', () => { it('can explicitly provide a namespace', () => { const namespace = 'blah' - const store = new Vuex.Store({ - plugins: [service('/v1/tests', { namespace })] + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Test, + service: feathersClient.service('/v1/tests'), + namespace + }) + ] }) assert(store.state.blah, 'the namespace option was used as the namespace') }) @@ -971,8 +1141,15 @@ describe('Service Module', () => { it('prioritizes the explicit namespace', () => { const namespace = 'blah' const nameStyle = 'path' - const store = new Vuex.Store({ - plugins: [service('/v1/tests', { namespace, nameStyle })] + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Test, + service: feathersClient.service('/v1/tests'), + namespace, + nameStyle + }) + ] }) assert(store.state.blah, 'the namespace option was used as the namespace') }) @@ -980,16 +1157,23 @@ describe('Service Module', () => { describe('Basics', () => { beforeEach(function() { - this.feathersClient = makeFeathersRestClient() - this.feathersClient.use('todos', memory({ store: makeTodos() })) - this.service = setupVuexService(this.feathersClient) + this.feathers = makeFeathersRestClient() + this.feathers.use('service-todos', memory({ store: makeTodos() })) + this.fv = feathersVuex(this.feathers, { + serverAlias: 'basics' + }) }) it('populates default store', () => { - const store = new Vuex.Store({ - plugins: [service('todos')] + const store = new Vuex.Store({ + plugins: [ + this.fv.makeServicePlugin({ + Model: ServiceTodo, + service: this.feathers.service('service-todos') + }) + ] }) - const todoState = store.state.todos + const todoState = store.state['service-todos'] const expectedState = { autoRemove: false, copiesById: {}, @@ -1017,7 +1201,7 @@ describe('Service Module', () => { skipRequestIfExists: false, preferUpdate: false, replaceItems: false, - servicePath: 'todos', + servicePath: 'service-todos', pagination: {}, paramsForServer: [], whitelist: [] @@ -1047,8 +1231,8 @@ describe('Service Module', () => { }) it(`populates items on find`, function(done) { - const store = new Vuex.Store({ - plugins: [this.service('todos', { idField: '_id' })] + const store = new Vuex.Store({ + plugins: [this.service('service-todos', { idField: '_id' })] }) const todoState = store.state.todos @@ -1071,7 +1255,7 @@ describe('Service Module', () => { beforeEach(function() { this.feathersClient = makeFeathersRestClient() this.feathersClient.use( - 'todos', + 'service-todos', memory({ store: makeTodos() }) @@ -1086,15 +1270,22 @@ describe('Service Module', () => { } }) ) - this.service = setupVuexService(this.feathersClient) + this.fv = feathersVuex(this.feathersClient, { + serverAlias: 'auto-remove' + }) }) it(`removes missing items when pagination is off`, function(done) { - const store = new Vuex.Store({ - plugins: [this.service('todos', { idField: '_id', autoRemove: true })] + const store = new Vuex.Store({ + plugins: [ + this.service('service-todos', { + idField: '_id', + autoRemove: true + }) + ] }) - const todoState = store.state.todos + const todoState = store.state['service-todos'] assert(todoState.ids.length === 0) @@ -1103,7 +1294,7 @@ describe('Service Module', () => { .dispatch('todos/find', { query: {} }) .then(todos => { // Remove the third item from the service - delete this.feathersClient.service('todos').store[3] + delete this.feathersClient.service('service-todos').store[3] // We went around using the store actions, so there will still be three items. assert( todoState.ids.length === 3, @@ -1127,7 +1318,7 @@ describe('Service Module', () => { }) it(`does not remove missing items when pagination is on`, function(done) { - const store = new Vuex.Store({ + const store = new Vuex.Store({ plugins: [this.service('tasks', { idField: '_id', autoRemove: true })] }) @@ -1165,9 +1356,12 @@ describe('Service Module', () => { }) it(`does not remove missing items when autoRemove is off`, function(done) { - const store = new Vuex.Store({ + const store = new Vuex.Store({ plugins: [ - this.service('todos', { idField: '_id', autoRemove: false }) + this.service('service-todos', { + idField: '_id', + autoRemove: false + }) ] }) const todoState = store.state.todos @@ -1179,7 +1373,7 @@ describe('Service Module', () => { .dispatch('todos/find', { query: {} }) .then(todos => { // Remove the third item from the service - delete this.feathersClient.service('todos').store[3] + delete this.feathersClient.service('service-todos').store[3] // We went around using the store actions, so there will still be three items. assert( todoState.ids.length === 3, @@ -1212,8 +1406,14 @@ describe('Service Module', () => { test: true } } - const store = new Vuex.Store({ - plugins: [service('todos', { state: customState })] + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: ServiceTodo, + service: feathersClient.service('service-todos'), + state: customState + }) + ] }) assert(store.state.todos.test === true, 'added custom state') @@ -1227,8 +1427,15 @@ describe('Service Module', () => { state.test = false } } - const store = new Vuex.Store({ - plugins: [service('todos', { state, mutations: customMutations })] + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: ServiceTodo, + service: feathersClient.service('service-todos'), + state, + mutations: customMutations + }) + ] }) store.commit('todos/setTestToFalse') @@ -1244,8 +1451,14 @@ describe('Service Module', () => { return 123 } } - const store = new Vuex.Store({ - plugins: [service('todos', { getters: customGetters })] + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: ServiceTodo, + service: feathersClient.service('service-todos'), + getters: customGetters + }) + ] }) assert( @@ -1270,8 +1483,14 @@ describe('Service Module', () => { } } } - const store = new Vuex.Store({ - plugins: [service('todos', config)] + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: ServiceTodo, + service: feathersClient.service('service-todos'), + ...config + }) + ] }) store.dispatch('todos/trigger') @@ -1280,11 +1499,18 @@ describe('Service Module', () => { }) describe.skip('Updates the Store on Events', function() { - const socketService = setupVuexService(feathersSocketioClient) + const fv = feathersVuex(feathersSocketioClient, { + serverAlias: 'updates-store-on-events' + }) it('created', function(done) { - const store = new Vuex.Store({ - plugins: [socketService('things')] + const store = new Vuex.Store({ + plugins: [ + fv.makeServicePlugin({ + Model: Thing, + service: feathersSocketioClient.service('things') + }) + ] }) feathersSocketioClient.service('things').on('created', item => { @@ -1299,8 +1525,13 @@ describe('Service Module', () => { }) it('patched', function(done) { - const store = new Vuex.Store({ - plugins: [socketService('things')] + const store = new Vuex.Store({ + plugins: [ + fv.makeServicePlugin({ + Model: Thing, + service: feathersSocketioClient.service('things') + }) + ] }) store.commit('things/addItem', { id: 1, test: false }) @@ -1317,8 +1548,13 @@ describe('Service Module', () => { }) it('updated', function(done) { - const store = new Vuex.Store({ - plugins: [socketService('things')] + const store = new Vuex.Store({ + plugins: [ + fv.makeServicePlugin({ + Model: Thing, + service: feathersSocketioClient.service('things') + }) + ] }) store.commit('things/addItem', { id: 1, test: false }) @@ -1335,8 +1571,13 @@ describe('Service Module', () => { }) it('removed', function(done) { - const store = new Vuex.Store({ - plugins: [socketService('things')] + const store = new Vuex.Store({ + plugins: [ + fv.makeServicePlugin({ + Model: Thing, + service: feathersSocketioClient.service('things') + }) + ] }) store.commit('things/addItem', { id: 1, test: false }) From e3e796d7dc2aad15e5d9858ad06c12a614ed3add Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 20:44:45 -0600 Subject: [PATCH 061/404] Prevent duplicate calls to mergeWithAccessors --- src/service-module/make-model.ts | 2 +- src/service-module/make-service-plugin.ts | 8 +- .../service-module.mutations.ts | 15 +- src/utils.ts | 4 + test/service-module/service-module.test.ts | 161 ++++++++++++------ 5 files changed, 127 insertions(+), 63 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 1cf6d6a2..8690dc44 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -130,7 +130,7 @@ export default function makeModel(options: FeathersVuexOptions) { const id = this[BaseModel.idField] BaseModel.store.commit(`${BaseModel.namespace}/commitCopy`, id) - return this._clone(id) + return this } else { throw new Error('You cannnot call commit on a non-copy') } diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index 52a6d2ed..9a827796 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -7,6 +7,7 @@ import { FeathersVuexOptions, MakeServicePluginOptions } from './types' import makeServiceModule from './make-service-module' import { globalModels, prepareAddModel } from './global-models' import { makeNamespace, getServicePath } from '../utils' +import { get as _get } from 'lodash' const defaults = { namespace: '', // The namespace for the Vuex module. Will generally be derived from the service.path, service.name, when available. Otherwise, it must be provided here, explicitly. @@ -58,8 +59,8 @@ export default function prepareMakeServicePlugin( store.registerModule(options.namespace, module) // (2a^) Monkey patch the BaseModel in globalModels - const { BaseModel } = globalModels[options.serverAlias] - if (!BaseModel.store) { + const BaseModel = _get(globalModels, `[${options.serverAlias}].BaseModel`) + if (BaseModel && !BaseModel.store) { Object.assign(BaseModel, { store, namespace: options.namespace, @@ -67,7 +68,7 @@ export default function prepareMakeServicePlugin( }) } // (2b^) Monkey patch the Model(s) and add to globalModels - if (!(Model.prototype instanceof BaseModel)) { + if (!BaseModel || !(Model.prototype instanceof BaseModel)) { Object.assign(Model, { store, namespace: options.namespace, @@ -75,6 +76,7 @@ export default function prepareMakeServicePlugin( }) } addModel(Model) + console.log(globalModels) // (3^) Setup real-time events if (options.enableEvents) { diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 3dd3c5b4..a4120814 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -163,14 +163,21 @@ export default function makeServiceMutations() { globalModels, `[${state.serverAlias}].byServicePath[${servicePath}]` ) - const copyData = mergeWithAccessors({}, current) + if (Model) { - var model = new Model(copyData, { isClone: true }) + var model = new Model(current, { isClone: true }) + } else { + var copyData = mergeWithAccessors({}, current) } + + let item = model || copyData if (keepCopiesInStore) { - state.copiesById[id] = model || copyData + state.copiesById[id] = item } else { - Model.copiesById[id] = Vue.observable(model || copyData) + if (!item.hasOwnProperty('__ob__')) { + item = Vue.observable(item) + } + Model.copiesById[id] = item } }, diff --git a/src/utils.ts b/src/utils.ts index 83bff8c6..0e9aaa75 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -310,6 +310,10 @@ export function mergeWithAccessors(dest, source) { sourceProps.forEach(key => { const desc = Object.getOwnPropertyDescriptor(source, key) + if (!desc.enumerable) { + return + } + // If we're dealing with a Vue Observable, just assign the values. if (destIsVueObservable || sourceIsVueObservable) { dest[key] = source[key] diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 5390a12a..5baab747 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -36,50 +36,72 @@ interface RootState { things: ServiceState } -const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { - serverAlias: 'service-module' -}) +function makeContext() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'service-module' + }) -class ServiceTodo extends BaseModel { - public id - public description: string -} -class HotspotMedia extends BaseModel { - public id - public description: string -} -class Media extends BaseModel { - public id - public description: string -} -class Person extends BaseModel { - public static test: boolean = true -} -class Item extends BaseModel { - public static test: boolean = true -} -class Task extends BaseModel { - public static test: boolean = true -} -class Car extends BaseModel { - public static test: boolean = true -} -class Group extends BaseModel { - public static test: boolean = true -} -class Test extends BaseModel { - public static test: boolean = true -} -class Thing extends BaseModel { - public static test: boolean = true + class ServiceTodo extends BaseModel { + public id + public description: string + + public constructor(data, options?) { + super(data, options) + } + } + class HotspotMedia extends BaseModel { + public id + public description: string + } + class Media extends BaseModel { + public id + public description: string + } + class Person extends BaseModel { + public static test: boolean = true + } + class Item extends BaseModel { + public static test: boolean = true + } + class Task extends BaseModel { + public static test: boolean = true + } + class Car extends BaseModel { + public static test: boolean = true + } + class Group extends BaseModel { + public static test: boolean = true + } + class Test extends BaseModel { + public static test: boolean = true + } + class Thing extends BaseModel { + public static test: boolean = true + } + + return { + makeServicePlugin, + BaseModel, + ServiceTodo, + HotspotMedia, + Media, + Person, + Item, + Task, + Car, + Group, + Test, + Thing + } } -describe.skip('Service Module', () => { - before(() => { +describe.only('Service Module', function() { + beforeEach(() => { clearModels() }) - it('registers a vuex plugin and Model for the service', () => { + it('registers a vuex plugin and Model for the service', function() { + const { makeServicePlugin, ServiceTodo, BaseModel } = makeContext() const serviceName = 'service-todos' const feathersService = feathersClient.service(serviceName) const store = new Vuex.Store({ @@ -99,18 +121,19 @@ describe.skip('Service Module', () => { 'the Model is also found at service.FeathersVuexModel' ) - // const serviceTodo = new ServiceTodo({ - // description: 'Do the dishes', - // isComplete: false - // }) - // assert(serviceTodo instanceof ServiceTodo, 'Model can be instantiated.') - // assert(serviceTodo instanceof BaseModel, 'Model can be instantiated.') + const serviceTodo = new ServiceTodo({ + description: 'Do the dishes', + isComplete: false + }) + assert(serviceTodo instanceof ServiceTodo, 'Model can be instantiated.') + assert(serviceTodo instanceof BaseModel, 'Model can be instantiated.') assert(store.state[serviceName]) }) describe('Models', function() { beforeEach(function() { + const { makeServicePlugin, ServiceTodo } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -140,9 +163,11 @@ describe.skip('Service Module', () => { const serviceTodo = store.state['service-todos'].keyedById[1] this.serviceTodo = serviceTodo + this.ServiceTodo = ServiceTodo }) it('allows creating model clones', function() { + const { ServiceTodo } = this const serviceTodoClone = this.serviceTodo.clone() assert( @@ -167,14 +192,15 @@ describe.skip('Service Module', () => { ) }) - it('allows commiting changes back to the original in the store', function() { - const { module, moduleClone } = this + it.only('allows commiting changes back to the original in the store', function() { + const { serviceTodo } = this + const serviceTodoClone = serviceTodo.clone() - moduleClone.description = 'Do something else' - moduleClone.commit() + serviceTodoClone.description = 'Do something else' + serviceTodoClone.commit() assert( - module.description === 'Do something else', + serviceTodo.description === 'Do something else', 'the original todo was updated' ) }) @@ -314,6 +340,8 @@ describe.skip('Service Module', () => { describe('Models - Default Values', function() { beforeEach(function() { + const { makeServicePlugin, ServiceTodo, Person, Car, Group } = this + const taskDefaults = (this.taskDefaults = { id: null, description: '', @@ -496,6 +524,7 @@ describe.skip('Service Module', () => { describe('Models - Methods', function() { beforeEach(function() { + const { makeServicePlugin, Task, ServiceTodo, Item } = this this.store = new Vuex.Store({ strict: true, plugins: [ @@ -630,6 +659,7 @@ describe.skip('Service Module', () => { describe('Models - modelName', function() { beforeEach(function() { + const { makeServicePlugin, HotspotMedia, Media } = this this.store = new Vuex.Store({ strict: true, plugins: [ @@ -659,6 +689,7 @@ describe.skip('Service Module', () => { describe('Models - Dates', function() { beforeEach(function() { + const { makeServicePlugin, ServiceTodo } = this const instanceDefaults = { id: null, description: '', @@ -703,6 +734,7 @@ describe.skip('Service Module', () => { describe('Models - Relationships', function() { beforeEach(function() { + const { makeServicePlugin, BaseModel } = this class Task extends BaseModel { public static instanceDefaults: { id: null @@ -1046,7 +1078,8 @@ describe.skip('Service Module', () => { }) describe('Setting Up', () => { - it('service stores have global defaults', () => { + it('service stores have global defaults', function() { + const { makeServicePlugin, BaseModel, Task } = this class Todo extends BaseModel { public static test: boolean = true } @@ -1070,6 +1103,7 @@ describe.skip('Service Module', () => { }) it('can customize the idField for each service', function() { + const { makeServicePlugin, Test } = this const idField = '_id' const store = new Vuex.Store({ plugins: [ @@ -1088,6 +1122,7 @@ describe.skip('Service Module', () => { }) it('allows enabling autoRemove', function() { + const { makeServicePlugin, Test } = this const autoRemove = true const store = new Vuex.Store({ plugins: [ @@ -1104,7 +1139,8 @@ describe.skip('Service Module', () => { ) }) - it('can switch to path name as namespace', () => { + it('can switch to path name as namespace', function() { + const { makeServicePlugin, Test } = this const nameStyle = 'path' const serviceName = '/v1/tests' const store = new Vuex.Store({ @@ -1124,7 +1160,8 @@ describe.skip('Service Module', () => { ) }) - it('can explicitly provide a namespace', () => { + it('can explicitly provide a namespace', function() { + const { makeServicePlugin, Test } = this const namespace = 'blah' const store = new Vuex.Store({ plugins: [ @@ -1138,7 +1175,8 @@ describe.skip('Service Module', () => { assert(store.state.blah, 'the namespace option was used as the namespace') }) - it('prioritizes the explicit namespace', () => { + it('prioritizes the explicit namespace', function() { + const { makeServicePlugin, Test } = this const namespace = 'blah' const nameStyle = 'path' const store = new Vuex.Store({ @@ -1162,13 +1200,17 @@ describe.skip('Service Module', () => { this.fv = feathersVuex(this.feathers, { serverAlias: 'basics' }) + class ServiceTodo extends this.fv.BaseModel { + public static test: boolean = true + } + this.ServiceTodo = ServiceTodo }) - it('populates default store', () => { + it('populates default store', function() { const store = new Vuex.Store({ plugins: [ this.fv.makeServicePlugin({ - Model: ServiceTodo, + Model: this.ServiceTodo, service: this.feathers.service('service-todos') }) ] @@ -1400,6 +1442,8 @@ describe.skip('Service Module', () => { describe('Customizing Service Stores', function() { it('allows adding custom state', function() { + const { makeServicePlugin, ServiceTodo } = this + const customState = { test: true, test2: { @@ -1421,6 +1465,7 @@ describe.skip('Service Module', () => { }) it('allows custom mutations', function() { + const { makeServicePlugin, ServiceTodo } = this const state = { test: true } const customMutations = { setTestToFalse(state) { @@ -1446,6 +1491,7 @@ describe.skip('Service Module', () => { }) it('allows custom getters', function() { + const { makeServicePlugin, ServiceTodo } = this const customGetters = { oneTwoThree(state) { return 123 @@ -1468,6 +1514,7 @@ describe.skip('Service Module', () => { }) it('allows adding custom actions', function() { + const { makeServicePlugin, ServiceTodo } = this const config = { state: { isTrue: false @@ -1504,6 +1551,7 @@ describe.skip('Service Module', () => { }) it('created', function(done) { + const { Thing } = this const store = new Vuex.Store({ plugins: [ fv.makeServicePlugin({ @@ -1525,6 +1573,7 @@ describe.skip('Service Module', () => { }) it('patched', function(done) { + const { Thing } = this const store = new Vuex.Store({ plugins: [ fv.makeServicePlugin({ @@ -1548,6 +1597,7 @@ describe.skip('Service Module', () => { }) it('updated', function(done) { + const { Thing } = this const store = new Vuex.Store({ plugins: [ fv.makeServicePlugin({ @@ -1571,6 +1621,7 @@ describe.skip('Service Module', () => { }) it('removed', function(done) { + const { Thing } = this const store = new Vuex.Store({ plugins: [ fv.makeServicePlugin({ From 4364a7f4dbdbe486c7c81da7c2f2ab3918d51501 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 21:25:07 -0600 Subject: [PATCH 062/404] Handle cloning of objects in vue accessors --- src/service-module/make-model.ts | 1 + src/service-module/make-service-plugin.ts | 1 - src/utils.ts | 19 ++++----- test/service-module/service-module.test.ts | 45 ++++++++++++---------- 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 8690dc44..f371542b 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -46,6 +46,7 @@ export default function makeModel(options: FeathersVuexOptions) { public data: Record public constructor(data, options: BaseModelConstructorOptions = {}) { + data = data || {} if (options.isClone) { Object.defineProperty(this, 'isClone', { value: true, diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index 9a827796..86bacd4f 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -76,7 +76,6 @@ export default function prepareMakeServicePlugin( }) } addModel(Model) - console.log(globalModels) // (3^) Setup real-time events if (options.enableEvents) { diff --git a/src/utils.ts b/src/utils.ts index 0e9aaa75..f19c0519 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -316,7 +316,11 @@ export function mergeWithAccessors(dest, source) { // If we're dealing with a Vue Observable, just assign the values. if (destIsVueObservable || sourceIsVueObservable) { - dest[key] = source[key] + if (_isObject(source[key])) { + dest[key] = fastCopy(source[key]) + } else { + dest[key] = source[key] + } return } @@ -331,15 +335,12 @@ export function mergeWithAccessors(dest, source) { } // Assign values - if (key !== '__ob__') { - // Do not allow sharing of deeply-nested objects between instances - // Probably breaks accessors on nested data. Use recursion if this is an issue - if (_isPlainObject(desc.value)) { - desc.value = fastCopy(desc.value) - } - // Vue.set(dest, key, desc.value) - dest[key] = desc.value + // Do not allow sharing of deeply-nested objects between instances + // Potentially breaks accessors on nested data. Needs recursion if this is an issue + if (_isPlainObject(desc.value)) { + desc.value = fastCopy(desc.value) } + dest[key] = desc.value }) return dest } diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 5baab747..a55eccd0 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -95,7 +95,7 @@ function makeContext() { } } -describe.only('Service Module', function() { +describe.skip('Service Module', function() { beforeEach(() => { clearModels() }) @@ -192,7 +192,7 @@ describe.only('Service Module', function() { ) }) - it.only('allows commiting changes back to the original in the store', function() { + it('allows commiting changes back to the original in the store', function() { const { serviceTodo } = this const serviceTodoClone = serviceTodo.clone() @@ -206,60 +206,63 @@ describe.only('Service Module', function() { }) it('performs a shallow merge when commiting back to the original record', function() { - const { module, moduleClone, owners } = this + const { serviceTodo, owners } = this + const serviceTodoClone = serviceTodo.clone() - moduleClone.owners = [ + serviceTodoClone.owners = [ { id: 1, name: 'Marshall' }, { id: 2, name: 'Mariah' } ] assert.deepEqual( - module.owners, + serviceTodo.owners, owners, 'original todo remained unchanged' ) - moduleClone.commit() + serviceTodoClone.commit() assert.deepEqual( - module.owners, + serviceTodo.owners, [owners[0], owners[1]], 'ownerIds were updated properly' ) }) - it(`changes the original record if you don't use the return value of commit()`, function() { - const { module, moduleClone, owners } = this + it(`no longer changes original if you don't use the return value of commit()`, function() { + const { serviceTodo, owners } = this + const serviceTodoClone = serviceTodo.clone() assert.deepEqual( - module.owners, + serviceTodo.owners, owners, 'original todo remained unchanged' ) - moduleClone.commit() - moduleClone.owners[0].name = 'Ted' + serviceTodoClone.commit() + serviceTodoClone.owners[0].name = 'Ted' assert.deepEqual( - module.owners[0].name, - 'Ted', - 'nested object in original todo was changed' + serviceTodo.owners[0].name, + 'Marshall', + 'nested object in original todo was unchanged' ) }) - it(`doesn't change the original record if you use modify return value of a commit`, function() { - let { module, moduleClone, owners } = this + it(`doesn't change the original if you modify return value of a commit`, function() { + const { serviceTodo, owners } = this + let serviceTodoClone = serviceTodo.clone() assert.deepEqual( - module.owners, + serviceTodo.owners, owners, 'original todo remained unchanged' ) - moduleClone = moduleClone.commit() - moduleClone.owners[0].name = 'Ted' + serviceTodoClone = serviceTodoClone.commit() + serviceTodoClone.owners[0].name = 'Ted' assert.deepEqual( - module.owners[0].name, + serviceTodo.owners[0].name, 'Marshall', 'nested object in original todo was NOT changed' ) From aafcdd6b525a8e5ae16e68ccd7967e30706df969 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 22:38:48 -0600 Subject: [PATCH 063/404] Two more service-module tests --- test/service-module/service-module.test.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index a55eccd0..96b6067b 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -269,23 +269,24 @@ describe.skip('Service Module', function() { }) it('allows reseting copy changes back to match the original', function() { - const { module, moduleClone } = this + const { serviceTodo } = this + let serviceTodoClone = serviceTodo.clone() - moduleClone.description = 'Do something else' - moduleClone.reset() + serviceTodoClone.description = 'Do something else' + serviceTodoClone.reset() assert( - module.description === 'Do the dishes', + serviceTodo.description === 'Do the dishes', 'the original todo was untouched' ) assert( - moduleClone.description === 'Do the dishes', + serviceTodoClone.description === 'Do the dishes', 'the clone was reset to match the original' ) }) it('adds additional properties to model instances when more data arrives for the same id', function() { - const { module, owners } = this + const { serviceTodo, owners } = this const newData = { id: 1, description: 'Do the dishes', @@ -293,12 +294,12 @@ describe.skip('Service Module', function() { owners, test: true } - const newTodo = new module.constructor(newData) + const newTodo = new serviceTodo.constructor(newData) - assert(newTodo === module, 'the records are the same') + assert(newTodo === serviceTodo, 'the records are the same') assert(newTodo.test === true, 'the new attribute was added') assert( - module.test === true, + serviceTodo.test === true, 'the new attribute was also added to the original' ) }) From ab4696893306d355d26e39ed47c771b1960105c0 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 22:39:10 -0600 Subject: [PATCH 064/404] Add makeContext util for service-module actions tests --- .../service-module.actions.test.ts | 64 +++++++++++++++---- 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/test/service-module/service-module.actions.test.ts b/test/service-module/service-module.actions.test.ts index 219302ab..f2da584e 100644 --- a/test/service-module/service-module.actions.test.ts +++ b/test/service-module/service-module.actions.test.ts @@ -20,20 +20,30 @@ interface NumberedList { 1?: {} } -const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { - serverAlias: 'default' -}) -class Todo extends BaseModel { - public static test: boolean = true -} -class Task extends BaseModel { - public static test: boolean = true -} -class NoId extends BaseModel { - public static test: boolean = true -} -class Broken extends BaseModel { - public static test: boolean = true +function makeContext() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'default' + }) + class Todo extends BaseModel { + public static test: boolean = true + } + class Task extends BaseModel { + public static test: boolean = true + } + class NoId extends BaseModel { + public static test: boolean = true + } + class Broken extends BaseModel { + public static test: boolean = true + } + return { + makeServicePlugin, + BaseModel, + Todo, + Task, + NoId, + Broken + } } const makeStore = () => { return { @@ -123,6 +133,7 @@ describe('Service Module - Actions', () => { describe('Find', () => { describe('without pagination', () => { it('Find without pagination', done => { + const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -170,6 +181,7 @@ describe('Service Module - Actions', () => { }) it('find with limit', done => { + const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -196,6 +208,7 @@ describe('Service Module - Actions', () => { }) it('find with skip', done => { + const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -222,6 +235,7 @@ describe('Service Module - Actions', () => { }) it('Find with limit and skip', done => { + const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -250,6 +264,7 @@ describe('Service Module - Actions', () => { describe('with pagination', () => { it('find with limit', done => { + const { makeServicePlugin, Task } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -279,6 +294,7 @@ describe('Service Module - Actions', () => { }) it('find with skip', done => { + const { makeServicePlugin, Task } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -308,6 +324,7 @@ describe('Service Module - Actions', () => { }) it('find with limit and skip', done => { + const { makeServicePlugin, Task } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -337,6 +354,7 @@ describe('Service Module - Actions', () => { }) it('adds default pagination data to the store', done => { + const { makeServicePlugin, Task } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -364,6 +382,7 @@ describe('Service Module - Actions', () => { }) it('can provide a query identifier to store pagination', done => { + const { makeServicePlugin, Task } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -392,6 +411,7 @@ describe('Service Module - Actions', () => { }) it('updates properly with limit and skip', done => { + const { makeServicePlugin, Task } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -422,6 +442,7 @@ describe('Service Module - Actions', () => { }) it('works with multiple queries and identifiers', done => { + const { makeServicePlugin, Task } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -458,6 +479,7 @@ describe('Service Module - Actions', () => { }) it(`allows non-id'd data to pass through`, done => { + const { makeServicePlugin, NoId } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -482,6 +504,7 @@ describe('Service Module - Actions', () => { }) it(`runs the afterFind action`, done => { + const { makeServicePlugin, NoId } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -513,6 +536,7 @@ describe('Service Module - Actions', () => { }) it('updates errorOnFind state on service failure', done => { + const { makeServicePlugin, Broken } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -543,6 +567,7 @@ describe('Service Module - Actions', () => { describe('Get', function() { it('updates store list state on service success', done => { + const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -625,6 +650,7 @@ describe('Service Module - Actions', () => { }) it('does not make remote call when skipRequestIfExists=true', done => { + const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -708,6 +734,7 @@ describe('Service Module - Actions', () => { }) it('updates errorOnGet state on service failure', done => { + const { makeServicePlugin, Broken } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -738,6 +765,7 @@ describe('Service Module - Actions', () => { describe('Create', function() { it('updates store list state on service success', done => { + const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -769,6 +797,7 @@ describe('Service Module - Actions', () => { }) it('updates errorOnCreate state on service failure', done => { + const { makeServicePlugin, Broken } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -802,6 +831,7 @@ describe('Service Module - Actions', () => { describe('Update', () => { it('updates store list state on service success', done => { + const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -845,6 +875,7 @@ describe('Service Module - Actions', () => { }) it('updates errorOnUpdate state on service failure', done => { + const { makeServicePlugin, Broken } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -882,6 +913,7 @@ describe('Service Module - Actions', () => { describe('Patch', () => { it('updates only the changed properties', done => { + const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -934,6 +966,7 @@ describe('Service Module - Actions', () => { }) it('updates store state on service success', done => { + const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -971,6 +1004,7 @@ describe('Service Module - Actions', () => { }) it('updates errorOnPatch state on service failure', done => { + const { makeServicePlugin, Broken } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -1008,6 +1042,7 @@ describe('Service Module - Actions', () => { describe('Remove', () => { it('updates store state on service success', done => { + const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -1045,6 +1080,7 @@ describe('Service Module - Actions', () => { }) it('updates errorOnRemove state on service failure', done => { + const { makeServicePlugin, Broken } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ From a1da670eb7e4ccd8c63f299fac62ce90e87f3dbb Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 27 Mar 2019 22:40:42 -0600 Subject: [PATCH 065/404] Updates to BaseModel To add visual clarity, the store getters, mutations, and actions are now aliased in their own BaseModel methods. Existing ID checks are done for incoming data. Returns the same object if it already exists. --- src/service-module/make-model.ts | 85 +++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index f371542b..c85668be 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -45,8 +45,20 @@ export default function makeModel(options: FeathersVuexOptions) { protected isClone: boolean public data: Record + public constructor(data, options: BaseModelConstructorOptions = {}) { data = data || {} + const { idField } = BaseModel + const id = data[idField] + + // Update original item if it already exists. + const existingItem = + id !== null && id !== undefined && BaseModel.getFromStore(id) + if (existingItem) { + BaseModel.commit('updateItem', data) + return existingItem + } + if (options.isClone) { Object.defineProperty(this, 'isClone', { value: true, @@ -63,31 +75,63 @@ export default function makeModel(options: FeathersVuexOptions) { } public static find(params) { - return BaseModel.store.dispatch(`${BaseModel.namespace}/find`, params) + this.dispatch('find', params) } public static findInStore(params) { - return BaseModel.store.getters[`${BaseModel.namespace}/find`](params) + return BaseModel.getters('find', params) } public static get(id, params) { - const { store } = BaseModel if (params) { - return store.dispatch(`${BaseModel.namespace}/get`, [id, params]) + return BaseModel.dispatch('get', [id, params]) } else { - return store.dispatch(`${BaseModel.namespace}/get`, id) + return BaseModel.dispatch('get', id) } } - public static getFromStore(id, params) { - const { store } = BaseModel + public static getFromStore(id, params?) { if (params) { - return store.getters[`${BaseModel.namespace}/get`]([id, params]) + return BaseModel.getters('get', [id, params]) } else { - return store.getters[`${BaseModel.namespace}/get`](id) + return BaseModel.getters('get', id) } } + /** + * An alias for store.getters + * @param method the vuex getter name without the namespace + * @param payload if provided, the getter will be called as a function + */ + public static getters(name: string, payload?: any) { + if (payload !== undefined) { + return BaseModel.store.getters[`${BaseModel.namespace}/${name}`]( + payload + ) + } else { + return BaseModel.store.getters[`${BaseModel.namespace}/${name}`] + } + } + /** + * An alias for store.commit + * @param method the vuex mutation name without the namespace + * @param payload the payload for the mutation + */ + public static commit(method: string, payload: any): void { + BaseModel.store.commit(`${BaseModel.namespace}/${method}`, payload) + } + /** + * An alias for store.dispatch + * @param method the vuex action name without the namespace + * @param payload the payload for the action + */ + public static dispatch(method: string, payload: any) { + return BaseModel.store.dispatch( + `${BaseModel.namespace}/${method}`, + payload + ) + } + /** * clone the current record using the `createCopy` mutation */ @@ -105,7 +149,7 @@ export default function makeModel(options: FeathersVuexOptions) { store.commit(`${namespace}/createCopy`, id) if (store.state[namespace].keepCopiesInStore) { - return store.getters[`${namespace}/getCopyById`](id) + return BaseModel.getters('getCopyById', id) } else { return copiesById[id] } @@ -117,7 +161,7 @@ export default function makeModel(options: FeathersVuexOptions) { public reset() { if (this.isClone) { const id = this[BaseModel.idField] - BaseModel.store.commit(`${BaseModel.namespace}/resetCopy`, id) + BaseModel.commit('resetCopy', id) } else { throw new Error('You cannot reset a non-copy') } @@ -129,7 +173,7 @@ export default function makeModel(options: FeathersVuexOptions) { public commit() { if (this.isClone) { const id = this[BaseModel.idField] - BaseModel.store.commit(`${BaseModel.namespace}/commitCopy`, id) + BaseModel.commit('commitCopy', id) return this } else { @@ -158,14 +202,14 @@ export default function makeModel(options: FeathersVuexOptions) { if (data[options.idField] === null) { delete data[options.idField] } - return store.dispatch(`${BaseModel.namespace}/create`, [data, params]) + return BaseModel.dispatch('create', [data, params]) } /** * Calls service patch with the current instance data * @param params */ - public patch(params) { + public patch(params?) { if (!this[options.idField]) { const error = new Error( `Missing ${ @@ -174,8 +218,8 @@ export default function makeModel(options: FeathersVuexOptions) { ) return Promise.reject(error) } - return BaseModel.store.dispatch(`${BaseModel.namespace}/patch`, [ - this[options.idField], + return BaseModel.dispatch('patch', [ + this[BaseModel.idField], this, params ]) @@ -194,8 +238,8 @@ export default function makeModel(options: FeathersVuexOptions) { ) return Promise.reject(error) } - return BaseModel.store.dispatch(`${BaseModel.namespace}/update`, [ - this[options.idField], + return BaseModel.dispatch('update', [ + this[BaseModel.idField], this, params ]) @@ -206,10 +250,7 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public remove(params) { - return BaseModel.store.dispatch(`${BaseModel.namespace}/remove`, [ - this[options.idField], - params - ]) + return BaseModel.dispatch('remove', [this[BaseModel.idField], params]) } } addModel(BaseModel) From 64bbbc01f246cb18265fb08b9a3213b30622c77d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 28 Mar 2019 07:25:57 -0600 Subject: [PATCH 066/404] Two ways of handling instance defaults --- src/service-module/make-model.ts | 56 ++- src/service-module/make-service-plugin.ts | 11 +- src/service-module/notes.md | 4 + .../service-module.mutations.ts | 20 +- src/service-module/types.ts | 1 + src/utils.ts | 42 +- .../make-service-plugin.test.ts | 9 +- .../model-instance-defaults.test.ts | 400 ++++++++++++++++++ test/service-module/service-module.test.ts | 203 +-------- test/service-module/types.ts | 4 + 10 files changed, 517 insertions(+), 233 deletions(-) create mode 100644 test/service-module/model-instance-defaults.test.ts diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index c85668be..03da0701 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -5,7 +5,7 @@ eslint */ import { FeathersVuexOptions } from './types' import { globalModels, prepareAddModel } from './global-models' -import { mergeWithAccessors } from '../utils' +import { mergeWithAccessors, separateAccessors } from '../utils' import { get as _get } from 'lodash' interface BaseConstructor { @@ -14,6 +14,9 @@ interface BaseConstructor { interface BaseModelConstructorOptions { isClone?: boolean } +interface ChildClassOptions { + merge?: boolean +} /** * @@ -35,6 +38,8 @@ export default function makeModel(options: FeathersVuexOptions) { public static namespace: string public static servicePath: string + public static instanceDefaults + public static idField: string = options.idField public static preferUpdate: boolean = options.preferUpdate public static serverAlias: string = options.serverAlias @@ -42,32 +47,56 @@ export default function makeModel(options: FeathersVuexOptions) { public static readonly models = globalModels // Can access other Models here public static readonly copiesById = {} - protected isClone: boolean + protected __isClone: boolean public data: Record - public constructor(data, options: BaseModelConstructorOptions = {}) { + public static merge = mergeWithAccessors + + public constructor( + data, + options: BaseModelConstructorOptions = {}, + childClassOptions: ChildClassOptions = { merge: true } + ) { data = data || {} + const { merge } = childClassOptions const { idField } = BaseModel const id = data[idField] + const hasValidId = !options.isClone && id !== null && id !== undefined // Update original item if it already exists. - const existingItem = - id !== null && id !== undefined && BaseModel.getFromStore(id) - if (existingItem) { - BaseModel.commit('updateItem', data) - return existingItem + if (hasValidId) { + const existingItem = BaseModel.getFromStore(id) + if (existingItem) { + BaseModel.commit('updateItem', data) + return existingItem + } } if (options.isClone) { - Object.defineProperty(this, 'isClone', { + Object.defineProperty(this, '__isClone', { value: true, enumerable: false, writable: false }) } + if (BaseModel.instanceDefaults) { + const instanceDefaults = BaseModel.instanceDefaults() + const separatedDefaults = separateAccessors(instanceDefaults) + mergeWithAccessors(this, separatedDefaults.accessors) + mergeWithAccessors(this, separatedDefaults.values) + } + + // Handles Vue objects or regular ones. We can't simply assign or return + // the data due to how Vue wraps everything into an accessor. mergeWithAccessors(this, data) + + // Add the item to the store + if (hasValidId && merge !== false) { + BaseModel.commit('addItem', this) + } + return this } public static getId(record: Record): string { @@ -136,7 +165,7 @@ export default function makeModel(options: FeathersVuexOptions) { * clone the current record using the `createCopy` mutation */ public clone() { - if (this.isClone) { + if (this.__isClone) { throw new Error('You cannot clone a copy') } const id = this[BaseModel.idField] @@ -145,10 +174,11 @@ export default function makeModel(options: FeathersVuexOptions) { private _clone(id) { const { store, copiesById, namespace } = BaseModel + const { keepCopiesInStore } = store.state[namespace] // const { store } = this.constructor store.commit(`${namespace}/createCopy`, id) - if (store.state[namespace].keepCopiesInStore) { + if (keepCopiesInStore) { return BaseModel.getters('getCopyById', id) } else { return copiesById[id] @@ -159,7 +189,7 @@ export default function makeModel(options: FeathersVuexOptions) { * Reset a clone to match the instance in the store. */ public reset() { - if (this.isClone) { + if (this.__isClone) { const id = this[BaseModel.idField] BaseModel.commit('resetCopy', id) } else { @@ -171,7 +201,7 @@ export default function makeModel(options: FeathersVuexOptions) { * Update a store instance to match a clone. */ public commit() { - if (this.isClone) { + if (this.__isClone) { const id = this[BaseModel.idField] BaseModel.commit('commitCopy', id) diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index 86bacd4f..34e21e02 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -16,7 +16,8 @@ const defaults = { state: {}, // for custom state getters: {}, // for custom getters mutations: {}, // for custom mutations - actions: {} // for custom actions + actions: {}, // for custom actions + instanceDefaults: () => ({}) // Default instanceDefaults is an empty object } /** @@ -35,7 +36,7 @@ export default function prepareMakeServicePlugin( */ return function makeServicePlugin(config: MakeServicePluginOptions) { const options = Object.assign({}, defaults, globalOptions, config) - const { Model, service, namespace, nameStyle } = options + const { Model, service, namespace, nameStyle, instanceDefaults } = options if (!service) { throw new Error( @@ -64,7 +65,8 @@ export default function prepareMakeServicePlugin( Object.assign(BaseModel, { store, namespace: options.namespace, - servicePath + servicePath, + instanceDefaults }) } // (2b^) Monkey patch the Model(s) and add to globalModels @@ -72,7 +74,8 @@ export default function prepareMakeServicePlugin( Object.assign(Model, { store, namespace: options.namespace, - servicePath + servicePath, + instanceDefaults }) } addModel(Model) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index cfc5fcf8..ecc38f9e 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -146,6 +146,10 @@ const store = new Vuex.Store({ }) ``` +## Options are no longer kept on the Model + +The Model class no longer has an `options` property. You can access the same information through the `Model.store.state[Model.namespace]`. + ## The 'apiPrefix' option has been removed Feathers-Vuex now includes full support for communicating with multiple FeathersJS APIs. The `apiPrefix` option was a poorly implemented, hacky first attempt at this same feature. It was buggy. Since it didn't work as intended, it has been removed. See this example test for working with multiple APIs: diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index a4120814..55daf1a8 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -7,16 +7,14 @@ import Vue from 'vue' import serializeError from 'serialize-error' import isObject from 'lodash.isobject' import { checkId, updateOriginal, mergeWithAccessors } from '../utils' -import { globalModels } from './global-models' +import { globalModels as models } from './global-models' import { get as _get } from 'lodash' export default function makeServiceMutations() { function addItems(state, items) { - const { idField, debug, servicePath } = state - const Model = _get( - globalModels, - `[${state.serverAlias}].byServicePath[${servicePath}]` - ) + const { idField, debug, servicePath, serverAlias, modelName } = state + const Model = _get(models, `[${state.serverAlias}][${modelName}]`) + const BaseModel = _get(models, `[${state.serverAlias}].BaseModel`) let newKeyedById = { ...state.keyedById } @@ -25,7 +23,7 @@ export default function makeServiceMutations() { const isIdOk = checkId(id, item, debug) if (isIdOk) { - if (Model && !item.isFeathersVuexInstance) { + if (Model && !(item instanceof BaseModel) && !(item instanceof Model)) { item = new Model(item) } @@ -44,7 +42,7 @@ export default function makeServiceMutations() { function updateItems(state, items) { const { idField, replaceItems, addOnUpsert, debug, servicePath } = state const Model = _get( - globalModels, + models, `[${state.serverAlias}].byServicePath[${servicePath}]` ) @@ -160,7 +158,7 @@ export default function makeServiceMutations() { const { servicePath, keepCopiesInStore } = state const current = state.keyedById[id] const Model = _get( - globalModels, + models, `[${state.serverAlias}].byServicePath[${servicePath}]` ) @@ -186,7 +184,7 @@ export default function makeServiceMutations() { const { debug, servicePath, keepCopiesInStore } = state checkId(id, undefined, debug) const Model = _get( - globalModels, + models, `[${state.serverAlias}].byServicePath[${servicePath}]` ) const copy = keepCopiesInStore @@ -203,7 +201,7 @@ export default function makeServiceMutations() { const { debug, servicePath, keepCopiesInStore } = state checkId(id, undefined, debug) const Model = _get( - globalModels, + models, `[${state.serverAlias}].byServicePath[${servicePath}]` ) const copy = keepCopiesInStore diff --git a/src/service-module/types.ts b/src/service-module/types.ts index 3d2134e6..432e79e8 100644 --- a/src/service-module/types.ts +++ b/src/service-module/types.ts @@ -30,6 +30,7 @@ export interface MakeServicePluginOptions { namespace?: string preferUpdate?: boolean servicePath?: string + instanceDefaults?: () => {} state?: {} getters?: {} mutations?: {} diff --git a/src/utils.ts b/src/utils.ts index f19c0519..4dc33b9e 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -308,9 +308,10 @@ export function mergeWithAccessors(dest, source) { const sourceIsVueObservable = sourceProps.includes('__ob__') const destIsVueObservable = destProps.includes('__ob__') sourceProps.forEach(key => { - const desc = Object.getOwnPropertyDescriptor(source, key) + const sourceDesc = Object.getOwnPropertyDescriptor(source, key) + const destDesc = Object.getOwnPropertyDescriptor(dest, key) - if (!desc.enumerable) { + if (!sourceDesc.enumerable) { return } @@ -325,22 +326,26 @@ export function mergeWithAccessors(dest, source) { } // Handle defining accessors - if (typeof desc.get === 'function' || typeof desc.set === 'function') { - if (destIsVueObservable) { - dest[key] = desc.value - } else { - Object.defineProperty(dest, key, desc) - } + if ( + typeof sourceDesc.get === 'function' || + typeof sourceDesc.set === 'function' + ) { + Object.defineProperty(dest, key, sourceDesc) + return + } + + // Do not attempt to overwrite a getter in the dest object + if (destDesc && typeof destDesc.get === 'function') { return } // Assign values // Do not allow sharing of deeply-nested objects between instances // Potentially breaks accessors on nested data. Needs recursion if this is an issue - if (_isPlainObject(desc.value)) { - desc.value = fastCopy(desc.value) + if (_isObject(sourceDesc.value)) { + var value = fastCopy(sourceDesc.value) } - dest[key] = desc.value + dest[key] = value || sourceDesc.value }) return dest } @@ -362,3 +367,18 @@ export function cloneWithAccessors(obj) { return clone } + +export function separateAccessors(props) { + return Object.keys(props).reduce( + ({ accessors, values }, key) => { + const desc = Object.getOwnPropertyDescriptor(props, key) + if (typeof desc.get === 'function' || typeof desc.set === 'function') { + Object.defineProperty(accessors, key, desc) + } else { + Object.defineProperty(values, key, desc) + } + return { accessors, values } + }, + { accessors: {}, values: {} } + ) +} diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index 52434c4b..3b34fae8 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -9,7 +9,7 @@ import Vuex from 'vuex' import { clearModels } from '../../src/service-module/global-models' import { feathersRestClient as feathers } from '../../test/fixtures/feathers-client' import feathersVuex from '../../src/index' -import _pick from 'lodash.pick' +import { pick as _pick, omit as _omit } from 'lodash' Vue.use(Vuex) @@ -55,6 +55,7 @@ describe('makeServicePlugin', function() { errorOnUpdate: null, idField: 'id', ids: [], + instanceDefaults: () => ({}), isCreatePending: false, isFindPending: false, isGetPending: false, @@ -76,7 +77,11 @@ describe('makeServicePlugin', function() { whitelist: [] } - assert.deepEqual(received, expected, 'The module was registered.') + assert.deepEqual( + _omit(received, ['instanceDefaults']), + _omit(expected, ['instanceDefaults']), + 'The module was registered.' + ) }) it('sets up Model.store && service.FeathersVuexModel', function() { diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts new file mode 100644 index 00000000..2ae739e6 --- /dev/null +++ b/test/service-module/model-instance-defaults.test.ts @@ -0,0 +1,400 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { ServiceState, Location } from './types' +import { assert } from 'chai' +import feathersVuex, { models } from '../../src/index' +import { mergeWithAccessors } from '../../src/utils' +import { clearModels } from '../../src/service-module/global-models' +import { + makeFeathersRestClient, + feathersRestClient as feathersClient, + feathersSocketioClient +} from '../fixtures/feathers-client' +import Vuex from 'vuex' + +interface TodoState extends ServiceState { + test: any + test2: { + test: boolean + } + isTrue: boolean +} +interface RootState { + todos: TodoState + tasks: ServiceState + tests: ServiceState + blah: ServiceState + things: ServiceState +} + +function makeContext() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'service-module' + }) + + class ServiceTodo extends BaseModel { + public id + public description: string + + public constructor(data, options?) { + super(data, options) + } + } + class Person extends BaseModel { + public static test: boolean = true + } + class Item extends BaseModel { + public static test: boolean = true + } + class Task extends BaseModel { + public static test: boolean = true + } + class Car extends BaseModel { + public static test: boolean = true + } + class Group extends BaseModel { + public static test: boolean = true + } + class Test extends BaseModel { + public static test: boolean = true + } + class Thing extends BaseModel { + public static test: boolean = true + } + + return { + makeServicePlugin, + BaseModel, + ServiceTodo, + Person, + Item, + Task, + Car, + Group, + Test, + Thing + } +} + +describe('Models - Default Values', function() { + beforeEach(function() { + const { makeServicePlugin, ServiceTodo, Person, Car, Group } = makeContext() + + const taskDefaults = (this.taskDefaults = { + id: null, + description: '', + isComplete: false + }) + + // TODO: Do Something with this! + const instanceDefaultsForPerson = { + firstName: '', + lastName: '', + location: { + coordinates: [-111.549668, 39.014] + }, + get fullName() { + return `${this.firstName} ${this.lastName}` + }, + todos({ store }) { + console.log(Object.keys(store)) + } + } + const instanceDefaultsForCars = { + keepCopiesInStore: true, + instanceDefaults: taskDefaults + } + const instanceDefaultsForGroups = function instanceDefaults() { + return { + name: '', + get todos() { + return models.Todo.findInStore({ query: {} }).data + } + } + } + this.store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: ServiceTodo, + service: feathersClient.service('service-todos') + }), + makeServicePlugin({ + Model: Person, + service: feathersClient.service('people') + }), + makeServicePlugin({ + Model: Car, + service: feathersClient.service('cars') + }), + makeServicePlugin({ + Model: Group, + service: feathersClient.service('groups') + }) + ] + }) + this.Todo = ServiceTodo + this.Task = models.Task + this.Person = models.Person + this.Group = models.Group + }) + + // store.commit('todos/addItem', data) + + it('models default to an empty object', function() { + const { Todo } = this + const module = new Todo() + + assert.deepEqual(module, {}, 'default model is an empty object') + }) + + it('adds new instances containing an id to the store', function() { + const { ServiceTodo } = makeContext() + + const todo = new ServiceTodo({ + id: 1, + description: 'test', + isComplete: true + }) + const todoInStore = ServiceTodo.store.state['service-todos'].keyedById[1] + + assert.deepEqual(todoInStore, todo, 'task was added to the store') + }) + + it('stores clones in Model.copiesById by default', function() { + const { ServiceTodo } = makeContext() + const todo = new ServiceTodo({ id: 1, description: 'This is the original' }) + + assert.deepEqual( + ServiceTodo.copiesById, + {}, + 'Model.copiesById should start out empty' + ) + + const todoClone = todo.clone() + assert( + ServiceTodo.copiesById[1], + 'should have a copy stored on Model.copiesById' + ) + + todoClone.description = `I'm a clone, now!` + todoClone.commit() + + assert.equal( + todo.description, + `I'm a clone, now!`, + 'the original should have been updated' + ) + }) + + it('allows instance defaults, including getters and setters', function() { + const { BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'instance-defaults' + }) + + class Car extends BaseModel { + public id? + public year: number = 1905 + public make: string = 'Tesla' + public model: string = 'Roadster' + public get combined(): string { + return `${this.year} ${this.make} ${this.model}` + } + public set yearBeforeCurrent(year) { + if (year < this.year) { + this.year = year + } + } + + public constructor(data?, options?) { + super(data, options) + } + } + + const car = new Car() + + assert.equal(car.year, 1905, 'default year set') + assert.equal(car.make, 'Tesla', 'default make set') + assert.equal(car.model, 'Roadster', 'default model set') + assert.equal(car.combined, '1905 Tesla Roadster', 'getters work, too!') + + car.yearBeforeCurrent = 1900 + + assert.equal(car.combined, '1900 Tesla Roadster', 'setters work, too!') + }) + + it('allows overriding default values in the constructor', function() { + const { BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'instance-defaults' + }) + + class Car extends BaseModel { + public id? + public year: number = 1905 + public make: string = 'Tesla' + public model: string = 'Roadster' + + public constructor(data?, options?) { + super(data, options) + if (this.make === 'Tesla') { + this.make = 'Porsche' + } + } + } + + const car = new Car() + + assert.equal(car.make, 'Porsche', 'default make set') + }) + + it(`uses the class defaults if you don't override them in the constructor`, function() { + const { BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'instance-defaults' + }) + + class Person extends BaseModel { + public id? + public firstName: string = 'Harry' + public location: Location = { + coordinates: [0, 0] + } + + public constructor(data?, options?) { + // Calling super calls the BaseModel constructor, which merges the data + // onto `this`. + super(data, options) + + // Once the BaseModel constructor has finished, the props in the class + // definition are applied to `this` before running any additional code in the + // extending class's constructor. This means that at this point, all + // new instances have `location.coordinates = [0, 0]` + + // Since we're not re-applying the `data` to `this`, the class defaults have + // overwritten whatever we passed in. + return this + } + } + + const location: Location = { + coordinates: [1, 1] + } + + const person1 = new Person({ firstName: 'Marshall', location }) + const person2 = new Person({ firstName: 'Austin', location }) + const areSame = person1.location === person2.location + + assert(!areSame, 'the locations are different objects') + assert(person1.firstName === 'Harry', 'the defaults replaced our args') + assert(person2.firstName === 'Harry', 'the defaults replaced our args') + + // See, even the location we passed in was overwritten by the defaults. + assert.deepEqual(person1.location.coordinates, [0, 0], 'defaults won') + }) + + it('does not share nested objects between instances when you override class defaults in the constructor', function() { + const { BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'instance-defaults' + }) + + class Person extends BaseModel { + public id? + public firstName: string + public location: Location = { + coordinates: [0, 0] + } + + public constructor(data?, options?) { + // Pass { merge: false } in the third arg to prevent BaseModel from + // doing its own merge + super(data, options, { merge: false }) + + // Calling merge here overwrites the Class's default location. + // You could also write `this.location = data.location` + return Person.merge(this, data) + } + } + + const location: Location = { + coordinates: [1, 1] + } + + // Look, I'm passing in location with coordinates [1, 1] + const person1 = new Person({ firstName: 'Marshall', location }) + const person2 = new Person({ firstName: 'Austin', location }) + const areSame = person1.location === person2.location + + // But the objects are distinct because they've been merged in the constructor + assert(!areSame, 'the locations are different objects') + }) + + it('allows passing instanceDefaults in the service plugin options', function() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'instance-defaults' + }) + + class Person extends BaseModel { + public constructor(data?, options?) { + super(data, options, { merge: false }) + } + } + + const location: Location = { + coordinates: [1, 1] + } + + new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Person, + service: feathersClient.service('people'), + instanceDefaults: () => ({ + firstName: 'Harry', + lastName: 'Potter', + location, + get fullName() { + return `${this.firstName} ${this.lastName}` + }, + set fullName(val) { + const [firstName, lastName] = val.split(' ') + Object.assign(this, { firstName, lastName }) + } + }) + }) + ] + }) + + const person1 = new Person({ firstName: 'Marshall', lastName: 'Thompson' }) + const person2 = new Person({ + firstName: 'Kai', + location: { coordinates: [0, 0] }, + fullName: 'Jerry Seinfeld' + }) + const areSame = person1.location === person2.location + assert(!areSame, 'nested objects are unique') + + assert.equal(person1.lastName, 'Thompson', 'person1 has correct lastName') + assert.equal(person2.lastName, 'Potter', 'person2 got default lastName') + assert.deepEqual( + person1.location.coordinates, + [1, 1], + 'person1 got default location' + ) + assert.deepEqual( + person2.location.coordinates, + [0, 0], + 'person2 got provided location' + ) + assert.equal(person1.fullName, 'Marshall Thompson', 'getter is in place') + assert.equal(person2.fullName, 'Kai Potter', 'getter is still in place') + + person1.fullName = 'Marshall Me' + person2.fullName = 'Kai Me' + + assert.equal(person1.firstName, 'Marshall', 'firstName was set') + assert.equal(person1.lastName, 'Me', 'lastName was set') + assert.equal(person2.firstName, 'Kai', 'firstName was set') + assert.equal(person2.lastName, 'Me', 'lastName was set') + }) +}) diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 96b6067b..88cf5201 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -305,223 +305,42 @@ describe.skip('Service Module', function() { }) it('ignores when new data with matching id has fewer props than current record', function() { - const { module, owners } = this + const { serviceTodo, owners } = this const newData = { id: 1, owners } - const newTodo = new module.constructor(newData) + const newTodo = new serviceTodo.constructor(newData) - assert(newTodo === module, 'the records are the same') + assert(newTodo === serviceTodo, 'the records are the same') assert( - module.description === 'Do the dishes', + serviceTodo.description === 'Do the dishes', 'the existing attributes remained in place' ) assert( - module.isComplete === false, + serviceTodo.isComplete === false, 'the existing attributes remained in place' ) }) it('updates the new record when non-null, non-undefined values do not match', function() { - const { module, owners } = this + const { serviceTodo, owners } = this const newData = { id: 1, description: 'Do the mopping', isComplete: true, owners } - const newTodo = new module.constructor(newData) + const newTodo = new serviceTodo.constructor(newData) - assert(newTodo === module, 'the records are the same') + assert(newTodo === serviceTodo, 'the records are the same') assert( - module.description === 'Do the mopping', + serviceTodo.description === 'Do the mopping', 'non-matching string was updated' ) - assert(module.isComplete === true, 'non-matching boolean was updated') - }) - }) - - describe('Models - Default Values', function() { - beforeEach(function() { - const { makeServicePlugin, ServiceTodo, Person, Car, Group } = this - - const taskDefaults = (this.taskDefaults = { - id: null, - description: '', - isComplete: false - }) - - // TODO: Do Something with this! - const instanceDefaultsForPerson = { - firstName: '', - lastName: '', - location: { - coordinates: [-111.549668, 39.014] - }, - get fullName() { - return `${this.firstName} ${this.lastName}` - }, - todos({ store }) { - console.log(Object.keys(store)) - } - } - const instanceDefaultsForCars = { - keepCopiesInStore: true, - instanceDefaults: taskDefaults - } - const instanceDefaultsForGroups = function instanceDefaults() { - return { - name: '', - get todos() { - return models.Todo.findInStore({ query: {} }).data - } - } - } - this.store = new Vuex.Store({ - plugins: [ - makeServicePlugin({ - Model: ServiceTodo, - service: feathersClient.service('service-todos') - }), - makeServicePlugin({ - Model: Person, - service: feathersClient.service('people') - }), - makeServicePlugin({ - Model: Car, - service: feathersClient.service('cars') - }), - makeServicePlugin({ - Model: Group, - service: feathersClient.service('groups') - }) - ] - }) - this.Todo = ServiceTodo - this.Task = models.Task - this.Person = models.Person - this.Group = models.Group - }) - - // store.commit('todos/addItem', data) - - it('models default to an empty object', function() { - const { Todo } = this - const module = new Todo() - - assert.deepEqual(module, {}, 'default model is an empty object') - }) - - // it('stores clones in Model.copiesById by default', function() { - // const module = new ServiceTodo({ id: 1, description: 'Do something' }) - - // assert.deepEqual( - // ServiceTodo.copiesById, - // {}, - // 'Model.copiesById should start out empty' - // ) - - // const moduleClone = module.clone() - // assert( - // ServiceTodo.copiesById[1], - // 'should have a copy stored on Model.copiesById' - // ) - - // // moduleClone.description = 'Do something else' - // // moduleClone.commit() - - // assert.equal( - // module.description, - // 'Do something else', - // 'the original should have been updated' - // ) - // }) - - it('allows customizing the default values for a model', function() { - const { Task, taskDefaults } = this - const task = new Task() - - assert.deepEqual( - task, - taskDefaults, - 'the instance had the customized values' - ) - }) - - it('allows model classes to be customized with es5 getters', function() { - const { Person } = this - const person = new Person({ - firstName: 'Marshall', - lastName: 'Thompson' - }) - - assert.equal( - person.fullName, - `Marshall Thompson`, - 'the es5 getter returned the correct value' - ) - }) - - it('instanceDefaults can be a function that receives the store', function() { - const { Group } = this - const group = new Group({ - name: 'test' - }) - assert( - Array.isArray(group.todos), - 'instanceDefaults correctly assigned as function' - ) - }) - - it('does not allow sharing of deeply nested objects between instances', function() { - const { Person } = this - const person1 = new Person({ - firstName: 'Marshall', - lastName: 'Thompson' - }) - const person2 = new Person({ firstName: 'Austin', lastName: 'Thompson' }) - - person1.location.coordinates[0] = 5 - - assert.equal( - person2.location.coordinates[0], - -111.549668, - 'the value was not shared' - ) - }) - - it('keeps the options on the Model', function() { - const { Task, taskDefaults } = this - const options = { - actions: {}, - apiPrefix: '', - autoRemove: false, - debug: false, - enableEvents: true, - addOnUpsert: false, - diffOnPatch: false, - skipRequestIfExists: false, - getters: {}, - models, - idField: 'id', - instanceDefaults: taskDefaults, - keepCopiesInStore: true, - modelName: '', - mutations: {}, - nameStyle: 'short', - preferUpdate: false, - replaceItems: false, - paramsForServer: [], - whitelist: [], - state: {} - } - - assert.deepEqual( - Task.options, - options, - 'The Model.options object should be in place' + serviceTodo.isComplete === true, + 'non-matching boolean was updated' ) }) }) diff --git a/test/service-module/types.ts b/test/service-module/types.ts index 84e102e0..378d9aeb 100644 --- a/test/service-module/types.ts +++ b/test/service-module/types.ts @@ -36,3 +36,7 @@ export interface PaginationState { ip: number total: number } + +export interface Location { + coordinates: number[] +} From 8bf527e6916ee2a20a55e184ad615fc967286643 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 28 Mar 2019 20:56:17 -0600 Subject: [PATCH 067/404] Add support for tempIds --- package-lock.json | 5 + package.json | 1 + src/index.ts | 1 + src/service-module/make-model.ts | 71 +++++----- src/service-module/notes.md | 6 + src/service-module/service-module.actions.ts | 8 +- .../service-module.mutations.ts | 53 ++++---- src/service-module/service-module.state.ts | 1 + src/service-module/types.ts | 2 + src/utils.ts | 24 ++-- .../make-service-plugin.test.ts | 2 + .../model-instance-defaults.test.ts | 83 +++++++++++- test/service-module/model-temp-ids.test.ts | 122 ++++++++++++++++++ test/service-module/types.ts | 1 + 14 files changed, 303 insertions(+), 77 deletions(-) create mode 100644 test/service-module/model-temp-ids.test.ts diff --git a/package-lock.json b/package-lock.json index 5a17b69a..0d17e0e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6878,6 +6878,11 @@ "unzip": "~0.1.9" } }, + "bson-objectid": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/bson-objectid/-/bson-objectid-1.2.4.tgz", + "integrity": "sha512-z511nO3HgvLpB0Ax2+kfM2HRfgGKB0VbMnRKh5yNM9Eoh2o1/DRFXBrsoTpvjR09vNIHUMUmcwFFYhSU+0PBGQ==" + }, "buffer": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.0.8.tgz", diff --git a/package.json b/package.json index febff351..d9019645 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "@feathersjs/adapter-commons": "^2.0.0", "@feathersjs/commons": "^4.0.0", "@feathersjs/errors": "^3.3.6", + "bson-objectid": "^1.2.4", "debug": "^4.1.1", "deep-diff": "^1.0.2", "fast-copy": "^1.2.3", diff --git a/src/index.ts b/src/index.ts index 3be1b73a..70492e35 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,6 +22,7 @@ const defaultOptions: FeathersVuexOptions = { diffOnPatch: true, // Only send changed data on patch. Sends the full object if set to false. enableEvents: true, // Listens to socket.io events when available idField: 'id', // The field in each record that will contain the id + tempIdField: '__id', debug: false, // Set to true to enable logging messages. keepCopiesInStore: false, // Set to true to store cloned copies in the store instead of on the Model. nameStyle: 'short', // Determines the source of the module name. 'short', 'path', or 'explicit' diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 03da0701..03146cac 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -11,8 +11,9 @@ import { get as _get } from 'lodash' interface BaseConstructor { store: {} } -interface BaseModelConstructorOptions { - isClone?: boolean +interface BaseModelInstanceOptions { + clone?: boolean + commit?: boolean } interface ChildClassOptions { merge?: boolean @@ -41,6 +42,7 @@ export default function makeModel(options: FeathersVuexOptions) { public static instanceDefaults public static idField: string = options.idField + public static tempIdField: string = options.tempIdField public static preferUpdate: boolean = options.preferUpdate public static serverAlias: string = options.serverAlias @@ -49,31 +51,33 @@ export default function makeModel(options: FeathersVuexOptions) { protected __isClone: boolean + public __id: string public data: Record public static merge = mergeWithAccessors public constructor( data, - options: BaseModelConstructorOptions = {}, + options: BaseModelInstanceOptions = {}, childClassOptions: ChildClassOptions = { merge: true } ) { data = data || {} const { merge } = childClassOptions - const { idField } = BaseModel - const id = data[idField] - const hasValidId = !options.isClone && id !== null && id !== undefined + const { idField, tempIdField } = BaseModel + const id = data[idField] || data[tempIdField] + const hasValidId = id !== null && id !== undefined - // Update original item if it already exists. - if (hasValidId) { + // If it already exists, update the original and return + if (hasValidId && !options.clone) { const existingItem = BaseModel.getFromStore(id) if (existingItem) { - BaseModel.commit('updateItem', data) + BaseModel._commit('updateItem', data) return existingItem } } - if (options.isClone) { + // Mark as a clone + if (options.clone) { Object.defineProperty(this, '__isClone', { value: true, enumerable: false, @@ -81,6 +85,7 @@ export default function makeModel(options: FeathersVuexOptions) { }) } + // Setup instanceDefaults, separate out accessors if (BaseModel.instanceDefaults) { const instanceDefaults = BaseModel.instanceDefaults() const separatedDefaults = separateAccessors(instanceDefaults) @@ -90,11 +95,13 @@ export default function makeModel(options: FeathersVuexOptions) { // Handles Vue objects or regular ones. We can't simply assign or return // the data due to how Vue wraps everything into an accessor. - mergeWithAccessors(this, data) + if (merge !== false) { + mergeWithAccessors(this, data) + } // Add the item to the store - if (hasValidId && merge !== false) { - BaseModel.commit('addItem', this) + if (!options.clone && options.commit !== false && BaseModel.store) { + BaseModel._commit('addItem', this) } return this } @@ -104,26 +111,26 @@ export default function makeModel(options: FeathersVuexOptions) { } public static find(params) { - this.dispatch('find', params) + BaseModel._dispatch('find', params) } public static findInStore(params) { - return BaseModel.getters('find', params) + return BaseModel._getters('find', params) } public static get(id, params) { if (params) { - return BaseModel.dispatch('get', [id, params]) + return BaseModel._dispatch('get', [id, params]) } else { - return BaseModel.dispatch('get', id) + return BaseModel._dispatch('get', id) } } public static getFromStore(id, params?) { if (params) { - return BaseModel.getters('get', [id, params]) + return BaseModel._getters('get', [id, params]) } else { - return BaseModel.getters('get', id) + return BaseModel._getters('get', id) } } @@ -132,7 +139,7 @@ export default function makeModel(options: FeathersVuexOptions) { * @param method the vuex getter name without the namespace * @param payload if provided, the getter will be called as a function */ - public static getters(name: string, payload?: any) { + public static _getters(name: string, payload?: any) { if (payload !== undefined) { return BaseModel.store.getters[`${BaseModel.namespace}/${name}`]( payload @@ -146,7 +153,7 @@ export default function makeModel(options: FeathersVuexOptions) { * @param method the vuex mutation name without the namespace * @param payload the payload for the mutation */ - public static commit(method: string, payload: any): void { + public static _commit(method: string, payload: any): void { BaseModel.store.commit(`${BaseModel.namespace}/${method}`, payload) } /** @@ -154,7 +161,7 @@ export default function makeModel(options: FeathersVuexOptions) { * @param method the vuex action name without the namespace * @param payload the payload for the action */ - public static dispatch(method: string, payload: any) { + public static _dispatch(method: string, payload: any) { return BaseModel.store.dispatch( `${BaseModel.namespace}/${method}`, payload @@ -168,7 +175,7 @@ export default function makeModel(options: FeathersVuexOptions) { if (this.__isClone) { throw new Error('You cannot clone a copy') } - const id = this[BaseModel.idField] + const id = this[BaseModel.idField] || this[BaseModel.tempIdField] return this._clone(id) } @@ -179,19 +186,18 @@ export default function makeModel(options: FeathersVuexOptions) { store.commit(`${namespace}/createCopy`, id) if (keepCopiesInStore) { - return BaseModel.getters('getCopyById', id) + return BaseModel._getters('getCopyById', id) } else { return copiesById[id] } } - /** * Reset a clone to match the instance in the store. */ public reset() { if (this.__isClone) { const id = this[BaseModel.idField] - BaseModel.commit('resetCopy', id) + BaseModel._commit('resetCopy', id) } else { throw new Error('You cannot reset a non-copy') } @@ -203,11 +209,11 @@ export default function makeModel(options: FeathersVuexOptions) { public commit() { if (this.__isClone) { const id = this[BaseModel.idField] - BaseModel.commit('commitCopy', id) + BaseModel._commit('commitCopy', id) return this } else { - throw new Error('You cannnot call commit on a non-copy') + throw new Error('You cannot call commit on a non-copy') } } @@ -227,12 +233,11 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public create(params) { - const { store } = BaseModel const data = Object.assign({}, this) if (data[options.idField] === null) { delete data[options.idField] } - return BaseModel.dispatch('create', [data, params]) + return BaseModel._dispatch('create', [data, params]) } /** @@ -248,7 +253,7 @@ export default function makeModel(options: FeathersVuexOptions) { ) return Promise.reject(error) } - return BaseModel.dispatch('patch', [ + return BaseModel._dispatch('patch', [ this[BaseModel.idField], this, params @@ -268,7 +273,7 @@ export default function makeModel(options: FeathersVuexOptions) { ) return Promise.reject(error) } - return BaseModel.dispatch('update', [ + return BaseModel._dispatch('update', [ this[BaseModel.idField], this, params @@ -280,7 +285,7 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public remove(params) { - return BaseModel.dispatch('remove', [this[BaseModel.idField], params]) + return BaseModel._dispatch('remove', [this[BaseModel.idField], params]) } } addModel(BaseModel) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index ecc38f9e..042536aa 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -83,6 +83,12 @@ created () { } ``` +## Support for Temporary Records + +Feathers-Vuex 2.0 supports tracking temporary items and automatically assigns a temporary id (customizable using the `options.tempIdField`) and adds the records to the `state.tempsById` field. + +Previously, when a record didn't have an `[idField]`, a console.error would ask if you had configured the `idField` option. Because of the new ability to handle temporary records, a message is only logged when assigning a temporary id to a record. The `checkId` utility function has been removed, since this was its main purpose. + ## Changes to service module state The options are no longer at the root level of the service module state. You'll find them all in the options key: diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index f1a11904..14b2a505 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -3,7 +3,7 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import { checkId, diffFunctions } from '../utils' +import { diffFunctions } from '../utils' export default function makeServiceActions(service, { debug }) { const serviceActions = { @@ -253,9 +253,7 @@ export default function makeServiceActions(service, { debug }) { let id = item[idField] let existingItem = state.keyedById[id] - const isIdOk = checkId(id, item, debug) - - if (isIdOk) { + if (id !== null && id !== undefined) { existingItem ? toUpdate.push(item) : toAdd.push(item) } }) @@ -289,7 +287,7 @@ export default function makeServiceActions(service, { debug }) { let id = item[idField] let existingItem = state.keyedById[id] - const isIdOk = checkId(id, item, debug) + const isIdOk = id !== null && id !== undefined if ( service.FeathersVuexModel && diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 55daf1a8..106699e6 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -6,52 +6,54 @@ eslint import Vue from 'vue' import serializeError from 'serialize-error' import isObject from 'lodash.isobject' -import { checkId, updateOriginal, mergeWithAccessors } from '../utils' +import { updateOriginal, mergeWithAccessors, assignTempId } from '../utils' import { globalModels as models } from './global-models' import { get as _get } from 'lodash' export default function makeServiceMutations() { function addItems(state, items) { - const { idField, debug, servicePath, serverAlias, modelName } = state - const Model = _get(models, `[${state.serverAlias}][${modelName}]`) + const { serverAlias, idField, tempIdField, modelName } = state + const Model = _get(models, `[${serverAlias}][${modelName}]`) const BaseModel = _get(models, `[${state.serverAlias}].BaseModel`) - let newKeyedById = { ...state.keyedById } + const newKeyedById = { ...state.keyedById } + const newTempsById = { ...state.tempsById } for (let item of items) { - let id = item[idField] - const isIdOk = checkId(id, item, debug) + const id = item[idField] + const isTemp = id === null || id === undefined - if (isIdOk) { - if (Model && !(item instanceof BaseModel) && !(item instanceof Model)) { - item = new Model(item) - } + if (Model && !(item instanceof BaseModel) && !(item instanceof Model)) { + item = new Model(item) + } + if (isTemp) { + if (!item[tempIdField]) { + var tempId = assignTempId(state, item) + } + newTempsById[tempId] = item + } else { // Only add the id if it's not already in the `ids` list. if (!state.ids.includes(id)) { state.ids.push(id) } - newKeyedById[id] = item } } state.keyedById = newKeyedById + state.tempsById = newTempsById } function updateItems(state, items) { - const { idField, replaceItems, addOnUpsert, debug, servicePath } = state - const Model = _get( - models, - `[${state.serverAlias}].byServicePath[${servicePath}]` - ) + const { idField, replaceItems, addOnUpsert, serverAlias, modelName } = state + const Model = _get(models, `[${serverAlias}][${modelName}]`) for (let item of items) { let id = item[idField] - const isIdOk = checkId(id, item, debug) // Update the record - if (isIdOk) { + if (id !== null && id !== undefined) { if (state.ids.includes(id)) { // Completely replace the item if (replaceItems) { @@ -92,9 +94,9 @@ export default function makeServiceMutations() { }, removeItem(state, item) { - const { idField, debug } = state + const { idField } = state const idToBeRemoved = isObject(item) ? item[idField] : item - const isIdOk = checkId(idToBeRemoved, item, debug) + const isIdOk = idToBeRemoved !== null && idToBeRemoved !== undefined const index = state.ids.findIndex(i => i === idToBeRemoved) if (isIdOk && index !== null && index !== undefined) { @@ -156,14 +158,14 @@ export default function makeServiceMutations() { // Creates a copy of the record with the passed-in id, stores it in copiesById createCopy(state, id) { const { servicePath, keepCopiesInStore } = state - const current = state.keyedById[id] + const current = state.keyedById[id] || state.tempsById[id] const Model = _get( models, `[${state.serverAlias}].byServicePath[${servicePath}]` ) if (Model) { - var model = new Model(current, { isClone: true }) + var model = new Model(current, { clone: true }) } else { var copyData = mergeWithAccessors({}, current) } @@ -172,6 +174,7 @@ export default function makeServiceMutations() { if (keepCopiesInStore) { state.copiesById[id] = item } else { + // Since it won't be added to the store, make it a Vue object if (!item.hasOwnProperty('__ob__')) { item = Vue.observable(item) } @@ -181,8 +184,7 @@ export default function makeServiceMutations() { // Resets the copy to match the original record, locally resetCopy(state, id) { - const { debug, servicePath, keepCopiesInStore } = state - checkId(id, undefined, debug) + const { servicePath, keepCopiesInStore } = state const Model = _get( models, `[${state.serverAlias}].byServicePath[${servicePath}]` @@ -198,8 +200,7 @@ export default function makeServiceMutations() { // Deep assigns copy to original record, locally commitCopy(state, id) { - const { debug, servicePath, keepCopiesInStore } = state - checkId(id, undefined, debug) + const { servicePath, keepCopiesInStore } = state const Model = _get( models, `[${state.serverAlias}].byServicePath[${servicePath}]` diff --git a/src/service-module/service-module.state.ts b/src/service-module/service-module.state.ts index d4a4a1a6..bd84bfb4 100644 --- a/src/service-module/service-module.state.ts +++ b/src/service-module/service-module.state.ts @@ -22,6 +22,7 @@ export default function makeDefaultState(servicePath, options) { ids: [], keyedById: {}, copiesById: {}, + tempsById: {}, idField, servicePath, autoRemove, diff --git a/src/service-module/types.ts b/src/service-module/types.ts index 432e79e8..1df6c443 100644 --- a/src/service-module/types.ts +++ b/src/service-module/types.ts @@ -10,6 +10,7 @@ export interface FeathersVuexOptions { diffOnPatch?: boolean enableEvents?: boolean idField?: string + tempIdField?: string keepCopiesInStore?: boolean nameStyle?: string paramsForServer?: string[] @@ -26,6 +27,7 @@ export interface MakeServicePluginOptions { diffOnPatch?: boolean enableEvents?: boolean idField?: string + tempIdField?: string nameStyle?: string namespace?: string preferUpdate?: boolean diff --git a/src/utils.ts b/src/utils.ts index 4dc33b9e..435baa0f 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -10,6 +10,7 @@ import { diff } from 'deep-diff' import Vue from 'vue' import fastCopy from 'fast-copy' import { isPlainObject as _isPlainObject, isObject as _isObject } from 'lodash' +import ObjectID from 'bson-objectid' export function stripSlashes(location) { return Array.isArray(location) @@ -153,17 +154,20 @@ export const initAuth = function initAuth(options) { return Promise.resolve(payload) } -export function checkId(id, item, debug) { - if (id === undefined || id === null) { - if (debug) { - console.error( - 'No id found for item. Do you need to customize the `idField`?', - item - ) - } - return false +/** + * Generate a new tempId and mark the record as a temp + * @param state + * @param item + */ +export function assignTempId(state, item) { + const { debug, tempIdField } = state + if (debug) { + console.info('assigning temporary id to item', item) } - return true + const newId = new ObjectID().toHexString() + item[tempIdField] = newId + item.__isTemp = true + return newId } // Creates a Model class name from the last part of the servicePath diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index 3b34fae8..d69975fd 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -54,6 +54,7 @@ describe('makeServicePlugin', function() { errorOnRemove: null, errorOnUpdate: null, idField: 'id', + tempIdField: '__id', ids: [], instanceDefaults: () => ({}), isCreatePending: false, @@ -74,6 +75,7 @@ describe('makeServicePlugin', function() { serverAlias: 'default', servicePath: 'todos', skipRequestIfExists: false, + tempsById: {}, whitelist: [] } diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts index 2ae739e6..98cca00d 100644 --- a/test/service-module/model-instance-defaults.test.ts +++ b/test/service-module/model-instance-defaults.test.ts @@ -147,7 +147,13 @@ describe('Models - Default Values', function() { const { Todo } = this const module = new Todo() - assert.deepEqual(module, {}, 'default model is an empty object') + const expectedProps = ['__id', '__isTemp'] + + assert.deepEqual( + Object.keys(module), + expectedProps, + 'default model is a temp' + ) }) it('adds new instances containing an id to the store', function() { @@ -329,14 +335,14 @@ describe('Models - Default Values', function() { assert(!areSame, 'the locations are different objects') }) - it('allows passing instanceDefaults in the service plugin options', function() { + it('RECOMMENDED: allows passing instanceDefaults in the service plugin options', function() { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { serverAlias: 'instance-defaults' }) class Person extends BaseModel { public constructor(data?, options?) { - super(data, options, { merge: false }) + super(data, options) } } @@ -397,4 +403,75 @@ describe('Models - Default Values', function() { assert.equal(person2.firstName, 'Kai', 'firstName was set') assert.equal(person2.lastName, 'Me', 'lastName was set') }) + + it.skip('instanceDefault accessors stay intact with clone and commit', function() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'instance-defaults' + }) + + class Person extends BaseModel { + public constructor(data?, options?) { + super(data, options, { merge: false }) + } + } + + const location: Location = { + coordinates: [1, 1] + } + + new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Person, + service: feathersClient.service('people'), + instanceDefaults: () => ({ + firstName: 'Harry', + lastName: 'Potter', + location, + get fullName() { + return `${this.firstName} ${this.lastName}` + }, + set fullName(val) { + const [firstName, lastName] = val.split(' ') + Object.assign(this, { firstName, lastName }) + } + }) + }) + ] + }) + + const person = new Person({ firstName: 'Marshall', lastName: 'Thompson' }) + + // Clone the person + const clone = person.clone() + + // Check the getter + clone.firstName = 'FeathersJS' + clone.lastName = 'Developer' + assert.equal(clone.fullName, 'FeathersJS Developer', 'getter is in place') + + // Check the setter + clone.fullName = 'Marshall Me' + assert.equal( + `${clone.firstName} ${clone.lastName}`, + 'Marshall Me', + 'Setter is in place' + ) + + // Commit the clone + clone.commit() + + //Check the getter + person.firstName = 'FeathersJS' + person.lastName = 'Developer' + assert.equal(person.fullName, 'FeathersJS Developer', 'getter is in place') + + // Check the setter + person.fullName = 'Scooby Doo' + assert.equal( + `${person.firstName} ${person.lastName}`, + 'Scooby Doo', + 'Setter is in place' + ) + }) }) diff --git a/test/service-module/model-temp-ids.test.ts b/test/service-module/model-temp-ids.test.ts new file mode 100644 index 00000000..f33c4c22 --- /dev/null +++ b/test/service-module/model-temp-ids.test.ts @@ -0,0 +1,122 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { ServiceState } from './types' +import { assert } from 'chai' +import feathersVuex from '../../src/index' +import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' +import { clearModels } from '../../src/service-module/global-models' +import Vuex from 'vuex' + +interface RootState { + transactions: ServiceState +} + +describe('Models - Default Values', function() { + beforeEach(() => { + clearModels() + }) + + it('adds tempIds for items without an [idField]', function() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + idField: '_id', + serverAlias: 'temp-ids' + }) + + class Transaction extends BaseModel { + public constructor(data?, options?) { + super(data, options) + } + } + + new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Transaction, + service: feathersClient.service('transactions') + }) + ] + }) + + const txn = new Transaction({ + description: 'Green Pasture - No More Dentists!', + website: 'https://www.greenpasture.org', + amount: 1.99 + }) + + // Make sure we got an id. + assert(txn.__id, 'the record got an __id') + + // It should be non-enumerable and non-writable + const desc = Object.getOwnPropertyDescriptor(txn, '__id') + assert(desc.enumerable, 'it is enumerable') + }) + + it('adds to state.tempsById', function() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + idField: '_id', + serverAlias: 'temp-ids' + }) + + class Transaction extends BaseModel { + public constructor(data?, options?) { + super(data, options) + } + } + + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Transaction, + service: feathersClient.service('transactions') + }) + ] + }) + + const txn = new Transaction({ + description: 'Amazon - Cure Teeth Book', + website: + 'https://www.amazon.com/Cure-Tooth-Decay-Cavities-Nutrition-ebook/dp/B004GB0JIM', + amount: 1.99 + }) + + // Make sure we got an id. + assert(store.state.transactions.tempsById[txn.__id], 'it is in the store') + }) + + it('clones into Model.copiesById', function() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + idField: '_id', + serverAlias: 'temp-ids' + }) + + class Transaction extends BaseModel { + public constructor(data?, options?) { + super(data, options) + } + } + + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Transaction, + service: feathersClient.service('transactions') + }) + ] + }) + + const txn = new Transaction({ + description: 'Robb Wolf - the Paleo Solution', + website: + 'https://robbwolf.com/shop-old/products/the-paleo-solution-the-original-human-diet/', + amount: 1.99 + }) + + txn.clone() + + // Make sure we got an id. + assert(Transaction.copiesById[txn.__id], 'it is in the copiesById') + }) +}) diff --git a/test/service-module/types.ts b/test/service-module/types.ts index 378d9aeb..6e10842d 100644 --- a/test/service-module/types.ts +++ b/test/service-module/types.ts @@ -22,6 +22,7 @@ export interface ServiceState { isRemovePending: boolean idField: string keyedById: {} + tempsById: {} namespace: string nameStyle: string // Should be enum of 'short' or 'path' pagination?: { From 6934913541e09834c4924e748b8b86a525f53656 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 28 Mar 2019 21:10:05 -0600 Subject: [PATCH 068/404] Temp clones should commit into tempsById --- src/service-module/make-model.ts | 2 +- .../service-module.mutations.ts | 5 ++- test/service-module/model-temp-ids.test.ts | 38 ++++++++++++++++++- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 03146cac..c1e32eac 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -208,7 +208,7 @@ export default function makeModel(options: FeathersVuexOptions) { */ public commit() { if (this.__isClone) { - const id = this[BaseModel.idField] + const id = this[BaseModel.idField] || this[BaseModel.tempIdField] BaseModel._commit('commitCopy', id) return this diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 106699e6..6468f4e5 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -210,7 +210,10 @@ export default function makeServiceMutations() { : Model && _get(Model, `copiesById[${id}]`) if (copy) { - mergeWithAccessors(state.keyedById[id], copy) + const original = copy.__isTemp + ? state.tempsById[id] + : state.keyedById[id] + mergeWithAccessors(original, copy) } }, diff --git a/test/service-module/model-temp-ids.test.ts b/test/service-module/model-temp-ids.test.ts index f33c4c22..d976de1e 100644 --- a/test/service-module/model-temp-ids.test.ts +++ b/test/service-module/model-temp-ids.test.ts @@ -116,7 +116,43 @@ describe('Models - Default Values', function() { txn.clone() - // Make sure we got an id. assert(Transaction.copiesById[txn.__id], 'it is in the copiesById') }) + + it('commits into store.tempsById', function() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + idField: '_id', + serverAlias: 'temp-ids' + }) + + class Transaction extends BaseModel { + public constructor(data?, options?) { + super(data, options) + } + } + + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Transaction, + service: feathersClient.service('transactions') + }) + ] + }) + + const txn = new Transaction({ + description: 'Rovit Monthly Subscription', + website: 'https://rovit.com', + amount: 1.99 + }) + + // Clone it, change it and commit it. + const clone = txn.clone() + clone.amount = 11.99 + clone.commit() + + const originalTemp = store.state.transactions.tempsById[txn.__id] + + assert.equal(originalTemp.amount, 11.99, 'original was updated') + }) }) From 8c7387a36409856f14372113f8df92357f0a11ac Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 28 Mar 2019 21:18:31 -0600 Subject: [PATCH 069/404] temp models can reset properly back to original --- src/service-module/make-model.ts | 2 +- .../service-module.mutations.ts | 5 ++- test/service-module/model-temp-ids.test.ts | 42 ++++++++++++++----- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index c1e32eac..0c4c828c 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -196,7 +196,7 @@ export default function makeModel(options: FeathersVuexOptions) { */ public reset() { if (this.__isClone) { - const id = this[BaseModel.idField] + const id = this[BaseModel.idField] || this[BaseModel.tempIdField] BaseModel._commit('resetCopy', id) } else { throw new Error('You cannot reset a non-copy') diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 6468f4e5..094ded6e 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -194,7 +194,10 @@ export default function makeServiceMutations() { : Model && _get(Model, `copiesById[${id}]`) if (copy) { - mergeWithAccessors(copy, state.keyedById[id]) + const original = copy.__isTemp + ? state.tempsById[id] + : state.keyedById[id] + mergeWithAccessors(copy, original) } }, diff --git a/test/service-module/model-temp-ids.test.ts b/test/service-module/model-temp-ids.test.ts index d976de1e..0606dfba 100644 --- a/test/service-module/model-temp-ids.test.ts +++ b/test/service-module/model-temp-ids.test.ts @@ -24,13 +24,11 @@ describe('Models - Default Values', function() { idField: '_id', serverAlias: 'temp-ids' }) - class Transaction extends BaseModel { public constructor(data?, options?) { super(data, options) } } - new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -39,7 +37,6 @@ describe('Models - Default Values', function() { }) ] }) - const txn = new Transaction({ description: 'Green Pasture - No More Dentists!', website: 'https://www.greenpasture.org', @@ -59,13 +56,11 @@ describe('Models - Default Values', function() { idField: '_id', serverAlias: 'temp-ids' }) - class Transaction extends BaseModel { public constructor(data?, options?) { super(data, options) } } - const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -91,13 +86,11 @@ describe('Models - Default Values', function() { idField: '_id', serverAlias: 'temp-ids' }) - class Transaction extends BaseModel { public constructor(data?, options?) { super(data, options) } } - const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -106,7 +99,6 @@ describe('Models - Default Values', function() { }) ] }) - const txn = new Transaction({ description: 'Robb Wolf - the Paleo Solution', website: @@ -124,13 +116,11 @@ describe('Models - Default Values', function() { idField: '_id', serverAlias: 'temp-ids' }) - class Transaction extends BaseModel { public constructor(data?, options?) { super(data, options) } } - const store = new Vuex.Store({ plugins: [ makeServicePlugin({ @@ -139,7 +129,6 @@ describe('Models - Default Values', function() { }) ] }) - const txn = new Transaction({ description: 'Rovit Monthly Subscription', website: 'https://rovit.com', @@ -155,4 +144,35 @@ describe('Models - Default Values', function() { assert.equal(originalTemp.amount, 11.99, 'original was updated') }) + + it('can reset a temp clone', function() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'temp-ids' + }) + class Transaction extends BaseModel { + public constructor(data?, options?) { + super(data, options) + } + } + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Transaction, + service: feathersClient.service('transactions') + }) + ] + }) + const txn = new Transaction({ + description: 'Rovit Monthly Subscription', + website: 'https://rovit.com', + amount: 1.99 + }) + + // Clone it, change it and commit it. + const clone = txn.clone() + clone.amount = 11.99 + clone.reset() + + assert.equal(clone.amount, 1.99, 'clone was reset') + }) }) From d4359884529ab038a799ab6f05a51ec18e928b4e Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 28 Mar 2019 22:59:18 -0600 Subject: [PATCH 070/404] Checkpoing --- src/service-module/make-model.ts | 41 +++-- src/service-module/make-service-plugin.ts | 34 ++-- src/service-module/types.ts | 1 + .../model-instance-defaults.test.ts | 4 +- test/service-module/model-methods.test.ts | 174 ++++++++++++++++++ test/service-module/service-module.test.ts | 137 +------------- 6 files changed, 226 insertions(+), 165 deletions(-) create mode 100644 test/service-module/model-methods.test.ts diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 0c4c828c..2e6e792a 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -6,10 +6,16 @@ eslint import { FeathersVuexOptions } from './types' import { globalModels, prepareAddModel } from './global-models' import { mergeWithAccessors, separateAccessors } from '../utils' -import { get as _get } from 'lodash' +import { get as _get, merge as _merge } from 'lodash' + +// A hack to prevent error with this.constructor.preferUpdate +interface Function { + preferUpdate: boolean +} interface BaseConstructor { store: {} + preferUpdate: boolean } interface BaseModelInstanceOptions { clone?: boolean @@ -33,13 +39,14 @@ export default function makeModel(options: FeathersVuexOptions) { return ExistingBaseModel } - abstract class BaseModel { + abstract class BaseModel { // Monkey patched onto the Model class in `makeServicePlugin()` public static store: Record public static namespace: string public static servicePath: string public static instanceDefaults + public static serialize public static idField: string = options.idField public static tempIdField: string = options.tempIdField @@ -140,12 +147,11 @@ export default function makeModel(options: FeathersVuexOptions) { * @param payload if provided, the getter will be called as a function */ public static _getters(name: string, payload?: any) { + const { namespace } = this.constructor.namespace if (payload !== undefined) { - return BaseModel.store.getters[`${BaseModel.namespace}/${name}`]( - payload - ) + return BaseModel.store.getters[`${namespace}/${name}`](payload) } else { - return BaseModel.store.getters[`${BaseModel.namespace}/${name}`] + return BaseModel.store.getters[`${namespace}/${name}`] } } /** @@ -154,7 +160,8 @@ export default function makeModel(options: FeathersVuexOptions) { * @param payload the payload for the mutation */ public static _commit(method: string, payload: any): void { - BaseModel.store.commit(`${BaseModel.namespace}/${method}`, payload) + const { namespace } = this.constructor.namespace + BaseModel.store.commit(`${namespace}/${method}`, payload) } /** * An alias for store.dispatch @@ -162,10 +169,8 @@ export default function makeModel(options: FeathersVuexOptions) { * @param payload the payload for the action */ public static _dispatch(method: string, payload: any) { - return BaseModel.store.dispatch( - `${BaseModel.namespace}/${method}`, - payload - ) + const { namespace } = this.constructor.namespace + return BaseModel.store.dispatch(`${namespace}/${method}`, payload) } /** @@ -222,8 +227,11 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public save(params) { - if (this[options.idField]) { - return options.preferUpdate ? this.update(params) : this.patch(params) + const id = this[options.idField] + if (id) { + const preferUpdate = Object.getPrototypeOf(this).constructor + .preferUpdate + return preferUpdate ? this.update(params) : this.patch(params) } else { return this.create(params) } @@ -287,6 +295,13 @@ export default function makeModel(options: FeathersVuexOptions) { public remove(params) { return BaseModel._dispatch('remove', [this[BaseModel.idField], params]) } + + public toJSON() { + const { serialize } = Object.getPrototypeOf(this).constructor + const obj = serialize(this) + const data = _merge({}, obj) + return data + } } addModel(BaseModel) return BaseModel diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index 34e21e02..8ec7b10d 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -17,7 +17,8 @@ const defaults = { getters: {}, // for custom getters mutations: {}, // for custom mutations actions: {}, // for custom actions - instanceDefaults: () => ({}) // Default instanceDefaults is an empty object + instanceDefaults: () => ({}), // Default instanceDefaults is an empty object + serialize: item => item // Default serialize function } /** @@ -36,7 +37,15 @@ export default function prepareMakeServicePlugin( */ return function makeServicePlugin(config: MakeServicePluginOptions) { const options = Object.assign({}, defaults, globalOptions, config) - const { Model, service, namespace, nameStyle, instanceDefaults } = options + const { + Model, + service, + namespace, + nameStyle, + instanceDefaults, + preferUpdate, + serialize + } = options if (!service) { throw new Error( @@ -63,21 +72,18 @@ export default function prepareMakeServicePlugin( const BaseModel = _get(globalModels, `[${options.serverAlias}].BaseModel`) if (BaseModel && !BaseModel.store) { Object.assign(BaseModel, { - store, - namespace: options.namespace, - servicePath, - instanceDefaults + store }) } // (2b^) Monkey patch the Model(s) and add to globalModels - if (!BaseModel || !(Model.prototype instanceof BaseModel)) { - Object.assign(Model, { - store, - namespace: options.namespace, - servicePath, - instanceDefaults - }) - } + Object.assign(Model, { + store, + namespace: options.namespace, + servicePath, + instanceDefaults, + serialize, + preferUpdate + }) addModel(Model) // (3^) Setup real-time events diff --git a/src/service-module/types.ts b/src/service-module/types.ts index 1df6c443..7ce5e9fa 100644 --- a/src/service-module/types.ts +++ b/src/service-module/types.ts @@ -33,6 +33,7 @@ export interface MakeServicePluginOptions { preferUpdate?: boolean servicePath?: string instanceDefaults?: () => {} + serialize?: () => {} state?: {} getters?: {} mutations?: {} diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts index 98cca00d..b9d2b76d 100644 --- a/test/service-module/model-instance-defaults.test.ts +++ b/test/service-module/model-instance-defaults.test.ts @@ -404,14 +404,14 @@ describe('Models - Default Values', function() { assert.equal(person2.lastName, 'Me', 'lastName was set') }) - it.skip('instanceDefault accessors stay intact with clone and commit', function() { + it('instanceDefault accessors stay intact with clone and commit', function() { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { serverAlias: 'instance-defaults' }) class Person extends BaseModel { public constructor(data?, options?) { - super(data, options, { merge: false }) + super(data, options) } } diff --git a/test/service-module/model-methods.test.ts b/test/service-module/model-methods.test.ts new file mode 100644 index 00000000..ffa103cd --- /dev/null +++ b/test/service-module/model-methods.test.ts @@ -0,0 +1,174 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { ServiceState } from './types' +import { assert } from 'chai' +import feathersVuex, { models } from '../../src/index' +import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' +import Vuex from 'vuex' + +interface TodoState extends ServiceState { + test: any + test2: { + test: boolean + } + isTrue: boolean +} +interface RootState { + todos: TodoState + tasks: ServiceState + tests: ServiceState + blah: ServiceState + things: ServiceState +} + +function makeContext() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'model-methods' + }) + class Task extends BaseModel { + public constructor(data?, options?) { + super(data, options) + } + } + class Todo extends BaseModel { + public constructor(data?, options?) { + super(data, options) + } + } + const store = new Vuex.Store({ + strict: true, + plugins: [ + makeServicePlugin({ + Model: Task, + service: feathersClient.service('tasks'), + preferUpdate: true + }), + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('todos') + }) + ] + }) + return { + BaseModel, + Task, + Todo, + store + } +} + +describe.only('Models - Methods', function() { + it('Model.find', function() { + const { Task } = makeContext() + + assert(typeof Task.find === 'function') + }) + + it('Model.findInStore', function() { + const { Task } = makeContext() + + assert(typeof Task.findInStore === 'function') + }) + + it('Model.get', function() { + const { Task } = makeContext() + + assert(typeof Task.get === 'function') + }) + + it('Model.getFromStore', function() { + const { Task } = makeContext() + + assert(typeof Task.getFromStore === 'function') + }) + + it('instance.save calls create with correct arguments', function() { + const { Task } = makeContext() + const module = new Task({ test: true }) + + Object.defineProperty(module, 'create', { + value(params) { + assert(arguments.length === 1, 'should have only called with params') + assert( + params === undefined, + 'no params should have been passed this time' + ) + } + }) + + module.save() + }) + + it('instance.save passes params to create', function() { + const { Task } = makeContext() + const task = new Task({ test: true }) + let called = false + + Object.defineProperty(task, 'create', { + value(params) { + assert(arguments.length === 1, 'should have only called with params') + assert(params.test, 'should have received params') + called = true + } + }) + + task.save({ test: true }) + assert(called, 'create should have been called') + }) + + it.only('instance.save passes params to patch', function() { + const { Todo } = makeContext() + const todo = new Todo({ id: 1, test: true }) + let called = false + + Object.defineProperty(todo, 'patch', { + value(params) { + assert(arguments.length === 1, 'should have only called with params') + assert(params.test, 'should have received params') + called = true + } + }) + + todo.save({ test: true }) + assert(called, 'patch should have been called') + }) + + it('instance.save passes params to update', function() { + const { Task } = makeContext() + Task.preferUpdate = true + + const task = new Task({ id: 1, test: true }) + let called = false + + Object.defineProperty(task, 'update', { + value(params) { + assert(arguments.length === 1, 'should have only called with params') + assert(params.test, 'should have received params') + called = true + } + }) + + task.save({ test: true }) + assert(called, 'update should have been called') + }) + + it('instance.toJSON', function() { + const { Task } = makeContext() + const task = new Task({ id: 1, test: true }) + + Object.defineProperty(task, 'getter', { + get() { + return `got'er` + } + }) + + assert.equal(task.getter, `got'er`) + + const json = task.toJSON() + + assert(json, 'got json') + }) +}) diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 88cf5201..31b314e6 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -95,7 +95,7 @@ function makeContext() { } } -describe.skip('Service Module', function() { +describe('Service Module', function() { beforeEach(() => { clearModels() }) @@ -345,141 +345,6 @@ describe.skip('Service Module', function() { }) }) - describe('Models - Methods', function() { - beforeEach(function() { - const { makeServicePlugin, Task, ServiceTodo, Item } = this - this.store = new Vuex.Store({ - strict: true, - plugins: [ - makeServicePlugin({ - Model: Task, - service: feathersClient.service('tasks'), - preferUpdate: true - }), - makeServicePlugin({ - Model: ServiceTodo, - service: feathersClient.service('service-todos') - }), - makeServicePlugin({ - Model: Item, - service: feathersClient.service('items') - }) - ] - }) - this.Todo = ServiceTodo - this.Task = models.Task - }) - - it('Model.find', function() { - const { Todo } = this - - assert(typeof Todo.find === 'function') - }) - - it('Model.findInStore', function() { - const { Todo } = this - - assert(typeof Todo.findInStore === 'function') - }) - - it('Model.get', function() { - const { Todo } = this - - assert(typeof Todo.get === 'function') - }) - - it('Model.getFromStore', function() { - const { Todo } = this - - assert(typeof Todo.getFromStore === 'function') - }) - - it('instance.save calls create with correct arguments', function() { - const { Todo } = this - const module = new Todo({ test: true }) - - Object.defineProperty(module, 'create', { - value(params) { - assert(arguments.length === 1, 'should have only called with params') - assert( - params === undefined, - 'no params should have been passed this time' - ) - } - }) - - module.save() - }) - - it('instance.save passes params to create', function() { - const { Todo } = this - const module = new Todo({ test: true }) - let called = false - - Object.defineProperty(module, 'create', { - value(params) { - assert(arguments.length === 1, 'should have only called with params') - assert(params.test, 'should have received params') - called = true - } - }) - - module.save({ test: true }) - assert(called, 'create should have been called') - }) - - it('instance.save passes params to patch', function() { - const { Todo } = this - const module = new Todo({ id: 1, test: true }) - let called = false - - Object.defineProperty(module, 'patch', { - value(params) { - assert(arguments.length === 1, 'should have only called with params') - assert(params.test, 'should have received params') - called = true - } - }) - - module.save({ test: true }) - assert(called, 'patch should have been called') - }) - - it('instance.save passes params to update', function() { - const { Task } = this - const task = new Task({ id: 1, test: true }) - let called = false - - Object.defineProperty(task, 'update', { - value(params) { - assert(arguments.length === 1, 'should have only called with params') - assert(params.test, 'should have received params') - called = true - } - }) - - task.save({ test: true }) - assert(called, 'update should have been called') - }) - - it('instance.toJSON', function() { - const { Task } = this - const task = new Task({ id: 1, test: true }) - - Object.defineProperty(task, 'getter', { - get() { - return `got'er` - } - }) - - assert.equal(task.getter, `got'er`) - - const json = task.toJSON() - - assert(json, 'got json') - }) - }) - describe('Models - modelName', function() { beforeEach(function() { const { makeServicePlugin, HotspotMedia, Media } = this From 5ee2150d9a4660f9eaf4ca51feed97b503c44d35 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 29 Mar 2019 19:22:50 -0600 Subject: [PATCH 071/404] Simplify makeModel --- src/service-module/make-model.ts | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 2e6e792a..c42b7ffa 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -13,10 +13,6 @@ interface Function { preferUpdate: boolean } -interface BaseConstructor { - store: {} - preferUpdate: boolean -} interface BaseModelInstanceOptions { clone?: boolean commit?: boolean @@ -39,15 +35,16 @@ export default function makeModel(options: FeathersVuexOptions) { return ExistingBaseModel } - abstract class BaseModel { - // Monkey patched onto the Model class in `makeServicePlugin()` - public static store: Record - public static namespace: string + abstract class BaseModel { + // Think of these as abstract static properties public static servicePath: string - + public static namespace: string public static instanceDefaults public static serialize + // Monkey patched onto the Model class in `makeServicePlugin()` + public static store: Record + public static idField: string = options.idField public static tempIdField: string = options.tempIdField public static preferUpdate: boolean = options.preferUpdate @@ -147,7 +144,7 @@ export default function makeModel(options: FeathersVuexOptions) { * @param payload if provided, the getter will be called as a function */ public static _getters(name: string, payload?: any) { - const { namespace } = this.constructor.namespace + const { namespace } = this.constructor as typeof BaseModel if (payload !== undefined) { return BaseModel.store.getters[`${namespace}/${name}`](payload) } else { @@ -160,7 +157,7 @@ export default function makeModel(options: FeathersVuexOptions) { * @param payload the payload for the mutation */ public static _commit(method: string, payload: any): void { - const { namespace } = this.constructor.namespace + const { namespace } = this.constructor as typeof BaseModel BaseModel.store.commit(`${namespace}/${method}`, payload) } /** @@ -169,7 +166,7 @@ export default function makeModel(options: FeathersVuexOptions) { * @param payload the payload for the action */ public static _dispatch(method: string, payload: any) { - const { namespace } = this.constructor.namespace + const { namespace } = this.constructor as typeof BaseModel return BaseModel.store.dispatch(`${namespace}/${method}`, payload) } From 0c01540da12c48b80029cf4f9b97833dc455c018 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 29 Mar 2019 22:32:44 -0600 Subject: [PATCH 072/404] Model Class Inheritance Tests --- test/service-module/model-tests.test.ts | 136 ++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 test/service-module/model-tests.test.ts diff --git a/test/service-module/model-tests.test.ts b/test/service-module/model-tests.test.ts new file mode 100644 index 00000000..224f0b7e --- /dev/null +++ b/test/service-module/model-tests.test.ts @@ -0,0 +1,136 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { assert } from 'chai' + +interface ModelOptions { + servicePath: string +} + +describe('TypeScript Class Inheritance', () => { + it('Can access static instanceDefaults from BaseModel', () => { + abstract class BaseModel { + public static instanceDefaults + public constructor(data, options?) { + const { instanceDefaults } = this.constructor as typeof BaseModel + const defaults = instanceDefaults(data, options) + assert( + defaults.description === 'default description', + 'We get defaults in the BaseModel constructor' + ) + Object.assign(this, defaults, data) + } + } + class Todo extends BaseModel { + public description: string + + public static instanceDefaults = (data, options) => ({ + description: 'default description' + }) + + public constructor(data, options?) { + super(data, options) + const { instanceDefaults } = this.constructor as typeof BaseModel + const defaults = instanceDefaults(data, options) + assert( + defaults.description === 'default description', + 'We get defaults in the Todo constructor, too' + ) + } + } + + const todo = new Todo({ + test: true + }) + + assert( + todo.description === 'default description', + 'got default description' + ) + }) + + it('Can access static instanceDefaults from two levels of inheritance', () => { + abstract class BaseModel { + public static instanceDefaults + public constructor(data, options?) { + const { instanceDefaults } = this.constructor as typeof BaseModel + const defaults = instanceDefaults(data, options) + assert( + defaults.description === 'default description', + 'We get defaults in the BaseModel constructor' + ) + Object.assign(this, defaults, data) + } + } + + function makeServiceModel(options) { + const { servicePath } = options + + class ServiceModel extends BaseModel { + public constructor(data, options: ModelOptions = { servicePath: '' }) { + options.servicePath = servicePath + super(data, options) + } + } + return ServiceModel + } + + class Todo extends makeServiceModel({ servicePath: 'todos' }) { + public description: string + + public static instanceDefaults = (data, options) => ({ + description: 'default description' + }) + } + + const todo = new Todo({ + test: true + }) + + assert( + todo.description === 'default description', + 'got default description' + ) + }) + + it('Can access static servicePath from Todo in BaseModel', () => { + abstract class BaseModel { + public static instanceDefaults + public static servicePath + public static namespace + + public constructor(data, options?) { + const { instanceDefaults, servicePath, namespace } = this + .constructor as typeof BaseModel + const defaults = instanceDefaults(data, options) + assert( + defaults.description === 'default description', + 'We get defaults in the BaseModel constructor' + ) + Object.assign(this, defaults, data, { + _options: { namespace, servicePath } + }) + } + } + + class Todo extends BaseModel { + public static namespace: string = 'todos' + public static servicePath: string = 'v1/todos' + + public description: string + public _options + + public static instanceDefaults = (data, models) => ({ + description: 'default description' + }) + } + + const todo = new Todo({ + test: true + }) + + assert(todo._options.servicePath === 'v1/todos', 'got static servicePath') + }) +}) From 9deb1a8e58bfc87f50c98e8ca0d8b7226424fead Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 00:24:27 -0600 Subject: [PATCH 073/404] Give global-models an any --- src/service-module/global-models.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/global-models.ts b/src/service-module/global-models.ts index faba1d21..7fafae9b 100644 --- a/src/service-module/global-models.ts +++ b/src/service-module/global-models.ts @@ -8,7 +8,7 @@ import { FeathersVuexOptions } from './types' /** * A global object that holds references to all Model Classes in the application. */ -export const globalModels: { [k: string]: Record } = {} +export const globalModels: { [k: string]: any } = {} /** * prepareAddModel wraps options in a closure around addModel From 64332edd97e6ce1e1b39cc431ee7b5bfeee18dbb Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 00:28:13 -0600 Subject: [PATCH 074/404] Use lodash instead of lodash.whatever packages --- src/service-module/make-service-module.ts | 3 +-- src/service-module/service-module.actions.ts | 2 +- src/service-module/service-module.getters.ts | 6 +++--- src/service-module/service-module.mutations.ts | 7 +++---- src/utils.ts | 12 +++++------- test/service-module/make-service-plugin.test.ts | 15 +++++++++------ 6 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/service-module/make-service-module.ts b/src/service-module/make-service-module.ts index 46010bf7..7b589792 100644 --- a/src/service-module/make-service-module.ts +++ b/src/service-module/make-service-module.ts @@ -3,8 +3,7 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import _omit from 'lodash.omit' -import _pick from 'lodash.pick' +import { omit as _omit, pick as _pick } from 'lodash' import makeDefaultState from './service-module.state' import makeGetters from './service-module.getters' diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 14b2a505..0a069731 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -3,7 +3,7 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import { diffFunctions } from '../utils' +import { observableDiff, applyChange } from 'deep-diff' export default function makeServiceActions(service, { debug }) { const serviceActions = { diff --git a/src/service-module/service-module.getters.ts b/src/service-module/service-module.getters.ts index 22aa1910..922352dc 100644 --- a/src/service-module/service-module.getters.ts +++ b/src/service-module/service-module.getters.ts @@ -6,7 +6,7 @@ eslint import sift from 'sift' import commons from '@feathersjs/commons' import dbCommons from '@feathersjs/adapter-commons' -import omit from 'lodash.omit' +import { omit as _omit } from 'lodash' const { _ } = commons const { filterQuery, sorter, select } = dbCommons @@ -23,11 +23,11 @@ export default function makeServiceGetters() { find: state => params => { params = params || {} const { paramsForServer, whitelist } = state - const q = omit(params.query || {}, paramsForServer) + const q = _omit(params.query || {}, paramsForServer) const customOperators = Object.keys(q).filter( k => k[0] === '$' && !defaultOps.includes(k) ) - const cleanQuery = omit(q, customOperators) + const cleanQuery = _omit(q, customOperators) const { query, filters } = filterQuery(cleanQuery, { operators: additionalOperators.concat(whitelist) diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 094ded6e..a5ac6a04 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -5,10 +5,9 @@ eslint */ import Vue from 'vue' import serializeError from 'serialize-error' -import isObject from 'lodash.isobject' import { updateOriginal, mergeWithAccessors, assignTempId } from '../utils' import { globalModels as models } from './global-models' -import { get as _get } from 'lodash' +import { get as _get, isObject as _isObject } from 'lodash' export default function makeServiceMutations() { function addItems(state, items) { @@ -95,7 +94,7 @@ export default function makeServiceMutations() { removeItem(state, item) { const { idField } = state - const idToBeRemoved = isObject(item) ? item[idField] : item + const idToBeRemoved = _isObject(item) ? item[idField] : item const isIdOk = idToBeRemoved !== null && idToBeRemoved !== undefined const index = state.ids.findIndex(i => i === idToBeRemoved) @@ -114,7 +113,7 @@ export default function makeServiceMutations() { ) } // Make sure we have an array of ids. Assume all are the same. - const containsObjects = items[0] && isObject(items[0]) + const containsObjects = items[0] && _isObject(items[0]) const idsToRemove = containsObjects ? items.map(item => item[idField]) : items diff --git a/src/utils.ts b/src/utils.ts index 435baa0f..34f0ca33 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -3,13 +3,15 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import _trim from 'lodash.trim' import decode from 'jwt-decode' import inflection from 'inflection' -import { diff } from 'deep-diff' import Vue from 'vue' import fastCopy from 'fast-copy' -import { isPlainObject as _isPlainObject, isObject as _isObject } from 'lodash' +import { + isPlainObject as _isPlainObject, + isObject as _isObject, + trim as _trim +} from 'lodash' import ObjectID from 'bson-objectid' export function stripSlashes(location) { @@ -216,10 +218,6 @@ export function getServiceCapitalization(servicePath) { return name } -export function diffFunctions() { - return diff -} - export function updateOriginal(newData, existingItem) { Object.keys(newData).forEach(key => { const newProp = newData[key] diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index d69975fd..4057afef 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -19,11 +19,14 @@ describe('makeServicePlugin', function() { }) it('registers the vuex module with options', function() { + interface RootState { + todos: { options: {} } + } + const serverAlias = 'default' const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { serverAlias }) - const servicePath = 'todos' class Todo extends BaseModel { public servicePath = servicePath @@ -33,9 +36,6 @@ describe('makeServicePlugin', function() { Model: Todo, service: feathers.service(servicePath) }) - interface RootState { - todos: { options: {} } - } const store = new Vuex.Store({ plugins: [todosPlugin] }) const keys = Object.keys(store.state.todos) @@ -75,15 +75,18 @@ describe('makeServicePlugin', function() { serverAlias: 'default', servicePath: 'todos', skipRequestIfExists: false, + serialize: item => item, tempsById: {}, whitelist: [] } assert.deepEqual( - _omit(received, ['instanceDefaults']), - _omit(expected, ['instanceDefaults']), + _omit(received, ['instanceDefaults', 'serialize']), + _omit(expected, ['instanceDefaults', 'serialize']), 'The module was registered.' ) + assert.equal(typeof received.serialize, 'function') + assert.equal(typeof received.instanceDefaults, 'function') }) it('sets up Model.store && service.FeathersVuexModel', function() { From 325df2396aee5894eb2a5316f8a6e40eaddf1aa7 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 00:53:35 -0600 Subject: [PATCH 075/404] Upgrade all packages --- package-lock.json | 192 ++++++++++++++++++++++------------------------ package.json | 23 +++--- 2 files changed, 106 insertions(+), 109 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0d17e0e6..1164118d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3205,37 +3205,20 @@ } }, "@feathersjs/authentication-client": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@feathersjs/authentication-client/-/authentication-client-1.0.10.tgz", - "integrity": "sha512-a3ISiKIbId5ZZsfxR2WrlQzcMzCWVWP1okRG7wLki/zcGJ2l+Prcoh+axsJoxyRJFtpf5VhdpGkVQr8Yw3tdVQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@feathersjs/authentication-client/-/authentication-client-1.0.11.tgz", + "integrity": "sha512-4CWQdmdRINMMqHT1/g0N5jqw16u1RjaSPhlZtJZ0OLdqgN3tl5wL+Lb8ThPxihvt1WHiOdwGt141LvWQ446Bsw==", "dev": true, "requires": { "@feathersjs/errors": "^3.3.6", "debug": "^4.0.0", "jwt-decode": "^2.1.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "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 - } } }, "@feathersjs/authentication-jwt": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@feathersjs/authentication-jwt/-/authentication-jwt-2.0.9.tgz", - "integrity": "sha512-DFpexhyd4WXvVWnMJdHr8IpRFkcnYo2urWc+3d6RS5dt12hxm69zLu0R6TmZhxwV1hpTW4Kmz8sFAgt/aLMQAw==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@feathersjs/authentication-jwt/-/authentication-jwt-2.0.10.tgz", + "integrity": "sha512-4IVBXDa4w17rroWiSM6LpSzUVG9Za1x1t7fioSObYt60PTkY7QunZt77GkdWfTNLNFvV++VVZ5tGFN6kfIKqCA==", "dev": true, "requires": { "@feathersjs/errors": "^3.3.6", @@ -3244,29 +3227,12 @@ "lodash.omit": "^4.5.0", "lodash.pick": "^4.4.0", "passport-jwt": "^4.0.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "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 - } } }, "@feathersjs/client": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@feathersjs/client/-/client-3.7.7.tgz", - "integrity": "sha512-xCD+8Sd495GglSUOxHh6qS55Strgd6mUszumRSFjCwI9Fqz6AXKMWbWAIs2SAmDvYnoNGsrGZxnWNK4qXoYTJg==", + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/@feathersjs/client/-/client-3.7.8.tgz", + "integrity": "sha512-SsLVU6wq1PToBCC3XAvMRV18RBqCG1Ipt0G0+cyNKvYpcKW238Prvw7uYyAxPyQw+JL1c0xHkyDId03Duu6ZTA==", "dev": true }, "@feathersjs/commons": { @@ -3480,6 +3446,30 @@ "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", "dev": true }, + "@types/deep-diff": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/deep-diff/-/deep-diff-1.0.0.tgz", + "integrity": "sha512-ENsJcujGbCU/oXhDfQ12mSo/mCBWodT2tpARZKmatoSrf8+cGRCPi0KVj3I0FORhYZfLXkewXu7AoIWqiBLkNw==" + }, + "@types/feathersjs__feathers": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/feathersjs__feathers/-/feathersjs__feathers-3.1.1.tgz", + "integrity": "sha512-4/IC/qQI+V9WbhmQnMvuQctcURvdyVvSJ+3JANVEqedzvApW/P8TUfVHeJ/k7EaXBgglShI6rNSKwZTVNOiVRw==", + "requires": { + "@types/feathersjs__feathers": "*", + "@types/node": "*" + } + }, + "@types/inflection": { + "version": "1.5.28", + "resolved": "https://registry.npmjs.org/@types/inflection/-/inflection-1.5.28.tgz", + "integrity": "sha1-Q9VeDXLPMzot/9nE7AQHRVobCTE=" + }, + "@types/lodash": { + "version": "4.14.123", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.123.tgz", + "integrity": "sha512-pQvPkc4Nltyx7G1Ww45OjVqUsJP4UsZm+GWJpigXgkikZqJgRm4c48g027o6tdgubWHwFRF15iFd+Y4Pmqv6+Q==" + }, "@types/mocha": { "version": "5.2.6", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.6.tgz", @@ -3489,8 +3479,15 @@ "@types/node": { "version": "11.11.6", "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", - "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==", - "dev": true + "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==" + }, + "@types/npm": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/@types/npm/-/npm-2.0.30.tgz", + "integrity": "sha512-juetEKXQJZlVrhRg3Z8WAKFeUr2sRapp8IGOxOaWI07rrrt0T0lgLiv7NtpqoP6Ul/If5vD0/17C0Q84saiwBg==", + "requires": { + "@types/node": "*" + } }, "@types/socket.io": { "version": "1.4.40", @@ -8823,9 +8820,9 @@ } }, "ecdsa-sig-formatter": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", - "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "dev": true, "requires": { "safe-buffer": "^5.0.1" @@ -9132,9 +9129,9 @@ } }, "eslint": { - "version": "5.15.3", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.15.3.tgz", - "integrity": "sha512-vMGi0PjCHSokZxE0NLp2VneGw5sio7SSiDNgIUn2tC0XkWJRNOIoHIg3CliLVfXnJsiHxGAYrkw0PieAu8+KYQ==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -9157,7 +9154,7 @@ "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "inquirer": "^6.2.2", - "js-yaml": "^3.12.0", + "js-yaml": "^3.13.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", "lodash": "^4.17.11", @@ -9261,9 +9258,9 @@ "dev": true }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true }, "slice-ansi": { @@ -9876,9 +9873,9 @@ "dev": true }, "fast-copy": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-1.2.3.tgz", - "integrity": "sha512-ws7blvcPYbGyl/C8Pc2v7cdJerlimT6+FqHW9vp3JvwZ4NfG/fV/cm+Hyglw6hLMFb3Zx3JnM3oEsJPNrcL6Xw==" + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-1.2.4.tgz", + "integrity": "sha512-LCRjn7/wRBxeM//UVnya1eejlpiNTNz7MsAJnQXUSqkJwvzG35inF/GHDbispN0041A/Rhtuk06xS4IA4YNMBg==" }, "fast-deep-equal": { "version": "2.0.1", @@ -10310,27 +10307,15 @@ } }, "feathers-memory": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/feathers-memory/-/feathers-memory-3.0.1.tgz", - "integrity": "sha512-Z3AodnPKXWWhstzQn/EYJ+/aZCGH+//AdSHiVV1jrP+RR2oT+TCjGwWoQl8nZd7oMEJOkgEuFcjzXx5IB1kNjg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/feathers-memory/-/feathers-memory-3.0.2.tgz", + "integrity": "sha512-GlSYSlIgN5BhvGaCi2AMaltteJvmCOoA5u9j1dIwnwWveF4586TLGsUKu1CASisva5DVczDlmIltq+GJpO6D7w==", "dev": true, "requires": { - "@feathersjs/adapter-commons": "^1.0.2", + "@feathersjs/adapter-commons": "^2.0.0", "@feathersjs/commons": "^4.0.0", - "@feathersjs/errors": "^3.3.4", + "@feathersjs/errors": "^3.3.6", "sift": "^7.0.1" - }, - "dependencies": { - "@feathersjs/adapter-commons": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@feathersjs/adapter-commons/-/adapter-commons-1.0.7.tgz", - "integrity": "sha512-VZLbos2840xUfEe+CYqKAKLpSm7l+26T2wWz2OLlnYy5UkCjosfsd/coJPtSwAn3dsTNUpQU2Gcb6xdOfZCy1w==", - "dev": true, - "requires": { - "@feathersjs/commons": "^4.0.0", - "@feathersjs/errors": "^3.3.6" - } - } } }, "feathers-query-filters": { @@ -13475,12 +13460,12 @@ "dev": true }, "jsonwebtoken": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz", - "integrity": "sha512-coyXjRTCy0pw5WYBpMvWOMN+Kjaik2MwTUIq9cna/W7NpO9E+iYbumZONAz3hcr+tXFJECoQVrtmIoC3Oz0gvg==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", "dev": true, "requires": { - "jws": "^3.1.5", + "jws": "^3.2.2", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", @@ -13488,7 +13473,8 @@ "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", - "ms": "^2.1.1" + "ms": "^2.1.1", + "semver": "^5.6.0" }, "dependencies": { "ms": { @@ -13496,6 +13482,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true + }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true } } }, @@ -13521,23 +13513,23 @@ } }, "jwa": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz", - "integrity": "sha512-tBO/cf++BUsJkYql/kBbJroKOgHWEigTKBAjjBEmrMGYd1QMBC74Hr4Wo2zCZw6ZrVhlJPvoMrkcOnlWR/DJfw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", "dev": true, "requires": { "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.10", + "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "jws": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz", - "integrity": "sha512-GsCSexFADNQUr8T5HPJvayTjvPIfoyJPtLQBwn5a4WZQchcrPMPMAWcC1AzJVRDKyD6ZPROPAxgv6rfHViO4uQ==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", "dev": true, "requires": { - "jwa": "^1.1.5", + "jwa": "^1.4.1", "safe-buffer": "^5.0.1" } }, @@ -15503,9 +15495,9 @@ } }, "parent-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.0.tgz", - "integrity": "sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "requires": { "callsites": "^3.0.0" @@ -18730,9 +18722,9 @@ } }, "steal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/steal/-/steal-2.2.0.tgz", - "integrity": "sha512-aX2uTCktgSYP0ByPLCDZ9o27LzV+HUJ46930tGSBpEa6v7jKxuHM11OjivGqymBX2DlCFj34UqYAsXkWqZJzOg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/steal/-/steal-2.2.1.tgz", + "integrity": "sha512-3v1ZJ6ucEG6Rb4iY8hOMAMDBeSio1RTLeNpTD5t60JEkzBb95W9SI2Xg0gYg5Q9f7TAHGyioTx+eR9XzrLjmMA==", "dev": true, "requires": { "assert": "~1.4.1", @@ -20224,9 +20216,9 @@ "dev": true }, "typescript": { - "version": "3.3.4000", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.4000.tgz", - "integrity": "sha512-jjOcCZvpkl2+z7JFn0yBOoLQyLoIkNZAs/fYJkUG6VKy6zLPHJGfQJYFHzibB6GJaF/8QrcECtlQ5cpvRHSMEA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.1.tgz", + "integrity": "sha512-3NSMb2VzDQm8oBTLH6Nj55VVtUEpe/rgkIzMir0qVoLyjDZlnMBva0U6vDiV3IH+sl/Yu6oP5QwsAQtHPmDd2Q==", "dev": true }, "uberproto": { @@ -21953,9 +21945,9 @@ } }, "vuex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.0.1.tgz", - "integrity": "sha512-wLoqz0B7DSZtgbWL1ShIBBCjv22GV5U+vcBFox658g6V0s4wZV9P4YjCNyoHSyIBpj1f29JBoNQIqD82cR4O3w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.1.0.tgz", + "integrity": "sha512-mdHeHT/7u4BncpUZMlxNaIdcN/HIt1GsGG5LKByArvYG/v6DvHcOxvDCts+7SRdCoIRGllK8IMZvQtQXLppDYg==", "dev": true }, "w3c-hr-time": { diff --git a/package.json b/package.json index d9019645..5ae4881a 100644 --- a/package.json +++ b/package.json @@ -101,10 +101,15 @@ "@feathersjs/adapter-commons": "^2.0.0", "@feathersjs/commons": "^4.0.0", "@feathersjs/errors": "^3.3.6", + "@types/deep-diff": "^1.0.0", + "@types/feathersjs__feathers": "^3.1.1", + "@types/inflection": "^1.5.28", + "@types/lodash": "^4.14.123", + "@types/npm": "^2.0.30", "bson-objectid": "^1.2.4", "debug": "^4.1.1", "deep-diff": "^1.0.2", - "fast-copy": "^1.2.3", + "fast-copy": "^1.2.4", "inflection": "^1.12.0", "jwt-decode": "^2.2.0", "lodash": "^4.17.11", @@ -119,9 +124,9 @@ "steal-typescript": "^0.5.0" }, "devDependencies": { - "@feathersjs/authentication-client": "^1.0.10", - "@feathersjs/authentication-jwt": "^2.0.9", - "@feathersjs/client": "^3.7.7", + "@feathersjs/authentication-client": "^1.0.11", + "@feathersjs/authentication-jwt": "^2.0.10", + "@feathersjs/client": "^3.7.8", "@feathersjs/feathers": "^3.3.1", "@feathersjs/rest-client": "^1.4.7", "@feathersjs/socketio-client": "^1.2.1", @@ -142,11 +147,11 @@ "body-parser": "^1.18.3", "can-fixture-socket": "^2.0.0", "chai": "^4.2.0", - "eslint": "^5.15.3", + "eslint": "^5.16.0", "eslint-config-prettier": "^4.1.0", "eslint-plugin-prettier": "^3.0.1", "eslint-plugin-vue": "^5.2.2", - "feathers-memory": "^3.0.1", + "feathers-memory": "^3.0.2", "istanbul": "^1.1.0-alpha.1", "jsdom": "^14.0.0", "jsdom-global": "^3.0.2", @@ -155,13 +160,13 @@ "shx": "^0.3.2", "socket.io-client": "^2.2.0", "standard": "^12.0.1", - "steal": "^2.2.0", + "steal": "^2.2.1", "steal-mocha": "^2.0.1", "testee": "^0.9.0", "ts-node": "^8.0.3", - "typescript": "^3.3.4000", + "typescript": "^3.4.1", "vue": "^2.6.10", "vuepress": "^0.14.10", - "vuex": "^3.0.1" + "vuex": "^3.1.0" } } From b8931ebf77b46640f41694e178abbeffbbc5ecf9 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 00:53:58 -0600 Subject: [PATCH 076/404] Keep this context as we call BaseModel methods --- src/service-module/make-model.ts | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index c42b7ffa..8f46b3bd 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -73,7 +73,7 @@ export default function makeModel(options: FeathersVuexOptions) { // If it already exists, update the original and return if (hasValidId && !options.clone) { - const existingItem = BaseModel.getFromStore(id) + const existingItem = BaseModel.getFromStore.call(this, id) if (existingItem) { BaseModel._commit('updateItem', data) return existingItem @@ -105,7 +105,7 @@ export default function makeModel(options: FeathersVuexOptions) { // Add the item to the store if (!options.clone && options.commit !== false && BaseModel.store) { - BaseModel._commit('addItem', this) + BaseModel._commit.call(this, 'addItem', this) } return this } @@ -115,7 +115,7 @@ export default function makeModel(options: FeathersVuexOptions) { } public static find(params) { - BaseModel._dispatch('find', params) + BaseModel._dispatch.call('find', params) } public static findInStore(params) { @@ -124,17 +124,17 @@ export default function makeModel(options: FeathersVuexOptions) { public static get(id, params) { if (params) { - return BaseModel._dispatch('get', [id, params]) + return BaseModel._dispatch.call(this, 'get', [id, params]) } else { - return BaseModel._dispatch('get', id) + return BaseModel._dispatch.call(this, 'get', id) } } public static getFromStore(id, params?) { if (params) { - return BaseModel._getters('get', [id, params]) + return BaseModel._getters.call(this, 'get', [id, params]) } else { - return BaseModel._getters('get', id) + return BaseModel._getters.call(this, 'get', id) } } @@ -242,7 +242,7 @@ export default function makeModel(options: FeathersVuexOptions) { if (data[options.idField] === null) { delete data[options.idField] } - return BaseModel._dispatch('create', [data, params]) + return BaseModel._dispatch.call(this, 'create', [data, params]) } /** @@ -258,7 +258,7 @@ export default function makeModel(options: FeathersVuexOptions) { ) return Promise.reject(error) } - return BaseModel._dispatch('patch', [ + return BaseModel._dispatch.call(this, 'patch', [ this[BaseModel.idField], this, params @@ -278,7 +278,7 @@ export default function makeModel(options: FeathersVuexOptions) { ) return Promise.reject(error) } - return BaseModel._dispatch('update', [ + return BaseModel._dispatch.call(this, 'update', [ this[BaseModel.idField], this, params @@ -290,7 +290,10 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public remove(params) { - return BaseModel._dispatch('remove', [this[BaseModel.idField], params]) + return BaseModel._dispatch.call(this, 'remove', [ + this[BaseModel.idField], + params + ]) } public toJSON() { From 6c2a39e87c84f5ba12741ca18fc7eafa1a88ee3c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 00:54:31 -0600 Subject: [PATCH 077/404] makeActions no longer requires options They are pulled from the state. --- src/service-module/make-service-module.ts | 2 +- src/service-module/service-module.actions.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/service-module/make-service-module.ts b/src/service-module/make-service-module.ts index 7b589792..1b14ef13 100644 --- a/src/service-module/make-service-module.ts +++ b/src/service-module/make-service-module.ts @@ -25,7 +25,7 @@ export default function makeServiceModule(service, options) { const defaultState = makeDefaultState(stateOptions.servicePath, stateOptions) const defaultGetters = makeGetters() const defaultMutations = makeMutations() - const defaultActions = makeActions(service, options) + const defaultActions = makeActions(service) Object.assign(stateOptions, { modelName: options.Model.name diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 0a069731..dc7f64fd 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -5,7 +5,7 @@ eslint */ import { observableDiff, applyChange } from 'deep-diff' -export default function makeServiceActions(service, { debug }) { +export default function makeServiceActions(service) { const serviceActions = { find({ commit, dispatch, state }, params) { params = params || {} From 1385097b6fba4347e16db9c05793ee17de44d3fa Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 00:54:40 -0600 Subject: [PATCH 078/404] Remove empty file --- src/service-module/model.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/service-module/model.ts diff --git a/src/service-module/model.ts b/src/service-module/model.ts deleted file mode 100644 index e69de29b..00000000 From c6433c1994f1e7cf9e577605ecfd58136263b911 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 00:54:57 -0600 Subject: [PATCH 079/404] Simplify stripSlashes function for our use --- src/utils.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 34f0ca33..f472abd0 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -14,10 +14,8 @@ import { } from 'lodash' import ObjectID from 'bson-objectid' -export function stripSlashes(location) { - return Array.isArray(location) - ? location.map(l => _trim(l, '/')) - : _trim(location, '/') +export function stripSlashes(location: string) { + return _trim(location, '/') } // From feathers-plus/feathers-hooks-common From 56f309d295028fbebaf65714d2c1f1dfcd4dcf2c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 00:55:27 -0600 Subject: [PATCH 080/404] lint cleanup --- test/make-find-mixin.test.ts | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/test/make-find-mixin.test.ts b/test/make-find-mixin.test.ts index 3b78cc87..e0391cec 100644 --- a/test/make-find-mixin.test.ts +++ b/test/make-find-mixin.test.ts @@ -1,25 +1,35 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ import jsdom from 'jsdom-global' import { assert } from 'chai' import feathersVuex, { FeathersVuex } from '../src/index' import { feathersRestClient as feathersClient } from './fixtures/feathers-client' import makeFindMixin from '../src/make-find-mixin' -import Vue from 'vue/dist/vue' +import Vue from 'vue' import Vuex from 'vuex' jsdom() -const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { - serverAlias: 'make-find-mixin' -}) +function makeContext() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'make-find-mixin' + }) -class FindModel extends BaseModel { - public static test: boolean = true + class FindModel extends BaseModel { + public static test: boolean = true + } + + return { FindModel, BaseModel, makeServicePlugin } } Vue.use(Vuex) Vue.use(FeathersVuex) describe('Find Mixin', function() { + const { makeServicePlugin, FindModel } = makeContext() const serviceName = 'todos' const store = new Vuex.Store({ plugins: [ @@ -33,7 +43,19 @@ describe('Find Mixin', function() { it('correctly forms mixin data', function() { const todosMixin = makeFindMixin({ service: 'todos' }) - const vm = new Vue({ + interface TodosComponent { + todos: [] + todosServiceName: string + isFindTodosPending: boolean + findTodos: Function + todosLocal: boolean + todosQid: string + todosQueryWhen: Function + todosParams: any + todosFetchParams: any + } + + const vm = new Vue({ name: 'todos-component', mixins: [todosMixin], store, From 0eb78395b06573037ff34b3bc45a6cd09d9b1b12 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 00:58:23 -0600 Subject: [PATCH 081/404] Allow model methods to run --- test/service-module/model-methods.test.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/service-module/model-methods.test.ts b/test/service-module/model-methods.test.ts index ffa103cd..0e554fb7 100644 --- a/test/service-module/model-methods.test.ts +++ b/test/service-module/model-methods.test.ts @@ -5,7 +5,7 @@ eslint */ import { ServiceState } from './types' import { assert } from 'chai' -import feathersVuex, { models } from '../../src/index' +import feathersVuex from '../../src/index' import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' import Vuex from 'vuex' @@ -29,11 +29,13 @@ function makeContext() { serverAlias: 'model-methods' }) class Task extends BaseModel { + public servicePath: 'tasks' public constructor(data?, options?) { super(data, options) } } class Todo extends BaseModel { + public servicePath: 'todos' public constructor(data?, options?) { super(data, options) } @@ -60,7 +62,7 @@ function makeContext() { } } -describe.only('Models - Methods', function() { +describe('Models - Methods', function() { it('Model.find', function() { const { Task } = makeContext() @@ -119,7 +121,7 @@ describe.only('Models - Methods', function() { assert(called, 'create should have been called') }) - it.only('instance.save passes params to patch', function() { + it('instance.save passes params to patch', function() { const { Todo } = makeContext() const todo = new Todo({ id: 1, test: true }) let called = false From 6cb234484aa6ac77402dd8887883b942d43edeb4 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 01:00:46 -0600 Subject: [PATCH 082/404] Get the compiler to to run --- .../make-service-plugin.test.ts | 4 ++ .../service-module.actions.test.ts | 3 ++ test/service-module/service-module.test.ts | 3 +- test/utils.test.ts | 1 + test/vue-plugin.test.ts | 47 ++++++++++++------- tsconfig.json | 2 +- 6 files changed, 41 insertions(+), 19 deletions(-) diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index 4057afef..43489567 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -82,10 +82,13 @@ describe('makeServicePlugin', function() { assert.deepEqual( _omit(received, ['instanceDefaults', 'serialize']), + // @ts-ignore _omit(expected, ['instanceDefaults', 'serialize']), 'The module was registered.' ) + // @ts-ignore assert.equal(typeof received.serialize, 'function') + // @ts-ignore assert.equal(typeof received.instanceDefaults, 'function') }) @@ -104,6 +107,7 @@ describe('makeServicePlugin', function() { const store = new Vuex.Store({ plugins: [todosPlugin] }) assert(Todo.store === store, 'the store is on the Model!') + // @ts-ignore assert.equal(service.FeathersVuexModel, Todo, 'Model accessible on service') }) diff --git a/test/service-module/service-module.actions.test.ts b/test/service-module/service-module.actions.test.ts index f2da584e..e3c089a4 100644 --- a/test/service-module/service-module.actions.test.ts +++ b/test/service-module/service-module.actions.test.ts @@ -80,6 +80,7 @@ describe('Service Module - Actions', () => { beforeEach(function() { this.todoService = feathersClient.use( 'my-todos', + // @ts-ignore memory({ store: makeStore() }) @@ -87,6 +88,7 @@ describe('Service Module - Actions', () => { this.taskService = feathersClient.use( 'my-tasks', + // @ts-ignore memory({ store: makeStore(), paginate: { @@ -98,6 +100,7 @@ describe('Service Module - Actions', () => { this.noIdService = feathersClient.use( 'no-ids', + // @ts-ignore memory({ store: makeStore(), paginate: { diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 31b314e6..fe7a5c29 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -4,7 +4,7 @@ eslint @typescript-eslint/no-explicit-any: 0 */ import { ServiceState } from './types' -import { assert } from 'chai/chai' +import { assert } from 'chai' import feathersVuex, { models } from '../../src/index' import { clearModels } from '../../src/service-module/global-models' @@ -117,6 +117,7 @@ describe('Service Module', function() { 'the Model was added to the models' ) assert( + // @ts-ignore feathersService.FeathersVuexModel === ServiceTodo, 'the Model is also found at service.FeathersVuexModel' ) diff --git a/test/utils.test.ts b/test/utils.test.ts index c21fa024..6983b7ad 100644 --- a/test/utils.test.ts +++ b/test/utils.test.ts @@ -65,6 +65,7 @@ describe('Utils', function() { 'the token was in place' ) assert(store.state.auth.payload, 'the payload was set') + // @ts-ignore return feathersClient.passport.getJWT() }) .then(token => { diff --git a/test/vue-plugin.test.ts b/test/vue-plugin.test.ts index 3b275ef7..0824355f 100644 --- a/test/vue-plugin.test.ts +++ b/test/vue-plugin.test.ts @@ -1,36 +1,49 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ import { assert } from 'chai' import feathersVuex, { FeathersVuex } from '../src/index' import { feathersRestClient as feathersClient } from './fixtures/feathers-client' import Vue from 'vue/dist/vue' import Vuex from 'vuex' +// @ts-ignore Vue.use(Vuex) +// @ts-ignore Vue.use(FeathersVuex) -const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { - serverAlias: 'make-find-mixin' -}) -class FindModel extends BaseModel { - public static test: boolean = true +interface VueWithFeathers { + $FeathersVuex: {} } -const serviceName = 'todos' -const store = new Vuex.Store({ - plugins: [ - makeServicePlugin({ - Model: FindModel, - service: feathersClient.service(serviceName) - }) - ] -}) +function makeContext() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'make-find-mixin' + }) + class FindModel extends BaseModel { + public static test: boolean = true + } -interface VueWithFeathers { - $FeathersVuex: {} + const serviceName = 'todos' + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: FindModel, + service: feathersClient.service(serviceName) + }) + ] + }) + return { + store + } } describe('Vue Plugin', function() { it('Adds the `$FeathersVuex` object to components', function() { - const vm = new Vue({ + const { store } = makeContext() + const vm = new Vue({ name: 'todos-component', store, template: `
` diff --git a/tsconfig.json b/tsconfig.json index 6f22f643..addabcda 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,7 @@ "esModuleInterop": true, "outDir": "dist", "moduleResolution": "node", - "target": "ES6" + "target": "ES2017" }, "include": [ "src/**/*", "test/**/*" From 5e343466de1dc8b14617c377257ea02df851f3d3 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 01:01:02 -0600 Subject: [PATCH 083/404] Fix broken import of diff functions --- src/service-module/service-module.actions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index dc7f64fd..21b377bd 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -178,7 +178,6 @@ export default function makeServiceActions(service) { commit('setPending', 'patch') if (diffOnPatch) { - const { observableDiff, applyChange } = diffFunctions() let diff = {} observableDiff(state.copy, data, function(d) { From a9bdfeadd763c123c68b311a7433cf129e1e093c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 01:01:42 -0600 Subject: [PATCH 084/404] Fix some instance defaults tests --- .../model-instance-defaults.test.ts | 98 +++++++------------ 1 file changed, 35 insertions(+), 63 deletions(-) diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts index b9d2b76d..15cfa2e3 100644 --- a/test/service-module/model-instance-defaults.test.ts +++ b/test/service-module/model-instance-defaults.test.ts @@ -65,6 +65,28 @@ function makeContext() { public static test: boolean = true } + const todosPlugin = makeServicePlugin({ + Model: ServiceTodo, + service: feathersClient.service('service-todos') + }) + this.store = new Vuex.Store({ + plugins: [ + todosPlugin + makeServicePlugin({ + Model: Person, + service: feathersClient.service('people') + }), + makeServicePlugin({ + Model: Car, + service: feathersClient.service('cars') + }), + makeServicePlugin({ + Model: Group, + service: feathersClient.service('groups') + }) + ] + }) + return { makeServicePlugin, BaseModel, @@ -80,83 +102,33 @@ function makeContext() { } describe('Models - Default Values', function() { - beforeEach(function() { - const { makeServicePlugin, ServiceTodo, Person, Car, Group } = makeContext() + it('models default to an empty object when there is no BaseModel.store', function() { + const { BaseModel } = makeContext() - const taskDefaults = (this.taskDefaults = { - id: null, - description: '', - isComplete: false - }) - - // TODO: Do Something with this! - const instanceDefaultsForPerson = { - firstName: '', - lastName: '', - location: { - coordinates: [-111.549668, 39.014] - }, - get fullName() { - return `${this.firstName} ${this.lastName}` - }, - todos({ store }) { - console.log(Object.keys(store)) - } + // Since we're not using this NakedTodo model in a service plugin, it doesn't get + // monkey patched with the store. + class NakedTodo extends BaseModel { + public static test: boolean = true } - const instanceDefaultsForCars = { - keepCopiesInStore: true, - instanceDefaults: taskDefaults - } - const instanceDefaultsForGroups = function instanceDefaults() { - return { - name: '', - get todos() { - return models.Todo.findInStore({ query: {} }).data - } - } - } - this.store = new Vuex.Store({ - plugins: [ - makeServicePlugin({ - Model: ServiceTodo, - service: feathersClient.service('service-todos') - }), - makeServicePlugin({ - Model: Person, - service: feathersClient.service('people') - }), - makeServicePlugin({ - Model: Car, - service: feathersClient.service('cars') - }), - makeServicePlugin({ - Model: Group, - service: feathersClient.service('groups') - }) - ] - }) - this.Todo = ServiceTodo - this.Task = models.Task - this.Person = models.Person - this.Group = models.Group - }) + const todo = new NakedTodo() - // store.commit('todos/addItem', data) + assert.deepEqual(todo, {}, 'default model is a temp') + }) - it('models default to an empty object', function() { + it('models have tempIds when there is a store', function() { const { Todo } = this - const module = new Todo() + const todo = new Todo() const expectedProps = ['__id', '__isTemp'] assert.deepEqual( - Object.keys(module), + Object.keys(todo), expectedProps, 'default model is a temp' ) }) - it('adds new instances containing an id to the store', function() { + it.only('adds new instances containing an id to the store', function() { const { ServiceTodo } = makeContext() const todo = new ServiceTodo({ From 9f61e522acb1756baf95c8b1ac6e080043b75ae0 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 01:01:57 -0600 Subject: [PATCH 085/404] Fix missing comma --- test/service-module/model-instance-defaults.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts index 15cfa2e3..ac4afd1b 100644 --- a/test/service-module/model-instance-defaults.test.ts +++ b/test/service-module/model-instance-defaults.test.ts @@ -71,7 +71,7 @@ function makeContext() { }) this.store = new Vuex.Store({ plugins: [ - todosPlugin + todosPlugin, makeServicePlugin({ Model: Person, service: feathersClient.service('people') From 8eb8788a17a5424ddee85a0e5a3845cd78ed251d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 01:18:54 -0600 Subject: [PATCH 086/404] Fix store assignment --- test/service-module/model-instance-defaults.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts index ac4afd1b..35b2221a 100644 --- a/test/service-module/model-instance-defaults.test.ts +++ b/test/service-module/model-instance-defaults.test.ts @@ -69,7 +69,7 @@ function makeContext() { Model: ServiceTodo, service: feathersClient.service('service-todos') }) - this.store = new Vuex.Store({ + const store = new Vuex.Store({ plugins: [ todosPlugin, makeServicePlugin({ @@ -97,7 +97,8 @@ function makeContext() { Car, Group, Test, - Thing + Thing, + store } } From 460134312ea08e6bc8ff7c4a6550638750fcffa9 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 09:40:42 -0600 Subject: [PATCH 087/404] Add checkNamespace util to Model --- src/service-module/make-model.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 8f46b3bd..84afc7a6 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -5,7 +5,7 @@ eslint */ import { FeathersVuexOptions } from './types' import { globalModels, prepareAddModel } from './global-models' -import { mergeWithAccessors, separateAccessors } from '../utils' +import { mergeWithAccessors, separateAccessors, checkNamespace } from '../utils' import { get as _get, merge as _merge } from 'lodash' // A hack to prevent error with this.constructor.preferUpdate @@ -145,6 +145,7 @@ export default function makeModel(options: FeathersVuexOptions) { */ public static _getters(name: string, payload?: any) { const { namespace } = this.constructor as typeof BaseModel + checkNamespace(namespace, this) if (payload !== undefined) { return BaseModel.store.getters[`${namespace}/${name}`](payload) } else { @@ -158,6 +159,8 @@ export default function makeModel(options: FeathersVuexOptions) { */ public static _commit(method: string, payload: any): void { const { namespace } = this.constructor as typeof BaseModel + checkNamespace(namespace, this) + BaseModel.store.commit(`${namespace}/${method}`, payload) } /** @@ -167,6 +170,7 @@ export default function makeModel(options: FeathersVuexOptions) { */ public static _dispatch(method: string, payload: any) { const { namespace } = this.constructor as typeof BaseModel + checkNamespace(namespace, this) return BaseModel.store.dispatch(`${namespace}/${method}`, payload) } @@ -182,7 +186,9 @@ export default function makeModel(options: FeathersVuexOptions) { } private _clone(id) { - const { store, copiesById, namespace } = BaseModel + const { store, copiesById, namespace } = this + .constructor as typeof BaseModel + checkNamespace(namespace, this) const { keepCopiesInStore } = store.state[namespace] // const { store } = this.constructor store.commit(`${namespace}/createCopy`, id) From 1da61142e43a836b22a6e357c2185520d310854c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 09:40:56 -0600 Subject: [PATCH 088/404] Call Model._commit with correct context --- src/service-module/make-model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 84afc7a6..7167dc96 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -217,7 +217,7 @@ export default function makeModel(options: FeathersVuexOptions) { public commit() { if (this.__isClone) { const id = this[BaseModel.idField] || this[BaseModel.tempIdField] - BaseModel._commit('commitCopy', id) + BaseModel._commit.call(this, 'commitCopy', id) return this } else { From ba9ac018ef9c13f1db1bffea651f3ba6aeb9ebe1 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 09:41:05 -0600 Subject: [PATCH 089/404] checkNamespace util --- src/utils.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/utils.ts b/src/utils.ts index f472abd0..d40b1a9a 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -382,3 +382,13 @@ export function separateAccessors(props) { { accessors: {}, values: {} } ) } + +export function checkNamespace(namespace, item) { + if (!namespace) { + console.error( + 'A `namespace` was not available on the Model for this item:', + item, + 'this can be caused by not passing the Model into the makeServicePlugin function' + ) + } +} From 60bfc77ad08c97ae8648df105bb7c7279c6abc29 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 09:41:14 -0600 Subject: [PATCH 090/404] Rename test --- test/service-module/model-temp-ids.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/service-module/model-temp-ids.test.ts b/test/service-module/model-temp-ids.test.ts index 0606dfba..6b587187 100644 --- a/test/service-module/model-temp-ids.test.ts +++ b/test/service-module/model-temp-ids.test.ts @@ -14,7 +14,7 @@ interface RootState { transactions: ServiceState } -describe('Models - Default Values', function() { +describe('Models - Temp Ids', function() { beforeEach(() => { clearModels() }) From 5ff645600a776f73d68afb9e711cb79848df3318 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 09:41:43 -0600 Subject: [PATCH 091/404] Clear models beforeEach test --- test/service-module/model-instance-defaults.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts index 35b2221a..a5e7742e 100644 --- a/test/service-module/model-instance-defaults.test.ts +++ b/test/service-module/model-instance-defaults.test.ts @@ -103,6 +103,10 @@ function makeContext() { } describe('Models - Default Values', function() { + beforeEach(() => { + clearModels() + }) + it('models default to an empty object when there is no BaseModel.store', function() { const { BaseModel } = makeContext() From b968d6d827998c8cd79039687da7ad88c955a27a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 09:42:17 -0600 Subject: [PATCH 092/404] Remove recommendation for where to place defaults --- test/service-module/model-instance-defaults.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts index a5e7742e..f465c909 100644 --- a/test/service-module/model-instance-defaults.test.ts +++ b/test/service-module/model-instance-defaults.test.ts @@ -312,7 +312,7 @@ describe('Models - Default Values', function() { assert(!areSame, 'the locations are different objects') }) - it('RECOMMENDED: allows passing instanceDefaults in the service plugin options', function() { + it.only('allows passing instanceDefaults in the service plugin options', function() { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { serverAlias: 'instance-defaults' }) From 492c91177bc8dc354b80c3718f81935959649719 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 09:42:32 -0600 Subject: [PATCH 093/404] Simplify Model name in test --- .../model-instance-defaults.test.ts | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts index f465c909..81db0666 100644 --- a/test/service-module/model-instance-defaults.test.ts +++ b/test/service-module/model-instance-defaults.test.ts @@ -35,11 +35,11 @@ function makeContext() { serverAlias: 'service-module' }) - class ServiceTodo extends BaseModel { + class Todo extends BaseModel { public id public description: string - public constructor(data, options?) { + public constructor(data = {}, options?) { super(data, options) } } @@ -66,7 +66,7 @@ function makeContext() { } const todosPlugin = makeServicePlugin({ - Model: ServiceTodo, + Model: Todo, service: feathersClient.service('service-todos') }) const store = new Vuex.Store({ @@ -90,7 +90,7 @@ function makeContext() { return { makeServicePlugin, BaseModel, - ServiceTodo, + Todo, Person, Item, Task, @@ -121,7 +121,7 @@ describe('Models - Default Values', function() { }) it('models have tempIds when there is a store', function() { - const { Todo } = this + const { Todo } = makeContext() const todo = new Todo() const expectedProps = ['__id', '__isTemp'] @@ -133,34 +133,31 @@ describe('Models - Default Values', function() { ) }) - it.only('adds new instances containing an id to the store', function() { - const { ServiceTodo } = makeContext() + it('adds new instances containing an id to the store', function() { + const { Todo } = makeContext() - const todo = new ServiceTodo({ + const todo = new Todo({ id: 1, description: 'test', isComplete: true }) - const todoInStore = ServiceTodo.store.state['service-todos'].keyedById[1] + const todoInStore = Todo.store.state['service-todos'].keyedById[1] assert.deepEqual(todoInStore, todo, 'task was added to the store') }) it('stores clones in Model.copiesById by default', function() { - const { ServiceTodo } = makeContext() - const todo = new ServiceTodo({ id: 1, description: 'This is the original' }) + const { Todo } = makeContext() + const todo = new Todo({ id: 1, description: 'This is the original' }) assert.deepEqual( - ServiceTodo.copiesById, + Todo.copiesById, {}, 'Model.copiesById should start out empty' ) const todoClone = todo.clone() - assert( - ServiceTodo.copiesById[1], - 'should have a copy stored on Model.copiesById' - ) + assert(Todo.copiesById[1], 'should have a copy stored on Model.copiesById') todoClone.description = `I'm a clone, now!` todoClone.commit() From 7df2c841c53113c48a690f0361b5758d355c07ac Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 09:42:53 -0600 Subject: [PATCH 094/404] Fix reference to instanceDefaults --- src/service-module/make-model.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 7167dc96..87a6a584 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -67,7 +67,8 @@ export default function makeModel(options: FeathersVuexOptions) { ) { data = data || {} const { merge } = childClassOptions - const { idField, tempIdField } = BaseModel + const { instanceDefaults, idField, tempIdField } = this + .constructor as typeof BaseModel const id = data[idField] || data[tempIdField] const hasValidId = id !== null && id !== undefined @@ -90,11 +91,11 @@ export default function makeModel(options: FeathersVuexOptions) { } // Setup instanceDefaults, separate out accessors - if (BaseModel.instanceDefaults) { - const instanceDefaults = BaseModel.instanceDefaults() - const separatedDefaults = separateAccessors(instanceDefaults) - mergeWithAccessors(this, separatedDefaults.accessors) - mergeWithAccessors(this, separatedDefaults.values) + if (instanceDefaults && typeof instanceDefaults === 'function') { + const defaults = instanceDefaults() + const { accessors, values } = separateAccessors(defaults) + mergeWithAccessors(this, accessors) + mergeWithAccessors(this, values) } // Handles Vue objects or regular ones. We can't simply assign or return From b2ba717ad34d977a916fd0cfd8b8e1f3d39ac460 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 09:45:31 -0600 Subject: [PATCH 095/404] Fix context when calling BaseModel._commit --- src/service-module/make-model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 87a6a584..0edbff6e 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -206,7 +206,7 @@ export default function makeModel(options: FeathersVuexOptions) { public reset() { if (this.__isClone) { const id = this[BaseModel.idField] || this[BaseModel.tempIdField] - BaseModel._commit('resetCopy', id) + BaseModel._commit.call(this, 'resetCopy', id) } else { throw new Error('You cannot reset a non-copy') } From 0c68775a6681f19f6e23622f175d7978989a3267 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 09:45:44 -0600 Subject: [PATCH 096/404] Remove .only --- test/service-module/model-instance-defaults.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts index 81db0666..5094966f 100644 --- a/test/service-module/model-instance-defaults.test.ts +++ b/test/service-module/model-instance-defaults.test.ts @@ -309,7 +309,7 @@ describe('Models - Default Values', function() { assert(!areSame, 'the locations are different objects') }) - it.only('allows passing instanceDefaults in the service plugin options', function() { + it('allows passing instanceDefaults in the service plugin options', function() { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { serverAlias: 'instance-defaults' }) From 86fef8b4ae6f3196237c172131313294d4f00868 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 17:36:41 -0600 Subject: [PATCH 097/404] Call BaseModel getters with the correct context. --- src/service-module/make-model.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 0edbff6e..c22e9094 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -76,7 +76,7 @@ export default function makeModel(options: FeathersVuexOptions) { if (hasValidId && !options.clone) { const existingItem = BaseModel.getFromStore.call(this, id) if (existingItem) { - BaseModel._commit('updateItem', data) + BaseModel._commit.call(this, 'updateItem', data) return existingItem } } @@ -120,7 +120,7 @@ export default function makeModel(options: FeathersVuexOptions) { } public static findInStore(params) { - return BaseModel._getters('find', params) + return BaseModel._getters.call(this, 'find', params) } public static get(id, params) { @@ -147,6 +147,9 @@ export default function makeModel(options: FeathersVuexOptions) { public static _getters(name: string, payload?: any) { const { namespace } = this.constructor as typeof BaseModel checkNamespace(namespace, this) + if (!BaseModel.store.getters.hasOwnProperty(`${namespace}/${name}`)) { + throw new Error(`Could not find getter named ${namespace}/${name}`) + } if (payload !== undefined) { return BaseModel.store.getters[`${namespace}/${name}`](payload) } else { From 53af3f3ae14c19b3c1ad95e683c6cef213eb1a5e Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 17:36:58 -0600 Subject: [PATCH 098/404] Use the compiler-included version of vue --- test/make-find-mixin.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/make-find-mixin.test.ts b/test/make-find-mixin.test.ts index e0391cec..028160f2 100644 --- a/test/make-find-mixin.test.ts +++ b/test/make-find-mixin.test.ts @@ -8,10 +8,11 @@ import { assert } from 'chai' import feathersVuex, { FeathersVuex } from '../src/index' import { feathersRestClient as feathersClient } from './fixtures/feathers-client' import makeFindMixin from '../src/make-find-mixin' -import Vue from 'vue' +import Vue from 'vue/dist/vue' import Vuex from 'vuex' jsdom() +require('events').EventEmitter.prototype._maxListeners = 100 function makeContext() { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { @@ -25,7 +26,9 @@ function makeContext() { return { FindModel, BaseModel, makeServicePlugin } } +// @ts-ignore Vue.use(Vuex) +// @ts-ignore Vue.use(FeathersVuex) describe('Find Mixin', function() { From 6ce2fa358b23daa84390c4e5c3fbcc25d1b79b4d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 17:37:22 -0600 Subject: [PATCH 099/404] Lift maxListeners eventEmitter warning --- test/service-module/model-base.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/service-module/model-base.test.ts b/test/service-module/model-base.test.ts index 81cad14c..784a8b0c 100644 --- a/test/service-module/model-base.test.ts +++ b/test/service-module/model-base.test.ts @@ -15,6 +15,8 @@ import feathersVuex from '../../src/index' Vue.use(Vuex) +process.setMaxListeners(100) + describe('makeModel / BaseModel', function() { before(() => { clearModels() From fe0fa664dbfaa71154fbc8497d88b524d3489e7b Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 17:37:41 -0600 Subject: [PATCH 100/404] Remove unused variable declaration --- test/service-module/model-temp-ids.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/service-module/model-temp-ids.test.ts b/test/service-module/model-temp-ids.test.ts index 6b587187..37a80c5d 100644 --- a/test/service-module/model-temp-ids.test.ts +++ b/test/service-module/model-temp-ids.test.ts @@ -154,7 +154,7 @@ describe('Models - Temp Ids', function() { super(data, options) } } - const store = new Vuex.Store({ + new Vuex.Store({ plugins: [ makeServicePlugin({ Model: Transaction, From d9ab18ac1440b025661012abe02147718689f8b1 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 17:37:58 -0600 Subject: [PATCH 101/404] Fix variable reference & cleanup tests --- test/service-module/service-module.test.ts | 51 ++++------------------ 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index fe7a5c29..254082c9 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -172,7 +172,7 @@ describe('Service Module', function() { const serviceTodoClone = this.serviceTodo.clone() assert( - serviceTodoClone.isClone, + serviceTodoClone.__isClone, 'created a todo clone with isClone attribute' ) assert( @@ -346,36 +346,6 @@ describe('Service Module', function() { }) }) - describe('Models - modelName', function() { - beforeEach(function() { - const { makeServicePlugin, HotspotMedia, Media } = this - this.store = new Vuex.Store({ - strict: true, - plugins: [ - makeServicePlugin({ - Model: HotspotMedia, - service: feathersClient.service('hotspot-media') - }), - makeServicePlugin({ - Model: Media, - service: feathersClient.service('media') - }), - makeServicePlugin({ - Model: HotspotMedia, - service: feathersClient.service('hotspot-media') - }) - ] - }) - this.Medium = models.Medium - this.HotspotMedia = models.HotspotMedia - }) - - it('allows passing a custom Model name', function() { - assert(!this.HotspotMedium, `the model wasn't in the default location`) - assert(this.HotspotMedia, 'the model is named correctly.') - }) - }) - describe('Models - Dates', function() { beforeEach(function() { const { makeServicePlugin, ServiceTodo } = this @@ -829,19 +799,16 @@ describe('Service Module', function() { }) it('can switch to path name as namespace', function() { - const { makeServicePlugin, Test } = this - const nameStyle = 'path' - const serviceName = '/v1/tests' + const { makeServicePlugin, Test } = makeContext() + const plugin = makeServicePlugin({ + Model: Test, + service: feathersClient.service('/v1/tests'), + nameStyle: 'path' + }) const store = new Vuex.Store({ - plugins: [ - makeServicePlugin({ - Model: Test, - service: feathersClient.service(serviceName), - nameStyle - }) - ] + plugins: [plugin] }) - const namespace = stripSlashes(serviceName) + const namespace = stripSlashes('/v1/tests') assert( store.state[namespace], From a43cc02ccd7fb2ee2f1686d400736b664158c7d3 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 17:38:09 -0600 Subject: [PATCH 102/404] Make sure models are cleared between tests --- test/service-module/model-methods.test.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/service-module/model-methods.test.ts b/test/service-module/model-methods.test.ts index 0e554fb7..a22cf649 100644 --- a/test/service-module/model-methods.test.ts +++ b/test/service-module/model-methods.test.ts @@ -8,6 +8,9 @@ import { assert } from 'chai' import feathersVuex from '../../src/index' import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' import Vuex from 'vuex' +import { clearModels } from '../../src/service-module/global-models' + +require('events').EventEmitter.prototype._maxListeners = 100 interface TodoState extends ServiceState { test: any @@ -63,6 +66,10 @@ function makeContext() { } describe('Models - Methods', function() { + beforeEach(() => { + clearModels() + }) + it('Model.find', function() { const { Task } = makeContext() From af7523a164f7fb0f2fccd58b3011b40061114b1d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 17:38:19 -0600 Subject: [PATCH 103/404] Clean up actions.test --- .../service-module.actions.test.ts | 155 +++++++++--------- 1 file changed, 79 insertions(+), 76 deletions(-) diff --git a/test/service-module/service-module.actions.test.ts b/test/service-module/service-module.actions.test.ts index e3c089a4..99a5f5d0 100644 --- a/test/service-module/service-module.actions.test.ts +++ b/test/service-module/service-module.actions.test.ts @@ -9,6 +9,7 @@ import feathersVuex from '../../src/index' import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' import Vuex, { mapActions } from 'vuex' import memory from 'feathers-memory' +import { clearModels } from '../../src/service-module/global-models' interface RootState { 'my-todos': ServiceState @@ -20,7 +21,73 @@ interface NumberedList { 1?: {} } +const makeStore = () => { + return { + 0: { id: 0, description: 'Do the first' }, + 1: { id: 1, description: 'Do the second' }, + 2: { id: 2, description: 'Do the third' }, + 3: { id: 3, description: 'Do the fourth' }, + 4: { id: 4, description: 'Do the fifth' }, + 5: { id: 5, description: 'Do the sixth' }, + 6: { id: 6, description: 'Do the seventh' }, + 7: { id: 7, description: 'Do the eighth' }, + 8: { id: 8, description: 'Do the ninth' }, + 9: { id: 9, description: 'Do the tenth' } + } +} + function makeContext() { + const todoService = feathersClient.use( + 'my-todos', + // @ts-ignore + memory({ + store: makeStore() + }) + ) + const taskService = feathersClient.use( + 'my-tasks', + // @ts-ignore + memory({ + store: makeStore(), + paginate: { + default: 10, + max: 50 + } + }) + ) + const noIdService = feathersClient.use( + 'no-ids', + // @ts-ignore + memory({ + store: makeStore(), + paginate: { + default: 10, + max: 50 + } + }) + ) + const brokenService = feathersClient.use('broken', { + find() { + return Promise.reject(new Error('find error')) + }, + get() { + return Promise.reject(new Error('get error')) + }, + create() { + return Promise.reject(new Error('create error')) + }, + update() { + return Promise.reject(new Error('update error')) + }, + patch() { + return Promise.reject(new Error('patch error')) + }, + remove() { + return Promise.reject(new Error('remove error')) + }, + setup() {} + }) + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { serverAlias: 'default' }) @@ -39,26 +106,16 @@ function makeContext() { return { makeServicePlugin, BaseModel, + todoService, + taskService, + noIdService, + brokenService, Todo, Task, NoId, Broken } } -const makeStore = () => { - return { - 0: { id: 0, description: 'Do the first' }, - 1: { id: 1, description: 'Do the second' }, - 2: { id: 2, description: 'Do the third' }, - 3: { id: 3, description: 'Do the fourth' }, - 4: { id: 4, description: 'Do the fifth' }, - 5: { id: 5, description: 'Do the sixth' }, - 6: { id: 6, description: 'Do the seventh' }, - 7: { id: 7, description: 'Do the eighth' }, - 8: { id: 8, description: 'Do the ninth' }, - 9: { id: 9, description: 'Do the tenth' } - } -} const assertRejected = (promise, done, callback) => { // resolve handler @@ -77,74 +134,20 @@ const assertRejected = (promise, done, callback) => { } describe('Service Module - Actions', () => { - beforeEach(function() { - this.todoService = feathersClient.use( - 'my-todos', - // @ts-ignore - memory({ - store: makeStore() - }) - ) - - this.taskService = feathersClient.use( - 'my-tasks', - // @ts-ignore - memory({ - store: makeStore(), - paginate: { - default: 10, - max: 50 - } - }) - ) - - this.noIdService = feathersClient.use( - 'no-ids', - // @ts-ignore - memory({ - store: makeStore(), - paginate: { - default: 10, - max: 50 - } - }) - ) - - this.brokenService = feathersClient.use('broken', { - find() { - return Promise.reject(new Error('find error')) - }, - get() { - return Promise.reject(new Error('get error')) - }, - create() { - return Promise.reject(new Error('create error')) - }, - update() { - return Promise.reject(new Error('update error')) - }, - patch() { - return Promise.reject(new Error('patch error')) - }, - remove() { - return Promise.reject(new Error('remove error')) - }, - setup() {} - }) + beforeEach(() => { + clearModels() }) - describe('Find', () => { describe('without pagination', () => { it('Find without pagination', done => { const { makeServicePlugin, Todo } = makeContext() + const todosPlugin = makeServicePlugin({ + servicePath: 'my-todos', + Model: Todo, + service: feathersClient.service('my-todos') + }) const store = new Vuex.Store({ - plugins: [ - makeServicePlugin({ - servicePath: 'my-todos', - Model: Todo, - service: feathersClient.service('my-todos') - }) - ] + plugins: [todosPlugin] }) const todoState = store.state['my-todos'] const actions = mapActions('my-todos', ['find']) From 5370b351f9dc5f37eb1455803b0fcbcac88d5320 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 17:52:04 -0600 Subject: [PATCH 104/404] checkNamespace now returns if the namespace is valid --- src/utils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils.ts b/src/utils.ts index d40b1a9a..1ea57788 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -391,4 +391,5 @@ export function checkNamespace(namespace, item) { 'this can be caused by not passing the Model into the makeServicePlugin function' ) } + return namespace !== null && namespace !== undefined } From ffaaeb9150bd93814813e3eca417925231a99c24 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 17:57:40 -0600 Subject: [PATCH 105/404] Always use values from the contructor instead of BaseModel --- src/service-module/make-model.ts | 76 ++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index c22e9094..a18657c4 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -65,6 +65,7 @@ export default function makeModel(options: FeathersVuexOptions) { options: BaseModelInstanceOptions = {}, childClassOptions: ChildClassOptions = { merge: true } ) { + const { store } = this.constructor as typeof BaseModel data = data || {} const { merge } = childClassOptions const { instanceDefaults, idField, tempIdField } = this @@ -105,14 +106,15 @@ export default function makeModel(options: FeathersVuexOptions) { } // Add the item to the store - if (!options.clone && options.commit !== false && BaseModel.store) { + if (!options.clone && options.commit !== false && store) { BaseModel._commit.call(this, 'addItem', this) } return this } public static getId(record: Record): string { - return record[BaseModel.idField] + const { idField } = this.constructor as typeof BaseModel + return record[idField] } public static find(params) { @@ -145,15 +147,17 @@ export default function makeModel(options: FeathersVuexOptions) { * @param payload if provided, the getter will be called as a function */ public static _getters(name: string, payload?: any) { - const { namespace } = this.constructor as typeof BaseModel - checkNamespace(namespace, this) - if (!BaseModel.store.getters.hasOwnProperty(`${namespace}/${name}`)) { - throw new Error(`Could not find getter named ${namespace}/${name}`) - } - if (payload !== undefined) { - return BaseModel.store.getters[`${namespace}/${name}`](payload) - } else { - return BaseModel.store.getters[`${namespace}/${name}`] + const { namespace, store } = this.constructor as typeof BaseModel + + if (checkNamespace(namespace, this)) { + if (!store.getters.hasOwnProperty(`${namespace}/${name}`)) { + throw new Error(`Could not find getter named ${namespace}/${name}`) + } + if (payload !== undefined) { + return store.getters[`${namespace}/${name}`](payload) + } else { + return store.getters[`${namespace}/${name}`] + } } } /** @@ -162,10 +166,11 @@ export default function makeModel(options: FeathersVuexOptions) { * @param payload the payload for the mutation */ public static _commit(method: string, payload: any): void { - const { namespace } = this.constructor as typeof BaseModel - checkNamespace(namespace, this) + const { namespace, store } = this.constructor as typeof BaseModel - BaseModel.store.commit(`${namespace}/${method}`, payload) + if (checkNamespace(namespace, this)) { + store.commit(`${namespace}/${method}`, payload) + } } /** * An alias for store.dispatch @@ -173,32 +178,34 @@ export default function makeModel(options: FeathersVuexOptions) { * @param payload the payload for the action */ public static _dispatch(method: string, payload: any) { - const { namespace } = this.constructor as typeof BaseModel - checkNamespace(namespace, this) - return BaseModel.store.dispatch(`${namespace}/${method}`, payload) + const { namespace, store } = this.constructor as typeof BaseModel + + if (checkNamespace(namespace, this)) { + return store.dispatch(`${namespace}/${method}`, payload) + } } /** * clone the current record using the `createCopy` mutation */ public clone() { + const { idField, tempIdField } = this.constructor as typeof BaseModel if (this.__isClone) { throw new Error('You cannot clone a copy') } - const id = this[BaseModel.idField] || this[BaseModel.tempIdField] + const id = this[idField] || this[tempIdField] return this._clone(id) } private _clone(id) { const { store, copiesById, namespace } = this .constructor as typeof BaseModel - checkNamespace(namespace, this) const { keepCopiesInStore } = store.state[namespace] - // const { store } = this.constructor - store.commit(`${namespace}/createCopy`, id) + + BaseModel._commit.call(this, `createCopy`, id) if (keepCopiesInStore) { - return BaseModel._getters('getCopyById', id) + return BaseModel._getters.call(this, 'getCopyById', id) } else { return copiesById[id] } @@ -207,8 +214,9 @@ export default function makeModel(options: FeathersVuexOptions) { * Reset a clone to match the instance in the store. */ public reset() { + const { idField, tempIdField } = this.constructor as typeof BaseModel if (this.__isClone) { - const id = this[BaseModel.idField] || this[BaseModel.tempIdField] + const id = this[idField] || this[tempIdField] BaseModel._commit.call(this, 'resetCopy', id) } else { throw new Error('You cannot reset a non-copy') @@ -219,8 +227,9 @@ export default function makeModel(options: FeathersVuexOptions) { * Update a store instance to match a clone. */ public commit() { + const { idField, tempIdField } = this.constructor as typeof BaseModel if (this.__isClone) { - const id = this[BaseModel.idField] || this[BaseModel.tempIdField] + const id = this[idField] || this[tempIdField] BaseModel._commit.call(this, 'commitCopy', id) return this @@ -260,7 +269,9 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public patch(params?) { - if (!this[options.idField]) { + const { idField } = this.constructor as typeof BaseModel + + if (!this[idField]) { const error = new Error( `Missing ${ options.idField @@ -269,7 +280,7 @@ export default function makeModel(options: FeathersVuexOptions) { return Promise.reject(error) } return BaseModel._dispatch.call(this, 'patch', [ - this[BaseModel.idField], + this[idField], this, params ]) @@ -280,7 +291,9 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public update(params) { - if (!this[options.idField]) { + const { idField } = this.constructor as typeof BaseModel + + if (!this[idField]) { const error = new Error( `Missing ${ options.idField @@ -289,7 +302,7 @@ export default function makeModel(options: FeathersVuexOptions) { return Promise.reject(error) } return BaseModel._dispatch.call(this, 'update', [ - this[BaseModel.idField], + this[idField], this, params ]) @@ -300,10 +313,9 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public remove(params) { - return BaseModel._dispatch.call(this, 'remove', [ - this[BaseModel.idField], - params - ]) + const { idField } = this.constructor as typeof BaseModel + + return BaseModel._dispatch.call(this, 'remove', [this[idField], params]) } public toJSON() { From 57db1fd2411f48eb887f0a35163414c5ba500f25 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 22:45:22 -0600 Subject: [PATCH 106/404] Merge model options and childClassOptions --- src/service-module/make-model.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index a18657c4..24a868a6 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -16,11 +16,18 @@ interface Function { interface BaseModelInstanceOptions { clone?: boolean commit?: boolean + merge?: boolean } interface ChildClassOptions { merge?: boolean } +const defaultOptions = { + clone: false, + commit: true, + merge: true +} + /** * * @param options From e1a624bc79c21acdcc8cebe714c8e7cffcb7b382 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 22:45:46 -0600 Subject: [PATCH 107/404] Lint cleanup --- test/make-find-mixin.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/make-find-mixin.test.ts b/test/make-find-mixin.test.ts index 028160f2..06da34f2 100644 --- a/test/make-find-mixin.test.ts +++ b/test/make-find-mixin.test.ts @@ -58,7 +58,7 @@ describe('Find Mixin', function() { todosFetchParams: any } - const vm = new Vue({ + const vm = new Vue({ name: 'todos-component', mixins: [todosMixin], store, From c84998cb54b4d01836052f6e874b8b3be11bb047 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 22:46:11 -0600 Subject: [PATCH 108/404] Add isBaseModelInstance util & use in mergeWithAccessors --- src/utils.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/utils.ts b/src/utils.ts index 1ea57788..7d585465 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -13,6 +13,7 @@ import { trim as _trim } from 'lodash' import ObjectID from 'bson-objectid' +import { models } from './index' export function stripSlashes(location: string) { return _trim(location, '/') @@ -302,6 +303,13 @@ export function createRelatedInstance({ item, Model, idField, store }) { return { model, storedModel } } +export function isBaseModelInstance(item) { + const baseModels = Object.keys(models).map(alias => models[alias].BaseModel) + return !!baseModels.find(BaseModel => { + return item instanceof BaseModel + }) +} + export function mergeWithAccessors(dest, source) { const sourceProps = Object.getOwnPropertyNames(source) const destProps = Object.getOwnPropertyNames(dest) @@ -342,7 +350,7 @@ export function mergeWithAccessors(dest, source) { // Assign values // Do not allow sharing of deeply-nested objects between instances // Potentially breaks accessors on nested data. Needs recursion if this is an issue - if (_isObject(sourceDesc.value)) { + if (_isObject(sourceDesc.value) && !isBaseModelInstance(sourceDesc.value)) { var value = fastCopy(sourceDesc.value) } dest[key] = value || sourceDesc.value From a0c33fad98a5399104253c3f5fe84d478be58a02 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 22:46:44 -0600 Subject: [PATCH 109/404] Add setupInstance API --- src/service-module/make-model.ts | 100 ++-- src/service-module/make-service-plugin.ts | 5 +- src/service-module/notes.md | 136 +++++ src/service-module/types.ts | 1 + .../model-relationships.test.ts | 481 ++++++++++++++++++ test/service-module/service-module.test.ts | 390 -------------- 6 files changed, 675 insertions(+), 438 deletions(-) create mode 100644 test/service-module/model-relationships.test.ts diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 24a868a6..588d9461 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -47,6 +47,7 @@ export default function makeModel(options: FeathersVuexOptions) { public static servicePath: string public static namespace: string public static instanceDefaults + public static setupInstance public static serialize // Monkey patched onto the Model class in `makeServicePlugin()` @@ -67,24 +68,31 @@ export default function makeModel(options: FeathersVuexOptions) { public static merge = mergeWithAccessors - public constructor( - data, - options: BaseModelInstanceOptions = {}, - childClassOptions: ChildClassOptions = { merge: true } - ) { - const { store } = this.constructor as typeof BaseModel - data = data || {} - const { merge } = childClassOptions - const { instanceDefaults, idField, tempIdField } = this - .constructor as typeof BaseModel + public constructor(data, options: BaseModelInstanceOptions) { + if (!data) { + return + } + options = Object.assign({}, defaultOptions, options) + const { + store, + models, + instanceDefaults, + idField, + tempIdField, + setupInstance, + getFromStore, + _commit + } = this.constructor as typeof BaseModel const id = data[idField] || data[tempIdField] const hasValidId = id !== null && id !== undefined + data = data || {} + // If it already exists, update the original and return if (hasValidId && !options.clone) { - const existingItem = BaseModel.getFromStore.call(this, id) + const existingItem = getFromStore(id) if (existingItem) { - BaseModel._commit.call(this, 'updateItem', data) + _commit('updateItem', data) return existingItem } } @@ -100,7 +108,7 @@ export default function makeModel(options: FeathersVuexOptions) { // Setup instanceDefaults, separate out accessors if (instanceDefaults && typeof instanceDefaults === 'function') { - const defaults = instanceDefaults() + const defaults = instanceDefaults.call(this, this, { models, store }) const { accessors, values } = separateAccessors(defaults) mergeWithAccessors(this, accessors) mergeWithAccessors(this, values) @@ -108,13 +116,16 @@ export default function makeModel(options: FeathersVuexOptions) { // Handles Vue objects or regular ones. We can't simply assign or return // the data due to how Vue wraps everything into an accessor. - if (merge !== false) { - mergeWithAccessors(this, data) + if (options.merge !== false) { + mergeWithAccessors( + this, + setupInstance.call(this, data, { models, store }) + ) } // Add the item to the store if (!options.clone && options.commit !== false && store) { - BaseModel._commit.call(this, 'addItem', this) + _commit.call(this.constructor, 'addItem', this) } return this } @@ -125,26 +136,26 @@ export default function makeModel(options: FeathersVuexOptions) { } public static find(params) { - BaseModel._dispatch.call('find', params) + this._dispatch('find', params) } public static findInStore(params) { - return BaseModel._getters.call(this, 'find', params) + return this._getters('find', params) } public static get(id, params) { if (params) { - return BaseModel._dispatch.call(this, 'get', [id, params]) + return this._dispatch('get', [id, params]) } else { - return BaseModel._dispatch.call(this, 'get', id) + return this._dispatch('get', id) } } public static getFromStore(id, params?) { if (params) { - return BaseModel._getters.call(this, 'get', [id, params]) + return this._getters('get', [id, params]) } else { - return BaseModel._getters.call(this, 'get', id) + return this._getters('get', id) } } @@ -154,7 +165,7 @@ export default function makeModel(options: FeathersVuexOptions) { * @param payload if provided, the getter will be called as a function */ public static _getters(name: string, payload?: any) { - const { namespace, store } = this.constructor as typeof BaseModel + const { namespace, store } = this if (checkNamespace(namespace, this)) { if (!store.getters.hasOwnProperty(`${namespace}/${name}`)) { @@ -173,7 +184,7 @@ export default function makeModel(options: FeathersVuexOptions) { * @param payload the payload for the mutation */ public static _commit(method: string, payload: any): void { - const { namespace, store } = this.constructor as typeof BaseModel + const { namespace, store } = this if (checkNamespace(namespace, this)) { store.commit(`${namespace}/${method}`, payload) @@ -185,7 +196,7 @@ export default function makeModel(options: FeathersVuexOptions) { * @param payload the payload for the action */ public static _dispatch(method: string, payload: any) { - const { namespace, store } = this.constructor as typeof BaseModel + const { namespace, store } = this if (checkNamespace(namespace, this)) { return store.dispatch(`${namespace}/${method}`, payload) @@ -205,14 +216,14 @@ export default function makeModel(options: FeathersVuexOptions) { } private _clone(id) { - const { store, copiesById, namespace } = this + const { store, copiesById, namespace, _commit, _getters } = this .constructor as typeof BaseModel const { keepCopiesInStore } = store.state[namespace] - BaseModel._commit.call(this, `createCopy`, id) + _commit.call(this, `createCopy`, id) if (keepCopiesInStore) { - return BaseModel._getters.call(this, 'getCopyById', id) + return _getters.call(this, 'getCopyById', id) } else { return copiesById[id] } @@ -221,10 +232,11 @@ export default function makeModel(options: FeathersVuexOptions) { * Reset a clone to match the instance in the store. */ public reset() { - const { idField, tempIdField } = this.constructor as typeof BaseModel + const { idField, tempIdField, _commit } = this + .constructor as typeof BaseModel if (this.__isClone) { const id = this[idField] || this[tempIdField] - BaseModel._commit.call(this, 'resetCopy', id) + _commit('resetCopy', id) } else { throw new Error('You cannot reset a non-copy') } @@ -234,10 +246,11 @@ export default function makeModel(options: FeathersVuexOptions) { * Update a store instance to match a clone. */ public commit() { - const { idField, tempIdField } = this.constructor as typeof BaseModel + const { idField, tempIdField, _commit } = this + .constructor as typeof BaseModel if (this.__isClone) { const id = this[idField] || this[tempIdField] - BaseModel._commit.call(this, 'commitCopy', id) + _commit('commitCopy', id) return this } else { @@ -264,11 +277,12 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public create(params) { + const { _dispatch } = this.constructor as typeof BaseModel const data = Object.assign({}, this) if (data[options.idField] === null) { delete data[options.idField] } - return BaseModel._dispatch.call(this, 'create', [data, params]) + return _dispatch('create', [data, params]) } /** @@ -276,7 +290,7 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public patch(params?) { - const { idField } = this.constructor as typeof BaseModel + const { idField, _dispatch } = this.constructor as typeof BaseModel if (!this[idField]) { const error = new Error( @@ -286,11 +300,7 @@ export default function makeModel(options: FeathersVuexOptions) { ) return Promise.reject(error) } - return BaseModel._dispatch.call(this, 'patch', [ - this[idField], - this, - params - ]) + return _dispatch('patch', [this[idField], this, params]) } /** @@ -298,7 +308,7 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public update(params) { - const { idField } = this.constructor as typeof BaseModel + const { idField, _dispatch } = this.constructor as typeof BaseModel if (!this[idField]) { const error = new Error( @@ -308,11 +318,7 @@ export default function makeModel(options: FeathersVuexOptions) { ) return Promise.reject(error) } - return BaseModel._dispatch.call(this, 'update', [ - this[idField], - this, - params - ]) + return _dispatch('update', [this[idField], this, params]) } /** @@ -320,9 +326,9 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public remove(params) { - const { idField } = this.constructor as typeof BaseModel + const { idField, _dispatch } = this.constructor as typeof BaseModel - return BaseModel._dispatch.call(this, 'remove', [this[idField], params]) + return _dispatch('remove', [this[idField], params]) } public toJSON() { diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index 8ec7b10d..8f71f552 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -17,7 +17,8 @@ const defaults = { getters: {}, // for custom getters mutations: {}, // for custom mutations actions: {}, // for custom actions - instanceDefaults: () => ({}), // Default instanceDefaults is an empty object + instanceDefaults: () => ({}), // Default instanceDefaults returns an empty object + setupInstance: instance => instance, // Default setupInstance returns the instance serialize: item => item // Default serialize function } @@ -43,6 +44,7 @@ export default function prepareMakeServicePlugin( namespace, nameStyle, instanceDefaults, + setupInstance, preferUpdate, serialize } = options @@ -81,6 +83,7 @@ export default function prepareMakeServicePlugin( namespace: options.namespace, servicePath, instanceDefaults, + setupInstance, serialize, preferUpdate }) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 042536aa..2c5f27cd 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -252,3 +252,139 @@ commit('clearFindError') commit('setError', { method: 'find', error }) commit('clearError', 'find') ``` + +## Relationships have been separated from `instanceDefaults` + +Feathers-Vuex 2.0 has a new API for establishing relationships between data. Before we cover how it works, let's review the old API, first. + +Feathers-Vuex 1.x allowed using the `instanceDefaults` API to both setup default values for Vue reactivity AND establishing relationships between services. It supported passing a string name that matched a model name to setup a relationship, as shown in this next example. This was a simple, but very limited API: + +```js +// Defaults for a todo service +instanceDefaults: { + _id: '', + description: '', + isCompleted: false, + user: 'User' +} +``` + +Any instance data with a matching key would overwrite the same property in the instanceDefaults, which resulted in an inconsistent API. + +In Feathers-Vuex 2.0, the `instanceDefaults` work the same for setting defaults with only one exception (see the next example). They no longer setup the relationships, though. The new `setupInstance` function provides an API that is much more powerful. + +The main difference with `instanceDefaults` in Feathers-Vuex 2.0 is that it MUST be provided as a function, now: + +```js +// See the `model-instance-defaults.test.ts` file for example usage. +// This is a brief example. +instanceDefaults(data, { models, store}) { + return { + _id: '', + description: '', + isCompleted: false + // No user props, here. + } +} +``` + +Notice in the above example that we did not return `user`. We'll handle it in the `setupInstance` method. + +Where `instanceDefaults` props get replaced by instance data, the props returned from `setupInstance` overwrite the instance data. If it were using `Object.assign`, internally (it's not, but IF it were), it would look like the below example, where `data` is the original instance data passed to the constructor. + +```js +Object.assign({}, instanceDefaults(data), data, setupInstance(data)) +``` + +## Define Relationships and Modify Data with `setupInstance` + +The new `setupInstance` method allows a lot of flexibility in creating new instances. It has the exact same API as the `instanceDefaults` method. The only difference is the order in which they are applied to the instance data. + +While you could technically use `setupInstance` to do all of your default values, the APIs have been kept separate to allow a clean separation between setting up defaults and establishing relationships and other constructors. + + +```js +// See the `model-relationships.test.ts` file for example usage. +// This is a brief example. +function setupInstance(data, { models, store }) { + const { User, Tag } = models.myServerAlias // Based on the serverAlias you provide, initially + + // A single User instance + if (data.user) { + data.user = new User(data.user) + } + // An array of Tag instances + if (data.tags) { + data.tags = data.tags.map(t => new Tag(t)) + } + // A JavaScript Date Object + if (data.createdAt) { + data.createdAt = new Date(data.createdAt) + } +} +``` + +Or below is an example that does the exact same thing with one line per attribute: + +```js +function setupInstance(data, { models, store }) { + const { User } = models.myServerAlias + + return Object.assign(data, { + ...(data.user && { user: new User(data.user) }), // A single User instance + ...(data.tags && { tags: data.tags.map(t => new Tag(t)) }), // An array of Tag instances + ...(data.createdAt && { createdAt: new Date(data.createdAt) }) // A JavaScript Date Object + }) +} +``` + +Where `instanceDefaults` props get replaced by instance data, the props returned from `setupInstance` overwrite the instance data. If it were using `Object.assign`, internally (it's not, but IF it were), it would look like the below example, where `data` is the original instance data passed to the constructor. + +```js +Object.assign({}, instanceDefaults(data), data, setupInstance(data)) +``` + +## Preventing duplicate merge when extending BaseModel with a custom constructor + +The BaseModel constructor calls `mergeWithAccessors(this, newData)`. This utility function correctly copies data between both regular objects and Vue.observable instances. If you create a class where you need to do your own merging, you probably don't want `mergeWithAccessors` to run twice. In this case, you can use the `merge: false` BaseModel instance option to prevent the internal merge. You can then access the `mergeWithAccessors` method by calling `MyModel.merge(this, newData)`. Here's an example: + +```ts +const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'myApiServer' +}) + +class Todo extends BaseModel { + public constructor(data, options?) { + options.merge = false // Prevent the internal merge from occurring. + super(data, options) + + // ... your custom construcor logic happens here. + + // Call the static merge method to do your own merging. + Todo.merge(this, data) + } +} +``` + +It's important to note that setting `merge: false` in the options will disable the `setupinstance` function. You need to manually call it, like this: + +```ts +class Todo extends BaseModel { + public constructor(data, options?) { + options.merge = false // Prevent the internal merge from occurring. + super(data, options) + + // ... your custom construcor logic happens here. + + // Call setupInstance manually + const { models, store } = Todo + // JavaScript fundamentals: if you're using `this` in `setupInstance`, use .call(this, ...) + const instanceData = Todo.setupInstance.call(this, data, { models, store }) + // If you're not using `this, just call it like normal + const instanceData = Todo.setupInstance(data, { models, store }) + + // Call the static merge method to do your own merging. + Todo.merge(this, instanceData) + } +} +``` \ No newline at end of file diff --git a/src/service-module/types.ts b/src/service-module/types.ts index 7ce5e9fa..d916ed58 100644 --- a/src/service-module/types.ts +++ b/src/service-module/types.ts @@ -33,6 +33,7 @@ export interface MakeServicePluginOptions { preferUpdate?: boolean servicePath?: string instanceDefaults?: () => {} + setupInstance?: (data, { models, store }) => {} serialize?: () => {} state?: {} getters?: {} diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts new file mode 100644 index 00000000..56fc329c --- /dev/null +++ b/test/service-module/model-relationships.test.ts @@ -0,0 +1,481 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { assert } from 'chai' +import feathersVuex, { models } from '../../src/index' +import { clearModels } from '../../src/service-module/global-models' + +import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' +import Vuex from 'vuex' + +describe('Models - `setupInstance` & Relational Data', function() { + beforeEach(function() { + clearModels() + }) + + it('initializes instance with return value from setupInstance', function() { + let calledSetupInstance = false + + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'myApi' + }) + class Todo extends BaseModel { + public id? + public description: string + + public constructor(data, options?) { + super(data, options) + } + } + function setupInstance(instance, { models, store }): Todo { + calledSetupInstance = true + + return Object.assign(instance, { + extraProp: true + }) + } + const store = new Vuex.Store({ + strict: true, + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('service-todos'), + setupInstance + }) + ] + }) + + const createdAt = '2018-05-01T04:42:24.136Z' + const todo = new Todo({ + description: 'Go on a date.', + isComplete: true, + createdAt + }) + + assert(calledSetupInstance, 'setupInstance was called') + assert(todo.extraProp, 'got the extraProp') + }) + + it.only('allows setting up relationships between models and other constructors', function() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'myApi' + }) + class Todo extends BaseModel { + public id? + public description: string + public user: User + + public constructor(data, options?) { + super(data, options) + } + } + class User extends BaseModel { + public _id: string + public firstName: string + public email: string + + public constructor(data, options?) { + super(data, options) + + console.log(this) + } + } + + function setupInstance(instance, { models, store }): Todo { + const { User } = models.myApi + + return Object.assign(instance, { + // If instance.user exists, convert it to a User instance + ...(instance.user && { user: new User(instance.user) }), + // If instance.createdAt exists, convert it to an actual date + ...(instance.createdAt && { createdAt: new Date(instance.createdAt) }) + }) + } + const store = new Vuex.Store({ + strict: true, + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('service-todos'), + setupInstance + }), + makeServicePlugin({ + Model: User, + service: feathersClient.service('users'), + idField: '_id' + }) + ] + }) + + const todo = new Todo({ + description: `Show Master Splinter what's up.`, + isComplete: true, + createdAt: '2018-05-01T04:42:24.136Z', + user: { + _id: 1, + firstName: 'Michaelangelo', + email: 'mike@tmnt.com' + } + }) + + // Check the date + assert( + typeof todo.createdAt === 'object', + 'module.createdAt is an instance of object' + ) + assert( + todo.createdAt.constructor.name === 'Date', + 'module.createdAt is an instance of date' + ) + + // Check the user + assert(todo.user instanceof User, 'the user is an instance of User') + + const user = User.getFromStore(1) + assert.equal(todo.user, user, 'user was added to the user store.') + }) +}) + +describe('Models - Relationships', function() { + beforeEach(function() { + const { makeServicePlugin, BaseModel } = this + class Task extends BaseModel { + public static instanceDefaults: { + id: null + description: '' + isComplete: false + } + } + class ServiceTodo extends BaseModel { + public static instanceDefaults(data) { + const priority = data.priority || 'normal' + const defaultsByPriority = { + normal: { + description: '', + isComplete: false, + task: 'Task', + item: 'Item', + priority: '' + }, + high: { + isHighPriority: true, + priority: '' + } + } + return defaultsByPriority[priority] + } + } + class Item extends BaseModel { + public static instanceDefaults({ Models }) { + return { + test: false, + todo: 'Todo', + get todos() { + return Models.Todo.findInStore({ query: {} }).data + } + } + } + } + this.store = new Vuex.Store({ + strict: true, + plugins: [ + makeServicePlugin({ + Model: Task, + service: feathersClient.service('tasks') + }), + makeServicePlugin({ + Model: ServiceTodo, + service: feathersClient.service('service-todos') + }), + makeServicePlugin({ + Model: Item, + service: feathersClient.service('items'), + mutations: { + toggleTestBoolean(state, item) { + item.test = !item.test + } + } + }) + ] + }) + this.Todo = ServiceTodo + this.Task = models.Task + this.Item = models.Item + }) + + it('can setup relationships through es5 getters in instanceDefaults', function() { + const { Item, Todo } = this + const module = new Todo({ id: 5, description: 'hey' }) + const item = new Item({}) + + assert(Array.isArray(item.todos), 'Received an array of todos') + assert(item.todos[0] === module, 'The todo was returned through the getter') + }) + + it('can have different instanceDefaults based on new instance data', function() { + const { Todo } = this + const normalTodo = new Todo({ + description: 'Normal' + }) + const highPriorityTodo = new Todo({ + description: 'High Priority', + priority: 'high' + }) + + assert( + !normalTodo.hasOwnProperty('isHighPriority'), + 'Normal todos do not have an isHighPriority default attribute' + ) + assert( + highPriorityTodo.isHighPriority, + 'High priority todos have a unique attribute' + ) + }) + + it('converts keys that match Model names into Model instances', function() { + const { Todo, store } = this + const module = new Todo({ + task: { + description: 'test', + isComplete: true + } + }) + + assert( + module.task.constructor.className === 'Task', + 'task is an instance of Task' + ) + assert.deepEqual( + store.state.tasks.keyedById, + {}, + 'nothing was added to the store' + ) + }) + + it('adds model instances containing an id to the store', function() { + const { Todo, store } = this + + const module = new Todo({ + task: { + id: 1, + description: 'test', + isComplete: true + } + }) + + assert.deepEqual( + store.state.tasks.keyedById[1], + module.task, + 'task was added to the store' + ) + }) + + it('works with multiple keys that match Model names', function() { + const { Todo, store } = this + + const module = new Todo({ + task: { + id: 1, + description: 'test', + isComplete: true + }, + item: { + id: 2, + test: true + } + }) + + assert.deepEqual( + store.state.tasks.keyedById[1], + module.task, + 'task was added to the store' + ) + assert.deepEqual( + store.state.items.keyedById[2], + module.item, + 'item was added to the store' + ) + }) + + it('handles nested relationships', function() { + const { Todo } = this + + const module = new Todo({ + task: { + id: 1, + description: 'test', + isComplete: true + }, + item: { + id: 2, + test: true, + todo: { + description: 'nested todo under item' + } + } + }) + + assert( + module.item.module.constructor.className === 'Todo', + 'the nested todo is an instance of Todo' + ) + }) + + it('handles recursive nested relationships', function() { + const { Todo, store } = this + + const module = new Todo({ + id: 1, + description: 'todo description', + item: { + id: 2, + test: true, + todo: { + id: 1, + description: 'todo description' + } + } + }) + + assert.deepEqual( + store.state.todos.keyedById[1], + module, + 'todo was added to the store' + ) + assert.deepEqual( + store.state.items.keyedById[2], + module.item, + 'item was added to the store' + ) + assert(module.item, 'todo still has an item') + assert(module.item.module, 'todo still nested in itself') + }) + + it('updates related data', function() { + const { Todo, store } = this + + const module = new Todo({ + id: 'todo-1', + description: 'todo description', + item: { + id: 'item-2', + test: true, + todo: { + id: 'todo-1', + description: 'todo description' + } + } + }) + + const storedTodo = store.state.todos.keyedById['todo-1'] + const storedItem = store.state.items.keyedById['item-2'] + + store.commit('items/toggleTestBoolean', storedItem) + // module.item.test = false + + assert.equal( + module.item.test, + false, + 'the nested module.item.test should be false' + ) + assert.equal( + storedTodo.item.test, + false, + 'the nested item.test should be false' + ) + assert.equal(storedItem.test, false, 'item.test should be false') + }) + + it(`allows creating more than once relational instance`, function() { + const { Todo, store } = this + + const todo1 = new Todo({ + id: 'todo-1', + description: 'todo description', + item: { + id: 'item-2', + test: true + } + }) + const todo2 = new Todo({ + id: 'todo-2', + description: 'todo description', + item: { + id: 'item-3', + test: true + } + }) + + const storedTodo = store.state.todos.keyedById['todo-2'] + const storedItem = store.state.items.keyedById['item-3'] + + assert.equal( + todo1.item.test, + true, + 'the nested module.item.test should be true' + ) + assert.equal( + todo2.item.test, + true, + 'the nested module.item.test should be true' + ) + assert.equal( + storedTodo.item.test, + true, + 'the nested item.test should be true' + ) + assert.equal(storedItem.test, true, 'item.test should be true') + }) + + it(`handles arrays of related data`, function() { + const { Todo, store } = this + + const todo1 = new Todo({ + id: 'todo-1', + description: 'todo description', + item: [ + { + id: 'item-1', + test: true + }, + { + id: 'item-2', + test: true + } + ] + }) + const todo2 = new Todo({ + id: 'todo-2', + description: 'todo description', + item: [ + { + id: 'item-3', + test: true + }, + { + id: 'item-4', + test: true + } + ] + }) + + assert(todo1, 'todo1 is an instance') + assert(todo2, 'todo2 is an instance') + + const storedTodo1 = store.state.todos.keyedById['todo-1'] + const storedTodo2 = store.state.todos.keyedById['todo-2'] + const storedItem1 = store.state.items.keyedById['item-1'] + const storedItem2 = store.state.items.keyedById['item-2'] + const storedItem3 = store.state.items.keyedById['item-3'] + const storedItem4 = store.state.items.keyedById['item-4'] + + assert(storedTodo1, 'should have todo 1') + assert(storedTodo2, 'should have todo 2') + assert(storedItem1, 'should have item 1') + assert(storedItem2, 'should have item 2') + assert(storedItem3, 'should have item 3') + assert(storedItem4, 'should have item 4') + }) +}) diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 254082c9..80ebfbbf 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -346,396 +346,6 @@ describe('Service Module', function() { }) }) - describe('Models - Dates', function() { - beforeEach(function() { - const { makeServicePlugin, ServiceTodo } = this - const instanceDefaults = { - id: null, - description: '', - isComplete: false, - createdAt: Date - } - this.store = new Vuex.Store({ - strict: true, - plugins: [ - makeServicePlugin({ - Model: ServiceTodo, - service: feathersClient.service('service-todos') - }) - ] - }) - this.Todo = ServiceTodo - }) - - it('converts keys that contain the Date constructor into date instances', function() { - const { Todo } = this - const createdAt = '2018-05-01T04:42:24.136Z' - const module = new Todo({ - description: 'Go on a date.', - isComplete: true, - createdAt - }) - - assert( - typeof module.createdAt === 'object', - 'module.createdAt is an instance of object' - ) - assert( - module.createdAt.constructor.name === 'Date', - 'module.createdAt is an instance of date' - ) - assert( - module.createdAt.toString() === new Date(createdAt).toString(), - 'the correct date was used' - ) - }) - }) - - describe('Models - Relationships', function() { - beforeEach(function() { - const { makeServicePlugin, BaseModel } = this - class Task extends BaseModel { - public static instanceDefaults: { - id: null - description: '' - isComplete: false - } - } - class ServiceTodo extends BaseModel { - public static instanceDefaults(data) { - const priority = data.priority || 'normal' - const defaultsByPriority = { - normal: { - description: '', - isComplete: false, - task: 'Task', - item: 'Item', - priority: '' - }, - high: { - isHighPriority: true, - priority: '' - } - } - return defaultsByPriority[priority] - } - } - class Item extends BaseModel { - public static instanceDefaults({ Models }) { - return { - test: false, - todo: 'Todo', - get todos() { - return Models.Todo.findInStore({ query: {} }).data - } - } - } - } - this.store = new Vuex.Store({ - strict: true, - plugins: [ - makeServicePlugin({ - Model: Task, - service: feathersClient.service('tasks') - }), - makeServicePlugin({ - Model: ServiceTodo, - service: feathersClient.service('service-todos') - }), - makeServicePlugin({ - Model: Item, - service: feathersClient.service('items'), - mutations: { - toggleTestBoolean(state, item) { - item.test = !item.test - } - } - }) - ] - }) - this.Todo = ServiceTodo - this.Task = models.Task - this.Item = models.Item - }) - - it('can setup relationships through es5 getters in instanceDefaults', function() { - const { Item, Todo } = this - const module = new Todo({ id: 5, description: 'hey' }) - const item = new Item({}) - - assert(Array.isArray(item.todos), 'Received an array of todos') - assert( - item.todos[0] === module, - 'The todo was returned through the getter' - ) - }) - - it('can have different instanceDefaults based on new instance data', function() { - const { Todo } = this - const normalTodo = new Todo({ - description: 'Normal' - }) - const highPriorityTodo = new Todo({ - description: 'High Priority', - priority: 'high' - }) - - assert( - !normalTodo.hasOwnProperty('isHighPriority'), - 'Normal todos do not have an isHighPriority default attribute' - ) - assert( - highPriorityTodo.isHighPriority, - 'High priority todos have a unique attribute' - ) - }) - - it('converts keys that match Model names into Model instances', function() { - const { Todo, store } = this - const module = new Todo({ - task: { - description: 'test', - isComplete: true - } - }) - - assert( - module.task.constructor.className === 'Task', - 'task is an instance of Task' - ) - assert.deepEqual( - store.state.tasks.keyedById, - {}, - 'nothing was added to the store' - ) - }) - - it('adds model instances containing an id to the store', function() { - const { Todo, store } = this - - const module = new Todo({ - task: { - id: 1, - description: 'test', - isComplete: true - } - }) - - assert.deepEqual( - store.state.tasks.keyedById[1], - module.task, - 'task was added to the store' - ) - }) - - it('works with multiple keys that match Model names', function() { - const { Todo, store } = this - - const module = new Todo({ - task: { - id: 1, - description: 'test', - isComplete: true - }, - item: { - id: 2, - test: true - } - }) - - assert.deepEqual( - store.state.tasks.keyedById[1], - module.task, - 'task was added to the store' - ) - assert.deepEqual( - store.state.items.keyedById[2], - module.item, - 'item was added to the store' - ) - }) - - it('handles nested relationships', function() { - const { Todo } = this - - const module = new Todo({ - task: { - id: 1, - description: 'test', - isComplete: true - }, - item: { - id: 2, - test: true, - todo: { - description: 'nested todo under item' - } - } - }) - - assert( - module.item.module.constructor.className === 'Todo', - 'the nested todo is an instance of Todo' - ) - }) - - it('handles recursive nested relationships', function() { - const { Todo, store } = this - - const module = new Todo({ - id: 1, - description: 'todo description', - item: { - id: 2, - test: true, - todo: { - id: 1, - description: 'todo description' - } - } - }) - - assert.deepEqual( - store.state.todos.keyedById[1], - module, - 'todo was added to the store' - ) - assert.deepEqual( - store.state.items.keyedById[2], - module.item, - 'item was added to the store' - ) - assert(module.item, 'todo still has an item') - assert(module.item.module, 'todo still nested in itself') - }) - - it('updates related data', function() { - const { Todo, store } = this - - const module = new Todo({ - id: 'todo-1', - description: 'todo description', - item: { - id: 'item-2', - test: true, - todo: { - id: 'todo-1', - description: 'todo description' - } - } - }) - - const storedTodo = store.state.todos.keyedById['todo-1'] - const storedItem = store.state.items.keyedById['item-2'] - - store.commit('items/toggleTestBoolean', storedItem) - // module.item.test = false - - assert.equal( - module.item.test, - false, - 'the nested module.item.test should be false' - ) - assert.equal( - storedTodo.item.test, - false, - 'the nested item.test should be false' - ) - assert.equal(storedItem.test, false, 'item.test should be false') - }) - - it(`allows creating more than once relational instance`, function() { - const { Todo, store } = this - - const todo1 = new Todo({ - id: 'todo-1', - description: 'todo description', - item: { - id: 'item-2', - test: true - } - }) - const todo2 = new Todo({ - id: 'todo-2', - description: 'todo description', - item: { - id: 'item-3', - test: true - } - }) - - const storedTodo = store.state.todos.keyedById['todo-2'] - const storedItem = store.state.items.keyedById['item-3'] - - assert.equal( - todo1.item.test, - true, - 'the nested module.item.test should be true' - ) - assert.equal( - todo2.item.test, - true, - 'the nested module.item.test should be true' - ) - assert.equal( - storedTodo.item.test, - true, - 'the nested item.test should be true' - ) - assert.equal(storedItem.test, true, 'item.test should be true') - }) - - it(`handles arrays of related data`, function() { - const { Todo, store } = this - - const todo1 = new Todo({ - id: 'todo-1', - description: 'todo description', - item: [ - { - id: 'item-1', - test: true - }, - { - id: 'item-2', - test: true - } - ] - }) - const todo2 = new Todo({ - id: 'todo-2', - description: 'todo description', - item: [ - { - id: 'item-3', - test: true - }, - { - id: 'item-4', - test: true - } - ] - }) - - assert(todo1, 'todo1 is an instance') - assert(todo2, 'todo2 is an instance') - - const storedTodo1 = store.state.todos.keyedById['todo-1'] - const storedTodo2 = store.state.todos.keyedById['todo-2'] - const storedItem1 = store.state.items.keyedById['item-1'] - const storedItem2 = store.state.items.keyedById['item-2'] - const storedItem3 = store.state.items.keyedById['item-3'] - const storedItem4 = store.state.items.keyedById['item-4'] - - assert(storedTodo1, 'should have todo 1') - assert(storedTodo2, 'should have todo 2') - assert(storedItem1, 'should have item 1') - assert(storedItem2, 'should have item 2') - assert(storedItem3, 'should have item 3') - assert(storedItem4, 'should have item 4') - }) - }) - describe('Setting Up', () => { it('service stores have global defaults', function() { const { makeServicePlugin, BaseModel, Task } = this From a507a0b6cc60e1f2bd9efb3f68b167e69545b79f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 23:00:57 -0600 Subject: [PATCH 110/404] Fix test --- test/service-module/make-service-plugin.test.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index 43489567..a8015bc4 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -20,7 +20,7 @@ describe('makeServicePlugin', function() { it('registers the vuex module with options', function() { interface RootState { - todos: { options: {} } + todos: {} } const serverAlias = 'default' @@ -75,20 +75,23 @@ describe('makeServicePlugin', function() { serverAlias: 'default', servicePath: 'todos', skipRequestIfExists: false, + setupInstance: item => item, serialize: item => item, tempsById: {}, whitelist: [] } assert.deepEqual( - _omit(received, ['instanceDefaults', 'serialize']), + _omit(received, ['instanceDefaults', 'serialize', 'setupInstance']), // @ts-ignore - _omit(expected, ['instanceDefaults', 'serialize']), + _omit(expected, ['instanceDefaults', 'serialize', 'setupInstance']), 'The module was registered.' ) // @ts-ignore assert.equal(typeof received.serialize, 'function') // @ts-ignore + assert.equal(typeof received.setupInstance, 'function') + // @ts-ignore assert.equal(typeof received.instanceDefaults, 'function') }) From bb614ca65431c026651a17f3879361ae0f963dac Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 23:17:41 -0600 Subject: [PATCH 111/404] Fix all contexts --- src/service-module/make-model.ts | 41 ++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 588d9461..2c743dd0 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -46,8 +46,12 @@ export default function makeModel(options: FeathersVuexOptions) { // Think of these as abstract static properties public static servicePath: string public static namespace: string - public static instanceDefaults - public static setupInstance + public static instanceDefaults(data, { models, store }) { + return data + } + public static setupInstance(data, { models, store }) { + return data + } public static serialize // Monkey patched onto the Model class in `makeServicePlugin()` @@ -90,9 +94,9 @@ export default function makeModel(options: FeathersVuexOptions) { // If it already exists, update the original and return if (hasValidId && !options.clone) { - const existingItem = getFromStore(id) + const existingItem = getFromStore.call(this.constructor, id) if (existingItem) { - _commit('updateItem', data) + _commit.call(this.constructor, 'updateItem', data) return existingItem } } @@ -220,10 +224,10 @@ export default function makeModel(options: FeathersVuexOptions) { .constructor as typeof BaseModel const { keepCopiesInStore } = store.state[namespace] - _commit.call(this, `createCopy`, id) + _commit.call(this.constructor, `createCopy`, id) if (keepCopiesInStore) { - return _getters.call(this, 'getCopyById', id) + return _getters.call(this.constructor, 'getCopyById', id) } else { return copiesById[id] } @@ -236,7 +240,7 @@ export default function makeModel(options: FeathersVuexOptions) { .constructor as typeof BaseModel if (this.__isClone) { const id = this[idField] || this[tempIdField] - _commit('resetCopy', id) + _commit.call(this.constructor, 'resetCopy', id) } else { throw new Error('You cannot reset a non-copy') } @@ -250,7 +254,7 @@ export default function makeModel(options: FeathersVuexOptions) { .constructor as typeof BaseModel if (this.__isClone) { const id = this[idField] || this[tempIdField] - _commit('commitCopy', id) + _commit.call(this.constructor, 'commitCopy', id) return this } else { @@ -263,10 +267,9 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public save(params) { - const id = this[options.idField] + const { idField, preferUpdate } = this.constructor as typeof BaseModel + const id = this[idField] if (id) { - const preferUpdate = Object.getPrototypeOf(this).constructor - .preferUpdate return preferUpdate ? this.update(params) : this.patch(params) } else { return this.create(params) @@ -282,7 +285,7 @@ export default function makeModel(options: FeathersVuexOptions) { if (data[options.idField] === null) { delete data[options.idField] } - return _dispatch('create', [data, params]) + return _dispatch.call(this.constructor, 'create', [data, params]) } /** @@ -300,7 +303,11 @@ export default function makeModel(options: FeathersVuexOptions) { ) return Promise.reject(error) } - return _dispatch('patch', [this[idField], this, params]) + return _dispatch.call(this.constructor, 'patch', [ + this[idField], + this, + params + ]) } /** @@ -318,7 +325,11 @@ export default function makeModel(options: FeathersVuexOptions) { ) return Promise.reject(error) } - return _dispatch('update', [this[idField], this, params]) + return _dispatch.call(this.constructor, 'update', [ + this[idField], + this, + params + ]) } /** @@ -328,7 +339,7 @@ export default function makeModel(options: FeathersVuexOptions) { public remove(params) { const { idField, _dispatch } = this.constructor as typeof BaseModel - return _dispatch('remove', [this[idField], params]) + return _dispatch.call(this.constructor, 'remove', [this[idField], params]) } public toJSON() { From f8f0dba619f3bdff5787351b833af027825280a1 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 30 Mar 2019 23:17:56 -0600 Subject: [PATCH 112/404] Fix many tests after adding setupInstance --- test/service-module/model-relationships.test.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index 56fc329c..1f2dc045 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -58,7 +58,7 @@ describe('Models - `setupInstance` & Relational Data', function() { assert(todo.extraProp, 'got the extraProp') }) - it.only('allows setting up relationships between models and other constructors', function() { + it('allows setting up relationships between models and other constructors', function() { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { serverAlias: 'myApi' }) @@ -75,12 +75,6 @@ describe('Models - `setupInstance` & Relational Data', function() { public _id: string public firstName: string public email: string - - public constructor(data, options?) { - super(data, options) - - console.log(this) - } } function setupInstance(instance, { models, store }): Todo { From 40d1906459220a0c6634221847a61d4885f4d4c2 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 00:03:11 -0600 Subject: [PATCH 113/404] Pass data into instanceDefaults, not this --- src/service-module/make-model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 2c743dd0..dab6ff21 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -112,7 +112,7 @@ export default function makeModel(options: FeathersVuexOptions) { // Setup instanceDefaults, separate out accessors if (instanceDefaults && typeof instanceDefaults === 'function') { - const defaults = instanceDefaults.call(this, this, { models, store }) + const defaults = instanceDefaults.call(this, data, { models, store }) const { accessors, values } = separateAccessors(defaults) mergeWithAccessors(this, accessors) mergeWithAccessors(this, values) From 95746c49c596a2162cb487019262d82c4fc82b5f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 00:03:29 -0600 Subject: [PATCH 114/404] =?UTF-8?q?Don=E2=80=99t=20overwrite=20props=20def?= =?UTF-8?q?ined=20on=20the=20Model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service-module/make-service-plugin.ts | 4 ++-- src/utils.ts | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index 8f71f552..b70f1473 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -6,7 +6,7 @@ eslint import { FeathersVuexOptions, MakeServicePluginOptions } from './types' import makeServiceModule from './make-service-module' import { globalModels, prepareAddModel } from './global-models' -import { makeNamespace, getServicePath } from '../utils' +import { makeNamespace, getServicePath, assignIfNotPresent } from '../utils' import { get as _get } from 'lodash' const defaults = { @@ -78,7 +78,7 @@ export default function prepareMakeServicePlugin( }) } // (2b^) Monkey patch the Model(s) and add to globalModels - Object.assign(Model, { + assignIfNotPresent(Model, { store, namespace: options.namespace, servicePath, diff --git a/src/utils.ts b/src/utils.ts index 7d585465..d2e5b637 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -401,3 +401,11 @@ export function checkNamespace(namespace, item) { } return namespace !== null && namespace !== undefined } + +export function assignIfNotPresent(Model, props): void { + for (let key in props) { + if (!Model.hasOwnProperty(key)) { + Model[key] = props[key] + } + } +} From 3d4ec84ad387bd41c6be1ecf289f4ad662e4971f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 00:03:49 -0600 Subject: [PATCH 115/404] Clean up some relationship tests --- .../model-relationships.test.ts | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index 1f2dc045..293ecfe2 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -134,15 +134,21 @@ describe('Models - `setupInstance` & Relational Data', function() { describe('Models - Relationships', function() { beforeEach(function() { - const { makeServicePlugin, BaseModel } = this + clearModels() + + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'myApi' + }) class Task extends BaseModel { - public static instanceDefaults: { - id: null - description: '' - isComplete: false + public static instanceDefaults() { + return { + id: null, + description: '', + isComplete: false + } } } - class ServiceTodo extends BaseModel { + class Todo extends BaseModel { public static instanceDefaults(data) { const priority = data.priority || 'normal' const defaultsByPriority = { @@ -180,7 +186,7 @@ describe('Models - Relationships', function() { service: feathersClient.service('tasks') }), makeServicePlugin({ - Model: ServiceTodo, + Model: Todo, service: feathersClient.service('service-todos') }), makeServicePlugin({ @@ -194,21 +200,12 @@ describe('Models - Relationships', function() { }) ] }) - this.Todo = ServiceTodo - this.Task = models.Task - this.Item = models.Item - }) - - it('can setup relationships through es5 getters in instanceDefaults', function() { - const { Item, Todo } = this - const module = new Todo({ id: 5, description: 'hey' }) - const item = new Item({}) - - assert(Array.isArray(item.todos), 'Received an array of todos') - assert(item.todos[0] === module, 'The todo was returned through the getter') + this.Todo = Todo + this.Task = Task + this.Item = Item }) - it('can have different instanceDefaults based on new instance data', function() { + it.only('can have different instanceDefaults based on new instance data', function() { const { Todo } = this const normalTodo = new Todo({ description: 'Normal' From 173de0426f65ab0fb5be667f3e96509e83b5e3dc Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 00:20:06 -0600 Subject: [PATCH 116/404] Add more relational data tests --- .../model-relationships.test.ts | 66 +++++++++---------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index 293ecfe2..9270281f 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -10,7 +10,7 @@ import { clearModels } from '../../src/service-module/global-models' import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' import Vuex from 'vuex' -describe('Models - `setupInstance` & Relational Data', function() { +describe('Models - `setupInstance` & Relatioships', function() { beforeEach(function() { clearModels() }) @@ -166,16 +166,30 @@ describe('Models - Relationships', function() { } return defaultsByPriority[priority] } + public static setupInstance(data, { models, store }) { + const { Task, Item } = models.myApi + + return Object.assign(data, { + ...(data.task && { task: new Task(data.task) }), + ...(data.item && { item: new Item(data.item) }) + }) + } } class Item extends BaseModel { - public static instanceDefaults({ Models }) { + public static instanceDefaults() { return { test: false, - todo: 'Todo', + todo: 'Todo' + } + } + public static setupInstance(data, { models, store }) { + const { Todo } = models.myApi + + return Object.assign(data, { get todos() { - return Models.Todo.findInStore({ query: {} }).data + return Todo.findInStore({ query: {} }).data } - } + }) } } this.store = new Vuex.Store({ @@ -205,7 +219,7 @@ describe('Models - Relationships', function() { this.Item = Item }) - it.only('can have different instanceDefaults based on new instance data', function() { + it('can have different instanceDefaults based on new instance data', function() { const { Todo } = this const normalTodo = new Todo({ description: 'Normal' @@ -225,30 +239,10 @@ describe('Models - Relationships', function() { ) }) - it('converts keys that match Model names into Model instances', function() { - const { Todo, store } = this - const module = new Todo({ - task: { - description: 'test', - isComplete: true - } - }) - - assert( - module.task.constructor.className === 'Task', - 'task is an instance of Task' - ) - assert.deepEqual( - store.state.tasks.keyedById, - {}, - 'nothing was added to the store' - ) - }) - it('adds model instances containing an id to the store', function() { - const { Todo, store } = this + const { Todo, Task } = this - const module = new Todo({ + const todo = new Todo({ task: { id: 1, description: 'test', @@ -257,16 +251,16 @@ describe('Models - Relationships', function() { }) assert.deepEqual( - store.state.tasks.keyedById[1], - module.task, + Task.getFromStore(1), + todo.task, 'task was added to the store' ) }) it('works with multiple keys that match Model names', function() { - const { Todo, store } = this + const { Todo, Task, Item } = this - const module = new Todo({ + const todo = new Todo({ task: { id: 1, description: 'test', @@ -279,13 +273,13 @@ describe('Models - Relationships', function() { }) assert.deepEqual( - store.state.tasks.keyedById[1], - module.task, + Task.getFromStore(1), + todo.task, 'task was added to the store' ) assert.deepEqual( - store.state.items.keyedById[2], - module.item, + Item.getFromStore(2), + todo.item, 'item was added to the store' ) }) From b10d821b023f1f98c2a112cce41248a43e53a4e3 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 00:24:27 -0600 Subject: [PATCH 117/404] Add test for nested relationships --- test/service-module/model-relationships.test.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index 9270281f..85409cbe 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -188,7 +188,8 @@ describe('Models - Relationships', function() { return Object.assign(data, { get todos() { return Todo.findInStore({ query: {} }).data - } + }, + ...(data.todo && { todo: new Todo(data.todo) }) }) } } @@ -287,7 +288,7 @@ describe('Models - Relationships', function() { it('handles nested relationships', function() { const { Todo } = this - const module = new Todo({ + const todo = new Todo({ task: { id: 1, description: 'test', @@ -303,7 +304,7 @@ describe('Models - Relationships', function() { }) assert( - module.item.module.constructor.className === 'Todo', + todo.item.todo.constructor.name === 'Todo', 'the nested todo is an instance of Todo' ) }) From 4377ecbea0b5888cafa9880ebdf45670d792c5c0 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 00:26:54 -0600 Subject: [PATCH 118/404] Add test for circular relationships --- .../model-relationships.test.ts | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index 85409cbe..6ccf7b51 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -309,10 +309,10 @@ describe('Models - Relationships', function() { ) }) - it('handles recursive nested relationships', function() { - const { Todo, store } = this + it('handles circular nested relationships', function() { + const { Todo, Item } = this - const module = new Todo({ + const todo = new Todo({ id: 1, description: 'todo description', item: { @@ -325,18 +325,14 @@ describe('Models - Relationships', function() { } }) + assert.deepEqual(Todo.getFromStore(1), todo, 'todo was added to the store') assert.deepEqual( - store.state.todos.keyedById[1], - module, - 'todo was added to the store' - ) - assert.deepEqual( - store.state.items.keyedById[2], - module.item, + Item.getFromStore(2), + todo.item, 'item was added to the store' ) - assert(module.item, 'todo still has an item') - assert(module.item.module, 'todo still nested in itself') + assert(todo.item, 'todo still has an item') + assert(todo.item.todo, 'todo still nested in itself') }) it('updates related data', function() { From c11b2d21ad7ce4c474c1d582e61b5b10d85433d1 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 00:28:52 -0600 Subject: [PATCH 119/404] Add test for updating related data --- test/service-module/model-relationships.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index 6ccf7b51..71423614 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -336,7 +336,7 @@ describe('Models - Relationships', function() { }) it('updates related data', function() { - const { Todo, store } = this + const { Todo, Item, store } = this const module = new Todo({ id: 'todo-1', @@ -351,8 +351,8 @@ describe('Models - Relationships', function() { } }) - const storedTodo = store.state.todos.keyedById['todo-1'] - const storedItem = store.state.items.keyedById['item-2'] + const storedTodo = Todo.getFromStore('todo-1') + const storedItem = Item.getFromStore('item-2') store.commit('items/toggleTestBoolean', storedItem) // module.item.test = false From ddb15fb5b134bb98927ac57030b5cc198a121e98 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 00:30:21 -0600 Subject: [PATCH 120/404] Add test for creating more than one relationsihp --- test/service-module/model-relationships.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index 71423614..6eec60e8 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -371,7 +371,7 @@ describe('Models - Relationships', function() { }) it(`allows creating more than once relational instance`, function() { - const { Todo, store } = this + const { Todo, Item } = this const todo1 = new Todo({ id: 'todo-1', @@ -390,8 +390,8 @@ describe('Models - Relationships', function() { } }) - const storedTodo = store.state.todos.keyedById['todo-2'] - const storedItem = store.state.items.keyedById['item-3'] + const storedTodo = Todo.getFromStore('todo-1') + const storedItem = Item.getFromStore('item-2') assert.equal( todo1.item.test, From 18f88852d39bfe2d2601cda56c0fd2ec465033e8 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 00:34:42 -0600 Subject: [PATCH 121/404] Add test for arrays of related instances --- .../model-relationships.test.ts | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index 6eec60e8..38f7e624 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -171,7 +171,8 @@ describe('Models - Relationships', function() { return Object.assign(data, { ...(data.task && { task: new Task(data.task) }), - ...(data.item && { item: new Item(data.item) }) + ...(data.item && { item: new Item(data.item) }), + ...(data.items && { items: data.items.map(item => new Item(item)) }) }) } } @@ -412,12 +413,12 @@ describe('Models - Relationships', function() { }) it(`handles arrays of related data`, function() { - const { Todo, store } = this + const { Todo, Item } = this const todo1 = new Todo({ id: 'todo-1', description: 'todo description', - item: [ + items: [ { id: 'item-1', test: true @@ -431,7 +432,7 @@ describe('Models - Relationships', function() { const todo2 = new Todo({ id: 'todo-2', description: 'todo description', - item: [ + items: [ { id: 'item-3', test: true @@ -446,12 +447,12 @@ describe('Models - Relationships', function() { assert(todo1, 'todo1 is an instance') assert(todo2, 'todo2 is an instance') - const storedTodo1 = store.state.todos.keyedById['todo-1'] - const storedTodo2 = store.state.todos.keyedById['todo-2'] - const storedItem1 = store.state.items.keyedById['item-1'] - const storedItem2 = store.state.items.keyedById['item-2'] - const storedItem3 = store.state.items.keyedById['item-3'] - const storedItem4 = store.state.items.keyedById['item-4'] + const storedTodo1 = Todo.getFromStore('todo-1') + const storedTodo2 = Todo.getFromStore('todo-2') + const storedItem1 = Item.getFromStore('item-1') + const storedItem2 = Item.getFromStore('item-2') + const storedItem3 = Item.getFromStore('item-3') + const storedItem4 = Item.getFromStore('item-4') assert(storedTodo1, 'should have todo 1') assert(storedTodo2, 'should have todo 2') From 206da36f240582eaa857d219e33ab49171c45b16 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 11:10:02 -0600 Subject: [PATCH 122/404] Fix a few more tests. Add autoremove to options interface --- src/service-module/types.ts | 1 + test/service-module/model-relationships.test.ts | 3 +++ test/service-module/service-module.test.ts | 13 +++++++------ 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/service-module/types.ts b/src/service-module/types.ts index d916ed58..0dc3b6ac 100644 --- a/src/service-module/types.ts +++ b/src/service-module/types.ts @@ -31,6 +31,7 @@ export interface MakeServicePluginOptions { nameStyle?: string namespace?: string preferUpdate?: boolean + autoRemove?: boolean servicePath?: string instanceDefaults?: () => {} setupInstance?: (data, { models, store }) => {} diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index 38f7e624..1207a74c 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -461,4 +461,7 @@ describe('Models - Relationships', function() { assert(storedItem3, 'should have item 3') assert(storedItem4, 'should have item 4') }) + + it.skip('preserves relationships on clone', function() {}) + it.skip('preserves relationships on commit', function() {}) }) diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 80ebfbbf..9ec448b8 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -348,7 +348,7 @@ describe('Service Module', function() { describe('Setting Up', () => { it('service stores have global defaults', function() { - const { makeServicePlugin, BaseModel, Task } = this + const { makeServicePlugin, BaseModel, Task } = makeContext() class Todo extends BaseModel { public static test: boolean = true } @@ -372,7 +372,7 @@ describe('Service Module', function() { }) it('can customize the idField for each service', function() { - const { makeServicePlugin, Test } = this + const { makeServicePlugin, Test } = makeContext() const idField = '_id' const store = new Vuex.Store({ plugins: [ @@ -391,13 +391,14 @@ describe('Service Module', function() { }) it('allows enabling autoRemove', function() { - const { makeServicePlugin, Test } = this + const { makeServicePlugin, Test } = makeContext() const autoRemove = true const store = new Vuex.Store({ plugins: [ makeServicePlugin({ Model: Test, - service: feathersClient.service('tests') + service: feathersClient.service('tests'), + autoRemove }) ] }) @@ -427,7 +428,7 @@ describe('Service Module', function() { }) it('can explicitly provide a namespace', function() { - const { makeServicePlugin, Test } = this + const { makeServicePlugin, Test } = makeContext() const namespace = 'blah' const store = new Vuex.Store({ plugins: [ @@ -442,7 +443,7 @@ describe('Service Module', function() { }) it('prioritizes the explicit namespace', function() { - const { makeServicePlugin, Test } = this + const { makeServicePlugin, Test } = makeContext() const namespace = 'blah' const nameStyle = 'path' const store = new Vuex.Store({ From a68f615dec1ef9ab33f052e55626ed21c781d193 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 12:05:04 -0600 Subject: [PATCH 123/404] Fix default state and test for the same --- src/service-module/make-service-module.ts | 21 +------- src/service-module/service-module.state.ts | 46 ++++++++--------- test/service-module/service-module.test.ts | 58 ++++++++++++++-------- 3 files changed, 60 insertions(+), 65 deletions(-) diff --git a/src/service-module/make-service-module.ts b/src/service-module/make-service-module.ts index 1b14ef13..b6d17ced 100644 --- a/src/service-module/make-service-module.ts +++ b/src/service-module/make-service-module.ts @@ -3,37 +3,20 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import { omit as _omit, pick as _pick } from 'lodash' - import makeDefaultState from './service-module.state' import makeGetters from './service-module.getters' import makeMutations from './service-module.mutations' import makeActions from './service-module.actions' export default function makeServiceModule(service, options) { - const nonStateProps = [ - 'Model', - 'service', - 'state', - 'getters', - 'mutations', - 'actions' - ] - const stateOptions = _omit(options, nonStateProps) - const nonStateOptions = _pick(options, nonStateProps) - - const defaultState = makeDefaultState(stateOptions.servicePath, stateOptions) + const defaultState = makeDefaultState(options.servicePath, options) const defaultGetters = makeGetters() const defaultMutations = makeMutations() const defaultActions = makeActions(service) - Object.assign(stateOptions, { - modelName: options.Model.name - }) - return { namespaced: true, - state: Object.assign(stateOptions, defaultState, nonStateOptions.state), + state: Object.assign(defaultState, options.state), getters: Object.assign({}, defaultGetters, options.getters), mutations: Object.assign({}, defaultMutations, options.mutations), actions: Object.assign({}, defaultActions, options.actions) diff --git a/src/service-module/service-module.state.ts b/src/service-module/service-module.state.ts index bd84bfb4..3b1f1305 100644 --- a/src/service-module/service-module.state.ts +++ b/src/service-module/service-module.state.ts @@ -3,40 +3,32 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ + +import { omit as _omit, pick as _pick } from 'lodash' + export default function makeDefaultState(servicePath, options) { - const { - idField, - autoRemove, - enableEvents, - addOnUpsert, - diffOnPatch, - serverAlias, - skipRequestIfExists, - preferUpdate, - replaceItems, - paramsForServer, - whitelist - } = options + const nonStateProps = [ + 'actions', + 'getters', + 'instanceDefaults', + 'Model', + 'mutations', + 'serialize', + 'service', + 'setupInstance', + 'state', + 'actions' + ] const state = { ids: [], keyedById: {}, copiesById: {}, tempsById: {}, - idField, - servicePath, - autoRemove, - enableEvents, - addOnUpsert, - diffOnPatch, - skipRequestIfExists, - preferUpdate, - replaceItems, - serverAlias, - paramsForServer, - whitelist, pagination: {}, + modelName: options.Model.name, + isFindPending: false, isGetPending: false, isCreatePending: false, @@ -52,5 +44,7 @@ export default function makeDefaultState(servicePath, options) { errorOnRemove: null } - return state + const startingState = _omit(options, nonStateProps) + + return Object.assign({}, state, startingState) } diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 9ec448b8..3a386e4d 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -95,6 +95,25 @@ function makeContext() { } } +function makeContextWithState() { + const feathers = makeFeathersRestClient() + const service = feathers.use('service-todos', memory({ store: makeTodos() })) + const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { + serverAlias: 'basics' + }) + class ServiceTodo extends BaseModel { + public static test: boolean = true + } + + return { + feathers, + service, + makeServicePlugin, + BaseModel, + ServiceTodo + } +} + describe('Service Module', function() { beforeEach(() => { clearModels() @@ -461,33 +480,28 @@ describe('Service Module', function() { }) describe('Basics', () => { - beforeEach(function() { - this.feathers = makeFeathersRestClient() - this.feathers.use('service-todos', memory({ store: makeTodos() })) - this.fv = feathersVuex(this.feathers, { - serverAlias: 'basics' - }) - class ServiceTodo extends this.fv.BaseModel { - public static test: boolean = true - } - this.ServiceTodo = ServiceTodo - }) - it('populates default store', function() { + const { + makeServicePlugin, + feathers, + ServiceTodo + } = makeContextWithState() const store = new Vuex.Store({ plugins: [ - this.fv.makeServicePlugin({ - Model: this.ServiceTodo, - service: this.feathers.service('service-todos') + makeServicePlugin({ + servicePath: 'service-todos', + Model: ServiceTodo, + service: feathers.service('service-todos') }) ] }) const todoState = store.state['service-todos'] const expectedState = { + addOnUpsert: false, autoRemove: false, copiesById: {}, - copy: null, - currentId: null, + debug: false, + diffOnPatch: true, enableEvents: true, errorOnCreate: null, errorOnGet: null, @@ -503,14 +517,18 @@ describe('Service Module', function() { isUpdatePending: false, isPatchPending: false, isRemovePending: false, + keepCopiesInStore: false, keyedById: {}, - modelName: 'Todo', - addOnUpsert: false, - diffOnPatch: false, + nameStyle: 'short', + namespace: 'service-todos', + modelName: 'ServiceTodo', + serverAlias: 'basics', skipRequestIfExists: false, preferUpdate: false, replaceItems: false, servicePath: 'service-todos', + tempIdField: '__id', + tempsById: {}, pagination: {}, paramsForServer: [], whitelist: [] From 8e8c8bb2510b5947c37e1002a17621ce2c23f1bf Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 12:08:12 -0600 Subject: [PATCH 124/404] Fix test for default state --- test/service-module/make-service-plugin.test.ts | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index a8015bc4..f21dae39 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -56,7 +56,6 @@ describe('makeServicePlugin', function() { idField: 'id', tempIdField: '__id', ids: [], - instanceDefaults: () => ({}), isCreatePending: false, isFindPending: false, isGetPending: false, @@ -75,24 +74,11 @@ describe('makeServicePlugin', function() { serverAlias: 'default', servicePath: 'todos', skipRequestIfExists: false, - setupInstance: item => item, - serialize: item => item, tempsById: {}, whitelist: [] } - assert.deepEqual( - _omit(received, ['instanceDefaults', 'serialize', 'setupInstance']), - // @ts-ignore - _omit(expected, ['instanceDefaults', 'serialize', 'setupInstance']), - 'The module was registered.' - ) - // @ts-ignore - assert.equal(typeof received.serialize, 'function') - // @ts-ignore - assert.equal(typeof received.setupInstance, 'function') - // @ts-ignore - assert.equal(typeof received.instanceDefaults, 'function') + assert.deepEqual(_omit(received), _omit(expected), 'defaults in place.') }) it('sets up Model.store && service.FeathersVuexModel', function() { From d058a7f49fcd54c51679358ebe713d342ee082d8 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 12:08:22 -0600 Subject: [PATCH 125/404] Remove unused import --- src/service-module/service-module.state.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/service-module.state.ts b/src/service-module/service-module.state.ts index 3b1f1305..673fb215 100644 --- a/src/service-module/service-module.state.ts +++ b/src/service-module/service-module.state.ts @@ -4,7 +4,7 @@ eslint @typescript-eslint/no-explicit-any: 0 */ -import { omit as _omit, pick as _pick } from 'lodash' +import { omit as _omit } from 'lodash' export default function makeDefaultState(servicePath, options) { const nonStateProps = [ From 18e87e5efce4778d83d5b6278160e690e06558d5 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 12:21:04 -0600 Subject: [PATCH 126/404] Fix getter tests --- src/service-module/service-module.state.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/service-module/service-module.state.ts b/src/service-module/service-module.state.ts index 673fb215..e1eb40ae 100644 --- a/src/service-module/service-module.state.ts +++ b/src/service-module/service-module.state.ts @@ -27,8 +27,6 @@ export default function makeDefaultState(servicePath, options) { tempsById: {}, pagination: {}, - modelName: options.Model.name, - isFindPending: false, isGetPending: false, isCreatePending: false, @@ -44,6 +42,11 @@ export default function makeDefaultState(servicePath, options) { errorOnRemove: null } + if (options.Model) { + // @ts-ignore + state.modelName = options.Model.name + } + const startingState = _omit(options, nonStateProps) return Object.assign({}, state, startingState) From 882d28d077e7357c1bd26b3b9f9e98b121b40f28 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 13:20:53 -0600 Subject: [PATCH 127/404] Allow getting servicePath from Model --- src/service-module/make-service-plugin.ts | 4 ++-- src/utils.ts | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index b70f1473..40fa00d1 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -51,14 +51,14 @@ export default function prepareMakeServicePlugin( if (!service) { throw new Error( - 'No service was provided. If you passed one in, check that you have configured a transport plugin on the Feathers Client. Make sure you use the client version of the transport`.' + 'No service was provided. If you passed one in, check that you have configured a transport plugin on the Feathers Client. Make sure you use the client version of the transport.' ) } // Make sure we get a service path from either the service or the options let { servicePath } = options if (!servicePath) { - servicePath = getServicePath(service, Model.name) + servicePath = getServicePath(service, Model) } options.servicePath = servicePath diff --git a/src/utils.ts b/src/utils.ts index d2e5b637..45107dc8 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -273,13 +273,18 @@ export function makeNamespace(namespace, servicePath, nameStyle) { * @param service * @param modelName */ -export function getServicePath(service: any, modelName: string) { - if (!service.name) { +export function getServicePath(service: any, Model: 'any') { + // @ts-ignore + if (!service.name && !service.path && !Model.servicePath) { throw new Error( - `Service for model named ${modelName} is missing a path or name property. The feathers adapter needs to be updated with a PR to expose this property. You can work around this by passing a 'servicePath' attribute in the options: makeServicePlugin({servicePath: '/path/to/my/service'})` + `Service for model named ${ + // @ts-ignore + Model.name + } is missing a path or name property. The feathers adapter needs to be updated with a PR to expose this property. You can work around this by adding a static servicePath = passing a 'servicePath' attribute in the options: makeServicePlugin({servicePath: '/path/to/my/service'})` ) } - return service.path || service.name + // @ts-ignore + return service.path || service.name || Model.servicePath } export function randomString(length) { From c871e3f40fb6e8b6dd22c8c08b258790e40b074c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 13:21:08 -0600 Subject: [PATCH 128/404] Remove extra character from error --- test/service-module/misconfigured-client.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/service-module/misconfigured-client.test.ts b/test/service-module/misconfigured-client.test.ts index 2a1b1d87..4a12bc03 100644 --- a/test/service-module/misconfigured-client.test.ts +++ b/test/service-module/misconfigured-client.test.ts @@ -22,7 +22,7 @@ describe('Service Module - Bad Client Setup', () => { } catch (error) { assert( error.message.includes( - 'No service was provided. If you passed one in, check that you have configured a transport plugin on the Feathers Client. Make sure you use the client version of the transport`.' + 'No service was provided. If you passed one in, check that you have configured a transport plugin on the Feathers Client. Make sure you use the client version of the transport.' ), 'got an error with a misconfigured client' ) From 368e756a09e982c5acf60c50fb46920f104ea67c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 13:21:16 -0600 Subject: [PATCH 129/404] Fix autoRemove test --- test/service-module/service-module.test.ts | 116 +++++++++++---------- 1 file changed, 63 insertions(+), 53 deletions(-) diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 3a386e4d..04f4964d 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -114,6 +114,48 @@ function makeContextWithState() { } } +function makeAutoRemoveContext() { + const feathers = makeFeathersRestClient() + .use( + 'todos', + memory({ + store: makeTodos() + }) + ) + .use( + 'tasks', + memory({ + store: makeTodos(), + paginate: { + default: 10, + max: 50 + } + }) + ) + const todosService = feathers.service('todos') + const tasksService = feathers.service('tasks') + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'autoRemove' + }) + class Todo extends BaseModel { + public static servicePath: string = 'todos' + public static test: boolean = true + } + class Task extends BaseModel { + public static servicePath: string = 'tasks' + public static test: boolean = true + } + return { + feathers, + todosService, + tasksService, + makeServicePlugin, + BaseModel, + Todo, + Task + } +} + describe('Service Module', function() { beforeEach(() => { clearModels() @@ -541,78 +583,45 @@ describe('Service Module', function() { ) }) - it('throws an error if first arg is not a string', function() { - const { service } = this + it('throws an error if no service is provided', function() { + const { makeServicePlugin } = makeContext() try { new Vuex.Store({ - // eslint-disable-line no-new - plugins: [service({})] + // @ts-ignore + plugins: [makeServicePlugin({})] }) } catch (error) { - assert( - error.message === - 'The first argument to setup a feathers-vuex service must be a string', + assert.equal( + error.message, + 'No service was provided. If you passed one in, check that you have configured a transport plugin on the Feathers Client. Make sure you use the client version of the transport.', 'threw an error' ) } }) - it(`populates items on find`, function(done) { - const store = new Vuex.Store({ - plugins: [this.service('service-todos', { idField: '_id' })] - }) - - const todoState = store.state.todos - - assert(todoState.ids.length === 0) - - store - .dispatch('todos/find', { query: {} }) - .then(todos => { - assert(todoState.ids.length === 3) - done() - }) - .catch(error => { - assert(!error, error.message) - done() - }) - }) - - describe('Auto-remove items', function() { + describe('Auto-Remove Items', function() { beforeEach(function() { - this.feathersClient = makeFeathersRestClient() - this.feathersClient.use( - 'service-todos', - memory({ - store: makeTodos() - }) - ) - this.feathersClient.use( - 'tasks', - memory({ - store: makeTodos(), - paginate: { - default: 10, - max: 50 - } - }) - ) - this.fv = feathersVuex(this.feathersClient, { - serverAlias: 'auto-remove' - }) + clearModels() }) - it(`removes missing items when pagination is off`, function(done) { + it.only(`removes missing items when pagination is off`, function(done) { + const { + makeServicePlugin, + Todo, + todosService + } = makeAutoRemoveContext() const store = new Vuex.Store({ plugins: [ - this.service('service-todos', { + makeServicePlugin({ + Model: Todo, + service: todosService, idField: '_id', autoRemove: true }) ] }) - const todoState = store.state['service-todos'] + const todoState = store.state['todos'] assert(todoState.ids.length === 0) @@ -621,7 +630,8 @@ describe('Service Module', function() { .dispatch('todos/find', { query: {} }) .then(todos => { // Remove the third item from the service - delete this.feathersClient.service('service-todos').store[3] + // @ts-ignore + delete todosService.store[3] // We went around using the store actions, so there will still be three items. assert( todoState.ids.length === 3, From b6c6503101d0892636b1e00973bc564c579b9de8 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 13:23:56 -0600 Subject: [PATCH 130/404] Fix second autoRemove test --- test/service-module/service-module.test.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 04f4964d..a4c20f37 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -604,7 +604,7 @@ describe('Service Module', function() { clearModels() }) - it.only(`removes missing items when pagination is off`, function(done) { + it(`removes missing items when pagination is off`, function(done) { const { makeServicePlugin, Todo, @@ -655,8 +655,20 @@ describe('Service Module', function() { }) it(`does not remove missing items when pagination is on`, function(done) { + const { + makeServicePlugin, + Task, + tasksService + } = makeAutoRemoveContext() const store = new Vuex.Store({ - plugins: [this.service('tasks', { idField: '_id', autoRemove: true })] + plugins: [ + makeServicePlugin({ + Model: Task, + service: tasksService, + idField: '_id', + autoRemove: true + }) + ] }) const taskState = store.state.tasks @@ -668,7 +680,8 @@ describe('Service Module', function() { .dispatch('tasks/find', { query: {} }) .then(todos => { // Remove the third item from the service - delete this.feathersClient.service('tasks').store[3] + // @ts-ignore + delete tasksService.store[3] // We went around using the store actions, so there will still be three items. assert( taskState.ids.length === 3, From 803d0c683d6f0810d2692ebce7f7335b2c977e90 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 13:26:30 -0600 Subject: [PATCH 131/404] Fix third autoRemove test --- test/service-module/service-module.test.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index a4c20f37..1ce7b822 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -706,14 +706,21 @@ describe('Service Module', function() { }) it(`does not remove missing items when autoRemove is off`, function(done) { + const { + makeServicePlugin, + Todo, + todosService + } = makeAutoRemoveContext() const store = new Vuex.Store({ plugins: [ - this.service('service-todos', { - idField: '_id', - autoRemove: false + makeServicePlugin({ + Model: Todo, + service: todosService, + idField: '_id' }) ] }) + const todoState = store.state.todos assert(todoState.ids.length === 0) @@ -723,7 +730,8 @@ describe('Service Module', function() { .dispatch('todos/find', { query: {} }) .then(todos => { // Remove the third item from the service - delete this.feathersClient.service('service-todos').store[3] + // @ts-ignore + delete todosService.store[3] // We went around using the store actions, so there will still be three items. assert( todoState.ids.length === 3, From d779b8cb960da6c3537c9cf30eef7418b7a3d28f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 13:34:29 -0600 Subject: [PATCH 132/404] Fix customizing service store tests --- test/service-module/service-module.test.ts | 28 +++++++++++++--------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 1ce7b822..48e7bc82 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -758,7 +758,7 @@ describe('Service Module', function() { describe('Customizing Service Stores', function() { it('allows adding custom state', function() { - const { makeServicePlugin, ServiceTodo } = this + const { makeServicePlugin, ServiceTodo } = makeContext() const customState = { test: true, @@ -776,12 +776,15 @@ describe('Service Module', function() { ] }) - assert(store.state.todos.test === true, 'added custom state') - assert(store.state.todos.test2.test === true, 'added custom state') + assert(store.state['service-todos'].test === true, 'added custom state') + assert( + store.state['service-todos'].test2.test === true, + 'added custom state' + ) }) it('allows custom mutations', function() { - const { makeServicePlugin, ServiceTodo } = this + const { makeServicePlugin, ServiceTodo } = makeContext() const state = { test: true } const customMutations = { setTestToFalse(state) { @@ -799,15 +802,15 @@ describe('Service Module', function() { ] }) - store.commit('todos/setTestToFalse') + store.commit('service-todos/setTestToFalse') assert( - store.state.todos.test === false, + store.state['service-todos'].test === false, 'the custom state was modified by the custom mutation' ) }) it('allows custom getters', function() { - const { makeServicePlugin, ServiceTodo } = this + const { makeServicePlugin, ServiceTodo } = makeContext() const customGetters = { oneTwoThree(state) { return 123 @@ -824,13 +827,13 @@ describe('Service Module', function() { }) assert( - store.getters['todos/oneTwoThree'] === 123, + store.getters['service-todos/oneTwoThree'] === 123, 'the custom getter was available' ) }) it('allows adding custom actions', function() { - const { makeServicePlugin, ServiceTodo } = this + const { makeServicePlugin, ServiceTodo } = makeContext() const config = { state: { isTrue: false @@ -856,8 +859,11 @@ describe('Service Module', function() { ] }) - store.dispatch('todos/trigger') - assert(store.state.todos.isTrue === true, 'the custom action was run') + store.dispatch('service-todos/trigger') + assert( + store.state['service-todos'].isTrue === true, + 'the custom action was run' + ) }) }) From 67231dddbfce31bffc121742526e0d717b9b797b Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 15:52:24 -0600 Subject: [PATCH 133/404] simplify toJSON --- src/service-module/make-model.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index dab6ff21..b455461e 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -343,9 +343,8 @@ export default function makeModel(options: FeathersVuexOptions) { } public toJSON() { - const { serialize } = Object.getPrototypeOf(this).constructor - const obj = serialize(this) - const data = _merge({}, obj) + const { serialize } = this.constructor as typeof BaseModel + const data = _merge({}, serialize(this)) return data } } From 83142db75bce1ad7ca4b99f52d176d5de0a08111 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 15:52:31 -0600 Subject: [PATCH 134/404] Add test for toJSON --- .../model-relationships.test.ts | 237 +++++++++++------- test/service-module/model-serialize.test.ts | 44 ++++ 2 files changed, 193 insertions(+), 88 deletions(-) create mode 100644 test/service-module/model-serialize.test.ts diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index 1207a74c..f187cbb3 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -132,97 +132,113 @@ describe('Models - `setupInstance` & Relatioships', function() { }) }) -describe('Models - Relationships', function() { - beforeEach(function() { - clearModels() - - const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { - serverAlias: 'myApi' - }) - class Task extends BaseModel { - public static instanceDefaults() { - return { - id: null, - description: '', - isComplete: false - } +function makeContext() { + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'myApi' + }) + class Task extends BaseModel { + public static instanceDefaults() { + return { + id: null, + description: '', + isComplete: false } } - class Todo extends BaseModel { - public static instanceDefaults(data) { - const priority = data.priority || 'normal' - const defaultsByPriority = { - normal: { - description: '', - isComplete: false, - task: 'Task', - item: 'Item', - priority: '' - }, - high: { - isHighPriority: true, - priority: '' - } + public constructor(data, options?) { + super(data, options) + } + } + class Todo extends BaseModel { + public static instanceDefaults(data) { + const priority = data.priority || 'normal' + const defaultsByPriority = { + normal: { + description: '', + isComplete: false, + task: 'Task', + item: 'Item', + priority: '' + }, + high: { + isHighPriority: true, + priority: '' } - return defaultsByPriority[priority] } - public static setupInstance(data, { models, store }) { - const { Task, Item } = models.myApi + return defaultsByPriority[priority] + } + public static setupInstance(data, { models, store }) { + const { Task, Item } = models.myApi - return Object.assign(data, { - ...(data.task && { task: new Task(data.task) }), - ...(data.item && { item: new Item(data.item) }), - ...(data.items && { items: data.items.map(item => new Item(item)) }) - }) - } + return Object.assign(data, { + ...(data.task && { task: new Task(data.task) }), + ...(data.item && { item: new Item(data.item) }), + ...(data.items && { items: data.items.map(item => new Item(item)) }) + }) } - class Item extends BaseModel { - public static instanceDefaults() { - return { - test: false, - todo: 'Todo' - } - } - public static setupInstance(data, { models, store }) { - const { Todo } = models.myApi - - return Object.assign(data, { - get todos() { - return Todo.findInStore({ query: {} }).data - }, - ...(data.todo && { todo: new Todo(data.todo) }) - }) + public constructor(data, options?) { + super(data, options) + } + } + class Item extends BaseModel { + public static instanceDefaults() { + return { + test: false, + todo: 'Todo' } } - this.store = new Vuex.Store({ - strict: true, - plugins: [ - makeServicePlugin({ - Model: Task, - service: feathersClient.service('tasks') - }), - makeServicePlugin({ - Model: Todo, - service: feathersClient.service('service-todos') - }), - makeServicePlugin({ - Model: Item, - service: feathersClient.service('items'), - mutations: { - toggleTestBoolean(state, item) { - item.test = !item.test - } + public static setupInstance(data, { models, store }) { + const { Todo } = models.myApi + + return Object.assign(data, { + get todos() { + return Todo.findInStore({ query: {} }).data + }, + ...(data.todo && { todo: new Todo(data.todo) }) + }) + } + public constructor(data, options?) { + super(data, options) + } + } + const store = new Vuex.Store({ + strict: true, + plugins: [ + makeServicePlugin({ + Model: Task, + service: feathersClient.service('tasks') + }), + makeServicePlugin({ + Model: Todo, + service: feathersClient.service('service-todos') + }), + makeServicePlugin({ + Model: Item, + service: feathersClient.service('items'), + mutations: { + toggleTestBoolean(state, item) { + item.test = !item.test } - }) - ] - }) - this.Todo = Todo - this.Task = Task - this.Item = Item + } + }) + ] + }) + return { + makeServicePlugin, + BaseModel, + store, + Todo, + Task, + Item + } +} + +describe('Models - Relationships', function() { + beforeEach(function() { + clearModels() }) it('can have different instanceDefaults based on new instance data', function() { - const { Todo } = this + const { Todo } = makeContext() const normalTodo = new Todo({ description: 'Normal' }) @@ -242,7 +258,7 @@ describe('Models - Relationships', function() { }) it('adds model instances containing an id to the store', function() { - const { Todo, Task } = this + const { Todo, Task } = makeContext() const todo = new Todo({ task: { @@ -260,7 +276,7 @@ describe('Models - Relationships', function() { }) it('works with multiple keys that match Model names', function() { - const { Todo, Task, Item } = this + const { Todo, Task, Item } = makeContext() const todo = new Todo({ task: { @@ -287,7 +303,7 @@ describe('Models - Relationships', function() { }) it('handles nested relationships', function() { - const { Todo } = this + const { Todo } = makeContext() const todo = new Todo({ task: { @@ -311,7 +327,7 @@ describe('Models - Relationships', function() { }) it('handles circular nested relationships', function() { - const { Todo, Item } = this + const { Todo, Item } = makeContext() const todo = new Todo({ id: 1, @@ -337,7 +353,7 @@ describe('Models - Relationships', function() { }) it('updates related data', function() { - const { Todo, Item, store } = this + const { Todo, Item, store } = makeContext() const module = new Todo({ id: 'todo-1', @@ -372,7 +388,7 @@ describe('Models - Relationships', function() { }) it(`allows creating more than once relational instance`, function() { - const { Todo, Item } = this + const { Todo, Item } = makeContext() const todo1 = new Todo({ id: 'todo-1', @@ -413,7 +429,7 @@ describe('Models - Relationships', function() { }) it(`handles arrays of related data`, function() { - const { Todo, Item } = this + const { Todo, Item } = makeContext() const todo1 = new Todo({ id: 'todo-1', @@ -462,6 +478,51 @@ describe('Models - Relationships', function() { assert(storedItem4, 'should have item 4') }) - it.skip('preserves relationships on clone', function() {}) - it.skip('preserves relationships on commit', function() {}) + it('preserves relationships on clone', function() { + const { Todo, Task } = makeContext() + + const todo = new Todo({ + task: { + id: 1, + description: 'test', + isComplete: true + } + }) + const clone = todo.clone() + + assert(clone.task instanceof Task, 'nested task is a Task') + }) + it('preserves relationships on commit', function() { + const { Todo, Task } = makeContext() + + const todo = new Todo({ + task: { + id: 1, + description: 'test', + isComplete: true + } + }) + const clone = todo.clone() + const original = clone.commit() + + assert(original.task instanceof Task, 'nested task is a Task') + }) + + it('preserves relationship with nested data clone and commit', function() { + const { Todo } = makeContext() + + const todo = new Todo({ + task: { + id: 1, + description: 'test', + isComplete: true + } + }) + // Create a clone of the nested task, modify and commit. + const taskClone = todo.task.clone() + taskClone.isComplete = false + taskClone.commit() + + assert.equal(todo.task.isComplete, false, 'preserved after clone') + }) }) diff --git a/test/service-module/model-serialize.test.ts b/test/service-module/model-serialize.test.ts new file mode 100644 index 00000000..d7fe91bb --- /dev/null +++ b/test/service-module/model-serialize.test.ts @@ -0,0 +1,44 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { assert } from 'chai' +import feathersVuex from '../../src/index' +import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' +import { clearModels } from '../../src/service-module/global-models' +import { omit as _omit } from 'lodash' + +describe('Models - Serialize', function() { + beforeEach(() => { + clearModels() + }) + + it('allows customizing toJSON', function() { + const { BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'myApi' + }) + class Task extends BaseModel { + public static instanceDefaults() { + return { + id: null, + description: '', + isComplete: false + } + } + public toJSON() { + return _omit(this, ['isComplete']) + } + public constructor(data, options?) { + super(data, options) + } + } + + const task = new Task({ + description: 'Hello, World!', + isComplete: true + }) + + assert(!task.toJSON().hasOwnProperty('isComplete'), 'custom toJSON worked') + }) +}) From a0cd76d42d00b2d33a91fa696dc6714143f84603 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 17:29:12 -0600 Subject: [PATCH 135/404] Remove temp records after successful save --- src/service-module/service-module.actions.ts | 10 ++- .../service-module.mutations.ts | 7 +- test/service-module/model-temp-ids.test.ts | 76 +++++++++++++++++++ .../service-module.actions.test.ts | 24 ++---- test/test-utils.ts | 15 ++++ 5 files changed, 111 insertions(+), 21 deletions(-) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 21b377bd..1d9627f2 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -110,9 +110,10 @@ export default function makeServiceActions(service) { }, create({ commit, dispatch, state }, dataOrArray) { - const { idField } = state + const { idField, tempIdField } = state let data let params + let tempIds if (Array.isArray(dataOrArray)) { data = dataOrArray[0] @@ -121,6 +122,12 @@ export default function makeServiceActions(service) { data = dataOrArray } + if (Array.isArray(data)) { + tempIds = data.map(i => i[tempIdField]) + } else { + tempIds = [data[tempIdField]] // Array of tempIds + } + params = params || {} commit('setPending', 'create') @@ -143,6 +150,7 @@ export default function makeServiceActions(service) { response = state.keyedById[id] } commit('unsetPending', 'create') + commit('removeTemps', tempIds) return response }) .catch(error => { diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index a5ac6a04..8df5aedf 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -7,7 +7,7 @@ import Vue from 'vue' import serializeError from 'serialize-error' import { updateOriginal, mergeWithAccessors, assignTempId } from '../utils' import { globalModels as models } from './global-models' -import { get as _get, isObject as _isObject } from 'lodash' +import { get as _get, isObject as _isObject, omit as _omit } from 'lodash' export default function makeServiceMutations() { function addItems(state, items) { @@ -104,6 +104,11 @@ export default function makeServiceMutations() { } }, + // Removes temp records + removeTemps(state, tempIds) { + state.tempsById = _omit(state.tempsById, tempIds) + }, + removeItems(state, items) { const { idField } = state diff --git a/test/service-module/model-temp-ids.test.ts b/test/service-module/model-temp-ids.test.ts index 37a80c5d..bc8f1058 100644 --- a/test/service-module/model-temp-ids.test.ts +++ b/test/service-module/model-temp-ids.test.ts @@ -8,12 +8,61 @@ import { assert } from 'chai' import feathersVuex from '../../src/index' import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' import { clearModels } from '../../src/service-module/global-models' +import memory from 'feathers-memory' import Vuex from 'vuex' +import { makeStore } from '../test-utils' interface RootState { transactions: ServiceState } +class ComicService extends memory.Service { + public create(data, params, callback) { + return super.create(data, params, callback).then(response => { + delete response.__id + delete response.__isTemp + return response + }) + } + public update(id, data, params, callback) { + data.createdAt = new Date() + // this._super(data, params, callback) + } +} + +function makeContext() { + feathersClient.use( + 'comics', + // @ts-ignore + new ComicService({ store: makeStore() }) + ) + const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'default' + }) + class Comic extends BaseModel { + public static test: boolean = true + + public constructor(data, options?) { + super(data, options) + } + } + const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Comic, + service: feathersClient.service('comics'), + servicePath: 'comics' + }) + ] + }) + return { + makeServicePlugin, + BaseModel, + Comic, + store + } +} + describe('Models - Temp Ids', function() { beforeEach(() => { clearModels() @@ -175,4 +224,31 @@ describe('Models - Temp Ids', function() { assert.equal(clone.amount, 1.99, 'clone was reset') }) + + it('returns the keyedById record after create, not the tempsById record', function(done) { + const { Comic, store } = makeContext() + + const comic = new Comic({ + name: 'The Uncanny X-Men', + year: 1969 + }) + + // Create a temp and make sure it's in the tempsById + const tempId = comic.__id + // @ts-ignore + assert(store.state.comics.tempsById[tempId]) + + comic + .save() + .then(response => { + // The comic record is no longer in tempsById + // @ts-ignore + assert(!store.state.comics.tempsById[tempId], 'temp is gone') + // The comic record moved to keyedById + // @ts-ignore + assert(store.state.comics.keyedById[response.id], 'now a real record') + done() + }) + .catch(done) + }) }) diff --git a/test/service-module/service-module.actions.test.ts b/test/service-module/service-module.actions.test.ts index 99a5f5d0..dd8082c2 100644 --- a/test/service-module/service-module.actions.test.ts +++ b/test/service-module/service-module.actions.test.ts @@ -10,6 +10,7 @@ import { feathersRestClient as feathersClient } from '../fixtures/feathers-clien import Vuex, { mapActions } from 'vuex' import memory from 'feathers-memory' import { clearModels } from '../../src/service-module/global-models' +import { makeStore } from '../test-utils' interface RootState { 'my-todos': ServiceState @@ -21,32 +22,15 @@ interface NumberedList { 1?: {} } -const makeStore = () => { - return { - 0: { id: 0, description: 'Do the first' }, - 1: { id: 1, description: 'Do the second' }, - 2: { id: 2, description: 'Do the third' }, - 3: { id: 3, description: 'Do the fourth' }, - 4: { id: 4, description: 'Do the fifth' }, - 5: { id: 5, description: 'Do the sixth' }, - 6: { id: 6, description: 'Do the seventh' }, - 7: { id: 7, description: 'Do the eighth' }, - 8: { id: 8, description: 'Do the ninth' }, - 9: { id: 9, description: 'Do the tenth' } - } -} - function makeContext() { - const todoService = feathersClient.use( + feathersClient.use( 'my-todos', - // @ts-ignore memory({ store: makeStore() }) ) - const taskService = feathersClient.use( + feathersClient.use( 'my-tasks', - // @ts-ignore memory({ store: makeStore(), paginate: { @@ -55,6 +39,8 @@ function makeContext() { } }) ) + const todoService = feathersClient.service('my-todos') + const taskService = feathersClient.service('my-tasks') const noIdService = feathersClient.use( 'no-ids', // @ts-ignore diff --git a/test/test-utils.ts b/test/test-utils.ts index eb6022aa..fd06fff5 100644 --- a/test/test-utils.ts +++ b/test/test-utils.ts @@ -12,3 +12,18 @@ export function assertGetter(item, prop, value) { ) assert.equal(item[prop], value, 'returned value matches') } + +export const makeStore = () => { + return { + 0: { id: 0, description: 'Do the first' }, + 1: { id: 1, description: 'Do the second' }, + 2: { id: 2, description: 'Do the third' }, + 3: { id: 3, description: 'Do the fourth' }, + 4: { id: 4, description: 'Do the fifth' }, + 5: { id: 5, description: 'Do the sixth' }, + 6: { id: 6, description: 'Do the seventh' }, + 7: { id: 7, description: 'Do the eighth' }, + 8: { id: 8, description: 'Do the ninth' }, + 9: { id: 9, description: 'Do the tenth' } + } +} From 8535355463a6b639629c4182864602ac22dc1b48 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 17:30:46 -0600 Subject: [PATCH 136/404] lint cleanup --- test/auth.test.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/test/auth.test.js b/test/auth.test.js index 284b6c86..ed0c43be 100644 --- a/test/auth.test.js +++ b/test/auth.test.js @@ -17,12 +17,15 @@ describe('feathers-vuex:auth', () => { var app = {} var store = {} var plugin = feathersVuexAuth(store).bind(app) - assert.throws(plugin, 'You must first register the @feathersjs/authentication-client plugin') + assert.throws( + plugin, + 'You must first register the @feathersjs/authentication-client plugin' + ) }) it('returns the app, is chainable', () => { var app = { - authenticate () {} + authenticate() {} } var store = {} var returnValue = feathersVuexAuth(store).bind(app)() @@ -37,10 +40,10 @@ describe('feathers-vuex:auth', () => { assert(oldAuthenticate !== feathersClient.authenticate) }) - it('dispatches actions to the store.', (done) => { + it('dispatches actions to the store.', done => { const feathersClient = makeFeathersRestClient() const fakeStore = { - dispatch (action) { + dispatch(action) { switch (action.type) { case actionTypes.FEATHERS_AUTH_REQUEST: assert(action.payload.test || action.payload.accessToken) @@ -62,7 +65,8 @@ describe('feathers-vuex:auth', () => { feathersClient.configure(feathersVuexAuth(fakeStore)) try { - feathersClient.authenticate({ test: true }) + feathersClient + .authenticate({ test: true }) .then(response => { feathersClient.logout() return response @@ -70,11 +74,12 @@ describe('feathers-vuex:auth', () => { .catch(error => { assert(error.className === 'not-authenticated') }) - } catch (err) { - - } + } catch (err) {} try { - feathersClient.authenticate({ strategy: 'jwt', accessToken: 'q34twershtdyfhgmj' }) + feathersClient.authenticate({ + strategy: 'jwt', + accessToken: 'q34twershtdyfhgmj' + }) } catch (err) { console.log(err) } From 337f79c599819bcbae23bdffcff2fabcc6ff5b64 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 17:31:43 -0600 Subject: [PATCH 137/404] Lint cleanup --- test/fixtures/server.js | 34 +++++++++++++++++++--------------- test/fixtures/store.js | 4 ++-- test/fixtures/todos.js | 2 +- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/test/fixtures/server.js b/test/fixtures/server.js index 87956119..8b98247d 100644 --- a/test/fixtures/server.js +++ b/test/fixtures/server.js @@ -1,10 +1,10 @@ -const feathers = require('@feathersjs/feathers') -const rest = require('@feathersjs/express/rest') -const socketio = require('@feathersjs/socketio') -const bodyParser = require('body-parser') -const auth = require('@feathersjs/authentication') -const jwt = require('@feathersjs/authentication-jwt') -const memory = require('feathers-memory') +import feathers from '@feathersjs/feathers' +import rest from '@feathersjs/express/rest' +import socketio from '@feathersjs/socketio' +import bodyParser from 'body-parser' +import auth from '@feathersjs/authentication' +import jwt from '@feathersjs/authentication-jwt' +import memory from 'feathers-memory' const app = feathers() .use(bodyParser.json()) @@ -14,17 +14,21 @@ const app = feathers() .use('/users', memory()) .use('/todos', memory()) .use('/errors', memory()) - .configure(auth({ - secret: 'test', - service: '/users' - })) + .configure( + auth({ + secret: 'test', + service: '/users' + }) + ) .configure(jwt()) app.service('/errors').hooks({ before: { - all: [hook => { - throw new Error(`${hook.method} Denied!`) - }] + all: [ + hook => { + throw new Error(`${hook.method} Denied!`) + } + ] } }) @@ -38,7 +42,7 @@ process.on('unhandledRejection', (reason, p) => server.on('listening', () => { console.log(`Feathers application started on localhost:${port}`) - setTimeout(function () { + setTimeout(function() { server.close() }, 50000) }) diff --git a/test/fixtures/store.js b/test/fixtures/store.js index fb25a7c4..63095b96 100644 --- a/test/fixtures/store.js +++ b/test/fixtures/store.js @@ -3,13 +3,13 @@ import Vuex from 'vuex' Vue.use(Vuex) -export default function makeStore () { +export default function makeStore() { return new Vuex.Store({ state: { count: 0 }, mutations: { - increment (state) { + increment(state) { state.count++ } } diff --git a/test/fixtures/todos.js b/test/fixtures/todos.js index aa142997..f3d7f11f 100644 --- a/test/fixtures/todos.js +++ b/test/fixtures/todos.js @@ -1,4 +1,4 @@ -export function makeTodos () { +export function makeTodos() { return { 1: { _id: 1, description: 'Dishes', isComplete: true }, 2: { _id: 2, description: 'Laundry', isComplete: true }, From d9ff842b3165e1c503c8f3c73e9d95f02c3e2724 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 17:50:40 -0600 Subject: [PATCH 138/404] =?UTF-8?q?Compile=20to=20ES5=20and=20don=E2=80=99?= =?UTF-8?q?t=20compile=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 6 ++---- tsconfig.json | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 5ae4881a..a5fba20b 100644 --- a/package.json +++ b/package.json @@ -33,13 +33,11 @@ "release:minor": "npm version minor && npm publish", "release:major": "npm version major && npm publish", "changelog": "github_changelog_generator && git add CHANGELOG.md && git commit -am \"Updating changelog\"", - "compile": "shx rm -rf lib/ && babel -d lib/ src/", + "compile": "shx rm -rf lib/ && tsc", "watch": "shx rm -rf lib/ && babel --watch -d lib/ src/", "lint": "standard --fix", "coverage": "istanbul cover node_modules/mocha/bin/_mocha -- --opts mocha.opts", - "test": "npm run lint && npm run test-node && npm run testee", - "test-ts": "mocha --require ts-node/register test/**/*.test.ts]", - "test-node": "mocha --opts mocha.opts", + "test": "mocha --require ts-node/register test/**/*.test.ts", "testee": "testee test/index.html --browsers firefox", "start": "npm run compile && node example/app", "docs:dev": "vuepress dev docs", diff --git a/tsconfig.json b/tsconfig.json index addabcda..42c693ae 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,10 +5,10 @@ "esModuleInterop": true, "outDir": "dist", "moduleResolution": "node", - "target": "ES2017" + "target": "ES5" }, "include": [ - "src/**/*", "test/**/*" + "src/**/*" ], "exclude": [ "node_modules", From 14b3c1eb85093d08a0249b1e16530f6a82dc7d13 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 18:11:36 -0600 Subject: [PATCH 139/404] gitignore /dist --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5040cc64..a13bd8c6 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,4 @@ lib/ *.ntvs* *.njsproj *.sln +/dist From 128e1354b52998841d103545982753d085baeaf3 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 18:11:56 -0600 Subject: [PATCH 140/404] Update npm scripts for publishing --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a5fba20b..0b3998ea 100644 --- a/package.json +++ b/package.json @@ -29,11 +29,13 @@ "prepare": "npm run compile", "prepublish": "npm run compile", "publish": "git push origin --tags && git push origin", + "release:pre": "npm run compile && npm publish --tag pre", "release:patch": "npm version patch && npm publish", "release:minor": "npm version minor && npm publish", "release:major": "npm version major && npm publish", "changelog": "github_changelog_generator && git add CHANGELOG.md && git commit -am \"Updating changelog\"", - "compile": "shx rm -rf lib/ && tsc", + "compile": "shx rm -rf lib/ && tsc && npm run lint-dist", + "lint-dist": "prettier --write \"dist/**/*.js\"", "watch": "shx rm -rf lib/ && babel --watch -d lib/ src/", "lint": "standard --fix", "coverage": "istanbul cover node_modules/mocha/bin/_mocha -- --opts mocha.opts", @@ -44,7 +46,6 @@ "docs:build": "vuepress build docs" }, "prettier": { - "fix": true, "singleQuote": true, "semi": false, "trailingComma": "none", From 221457578bd8fe0eceb21f7d33c4cd6f8954167c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 18:12:03 -0600 Subject: [PATCH 141/404] v2.0.0-pre.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0b3998ea..4992d53d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "1.7.0", + "version": "2.0.0-pre.0", "homepage": "https://github.com/feathersjs/feathers-vuex", "main": "lib/", "keywords": [ From 098735cccb9d309bef3ed8cf516963cdcac9e410 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 19:18:48 -0600 Subject: [PATCH 142/404] Create second tsconfig for es5, esnext goes to dist --- tsconfig.es5.json | 18 ++++++++++++++++++ tsconfig.json | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tsconfig.es5.json diff --git a/tsconfig.es5.json b/tsconfig.es5.json new file mode 100644 index 00000000..21d5ac2a --- /dev/null +++ b/tsconfig.es5.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "allowJs": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "outDir": "dist", + "moduleResolution": "node", + "target": "ES5", + "sourceMap": true + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "**/*.test.js" + ] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 42c693ae..97505072 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,8 @@ "esModuleInterop": true, "outDir": "dist", "moduleResolution": "node", - "target": "ES5" + "target": "esnext", + "sourceMap": true }, "include": [ "src/**/*" From f829adff7bd47317642139bb1845b09d750676e7 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 19:20:30 -0600 Subject: [PATCH 143/404] Add module field to package.json --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 4992d53d..601943c8 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "version": "2.0.0-pre.0", "homepage": "https://github.com/feathersjs/feathers-vuex", "main": "lib/", + "module": "dist/", "keywords": [ "feathers", "feathers-plugin" From d41ce6701c6fce346110237d04a975b18b419f17 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 19:20:39 -0600 Subject: [PATCH 144/404] v2.0.0-pre.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 601943c8..88e690c4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.0", + "version": "2.0.0-pre.1", "homepage": "https://github.com/feathersjs/feathers-vuex", "main": "lib/", "module": "dist/", From 5c26615b2d006fd9e38c81e63b5167d3979ade89 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 20:33:00 -0600 Subject: [PATCH 145/404] compile to es6 --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 97505072..7ca4ccb5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,7 @@ "esModuleInterop": true, "outDir": "dist", "moduleResolution": "node", - "target": "esnext", + "target": "es6", "sourceMap": true }, "include": [ From e6cfa9355463729b296e180a7eabc1b149ae0522 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 20:33:04 -0600 Subject: [PATCH 146/404] v2.0.0-pre.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 88e690c4..3fd59d95 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.1", + "version": "2.0.0-pre.2", "homepage": "https://github.com/feathersjs/feathers-vuex", "main": "lib/", "module": "dist/", From f9b0e10e30951e17fc01d1bbbee2c4c57aa8235b Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 20:49:03 -0600 Subject: [PATCH 147/404] Compile to es5 to avoid transpileDependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes it so we don’t have to use `transpileDependencies` in the vue.config.js file. --- tsconfig.es5.json | 18 ------------------ tsconfig.json | 2 +- 2 files changed, 1 insertion(+), 19 deletions(-) delete mode 100644 tsconfig.es5.json diff --git a/tsconfig.es5.json b/tsconfig.es5.json deleted file mode 100644 index 21d5ac2a..00000000 --- a/tsconfig.es5.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "allowJs": true, - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "outDir": "dist", - "moduleResolution": "node", - "target": "ES5", - "sourceMap": true - }, - "include": [ - "src/**/*" - ], - "exclude": [ - "node_modules", - "**/*.test.js" - ] -} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 7ca4ccb5..cdb5db90 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,7 @@ "esModuleInterop": true, "outDir": "dist", "moduleResolution": "node", - "target": "es6", + "target": "es5", "sourceMap": true }, "include": [ From 64020e4b33dab92f6171928108b04bdc86adadeb Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 20:49:16 -0600 Subject: [PATCH 148/404] v2.0.0-pre.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3fd59d95..c6d616af 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.2", + "version": "2.0.0-pre.3", "homepage": "https://github.com/feathersjs/feathers-vuex", "main": "lib/", "module": "dist/", From 8380b0bb595622c3422c7d50ff5855694df440dd Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 20:51:48 -0600 Subject: [PATCH 149/404] =?UTF-8?q?Don=E2=80=99t=20double=20compile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c6d616af..1962451d 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "prepare": "npm run compile", "prepublish": "npm run compile", "publish": "git push origin --tags && git push origin", - "release:pre": "npm run compile && npm publish --tag pre", + "release:pre": "npm publish --tag pre", "release:patch": "npm version patch && npm publish", "release:minor": "npm version minor && npm publish", "release:major": "npm version major && npm publish", From be8edc123860575775b4b145e8568f7524755d2e Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 22:17:55 -0600 Subject: [PATCH 150/404] Use ts-config esnext in tests --- .vscode/launch.json | 3 +++ tsconfig.esnext.json | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 tsconfig.esnext.json diff --git a/.vscode/launch.json b/.vscode/launch.json index f5636140..61146d50 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -20,6 +20,9 @@ "--recursive", "${workspaceFolder}/test/**/*.ts" ], + "env": { + "TS_NODE_PROJECT": "tsconfig.esnext.json" + }, "internalConsoleOptions": "openOnSessionStart" }, { diff --git a/tsconfig.esnext.json b/tsconfig.esnext.json new file mode 100644 index 00000000..97505072 --- /dev/null +++ b/tsconfig.esnext.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "allowJs": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "outDir": "dist", + "moduleResolution": "node", + "target": "esnext", + "sourceMap": true + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "**/*.test.js" + ] +} \ No newline at end of file From 121661309c564ca0e27ae4e9c6a642380f20b513 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 22:18:57 -0600 Subject: [PATCH 151/404] Getters work with temp records --- src/service-module/make-model.ts | 21 ++++++++-- src/service-module/notes.md | 7 ++++ src/service-module/service-module.getters.ts | 15 ++++--- .../model-instance-defaults.test.ts | 2 +- test/service-module/module.getters.test.ts | 42 +++++++++++++++---- 5 files changed, 67 insertions(+), 20 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index b455461e..db684401 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -6,7 +6,7 @@ eslint import { FeathersVuexOptions } from './types' import { globalModels, prepareAddModel } from './global-models' import { mergeWithAccessors, separateAccessors, checkNamespace } from '../utils' -import { get as _get, merge as _merge } from 'lodash' +import { get as _get, merge as _merge, omit as _omit } from 'lodash' // A hack to prevent error with this.constructor.preferUpdate interface Function { @@ -52,7 +52,20 @@ export default function makeModel(options: FeathersVuexOptions) { public static setupInstance(data, { models, store }) { return data } - public static serialize + public static serialize(item, { models, store }) { + return _omit(item, [ + '_clone', + 'clone', + 'commit', + 'create', + 'patch', + 'remove', + 'reset', + 'save', + 'toJSON', + 'update' + ]) + } // Monkey patched onto the Model class in `makeServicePlugin()` public static store: Record @@ -343,8 +356,8 @@ export default function makeModel(options: FeathersVuexOptions) { } public toJSON() { - const { serialize } = this.constructor as typeof BaseModel - const data = _merge({}, serialize(this)) + const { serialize, store, models } = this.constructor as typeof BaseModel + const data = _merge({}, serialize(this, { store, models })) return data } } diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 2c5f27cd..726f9ee5 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -89,6 +89,13 @@ Feathers-Vuex 2.0 supports tracking temporary items and automatically assigns a Previously, when a record didn't have an `[idField]`, a console.error would ask if you had configured the `idField` option. Because of the new ability to handle temporary records, a message is only logged when assigning a temporary id to a record. The `checkId` utility function has been removed, since this was its main purpose. +## Getters Work with Temporary Records + +The `find` getter has been updated to include records from `state.tempsById`, by default. You can pass `temps: false` in the params to only search `state.keyedById`. + + + + ## Changes to service module state The options are no longer at the root level of the service module state. You'll find them all in the options key: diff --git a/src/service-module/service-module.getters.ts b/src/service-module/service-module.getters.ts index 922352dc..41446798 100644 --- a/src/service-module/service-module.getters.ts +++ b/src/service-module/service-module.getters.ts @@ -22,6 +22,10 @@ export default function makeServiceGetters() { }, find: state => params => { params = params || {} + + // Set params.temps to false to not include the tempsById records + params.temps = params.hasOwnProperty('temps') ? params.temps : true + const { paramsForServer, whitelist } = state const q = _omit(params.query || {}, paramsForServer) const customOperators = Object.keys(q).filter( @@ -33,6 +37,11 @@ export default function makeServiceGetters() { operators: additionalOperators.concat(whitelist) }) let values = _.values(state.keyedById) + + if (params.temps) { + values = values.concat(_.values(state.tempsById)) + } + values = sift(query, values) const total = values.length @@ -63,12 +72,6 @@ export default function makeServiceGetters() { get: ({ keyedById, idField }) => (id, params = {}) => { return keyedById[id] ? select(params, idField)(keyedById[id]) : undefined }, - current(state) { - return state.currentId ? state.keyedById[state.currentId] : null - }, - getCopy(state) { - return state.copy ? state.copy : null - }, getCopyById: state => id => { return state.copiesById[id] } diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts index 5094966f..dd280614 100644 --- a/test/service-module/model-instance-defaults.test.ts +++ b/test/service-module/model-instance-defaults.test.ts @@ -117,7 +117,7 @@ describe('Models - Default Values', function() { } const todo = new NakedTodo() - assert.deepEqual(todo, {}, 'default model is a temp') + assert.deepEqual(todo.toJSON(), {}, 'default model is an empty object') }) it('models have tempIds when there is a store', function() { diff --git a/test/service-module/module.getters.test.ts b/test/service-module/module.getters.test.ts index 1ac8e622..c4a62481 100644 --- a/test/service-module/module.getters.test.ts +++ b/test/service-module/module.getters.test.ts @@ -14,7 +14,7 @@ const options = { serverAlias: 'default' } -const { find, list } = makeServiceGetters() +const { find, list, get } = makeServiceGetters() const { addItems } = makeServiceMutations() describe('Service Module - Getters', function() { @@ -34,6 +34,10 @@ describe('Service Module - Getters', function() { otherField: true, test: false, movies: [{ actors: ['Tom Hanks', 'Tom Cruise', 'Tomcat'] }] + }, + { + name: 'Mariah', + status: 'temp' } ] addItems(state, this.items) @@ -59,6 +63,22 @@ describe('Service Module - Getters', function() { assert.deepEqual(results.data, items, 'the list was correct') assert(results.limit === 0, 'limit was correct') assert(results.skip === 0, 'skip was correct') + assert(results.total === 4, 'total was correct') + }) + + it('find without temps', function() { + const { state, items } = this + // Set temps: false to skip the temps. + const params = { query: {}, temps: false } + const results = find(state)(params) + + assert.deepEqual( + results.data, + items.filter(i => i._id), + 'the list was correct' + ) + assert(results.limit === 0, 'limit was correct') + assert(results.skip === 0, 'skip was correct') assert(results.total === 3, 'total was correct') }) @@ -155,7 +175,7 @@ describe('Service Module - Getters', function() { assert(results.data[0]._id === 1, 'the correct record was returned') assert(results.limit === 1, 'limit was correct') assert(results.skip === 0, 'skip was correct') - assert(results.total === 3, 'total was correct') + assert(results.total === 4, 'total was correct') }) it('find with skip', function() { @@ -163,12 +183,12 @@ describe('Service Module - Getters', function() { const params = { query: { $skip: 1 } } const results = find(state)(params) - assert(results.data.length === 2, 'the length was correct') + assert(results.data.length === 3, 'the length was correct') assert(results.data[0]._id === 2, 'the correct record was returned') assert(results.data[1]._id === 3, 'the correct record was returned') assert(results.limit === 0, 'limit was correct') assert(results.skip === 1, 'skip was correct') - assert(results.total === 3, 'total was correct') + assert(results.total === 4, 'total was correct') }) it('find with limit and skip', function() { @@ -180,7 +200,7 @@ describe('Service Module - Getters', function() { assert(results.data[0]._id === 2, 'the correct record was returned') assert(results.limit === 1, 'limit was correct') assert(results.skip === 1, 'skip was correct') - assert(results.total === 3, 'total was correct') + assert(results.total === 4, 'total was correct') }) it('find with select', function() { @@ -188,13 +208,17 @@ describe('Service Module - Getters', function() { const params = { query: { $select: ['otherField'] } } const results = find(state)(params) - assert(results.data.length === 3, 'the length was correct') + assert(results.data.length === 4, 'the length was correct') results.data.forEach(result => { - assert(Object.keys(result).length === 1, 'only one field was returned') - assert(result.otherField, 'the correct field was returned') + assert(Object.keys(result).length <= 1, 'only one field was returned') }) + assert.equal( + results.data.filter(i => i.otherField).length, + 3, + 'three records have the field.' + ) assert(results.limit === 0, 'limit was correct') assert(results.skip === 0, 'skip was correct') - assert(results.total === 3, 'total was correct') + assert(results.total === 4, 'total was correct') }) }) From b6d0a1483b2ee71515503c90a0022f575c45a4c8 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 22:44:56 -0600 Subject: [PATCH 152/404] The `get` getter now supports temp records --- src/service-module/service-module.getters.ts | 11 +++++++++-- test/service-module/module.getters.test.ts | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/service-module/service-module.getters.ts b/src/service-module/service-module.getters.ts index 41446798..f7af79ec 100644 --- a/src/service-module/service-module.getters.ts +++ b/src/service-module/service-module.getters.ts @@ -69,8 +69,15 @@ export default function makeServiceGetters() { data: values } }, - get: ({ keyedById, idField }) => (id, params = {}) => { - return keyedById[id] ? select(params, idField)(keyedById[id]) : undefined + get: state => (id, params = {}) => { + const { keyedById, tempsById, idField, tempIdField } = state + const record = keyedById[id] + ? select(params, idField)(keyedById[id]) + : undefined + const tempRecord = tempsById[id] + ? select(params, tempIdField)(tempsById[id]) + : undefined + return record || tempRecord }, getCopyById: state => id => { return state.copiesById[id] diff --git a/test/service-module/module.getters.test.ts b/test/service-module/module.getters.test.ts index c4a62481..1f85e0e7 100644 --- a/test/service-module/module.getters.test.ts +++ b/test/service-module/module.getters.test.ts @@ -10,6 +10,7 @@ import makeServiceState from '../../src/service-module/service-module.state' const options = { idField: '_id', + tempIdField: '__id', autoRemove: false, serverAlias: 'default' } @@ -55,6 +56,25 @@ describe('Service Module - Getters', function() { }) }) + it('get works on keyedById', function() { + const { state, items } = this + // @ts-ignore + const result = get(state)(1) + + // @ts-ignore + assert.deepEqual(result, items[0]) + }) + + it('get works on tempsById', function() { + const { state, items } = this + const tempId = Object.keys(state.tempsById)[0] + // @ts-ignore + const result = get(state)(tempId) + + // @ts-ignore + assert(result.__id === tempId) + }) + it('find', function() { const { state, items } = this const params = { query: {} } From ca07a27591a4c6a17604586e18b7109fef0cdb74 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 22:45:33 -0600 Subject: [PATCH 153/404] v2.0.0-pre.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1962451d..57b1031b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.3", + "version": "2.0.0-pre.4", "homepage": "https://github.com/feathersjs/feathers-vuex", "main": "lib/", "module": "dist/", From 7da19880a8aff1e9daecf18368ea94f0c2fe2481 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 22:47:37 -0600 Subject: [PATCH 154/404] Clean up docs --- src/service-module/notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 726f9ee5..5341149d 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -91,9 +91,9 @@ Previously, when a record didn't have an `[idField]`, a console.error would ask ## Getters Work with Temporary Records -The `find` getter has been updated to include records from `state.tempsById`, by default. You can pass `temps: false` in the params to only search `state.keyedById`. - +The `find` getter has been updated to include records from `state.tempsById`, by default. You can pass `temps: false` in the params to only search `state.keyedById`: `find({ query: {}, temps: false })` +The `get` getter has also been updated to work with temp ids. Pass the tempId the way you normally would pass the id: `get(tempId)` ## Changes to service module state From fbb4ba80ed4fb0a8f992500948f56224d990f1ce Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 22:47:58 -0600 Subject: [PATCH 155/404] Lint cleanup --- src/service-module/notes.md | 2 -- test/service-module/module.getters.test.ts | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 5341149d..d937cd43 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -95,7 +95,6 @@ The `find` getter has been updated to include records from `state.tempsById`, by The `get` getter has also been updated to work with temp ids. Pass the tempId the way you normally would pass the id: `get(tempId)` - ## Changes to service module state The options are no longer at the root level of the service module state. You'll find them all in the options key: @@ -309,7 +308,6 @@ The new `setupInstance` method allows a lot of flexibility in creating new insta While you could technically use `setupInstance` to do all of your default values, the APIs have been kept separate to allow a clean separation between setting up defaults and establishing relationships and other constructors. - ```js // See the `model-relationships.test.ts` file for example usage. // This is a brief example. diff --git a/test/service-module/module.getters.test.ts b/test/service-module/module.getters.test.ts index 1f85e0e7..6f67f020 100644 --- a/test/service-module/module.getters.test.ts +++ b/test/service-module/module.getters.test.ts @@ -66,7 +66,7 @@ describe('Service Module - Getters', function() { }) it('get works on tempsById', function() { - const { state, items } = this + const { state } = this const tempId = Object.keys(state.tempsById)[0] // @ts-ignore const result = get(state)(tempId) From 4215d0aa26c1576c064fcd0f5c73202181395dda Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 23:08:35 -0600 Subject: [PATCH 156/404] Model instance.remove works with temp records --- src/service-module/make-model.ts | 13 +++++++++++-- test/service-module/model-methods.test.ts | 11 +++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index db684401..9396aa84 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -350,9 +350,18 @@ export default function makeModel(options: FeathersVuexOptions) { * @param params */ public remove(params) { - const { idField, _dispatch } = this.constructor as typeof BaseModel + const { idField, tempIdField, _dispatch, _commit } = this + .constructor as typeof BaseModel - return _dispatch.call(this.constructor, 'remove', [this[idField], params]) + if (this.hasOwnProperty(idField)) { + return _dispatch.call(this.constructor, 'remove', [ + this[idField], + params + ]) + } else { + _commit.call(this.constructor, 'removeTemps', [this[tempIdField]]) + return Promise.resolve(this) + } } public toJSON() { diff --git a/test/service-module/model-methods.test.ts b/test/service-module/model-methods.test.ts index a22cf649..92f18300 100644 --- a/test/service-module/model-methods.test.ts +++ b/test/service-module/model-methods.test.ts @@ -164,6 +164,17 @@ describe('Models - Methods', function() { assert(called, 'update should have been called') }) + it.only('instance.remove works with temp records', function() { + const { Task, store } = makeContext() + const task = new Task({ test: true }) + const tempId = task.__id + + task.remove() + + // @ts-ignore + assert(!store.state.tasks.tempsById[tempId], 'temp was removed') + }) + it('instance.toJSON', function() { const { Task } = makeContext() const task = new Task({ id: 1, test: true }) From 4f49da4702c953cd77abab5b6c7f577ed4d9a8ba Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 23:09:20 -0600 Subject: [PATCH 157/404] Remove .only from tests --- test/service-module/model-methods.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/service-module/model-methods.test.ts b/test/service-module/model-methods.test.ts index 92f18300..3d282b85 100644 --- a/test/service-module/model-methods.test.ts +++ b/test/service-module/model-methods.test.ts @@ -164,7 +164,7 @@ describe('Models - Methods', function() { assert(called, 'update should have been called') }) - it.only('instance.remove works with temp records', function() { + it('instance.remove works with temp records', function() { const { Task, store } = makeContext() const task = new Task({ test: true }) const tempId = task.__id From ff8b239381ac7182b50096177152e1fa73c2a9f3 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 31 Mar 2019 23:09:40 -0600 Subject: [PATCH 158/404] v2.0.0-pre.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 57b1031b..1c87ec9d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.4", + "version": "2.0.0-pre.5", "homepage": "https://github.com/feathersjs/feathers-vuex", "main": "lib/", "module": "dist/", From 8687e4b9d0e24eb5548343aacfb8aed78ba34bc5 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 1 Apr 2019 16:43:49 -0600 Subject: [PATCH 159/404] Test customizing idField for two services --- test/service-module/service-module.test.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 48e7bc82..f365ac38 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -432,21 +432,30 @@ describe('Service Module', function() { assert(state.todos, 'uses `short` nameStyle by default') }) - it('can customize the idField for each service', function() { - const { makeServicePlugin, Test } = makeContext() - const idField = '_id' + it.only('can customize the idField for each service', function() { + const { makeServicePlugin, Test, Person } = makeContext() const store = new Vuex.Store({ plugins: [ makeServicePlugin({ - idField, + idField: '_id', Model: Test, service: feathersClient.service('tests') + }), + makeServicePlugin({ + idField: 'name', + Model: Person, + service: feathersClient.service('people') }) ] }) assert( - store.state.tests.idField === idField, + store.state.tests.idField === '_id', + 'the idField was properly set' + ) + assert( + // @ts-ignore + store.state.people.idField === 'name', 'the idField was properly set' ) }) From 227f8dd20c4e40e5130c49c08d985dbc6cd6bf7c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 1 Apr 2019 16:44:39 -0600 Subject: [PATCH 160/404] Run all tests --- test/service-module/service-module.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index f365ac38..c777509c 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -432,7 +432,7 @@ describe('Service Module', function() { assert(state.todos, 'uses `short` nameStyle by default') }) - it.only('can customize the idField for each service', function() { + it('can customize the idField for each service', function() { const { makeServicePlugin, Test, Person } = makeContext() const store = new Vuex.Store({ plugins: [ From d1fa45b3675c7c58c0fc0dd39ddbbbe5f123a775 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Apr 2019 10:16:51 -0600 Subject: [PATCH 161/404] Fix bug with makeFindMixin watcher If you watched a single param in the watcher, it would pass the single param to the `find` action instead of passing all props. This change makes sure no params are passed, which allows the `find` mixin to perform the proper params-picking logic, internally. --- src/make-find-mixin.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index edb1b9a2..daf1bc57 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -139,7 +139,9 @@ export default function makeFindMixin(options) { prop = prop.replace(PARAMS, FETCH_PARAMS) } } - this.$watch(prop, this[FIND_ACTION]) + this.$watch(prop, function() { + return this[FIND_ACTION]() + }) }) return this[FIND_ACTION]() From d2ef20964c65d0d644a481546f384dd32ef1e9fc Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Apr 2019 10:17:19 -0600 Subject: [PATCH 162/404] Start test for makeFindMixin with dynamic service --- test/make-find-mixin.test.ts | 54 ++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/test/make-find-mixin.test.ts b/test/make-find-mixin.test.ts index 06da34f2..5e99f5fd 100644 --- a/test/make-find-mixin.test.ts +++ b/test/make-find-mixin.test.ts @@ -89,4 +89,58 @@ describe('Find Mixin', function() { 'no fetch params are in place by default, must be specified by the user' ) }) + + it.skip('correctly forms mixin data for dynamic service', function() { + const tasksMixin = makeFindMixin({ + service() { + return this.serviceName + } + }) + + interface TasksComponent { + tasks: [] + serviceServiceName: string + isFindTasksPending: boolean + findTasks: Function + tasksLocal: boolean + tasksQid: string + tasksQueryWhen: Function + tasksParams: any + tasksFetchParams: any + } + + const vm = new Vue({ + name: 'tasls-component', + data: () => ({ + serviceName: 'tasks' + }), + mixins: [tasksMixin], + store, + template: `
` + }).$mount() + + assert.deepEqual(vm.tasks, [], 'tasks prop was empty array') + assert( + vm.hasOwnProperty('tasksPaginationData'), + 'pagination data prop was present, even if undefined' + ) + assert(vm.tasksServiceName === 'tasks', 'service name was correct') + assert(vm.isFindTasksPending === false, 'loading boolean is in place') + assert(typeof vm.findTasks === 'function', 'the find action is in place') + assert(vm.tasksLocal === false, 'local boolean is false by default') + assert( + vm.tasksQid === 'default', + 'the default query identifier is in place' + ) + assert(vm.tasksQueryWhen() === true, 'the default queryWhen is true') + // assert(vm.tasksWatch.length === 0, 'the default watch is an empty array') + assert( + vm.tasksParams === undefined, + 'no params are in place by default, must be specified by the user' + ) + assert( + vm.tasksFetchParams === undefined, + 'no fetch params are in place by default, must be specified by the user' + ) + }) }) From f79a029c9469f39c61dd73d7a519a5387d76c273 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Apr 2019 10:19:37 -0600 Subject: [PATCH 163/404] Expose handleFindResponse and handleFindError New actions expose functionality that was previously enclosed inside the `find` action. --- src/service-module/notes.md | 4 + src/service-module/service-module.actions.ts | 84 ++++++++++---------- 2 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index d937cd43..3a90ad7d 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -259,6 +259,10 @@ commit('setError', { method: 'find', error }) commit('clearError', 'find') ``` +## New Actions in the Service Module + +The `handleFindResponse` and `handleFindError` actions were previously enclosed inside the `find` action. Since the majority fo the `find` action consisted of the response handler, they've been pulled out. This allows for much better readability. It's technically now possible to override both actions by providing replacements in the `makeServicePlugin` config. + ## Relationships have been separated from `instanceDefaults` Feathers-Vuex 2.0 has a new API for establishing relationships between data. Before we cover how it works, let's review the old API, first. diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 1d9627f2..56f47229 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -7,54 +7,15 @@ import { observableDiff, applyChange } from 'deep-diff' export default function makeServiceActions(service) { const serviceActions = { - find({ commit, dispatch, state }, params) { + find({ commit, dispatch }, params) { params = params || {} - const { idField } = state - const handleResponse = response => { - const { qid = 'default', query } = params - - dispatch('addOrUpdateList', response) - commit('unsetPending', 'find') - - const mapItemFromState = item => { - const id = item[idField] - - return state.keyedById[id] - } - - // The pagination data will be under `pagination.default` or whatever qid is passed. - if (response.data) { - commit('updatePaginationForQuery', { qid, response, query }) - - const mappedFromState = response.data.map(mapItemFromState) - - if (mappedFromState[0] !== undefined) { - response.data = mappedFromState - } - } else { - const mappedFromState = response.map(mapItemFromState) - - if (mappedFromState[0] !== undefined) { - response = mappedFromState - } - } - - dispatch('afterFind', response) - - return response - } - const handleError = error => { - commit('setError', { method: 'find', error }) - commit('unsetPending', 'find') - return Promise.reject(error) - } commit('setPending', 'find') return service .find(params) - .then(handleResponse) - .catch(handleError) + .then(response => dispatch('handleFindResponse', { params, response })) + .catch(error => dispatch('handleFindError', { params, error })) }, // Two query syntaxes are supported, since actions only receive one argument. @@ -247,6 +208,45 @@ export default function makeServiceActions(service) { } const actions = { + handleFindResponse({ state, commit, dispatch }, { params, response }) { + const { qid = 'default', query } = params + const { idField } = state + + dispatch('addOrUpdateList', response) + commit('unsetPending', 'find') + + const mapItemFromState = item => { + const id = item[idField] + + return state.keyedById[id] + } + + // The pagination data will be under `pagination.default` or whatever qid is passed. + if (response.data) { + commit('updatePaginationForQuery', { qid, response, query }) + + const mappedFromState = response.data.map(mapItemFromState) + + if (mappedFromState[0] !== undefined) { + response.data = mappedFromState + } + } else { + const mappedFromState = response.map(mapItemFromState) + + if (mappedFromState[0] !== undefined) { + response = mappedFromState + } + } + + dispatch('afterFind', response) + + return response + }, + handleFindError({ commit }, { params, error }) { + commit('setError', { method: 'find', error }) + commit('unsetPending', 'find') + return Promise.reject(error) + }, afterFind() {}, addOrUpdateList({ state, commit }, response) { const list = response.data || response From e74c6bd7323141c280bc4d2bac0794ef0d04c363 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Apr 2019 10:32:49 -0600 Subject: [PATCH 164/404] Clone params for all actions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Feathers client directly modifies params, so this clones them so that the Feathers client doesn’t modify the query that gets passed to the `find` getter (when the same query params are used for both the action and the getter, as is done with the `makeFindMixin`. --- src/service-module/service-module.actions.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 56f47229..8d44732a 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -4,11 +4,13 @@ eslint @typescript-eslint/no-explicit-any: 0 */ import { observableDiff, applyChange } from 'deep-diff' +import fastCopy from 'fast-copy' export default function makeServiceActions(service) { const serviceActions = { find({ commit, dispatch }, params) { params = params || {} + params = fastCopy(params) commit('setPending', 'find') @@ -35,6 +37,8 @@ export default function makeServiceActions(service) { params = {} } + params = fastCopy(params) + if ('skipRequestIfExists' in params) { skipRequestIfExists = params.skipRequestIfExists delete params.skipRequestIfExists @@ -83,6 +87,8 @@ export default function makeServiceActions(service) { data = dataOrArray } + params = fastCopy(params) + if (Array.isArray(data)) { tempIds = data.map(i => i[tempIdField]) } else { @@ -126,6 +132,8 @@ export default function makeServiceActions(service) { commit('setPending', 'update') + params = fastCopy(params) + return service .update(id, data, params) .then(item => { @@ -146,6 +154,8 @@ export default function makeServiceActions(service) { commit('setPending', 'patch') + params = fastCopy(params) + if (diffOnPatch) { let diff = {} @@ -189,6 +199,7 @@ export default function makeServiceActions(service) { } params = params || {} + params = fastCopy(params) commit('setPending', 'remove') @@ -208,6 +219,14 @@ export default function makeServiceActions(service) { } const actions = { + /** + * Handle the response from the find action. + * + * @param payload consists of the following two params + * @param params - Remember that these params aren't what was sent to the + * Feathers client. The client modifies the params object. + * @param response + */ handleFindResponse({ state, commit, dispatch }, { params, response }) { const { qid = 'default', query } = params const { idField } = state From 1d9c6f092af54797f05816ba260567f27031f39c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Apr 2019 10:33:37 -0600 Subject: [PATCH 165/404] v2.0.0-pre.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1c87ec9d..538cce19 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.5", + "version": "2.0.0-pre.6", "homepage": "https://github.com/feathersjs/feathers-vuex", "main": "lib/", "module": "dist/", From 1df7ae26081ed236ee43ae0afbbf6448afa32d4b Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Apr 2019 10:33:58 -0600 Subject: [PATCH 166/404] 2.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1164118d..00dd66dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "1.7.0", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 538cce19..20084c10 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.6", + "version": "2.0.0", "homepage": "https://github.com/feathersjs/feathers-vuex", "main": "lib/", "module": "dist/", From 66e09690f019752a399928bc1477787dd2d63f34 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Apr 2019 18:43:51 -0600 Subject: [PATCH 167/404] v2.0.0-pre.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 20084c10..1c24b7c6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0", + "version": "2.0.0-pre.7", "homepage": "https://github.com/feathersjs/feathers-vuex", "main": "lib/", "module": "dist/", From 243032c0e948908fb334b6e49e3a976898a92177 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Apr 2019 20:44:23 -0600 Subject: [PATCH 168/404] More DRY handleFindResponse, with comment --- src/service-module/service-module.actions.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 8d44732a..7b0b653e 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -241,20 +241,16 @@ export default function makeServiceActions(service) { } // The pagination data will be under `pagination.default` or whatever qid is passed. - if (response.data) { + response.data && commit('updatePaginationForQuery', { qid, response, query }) - const mappedFromState = response.data.map(mapItemFromState) - - if (mappedFromState[0] !== undefined) { - response.data = mappedFromState - } - } else { - const mappedFromState = response.map(mapItemFromState) - - if (mappedFromState[0] !== undefined) { - response = mappedFromState - } + // Swap out the response records for their Vue-observable store versions + const data = response.data || response + const mappedFromState = data.map(mapItemFromState) + if (mappedFromState[0] !== undefined) { + response.data + ? (response.data = mappedFromState) + : (response = mappedFromState) } dispatch('afterFind', response) From 371f7d8e6a7e1da39ce57ebc17a75927d8d2a51b Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Apr 2019 21:34:49 -0600 Subject: [PATCH 169/404] =?UTF-8?q?Allow=20cloning=20non-enumerable=20prop?= =?UTF-8?q?s=20that=20aren=E2=80=99t=20=5F=5Fob=5F=5F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utils.ts b/src/utils.ts index 45107dc8..5fd614c1 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -324,7 +324,11 @@ export function mergeWithAccessors(dest, source) { const sourceDesc = Object.getOwnPropertyDescriptor(source, key) const destDesc = Object.getOwnPropertyDescriptor(dest, key) - if (!sourceDesc.enumerable) { + // This might have to be uncommented, but we'll try it this way, for now. + // if (!sourceDesc.enumerable) { + // return + // } + if (key === '__ob__') { return } From c975735ebb8bfd56b130d81658e8e69b5fa49afe Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Apr 2019 21:37:43 -0600 Subject: [PATCH 170/404] Add notes about enumerables --- src/service-module/notes.md | 74 +++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 3a90ad7d..7f709399 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -353,6 +353,80 @@ Where `instanceDefaults` props get replaced by instance data, the props returned Object.assign({}, instanceDefaults(data), data, setupInstance(data)) ``` +### This part is out of date + +I'm testing out a version of the `mergeWithAccessors` utility function that allows copying non-enumerables, but still skips `__ob__` properties for Vue.Observables. This section will require updating after I've integration tested it. + +Another important note when using es5 accessors (get/set) is that you must define the property as enumerable. This is because the `mergeWithAccessors` utility that's used to clone and commit instances ignores any non-enumerable props. Using the previous example as a starting point, this is how to define an es5 getter: + +```js +function setupInstance(data, { models, store }) { + const { User } = models.myServerAlias + + data = Object.assign(data, { + ...(data.user && { user: new User(data.user) }), // A single User instance + ...(data.tags && { tags: data.tags.map(t => new Tag(t)) }), // An array of Tag instances + ...(data.createdAt && { createdAt: new Date(data.createdAt) }) // A JavaScript Date Object + }) + + Object.defineProperties(data, { + fullName: { + enumerable: true, + get () { + return `${this.firstName} ${this.lastName}` + } + } + }) + + return data +} +``` + +Making a getter enumerable means that it will get serialized in the toJSON method, by default. This means that the attribute will get sent in requests to the API server. This isn't a problem if the API strips away extra params without throwing an error. For other APIs, it might be an issue. To prevent the attribute from getting serialized in requests, you can override the toJSON method in the model class: + +```js +import fastCopy from 'fast-copy' + +const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'myApi' +}) + +const Todo extends BaseModel { + // The `setupInstance` method must be a static method + static setupInstance(data, { models, store }) { + const { User } = models.myServerAlias + + data = Object.assign(data, { + ...(data.user && { user: new User(data.user) }), // A single User instance + ...(data.tags && { tags: data.tags.map(t => new Tag(t)) }), // An array of Tag instances + ...(data.createdAt && { createdAt: new Date(data.createdAt) }) // A JavaScript Date Object + }) + + Object.defineProperties(data, { + fullName: { + enumerable: true, + get () { + return `${this.firstName} ${this.lastName}` + } + } + }) + + return data + } + // And toJSON is an instance prop + toJSON () { + // Copy the data so you don't modify the original + const copy = fastCopy(this) + + // Delete the prop / modify as required + delete copy.fullName + + // Return the modified data + return copy + } +} +``` + ## Preventing duplicate merge when extending BaseModel with a custom constructor The BaseModel constructor calls `mergeWithAccessors(this, newData)`. This utility function correctly copies data between both regular objects and Vue.observable instances. If you create a class where you need to do your own merging, you probably don't want `mergeWithAccessors` to run twice. In this case, you can use the `merge: false` BaseModel instance option to prevent the internal merge. You can then access the `mergeWithAccessors` method by calling `MyModel.merge(this, newData)`. Here's an example: From 766c3c3bf03b9ad8421b599254318c340e1b1df4 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Apr 2019 21:38:00 -0600 Subject: [PATCH 171/404] v2.0.0-pre.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1c24b7c6..02830d63 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.7", + "version": "2.0.0-pre.8", "homepage": "https://github.com/feathersjs/feathers-vuex", "main": "lib/", "module": "dist/", From 77b58cfe2c49665b6caddeb779df52553c1c0261 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 14 Apr 2019 18:38:34 -0600 Subject: [PATCH 172/404] Add module to store references to global feathers clients --- src/index.ts | 9 +++- src/service-module/global-clients.ts | 41 +++++++++++++++++++ .../make-service-plugin.test.ts | 8 ++++ test/service-module/model-base.test.ts | 5 +++ 4 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/service-module/global-clients.ts diff --git a/src/index.ts b/src/index.ts index 70492e35..cc1420a3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,7 @@ import FeathersVuexGet from './FeathersVuexGet' import makeFindMixin from './make-find-mixin' import makeGetMixin from './make-get-mixin' import { globalModels as models } from './service-module/global-models' +import { clients, addClient } from './service-module/global-clients' import makeModel from './service-module/make-model' import prepareMakeServicePlugin from './service-module/make-service-plugin' @@ -48,6 +49,8 @@ export default function feathersVuex(feathers, options: FeathersVuexOptions) { ) } + addClient({ client: feathers, serverAlias: options.serverAlias }) + const BaseModel = makeModel(options) const makeServicePlugin = prepareMakeServicePlugin(options) @@ -56,7 +59,8 @@ export default function feathersVuex(feathers, options: FeathersVuexOptions) { BaseModel, makeAuthPlugin: setupAuthModule(feathers), FeathersVuex, - models + models, + clients } } @@ -67,5 +71,6 @@ export { FeathersVuex, makeFindMixin, makeGetMixin, - models + models, + clients } diff --git a/src/service-module/global-clients.ts b/src/service-module/global-clients.ts new file mode 100644 index 00000000..cf91b521 --- /dev/null +++ b/src/service-module/global-clients.ts @@ -0,0 +1,41 @@ +/* +eslint +@typescript-eslint/explicit-function-return-type: 0, +@typescript-eslint/no-explicit-any: 0 +*/ +import { get as _get } from 'lodash' + +/** + * A global object that holds references to all Model Classes in the application. + */ +export const clients: { [k: string]: any } = { + byAlias: {}, + byHost: {} +} + +/** + * prepareAddModel wraps options in a closure around addModel + * @param options + */ +export function addClient({ client, serverAlias }) { + // Save reference to the clients by host uri, if it was available. + let uri = '' + if (client.io) { + uri = _get(client, 'io.io.uri') + } + if (uri) { + clients.byHost[uri] = client + } + // Save reference to clients by serverAlias. + clients.byAlias[serverAlias] = client +} + +export function clearClients() { + function deleteKeys(path) { + Object.keys(clients[path]).forEach(key => { + delete clients[path][key] + }) + } + deleteKeys('byAlias') + deleteKeys('byHost') +} diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index f21dae39..1c875d1b 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -7,6 +7,7 @@ import { assert } from 'chai' import Vue from 'vue' import Vuex from 'vuex' import { clearModels } from '../../src/service-module/global-models' +import { clients } from '../../src/service-module/global-clients' import { feathersRestClient as feathers } from '../../test/fixtures/feathers-client' import feathersVuex from '../../src/index' import { pick as _pick, omit as _omit } from 'lodash' @@ -18,6 +19,13 @@ describe('makeServicePlugin', function() { clearModels() }) + it('adds Feathers client to the global clients', () => { + feathersVuex(feathers, { + serverAlias: 'this is a test' + }) + assert(clients.byAlias['this is a test'], 'got a reference to the client.') + }) + it('registers the vuex module with options', function() { interface RootState { todos: {} diff --git a/test/service-module/model-base.test.ts b/test/service-module/model-base.test.ts index 784a8b0c..82c7d8ef 100644 --- a/test/service-module/model-base.test.ts +++ b/test/service-module/model-base.test.ts @@ -17,6 +17,11 @@ Vue.use(Vuex) process.setMaxListeners(100) +describe.skip('Model - Standalone', function() { + it.skip('allows using a model without a service', function() {}) + it.skip('rename serverAlias to just `alias` or maybe `groupName`', function() {}) +}) + describe('makeModel / BaseModel', function() { before(() => { clearModels() From e8e376a495ae05d1583bd2ce75c9b7b9e706bb72 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 14 Apr 2019 18:39:14 -0600 Subject: [PATCH 173/404] v2.0.0-pre.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 02830d63..fbfa14a8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.8", + "version": "2.0.0-pre.9", "homepage": "https://github.com/feathersjs/feathers-vuex", "main": "lib/", "module": "dist/", From f1cb47c72ad9c7b1fa73a5383250eb12a62a2d42 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 14 Apr 2019 18:40:39 -0600 Subject: [PATCH 174/404] Fix git url --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fbfa14a8..7c621793 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "license": "MIT", "repository": { "type": "git", - "url": "git://github.com/feathersjs/feathers-vuex.git" + "url": "git://github.com/feathers-plus/feathers-vuex.git" }, "author": { "name": "Marshall Thompson", From 540d4764affc8729485420cdc61d37a5e7e6180b Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 14 Apr 2019 18:43:02 -0600 Subject: [PATCH 175/404] Fix more URLs in package.json --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7c621793..ffeb74ff 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", "version": "2.0.0-pre.9", - "homepage": "https://github.com/feathersjs/feathers-vuex", + "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", "keywords": [ @@ -21,7 +21,7 @@ }, "contributors": [], "bugs": { - "url": "https://github.com/feathersjs/feathers-vuex/issues" + "url": "https://github.com/feathers-plus/feathers-vuex/issues" }, "engines": { "node": ">= 4.6.0" From 3fc03ecc9157852cb4400521eded351b92a15bab Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 14 Apr 2019 23:57:33 -0600 Subject: [PATCH 176/404] Allow eager removal from store --- src/service-module/make-model.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 9396aa84..b756199b 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -354,6 +354,9 @@ export default function makeModel(options: FeathersVuexOptions) { .constructor as typeof BaseModel if (this.hasOwnProperty(idField)) { + if (params.eager) { + _commit.call(this.constructor, 'removeItem', [this[idField]]) + } return _dispatch.call(this.constructor, 'remove', [ this[idField], params From f26d3778b47ca5b9b9b8e8fff9db844ddbd57246 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 14 Apr 2019 23:57:46 -0600 Subject: [PATCH 177/404] v2.0.0-pre.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ffeb74ff..ed6685d5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.9", + "version": "2.0.0-pre.10", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From 7b3a46d2c2182f6137603d6b8b915910a00e7b70 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 15 Apr 2019 00:11:51 -0600 Subject: [PATCH 178/404] Fix eager removal --- src/service-module/make-model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index b756199b..375e3589 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -355,7 +355,7 @@ export default function makeModel(options: FeathersVuexOptions) { if (this.hasOwnProperty(idField)) { if (params.eager) { - _commit.call(this.constructor, 'removeItem', [this[idField]]) + _commit.call(this.constructor, 'removeItem', this[idField]) } return _dispatch.call(this.constructor, 'remove', [ this[idField], From aa3e351d0a41cdfd008886828221addf566b6a46 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 15 Apr 2019 00:12:04 -0600 Subject: [PATCH 179/404] v2.0.0-pre.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ed6685d5..ef3cedbb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.10", + "version": "2.0.0-pre.11", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From 289010c9602d40c3ee2146bc0c72657fe3b99035 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 15 Apr 2019 07:52:44 -0600 Subject: [PATCH 180/404] Guard against missing params in instance.remove() --- src/service-module/make-model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 375e3589..81d6cb6b 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -354,7 +354,7 @@ export default function makeModel(options: FeathersVuexOptions) { .constructor as typeof BaseModel if (this.hasOwnProperty(idField)) { - if (params.eager) { + if (params && params.eager) { _commit.call(this.constructor, 'removeItem', this[idField]) } return _dispatch.call(this.constructor, 'remove', [ From 4b416a7e63d3aecd547952ac42b1eafc69ef1ecc Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 15 Apr 2019 07:53:01 -0600 Subject: [PATCH 181/404] v2.0.0-pre.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ef3cedbb..e99a6f66 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.11", + "version": "2.0.0-pre.12", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From 0e356b9dc1bbbb74a23a082b0cfdf440a0d6c686 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 15 Apr 2019 08:36:08 -0600 Subject: [PATCH 182/404] diff on patch should use the keyedById record. --- src/service-module/service-module.actions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 7b0b653e..4d7c5459 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -159,7 +159,7 @@ export default function makeServiceActions(service) { if (diffOnPatch) { let diff = {} - observableDiff(state.copy, data, function(d) { + observableDiff(state.keyedById[id], data, function(d) { if (d.path && d.path.length) { // Apply all changes except to the id property... if (d.path[d.path.length - 1] !== idField) { From 0ce98949624d04d9a81ff63e1ad48e852db99669 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 15 Apr 2019 08:36:24 -0600 Subject: [PATCH 183/404] v2.0.0-pre.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e99a6f66..a16808c6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.12", + "version": "2.0.0-pre.13", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From 5e06e45e376bece41c770362414bbee0f53723c7 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 15 Apr 2019 08:40:21 -0600 Subject: [PATCH 184/404] Remove diffOnPatch diffOnPatch requires to be rewritten with some tests. Now that state.copy has been removed, diffOnPatch is broken. --- src/service-module/service-module.actions.ts | 29 ++++++++++---------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 4d7c5459..5676a40b 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -156,20 +156,21 @@ export default function makeServiceActions(service) { params = fastCopy(params) - if (diffOnPatch) { - let diff = {} - - observableDiff(state.keyedById[id], data, function(d) { - if (d.path && d.path.length) { - // Apply all changes except to the id property... - if (d.path[d.path.length - 1] !== idField) { - applyChange(diff, data, d) - } - } - }) - - data = diff - } + // This needs to be re-built, since we've removed state.copy + // if (diffOnPatch) { + // let diff = {} + + // observableDiff(state.keyedById[id], data, function(d) { + // if (d.path && d.path.length) { + // // Apply all changes except to the id property... + // if (d.path[d.path.length - 1] !== idField) { + // applyChange(diff, data, d) + // } + // } + // }) + + // data = diff + // } return service .patch(id, data, params) From 2ac3f39f9a4e21888a4fd2aa4806ac22c2d22293 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 15 Apr 2019 08:40:40 -0600 Subject: [PATCH 185/404] v2.0.0-pre.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a16808c6..af905d04 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.13", + "version": "2.0.0-pre.14", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From 128f12641c068197df8f86c44d02945323666bd3 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 15 Apr 2019 15:44:51 -0600 Subject: [PATCH 186/404] Remove serialize since we can just override toJSON --- src/service-module/make-model.ts | 18 +--------------- src/service-module/make-service-plugin.ts | 7 ++----- src/service-module/service-module.state.ts | 1 - src/service-module/types.ts | 1 - test/service-module/model-tests.test.ts | 24 ++++++++++++++++++++++ 5 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 81d6cb6b..3007e6a2 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -52,20 +52,6 @@ export default function makeModel(options: FeathersVuexOptions) { public static setupInstance(data, { models, store }) { return data } - public static serialize(item, { models, store }) { - return _omit(item, [ - '_clone', - 'clone', - 'commit', - 'create', - 'patch', - 'remove', - 'reset', - 'save', - 'toJSON', - 'update' - ]) - } // Monkey patched onto the Model class in `makeServicePlugin()` public static store: Record @@ -368,9 +354,7 @@ export default function makeModel(options: FeathersVuexOptions) { } public toJSON() { - const { serialize, store, models } = this.constructor as typeof BaseModel - const data = _merge({}, serialize(this, { store, models })) - return data + return _merge({}, this) } } addModel(BaseModel) diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index 40fa00d1..8d4cbad2 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -18,8 +18,7 @@ const defaults = { mutations: {}, // for custom mutations actions: {}, // for custom actions instanceDefaults: () => ({}), // Default instanceDefaults returns an empty object - setupInstance: instance => instance, // Default setupInstance returns the instance - serialize: item => item // Default serialize function + setupInstance: instance => instance // Default setupInstance returns the instance } /** @@ -45,8 +44,7 @@ export default function prepareMakeServicePlugin( nameStyle, instanceDefaults, setupInstance, - preferUpdate, - serialize + preferUpdate } = options if (!service) { @@ -84,7 +82,6 @@ export default function prepareMakeServicePlugin( servicePath, instanceDefaults, setupInstance, - serialize, preferUpdate }) addModel(Model) diff --git a/src/service-module/service-module.state.ts b/src/service-module/service-module.state.ts index e1eb40ae..3bff0d4e 100644 --- a/src/service-module/service-module.state.ts +++ b/src/service-module/service-module.state.ts @@ -13,7 +13,6 @@ export default function makeDefaultState(servicePath, options) { 'instanceDefaults', 'Model', 'mutations', - 'serialize', 'service', 'setupInstance', 'state', diff --git a/src/service-module/types.ts b/src/service-module/types.ts index 0dc3b6ac..c716b59e 100644 --- a/src/service-module/types.ts +++ b/src/service-module/types.ts @@ -35,7 +35,6 @@ export interface MakeServicePluginOptions { servicePath?: string instanceDefaults?: () => {} setupInstance?: (data, { models, store }) => {} - serialize?: () => {} state?: {} getters?: {} mutations?: {} diff --git a/test/service-module/model-tests.test.ts b/test/service-module/model-tests.test.ts index 224f0b7e..717fb850 100644 --- a/test/service-module/model-tests.test.ts +++ b/test/service-module/model-tests.test.ts @@ -133,4 +133,28 @@ describe('TypeScript Class Inheritance', () => { assert(todo._options.servicePath === 'v1/todos', 'got static servicePath') }) + + it('cannot serialize instance methods', () => { + class BaseModel { + public clone() { + return this + } + + public constructor(data) { + Object.assign(this, data) + } + } + + class Todo extends BaseModel { + public serialize() { + return Object.assign({}, this, { serialized: true }) + } + } + + const todo = new Todo({ name: 'test' }) + const json = JSON.parse(JSON.stringify(todo)) + + assert(!json.clone) + assert(!json.serialize) + }) }) From bd18147d7c531d60c823d05cfd425973f218ec61 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 15 Apr 2019 15:45:07 -0600 Subject: [PATCH 187/404] v2.0.0-pre.15 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index af905d04..d109f98d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.14", + "version": "2.0.0-pre.15", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From c21b098ce80a65a4637e81c529c78aa7748815c3 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 17 Apr 2019 00:05:37 -0600 Subject: [PATCH 188/404] Add blacklist to cloneWithAccessors, ignore __isClone --- src/service-module/make-model.ts | 3 +-- src/utils.ts | 8 ++++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 3007e6a2..8de0af0e 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -64,9 +64,8 @@ export default function makeModel(options: FeathersVuexOptions) { public static readonly models = globalModels // Can access other Models here public static readonly copiesById = {} - protected __isClone: boolean - public __id: string + public __isClone: boolean public data: Record public static merge = mergeWithAccessors diff --git a/src/utils.ts b/src/utils.ts index 5fd614c1..af18ede2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -315,7 +315,11 @@ export function isBaseModelInstance(item) { }) } -export function mergeWithAccessors(dest, source) { +export function mergeWithAccessors( + dest, + source, + blacklist = ['__isClone', '__ob__'] +) { const sourceProps = Object.getOwnPropertyNames(source) const destProps = Object.getOwnPropertyNames(dest) const sourceIsVueObservable = sourceProps.includes('__ob__') @@ -328,7 +332,7 @@ export function mergeWithAccessors(dest, source) { // if (!sourceDesc.enumerable) { // return // } - if (key === '__ob__') { + if (blacklist.includes(key)) { return } From 5c922934fa0af36d10af1ef22617c08b275a7baa Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 17 Apr 2019 00:05:54 -0600 Subject: [PATCH 189/404] v2.0.0-pre.16 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d109f98d..8409fc0d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.15", + "version": "2.0.0-pre.16", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From 72375e86ca274feb816232bb257202cbb9a57a03 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 17 Apr 2019 00:45:14 -0600 Subject: [PATCH 190/404] =?UTF-8?q?Don=E2=80=99t=20make=20=5F=5FisClone=20?= =?UTF-8?q?readonly?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service-module/make-model.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 8de0af0e..07027cf8 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -103,8 +103,7 @@ export default function makeModel(options: FeathersVuexOptions) { if (options.clone) { Object.defineProperty(this, '__isClone', { value: true, - enumerable: false, - writable: false + enumerable: false }) } From 65fcc383c8367573798a949862d1bbb871318f37 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 17 Apr 2019 00:45:35 -0600 Subject: [PATCH 191/404] v2.0.0-pre.17 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8409fc0d..e2ed49d4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.16", + "version": "2.0.0-pre.17", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From 682ec64b7e95985d2452a9ac28975559058290e6 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 17 Apr 2019 10:17:56 -0600 Subject: [PATCH 192/404] Return correct values after .clone() and .commit() --- src/service-module/make-model.ts | 5 +++-- test/service-module/service-module.test.ts | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 07027cf8..840f2eef 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -238,6 +238,7 @@ export default function makeModel(options: FeathersVuexOptions) { if (this.__isClone) { const id = this[idField] || this[tempIdField] _commit.call(this.constructor, 'resetCopy', id) + return this } else { throw new Error('You cannot reset a non-copy') } @@ -247,13 +248,13 @@ export default function makeModel(options: FeathersVuexOptions) { * Update a store instance to match a clone. */ public commit() { - const { idField, tempIdField, _commit } = this + const { idField, tempIdField, _commit, _getters } = this .constructor as typeof BaseModel if (this.__isClone) { const id = this[idField] || this[tempIdField] _commit.call(this.constructor, 'commitCopy', id) - return this + return _getters.call(this.constructor, 'get', id) } else { throw new Error('You cannot call commit on a non-copy') } diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index c777509c..2c8dc5fa 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -310,7 +310,7 @@ describe('Service Module', function() { ) }) - it(`doesn't change the original if you modify return value of a commit`, function() { + it(`changes the original if you modify return value of a commit`, function() { const { serviceTodo, owners } = this let serviceTodoClone = serviceTodo.clone() @@ -325,8 +325,8 @@ describe('Service Module', function() { assert.deepEqual( serviceTodo.owners[0].name, - 'Marshall', - 'nested object in original todo was NOT changed' + 'Ted', + 'nested object in original todo was changed' ) }) From 4c53e128b7e9e0c32841b62c1d992c9d01b14ccb Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 17 Apr 2019 10:19:30 -0600 Subject: [PATCH 193/404] v2.0.0-pre.18 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e2ed49d4..2fb46747 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.17", + "version": "2.0.0-pre.18", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From 1d040e9a1e1eeb893fe66de60f966f7b5801d10a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 17 Apr 2019 18:01:18 -0600 Subject: [PATCH 194/404] getCopyById getter now supports Model.copiesById --- src/service-module/service-module.getters.ts | 15 +++++- .../service-module.mutations.ts | 4 +- test/service-module/module.getters.test.ts | 49 ++++++++++++++++++- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/service-module/service-module.getters.ts b/src/service-module/service-module.getters.ts index f7af79ec..5e4b05d0 100644 --- a/src/service-module/service-module.getters.ts +++ b/src/service-module/service-module.getters.ts @@ -7,6 +7,8 @@ import sift from 'sift' import commons from '@feathersjs/commons' import dbCommons from '@feathersjs/adapter-commons' import { omit as _omit } from 'lodash' +import { globalModels as models } from './global-models' +import { get as _get } from 'lodash' const { _ } = commons const { filterQuery, sorter, select } = dbCommons @@ -80,7 +82,18 @@ export default function makeServiceGetters() { return record || tempRecord }, getCopyById: state => id => { - return state.copiesById[id] + const { servicePath, keepCopiesInStore, serverAlias } = state + + if (keepCopiesInStore) { + return state.copiesById[id] + } else { + const Model = _get( + models, + `[${serverAlias}].byServicePath[${servicePath}]` + ) + + return Model.copiesById[id] + } } } } diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 8df5aedf..662baec0 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -161,11 +161,11 @@ export default function makeServiceMutations() { // Creates a copy of the record with the passed-in id, stores it in copiesById createCopy(state, id) { - const { servicePath, keepCopiesInStore } = state + const { servicePath, keepCopiesInStore, serverAlias } = state const current = state.keyedById[id] || state.tempsById[id] const Model = _get( models, - `[${state.serverAlias}].byServicePath[${servicePath}]` + `[${serverAlias}].byServicePath[${servicePath}]` ) if (Model) { diff --git a/test/service-module/module.getters.test.ts b/test/service-module/module.getters.test.ts index 6f67f020..c55fdbe9 100644 --- a/test/service-module/module.getters.test.ts +++ b/test/service-module/module.getters.test.ts @@ -7,6 +7,10 @@ import { assert } from 'chai' import makeServiceGetters from '../../src/service-module/service-module.getters' import makeServiceMutations from '../../src/service-module/service-module.mutations' import makeServiceState from '../../src/service-module/service-module.state' +import { + globalModels, + clearModels +} from '../../src/service-module/global-models' const options = { idField: '_id', @@ -15,7 +19,7 @@ const options = { serverAlias: 'default' } -const { find, list, get } = makeServiceGetters() +const { find, list, get, getCopyById } = makeServiceGetters() const { addItems } = makeServiceMutations() describe('Service Module - Getters', function() { @@ -56,6 +60,49 @@ describe('Service Module - Getters', function() { }) }) + it('getCopyById with keepCopiesInStore: true', function() { + const state = { + keepCopiesInStore: true, + copiesById: { + 1: { test: true } + } + } + // @ts-ignore + const result = getCopyById(state)(1) + + // @ts-ignore + assert(result.test, 'got the copy') + }) + + it('getCopyById with keepCopiesInStore: false', function() { + const state = { + keepCopiesInStore: false, + servicePath: 'todos', + serverAlias: 'my-getters-test', + copiesById: { + 1: { test: true } + } + } + Object.assign(globalModels, { + 'my-getters-test': { + byServicePath: { + todos: { + copiesById: { + 1: { test: true } + } + } + } + } + }) + // @ts-ignore + const result = getCopyById(state)(1) + + // @ts-ignore + assert(result.test, 'got the copy') + + clearModels() + }) + it('get works on keyedById', function() { const { state, items } = this // @ts-ignore From d129cd69295d23dce6e85a2616eb4eaa008b0428 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 17 Apr 2019 18:01:34 -0600 Subject: [PATCH 195/404] v2.0.0-pre.19 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2fb46747..f560db81 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.18", + "version": "2.0.0-pre.19", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From ff36eed7f7a76330b511f3f5b6274661dd167005 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 19 Apr 2019 00:24:21 -0600 Subject: [PATCH 196/404] Allow instantiating models without any data --- src/service-module/make-model.ts | 7 +++++-- src/utils.ts | 11 +++++++++-- test/service-module/model-relationships.test.ts | 2 -- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 840f2eef..98f8593a 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -6,7 +6,7 @@ eslint import { FeathersVuexOptions } from './types' import { globalModels, prepareAddModel } from './global-models' import { mergeWithAccessors, separateAccessors, checkNamespace } from '../utils' -import { get as _get, merge as _merge, omit as _omit } from 'lodash' +import { get as _get, merge as _merge } from 'lodash' // A hack to prevent error with this.constructor.preferUpdate interface Function { @@ -46,9 +46,11 @@ export default function makeModel(options: FeathersVuexOptions) { // Think of these as abstract static properties public static servicePath: string public static namespace: string + // eslint-disable-next-line public static instanceDefaults(data, { models, store }) { return data } + // eslint-disable-next-line public static setupInstance(data, { models, store }) { return data } @@ -125,7 +127,8 @@ export default function makeModel(options: FeathersVuexOptions) { } // Add the item to the store - if (!options.clone && options.commit !== false && store) { + // Make sure it wasn't an empty object. + if (!options.clone && options.commit !== false && store && data) { _commit.call(this.constructor, 'addItem', this) } return this diff --git a/src/utils.ts b/src/utils.ts index af18ede2..2b8701d3 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -322,12 +322,19 @@ export function mergeWithAccessors( ) { const sourceProps = Object.getOwnPropertyNames(source) const destProps = Object.getOwnPropertyNames(dest) - const sourceIsVueObservable = sourceProps.includes('__ob__') - const destIsVueObservable = destProps.includes('__ob__') + let sourceIsVueObservable = sourceProps.includes('__ob__') + let destIsVueObservable = destProps.includes('__ob__') sourceProps.forEach(key => { const sourceDesc = Object.getOwnPropertyDescriptor(source, key) const destDesc = Object.getOwnPropertyDescriptor(dest, key) + // if (Array.isArray(source[key]) && source[key].find(i => i.__ob__)) { + // sourceIsVueObservable = true + // } + // if (Array.isArray(dest[key]) && dest[key].find(i => i.__ob__)) { + // destIsVueObservable = true + // } + // This might have to be uncommented, but we'll try it this way, for now. // if (!sourceDesc.enumerable) { // return diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index f187cbb3..76a2aebf 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -155,8 +155,6 @@ function makeContext() { normal: { description: '', isComplete: false, - task: 'Task', - item: 'Item', priority: '' }, high: { From 887414b37e3fd6652a8087d58eaddf933dec850d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 19 Apr 2019 00:24:54 -0600 Subject: [PATCH 197/404] v2.0.0-pre.20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f560db81..a31624eb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.19", + "version": "2.0.0-pre.20", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From 9dbb0e0016ea05718d743cb307115d944a85874e Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 19 Apr 2019 00:47:16 -0600 Subject: [PATCH 198/404] Getters should always be declared in the class --- test/service-module/model-relationships.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index 76a2aebf..35daf201 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -178,6 +178,9 @@ function makeContext() { } } class Item extends BaseModel { + public get todos() { + return BaseModel.models.Todo.findInStore({ query: {} }).data + } public static instanceDefaults() { return { test: false, @@ -188,9 +191,6 @@ function makeContext() { const { Todo } = models.myApi return Object.assign(data, { - get todos() { - return Todo.findInStore({ query: {} }).data - }, ...(data.todo && { todo: new Todo(data.todo) }) }) } From 18ad378bf28cefac0702a477633725dc23078509 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 19 Apr 2019 00:47:27 -0600 Subject: [PATCH 199/404] Actually allow passing undefined this time --- src/service-module/make-model.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 98f8593a..5947a159 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -73,9 +73,7 @@ export default function makeModel(options: FeathersVuexOptions) { public static merge = mergeWithAccessors public constructor(data, options: BaseModelInstanceOptions) { - if (!data) { - return - } + const originalData = data options = Object.assign({}, defaultOptions, options) const { store, @@ -87,7 +85,7 @@ export default function makeModel(options: FeathersVuexOptions) { getFromStore, _commit } = this.constructor as typeof BaseModel - const id = data[idField] || data[tempIdField] + const id = data && (data[idField] || data[tempIdField]) const hasValidId = id !== null && id !== undefined data = data || {} @@ -127,8 +125,8 @@ export default function makeModel(options: FeathersVuexOptions) { } // Add the item to the store - // Make sure it wasn't an empty object. - if (!options.clone && options.commit !== false && store && data) { + // Make sure originalData wasn't an empty object. + if (!options.clone && options.commit !== false && store && originalData) { _commit.call(this.constructor, 'addItem', this) } return this From 2b61a266cec0f4fa7c98b177b0494ae58ad0f175 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 19 Apr 2019 00:47:39 -0600 Subject: [PATCH 200/404] v2.0.0-pre.21 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a31624eb..9e78bb3f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.20", + "version": "2.0.0-pre.21", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From fec423d9d84a45c3da15e126369dc160c56f6efa Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 19 Apr 2019 01:24:03 -0600 Subject: [PATCH 201/404] You must pass an empty object to get a tempId --- src/service-module/make-model.ts | 1 + src/service-module/notes.md | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 5947a159..1104a220 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -73,6 +73,7 @@ export default function makeModel(options: FeathersVuexOptions) { public static merge = mergeWithAccessors public constructor(data, options: BaseModelInstanceOptions) { + // You have to pass at least an empty object to get a tempId. const originalData = data options = Object.assign({}, defaultOptions, options) const { diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 7f709399..cb143ccc 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -89,6 +89,16 @@ Feathers-Vuex 2.0 supports tracking temporary items and automatically assigns a Previously, when a record didn't have an `[idField]`, a console.error would ask if you had configured the `idField` option. Because of the new ability to handle temporary records, a message is only logged when assigning a temporary id to a record. The `checkId` utility function has been removed, since this was its main purpose. +Note: In order to get a tempId, you must pass at least an empty object to the constructor. Supposing you have a Class named Todo: + +```js +// This will not get you a tempId +const noTempId = new Todo() + +// This will +const todoWithTempId = new Todo({}) +``` + ## Getters Work with Temporary Records The `find` getter has been updated to include records from `state.tempsById`, by default. You can pass `temps: false` in the params to only search `state.keyedById`: `find({ query: {}, temps: false })` From 988e2735968f384eef82612ed0a969a8a70b0360 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 19 Apr 2019 12:33:41 -0600 Subject: [PATCH 202/404] Remove __isTemp after a temp record is saved --- src/service-module/service-module.actions.ts | 11 +++++++++++ test/service-module/model-temp-ids.test.ts | 2 ++ 2 files changed, 13 insertions(+) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 5676a40b..aee7e492 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -103,6 +103,12 @@ export default function makeServiceActions(service) { .create(data, params) .then(response => { if (Array.isArray(response)) { + // If the response contains a real id, remove isTemp + response.forEach(item => { + if (item[idField]) { + delete item.__isTemp + } + }) dispatch('addOrUpdateList', response) response = response.map(item => { const id = item[idField] @@ -112,6 +118,11 @@ export default function makeServiceActions(service) { } else { const id = response[idField] + // If the response contains a real id, remove isTemp + if (response[idField]) { + delete response.__isTemp + } + dispatch('addOrUpdate', response) response = state.keyedById[id] diff --git a/test/service-module/model-temp-ids.test.ts b/test/service-module/model-temp-ids.test.ts index bc8f1058..16162c6c 100644 --- a/test/service-module/model-temp-ids.test.ts +++ b/test/service-module/model-temp-ids.test.ts @@ -237,10 +237,12 @@ describe('Models - Temp Ids', function() { const tempId = comic.__id // @ts-ignore assert(store.state.comics.tempsById[tempId]) + assert(comic.__isTemp) comic .save() .then(response => { + assert(!response.hasOwnProperty('__isTemp')) // The comic record is no longer in tempsById // @ts-ignore assert(!store.state.comics.tempsById[tempId], 'temp is gone') From 15ca4f6048fc2fc6db2ee130eff58bb447997a50 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 19 Apr 2019 12:36:21 -0600 Subject: [PATCH 203/404] Delete __isTemp in the mutation instead of the action --- src/service-module/service-module.actions.ts | 11 ----------- src/service-module/service-module.mutations.ts | 10 ++++++++++ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index aee7e492..5676a40b 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -103,12 +103,6 @@ export default function makeServiceActions(service) { .create(data, params) .then(response => { if (Array.isArray(response)) { - // If the response contains a real id, remove isTemp - response.forEach(item => { - if (item[idField]) { - delete item.__isTemp - } - }) dispatch('addOrUpdateList', response) response = response.map(item => { const id = item[idField] @@ -118,11 +112,6 @@ export default function makeServiceActions(service) { } else { const id = response[idField] - // If the response contains a real id, remove isTemp - if (response[idField]) { - delete response.__isTemp - } - dispatch('addOrUpdate', response) response = state.keyedById[id] diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 662baec0..1c529af1 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -22,6 +22,11 @@ export default function makeServiceMutations() { const id = item[idField] const isTemp = id === null || id === undefined + // If the response contains a real id, remove isTemp + if (id) { + delete item.__isTemp + } + if (Model && !(item instanceof BaseModel) && !(item instanceof Model)) { item = new Model(item) } @@ -51,6 +56,11 @@ export default function makeServiceMutations() { for (let item of items) { let id = item[idField] + // If the response contains a real id, remove isTemp + if (id) { + delete item.__isTemp + } + // Update the record if (id !== null && id !== undefined) { if (state.ids.includes(id)) { From 971a8519f26484558b36bc70d65fe2817cfccbbd Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 19 Apr 2019 12:36:39 -0600 Subject: [PATCH 204/404] v2.0.0-pre.22 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9e78bb3f..39d542eb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.21", + "version": "2.0.0-pre.22", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From bb9e6296f4ea840849870f9b2cd1856189becf2d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 19 Apr 2019 22:13:55 -0600 Subject: [PATCH 205/404] Add test for specifying a tempId in a new record --- test/service-module/model-temp-ids.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/service-module/model-temp-ids.test.ts b/test/service-module/model-temp-ids.test.ts index 16162c6c..56268130 100644 --- a/test/service-module/model-temp-ids.test.ts +++ b/test/service-module/model-temp-ids.test.ts @@ -11,6 +11,7 @@ import { clearModels } from '../../src/service-module/global-models' import memory from 'feathers-memory' import Vuex from 'vuex' import { makeStore } from '../test-utils' +import ObjectID from 'bson-objectid' interface RootState { transactions: ServiceState @@ -100,6 +101,16 @@ describe('Models - Temp Ids', function() { assert(desc.enumerable, 'it is enumerable') }) + it('allows specifying the value for the tempId', function() { + const context = makeContext() + const Comic = context.Comic + const oid = new ObjectID().toHexString() + + const comic = new Comic({ __id: oid }) + + assert.equal(comic.__id, oid, 'the objectid was used') + }) + it('adds to state.tempsById', function() { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { idField: '_id', From 2c794299f7bbca29f739d1ed3f79b168a4188c25 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 21 Apr 2019 02:41:29 -0600 Subject: [PATCH 206/404] Make sure temp items are always marked with __isTemp --- src/service-module/service-module.mutations.ts | 1 + src/utils.ts | 1 - test/service-module/model-temp-ids.test.ts | 2 ++ 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 1c529af1..4ccfc8c7 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -35,6 +35,7 @@ export default function makeServiceMutations() { if (!item[tempIdField]) { var tempId = assignTempId(state, item) } + item.__isTemp = true newTempsById[tempId] = item } else { // Only add the id if it's not already in the `ids` list. diff --git a/src/utils.ts b/src/utils.ts index 2b8701d3..dc7e87a9 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -167,7 +167,6 @@ export function assignTempId(state, item) { } const newId = new ObjectID().toHexString() item[tempIdField] = newId - item.__isTemp = true return newId } diff --git a/test/service-module/model-temp-ids.test.ts b/test/service-module/model-temp-ids.test.ts index 56268130..967a1550 100644 --- a/test/service-module/model-temp-ids.test.ts +++ b/test/service-module/model-temp-ids.test.ts @@ -95,6 +95,7 @@ describe('Models - Temp Ids', function() { // Make sure we got an id. assert(txn.__id, 'the record got an __id') + assert(txn.__isTemp, 'item is a temp') // It should be non-enumerable and non-writable const desc = Object.getOwnPropertyDescriptor(txn, '__id') @@ -108,6 +109,7 @@ describe('Models - Temp Ids', function() { const comic = new Comic({ __id: oid }) + assert(comic.__isTemp, 'item is a temp') assert.equal(comic.__id, oid, 'the objectid was used') }) From 9f348ad08c41f5bcb6655910d3545ea6af157931 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 21 Apr 2019 02:41:56 -0600 Subject: [PATCH 207/404] v2.0.0-pre.23 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 39d542eb..b729e30a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.22", + "version": "2.0.0-pre.23", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From 24811cbbf4ba398f4589f8dd9d584878920e0762 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 23 Apr 2019 22:31:53 -0600 Subject: [PATCH 208/404] Add find getter to make-find-mixin --- src/make-find-mixin.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index daf1bc57..e672552a 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -51,6 +51,7 @@ export default function makeFindMixin(options) { const WATCH = `${prefix}Watch` const QUERY_WHEN = `${prefix}QueryWhen` const FIND_ACTION = `find${capitalized}` + const FIND_GETTER = `find${capitalized}InStore` const PAGINATION = `${prefix}PaginationData` const LOCAL = `${prefix}Local` const QID = `${prefix}Qid` @@ -66,18 +67,18 @@ export default function makeFindMixin(options) { }, computed: { [ITEMS]() { - return this[PARAMS] - ? this.$store.getters[`${this[SERVICE_NAME]}/find`](this[PARAMS]).data - : [] + return this[PARAMS] ? this[FIND_GETTER](this[PARAMS]).data : [] }, [ITEMS_FETCHED]() { if (this[FETCH_PARAMS]) { - return this.$store.getters[`${this[SERVICE_NAME]}/find`]( - this[FETCH_PARAMS] - ).data + return this[FIND_GETTER](this[FETCH_PARAMS]).data } else { return this[ITEMS] } + }, + [FIND_GETTER]() { + return params => + this.$store.getters[`${this[SERVICE_NAME]}/find`](params) } }, methods: { From 06321b65aa94ae9053c5b93e8bb25298637a2038 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 23 Apr 2019 22:32:42 -0600 Subject: [PATCH 209/404] v2.0.0-pre.24 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b729e30a..701cf8b9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.23", + "version": "2.0.0-pre.24", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From 1fefe75c50839d92d12e9dfbdc744b5349385cb5 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 8 May 2019 06:04:38 -0600 Subject: [PATCH 210/404] Add name to BaseModel This allows model registration to work in production, which likely has mangled class name from minification and uglification plugins. --- src/service-module/make-model.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 1104a220..f3e51c4b 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -71,6 +71,8 @@ export default function makeModel(options: FeathersVuexOptions) { public data: Record public static merge = mergeWithAccessors + // @ts-ignore + public static name = 'BaseModel' public constructor(data, options: BaseModelInstanceOptions) { // You have to pass at least an empty object to get a tempId. From a441bc93de97e0b3b423de11e25b87bcd252065d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 8 May 2019 06:06:14 -0600 Subject: [PATCH 211/404] 2.0.0-pre.25 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 00dd66dd..5916d0e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0", + "version": "2.0.0-pre.25", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 701cf8b9..39d6f6a2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.24", + "version": "2.0.0-pre.25", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "lib/", "module": "dist/", From 76be529939b1226393629a7a4350eb17c38fb201 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 8 May 2019 06:06:52 -0600 Subject: [PATCH 212/404] Add prerelease publishing script --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 39d6f6a2..11af8edb 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "prepare": "npm run compile", "prepublish": "npm run compile", "publish": "git push origin --tags && git push origin", - "release:pre": "npm publish --tag pre", + "release:pre": "npm version prerelease && npm publish --tag pre", "release:patch": "npm version patch && npm publish", "release:minor": "npm version minor && npm publish", "release:major": "npm version major && npm publish", @@ -169,4 +169,4 @@ "vuepress": "^0.14.10", "vuex": "^3.1.0" } -} +} \ No newline at end of file From 9d8da0563cda5cb11a87296d8ae1c048a8d40e60 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 8 May 2019 06:58:54 -0600 Subject: [PATCH 213/404] Fix main --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 11af8edb..16860194 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "FeathersJS, Vue, and Nuxt for the artisan developer", "version": "2.0.0-pre.25", "homepage": "https:feathers-vuex.feathers-plus.com", - "main": "lib/", + "main": "dist/", "module": "dist/", "keywords": [ "feathers", From 59739bab4d2a9812af24c232afa15b3d69da050d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 8 May 2019 06:59:07 -0600 Subject: [PATCH 214/404] 2.0.0-pre.26 --- package-lock.json | 2 +- package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5916d0e0..86f3e94d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.25", + "version": "2.0.0-pre.26", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 16860194..a0a3ee40 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.25", + "version": "2.0.0-pre.26", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", @@ -169,4 +169,4 @@ "vuepress": "^0.14.10", "vuex": "^3.1.0" } -} \ No newline at end of file +} From a8a464bbad78b0042270c2f45c5d437bf7a99976 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 8 May 2019 07:53:46 -0600 Subject: [PATCH 215/404] use BaseModel.modelName instead of BaseModel.name --- src/service-module/global-models.ts | 7 ++++--- src/service-module/make-model.ts | 7 +++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/service-module/global-models.ts b/src/service-module/global-models.ts index 7fafae9b..e8864af7 100644 --- a/src/service-module/global-models.ts +++ b/src/service-module/global-models.ts @@ -21,10 +21,11 @@ export function prepareAddModel(options: FeathersVuexOptions) { globalModels[serverAlias] = globalModels[serverAlias] || { byServicePath: {} } - if (globalModels[serverAlias][Model.name] && options.debug) { - console.error(`Overwriting Model: models[${serverAlias}][${Model.name}].`) + const name = Model.modelName || Model.name + if (globalModels[serverAlias][name] && options.debug) { + console.error(`Overwriting Model: models[${serverAlias}][${name}].`) } - globalModels[serverAlias][Model.name] = Model + globalModels[serverAlias][name] = Model globalModels[serverAlias].byServicePath[Model.servicePath] = Model } } diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index f3e51c4b..a8ff3cbf 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -71,8 +71,7 @@ export default function makeModel(options: FeathersVuexOptions) { public data: Record public static merge = mergeWithAccessors - // @ts-ignore - public static name = 'BaseModel' + public static modelName = 'BaseModel' public constructor(data, options: BaseModelInstanceOptions) { // You have to pass at least an empty object to get a tempId. @@ -300,7 +299,7 @@ export default function makeModel(options: FeathersVuexOptions) { if (!this[idField]) { const error = new Error( `Missing ${ - options.idField + options.idField } property. You must create the data before you can patch with this data` ) return Promise.reject(error) @@ -322,7 +321,7 @@ export default function makeModel(options: FeathersVuexOptions) { if (!this[idField]) { const error = new Error( `Missing ${ - options.idField + options.idField } property. You must create the data before you can update with this data` ) return Promise.reject(error) From eec9f100bd8f496cbd8de5276f2ffdadc3d5c402 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 8 May 2019 07:54:02 -0600 Subject: [PATCH 216/404] 2.0.0-pre.27 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 86f3e94d..fc9df868 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.26", + "version": "2.0.0-pre.27", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a0a3ee40..c4c341c9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.26", + "version": "2.0.0-pre.27", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 89e9f60ca598d84b661753876fa835d6b8aea7d6 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 8 May 2019 09:07:34 -0600 Subject: [PATCH 217/404] Give all Model classes a modelName static prop This syntax is necessary for uglified production builds, which will be the most common use case scenario, so all examples will now show adding a modelName prop to every Model class. --- src/service-module/notes.md | 6 ++ test/make-find-mixin.test.ts | 7 +- .../make-service-plugin.test.ts | 17 ++-- test/service-module/model-base.test.ts | 22 +++--- .../model-instance-defaults.test.ts | 30 ++++--- test/service-module/model-methods.test.ts | 28 +++---- .../model-relationships.test.ts | 40 ++++++---- test/service-module/model-serialize.test.ts | 5 +- test/service-module/model-temp-ids.test.ts | 22 ++++-- test/service-module/model-tests.test.ts | 7 +- .../service-module.actions.test.ts | 12 ++- test/service-module/service-module.test.ts | 78 ++++++++++--------- test/utils.test.ts | 13 ++-- test/vue-plugin.test.ts | 5 +- 14 files changed, 172 insertions(+), 120 deletions(-) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index cb143ccc..9fbe1795 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -48,6 +48,7 @@ const { }) class Todo extends BaseModel { + public static modelName = 'Todo' // customize the model as you see fit! } @@ -155,6 +156,7 @@ Previous versions of Feathers-Vuex only supported a single FeathersVuexModel cla const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { serverAlias: 'myApi' }) class Todo extends BaseModel { + public static modelName = 'Todo' public static exampleProp: string = 'Hello, World! (notice the comma, folks!)' } @@ -194,6 +196,7 @@ it('works with multiple, independent Feathers servers', function() { serverAlias: 'myApi' }) class Todo extends myApi.BaseModel { + public static modelName = 'Todo' public test: boolean = true } const todosPlugin = myApi.makeServicePlugin({ @@ -207,6 +210,7 @@ it('works with multiple, independent Feathers servers', function() { serverAlias: 'theirApi' }) class Task extends theirApi.BaseModel { + public static modelName = 'Task' public test: boolean = true } const tasksPlugin = theirApi.makeServicePlugin({ @@ -456,6 +460,7 @@ class Todo extends BaseModel { // Call the static merge method to do your own merging. Todo.merge(this, data) } + public static modelName = 'Todo' } ``` @@ -479,5 +484,6 @@ class Todo extends BaseModel { // Call the static merge method to do your own merging. Todo.merge(this, instanceData) } + public static modelName = 'Todo' } ``` \ No newline at end of file diff --git a/test/make-find-mixin.test.ts b/test/make-find-mixin.test.ts index 5e99f5fd..7d1ba7cd 100644 --- a/test/make-find-mixin.test.ts +++ b/test/make-find-mixin.test.ts @@ -20,6 +20,7 @@ function makeContext() { }) class FindModel extends BaseModel { + public static modelName = 'FindModel' public static test: boolean = true } @@ -31,7 +32,7 @@ Vue.use(Vuex) // @ts-ignore Vue.use(FeathersVuex) -describe('Find Mixin', function() { +describe('Find Mixin', function () { const { makeServicePlugin, FindModel } = makeContext() const serviceName = 'todos' const store = new Vuex.Store({ @@ -43,7 +44,7 @@ describe('Find Mixin', function() { ] }) - it('correctly forms mixin data', function() { + it('correctly forms mixin data', function () { const todosMixin = makeFindMixin({ service: 'todos' }) interface TodosComponent { @@ -90,7 +91,7 @@ describe('Find Mixin', function() { ) }) - it.skip('correctly forms mixin data for dynamic service', function() { + it.skip('correctly forms mixin data for dynamic service', function () { const tasksMixin = makeFindMixin({ service() { return this.serviceName diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index 1c875d1b..7fc09a53 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -14,7 +14,7 @@ import { pick as _pick, omit as _omit } from 'lodash' Vue.use(Vuex) -describe('makeServicePlugin', function() { +describe('makeServicePlugin', function () { beforeEach(() => { clearModels() }) @@ -26,7 +26,7 @@ describe('makeServicePlugin', function() { assert(clients.byAlias['this is a test'], 'got a reference to the client.') }) - it('registers the vuex module with options', function() { + it('registers the vuex module with options', function () { interface RootState { todos: {} } @@ -37,7 +37,8 @@ describe('makeServicePlugin', function() { }) const servicePath = 'todos' class Todo extends BaseModel { - public servicePath = servicePath + public static modelName = 'Todo' + public static servicePath = servicePath } const todosPlugin = makeServicePlugin({ servicePath, @@ -89,7 +90,7 @@ describe('makeServicePlugin', function() { assert.deepEqual(_omit(received), _omit(expected), 'defaults in place.') }) - it('sets up Model.store && service.FeathersVuexModel', function() { + it('sets up Model.store && service.FeathersVuexModel', function () { const serverAlias = 'default' const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { serverAlias @@ -98,7 +99,8 @@ describe('makeServicePlugin', function() { const servicePath = 'todos' const service = feathers.service(servicePath) class Todo extends BaseModel { - public servicePath = servicePath + public static modelName = 'Todo' + public static servicePath = servicePath } const todosPlugin = makeServicePlugin({ servicePath, Model: Todo, service }) const store = new Vuex.Store({ plugins: [todosPlugin] }) @@ -108,7 +110,7 @@ describe('makeServicePlugin', function() { assert.equal(service.FeathersVuexModel, Todo, 'Model accessible on service') }) - it('allows accessing other models', function() { + it('allows accessing other models', function () { const serverAlias = 'default' const { makeServicePlugin, BaseModel, models } = feathersVuex(feathers, { idField: '_id', @@ -117,7 +119,8 @@ describe('makeServicePlugin', function() { const servicePath = 'todos' class Todo extends BaseModel { - public servicePath = servicePath + public static modelName = 'Todo' + public static servicePath = servicePath } const todosPlugin = makeServicePlugin({ servicePath, diff --git a/test/service-module/model-base.test.ts b/test/service-module/model-base.test.ts index 82c7d8ef..0b6cec1a 100644 --- a/test/service-module/model-base.test.ts +++ b/test/service-module/model-base.test.ts @@ -17,17 +17,17 @@ Vue.use(Vuex) process.setMaxListeners(100) -describe.skip('Model - Standalone', function() { - it.skip('allows using a model without a service', function() {}) - it.skip('rename serverAlias to just `alias` or maybe `groupName`', function() {}) +describe.skip('Model - Standalone', function () { + it.skip('allows using a model without a service', function () { }) + it.skip('rename serverAlias to just `alias` or maybe `groupName`', function () { }) }) -describe('makeModel / BaseModel', function() { +describe('makeModel / BaseModel', function () { before(() => { clearModels() }) - it('properly sets up the BaseModel', function() { + it('properly sets up the BaseModel', function () { const alias = 'default' const { BaseModel } = feathersVuex(feathers, { serverAlias: alias }) const { @@ -86,7 +86,7 @@ describe('makeModel / BaseModel', function() { }) }) - it('allows customization through the FeathersVuexOptions', function() { + it('allows customization through the FeathersVuexOptions', function () { const { BaseModel } = feathersVuex(feathers, { serverAlias: 'myApi', idField: '_id', @@ -99,7 +99,7 @@ describe('makeModel / BaseModel', function() { assert(serverAlias === 'myApi', 'serverAlias was set') }) - it('receives store & other props after Vuex plugin is registered', function() { + it('receives store & other props after Vuex plugin is registered', function () { const { BaseModel, makeServicePlugin } = feathersVuex(feathers, { serverAlias: 'myApi' }) @@ -118,7 +118,7 @@ describe('makeModel / BaseModel', function() { assert.equal(servicePath, 'todos', 'servicePath is in place') }) - it('allows access to other models after Vuex plugins are registered', function() { + it('allows access to other models after Vuex plugins are registered', function () { const serverAlias = 'default' const { makeServicePlugin, BaseModel, models } = feathersVuex(feathers, { idField: '_id', @@ -127,6 +127,7 @@ describe('makeModel / BaseModel', function() { // Create a Todo Model & Plugin class Todo extends BaseModel { + public static modelName = 'Todo' public test: boolean = true } const todosPlugin = makeServicePlugin({ @@ -137,6 +138,7 @@ describe('makeModel / BaseModel', function() { // Create a Task Model & Plugin class Task extends BaseModel { + public static modelName = 'Task' public test: boolean = true } const tasksPlugin = makeServicePlugin({ @@ -155,7 +157,7 @@ describe('makeModel / BaseModel', function() { assert.equal(Task.models, models, 'models available at Model.models') }) - it('works with multiple, independent Feathers servers', function() { + it('works with multiple, independent Feathers servers', function () { // Create a Todo Model & Plugin on myApi const feathersMyApi = makeFeathersRestClient('https://api.my-api.com') const myApi = feathersVuex(feathersMyApi, { @@ -163,6 +165,7 @@ describe('makeModel / BaseModel', function() { serverAlias: 'myApi' }) class Todo extends myApi.BaseModel { + public static modelName = 'Todo' public test: boolean = true } const todosPlugin = myApi.makeServicePlugin({ @@ -176,6 +179,7 @@ describe('makeModel / BaseModel', function() { serverAlias: 'theirApi' }) class Task extends theirApi.BaseModel { + public static modelName = 'Task' public test: boolean = true } const tasksPlugin = theirApi.makeServicePlugin({ diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts index dd280614..a3dfbaa0 100644 --- a/test/service-module/model-instance-defaults.test.ts +++ b/test/service-module/model-instance-defaults.test.ts @@ -36,6 +36,7 @@ function makeContext() { }) class Todo extends BaseModel { + public static modelName = 'Todo' public id public description: string @@ -44,24 +45,31 @@ function makeContext() { } } class Person extends BaseModel { + public static modelName = 'Person' public static test: boolean = true } class Item extends BaseModel { + public static modelName = 'Item' public static test: boolean = true } class Task extends BaseModel { + public static modelName = 'Task' public static test: boolean = true } class Car extends BaseModel { + public static modelName = 'Car' public static test: boolean = true } class Group extends BaseModel { + public static modelName = 'Group' public static test: boolean = true } class Test extends BaseModel { + public static modelName = 'Test' public static test: boolean = true } class Thing extends BaseModel { + public static modelName = 'Thing' public static test: boolean = true } @@ -102,12 +110,12 @@ function makeContext() { } } -describe('Models - Default Values', function() { +describe('Models - Default Values', function () { beforeEach(() => { clearModels() }) - it('models default to an empty object when there is no BaseModel.store', function() { + it('models default to an empty object when there is no BaseModel.store', function () { const { BaseModel } = makeContext() // Since we're not using this NakedTodo model in a service plugin, it doesn't get @@ -120,7 +128,7 @@ describe('Models - Default Values', function() { assert.deepEqual(todo.toJSON(), {}, 'default model is an empty object') }) - it('models have tempIds when there is a store', function() { + it('models have tempIds when there is a store', function () { const { Todo } = makeContext() const todo = new Todo() @@ -133,7 +141,7 @@ describe('Models - Default Values', function() { ) }) - it('adds new instances containing an id to the store', function() { + it('adds new instances containing an id to the store', function () { const { Todo } = makeContext() const todo = new Todo({ @@ -146,7 +154,7 @@ describe('Models - Default Values', function() { assert.deepEqual(todoInStore, todo, 'task was added to the store') }) - it('stores clones in Model.copiesById by default', function() { + it('stores clones in Model.copiesById by default', function () { const { Todo } = makeContext() const todo = new Todo({ id: 1, description: 'This is the original' }) @@ -169,7 +177,7 @@ describe('Models - Default Values', function() { ) }) - it('allows instance defaults, including getters and setters', function() { + it('allows instance defaults, including getters and setters', function () { const { BaseModel } = feathersVuex(feathersClient, { serverAlias: 'instance-defaults' }) @@ -205,7 +213,7 @@ describe('Models - Default Values', function() { assert.equal(car.combined, '1900 Tesla Roadster', 'setters work, too!') }) - it('allows overriding default values in the constructor', function() { + it('allows overriding default values in the constructor', function () { const { BaseModel } = feathersVuex(feathersClient, { serverAlias: 'instance-defaults' }) @@ -229,7 +237,7 @@ describe('Models - Default Values', function() { assert.equal(car.make, 'Porsche', 'default make set') }) - it(`uses the class defaults if you don't override them in the constructor`, function() { + it(`uses the class defaults if you don't override them in the constructor`, function () { const { BaseModel } = feathersVuex(feathersClient, { serverAlias: 'instance-defaults' }) @@ -273,7 +281,7 @@ describe('Models - Default Values', function() { assert.deepEqual(person1.location.coordinates, [0, 0], 'defaults won') }) - it('does not share nested objects between instances when you override class defaults in the constructor', function() { + it('does not share nested objects between instances when you override class defaults in the constructor', function () { const { BaseModel } = feathersVuex(feathersClient, { serverAlias: 'instance-defaults' }) @@ -309,7 +317,7 @@ describe('Models - Default Values', function() { assert(!areSame, 'the locations are different objects') }) - it('allows passing instanceDefaults in the service plugin options', function() { + it('allows passing instanceDefaults in the service plugin options', function () { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { serverAlias: 'instance-defaults' }) @@ -378,7 +386,7 @@ describe('Models - Default Values', function() { assert.equal(person2.lastName, 'Me', 'lastName was set') }) - it('instanceDefault accessors stay intact with clone and commit', function() { + it('instanceDefault accessors stay intact with clone and commit', function () { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { serverAlias: 'instance-defaults' }) diff --git a/test/service-module/model-methods.test.ts b/test/service-module/model-methods.test.ts index 3d282b85..3a9295bb 100644 --- a/test/service-module/model-methods.test.ts +++ b/test/service-module/model-methods.test.ts @@ -32,13 +32,15 @@ function makeContext() { serverAlias: 'model-methods' }) class Task extends BaseModel { - public servicePath: 'tasks' + public static modelName = 'Task' + public static servicePath: 'tasks' public constructor(data?, options?) { super(data, options) } } class Todo extends BaseModel { - public servicePath: 'todos' + public static modelName = 'Todo' + public static servicePath: 'todos' public constructor(data?, options?) { super(data, options) } @@ -65,36 +67,36 @@ function makeContext() { } } -describe('Models - Methods', function() { +describe('Models - Methods', function () { beforeEach(() => { clearModels() }) - it('Model.find', function() { + it('Model.find', function () { const { Task } = makeContext() assert(typeof Task.find === 'function') }) - it('Model.findInStore', function() { + it('Model.findInStore', function () { const { Task } = makeContext() assert(typeof Task.findInStore === 'function') }) - it('Model.get', function() { + it('Model.get', function () { const { Task } = makeContext() assert(typeof Task.get === 'function') }) - it('Model.getFromStore', function() { + it('Model.getFromStore', function () { const { Task } = makeContext() assert(typeof Task.getFromStore === 'function') }) - it('instance.save calls create with correct arguments', function() { + it('instance.save calls create with correct arguments', function () { const { Task } = makeContext() const module = new Task({ test: true }) @@ -111,7 +113,7 @@ describe('Models - Methods', function() { module.save() }) - it('instance.save passes params to create', function() { + it('instance.save passes params to create', function () { const { Task } = makeContext() const task = new Task({ test: true }) let called = false @@ -128,7 +130,7 @@ describe('Models - Methods', function() { assert(called, 'create should have been called') }) - it('instance.save passes params to patch', function() { + it('instance.save passes params to patch', function () { const { Todo } = makeContext() const todo = new Todo({ id: 1, test: true }) let called = false @@ -145,7 +147,7 @@ describe('Models - Methods', function() { assert(called, 'patch should have been called') }) - it('instance.save passes params to update', function() { + it('instance.save passes params to update', function () { const { Task } = makeContext() Task.preferUpdate = true @@ -164,7 +166,7 @@ describe('Models - Methods', function() { assert(called, 'update should have been called') }) - it('instance.remove works with temp records', function() { + it('instance.remove works with temp records', function () { const { Task, store } = makeContext() const task = new Task({ test: true }) const tempId = task.__id @@ -175,7 +177,7 @@ describe('Models - Methods', function() { assert(!store.state.tasks.tempsById[tempId], 'temp was removed') }) - it('instance.toJSON', function() { + it('instance.toJSON', function () { const { Task } = makeContext() const task = new Task({ id: 1, test: true }) diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index 35daf201..73497121 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -10,18 +10,19 @@ import { clearModels } from '../../src/service-module/global-models' import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' import Vuex from 'vuex' -describe('Models - `setupInstance` & Relatioships', function() { - beforeEach(function() { +describe('Models - `setupInstance` & Relatioships', function () { + beforeEach(function () { clearModels() }) - it('initializes instance with return value from setupInstance', function() { + it('initializes instance with return value from setupInstance', function () { let calledSetupInstance = false const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { serverAlias: 'myApi' }) class Todo extends BaseModel { + public static modelName = 'Todo' public id? public description: string @@ -58,11 +59,12 @@ describe('Models - `setupInstance` & Relatioships', function() { assert(todo.extraProp, 'got the extraProp') }) - it('allows setting up relationships between models and other constructors', function() { + it('allows setting up relationships between models and other constructors', function () { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { serverAlias: 'myApi' }) class Todo extends BaseModel { + public static modelName = 'Todo' public id? public description: string public user: User @@ -72,6 +74,7 @@ describe('Models - `setupInstance` & Relatioships', function() { } } class User extends BaseModel { + public static modelName = 'User' public _id: string public firstName: string public email: string @@ -137,6 +140,7 @@ function makeContext() { serverAlias: 'myApi' }) class Task extends BaseModel { + public static modelName = 'Task' public static instanceDefaults() { return { id: null, @@ -149,6 +153,7 @@ function makeContext() { } } class Todo extends BaseModel { + public static modelName = 'Todo' public static instanceDefaults(data) { const priority = data.priority || 'normal' const defaultsByPriority = { @@ -178,6 +183,7 @@ function makeContext() { } } class Item extends BaseModel { + public static modelName = 'Item' public get todos() { return BaseModel.models.Todo.findInStore({ query: {} }).data } @@ -230,12 +236,12 @@ function makeContext() { } } -describe('Models - Relationships', function() { - beforeEach(function() { +describe('Models - Relationships', function () { + beforeEach(function () { clearModels() }) - it('can have different instanceDefaults based on new instance data', function() { + it('can have different instanceDefaults based on new instance data', function () { const { Todo } = makeContext() const normalTodo = new Todo({ description: 'Normal' @@ -255,7 +261,7 @@ describe('Models - Relationships', function() { ) }) - it('adds model instances containing an id to the store', function() { + it('adds model instances containing an id to the store', function () { const { Todo, Task } = makeContext() const todo = new Todo({ @@ -273,7 +279,7 @@ describe('Models - Relationships', function() { ) }) - it('works with multiple keys that match Model names', function() { + it('works with multiple keys that match Model names', function () { const { Todo, Task, Item } = makeContext() const todo = new Todo({ @@ -300,7 +306,7 @@ describe('Models - Relationships', function() { ) }) - it('handles nested relationships', function() { + it('handles nested relationships', function () { const { Todo } = makeContext() const todo = new Todo({ @@ -324,7 +330,7 @@ describe('Models - Relationships', function() { ) }) - it('handles circular nested relationships', function() { + it('handles circular nested relationships', function () { const { Todo, Item } = makeContext() const todo = new Todo({ @@ -350,7 +356,7 @@ describe('Models - Relationships', function() { assert(todo.item.todo, 'todo still nested in itself') }) - it('updates related data', function() { + it('updates related data', function () { const { Todo, Item, store } = makeContext() const module = new Todo({ @@ -385,7 +391,7 @@ describe('Models - Relationships', function() { assert.equal(storedItem.test, false, 'item.test should be false') }) - it(`allows creating more than once relational instance`, function() { + it(`allows creating more than once relational instance`, function () { const { Todo, Item } = makeContext() const todo1 = new Todo({ @@ -426,7 +432,7 @@ describe('Models - Relationships', function() { assert.equal(storedItem.test, true, 'item.test should be true') }) - it(`handles arrays of related data`, function() { + it(`handles arrays of related data`, function () { const { Todo, Item } = makeContext() const todo1 = new Todo({ @@ -476,7 +482,7 @@ describe('Models - Relationships', function() { assert(storedItem4, 'should have item 4') }) - it('preserves relationships on clone', function() { + it('preserves relationships on clone', function () { const { Todo, Task } = makeContext() const todo = new Todo({ @@ -490,7 +496,7 @@ describe('Models - Relationships', function() { assert(clone.task instanceof Task, 'nested task is a Task') }) - it('preserves relationships on commit', function() { + it('preserves relationships on commit', function () { const { Todo, Task } = makeContext() const todo = new Todo({ @@ -506,7 +512,7 @@ describe('Models - Relationships', function() { assert(original.task instanceof Task, 'nested task is a Task') }) - it('preserves relationship with nested data clone and commit', function() { + it('preserves relationship with nested data clone and commit', function () { const { Todo } = makeContext() const todo = new Todo({ diff --git a/test/service-module/model-serialize.test.ts b/test/service-module/model-serialize.test.ts index d7fe91bb..9dd1d6e5 100644 --- a/test/service-module/model-serialize.test.ts +++ b/test/service-module/model-serialize.test.ts @@ -9,16 +9,17 @@ import { feathersRestClient as feathersClient } from '../fixtures/feathers-clien import { clearModels } from '../../src/service-module/global-models' import { omit as _omit } from 'lodash' -describe('Models - Serialize', function() { +describe('Models - Serialize', function () { beforeEach(() => { clearModels() }) - it('allows customizing toJSON', function() { + it('allows customizing toJSON', function () { const { BaseModel } = feathersVuex(feathersClient, { serverAlias: 'myApi' }) class Task extends BaseModel { + public static modelName = 'Task' public static instanceDefaults() { return { id: null, diff --git a/test/service-module/model-temp-ids.test.ts b/test/service-module/model-temp-ids.test.ts index 967a1550..3ece1239 100644 --- a/test/service-module/model-temp-ids.test.ts +++ b/test/service-module/model-temp-ids.test.ts @@ -41,6 +41,7 @@ function makeContext() { serverAlias: 'default' }) class Comic extends BaseModel { + public static modelName = 'Comic' public static test: boolean = true public constructor(data, options?) { @@ -64,17 +65,18 @@ function makeContext() { } } -describe('Models - Temp Ids', function() { +describe('Models - Temp Ids', function () { beforeEach(() => { clearModels() }) - it('adds tempIds for items without an [idField]', function() { + it('adds tempIds for items without an [idField]', function () { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { idField: '_id', serverAlias: 'temp-ids' }) class Transaction extends BaseModel { + public static modelName = 'Transaction' public constructor(data?, options?) { super(data, options) } @@ -102,7 +104,7 @@ describe('Models - Temp Ids', function() { assert(desc.enumerable, 'it is enumerable') }) - it('allows specifying the value for the tempId', function() { + it('allows specifying the value for the tempId', function () { const context = makeContext() const Comic = context.Comic const oid = new ObjectID().toHexString() @@ -113,12 +115,13 @@ describe('Models - Temp Ids', function() { assert.equal(comic.__id, oid, 'the objectid was used') }) - it('adds to state.tempsById', function() { + it('adds to state.tempsById', function () { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { idField: '_id', serverAlias: 'temp-ids' }) class Transaction extends BaseModel { + public static modelName = 'Transaction' public constructor(data?, options?) { super(data, options) } @@ -143,12 +146,13 @@ describe('Models - Temp Ids', function() { assert(store.state.transactions.tempsById[txn.__id], 'it is in the store') }) - it('clones into Model.copiesById', function() { + it('clones into Model.copiesById', function () { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { idField: '_id', serverAlias: 'temp-ids' }) class Transaction extends BaseModel { + public static modelName = 'Transaction' public constructor(data?, options?) { super(data, options) } @@ -173,12 +177,13 @@ describe('Models - Temp Ids', function() { assert(Transaction.copiesById[txn.__id], 'it is in the copiesById') }) - it('commits into store.tempsById', function() { + it('commits into store.tempsById', function () { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { idField: '_id', serverAlias: 'temp-ids' }) class Transaction extends BaseModel { + public static modelName = 'Transaction' public constructor(data?, options?) { super(data, options) } @@ -207,11 +212,12 @@ describe('Models - Temp Ids', function() { assert.equal(originalTemp.amount, 11.99, 'original was updated') }) - it('can reset a temp clone', function() { + it('can reset a temp clone', function () { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { serverAlias: 'temp-ids' }) class Transaction extends BaseModel { + public static modelName = 'Transaction' public constructor(data?, options?) { super(data, options) } @@ -238,7 +244,7 @@ describe('Models - Temp Ids', function() { assert.equal(clone.amount, 1.99, 'clone was reset') }) - it('returns the keyedById record after create, not the tempsById record', function(done) { + it('returns the keyedById record after create, not the tempsById record', function (done) { const { Comic, store } = makeContext() const comic = new Comic({ diff --git a/test/service-module/model-tests.test.ts b/test/service-module/model-tests.test.ts index 717fb850..d11e8287 100644 --- a/test/service-module/model-tests.test.ts +++ b/test/service-module/model-tests.test.ts @@ -24,8 +24,9 @@ describe('TypeScript Class Inheritance', () => { } } class Todo extends BaseModel { - public description: string + public static modelName = 'Todo' + public description: string public static instanceDefaults = (data, options) => ({ description: 'default description' }) @@ -69,6 +70,7 @@ describe('TypeScript Class Inheritance', () => { const { servicePath } = options class ServiceModel extends BaseModel { + public static modelName = 'ServiceModel' public constructor(data, options: ModelOptions = { servicePath: '' }) { options.servicePath = servicePath super(data, options) @@ -78,6 +80,7 @@ describe('TypeScript Class Inheritance', () => { } class Todo extends makeServiceModel({ servicePath: 'todos' }) { + public static modelName = 'Todo' public description: string public static instanceDefaults = (data, options) => ({ @@ -116,6 +119,7 @@ describe('TypeScript Class Inheritance', () => { } class Todo extends BaseModel { + public static modelName = 'Todo' public static namespace: string = 'todos' public static servicePath: string = 'v1/todos' @@ -146,6 +150,7 @@ describe('TypeScript Class Inheritance', () => { } class Todo extends BaseModel { + public static modelName = 'Todo' public serialize() { return Object.assign({}, this, { serialized: true }) } diff --git a/test/service-module/service-module.actions.test.ts b/test/service-module/service-module.actions.test.ts index dd8082c2..b979891e 100644 --- a/test/service-module/service-module.actions.test.ts +++ b/test/service-module/service-module.actions.test.ts @@ -71,22 +71,26 @@ function makeContext() { remove() { return Promise.reject(new Error('remove error')) }, - setup() {} + setup() { } }) const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { serverAlias: 'default' }) class Todo extends BaseModel { + public static modelName = 'Todo' public static test: boolean = true } class Task extends BaseModel { + public static modelName = 'Task' public static test: boolean = true } class NoId extends BaseModel { + public static modelName = 'NoId' public static test: boolean = true } class Broken extends BaseModel { + public static modelName = 'Broken' public static test: boolean = true } return { @@ -505,7 +509,7 @@ describe('Service Module - Actions', () => { service: feathersClient.service('no-ids'), idField: '_id', actions: { - afterFind({}, response) { + afterFind({ }, response) { assert( response.data.length === 10, 'records were still returned' @@ -557,7 +561,7 @@ describe('Service Module - Actions', () => { }) }) - describe('Get', function() { + describe('Get', function () { it('updates store list state on service success', done => { const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ @@ -755,7 +759,7 @@ describe('Service Module - Actions', () => { }) }) - describe('Create', function() { + describe('Create', function () { it('updates store list state on service success', done => { const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 2c8dc5fa..d1a20df6 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -64,6 +64,7 @@ function makeContext() { public static test: boolean = true } class Task extends BaseModel { + public static modelName = 'Task' public static test: boolean = true } class Car extends BaseModel { @@ -138,10 +139,12 @@ function makeAutoRemoveContext() { serverAlias: 'autoRemove' }) class Todo extends BaseModel { + public static modelName = 'Todo' public static servicePath: string = 'todos' public static test: boolean = true } class Task extends BaseModel { + public static modelName = 'Task' public static servicePath: string = 'tasks' public static test: boolean = true } @@ -156,12 +159,12 @@ function makeAutoRemoveContext() { } } -describe('Service Module', function() { +describe('Service Module', function () { beforeEach(() => { clearModels() }) - it('registers a vuex plugin and Model for the service', function() { + it('registers a vuex plugin and Model for the service', function () { const { makeServicePlugin, ServiceTodo, BaseModel } = makeContext() const serviceName = 'service-todos' const feathersService = feathersClient.service(serviceName) @@ -193,8 +196,8 @@ describe('Service Module', function() { assert(store.state[serviceName]) }) - describe('Models', function() { - beforeEach(function() { + describe('Models', function () { + beforeEach(function () { const { makeServicePlugin, ServiceTodo } = makeContext() const store = new Vuex.Store({ plugins: [ @@ -228,7 +231,7 @@ describe('Service Module', function() { this.ServiceTodo = ServiceTodo }) - it('allows creating model clones', function() { + it('allows creating model clones', function () { const { ServiceTodo } = this const serviceTodoClone = this.serviceTodo.clone() @@ -242,7 +245,7 @@ describe('Service Module', function() { ) }) - it('allows modifying clones without affecting the original', function() { + it('allows modifying clones without affecting the original', function () { const { serviceTodo } = this const serviceTodoClone = serviceTodo.clone() @@ -254,7 +257,7 @@ describe('Service Module', function() { ) }) - it('allows commiting changes back to the original in the store', function() { + it('allows commiting changes back to the original in the store', function () { const { serviceTodo } = this const serviceTodoClone = serviceTodo.clone() @@ -267,7 +270,7 @@ describe('Service Module', function() { ) }) - it('performs a shallow merge when commiting back to the original record', function() { + it('performs a shallow merge when commiting back to the original record', function () { const { serviceTodo, owners } = this const serviceTodoClone = serviceTodo.clone() @@ -290,7 +293,7 @@ describe('Service Module', function() { ) }) - it(`no longer changes original if you don't use the return value of commit()`, function() { + it(`no longer changes original if you don't use the return value of commit()`, function () { const { serviceTodo, owners } = this const serviceTodoClone = serviceTodo.clone() @@ -310,7 +313,7 @@ describe('Service Module', function() { ) }) - it(`changes the original if you modify return value of a commit`, function() { + it(`changes the original if you modify return value of a commit`, function () { const { serviceTodo, owners } = this let serviceTodoClone = serviceTodo.clone() @@ -330,7 +333,7 @@ describe('Service Module', function() { ) }) - it('allows reseting copy changes back to match the original', function() { + it('allows reseting copy changes back to match the original', function () { const { serviceTodo } = this let serviceTodoClone = serviceTodo.clone() @@ -347,7 +350,7 @@ describe('Service Module', function() { ) }) - it('adds additional properties to model instances when more data arrives for the same id', function() { + it('adds additional properties to model instances when more data arrives for the same id', function () { const { serviceTodo, owners } = this const newData = { id: 1, @@ -366,7 +369,7 @@ describe('Service Module', function() { ) }) - it('ignores when new data with matching id has fewer props than current record', function() { + it('ignores when new data with matching id has fewer props than current record', function () { const { serviceTodo, owners } = this const newData = { id: 1, @@ -385,7 +388,7 @@ describe('Service Module', function() { ) }) - it('updates the new record when non-null, non-undefined values do not match', function() { + it('updates the new record when non-null, non-undefined values do not match', function () { const { serviceTodo, owners } = this const newData = { id: 1, @@ -408,9 +411,10 @@ describe('Service Module', function() { }) describe('Setting Up', () => { - it('service stores have global defaults', function() { + it('service stores have global defaults', function () { const { makeServicePlugin, BaseModel, Task } = makeContext() class Todo extends BaseModel { + public static modelName = 'Todo' public static test: boolean = true } const store = new Vuex.Store({ @@ -432,7 +436,7 @@ describe('Service Module', function() { assert(state.todos, 'uses `short` nameStyle by default') }) - it('can customize the idField for each service', function() { + it('can customize the idField for each service', function () { const { makeServicePlugin, Test, Person } = makeContext() const store = new Vuex.Store({ plugins: [ @@ -460,7 +464,7 @@ describe('Service Module', function() { ) }) - it('allows enabling autoRemove', function() { + it('allows enabling autoRemove', function () { const { makeServicePlugin, Test } = makeContext() const autoRemove = true const store = new Vuex.Store({ @@ -479,7 +483,7 @@ describe('Service Module', function() { ) }) - it('can switch to path name as namespace', function() { + it('can switch to path name as namespace', function () { const { makeServicePlugin, Test } = makeContext() const plugin = makeServicePlugin({ Model: Test, @@ -497,7 +501,7 @@ describe('Service Module', function() { ) }) - it('can explicitly provide a namespace', function() { + it('can explicitly provide a namespace', function () { const { makeServicePlugin, Test } = makeContext() const namespace = 'blah' const store = new Vuex.Store({ @@ -512,7 +516,7 @@ describe('Service Module', function() { assert(store.state.blah, 'the namespace option was used as the namespace') }) - it('prioritizes the explicit namespace', function() { + it('prioritizes the explicit namespace', function () { const { makeServicePlugin, Test } = makeContext() const namespace = 'blah' const nameStyle = 'path' @@ -531,7 +535,7 @@ describe('Service Module', function() { }) describe('Basics', () => { - it('populates default store', function() { + it('populates default store', function () { const { makeServicePlugin, feathers, @@ -592,7 +596,7 @@ describe('Service Module', function() { ) }) - it('throws an error if no service is provided', function() { + it('throws an error if no service is provided', function () { const { makeServicePlugin } = makeContext() try { new Vuex.Store({ @@ -608,12 +612,12 @@ describe('Service Module', function() { } }) - describe('Auto-Remove Items', function() { - beforeEach(function() { + describe('Auto-Remove Items', function () { + beforeEach(function () { clearModels() }) - it(`removes missing items when pagination is off`, function(done) { + it(`removes missing items when pagination is off`, function (done) { const { makeServicePlugin, Todo, @@ -663,7 +667,7 @@ describe('Service Module', function() { }) }) - it(`does not remove missing items when pagination is on`, function(done) { + it(`does not remove missing items when pagination is on`, function (done) { const { makeServicePlugin, Task, @@ -714,7 +718,7 @@ describe('Service Module', function() { }) }) - it(`does not remove missing items when autoRemove is off`, function(done) { + it(`does not remove missing items when autoRemove is off`, function (done) { const { makeServicePlugin, Todo, @@ -765,8 +769,8 @@ describe('Service Module', function() { }) }) - describe('Customizing Service Stores', function() { - it('allows adding custom state', function() { + describe('Customizing Service Stores', function () { + it('allows adding custom state', function () { const { makeServicePlugin, ServiceTodo } = makeContext() const customState = { @@ -792,7 +796,7 @@ describe('Service Module', function() { ) }) - it('allows custom mutations', function() { + it('allows custom mutations', function () { const { makeServicePlugin, ServiceTodo } = makeContext() const state = { test: true } const customMutations = { @@ -818,7 +822,7 @@ describe('Service Module', function() { ) }) - it('allows custom getters', function() { + it('allows custom getters', function () { const { makeServicePlugin, ServiceTodo } = makeContext() const customGetters = { oneTwoThree(state) { @@ -841,7 +845,7 @@ describe('Service Module', function() { ) }) - it('allows adding custom actions', function() { + it('allows adding custom actions', function () { const { makeServicePlugin, ServiceTodo } = makeContext() const config = { state: { @@ -876,12 +880,12 @@ describe('Service Module', function() { }) }) - describe.skip('Updates the Store on Events', function() { + describe.skip('Updates the Store on Events', function () { const fv = feathersVuex(feathersSocketioClient, { serverAlias: 'updates-store-on-events' }) - it('created', function(done) { + it('created', function (done) { const { Thing } = this const store = new Vuex.Store({ plugins: [ @@ -903,7 +907,7 @@ describe('Service Module', function() { feathersSocketioClient.service('things').create({ test: true }) }) - it('patched', function(done) { + it('patched', function (done) { const { Thing } = this const store = new Vuex.Store({ plugins: [ @@ -927,7 +931,7 @@ describe('Service Module', function() { feathersSocketioClient.service('things').patch(1, { test: true }) }) - it('updated', function(done) { + it('updated', function (done) { const { Thing } = this const store = new Vuex.Store({ plugins: [ @@ -951,7 +955,7 @@ describe('Service Module', function() { feathersSocketioClient.service('things').update(1, { test: true }) }) - it('removed', function(done) { + it('removed', function (done) { const { Thing } = this const store = new Vuex.Store({ plugins: [ diff --git a/test/utils.test.ts b/test/utils.test.ts index 6983b7ad..adf99f31 100644 --- a/test/utils.test.ts +++ b/test/utils.test.ts @@ -17,14 +17,15 @@ interface RootState { auth: AuthState } -describe('Utils', function() { - before(function() { +describe('Utils', function () { + before(function () { const { makeServicePlugin, makeAuthPlugin, BaseModel } = feathersVuex( feathersClient, { serverAlias: 'utils' } ) class User extends BaseModel { + public static modelName = 'User' public static test: boolean = true } @@ -35,7 +36,7 @@ describe('Utils', function() { User }) }) - it('properly populates auth', function() { + it('properly populates auth', function () { const store = new Vuex.Store({ plugins: [ this.makeServicePlugin({ @@ -73,8 +74,8 @@ describe('Utils', function() { }) }) - describe('Inflections', function() { - it('properly inflects the service prefix', function() { + describe('Inflections', function () { + it('properly inflects the service prefix', function () { const decisionTable = [ ['todos', 'todos'], ['TODOS', 'tODOS'], @@ -93,7 +94,7 @@ describe('Utils', function() { }) }) - it('properly inflects the service capitalization', function() { + it('properly inflects the service capitalization', function () { const decisionTable = [ ['todos', 'Todos'], ['TODOS', 'TODOS'], diff --git a/test/vue-plugin.test.ts b/test/vue-plugin.test.ts index 0824355f..9b27261a 100644 --- a/test/vue-plugin.test.ts +++ b/test/vue-plugin.test.ts @@ -23,6 +23,7 @@ function makeContext() { serverAlias: 'make-find-mixin' }) class FindModel extends BaseModel { + public static modelName = 'FindModel' public static test: boolean = true } @@ -40,8 +41,8 @@ function makeContext() { } } -describe('Vue Plugin', function() { - it('Adds the `$FeathersVuex` object to components', function() { +describe('Vue Plugin', function () { + it('Adds the `$FeathersVuex` object to components', function () { const { store } = makeContext() const vm = new Vue({ name: 'todos-component', From 048a52a5cff4ed1f458c5d9605dab60b0789ca47 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 13 May 2019 06:29:10 -0600 Subject: [PATCH 218/404] Update vscode settings --- .vscode/settings.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4a1ddbe4..e46adb92 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,5 +8,10 @@ "lib/**": true, "**/node_modules": true, "**/bower_components": true + }, + "workbench.colorCustomizations": { + "activityBar.background": "#2B3011", + "titleBar.activeBackground": "#3C4418", + "titleBar.activeForeground": "#FAFBF4" } } \ No newline at end of file From 0b365f7064782a23e0e86e835fa342ce0477e383 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 5 Jun 2019 14:04:32 -0700 Subject: [PATCH 219/404] Make modelName required --- src/service-module/make-model.ts | 2 +- src/service-module/make-service-plugin.ts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index a8ff3cbf..317fb7aa 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -71,7 +71,7 @@ export default function makeModel(options: FeathersVuexOptions) { public data: Record public static merge = mergeWithAccessors - public static modelName = 'BaseModel' + public static modelName public constructor(data, options: BaseModelInstanceOptions) { // You have to pass at least an empty object to get a tempId. diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index 8d4cbad2..5db77b60 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -84,6 +84,9 @@ export default function prepareMakeServicePlugin( setupInstance, preferUpdate }) + if (!Model.modelName) { + throw new Error('The modelName property is required for Feathers-Vuex Models') + } addModel(Model) // (3^) Setup real-time events From 8b4ba70353ab83a00f4e54e64fd7446a0d0df90e Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 5 Jun 2019 14:05:10 -0700 Subject: [PATCH 220/404] Make debugging easier. --- src/make-find-mixin.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index e672552a..e0b8136d 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -77,8 +77,10 @@ export default function makeFindMixin(options) { } }, [FIND_GETTER]() { - return params => - this.$store.getters[`${this[SERVICE_NAME]}/find`](params) + return params => { + const serviceName = this[SERVICE_NAME] + return this.$store.getters[`${serviceName}/find`](params) + } } }, methods: { @@ -106,9 +108,9 @@ export default function makeFindMixin(options) { if (qid) { paramsToUse.qid = qid } - + const serviceName = this[SERVICE_NAME] return this.$store - .dispatch(`${this[SERVICE_NAME]}/find`, paramsToUse) + .dispatch(`${serviceName}/find`, paramsToUse) .then(response => { this[IS_FIND_PENDING] = false return response @@ -160,7 +162,8 @@ export default function makeFindMixin(options) { if (qid) { mixin.computed[PAGINATION] = function() { - return this.$store.state[this[SERVICE_NAME]].pagination[qid] + const serviceName = this[SERVICE_NAME] + return this.$store.state[serviceName].pagination[qid] } } From 992201551bf3cbac8a9881bd8c1c13d17ab3434e Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 5 Jun 2019 14:12:20 -0700 Subject: [PATCH 221/404] Update tests now that modelName is required --- src/service-module/notes.md | 3 +++ test/service-module/misconfigured-client.test.ts | 1 + test/service-module/model-base.test.ts | 1 + test/service-module/model-instance-defaults.test.ts | 5 +++++ test/service-module/service-module.test.ts | 11 +++++++++++ 5 files changed, 21 insertions(+) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 9fbe1795..9347ffad 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -406,6 +406,7 @@ const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { }) const Todo extends BaseModel { + public static modelName = 'Todo' // The `setupInstance` method must be a static method static setupInstance(data, { models, store }) { const { User } = models.myServerAlias @@ -451,6 +452,7 @@ const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { }) class Todo extends BaseModel { + public static modelName = 'Todo' public constructor(data, options?) { options.merge = false // Prevent the internal merge from occurring. super(data, options) @@ -468,6 +470,7 @@ It's important to note that setting `merge: false` in the options will disable t ```ts class Todo extends BaseModel { + public static modelName = 'Todo' public constructor(data, options?) { options.merge = false // Prevent the internal merge from occurring. super(data, options) diff --git a/test/service-module/misconfigured-client.test.ts b/test/service-module/misconfigured-client.test.ts index 4a12bc03..0543fd4e 100644 --- a/test/service-module/misconfigured-client.test.ts +++ b/test/service-module/misconfigured-client.test.ts @@ -11,6 +11,7 @@ describe('Service Module - Bad Client Setup', () => { serverAlias: 'misconfigured' }) class MisconfiguredTask extends BaseModel { + public static modelName = 'MisconfiguredTask' public static test: boolean = true } diff --git a/test/service-module/model-base.test.ts b/test/service-module/model-base.test.ts index 0b6cec1a..41d19624 100644 --- a/test/service-module/model-base.test.ts +++ b/test/service-module/model-base.test.ts @@ -103,6 +103,7 @@ describe('makeModel / BaseModel', function () { const { BaseModel, makeServicePlugin } = feathersVuex(feathers, { serverAlias: 'myApi' }) + BaseModel.modelName = 'BaseModel' const plugin = makeServicePlugin({ servicePath: 'todos', service: feathers.service('todos'), diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts index a3dfbaa0..0d8769bb 100644 --- a/test/service-module/model-instance-defaults.test.ts +++ b/test/service-module/model-instance-defaults.test.ts @@ -121,6 +121,7 @@ describe('Models - Default Values', function () { // Since we're not using this NakedTodo model in a service plugin, it doesn't get // monkey patched with the store. class NakedTodo extends BaseModel { + public static modelName = 'NakedTodo' public static test: boolean = true } const todo = new NakedTodo() @@ -323,6 +324,8 @@ describe('Models - Default Values', function () { }) class Person extends BaseModel { + public static modelName = 'Person' + public constructor(data?, options?) { super(data, options) } @@ -392,6 +395,8 @@ describe('Models - Default Values', function () { }) class Person extends BaseModel { + public static modelName = 'Person' + public constructor(data?, options?) { super(data, options) } diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index d1a20df6..98fc4ea1 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -42,6 +42,7 @@ function makeContext() { }) class ServiceTodo extends BaseModel { + public static modelName = 'ServiceTodo' public id public description: string @@ -50,17 +51,21 @@ function makeContext() { } } class HotspotMedia extends BaseModel { + public static modelName = 'HotspotMedia' public id public description: string } class Media extends BaseModel { + public static modelName = 'Media' public id public description: string } class Person extends BaseModel { + public static modelName = 'Person' public static test: boolean = true } class Item extends BaseModel { + public static modelName = 'Item' public static test: boolean = true } class Task extends BaseModel { @@ -68,15 +73,19 @@ function makeContext() { public static test: boolean = true } class Car extends BaseModel { + public static modelName = 'Car' public static test: boolean = true } class Group extends BaseModel { + public static modelName = 'Group' public static test: boolean = true } class Test extends BaseModel { + public static modelName = 'Test' public static test: boolean = true } class Thing extends BaseModel { + public static modelName = 'Thing' public static test: boolean = true } @@ -103,6 +112,8 @@ function makeContextWithState() { serverAlias: 'basics' }) class ServiceTodo extends BaseModel { + public static modelName = 'ServiceTodo' + public static test: boolean = true } From c15cd04eca366ef6cca6c0b9b0360b741fcd4d04 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 5 Jun 2019 14:32:49 -0700 Subject: [PATCH 222/404] 2.0.0-pre.28 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index fc9df868..ff7ea067 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.27", + "version": "2.0.0-pre.28", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index c4c341c9..cdfbe0d1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.27", + "version": "2.0.0-pre.28", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From a7097ea3b064f9d0b6b042d7f8fe340609f9f22a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 10:44:54 -0700 Subject: [PATCH 223/404] lint cleanup --- src/service-module/notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 9347ffad..58516478 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -489,4 +489,4 @@ class Todo extends BaseModel { } public static modelName = 'Todo' } -``` \ No newline at end of file +``` From 82fedf5af412f6a3264142ee52a949cb4a917c05 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 10:53:24 -0700 Subject: [PATCH 224/404] Target es6 --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index cdb5db90..7ca4ccb5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,7 @@ "esModuleInterop": true, "outDir": "dist", "moduleResolution": "node", - "target": "es5", + "target": "es6", "sourceMap": true }, "include": [ From ed8c7761f544e2d6e050a382caedb4aba2eb5dcb Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 11:29:13 -0700 Subject: [PATCH 225/404] BaseModel has modelName of BaseModel --- src/service-module/make-model.ts | 2 +- src/service-module/make-service-plugin.ts | 2 +- test/service-module/model-base.test.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 317fb7aa..a8ff3cbf 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -71,7 +71,7 @@ export default function makeModel(options: FeathersVuexOptions) { public data: Record public static merge = mergeWithAccessors - public static modelName + public static modelName = 'BaseModel' public constructor(data, options: BaseModelInstanceOptions) { // You have to pass at least an empty object to get a tempId. diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index 5db77b60..06412744 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -84,7 +84,7 @@ export default function prepareMakeServicePlugin( setupInstance, preferUpdate }) - if (!Model.modelName) { + if (!Model.modelName || Model.modelName === 'BaseModel') { throw new Error('The modelName property is required for Feathers-Vuex Models') } addModel(Model) diff --git a/test/service-module/model-base.test.ts b/test/service-module/model-base.test.ts index 41d19624..fc31a0c6 100644 --- a/test/service-module/model-base.test.ts +++ b/test/service-module/model-base.test.ts @@ -103,7 +103,7 @@ describe('makeModel / BaseModel', function () { const { BaseModel, makeServicePlugin } = feathersVuex(feathers, { serverAlias: 'myApi' }) - BaseModel.modelName = 'BaseModel' + BaseModel.modelName = 'TestModel' const plugin = makeServicePlugin({ servicePath: 'todos', service: feathers.service('todos'), From 9703cee9fea8072922be4878be15fdd2fb6737e5 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 11:36:58 -0700 Subject: [PATCH 226/404] 2.0.0-pre.29 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index ff7ea067..0d59e2dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.28", + "version": "2.0.0-pre.29", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index cdfbe0d1..52d0f220 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.28", + "version": "2.0.0-pre.29", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From bca692e0b483f96b17c08422dee9111402e2b0ac Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 11:39:38 -0700 Subject: [PATCH 227/404] 2.0.0-pre.30 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0d59e2dd..9cc332b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.29", + "version": "2.0.0-pre.30", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 52d0f220..eef02633 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.29", + "version": "2.0.0-pre.30", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 1213e683403a28fde9141af3d52d44b5e5e55f8e Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 11:40:10 -0700 Subject: [PATCH 228/404] 2.0.0-pre.31 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9cc332b5..15463961 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.30", + "version": "2.0.0-pre.31", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index eef02633..ed8ff11b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.30", + "version": "2.0.0-pre.31", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From eac6fc75c242394cbaa490c3c92fdcc64c4808f7 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 11:40:34 -0700 Subject: [PATCH 229/404] 2.0.0-pre.32 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 15463961..3278a610 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.31", + "version": "2.0.0-pre.32", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ed8ff11b..cb46765a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.31", + "version": "2.0.0-pre.32", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 1c4fe500d3f1c85fa9e3b97aa813a4d09f000eca Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 15:40:00 -0700 Subject: [PATCH 230/404] 2.0.0-pre.33 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3278a610..0fe75804 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.32", + "version": "2.0.0-pre.33", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index cb46765a..36d3d17b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.32", + "version": "2.0.0-pre.33", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From b31f30f385078abb98e56ce58408f0d84060274b Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 18:58:22 -0700 Subject: [PATCH 231/404] Test env:modules:false in babelrc https://stackoverflow.com/questions/43042889/typescript-referenceerror-exports-is-not-defined --- .babelrc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.babelrc b/.babelrc index 7b812612..2555d115 100644 --- a/.babelrc +++ b/.babelrc @@ -1,4 +1,8 @@ { "plugins": [ "add-module-exports" ], - "presets": [ "es2015", "stage-2"] + "presets": [ + [ "env", { "modules": false } ], + "es2015", + "stage-2" + ] } From fbd60502d706cd11a69ab0a9a2ec610583a5c7b0 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 18:58:28 -0700 Subject: [PATCH 232/404] 2.0.0-pre.34 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0fe75804..c3ca9e52 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.33", + "version": "2.0.0-pre.34", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 36d3d17b..99974eea 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.33", + "version": "2.0.0-pre.34", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 1802514d04732648c5a3448e035097cf103bb7e8 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 21:10:05 -0700 Subject: [PATCH 233/404] turn off source maps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They’re messing up the debugger, causing incorrect line numbers --- tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 7ca4ccb5..99a633cf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "outDir": "dist", "moduleResolution": "node", "target": "es6", - "sourceMap": true + "sourceMap": false }, "include": [ "src/**/*" From cf40972e1babe60a1c85e8ddf90e68d74c898256 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 21:10:40 -0700 Subject: [PATCH 234/404] 2.0.0-pre.35 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index c3ca9e52..5cb7d734 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.34", + "version": "2.0.0-pre.35", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 99974eea..cc7358e3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.34", + "version": "2.0.0-pre.35", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 9f5cd94b43931eab9b638c1d297cbb26f0daae7a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 22:00:39 -0700 Subject: [PATCH 235/404] Lint Cleanup --- src/make-find-mixin.ts | 3 +-- src/make-get-mixin.ts | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index e0b8136d..07c7a622 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -184,8 +184,7 @@ export default function makeFindMixin(options) { } else if (typeof value === 'string') { mixin.computed[NAME] = function() { // If the specified computed prop wasn't found, display an error. - if (returnTheValue) { - } else { + if (!returnTheValue) { if (!hasSomeAttribute(this, value, NAME)) { throw new Error( `Value for ${NAME} was not found on the component at '${value}'.` diff --git a/src/make-get-mixin.ts b/src/make-get-mixin.ts index 5f428483..f3e79a1d 100644 --- a/src/make-get-mixin.ts +++ b/src/make-get-mixin.ts @@ -156,8 +156,7 @@ export default function makeFindMixin(options) { } else if (typeof value === 'string') { mixin.computed[NAME] = function() { // If the specified computed prop wasn't found, display an error. - if (returnTheValue) { - } else { + if (!returnTheValue) { if (!hasSomeAttribute(this, value, NAME)) { throw new Error( `Value for ${NAME} was not found on the component at '${value}'.` From f9607eaea31a52389f6396e83267ffc64015b6f6 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 22:00:49 -0700 Subject: [PATCH 236/404] 2.0.0-pre.36 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5cb7d734..f69d3e60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.35", + "version": "2.0.0-pre.36", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index cc7358e3..5e278dc3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.35", + "version": "2.0.0-pre.36", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 674fd7012b8f3dc6de3498b0569b1f20257a4eac Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 22:04:23 -0700 Subject: [PATCH 237/404] More lint cleanup --- src/service-module/service-module.actions.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 5676a40b..dae8c127 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -150,6 +150,7 @@ export default function makeServiceActions(service) { }, patch({ commit, dispatch, state }, [id, data, params]) { + // eslint-disable-next-line no-unused-vars const { idField, diffOnPatch } = state commit('setPending', 'patch') @@ -259,7 +260,7 @@ export default function makeServiceActions(service) { return response }, handleFindError({ commit }, { params, error }) { - commit('setError', { method: 'find', error }) + commit('setError', { method: 'find', params, error }) commit('unsetPending', 'find') return Promise.reject(error) }, From 749457d69554814f155973f9034795885fe512ad Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 22:04:30 -0700 Subject: [PATCH 238/404] 2.0.0-pre.37 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index f69d3e60..f9d78c04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.36", + "version": "2.0.0-pre.37", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5e278dc3..9a95c0c3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.36", + "version": "2.0.0-pre.37", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From c051b3fc47f0ea21a18c7a69cd033ed2a51a9395 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 22:12:14 -0700 Subject: [PATCH 239/404] Use data if no instanceDefaults returned Same for setupInstance. This prevents trying to operate on undefined (no return from either function) as an object. --- src/service-module/make-model.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index a8ff3cbf..512567cd 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -111,7 +111,7 @@ export default function makeModel(options: FeathersVuexOptions) { // Setup instanceDefaults, separate out accessors if (instanceDefaults && typeof instanceDefaults === 'function') { - const defaults = instanceDefaults.call(this, data, { models, store }) + const defaults = instanceDefaults.call(this, data, { models, store }) || data const { accessors, values } = separateAccessors(defaults) mergeWithAccessors(this, accessors) mergeWithAccessors(this, values) @@ -122,7 +122,7 @@ export default function makeModel(options: FeathersVuexOptions) { if (options.merge !== false) { mergeWithAccessors( this, - setupInstance.call(this, data, { models, store }) + setupInstance.call(this, data, { models, store }) || data ) } From cabe31ba916b1b34084ab9f2b4c3e2d03b3a46bf Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 6 Jun 2019 22:12:29 -0700 Subject: [PATCH 240/404] 2.0.0-pre.38 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index f9d78c04..b2110846 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.37", + "version": "2.0.0-pre.38", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 9a95c0c3..04ee1263 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.37", + "version": "2.0.0-pre.38", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 743090f7ec3bc2d20bd71fffb1cde25e49cf9b28 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 14 Jun 2019 08:15:13 -0700 Subject: [PATCH 241/404] Make queryWhen a computed property --- src/make-find-mixin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index 07c7a622..fdebb8cc 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -201,7 +201,7 @@ export default function makeFindMixin(options) { setupAttribute(SERVICE_NAME, service, 'computed', true) setupAttribute(PARAMS, params) setupAttribute(FETCH_PARAMS, fetchQuery) - setupAttribute(QUERY_WHEN, queryWhen, 'methods') + setupAttribute(QUERY_WHEN, queryWhen, 'computed') setupAttribute(LOCAL, local) return mixin From 56a60765ba2e8c08bc9f1ec6c6d4b3a6ec39928a Mon Sep 17 00:00:00 2001 From: Jimbob Date: Mon, 10 Jun 2019 14:32:23 +0100 Subject: [PATCH 242/404] Warn against instanceDefaults as an object #224 --- docs/model-classes.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/model-classes.md b/docs/model-classes.md index d8fe87cb..542ef1db 100644 --- a/docs/model-classes.md +++ b/docs/model-classes.md @@ -138,6 +138,12 @@ export default new Vuex.Store({ With the above configuration, when you create a [`Todo` instance](./model-classes.md), it will have the attributes provided as `instanceDefaults`. This is especially useful for binding to form data. If the attributes aren't defined while binding, the automatic Vue reactivity won't work. Remember to not set any of the attributes to `undefined`, but instead use `null`. If not, the reactivity breaks, and you might spend some time wondering why your form is broken. +### A Word Of Warning + +One thing to be aware of when using `instanceDefaults` as an object is that values can persist between instances and mutate separate instances. For example, when including an `Array`, changes made to one instance will affect any other instances of this model too. + +Using `instanceDefaults` as an object will be deprecated in the next major version of `feathers-vuex` so it's best to stick to the function option below. + ## instanceDefaults | Function A much more powerful API is available when you provide `instanceDefaults` as a function. The function will be called with the following arguments and should return an instanceDefaults object. From 05dd38f60c0cd1dfea1670e197b4e1a9c530e7df Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 14 Jun 2019 08:23:33 -0700 Subject: [PATCH 243/404] Fix test for todosQueryWhen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since it’s no longer a function and is now a computed property. --- test/make-find-mixin.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/make-find-mixin.test.ts b/test/make-find-mixin.test.ts index 7d1ba7cd..d5750275 100644 --- a/test/make-find-mixin.test.ts +++ b/test/make-find-mixin.test.ts @@ -79,7 +79,7 @@ describe('Find Mixin', function () { vm.todosQid === 'default', 'the default query identifier is in place' ) - assert(vm.todosQueryWhen() === true, 'the default queryWhen is true') + assert(vm.todosQueryWhen === true, 'the default queryWhen is true') // assert(vm.todosWatch.length === 0, 'the default watch is an empty array') assert( vm.todosParams === undefined, From 9323a8156748ebe4157e15686fe70426d74730f6 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 14 Jun 2019 08:24:05 -0700 Subject: [PATCH 244/404] Add requestedOnce and loadedOnce to the makeFindMixin --- src/make-find-mixin.ts | 4 ++++ test/make-find-mixin.test.ts | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index fdebb8cc..fbaac7bf 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -52,11 +52,15 @@ export default function makeFindMixin(options) { const QUERY_WHEN = `${prefix}QueryWhen` const FIND_ACTION = `find${capitalized}` const FIND_GETTER = `find${capitalized}InStore` + const HAVE_ITEMS_BEEN_REQUESTED_ONCE = `have${capitalized}BeenRequestedOnce` + const HAVE_ITEMS_LOADED_ONCE = `have${capitalized}LoadedOnce` const PAGINATION = `${prefix}PaginationData` const LOCAL = `${prefix}Local` const QID = `${prefix}Qid` const data = { [IS_FIND_PENDING]: false, + [HAVE_ITEMS_BEEN_REQUESTED_ONCE]: false, + [HAVE_ITEMS_LOADED_ONCE]: false, [WATCH]: watch, [QID]: qid } diff --git a/test/make-find-mixin.test.ts b/test/make-find-mixin.test.ts index d5750275..88dbbb54 100644 --- a/test/make-find-mixin.test.ts +++ b/test/make-find-mixin.test.ts @@ -51,6 +51,8 @@ describe('Find Mixin', function () { todos: [] todosServiceName: string isFindTodosPending: boolean + haveTodosBeenRequestedOnce: boolean + haveTodosLoadedOnce: boolean findTodos: Function todosLocal: boolean todosQid: string @@ -73,6 +75,8 @@ describe('Find Mixin', function () { ) assert(vm.todosServiceName === 'todos', 'service name was correct') assert(vm.isFindTodosPending === false, 'loading boolean is in place') + assert(vm.haveTodosBeenRequestedOnce === false, 'requested once boolean is in place') + assert(vm.haveTodosLoadedOnce === false, 'loaded once boolean is in place') assert(typeof vm.findTodos === 'function', 'the find action is in place') assert(vm.todosLocal === false, 'local boolean is false by default') assert( From 1c63c90ecb2ebc1fe934310b912f3aaeda1df141 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 14 Jun 2019 08:24:48 -0700 Subject: [PATCH 245/404] 2.0.0-pre.39 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index b2110846..5e762024 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.38", + "version": "2.0.0-pre.39", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 04ee1263..3c3c502e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.38", + "version": "2.0.0-pre.39", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 47d6a2011bee332edcf39b1bcf4c6eb6ef7eeca5 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 15 Jun 2019 20:06:56 -0700 Subject: [PATCH 246/404] Add note about es5 accessors going on model classes --- src/service-module/notes.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 58516478..198f2d54 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -320,6 +320,35 @@ Where `instanceDefaults` props get replaced by instance data, the props returned Object.assign({}, instanceDefaults(data), data, setupInstance(data)) ``` +## ES5 accessors are specified as properties of the model classes + +In the previous version of feathers-vuex, es5 getters and setters would commonly be put in the `instanceDefaults`. They are now specified in the model class definition: + +```js +class User extends BaseModel { + constructor(data, options) { + super(data, options) + } + static modelName = 'User' + static instanceDefaults() { + return { + firstName: '', + lastName: '', + email: '', + password: '', + roles: [] + } + } + // Getters + get fullName() { + return `${this.firstName} ${this.lastName}` + } + set primalName(val) { + this.name = 'Gorilla Dan' + } +} +``` + ## Define Relationships and Modify Data with `setupInstance` The new `setupInstance` method allows a lot of flexibility in creating new instances. It has the exact same API as the `instanceDefaults` method. The only difference is the order in which they are applied to the instance data. From c16734ab7a3a5afe49c6613a723bd59753d04516 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 17 Jun 2019 22:21:30 -0700 Subject: [PATCH 247/404] catch errors about getters without a setter Sometimes the getter definition is returning as undefined when the value can actually be read out as null, which messes up the logic that prevents attempting to set a getter. This adds a try / catch to prevent lots of errors. --- src/utils.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index dc7e87a9..e738e0c9 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -345,9 +345,21 @@ export function mergeWithAccessors( // If we're dealing with a Vue Observable, just assign the values. if (destIsVueObservable || sourceIsVueObservable) { if (_isObject(source[key])) { - dest[key] = fastCopy(source[key]) + try { + dest[key] = fastCopy(source[key]) + } catch (err) { + if(!err.message.includes('getter')) { + throw err + } + } } else { - dest[key] = source[key] + try { + dest[key] = source[key] + } catch(err) { + if(!err.message.includes('getter')) { + throw err + } + } } return } From 2ecc8830c3c863a5bc04fcc6ddaae1f9d88b7a37 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 17 Jun 2019 22:21:55 -0700 Subject: [PATCH 248/404] 2.0.0-pre.40 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5e762024..95e8a644 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.39", + "version": "2.0.0-pre.40", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 3c3c502e..244b9ec9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.39", + "version": "2.0.0-pre.40", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 3acec71d18dddb763d184c50ccb75ad4700c34af Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 18 Jun 2019 07:25:21 -0700 Subject: [PATCH 249/404] remove node moduleresolution --- tsconfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 99a633cf..5922a382 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,6 @@ "allowSyntheticDefaultImports": true, "esModuleInterop": true, "outDir": "dist", - "moduleResolution": "node", "target": "es6", "sourceMap": false }, From 04a87fb63974166041bd753d4b359e362959ab7c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 18 Jun 2019 07:25:26 -0700 Subject: [PATCH 250/404] 2.0.0-pre.41 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 95e8a644..ef14e0ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.40", + "version": "2.0.0-pre.41", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 244b9ec9..b3855e17 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.40", + "version": "2.0.0-pre.41", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From bcec98710d7305081b3a42959654863f554f8f23 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 18 Jun 2019 07:26:17 -0700 Subject: [PATCH 251/404] Revert "remove node moduleresolution" This reverts commit 3acec71d18dddb763d184c50ccb75ad4700c34af. --- tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/tsconfig.json b/tsconfig.json index 5922a382..99a633cf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,7 @@ "allowSyntheticDefaultImports": true, "esModuleInterop": true, "outDir": "dist", + "moduleResolution": "node", "target": "es6", "sourceMap": false }, From 7658a6879e996d76282daef4ac9bb820520d1a24 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 18 Jun 2019 23:32:56 -0700 Subject: [PATCH 252/404] Make sure update/patched data become model instances --- src/service-module/service-module.actions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index dae8c127..338fb551 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -315,7 +315,6 @@ export default function makeServiceActions(service) { if ( service.FeathersVuexModel && - !existingItem && !item.isFeathersVuexInstance ) { item = new service.FeathersVuexModel(item) From 401d8a3c4bc5123e2f9ff1ded1089802ac17d16f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 18 Jun 2019 23:33:07 -0700 Subject: [PATCH 253/404] 2.0.0-pre.42 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index ef14e0ad..d8c5a566 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.41", + "version": "2.0.0-pre.42", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b3855e17..2933221e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.41", + "version": "2.0.0-pre.42", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 257db6a069d951bf20ce2ee759b2b313f23a1e91 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 19 Jun 2019 08:57:45 -0700 Subject: [PATCH 254/404] Add getId method This normalizes how ids are found on records. --- src/utils.ts | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index e738e0c9..6560469e 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -170,6 +170,28 @@ export function assignTempId(state, item) { return newId } +/** + * Get the id from a record in this order: + * 1. id + * 2. _id + * 3. the `idField` + * @param item + */ +export function getId(item, idField) { + if (!item) { + return + } + if (item.hasOwnProperty('id')) { + return item.id + } + if (item.hasOwnProperty('_id')) { + return item._id + } + if (item.hasOwnProperty(idField)) { + return item[idField] + } +} + // Creates a Model class name from the last part of the servicePath export function getModelName(Model) { // If the Model.name has been customized, use it. @@ -216,10 +238,10 @@ export function getServiceCapitalization(servicePath) { return name } -export function updateOriginal(newData, existingItem) { +export function updateOriginal(original, newData) { Object.keys(newData).forEach(key => { const newProp = newData[key] - const oldProp = existingItem[key] + const oldProp = original[key] let shouldCopyProp = false if (newProp === oldProp) { @@ -227,7 +249,7 @@ export function updateOriginal(newData, existingItem) { } // If the old item doesn't already have this property, update it - if (!existingItem.hasOwnProperty(key)) { + if (!original.hasOwnProperty(key)) { shouldCopyProp = true // If the old prop is null or undefined, and the new prop is neither } else if ( @@ -249,10 +271,10 @@ export function updateOriginal(newData, existingItem) { } if (shouldCopyProp) { - if (existingItem.hasOwnProperty(key)) { - existingItem[key] = newProp + if (original.hasOwnProperty(key)) { + original[key] = newProp } else { - Vue.set(existingItem, key, newProp) + Vue.set(original, key, newProp) } } }) From c3f1b914587c7ff8b90b6c0fe947d55b0d7578da Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 19 Jun 2019 08:59:04 -0700 Subject: [PATCH 255/404] Remove mergeWithAccessors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since mergeWithAccessors handles the accessors, there’s no need to separate these out. mini performance optimization. --- src/service-module/make-model.ts | 4 +--- src/utils.ts | 15 --------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 512567cd..2148093a 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -112,9 +112,7 @@ export default function makeModel(options: FeathersVuexOptions) { // Setup instanceDefaults, separate out accessors if (instanceDefaults && typeof instanceDefaults === 'function') { const defaults = instanceDefaults.call(this, data, { models, store }) || data - const { accessors, values } = separateAccessors(defaults) - mergeWithAccessors(this, accessors) - mergeWithAccessors(this, values) + mergeWithAccessors(this, defaults) } // Handles Vue objects or regular ones. We can't simply assign or return diff --git a/src/utils.ts b/src/utils.ts index 6560469e..80c99301 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -429,21 +429,6 @@ export function cloneWithAccessors(obj) { return clone } -export function separateAccessors(props) { - return Object.keys(props).reduce( - ({ accessors, values }, key) => { - const desc = Object.getOwnPropertyDescriptor(props, key) - if (typeof desc.get === 'function' || typeof desc.set === 'function') { - Object.defineProperty(accessors, key, desc) - } else { - Object.defineProperty(values, key, desc) - } - return { accessors, values } - }, - { accessors: {}, values: {} } - ) -} - export function checkNamespace(namespace, item) { if (!namespace) { console.error( From 75eacf1aaf0a6bdcae0c9f8c2056889a157eb89c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 19 Jun 2019 09:03:40 -0700 Subject: [PATCH 256/404] Remove old model --- src/service-module/model.old.js | 223 -------------------------------- 1 file changed, 223 deletions(-) delete mode 100644 src/service-module/model.old.js diff --git a/src/service-module/model.old.js b/src/service-module/model.old.js deleted file mode 100644 index 4cca170b..00000000 --- a/src/service-module/model.old.js +++ /dev/null @@ -1,223 +0,0 @@ -import { updateOriginal, cloneWithAccessors } from '../utils' - -const defaults = { - idField: 'id', - preferUpdate: false, - instanceDefaults: {} -} - -export default function(options) { - options = Object.assign({}, defaults, options) - const { idField, preferUpdate, globalModels, modelName } = options - const instanceDefaults = options.instanceDefaults || {} - - class FeathersVuexModel { - constructor(data = {}, options = {}) { - const { store, namespace } = this.constructor - const existingItem = - data[idField] && FeathersVuexModel.getFromStore(data[idField]) - const _relationships = {} - let fnDefaults - - if (options.isClone) { - Object.defineProperty(this, 'isClone', { value: true }) - } - - Object.defineProperty(this, 'isFeathersVuexInstance', { value: true }) - - if (existingItem && !options.isClone) { - if (!data.isFeathersVuexInstance) { - updateOriginal(data, existingItem) - } - return existingItem - } - - // Don't modify the original instanceDefaults. Clone it with accessors intact - if (typeof instanceDefaults === 'function') { - fnDefaults = instanceDefaults(data, { - store, - Model: this.constructor, - Models: globalModels - }) - } - const _instanceDefaults = cloneWithAccessors( - fnDefaults || instanceDefaults - ) - - Object.keys(_instanceDefaults).forEach(key => { - // Prevent getters and setters from firing before the instance is constructed - const desc = Object.getOwnPropertyDescriptor(_instanceDefaults, key) - if (desc.get || desc.set || typeof desc.value === 'function') { - return - } - - // If the default value for an instanceDefault matches a model name... - const modelName = _instanceDefaults[key] - if (globalModels.hasOwnProperty(modelName)) { - // Store the relationship - _relationships[key] = globalModels[modelName] - // Reset the instance default for this prop to null - _instanceDefaults[key] = null - } - - // Or if the value is a Date - if (modelName === Date) { - // Store the relationships - _relationships[key] = Date - - // Reset the instance default for this prop to null - _instanceDefaults[key] = null - } - }) - - // Check the relationships to instantiate. - Object.keys(_relationships).forEach(prop => { - const Model = _relationships[prop] - const related = data[prop] - - if (related) { - // Handle arrays - if (Array.isArray(related)) { - related.forEach((item, index) => { - if (Model === Date) { - related[index] = new Date(item) - } else { - const { model, storedModel } = createRelatedInstance({ - item, - Model, - idField, - store - }) - - // Replace the original array index with a reference to the model - related[index] = storedModel || model - } - }) - - // Handle objects - } else { - if (Model === Date) { - data[prop] = new Date(data[prop]) - } else { - const { model, storedModel } = createRelatedInstance({ - item: related, - Model, - idField, - store - }) - - // Replace the data's prop value with a reference to the model - data[prop] = storedModel || model - } - } - } - }) - - // Copy all instanceDefaults, including accessors - const props = Object.getOwnPropertyNames(_instanceDefaults) - props.forEach(key => { - var desc = Object.getOwnPropertyDescriptor(_instanceDefaults, key) - Object.defineProperty(this, key, desc) - }) - - // Copy over all instance data - const dataProps = Object.getOwnPropertyNames(data) - dataProps.forEach(key => { - const desc = Object.getOwnPropertyDescriptor(data, key) - const propertyExists = this.hasOwnProperty(key) - const isComputed = - desc.get || desc.set || typeof desc.value === 'function' - if (propertyExists && isComputed) { - return - } - Object.defineProperty(this, key, desc) - }) - - // If this record has an id, addOrUpdate the store - if (data[idField] && !options.isClone && !options.skipCommit) { - store.dispatch(`${namespace}/addOrUpdate`, this) - } - } - - clone() { - if (this.isClone) { - throw new Error('You cannot clone a copy') - } - const id = this[idField] - - return this._clone(id) - } - - reset() { - if (this.isClone) { - const id = this[idField] - this._reset(id) - } else { - throw new Error('You cannot reset a non-copy') - } - } - - commit() { - if (this.isClone) { - const id = this[idField] - return this._commit(id) - } else { - throw new Error('You cannnot call commit on a non-copy') - } - } - - save(params) { - if (this[idField]) { - return preferUpdate ? this.update(params) : this.patch(params) - } else { - return this.create(params) - } - } - - create(params) { - const data = Object.assign({}, this) - if (data[idField] === null) { - delete data[idField] - } - return this._create(data, params) - } - - patch(params) { - if (!this[idField]) { - const error = new Error( - `Missing ${idField} property. You must create the data before you can patch with this data`, - this - ) - return Promise.reject(error) - } - return this._patch(this[idField], this, params) - } - - update(params) { - if (!this[idField]) { - const error = new Error( - `Missing ${idField} property. You must create the data before you can update with this data`, - this - ) - return Promise.reject(error) - } - return this._update(this[idField], this, params) - } - - remove(params) { - return this._remove(this[idField], params) - } - - toJSON() { - return merge({}, this) - } - } - - Object.assign(FeathersVuexModel, { - options, - copiesById: {}, // For cloned data - modelName - }) - - return FeathersVuexModel -} From f73ba8092653a696737056d4a5c96e63e48dee10 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 19 Jun 2019 09:07:08 -0700 Subject: [PATCH 257/404] lint cleanup --- src/service-module/make-model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 2148093a..254c7d83 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -5,7 +5,7 @@ eslint */ import { FeathersVuexOptions } from './types' import { globalModels, prepareAddModel } from './global-models' -import { mergeWithAccessors, separateAccessors, checkNamespace } from '../utils' +import { mergeWithAccessors, checkNamespace, getId } from '../utils' import { get as _get, merge as _merge } from 'lodash' // A hack to prevent error with this.constructor.preferUpdate From 00d23c37d6c656fa83f9d5cef902026fda215289 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 19 Jun 2019 09:21:17 -0700 Subject: [PATCH 258/404] Support id and _id without configuration Since `id` and `_id` are the most commonly-used idField options, this PR allows support for both without specifying either. This will solve a common issue that people run into. --- src/service-module/make-model.ts | 37 ++++++----- src/service-module/service-module.actions.ts | 19 ++---- .../service-module.mutations.ts | 28 ++++++-- src/utils.ts | 4 +- test/service-module/model-methods.test.ts | 65 ++++++++++++++++++- .../service-module.actions.test.ts | 4 +- test/test-utils.ts | 15 +++++ 7 files changed, 128 insertions(+), 44 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 254c7d83..2a09f19f 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -87,7 +87,7 @@ export default function makeModel(options: FeathersVuexOptions) { getFromStore, _commit } = this.constructor as typeof BaseModel - const id = data && (data[idField] || data[tempIdField]) + const id = getId(data, idField) const hasValidId = id !== null && id !== undefined data = data || {} @@ -134,7 +134,7 @@ export default function makeModel(options: FeathersVuexOptions) { public static getId(record: Record): string { const { idField } = this.constructor as typeof BaseModel - return record[idField] + return getId(record, idField) } public static find(params) { @@ -213,7 +213,7 @@ export default function makeModel(options: FeathersVuexOptions) { if (this.__isClone) { throw new Error('You cannot clone a copy') } - const id = this[idField] || this[tempIdField] + const id = getId(this, idField) || this[tempIdField] return this._clone(id) } @@ -236,8 +236,9 @@ export default function makeModel(options: FeathersVuexOptions) { public reset() { const { idField, tempIdField, _commit } = this .constructor as typeof BaseModel + if (this.__isClone) { - const id = this[idField] || this[tempIdField] + const id = getId(this, idField) || this[tempIdField] _commit.call(this.constructor, 'resetCopy', id) return this } else { @@ -252,7 +253,7 @@ export default function makeModel(options: FeathersVuexOptions) { const { idField, tempIdField, _commit, _getters } = this .constructor as typeof BaseModel if (this.__isClone) { - const id = this[idField] || this[tempIdField] + const id = getId(this, idField) || this[tempIdField] _commit.call(this.constructor, 'commitCopy', id) return _getters.call(this.constructor, 'get', id) @@ -267,7 +268,7 @@ export default function makeModel(options: FeathersVuexOptions) { */ public save(params) { const { idField, preferUpdate } = this.constructor as typeof BaseModel - const id = this[idField] + const id = getId(this, idField) if (id) { return preferUpdate ? this.update(params) : this.patch(params) } else { @@ -293,17 +294,18 @@ export default function makeModel(options: FeathersVuexOptions) { */ public patch(params?) { const { idField, _dispatch } = this.constructor as typeof BaseModel + const id = getId(this, idField) - if (!this[idField]) { + if (!id) { const error = new Error( `Missing ${ - options.idField + idField } property. You must create the data before you can patch with this data` ) return Promise.reject(error) } return _dispatch.call(this.constructor, 'patch', [ - this[idField], + id, this, params ]) @@ -315,17 +317,18 @@ export default function makeModel(options: FeathersVuexOptions) { */ public update(params) { const { idField, _dispatch } = this.constructor as typeof BaseModel + const id = getId(this, idField) - if (!this[idField]) { + if (!id) { const error = new Error( `Missing ${ - options.idField + idField } property. You must create the data before you can update with this data` ) return Promise.reject(error) } return _dispatch.call(this.constructor, 'update', [ - this[idField], + id, this, params ]) @@ -338,15 +341,13 @@ export default function makeModel(options: FeathersVuexOptions) { public remove(params) { const { idField, tempIdField, _dispatch, _commit } = this .constructor as typeof BaseModel + const id = getId(this, idField) - if (this.hasOwnProperty(idField)) { + if (id) { if (params && params.eager) { - _commit.call(this.constructor, 'removeItem', this[idField]) + _commit.call(this.constructor, 'removeItem', id) } - return _dispatch.call(this.constructor, 'remove', [ - this[idField], - params - ]) + return _dispatch.call(this.constructor, 'remove', [ id, params ]) } else { _commit.call(this.constructor, 'removeTemps', [this[tempIdField]]) return Promise.resolve(this) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 338fb551..27b92421 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -5,6 +5,7 @@ eslint */ import { observableDiff, applyChange } from 'deep-diff' import fastCopy from 'fast-copy' +import { getId } from '../utils' export default function makeServiceActions(service) { const serviceActions = { @@ -51,10 +52,7 @@ export default function makeServiceActions(service) { return service .get(id, params) .then(item => { - const id = item[idField] - dispatch('addOrUpdate', item) - commit('unsetPending', 'get') return state.keyedById[id] }) @@ -105,12 +103,12 @@ export default function makeServiceActions(service) { if (Array.isArray(response)) { dispatch('addOrUpdateList', response) response = response.map(item => { - const id = item[idField] + const id = getId(item, idField) return state.keyedById[id] }) } else { - const id = response[idField] + const id = getId(response, idField) dispatch('addOrUpdate', response) @@ -137,7 +135,6 @@ export default function makeServiceActions(service) { return service .update(id, data, params) .then(item => { - const id = item[idField] dispatch('addOrUpdate', item) commit('unsetPending', 'update') return state.keyedById[id] @@ -176,8 +173,6 @@ export default function makeServiceActions(service) { return service .patch(id, data, params) .then(item => { - const id = item[idField] - dispatch('addOrUpdate', item) commit('unsetPending', 'patch') return state.keyedById[id] @@ -237,7 +232,7 @@ export default function makeServiceActions(service) { commit('unsetPending', 'find') const mapItemFromState = item => { - const id = item[idField] + const id = getId(item, idField) return state.keyedById[id] } @@ -274,7 +269,7 @@ export default function makeServiceActions(service) { const { idField, autoRemove } = state list.forEach(item => { - let id = item[idField] + let id = getId(item, idField) let existingItem = state.keyedById[id] if (id !== null && id !== undefined) { @@ -287,7 +282,7 @@ export default function makeServiceActions(service) { state.ids.forEach(id => { if ( id !== state.currentId && - !list.some(item => item[idField] === id) + !list.some(item => getId(item, idField) === id) ) { toRemove.push(state.keyedById[id]) } @@ -308,7 +303,7 @@ export default function makeServiceActions(service) { }, addOrUpdate({ state, commit }, item) { const { idField } = state - let id = item[idField] + let id = getId(item, idField) let existingItem = state.keyedById[id] const isIdOk = id !== null && id !== undefined diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 4ccfc8c7..8cf2acb5 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -5,7 +5,7 @@ eslint */ import Vue from 'vue' import serializeError from 'serialize-error' -import { updateOriginal, mergeWithAccessors, assignTempId } from '../utils' +import { updateOriginal, mergeWithAccessors, assignTempId, getId } from '../utils' import { globalModels as models } from './global-models' import { get as _get, isObject as _isObject, omit as _omit } from 'lodash' @@ -19,7 +19,7 @@ export default function makeServiceMutations() { const newTempsById = { ...state.tempsById } for (let item of items) { - const id = item[idField] + const id = getId(item, idField) const isTemp = id === null || id === undefined // If the response contains a real id, remove isTemp @@ -53,9 +53,10 @@ export default function makeServiceMutations() { function updateItems(state, items) { const { idField, replaceItems, addOnUpsert, serverAlias, modelName } = state const Model = _get(models, `[${serverAlias}][${modelName}]`) + const BaseModel = _get(models, `[${state.serverAlias}].BaseModel`) for (let item of items) { - let id = item[idField] + const id = getId(item, idField) // If the response contains a real id, remove isTemp if (id) { @@ -64,6 +65,18 @@ export default function makeServiceMutations() { // Update the record if (id !== null && id !== undefined) { + + + + + // if (Model && !(item instanceof BaseModel) && !(item instanceof Model)) { + // item = new Model(item) + // } + + + + + if (state.ids.includes(id)) { // Completely replace the item if (replaceItems) { @@ -73,7 +86,8 @@ export default function makeServiceMutations() { Vue.set(state.keyedById, id, item) // Merge in changes } else { - updateOriginal(item, state.keyedById[id]) + const original = state.keyedById[id] + updateOriginal(original, item) } // if addOnUpsert then add the record into the state, else discard it. @@ -105,7 +119,7 @@ export default function makeServiceMutations() { removeItem(state, item) { const { idField } = state - const idToBeRemoved = _isObject(item) ? item[idField] : item + const idToBeRemoved = _isObject(item) ? getId(item, idField) : item const isIdOk = idToBeRemoved !== null && idToBeRemoved !== undefined const index = state.ids.findIndex(i => i === idToBeRemoved) @@ -131,7 +145,7 @@ export default function makeServiceMutations() { // Make sure we have an array of ids. Assume all are the same. const containsObjects = items[0] && _isObject(items[0]) const idsToRemove = containsObjects - ? items.map(item => item[idField]) + ? items.map(item => getId(item, idField)) : items const mapOfIdsToRemove = idsToRemove.reduce((map, id) => { map[id] = true @@ -250,7 +264,7 @@ export default function makeServiceMutations() { const { data, limit, skip, total } = response const { idField } = state const ids = data.map(item => { - return item[idField] + return getId(item, idField) }) const queriedAt = new Date().getTime() Vue.set(state.pagination, qid, { diff --git a/src/utils.ts b/src/utils.ts index 80c99301..533b35fe 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -188,7 +188,7 @@ export function getId(item, idField) { return item._id } if (item.hasOwnProperty(idField)) { - return item[idField] + return getId(item, idField) } } @@ -323,7 +323,7 @@ export function randomString(length) { export function createRelatedInstance({ item, Model, idField, store }) { // Create store instances (if data contains an idField) const model = new Model(item) - const id = model[idField] + const id = getId(model, idField) const storedModel = store.state[model.constructor.namespace].keyedById[id] return { model, storedModel } diff --git a/test/service-module/model-methods.test.ts b/test/service-module/model-methods.test.ts index 3a9295bb..acedef7b 100644 --- a/test/service-module/model-methods.test.ts +++ b/test/service-module/model-methods.test.ts @@ -9,6 +9,8 @@ import feathersVuex from '../../src/index' import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' import Vuex from 'vuex' import { clearModels } from '../../src/service-module/global-models' +import memory from 'feathers-memory' +import { makeStore } from '../test-utils' require('events').EventEmitter.prototype._maxListeners = 100 @@ -31,6 +33,33 @@ function makeContext() { const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { serverAlias: 'model-methods' }) + + const serialize = context => { + context.data = JSON.parse(JSON.stringify(context.data)) + } + const deserialize = context => { + context.result = JSON.parse(JSON.stringify(context.result)) + } + + feathersClient.use( 'letters', memory() ) + + const lettersService = feathersClient.service('letters') + + // Setup hooks on letters service to simulate toJSON serialization that occurs + // with a remote API request. + lettersService.hooks({ + before: { + create: [ serialize ], + update: [ serialize ], + patch: [ serialize ] + }, + after: { + create: [ deserialize ], + patch: [ deserialize ], + update: [ deserialize ] + } + }) + class Task extends BaseModel { public static modelName = 'Task' public static servicePath: 'tasks' @@ -45,6 +74,14 @@ function makeContext() { super(data, options) } } + + class Letter extends BaseModel { + public static modelName = 'Letter' + public constructor(data?, options?) { + super(data, options) + } + } + const store = new Vuex.Store({ strict: true, plugins: [ @@ -56,6 +93,11 @@ function makeContext() { makeServicePlugin({ Model: Todo, service: feathersClient.service('todos') + }), + makeServicePlugin({ + Model: Letter, + servicePath: 'letters', + service: feathersClient.service('letters') }) ] }) @@ -63,6 +105,8 @@ function makeContext() { BaseModel, Task, Todo, + Letter, + lettersService, store } } @@ -98,9 +142,9 @@ describe('Models - Methods', function () { it('instance.save calls create with correct arguments', function () { const { Task } = makeContext() - const module = new Task({ test: true }) + const task = new Task({ test: true }) - Object.defineProperty(module, 'create', { + Object.defineProperty(task, 'create', { value(params) { assert(arguments.length === 1, 'should have only called with params') assert( @@ -110,7 +154,7 @@ describe('Models - Methods', function () { } }) - module.save() + task.save() }) it('instance.save passes params to create', function () { @@ -177,6 +221,21 @@ describe('Models - Methods', function () { assert(!store.state.tasks.tempsById[tempId], 'temp was removed') }) + it('instance methods still available in store data after updateItem mutation (or socket event)', async function () { + const { Letter, store, lettersService } = makeContext() + let letter = new Letter({ name: 'Garmadon', age: 1025 }) + + letter = await letter.save() + + assert.equal(typeof letter.save, 'function', 'saved instance has a save method') + + store.commit('letters/updateItem', { id: letter.id, name: 'Garmadon / Dad', age: 1026 }) + + const letter2 = new Letter({ id: letter.id, name: 'Just Garmadon', age: 1027 }) + + assert.equal(typeof letter2.save, 'function', 'new instance has a save method') + }) + it('instance.toJSON', function () { const { Task } = makeContext() const task = new Task({ id: 1, test: true }) diff --git a/test/service-module/service-module.actions.test.ts b/test/service-module/service-module.actions.test.ts index b979891e..cd348382 100644 --- a/test/service-module/service-module.actions.test.ts +++ b/test/service-module/service-module.actions.test.ts @@ -10,7 +10,7 @@ import { feathersRestClient as feathersClient } from '../fixtures/feathers-clien import Vuex, { mapActions } from 'vuex' import memory from 'feathers-memory' import { clearModels } from '../../src/service-module/global-models' -import { makeStore } from '../test-utils' +import { makeStore, makeStoreWithAtypicalIds} from '../test-utils' interface RootState { 'my-todos': ServiceState @@ -45,7 +45,7 @@ function makeContext() { 'no-ids', // @ts-ignore memory({ - store: makeStore(), + store: makeStoreWithAtypicalIds(), paginate: { default: 10, max: 50 diff --git a/test/test-utils.ts b/test/test-utils.ts index fd06fff5..34900671 100644 --- a/test/test-utils.ts +++ b/test/test-utils.ts @@ -27,3 +27,18 @@ export const makeStore = () => { 9: { id: 9, description: 'Do the tenth' } } } + +export const makeStoreWithAtypicalIds = () => { + return { + 0: { someId: 0, description: 'Do the first' }, + 1: { someId: 1, description: 'Do the second' }, + 2: { someId: 2, description: 'Do the third' }, + 3: { someId: 3, description: 'Do the fourth' }, + 4: { someId: 4, description: 'Do the fifth' }, + 5: { someId: 5, description: 'Do the sixth' }, + 6: { someId: 6, description: 'Do the seventh' }, + 7: { someId: 7, description: 'Do the eighth' }, + 8: { someId: 8, description: 'Do the ninth' }, + 9: { someId: 9, description: 'Do the tenth' } + } +} From 2bbb8777e63eadad3661649066a45bb7e8735c79 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 19 Jun 2019 09:25:46 -0700 Subject: [PATCH 259/404] Document idField support --- src/service-module/notes.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 198f2d54..685a65ad 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -84,6 +84,16 @@ created () { } ``` +## Common idField support + +Since `id` and `_id` are the most commonly-used idField options, both are supported without additional configuration. The idField is detected in this order: + +1. `item.id` +2. `item._id` +3. `item[idField]` + +This solves a common issue that occurs when the `idField` is not provided. This also means that the only time you must specify an `idField` is when your data does not contain an `id` or `_id` field. + ## Support for Temporary Records Feathers-Vuex 2.0 supports tracking temporary items and automatically assigns a temporary id (customizable using the `options.tempIdField`) and adds the records to the `state.tempsById` field. From 2e2dff1d8747b0192d21aac250150024f6fe36c5 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 19 Jun 2019 09:43:37 -0700 Subject: [PATCH 260/404] 2.0.0-pre.43 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index d8c5a566..4b1ff601 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.42", + "version": "2.0.0-pre.43", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 2933221e..805268a6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.42", + "version": "2.0.0-pre.43", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From ce63d4de4a1930abbec66f1558ab892f4ae17568 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 19 Jun 2019 09:54:05 -0700 Subject: [PATCH 261/404] Use addOrUpdate method for socket events This provides a consistent interface for adding something to the store with Model class functionality. --- src/service-module/make-service-plugin.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index 06412744..8ca86490 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -93,13 +93,13 @@ export default function prepareMakeServicePlugin( if (options.enableEvents) { // Listen to socket events when available. service.on('created', item => - store.commit(`${options.namespace}/addItem`, item) + store.dispatch(`${options.namespace}/addOrUpdate`, item) ) service.on('updated', item => - store.commit(`${options.namespace}/updateItem`, item) + store.dispatch(`${options.namespace}/addOrUpdate`, item) ) service.on('patched', item => - store.commit(`${options.namespace}/updateItem`, item) + store.dispatch(`${options.namespace}/addOrUpdate`, item) ) service.on('removed', item => store.commit(`${options.namespace}/removeItem`, item) From 0352fe0ef27c1d9902702a65b87ba4d2d6273a1b Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 19 Jun 2019 09:54:17 -0700 Subject: [PATCH 262/404] 2.0.0-pre.44 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4b1ff601..48983eb0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.43", + "version": "2.0.0-pre.44", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 805268a6..98d311e4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.43", + "version": "2.0.0-pre.44", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 8ebddc3fdd7a8f5d7c6bc81fcf79cde71d26343d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 27 Jun 2019 10:19:32 -0700 Subject: [PATCH 263/404] Fix create action documentation Fixes https://github.com/feathers-plus/feathers-vuex/issues/230 --- docs/service-module.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/service-module.md b/docs/service-module.md index 8d042b27..7d031bf8 100644 --- a/docs/service-module.md +++ b/docs/service-module.md @@ -283,24 +283,30 @@ store.dispatch('todos/get', [1, params]) Make sure your returned records have a unique field that matches the `idField` option for the service plugin. -### `create(data)` +### `create(data|ParamArray)` -Create one or multiple records. +Create one or multiple records. Note that the method is overloaded to accept two types of arguments. If you want a consistent interface for creating single or multiple records, use the array syntax, described below. Creating multiple records requires using the `paramArray` syntax. -- `data {Object|Array}` - if an object is provided, a single record will be created. If an array of objects is provided, multiple records will be created. +- `data {Object|ParamArray}` - if an object is provided, a single record will be created. ```js let newTodo = {description: 'write good tests'} store.dispatch('todos/create', newTodo) ``` +- `data {ParamArray}` - if an array is provided, it is assumed to have this structure: + +- `ParamArray {Array}` - array containing the two parameters that Feathers' `service.create` method accepts. + - `data {Object|Array}` - the data to create. Providing an object creates a single record. Providing an array of objects creates multiple records. + - `params {Object}` - optional - an object containing a `query` object. Can be useful in rare situations. + Make sure your returned records have a unique field that matches the `idField` option for the service plugin. ### `update(paramArray)` Update (overwrite) a record. -- `paramArray {Array}` - array containing the three parameters update takes. +- `paramArray {Array}` - array containing the three parameters update accepts. - `id {Number|String}` - the `id` of the existing record being requested from the API server. - `data {Object}` - the data that will overwrite the existing record - `params {Object}` - An object containing a `query` object. From 97b449e278db34836aa8a301b7e22d82483075cd Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 27 Jun 2019 10:19:46 -0700 Subject: [PATCH 264/404] Document setting the `idField` and `debug` mode. --- docs/common-patterns.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/common-patterns.md b/docs/common-patterns.md index b0039876..da1cf897 100755 --- a/docs/common-patterns.md +++ b/docs/common-patterns.md @@ -2,6 +2,14 @@ title: Common Patterns --- +## Set the `idField` + +If you have a "WTF this isn't working" moment while setting up a new service, make sure you've set the `idField` property on your service. In `feathers-vuex@1.x`, the `id` is the default `idField`. You have to manually set `_id`. Starting in `feathers-vuex@2.x`, both the `id` and `_id` fields are supported without any configuration, so you only set the `idField` when your service uses something else. + +## Enable debugging + +You can set `debug: true` in the options to enable some logging to assist with debugging. + ## Use the `` and `` components Using the new `` and `` components provides concise access to the best features of `feathers-vuex`, including live queries, reactive lists, custom pagination tracking per component, and fall-through cacheing of local data in the Vuex store. Check out the [Renderless Data Components](./components.md) docs for more details. From 78f98e5fb1e1ef5dbd26346adea6f6dce7d68011 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 27 Jun 2019 10:42:29 -0700 Subject: [PATCH 265/404] Remove old Mocha config in launch.json --- .vscode/launch.json | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 61146d50..38f844c3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -25,26 +25,6 @@ }, "internalConsoleOptions": "openOnSessionStart" }, - { - "type": "node", - "request": "launch", - "name": "Mocha Tests", - "cwd": "${workspaceRoot}", - "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/mocha", - "windows": { - "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/mocha.cmd" - }, - "runtimeArgs": [ - "--opts", - "mocha.opts", - "-u", - "tdd", - "--timeout", - "999999", - "--colors" - ], - "internalConsoleOptions":"openOnFirstSessionStart" - }, { "type": "node", "request": "launch", From 88ead37938487451aeef71618840efba78187931 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 27 Jun 2019 10:42:49 -0700 Subject: [PATCH 266/404] Make sure instanceDefaults stay after patch Fixes https://github.com/feathers-plus/feathers-vuex/issues/228 --- .../model-instance-defaults.test.ts | 16 ++++++++++++++++ test/service-module/model-methods.test.ts | 13 ++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/test/service-module/model-instance-defaults.test.ts b/test/service-module/model-instance-defaults.test.ts index 0d8769bb..32a24fb4 100644 --- a/test/service-module/model-instance-defaults.test.ts +++ b/test/service-module/model-instance-defaults.test.ts @@ -14,6 +14,7 @@ import { feathersSocketioClient } from '../fixtures/feathers-client' import Vuex from 'vuex' +import { makeContext as makeLetterContext } from './model-methods.test' interface TodoState extends ServiceState { test: any @@ -461,4 +462,19 @@ describe('Models - Default Values', function () { 'Setter is in place' ) }) + + it('instanceDefaults in place after patch', async function () { + const { Letter, store, lettersService } = makeLetterContext() + let letter = new Letter({ name: 'Garmadon', age: 1025 }) + + letter = await letter.save() + + assert.equal(typeof letter.to, 'string', 'default to field still in place') + assert.equal(typeof letter.status, 'string', 'accessor prop still in place') + + letter = await letter.save() + + assert.equal(typeof letter.to, 'string', 'default to field still in place') + assert.equal(typeof letter.status, 'string', 'accessor prop still in place') + }) }) diff --git a/test/service-module/model-methods.test.ts b/test/service-module/model-methods.test.ts index acedef7b..9540a9d6 100644 --- a/test/service-module/model-methods.test.ts +++ b/test/service-module/model-methods.test.ts @@ -76,10 +76,19 @@ function makeContext() { } class Letter extends BaseModel { - public static modelName = 'Letter' public constructor(data?, options?) { super(data, options) } + public static modelName = 'Letter' + public static instanceDefaults(data, { models, store }) { + return { + to: '', + from: '' + } + } + public get status() { + return 'pending' + } } const store = new Vuex.Store({ @@ -111,6 +120,8 @@ function makeContext() { } } +export { makeContext } + describe('Models - Methods', function () { beforeEach(() => { clearModels() From 9f112dd28230c00ed7744fc6510d9209d0322734 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 27 Jun 2019 10:43:48 -0700 Subject: [PATCH 267/404] 2.0.0-pre.45 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 48983eb0..46b49120 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.44", + "version": "2.0.0-pre.45", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 98d311e4..556d504b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.44", + "version": "2.0.0-pre.45", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 7ea70f9548f300fffa296874a3bdee4fe03347d1 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 30 Jun 2019 22:14:05 -0700 Subject: [PATCH 268/404] Remove diffOnPatch option The same functionality can now be provided by using a custom Model class. --- package.json | 2 - src/index.ts | 1 - src/service-module/make-model.ts | 3 + src/service-module/service-module.actions.ts | 19 +- src/service-module/service-module.state.ts | 2 +- yarn.lock | 950 ++++++++++++++++--- 6 files changed, 843 insertions(+), 134 deletions(-) diff --git a/package.json b/package.json index 556d504b..a91bd4c6 100644 --- a/package.json +++ b/package.json @@ -101,14 +101,12 @@ "@feathersjs/adapter-commons": "^2.0.0", "@feathersjs/commons": "^4.0.0", "@feathersjs/errors": "^3.3.6", - "@types/deep-diff": "^1.0.0", "@types/feathersjs__feathers": "^3.1.1", "@types/inflection": "^1.5.28", "@types/lodash": "^4.14.123", "@types/npm": "^2.0.30", "bson-objectid": "^1.2.4", "debug": "^4.1.1", - "deep-diff": "^1.0.2", "fast-copy": "^1.2.4", "inflection": "^1.12.0", "jwt-decode": "^2.2.0", diff --git a/src/index.ts b/src/index.ts index cc1420a3..1c9e8c88 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,7 +20,6 @@ import { FeathersVuex } from './vue-plugin/vue-plugin' const defaultOptions: FeathersVuexOptions = { autoRemove: false, // Automatically remove records missing from responses (only use with feathers-rest) addOnUpsert: false, // Add new records pushed by 'updated/patched' socketio events into store, instead of discarding them - diffOnPatch: true, // Only send changed data on patch. Sends the full object if set to false. enableEvents: true, // Listens to socket.io events when available idField: 'id', // The field in each record that will contain the id tempIdField: '__id', diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 2a09f19f..8e05f4f6 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -54,6 +54,9 @@ export default function makeModel(options: FeathersVuexOptions) { public static setupInstance(data, { models, store }) { return data } + public static diffOnPatch(data) { + return data + } // Monkey patched onto the Model class in `makeServicePlugin()` public static store: Record diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 27b92421..51aaee62 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -3,7 +3,6 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import { observableDiff, applyChange } from 'deep-diff' import fastCopy from 'fast-copy' import { getId } from '../utils' @@ -154,21 +153,9 @@ export default function makeServiceActions(service) { params = fastCopy(params) - // This needs to be re-built, since we've removed state.copy - // if (diffOnPatch) { - // let diff = {} - - // observableDiff(state.keyedById[id], data, function(d) { - // if (d.path && d.path.length) { - // // Apply all changes except to the id property... - // if (d.path[d.path.length - 1] !== idField) { - // applyChange(diff, data, d) - // } - // } - // }) - - // data = diff - // } + if (service.FeathersVuexModel) { + data = diffOnPatch(data) + } return service .patch(id, data, params) diff --git a/src/service-module/service-module.state.ts b/src/service-module/service-module.state.ts index 3bff0d4e..c14d9208 100644 --- a/src/service-module/service-module.state.ts +++ b/src/service-module/service-module.state.ts @@ -43,7 +43,7 @@ export default function makeDefaultState(servicePath, options) { if (options.Model) { // @ts-ignore - state.modelName = options.Model.name + state.modelName = options.Model.modelName } const startingState = _omit(options, nonStateProps) diff --git a/yarn.lock b/yarn.lock index 0bee399d..df4d860f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -819,7 +819,7 @@ "@feathersjs/commons" "^4.0.0" "@feathersjs/errors" "^3.3.6" -"@feathersjs/authentication-client@^1.0.10": +"@feathersjs/authentication-client@^1.0.11": version "1.0.11" resolved "https://registry.yarnpkg.com/@feathersjs/authentication-client/-/authentication-client-1.0.11.tgz#86352bf4c7179b905c9a977b26f389830c974e72" integrity sha512-4CWQdmdRINMMqHT1/g0N5jqw16u1RjaSPhlZtJZ0OLdqgN3tl5wL+Lb8ThPxihvt1WHiOdwGt141LvWQ446Bsw== @@ -828,7 +828,7 @@ debug "^4.0.0" jwt-decode "^2.1.0" -"@feathersjs/authentication-jwt@^2.0.9": +"@feathersjs/authentication-jwt@^2.0.10": version "2.0.10" resolved "https://registry.yarnpkg.com/@feathersjs/authentication-jwt/-/authentication-jwt-2.0.10.tgz#f8ec25d1230552b311af21822c5974cbc5f99b5e" integrity sha512-4IVBXDa4w17rroWiSM6LpSzUVG9Za1x1t7fioSObYt60PTkY7QunZt77GkdWfTNLNFvV++VVZ5tGFN6kfIKqCA== @@ -840,7 +840,7 @@ lodash.pick "^4.4.0" passport-jwt "^4.0.0" -"@feathersjs/client@^3.7.7": +"@feathersjs/client@^3.7.8": version "3.7.8" resolved "https://registry.yarnpkg.com/@feathersjs/client/-/client-3.7.8.tgz#a17e8c241e91a6d80dedf5c187443b416a3e7c82" integrity sha512-SsLVU6wq1PToBCC3XAvMRV18RBqCG1Ipt0G0+cyNKvYpcKW238Prvw7uYyAxPyQw+JL1c0xHkyDId03Duu6ZTA== @@ -925,11 +925,50 @@ "@shellscape/koa-send" "^4.1.0" debug "^2.6.8" +"@types/chai@^4.1.7": + version "4.1.7" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.7.tgz#1b8e33b61a8c09cbe1f85133071baa0dbf9fa71a" + integrity sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA== + +"@types/eslint-visitor-keys@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" + integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== + +"@types/feathersjs__feathers@^3.1.1": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@types/feathersjs__feathers/-/feathersjs__feathers-3.1.5.tgz#4a2b3ef7d561c64c08b82463276d69119e7fc4b9" + integrity sha512-sv8sIp59wVLpDQs2Mo3t437KQxUCFSS0JrGjMcjLSdvFzjHB81IhHhVHnH5g4VBUa6Yt4INr1eOEq/Ql0Ij9+g== + dependencies: + "@types/node" "*" + +"@types/inflection@^1.5.28": + version "1.5.28" + resolved "https://registry.yarnpkg.com/@types/inflection/-/inflection-1.5.28.tgz#43d55e0d72cf333a2dffd9c4ec0407455a1b0931" + integrity sha1-Q9VeDXLPMzot/9nE7AQHRVobCTE= + +"@types/lodash@^4.14.123": + version "4.14.135" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.135.tgz#d2607c35dd68f70c2b35ba020c667493dedd8447" + integrity sha512-Ed+tSZ9qM1oYpi5kzdsBuOzcAIn1wDW+e8TFJ50IMJMlSopGdJgKAbhHzN6h1E1OfjlGOr2JepzEWtg9NIfoNg== + +"@types/mocha@^5.2.6": + version "5.2.7" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" + integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== + "@types/node@*": version "11.9.4" resolved "https://registry.yarnpkg.com/@types/node/-/node-11.9.4.tgz#ceb0048a546db453f6248f2d1d95e937a6f00a14" integrity sha512-Zl8dGvAcEmadgs1tmSPcvwzO1YRsz38bVJQvH1RvRqSR9/5n61Q1ktcDL0ht3FXWR+ZpVmXVwN1LuH4Ax23NsA== +"@types/npm@^2.0.30": + version "2.0.30" + resolved "https://registry.yarnpkg.com/@types/npm/-/npm-2.0.30.tgz#871ce96be7c3a89687e240569f382bc687488600" + integrity sha512-juetEKXQJZlVrhRg3Z8WAKFeUr2sRapp8IGOxOaWI07rrrt0T0lgLiv7NtpqoP6Ul/If5vD0/17C0Q84saiwBg== + dependencies: + "@types/node" "*" + "@types/socket.io@~1.4.27": version "1.4.40" resolved "https://registry.yarnpkg.com/@types/socket.io/-/socket.io-1.4.40.tgz#4f6955a8bdab66f8af47edcebea038f89aea7ad2" @@ -937,6 +976,43 @@ dependencies: "@types/node" "*" +"@typescript-eslint/eslint-plugin@^1.1.0", "@typescript-eslint/eslint-plugin@^1.5.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.11.0.tgz#870f752c520db04db6d3668af7479026a6f2fb9a" + integrity sha512-mXv9ccCou89C8/4avKHuPB2WkSZyY/XcTQUXd5LFZAcLw1I3mWYVjUu6eS9Ja0QkP/ClolbcW9tb3Ov/pMdcqw== + dependencies: + "@typescript-eslint/experimental-utils" "1.11.0" + eslint-utils "^1.3.1" + functional-red-black-tree "^1.0.1" + regexpp "^2.0.1" + tsutils "^3.7.0" + +"@typescript-eslint/experimental-utils@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-1.11.0.tgz#594abe47091cbeabac1d6f9cfed06d0ad99eb7e3" + integrity sha512-7LbfaqF6B8oa8cp/315zxKk8FFzosRzzhF8Kn/ZRsRsnpm7Qcu25cR/9RnAQo5utZ2KIWVgaALr+ZmcbG47ruw== + dependencies: + "@typescript-eslint/typescript-estree" "1.11.0" + eslint-scope "^4.0.0" + +"@typescript-eslint/parser@^1.1.0", "@typescript-eslint/parser@^1.5.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-1.11.0.tgz#2f6d4f7e64eeb1e7c25b422f8df14d0c9e508e36" + integrity sha512-5xBExyXaxVyczrZvbRKEXvaTUFFq7gIM9BynXukXZE0zF3IQP/FxF4mPmmh3gJ9egafZFqByCpPTFm3dk4SY7Q== + dependencies: + "@types/eslint-visitor-keys" "^1.0.0" + "@typescript-eslint/experimental-utils" "1.11.0" + "@typescript-eslint/typescript-estree" "1.11.0" + eslint-visitor-keys "^1.0.0" + +"@typescript-eslint/typescript-estree@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-1.11.0.tgz#b7b5782aab22e4b3b6d84633652c9f41e62d37d5" + integrity sha512-fquUHF5tAx1sM2OeRCC7wVxFd1iMELWMGCzOSmJ3pLzArj9+kRixdlC4d5MncuzXpjEqc6045p3KwM0o/3FuUA== + dependencies: + lodash.unescape "4.0.1" + semver "5.5.0" + "@vue/babel-preset-app@3.0.0-beta.11": version "3.0.0-beta.11" resolved "https://registry.yarnpkg.com/@vue/babel-preset-app/-/babel-preset-app-3.0.0-beta.11.tgz#c8b889aa73464050f9cd3f9dc621951d85c24508" @@ -966,6 +1042,31 @@ source-map "~0.6.1" vue-template-es2015-compiler "^1.8.2" +"@vue/eslint-config-prettier@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@vue/eslint-config-prettier/-/eslint-config-prettier-4.0.1.tgz#a036d0d2193c5c836542b35a3a7c35c4e1c68c97" + integrity sha512-rJEDXPb61Hfgg8GllO3XXFP98bcIxdNNHSrNcxP/vBSukOolgOwQyZJ5f5z/c7ViPyh5/IDlC4qBnhx/0n+I4g== + dependencies: + eslint-config-prettier "^3.3.0" + eslint-plugin-prettier "^3.0.0" + prettier "^1.15.2" + +"@vue/eslint-config-typescript@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@vue/eslint-config-typescript/-/eslint-config-typescript-4.0.0.tgz#a202983598a4a826460cbb8ee43826875b0f6673" + integrity sha512-uSMAMgw4xDgVdZQhpbtJRo8nMV4oOy3Ht8olfOo7xvYFYLMF2JZ1tDRKd9/NSusxA72O2Vma+HzmyzDHg9evcQ== + dependencies: + "@typescript-eslint/eslint-plugin" "^1.1.0" + "@typescript-eslint/parser" "^1.1.0" + +"@vue/test-utils@^1.0.0-beta.29": + version "1.0.0-beta.29" + resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.29.tgz#c942cf25e891cf081b6a03332b4ae1ef430726f0" + integrity sha512-yX4sxEIHh4M9yAbLA/ikpEnGKMNBCnoX98xE1RwxfhQVcn0MaXNSj1Qmac+ZydTj6VBSEVukchBogXBTwc+9iA== + dependencies: + dom-event-types "^1.0.0" + lodash "^4.17.4" + "@webassemblyjs/ast@1.8.3": version "1.8.3" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.3.tgz#63a741bd715a6b6783f2ea5c6ab707516aa215eb" @@ -1154,6 +1255,11 @@ Base64@~0.2.0: resolved "https://registry.yarnpkg.com/Base64/-/Base64-0.2.1.tgz#ba3a4230708e186705065e66babdd4c35cf60028" integrity sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg= +abab@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f" + integrity sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w== + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -1177,11 +1283,29 @@ acorn-dynamic-import@^4.0.0: resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== +acorn-globals@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.2.tgz#4e2c2313a597fd589720395f6354b41cd5ec8006" + integrity sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ== + dependencies: + acorn "^6.0.1" + acorn-walk "^6.0.1" + acorn-jsx@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== +acorn-walk@^6.0.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.1.tgz#d363b66f5fac5f018ff9c3a1e7b6f8e310cc3913" + integrity sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw== + +acorn@^6.0.1, acorn@^6.0.4, acorn@^6.0.7: + version "6.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" + integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== + acorn@^6.0.2, acorn@^6.0.5: version "6.1.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.0.tgz#b0a3be31752c97a0f7013c5f4903b71a05db6818" @@ -1224,6 +1348,16 @@ ajv@^6.0.1, ajv@^6.1.0, ajv@^6.5.0, ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.9.1: + version "6.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" + integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + algoliasearch@^3.24.5: version "3.32.0" resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-3.32.0.tgz#5818168c26ff921bd0346a919071bac928b747ce" @@ -1267,7 +1401,7 @@ ansi-colors@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== -ansi-escapes@^3.0.0: +ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== @@ -1282,12 +1416,17 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= -ansi-styles@^3.2.1: +ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -1345,6 +1484,11 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" +arg@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.0.tgz#583c518199419e0037abb74062c37f8519e575f0" + integrity sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1374,6 +1518,11 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" + integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= + array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" @@ -1462,6 +1611,11 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + async-each@^1.0.0, async-each@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" @@ -2322,6 +2476,11 @@ better-assert@~1.0.0: dependencies: callsite "1.0.0" +big-integer@^1.6.17: + version "1.6.44" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.44.tgz#4ee9ae5f5839fc11ade338fea216b4513454a539" + integrity sha512-7MzElZPTyJ2fNvBkPxtFQ2fWIkVmuzw41+BZHSzpEq3ymB2MfeKp1+yXl/tS75xCx+WnyV+yb0kp+K1C3UNwmQ== + big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" @@ -2337,7 +2496,7 @@ binary-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.0.tgz#9523e001306a32444b907423f1de2164222f6ab1" integrity sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw== -"binary@>= 0.3.0 < 1": +binary@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79" integrity sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk= @@ -2355,6 +2514,11 @@ bluebird@^3.1.1, bluebird@^3.5.1, bluebird@^3.5.3: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== +bluebird@~3.4.1: + version "3.4.7" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" + integrity sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM= + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" @@ -2432,6 +2596,11 @@ brorand@^1.0.1: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= +browser-process-hrtime@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" + integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw== + browser-stdout@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" @@ -2524,12 +2693,18 @@ browserstack@^1.2.0: dependencies: https-proxy-agent "^2.2.1" -browserstacktunnel-wrapper@^1.2.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-1.4.2.tgz#6598fb7d784b6ff348e3df7c104b0d9c27ea5275" - integrity sha1-ZZj7fXhLb/NI4998EEsNnCfqUnU= +browserstacktunnel-wrapper@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-2.0.4.tgz#0ebffd3d6311b8526c30d8b430fdc651a535eebb" + integrity sha512-GCV599FUUxNOCFl3WgPnfc5dcqq9XTmMXoxWpqkvmk0R9TOIoqmjENNU6LY6DtgIL6WfBVbg/jmWtnM5K6UYSg== dependencies: - unzip "~0.1.9" + https-proxy-agent "^2.2.1" + unzipper "^0.9.3" + +bson-objectid@^1.2.4: + version "1.3.0" + resolved "https://registry.yarnpkg.com/bson-objectid/-/bson-objectid-1.3.0.tgz#f0f4c7c949fece975f12790510d75d7fe39fb456" + integrity sha512-YcB+lRJEEEIcHNLKyhmHujW7OCVE3+xr9IpEhlprBZnXgF3hqeePeexIsAaOtu1SbkgZRlJVUxvYZ3ngUOyIew== buffer-equal-constant-time@1.0.1: version "1.0.1" @@ -2541,6 +2716,11 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== +buffer-indexof-polyfill@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.1.tgz#a9fb806ce8145d5428510ce72f278bb363a638bf" + integrity sha1-qfuAbOgUXVQoUQznLyeLs2OmOL8= + buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -2691,6 +2871,11 @@ callsites@^2.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + camel-case@3.0.x: version "3.0.0" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" @@ -2921,6 +3106,11 @@ chardet@^0.4.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + check-error@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" @@ -3593,6 +3783,18 @@ csso@~2.3.1: clap "^1.0.9" source-map "^0.5.3" +cssom@0.3.x, cssom@^0.3.4: + version "0.3.6" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.6.tgz#f85206cee04efa841f3c5982a74ba96ab20d65ad" + integrity sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A== + +cssstyle@^1.1.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.2.2.tgz#427ea4d585b18624f6fdbf9de7a2a1a3ba713077" + integrity sha512-43wY3kl1CVQSvL7wUY1qXkxVGkStjpkDmVjiIKX8R97uhajy8Bybay78uOtqvh7Q5GK75dNPfW0geWjE6qQQow== + dependencies: + cssom "0.3.x" + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -3619,6 +3821,15 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-urls@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" + integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ== + dependencies: + abab "^2.0.0" + whatwg-mimetype "^2.2.0" + whatwg-url "^7.0.0" + date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" @@ -3634,7 +3845,7 @@ debug-log@^1.0.0: resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" integrity sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8= -debug@*, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@~4.1.0: +debug@*, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@~4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -3680,11 +3891,6 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= -deep-diff@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-1.0.2.tgz#afd3d1f749115be965e89c63edc7abb1506b9c26" - integrity sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg== - deep-eql@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" @@ -3835,6 +4041,11 @@ diff@3.5.0: resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== +diff@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" + integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -3887,6 +4098,13 @@ doctrine@^2.1.0: dependencies: esutils "^2.0.2" +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + dom-converter@~0.2: version "0.2.0" resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" @@ -3894,6 +4112,11 @@ dom-converter@~0.2: dependencies: utila "~0.4" +dom-event-types@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dom-event-types/-/dom-event-types-1.0.0.tgz#5830a0a29e1bf837fe50a70cd80a597232813cae" + integrity sha512-2G2Vwi2zXTHBGqXHsJ4+ak/iP0N8Ar+G8a7LiD2oup5o4sQWytwqqrZu/O6hIMV0KMID2PL69OhpshLO0n7UJQ== + dom-serializer@0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" @@ -3922,6 +4145,13 @@ domelementtype@1, domelementtype@^1.3.0: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== +domexception@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" + integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== + dependencies: + webidl-conversions "^4.0.2" + domhandler@2.1: version "2.1.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.1.0.tgz#d2646f5e57f6c3bab11cf6cb05d3c0acf7412594" @@ -3951,6 +4181,13 @@ dot-prop@^4.1.0: dependencies: is-obj "^1.0.0" +duplexer2@~0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" + integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME= + dependencies: + readable-stream "^2.0.2" + duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" @@ -4004,6 +4241,11 @@ elliptic@^6.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -4188,6 +4430,32 @@ escodegen@1.8.x: optionalDependencies: source-map "~0.2.0" +escodegen@^1.11.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.1.tgz#c485ff8d6b4cdb89e27f4a856e91f118401ca510" + integrity sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw== + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +eslint-config-prettier@^3.3.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-3.6.0.tgz#8ca3ffac4bd6eeef623a0651f9d754900e3ec217" + integrity sha512-ixJ4U3uTLXwJts4rmSVW/lMXjlGwCijhBJHk8iVqKKSifeI0qgFEfWl8L63isfc8Od7EiBALF6BX3jKLluf/jQ== + dependencies: + get-stdin "^6.0.0" + +eslint-config-prettier@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-4.3.0.tgz#c55c1fcac8ce4518aeb77906984e134d9eb5a4f0" + integrity sha512-sZwhSTHVVz78+kYD3t5pCWSYEdVSBR0PXnwjDRsUs8ytIrK8PLXw+6FKp8r3Z7rx4ZszdetWlXYKOHoUrrwPlA== + dependencies: + get-stdin "^6.0.0" + eslint-config-standard-jsx@6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/eslint-config-standard-jsx/-/eslint-config-standard-jsx-6.0.2.tgz#90c9aa16ac2c4f8970c13fc7efc608bacd02da70" @@ -4250,6 +4518,13 @@ eslint-plugin-node@~7.0.1: resolve "^1.8.1" semver "^5.5.0" +eslint-plugin-prettier@^3.0.0, eslint-plugin-prettier@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.0.tgz#8695188f95daa93b0dc54b249347ca3b79c4686d" + integrity sha512-XWX2yVuwVNLOUhQijAkXz+rMPPoCr7WFiAl8ig6I7Xn+pPVhDhzg4DxHpmbeb0iqjO9UronEA3Tb09ChnFVHHA== + dependencies: + prettier-linter-helpers "^1.0.0" + eslint-plugin-promise@~4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz#2d074b653f35a23d1ba89d8e976a985117d1c6a2" @@ -4271,6 +4546,13 @@ eslint-plugin-standard@~4.0.0: resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz#f845b45109c99cd90e77796940a344546c8f6b5c" integrity sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA== +eslint-plugin-vue@^5.2.2: + version "5.2.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-5.2.3.tgz#3ee7597d823b5478804b2feba9863b1b74273961" + integrity sha512-mGwMqbbJf0+VvpGR5Lllq0PMxvTdrZ/ZPjmhkacrCHbubJeJOt+T6E3HUzAifa2Mxi7RSdJfC9HFpOeSYVMMIw== + dependencies: + vue-eslint-parser "^5.0.0" + eslint-scope@3.7.1: version "3.7.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" @@ -4287,6 +4569,14 @@ eslint-scope@^4.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-utils@^1.3.0, eslint-utils@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512" @@ -4297,6 +4587,48 @@ eslint-visitor-keys@^1.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== +eslint@^5.16.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" + integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.9.1" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^4.0.3" + eslint-utils "^1.3.1" + eslint-visitor-keys "^1.0.0" + espree "^5.0.1" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^6.2.2" + js-yaml "^3.13.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.11" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^5.5.1" + strip-ansi "^4.0.0" + strip-json-comments "^2.0.1" + table "^5.2.3" + text-table "^0.2.0" + eslint@~5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.4.0.tgz#d068ec03006bb9e06b429dc85f7e46c1b69fac62" @@ -4341,7 +4673,7 @@ eslint@~5.4.0: table "^4.0.3" text-table "^0.2.0" -espree@^4.0.0: +espree@^4.0.0, espree@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/espree/-/espree-4.1.0.tgz#728d5451e0fd156c04384a7ad89ed51ff54eb25f" integrity sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w== @@ -4350,11 +4682,25 @@ espree@^4.0.0: acorn-jsx "^5.0.0" eslint-visitor-keys "^1.0.0" +espree@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" + integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== + dependencies: + acorn "^6.0.7" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" + esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= +esprima@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= + esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -4379,7 +4725,7 @@ estraverse@^1.9.1: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= @@ -4535,6 +4881,15 @@ external-editor@^2.1.0: iconv-lite "^0.4.17" tmp "^0.0.33" +external-editor@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" + integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" @@ -4566,7 +4921,7 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -fast-copy@^1.2.3: +fast-copy@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-1.2.4.tgz#456e3b3ccf57a3c81f5223f2882532fca0c3f4a7" integrity sha512-LCRjn7/wRBxeM//UVnya1eejlpiNTNz7MsAJnQXUSqkJwvzG35inF/GHDbispN0041A/Rhtuk06xS4IA4YNMBg== @@ -4576,6 +4931,11 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-glob@^2.0.2: version "2.2.6" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.6.tgz#a5d5b697ec8deda468d85a74035290a025a95295" @@ -4627,7 +4987,7 @@ feathers-memory@^1.0.1: sift "^5.0.0" uberproto "^1.2.0" -feathers-memory@^3.0.1: +feathers-memory@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/feathers-memory/-/feathers-memory-3.0.2.tgz#f6e8128ff8939d74930c2771ff0c4c20f04d6b88" integrity sha512-GlSYSlIgN5BhvGaCi2AMaltteJvmCOoA5u9j1dIwnwWveF4586TLGsUKu1CASisva5DVczDlmIltq+GJpO6D7w== @@ -4707,6 +5067,13 @@ file-entry-cache@^2.0.0: flat-cache "^1.2.1" object-assign "^4.0.1" +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + file-loader@^1.1.11: version "1.1.11" resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-1.1.11.tgz#6fe886449b0f2a936e43cabaac0cdbfb369506f8" @@ -4817,6 +5184,20 @@ flat-cache@^1.2.1: rimraf "~2.6.2" write "^0.2.1" +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" + integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== + flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" @@ -4963,14 +5344,14 @@ fsevents@^1.0.0, fsevents@^1.2.7: nan "^2.9.2" node-pre-gyp "^0.10.0" -"fstream@>= 0.1.30 < 1": - version "0.1.31" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-0.1.31.tgz#7337f058fbbbbefa8c9f561a28cab0849202c988" - integrity sha1-czfwWPu7vvqMn1YaKMqwhJICyYg= +fstream@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" + integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== dependencies: - graceful-fs "~3.0.2" + graceful-fs "^4.1.2" inherits "~2.0.0" - mkdirp "0.5" + mkdirp ">=0.5 0" rimraf "2" function-bind@^1.1.1: @@ -5193,13 +5574,6 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== -graceful-fs@~3.0.2: - version "3.0.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818" - integrity sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg= - dependencies: - natives "^1.1.0" - gray-matter@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.2.tgz#9aa379e3acaf421193fce7d2a28cebd4518ac454" @@ -5397,6 +5771,13 @@ html-comment-regex@^1.1.0: resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== +html-encoding-sniffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" + integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== + dependencies: + whatwg-encoding "^1.0.1" + html-minifier@^3.2.3: version "3.5.21" resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.21.tgz#d0040e054730e354db008463593194015212d20c" @@ -5495,7 +5876,7 @@ iconv-lite@0.4.23: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.4.17, iconv-lite@^0.4.4: +iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -5536,7 +5917,7 @@ ignore@^3.0.9, ignore@^3.3.5: resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== -ignore@^4.0.2: +ignore@^4.0.2, ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== @@ -5561,6 +5942,14 @@ import-fresh@^2.0.0: caller-path "^2.0.0" resolve-from "^3.0.0" +import-fresh@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" + integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + import-from@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" @@ -5648,6 +6037,25 @@ inquirer@^5.2.0: strip-ansi "^4.0.0" through "^2.3.6" +inquirer@^6.2.2: + version "6.4.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.4.1.tgz#7bd9e5ab0567cd23b41b0180b68e0cfa82fc3c0b" + integrity sha512-/Jw+qPZx4EDYsaT6uz7F4GJRNFMRdKNeUZw3ZnKV8lyuUgz/YWRCSUAJMZSVhSq4Ec0R2oYnyi6b3d4JXcL5Nw== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.11" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + interpret@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" @@ -6166,6 +6574,14 @@ js-yaml@3.x, js-yaml@^3.11.0, js-yaml@^3.7.0, js-yaml@^3.9.0: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@^3.13.0: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@~3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" @@ -6179,6 +6595,43 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= +jsdom-global@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/jsdom-global/-/jsdom-global-3.0.2.tgz#6bd299c13b0c4626b2da2c0393cd4385d606acb9" + integrity sha1-a9KZwTsMRiay2iwDk81DhdYGrLk= + +jsdom@^14.0.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-14.1.0.tgz#916463b6094956b0a6c1782c94e380cd30e1981b" + integrity sha512-O901mfJSuTdwU2w3Sn+74T+RnDVP+FuV5fH8tcPWyqrseRAb0s5xOtPgCFiPOtLcyK7CLIJwPyD83ZqQWvA5ng== + dependencies: + abab "^2.0.0" + acorn "^6.0.4" + acorn-globals "^4.3.0" + array-equal "^1.0.0" + cssom "^0.3.4" + cssstyle "^1.1.1" + data-urls "^1.1.0" + domexception "^1.0.1" + escodegen "^1.11.0" + html-encoding-sniffer "^1.0.2" + nwsapi "^2.1.3" + parse5 "5.1.0" + pn "^1.1.0" + request "^2.88.0" + request-promise-native "^1.0.5" + saxes "^3.1.9" + symbol-tree "^3.2.2" + tough-cookie "^2.5.0" + w3c-hr-time "^1.0.1" + w3c-xmlserializer "^1.1.2" + webidl-conversions "^4.0.2" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^7.0.0" + ws "^6.1.2" + xml-name-validator "^3.0.0" + jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" @@ -6450,10 +6903,10 @@ latest-version@^3.0.0: dependencies: package-json "^4.0.0" -launchpad@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/launchpad/-/launchpad-0.6.0.tgz#6a122deaa3cbd7b9bedc13e7c8dd20a90951aaa3" - integrity sha1-ahIt6qPL17m+3BPnyN0gqQlRqqM= +launchpad@^0.7.1: + version "0.7.2" + resolved "https://registry.yarnpkg.com/launchpad/-/launchpad-0.7.2.tgz#88de897d7f9e664cdab94a680fd1470b58bf5f31" + integrity sha512-nmfx8QWqCvAmukHPticyO3+frnUKp0tDKXz3Au570XHBE0G1lNyN+KSODHgTqIIEuCIAlAgpbWjI36Vjk1mDKA== dependencies: async "^2.0.1" browserstack "^1.2.0" @@ -6484,6 +6937,11 @@ linkify-it@^2.0.0: dependencies: uc.micro "^1.0.1" +listenercount@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937" + integrity sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc= + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -6650,6 +7108,11 @@ lodash.pick@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= + lodash.template@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0" @@ -6675,6 +7138,11 @@ lodash.trim@^4.5.1: resolved "https://registry.yarnpkg.com/lodash.trim/-/lodash.trim-4.5.1.tgz#36425e7ee90be4aa5e27bcebb85b7d11ea47aa57" integrity sha1-NkJefukL5KpeJ7zruFt9EepHqlc= +lodash.unescape@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" + integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= + lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" @@ -6756,6 +7224,11 @@ make-dir@^1.0.0: dependencies: pify "^3.0.0" +make-error@^1.1.1: + version "1.3.5" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" + integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== + mamacro@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" @@ -6814,14 +7287,6 @@ markdown-it@^8.4.1: mdurl "^1.0.1" uc.micro "^1.0.5" -"match-stream@>= 0.0.2 < 1": - version "0.0.2" - resolved "https://registry.yarnpkg.com/match-stream/-/match-stream-0.0.2.tgz#99eb050093b34dffade421b9ac0b410a9cfa17cf" - integrity sha1-mesFAJOzTf+t5CG5rAtBCpz6F88= - dependencies: - buffers "~0.1.1" - readable-stream "~1.0.0" - math-expression-evaluator@^1.2.14: version "1.2.17" resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" @@ -6988,12 +7453,12 @@ min-document@^2.19.0: dependencies: dom-walk "^0.1.0" -miner@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/miner/-/miner-0.2.1.tgz#b3224148f97b65ae4296b5054984f2276056b124" - integrity sha1-syJBSPl7Za5ClrUFSYTyJ2BWsSQ= +miner@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/miner/-/miner-1.0.0.tgz#9050026c804539479f46b2564cde81c9c8eea40c" + integrity sha512-+m7Y0fN4cmRh8iwoeWTeza88+8aUVK8Ru1g6/XdosLxW9Vhf63CcneSBcGfFXotnKBNtxj5O8b1JUoWld2rM7g== dependencies: - browserstacktunnel-wrapper "^1.2.1" + browserstacktunnel-wrapper "^2.0.4" localtunnel "^1.2.0" mini-css-extract-plugin@0.4.1: @@ -7113,7 +7578,7 @@ mkdirp@0.3.0: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" integrity sha1-G79asbqCevI1dRQ0kEJkVfSB/h4= -mkdirp@0.5, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -7240,11 +7705,6 @@ nanotiming@^7.2.0: nanoassert "^1.1.0" nanoscheduler "^1.0.2" -natives@^1.1.0: - version "1.1.6" - resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.6.tgz#a603b4a498ab77173612b9ea1acdec4d980f00bb" - integrity sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -7442,6 +7902,11 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= +nwsapi@^2.1.3: + version "2.1.4" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.1.4.tgz#e006a878db23636f8e8a67d33ca0e4edf61a842f" + integrity sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw== + oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" @@ -7621,11 +8086,6 @@ output-file-sync@^1.1.2: mkdirp "^0.5.1" object-assign "^4.1.0" -"over@>= 0.0.5 < 1": - version "0.0.5" - resolved "https://registry.yarnpkg.com/over/-/over-0.0.5.tgz#f29852e70fd7e25f360e013a8ec44c82aedb5708" - integrity sha1-8phS5w/X4l82DgE6jsRMgq7bVwg= - p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -7700,6 +8160,13 @@ param-case@2.1.x: dependencies: no-case "^2.2.0" +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + parse-asn1@^5.0.0: version "5.1.4" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" @@ -7737,6 +8204,11 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse5@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" + integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== + parseqs@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" @@ -7945,6 +8417,11 @@ pluralize@^7.0.0: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== +pn@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" + integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== + portfinder@^1.0.13: version "1.0.20" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.20.tgz#bea68632e54b2e13ab7b0c4775e9b41bf270e44a" @@ -8289,11 +8766,23 @@ preserve@^0.2.0: resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + prettier@1.16.3: version "1.16.3" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.3.tgz#8c62168453badef702f34b45b6ee899574a6a65d" integrity sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw== +prettier@^1.15.2, prettier@^1.16.4: + version "1.18.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" + integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== + pretty-bytes@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9" @@ -8381,6 +8870,11 @@ psl@^1.1.24: resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184" integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw== +psl@^1.1.28: + version "1.1.33" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.33.tgz#5533d9384ca7aab86425198e10e8053ebfeab661" + integrity sha512-LTDP2uSrsc7XCb5lO7A8BI1qYxRe/8EqlRvMeEl6rsnYAqDOl8xHR+8lSAIVfrNaSAlTPTNOCgNjWcoUL3AZsw== + public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" @@ -8393,16 +8887,6 @@ public-encrypt@^4.0.0: randombytes "^2.0.1" safe-buffer "^5.1.2" -"pullstream@>= 0.4.1 < 1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/pullstream/-/pullstream-0.4.1.tgz#d6fb3bf5aed697e831150eb1002c25a3f8ae1314" - integrity sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ= - dependencies: - over ">= 0.0.5 < 1" - readable-stream "~1.0.31" - setimmediate ">= 1.0.2 < 2" - slice-stream ">= 1.0.0 < 2" - pump@^2.0.0, pump@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" @@ -8433,7 +8917,7 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@2.x.x, punycode@^2.1.0: +punycode@2.x.x, punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== @@ -8609,7 +9093,7 @@ read-pkg@^3.0.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@1.0, readable-stream@~1.0.0, readable-stream@~1.0.31: +readable-stream@1.0: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= @@ -8841,7 +9325,23 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@^2.87.0: +request-promise-core@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346" + integrity sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag== + dependencies: + lodash "^4.17.11" + +request-promise-native@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.7.tgz#a49868a624bdea5069f1251d0a836e0d89aa2c59" + integrity sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w== + dependencies: + request-promise-core "1.1.2" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +request@^2.87.0, request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== @@ -8912,6 +9412,11 @@ resolve-from@^3.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" integrity sha1-six699nWiBvItuZTM17rywoYh0g= +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + resolve-path@^1.3.3, resolve-path@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/resolve-path/-/resolve-path-1.4.0.tgz#c4bda9f5efb2fce65247873ab36bb4d834fe16f7" @@ -8950,7 +9455,7 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -rimraf@2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2: +rimraf@2, rimraf@2.6.3, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -8996,6 +9501,13 @@ rxjs@^5.5.2: dependencies: symbol-observable "1.0.1" +rxjs@^6.4.0: + version "6.5.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7" + integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg== + dependencies: + tslib "^1.9.0" + safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -9023,6 +9535,13 @@ sax@^1.2.4, sax@~1.2.1: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +saxes@^3.1.9: + version "3.1.11" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-3.1.11.tgz#d59d1fd332ec92ad98a2e0b2ee644702384b1c5b" + integrity sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g== + dependencies: + xmlchars "^2.1.1" + schema-utils@^0.4.0, schema-utils@^0.4.2, schema-utils@^0.4.5: version "0.4.7" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187" @@ -9065,6 +9584,16 @@ semver-diff@^2.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== +semver@5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== + +semver@^5.5.1: + version "5.7.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" + integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== + send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" @@ -9129,7 +9658,7 @@ set-value@^2.0.0: is-plain-object "^2.0.3" split-string "^3.0.1" -"setimmediate@>= 1.0.1 < 2", "setimmediate@>= 1.0.2 < 2", setimmediate@^1.0.4: +setimmediate@^1.0.4, setimmediate@~1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= @@ -9218,12 +9747,14 @@ slice-ansi@1.0.0: dependencies: is-fullwidth-code-point "^2.0.0" -"slice-stream@>= 1.0.0 < 2": - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-stream/-/slice-stream-1.0.0.tgz#5b33bd66f013b1a7f86460b03d463dec39ad3ea0" - integrity sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA= +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== dependencies: - readable-stream "~1.0.31" + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" snapdragon-node@^2.0.1: version "2.1.1" @@ -9331,6 +9862,14 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" +source-map-support@^0.5.6: + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-support@~0.5.9: version "0.5.10" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" @@ -9509,6 +10048,14 @@ steal-mocha@^2.0.1: steal "^1.11.0" steal-css "^1.3.2" +steal-typescript@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/steal-typescript/-/steal-typescript-0.5.0.tgz#5f120dbb0536862545e21c792aa2b7bc9b16c0db" + integrity sha1-XxINuwU2hiVF4hx5KqK3vJsWwNs= + dependencies: + object-assign "^4.1.0" + typescript "^2.1.4" + steal@^1.11.0: version "1.12.6" resolved "https://registry.yarnpkg.com/steal/-/steal-1.12.6.tgz#02d6c9125d8ac4a8575ae233e48472299a898903" @@ -9533,10 +10080,10 @@ steal@^1.11.0: vm-browserify "~0.0.4" zlib-browserify "~0.0.3" -steal@^2.1.13: - version "2.1.14" - resolved "https://registry.yarnpkg.com/steal/-/steal-2.1.14.tgz#ffd0e383e6ec738edd5f942db7d0bc1a3df08fdf" - integrity sha512-mE3+LqExfPGhkpeVbK9HySc4t+f2S81tfH1RjcSZULQnV4jLu+HZXOd6AknGrgKQoiikPu/EJ50tFe3fx7ZlAA== +steal@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/steal/-/steal-2.2.1.tgz#5c67d34ab57d0b037e052dcbd3df05662f180384" + integrity sha512-3v1ZJ6ucEG6Rb4iY8hOMAMDBeSio1RTLeNpTD5t60JEkzBb95W9SI2Xg0gYg5Q9f7TAHGyioTx+eR9XzrLjmMA== dependencies: assert "~1.4.1" buffer "~5.0.4" @@ -9557,6 +10104,11 @@ steal@^2.1.13: vm-browserify "~0.0.4" zlib-browserify "~0.0.3" +stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" @@ -9621,6 +10173,15 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + string_decoder@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" @@ -9670,6 +10231,13 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + strip-bom-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" @@ -9805,6 +10373,11 @@ symbol-observable@1.0.1: resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" integrity sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ= +symbol-tree@^3.2.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + table@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc" @@ -9817,6 +10390,16 @@ table@^4.0.3: slice-ansi "1.0.0" string-width "^2.1.1" +table@^5.2.3: + version "5.4.1" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.1.tgz#0691ae2ebe8259858efb63e550b6d5f9300171e8" + integrity sha512-E6CK1/pZe2N75rGZQotFOdmzWQ1AILtgYbMAbAjvms0S1l5IDB47zG3nCnFGB/w+7nB3vKofbLXCH7HPBo864w== + dependencies: + ajv "^6.9.1" + lodash "^4.17.11" + slice-ansi "^2.1.0" + string-width "^3.0.0" + tapable@^1.0.0, tapable@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.1.tgz#4d297923c5a72a42360de2ab52dadfaaec00018e" @@ -9893,10 +10476,10 @@ testee-client@^0.5.0: feathers-rest "^1.5.0" superagent "^3.0.0" -testee@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/testee/-/testee-0.8.1.tgz#6752e907db8d7b898be238eea1fd553cfa65f318" - integrity sha512-lJ2HHDgPiU06NTYfMr5to7GZwO74plk5PugkfvY8W+pJzbkSCrhO2ruAzBTBX8kzPXO+EPpKv1Jx1lFVJ6aztQ== +testee@^0.9.0: + version "0.9.1" + resolved "https://registry.yarnpkg.com/testee/-/testee-0.9.1.tgz#5e3138332a0169c4481e7d573a483009b9280437" + integrity sha512-h6Iunv8LKQgcRKmTrE3LInrTl8oXTK7erEFVSCguyWXotY2hSsvOv2kPVnSOS903r/FWNktQuqkAJ/IyO4yXOQ== dependencies: babel-core "^6.24.0" babel-plugin-istanbul "^4.1.1" @@ -9910,10 +10493,10 @@ testee@^0.8.1: feathers-socketio "^2.0.1" http-proxy "^1.1.4" istanbul "^0.4.0" - launchpad "^0.6.0" + launchpad "^0.7.1" lodash "^4.17.10" mime-types "^2.1.6" - miner "^0.2.1" + miner "^1.0.0" mocha "^4.1.0" path "^0.12.7" testee-client "^0.5.0" @@ -10052,6 +10635,14 @@ toposort@^1.0.0: resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029" integrity sha1-LmhELZ9k7HILjMieZEOsbKqVACk= +tough-cookie@^2.3.3, tough-cookie@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" @@ -10060,6 +10651,13 @@ tough-cookie@~2.4.3: psl "^1.1.24" punycode "^1.4.1" +tr46@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= + dependencies: + punycode "^2.1.0" + "traverse@>=0.3.0 <0.4": version "0.3.9" resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" @@ -10075,11 +10673,34 @@ trim-right@^1.0.1: resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= +ts-node@^8.0.3: + version "8.3.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.3.0.tgz#e4059618411371924a1fb5f3b125915f324efb57" + integrity sha512-dyNS/RqyVTDcmNM4NIBAeDMpsAdaQ+ojdf0GOLqE6nwJOgzEkdRNzJywhDfwnuvB10oa6NLVG1rUJQCpRN7qoQ== + dependencies: + arg "^4.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.6" + yn "^3.0.0" + +tslib@^1.8.1: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + tslib@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== +tsutils@^3.7.0: + version "3.14.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.14.0.tgz#bf8d5a7bae5369331fa0f2b0a5a10bd7f7396c77" + integrity sha512-SmzGbB0l+8I0QwsPgjooFRaRvHLBLNYM8SeQ0k6rtNDru5sCGeLJcZdwilNndN+GysuFjF5EIYgN8GfFG6UeUw== + dependencies: + tslib "^1.8.1" + tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" @@ -10127,6 +10748,16 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typescript@^2.1.4: + version "2.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" + integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w== + +typescript@^3.4.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.2.tgz#a09e1dc69bc9551cadf17dba10ee42cf55e5d56c" + integrity sha512-7KxJovlYhTX5RaRbUdkAXN1KUZ8PwWlTzQdHV6xNqvuFOs7+WBo10TQUqT19Q/Jz2hk5v9TQDIhyLhhJY4p5AA== + uberproto@^1.1.0, uberproto@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/uberproto/-/uberproto-1.2.0.tgz#61d4eab024f909c4e6ea52be867c4894a4beeb76" @@ -10242,17 +10873,20 @@ unzip-response@^2.0.1: resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= -unzip@~0.1.9: - version "0.1.11" - resolved "https://registry.yarnpkg.com/unzip/-/unzip-0.1.11.tgz#89749c63b058d7d90d619f86b98aa1535d3b97f0" - integrity sha1-iXScY7BY19kNYZ+GuYqhU107l/A= - dependencies: - binary ">= 0.3.0 < 1" - fstream ">= 0.1.30 < 1" - match-stream ">= 0.0.2 < 1" - pullstream ">= 0.4.1 < 1" - readable-stream "~1.0.31" - setimmediate ">= 1.0.1 < 2" +unzipper@^0.9.3: + version "0.9.15" + resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.9.15.tgz#97d99203dad17698ee39882483c14e4845c7549c" + integrity sha512-2aaUvO4RAeHDvOCuEtth7jrHFaCKTSXPqUkXwADaLBzGbgZGzUDccoEdJ5lW+3RmfpOZYNx0Rw6F6PUzM6caIA== + dependencies: + big-integer "^1.6.17" + binary "~0.3.0" + bluebird "~3.4.1" + buffer-indexof-polyfill "~1.0.0" + duplexer2 "~0.1.4" + fstream "^1.0.12" + listenercount "~1.0.1" + readable-stream "~2.3.6" + setimmediate "~1.0.4" upath@^1.1.0: version "1.1.0" @@ -10434,6 +11068,18 @@ vm-browserify@0.0.4, vm-browserify@~0.0.4: dependencies: indexof "0.0.1" +vue-eslint-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-5.0.0.tgz#00f4e4da94ec974b821a26ff0ed0f7a78402b8a1" + integrity sha512-JlHVZwBBTNVvzmifwjpZYn0oPWH2SgWv5dojlZBsrhablDu95VFD+hriB1rQGwbD+bms6g+rAFhQHk6+NyiS6g== + dependencies: + debug "^4.1.0" + eslint-scope "^4.0.0" + eslint-visitor-keys "^1.0.0" + espree "^4.1.0" + esquery "^1.0.1" + lodash "^4.17.11" + vue-hot-reload-api@^2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.2.tgz#1fcc1495effe08a790909b46bf7b5c4cfeb6f21b" @@ -10490,11 +11136,16 @@ vue-template-es2015-compiler@^1.8.2: resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.8.2.tgz#dd73e80ba58bb65dd7a8aa2aeef6089cf6116f2a" integrity sha512-cliV19VHLJqFUYbz/XeWXe5CO6guzwd0yrrqqp0bmjlMP3ZZULY7fu8RTC4+3lmHwo6ESVDHFDsvjB15hcR5IA== -vue@^2.5.16, vue@^2.5.22: +vue@^2.5.16: version "2.6.6" resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.6.tgz#dde41e483c11c46a7bf523909f4f2f816ab60d25" integrity sha512-Y2DdOZD8sxApS+iUlwv1v8U1qN41kq6Kw45lM6nVZKhygeWA49q7VCCXkjXqeDBXgurrKWkYQ9cJeEJwAq0b9Q== +vue@^2.6.10: + version "2.6.10" + resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637" + integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ== + vuepress-html-webpack-plugin@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/vuepress-html-webpack-plugin/-/vuepress-html-webpack-plugin-3.2.0.tgz#219be272ad510faa8750d2d4e70fd028bfd1c16e" @@ -10508,10 +11159,10 @@ vuepress-html-webpack-plugin@^3.2.0: toposort "^1.0.0" util.promisify "1.0.0" -vuepress@^0.14.9: - version "0.14.9" - resolved "https://registry.yarnpkg.com/vuepress/-/vuepress-0.14.9.tgz#94c0fdf44e2dee22b6452b76dbfd03a9c22495a6" - integrity sha512-fsbAmo5TG39q2frEhNYFu7IwuFkYpuTe2BinwdU7BjXyjdApzkWza8n2SPMsBYakAgba5JIwNEZR8bkvnVUhXQ== +vuepress@^0.14.10: + version "0.14.11" + resolved "https://registry.yarnpkg.com/vuepress/-/vuepress-0.14.11.tgz#fc6ba0e609e3433a8070e95301b4d987712b2a08" + integrity sha512-5iB7iWeEG7GtEiNwmS2LOcifp2V93aZ4+oO9pq8OcUgOWay9/NqmNqzg7KQ7AJ0puZGg0tYwUKKjifIWIPE8jQ== dependencies: "@babel/core" "7.0.0-beta.47" "@vue/babel-preset-app" "3.0.0-beta.11" @@ -10570,10 +11221,26 @@ vuepress@^0.14.9: webpackbar "^2.6.1" workbox-build "^3.1.0" -vuex@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.1.0.tgz#634b81515cf0cfe976bd1ffe9601755e51f843b9" - integrity sha512-mdHeHT/7u4BncpUZMlxNaIdcN/HIt1GsGG5LKByArvYG/v6DvHcOxvDCts+7SRdCoIRGllK8IMZvQtQXLppDYg== +vuex@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.1.1.tgz#0c264bfe30cdbccf96ab9db3177d211828a5910e" + integrity sha512-ER5moSbLZuNSMBFnEBVGhQ1uCBNJslH9W/Dw2W7GZN23UQA69uapP5GTT9Vm8Trc0PzBSVt6LzF3hGjmv41xcg== + +w3c-hr-time@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" + integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU= + dependencies: + browser-process-hrtime "^0.1.2" + +w3c-xmlserializer@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz#30485ca7d70a6fd052420a3d12fd90e6339ce794" + integrity sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg== + dependencies: + domexception "^1.0.1" + webidl-conversions "^4.0.2" + xml-name-validator "^3.0.0" watchpack@^1.5.0: version "1.6.0" @@ -10584,6 +11251,11 @@ watchpack@^1.5.0: graceful-fs "^4.1.2" neo-async "^2.5.0" +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + webpack-chain@^4.6.0: version "4.12.1" resolved "https://registry.yarnpkg.com/webpack-chain/-/webpack-chain-4.12.1.tgz#6c8439bbb2ab550952d60e1ea9319141906c02a6" @@ -10723,6 +11395,27 @@ webpackbar@^2.6.1: std-env "^1.3.1" table "^4.0.3" +whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-url@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.0.0.tgz#fde926fa54a599f3adf82dff25a9f7be02dc6edd" + integrity sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + when@~3.6.x: version "3.6.4" resolved "https://registry.yarnpkg.com/when/-/when-3.6.4.tgz#473b517ec159e2b85005497a13983f095412e34e" @@ -10924,6 +11617,13 @@ write-file-atomic@^2.0.0: imurmurhash "^0.1.4" signal-exit "^3.0.2" +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" @@ -10939,6 +11639,13 @@ ws@^4.0.0: async-limiter "~1.0.0" safe-buffer "~5.1.0" +ws@^6.1.2: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== + dependencies: + async-limiter "~1.0.0" + ws@~6.1.0: version "6.1.4" resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.4.tgz#5b5c8800afab925e94ccb29d153c8d02c1776ef9" @@ -10951,11 +11658,21 @@ xdg-basedir@^3.0.0: resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + xmlbuilder@8.2.2: version "8.2.2" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-8.2.2.tgz#69248673410b4ba42e1a6136551d2922335aa773" integrity sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M= +xmlchars@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.1.1.tgz#ef1a81c05bff629c2280007f12daca21bd6f6c93" + integrity sha512-7hew1RPJ1iIuje/Y01bGD/mXokXxegAgVS+e+E0wSi2ILHQkYAH1+JXARwTjZSM4Z4Z+c73aKspEcqj+zPPL/w== + xmldom@0.1.x: version "0.1.27" resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" @@ -11034,6 +11751,11 @@ ylru@^1.2.0: resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.2.1.tgz#f576b63341547989c1de7ba288760923b27fe84f" integrity sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ== +yn@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.0.tgz#fcbe2db63610361afcc5eb9e0ac91e976d046114" + integrity sha512-kKfnnYkbTfrAdd0xICNFw7Atm8nKpLcLv9AZGEt+kczL/WQVai4e2V6ZN8U/O+iI6WrNuJjNNOyu4zfhl9D3Hg== + zepto@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/zepto/-/zepto-1.2.0.tgz#e127bd9e66fd846be5eab48c1394882f7c0e4f98" From dac81ef3145518b9f815edbdfbac3afafb9b24c4 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 30 Jun 2019 22:14:11 -0700 Subject: [PATCH 269/404] update notes --- src/service-module/notes.md | 674 +++++++++++++++++++++++++----------- 1 file changed, 465 insertions(+), 209 deletions(-) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 685a65ad..3c148a0f 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -1,60 +1,148 @@ # Differences in Feathers-Vuex 2.0 -The biggest change in Feathers-Vuex 2.0 is that it has been refactored with TypeScript! - -> I will admit that I was less than excited to try out TypeScript. It definitely introduces a bigger learning curve. I'm not a fan of large barriers to entry, especially when it comes to software development. I thought "It's hard enough already!". And I still feel that's accurate, but it's not an excuse to stay away from TypeScript. I see now that it's actually one of the reasons to use TypeScript. -> -> It only took me a couple of hours to learn some of the basics of TypeScript. Most of the time was spent configuring Visual Studio Code in a way that I liked. For those interested in what I picked, check out [this article](https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project). Thank you, Robert Cooper for such a great setup. -> -> As I started devloping with TypeScript, I really appreciated how it started to rewire how I thought about code organization. The cdde is much cleaner, especially the service plugin. When adding Model support in Feathers-Vuex 1.0, I ran into a difficult race condition. The Models need the store to first be initialized. But the store actions/mutations need the Models to first be initialized. In version 1.0 this resulted in a 115-line monkey patch! With TypeScript's assistance, I was able to see how to reduce it to a clean, two-line monkey patch. Much better! -> -> Some huge benefits came from this refactor. -> -> 1. The FeathersVuex Model class is now fully extendable. This introduces a new level of flexibility. -> 1. Test coverage has improved. The newly-organized code is much easier to test in smaller units. -> 1. Greater compatibility for communicating with multiple FeathersJS servers. The organized code made it easy to see where to add support for this. -> -> TypeScript users will likely notice plenty of room for more accurate types. I'm just getting started with this stuff. Please feel free to make PRs. I'm really excited to see what we can make out of this. +The biggest change in Feathers-Vuex 2.0 is that it has been refactored with TypeScript! (It's mostly ES6, still) + +Your project does NOT require to be written in TypeScript. The `dist` is now set to compile to ES6. + +## Trying it out + +One note about trying it out. Because I accidentally published `feathers-vuex@2.0.0` with a `pre` tag on npm, you have to install the specific version number to get the latest code. To find out which is the most-recently published version, run `npm view feathers-vuex` and look at the `pre` tag. You can ignore the `next` and `pegasus` tags. Those were that happened because I publish a lot of packages. :) + +To try the latest code. + +```console +npm view feathers-vuex +``` + +The end of the output looks something like this: + +```console +dist-tags: +latest: 1.7.0 next: 1.7.0-pre.37 pegasus: 1.7.0-pre.1 pre: 2.0.0-pre.45 +``` + +Now use the latest `pre` tag: + +```console +npm i feathers-vuex@2.0.0-pre.45 + +# or with yarn +yarn add feathers-vuex@2.0.0-pre.45 +``` + +## My TypeScript experience + +Initially, I wasn't a fan of TypeScript. I'm turned off by the steeper learning curve it introduces to writing code. + +What I do like is the tooling. It's like having an assistant that alerts you to stupid moves before you have to accidentally discover them yourself. I'm only able to appreciate it for one reason: you can use directives to tell it to ignore lines or files, similar to ESLint. The tooling will then shut up and let me write JavaScript. TypeScript has been quite beneficial to allowing me to better see how to refactor and get rid of a huge monkey patch. It's down to a few lines of code, now. + +I imagine I will like TypeScript more when there's first-class support for it built into Vue. I imagine how powerful it will be in an entire Vue project. It's one of the reasons that I'm REALLY excited about the new VueJS 3.0 API (The new function-based syntax is way more exciting, though. It's going to let me write some really pretty, well-organized code :) + +But that's enough about TypeScript. + +## Where I need assistance: the build + +The build system has been my only frustration with switching to TypeScript. Transpiling from TypeScript to JavaScript only to be transpiled by Babel (or whichever) into another form of JavaScript... has proven to be frustrating. I could really use some help in this area. + +My original intent was to target the build to ES5. But there are some weird errors that show up when classes get transpiled into old Javascript code. Classes don't quite behave the same after transpiling. Things were so inconsistent that I couldn't write down any useful notes to tell you what I was experiencing. The only clarity I got out of the experience was that it was frustrating. ;) + +I found that the simplest way around my frustration was to target ES6. I found next that Vue's default build assumes packages in the `node_modules` folder to be compiled to ES5. So you'll run into this error: + +```text +TypeError : Class constructor BaseModel cannot be invoked without 'new' +``` + +This error was fixed by adding `feathers-vuex` to the `transpileDependencies` in the `vue.config.js` file: ```js -const differencesToDocument = { - instanceDefaults: {}, // The default values for the instance when `const instance =new Model()` +module.exports = { + transpileDependencies: ['feathers-vuex'] +} +``` + +It felt like everything was solved until I ran the production build. There were more errors. I finally copied the `feathers-vuex` folder from `node_modules` into a `src/libs` folder in my project. Voila! It all works. So I'm currently running this code in production by using a shell script to copy it inside my project. + +```bash +rm -rf src/libs +mkdir src/libs + +# feathers-vuex +cp -r node_modules/feathers-vuex/dist src/libs/feathers-vuex +``` + +Then in my `package.json` scripts: + +```json +{ + "copy": ". ./copy-deps.sh", + "serve": "npm run copy && vue-cli-service serve", + "build": "npm run copy && vue-cli-service build", + "postinstall": "npm run copy" } ``` +I don't consider the above solution to be a pretty one. I likely will not publish 2.0 until a solution is discovered which doesn't required copying from `node_modules`. I know it's got to be simple. It's has something to do with transpile settings for `node_modules`. I just haven't found it yet. + +## Here's what's new in `feathers-vuex` + +Check out the tests for the best documentation. They've been reorganized. This is still a Work in Progress. + ## Changes to Initialization 1. To assist in connecting with multiple FeathersJS API servers, a new `serverAlias` option is now required. This requires a simple addition to the initial options. -2. The returned object has also changed. The `service` method has been renamed to `makeServicePlugin`. -3. The `auth` method is now called `makeAuthPlugin` -4. You get back the actual FeathersVuexModel / BaseModel. Feel free to extend it and make it fit your awesome apps! -5. You no longer pass a `servicePath` to create a service-plugin. Instead, pass the actual Feathers service. -6. Since you can customize the Model, you also pass the model into the `makeServicePlugin` method. +2. The exports have changed. + - (a) A new `BaseModel` is available. This is the base `FeathersVuexModel` which contains the model methods. Feel free to extend it and make it fit your awesome services! + - (b) The `service` method has been renamed to `makeServicePlugin`. + - (c) The `auth` method is now called `makeAuthPlugin` + - (d) The `models` object is now exported, so you can access them from anywhere. They are keyed by `serverAlias`. + - (e) A new `clients` object is available. The intention is to allow working with multiple FeathersJS API servers. +3. You no longer pass a `servicePath` to create a service-plugin. Instead, pass the actual Feathers service. +4. Since you can customize the Model, you also pass the extended Model into the `makeServicePlugin` method. + +Below is an all-in-one example of a the basic configuration steps. See the next section for how to setup a project. ```js +// ./src/store/store.js import feathers from './feathers-client' import Vuex from 'vuex' import feathersVuex from 'feathers-vuex' const { - BaseModel, - makeServicePlugin, // (2^) - makeAuthPlugin, // (3^) - FeathersVuex, - models // (4^) + BaseModel, // (2a) + makeServicePlugin, // (2b) + makeAuthPlugin, // (2c) + models, // (2d) + clients // (2e) } = feathersVuex(feathers, { idField: '_id', - serverAlias: 'myApiServer' // (1^) + serverAlias: 'myApi' // (1) }) class Todo extends BaseModel { - public static modelName = 'Todo' + constructor (data, options) { + super(data, options) + } + static modelName = 'Todo' + static instanceDefaults(data) { + return { + name: '', + isComplete: false, + userId: null, + user: null // populated on the server + } + } + static setupInstance(data) { + if (data.user) { + data.user = new models.myApi.User(data.user) + } + return data + } // customize the model as you see fit! } const todosPlugin = makeServicePlugin({ - Model: Todo, // (6^) - service: feathers.service('todos') // (5^) + Model: Todo, // (3) + service: feathers.service('todos') // (4) }) const store = new Vuex.Store({ @@ -64,6 +152,188 @@ const store = new Vuex.Store({ }) ``` +## Setting up a project + +There are four steps to setting up the entirety of `feathers-vuex`: + +1. Setup the FeathersJS Client. +2. Setup each Service plugin +3. Setup the Auth plugin +4. Register all plugins with Vuex + +### Setup the FeathersJS Client + +It's now recommended that the FeathersJS and client live together in the same file. This cleans up imports when setting up services. So let's start with the `feathers-client.js` file. I usually put this in `src/feathers-client.js`, but you can put it in the store folder if you want. + +```js +// src/feathers-client.js +import feathers from '@feathersjs/feathers' +import socketio from '@feathersjs/socketio-client' +import authClient from '@feathersjs/authentication-client' +import io from 'socket.io-client' +import feathersVuex from 'feathers-vuex' // or '@/libs/feathers-vuex' if you're copying feathers-vuex as mentioned earlier. + +// Setup the Feathers client +const host = process.env.VUE_APP_API_URL // or set a string here, directly +const socket = io(host, { transports: ['websocket'] }) +const feathersClient = feathers() + .configure(socketio(socket)) + .configure(authClient({ storage: window.localStorage })) + +export default feathersClient + +// Setup feathers-vuex +const { + makeServicePlugin, + makeAuthPlugin, + BaseModel, + models, + clients, + FeathersVuex +} = feathersVuex(feathersClient, { + serverAlias: 'api', // or whatever that makes sense for your project + idField: '_id' // `id` and `_id` are both supported, so this is only necessary if you're using something else. +}) + +export { + makeAuthPlugin, + makeServicePlugin, + BaseModel, + models, + clients, + FeathersVuex +} + +``` + +Now that we have setup the client, we can use the configured exports in each of our services. + +### Setup the Services Plugins + +Now let's setup a Vuex plugin for each service. I use Webpack's `require.context` to automatically import all of the services instead of explicitly typing them all. So, I'll put the services in the `src/store/services` folder. + +```js +// Bring in the imports from the feathers-client.js file. +import feathersClient, { + makeServicePlugin, + BaseModel +} from '../../feathers-client' + +// Extend the base class +class User extends BaseModel { + constructor(data, options) { + super(data, options) + } + static modelName = 'User' + static instanceDefaults() { + return { + firstName: '', + lastName: '', + email: '', + password: '' + } + } + get fullName() { + return `${this.firstName} ${this.lastName}` + } +} +const servicePath = 'users' +const servicePlugin = makeServicePlugin({ + Model: User, + service: feathersClient.service(servicePath), + servicePath +}) + +// Optionally add service-level hooks, here: +feathersClient.service(servicePath).hooks({ + before: { + all: [], + find: [], + get: [], + create: [], + update: [], + patch: [], + remove: [] + }, + after: { + all: [], + find: [], + get: [], + create: [], + update: [], + patch: [], + remove: [] + }, + error: { + all: [], + find: [], + get: [], + create: [], + update: [], + patch: [], + remove: [] + } +}) + +export default servicePlugin + +``` + +Once the service plugin is exported, we can register it with Vuex, but first let's setup the auth plugin. + +### Setup the Auth Plugin + +We'll use the `makeAuthPlugin` method to tell the auth plugin where to find our `/users` service: + +```js +// src/store/store.auth.js +import feathersClient, { makeAuthPlugin } from '../feathers-client' + +export default makeAuthPlugin({ userService: 'users' }) + +``` + +Once you've added the export, we're finally ready to setup the store. + +### Register all plugins with Vuex + +The final step is to add all of the plugins to the Vuex store. + +```js +// src/store/store.js +import Vue from 'vue' +import Vuex from 'vuex' +import { FeathersVuex } from 'feathers-vuex' +import auth from './store.auth' + +Vue.use(Vuex) +Vue.use(FeathersVuex) + +// Require the entire folder of service plugins with Webpack +const requireModule = require.context( './services', false, /.js$/ ) +const servicePlugins = requireModule + .keys() + .map(modulePath => requireModule(modulePath).default) + +// Or you can import them manually for Rollup, etc. +import users from './services/users' + +export default new Vuex.Store({ + state: {}, + getters: {}, + mutations: {}, + actions: {}, + plugins: [ + ...servicePlugins, // if you're using require.context, spread the plugins into the array. + users, // if you're manually importing, just add the plugins into the array, like this + auth + ] +}) + +``` + +With the above four steps accomplished, the base of most any application using `feathers-vuex` is ready to build something awesome! + ## FeathersVuex Vue plugin changes The Vue plugin is registered in exactly the same way. The difference comes when you try to find the Model classes in the `$FeathersVuex` object. Instead of finding models directly on the `$FeathersVuex` object, they are namespaced by the `serverAlias` you provided. This allows cleaner support for multiple APIs. Supposing you had this code in a component, previously... @@ -84,31 +354,17 @@ created () { } ``` -## Common idField support - -Since `id` and `_id` are the most commonly-used idField options, both are supported without additional configuration. The idField is detected in this order: +## Better default `idField` support -1. `item.id` -2. `item._id` -3. `item[idField]` +Since records are keyed by id, `feathers-vuex` needs to know what the `idField` is for each service. In the last version, the default was `id`, and you had to specify something different. This version supports `id` and `_id` with zero configuration. You only need to set `idField` when you're using something other than `id` or `_id`. -This solves a common issue that occurs when the `idField` is not provided. This also means that the only time you must specify an `idField` is when your data does not contain an `id` or `_id` field. +There's still a warning message when records don't have a property matching the `idField`. Just like in the last version, it only appears when you turn on `debug: true` in the options. ## Support for Temporary Records -Feathers-Vuex 2.0 supports tracking temporary items and automatically assigns a temporary id (customizable using the `options.tempIdField`) and adds the records to the `state.tempsById` field. +Feathers-Vuex 2.0 supports tracking temporary items and automatically assigns a temporary id to new records. It also adds the records to `state.tempsById`. This is customizable using the `tempIdField` option. -Previously, when a record didn't have an `[idField]`, a console.error would ask if you had configured the `idField` option. Because of the new ability to handle temporary records, a message is only logged when assigning a temporary id to a record. The `checkId` utility function has been removed, since this was its main purpose. - -Note: In order to get a tempId, you must pass at least an empty object to the constructor. Supposing you have a Class named Todo: - -```js -// This will not get you a tempId -const noTempId = new Todo() - -// This will -const todoWithTempId = new Todo({}) -``` +Because of the new ability to handle temporary records, a message is only logged when assigning a temporary id to a record. The `checkId` utility function has been removed, since this was its main purpose. ## Getters Work with Temporary Records @@ -116,36 +372,6 @@ The `find` getter has been updated to include records from `state.tempsById`, by The `get` getter has also been updated to work with temp ids. Pass the tempId the way you normally would pass the id: `get(tempId)` -## Changes to service module state - -The options are no longer at the root level of the service module state. You'll find them all in the options key: - -```js -const state = { - // ... - options: { - addOnUpsert: false, - autoRemove: false, - debug: false, - diffOnPatch: true, - enableEvents: true, - idField: 'id', - keepCopiesInStore: false, - modelName: 'Todo', - nameStyle: 'short', - namespace: 'todos', - paramsForServer: [], - preferUpdate: false, - replaceItems: false, - serverAlias: 'default', - servicePath: 'todos', - skipRequestIfExists: false, - whitelist: [] - }, - // ... -} -``` - ## The "currentItem" workflow is no longer supported The `setCurrent` mutation and `currentId` state encouraged use of a very limiting API. It's much more common for apps to require more than one current record. The `createCopy`, `resetCopy` (formerly called `rejectCopy`), `commitCopy`, and `clearCopy` mutations (since v1.x) provide a more flexible solution for implementing the same functionality. As a result of this, following have been removed from the modules: @@ -154,19 +380,59 @@ The `setCurrent` mutation and `currentId` state encouraged use of a very limitin - getters: `current` - mutations: `setCurrent`, `clearList`, `copy` -## The `diffOnPatch` option is turned on by default +## The `diffOnPatch` option has been removed -In Feathers-Vuex 2.0, the `diffOnPatch` option is enabled, by default. This means that only the necessary data is sent to the API server. Set `diffOnPatch: false` in the options to revert back to the old way. +(See the next section for its replacement.) -## The `modelName` option has been removed +I have not been able to find a diffing algorithm that works equally well acroos all schemas. It's especially difficult for nested schemas. Because of this, `diffOnPatch` is no longer a global option. It is being replaced by the `diffOnPatch` static Model method. See the next section. -Previous versions of Feathers-Vuex only supported a single FeathersVuexModel class, which was difficult to customize. This limitation required internal use of using inflections or passing a `modelName`. Version 2.0, with its full support for extending the FeathersVuexModel/BaseModel class no longer requires this option. Just name your class something new: +## Model Classes: BYOD (Bring Your Own Diffing) + +First, why do any diffing? On the API server, an `update` request replaces an entire object, but a `patch` request only overwrites the attributes that are provided in the data. For services with simple schemas, it doesn't really matter. But if your schema grows really large, it can be supportive to only send the updates instead of the entire object. + +A new `diffOnPatch` method is available to override in your extended models. `diffOnPatch` gets called just before sending the data to the API server. It gets called with the data and must return the diffed data. By default, it is set to `diffOnPatch: data => data`. + +Below is an example of how you might implement `diffOnPatch`. You would only ever use this with a cloned instance, otherwise there's nothing to diff. ```js +import { diff } from 'deep-object-diff' const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { serverAlias: 'myApi' }) class Todo extends BaseModel { + public constructor (data, options?) { + super(data, options) + } public static modelName = 'Todo' + public static diffOnPatch (data) { + const originalObject = Todo.store.state.keyedById[data._id] + return diff(originalObject, data) + } +} + +const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathers.service(servicePath) + }) + ] +}) +``` + +## The `modelName` option has moved + +While the original intent was to completely remove the `modelName` option, it's still required after transpiling to ES5. This is because during transpilation, the class name gets stripped and can't be put back into place. Since ES5 is the default target for most build environments, the `modelName` is still required to be specified, but it has been moved. Instead of being an option, it's required as a static property of each class. + +Note: Once ES6 is the default target for most build systems, modelName will become optional. For future upgradability, it's recommended that you give your `modelName` the exact same name as your model class. + +```js +const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { serverAlias: 'myApi' }) + +class Todo extends BaseModel { + public constructor (data, options?) { + super(data, options) + } + public static modelName = 'Todo' // modelName is required on all Model classes. public static exampleProp: string = 'Hello, World! (notice the comma, folks!)' } @@ -186,7 +452,7 @@ The Model class no longer has an `options` property. You can access the same in ## The 'apiPrefix' option has been removed -Feathers-Vuex now includes full support for communicating with multiple FeathersJS APIs. The `apiPrefix` option was a poorly implemented, hacky first attempt at this same feature. It was buggy. Since it didn't work as intended, it has been removed. See this example test for working with multiple APIs: +Feathers-Vuex now includes full support for communicating with multiple FeathersJS APIs. The `apiPrefix` option was a poorly-implemented, hacky, first attempt at this same feature. Since it didn't work as intended, it has been removed. See this example test for working with multiple APIs: ```js import { assert } from 'chai' @@ -206,7 +472,6 @@ it('works with multiple, independent Feathers servers', function() { serverAlias: 'myApi' }) class Todo extends myApi.BaseModel { - public static modelName = 'Todo' public test: boolean = true } const todosPlugin = myApi.makeServicePlugin({ @@ -220,7 +485,6 @@ it('works with multiple, independent Feathers servers', function() { serverAlias: 'theirApi' }) class Task extends theirApi.BaseModel { - public static modelName = 'Task' public test: boolean = true } const tasksPlugin = theirApi.makeServicePlugin({ @@ -251,9 +515,9 @@ it('works with multiple, independent Feathers servers', function() { ) ``` -## Services are no longer set up internally +## Services are no longer set up, internally -You no longer just pass a servicePath, but instead an entire service object. +You no longer just pass a servicePath. Instead, create the service, then pass the returned service object. ## Simplified Pending Mutations @@ -283,18 +547,61 @@ commit('setError', { method: 'find', error }) commit('clearError', 'find') ``` -## New Actions in the Service Module +## `instanceDefaults` must be a function + +In the previous version, you could specify instanceDefaults as an object. It was buggy and limiting. In this new version, `instanceDefaults` must always be a function. See the next section for an example. + +## Getter and Setter props go on the Model classes -The `handleFindResponse` and `handleFindError` actions were previously enclosed inside the `find` action. Since the majority fo the `find` action consisted of the response handler, they've been pulled out. This allows for much better readability. It's technically now possible to override both actions by providing replacements in the `makeServicePlugin` config. +One of the great features about using Model classes is data-level computed properties. You get to specify computed properties directly on your data structures instead of inside components, which keeps a better separation of concerns. In `feathers-vuex@2.x`, since we have direct access to the Model classes, it's the perfect place to define the computed properties: + +```js +import feathersClient, { + makeServicePlugin, + BaseModel +} from '../../feathers-client' + +class User extends BaseModel { + constructor(data, options) { + super(data, options) + } + static modelName = 'User' // required + // Computed properties don't go on in the instanceDefaults, anymore. + static instanceDefaults() { + return { + firstName: '', + lastName: '', + email: '', + password: '', + isAdmin: false, + } + } + // Here's a computed getter + get fullName() { + return `${this.firstName} ${this.lastName}` + } + // Probably not something you'd do in real life, but it's an example of a setter. + set fullName(fullName) { + const [ firstName, lastName ] = fullName.split(' ') + Object.assign(this, { firstName, lastName }) + } +} +const servicePath = 'users' +const servicePlugin = makeServicePlugin({ + Model: User, + service: feathersClient.service(servicePath), + servicePath +}) +``` ## Relationships have been separated from `instanceDefaults` -Feathers-Vuex 2.0 has a new API for establishing relationships between data. Before we cover how it works, let's review the old API, first. +Feathers-Vuex 2.0 has a new API for establishing relationships between data. Before we cover how it works, let's review the old API. Feathers-Vuex 1.x allowed using the `instanceDefaults` API to both setup default values for Vue reactivity AND establishing relationships between services. It supported passing a string name that matched a model name to setup a relationship, as shown in this next example. This was a simple, but very limited API: ```js -// Defaults for a todo service +// The old way instanceDefaults: { _id: '', description: '', @@ -305,9 +612,9 @@ instanceDefaults: { Any instance data with a matching key would overwrite the same property in the instanceDefaults, which resulted in an inconsistent API. -In Feathers-Vuex 2.0, the `instanceDefaults` work the same for setting defaults with only one exception (see the next example). They no longer setup the relationships, though. The new `setupInstance` function provides an API that is much more powerful. +In Feathers-Vuex 2.0, the `instanceDefaults` work the same for setting defaults with only one exception: They no longer setup the relationships. The new `setupInstance` function provides an API that is much more powerful. -The main difference with `instanceDefaults` in Feathers-Vuex 2.0 is that it MUST be provided as a function, now: +As mentioned earlier, it MUST be provided as a function: ```js // See the `model-instance-defaults.test.ts` file for example usage. @@ -322,48 +629,19 @@ instanceDefaults(data, { models, store}) { } ``` -Notice in the above example that we did not return `user`. We'll handle it in the `setupInstance` method. +Notice in the above example that we did not return `user`. Relationships are now handled in the `setupInstance` method. -Where `instanceDefaults` props get replaced by instance data, the props returned from `setupInstance` overwrite the instance data. If it were using `Object.assign`, internally (it's not, but IF it were), it would look like the below example, where `data` is the original instance data passed to the constructor. +Where `instanceDefaults` props get overwritten with instance data, the props returned from `setupInstance` overwrite the instance data. If it were using `Object.assign`, internally (it's not, but IF it were), it would look like the below example, where `data` is the original instance data passed to the constructor. ```js Object.assign({}, instanceDefaults(data), data, setupInstance(data)) ``` -## ES5 accessors are specified as properties of the model classes - -In the previous version of feathers-vuex, es5 getters and setters would commonly be put in the `instanceDefaults`. They are now specified in the model class definition: - -```js -class User extends BaseModel { - constructor(data, options) { - super(data, options) - } - static modelName = 'User' - static instanceDefaults() { - return { - firstName: '', - lastName: '', - email: '', - password: '', - roles: [] - } - } - // Getters - get fullName() { - return `${this.firstName} ${this.lastName}` - } - set primalName(val) { - this.name = 'Gorilla Dan' - } -} -``` - ## Define Relationships and Modify Data with `setupInstance` The new `setupInstance` method allows a lot of flexibility in creating new instances. It has the exact same API as the `instanceDefaults` method. The only difference is the order in which they are applied to the instance data. -While you could technically use `setupInstance` to do all of your default values, the APIs have been kept separate to allow a clean separation between setting up defaults and establishing relationships and other constructors. +Although it looks similar to `instanceDefaults`, it can't be used for default values. This is because it overwrites instance data. Having separate methods allows a clean separation between setting up defaults and establishing relationships with other constructors. ```js // See the `model-relationships.test.ts` file for example usage. @@ -383,6 +661,7 @@ function setupInstance(data, { models, store }) { if (data.createdAt) { data.createdAt = new Date(data.createdAt) } + return data } ``` @@ -392,11 +671,12 @@ Or below is an example that does the exact same thing with one line per attribut function setupInstance(data, { models, store }) { const { User } = models.myServerAlias - return Object.assign(data, { + Object.assign(data, { ...(data.user && { user: new User(data.user) }), // A single User instance ...(data.tags && { tags: data.tags.map(t => new Tag(t)) }), // An array of Tag instances ...(data.createdAt && { createdAt: new Date(data.createdAt) }) // A JavaScript Date Object }) + return data } ``` @@ -406,84 +686,9 @@ Where `instanceDefaults` props get replaced by instance data, the props returned Object.assign({}, instanceDefaults(data), data, setupInstance(data)) ``` -### This part is out of date - -I'm testing out a version of the `mergeWithAccessors` utility function that allows copying non-enumerables, but still skips `__ob__` properties for Vue.Observables. This section will require updating after I've integration tested it. - -Another important note when using es5 accessors (get/set) is that you must define the property as enumerable. This is because the `mergeWithAccessors` utility that's used to clone and commit instances ignores any non-enumerable props. Using the previous example as a starting point, this is how to define an es5 getter: - -```js -function setupInstance(data, { models, store }) { - const { User } = models.myServerAlias - - data = Object.assign(data, { - ...(data.user && { user: new User(data.user) }), // A single User instance - ...(data.tags && { tags: data.tags.map(t => new Tag(t)) }), // An array of Tag instances - ...(data.createdAt && { createdAt: new Date(data.createdAt) }) // A JavaScript Date Object - }) - - Object.defineProperties(data, { - fullName: { - enumerable: true, - get () { - return `${this.firstName} ${this.lastName}` - } - } - }) - - return data -} -``` - -Making a getter enumerable means that it will get serialized in the toJSON method, by default. This means that the attribute will get sent in requests to the API server. This isn't a problem if the API strips away extra params without throwing an error. For other APIs, it might be an issue. To prevent the attribute from getting serialized in requests, you can override the toJSON method in the model class: - -```js -import fastCopy from 'fast-copy' - -const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { - serverAlias: 'myApi' -}) - -const Todo extends BaseModel { - public static modelName = 'Todo' - // The `setupInstance` method must be a static method - static setupInstance(data, { models, store }) { - const { User } = models.myServerAlias - - data = Object.assign(data, { - ...(data.user && { user: new User(data.user) }), // A single User instance - ...(data.tags && { tags: data.tags.map(t => new Tag(t)) }), // An array of Tag instances - ...(data.createdAt && { createdAt: new Date(data.createdAt) }) // A JavaScript Date Object - }) - - Object.defineProperties(data, { - fullName: { - enumerable: true, - get () { - return `${this.firstName} ${this.lastName}` - } - } - }) - - return data - } - // And toJSON is an instance prop - toJSON () { - // Copy the data so you don't modify the original - const copy = fastCopy(this) - - // Delete the prop / modify as required - delete copy.fullName - - // Return the modified data - return copy - } -} -``` - ## Preventing duplicate merge when extending BaseModel with a custom constructor -The BaseModel constructor calls `mergeWithAccessors(this, newData)`. This utility function correctly copies data between both regular objects and Vue.observable instances. If you create a class where you need to do your own merging, you probably don't want `mergeWithAccessors` to run twice. In this case, you can use the `merge: false` BaseModel instance option to prevent the internal merge. You can then access the `mergeWithAccessors` method by calling `MyModel.merge(this, newData)`. Here's an example: +The BaseModel constructor calls `mergeWithAccessors(this, newData)`. This utility function correctly copies data between both regular objects and Vue.observable instances. If you create a class where you need to do your own merging, you probably don't want `mergeWithAccessors` to run twice. In this case, you can use the `merge: false` BaseModel ___instance option___ to prevent the internal merge. You can then access the `mergeWithAccessors` method by calling `MyModel.merge(this, newData)`. Here's an example: ```ts const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { @@ -491,17 +696,15 @@ const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { }) class Todo extends BaseModel { - public static modelName = 'Todo' public constructor(data, options?) { options.merge = false // Prevent the internal merge from occurring. super(data, options) - // ... your custom construcor logic happens here. + // ... your custom constructor logic happens here. // Call the static merge method to do your own merging. Todo.merge(this, data) } - public static modelName = 'Todo' } ``` @@ -509,8 +712,8 @@ It's important to note that setting `merge: false` in the options will disable t ```ts class Todo extends BaseModel { - public static modelName = 'Todo' public constructor(data, options?) { + options = options || {} options.merge = false // Prevent the internal merge from occurring. super(data, options) @@ -526,6 +729,59 @@ class Todo extends BaseModel { // Call the static merge method to do your own merging. Todo.merge(this, instanceData) } - public static modelName = 'Todo' } ``` + +## Customizing the BaseModel + +Because we have access to the BaseModel, we can extend it to do whatever custom stuff we need in our application. The `feathers-client.js` file is a great, centralized location for accomplishing this: + +```js +// src/feathers-client.js +import feathers from '@feathersjs/feathers' +import socketio from '@feathersjs/socketio-client' +import authClient from '@feathersjs/authentication-client' +import io from 'socket.io-client' +import feathersVuex from 'feathers-vuex' // or '@/libs/feathers-vuex' if you're copying feathers-vuex as mentioned earlier. + +// Setup the Feathers client +const host = process.env.VUE_APP_API_URL // or set a string here, directly +const socket = io(host, { transports: ['websocket'] }) +const feathersClient = feathers() + .configure(socketio(socket)) + .configure(authClient({ storage: window.localStorage })) + +export default feathersClient + +// Setup feathers-vuex +const { + makeServicePlugin, + makeAuthPlugin, + BaseModel, + models, + clients, + FeathersVuex +} = feathersVuex(feathersClient, { + serverAlias: 'api', // or whatever that makes sense for your project + idField: '_id' // `id` and `_id` are both supported, so this is only necessary if you're using something else. +}) + +// Note that if you want to +// extend the BaseClass for the rest of the app, this is a great place to do it. +// After you've extended the BaseClass with your CustomClass, export it, here. +class CustomBaseModel extends BaseModel { + // Optionally add custom functionality for all services, here. +} + +// Export all of the utilities for the rest of the app. +export { + makeAuthPlugin, + makeServicePlugin, + BaseModel, + models, + clients, + FeathersVuex, + CustomBaseModel // Don't forget to export it for use in all other services. +} + +``` From 39562c431e8484f1daff0e4ff12a75673516f8e4 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 1 Jul 2019 07:10:50 -0700 Subject: [PATCH 270/404] Clarifications in notes --- src/service-module/notes.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 3c148a0f..f8f5e896 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -2,7 +2,7 @@ The biggest change in Feathers-Vuex 2.0 is that it has been refactored with TypeScript! (It's mostly ES6, still) -Your project does NOT require to be written in TypeScript. The `dist` is now set to compile to ES6. +Your project does NOT require to be written in TypeScript. The `dist` is compiled to ES6. ## Trying it out @@ -119,10 +119,14 @@ const { }) class Todo extends BaseModel { + // required constructor (data, options) { super(data, options) } + // required static modelName = 'Todo' + + // optional, but useful static instanceDefaults(data) { return { name: '', @@ -131,6 +135,8 @@ class Todo extends BaseModel { user: null // populated on the server } } + + // optional, but useful static setupInstance(data) { if (data.user) { data.user = new models.myApi.User(data.user) From 07b51d7580a63b67f9d040f02048f7157caacc89 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 1 Jul 2019 22:15:29 -0700 Subject: [PATCH 271/404] Fix id checks through the app If the id is 0, this check fails. Updated to check for null and undefined. --- src/make-get-mixin.ts | 2 +- src/service-module/make-model.ts | 6 +++--- src/service-module/service-module.mutations.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/make-get-mixin.ts b/src/make-get-mixin.ts index f3e79a1d..d1271363 100644 --- a/src/make-get-mixin.ts +++ b/src/make-get-mixin.ts @@ -84,7 +84,7 @@ export default function makeFindMixin(options) { if (this[QUERY_WHEN]) { this[IS_GET_PENDING] = true - if (idToUse) { + if (idToUse != null) { return this.$store .dispatch(`${this[SERVICE_NAME]}/get`, [idToUse, paramsToUse]) .then(response => { diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 8e05f4f6..8fa8d5d1 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -272,7 +272,7 @@ export default function makeModel(options: FeathersVuexOptions) { public save(params) { const { idField, preferUpdate } = this.constructor as typeof BaseModel const id = getId(this, idField) - if (id) { + if (id != null) { return preferUpdate ? this.update(params) : this.patch(params) } else { return this.create(params) @@ -299,7 +299,7 @@ export default function makeModel(options: FeathersVuexOptions) { const { idField, _dispatch } = this.constructor as typeof BaseModel const id = getId(this, idField) - if (!id) { + if (id == null) { const error = new Error( `Missing ${ idField @@ -346,7 +346,7 @@ export default function makeModel(options: FeathersVuexOptions) { .constructor as typeof BaseModel const id = getId(this, idField) - if (id) { + if (id != null) { if (params && params.eager) { _commit.call(this.constructor, 'removeItem', id) } diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 8cf2acb5..43af0542 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -23,7 +23,7 @@ export default function makeServiceMutations() { const isTemp = id === null || id === undefined // If the response contains a real id, remove isTemp - if (id) { + if (id != null) { delete item.__isTemp } @@ -59,7 +59,7 @@ export default function makeServiceMutations() { const id = getId(item, idField) // If the response contains a real id, remove isTemp - if (id) { + if (id != null) { delete item.__isTemp } From 7ee187fd9b87a35790cee22eb3d599cebcf14f45 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 1 Jul 2019 22:16:11 -0700 Subject: [PATCH 272/404] Move diffOnPatch to the Model The diffOnPatch option has been moved to the Model, where it can be overridden as required. --- src/service-module/service-module.actions.ts | 4 ++-- src/service-module/types.ts | 2 -- test/service-module/make-service-plugin.test.ts | 1 - test/service-module/service-module.test.ts | 1 - 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 51aaee62..e54e0aff 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -147,14 +147,14 @@ export default function makeServiceActions(service) { patch({ commit, dispatch, state }, [id, data, params]) { // eslint-disable-next-line no-unused-vars - const { idField, diffOnPatch } = state + const { idField } = state commit('setPending', 'patch') params = fastCopy(params) if (service.FeathersVuexModel) { - data = diffOnPatch(data) + data = service.FeathersVuexModel.diffOnPatch(data) } return service diff --git a/src/service-module/types.ts b/src/service-module/types.ts index c716b59e..bee13ae0 100644 --- a/src/service-module/types.ts +++ b/src/service-module/types.ts @@ -7,7 +7,6 @@ export interface FeathersVuexOptions { addOnUpsert?: boolean autoRemove?: boolean debug?: boolean - diffOnPatch?: boolean enableEvents?: boolean idField?: string tempIdField?: string @@ -24,7 +23,6 @@ export interface MakeServicePluginOptions { Model: any service: any addOnUpsert?: boolean - diffOnPatch?: boolean enableEvents?: boolean idField?: string tempIdField?: string diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index 7fc09a53..8c184e1c 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -54,7 +54,6 @@ describe('makeServicePlugin', function () { autoRemove: false, debug: false, copiesById: {}, - diffOnPatch: true, enableEvents: true, errorOnCreate: null, errorOnFind: null, diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 98fc4ea1..9d908ead 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -567,7 +567,6 @@ describe('Service Module', function () { autoRemove: false, copiesById: {}, debug: false, - diffOnPatch: true, enableEvents: true, errorOnCreate: null, errorOnGet: null, From 6993e4adf338f3823fbc474a8c69fb9d209a49cc Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 1 Jul 2019 22:16:59 -0700 Subject: [PATCH 273/404] 2.0.0-pre.46 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 46b49120..0832a3ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.45", + "version": "2.0.0-pre.46", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a91bd4c6..34634cb8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.45", + "version": "2.0.0-pre.46", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 3de710421b48dd49994fce70d632675ced1023fd Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 1 Jul 2019 23:02:20 -0700 Subject: [PATCH 274/404] Fix another round of broken ids --- src/service-module/make-model.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 8fa8d5d1..b4e126e2 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -216,7 +216,7 @@ export default function makeModel(options: FeathersVuexOptions) { if (this.__isClone) { throw new Error('You cannot clone a copy') } - const id = getId(this, idField) || this[tempIdField] + const id = getId(this, idField) != null ? getId(this, idField) : this[tempIdField] return this._clone(id) } @@ -241,7 +241,7 @@ export default function makeModel(options: FeathersVuexOptions) { .constructor as typeof BaseModel if (this.__isClone) { - const id = getId(this, idField) || this[tempIdField] + const id = getId(this, idField) != null ? getId(this, idField) : this[tempIdField] _commit.call(this.constructor, 'resetCopy', id) return this } else { @@ -256,7 +256,7 @@ export default function makeModel(options: FeathersVuexOptions) { const { idField, tempIdField, _commit, _getters } = this .constructor as typeof BaseModel if (this.__isClone) { - const id = getId(this, idField) || this[tempIdField] + const id = getId(this, idField) != null ? getId(this, idField) : this[tempIdField] _commit.call(this.constructor, 'commitCopy', id) return _getters.call(this.constructor, 'get', id) From 0302586d646e1b8b613a93e9dd09eea53314efea Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 1 Jul 2019 23:02:39 -0700 Subject: [PATCH 275/404] 2.0.0-pre.47 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0832a3ee..67eb7583 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.46", + "version": "2.0.0-pre.47", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 34634cb8..f587b3a2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.46", + "version": "2.0.0-pre.47", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From d9aef66bdf363cbefbba358b69eb03efd04935bb Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Jul 2019 05:43:11 -0700 Subject: [PATCH 276/404] Lint cleanup --- src/FeathersVuexFind.ts | 1 + src/FeathersVuexGet.ts | 1 + src/make-find-mixin.ts | 1 + src/make-get-mixin.ts | 1 + src/service-module/global-models.ts | 2 ++ src/service-module/make-model.ts | 1 - src/service-module/service-module.actions.ts | 5 ----- src/service-module/service-module.mutations.ts | 2 +- src/utils.ts | 3 +++ test/auth.test.js | 1 + test/service-module/service-module.actions.test.ts | 1 + test/service-module/service-module.mutations.test.ts | 1 + 12 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/FeathersVuexFind.ts b/src/FeathersVuexFind.ts index c95cf79d..f0e5053c 100644 --- a/src/FeathersVuexFind.ts +++ b/src/FeathersVuexFind.ts @@ -89,6 +89,7 @@ export default { return this.findData() } else { // TODO: access debug boolean from from the store config, somehow. + // eslint-disable-next-line no-console console.log( `No query and no id provided, so no data will be fetched.` ) diff --git a/src/FeathersVuexGet.ts b/src/FeathersVuexGet.ts index 76e1c9d2..bc021d18 100644 --- a/src/FeathersVuexGet.ts +++ b/src/FeathersVuexGet.ts @@ -107,6 +107,7 @@ export default { ) { return this.getData() } else { + // eslint-disable-next-line no-console console.log( `No query and no id provided, so no data will be fetched.` ) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index fbaac7bf..3f1cead0 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -1,5 +1,6 @@ /* eslint +no-console: 0, @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ diff --git a/src/make-get-mixin.ts b/src/make-get-mixin.ts index d1271363..3aa7ef10 100644 --- a/src/make-get-mixin.ts +++ b/src/make-get-mixin.ts @@ -1,5 +1,6 @@ /* eslint +no-console: 0, @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ diff --git a/src/service-module/global-models.ts b/src/service-module/global-models.ts index e8864af7..06b5fef4 100644 --- a/src/service-module/global-models.ts +++ b/src/service-module/global-models.ts @@ -1,5 +1,6 @@ /* eslint +no-console: 0, @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ @@ -23,6 +24,7 @@ export function prepareAddModel(options: FeathersVuexOptions) { } const name = Model.modelName || Model.name if (globalModels[serverAlias][name] && options.debug) { + // eslint-disable-next-line no-console console.error(`Overwriting Model: models[${serverAlias}][${name}].`) } globalModels[serverAlias][name] = Model diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index b4e126e2..2edbe974 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -85,7 +85,6 @@ export default function makeModel(options: FeathersVuexOptions) { models, instanceDefaults, idField, - tempIdField, setupInstance, getFromStore, _commit diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index e54e0aff..00cc5de4 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -24,7 +24,6 @@ export default function makeServiceActions(service) { // 1. Just pass the id: `get(1)` // 2. Pass arguments as an array: `get([null, params])` get({ state, getters, commit, dispatch }, args) { - const { idField } = state let id let params let skipRequestIfExists @@ -125,7 +124,6 @@ export default function makeServiceActions(service) { }, update({ commit, dispatch, state }, [id, data, params]) { - const { idField } = state commit('setPending', 'update') @@ -146,9 +144,6 @@ export default function makeServiceActions(service) { }, patch({ commit, dispatch, state }, [id, data, params]) { - // eslint-disable-next-line no-unused-vars - const { idField } = state - commit('setPending', 'patch') params = fastCopy(params) diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 43af0542..9f4d5e30 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -53,7 +53,7 @@ export default function makeServiceMutations() { function updateItems(state, items) { const { idField, replaceItems, addOnUpsert, serverAlias, modelName } = state const Model = _get(models, `[${serverAlias}][${modelName}]`) - const BaseModel = _get(models, `[${state.serverAlias}].BaseModel`) + // const BaseModel = _get(models, `[${state.serverAlias}].BaseModel`) for (let item of items) { const id = getId(item, idField) diff --git a/src/utils.ts b/src/utils.ts index 533b35fe..f9c6e195 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -22,6 +22,7 @@ export function stripSlashes(location: string) { // From feathers-plus/feathers-hooks-common export function setByDot(obj, path, value, ifDelete?) { if (ifDelete) { + // eslint-disable-next-line no-console console.log( 'DEPRECATED. Use deleteByDot instead of setByDot(obj,path,value,true). (setByDot)' ) @@ -163,6 +164,7 @@ export const initAuth = function initAuth(options) { export function assignTempId(state, item) { const { debug, tempIdField } = state if (debug) { + // eslint-disable-next-line no-console console.info('assigning temporary id to item', item) } const newId = new ObjectID().toHexString() @@ -431,6 +433,7 @@ export function cloneWithAccessors(obj) { export function checkNamespace(namespace, item) { if (!namespace) { + // eslint-disable-next-line no-console console.error( 'A `namespace` was not available on the Model for this item:', item, diff --git a/test/auth.test.js b/test/auth.test.js index ed0c43be..4a4c40ff 100644 --- a/test/auth.test.js +++ b/test/auth.test.js @@ -81,6 +81,7 @@ describe('feathers-vuex:auth', () => { accessToken: 'q34twershtdyfhgmj' }) } catch (err) { + // eslint-disable-next-line no-console console.log(err) } }) diff --git a/test/service-module/service-module.actions.test.ts b/test/service-module/service-module.actions.test.ts index cd348382..250fc79e 100644 --- a/test/service-module/service-module.actions.test.ts +++ b/test/service-module/service-module.actions.test.ts @@ -1064,6 +1064,7 @@ describe('Service Module - Actions', () => { done() }) .catch(error => { + // eslint-disable-next-line no-console console.log(error) }) diff --git a/test/service-module/service-module.mutations.test.ts b/test/service-module/service-module.mutations.test.ts index eb7ba272..f7dd805d 100644 --- a/test/service-module/service-module.mutations.test.ts +++ b/test/service-module/service-module.mutations.test.ts @@ -283,6 +283,7 @@ describe('Service Module - Mutations', function() { }, watch: { 'item.getter'() { + // eslint-disable-next-line no-console console.log(state.keyedById) throw new Error('this should never happen') } From d983424fef0789f6c4d6d03fe5b35036a3b14f5f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Jul 2019 05:43:27 -0700 Subject: [PATCH 277/404] 2.0.0-pre.48 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 67eb7583..8670407b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.47", + "version": "2.0.0-pre.48", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f587b3a2..f291b454 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.47", + "version": "2.0.0-pre.48", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 6484c2d557d4d2e73d59b8d2d0a0f40d89731c6a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Jul 2019 05:49:24 -0700 Subject: [PATCH 278/404] More lint cleanup --- src/FeathersVuexFind.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/FeathersVuexFind.ts b/src/FeathersVuexFind.ts index f0e5053c..be7f8cfe 100644 --- a/src/FeathersVuexFind.ts +++ b/src/FeathersVuexFind.ts @@ -105,9 +105,7 @@ export default { } if (!this.$store.state[this.service]) { throw new Error( - `The '${ - this.service - }' plugin cannot be found. Did you register the service with feathers-vuex?` + `The '${ this.service }' plugin not registered with feathers-vuex` ) } From c357e655c80513146d22be932cb391fe9938b244 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Jul 2019 05:49:35 -0700 Subject: [PATCH 279/404] 2.0.0-pre.49 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8670407b..cd057fdc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.48", + "version": "2.0.0-pre.49", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f291b454..73920c12 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.48", + "version": "2.0.0-pre.49", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 9f272b58a28558f06c490d8bd06fee0b7b5c6869 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Jul 2019 05:53:33 -0700 Subject: [PATCH 280/404] Lint cleanup --- src/FeathersVuexGet.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/FeathersVuexGet.ts b/src/FeathersVuexGet.ts index bc021d18..4ce1f563 100644 --- a/src/FeathersVuexGet.ts +++ b/src/FeathersVuexGet.ts @@ -123,9 +123,7 @@ export default { } if (!this.$store.state[this.service]) { throw new Error( - `The '${ - this.service - }' plugin cannot be found. Did you register the service with feathers-vuex?` + `The '${ this.service }' plugin is not registered with feathers-vuex` ) } From 99b497a54e80f7771dacdec4bef5b81af4011aa4 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Jul 2019 05:53:39 -0700 Subject: [PATCH 281/404] 2.0.0-pre.50 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index cd057fdc..eab01e72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.49", + "version": "2.0.0-pre.50", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 73920c12..c62e0792 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.49", + "version": "2.0.0-pre.50", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 462212c1a46d15557dd283f0904b4016f9b6fa8d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Jul 2019 06:42:11 -0700 Subject: [PATCH 282/404] Only log namespace error when debug is enabled. Sometimes the model needs to be used before the class is passed to makeServicePlugin, where the namespace attribute is used for the getter. --- src/service-module/make-model.ts | 6 +++--- src/utils.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 2edbe974..7c142411 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -171,7 +171,7 @@ export default function makeModel(options: FeathersVuexOptions) { public static _getters(name: string, payload?: any) { const { namespace, store } = this - if (checkNamespace(namespace, this)) { + if (checkNamespace(namespace, this, options.debug)) { if (!store.getters.hasOwnProperty(`${namespace}/${name}`)) { throw new Error(`Could not find getter named ${namespace}/${name}`) } @@ -190,7 +190,7 @@ export default function makeModel(options: FeathersVuexOptions) { public static _commit(method: string, payload: any): void { const { namespace, store } = this - if (checkNamespace(namespace, this)) { + if (checkNamespace(namespace, this, options.debug)) { store.commit(`${namespace}/${method}`, payload) } } @@ -202,7 +202,7 @@ export default function makeModel(options: FeathersVuexOptions) { public static _dispatch(method: string, payload: any) { const { namespace, store } = this - if (checkNamespace(namespace, this)) { + if (checkNamespace(namespace, this, options.debug)) { return store.dispatch(`${namespace}/${method}`, payload) } } diff --git a/src/utils.ts b/src/utils.ts index f9c6e195..635b4dd2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -431,8 +431,8 @@ export function cloneWithAccessors(obj) { return clone } -export function checkNamespace(namespace, item) { - if (!namespace) { +export function checkNamespace(namespace, item, debug) { + if (!namespace && debug) { // eslint-disable-next-line no-console console.error( 'A `namespace` was not available on the Model for this item:', From 8a0e310d8aa6efc3806bc405544ba971da592f09 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 2 Jul 2019 06:42:25 -0700 Subject: [PATCH 283/404] 2.0.0-pre.51 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index eab01e72..f02b9710 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.50", + "version": "2.0.0-pre.51", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index c62e0792..c6c79bbd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.50", + "version": "2.0.0-pre.51", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 55f6fd451577fc32549185feb9767820c652226f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 7 Jul 2019 13:11:13 -0700 Subject: [PATCH 284/404] Turn temps off in find getter by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As pointed out by @t2t2 in #216, it’s more intuitive to opt in to the temps feature than to include temps by default. It leads to some confusing behavior when new records just start appearing. It’s also a lesser use case to need temp records in an app. --- src/service-module/service-module.getters.ts | 2 +- test/service-module/module.getters.test.ts | 34 ++++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/service-module/service-module.getters.ts b/src/service-module/service-module.getters.ts index 5e4b05d0..98d22d07 100644 --- a/src/service-module/service-module.getters.ts +++ b/src/service-module/service-module.getters.ts @@ -26,7 +26,7 @@ export default function makeServiceGetters() { params = params || {} // Set params.temps to false to not include the tempsById records - params.temps = params.hasOwnProperty('temps') ? params.temps : true + params.temps = params.hasOwnProperty('temps') ? params.temps : false const { paramsForServer, whitelist } = state const q = _omit(params.query || {}, paramsForServer) diff --git a/test/service-module/module.getters.test.ts b/test/service-module/module.getters.test.ts index c55fdbe9..b8bdb382 100644 --- a/test/service-module/module.getters.test.ts +++ b/test/service-module/module.getters.test.ts @@ -122,31 +122,31 @@ describe('Service Module - Getters', function() { assert(result.__id === tempId) }) - it('find', function() { + it('find - no temps by default', function() { const { state, items } = this const params = { query: {} } const results = find(state)(params) - assert.deepEqual(results.data, items, 'the list was correct') + assert.deepEqual( + results.data, + items.filter(i => i._id), + 'the list was correct' + ) assert(results.limit === 0, 'limit was correct') assert(results.skip === 0, 'skip was correct') - assert(results.total === 4, 'total was correct') + assert(results.total === 3, 'total was correct') }) - it('find without temps', function() { + it('find with temps', function() { const { state, items } = this // Set temps: false to skip the temps. - const params = { query: {}, temps: false } + const params = { query: {}, temps: true } const results = find(state)(params) - assert.deepEqual( - results.data, - items.filter(i => i._id), - 'the list was correct' - ) + assert.deepEqual(results.data, items, 'the list was correct') assert(results.limit === 0, 'limit was correct') assert(results.skip === 0, 'skip was correct') - assert(results.total === 3, 'total was correct') + assert(results.total === 4, 'total was correct') }) it('find with query', function() { @@ -242,7 +242,7 @@ describe('Service Module - Getters', function() { assert(results.data[0]._id === 1, 'the correct record was returned') assert(results.limit === 1, 'limit was correct') assert(results.skip === 0, 'skip was correct') - assert(results.total === 4, 'total was correct') + assert(results.total === 3, 'total was correct') }) it('find with skip', function() { @@ -250,12 +250,12 @@ describe('Service Module - Getters', function() { const params = { query: { $skip: 1 } } const results = find(state)(params) - assert(results.data.length === 3, 'the length was correct') + assert(results.data.length === 2, 'the length was correct') assert(results.data[0]._id === 2, 'the correct record was returned') assert(results.data[1]._id === 3, 'the correct record was returned') assert(results.limit === 0, 'limit was correct') assert(results.skip === 1, 'skip was correct') - assert(results.total === 4, 'total was correct') + assert(results.total === 3, 'total was correct') }) it('find with limit and skip', function() { @@ -267,7 +267,7 @@ describe('Service Module - Getters', function() { assert(results.data[0]._id === 2, 'the correct record was returned') assert(results.limit === 1, 'limit was correct') assert(results.skip === 1, 'skip was correct') - assert(results.total === 4, 'total was correct') + assert(results.total === 3, 'total was correct') }) it('find with select', function() { @@ -275,7 +275,7 @@ describe('Service Module - Getters', function() { const params = { query: { $select: ['otherField'] } } const results = find(state)(params) - assert(results.data.length === 4, 'the length was correct') + assert(results.data.length === 3, 'the length was correct') results.data.forEach(result => { assert(Object.keys(result).length <= 1, 'only one field was returned') }) @@ -286,6 +286,6 @@ describe('Service Module - Getters', function() { ) assert(results.limit === 0, 'limit was correct') assert(results.skip === 0, 'skip was correct') - assert(results.total === 4, 'total was correct') + assert(results.total === 3, 'total was correct') }) }) From b9679ce13c975c813c7079402847ff52ba598929 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 7 Jul 2019 13:16:12 -0700 Subject: [PATCH 285/404] Change registration of components to PascalCase as pointed out by @t2t2 in #216 --- docs/common-patterns.md | 4 +- docs/components.md | 99 +++++++++++++++++++----------------- src/FeathersVuexFind.ts | 14 +++-- src/FeathersVuexGet.ts | 2 +- src/vue-plugin/vue-plugin.ts | 4 +- 5 files changed, 67 insertions(+), 56 deletions(-) diff --git a/docs/common-patterns.md b/docs/common-patterns.md index da1cf897..da1a4be0 100755 --- a/docs/common-patterns.md +++ b/docs/common-patterns.md @@ -10,9 +10,9 @@ If you have a "WTF this isn't working" moment while setting up a new service, ma You can set `debug: true` in the options to enable some logging to assist with debugging. -## Use the `` and `` components +## Use the `` and `` components -Using the new `` and `` components provides concise access to the best features of `feathers-vuex`, including live queries, reactive lists, custom pagination tracking per component, and fall-through cacheing of local data in the Vuex store. Check out the [Renderless Data Components](./components.md) docs for more details. +Using the new `` and `` components provides concise access to the best features of `feathers-vuex`, including live queries, reactive lists, custom pagination tracking per component, and fall-through cacheing of local data in the Vuex store. Check out the [Renderless Data Components](./components.md) docs for more details. ## Use the `makeFindMixin` and `makeGetMixin` utilities diff --git a/docs/components.md b/docs/components.md index 71c441d6..7ac605bd 100644 --- a/docs/components.md +++ b/docs/components.md @@ -2,7 +2,7 @@ title: Renderless Data Components --- -Currently in `feathers-vuex@next`, a set of new, renderless data provider components -- `` and `` -- simplify performing queries against the store and/or the API server. They make the data available inside the component's default slot. +Currently in `feathers-vuex@next`, a set of new, renderless data provider components -- `` and `` -- simplify performing queries against the store and/or the API server. They make the data available inside the component's default slot. This first version does not assist with server-side pagination, but you can use it with your own pagination logic using the `query` or `fetchQuery` attributes, described later. To see why you might want to use these components, here are two example components that are functionally equivalent. @@ -10,11 +10,11 @@ Here's what it looks like to use the new component: ```html - + ``` -Notice in the above example that using the mixin automatically makes the `todos` available in the template. The mixins automatically setup a few properties in the viewModel based on the camelCased name of the service. You can also provide a `name` attribute. +In the above example, any records returned from the server will automatically show up when they become available. It also automatically responds to realtime events when you're using one of FeathersJS's realtime transports, like Socket.io. + +Notice in the above example that using the mixin automatically makes the `serverTasks` available in the template. The mixins automatically setup a few properties in the viewModel based on the camelCased name of the service. You can also provide a `name` attribute to override the defaults: ## Options @@ -78,8 +83,6 @@ The `makeFindMixin` has these unique options: - **qid {String}** - The "query identifier" ("qid", for short) is used for storing pagination data in the Vuex store. See the service module docs to see what you'll find inside. The `qid` and its accompanying pagination data from the store will eventually be used for cacheing and preventing duplicate queries to the API. -**Important: For the built in pagination features to work, you must not directly manipulate the `context.params` object in any hooks.** - ### Options for only `makeGetMixin` The `makeGetMixin` has these unique options: @@ -221,6 +224,117 @@ const mixedInDataFromAboveExample = { } ``` +## Pagination with fall-through cacheing + +The `makeFindMixin` in `feathers-vuex@2.x` features a great new, high performance, fall-through cacheing feature, which only uses a single query! Read the service module documentation for details of how it works under the hood. It really makes easy work of high-performance pagination. To use the pagination, provide `$limit` and `$skip` attributes in `params.query`. This is exactly the same way you would normally do with any FeathersJS query. So this is completely transparent to how you'd normally do it. + +Let's extend the first example on this page to support pagination. We'll do the following: + +1. Setup the `makeFindMixin` to use the `watch` property. +2. Add a `data` attribute to the component with `limit` and `skip` properties. +3. Reference the `limit` and `skip` in `params.query`. +4. Add methods for `previousPage` and `nextPage` +5. Create buttons for changing the limit and skip. + +```vue + + + +``` + +In the above example, since we've enabled the `watch` attribute on the makeFindMixin, every time the params change, the query will run again. `feathers-vuex` will keep track of the queries and the pages that are visited, noting which records are returned on each page. When a page is revisited, the data in the store will *immedately* display to the user. The query will (by default) go out to the API server, and data will be updated in the background when the response arrives. + +## Enabling live lists with pagination + +The new fall-through cacheing pagination does not currently support live sorting of lists. This means that when a new record arrives from the database, it doesn't automatically get sorted into the correct page and shuffle the other records around it. The lists will update as the user navigates to previous/next pages. Fixing this will be a top priority after 2.x ships. + +If you would like to enable live lists again, you'll need to do it manually, the way it has always been done: Use the `find` getter and pass a query to it. To accomplish this goal, we'll override the items property in the component in order to + +1. Provide a new query without the pagination properties. +2. Create a new query just for the local records. +3. Use the new `find<Resource>InStore` method (where Resource is the PascalCased name of the items) + +```vue + + + +``` + +In the above example, since we provided the `serverTasks` attribute, the `makeFindMixin` will not set one up to overwrite it. This allows us to create our own query and call the alias for the `find` getter. When we create this new query, let's remember to not use the same `$skip` and `$sort` as the API query. Otherwise, it's likely that no records from the Vuex store will show. + ## Debugging the makeFindMixin **Important: For the built in pagination features to work, you must not directly manipulate the `context.params` object in any hooks.** From 88c8074a6272504c782095e403338740651593cf Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 8 Jul 2019 01:36:28 -0700 Subject: [PATCH 295/404] 2.0.0-pre.54 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 54f44fd9..8e4040a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.53", + "version": "2.0.0-pre.54", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 488fbbdd..3fcb0e81 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.53", + "version": "2.0.0-pre.54", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From b5a81aee559a23fea375c2ad14410c6ef8fb1353 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 8 Jul 2019 08:14:17 -0700 Subject: [PATCH 296/404] Add docs about makeFindMixin debouncing --- docs/mixins.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/docs/mixins.md b/docs/mixins.md index b6ec21bc..13269986 100644 --- a/docs/mixins.md +++ b/docs/mixins.md @@ -279,11 +279,87 @@ export default { In the above example, since we've enabled the `watch` attribute on the makeFindMixin, every time the params change, the query will run again. `feathers-vuex` will keep track of the queries and the pages that are visited, noting which records are returned on each page. When a page is revisited, the data in the store will *immedately* display to the user. The query will (by default) go out to the API server, and data will be updated in the background when the response arrives. +## Debouncing requests + +What happens when a query with a watcher is attached to an attribute that might change rapidly? A lot of API requests can get sent in succession. If too many are sent, some of them will start to fail (a.k.a. bounce). The `makeFindMixin` has a built-in utility for debouncing requests. Enabling it makes it so requests only are sent after a specific amount of time has passed. To enable it, pass a `debounce` attribute in the `params`, as shown in the next example. + +Let's build on our previous example by adding a `search` feature where the user can type some input. Here are the steps: + +1. Add an attribute to the data to which we will bind user input. We'll call it `search`. +2. Modify params to include the `search` attribute in a supportive way. +3. Enable the the debounce feature. +4. Add an `input:text` to the template which binds to the attribute in step 1. + +```vue + + + +``` + +Notice a couple of things in the above example. We enabled the internal `debounce` feature by simply adding `debounce: 500` to the params (outside the query). This means that as the user types, requests will be queued inside a 500 ms interval. The request will be sent as soon as the user stops typing for 500 milliseconds. For example, if the user types a single character, waits ~400ms, then types a second character, the first request will be cancelled and another request will be sent 500ms after typing the second character. It's more likely that these requests will not bounce. :) + +We also added a `$regex` search to the params. This is a MongoDB feature, which naturally also works with Mongoose services (since Mongoose is a tool built for MongoDB). If you're using another type of service, you will need to come up with a solution for performing searches safely. The solution will vary depending on the database used. + +Feel free to make a PR for using something else that could be useful to the community! We love those! + ## Enabling live lists with pagination The new fall-through cacheing pagination does not currently support live sorting of lists. This means that when a new record arrives from the database, it doesn't automatically get sorted into the correct page and shuffle the other records around it. The lists will update as the user navigates to previous/next pages. Fixing this will be a top priority after 2.x ships. -If you would like to enable live lists again, you'll need to do it manually, the way it has always been done: Use the `find` getter and pass a query to it. To accomplish this goal, we'll override the items property in the component in order to +If you would like to enable live lists again, it requires manual setup, meaning the way it has always been done in `1.x`: Use the `find` getter and pass a query to it. To accomplish this goal, we'll override the items property in the component in order to 1. Provide a new query without the pagination properties. 2. Create a new query just for the local records. From 8288aa356d82167a8fb3bec174b4a1c9c053646f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 8 Jul 2019 22:15:28 -0700 Subject: [PATCH 297/404] Refactor & simplify the find getter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The find getter will never use the FETCH_PARAMS, so it doesn’t need to use the `getParams` function at all. This means the `getParams` function doesn’t need any branching logic centered around the find getter, so it has been simplified. These changes also make it so that if FETCH_PARAMS and PARAMS are both provided, the find getter will NOT use the internal pagination feature, and instead will behave the same as it does in feathers-vued@1.x. --- src/make-find-mixin.ts | 62 +++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index 2e93db65..b0a522d1 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -73,13 +73,13 @@ export default function makeFindMixin(options) { [QID]: qid, [MOST_RECENT_QUERY]: null } - const getParams = (providedParams, params, fetchParams) => { + // Should only be used with actual fetching API calls. + const getParams = ({ providedParams, params, fetchParams }) => { if (providedParams) { return providedParams - } else if (fetchParams || fetchParams === null) { - return fetchParams } else { - return params + // Returning null fetchParams allows the query to be skipped. + return (fetchParams || fetchParams === null) ? fetchParams : params } } @@ -94,28 +94,32 @@ export default function makeFindMixin(options) { [ITEMS]() { const serviceName = this[SERVICE_NAME] const serviceState = this.$store.state[serviceName] - const paramsToUse = getParams(undefined, this[PARAMS], this[FETCH_PARAMS]) - if (!paramsToUse) { - return [] - } - const { defaultSkip: skip, defaultLimit: limit } = serviceState.pagination - const pagination = this[PAGINATION][paramsToUse.qid || this[QID]] || {} - const response = ( - skip !== null && - skip !== undefined && - limit !== null && - limit !== undefined - ) ? { limit, skip } : {} - const queryInfo = getQueryInfo(paramsToUse, response) - const items = getItemsFromQueryInfo(pagination, queryInfo, serviceState.keyedById) - if (this[LOCAL] && this[PARAMS]) { + // If both queries are provided, we're not using fall-through pagination. + if (this[FETCH_PARAMS] && this[PARAMS]) { return this.$store.getters[`${this[SERVICE_NAME]}/find`](this[PARAMS]).data - } else if (items && items.length) { - return items - } else { - return [] } + + const params = this[PARAMS] + // Check for pagination data for this query. + if (params) { + const { defaultSkip: skip, defaultLimit: limit } = serviceState.pagination + const pagination = this[PAGINATION][params.qid || this[QID]] || {} + const response = ( + skip !== null && + skip !== undefined && + limit !== null && + limit !== undefined + ) ? { limit, skip } : {} + const queryInfo = getQueryInfo(params, response) + const items = getItemsFromQueryInfo(pagination, queryInfo, serviceState.keyedById) + + if (items && items.length) { + return items + } + } + + return [] }, // Queries the Vuex store with the exact same query that was sent to the API server. [ITEMS_FETCHED]() { @@ -135,7 +139,11 @@ export default function makeFindMixin(options) { }, methods: { [`${FIND_ACTION}DebouncedProxy`](params) { - const paramsToUse = getParams(params, this[PARAMS], this[FETCH_PARAMS]) + const paramsToUse = getParams({ + providedParams: params, + params: this[PARAMS], + fetchParams: this[FETCH_PARAMS] + }) if (paramsToUse && paramsToUse.debounce) { const cachedDebounceFunction = this[`${FIND_ACTION}Debounced`] const mostRecentTime = this[`${FIND_ACTION}MostRecentDebounceTime`] @@ -150,7 +158,11 @@ export default function makeFindMixin(options) { } }, [FIND_ACTION](params) { - const paramsToUse = getParams(params, this[PARAMS], this[FETCH_PARAMS]) + const paramsToUse = getParams({ + providedParams: params, + params: this[PARAMS], + fetchParams: this[FETCH_PARAMS] + }) if (!this[LOCAL]) { const shouldExecuteQuery = typeof this[QUERY_WHEN] === 'function' From 1590997e4f52bed2b9c200863542a0f37ec3ae80 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 8 Jul 2019 22:16:53 -0700 Subject: [PATCH 298/404] Fix _get with complex stringified objects as keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _get doesn’t seem to do well finding nested data when the keys are stringified objects. This grabs the ids using guarding and checks at each level of the pagination object. --- src/utils.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index daf7cdd2..3e9f401a 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -321,8 +321,10 @@ export function getQueryInfo(params = {}, response = {}) { export function getItemsFromQueryInfo(pagination, queryInfo, keyedById) { const { queryId, pageId } = queryInfo - // @ts-ignore - const ids = _get(pagination, `[${queryId}][${pageId}].ids`) + const queryLevel = pagination[queryId] + const pageLevel = queryLevel && queryLevel[pageId] + const ids = pageLevel && pageLevel.ids + if (ids && ids.length) { return ids.map(id => keyedById[id]) } else { From 8308f2a6d2eb00a10b25f34e69ce558be52bfd3e Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 8 Jul 2019 22:19:52 -0700 Subject: [PATCH 299/404] 2.0.0-pre.55 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8e4040a5..1182e97c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.54", + "version": "2.0.0-pre.55", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 3fcb0e81..aadc0394 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.54", + "version": "2.0.0-pre.55", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From e4aa279900c881bcb65cc6c078aa1e08fe49a68b Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 9 Jul 2019 07:49:27 -0700 Subject: [PATCH 300/404] Better docs for enabling live lists again. --- docs/mixins.md | 90 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 31 deletions(-) diff --git a/docs/mixins.md b/docs/mixins.md index 13269986..394dee52 100644 --- a/docs/mixins.md +++ b/docs/mixins.md @@ -357,40 +357,27 @@ Feel free to make a PR for using something else that could be useful to the comm ## Enabling live lists with pagination -The new fall-through cacheing pagination does not currently support live sorting of lists. This means that when a new record arrives from the database, it doesn't automatically get sorted into the correct page and shuffle the other records around it. The lists will update as the user navigates to previous/next pages. Fixing this will be a top priority after 2.x ships. +The new fall-through cacheing pagination does not currently support live sorting of lists. This means that when a new record arrives from the database, it doesn't automatically get sorted into the correct page and shuffle the other records around it. The lists will update as the user navigates to previous/next pages. Coming up with a solution for this will be a top priority after 2.x ships. In the meantime, here are some alternatives. -If you would like to enable live lists again, it requires manual setup, meaning the way it has always been done in `1.x`: Use the `find` getter and pass a query to it. To accomplish this goal, we'll override the items property in the component in order to +### Refresh the current query after changes -1. Provide a new query without the pagination properties. -2. Create a new query just for the local records. -3. Use the new `find<Resource>InStore` method (where Resource is the PascalCased name of the items) +This is a simplistic approach. In some cases, when you expect the data to have changed in whatever list you are currently showing to the user, you can simply call the find action for that list and get new data from the server. In the below example, whenever the `TodoEntryForm` component emits the `created` event, it triggers the `findTodos` method. Note: you wouldn't want to do `@created="findTodos` because that would potentially pass the new todo as the params like `findTodos(newTodo)` instead of `findTodos()`. Passing no params will automatically use the `todosParams` for the query. ```vue + + +``` ## Debugging the makeFindMixin From 39b4ce8958e18809dd2b83d3794cb90fbe0868c0 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 9 Jul 2019 07:50:19 -0700 Subject: [PATCH 301/404] Fix naming of the Service Module page in navigation --- docs/service-module.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/service-module.md b/docs/service-module.md index 9dcb50a8..c0f4e755 100644 --- a/docs/service-module.md +++ b/docs/service-module.md @@ -1,10 +1,9 @@ - - --- title: Service Module API - --- + + The `Service Module` creates plugins which can be used to connect a Feathers service to the Vuex store. Once you create the plugin, you must register it in the `plugins` section of your store setup: Here's a basic example of creating a service plugin: From 02e1c8f39e27664134660d13997993985eb82b1c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 9 Jul 2019 18:39:29 -0700 Subject: [PATCH 302/404] Allow passing paginate:false in the params This will allow disabling the client-side pagination in the make-find-mixin when the developer passes `paginate: false` in the params. The getter will then revert to the old behavior. This is important for easy upgradability for existing apps. --- src/make-find-mixin.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index b0a522d1..80d26ce2 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -96,7 +96,8 @@ export default function makeFindMixin(options) { const serviceState = this.$store.state[serviceName] // If both queries are provided, we're not using fall-through pagination. - if (this[FETCH_PARAMS] && this[PARAMS]) { + // User can pass `paginate: false` to force old behavior with a single query. + if (this[FETCH_PARAMS] && this[PARAMS] || this[PARAMS].paginate === false) { return this.$store.getters[`${this[SERVICE_NAME]}/find`](this[PARAMS]).data } From b3a8d6021040844dd8dbad70b0b810e8b8d9d481 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 9 Jul 2019 18:40:07 -0700 Subject: [PATCH 303/404] 2.0.0-pre.56 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1182e97c..71c9d8d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.55", + "version": "2.0.0-pre.56", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index aadc0394..415c572e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.55", + "version": "2.0.0-pre.56", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 50ad69b4de670b22652e2ead07cb4032635000a3 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 9 Jul 2019 19:15:05 -0700 Subject: [PATCH 304/404] Document the paginate: false in makeFindMixin --- docs/mixins.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/docs/mixins.md b/docs/mixins.md index 394dee52..617e0234 100644 --- a/docs/mixins.md +++ b/docs/mixins.md @@ -228,6 +228,8 @@ const mixedInDataFromAboveExample = { The `makeFindMixin` in `feathers-vuex@2.x` features a great new, high performance, fall-through cacheing feature, which only uses a single query! Read the service module documentation for details of how it works under the hood. It really makes easy work of high-performance pagination. To use the pagination, provide `$limit` and `$skip` attributes in `params.query`. This is exactly the same way you would normally do with any FeathersJS query. So this is completely transparent to how you'd normally do it. +> Note: By default, the pagination feature is turned on. To simplify updating existing apps using `feathers-vuex`, you can turn this feature off in any part of your app by passing `paginate: false` in the params for that particular query. This will completely restore the previous behavior and re-enable live lists. + Let's extend the first example on this page to support pagination. We'll do the following: 1. Setup the `makeFindMixin` to use the `watch` property. @@ -359,6 +361,43 @@ Feel free to make a PR for using something else that could be useful to the comm The new fall-through cacheing pagination does not currently support live sorting of lists. This means that when a new record arrives from the database, it doesn't automatically get sorted into the correct page and shuffle the other records around it. The lists will update as the user navigates to previous/next pages. Coming up with a solution for this will be a top priority after 2.x ships. In the meantime, here are some alternatives. +### Use `paginate:false` in the params + +Restore the previous default behavior by putting `paginate:false` in the params. This is the easiest way to upgrade existing apps using the `makeFindMixin`. Look at the `todosParams` in this example: + +```vue + + + +``` + +The `paginate` property will not be sent to the server, but it will locally disable the pagination and enable the live lists from the `find` getter. + ### Refresh the current query after changes This is a simplistic approach. In some cases, when you expect the data to have changed in whatever list you are currently showing to the user, you can simply call the find action for that list and get new data from the server. In the below example, whenever the `TodoEntryForm` component emits the `created` event, it triggers the `findTodos` method. Note: you wouldn't want to do `@created="findTodos` because that would potentially pass the new todo as the params like `findTodos(newTodo)` instead of `findTodos()`. Passing no params will automatically use the `todosParams` for the query. From 4a1c86a2f0d802e2e234de4c0f0818d8f475bee3 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 9 Jul 2019 21:13:14 -0700 Subject: [PATCH 305/404] Pagination++ add total to the mostRecent data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now you can pull the most recent total from the service pagination’s `mostRecent` state, in addition to each of the queries pagination state. --- src/service-module/service-module.mutations.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 12f6d765..4d0accaa 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -294,7 +294,8 @@ export default function makeServiceMutations() { queryParams, pageId, pageParams, - queriedAt + queriedAt, + total } const qidData = state.pagination[qid] || {} From 555ea53dcc5a851c5a78df5cd1ecc6780ed75cfc Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 9 Jul 2019 21:13:29 -0700 Subject: [PATCH 306/404] 2.0.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 71c9d8d1..00dd66dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.56", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 415c572e..5fb16b3e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.56", + "version": "2.0.0", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From e3a2c28d1fb548e844c5cca1850fe1efb2755558 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 9 Jul 2019 21:14:16 -0700 Subject: [PATCH 307/404] 2.0.1-0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 00dd66dd..55d4dafe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0", + "version": "2.0.1-0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5fb16b3e..8a327bc2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0", + "version": "2.0.1-0", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From f94490ccb5ff85fde25637e1ebce0b6f6d04b863 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 9 Jul 2019 21:16:25 -0700 Subject: [PATCH 308/404] Fix version number --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8a327bc2..415c572e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.1-0", + "version": "2.0.0-pre.56", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 94ab8ee01c8362d1e375a4c654985d69460b0f85 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 9 Jul 2019 21:16:33 -0700 Subject: [PATCH 309/404] 2.0.0-pre.57 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 55d4dafe..62d2fa48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.1-0", + "version": "2.0.0-pre.57", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 415c572e..65fb8b6e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.56", + "version": "2.0.0-pre.57", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From bc688a4f784073d5c2de963c547eeb0dfc62a7e7 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 10 Jul 2019 00:27:34 -0700 Subject: [PATCH 310/404] Fix infinite loop / stack overflow The getId was calling itself repeatedly. No more. --- src/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.ts b/src/utils.ts index 3e9f401a..1a0ffe37 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -193,7 +193,7 @@ export function getId(item, idField) { return item._id } if (item.hasOwnProperty(idField)) { - return getId(item, idField) + return item[idField] } } From 3af7a251e957a7b1967554d409dff47acaa8fc8f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 10 Jul 2019 00:27:48 -0700 Subject: [PATCH 311/404] Add total to mostRecent in tests --- test/service-module/service-module.mutations.test.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/service-module/service-module.mutations.test.ts b/test/service-module/service-module.mutations.test.ts index 1522bdb6..bc701a9a 100644 --- a/test/service-module/service-module.mutations.test.ts +++ b/test/service-module/service-module.mutations.test.ts @@ -891,7 +891,8 @@ describe('Service Module - Mutations', function() { queryParams, pageId, pageParams, - queriedAt + queriedAt, + total: 155 }, '{}': { total: fakeData.transactions.length, @@ -937,7 +938,8 @@ describe('Service Module - Mutations', function() { queryParams, pageId, pageParams, - queriedAt + queriedAt, + total: 155 }, '{}': { total: fakeData.transactions.length, @@ -983,7 +985,8 @@ describe('Service Module - Mutations', function() { queryParams, pageId, pageParams, - queriedAt + queriedAt, + total: 155 }, '{}': { total: fakeData.transactions.length, @@ -1042,7 +1045,8 @@ describe('Service Module - Mutations', function() { queryParams, pageId, pageParams, - queriedAt + queriedAt, + total: 155 }, '{}': { total: fakeData.transactions.length, From c9e0bfeba78fa870f7a54a06400806eaf8a2cf49 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 10 Jul 2019 00:28:02 -0700 Subject: [PATCH 312/404] Fix error in makeFindMixin when params are missing. --- src/make-find-mixin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index 80d26ce2..b3dd1a56 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -97,7 +97,7 @@ export default function makeFindMixin(options) { // If both queries are provided, we're not using fall-through pagination. // User can pass `paginate: false` to force old behavior with a single query. - if (this[FETCH_PARAMS] && this[PARAMS] || this[PARAMS].paginate === false) { + if (this[FETCH_PARAMS] && this[PARAMS] || this[PARAMS] && this[PARAMS].paginate === false) { return this.$store.getters[`${this[SERVICE_NAME]}/find`](this[PARAMS]).data } From f9f2a45d7645b3d01795fe05a1c66b5cc818fff3 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 10 Jul 2019 00:28:12 -0700 Subject: [PATCH 313/404] 2.0.0-pre.58 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 62d2fa48..0c439680 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.57", + "version": "2.0.0-pre.58", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 65fb8b6e..725443b6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.57", + "version": "2.0.0-pre.58", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From aa5bad0a241e6f274326b8adf049b54ac8179f68 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 10 Jul 2019 09:21:21 -0700 Subject: [PATCH 314/404] Fix logic for pagination lookup with skip and sort This makes sure that the limit and skip from a query is prioritized over the default limit and skip. --- src/make-find-mixin.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index b3dd1a56..bd28ed2c 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -104,14 +104,11 @@ export default function makeFindMixin(options) { const params = this[PARAMS] // Check for pagination data for this query. if (params) { - const { defaultSkip: skip, defaultLimit: limit } = serviceState.pagination + const { defaultSkip, defaultLimit } = serviceState.pagination + const skip = params.query.$skip || defaultSkip + const limit = params.query.$limit || defaultLimit const pagination = this[PAGINATION][params.qid || this[QID]] || {} - const response = ( - skip !== null && - skip !== undefined && - limit !== null && - limit !== undefined - ) ? { limit, skip } : {} + const response = skip != null && limit != null ? { limit, skip } : {} const queryInfo = getQueryInfo(params, response) const items = getItemsFromQueryInfo(pagination, queryInfo, serviceState.keyedById) From f29a76893a2c1ab1777e53bf344f20ec18bf5862 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 10 Jul 2019 09:22:04 -0700 Subject: [PATCH 315/404] 2.0.0-pre.59 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0c439680..24356714 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.58", + "version": "2.0.0-pre.59", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 725443b6..56586f6f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.58", + "version": "2.0.0-pre.59", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 0e147e91032b647d64d9faf8dae265605b7cc5a7 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 10 Jul 2019 09:26:37 -0700 Subject: [PATCH 316/404] Prevent error when params.query is assumed Since Feathers can assume that no query object means to use `{}`, the assumption can be safely assumed in the updatePaginationForQuery mutation. --- src/service-module/service-module.mutations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 4d0accaa..64096d8e 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -266,7 +266,7 @@ export default function makeServiceMutations() { * Stores pagination data on state.pagination based on the query identifier * (qid) The qid must be manually assigned to `params.qid` */ - updatePaginationForQuery(state, { qid, response, query }) { + updatePaginationForQuery(state, { qid, response, query = {} }) { const { data, total } = response const { idField } = state const ids = data.map(i => i[idField]) From 5645d34d863cc59a010119ebfe11c697a7a9b186 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 10 Jul 2019 09:26:45 -0700 Subject: [PATCH 317/404] 2.0.0-pre.60 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 24356714..23bdbca6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.59", + "version": "2.0.0-pre.60", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 56586f6f..bfbdcb2d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.59", + "version": "2.0.0-pre.60", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 4a2bac1ec8809e7123e7b0bc359095a27fcd3ea8 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 13 Jul 2019 07:46:01 -0700 Subject: [PATCH 318/404] Guard against null values for most recent query --- src/make-find-mixin.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index bd28ed2c..46630746 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -191,7 +191,9 @@ export default function makeFindMixin(options) { }) } } else { - this[MOST_RECENT_QUERY].isOutdated = true + if (this[MOST_RECENT_QUERY]) { + this[MOST_RECENT_QUERY].isOutdated = true + } } } }, From fb46f35216163f28ecbe62f0f3deed64eb8a6dd4 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 13 Jul 2019 07:46:09 -0700 Subject: [PATCH 319/404] 2.0.0-pre.61 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 23bdbca6..2fd46bba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.60", + "version": "2.0.0-pre.61", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index bfbdcb2d..6e5e57a9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.60", + "version": "2.0.0-pre.61", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 1411681dcce6a6e70e9c534f051bbb4d47e9f117 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 15 Jul 2019 13:06:47 -0700 Subject: [PATCH 320/404] Add `getFromStore` to makeFindGetter --- src/make-get-mixin.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/make-get-mixin.ts b/src/make-get-mixin.ts index 3aa7ef10..ec88f021 100644 --- a/src/make-get-mixin.ts +++ b/src/make-get-mixin.ts @@ -53,6 +53,7 @@ export default function makeFindMixin(options) { const WATCH = `${prefix}Watch` const QUERY_WHEN = `${prefix}QueryWhen` const GET_ACTION = `get${capitalized}` + const GET_GETTER = `get${capitalized}FromStore` const LOCAL = `${prefix}Local` const QID = `${prefix}Qid` const ID = `${prefix}Id` @@ -74,6 +75,13 @@ export default function makeFindMixin(options) { }, [QUERY_WHEN]() { return true + }, + // Exposes `getFromStore` + [GET_GETTER]() { + return id => { + const serviceName = this[SERVICE_NAME] + return this.$store.getters[`${serviceName}/get`](id) + } } }, methods: { From aad86b4ad85295b8d8a3d654c2088a449d4cb1cb Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 15 Jul 2019 13:06:56 -0700 Subject: [PATCH 321/404] 2.0.0-pre.62 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2fd46bba..9836ef9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.61", + "version": "2.0.0-pre.62", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 6e5e57a9..ff55b624 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.61", + "version": "2.0.0-pre.62", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From b1f25a55ff1ee9d98ffb7af9673ca1c1c908591f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 19 Jul 2019 01:15:13 -0700 Subject: [PATCH 322/404] Auth: prefer the user from the authenticate response. This makes it so that if a user is returned in the response to `authenticate`, that user will be commited to the store and the additional request will not be sent. This is especially useful when important server-side populating occurs during login. --- src/auth-module/auth-module.actions.ts | 7 +++++-- src/auth-module/auth-module.state.ts | 1 + src/make-find-mixin.ts | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/auth-module/auth-module.actions.ts b/src/auth-module/auth-module.actions.ts index 4f3de751..119d4eb5 100644 --- a/src/auth-module/auth-module.actions.ts +++ b/src/auth-module/auth-module.actions.ts @@ -34,8 +34,11 @@ export default function makeAuthActions(feathersClient) { .then(payload => { commit('setPayload', payload) - // Populate the user if the userService was provided - if ( + // If a user was returned in the authenticate response, use that user. + if (response[state.responseEntityField]) { + commit('setUser', response[state.responseEntityField]) + // Populate the user if the userService was provided + } else if ( state.userService && payload.hasOwnProperty(state.entityIdField) ) { diff --git a/src/auth-module/auth-module.state.ts b/src/auth-module/auth-module.state.ts index 47dd8468..f0702773 100644 --- a/src/auth-module/auth-module.state.ts +++ b/src/auth-module/auth-module.state.ts @@ -8,6 +8,7 @@ export default function setupAuthState({ userService }) { accessToken: null, // The JWT payload: null, // The JWT payload entityIdField: 'userId', + responseEntityField: 'user', isAuthenticatePending: false, isLogoutPending: false, diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index 46630746..b7a9566c 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -98,7 +98,7 @@ export default function makeFindMixin(options) { // If both queries are provided, we're not using fall-through pagination. // User can pass `paginate: false` to force old behavior with a single query. if (this[FETCH_PARAMS] && this[PARAMS] || this[PARAMS] && this[PARAMS].paginate === false) { - return this.$store.getters[`${this[SERVICE_NAME]}/find`](this[PARAMS]).data + return this.$store.getters[`${serviceName}/find`](this[PARAMS]).data } const params = this[PARAMS] From 2f79faba70a87c151345eae92cc954abb587674a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 19 Jul 2019 01:15:39 -0700 Subject: [PATCH 323/404] 2.0.0-pre.63 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9836ef9a..2a35efce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.62", + "version": "2.0.0-pre.63", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ff55b624..40dbd5f6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.62", + "version": "2.0.0-pre.63", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 1058170625e80fa343c1d8732d151d8c9127c1a8 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 20 Jul 2019 15:09:07 -0700 Subject: [PATCH 324/404] Properly instantiate user returned with auth response This adds a serverAlias and debug prop to the auth module --- src/auth-module/auth-module.actions.ts | 16 ++++++++++++++-- src/auth-module/auth-module.state.ts | 5 +++-- src/auth-module/auth-module.ts | 7 +++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/auth-module/auth-module.actions.ts b/src/auth-module/auth-module.actions.ts index 119d4eb5..db9dfa32 100644 --- a/src/auth-module/auth-module.actions.ts +++ b/src/auth-module/auth-module.actions.ts @@ -3,6 +3,8 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ +import { models } from '../index' + export default function makeAuthActions(feathersClient) { return { authenticate(store, data) { @@ -34,9 +36,19 @@ export default function makeAuthActions(feathersClient) { .then(payload => { commit('setPayload', payload) + let user = response[state.responseEntityField] + // If a user was returned in the authenticate response, use that user. - if (response[state.responseEntityField]) { - commit('setUser', response[state.responseEntityField]) + if (user) { + if (state.serverAlias && state.userService) { + const Model = Object.keys(models[state.serverAlias]) + .map(modelName => models[state.serverAlias][modelName]) + .find(model => model.servicePath === state.userService) + if (Model) { + user = new Model(user) + } + } + commit('setUser', user) // Populate the user if the userService was provided } else if ( state.userService && diff --git a/src/auth-module/auth-module.state.ts b/src/auth-module/auth-module.state.ts index f0702773..44d5a836 100644 --- a/src/auth-module/auth-module.state.ts +++ b/src/auth-module/auth-module.state.ts @@ -3,7 +3,7 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -export default function setupAuthState({ userService }) { +export default function setupAuthState({ userService, serverAlias }) { const state = { accessToken: null, // The JWT payload: null, // The JWT payload @@ -15,7 +15,8 @@ export default function setupAuthState({ userService }) { errorOnAuthenticate: null, errorOnLogout: null, - user: null + user: null, + serverAlias } // If a userService string was passed, add a user attribute if (userService) { diff --git a/src/auth-module/auth-module.ts b/src/auth-module/auth-module.ts index 9e77acfb..c9c60025 100644 --- a/src/auth-module/auth-module.ts +++ b/src/auth-module/auth-module.ts @@ -11,6 +11,8 @@ import setupActions from './auth-module.actions' const defaults = { namespace: 'auth', userService: '', // Set this to automatically populate the user (using an additional request) on login success. + serverAlias: null, + debug: false, state: {}, // for custom state getters: {}, // for custom getters mutations: {}, // for custom mutations @@ -30,6 +32,11 @@ export default function authPluginInit(feathersClient) { 'You must register the @feathersjs/authentication-client plugin before using the feathers-vuex auth module' ) } + if (options.debug && options.userService && !options.serverAlias) { + console.warn( + 'A userService was provided, but no serverAlias was provided. To make sure the user record is an instance of the User model, a serverAlias must be provided.' + ) + } const defaultState = setupState(options) const defaultGetters = setupGetters() From 8ff57fba9e70b4edc6b7f9ac9800157fbf39f643 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 20 Jul 2019 15:09:16 -0700 Subject: [PATCH 325/404] 2.0.0-pre.64 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2a35efce..ee363054 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.63", + "version": "2.0.0-pre.64", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 40dbd5f6..843609f4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.63", + "version": "2.0.0-pre.64", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 9cc1ae6d22357593125741d24d996edb8cfa09bc Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 21 Jul 2019 00:16:19 -0700 Subject: [PATCH 326/404] Call setupInstance before storing data. This update is for scenarios when using Model classes. Any incoming data will be converted to Model instances before it is added to the store. This also makes it so that the model data is setup properly when updates are received from the API server. --- src/service-module/make-model.ts | 16 +-- src/service-module/service-module.actions.ts | 63 +++++++----- .../service-module.mutations.ts | 34 ++++--- .../service-module.actions.test.ts | 99 ++++++++----------- 4 files changed, 106 insertions(+), 106 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 7c142411..1a389ec4 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -94,13 +94,15 @@ export default function makeModel(options: FeathersVuexOptions) { data = data || {} + const existingItem = hasValidId && !options.clone + ? getFromStore.call(this.constructor, id) + : null + // If it already exists, update the original and return - if (hasValidId && !options.clone) { - const existingItem = getFromStore.call(this.constructor, id) - if (existingItem) { - _commit.call(this.constructor, 'updateItem', data) - return existingItem - } + if (existingItem) { + data = setupInstance.call(this, data, { models, store }) || data + _commit.call(this.constructor, 'mergeInstance', data) + return existingItem } // Mark as a clone @@ -111,7 +113,7 @@ export default function makeModel(options: FeathersVuexOptions) { }) } - // Setup instanceDefaults, separate out accessors + // Setup instanceDefaults if (instanceDefaults && typeof instanceDefaults === 'function') { const defaults = instanceDefaults.call(this, data, { models, store }) || data mergeWithAccessors(this, defaults) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index 00cc5de4..bd906a65 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -8,7 +8,7 @@ import { getId } from '../utils' export default function makeServiceActions(service) { const serviceActions = { - find({ commit, dispatch }, params) { + async find({ commit, dispatch }, params) { params = params || {} params = fastCopy(params) @@ -23,7 +23,7 @@ export default function makeServiceActions(service) { // Two query syntaxes are supported, since actions only receive one argument. // 1. Just pass the id: `get(1)` // 2. Pass arguments as an array: `get([null, params])` - get({ state, getters, commit, dispatch }, args) { + async get({ state, getters, commit, dispatch }, args) { let id let params let skipRequestIfExists @@ -49,8 +49,8 @@ export default function makeServiceActions(service) { commit('setPending', 'get') return service .get(id, params) - .then(item => { - dispatch('addOrUpdate', item) + .then(async item => { + await dispatch('addOrUpdate', item) commit('unsetPending', 'get') return state.keyedById[id] }) @@ -62,15 +62,14 @@ export default function makeServiceActions(service) { } // If the records is already in store, return it - const existedItem = getters.get(id, params) - if (existedItem) { - if (!skipRequestIfExists) getFromRemote() - return Promise.resolve(existedItem) + const existingItem = getters.get(id, params) + if (existingItem && skipRequestIfExists) { + return Promise.resolve(existingItem) } return getFromRemote() }, - create({ commit, dispatch, state }, dataOrArray) { + async create({ commit, dispatch, state }, dataOrArray) { const { idField, tempIdField } = state let data let params @@ -97,9 +96,9 @@ export default function makeServiceActions(service) { return service .create(data, params) - .then(response => { + .then(async response => { if (Array.isArray(response)) { - dispatch('addOrUpdateList', response) + await dispatch('addOrUpdateList', response) response = response.map(item => { const id = getId(item, idField) @@ -108,7 +107,7 @@ export default function makeServiceActions(service) { } else { const id = getId(response, idField) - dispatch('addOrUpdate', response) + await dispatch('addOrUpdate', response) response = state.keyedById[id] } @@ -123,7 +122,7 @@ export default function makeServiceActions(service) { }) }, - update({ commit, dispatch, state }, [id, data, params]) { + async update({ commit, dispatch, state }, [id, data, params]) { commit('setPending', 'update') @@ -131,8 +130,8 @@ export default function makeServiceActions(service) { return service .update(id, data, params) - .then(item => { - dispatch('addOrUpdate', item) + .then(async item => { + await dispatch('addOrUpdate', item) commit('unsetPending', 'update') return state.keyedById[id] }) @@ -143,7 +142,7 @@ export default function makeServiceActions(service) { }) }, - patch({ commit, dispatch, state }, [id, data, params]) { + async patch({ commit, dispatch, state }, [id, data, params]) { commit('setPending', 'patch') params = fastCopy(params) @@ -154,8 +153,8 @@ export default function makeServiceActions(service) { return service .patch(id, data, params) - .then(item => { - dispatch('addOrUpdate', item) + .then(async item => { + await dispatch('addOrUpdate', item) commit('unsetPending', 'patch') return state.keyedById[id] }) @@ -166,7 +165,7 @@ export default function makeServiceActions(service) { }) }, - remove({ commit }, idOrArray) { + async remove({ commit }, idOrArray) { let id let params @@ -206,11 +205,11 @@ export default function makeServiceActions(service) { * Feathers client. The client modifies the params object. * @param response */ - handleFindResponse({ state, commit, dispatch }, { params, response }) { + async handleFindResponse({ state, commit, dispatch }, { params, response }) { const { qid = 'default', query } = params const { idField } = state - dispatch('addOrUpdateList', response) + await dispatch('addOrUpdateList', response) commit('unsetPending', 'find') const mapItemFromState = item => { @@ -232,17 +231,22 @@ export default function makeServiceActions(service) { : (response = mappedFromState) } - dispatch('afterFind', response) + response = await await dispatch('afterFind', response) return response }, - handleFindError({ commit }, { params, error }) { + + async handleFindError({ commit }, { params, error }) { commit('setError', { method: 'find', params, error }) commit('unsetPending', 'find') return Promise.reject(error) }, - afterFind() {}, - addOrUpdateList({ state, commit }, response) { + + async afterFind({}, response) { + return response + }, + + async addOrUpdateList({ state, commit }, response) { const list = response.data || response const isPaginated = response.hasOwnProperty('total') const toAdd = [] @@ -282,8 +286,11 @@ export default function makeServiceActions(service) { commit('addItems', toAdd) commit('updateItems', toUpdate) + + return response }, - addOrUpdate({ state, commit }, item) { + + async addOrUpdate({ state, commit }, item) { const { idField } = state let id = getId(item, idField) let existingItem = state.keyedById[id] @@ -300,8 +307,12 @@ export default function makeServiceActions(service) { if (isIdOk) { existingItem ? commit('updateItem', item) : commit('addItem', item) } + return item } } + /** + * Only add a method to the store if the service actually has that same method. + */ Object.keys(serviceActions).map(method => { if (service[method] && typeof service[method] === 'function') { actions[method] = serviceActions[method] diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 64096d8e..e5dbb48d 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -59,7 +59,7 @@ export default function makeServiceMutations() { function updateItems(state, items) { const { idField, replaceItems, addOnUpsert, serverAlias, modelName } = state const Model = _get(models, `[${serverAlias}][${modelName}]`) - // const BaseModel = _get(models, `[${state.serverAlias}].BaseModel`) + const BaseModel = _get(models, `[${state.serverAlias}].BaseModel`) for (let item of items) { const id = getId(item, idField) @@ -71,18 +71,6 @@ export default function makeServiceMutations() { // Update the record if (id !== null && id !== undefined) { - - - - - // if (Model && !(item instanceof BaseModel) && !(item instanceof Model)) { - // item = new Model(item) - // } - - - - - if (state.ids.includes(id)) { // Completely replace the item if (replaceItems) { @@ -92,6 +80,16 @@ export default function makeServiceMutations() { Vue.set(state.keyedById, id, item) // Merge in changes } else { + /** + * If we have a Model class, calling new Model(incomingData) will call update + * the original record with the accessors and setupInstance data. + * This means that date objects and relationships will be preserved. + * + * If there's no Model class, just call updateOriginal on the incoming data. + */ + if (Model && !(item instanceof BaseModel) && !(item instanceof Model)) { + item = new Model(item) + } const original = state.keyedById[id] updateOriginal(original, item) } @@ -106,7 +104,17 @@ export default function makeServiceMutations() { } } + function mergeInstance(state, item) { + const { serverAlias, idField, tempIdField, modelName } = state + const id = getId(item, idField) + const existingItem = state.keyedById[id] + if (existingItem) { + mergeWithAccessors(existingItem, item) + } + } + return { + mergeInstance, addItem(state, item) { addItems(state, [item]) }, diff --git a/test/service-module/service-module.actions.test.ts b/test/service-module/service-module.actions.test.ts index fa83a474..1a8e313d 100644 --- a/test/service-module/service-module.actions.test.ts +++ b/test/service-module/service-module.actions.test.ts @@ -552,7 +552,7 @@ describe('Service Module - Actions', () => { }) describe('Get', function () { - it('updates store list state on service success', done => { + it('updates store list state on service success', async () => { const { makeServicePlugin, Todo } = makeContext() const store = new Vuex.Store({ plugins: [ @@ -571,68 +571,47 @@ describe('Service Module - Actions', () => { assert(todoState.isGetPending === false) assert(todoState.idField === 'id') - actions.get.call({ $store: store }, 0).then(() => { - assert(todoState.ids.length === 1, 'only one item is in the store') - assert(todoState.errorOnGet === null, 'there was no errorOnGet') - assert(todoState.isGetPending === false, 'isGetPending is set to false') - - let expectedKeyedById: NumberedList = { - 0: { id: 0, description: 'Do the first' } - } - assert.deepEqual( - JSON.parse(JSON.stringify(todoState.keyedById)), - expectedKeyedById - ) - - // Make a request with the array syntax that allows passing params - actions.get.call({ $store: store }, [1, {}]).then(response2 => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the first' }, - 1: { id: 1, description: 'Do the second' } - } - assert(response2.description === 'Do the second') - assert.deepEqual( - JSON.parse(JSON.stringify(todoState.keyedById)), - expectedKeyedById - ) + const todo1 = await actions.get.call({ $store: store }, 0) + assert(todoState.ids.length === 1, 'only one item is in the store') + assert(todoState.errorOnGet === null, 'there was no errorOnGet') + assert(todoState.isGetPending === false, 'isGetPending is set to false') - // Make a request to an existing record and return the existing data first, then update `keyedById` - todoState.keyedById = { - 0: { id: 0, description: 'Do the FIRST' }, // twist the data to see difference - 1: { id: 1, description: 'Do the second' } - } - actions.get.call({ $store: store }, [0, {}]).then(response3 => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the FIRST' }, - 1: { id: 1, description: 'Do the second' } - } - assert(response3.description === 'Do the FIRST') - assert.deepEqual( - JSON.parse(JSON.stringify(todoState.keyedById)), - expectedKeyedById - ) + let expectedKeyedById: NumberedList = { + 0: { id: 0, description: 'Do the first' } + } + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) - // Wait for the remote data to arriive - setTimeout(() => { - expectedKeyedById = { - 0: { id: 0, description: 'Do the first' }, - 1: { id: 1, description: 'Do the second' } - } - assert.deepEqual( - JSON.parse(JSON.stringify(todoState.keyedById)), - expectedKeyedById - ) - done() - }, 100) - }) - }) - }) + // Make a request with the array syntax that allows passing params + const response2 = await actions.get.call({ $store: store }, [1, {}]) + expectedKeyedById = { + 0: { id: 0, description: 'Do the first' }, + 1: { id: 1, description: 'Do the second' } + } + assert(response2.description === 'Do the second') + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById + ) - // Make sure proper state changes occurred before response - assert(todoState.ids.length === 0) - assert(todoState.errorOnCreate === null) - assert(todoState.isGetPending === true) - assert.deepEqual(todoState.keyedById, {}) + // Edit the first record in the store so the data is different. + // Make a request for the first record again, and it should be updated. + const clone1 = todo1.clone() + clone1.description = 'MODIFIED IN THE VUEX STORE' + clone1.commit() + + assert.strictEqual(todoState.keyedById[0].description, clone1.description, 'the store instance was updated') + + const response3 = await actions.get.call({ $store: store }, [0, {}]) + const todo0 = Todo.getFromStore(0) + assert(response3.description === 'Do the first') + assert.deepEqual( + JSON.parse(JSON.stringify(todoState.keyedById)), + expectedKeyedById, + 'The data is back as it was on the API server' + ) }) it('does not make remote call when skipRequestIfExists=true', done => { From e7173fb773ae295b7a91f4db685f7a2d50a221ab Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 21 Jul 2019 00:36:11 -0700 Subject: [PATCH 327/404] Assure that dates on instances remain as dates This makes sure that setupInstance is called after create and patch or update --- package.json | 1 + test/service-module/model-methods.test.ts | 20 ++++++++++++++++++++ yarn.lock | 5 +++++ 3 files changed, 26 insertions(+) diff --git a/package.json b/package.json index 843609f4..5f517224 100644 --- a/package.json +++ b/package.json @@ -145,6 +145,7 @@ "body-parser": "^1.18.3", "can-fixture-socket": "^2.0.0", "chai": "^4.2.0", + "date-fns": "^2.0.0-beta.2", "deep-object-diff": "^1.1.0", "eslint": "^5.16.0", "eslint-config-prettier": "^4.1.0", diff --git a/test/service-module/model-methods.test.ts b/test/service-module/model-methods.test.ts index 9540a9d6..3ef3a3b2 100644 --- a/test/service-module/model-methods.test.ts +++ b/test/service-module/model-methods.test.ts @@ -11,6 +11,7 @@ import Vuex from 'vuex' import { clearModels } from '../../src/service-module/global-models' import memory from 'feathers-memory' import { makeStore } from '../test-utils' +import { isDate } from 'date-fns' require('events').EventEmitter.prototype._maxListeners = 100 @@ -86,6 +87,12 @@ function makeContext() { from: '' } } + public static setupInstance(data, { models }) { + if (typeof data.createdAt === 'string') { + data.createdAt = new Date(data.createdAt) // just assuming the date is formatted correctly ;) + } + return data + } public get status() { return 'pending' } @@ -247,6 +254,19 @@ describe('Models - Methods', function () { assert.equal(typeof letter2.save, 'function', 'new instance has a save method') }) + it('Dates remain as dates after changes', async function () { + const { Letter, store, lettersService } = makeContext() + let letter = new Letter({ name: 'Garmadon', age: 1025, createdAt: new Date().toString() }) + + assert(isDate(letter.createdAt), 'createdAt should be a date') + + letter = await letter.save() + assert(isDate(letter.createdAt), 'createdAt should be a date') + + letter = await letter.save() + assert(isDate(letter.createdAt), 'createdAt should be a date') + }) + it('instance.toJSON', function () { const { Task } = makeContext() const task = new Task({ id: 1, test: true }) diff --git a/yarn.lock b/yarn.lock index fe02b654..0d1a4028 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3781,6 +3781,11 @@ data-urls@^1.1.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" +date-fns@^2.0.0-beta.2: + version "2.0.0-beta.2" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.0.0-beta.2.tgz#ccd556df832ef761baa88c600f53d2e829245999" + integrity sha512-4cicZF707RNerr3/Q3CcdLo+3OHMCfrRXE7h5iFgn7AMvX07sqKLxSf8Yp+WJW5bvKr2cy9/PkctXLv4iFtOaA== + date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" From 8702c8ebfcbf96a2079c58c25cd8a42c14bf5036 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 21 Jul 2019 00:36:48 -0700 Subject: [PATCH 328/404] 2.0.0-pre.65 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index ee363054..2859f454 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.64", + "version": "2.0.0-pre.65", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5f517224..5eea8a89 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.64", + "version": "2.0.0-pre.65", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 25cd05479d74d2c19bec484490a6aea388445f49 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 21 Jul 2019 14:50:56 -0700 Subject: [PATCH 329/404] Test that getters are sorting properly with decmal values Fixes https://github.com/feathers-plus/feathers-vuex/issues/160 --- test/service-module/module.getters.test.ts | 74 +++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/test/service-module/module.getters.test.ts b/test/service-module/module.getters.test.ts index b8bdb382..85d0961b 100644 --- a/test/service-module/module.getters.test.ts +++ b/test/service-module/module.getters.test.ts @@ -26,22 +26,34 @@ describe('Service Module - Getters', function() { beforeEach(function() { const state = makeServiceState('getter-todos', options) this.items = [ - { _id: 1, otherField: true, test: true }, + { + _id: 1, + otherField: true, + age: 21, + teethRemaining: 2.501, + test: true + }, { _id: 2, name: 'Marshall', otherField: true, + age: 24, + teethRemaining: 2.5, test: true, movies: [{ actors: ['Jerry the Mouse'] }] }, { _id: 3, otherField: true, + age: 27, + teethRemaining: 12, test: false, movies: [{ actors: ['Tom Hanks', 'Tom Cruise', 'Tomcat'] }] }, { name: 'Mariah', + age: 19, + teethRemaining: 24, status: 'temp' } ] @@ -288,4 +300,64 @@ describe('Service Module - Getters', function() { assert(results.skip === 0, 'skip was correct') assert(results.total === 3, 'total was correct') }) + + it('find with sort ascending on integers', function () { + const { state } = this + const params = { + query: { + $sort: { age: 1 } + } + } + const results = find(state)(params) + + results.data.map(i => i.age).reduce((oldest, current) => { + assert(current > oldest, 'age should have been older than previous') + return current + }, 0) + }) + + it('find with sort descending on integers', function () { + const { state } = this + const params = { + query: { + $sort: { age: -1 } + } + } + const results = find(state)(params) + + results.data.map(i => i.age).reduce((oldest, current) => { + assert(current < oldest, 'age should have been younger than previous') + return current + }, 100) + }) + + it('find with sort ascending on floats', function () { + const { state } = this + const params = { + query: { + $sort: { teethRemaining: 1 } + } + } + const results = find(state)(params) + + results.data.map(i => i.teethRemaining).reduce((oldest, current) => { + assert(current > oldest, 'teethRemaining should have been older than previous') + return current + }, 0) + }) + + it('find with sort descending on floats', function () { + const { state } = this + const params = { + query: { + $sort: { teethRemaining: -1 } + } + } + const results = find(state)(params) + + results.data.map(i => i.teethRemaining).reduce((oldest, current) => { + assert(current < oldest, 'teethRemaining should have been younger than previous') + return current + }, 100) + }) }) From cf5fdf422b034fd324399a196eaa419a1e1933ec Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 21 Jul 2019 15:14:35 -0700 Subject: [PATCH 330/404] Add a simple form binding example --- docs/common-patterns.md | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/docs/common-patterns.md b/docs/common-patterns.md index 13277aa8..f0adce44 100755 --- a/docs/common-patterns.md +++ b/docs/common-patterns.md @@ -465,6 +465,68 @@ export default new Vuex.Store({ }) ``` +## Form Binding + +Use the Model classes to reduce the boilerplate required to work with forms and Vuex, even in strict mode! Every model instance has a `.clone()` method which can be used to get a fully-reactive copy of the record in the store. Here is a very simple version of how you could bind to a form and submit new data to the server. + +```vue + + + + + +``` + ## Multiple Copies The previous version of `feathers-vuex` was hard-coded to allow for a single `current` record and one copy. It was pretty easy to hit that limit. This new release allows for keeping many more copies, one copy per stored record. To make it easier to comply with Vuex's `strict` mode, copies are not kept in the store by default, but are instead kept on `Model.copiesById`. You can make changes to the copies without having to make custom mutations, then you can commit them back into the store: From 2bf57866fb82416120814e22e55a0064f5ef112b Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 23 Jul 2019 21:35:31 -0700 Subject: [PATCH 331/404] makeFindMixin, set variables for requested and loaded --- src/make-find-mixin.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index b7a9566c..68135470 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -156,6 +156,7 @@ export default function makeFindMixin(options) { } }, [FIND_ACTION](params) { + const serviceName = this[SERVICE_NAME] const paramsToUse = getParams({ providedParams: params, params: this[PARAMS], @@ -168,17 +169,19 @@ export default function makeFindMixin(options) { : this[QUERY_WHEN] if (shouldExecuteQuery) { - this[IS_FIND_PENDING] = true - if (paramsToUse) { + // Set the qid. paramsToUse.query = paramsToUse.query || {} paramsToUse.qid = paramsToUse.qid || this[QID] this[QID] = paramsToUse.qid - const serviceName = this[SERVICE_NAME] + this[IS_FIND_PENDING] = true + this[HAVE_ITEMS_BEEN_REQUESTED_ONCE] = true + return this.$store .dispatch(`${serviceName}/find`, paramsToUse) .then(response => { + this[HAVE_ITEMS_LOADED_ONCE] = true const queryInfo = getQueryInfo(paramsToUse, response) // @ts-ignore queryInfo.response = response From 78a2dfb6d92ccd534ed7258276d4d7a699528ca5 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 23 Jul 2019 21:35:39 -0700 Subject: [PATCH 332/404] 2.0.0-pre.66 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2859f454..2a72a2fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.65", + "version": "2.0.0-pre.66", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5eea8a89..c18bcc92 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.65", + "version": "2.0.0-pre.66", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From ef682f765e5b6452be7e3561bd8cd8081b1da333 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 26 Jul 2019 09:16:44 -0700 Subject: [PATCH 333/404] Fix watcher for makeGetMixin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The watcher in the makeGetMixin was calling the GET_ACTION with the params, which was effectively setting the params as the id for the query. Naturally, some really weird errors were showing up on the API server. This makes sure the watcher doesn’t call the GET_ACTION with any params, allowing the GET_ACTION to perform its param-choosing logic. --- src/make-get-mixin.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/make-get-mixin.ts b/src/make-get-mixin.ts index ec88f021..7b7cf6e2 100644 --- a/src/make-get-mixin.ts +++ b/src/make-get-mixin.ts @@ -136,7 +136,9 @@ export default function makeFindMixin(options) { prop.replace(PARAMS, FETCH_PARAMS) } } - this.$watch(prop, this[GET_ACTION]) + this.$watch(prop, function () { + return this[GET_ACTION]() + }) }) return this[GET_ACTION]() From cf9f50622f3e70a9bac26ec00e65410863574367 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 26 Jul 2019 09:16:54 -0700 Subject: [PATCH 334/404] 2.0.0-pre.67 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2a72a2fa..24dec103 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.66", + "version": "2.0.0-pre.67", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index c18bcc92..7fd13732 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.66", + "version": "2.0.0-pre.67", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From e0770645c65b46e489c0f3c05b0453ab36ae6b65 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 27 Jul 2019 13:56:11 -0700 Subject: [PATCH 335/404] fix: Remove unused utility function --- src/utils.ts | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 1a0ffe37..e2c03135 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -463,24 +463,6 @@ export function mergeWithAccessors( return dest } -export function cloneWithAccessors(obj) { - const clone = {} - - const props = Object.getOwnPropertyNames(obj) - props.forEach(key => { - const desc = Object.getOwnPropertyDescriptor(obj, key) - - // Do not allow sharing of deeply-nested objects between instances - if (_isPlainObject(desc.value)) { - desc.value = fastCopy(desc.value) - } - - Object.defineProperty(clone, key, desc) - }) - - return clone -} - export function checkNamespace(namespace, item, debug) { if (!namespace && debug) { // eslint-disable-next-line no-console From 73bd282b4e2c715ba914850a7eb0e2d3e62fb49f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 27 Jul 2019 17:31:15 -0700 Subject: [PATCH 336/404] docs: Document removal of isFeathersVuexInstance --- src/service-module/notes.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 579716a3..7e72cc0d 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -360,6 +360,18 @@ created () { } ``` +## No more `instance.isFeathersVuexInstance` property + +The `isFeathersVuexInstance` property has been removed from all instances and clones. This could be a breaking change in your project if you were specfically depending on the property to check for instances. You can check if an object is an instance using `instanceof`: + +```js +// Assuming you've already registered a few plugins with Model classes. +import { models } from 'feathers-vuex' +const todo = new models.myApi.Todo({ description: 'test' }) + +assert(todo instanceof models.myApi.Todo) // <--- true +``` + ## Better default `idField` support Since records are keyed by id, `feathers-vuex` needs to know what the `idField` is for each service. In the last version, the default was `id`, and you had to specify something different. This version supports `id` and `_id` with zero configuration. You only need to set `idField` when you're using something other than `id` or `_id`. From 7fbe3947cc9fd315b6ce11b6ef32978577bd2d32 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 27 Jul 2019 17:39:41 -0700 Subject: [PATCH 337/404] fix: assure only one clone ever exists in memory Clones are now handled in the same way that instances are. If you call clone twice on the same object, the return value is always the same clone. This assures that only one clone ever exists in memory, creating a very consistent API. (Of course, more clones can always be stored anywhere in an app by manual use of a cloning utility like fast-copy) --- src/service-module/make-model.ts | 23 ++++++++++++++++++- .../service-module.mutations.ts | 5 ++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 1a389ec4..c4b7a540 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -46,6 +46,7 @@ export default function makeModel(options: FeathersVuexOptions) { // Think of these as abstract static properties public static servicePath: string public static namespace: string + public static keepCopiesInStore = options.keepCopiesInStore // eslint-disable-next-line public static instanceDefaults(data, { models, store }) { return data @@ -79,20 +80,30 @@ export default function makeModel(options: FeathersVuexOptions) { public constructor(data, options: BaseModelInstanceOptions) { // You have to pass at least an empty object to get a tempId. const originalData = data + data = data || {} options = Object.assign({}, defaultOptions, options) + const { store, + keepCopiesInStore, + copiesById: copiesByIdOnModel, models, instanceDefaults, idField, + tempIdField, setupInstance, getFromStore, + namespace, _commit } = this.constructor as typeof BaseModel const id = getId(data, idField) const hasValidId = id !== null && id !== undefined + const tempId = data && data.hasOwnProperty(tempIdField) && data[tempIdField] + const hasValidTempId = tempId !== null && tempId !== undefined + const copiesById = keepCopiesInStore + ? store.state[namespace].copiesById + : copiesByIdOnModel - data = data || {} const existingItem = hasValidId && !options.clone ? getFromStore.call(this.constructor, id) @@ -105,6 +116,16 @@ export default function makeModel(options: FeathersVuexOptions) { return existingItem } + // If cloning and a clone already exists, update and return the original clone. Only one clone is allowed. + const existingClone = (hasValidId || hasValidTempId) && options.clone + ? copiesById[id] || copiesById[tempId] + : null + if (existingClone) { + // This must be done in a mutation to avoid Vuex errors. + _commit.call(this.constructor, 'merge', { dest: existingClone, source: data }) + return existingClone + } + // Mark as a clone if (options.clone) { Object.defineProperty(this, '__isClone', { diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index e5dbb48d..e2dcf876 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -113,8 +113,13 @@ export default function makeServiceMutations() { } } + function merge(state, { dest, source }) { + mergeWithAccessors(dest, source) + } + return { mergeInstance, + merge, addItem(state, item) { addItems(state, [item]) }, From e3dfb395a769736e516404d453cf4b604eabb79f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 27 Jul 2019 17:42:10 -0700 Subject: [PATCH 338/404] fix: Do not attempt to overwrite non-writable props --- src/utils.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/utils.ts b/src/utils.ts index e2c03135..284bdbfc 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -412,7 +412,10 @@ export function mergeWithAccessors( // if (!sourceDesc.enumerable) { // return // } - if (blacklist.includes(key)) { + + // If the destination is not writable, return. Also ignore blacklisted keys. + // Must explicitly check if writable is false + if (destDesc && destDesc.writable === false || blacklist.includes(key)) { return } From 5d3bf3c1e1072d386dbaac1e4715a959bbf5ff02 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 27 Jul 2019 17:44:45 -0700 Subject: [PATCH 339/404] fix: Fix memory leak fast-copying nested instance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ok, it’s not a real memory leak, but we don’t want extra instances in memory. This makes sure that fastCopy is never used on the first level of a model instance. (It works fine on nested model instances, because it always calls new prop.constructor on nested objects) It includes lots of tests for cloning and commiting. --- src/utils.ts | 8 ++- .../model-relationships.test.ts | 70 +++++++++++++++++++ test/service-module/service-module.test.ts | 42 ++++++++++- 3 files changed, 117 insertions(+), 3 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 284bdbfc..6371669e 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -419,10 +419,14 @@ export function mergeWithAccessors( return } - // If we're dealing with a Vue Observable, just assign the values. + // Handle Vue observable objects if (destIsVueObservable || sourceIsVueObservable) { - if (_isObject(source[key])) { + const isObject = _isObject(source[key]) + const isFeathersVuexInstance = isObject && !!(source[key].constructor.modelName || source[key].constructor.namespace) + // Do not use fastCopy directly on a feathers-vuex BaseModel instance to keep from breaking reactivity. + if (isObject && !isFeathersVuexInstance) { try { + const sourceObject = source[key] dest[key] = fastCopy(source[key]) } catch (err) { if(!err.message.includes('getter')) { diff --git a/test/service-module/model-relationships.test.ts b/test/service-module/model-relationships.test.ts index 73497121..70fa44fc 100644 --- a/test/service-module/model-relationships.test.ts +++ b/test/service-module/model-relationships.test.ts @@ -152,6 +152,9 @@ function makeContext() { super(data, options) } } + /** + * This Model demonstrates how to use a dynamic set of instanceDefaults based on incoming data. + */ class Todo extends BaseModel { public static modelName = 'Todo' public static instanceDefaults(data) { @@ -529,4 +532,71 @@ describe('Models - Relationships', function () { assert.equal(todo.task.isComplete, false, 'preserved after clone') }) + + it('returns the same object when an instance is cloned twice', function () { + const { Todo } = makeContext() + + const todo = new Todo({ + task: { + id: 1, + description: 'test', + isComplete: true + } + }) + + const clone1 = todo.clone() + const clone2 = todo.clone() + + assert(clone1 === clone2, 'there should only ever be one clone in memory for an instance with the same id') + }) + + it('on clone, nested instances do not get cloned', function () { + const { Todo } = makeContext() + + const todo = new Todo({ + task: { + id: 1, + description: 'test', + isComplete: true + } + }) + + const todoClone = todo.clone() + + assert(todoClone.task.__isClone === undefined, 'todo.task should still be the original item and not the clone') + }) + + it('on nested commit in instance, original nested instances get updated', function () { + const { Todo } = makeContext() + + const todo = new Todo({ + task: { + id: 1, + description: 'test', + isComplete: true + } + }) + + const taskClone = todo.task.clone() + + taskClone.description = 'changed' + taskClone.commit() + + assert(todo.task.description === 'changed', 'the nested task should have been updated') + }) + + it('nested instances get updated in clones and original records', function () { + const { Todo } = makeContext() + + const todo = new Todo({ + task: { + id: 1, + description: 'test', + isComplete: true + } + }) + const todoClone = todo.clone() + + assert(todo.task === todoClone.task, 'the same task instance should be in both the original and clone') + }) }) diff --git a/test/service-module/service-module.test.ts b/test/service-module/service-module.test.ts index 778b9b1a..deef3703 100644 --- a/test/service-module/service-module.test.ts +++ b/test/service-module/service-module.test.ts @@ -49,6 +49,11 @@ function makeContext() { public constructor(data, options?) { super(data, options) } + public static instanceDefaults(data) { + return { + description: '' + } + } } class HotspotMedia extends BaseModel { public static modelName = 'HotspotMedia' @@ -304,7 +309,42 @@ describe('Service Module', function () { ) }) - it(`no longer changes original if you don't use the return value of commit()`, function () { + it(`the object returned from clone is not the same as the original`, function () { + const { serviceTodo, owners } = this + const serviceTodoClone = serviceTodo.clone() + + assert(serviceTodo !== serviceTodoClone, 'the objects are distinct') + }) + + it(`the object returned from commit is not the same as the clone`, function () { + const { serviceTodo, owners } = this + const serviceTodoClone = serviceTodo.clone() + const committedTodo = serviceTodoClone.commit() + + assert(committedTodo !== serviceTodoClone, 'the objects are distinct') + }) + + it(`the object returned from commit is the same as the original`, function () { + const { serviceTodo, owners } = this + const serviceTodoClone = serviceTodo.clone() + const committedTodo = serviceTodoClone.commit() + + assert(serviceTodo === committedTodo, 'the objects are the same') + }) + + it(`nested arrays are distinct after clone`, function () { + const { ServiceTodo } = this + + const todo = new ServiceTodo({ + description: 'test', + owners: ['Marshall', 'Mariah'] + }) + const clone = todo.clone() + + assert(todo.owners !== clone.owners, 'the arrays are not the same in memory') + }) + + it.skip(`modifying a clone after calling commit() does not change the original `, function () { const { serviceTodo, owners } = this const serviceTodoClone = serviceTodo.clone() From d6f1fb67efab53e535a08c4c8d8e71abbc4ed7af Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 27 Jul 2019 18:22:51 -0700 Subject: [PATCH 340/404] 2.0.0-pre.68 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 24dec103..38a92d81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.67", + "version": "2.0.0-pre.68", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 7fd13732..1e709a39 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.67", + "version": "2.0.0-pre.68", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 0b9a7ed49ef0e7cd5f9fcd5a30c1fa167bd5993e Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 2 Aug 2019 07:24:42 -0600 Subject: [PATCH 341/404] feat: Add error state to the make-find-mixin --- src/make-find-mixin.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index 68135470..0d278855 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -57,6 +57,7 @@ export default function makeFindMixin(options) { const FETCH_PARAMS = `${prefix}FetchParams` const WATCH = `${prefix}Watch` const QUERY_WHEN = `${prefix}QueryWhen` + const ERROR = `${prefix}Error` const FIND_ACTION = `find${capitalized}` const FIND_GETTER = `find${capitalized}InStore` const HAVE_ITEMS_BEEN_REQUESTED_ONCE = `have${capitalized}BeenRequestedOnce` @@ -71,7 +72,8 @@ export default function makeFindMixin(options) { [HAVE_ITEMS_LOADED_ONCE]: false, [WATCH]: watch, [QID]: qid, - [MOST_RECENT_QUERY]: null + [MOST_RECENT_QUERY]: null, + [ERROR]: null } // Should only be used with actual fetching API calls. const getParams = ({ providedParams, params, fetchParams }) => { @@ -181,6 +183,9 @@ export default function makeFindMixin(options) { return this.$store .dispatch(`${serviceName}/find`, paramsToUse) .then(response => { + // To prevent thrashing, only clear ERROR on response, not on initial request. + this[ERROR] = null + this[HAVE_ITEMS_LOADED_ONCE] = true const queryInfo = getQueryInfo(paramsToUse, response) // @ts-ignore @@ -192,6 +197,10 @@ export default function makeFindMixin(options) { this[IS_FIND_PENDING] = false return response }) + .catch(error => { + this[ERROR] = error + return error + }) } } else { if (this[MOST_RECENT_QUERY]) { From ebccc6b7da80d9cd50dddb3961d4b2878a91c8f7 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 2 Aug 2019 07:26:16 -0600 Subject: [PATCH 342/404] feat: add error state to make-get-mixin --- src/make-get-mixin.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/make-get-mixin.ts b/src/make-get-mixin.ts index 7b7cf6e2..b64abfe8 100644 --- a/src/make-get-mixin.ts +++ b/src/make-get-mixin.ts @@ -52,6 +52,7 @@ export default function makeFindMixin(options) { const FETCH_PARAMS = `${prefix}FetchParams` const WATCH = `${prefix}Watch` const QUERY_WHEN = `${prefix}QueryWhen` + const ERROR = `${prefix}Error` const GET_ACTION = `get${capitalized}` const GET_GETTER = `get${capitalized}FromStore` const LOCAL = `${prefix}Local` @@ -60,7 +61,8 @@ export default function makeFindMixin(options) { const data = { [IS_GET_PENDING]: false, [WATCH]: watch, - [QID]: qid + [QID]: qid, + [ERROR]: null } const mixin = { @@ -97,9 +99,16 @@ export default function makeFindMixin(options) { return this.$store .dispatch(`${this[SERVICE_NAME]}/get`, [idToUse, paramsToUse]) .then(response => { + // To prevent thrashing, only clear ERROR on response, not on initial request. + this[ERROR] = null + this[IS_GET_PENDING] = false return response }) + .catch(error => { + this[ERROR] = error + return error + }) } } } From bc4d8883ea6caa4d77459dbfb346b77d871d24ac Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 2 Aug 2019 07:26:28 -0600 Subject: [PATCH 343/404] 2.0.0-pre.69 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 38a92d81..cbe63c2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.68", + "version": "2.0.0-pre.69", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 1e709a39..f716e8c4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.68", + "version": "2.0.0-pre.69", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From b2a0b11a1992d2cd47d46096226de33882ed8e4a Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 2 Aug 2019 13:48:52 -0600 Subject: [PATCH 344/404] chore: Add some skipped tests to fill out later --- test/service-module/model-methods.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/service-module/model-methods.test.ts b/test/service-module/model-methods.test.ts index 3ef3a3b2..3463f7e1 100644 --- a/test/service-module/model-methods.test.ts +++ b/test/service-module/model-methods.test.ts @@ -239,6 +239,10 @@ describe('Models - Methods', function () { assert(!store.state.tasks.tempsById[tempId], 'temp was removed') }) + it.skip('instance.remove removes cloned records from the store', function () {}) + it.skip('instance.remove removes cloned records from the Model.copiesById', function () {}) + it.skip('removes clone and original upon calling clone.remove()', function () {}) + it('instance methods still available in store data after updateItem mutation (or socket event)', async function () { const { Letter, store, lettersService } = makeContext() let letter = new Letter({ name: 'Garmadon', age: 1025 }) From 5682edc5ac7a0a359b9757709fd4582bdcde8a1e Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 5 Aug 2019 22:55:18 -0600 Subject: [PATCH 345/404] fix travis tests this is according to https://benlimmer.com/2019/01/14/travis-ci-xvfb/ --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5d49cc13..f37f6727 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,8 @@ addons: code_climate: repo_token: 'your repo token' firefox: "51.0" -before_install: - - "export DISPLAY=:99.0" - - "sh -e /etc/init.d/xvfb start" +services: + - xvfb notifications: email: false before_script: From 0ec4b8e989ab7579aac4b8c3d8af86bb20abac80 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 5 Aug 2019 23:09:34 -0600 Subject: [PATCH 346/404] Remove codeclimate test reporter --- .travis.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index f37f6727..d810af15 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,9 +8,4 @@ addons: services: - xvfb notifications: - email: false -before_script: - - npm install codeclimate-test-reporter - - alias codeclimate="./node_modules/codeclimate-test-reporter/bin/codeclimate.js" -after_script: - - codeclimate-test-reporter < coverage/lcov.info + email: false \ No newline at end of file From 9327b7e70f4dbe145aaba7459f5dd1f917fc30fd Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 8 Aug 2019 15:00:17 -0600 Subject: [PATCH 347/404] fix: makeGetMixin can now check data for the id --- src/make-get-mixin.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/make-get-mixin.ts b/src/make-get-mixin.ts index b64abfe8..abd387f6 100644 --- a/src/make-get-mixin.ts +++ b/src/make-get-mixin.ts @@ -126,6 +126,7 @@ export default function makeFindMixin(options) { const pType = Object.getPrototypeOf(this) if ( + this.hasOwnProperty(ID) || pType.hasOwnProperty(ID) || pType.hasOwnProperty(PARAMS) || pType.hasOwnProperty(FETCH_PARAMS) From a5cabade8e0cb6c4181bd3bbc598d9877f23c493 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 8 Aug 2019 15:00:30 -0600 Subject: [PATCH 348/404] 2.0.0-pre.70 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index cbe63c2e..870b54e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.69", + "version": "2.0.0-pre.70", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f716e8c4..cce904a6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.69", + "version": "2.0.0-pre.70", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 3d5ad284c4f63667ef9bf5bdc88985d4cfa440fe Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 14 Aug 2019 22:20:53 -0600 Subject: [PATCH 349/404] feat: set pending state before debounced requests In the `makeFindMixin`, if the request is going to be debounced, the `isFindPending` attribute is now set before the debounce timeout. This assures that a loading indicator can be shown during the debounce timeout. It makes pagination operate much more smoothly. --- src/make-find-mixin.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index 0d278855..1848ef47 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -241,6 +241,16 @@ export default function makeFindMixin(options) { } } this.$watch(prop, function() { + // If the request is going to be debounced, set IS_FIND_PENDING to true. + // Without this, there's not a way to show a loading indicator during the debounce timeout. + const paramsToUse = getParams({ + providedParams: null, + params: this[PARAMS], + fetchParams: this[FETCH_PARAMS] + }) + if (paramsToUse.debounce) { + this[IS_FIND_PENDING] = true + } return this[`${FIND_ACTION}DebouncedProxy`]() }) }) From 4862ac5fd86faadc05d997c986744526f4ba35c1 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Wed, 14 Aug 2019 22:21:05 -0600 Subject: [PATCH 350/404] 2.0.0-pre.71 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 870b54e5..1ffd9574 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.70", + "version": "2.0.0-pre.71", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index cce904a6..525954f4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.70", + "version": "2.0.0-pre.71", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 1980d6ae8ad069ec10d51f35cf37d8b2fa1fa410 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 22 Aug 2019 11:08:48 -0600 Subject: [PATCH 351/404] Fix circular dependencies --- src/auth-module/auth-module.actions.ts | 2 +- src/utils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/auth-module/auth-module.actions.ts b/src/auth-module/auth-module.actions.ts index db9dfa32..d8dbb43e 100644 --- a/src/auth-module/auth-module.actions.ts +++ b/src/auth-module/auth-module.actions.ts @@ -3,7 +3,7 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import { models } from '../index' +import { globalModels as models } from '../service-module/global-models' export default function makeAuthActions(feathersClient) { return { diff --git a/src/utils.ts b/src/utils.ts index 6371669e..83e06ba5 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -15,7 +15,7 @@ import { get as _get } from 'lodash' import ObjectID from 'bson-objectid' -import { models } from './index' +import { globalModels as models } from './service-module/global-models' import stringify from 'fast-json-stable-stringify' export function stripSlashes(location: string) { From 08d548e30a994cbc88fd02f72d1bd2aa424011c0 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 22 Aug 2019 11:08:59 -0600 Subject: [PATCH 352/404] 2.0.0-pre.72 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1ffd9574..27641a69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.71", + "version": "2.0.0-pre.72", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 525954f4..05bf7195 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.71", + "version": "2.0.0-pre.72", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 4cc9f664686b8cd4ab1c5e5dbc9931ff1f71f15d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 22 Aug 2019 20:31:26 -0600 Subject: [PATCH 353/404] fix transpilation bug for async arrow function --- src/service-module/service-module.actions.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/service-module/service-module.actions.ts b/src/service-module/service-module.actions.ts index bd906a65..6dc2f131 100644 --- a/src/service-module/service-module.actions.ts +++ b/src/service-module/service-module.actions.ts @@ -49,7 +49,7 @@ export default function makeServiceActions(service) { commit('setPending', 'get') return service .get(id, params) - .then(async item => { + .then(async function(item) { await dispatch('addOrUpdate', item) commit('unsetPending', 'get') return state.keyedById[id] @@ -130,7 +130,7 @@ export default function makeServiceActions(service) { return service .update(id, data, params) - .then(async item => { + .then(async function(item) { await dispatch('addOrUpdate', item) commit('unsetPending', 'update') return state.keyedById[id] @@ -153,7 +153,7 @@ export default function makeServiceActions(service) { return service .patch(id, data, params) - .then(async item => { + .then(async function(item) { await dispatch('addOrUpdate', item) commit('unsetPending', 'patch') return state.keyedById[id] From aa8ddd7e524ef0761e64d0894461bcfa5ad12132 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 22 Aug 2019 20:31:40 -0600 Subject: [PATCH 354/404] 2.0.0-pre.73 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 27641a69..cec54530 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.72", + "version": "2.0.0-pre.73", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 05bf7195..5fc831c8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.72", + "version": "2.0.0-pre.73", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 08cd3933c3b0400b828b9474cb297df8208118ff Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 22 Aug 2019 21:41:57 -0600 Subject: [PATCH 355/404] fix: tree shaking by using specific lodash modules --- package.json | 2 +- src/make-find-mixin.ts | 3 ++- src/service-module/global-clients.ts | 2 +- src/service-module/make-model.ts | 3 ++- src/service-module/make-service-plugin.ts | 2 +- src/service-module/service-module.getters.ts | 4 ++-- src/service-module/service-module.mutations.ts | 4 +++- src/service-module/service-module.state.ts | 2 +- src/utils.ts | 12 +++++------- test/service-module/make-service-plugin.test.ts | 3 ++- test/service-module/model-serialize.test.ts | 2 +- yarn.lock | 5 +++++ 12 files changed, 26 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 5fc831c8..c5a9f7a5 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "fast-json-stable-stringify": "^2.0.0", "inflection": "^1.12.0", "jwt-decode": "^2.2.0", - "lodash": "^4.17.11", + "lodash": "^4.17.15", "lodash.isobject": "^3.0.2", "lodash.isplainobject": "^4.0.6", "lodash.merge": "^4.6.1", diff --git a/src/make-find-mixin.ts b/src/make-find-mixin.ts index 1848ef47..0c719829 100644 --- a/src/make-find-mixin.ts +++ b/src/make-find-mixin.ts @@ -10,7 +10,8 @@ import { getQueryInfo, getItemsFromQueryInfo } from './utils' -import { get as _get, debounce } from 'lodash' +import debounce from 'lodash/debounce' +import _get from 'lodash/get' export default function makeFindMixin(options) { const { diff --git a/src/service-module/global-clients.ts b/src/service-module/global-clients.ts index cf91b521..8e7977ba 100644 --- a/src/service-module/global-clients.ts +++ b/src/service-module/global-clients.ts @@ -3,7 +3,7 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import { get as _get } from 'lodash' +import _get from 'lodash/get' /** * A global object that holds references to all Model Classes in the application. diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index c4b7a540..3d275e23 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -6,7 +6,8 @@ eslint import { FeathersVuexOptions } from './types' import { globalModels, prepareAddModel } from './global-models' import { mergeWithAccessors, checkNamespace, getId } from '../utils' -import { get as _get, merge as _merge } from 'lodash' +import _merge from 'lodash/merge' +import _get from 'lodash/get' // A hack to prevent error with this.constructor.preferUpdate interface Function { diff --git a/src/service-module/make-service-plugin.ts b/src/service-module/make-service-plugin.ts index 8ca86490..801ba784 100644 --- a/src/service-module/make-service-plugin.ts +++ b/src/service-module/make-service-plugin.ts @@ -7,7 +7,7 @@ import { FeathersVuexOptions, MakeServicePluginOptions } from './types' import makeServiceModule from './make-service-module' import { globalModels, prepareAddModel } from './global-models' import { makeNamespace, getServicePath, assignIfNotPresent } from '../utils' -import { get as _get } from 'lodash' +import _get from 'lodash/get' const defaults = { namespace: '', // The namespace for the Vuex module. Will generally be derived from the service.path, service.name, when available. Otherwise, it must be provided here, explicitly. diff --git a/src/service-module/service-module.getters.ts b/src/service-module/service-module.getters.ts index 98d22d07..a03a206b 100644 --- a/src/service-module/service-module.getters.ts +++ b/src/service-module/service-module.getters.ts @@ -6,9 +6,9 @@ eslint import sift from 'sift' import commons from '@feathersjs/commons' import dbCommons from '@feathersjs/adapter-commons' -import { omit as _omit } from 'lodash' import { globalModels as models } from './global-models' -import { get as _get } from 'lodash' +import _get from 'lodash/get' +import _omit from 'lodash/omit' const { _ } = commons const { filterQuery, sorter, select } = dbCommons diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index e2dcf876..3f3d3375 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -13,7 +13,9 @@ import { getQueryInfo } from '../utils' import { globalModels as models } from './global-models' -import { get as _get, isObject as _isObject, omit as _omit } from 'lodash' +import _omit from 'lodash/omit' +import _get from 'lodash/get' +import _isObject from 'lodash/isObject' export default function makeServiceMutations() { function addItems(state, items) { diff --git a/src/service-module/service-module.state.ts b/src/service-module/service-module.state.ts index 6d0d0917..bacf967b 100644 --- a/src/service-module/service-module.state.ts +++ b/src/service-module/service-module.state.ts @@ -4,7 +4,7 @@ eslint @typescript-eslint/no-explicit-any: 0 */ -import { omit as _omit } from 'lodash' +import _omit from 'lodash/omit' export default function makeDefaultState(servicePath, options) { const nonStateProps = [ diff --git a/src/utils.ts b/src/utils.ts index 83e06ba5..317d5fbb 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -7,13 +7,11 @@ import decode from 'jwt-decode' import inflection from 'inflection' import Vue from 'vue' import fastCopy from 'fast-copy' -import { - isPlainObject as _isPlainObject, - isObject as _isObject, - trim as _trim, - omit as _omit, - get as _get -} from 'lodash' +import _isPlainObject from 'lodash/isPlainObject' +import _isObject from 'lodash/isObject' +import _trim from 'lodash/trim' +import _omit from 'lodash/omit' +import _get from 'lodash/get' import ObjectID from 'bson-objectid' import { globalModels as models } from './service-module/global-models' import stringify from 'fast-json-stable-stringify' diff --git a/test/service-module/make-service-plugin.test.ts b/test/service-module/make-service-plugin.test.ts index 019bca82..b23893ba 100644 --- a/test/service-module/make-service-plugin.test.ts +++ b/test/service-module/make-service-plugin.test.ts @@ -10,7 +10,8 @@ import { clearModels } from '../../src/service-module/global-models' import { clients } from '../../src/service-module/global-clients' import { feathersRestClient as feathers } from '../../test/fixtures/feathers-client' import feathersVuex from '../../src/index' -import { pick as _pick, omit as _omit } from 'lodash' +import _pick from 'lodash/pick' +import _omit from 'lodash/omit' Vue.use(Vuex) diff --git a/test/service-module/model-serialize.test.ts b/test/service-module/model-serialize.test.ts index 9dd1d6e5..f97ff16e 100644 --- a/test/service-module/model-serialize.test.ts +++ b/test/service-module/model-serialize.test.ts @@ -7,7 +7,7 @@ import { assert } from 'chai' import feathersVuex from '../../src/index' import { feathersRestClient as feathersClient } from '../fixtures/feathers-client' import { clearModels } from '../../src/service-module/global-models' -import { omit as _omit } from 'lodash' +import _omit from 'lodash/omit' describe('Models - Serialize', function () { beforeEach(() => { diff --git a/yarn.lock b/yarn.lock index 0d1a4028..3137763f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7020,6 +7020,11 @@ lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== +lodash@^4.17.15: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + loglevel@^1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.3.tgz#77f2eb64be55a404c9fd04ad16d57c1d6d6b1280" From 6072c136bb76b730ea92b5ca4b35a7efa4908954 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 22 Aug 2019 21:42:08 -0600 Subject: [PATCH 356/404] 2.0.0-pre.74 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index cec54530..c42793ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.73", + "version": "2.0.0-pre.74", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index c5a9f7a5..848599e1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.73", + "version": "2.0.0-pre.74", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From c1020258e7102edf35439b70428c1ed0e80b2d3b Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 29 Aug 2019 09:36:09 -0600 Subject: [PATCH 357/404] Fix import --- src/service-module/service-module.getters.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/service-module/service-module.getters.ts b/src/service-module/service-module.getters.ts index a03a206b..10fc9418 100644 --- a/src/service-module/service-module.getters.ts +++ b/src/service-module/service-module.getters.ts @@ -4,13 +4,12 @@ eslint @typescript-eslint/no-explicit-any: 0 */ import sift from 'sift' -import commons from '@feathersjs/commons' +import { _ } from '@feathersjs/commons' import dbCommons from '@feathersjs/adapter-commons' import { globalModels as models } from './global-models' import _get from 'lodash/get' import _omit from 'lodash/omit' -const { _ } = commons const { filterQuery, sorter, select } = dbCommons const FILTERS = ['$sort', '$limit', '$skip', '$select'] const OPERATORS = ['$in', '$nin', '$lt', '$lte', '$gt', '$gte', '$ne', '$or'] From 92e1e8531097aded5d87b669fcd1b860559aa686 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 29 Aug 2019 09:36:38 -0600 Subject: [PATCH 358/404] 2.0.0-pre.75 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index c42793ec..2d326e7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "feathers-vuex", - "version": "2.0.0-pre.74", + "version": "2.0.0-pre.75", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 848599e1..849ca0c5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.74", + "version": "2.0.0-pre.75", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From a0794c07763b833585f569a1f6b3e1ac950dcc8b Mon Sep 17 00:00:00 2001 From: fratzinger <22286818+fratzinger@users.noreply.github.com> Date: Thu, 5 Sep 2019 13:23:18 +0200 Subject: [PATCH 359/404] addItems mutation fix tempId If `tempId` was assigned before calling `addItems`-mutation -> `tempId` is undefined -> `newTempsById[undefined] = item` --- src/service-module/service-module.mutations.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 3f3d3375..3bd8c247 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -40,8 +40,9 @@ export default function makeServiceMutations() { } if (isTemp) { - if (!item[tempIdField]) { - var tempId = assignTempId(state, item) + let tempId = item[tempIdField]; + if (!tempId) { + tempId = assignTempId(state, item) } item.__isTemp = true newTempsById[tempId] = item From 039da0200dc5d76b216e436db0e12c696a6a3515 Mon Sep 17 00:00:00 2001 From: fratzinger <22286818+fratzinger@users.noreply.github.com> Date: Thu, 5 Sep 2019 19:28:10 +0200 Subject: [PATCH 360/404] fix addItems-mutation for tempId works with falsey tempId --- src/service-module/service-module.mutations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/service-module.mutations.ts b/src/service-module/service-module.mutations.ts index 3bd8c247..1b00bfd4 100644 --- a/src/service-module/service-module.mutations.ts +++ b/src/service-module/service-module.mutations.ts @@ -41,7 +41,7 @@ export default function makeServiceMutations() { if (isTemp) { let tempId = item[tempIdField]; - if (!tempId) { + if (tempId == null) { tempId = assignTempId(state, item) } item.__isTemp = true From 2cf5775e6f2697372e6030054a2586ff620e13d4 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 5 Sep 2019 11:57:02 -0600 Subject: [PATCH 361/404] remove package-lock.json --- package-lock.json | 24070 -------------------------------------------- 1 file changed, 24070 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 2d326e7b..00000000 --- a/package-lock.json +++ /dev/null @@ -1,24070 +0,0 @@ -{ - "name": "feathers-vuex", - "version": "2.0.0-pre.75", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@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/core": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.0.0-beta.47.tgz", - "integrity": "sha512-7EIuAX0UVnCgZ0E9tz9rFK0gd+aovwMA9bul+dnkmBQYLrJdas2EHMUSmaK67i1cyZpvgVvXhHtXJxC7wo3rlQ==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/generator": "7.0.0-beta.47", - "@babel/helpers": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/traverse": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "convert-source-map": "^1.1.0", - "debug": "^3.1.0", - "json5": "^0.5.0", - "lodash": "^4.17.5", - "micromatch": "^2.3.11", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.47.tgz", - "integrity": "sha512-W7IeG4MoVf4oUvWfHUx9VG9if3E0xSUDf1urrnNYtC2ow1dz2ptvQ6YsJfyVXDuPTFXz66jkHhzMW7a5Eld7TA==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.47" - } - }, - "@babel/generator": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.47.tgz", - "integrity": "sha512-fJP+9X+gqgTTZzTqrKJHwebPwt6S/e/4YuyRyKyWHAIirGgUwjRoZgbFci24wwGYMJW7nlkCSwWG7QvCVsG0eg==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47", - "jsesc": "^2.5.1", - "lodash": "^4.17.5", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-function-name": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.47.tgz", - "integrity": "sha512-0LSvt95XCYaOrDA5K68KkTyldKXizDwBnKACdYzQszp1GdbtzmSeGwFU5Ecw86fU6bkYXtDvkFTOQwk/WQSJPw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.47.tgz", - "integrity": "sha512-63j0i3YUW8CO//uQc3ACffJdIlYcIlysuHjMF0yzQhqKoQ/CUPv0hf3nBwdRGjiWrr3JcL6++NF4XmXdwSU+fA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.47.tgz", - "integrity": "sha512-jx8GmxryT6Qy4+24W6M6TnVL9T8bxqdyg5UKHjxBdw0Y2Sano1n0WphUS2seuOugn04W2ZQLqGc0ut8nGe/taA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.47.tgz", - "integrity": "sha512-d505K3Hth1eg0b2swfEF7oFMw3J9M8ceFg0s6dhCSxOOF+07WDvJ0HKT/YbK/Jk9wn8Wyr6HIRAUPKJ9Wfv8Rg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.47.tgz", - "integrity": "sha512-mAzrOCLwOb4jAobHi0kTwIkoamP1Do28c6zxvrDXjYSJFZHz6KGuzMaT0AV7ZCq7M3si7QypVVMVX2bE6IsuOg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/traverse": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.47.tgz", - "integrity": "sha512-kYGGs//OnUnei+9TTldxlgf7llprj7VUeDKtG50+g+0k1g0yZyrkEgbyFheYFdnudR8IDEHOEXVsUuY82r5Aiw==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/generator": "7.0.0-beta.47", - "@babel/helper-function-name": "7.0.0-beta.47", - "@babel/helper-split-export-declaration": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "debug": "^3.1.0", - "globals": "^11.1.0", - "invariant": "^2.2.0", - "lodash": "^4.17.5" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "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" - } - }, - "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "ms": { - "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 - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.2.tgz", - "integrity": "sha512-I4o675J/iS8k+P38dvJ3IBGqObLXyQLTxtrR4u9cSUJOURvafeEWb/pFMOTwtNrmq73mJzyF6ueTbO1BtN0Zeg==", - "dev": true, - "requires": { - "@babel/types": "^7.2.2", - "jsesc": "^2.5.1", - "lodash": "^4.17.10", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - }, - "dependencies": { - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - } - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0-beta.47.tgz", - "integrity": "sha512-Pjxb/PrxyKWc7jcAXlawvNAQMxxY+tSSNC5wxJstJjpO10mocmGzBOqNYjxdvVhMb3d0BEPQ8mR+D65fFpZ+TA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.0.0-beta.47.tgz", - "integrity": "sha512-nv8d6TcDBb1CJMQzwab/e0rqyqoP9d2AQBjr4GdSiVRpJX4aiLEiLBm2XprdEb/sVIRmmBnVxPXJaHDsS/K2fw==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-call-delegate": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.0.0-beta.47.tgz", - "integrity": "sha512-Rx9TRmCCEP0pWau9gfR6ubcbbX3nVc4ImNY143ftC70jrKdSv5rS20yz2cmCilDzhexwGZQ3PFwOLKe3C/5aEg==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "7.0.0-beta.47", - "@babel/traverse": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.47.tgz", - "integrity": "sha512-W7IeG4MoVf4oUvWfHUx9VG9if3E0xSUDf1urrnNYtC2ow1dz2ptvQ6YsJfyVXDuPTFXz66jkHhzMW7a5Eld7TA==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.47" - } - }, - "@babel/generator": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.47.tgz", - "integrity": "sha512-fJP+9X+gqgTTZzTqrKJHwebPwt6S/e/4YuyRyKyWHAIirGgUwjRoZgbFci24wwGYMJW7nlkCSwWG7QvCVsG0eg==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47", - "jsesc": "^2.5.1", - "lodash": "^4.17.5", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-function-name": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.47.tgz", - "integrity": "sha512-0LSvt95XCYaOrDA5K68KkTyldKXizDwBnKACdYzQszp1GdbtzmSeGwFU5Ecw86fU6bkYXtDvkFTOQwk/WQSJPw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.47.tgz", - "integrity": "sha512-63j0i3YUW8CO//uQc3ACffJdIlYcIlysuHjMF0yzQhqKoQ/CUPv0hf3nBwdRGjiWrr3JcL6++NF4XmXdwSU+fA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.47.tgz", - "integrity": "sha512-jx8GmxryT6Qy4+24W6M6TnVL9T8bxqdyg5UKHjxBdw0Y2Sano1n0WphUS2seuOugn04W2ZQLqGc0ut8nGe/taA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.47.tgz", - "integrity": "sha512-d505K3Hth1eg0b2swfEF7oFMw3J9M8ceFg0s6dhCSxOOF+07WDvJ0HKT/YbK/Jk9wn8Wyr6HIRAUPKJ9Wfv8Rg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.47.tgz", - "integrity": "sha512-mAzrOCLwOb4jAobHi0kTwIkoamP1Do28c6zxvrDXjYSJFZHz6KGuzMaT0AV7ZCq7M3si7QypVVMVX2bE6IsuOg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/traverse": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.47.tgz", - "integrity": "sha512-kYGGs//OnUnei+9TTldxlgf7llprj7VUeDKtG50+g+0k1g0yZyrkEgbyFheYFdnudR8IDEHOEXVsUuY82r5Aiw==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/generator": "7.0.0-beta.47", - "@babel/helper-function-name": "7.0.0-beta.47", - "@babel/helper-split-export-declaration": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "debug": "^3.1.0", - "globals": "^11.1.0", - "invariant": "^2.2.0", - "lodash": "^4.17.5" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "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" - } - }, - "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "ms": { - "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 - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-define-map": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.0.0-beta.47.tgz", - "integrity": "sha512-pLB9RY7GZKcc/frzgfDY/HwdqxWPe60qMAvNUef1V1bDZ8i4AUgxAANgltFzj61t100WGhqaS0xGkALD+9VA+g==", - "dev": true, - "requires": { - "@babel/helper-function-name": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "lodash": "^4.17.5" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.47.tgz", - "integrity": "sha512-W7IeG4MoVf4oUvWfHUx9VG9if3E0xSUDf1urrnNYtC2ow1dz2ptvQ6YsJfyVXDuPTFXz66jkHhzMW7a5Eld7TA==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.47" - } - }, - "@babel/helper-function-name": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.47.tgz", - "integrity": "sha512-0LSvt95XCYaOrDA5K68KkTyldKXizDwBnKACdYzQszp1GdbtzmSeGwFU5Ecw86fU6bkYXtDvkFTOQwk/WQSJPw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.47.tgz", - "integrity": "sha512-63j0i3YUW8CO//uQc3ACffJdIlYcIlysuHjMF0yzQhqKoQ/CUPv0hf3nBwdRGjiWrr3JcL6++NF4XmXdwSU+fA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.47.tgz", - "integrity": "sha512-d505K3Hth1eg0b2swfEF7oFMw3J9M8ceFg0s6dhCSxOOF+07WDvJ0HKT/YbK/Jk9wn8Wyr6HIRAUPKJ9Wfv8Rg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.47.tgz", - "integrity": "sha512-mAzrOCLwOb4jAobHi0kTwIkoamP1Do28c6zxvrDXjYSJFZHz6KGuzMaT0AV7ZCq7M3si7QypVVMVX2bE6IsuOg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.0.0-beta.47.tgz", - "integrity": "sha512-1mwk27zmhSuMUcVWxw5ZKiPYfuWXviZNqgA4OvFBloPf9R+dKDhNgP2uUrkHh68ltVVc3Bup1nsbd/2KM5AxEw==", - "dev": true, - "requires": { - "@babel/traverse": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.47.tgz", - "integrity": "sha512-W7IeG4MoVf4oUvWfHUx9VG9if3E0xSUDf1urrnNYtC2ow1dz2ptvQ6YsJfyVXDuPTFXz66jkHhzMW7a5Eld7TA==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.47" - } - }, - "@babel/generator": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.47.tgz", - "integrity": "sha512-fJP+9X+gqgTTZzTqrKJHwebPwt6S/e/4YuyRyKyWHAIirGgUwjRoZgbFci24wwGYMJW7nlkCSwWG7QvCVsG0eg==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47", - "jsesc": "^2.5.1", - "lodash": "^4.17.5", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-function-name": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.47.tgz", - "integrity": "sha512-0LSvt95XCYaOrDA5K68KkTyldKXizDwBnKACdYzQszp1GdbtzmSeGwFU5Ecw86fU6bkYXtDvkFTOQwk/WQSJPw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.47.tgz", - "integrity": "sha512-63j0i3YUW8CO//uQc3ACffJdIlYcIlysuHjMF0yzQhqKoQ/CUPv0hf3nBwdRGjiWrr3JcL6++NF4XmXdwSU+fA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.47.tgz", - "integrity": "sha512-jx8GmxryT6Qy4+24W6M6TnVL9T8bxqdyg5UKHjxBdw0Y2Sano1n0WphUS2seuOugn04W2ZQLqGc0ut8nGe/taA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.47.tgz", - "integrity": "sha512-d505K3Hth1eg0b2swfEF7oFMw3J9M8ceFg0s6dhCSxOOF+07WDvJ0HKT/YbK/Jk9wn8Wyr6HIRAUPKJ9Wfv8Rg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.47.tgz", - "integrity": "sha512-mAzrOCLwOb4jAobHi0kTwIkoamP1Do28c6zxvrDXjYSJFZHz6KGuzMaT0AV7ZCq7M3si7QypVVMVX2bE6IsuOg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/traverse": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.47.tgz", - "integrity": "sha512-kYGGs//OnUnei+9TTldxlgf7llprj7VUeDKtG50+g+0k1g0yZyrkEgbyFheYFdnudR8IDEHOEXVsUuY82r5Aiw==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/generator": "7.0.0-beta.47", - "@babel/helper-function-name": "7.0.0-beta.47", - "@babel/helper-split-export-declaration": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "debug": "^3.1.0", - "globals": "^11.1.0", - "invariant": "^2.2.0", - "lodash": "^4.17.5" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "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" - } - }, - "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "ms": { - "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 - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0-beta.47.tgz", - "integrity": "sha512-5BcKFhyzrsInlrfO/tGoe6khUuJzGfROD7oozF/5MWsKo/c3gVJfQ5y83lZ4XoTKJt/x4PQlLU0aHd/SJpYONA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0-beta.47.tgz", - "integrity": "sha512-gpipslnZw2hcVGADUtqQII9KF8FPpRZsVUXwKP/0EnWwtujRFSVL+u2Fh+VXODRAxFmTLo6eGcOr/Vfan0MqYw==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-module-imports": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.47.tgz", - "integrity": "sha512-Rk43Ty+a6npu9znK22IqFlseStRGWxEHi2cjmLbbi63VGiseofdUtIJI65F9MTCuMTXAX7VbY/ghef1Jp5qpvw==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47", - "lodash": "^4.17.5" - }, - "dependencies": { - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-module-transforms": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.0.0-beta.47.tgz", - "integrity": "sha512-CziMe30ZunAhe6j05oNOFOg7im1lcv3dYuMxrwBYVe9YdP4NHPU7a1wrDBUhaPmyqTIZDwGnFne7k1KP79SeGQ==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "7.0.0-beta.47", - "@babel/helper-simple-access": "7.0.0-beta.47", - "@babel/helper-split-export-declaration": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "lodash": "^4.17.5" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.47.tgz", - "integrity": "sha512-W7IeG4MoVf4oUvWfHUx9VG9if3E0xSUDf1urrnNYtC2ow1dz2ptvQ6YsJfyVXDuPTFXz66jkHhzMW7a5Eld7TA==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.47" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.47.tgz", - "integrity": "sha512-jx8GmxryT6Qy4+24W6M6TnVL9T8bxqdyg5UKHjxBdw0Y2Sano1n0WphUS2seuOugn04W2ZQLqGc0ut8nGe/taA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.47.tgz", - "integrity": "sha512-d505K3Hth1eg0b2swfEF7oFMw3J9M8ceFg0s6dhCSxOOF+07WDvJ0HKT/YbK/Jk9wn8Wyr6HIRAUPKJ9Wfv8Rg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.47.tgz", - "integrity": "sha512-mAzrOCLwOb4jAobHi0kTwIkoamP1Do28c6zxvrDXjYSJFZHz6KGuzMaT0AV7ZCq7M3si7QypVVMVX2bE6IsuOg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0-beta.47.tgz", - "integrity": "sha512-NhnGhjwrhzGas4A/PoBDEtEPCGJHrzhaT6qGmo1hmkA2orG4UNi7KENC38DhJII0n2oUrKUuzTwgCvxKOTiHbw==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-plugin-utils": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0-beta.47.tgz", - "integrity": "sha512-GR67o8boOKVJRKM5Nhk7oVEHpxYy8R00lwu0F82WxxBH+iiT26DqW1e/4w/mo7Bdn1A6l0pNaOlNk1PdM2Hgag==", - "dev": true - }, - "@babel/helper-regex": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.0.0-beta.47.tgz", - "integrity": "sha512-dafidvVkjJP5AIWkJspV+7RGj1jeNts0qYvlmVzqAGb6BmQzEldJr6ZPzrmlpW/AW1YJGdw7br2yiwvlCRqDvQ==", - "dev": true, - "requires": { - "lodash": "^4.17.5" - } - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.0.0-beta.47.tgz", - "integrity": "sha512-Nmj3lUHQscD160asav2bZ3sMIjGwGY9r6Vrriy9TqH7bmaClKUKUs5Twv0htFWfOKNFLEeY/MaqiAXylr1GS2w==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "7.0.0-beta.47", - "@babel/helper-wrap-function": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/traverse": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.47.tgz", - "integrity": "sha512-W7IeG4MoVf4oUvWfHUx9VG9if3E0xSUDf1urrnNYtC2ow1dz2ptvQ6YsJfyVXDuPTFXz66jkHhzMW7a5Eld7TA==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.47" - } - }, - "@babel/generator": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.47.tgz", - "integrity": "sha512-fJP+9X+gqgTTZzTqrKJHwebPwt6S/e/4YuyRyKyWHAIirGgUwjRoZgbFci24wwGYMJW7nlkCSwWG7QvCVsG0eg==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47", - "jsesc": "^2.5.1", - "lodash": "^4.17.5", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-function-name": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.47.tgz", - "integrity": "sha512-0LSvt95XCYaOrDA5K68KkTyldKXizDwBnKACdYzQszp1GdbtzmSeGwFU5Ecw86fU6bkYXtDvkFTOQwk/WQSJPw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.47.tgz", - "integrity": "sha512-63j0i3YUW8CO//uQc3ACffJdIlYcIlysuHjMF0yzQhqKoQ/CUPv0hf3nBwdRGjiWrr3JcL6++NF4XmXdwSU+fA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.47.tgz", - "integrity": "sha512-jx8GmxryT6Qy4+24W6M6TnVL9T8bxqdyg5UKHjxBdw0Y2Sano1n0WphUS2seuOugn04W2ZQLqGc0ut8nGe/taA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.47.tgz", - "integrity": "sha512-d505K3Hth1eg0b2swfEF7oFMw3J9M8ceFg0s6dhCSxOOF+07WDvJ0HKT/YbK/Jk9wn8Wyr6HIRAUPKJ9Wfv8Rg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.47.tgz", - "integrity": "sha512-mAzrOCLwOb4jAobHi0kTwIkoamP1Do28c6zxvrDXjYSJFZHz6KGuzMaT0AV7ZCq7M3si7QypVVMVX2bE6IsuOg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/traverse": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.47.tgz", - "integrity": "sha512-kYGGs//OnUnei+9TTldxlgf7llprj7VUeDKtG50+g+0k1g0yZyrkEgbyFheYFdnudR8IDEHOEXVsUuY82r5Aiw==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/generator": "7.0.0-beta.47", - "@babel/helper-function-name": "7.0.0-beta.47", - "@babel/helper-split-export-declaration": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "debug": "^3.1.0", - "globals": "^11.1.0", - "invariant": "^2.2.0", - "lodash": "^4.17.5" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "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" - } - }, - "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "ms": { - "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 - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-replace-supers": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.0.0-beta.47.tgz", - "integrity": "sha512-yf2JAD1+xNTjavqazqknRgPfd6MbGfvfIcAkxWsPURynAwOMSs4zThED8ImT2d5a97rGPysRJcq1jNh2L0WYxg==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "7.0.0-beta.47", - "@babel/helper-optimise-call-expression": "7.0.0-beta.47", - "@babel/traverse": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.47.tgz", - "integrity": "sha512-W7IeG4MoVf4oUvWfHUx9VG9if3E0xSUDf1urrnNYtC2ow1dz2ptvQ6YsJfyVXDuPTFXz66jkHhzMW7a5Eld7TA==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.47" - } - }, - "@babel/generator": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.47.tgz", - "integrity": "sha512-fJP+9X+gqgTTZzTqrKJHwebPwt6S/e/4YuyRyKyWHAIirGgUwjRoZgbFci24wwGYMJW7nlkCSwWG7QvCVsG0eg==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47", - "jsesc": "^2.5.1", - "lodash": "^4.17.5", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-function-name": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.47.tgz", - "integrity": "sha512-0LSvt95XCYaOrDA5K68KkTyldKXizDwBnKACdYzQszp1GdbtzmSeGwFU5Ecw86fU6bkYXtDvkFTOQwk/WQSJPw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.47.tgz", - "integrity": "sha512-63j0i3YUW8CO//uQc3ACffJdIlYcIlysuHjMF0yzQhqKoQ/CUPv0hf3nBwdRGjiWrr3JcL6++NF4XmXdwSU+fA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.47.tgz", - "integrity": "sha512-jx8GmxryT6Qy4+24W6M6TnVL9T8bxqdyg5UKHjxBdw0Y2Sano1n0WphUS2seuOugn04W2ZQLqGc0ut8nGe/taA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.47.tgz", - "integrity": "sha512-d505K3Hth1eg0b2swfEF7oFMw3J9M8ceFg0s6dhCSxOOF+07WDvJ0HKT/YbK/Jk9wn8Wyr6HIRAUPKJ9Wfv8Rg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.47.tgz", - "integrity": "sha512-mAzrOCLwOb4jAobHi0kTwIkoamP1Do28c6zxvrDXjYSJFZHz6KGuzMaT0AV7ZCq7M3si7QypVVMVX2bE6IsuOg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/traverse": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.47.tgz", - "integrity": "sha512-kYGGs//OnUnei+9TTldxlgf7llprj7VUeDKtG50+g+0k1g0yZyrkEgbyFheYFdnudR8IDEHOEXVsUuY82r5Aiw==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/generator": "7.0.0-beta.47", - "@babel/helper-function-name": "7.0.0-beta.47", - "@babel/helper-split-export-declaration": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "debug": "^3.1.0", - "globals": "^11.1.0", - "invariant": "^2.2.0", - "lodash": "^4.17.5" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "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" - } - }, - "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "ms": { - "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 - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-simple-access": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.0.0-beta.47.tgz", - "integrity": "sha512-sd2t3QDKjd+hHkJKaC2AX39l6oIil1N548oMZAtV5YHlVGoWWkAVGnPMxRg7ICEjIftCU3ZI6UeaogyEhF8t7Q==", - "dev": true, - "requires": { - "@babel/template": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "lodash": "^4.17.5" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.47.tgz", - "integrity": "sha512-W7IeG4MoVf4oUvWfHUx9VG9if3E0xSUDf1urrnNYtC2ow1dz2ptvQ6YsJfyVXDuPTFXz66jkHhzMW7a5Eld7TA==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.47" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.47.tgz", - "integrity": "sha512-d505K3Hth1eg0b2swfEF7oFMw3J9M8ceFg0s6dhCSxOOF+07WDvJ0HKT/YbK/Jk9wn8Wyr6HIRAUPKJ9Wfv8Rg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.47.tgz", - "integrity": "sha512-mAzrOCLwOb4jAobHi0kTwIkoamP1Do28c6zxvrDXjYSJFZHz6KGuzMaT0AV7ZCq7M3si7QypVVMVX2bE6IsuOg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", - "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-wrap-function": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.0.0-beta.47.tgz", - "integrity": "sha512-SAasvh80Mz5q9x15dqH6z8jpM0WTBmxQSNZATSwJwhmWdme6r2gxpufIMr8LwQIJHmXmgNLmvh0zdWSbE/PR4Q==", - "dev": true, - "requires": { - "@babel/helper-function-name": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/traverse": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.47.tgz", - "integrity": "sha512-W7IeG4MoVf4oUvWfHUx9VG9if3E0xSUDf1urrnNYtC2ow1dz2ptvQ6YsJfyVXDuPTFXz66jkHhzMW7a5Eld7TA==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.47" - } - }, - "@babel/generator": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.47.tgz", - "integrity": "sha512-fJP+9X+gqgTTZzTqrKJHwebPwt6S/e/4YuyRyKyWHAIirGgUwjRoZgbFci24wwGYMJW7nlkCSwWG7QvCVsG0eg==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47", - "jsesc": "^2.5.1", - "lodash": "^4.17.5", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-function-name": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.47.tgz", - "integrity": "sha512-0LSvt95XCYaOrDA5K68KkTyldKXizDwBnKACdYzQszp1GdbtzmSeGwFU5Ecw86fU6bkYXtDvkFTOQwk/WQSJPw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.47.tgz", - "integrity": "sha512-63j0i3YUW8CO//uQc3ACffJdIlYcIlysuHjMF0yzQhqKoQ/CUPv0hf3nBwdRGjiWrr3JcL6++NF4XmXdwSU+fA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.47.tgz", - "integrity": "sha512-jx8GmxryT6Qy4+24W6M6TnVL9T8bxqdyg5UKHjxBdw0Y2Sano1n0WphUS2seuOugn04W2ZQLqGc0ut8nGe/taA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.47.tgz", - "integrity": "sha512-d505K3Hth1eg0b2swfEF7oFMw3J9M8ceFg0s6dhCSxOOF+07WDvJ0HKT/YbK/Jk9wn8Wyr6HIRAUPKJ9Wfv8Rg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.47.tgz", - "integrity": "sha512-mAzrOCLwOb4jAobHi0kTwIkoamP1Do28c6zxvrDXjYSJFZHz6KGuzMaT0AV7ZCq7M3si7QypVVMVX2bE6IsuOg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/traverse": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.47.tgz", - "integrity": "sha512-kYGGs//OnUnei+9TTldxlgf7llprj7VUeDKtG50+g+0k1g0yZyrkEgbyFheYFdnudR8IDEHOEXVsUuY82r5Aiw==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/generator": "7.0.0-beta.47", - "@babel/helper-function-name": "7.0.0-beta.47", - "@babel/helper-split-export-declaration": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "debug": "^3.1.0", - "globals": "^11.1.0", - "invariant": "^2.2.0", - "lodash": "^4.17.5" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "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" - } - }, - "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "ms": { - "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 - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/helpers": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.0.0-beta.47.tgz", - "integrity": "sha512-uWk7gIua2COEWLwZGxfF5Wq1bgXOt1V6xzWxqeFznrA6F1TUPiAhkK5zORiZEa5RAILp6Mswsn3xFjDyCpp3rQ==", - "dev": true, - "requires": { - "@babel/template": "7.0.0-beta.47", - "@babel/traverse": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.47.tgz", - "integrity": "sha512-W7IeG4MoVf4oUvWfHUx9VG9if3E0xSUDf1urrnNYtC2ow1dz2ptvQ6YsJfyVXDuPTFXz66jkHhzMW7a5Eld7TA==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.47" - } - }, - "@babel/generator": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.47.tgz", - "integrity": "sha512-fJP+9X+gqgTTZzTqrKJHwebPwt6S/e/4YuyRyKyWHAIirGgUwjRoZgbFci24wwGYMJW7nlkCSwWG7QvCVsG0eg==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47", - "jsesc": "^2.5.1", - "lodash": "^4.17.5", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "@babel/helper-function-name": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.47.tgz", - "integrity": "sha512-0LSvt95XCYaOrDA5K68KkTyldKXizDwBnKACdYzQszp1GdbtzmSeGwFU5Ecw86fU6bkYXtDvkFTOQwk/WQSJPw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.47.tgz", - "integrity": "sha512-63j0i3YUW8CO//uQc3ACffJdIlYcIlysuHjMF0yzQhqKoQ/CUPv0hf3nBwdRGjiWrr3JcL6++NF4XmXdwSU+fA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.47.tgz", - "integrity": "sha512-jx8GmxryT6Qy4+24W6M6TnVL9T8bxqdyg5UKHjxBdw0Y2Sano1n0WphUS2seuOugn04W2ZQLqGc0ut8nGe/taA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.47.tgz", - "integrity": "sha512-d505K3Hth1eg0b2swfEF7oFMw3J9M8ceFg0s6dhCSxOOF+07WDvJ0HKT/YbK/Jk9wn8Wyr6HIRAUPKJ9Wfv8Rg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.47.tgz", - "integrity": "sha512-mAzrOCLwOb4jAobHi0kTwIkoamP1Do28c6zxvrDXjYSJFZHz6KGuzMaT0AV7ZCq7M3si7QypVVMVX2bE6IsuOg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/traverse": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.47.tgz", - "integrity": "sha512-kYGGs//OnUnei+9TTldxlgf7llprj7VUeDKtG50+g+0k1g0yZyrkEgbyFheYFdnudR8IDEHOEXVsUuY82r5Aiw==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/generator": "7.0.0-beta.47", - "@babel/helper-function-name": "7.0.0-beta.47", - "@babel/helper-split-export-declaration": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "debug": "^3.1.0", - "globals": "^11.1.0", - "invariant": "^2.2.0", - "lodash": "^4.17.5" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "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" - } - }, - "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "ms": { - "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 - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@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" - }, - "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" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz", - "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==", - "dev": true - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.0.0-beta.47.tgz", - "integrity": "sha512-TQMLYVIqQ0MqVS1Z7jsuv3HlEetLo/7EnDY9mGBZ4c4/WLD/mu+tFuLiK2/2QH5wgi5viRfJGs/+L5TaDzxWng==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/helper-remap-async-to-generator": "7.0.0-beta.47", - "@babel/plugin-syntax-async-generators": "7.0.0-beta.47" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.0.0-beta.47.tgz", - "integrity": "sha512-6yuCiF+ZZHPLgAa+0a6/teNeAMsWqY6AVtZA4NhCWnwP4OH0JrRaY7rwvFCJSqNGurf8rF65W9IucM/l0+HOCg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "7.0.0-beta.47", - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/helper-replace-supers": "7.0.0-beta.47", - "@babel/plugin-syntax-class-properties": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.47.tgz", - "integrity": "sha512-W7IeG4MoVf4oUvWfHUx9VG9if3E0xSUDf1urrnNYtC2ow1dz2ptvQ6YsJfyVXDuPTFXz66jkHhzMW7a5Eld7TA==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.47" - } - }, - "@babel/helper-function-name": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.47.tgz", - "integrity": "sha512-0LSvt95XCYaOrDA5K68KkTyldKXizDwBnKACdYzQszp1GdbtzmSeGwFU5Ecw86fU6bkYXtDvkFTOQwk/WQSJPw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.47.tgz", - "integrity": "sha512-63j0i3YUW8CO//uQc3ACffJdIlYcIlysuHjMF0yzQhqKoQ/CUPv0hf3nBwdRGjiWrr3JcL6++NF4XmXdwSU+fA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.47.tgz", - "integrity": "sha512-d505K3Hth1eg0b2swfEF7oFMw3J9M8ceFg0s6dhCSxOOF+07WDvJ0HKT/YbK/Jk9wn8Wyr6HIRAUPKJ9Wfv8Rg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.47.tgz", - "integrity": "sha512-mAzrOCLwOb4jAobHi0kTwIkoamP1Do28c6zxvrDXjYSJFZHz6KGuzMaT0AV7ZCq7M3si7QypVVMVX2bE6IsuOg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/plugin-proposal-decorators": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.0.0-beta.47.tgz", - "integrity": "sha512-sI+cO1okrlOyV4I63HDXf/SFsCr492HLjzNsMsd7Lk9WrViA+eQIboIiI9wHicozdgD1WrpZGJTjz7Z3xwl2Qw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/plugin-syntax-decorators": "7.0.0-beta.47" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.0.0-beta.47.tgz", - "integrity": "sha512-tTYnPZzCrOm8NK+7lRi4LGxPaw6lErDsozNInM/FWOXGe7s2EpQnTa40S7/gLLNGvpNshYHdykJtKgfiar9qkA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/plugin-syntax-export-namespace-from": "7.0.0-beta.47" - } - }, - "@babel/plugin-proposal-function-sent": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-function-sent/-/plugin-proposal-function-sent-7.0.0-beta.47.tgz", - "integrity": "sha512-253O7PlXtV1LjJkRSMCzG7L16JaQE62AWFVUbbd/8LZI7evyGE5pP90d4R7V+ir/Ra17tL+nk9GfUpEKG7KT4A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/helper-wrap-function": "7.0.0-beta.47", - "@babel/plugin-syntax-function-sent": "7.0.0-beta.47" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.0.0-beta.47.tgz", - "integrity": "sha512-WSS8EVGwHF1g0nQ7IFjiCtBOSyONLqVA3yOriJR1oJS+0HVjfvbee5XwfwsIvdtEIh6YKEnHik5yh54qu7C/PQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/plugin-syntax-numeric-separator": "7.0.0-beta.47" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0-beta.47.tgz", - "integrity": "sha512-ujUjQUyTxUWHfixRD7Y5Nm8VCgHSf6YgbM37LEnojKp5lPahZO42qJfDty+Kh0tEanpI5H8BLPkJbFSzx6TNEw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/plugin-syntax-object-rest-spread": "7.0.0-beta.47" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0-beta.47.tgz", - "integrity": "sha512-XMZavW6uior8KD4BeMavxF3PGrwVpIFlZk/GJQGkd3lOeOHil8nhHDuTWvsbsJptKFWMPkhGR18boNdxgmxyFQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/plugin-syntax-optional-catch-binding": "7.0.0-beta.47" - } - }, - "@babel/plugin-proposal-throw-expressions": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-throw-expressions/-/plugin-proposal-throw-expressions-7.0.0-beta.47.tgz", - "integrity": "sha512-BGJ96kIVi9NlojyZkpJNkdkxABt+VQT6hLQfILpNfFBJUzdOnZbVecXJUmoTAzg56Wse29XbY9bpNmocdNmtFQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/plugin-syntax-throw-expressions": "7.0.0-beta.47" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0-beta.47.tgz", - "integrity": "sha512-TCQqSmPrgVB0Txr6WzCpxJyLuVTb9KoT0+oECKELtF717bvHOI4woR7o8D8DFkXzVQeb7Kqfu5w05gsvPq591g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/helper-regex": "7.0.0-beta.47", - "regexpu-core": "^4.1.4" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regexpu-core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", - "dev": true - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - } - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0-beta.47.tgz", - "integrity": "sha512-LCNGYTLpQAsvTmVmT/I2pz7dIh3Bu+9BLxqL7b3QfplsMQxNsoBBMend33Arb4EtPt5dX7KeeVof8tL0trDRRA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.0.0-beta.47.tgz", - "integrity": "sha512-vLoAuLSjHSenX3TQmri6ttQWZp3rEtGcRp4LgYEBQ012fN5h+KmcssvkCAqm6V6ozS5KzUWpBlZ6t7YhZG6oBw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-syntax-decorators": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.0.0-beta.47.tgz", - "integrity": "sha512-Lv10BM3C+0Ki53lI7T9xZsSsgzQqfoQZq4pZj0F6tkK54E5BBSFfUxGavRE43CFXHbK0Hd9uMqmpGWPGtCvgAw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.0.0-beta.47.tgz", - "integrity": "sha512-J2y7RAH2NwQ+ahJahj2eS1PqS2NWNWTDaEibqrE55VTJU7nPL8AhthRwIQfQkCH+8UIeL/T3Jh1iHIRkvJ6dXA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.0.0-beta.47.tgz", - "integrity": "sha512-mCNj425dtBdO95z1jMKoW0H3nZnTy9tjsdIuLw94uS+y97hvmFkFQtffqH+WIwEGxGBWq1Pn0OGfk3E8GfkhgQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-syntax-function-sent": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-function-sent/-/plugin-syntax-function-sent-7.0.0-beta.47.tgz", - "integrity": "sha512-S/jMyfNd+a/MbtUCvQ3wDC/Wt9Cftj/Q59bVROOX79DrWpKE9VL/kEeiIJzCNKetvDesUdDH+4xcXt3D0/5Rog==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.0.0-beta.47.tgz", - "integrity": "sha512-ISVXJZw9Q2Q0pwcXNv3nfA1p9Ia0clDMTtYxlqIGE5/3WaIQoHkkeaOYsckBKiIIL0hfU+GEjL1g5hRBYPlMUA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-syntax-jsx": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.0.0-beta.47.tgz", - "integrity": "sha512-5scuJzIYZY8M+A1ra8mcKANIwB5TtsRD6Aw94xZxfvnjhhVMFR5RYE9HshVlBrZVY+r3cJDNIQLJMC/fGJHImA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.0.0-beta.47.tgz", - "integrity": "sha512-qAGv7jHtZWNWy4n23OzKLrVk+xfaEO4LYRK3zCMyudXRfB3FPaer6NJNjU5rebvJzC4wB2EVb2nPwVENNNh2jQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0-beta.47.tgz", - "integrity": "sha512-UOGQCmzvNlZMQOuys7xPiTa2EjTT3xHuhUghcdJnYikqGV43obpIIaP+VDCWPvIT8g0QDIvmRWx5UefvkWXN+w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0-beta.47.tgz", - "integrity": "sha512-Dmq+REMR95Syg+VjV3bh63DD/tDxdraNQ4ErAOXFobfSCDbfov9YGkqSJ4K61LHTQwinQ0+dIUlgdFL2kbedIw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-syntax-throw-expressions": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-throw-expressions/-/plugin-syntax-throw-expressions-7.0.0-beta.47.tgz", - "integrity": "sha512-v9DcO3cmp0maysKG7MMjHqHeGTY0/UY4cOuPckIZK3HHmUtQliSLeAw6eaLXGRUv4ZgaqX/T3dbi8YH7YeK4YQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0-beta.47.tgz", - "integrity": "sha512-xiU+7RJAsqx+iZqWSQQWBu9ZDTruWimkg4puDSdRVfEwgZQdOtiU2LuO0+xGFyitJPHkKuje0WvK1tFu1dmxCw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.0.0-beta.47.tgz", - "integrity": "sha512-/TXK3v6ipvmhMO81Y2Vjc7RYROkS2PcmRc+kvmU3CWA7r5I73KWg10UEW/fpWqCuoTCHHHXu1ZcZ5u+nduJeFw==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "7.0.0-beta.47", - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/helper-remap-async-to-generator": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0-beta.47.tgz", - "integrity": "sha512-8KPxKyE6kb9VRbHwQ8XKsg/IPlxHaOMRyg2WfyV5C4dCmXbRdHDJy4hZKB3o4rGxjggmC/Bx8Fh51/P7UNtTcA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0-beta.47.tgz", - "integrity": "sha512-V/u3Zdy40KjVQeyYUaQnCGiHQbRNJoc6IEtNDERltuW9vYPHS1n6YGc+EHKi8JVYT4kE6UHOjD+BrbCCV4kjRw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.0.0-beta.47.tgz", - "integrity": "sha512-hzW/jL6TPBMHJXeXwzuxMN0PFAfjVD0UzATHrFSejY5A7SvhWWrv1cZ3K0/SzCXJ9LpMdxCNiREvVjeD/Tyx2g==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "7.0.0-beta.47", - "@babel/helper-define-map": "7.0.0-beta.47", - "@babel/helper-function-name": "7.0.0-beta.47", - "@babel/helper-optimise-call-expression": "7.0.0-beta.47", - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/helper-replace-supers": "7.0.0-beta.47", - "@babel/helper-split-export-declaration": "7.0.0-beta.47", - "globals": "^11.1.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.47.tgz", - "integrity": "sha512-W7IeG4MoVf4oUvWfHUx9VG9if3E0xSUDf1urrnNYtC2ow1dz2ptvQ6YsJfyVXDuPTFXz66jkHhzMW7a5Eld7TA==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.47" - } - }, - "@babel/helper-function-name": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.47.tgz", - "integrity": "sha512-0LSvt95XCYaOrDA5K68KkTyldKXizDwBnKACdYzQszp1GdbtzmSeGwFU5Ecw86fU6bkYXtDvkFTOQwk/WQSJPw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.47.tgz", - "integrity": "sha512-63j0i3YUW8CO//uQc3ACffJdIlYcIlysuHjMF0yzQhqKoQ/CUPv0hf3nBwdRGjiWrr3JcL6++NF4XmXdwSU+fA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.47.tgz", - "integrity": "sha512-jx8GmxryT6Qy4+24W6M6TnVL9T8bxqdyg5UKHjxBdw0Y2Sano1n0WphUS2seuOugn04W2ZQLqGc0ut8nGe/taA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.47.tgz", - "integrity": "sha512-d505K3Hth1eg0b2swfEF7oFMw3J9M8ceFg0s6dhCSxOOF+07WDvJ0HKT/YbK/Jk9wn8Wyr6HIRAUPKJ9Wfv8Rg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.47.tgz", - "integrity": "sha512-mAzrOCLwOb4jAobHi0kTwIkoamP1Do28c6zxvrDXjYSJFZHz6KGuzMaT0AV7ZCq7M3si7QypVVMVX2bE6IsuOg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0-beta.47.tgz", - "integrity": "sha512-V78qyzmjj4aq/tjpkMFbV5gPtrx7xdclW1Rn6vV9hIwMSMbtstYEXF4msy614MofvYj6gYbPbNfyhXFIUvz/xw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.0.0-beta.47.tgz", - "integrity": "sha512-3AaXC9H7qPybJbSs/QMhhj9EZF9MYrb/HRytwki1tckaYifqCJquENIZxDAYmwsWIGIHiq34WqwPRMIsz/b5uQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.0.0-beta.47.tgz", - "integrity": "sha512-ofB5GwipMoaOH3Qyr5g5FpXWePhIAaD4zMDOoAHDYBPuLWxzAME8YQCa0S3HJf3eTu/HTN/c/G1gDwDB8Z/gKQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/helper-regex": "7.0.0-beta.47", - "regexpu-core": "^4.1.3" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regexpu-core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", - "dev": true - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - } - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0-beta.47.tgz", - "integrity": "sha512-r3xNVYTLVasjqTowIr6s+27oc5n7A5TKbB0/4u9FHjF7ONTWaggO8UFbbj07DOJ4Ll2RkigrZA8/D+w2nJ+XlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.0.0-beta.47.tgz", - "integrity": "sha512-vyGG3kLIXpMuaPL485aqowdWFrxCxXtbzMXy9p1QTK5Q/+9UHpK9XoAVJZGknnsm091m0Ss7spo8uHaxbzYVog==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "7.0.0-beta.47", - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0-beta.47.tgz", - "integrity": "sha512-tfH5OMzV9fWLYJTzWDhoRJKr8kvBZWH26jiCgM0ayNq75ES/X947MqMNAgBjJdTAVEV2kOyks2ItgNAJT4rOUw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.0.0-beta.47.tgz", - "integrity": "sha512-/5I/f8NCouugsRT6ORB1UjCP3N+Rgv/OB6SzmaeIUEpYYPM6D7WQ+4BaRYXQn4eqtOJmTgxDXYa8FgYtoeqP9A==", - "dev": true, - "requires": { - "@babel/helper-function-name": "7.0.0-beta.47", - "@babel/helper-plugin-utils": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.47.tgz", - "integrity": "sha512-W7IeG4MoVf4oUvWfHUx9VG9if3E0xSUDf1urrnNYtC2ow1dz2ptvQ6YsJfyVXDuPTFXz66jkHhzMW7a5Eld7TA==", - "dev": true, - "requires": { - "@babel/highlight": "7.0.0-beta.47" - } - }, - "@babel/helper-function-name": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.47.tgz", - "integrity": "sha512-0LSvt95XCYaOrDA5K68KkTyldKXizDwBnKACdYzQszp1GdbtzmSeGwFU5Ecw86fU6bkYXtDvkFTOQwk/WQSJPw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "7.0.0-beta.47", - "@babel/template": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.47.tgz", - "integrity": "sha512-63j0i3YUW8CO//uQc3ACffJdIlYcIlysuHjMF0yzQhqKoQ/CUPv0hf3nBwdRGjiWrr3JcL6++NF4XmXdwSU+fA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/highlight": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.47.tgz", - "integrity": "sha512-d505K3Hth1eg0b2swfEF7oFMw3J9M8ceFg0s6dhCSxOOF+07WDvJ0HKT/YbK/Jk9wn8Wyr6HIRAUPKJ9Wfv8Rg==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^3.0.0" - } - }, - "@babel/template": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.47.tgz", - "integrity": "sha512-mAzrOCLwOb4jAobHi0kTwIkoamP1Do28c6zxvrDXjYSJFZHz6KGuzMaT0AV7ZCq7M3si7QypVVMVX2bE6IsuOg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.0.0-beta.47", - "@babel/types": "7.0.0-beta.47", - "babylon": "7.0.0-beta.47", - "lodash": "^4.17.5" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "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" - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/plugin-transform-literals": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0-beta.47.tgz", - "integrity": "sha512-PxBw+52qWypwR76YfS2FlW4wZfp61SjIyt3OSPZeWnf0zVQWNVrlRRunJ7lBYudDYvyMwStAE/VynZ0fHtPgng==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.0.0-beta.47.tgz", - "integrity": "sha512-zW84YqQ5Kt8+t5pYrnFhjWQP2w2wq6Nxz9pozxpnvXP+lhqyJPqNdWM1lcVApORpWL1BF7BlgP08yk+5MVRfGA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "7.0.0-beta.47", - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.0.0-beta.47.tgz", - "integrity": "sha512-MYoLyexybBJ9ODWWMsMFzxAQey68RzhQNPjfNAYPhPPB3X160EZ5qOjWxRS2rYNvuYAxs6guy5OdrDpESqFSrQ==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "7.0.0-beta.47", - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/helper-simple-access": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.0.0-beta.47.tgz", - "integrity": "sha512-bMQy3/jEZRpoUg7RdOouphBO8+7Sfjl7XrO84PtgBx4ck+ZPc4xOlBQyr2rkmsJNmmGLi42nnMI1cZZJT3LVnQ==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "7.0.0-beta.47", - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.0.0-beta.47.tgz", - "integrity": "sha512-rG7KioAFCLxZ33wNBqUoxPhtXOmVEvnZNIy9wv0fSbNIQr8lO1avZ7SeBL3OZduNvLocqrESt9Xhh1nzb/zOvA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "7.0.0-beta.47", - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0-beta.47.tgz", - "integrity": "sha512-2IRZtdoPXJn7KSwrmp0xtLTZ0PnhlQxhcTZ0XZ5wfFXmsZ9vi6AK4whIZ2IXI/c2qrYK9FEYLwR5QRfL5Qe6eQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.0.0-beta.47.tgz", - "integrity": "sha512-JN6ox2rH1xe6hlsd6/7d2kPjZSA97wH4oOdNOSaNqaFGEFuaP/Je4+ojHMgyHKU2nx9QHNBCTxHEj+ko+Ij6HQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/helper-replace-supers": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.0.0-beta.47.tgz", - "integrity": "sha512-UzQG8draO+30Y8eNEREuGBfmEHLL7WFxOjmTBbaTrbdOrm/znCUThqcuNz8cyn2nrZbln7M/loQ3stjf9Pt9fQ==", - "dev": true, - "requires": { - "@babel/helper-call-delegate": "7.0.0-beta.47", - "@babel/helper-get-function-arity": "7.0.0-beta.47", - "@babel/helper-plugin-utils": "7.0.0-beta.47" - }, - "dependencies": { - "@babel/helper-get-function-arity": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.47.tgz", - "integrity": "sha512-63j0i3YUW8CO//uQc3ACffJdIlYcIlysuHjMF0yzQhqKoQ/CUPv0hf3nBwdRGjiWrr3JcL6++NF4XmXdwSU+fA==", - "dev": true, - "requires": { - "@babel/types": "7.0.0-beta.47" - } - }, - "@babel/types": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.47.tgz", - "integrity": "sha512-MOP5pOosg7JETrVGg8OQyzmUmbyoSopT5j2HlblHsto89mPz3cmxzn1IA4UNUmnWKgeticSwfhS+Gdy25IIlBQ==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.5", - "to-fast-properties": "^2.0.0" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0-beta.47.tgz", - "integrity": "sha512-JEPIiJyqYRfjOYUTZguLkb2HTwudReqLyOljpOXnJ/1ymwsiof4D6ul611DGlMxJMZJGQ6TBi59iY9GoJ6j4Iw==", - "dev": true, - "requires": { - "regenerator-transform": "^0.12.3" - }, - "dependencies": { - "regenerator-transform": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.12.4.tgz", - "integrity": "sha512-p2I0fY+TbSLD2/VFTFb/ypEHxs3e3AjU0DzttdPqk2bSmDhfSh5E54b86Yc6XhUa5KykK1tgbvZ4Nr82oCJWkQ==", - "dev": true, - "requires": { - "private": "^0.1.6" - } - } - } - }, - "@babel/plugin-transform-runtime": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.0.0-beta.47.tgz", - "integrity": "sha512-RhnhjYsOxmKDGa1ePM5RQWFBYe1PnEZAhXTNEeIwtw1jluEoLL+PCTZDbt/aAcAkZvqwIWccjkNM/FwKTd5Sxw==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "7.0.0-beta.47", - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0-beta.47.tgz", - "integrity": "sha512-+o7/yb0Nrk4Gg/tnBgfBf+G1uGZbtkSluUnj8RyD37ajpDlWmysDjFEHSfktKcuD8YHeGz2M9AYNGcClk1fr/g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0-beta.47.tgz", - "integrity": "sha512-LFAozFdfT4bE2AQw2BnjzLufTX4GBsTUHUGRhT8XNoDYuGnV+7k9Yj6JU3/7csJc9u6W91PArYgoO+D56CMw6Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0-beta.47.tgz", - "integrity": "sha512-+Rc6NihGoXcwAqAxbiumvzOYxRR0aUg1ZExfyHnI5QnQf0sf4xAfgT/YpGvEgLd5Ci0rka+IWSj54PhzZkhuTg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/helper-regex": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0-beta.47.tgz", - "integrity": "sha512-ORfrfN/gQoRuI+xf+kOa2i/yvXfedFRgH+KtgoIrpUQom7OhexxzD280x80LMCIkdaVGzYhvlC3kdJkFMWAfUg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "7.0.0-beta.47", - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0-beta.47.tgz", - "integrity": "sha512-PhPy5NUY5MT++fEr7/sxN1/ERSM2siHSbGgdkbqgDlyvf1NlU1HeqyfomHJEFE1Y4PX0hj+XmtjSAali/6XqYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0-beta.47.tgz", - "integrity": "sha512-44nWn421tMVZ/A4+1uppzoAO7nrlwWzefMr9JUi5G+tXl0DLEtWy+F7L6zCVw19C4OAOA6WlolVro5CEs6g6AQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/helper-regex": "7.0.0-beta.47", - "regexpu-core": "^4.1.3" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regexpu-core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", - "dev": true - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - } - } - }, - "@babel/preset-env": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.0.0-beta.47.tgz", - "integrity": "sha512-ZFUgKdQDqw2H5TCMaWq6iDDO9+16RZPdDfOuoPID8Agm8I2MBlrqTI1MKWwqgEHICdZIOXkVszAMuuDTBwdzHA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "7.0.0-beta.47", - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/plugin-proposal-async-generator-functions": "7.0.0-beta.47", - "@babel/plugin-proposal-object-rest-spread": "7.0.0-beta.47", - "@babel/plugin-proposal-optional-catch-binding": "7.0.0-beta.47", - "@babel/plugin-proposal-unicode-property-regex": "7.0.0-beta.47", - "@babel/plugin-syntax-async-generators": "7.0.0-beta.47", - "@babel/plugin-syntax-object-rest-spread": "7.0.0-beta.47", - "@babel/plugin-syntax-optional-catch-binding": "7.0.0-beta.47", - "@babel/plugin-transform-arrow-functions": "7.0.0-beta.47", - "@babel/plugin-transform-async-to-generator": "7.0.0-beta.47", - "@babel/plugin-transform-block-scoped-functions": "7.0.0-beta.47", - "@babel/plugin-transform-block-scoping": "7.0.0-beta.47", - "@babel/plugin-transform-classes": "7.0.0-beta.47", - "@babel/plugin-transform-computed-properties": "7.0.0-beta.47", - "@babel/plugin-transform-destructuring": "7.0.0-beta.47", - "@babel/plugin-transform-dotall-regex": "7.0.0-beta.47", - "@babel/plugin-transform-duplicate-keys": "7.0.0-beta.47", - "@babel/plugin-transform-exponentiation-operator": "7.0.0-beta.47", - "@babel/plugin-transform-for-of": "7.0.0-beta.47", - "@babel/plugin-transform-function-name": "7.0.0-beta.47", - "@babel/plugin-transform-literals": "7.0.0-beta.47", - "@babel/plugin-transform-modules-amd": "7.0.0-beta.47", - "@babel/plugin-transform-modules-commonjs": "7.0.0-beta.47", - "@babel/plugin-transform-modules-systemjs": "7.0.0-beta.47", - "@babel/plugin-transform-modules-umd": "7.0.0-beta.47", - "@babel/plugin-transform-new-target": "7.0.0-beta.47", - "@babel/plugin-transform-object-super": "7.0.0-beta.47", - "@babel/plugin-transform-parameters": "7.0.0-beta.47", - "@babel/plugin-transform-regenerator": "7.0.0-beta.47", - "@babel/plugin-transform-shorthand-properties": "7.0.0-beta.47", - "@babel/plugin-transform-spread": "7.0.0-beta.47", - "@babel/plugin-transform-sticky-regex": "7.0.0-beta.47", - "@babel/plugin-transform-template-literals": "7.0.0-beta.47", - "@babel/plugin-transform-typeof-symbol": "7.0.0-beta.47", - "@babel/plugin-transform-unicode-regex": "7.0.0-beta.47", - "browserslist": "^3.0.0", - "invariant": "^2.2.2", - "semver": "^5.3.0" - } - }, - "@babel/preset-stage-2": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/preset-stage-2/-/preset-stage-2-7.0.0-beta.47.tgz", - "integrity": "sha512-IabxIY3AAAHRy3GCGJQ3KBfRMR59OZJSMLke24Kwpwlvk09WEP5ERReRbfmUGJeEPeZK3rAt0oZBdF83Ri+C5Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/plugin-proposal-decorators": "7.0.0-beta.47", - "@babel/plugin-proposal-export-namespace-from": "7.0.0-beta.47", - "@babel/plugin-proposal-function-sent": "7.0.0-beta.47", - "@babel/plugin-proposal-numeric-separator": "7.0.0-beta.47", - "@babel/plugin-proposal-throw-expressions": "7.0.0-beta.47", - "@babel/preset-stage-3": "7.0.0-beta.47" - } - }, - "@babel/preset-stage-3": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/preset-stage-3/-/preset-stage-3-7.0.0-beta.47.tgz", - "integrity": "sha512-JOOsIaC3sbcBPbRpELUij3xLE8ObIr7TjanKTExlMwc/Hvz0YG3/ioXmDbphvR9L2cb9a+QNIdjAyOebqDyaFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "7.0.0-beta.47", - "@babel/plugin-proposal-async-generator-functions": "7.0.0-beta.47", - "@babel/plugin-proposal-class-properties": "7.0.0-beta.47", - "@babel/plugin-proposal-object-rest-spread": "7.0.0-beta.47", - "@babel/plugin-proposal-optional-catch-binding": "7.0.0-beta.47", - "@babel/plugin-proposal-unicode-property-regex": "7.0.0-beta.47", - "@babel/plugin-syntax-dynamic-import": "7.0.0-beta.47", - "@babel/plugin-syntax-import-meta": "7.0.0-beta.47" - } - }, - "@babel/runtime": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0-beta.47.tgz", - "integrity": "sha512-3IaakAC5B4bHJ0aCUKVw0pt+GruavdgWDFbf7TfKh7ZJ8yQuUp7af7MNwf3e+jH8776cjqYmMO1JNDDAE9WfrA==", - "dev": true, - "requires": { - "core-js": "^2.5.3", - "regenerator-runtime": "^0.11.1" - }, - "dependencies": { - "core-js": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", - "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - } - } - }, - "@babel/template": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", - "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.2.2", - "@babel/types": "^7.2.2" - } - }, - "@babel/traverse": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.3.tgz", - "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.2.2", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.0.0", - "@babel/parser": "^7.2.3", - "@babel/types": "^7.2.2", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.10" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globals": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.10.0.tgz", - "integrity": "sha512-0GZF1RiPKU97IHUO5TORo9w1PwrH/NBPl+fS7oMLdaTRiYmYbwK4NWoZWrAdd0/abG9R2BU+OiwyQpTpE6pdfQ==", - "dev": true - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "ms": { - "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 - } - } - }, - "@babel/types": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.2.2.tgz", - "integrity": "sha512-fKCuD6UFUMkR541eDWL+2ih/xFZBXPOg/7EQFeTluMDebfqR4jrpaCjLhkWlQS4hT6nRa2PMEgXKbRB5/H2fpg==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.10", - "to-fast-properties": "^2.0.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@feathersjs/adapter-commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@feathersjs/adapter-commons/-/adapter-commons-2.0.0.tgz", - "integrity": "sha512-Fyb2RpV3pZWscjeSQnuvSfksixipwsY0ObpHbz8k0bdfbjpqT59MWTzVcvYsIJzCCHfD0KcsloiZ6jhW5wL9sg==", - "requires": { - "@feathersjs/commons": "^4.0.0", - "@feathersjs/errors": "^3.3.6" - } - }, - "@feathersjs/authentication-client": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@feathersjs/authentication-client/-/authentication-client-1.0.11.tgz", - "integrity": "sha512-4CWQdmdRINMMqHT1/g0N5jqw16u1RjaSPhlZtJZ0OLdqgN3tl5wL+Lb8ThPxihvt1WHiOdwGt141LvWQ446Bsw==", - "dev": true, - "requires": { - "@feathersjs/errors": "^3.3.6", - "debug": "^4.0.0", - "jwt-decode": "^2.1.0" - } - }, - "@feathersjs/authentication-jwt": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@feathersjs/authentication-jwt/-/authentication-jwt-2.0.10.tgz", - "integrity": "sha512-4IVBXDa4w17rroWiSM6LpSzUVG9Za1x1t7fioSObYt60PTkY7QunZt77GkdWfTNLNFvV++VVZ5tGFN6kfIKqCA==", - "dev": true, - "requires": { - "@feathersjs/errors": "^3.3.6", - "debug": "^4.0.0", - "lodash.merge": "^4.6.0", - "lodash.omit": "^4.5.0", - "lodash.pick": "^4.4.0", - "passport-jwt": "^4.0.0" - } - }, - "@feathersjs/client": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/@feathersjs/client/-/client-3.7.8.tgz", - "integrity": "sha512-SsLVU6wq1PToBCC3XAvMRV18RBqCG1Ipt0G0+cyNKvYpcKW238Prvw7uYyAxPyQw+JL1c0xHkyDId03Duu6ZTA==", - "dev": true - }, - "@feathersjs/commons": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@feathersjs/commons/-/commons-4.0.0.tgz", - "integrity": "sha512-hyCLse4RiNt7WLPQ0KSudjoVnwiRykhYzIZdtDon9i2usPaoYkFw/fEYZrkE5HVB+sUTwphZoZ1oOntRk1MShg==" - }, - "@feathersjs/errors": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/@feathersjs/errors/-/errors-3.3.6.tgz", - "integrity": "sha512-VCohY/AQU13xYyZGl6rfdUgE+2bjaI76a4aEb6reIphHKgb4mnjYlg2PzS1/hcU1qUNi515kY9yQa5HsE7J1dQ==", - "requires": { - "debug": "^4.0.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, - "@feathersjs/feathers": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@feathersjs/feathers/-/feathers-3.3.1.tgz", - "integrity": "sha512-Mb7Maz03TIIksomXeInmXNb5ykxgsAyBCuJDQHK+oIDrDRR9m+ZbUrslCkMk/s0nr6cW5DmVbWz9s11SCXFW5A==", - "dev": true, - "requires": { - "@feathersjs/commons": "^4.0.0", - "debug": "^4.0.0", - "events": "^3.0.0", - "uberproto": "^2.0.2" - }, - "dependencies": { - "@feathersjs/commons": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@feathersjs/commons/-/commons-4.0.0.tgz", - "integrity": "sha512-hyCLse4RiNt7WLPQ0KSudjoVnwiRykhYzIZdtDon9i2usPaoYkFw/fEYZrkE5HVB+sUTwphZoZ1oOntRk1MShg==", - "dev": true - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", - "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==", - "dev": true - }, - "ms": { - "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 - }, - "uberproto": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/uberproto/-/uberproto-2.0.4.tgz", - "integrity": "sha512-c/5xjTcztW9XVhrkCycHQRBIAxww5JpDKk/q0zc2tVdQn6ZQvnChWgLvQaWAT1Al5JvRyvloUI15ad41m6dYwg==", - "dev": true - } - } - }, - "@feathersjs/rest-client": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/@feathersjs/rest-client/-/rest-client-1.4.7.tgz", - "integrity": "sha512-Eybe9iTMz2r1J8ITRZH4/WGfIhwSIzP9kiTpwAVESo6NGE6rgwvN95FmtI5AtCABV5v4C2Cy/tVDsMMa9Dgs+A==", - "dev": true, - "requires": { - "@feathersjs/commons": "^4.0.0", - "@feathersjs/errors": "^3.3.6", - "qs": "^6.5.0" - }, - "dependencies": { - "@feathersjs/commons": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@feathersjs/commons/-/commons-4.0.0.tgz", - "integrity": "sha512-hyCLse4RiNt7WLPQ0KSudjoVnwiRykhYzIZdtDon9i2usPaoYkFw/fEYZrkE5HVB+sUTwphZoZ1oOntRk1MShg==", - "dev": true - } - } - }, - "@feathersjs/socketio-client": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@feathersjs/socketio-client/-/socketio-client-1.2.1.tgz", - "integrity": "sha512-OJUVhRc2nNxNS5XdEHWJDHES/wFmhpNYSakBcqCeTKwXXyxhN41U4u8C6qOeSFhb8iZA4pOGmpPWF1MOp1rfFA==", - "dev": true, - "requires": { - "@feathersjs/transport-commons": "^4.2.1" - } - }, - "@feathersjs/transport-commons": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@feathersjs/transport-commons/-/transport-commons-4.2.1.tgz", - "integrity": "sha512-HVj+pXAaM4JsBgyoQqG1w29ovRF480GgReuCrcktywq+sLKYNxLweogFz+cxyQjmZLL17r51REUJzbDEj20VTQ==", - "dev": true, - "requires": { - "@feathersjs/commons": "^4.0.0", - "@feathersjs/errors": "^3.3.6", - "debug": "^4.0.0", - "lodash": "^4.17.10", - "radix-router": "^3.0.1" - }, - "dependencies": { - "@feathersjs/commons": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@feathersjs/commons/-/commons-4.0.0.tgz", - "integrity": "sha512-hyCLse4RiNt7WLPQ0KSudjoVnwiRykhYzIZdtDon9i2usPaoYkFw/fEYZrkE5HVB+sUTwphZoZ1oOntRk1MShg==", - "dev": true - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "ms": { - "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 - } - } - }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "dev": true, - "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - } - }, - "@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", - "dev": true - }, - "@shellscape/koa-send": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@shellscape/koa-send/-/koa-send-4.1.3.tgz", - "integrity": "sha512-akNxJetq2ak8aj7U6ys+EYXfWY4k8keleDZJbHWvpuVDj0/PUbbOuPkeBYaie7C6d5fRNLK+0M1Puu8ywTlj3w==", - "dev": true, - "requires": { - "debug": "^2.6.3", - "http-errors": "^1.6.1", - "mz": "^2.6.0", - "resolve-path": "^1.3.3" - }, - "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" - } - } - } - }, - "@shellscape/koa-static": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@shellscape/koa-static/-/koa-static-4.0.5.tgz", - "integrity": "sha512-0T2g2NtaO2zhbqR8EBACIGtBy+haodKb8PuJ17RGDXAJwhjkgghUKLrLEnm05zuiwupfYm2APIax6D2TwLoflA==", - "dev": true, - "requires": { - "@shellscape/koa-send": "^4.1.0", - "debug": "^2.6.8" - }, - "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" - } - } - } - }, - "@types/chai": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", - "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", - "dev": true - }, - "@types/deep-diff": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/deep-diff/-/deep-diff-1.0.0.tgz", - "integrity": "sha512-ENsJcujGbCU/oXhDfQ12mSo/mCBWodT2tpARZKmatoSrf8+cGRCPi0KVj3I0FORhYZfLXkewXu7AoIWqiBLkNw==" - }, - "@types/feathersjs__feathers": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/feathersjs__feathers/-/feathersjs__feathers-3.1.1.tgz", - "integrity": "sha512-4/IC/qQI+V9WbhmQnMvuQctcURvdyVvSJ+3JANVEqedzvApW/P8TUfVHeJ/k7EaXBgglShI6rNSKwZTVNOiVRw==", - "requires": { - "@types/feathersjs__feathers": "*", - "@types/node": "*" - } - }, - "@types/inflection": { - "version": "1.5.28", - "resolved": "https://registry.npmjs.org/@types/inflection/-/inflection-1.5.28.tgz", - "integrity": "sha1-Q9VeDXLPMzot/9nE7AQHRVobCTE=" - }, - "@types/lodash": { - "version": "4.14.123", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.123.tgz", - "integrity": "sha512-pQvPkc4Nltyx7G1Ww45OjVqUsJP4UsZm+GWJpigXgkikZqJgRm4c48g027o6tdgubWHwFRF15iFd+Y4Pmqv6+Q==" - }, - "@types/mocha": { - "version": "5.2.6", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.6.tgz", - "integrity": "sha512-1axi39YdtBI7z957vdqXI4Ac25e7YihYQtJa+Clnxg1zTJEaIRbndt71O3sP4GAMgiAm0pY26/b9BrY4MR/PMw==", - "dev": true - }, - "@types/node": { - "version": "11.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz", - "integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ==" - }, - "@types/npm": { - "version": "2.0.30", - "resolved": "https://registry.npmjs.org/@types/npm/-/npm-2.0.30.tgz", - "integrity": "sha512-juetEKXQJZlVrhRg3Z8WAKFeUr2sRapp8IGOxOaWI07rrrt0T0lgLiv7NtpqoP6Ul/If5vD0/17C0Q84saiwBg==", - "requires": { - "@types/node": "*" - } - }, - "@types/socket.io": { - "version": "1.4.40", - "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-1.4.40.tgz", - "integrity": "sha512-B9luG4IRhql12JGoYeTlCTlizRAtaWmxu9dSyY+AOWO2pEMFFajZnzqF65GH8GVFsyJzfmXqnfdvPlS+mAM/Xw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.5.0.tgz", - "integrity": "sha512-TZ5HRDFz6CswqBUviPX8EfS+iOoGbclYroZKT3GWGYiGScX0qo6QjHc5uuM7JN920voP2zgCkHgF5SDEVlCtjQ==", - "dev": true, - "requires": { - "@typescript-eslint/parser": "1.5.0", - "@typescript-eslint/typescript-estree": "1.5.0", - "requireindex": "^1.2.0", - "tsutils": "^3.7.0" - } - }, - "@typescript-eslint/parser": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.5.0.tgz", - "integrity": "sha512-pRWTnJrnxuT0ragdY26hZL+bxqDd4liMlftpH2CBlMPryOIOb1J+MdZuw6R4tIu6bWVdwbHKPTs+Q34LuGvfGw==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "1.5.0", - "eslint-scope": "^4.0.0", - "eslint-visitor-keys": "^1.0.0" - }, - "dependencies": { - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - } - } - }, - "@typescript-eslint/typescript-estree": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.5.0.tgz", - "integrity": "sha512-XqR14d4BcYgxcrpxIwcee7UEjncl9emKc/MgkeUfIk2u85KlsGYyaxC7Zxjmb17JtWERk/NaO+KnBsqgpIXzwA==", - "dev": true, - "requires": { - "lodash.unescape": "4.0.1", - "semver": "5.5.0" - }, - "dependencies": { - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true - } - } - }, - "@vue/babel-preset-app": { - "version": "3.0.0-beta.11", - "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-3.0.0-beta.11.tgz", - "integrity": "sha1-yLiJqnNGQFD5zT+dxiGVHYXCRQg=", - "dev": true, - "requires": { - "@babel/plugin-syntax-jsx": "7.0.0-beta.47", - "@babel/plugin-transform-runtime": "7.0.0-beta.47", - "@babel/preset-env": "7.0.0-beta.47", - "@babel/preset-stage-2": "7.0.0-beta.47", - "@babel/runtime": "7.0.0-beta.47", - "babel-helper-vue-jsx-merge-props": "^2.0.3", - "babel-plugin-dynamic-import-node": "^1.2.0", - "babel-plugin-transform-vue-jsx": "^4.0.1" - } - }, - "@vue/component-compiler-utils": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-2.6.0.tgz", - "integrity": "sha512-IHjxt7LsOFYc0DkTncB7OXJL7UzwOLPPQCfEUNyxL2qt+tF12THV+EO33O1G2Uk4feMSWua3iD39Itszx0f0bw==", - "dev": true, - "requires": { - "consolidate": "^0.15.1", - "hash-sum": "^1.0.2", - "lru-cache": "^4.1.2", - "merge-source-map": "^1.1.0", - "postcss": "^7.0.14", - "postcss-selector-parser": "^5.0.0", - "prettier": "1.16.3", - "source-map": "~0.6.1", - "vue-template-es2015-compiler": "^1.9.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" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "postcss": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", - "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - } - }, - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "dev": true, - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "prettier": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.3.tgz", - "integrity": "sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw==", - "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 - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@vue/eslint-config-prettier": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-4.0.1.tgz", - "integrity": "sha512-rJEDXPb61Hfgg8GllO3XXFP98bcIxdNNHSrNcxP/vBSukOolgOwQyZJ5f5z/c7ViPyh5/IDlC4qBnhx/0n+I4g==", - "dev": true, - "requires": { - "eslint-config-prettier": "^3.3.0", - "eslint-plugin-prettier": "^3.0.0", - "prettier": "^1.15.2" - }, - "dependencies": { - "eslint-config-prettier": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-3.6.0.tgz", - "integrity": "sha512-ixJ4U3uTLXwJts4rmSVW/lMXjlGwCijhBJHk8iVqKKSifeI0qgFEfWl8L63isfc8Od7EiBALF6BX3jKLluf/jQ==", - "dev": true, - "requires": { - "get-stdin": "^6.0.0" - } - } - } - }, - "@vue/eslint-config-typescript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-4.0.0.tgz", - "integrity": "sha512-uSMAMgw4xDgVdZQhpbtJRo8nMV4oOy3Ht8olfOo7xvYFYLMF2JZ1tDRKd9/NSusxA72O2Vma+HzmyzDHg9evcQ==", - "dev": true, - "requires": { - "@typescript-eslint/eslint-plugin": "^1.1.0", - "@typescript-eslint/parser": "^1.1.0" - } - }, - "@vue/test-utils": { - "version": "1.0.0-beta.29", - "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-1.0.0-beta.29.tgz", - "integrity": "sha512-yX4sxEIHh4M9yAbLA/ikpEnGKMNBCnoX98xE1RwxfhQVcn0MaXNSj1Qmac+ZydTj6VBSEVukchBogXBTwc+9iA==", - "dev": true, - "requires": { - "dom-event-types": "^1.0.0", - "lodash": "^4.17.4" - } - }, - "@webassemblyjs/ast": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", - "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", - "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", - "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", - "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", - "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.8.5" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", - "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", - "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "mamacro": "^0.0.3" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", - "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", - "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", - "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", - "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", - "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", - "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/helper-wasm-section": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-opt": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "@webassemblyjs/wast-printer": "1.8.5" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", - "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", - "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-buffer": "1.8.5", - "@webassemblyjs/wasm-gen": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", - "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-wasm-bytecode": "1.8.5", - "@webassemblyjs/ieee754": "1.8.5", - "@webassemblyjs/leb128": "1.8.5", - "@webassemblyjs/utf8": "1.8.5" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", - "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/floating-point-hex-parser": "1.8.5", - "@webassemblyjs/helper-api-error": "1.8.5", - "@webassemblyjs/helper-code-frame": "1.8.5", - "@webassemblyjs/helper-fsm": "1.8.5", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", - "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/wast-parser": "1.8.5", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-contrib/config-loader": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@webpack-contrib/config-loader/-/config-loader-1.2.1.tgz", - "integrity": "sha512-C7XsS6bXft0aRlyt7YCLg+fm97Mb3tWd+i5fVVlEl0NW5HKy8LoXVKj3mB7ECcEHNEEdHhgzg8gxP+Or8cMj8Q==", - "dev": true, - "requires": { - "@webpack-contrib/schema-utils": "^1.0.0-beta.0", - "chalk": "^2.1.0", - "cosmiconfig": "^5.0.2", - "is-plain-obj": "^1.1.0", - "loud-rejection": "^1.6.0", - "merge-options": "^1.0.1", - "minimist": "^1.2.0", - "resolve": "^1.6.0", - "webpack-log": "^1.1.2" - }, - "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" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cosmiconfig": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.1.0.tgz", - "integrity": "sha512-kCNPvthka8gvLtzAxQXvWo4FxqRB+ftRZyPZNuab5ngvM9Y7yw7hbEysglptLgpkGX9nAOKTBVkHUAe8xtYR6Q==", - "dev": true, - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.9.0", - "lodash.get": "^4.4.2", - "parse-json": "^4.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 - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "resolve": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", - "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@webpack-contrib/schema-utils": { - "version": "1.0.0-beta.0", - "resolved": "https://registry.npmjs.org/@webpack-contrib/schema-utils/-/schema-utils-1.0.0-beta.0.tgz", - "integrity": "sha512-LonryJP+FxQQHsjGBi6W786TQB1Oym+agTpY0c+Kj8alnIw+DLUJb6SI8Y1GHGhLCH1yPRrucjObUmxNICQ1pg==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chalk": "^2.3.2", - "strip-ansi": "^4.0.0", - "text-table": "^0.2.0", - "webpack-log": "^1.1.2" - }, - "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 - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@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.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "Base64": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz", - "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg=", - "dev": true - }, - "abab": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", - "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", - "dev": true - }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "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" - } - }, - "acorn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.5.tgz", - "integrity": "sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg==", - "dev": true - }, - "acorn-dynamic-import": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", - "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", - "dev": true - }, - "acorn-globals": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", - "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", - "dev": true, - "requires": { - "acorn": "^6.0.1", - "acorn-walk": "^6.0.1" - } - }, - "acorn-jsx": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", - "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", - "dev": true - }, - "acorn-walk": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", - "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", - "dev": true - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true - }, - "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": { - "es6-promisify": "^5.0.0" - } - }, - "agentkeepalive": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-2.2.0.tgz", - "integrity": "sha1-xdG9SxKQCPEWPyNvhuX66iAm4u8=", - "dev": true - }, - "ajv": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", - "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", - "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-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true - }, - "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 - }, - "algoliasearch": { - "version": "3.32.1", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-3.32.1.tgz", - "integrity": "sha512-NaaHMboU9tKwrU3aim7LlzSDqKb+1TGaC+Lx3NOttSnuMHbPpaf+7LtJL4KlosbRWEwqb9t5wSYMVDrPTH2dNA==", - "dev": true, - "requires": { - "agentkeepalive": "^2.2.0", - "debug": "^2.6.9", - "envify": "^4.0.0", - "es6-promise": "^4.1.0", - "events": "^1.1.0", - "foreach": "^2.0.5", - "global": "^4.3.2", - "inherits": "^2.0.1", - "isarray": "^2.0.1", - "load-script": "^1.0.0", - "object-keys": "^1.0.11", - "querystring-es3": "^0.2.1", - "reduce": "^1.0.1", - "semver": "^5.1.0", - "tunnel-agent": "^0.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" - } - }, - "isarray": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz", - "integrity": "sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA==", - "dev": true - } - } - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - } - }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", - "dev": true - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", - "dev": true, - "requires": { - "string-width": "^2.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 - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", - "dev": true - }, - "ansi-escapes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "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 - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", - "dev": true - }, - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true, - "optional": true, - "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" - } - }, - "app-root-path": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.2.0.tgz", - "integrity": "sha512-qbXcJgmuLGNwO7FH2WrtoJpA0mpcm0ZFQZPm6RV7ZLfA0QR3bQFpoij33x74+u3Zn58JDy5Jc/Z/LXKxTvh1Rw==", - "dev": true - }, - "append-transform": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", - "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", - "dev": true, - "requires": { - "default-require-extensions": "^1.0.0" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "arch": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.1.1.tgz", - "integrity": "sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg==", - "dev": true - }, - "arg": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", - "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==", - "dev": true - }, - "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "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" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", - "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", - "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-includes": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", - "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.7.0" - } - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "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", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true, - "requires": { - "util": "0.10.3" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true - }, - "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 - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "autocomplete.js": { - "version": "0.33.0", - "resolved": "https://registry.npmjs.org/autocomplete.js/-/autocomplete.js-0.33.0.tgz", - "integrity": "sha512-J0F7BkPhYwXvfs8Skp6v2e2IHYv0SL8INyHYwb7nUpvKHr96g6zS8RNEFGEfEuO3ND+XUsesEMM59LlwQoLfoA==", - "dev": true, - "requires": { - "immediate": "^3.2.3" - } - }, - "autoprefixer": { - "version": "8.6.5", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.6.5.tgz", - "integrity": "sha512-PLWJN3Xo/rycNkx+mp8iBDMTm3FeWe4VmYaZDSqL5QQB9sLsQkG5k8n+LNDFnhh9kdq2K+egL/icpctOmDHwig==", - "dev": true, - "requires": { - "browserslist": "^3.2.8", - "caniuse-lite": "^1.0.30000864", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^6.0.23", - "postcss-value-parser": "^3.2.3" - } - }, - "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 - }, - "axios": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz", - "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", - "dev": true, - "requires": { - "follow-redirects": "^1.3.0", - "is-buffer": "^1.1.5" - }, - "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" - } - }, - "follow-redirects": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", - "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", - "dev": true, - "requires": { - "debug": "=3.1.0" - } - } - } - }, - "babel-cli": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", - "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", - "dev": true, - "requires": { - "babel-core": "^6.26.0", - "babel-polyfill": "^6.26.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "chokidar": "^1.6.1", - "commander": "^2.11.0", - "convert-source-map": "^1.5.0", - "fs-readdir-recursive": "^1.0.0", - "glob": "^7.1.2", - "lodash": "^4.17.4", - "output-file-sync": "^1.1.2", - "path-is-absolute": "^1.0.1", - "slash": "^1.0.0", - "source-map": "^0.5.6", - "v8flags": "^2.1.1" - } - }, - "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" - } - }, - "babel-core": { - "version": "6.26.3", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.1", - "debug": "^2.6.9", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.8", - "slash": "^1.0.0", - "source-map": "^0.5.7" - }, - "dependencies": { - "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true - }, - "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" - } - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "babel-eslint": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.1.tgz", - "integrity": "sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", - "eslint-scope": "3.7.1", - "eslint-visitor-keys": "^1.0.0" - } - }, - "babel-extract-comments": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/babel-extract-comments/-/babel-extract-comments-1.0.0.tgz", - "integrity": "sha512-qWWzi4TlddohA91bFwgt6zO/J0X+io7Qp184Fw0m2JYRSTZnJbFR8+07KmzudHCZgOiKRCrjhylwv9Xd8gfhVQ==", - "dev": true, - "requires": { - "babylon": "^6.18.0" - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "babel-helper-bindify-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", - "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, - "requires": { - "babel-helper-explode-assignable-expression": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-explode-class": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", - "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true, - "requires": { - "babel-helper-bindify-decorators": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, - "requires": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-vue-jsx-merge-props": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz", - "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==", - "dev": true - }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-loader": { - "version": "8.0.0-beta.3", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.0-beta.3.tgz", - "integrity": "sha512-yvaAx7cBEjh+R2oGL2vIPmveO6daS5TYP2FSPq4b6CUYjU/ilD4HHyfLIa9KUj6OKBcR9fQcl1NvUOTWNaJ6mw==", - "dev": true, - "requires": { - "find-cache-dir": "^1.0.0", - "loader-utils": "^1.0.2", - "mkdirp": "^0.5.1", - "util.promisify": "^1.0.0" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-add-module-exports": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.0.tgz", - "integrity": "sha512-m0sMxPL4FaN2K69GQgaRJa4Ny15qKSdoknIcpN+gz+NaJlAW9pge/povs13tPYsKDboflrEQC+/3kfIsONBTaw==", - "dev": true, - "requires": { - "chokidar": "^2.0.4" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "optional": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "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, - "optional": 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, - "optional": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "optional": 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, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "optional": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "optional": 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, - "optional": 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, - "optional": 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, - "optional": 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, - "optional": 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, - "optional": 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, - "optional": 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, - "optional": 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, - "optional": 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, - "optional": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "optional": 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, - "optional": 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, - "optional": 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, - "optional": 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, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "optional": 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" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": "^2.1.0" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.0.5" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "optional": 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, - "optional": true, - "requires": { - "is-extglob": "^2.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, - "optional": 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, - "optional": 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, - "optional": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "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, - "optional": 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, - "optional": 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, - "optional": 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, - "optional": 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, - "optional": 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, - "optional": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "optional": 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" - } - }, - "nan": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", - "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", - "dev": true, - "optional": true - } - } - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-dynamic-import-node": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-1.2.0.tgz", - "integrity": "sha512-yeDwKaLgGdTpXL7RgGt5r6T4LmnTza/hUn5Ul8uZSGGMtEjYo13Nxai7SQaGCTEzUtg9Zq9qJn0EjEr7SeSlTQ==", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "^6.18.0" - } - }, - "babel-plugin-istanbul": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz", - "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.13.0", - "find-up": "^2.1.0", - "istanbul-lib-instrument": "^1.10.1", - "test-exclude": "^4.2.1" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - } - } - }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true - }, - "babel-plugin-syntax-async-generators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", - "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", - "dev": true - }, - "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true - }, - "babel-plugin-syntax-decorators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", - "dev": true - }, - "babel-plugin-syntax-dynamic-import": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", - "dev": true - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true - }, - "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", - "dev": true - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", - "dev": true - }, - "babel-plugin-transform-async-generator-functions": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", - "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-generators": "^6.5.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-plugin-syntax-class-properties": "^6.8.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", - "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true, - "requires": { - "babel-helper-explode-class": "^6.24.1", - "babel-plugin-syntax-decorators": "^6.13.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, - "requires": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "requires": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "requires": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" - } - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", - "babel-plugin-syntax-exponentiation-operator": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-object-rest-spread": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", - "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.8.0", - "babel-runtime": "^6.26.0" - } - }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, - "requires": { - "regenerator-transform": "^0.10.0" - } - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-vue-jsx": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-4.0.1.tgz", - "integrity": "sha512-wbOz7ITB5cloLSjKUU1hWn8zhR+Dwah/RZiTiJY/CQliCwhowmzu6m7NEF+y5EJX/blDzGjRtZvC10Vdb3Q7vw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "babel-polyfill": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "regenerator-runtime": "^0.10.5" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", - "dev": true - } - } - }, - "babel-preset-es2015": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", - "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.24.1", - "babel-plugin-transform-es2015-classes": "^6.24.1", - "babel-plugin-transform-es2015-computed-properties": "^6.24.1", - "babel-plugin-transform-es2015-destructuring": "^6.22.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.24.1", - "babel-plugin-transform-es2015-for-of": "^6.22.0", - "babel-plugin-transform-es2015-function-name": "^6.24.1", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-plugin-transform-es2015-modules-systemjs": "^6.24.1", - "babel-plugin-transform-es2015-modules-umd": "^6.24.1", - "babel-plugin-transform-es2015-object-super": "^6.24.1", - "babel-plugin-transform-es2015-parameters": "^6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.24.1", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.22.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.24.1", - "babel-plugin-transform-regenerator": "^6.24.1" - } - }, - "babel-preset-stage-2": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", - "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "^6.18.0", - "babel-plugin-transform-class-properties": "^6.24.1", - "babel-plugin-transform-decorators": "^6.24.1", - "babel-preset-stage-3": "^6.24.1" - } - }, - "babel-preset-stage-3": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", - "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true, - "requires": { - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-generator-functions": "^6.24.1", - "babel-plugin-transform-async-to-generator": "^6.24.1", - "babel-plugin-transform-exponentiation-operator": "^6.24.1", - "babel-plugin-transform-object-rest-spread": "^6.22.0" - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, - "requires": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, - "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" - } - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "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 - }, - "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" - } - }, - "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" - } - }, - "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 - } - } - }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true - }, - "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true - }, - "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", - "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, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "1.0.0" - } - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, - "binary-extensions": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.10.0.tgz", - "integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=", - "dev": true - }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", - "dev": true - }, - "bluebird": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", - "dev": true - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" - }, - "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" - } - } - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "boxen": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", - "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", - "dev": true, - "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.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 - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "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" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "browser-process-hrtime": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", - "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", - "dev": true - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - } - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" - } - }, - "browserstack": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.2.tgz", - "integrity": "sha512-+6AFt9HzhKykcPF79W6yjEUJcdvZOV0lIXdkORXMJftGrDl0OKWqRF4GHqpDNkxiceDT/uB7Fb/aDwktvXX7dg==", - "dev": true, - "requires": { - "https-proxy-agent": "^2.2.1" - } - }, - "browserstacktunnel-wrapper": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/browserstacktunnel-wrapper/-/browserstacktunnel-wrapper-1.4.2.tgz", - "integrity": "sha1-ZZj7fXhLb/NI4998EEsNnCfqUnU=", - "dev": true, - "requires": { - "unzip": "~0.1.9" - } - }, - "bson-objectid": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/bson-objectid/-/bson-objectid-1.2.4.tgz", - "integrity": "sha512-z511nO3HgvLpB0Ax2+kfM2HRfgGKB0VbMnRKh5yNM9Eoh2o1/DRFXBrsoTpvjR09vNIHUMUmcwFFYhSU+0PBGQ==" - }, - "buffer": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.0.8.tgz", - "integrity": "sha512-xXvjQhVNz50v2nPeoOsNqWCLGfiv4ji/gXZM28jnVwdLJxH4mFyqgqCKfaK9zf1KUbG6zTkjLOy7ou+jSMarGA==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "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", - "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", - "dev": true, - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^2.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^5.2.4", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "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", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - } - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "dependencies": { - "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 - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "cache-content-type": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", - "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", - "dev": true, - "requires": { - "mime-types": "^2.1.18", - "ylru": "^1.2.0" - } - }, - "cache-loader": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-1.2.5.tgz", - "integrity": "sha512-enWKEQ4kO3YreDFd7AtVRjtJBmNiqh/X9hVDReu0C4qm8gsGmySkwuWtdc+N5O+vq5FzxL1mIZc30NyXCB7o/Q==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "mkdirp": "^0.5.1", - "neo-async": "^2.5.0", - "schema-utils": "^0.4.2" - } - }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", - "dev": true - }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "dev": true, - "requires": { - "callsites": "^2.0.0" - }, - "dependencies": { - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - } - } - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - }, - "dependencies": { - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - } - } - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true - }, - "callsites": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.0.0.tgz", - "integrity": "sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw==", - "dev": true - }, - "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", - "dev": true, - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, - "optional": true - }, - "camelcase-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", - "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", - "dev": true, - "requires": { - "camelcase": "^4.1.0", - "map-obj": "^2.0.0", - "quick-lru": "^1.0.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - } - } - }, - "can-assign": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/can-assign/-/can-assign-1.3.1.tgz", - "integrity": "sha512-lL5rt4hpEzk0TTEwP9kr3NTswZu/ld2+rukkh8+2NIKQY8BvxNDkaYuau8GFIwpT5IINZ4ztnhzuAFtCXj24hQ==", - "dev": true, - "requires": { - "can-namespace": "1.0.0" - } - }, - "can-define-lazy-value": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/can-define-lazy-value/-/can-define-lazy-value-1.1.0.tgz", - "integrity": "sha512-jkx2fBG9zz5p3G34+zVc1uyzzm0lesWmanKZBriRvmBXx724s7okiK8DViATrzAWX64RSAdEyv+wXLzwmDoOrA==", - "dev": true - }, - "can-deparam": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/can-deparam/-/can-deparam-1.2.0.tgz", - "integrity": "sha512-Qq1wkHTv7rUFrJ6YEC9LU5O1sahwoGUt7EStUTh19cKyISFI33dae4aEGcy4+ztPkCLGLS6EpAeTyau7TWdbig==", - "dev": true, - "requires": { - "can-namespace": "1.0.0" - } - }, - "can-diff": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/can-diff/-/can-diff-1.4.4.tgz", - "integrity": "sha512-XXcmuO0LClDaeuVLJ+poylmJ+79pLya7MaKm461jtpCNTjyLY8CwSF/ldfM2jsPYKLblueV/j0r+loMSYxR5tg==", - "dev": true, - "requires": { - "can-key-tree": "^1.0.2", - "can-queues": "^1.0.1", - "can-reflect": "^1.14.1" - } - }, - "can-fixture": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/can-fixture/-/can-fixture-3.0.4.tgz", - "integrity": "sha512-RjQetfNY6mQvFEwmeHOj1m/mHANqj8UdkVutXKAZ8/HtWlIfM+e7ZYeLm+tNOXSh3FP0qZ31U9wTYypmA88pzA==", - "dev": true, - "requires": { - "can-deparam": "^1.0.1", - "can-key": "<2.0.0", - "can-log": "^1.0.0", - "can-memory-store": "<2.0.0", - "can-namespace": "1.0.0", - "can-query-logic": "<2.0.0", - "can-reflect": "^1.15.1" - } - }, - "can-fixture-socket": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/can-fixture-socket/-/can-fixture-socket-2.0.0.tgz", - "integrity": "sha512-DYsOlz8qBX2VQA733sO48/XWsuSW9RBV7yYSq1nCYWST0p+hp28Q2BJCEWb0qCwMEhkOndyxjSUEO2FQVoQ1cw==", - "dev": true, - "requires": { - "can-assign": "^1.2.0", - "can-fixture": "^3.0.0" - } - }, - "can-key": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/can-key/-/can-key-1.2.0.tgz", - "integrity": "sha512-Y4IA74QqyOdf0C0Ar2nppf0U+hJpqdxlUfTXn4aIRy5NArBhxilP11y+u3Cm398QNcBXRtQb6iALCOFsZlJt3g==", - "dev": true, - "requires": { - "can-namespace": "^1.0.0", - "can-reflect": "^1.13.3", - "can-symbol": "^1.0.0" - } - }, - "can-key-tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/can-key-tree/-/can-key-tree-1.2.0.tgz", - "integrity": "sha512-zvv46l0iTwe3qGNcqg3tLuUSbMJeNQjN26DtXSeTWfPdGdgGK1yITE6LoJ3Sux9RpvzZdGJBJ6oXTnfv1NGYXg==", - "dev": true, - "requires": { - "can-reflect": "^1.4.0" - } - }, - "can-log": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/can-log/-/can-log-1.0.0.tgz", - "integrity": "sha512-5W1zw0jxwVnzRKJJtV6jtxWgobl80rhSVMX0aMQS7QB5GyYL+xbE+3IpARugWlOEutEKmWGXlOkD3LdCL/zyAg==", - "dev": true - }, - "can-memory-store": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/can-memory-store/-/can-memory-store-1.0.1.tgz", - "integrity": "sha512-gcYMMsmooBolL1RUmuNU8T4wLMXVcakdJJWGM4uj7DgJlRbnPTG/2gq/KOYdxOnzrU8OKDyWbtfNxOsFMIMm1Q==", - "dev": true, - "requires": { - "can-diff": "<2.0.0", - "can-namespace": "^1.0.0", - "can-query-logic": "<2.0.0", - "can-reflect": "^1.13.4", - "can-sort-object": "^1.0.1" - } - }, - "can-namespace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/can-namespace/-/can-namespace-1.0.0.tgz", - "integrity": "sha1-C4+vr7sRNSuerUIi/+OCJAW0Ppk=", - "dev": true - }, - "can-query-logic": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/can-query-logic/-/can-query-logic-1.1.8.tgz", - "integrity": "sha512-4nwm/EJq29BDNvS+Rq/c1X5ixHXB+8dFQvSafPx1w3m0v1NGdAHg6wP2RJ/erjv61a8aVvF1FOi850V9PIcH0g==", - "dev": true, - "requires": { - "can-assign": "^1.1.1", - "can-define-lazy-value": "^1.0.2", - "can-key": "<2.0.0", - "can-log": "^1.0.0", - "can-reflect": "^1.14.1", - "can-symbol": "^1.6.1" - } - }, - "can-queues": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/can-queues/-/can-queues-1.2.1.tgz", - "integrity": "sha512-xDUwu+hXFHCcb1XHlkVVGcHs3mvmtQkvQhkBFg6NvosZk2DxEmA2YuPor14K9RFADI9GYgzY7JnSkilTZcVHZw==", - "dev": true, - "requires": { - "can-assign": "^1.0.1", - "can-log": "^1.0.0", - "can-namespace": "^1.0.0" - } - }, - "can-reflect": { - "version": "1.17.9", - "resolved": "https://registry.npmjs.org/can-reflect/-/can-reflect-1.17.9.tgz", - "integrity": "sha512-BH8rKaQKK8Rj/1xnyKgj1zITLk3AVyDWZ9nR+aELDP19I0rbMS6w2Yeeo/yisWZUbsKS4moZRGDQi58Oo01Z4A==", - "dev": true, - "requires": { - "can-namespace": "^1.0.0", - "can-symbol": "^1.6.4" - } - }, - "can-sort-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/can-sort-object/-/can-sort-object-1.0.1.tgz", - "integrity": "sha512-45x5sLl2ZaqDQsaJBd8Ge9xY9m2B37bE818+RfncWs5czTSRojmIybvUUCC1tBjW9wGpJrrDbESlJdlTJHqOEA==", - "dev": true, - "requires": { - "can-reflect": "^1.13.4" - } - }, - "can-symbol": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/can-symbol/-/can-symbol-1.6.4.tgz", - "integrity": "sha512-fHRzqcjqZLTvdYoEzdEI/oXG4B7u21+TsYdSTOIB+I8ANe3khqLIhH5cpEa91NMFLDZK/d6TVoXIxevAkqBMDQ==", - "dev": true, - "requires": { - "can-namespace": "^1.0.0" - } - }, - "caniuse-api": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", - "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", - "dev": true, - "requires": { - "browserslist": "^1.3.6", - "caniuse-db": "^1.0.30000529", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - }, - "dependencies": { - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, - "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" - } - } - } - }, - "caniuse-db": { - "version": "1.0.30000951", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000951.tgz", - "integrity": "sha512-Nb8bgexT3HDxPMFOLcT5kol/dHsXpPiiFLU079+msbSBTsq9zZaCpzqDb122+9B9woZnTG5Z8lt+3adIaxKj2A==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30000951", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000951.tgz", - "integrity": "sha512-eRhP+nQ6YUkIcNQ6hnvdhMkdc7n3zadog0KXNRxAZTT2kHjUb1yGn71OrPhSn8MOvlX97g5CR97kGVj8fMsXWg==", - "dev": true - }, - "capture-stack-trace": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", - "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "optional": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, - "chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } - }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", - "dev": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - } - }, - "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" - } - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "optional": true, - "requires": { - "anymatch": "^1.3.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" - } - }, - "chownr": { - "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": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", - "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, - "clap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", - "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", - "dev": true, - "requires": { - "chalk": "^1.1.3" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.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" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", - "dev": true, - "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==", - "dev": true - } - } - }, - "cli-boxes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", - "dev": true - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "clipboard": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz", - "integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==", - "dev": true, - "optional": true, - "requires": { - "good-listener": "^1.2.2", - "select": "^1.1.2", - "tiny-emitter": "^2.0.0" - } - }, - "clipboardy": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-1.2.3.tgz", - "integrity": "sha512-2WNImOvCRe6r63Gk9pShfkwXsVtKCroMAevIbiae021mS850UkWPbevxsBz3tnvjZIEGvlwaqCPsw+4ulzNgJA==", - "dev": true, - "requires": { - "arch": "^2.1.0", - "execa": "^0.8.0" - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "optional": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true, - "optional": true - } - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-deep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-1.0.0.tgz", - "integrity": "sha512-hmJRX8x1QOJVV+GUjOBzi6iauhPqc9hIF6xitWRBbiPZOBb6vGo/mDRIK9P74RTKSQK7AE8B0DDWY/vpRrPmQw==", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "is-plain-object": "^2.0.4", - "kind-of": "^5.0.0", - "shallow-clone": "^1.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "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 - } - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "coa": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", - "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", - "dev": true, - "requires": { - "q": "^1.1.2" - } - }, - "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", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", - "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", - "dev": true, - "requires": { - "clone": "^1.0.2", - "color-convert": "^1.3.0", - "color-string": "^0.3.0" - } - }, - "color-convert": { - "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.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-string": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", - "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", - "dev": true, - "requires": { - "color-name": "^1.0.0" - } - }, - "colormin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", - "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", - "dev": true, - "requires": { - "color": "^0.11.0", - "css-color-names": "0.0.4", - "has": "^1.0.1" - } - }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true - }, - "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true - }, - "common-tags": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", - "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", - "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 - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "configstore": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", - "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", - "dev": true, - "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", - "dev": true - }, - "connect-injector": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/connect-injector/-/connect-injector-0.4.4.tgz", - "integrity": "sha1-qBlZwx7PXKoPPcwyXCjtkLgwqpA=", - "dev": true, - "requires": { - "debug": "^2.0.0", - "q": "^1.0.1", - "stream-buffers": "^0.2.3", - "uberproto": "^1.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" - } - } - } - }, - "consola": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/consola/-/consola-1.4.5.tgz", - "integrity": "sha512-movqq3MbyXbSf7cG/x+EbO3VjKQVZPB/zeB5+lN1TuBYh9BWDemLQca9P+a4xpO4lXva9rz+Bd8XyqlH136Lww==", - "dev": true, - "requires": { - "chalk": "^2.3.2", - "figures": "^2.0.0", - "lodash": "^4.17.5", - "std-env": "^1.1.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" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } - }, - "consolidate": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", - "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", - "dev": true, - "requires": { - "bluebird": "^3.1.1" - } - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "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 - }, - "convert-source-map": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", - "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 - }, - "cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", - "dev": true - }, - "cookies": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.3.tgz", - "integrity": "sha512-+gixgxYSgQLTaTIilDHAdlNPZDENDQernEMiIcZpYYP14zgHsCt4Ce1FEjFtcp6GefhozebB6orvhAAWx/IS0A==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "keygrip": "~1.0.3" - } - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "copy-webpack-plugin": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz", - "integrity": "sha512-Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==", - "dev": true, - "requires": { - "cacache": "^10.0.4", - "find-cache-dir": "^1.0.0", - "globby": "^7.1.1", - "is-glob": "^4.0.0", - "loader-utils": "^1.1.0", - "minimatch": "^3.0.4", - "p-limit": "^1.0.0", - "serialize-javascript": "^1.4.0" - }, - "dependencies": { - "globby": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", - "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "dir-glob": "^2.0.0", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - } - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "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=", - "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" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "core-js": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz", - "integrity": "sha1-VpwFCRi+ZIazg3VSAorgRmtxcIY=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cosmiconfig": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz", - "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==", - "dev": true, - "requires": { - "is-directory": "^0.3.1", - "js-yaml": "^3.9.0", - "parse-json": "^4.0.0", - "require-from-string": "^2.0.1" - }, - "dependencies": { - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - } - } - }, - "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.0.0" - } - }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "dev": true, - "requires": { - "capture-stack-trace": "^1.0.0" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "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" - }, - "dependencies": { - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true - } - } - }, - "crypto-browserify": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz", - "integrity": "sha512-Na7ZlwCOqoaW5RwUK1WpXws2kv8mNhWdTlzob0UXulk6G9BDbyiJaGTYBIX61Ozn9l1EPPJpICZb4DaOpT9NlQ==", - "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", - "dev": true - }, - "css-color-names": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", - "dev": true - }, - "css-loader": { - "version": "0.28.11", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz", - "integrity": "sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg==", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "css-selector-tokenizer": "^0.7.0", - "cssnano": "^3.10.0", - "icss-utils": "^2.1.0", - "loader-utils": "^1.0.2", - "lodash.camelcase": "^4.3.0", - "object-assign": "^4.1.1", - "postcss": "^5.0.6", - "postcss-modules-extract-imports": "^1.2.0", - "postcss-modules-local-by-default": "^1.2.0", - "postcss-modules-scope": "^1.1.0", - "postcss-modules-values": "^1.3.0", - "postcss-value-parser": "^3.3.0", - "source-list-map": "^2.0.0" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "css-parse": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz", - "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=", - "dev": true - }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dev": true, - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" - } - }, - "css-selector-tokenizer": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz", - "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==", - "dev": true, - "requires": { - "cssesc": "^0.1.0", - "fastparse": "^1.1.1", - "regexpu-core": "^1.0.0" - }, - "dependencies": { - "regexpu-core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", - "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - } - } - }, - "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", - "dev": true - }, - "cssesc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", - "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", - "dev": true - }, - "cssnano": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", - "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", - "dev": true, - "requires": { - "autoprefixer": "^6.3.1", - "decamelize": "^1.1.2", - "defined": "^1.0.0", - "has": "^1.0.1", - "object-assign": "^4.0.1", - "postcss": "^5.0.14", - "postcss-calc": "^5.2.0", - "postcss-colormin": "^2.1.8", - "postcss-convert-values": "^2.3.4", - "postcss-discard-comments": "^2.0.4", - "postcss-discard-duplicates": "^2.0.1", - "postcss-discard-empty": "^2.0.1", - "postcss-discard-overridden": "^0.1.1", - "postcss-discard-unused": "^2.2.1", - "postcss-filter-plugins": "^2.0.0", - "postcss-merge-idents": "^2.1.5", - "postcss-merge-longhand": "^2.0.1", - "postcss-merge-rules": "^2.0.3", - "postcss-minify-font-values": "^1.0.2", - "postcss-minify-gradients": "^1.0.1", - "postcss-minify-params": "^1.0.4", - "postcss-minify-selectors": "^2.0.4", - "postcss-normalize-charset": "^1.1.0", - "postcss-normalize-url": "^3.0.7", - "postcss-ordered-values": "^2.1.0", - "postcss-reduce-idents": "^2.2.2", - "postcss-reduce-initial": "^1.0.0", - "postcss-reduce-transforms": "^1.0.3", - "postcss-svgo": "^2.1.1", - "postcss-unique-selectors": "^2.0.2", - "postcss-value-parser": "^3.2.3", - "postcss-zindex": "^2.0.1" - }, - "dependencies": { - "autoprefixer": { - "version": "6.7.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", - "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", - "dev": true, - "requires": { - "browserslist": "^1.7.6", - "caniuse-db": "^1.0.30000634", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^5.2.16", - "postcss-value-parser": "^3.2.3" - } - }, - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, - "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" - } - }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "csso": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", - "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", - "dev": true, - "requires": { - "clap": "^1.0.9", - "source-map": "^0.5.3" - } - }, - "cssom": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", - "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==", - "dev": true - }, - "cssstyle": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.1.tgz", - "integrity": "sha512-7DYm8qe+gPx/h77QlCyFmX80+fGaE/6A/Ekl0zaszYOubvySO2saYFdQ78P29D0UsULxFKCetDGNaNRUdSF+2A==", - "dev": true, - "requires": { - "cssom": "0.3.x" - } - }, - "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 - }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "^0.10.9" - } - }, - "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" - } - }, - "data-urls": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", - "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", - "dev": true, - "requires": { - "abab": "^2.0.0", - "whatwg-mimetype": "^2.2.0", - "whatwg-url": "^7.0.0" - } - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, - "de-indent": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", - "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", - "dev": true - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, - "debug-log": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", - "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", - "dev": true - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "dev": true, - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "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-diff": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-1.0.2.tgz", - "integrity": "sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg==" - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-equal": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.0.0.tgz", - "integrity": "sha1-mWedO70EcVb81FDT0B7rkGhpHoM=", - "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 - }, - "deepmerge": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", - "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==", - "dev": true - }, - "default-require-extensions": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", - "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", - "dev": true, - "requires": { - "strip-bom": "^2.0.0" - } - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "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" - } - }, - "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 - } - } - }, - "defined": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", - "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=", - "dev": true - }, - "deglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.1.tgz", - "integrity": "sha512-2kjwuGGonL7gWE1XU4Fv79+vVzpoQCl0V+boMwWtOQJV2AGDabCwez++nB1Nli/8BabAfZQ/UuHPlp6AymKdWw==", - "dev": true, - "requires": { - "find-root": "^1.0.0", - "glob": "^7.0.5", - "ignore": "^3.0.9", - "pkg-config": "^1.1.0", - "run-parallel": "^1.1.2", - "uniq": "^1.0.1" - }, - "dependencies": { - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - } - } - }, - "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 - }, - "delegate": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "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", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "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 - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "diacritics": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/diacritics/-/diacritics-1.3.0.tgz", - "integrity": "sha1-PvqHMj67hj5mls67AILUj/PW96E=", - "dev": true - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", - "dev": true, - "requires": { - "path-type": "^3.0.0" - }, - "dependencies": { - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "docsearch.js": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/docsearch.js/-/docsearch.js-2.6.2.tgz", - "integrity": "sha512-qyQ+raZlHSkfdpFg8wJNhjiz9WsjdQkRGe2LiiKS6vIIsouNNole2Kg/9UvGoUIK9PLLl31uL3I4YDwnrXt5yQ==", - "dev": true, - "requires": { - "algoliasearch": "^3.24.5", - "autocomplete.js": "0.33.0", - "hogan.js": "^3.0.2", - "request": "^2.87.0", - "stack-utils": "^1.0.1", - "to-factory": "^1.0.0", - "zepto": "^1.2.0" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dev": true, - "requires": { - "utila": "~0.4" - } - }, - "dom-event-types": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dom-event-types/-/dom-event-types-1.0.0.tgz", - "integrity": "sha512-2G2Vwi2zXTHBGqXHsJ4+ak/iP0N8Ar+G8a7LiD2oup5o4sQWytwqqrZu/O6hIMV0KMID2PL69OhpshLO0n7UJQ==", - "dev": true - }, - "dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "dev": true, - "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" - } - }, - "dom-walk": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", - "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=", - "dev": true - }, - "domain-browser": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", - "dev": true - }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true - }, - "domexception": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", - "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", - "dev": true, - "requires": { - "webidl-conversions": "^4.0.2" - } - }, - "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "dev": true, - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "dot-prop": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "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, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "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-to-chromium": { - "version": "1.3.119", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.119.tgz", - "integrity": "sha512-3mtqcAWa4HgG+Djh/oNXlPH0cOH6MmtwxN1nHSaReb9P0Vn51qYPqYwLeoSuAX9loU1wrOBhFbiX3CkeIxPfgg==", - "dev": true - }, - "elliptic": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "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", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "engine.io": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.3.2.tgz", - "integrity": "sha512-AsaA9KG7cWPXWHp5FvHdDWY3AMWeZ8x+2pUVLcn71qE5AtAzgGbxuclOytygskw8XGmiQafTmnI9Bix3uihu2w==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~6.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" - } - } - } - }, - "engine.io-client": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.1.tgz", - "integrity": "sha512-q66JBFuQcy7CSlfAz9L3jH+v7DTT3i6ZEadYcVj2pOs8/0uJHLxKX3WBkGTvULJMdz0tUCyJag0aKT/dpXL9BQ==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "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" - } - } - } - }, - "engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", - "tapable": "^1.0.0" - } - }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", - "dev": true - }, - "envify": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/envify/-/envify-4.1.0.tgz", - "integrity": "sha512-IKRVVoAYr4pIx4yIWNsz9mOsboxlNXiu7TNBnem/K/uTHdkyzXWDzHCK7UTolqBbgaBz0tQHsD3YNls0uIIjiw==", - "dev": true, - "requires": { - "esprima": "^4.0.0", - "through": "~2.3.4" - } - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "error-inject": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/error-inject/-/error-inject-1.0.0.tgz", - "integrity": "sha1-4rPZG1Su1nLzCdlQ0VSFD6EdTzc=", - "dev": true - }, - "es-abstract": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.0", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-keys": "^1.0.12" - } - }, - "es-to-primitive": { - "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.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.49", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.49.tgz", - "integrity": "sha512-3NMEhi57E31qdzmYp2jwRArIUsj1HI/RxbQ4bgnSB+AIKIxsAmTiK83bYMifIcpWvEc3P1X30DhUKOqEtF/kvg==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "^1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-object-assign": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", - "integrity": "sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw=", - "dev": true - }, - "es6-promise": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", - "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==", - "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" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" - }, - "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - }, - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "eslint": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", - "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.9.1", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^4.0.3", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^5.0.1", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.7.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^6.2.2", - "js-yaml": "^3.13.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.11", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^5.5.1", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0" - }, - "dependencies": { - "ajv": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", - "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", - "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" - } - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "import-fresh": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz", - "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.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", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "dev": true - }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "table": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/table/-/table-5.2.3.tgz", - "integrity": "sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ==", - "dev": true, - "requires": { - "ajv": "^6.9.1", - "lodash": "^4.17.11", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - } - } - } - }, - "eslint-config-prettier": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-4.1.0.tgz", - "integrity": "sha512-zILwX9/Ocz4SV2vX7ox85AsrAgXV3f2o2gpIicdMIOra48WYqgUnWNH/cR/iHtmD2Vb3dLSC3LiEJnS05Gkw7w==", - "dev": true, - "requires": { - "get-stdin": "^6.0.0" - } - }, - "eslint-config-standard": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz", - "integrity": "sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ==", - "dev": true - }, - "eslint-config-standard-jsx": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-6.0.2.tgz", - "integrity": "sha512-D+YWAoXw+2GIdbMBRAzWwr1ZtvnSf4n4yL0gKGg7ShUOGXkSOLerI17K4F6LdQMJPNMoWYqepzQD/fKY+tXNSg==", - "dev": true - }, - "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", - "dev": true, - "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" - } - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "resolve": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", - "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } - } - }, - "eslint-module-utils": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", - "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", - "dev": true, - "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" - } - } - } - }, - "eslint-plugin-es": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz", - "integrity": "sha512-XfFmgFdIUDgvaRAlaXUkxrRg5JSADoRC8IkKLc/cISeR3yHVMefFHQZpcyXXEUUPHfy5DwviBcrfqlyqEwlQVw==", - "dev": true, - "requires": { - "eslint-utils": "^1.3.0", - "regexpp": "^2.0.1" - } - }, - "eslint-plugin-import": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", - "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", - "dev": true, - "requires": { - "contains-path": "^0.1.0", - "debug": "^2.6.8", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.1", - "eslint-module-utils": "^2.2.0", - "has": "^1.0.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.3", - "read-pkg-up": "^2.0.0", - "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", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, - "resolve": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", - "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } - } - }, - "eslint-plugin-node": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-7.0.1.tgz", - "integrity": "sha512-lfVw3TEqThwq0j2Ba/Ckn2ABdwmL5dkOgAux1rvOk6CO7A6yGyPI2+zIxN6FyNkp1X1X/BSvKOceD6mBWSj4Yw==", - "dev": true, - "requires": { - "eslint-plugin-es": "^1.3.1", - "eslint-utils": "^1.3.1", - "ignore": "^4.0.2", - "minimatch": "^3.0.4", - "resolve": "^1.8.1", - "semver": "^5.5.0" - }, - "dependencies": { - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "resolve": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", - "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true - } - } - }, - "eslint-plugin-prettier": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.1.tgz", - "integrity": "sha512-/PMttrarPAY78PLvV3xfWibMOdMDl57hmlQ2XqFeA37wd+CJ7WSxV7txqjVPHi/AAFKd2lX0ZqfsOc/i5yFCSQ==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0" - } - }, - "eslint-plugin-promise": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz", - "integrity": "sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg==", - "dev": true - }, - "eslint-plugin-react": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz", - "integrity": "sha512-cVVyMadRyW7qsIUh3FHp3u6QHNhOgVrLQYdQEB1bPWBsgbNCHdFAeNMquBMCcZJu59eNthX053L70l7gRt4SCw==", - "dev": true, - "requires": { - "array-includes": "^3.0.3", - "doctrine": "^2.1.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.0.1", - "prop-types": "^15.6.2" - } - }, - "eslint-plugin-standard": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz", - "integrity": "sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA==", - "dev": true - }, - "eslint-plugin-vue": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-5.2.2.tgz", - "integrity": "sha512-CtGWH7IB0DA6BZOwcV9w9q3Ri6Yuo8qMjx05SmOGJ6X6E0Yo3y9E/gQ5tuNxg2dEt30tRnBoFTbvtmW9iEoyHA==", - "dev": true, - "requires": { - "vue-eslint-parser": "^5.0.0" - } - }, - "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "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", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", - "dev": true - }, - "espree": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", - "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", - "dev": true, - "requires": { - "acorn": "^6.0.7", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" - }, - "dependencies": { - "acorn": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", - "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } - }, - "esrecurse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", - "dev": true, - "requires": { - "estraverse": "^4.1.0", - "object-assign": "^4.0.1" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "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 - }, - "eventemitter3": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", - "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", - "dev": true - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "execa": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz", - "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - } - } - }, - "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" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "^2.1.0" - } - }, - "express": { - "version": "4.16.4", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", - "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "array-flatten": "1.1.1", - "body-parser": "1.18.3", - "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.4", - "qs": "6.5.2", - "range-parser": "~1.2.0", - "safe-buffer": "5.1.2", - "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": { - "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" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "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", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "external-editor": { - "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.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "dependencies": { - "iconv-lite": { - "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" - } - } - } - }, - "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" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-copy": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-1.2.4.tgz", - "integrity": "sha512-LCRjn7/wRBxeM//UVnya1eejlpiNTNz7MsAJnQXUSqkJwvzG35inF/GHDbispN0041A/Rhtuk06xS4IA4YNMBg==" - }, - "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 - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-glob": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.6.tgz", - "integrity": "sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w==", - "dev": true, - "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - }, - "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" - } - } - } - }, - "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-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": { - "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" - }, - "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" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fastparse": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", - "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", - "dev": true - }, - "feathers": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/feathers/-/feathers-2.2.4.tgz", - "integrity": "sha512-9IYKbxRKoDuerLCkYmFkQuKOwyB2SMM1kSUswDzlE0AmdzDrcfocVYb87/BsQx2j6hFkdCVFYkXq3+YPSDMT3w==", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "debug": "^3.1.0", - "events": "^1.1.1", - "express": "^4.16.1", - "feathers-commons": "^0.8.7", - "rubberduck": "^1.1.1", - "uberproto": "^1.2.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" - } - }, - "ms": { - "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 - } - } - }, - "feathers-commons": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/feathers-commons/-/feathers-commons-0.8.7.tgz", - "integrity": "sha1-EcbyW1N3RamD6NYVUtfbiTLVN4I=", - "dev": true - }, - "feathers-errors": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/feathers-errors/-/feathers-errors-2.9.2.tgz", - "integrity": "sha512-qwIX97bNW7+1tWVG073+omUA0rCYKJtTtwuzTrrvfrtdr8J8Dk1Fy4iaV9Fa6/YBD5AZu0lsplPE0iu4u/d4GQ==", - "dev": true, - "requires": { - "debug": "^3.0.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" - } - }, - "ms": { - "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 - } - } - }, - "feathers-memory": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/feathers-memory/-/feathers-memory-3.0.2.tgz", - "integrity": "sha512-GlSYSlIgN5BhvGaCi2AMaltteJvmCOoA5u9j1dIwnwWveF4586TLGsUKu1CASisva5DVczDlmIltq+GJpO6D7w==", - "dev": true, - "requires": { - "@feathersjs/adapter-commons": "^2.0.0", - "@feathersjs/commons": "^4.0.0", - "@feathersjs/errors": "^3.3.6", - "sift": "^7.0.1" - } - }, - "feathers-query-filters": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/feathers-query-filters/-/feathers-query-filters-2.1.2.tgz", - "integrity": "sha1-zbGCJNteGcwBQNUoEI4JCNXrBlQ=", - "dev": true, - "requires": { - "feathers-commons": "^0.8.0" - } - }, - "feathers-rest": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/feathers-rest/-/feathers-rest-1.8.1.tgz", - "integrity": "sha512-FYVcBQLGocSdpjxEf+E/9Cb0QAX0S+biqRgB5KAGpoAF51cou9LV0WW1IwqwHzAT67KRyS4dT7fVCrE4kisM2w==", - "dev": true, - "requires": { - "debug": "^3.0.0", - "feathers-commons": "^0.8.0", - "feathers-errors": "^2.0.1", - "qs": "^6.4.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" - } - }, - "ms": { - "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 - } - } - }, - "feathers-socket-commons": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/feathers-socket-commons/-/feathers-socket-commons-2.4.0.tgz", - "integrity": "sha1-Bi79V/mocWZEFFuZOl9ycJlp8eE=", - "dev": true, - "requires": { - "debug": "^2.2.0", - "feathers-commons": "^0.8.0", - "feathers-errors": "^2.2.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" - } - } - } - }, - "feathers-socketio": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/feathers-socketio/-/feathers-socketio-2.0.1.tgz", - "integrity": "sha512-3ByXVr6UGyGN6TPRN+U5IhENYrSgeuADhbKWLG5cq2WvYH9h2N1l3cj7WBVsfRektUgVw/HkGNAoExy8yuknMA==", - "dev": true, - "requires": { - "@types/socket.io": "~1.4.27", - "debug": "^3.0.0", - "feathers-socket-commons": "^2.0.0", - "socket.io": "^2.0.1", - "uberproto": "^1.2.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" - } - }, - "ms": { - "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 - } - } - }, - "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", - "dev": true - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, - "file-loader": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", - "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", - "dev": true, - "requires": { - "loader-utils": "^1.0.2", - "schema-utils": "^0.4.5" - } - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "fileset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", - "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true, - "requires": { - "glob": "^7.0.3", - "minimatch": "^3.0.3" - } - }, - "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" - } - }, - "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" - }, - "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" - } - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true - } - } - }, - "find-cache-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", - "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^2.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - } - } - }, - "find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "dependencies": { - "glob": { - "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", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "flatted": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", - "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", - "dev": true - }, - "flatten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", - "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", - "dev": true - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "follow-redirects": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz", - "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==", - "dev": true, - "requires": { - "debug": "^3.2.6" - }, - "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" - } - }, - "ms": { - "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 - } - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, - "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.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", - "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==", - "dev": true - }, - "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", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "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 - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-readdir-recursive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.0.0.tgz", - "integrity": "sha1-jNF0XItPiinIyuw5JHaSG6GV9WA=", - "dev": true - }, - "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", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz", - "integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.3.0", - "node-pre-gyp": "^0.6.36" - }, - "dependencies": { - "abbrev": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "ajv": { - "version": "4.11.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "asn1": { - "version": "0.2.3", - "bundled": true, - "dev": true, - "optional": true - }, - "assert-plus": { - "version": "0.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "asynckit": { - "version": "0.4.0", - "bundled": true, - "dev": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "aws4": { - "version": "1.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "balanced-match": { - "version": "0.4.2", - "bundled": true, - "dev": true, - "optional": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "block-stream": { - "version": "0.0.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "inherits": "~2.0.0" - } - }, - "boom": { - "version": "2.10.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "hoek": "2.x.x" - } - }, - "brace-expansion": { - "version": "1.1.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^0.4.1", - "concat-map": "0.0.1" - } - }, - "buffer-shims": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true - }, - "co": { - "version": "4.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "combined-stream": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "cryptiles": { - "version": "2.0.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "boom": "2.x.x" - } - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "^1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "debug": { - "version": "2.6.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.4.2", - "bundled": true, - "dev": true, - "optional": true - }, - "delayed-stream": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "ecc-jsbn": { - "version": "0.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsbn": "~0.1.0" - } - }, - "extend": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "extsprintf": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true, - "dev": true, - "optional": true - }, - "form-data": { - "version": "2.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.12" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "fstream": { - "version": "1.0.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fstream": "^1.0.0", - "inherits": "2", - "minimatch": "^3.0.0" - } - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "^1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "optional": 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" - } - }, - "graceful-fs": { - "version": "4.1.11", - "bundled": true, - "dev": true, - "optional": true - }, - "har-schema": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "har-validator": { - "version": "4.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ajv": "^4.9.1", - "har-schema": "^1.0.5" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "hawk": { - "version": "3.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "boom": "2.x.x", - "cryptiles": "2.x.x", - "hoek": "2.x.x", - "sntp": "1.x.x" - } - }, - "hoek": { - "version": "2.16.3", - "bundled": true, - "dev": true, - "optional": true - }, - "http-signature": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.4", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "jodid25519": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsbn": "~0.1.0" - } - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true, - "dev": true, - "optional": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsonify": "~0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "jsonify": { - "version": "0.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "jsprim": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "mime-db": { - "version": "1.27.0", - "bundled": true, - "dev": true, - "optional": true - }, - "mime-types": { - "version": "2.1.15", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "mime-db": "~1.27.0" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "node-pre-gyp": { - "version": "0.6.36", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "mkdirp": "^0.5.1", - "nopt": "^4.0.1", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "request": "^2.81.0", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^2.2.1", - "tar-pack": "^3.4.0" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npmlog": { - "version": "4.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "oauth-sign": { - "version": "0.8.2", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "performance-now": { - "version": "0.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "1.0.7", - "bundled": true, - "dev": true, - "optional": true - }, - "punycode": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true - }, - "qs": { - "version": "6.4.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "~0.4.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.2.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "buffer-shims": "~1.0.0", - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "string_decoder": "~1.0.0", - "util-deprecate": "~1.0.1" - } - }, - "request": { - "version": "2.81.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.1.1", - "har-validator": "~4.2.1", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "oauth-sign": "~0.8.1", - "performance-now": "^0.2.0", - "qs": "~6.4.0", - "safe-buffer": "^5.0.1", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.0.0" - } - }, - "rimraf": { - "version": "2.6.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.0.5" - } - }, - "safe-buffer": { - "version": "5.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.3.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sntp": { - "version": "1.0.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "hoek": "2.x.x" - } - }, - "sshpk": { - "version": "1.13.0", - "bundled": true, - "dev": true, - "optional": 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", - "jodid25519": "^1.0.0", - "jsbn": "~0.1.0", - "tweetnacl": "~0.14.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "stringstream": { - "version": "0.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.2", - "inherits": "2" - } - }, - "tar-pack": { - "version": "3.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^2.2.0", - "fstream": "^1.0.10", - "fstream-ignore": "^1.0.5", - "once": "^1.3.3", - "readable-stream": "^2.1.4", - "rimraf": "^2.5.1", - "tar": "^2.2.1", - "uid-number": "^0.0.6" - } - }, - "tough-cookie": { - "version": "2.3.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "punycode": "^1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "dev": true, - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "uuid": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "verror": { - "version": "1.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "extsprintf": "1.0.2" - } - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "fstream": { - "version": "0.1.31", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", - "integrity": "sha1-czfwWPu7vvqMn1YaKMqwhJICyYg=", - "dev": true, - "requires": { - "graceful-fs": "~3.0.2", - "inherits": "~2.0.0", - "mkdirp": "0.5", - "rimraf": "2" - }, - "dependencies": { - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "^1.1.0" - } - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "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-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true - }, - "get-own-enumerable-property-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz", - "integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==", - "dev": true - }, - "get-port": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", - "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", - "dev": true - }, - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "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==", - "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" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - } - }, - "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" - } - }, - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", - "dev": true - }, - "global": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "dev": true, - "requires": { - "min-document": "^2.19.0", - "process": "~0.5.1" - }, - "dependencies": { - "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", - "dev": true - } - } - }, - "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", - "dev": true, - "requires": { - "ini": "^1.3.4" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "globby": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", - "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "dir-glob": "2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - }, - "dependencies": { - "dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "path-type": "^3.0.0" - } - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "good-listener": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", - "dev": true, - "optional": true, - "requires": { - "delegate": "^3.1.2" - } - }, - "got": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", - "dev": true, - "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "gray-matter": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.2.tgz", - "integrity": "sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw==", - "dev": true, - "requires": { - "js-yaml": "^3.11.0", - "kind-of": "^6.0.2", - "section-matter": "^1.0.0", - "strip-bom-string": "^1.0.0" - }, - "dependencies": { - "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 - } - } - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "handlebars": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", - "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", - "dev": true, - "requires": { - "async": "^1.4.0", - "optimist": "^0.6.1", - "source-map": "^0.4.4", - "uglify-js": "^2.6" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "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.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "dev": true, - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "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-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "dev": true, - "requires": { - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", - "dev": true - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "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", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "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": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "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", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "hash-sum": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", - "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", - "dev": true - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", - "dev": true - }, - "hogan.js": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", - "integrity": "sha1-TNnhq9QpQUbnZ55B14mHMrAse/0=", - "dev": true, - "requires": { - "mkdirp": "0.3.0", - "nopt": "1.0.10" - }, - "dependencies": { - "mkdirp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", - "dev": true - }, - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", - "dev": true, - "requires": { - "abbrev": "1" - } - } - } - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - } - }, - "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", - "dev": true - }, - "html-comment-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", - "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", - "dev": true - }, - "html-encoding-sniffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", - "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.1" - } - }, - "html-minifier": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", - "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", - "dev": true, - "requires": { - "camel-case": "3.0.x", - "clean-css": "4.2.x", - "commander": "2.17.x", - "he": "1.2.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "3.4.x" - }, - "dependencies": { - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "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-js": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", - "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", - "dev": true, - "requires": { - "commander": "~2.19.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - } - } - } - } - }, - "htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "dev": true, - "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.2.0.tgz", - "integrity": "sha512-RV20kLjdmpZuTF1INEb9IA3L68Nmi+Ri7ppZqo78wj//Pn62fCoJyV9zalccNzDD/OuJpMG4f+pfMl8+L6QdGw==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", - "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "http-assert": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.0.tgz", - "integrity": "sha512-tPVv62a6l3BbQoM/N5qo969l0OFxqpnQzNUPeYfTP6Spo4zkgWeDBD1D5thI7sDLg7jCCihXTLB0X8UtdyAy8A==", - "dev": true, - "requires": { - "deep-equal": "~1.0.1", - "http-errors": "~1.7.1" - }, - "dependencies": { - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - } - } - }, - "http-browserify": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-1.7.0.tgz", - "integrity": "sha1-M3la3nLfiKz7/TZ3PO/tp2RzWyA=", - "dev": true, - "requires": { - "Base64": "~0.2.0", - "inherits": "~2.0.1" - } - }, - "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-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true, - "requires": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "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" - } - }, - "ms": { - "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 - } - } - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", - "dev": true - }, - "icss-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", - "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", - "dev": true, - "requires": { - "postcss": "^6.0.1" - } - }, - "ieee754": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", - "dev": true - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, - "ignore": { - "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 - }, - "immediate": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", - "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=", - "dev": true - }, - "import-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", - "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", - "dev": true, - "requires": { - "import-from": "^2.1.0" - } - }, - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "dev": true, - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - }, - "dependencies": { - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "dev": true, - "requires": { - "caller-callsite": "^2.0.0" - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } - } - }, - "import-from": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", - "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } - } - }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true - }, - "import-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", - "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", - "dev": true, - "requires": { - "pkg-dir": "^2.0.0", - "resolve-cwd": "^2.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true - }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "inflection": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "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": "6.2.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.2.tgz", - "integrity": "sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA==", - "dev": true, - "requires": { - "ansi-escapes": "^3.2.0", - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.11", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - } - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "interpret": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", - "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", - "dev": true - }, - "invariant": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", - "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "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-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", - "dev": true - }, - "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" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", - "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", - "dev": true - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } - }, - "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } - }, - "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" - } - }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, - "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" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "^2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "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-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": "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" - } - }, - "is-generator-function": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz", - "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==", - "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" - } - }, - "is-installed-globally": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", - "dev": true, - "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" - } - }, - "is-npm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", - "dev": true - }, - "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" - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "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": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", - "dev": true - }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "requires": { - "has": "^1.0.1" - } - }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", - "dev": true - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-svg": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", - "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", - "dev": true, - "requires": { - "html-comment-regex": "^1.1.0" - } - }, - "is-symbol": { - "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-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 - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isemail": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", - "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", - "dev": true, - "requires": { - "punycode": "2.x.x" - } - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "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" - } - }, - "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 - }, - "istanbul": { - "version": "1.1.0-alpha.1", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-1.1.0-alpha.1.tgz", - "integrity": "sha1-eBeVZWAYohdMX2DzZ+5dNhy1e3c=", - "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "istanbul-api": "^1.1.0-alpha", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - } - }, - "istanbul-api": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", - "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", - "dev": true, - "requires": { - "async": "^2.1.4", - "fileset": "^2.0.2", - "istanbul-lib-coverage": "^1.2.1", - "istanbul-lib-hook": "^1.2.2", - "istanbul-lib-instrument": "^1.10.2", - "istanbul-lib-report": "^1.1.5", - "istanbul-lib-source-maps": "^1.2.6", - "istanbul-reports": "^1.5.1", - "js-yaml": "^3.7.0", - "mkdirp": "^0.5.1", - "once": "^1.4.0" - }, - "dependencies": { - "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, - "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" - } - }, - "istanbul-lib-coverage": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", - "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", - "dev": true - }, - "istanbul-lib-hook": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", - "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", - "dev": true, - "requires": { - "append-transform": "^0.4.0" - } - }, - "istanbul-lib-report": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", - "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^1.2.1", - "mkdirp": "^0.5.1", - "path-parse": "^1.0.5", - "supports-color": "^3.1.2" - } - }, - "istanbul-lib-source-maps": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", - "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "istanbul-lib-coverage": "^1.2.1", - "mkdirp": "^0.5.1", - "rimraf": "^2.6.1", - "source-map": "^0.5.3" - } - }, - "istanbul-reports": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", - "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", - "dev": true, - "requires": { - "handlebars": "^4.0.3" - } - }, - "ms": { - "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 - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "istanbul-lib-instrument": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", - "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true, - "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.1", - "semver": "^5.3.0" - }, - "dependencies": { - "istanbul-lib-coverage": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", - "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", - "dev": true - } - } - }, - "javascript-stringify": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-1.6.0.tgz", - "integrity": "sha1-FC0RHzpuPa6PSpr9d9RYVbWpzOM=", - "dev": true - }, - "joi": { - "version": "11.4.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-11.4.0.tgz", - "integrity": "sha512-O7Uw+w/zEWgbL6OcHbyACKSj0PkQeUgmehdoXVSxt92QFCq4+1390Rwh5moI2K/OgC7D8RHRZqHZxT2husMJHA==", - "dev": true, - "requires": { - "hoek": "4.x.x", - "isemail": "3.x.x", - "topo": "2.x.x" - } - }, - "js-base64": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", - "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==", - "dev": true - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz", - "integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "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 - }, - "jsdom": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-14.0.0.tgz", - "integrity": "sha512-/VkyPmdtbwqpJSkwDx3YyJ3U1oawYNB/h5z8vTUZGAzjtu2OHTeFRfnJqyMHsJ5Cyes23trOmvUpM1GfHH1leA==", - "dev": true, - "requires": { - "abab": "^2.0.0", - "acorn": "^6.0.4", - "acorn-globals": "^4.3.0", - "array-equal": "^1.0.0", - "cssom": "^0.3.4", - "cssstyle": "^1.1.1", - "data-urls": "^1.1.0", - "domexception": "^1.0.1", - "escodegen": "^1.11.0", - "html-encoding-sniffer": "^1.0.2", - "nwsapi": "^2.0.9", - "parse5": "5.1.0", - "pn": "^1.1.0", - "request": "^2.88.0", - "request-promise-native": "^1.0.5", - "saxes": "^3.1.5", - "symbol-tree": "^3.2.2", - "tough-cookie": "^2.5.0", - "w3c-hr-time": "^1.0.1", - "w3c-xmlserializer": "^1.0.1", - "webidl-conversions": "^4.0.2", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^7.0.0", - "ws": "^6.1.2", - "xml-name-validator": "^3.0.0" - }, - "dependencies": { - "escodegen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", - "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", - "dev": true, - "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - }, - "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 - }, - "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, - "optional": true - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - } - } - }, - "jsdom-global": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-3.0.2.tgz", - "integrity": "sha1-a9KZwTsMRiay2iwDk81DhdYGrLk=", - "dev": true - }, - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "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.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": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "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", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "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 - }, - "jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "dev": true, - "requires": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - }, - "dependencies": { - "ms": { - "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 - }, - "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", - "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" - } - }, - "jsx-ast-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz", - "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=", - "dev": true, - "requires": { - "array-includes": "^3.0.3" - } - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "jwt-decode": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", - "integrity": "sha1-fYa9VmefWM5qhHBKZX3TkruoGnk=" - }, - "keygrip": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.3.tgz", - "integrity": "sha512-/PpesirAIfaklxUzp4Yb7xBper9MwP6hNRA6BGGUFCgbJ+BM5CKBtsoxinNXkLHAr+GXS1/lSlF2rP7cv5Fl+g==", - "dev": true - }, - "killable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", - "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", - "dev": true - }, - "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" - } - }, - "koa": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/koa/-/koa-2.7.0.tgz", - "integrity": "sha512-7ojD05s2Q+hFudF8tDLZ1CpCdVZw8JQELWSkcfG9bdtoTDzMmkRF6BQBU7JzIzCCOY3xd3tftiy/loHBUYaY2Q==", - "dev": true, - "requires": { - "accepts": "^1.3.5", - "cache-content-type": "^1.0.0", - "content-disposition": "~0.5.2", - "content-type": "^1.0.4", - "cookies": "~0.7.1", - "debug": "~3.1.0", - "delegates": "^1.0.0", - "depd": "^1.1.2", - "destroy": "^1.0.4", - "error-inject": "^1.0.0", - "escape-html": "^1.0.3", - "fresh": "~0.5.2", - "http-assert": "^1.3.0", - "http-errors": "^1.6.3", - "is-generator-function": "^1.0.7", - "koa-compose": "^4.1.0", - "koa-convert": "^1.2.0", - "koa-is-json": "^1.0.0", - "on-finished": "^2.3.0", - "only": "~0.0.2", - "parseurl": "^1.3.2", - "statuses": "^1.5.0", - "type-is": "^1.6.16", - "vary": "^1.1.2" - }, - "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" - } - }, - "koa-compose": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", - "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==", - "dev": true - } - } - }, - "koa-compose": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", - "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", - "dev": true, - "requires": { - "any-promise": "^1.1.0" - } - }, - "koa-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/koa-connect/-/koa-connect-2.0.1.tgz", - "integrity": "sha512-MNaiK5og8aj4I+tx8l+jSW24QX7aaQyZemV821VPY+AOJ8XUbrrAj9AzrpZKDQp5jTmylAZW2sXhTz2+SRqZog==", - "dev": true - }, - "koa-convert": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz", - "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=", - "dev": true, - "requires": { - "co": "^4.6.0", - "koa-compose": "^3.0.0" - } - }, - "koa-is-json": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz", - "integrity": "sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ=", - "dev": true - }, - "koa-mount": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/koa-mount/-/koa-mount-3.0.0.tgz", - "integrity": "sha1-CMqzuD0xRC7Yt+dcVLGr65IuwZc=", - "dev": true, - "requires": { - "debug": "^2.6.1", - "koa-compose": "^3.2.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" - } - } - } - }, - "koa-range": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/koa-range/-/koa-range-0.3.0.tgz", - "integrity": "sha1-NYjjSWRzqDmhvSZNKkKx2FvX/qw=", - "dev": true, - "requires": { - "stream-slice": "^0.1.2" - } - }, - "koa-send": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-4.1.3.tgz", - "integrity": "sha512-3UetMBdaXSiw24qM2Mx5mKmxLKw5ZTPRjACjfhK6Haca55RKm9hr/uHDrkrxhSl5/S1CKI/RivZVIopiatZuTA==", - "dev": true, - "requires": { - "debug": "^2.6.3", - "http-errors": "^1.6.1", - "mz": "^2.6.0", - "resolve-path": "^1.4.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" - } - } - } - }, - "koa-static": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-4.0.3.tgz", - "integrity": "sha512-JGmxTuPWy4bH7bt6gD/OMWkhprawvRmzJSr8TWKmTL4N7+IMv3s0SedeQi5S4ilxM9Bo6ptkCyXj/7wf+VS5tg==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "koa-send": "^4.1.3" - }, - "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" - } - }, - "ms": { - "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 - } - } - }, - "koa-webpack": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/koa-webpack/-/koa-webpack-4.0.0.tgz", - "integrity": "sha512-P+j2TzeZAqFwscd/dlLykk/sxwr6wQ5Tp3FYDhqv1+y9aRIffTPnu2zK+1BhfM+Kyh8bepU1jFR420maE+Vajw==", - "dev": true, - "requires": { - "app-root-path": "^2.0.1", - "merge-options": "^1.0.0", - "webpack-dev-middleware": "^3.0.0", - "webpack-hot-client": "^3.0.0", - "webpack-log": "^1.1.1" - } - }, - "last-call-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", - "dev": true, - "requires": { - "lodash": "^4.17.5", - "webpack-sources": "^1.1.0" - } - }, - "latest-version": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", - "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", - "dev": true, - "requires": { - "package-json": "^4.0.0" - } - }, - "launchpad": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/launchpad/-/launchpad-0.6.0.tgz", - "integrity": "sha1-ahIt6qPL17m+3BPnyN0gqQlRqqM=", - "dev": true, - "requires": { - "async": "^2.0.1", - "browserstack": "^1.2.0", - "debug": "^2.2.0", - "plist": "^2.0.1", - "q": "^1.4.1", - "underscore": "^1.8.3" - }, - "dependencies": { - "async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", - "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, - "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" - } - } - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, - "optional": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "linkify-it": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.1.0.tgz", - "integrity": "sha512-4REs8/062kV2DSHxNfq5183zrqXMl7WP0WzABH9IeJI+NLm429FgE1PDecltYfnOoFDFlZGh2T8PfZn0r+GTRg==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "load-script": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", - "integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ=", - "dev": true - }, - "loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", - "dev": true - }, - "loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "localtunnel": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-1.9.1.tgz", - "integrity": "sha512-HWrhOslklDvxgOGFLxi6fQVnvpl6XdX4sPscfqMZkzi3gtt9V7LKBWYvNUcpHSVvjwCQ6xzXacVvICNbNcyPnQ==", - "dev": true, - "requires": { - "axios": "0.17.1", - "debug": "2.6.9", - "openurl": "1.1.1", - "yargs": "6.6.0" - }, - "dependencies": { - "axios": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", - "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", - "dev": true, - "requires": { - "follow-redirects": "^1.2.5", - "is-buffer": "^1.1.5" - } - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.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" - } - }, - "yargs": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", - "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^4.2.0" - } - } - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true, - "optional": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=", - "dev": true - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=", - "dev": true - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=", - "dev": true - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=", - "dev": true - }, - "lodash.isobject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=" - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "lodash.merge": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", - "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==" - }, - "lodash.omit": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", - "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=" - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", - "dev": true - }, - "lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" - }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true - }, - "lodash.template": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", - "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "dev": true, - "requires": { - "lodash._reinterpolate": "~3.0.0" - } - }, - "lodash.throttle": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=", - "dev": true - }, - "lodash.trim": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/lodash.trim/-/lodash.trim-4.5.1.tgz", - "integrity": "sha1-NkJefukL5KpeJ7zruFt9EepHqlc=" - }, - "lodash.unescape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", - "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - }, - "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" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" - }, - "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 - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - } - } - } - }, - "loglevelnext": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", - "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", - "dev": true, - "requires": { - "es6-symbol": "^3.1.1", - "object.assign": "^4.1.0" - } - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true, - "optional": true - }, - "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true, - "requires": { - "js-tokens": "^3.0.0" - } - }, - "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", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "dev": true - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "make-error": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", - "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", - "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==", - "dev": true - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", - "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "markdown-it": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", - "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "entities": "~1.1.1", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - } - }, - "markdown-it-anchor": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.0.2.tgz", - "integrity": "sha512-AFM/woBI8QDJMS/9+MmsBMT5/AR+ImfOsunQZTZhzcTmna3rIzAzbOh5E0l6mlFM/i9666BpUtkqQ9bS7WApCg==", - "dev": true - }, - "markdown-it-container": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-2.0.0.tgz", - "integrity": "sha1-ABm0P9Au7+zi8ZYKKJX7qBpARpU=", - "dev": true - }, - "markdown-it-emoji": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz", - "integrity": "sha1-m+4OmpkKljupbfaYDE/dsF37Tcw=", - "dev": true - }, - "markdown-it-table-of-contents": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.4.3.tgz", - "integrity": "sha512-x/OdaRzLYxAjmB+jIVlXuE3nX7tZTLDQxm58RkgjTLyQ+I290jYQvPS9cJjVN6SM3U6K6CHKYNgUtPNZmLblYQ==", - "dev": true - }, - "match-stream": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", - "integrity": "sha1-mesFAJOzTf+t5CG5rAtBCpz6F88=", - "dev": true, - "requires": { - "buffers": "~0.1.1", - "readable-stream": "~1.0.0" - }, - "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.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "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 - } - } - }, - "math-expression-evaluator": { - "version": "1.2.17", - "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", - "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", - "dev": true - }, - "math-random": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", - "dev": true - }, - "md5.js": { - "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", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "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", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "meow": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", - "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", - "dev": true, - "requires": { - "camelcase-keys": "^4.0.0", - "decamelize-keys": "^1.0.0", - "loud-rejection": "^1.0.0", - "minimist-options": "^3.0.1", - "normalize-package-data": "^2.3.4", - "read-pkg-up": "^3.0.0", - "redent": "^2.0.0", - "trim-newlines": "^2.0.0", - "yargs-parser": "^10.0.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", - "dev": true, - "requires": { - "camelcase": "^4.1.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 - }, - "merge-options": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz", - "integrity": "sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==", - "dev": true, - "requires": { - "is-plain-obj": "^1.1" - } - }, - "merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "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 - } - } - }, - "merge2": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz", - "integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==", - "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": "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" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - } - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true - }, - "mime-db": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", - "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==", - "dev": true - }, - "mime-types": { - "version": "2.1.22", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", - "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", - "dev": true, - "requires": { - "mime-db": "~1.38.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "dev": true, - "requires": { - "dom-walk": "^0.1.0" - } - }, - "miner": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/miner/-/miner-0.2.1.tgz", - "integrity": "sha1-syJBSPl7Za5ClrUFSYTyJ2BWsSQ=", - "dev": true, - "requires": { - "browserstacktunnel-wrapper": "^1.2.1", - "localtunnel": "^1.2.0" - } - }, - "mini-css-extract-plugin": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.1.tgz", - "integrity": "sha512-XWuB3G61Rtasq/gLe7cp5cuozehE6hN+E4sxCamRR/WDiHTg+f7ZIAS024r8UJQffY+e2gGELXQZgQoFDfNDCg==", - "dev": true, - "requires": { - "@webpack-contrib/schema-utils": "^1.0.0-beta.0", - "loader-utils": "^1.1.0", - "webpack-sources": "^1.1.0" - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "minimist-options": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", - "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0" - } - }, - "mississippi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", - "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^2.0.1", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mixin-object": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", - "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", - "dev": true, - "requires": { - "for-in": "^0.1.3", - "is-extendable": "^0.1.1" - }, - "dependencies": { - "for-in": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", - "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", - "dev": true - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, - "dependencies": { - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "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" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "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" - } - } - } - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nan": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", - "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=", - "dev": true, - "optional": true - }, - "nanoassert": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz", - "integrity": "sha1-TzFS4JVA/eKMdvRLGbvNHVpCR40=", - "dev": true - }, - "nanobus": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/nanobus/-/nanobus-4.4.0.tgz", - "integrity": "sha512-Hv9USGyH8EsPy0o8pPWE7x3YRIfuZDgMBirzjU6XLebhiSK2g53JlfqgolD0c39ne6wXAfaBNcIAvYe22Bav+Q==", - "dev": true, - "requires": { - "nanoassert": "^1.1.0", - "nanotiming": "^7.2.0", - "remove-array-items": "^1.0.0" - } - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "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 - } - } - }, - "nanoscheduler": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/nanoscheduler/-/nanoscheduler-1.0.3.tgz", - "integrity": "sha512-jBbrF3qdU9321r8n9X7yu18DjP31Do2ItJm3mWrt90wJTrnDO+HXpoV7ftaUglAtjgj9s+OaCxGufbvx6pvbEQ==", - "dev": true, - "requires": { - "nanoassert": "^1.1.0" - } - }, - "nanotiming": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/nanotiming/-/nanotiming-7.3.1.tgz", - "integrity": "sha512-l3lC7v/PfOuRWQa8vV29Jo6TG10wHtnthLElFXs4Te4Aas57Fo4n1Q8LH9n+NDh9riOzTVvb2QNBhTS4JUKNjw==", - "dev": true, - "requires": { - "nanoassert": "^1.1.0", - "nanoscheduler": "^1.0.2" - } - }, - "natives": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", - "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "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.6.0", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", - "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dev": true, - "requires": { - "lower-case": "^1.1.1" - } - }, - "node-libs-browser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", - "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.0", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "0.0.4" - }, - "dependencies": { - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", - "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==", - "dev": true - }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "nprogress": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", - "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=", - "dev": true - }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dev": true, - "requires": { - "boolbase": "~1.0.0" - } - }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true - }, - "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 - }, - "nwsapi": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.1.tgz", - "integrity": "sha512-T5GaA1J/d34AC8mkrFD2O0DR17kwJ702ZOtJOsS8RpbsQZVOC2/xYFb1i/cw+xdM54JIlMuojjDOYct8GIWtwg==", - "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", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "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" - } - } - } - }, - "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 - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "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.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "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" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "only": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", - "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=", - "dev": true - }, - "openurl": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/openurl/-/openurl-1.1.1.tgz", - "integrity": "sha1-OHW0sO96UsFW8NtB1GCduw+Us4c=", - "dev": true - }, - "opn": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", - "dev": true, - "requires": { - "is-wsl": "^1.1.0" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, - "optimize-css-assets-webpack-plugin": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-4.0.3.tgz", - "integrity": "sha512-iOfMsuGMPbM/bZZ731gwtAXfXjIkR97BXqUXsPGIzBaQzpvqajsoIFlR+z+Q7FLcq2TmV4JFGo80d98ttfRzhA==", - "dev": true, - "requires": { - "cssnano": "^3.10.0", - "last-call-webpack-plugin": "^3.0.0" - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "output-file-sync": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", - "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.4", - "mkdirp": "^0.5.1", - "object-assign": "^4.1.0" - } - }, - "over": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", - "integrity": "sha1-8phS5w/X4l82DgE6jsRMgq7bVwg=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", - "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", - "dev": true - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", - "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", - "dev": true - }, - "package-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", - "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", - "dev": true, - "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" - } - }, - "pako": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", - "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", - "dev": true - }, - "parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", - "dev": true, - "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "dev": true, - "requires": { - "no-case": "^2.2.0" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-asn1": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", - "dev": true, - "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse5": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", - "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", - "dev": true - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "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", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "passport-jwt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", - "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", - "dev": true, - "requires": { - "jsonwebtoken": "^8.2.0", - "passport-strategy": "^1.0.0" - } - }, - "passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=", - "dev": true - }, - "path": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", - "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", - "dev": true, - "requires": { - "process": "^0.11.1", - "util": "^0.10.3" - } - }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "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": "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" - } - }, - "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true - }, - "pbkdf2": { - "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", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-conf": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", - "integrity": "sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "load-json-file": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "pkg-config": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz", - "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=", - "dev": true, - "requires": { - "debug-log": "^1.0.0", - "find-root": "^1.0.0", - "xtend": "^4.0.1" - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - } - }, - "plist": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-2.1.0.tgz", - "integrity": "sha1-V8zbeggh3yGDEhejytVOPhRqECU=", - "dev": true, - "requires": { - "base64-js": "1.2.0", - "xmlbuilder": "8.2.2", - "xmldom": "0.1.x" - }, - "dependencies": { - "base64-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz", - "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=", - "dev": true - } - } - }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", - "dev": true - }, - "pn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", - "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", - "dev": true - }, - "portfinder": { - "version": "1.0.20", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz", - "integrity": "sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw==", - "dev": true, - "requires": { - "async": "^1.5.2", - "debug": "^2.2.0", - "mkdirp": "0.5.x" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.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" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "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 - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-calc": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", - "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", - "dev": true, - "requires": { - "postcss": "^5.0.2", - "postcss-message-helpers": "^2.0.0", - "reduce-css-calc": "^1.2.6" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-colormin": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", - "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", - "dev": true, - "requires": { - "colormin": "^1.0.5", - "postcss": "^5.0.13", - "postcss-value-parser": "^3.2.3" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-convert-values": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", - "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", - "dev": true, - "requires": { - "postcss": "^5.0.11", - "postcss-value-parser": "^3.1.2" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-comments": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", - "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", - "dev": true, - "requires": { - "postcss": "^5.0.14" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-duplicates": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", - "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-empty": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", - "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", - "dev": true, - "requires": { - "postcss": "^5.0.14" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-overridden": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", - "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", - "dev": true, - "requires": { - "postcss": "^5.0.16" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-discard-unused": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", - "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", - "dev": true, - "requires": { - "postcss": "^5.0.14", - "uniqs": "^2.0.0" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-filter-plugins": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz", - "integrity": "sha512-T53GVFsdinJhgwm7rg1BzbeBRomOg9y5MBVhGcsV0CxurUdVj1UlPdKtn7aqYA/c/QVkzKMjq2bSV5dKG5+AwQ==", - "dev": true, - "requires": { - "postcss": "^5.0.4" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-load-config": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz", - "integrity": "sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ==", - "dev": true, - "requires": { - "cosmiconfig": "^4.0.0", - "import-cwd": "^2.0.0" - } - }, - "postcss-loader": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.1.6.tgz", - "integrity": "sha512-hgiWSc13xVQAq25cVw80CH0l49ZKlAnU1hKPOdRrNj89bokRr/bZF2nT+hebPPF9c9xs8c3gw3Fr2nxtmXYnNg==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "postcss": "^6.0.0", - "postcss-load-config": "^2.0.0", - "schema-utils": "^0.4.0" - } - }, - "postcss-merge-idents": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", - "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.10", - "postcss-value-parser": "^3.1.1" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-merge-longhand": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", - "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-merge-rules": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", - "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", - "dev": true, - "requires": { - "browserslist": "^1.5.2", - "caniuse-api": "^1.5.2", - "postcss": "^5.0.4", - "postcss-selector-parser": "^2.2.2", - "vendors": "^1.0.0" - }, - "dependencies": { - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, - "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" - } - }, - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-message-helpers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", - "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", - "dev": true - }, - "postcss-minify-font-values": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", - "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-minify-gradients": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", - "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", - "dev": true, - "requires": { - "postcss": "^5.0.12", - "postcss-value-parser": "^3.3.0" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-minify-params": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", - "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.2", - "postcss-value-parser": "^3.0.2", - "uniqs": "^2.0.0" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-minify-selectors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", - "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.2", - "has": "^1.0.1", - "postcss": "^5.0.14", - "postcss-selector-parser": "^2.0.0" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-modules-extract-imports": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz", - "integrity": "sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==", - "dev": true, - "requires": { - "postcss": "^6.0.1" - } - }, - "postcss-modules-local-by-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", - "dev": true, - "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - } - }, - "postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", - "dev": true, - "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - } - }, - "postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", - "dev": true, - "requires": { - "icss-replace-symbols": "^1.1.0", - "postcss": "^6.0.1" - } - }, - "postcss-normalize-charset": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", - "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", - "dev": true, - "requires": { - "postcss": "^5.0.5" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-normalize-url": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", - "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", - "dev": true, - "requires": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^1.4.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-ordered-values": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", - "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", - "dev": true, - "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.1" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-reduce-idents": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", - "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", - "dev": true, - "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-reduce-initial": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", - "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", - "dev": true, - "requires": { - "postcss": "^5.0.4" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-reduce-transforms": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", - "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.8", - "postcss-value-parser": "^3.0.1" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "postcss-svgo": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", - "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", - "dev": true, - "requires": { - "is-svg": "^2.0.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3", - "svgo": "^0.7.0" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-unique-selectors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", - "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "postcss-zindex": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", - "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", - "dev": true, - "requires": { - "has": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" - }, - "dependencies": { - "postcss": { - "version": "5.2.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" - } - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "prettier": { - "version": "1.16.4", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz", - "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "pretty-bytes": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", - "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", - "dev": true - }, - "pretty-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", - "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", - "dev": true, - "requires": { - "renderkid": "^2.0.1", - "utila": "~0.4" - } - }, - "pretty-time": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", - "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", - "dev": true - }, - "prismjs": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.15.0.tgz", - "integrity": "sha512-Lf2JrFYx8FanHrjoV5oL8YHCclLQgbJcVZR+gikGGMqz6ub5QVWDTM6YIwm3BuPxM/LOV+rKns3LssXNLIf+DA==", - "dev": true, - "requires": { - "clipboard": "^2.0.0" - } - }, - "private": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", - "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=", - "dev": true - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "prop-types": { - "version": "15.6.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz", - "integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==", - "dev": true, - "requires": { - "loose-envify": "^1.3.1", - "object-assign": "^4.1.1" - } - }, - "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" - } - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.1.31", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", - "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", - "dev": true - }, - "public-encrypt": { - "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", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "pullstream": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", - "integrity": "sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ=", - "dev": true, - "requires": { - "over": ">= 0.0.5 < 1", - "readable-stream": "~1.0.31", - "setimmediate": ">= 1.0.2 < 2", - "slice-stream": ">= 1.0.0 < 2" - }, - "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.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "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 - } - } - }, - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "punycode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.0.1.tgz", - "integrity": "sha1-PxQv2ObvTpziSsv3uoaf+bANLCs=", - "dev": true - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, - "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 - }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, - "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "quick-lru": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", - "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", - "dev": true - }, - "radix-router": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/radix-router/-/radix-router-3.0.1.tgz", - "integrity": "sha512-jpHXHgP+ZmVzEfmZ7WVRSvc/EqMoAqYuMtBsHd9s47Hs9Iy8FDJhkweMrDH0wmdxanLzVIWhq0UpomLXNpW8tg==", - "dev": true - }, - "randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", - "dev": true, - "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "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 - } - } - }, - "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true, - "requires": { - "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.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } - }, - "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": "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" - }, - "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" - } - } - } - }, - "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" - } - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "readable-stream": "^2.0.2", - "set-immediate-shim": "^1.0.1" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "redent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", - "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", - "dev": true, - "requires": { - "indent-string": "^3.0.0", - "strip-indent": "^2.0.0" - } - }, - "reduce": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/reduce/-/reduce-1.0.2.tgz", - "integrity": "sha512-xX7Fxke/oHO5IfZSk77lvPa/7bjMh9BuCk4OOoX5XTXrM7s0Z+MkPfSDfz0q7r91BhhGSs8gii/VEN/7zhCPpQ==", - "dev": true, - "requires": { - "object-keys": "^1.1.0" - }, - "dependencies": { - "object-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", - "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", - "dev": true - } - } - }, - "reduce-css-calc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", - "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2", - "math-expression-evaluator": "^1.2.14", - "reduce-function-call": "^1.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, - "reduce-function-call": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", - "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", - "dev": true, - "requires": { - "balanced-match": "^0.4.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - } - } - }, - "regenerate": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz", - "integrity": "sha1-0ZQcZ7rUN+G+dkM63Vs4X5WxkmA=", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.0.2.tgz", - "integrity": "sha512-SbA/iNrBUf6Pv2zU8Ekv1Qbhv92yxL4hiDa2siuxs4KKn4oOoMDHXjAf7+Nz9qinUQ46B1LcWEi/PhJfPWpZWQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - }, - "dependencies": { - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - } - } - }, - "regenerator-runtime": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", - "dev": true - }, - "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, - "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" - } - }, - "regex-cache": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", - "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", - "dev": true, - "requires": { - "is-equal-shallow": "^0.1.3", - "is-primitive": "^2.0.0" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - }, - "register-service-worker": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/register-service-worker/-/register-service-worker-1.6.2.tgz", - "integrity": "sha512-I8L87fX2TK29LDx+wgyOUh2BJ3rDIRC1FtRZEHeP3rivzDv6p1DDZLGGtPucqjEkm45+2crtFIFssEWv56+9Wg==", - "dev": true - }, - "registry-auth-token": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", - "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", - "dev": true, - "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", - "dev": true, - "requires": { - "rc": "^1.0.1" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true - }, - "remove-array-items": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/remove-array-items/-/remove-array-items-1.1.1.tgz", - "integrity": "sha512-MXW/jtHyl5F1PZI7NbpS8SOtympdLuF20aoWJT5lELR1p/HJDd5nqW8Eu9uLh/hCRY3FgvrIT5AwDCgBODklcA==", - "dev": true - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "renderkid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.3.tgz", - "integrity": "sha512-z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA==", - "dev": true, - "requires": { - "css-select": "^1.1.0", - "dom-converter": "^0.2", - "htmlparser2": "^3.3.0", - "strip-ansi": "^3.0.0", - "utila": "^0.4.0" - } - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "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": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "request-promise-core": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", - "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, - "request-promise-native": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", - "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", - "dev": true, - "requires": { - "request-promise-core": "1.1.2", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - } - } - }, - "requireindex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", - "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", - "dev": true - }, - "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.4.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", - "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } - }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "resolve-path": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz", - "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=", - "dev": true, - "requires": { - "http-errors": "~1.6.2", - "path-is-absolute": "1.0.1" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "optional": true, - "requires": { - "align-text": "^0.1.1" - } - }, - "rimraf": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", - "dev": true, - "requires": { - "glob": "^7.0.5" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "rubberduck": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/rubberduck/-/rubberduck-1.1.1.tgz", - "integrity": "sha1-zSzaS4ZxeBNer8mVpxOE9fdD2wI=", - "dev": true - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } - }, - "run-parallel": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", - "dev": true - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } - }, - "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "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 - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "saxes": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.9.tgz", - "integrity": "sha512-FZeKhJglhJHk7eWG5YM0z46VHmI3KJpMBAQm3xa9meDvd+wevB5GuBB0wc0exPInZiBBHqi00DbS8AcvCGCFMw==", - "dev": true, - "requires": { - "xmlchars": "^1.3.1" - } - }, - "schema-utils": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", - "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" - } - }, - "section-matter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", - "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "kind-of": "^6.0.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" - } - }, - "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 - } - } - }, - "select": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", - "dev": true, - "optional": true - }, - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true - }, - "semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", - "dev": true, - "requires": { - "semver": "^5.0.3" - } - }, - "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" - }, - "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" - } - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true - } - } - }, - "serialize-error": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-3.0.0.tgz", - "integrity": "sha512-+y3nkkG/go1Vdw+2f/+XUXM1DXX1XcxTl99FfiD/OEPUNw4uo0i6FKABfTAN5ZcgGtjTRZcEbxcE/jtXbEY19A==" - }, - "serialize-javascript": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz", - "integrity": "sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==", - "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-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "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, - "optional": true - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^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" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "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", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shallow-clone": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-1.0.0.tgz", - "integrity": "sha512-oeXreoKR/SyNJtRJMAKPDSvd28OqEwG4eR/xc856cRGBII7gX9lvAqDxusPm0846z/w/hWYjI1NpKwJ00NHzRA==", - "dev": true, - "requires": { - "is-extendable": "^0.1.1", - "kind-of": "^5.0.0", - "mixin-object": "^2.0.1" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shx": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.2.tgz", - "integrity": "sha512-aS0mWtW3T2sHAenrSrip2XGv39O9dXIFUqxAEWHEOS1ePtGIBavdPJY1kE2IHl14V/4iCbUiNDPGdyYTtmhSoA==", - "dev": true, - "requires": { - "es6-object-assign": "^1.0.3", - "minimist": "^1.2.0", - "shelljs": "^0.8.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "shelljs": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", - "integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } - } - } - }, - "sift": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz", - "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==" - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, - "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - } - } - }, - "slice-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", - "integrity": "sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA=", - "dev": true, - "requires": { - "readable-stream": "~1.0.31" - }, - "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.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "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 - } - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "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", - "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" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^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" - } - }, - "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" - } - }, - "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 - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - } - }, - "socket.io": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.2.0.tgz", - "integrity": "sha512-wxXrIuZ8AILcn+f1B4ez4hJTPG24iNgxBBDaJfT6MsyOhVYiTXWexGoPkd87ktJG8kQEcL/NBvRi64+9k4Kc0w==", - "dev": true, - "requires": { - "debug": "~4.1.0", - "engine.io": "~3.3.1", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.2.0", - "socket.io-parser": "~3.3.0" - } - }, - "socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", - "dev": true - }, - "socket.io-client": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz", - "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.3.1", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - }, - "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" - } - } - } - }, - "socket.io-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", - "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "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" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } - }, - "source-list-map": { - "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.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.16.tgz", - "integrity": "sha512-A6vlydY7H/ljr4L2UOhDSajQdZQ6dMD7cLH0pzwcmwLyc9u8PNI4WGtnfDDzX7uzGL6c/T+ORL97Zlh+S4iOrg==", - "dev": true, - "requires": { - "source-map": "^0.5.6" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "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": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", - "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "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.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "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", - "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.1" - } - }, - "stack-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", - "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", - "dev": true - }, - "standard": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/standard/-/standard-12.0.1.tgz", - "integrity": "sha512-UqdHjh87OG2gUrNCSM4QRLF5n9h3TFPwrCNyVlkqu31Hej0L/rc8hzKqVvkb2W3x0WMq7PzZdkLfEcBhVOR6lg==", - "dev": true, - "requires": { - "eslint": "~5.4.0", - "eslint-config-standard": "12.0.0", - "eslint-config-standard-jsx": "6.0.2", - "eslint-plugin-import": "~2.14.0", - "eslint-plugin-node": "~7.0.1", - "eslint-plugin-promise": "~4.0.0", - "eslint-plugin-react": "~7.11.1", - "eslint-plugin-standard": "~4.0.0", - "standard-engine": "~9.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 - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, - "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" - } - }, - "eslint": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.4.0.tgz", - "integrity": "sha512-UIpL91XGex3qtL6qwyCQJar2j3osKxK9e3ano3OcGEIRM4oWIpCkDg9x95AXEC2wMs7PnxzOkPZ2gq+tsMS9yg==", - "dev": true, - "requires": { - "ajv": "^6.5.0", - "babel-code-frame": "^6.26.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^4.0.0", - "eslint-utils": "^1.3.1", - "eslint-visitor-keys": "^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.7.0", - "ignore": "^4.0.2", - "imurmurhash": "^0.1.4", - "inquirer": "^5.2.0", - "is-resolvable": "^1.1.0", - "js-yaml": "^3.11.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "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": "^2.0.0", - "require-uncached": "^1.0.3", - "semver": "^5.5.0", - "strip-ansi": "^4.0.0", - "strip-json-comments": "^2.0.1", - "table": "^4.0.3", - "text-table": "^0.2.0" - } - }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "espree": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", - "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", - "dev": true, - "requires": { - "acorn": "^6.0.2", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" - } - }, - "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true, - "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } - }, - "flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", - "dev": true, - "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" - } - }, - "globals": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", - "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "inquirer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", - "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", - "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.1.0", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^5.5.2", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "ms": { - "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 - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "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", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "rxjs": { - "version": "5.5.12", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz", - "integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==", - "dev": true, - "requires": { - "symbol-observable": "1.0.1" - } - }, - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - } - } - }, - "standard-engine": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-9.0.0.tgz", - "integrity": "sha512-ZfNfCWZ2Xq67VNvKMPiVMKHnMdvxYzvZkf1AH8/cw2NLDBm5LRsxMqvEJpsjLI/dUosZ3Z1d6JlHDp5rAvvk2w==", - "dev": true, - "requires": { - "deglob": "^2.1.0", - "get-stdin": "^6.0.0", - "minimist": "^1.1.0", - "pkg-conf": "^2.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "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" - } - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "std-env": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-1.3.1.tgz", - "integrity": "sha512-KI2F2pPJpd3lHjng+QLezu0eq+QDtXcv1um016mhOPAJFHKL+09ykK5PUBWta2pZDC8BVV0VPya08A15bUXSLQ==", - "dev": true, - "requires": { - "is-ci": "^1.1.0" - } - }, - "steal": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/steal/-/steal-2.2.1.tgz", - "integrity": "sha512-3v1ZJ6ucEG6Rb4iY8hOMAMDBeSio1RTLeNpTD5t60JEkzBb95W9SI2Xg0gYg5Q9f7TAHGyioTx+eR9XzrLjmMA==", - "dev": true, - "requires": { - "assert": "~1.4.1", - "buffer": "~5.0.4", - "console-browserify": "~1.1.0", - "constants-browserify": "~1.0.0", - "crypto-browserify": "~3.11.0", - "domain-browser": "~1.1.2", - "events": "~1.1.1", - "http-browserify": "~1.7.0", - "https-browserify": "~1.0.0", - "os-browserify": "~0.3.0", - "path-browserify": "~0.0.0", - "process": "~0.11.9", - "punycode": "~2.0.1", - "resolve": "^1.1.7", - "string_decoder": "~1.0.0", - "tty-browserify": "~0.0.0", - "vm-browserify": "~0.0.4", - "zlib-browserify": "~0.0.3" - } - }, - "steal-css": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/steal-css/-/steal-css-1.3.2.tgz", - "integrity": "sha512-hT3j9+p+qxqu3Jh46zGoB31V/8SKYba/C9sRtGkryKRR8vf582UmLpcbo2s1FysSNZCISbCGi7jl/pZgvdIxbg==", - "dev": true - }, - "steal-mocha": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/steal-mocha/-/steal-mocha-2.0.1.tgz", - "integrity": "sha512-ZDHV68EkG+8pUTMZgSRFVJC5yJmEfDXiA4QoEReuG9V/k6c5d2TDqd/Yzix10ml28fpW+2p4SfayZMFTzeG47g==", - "dev": true, - "requires": { - "mocha": "^5.0.5", - "steal": "^1.11.0", - "steal-css": "^1.3.2" - }, - "dependencies": { - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "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" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - } - }, - "steal": { - "version": "1.12.6", - "resolved": "https://registry.npmjs.org/steal/-/steal-1.12.6.tgz", - "integrity": "sha512-6lhEz7TMtxhaZJlegOWeEDEClrhWRWDgO+erOfLa4hyv//E2KQyG+7MbyxIoNdTHvYkcxLafxY8aeKd7F0hhaw==", - "dev": true, - "requires": { - "assert": "~1.4.1", - "buffer": "~5.0.4", - "console-browserify": "~1.1.0", - "constants-browserify": "~1.0.0", - "crypto-browserify": "~3.11.0", - "domain-browser": "~1.1.2", - "events": "~1.1.1", - "http-browserify": "~1.7.0", - "https-browserify": "~1.0.0", - "os-browserify": "~0.3.0", - "path-browserify": "~0.0.0", - "process": "~0.11.9", - "punycode": "~2.0.1", - "resolve": "^1.1.7", - "string_decoder": "~1.0.0", - "tty-browserify": "~0.0.0", - "vm-browserify": "~0.0.4", - "zlib-browserify": "~0.0.3" - } - }, - "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" - } - } - } - }, - "steal-typescript": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/steal-typescript/-/steal-typescript-0.5.0.tgz", - "integrity": "sha1-XxINuwU2hiVF4hx5KqK3vJsWwNs=", - "requires": { - "object-assign": "^4.1.0", - "typescript": "^2.1.4" - }, - "dependencies": { - "typescript": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", - "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==" - } - } - }, - "stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", - "dev": true - }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-buffers": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-0.2.6.tgz", - "integrity": "sha1-GBwI1bs2kARfaUAbmuanoM8zE/w=", - "dev": true - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "stream-slice": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/stream-slice/-/stream-slice-0.1.2.tgz", - "integrity": "sha1-LcT04bk2+xPz6zmi3vGTJ5jQeks=", - "dev": true - }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true - }, - "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" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dev": true, - "requires": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.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" - } - }, - "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" - } - }, - "strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", - "dev": true - }, - "strip-comments": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-1.0.2.tgz", - "integrity": "sha512-kL97alc47hoyIQSV165tTt9rG5dn4w1dNnBhOQ3bOU1Nc1hel09jnXANaHJ7vzHLd4Ju8kseDGzlev96pghLFw==", - "dev": true, - "requires": { - "babel-extract-comments": "^1.0.0", - "babel-plugin-transform-object-rest-spread": "^6.26.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true - }, - "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 - }, - "stylus": { - "version": "0.54.5", - "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz", - "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=", - "dev": true, - "requires": { - "css-parse": "1.7.x", - "debug": "*", - "glob": "7.0.x", - "mkdirp": "0.5.x", - "sax": "0.5.x", - "source-map": "0.1.x" - }, - "dependencies": { - "glob": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", - "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "sax": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", - "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=", - "dev": true - }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "stylus-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", - "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", - "dev": true, - "requires": { - "loader-utils": "^1.0.2", - "lodash.clonedeep": "^4.5.0", - "when": "~3.6.x" - } - }, - "superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "dev": true, - "requires": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" - }, - "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" - } - }, - "ms": { - "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 - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.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 - }, - "svgo": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", - "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", - "dev": true, - "requires": { - "coa": "~1.0.1", - "colors": "~1.1.2", - "csso": "~2.3.1", - "js-yaml": "~3.7.0", - "mkdirp": "~0.5.1", - "sax": "~1.2.1", - "whet.extend": "~0.9.9" - }, - "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "js-yaml": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", - "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^2.6.0" - } - } - } - }, - "symbol-observable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", - "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", - "dev": true - }, - "symbol-tree": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", - "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", - "dev": true - }, - "table": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", - "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", - "dev": true, - "requires": { - "ajv": "^6.0.1", - "ajv-keywords": "^3.0.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - }, - "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 - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "tapable": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz", - "integrity": "sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==", - "dev": true - }, - "tape": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/tape/-/tape-0.2.2.tgz", - "integrity": "sha1-ZMz6S37PSgBgAH5hcW1CR4FnFjc=", - "dev": true, - "requires": { - "deep-equal": "~0.0.0", - "defined": "~0.0.0", - "jsonify": "~0.0.0" - } - }, - "term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", - "dev": true, - "requires": { - "execa": "^0.7.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - } - } - }, - "terser": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", - "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.10" - }, - "dependencies": { - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "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 - }, - "source-map-support": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.11.tgz", - "integrity": "sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } - } - }, - "terser-webpack-plugin": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz", - "integrity": "sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA==", - "dev": true, - "requires": { - "cacache": "^11.0.2", - "find-cache-dir": "^2.0.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.4.0", - "source-map": "^0.6.1", - "terser": "^3.16.1", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" - }, - "dependencies": { - "cacache": { - "version": "11.3.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", - "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", - "dev": true, - "requires": { - "bluebird": "^3.5.3", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.3", - "graceful-fs": "^4.1.15", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "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" - } - }, - "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "p-limit": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "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 - }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", - "dev": true - } - } - }, - "test-exclude": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.3.tgz", - "integrity": "sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "micromatch": "^2.3.11", - "object-assign": "^4.1.0", - "read-pkg-up": "^1.0.1", - "require-main-filename": "^1.0.1" - } - }, - "testee": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/testee/-/testee-0.9.0.tgz", - "integrity": "sha512-vyP8iPx7aJNewQfpyKasgmzcTqNR52WwdWkQQ+CMhlkqA9rqvxy551yks4mAEdYcmHfYW663kLjB5UkFiK++0g==", - "dev": true, - "requires": { - "babel-core": "^6.24.0", - "babel-plugin-istanbul": "^4.1.1", - "body-parser": "^1.15.2", - "commander": "^2.3.0", - "connect-injector": "^0.4.0", - "debug": "^3.0.0", - "feathers": "^2.0.1", - "feathers-memory": "^1.0.1", - "feathers-rest": "^1.5.0", - "feathers-socketio": "^2.0.1", - "http-proxy": "^1.1.4", - "istanbul": "^0.4.0", - "launchpad": "^0.6.0", - "lodash": "^4.17.10", - "mime-types": "^2.1.6", - "miner": "^0.2.1", - "mocha": "^4.1.0", - "path": "^0.12.7", - "testee-client": "^0.5.0", - "useragent": "^2.0.9" - }, - "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" - } - }, - "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", - "dev": true - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "feathers-memory": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/feathers-memory/-/feathers-memory-1.3.1.tgz", - "integrity": "sha512-jE1yfKe40cgx2lUnYmVVKpXb2uYbFRGeSkx1tSuLDJd2aIBUw9/9oQg4/y+mwwS+BfiIMocQ1O6JTXAe4rezkg==", - "dev": true, - "requires": { - "clone-deep": "^1.0.0", - "feathers-commons": "^0.8.0", - "feathers-errors": "^2.0.1", - "feathers-query-filters": "^2.0.0", - "sift": "^5.0.0", - "uberproto": "^1.2.0" - } - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "growl": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", - "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", - "dev": true - }, - "istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - } - }, - "mocha": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", - "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.11.0", - "debug": "3.1.0", - "diff": "3.3.1", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.3", - "he": "1.1.1", - "mkdirp": "0.5.1", - "supports-color": "4.4.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" - } - }, - "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" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } - } - } - }, - "ms": { - "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 - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "sift": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/sift/-/sift-5.1.0.tgz", - "integrity": "sha1-G78t+w63HlbEzH+1Z/vRNRtlAV4=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "testee-client": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/testee-client/-/testee-client-0.5.3.tgz", - "integrity": "sha512-20yDaIjPHr4qUjfJyJFjXx6HoFt6Pn54daoacI/8s3ECjYnuHAouOlcV5vxwv+mpg0YG0asquTXppQq0dLQLww==", - "dev": true, - "requires": { - "feathers-rest": "^1.5.0", - "superagent": "^3.0.0" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "thenify": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", - "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", - "dev": true, - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", - "dev": true, - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "time-fix-plugin": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/time-fix-plugin/-/time-fix-plugin-2.0.5.tgz", - "integrity": "sha512-veHRiEsQ50KSrfdhkZiFvZIjRoyfyfxpgskD+P7uVQAcNe6rIMLZ8vhjFRE2XrPqQdy+4CF+jXsWAlgVy9Bfcg==", - "dev": true - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true - }, - "timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, - "tiny-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", - "dev": true, - "optional": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-factory": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-factory/-/to-factory-1.0.0.tgz", - "integrity": "sha1-hzivi9lxIK0dQEeXKtpVY7+UebE=", - "dev": true - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "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" - } - } - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - }, - "toml": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.6.tgz", - "integrity": "sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==", - "dev": true - }, - "topo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", - "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", - "dev": true, - "requires": { - "hoek": "4.x.x" - } - }, - "toposort": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", - "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", - "dev": true - }, - "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" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } - } - }, - "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "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 - } - } - }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", - "dev": true - }, - "trim-newlines": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", - "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", - "dev": true - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "ts-node": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.0.3.tgz", - "integrity": "sha512-2qayBA4vdtVRuDo11DEFSsD/SFsBXQBRZZhbRGSIkmYmVkWjULn/GGMdG10KVqkaGndljfaTD8dKjWgcejO8YA==", - "dev": true, - "requires": { - "arg": "^4.1.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "source-map-support": "^0.5.6", - "yn": "^3.0.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.11.tgz", - "integrity": "sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } - } - }, - "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", - "dev": true - }, - "tsutils": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.9.1.tgz", - "integrity": "sha512-hrxVtLtPqQr//p8/msPT1X1UYXUjizqSit5d9AQ5k38TcV38NyecL5xODNxa73cLe/5sdiJ+w1FqzDhRBA/anA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", - "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 - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "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" - }, - "dependencies": { - "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" - } - } - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typescript": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.1.tgz", - "integrity": "sha512-3NSMb2VzDQm8oBTLH6Nj55VVtUEpe/rgkIzMir0qVoLyjDZlnMBva0U6vDiV3IH+sl/Yu6oP5QwsAQtHPmDd2Q==", - "dev": true - }, - "uberproto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/uberproto/-/uberproto-1.2.0.tgz", - "integrity": "sha1-YdTqsCT5CcTm6lK+hnxIlKS+63Y=", - "dev": true - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "optional": true, - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, - "underscore": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", - "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", - "dev": true - }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", - "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", - "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", - "dev": true - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } - } - }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", - "dev": true - }, - "unique-filename": { - "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.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" - } - }, - "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", - "dev": true, - "requires": { - "crypto-random-string": "^1.0.0" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "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", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "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" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "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 - } - } - }, - "unzip": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/unzip/-/unzip-0.1.11.tgz", - "integrity": "sha1-iXScY7BY19kNYZ+GuYqhU107l/A=", - "dev": true, - "requires": { - "binary": ">= 0.3.0 < 1", - "fstream": ">= 0.1.30 < 1", - "match-stream": ">= 0.0.2 < 1", - "pullstream": ">= 0.4.1 < 1", - "readable-stream": "~1.0.31", - "setimmediate": ">= 1.0.1 < 2" - }, - "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.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "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 - } - } - }, - "unzip-response": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", - "dev": true - }, - "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", - "dev": true, - "optional": true - }, - "update-notifier": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", - "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", - "dev": true, - "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^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" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "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": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "url-join": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-3.0.0.tgz", - "integrity": "sha1-JugROs4ZXqMND8OBhuRUAPnOpnI=", - "dev": true - }, - "url-loader": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", - "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "mime": "^2.0.3", - "schema-utils": "^1.0.0" - }, - "dependencies": { - "mime": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", - "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", - "dev": true - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "requires": { - "prepend-http": "^1.0.1" - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, - "useragent": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", - "dev": true, - "requires": { - "lru-cache": "4.1.x", - "tmp": "0.0.x" - } - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "util.promisify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" - } - }, - "utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", - "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 - }, - "v8-compile-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz", - "integrity": "sha512-1wFuMUIM16MDJRCrpbpuEPTUGmM5QMUg0cr3KFwra2XgOgFcPGDQHDh3CszSCD2Zewc/dh/pamNEW8CbfDebUw==", - "dev": true - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "^1.1.1" - } - }, - "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", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "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 - }, - "vendors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.2.tgz", - "integrity": "sha512-w/hry/368nO21AN9QljsaIhb9ZiZtZARoVH5f3CsFbawdLdayCgKRPup7CggujvySMxx0I91NOyxdVENohprLQ==", - "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" - } - }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } - }, - "vue": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.10.tgz", - "integrity": "sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==", - "dev": true - }, - "vue-eslint-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-5.0.0.tgz", - "integrity": "sha512-JlHVZwBBTNVvzmifwjpZYn0oPWH2SgWv5dojlZBsrhablDu95VFD+hriB1rQGwbD+bms6g+rAFhQHk6+NyiS6g==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "eslint-scope": "^4.0.0", - "eslint-visitor-keys": "^1.0.0", - "espree": "^4.1.0", - "esquery": "^1.0.1", - "lodash": "^4.17.11" - }, - "dependencies": { - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "espree": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", - "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", - "dev": true, - "requires": { - "acorn": "^6.0.2", - "acorn-jsx": "^5.0.0", - "eslint-visitor-keys": "^1.0.0" - } - } - } - }, - "vue-hot-reload-api": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.3.tgz", - "integrity": "sha512-KmvZVtmM26BQOMK1rwUZsrqxEGeKiYSZGA7SNWE6uExx8UX/cj9hq2MRV/wWC3Cq6AoeDGk57rL9YMFRel/q+g==", - "dev": true - }, - "vue-loader": { - "version": "15.7.0", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.7.0.tgz", - "integrity": "sha512-x+NZ4RIthQOxcFclEcs8sXGEWqnZHodL2J9Vq+hUz+TDZzBaDIh1j3d9M2IUlTjtrHTZy4uMuRdTi8BGws7jLA==", - "dev": true, - "requires": { - "@vue/component-compiler-utils": "^2.5.1", - "hash-sum": "^1.0.2", - "loader-utils": "^1.1.0", - "vue-hot-reload-api": "^2.3.0", - "vue-style-loader": "^4.1.0" - } - }, - "vue-router": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.2.tgz", - "integrity": "sha512-opKtsxjp9eOcFWdp6xLQPLmRGgfM932Tl56U9chYTnoWqKxQ8M20N7AkdEbM5beUh6wICoFGYugAX9vQjyJLFg==", - "dev": true - }, - "vue-server-renderer": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/vue-server-renderer/-/vue-server-renderer-2.6.10.tgz", - "integrity": "sha512-UYoCEutBpKzL2fKCwx8zlRtRtwxbPZXKTqbl2iIF4yRZUNO/ovrHyDAJDljft0kd+K0tZhN53XRHkgvCZoIhug==", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "hash-sum": "^1.0.2", - "he": "^1.1.0", - "lodash.template": "^4.4.0", - "lodash.uniq": "^4.5.0", - "resolve": "^1.2.0", - "serialize-javascript": "^1.3.0", - "source-map": "0.5.6" - } - }, - "vue-style-loader": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz", - "integrity": "sha512-0ip8ge6Gzz/Bk0iHovU9XAUQaFt/G2B61bnWa2tCcqqdgfHs1lF9xXorFbE55Gmy92okFT+8bfmySuUOu13vxQ==", - "dev": true, - "requires": { - "hash-sum": "^1.0.2", - "loader-utils": "^1.0.2" - } - }, - "vue-template-compiler": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz", - "integrity": "sha512-jVZkw4/I/HT5ZMvRnhv78okGusqe0+qH2A0Em0Cp8aq78+NK9TII263CDVz2QXZsIT+yyV/gZc/j/vlwa+Epyg==", - "dev": true, - "requires": { - "de-indent": "^1.0.2", - "he": "^1.1.0" - } - }, - "vue-template-es2015-compiler": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", - "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", - "dev": true - }, - "vuepress": { - "version": "0.14.10", - "resolved": "https://registry.npmjs.org/vuepress/-/vuepress-0.14.10.tgz", - "integrity": "sha512-upD0br3AUmZQ+kNJMg135jW36JjYAdShl6XYwDmVMw4XbtcLDSMGWTLqLCQN3PTIs/7TgiJ3cLWNL1ps63gyUQ==", - "dev": true, - "requires": { - "@babel/core": "7.0.0-beta.47", - "@vue/babel-preset-app": "3.0.0-beta.11", - "autoprefixer": "^8.2.0", - "babel-loader": "8.0.0-beta.3", - "cache-loader": "^1.2.2", - "chalk": "^2.3.2", - "chokidar": "^2.0.3", - "commander": "^2.15.1", - "connect-history-api-fallback": "^1.5.0", - "copy-webpack-plugin": "^4.5.1", - "cross-spawn": "^6.0.5", - "css-loader": "^0.28.11", - "diacritics": "^1.3.0", - "docsearch.js": "^2.5.2", - "escape-html": "^1.0.3", - "file-loader": "^1.1.11", - "fs-extra": "^5.0.0", - "globby": "^8.0.1", - "gray-matter": "^4.0.1", - "js-yaml": "^3.11.0", - "koa-connect": "^2.0.1", - "koa-mount": "^3.0.0", - "koa-range": "^0.3.0", - "koa-static": "^4.0.2", - "loader-utils": "^1.1.0", - "lodash.throttle": "^4.1.1", - "lru-cache": "^4.1.2", - "markdown-it": "^8.4.1", - "markdown-it-anchor": "^5.0.2", - "markdown-it-container": "^2.0.0", - "markdown-it-emoji": "^1.4.0", - "markdown-it-table-of-contents": "^0.4.0", - "mini-css-extract-plugin": "0.4.1", - "nprogress": "^0.2.0", - "optimize-css-assets-webpack-plugin": "^4.0.0", - "portfinder": "^1.0.13", - "postcss-loader": "^2.1.5", - "prismjs": "^1.13.0", - "register-service-worker": "^1.5.1", - "semver": "^5.5.0", - "stylus": "^0.54.5", - "stylus-loader": "^3.0.2", - "toml": "^2.3.3", - "url-loader": "^1.0.1", - "vue": "^2.5.16", - "vue-loader": "^15.2.4", - "vue-router": "^3.0.1", - "vue-server-renderer": "^2.5.16", - "vue-template-compiler": "^2.5.16", - "vuepress-html-webpack-plugin": "^3.2.0", - "webpack": "^4.8.1", - "webpack-chain": "^4.6.0", - "webpack-merge": "^4.1.2", - "webpack-serve": "^1.0.2", - "webpackbar": "^2.6.1", - "workbox-build": "^3.1.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" - } - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "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" - } - } - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chokidar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", - "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - }, - "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" - } - } - } - }, - "fsevents": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", - "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": 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" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": 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", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "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" - } - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "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": { - "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" - }, - "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" - } - }, - "nan": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.1.tgz", - "integrity": "sha512-I6YB/YEuDeUZMmhscXKxGgZlFnhsn5y0hgOZBadkzfTRrZBtJDZeg6eQf7PYMIEclwmorTKK8GztsyOUSVBREA==", - "dev": true, - "optional": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "readdirp": { - "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.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "upath": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", - "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", - "dev": true - } - } - }, - "vuepress-html-webpack-plugin": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/vuepress-html-webpack-plugin/-/vuepress-html-webpack-plugin-3.2.0.tgz", - "integrity": "sha512-BebAEl1BmWlro3+VyDhIOCY6Gef2MCBllEVAP3NUAtMguiyOwo/dClbwJ167WYmcxHJKLl7b0Chr9H7fpn1d0A==", - "dev": true, - "requires": { - "html-minifier": "^3.2.3", - "loader-utils": "^0.2.16", - "lodash": "^4.17.3", - "pretty-error": "^2.0.2", - "tapable": "^1.0.0", - "toposort": "^1.0.0", - "util.promisify": "1.0.0" - }, - "dependencies": { - "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", - "dev": true - }, - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "dev": true, - "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0", - "object-assign": "^4.0.1" - } - } - } - }, - "vuex": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.1.0.tgz", - "integrity": "sha512-mdHeHT/7u4BncpUZMlxNaIdcN/HIt1GsGG5LKByArvYG/v6DvHcOxvDCts+7SRdCoIRGllK8IMZvQtQXLppDYg==", - "dev": true - }, - "w3c-hr-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", - "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", - "dev": true, - "requires": { - "browser-process-hrtime": "^0.1.2" - } - }, - "w3c-xmlserializer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", - "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", - "dev": true, - "requires": { - "domexception": "^1.0.1", - "webidl-conversions": "^4.0.2", - "xml-name-validator": "^3.0.0" - } - }, - "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true, - "requires": { - "chokidar": "^2.0.2", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "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" - } - } - } - }, - "chokidar": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", - "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "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" - } - } - } - }, - "fsevents": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", - "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": 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" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": 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", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "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-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": { - "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" - }, - "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" - } - }, - "nan": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.1.tgz", - "integrity": "sha512-I6YB/YEuDeUZMmhscXKxGgZlFnhsn5y0hgOZBadkzfTRrZBtJDZeg6eQf7PYMIEclwmorTKK8GztsyOUSVBREA==", - "dev": true, - "optional": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "readdirp": { - "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.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "upath": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", - "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", - "dev": true - } - } - }, - "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true - }, - "webpack": { - "version": "4.29.6", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.29.6.tgz", - "integrity": "sha512-MwBwpiE1BQpMDkbnUUaW6K8RFZjljJHArC6tWQJoFm0oQtfoSebtg4Y7/QHnJ/SddtjYLHaKGX64CFjG5rehJw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.8.5", - "@webassemblyjs/helper-module-context": "1.8.5", - "@webassemblyjs/wasm-edit": "1.8.5", - "@webassemblyjs/wasm-parser": "1.8.5", - "acorn": "^6.0.5", - "acorn-dynamic-import": "^4.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", - "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", - "schema-utils": "^1.0.0", - "tapable": "^1.1.0", - "terser-webpack-plugin": "^1.1.0", - "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" - }, - "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" - } - }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "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" - } - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "webpack-chain": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-4.12.1.tgz", - "integrity": "sha512-BCfKo2YkDe2ByqkEWe1Rw+zko4LsyS75LVr29C6xIrxAg9JHJ4pl8kaIZ396SUSNp6b4815dRZPSTAS8LlURRQ==", - "dev": true, - "requires": { - "deepmerge": "^1.5.2", - "javascript-stringify": "^1.6.0" - } - }, - "webpack-dev-middleware": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.6.1.tgz", - "integrity": "sha512-XQmemun8QJexMEvNFbD2BIg4eSKrmSIMrTfnl2nql2Sc6OGAYFyb8rwuYrCjl/IiEYYuyTEiimMscu7EXji/Dw==", - "dev": true, - "requires": { - "memory-fs": "^0.4.1", - "mime": "^2.3.1", - "range-parser": "^1.0.3", - "webpack-log": "^2.0.0" - }, - "dependencies": { - "mime": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", - "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", - "dev": true - }, - "webpack-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", - "dev": true, - "requires": { - "ansi-colors": "^3.0.0", - "uuid": "^3.3.2" - } - } - } - }, - "webpack-hot-client": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/webpack-hot-client/-/webpack-hot-client-3.0.0.tgz", - "integrity": "sha512-6k91015hZ4Okkz8u6OzRgJygEL+3J3ay6HVZhWBF3tT2P0rZJ0mgca39dotJxngggUm3S8707c0vrcynn1IzEQ==", - "dev": true, - "requires": { - "json-stringify-safe": "^5.0.1", - "loglevelnext": "^1.0.2", - "strip-ansi": "^4.0.0", - "uuid": "^3.1.0", - "webpack-log": "^1.1.1", - "ws": "^4.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-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "ws": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz", - "integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0" - } - } - } - }, - "webpack-log": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", - "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", - "dev": true, - "requires": { - "chalk": "^2.1.0", - "log-symbols": "^2.1.0", - "loglevelnext": "^1.0.1", - "uuid": "^3.1.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" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "webpack-merge": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", - "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==", - "dev": true, - "requires": { - "lodash": "^4.17.5" - } - }, - "webpack-serve": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/webpack-serve/-/webpack-serve-1.0.4.tgz", - "integrity": "sha512-WhI9PMY2YLFliZhDsQFE5Os/On5Py6DGZpeBJyDM8xl0cspxgvXmWFywACn2YWWDgowqIxRqveyGh2RwdFWTNQ==", - "dev": true, - "requires": { - "@shellscape/koa-static": "^4.0.4", - "@webpack-contrib/config-loader": "^1.1.1", - "chalk": "^2.3.0", - "clipboardy": "^1.2.2", - "cosmiconfig": "^5.0.2", - "debug": "^3.1.0", - "find-up": "^2.1.0", - "get-port": "^3.2.0", - "import-local": "^1.0.0", - "killable": "^1.0.0", - "koa": "^2.4.1", - "koa-webpack": "^4.0.0", - "lodash": "^4.17.5", - "loud-rejection": "^1.6.0", - "meow": "^5.0.0", - "nanobus": "^4.3.1", - "opn": "^5.1.0", - "resolve": "^1.6.0", - "time-fix-plugin": "^2.0.0", - "update-notifier": "^2.3.0", - "url-join": "3.0.0", - "v8-compile-cache": "^2.0.0", - "webpack-hot-client": "^3.0.0", - "webpack-log": "^1.1.2" - }, - "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" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cosmiconfig": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.1.0.tgz", - "integrity": "sha512-kCNPvthka8gvLtzAxQXvWo4FxqRB+ftRZyPZNuab5ngvM9Y7yw7hbEysglptLgpkGX9nAOKTBVkHUAe8xtYR6Q==", - "dev": true, - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.9.0", - "lodash.get": "^4.4.2", - "parse-json": "^4.0.0" - } - }, - "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" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^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 - }, - "ms": { - "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 - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "resolve": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", - "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "webpack-sources": { - "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 - } - } - }, - "webpackbar": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-2.6.4.tgz", - "integrity": "sha512-uQzJwuX172E+Vnk2NRFSM1hZBMCXd2CIpRUl1hr5tbAndTGVnDmYXQKHsbgbCKQXFJKKAl8EHYsdeauJZu2Qvg==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "consola": "^1.4.3", - "figures": "^2.0.0", - "loader-utils": "^1.1.0", - "lodash": "^4.17.10", - "log-update": "^2.3.0", - "pretty-time": "^1.1.0", - "schema-utils": "^1.0.0", - "std-env": "^1.3.1", - "table": "^4.0.3" - }, - "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" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "requires": { - "iconv-lite": "0.4.24" - }, - "dependencies": { - "iconv-lite": { - "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" - } - } - } - }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "whatwg-url": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", - "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "when": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz", - "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=", - "dev": true - }, - "whet.extend": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", - "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", - "dev": true - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "widest-line": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", - "dev": true, - "requires": { - "string-width": "^2.1.1" - }, - "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 - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, - "optional": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "workbox-background-sync": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-3.6.3.tgz", - "integrity": "sha512-ypLo0B6dces4gSpaslmDg5wuoUWrHHVJfFWwl1udvSylLdXvnrfhFfriCS42SNEe5lsZtcNZF27W/SMzBlva7Q==", - "dev": true, - "requires": { - "workbox-core": "^3.6.3" - } - }, - "workbox-broadcast-cache-update": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-broadcast-cache-update/-/workbox-broadcast-cache-update-3.6.3.tgz", - "integrity": "sha512-pJl4lbClQcvp0SyTiEw0zLSsVYE1RDlCPtpKnpMjxFtu8lCFTAEuVyzxp9w7GF4/b3P4h5nyQ+q7V9mIR7YzGg==", - "dev": true, - "requires": { - "workbox-core": "^3.6.3" - } - }, - "workbox-build": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-3.6.3.tgz", - "integrity": "sha512-w0clZ/pVjL8VXy6GfthefxpEXs0T8uiRuopZSFVQ8ovfbH6c6kUpEh6DcYwm/Y6dyWPiCucdyAZotgjz+nRz8g==", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "common-tags": "^1.4.0", - "fs-extra": "^4.0.2", - "glob": "^7.1.2", - "joi": "^11.1.1", - "lodash.template": "^4.4.0", - "pretty-bytes": "^4.0.2", - "stringify-object": "^3.2.2", - "strip-comments": "^1.0.2", - "workbox-background-sync": "^3.6.3", - "workbox-broadcast-cache-update": "^3.6.3", - "workbox-cache-expiration": "^3.6.3", - "workbox-cacheable-response": "^3.6.3", - "workbox-core": "^3.6.3", - "workbox-google-analytics": "^3.6.3", - "workbox-navigation-preload": "^3.6.3", - "workbox-precaching": "^3.6.3", - "workbox-range-requests": "^3.6.3", - "workbox-routing": "^3.6.3", - "workbox-strategies": "^3.6.3", - "workbox-streams": "^3.6.3", - "workbox-sw": "^3.6.3" - }, - "dependencies": { - "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - } - } - }, - "workbox-cache-expiration": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-cache-expiration/-/workbox-cache-expiration-3.6.3.tgz", - "integrity": "sha512-+ECNph/6doYx89oopO/UolYdDmQtGUgo8KCgluwBF/RieyA1ZOFKfrSiNjztxOrGJoyBB7raTIOlEEwZ1LaHoA==", - "dev": true, - "requires": { - "workbox-core": "^3.6.3" - } - }, - "workbox-cacheable-response": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-3.6.3.tgz", - "integrity": "sha512-QpmbGA9SLcA7fklBLm06C4zFg577Dt8u3QgLM0eMnnbaVv3rhm4vbmDpBkyTqvgK/Ly8MBDQzlXDtUCswQwqqg==", - "dev": true, - "requires": { - "workbox-core": "^3.6.3" - } - }, - "workbox-core": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-3.6.3.tgz", - "integrity": "sha512-cx9cx0nscPkIWs8Pt98HGrS9/aORuUcSkWjG25GqNWdvD/pSe7/5Oh3BKs0fC+rUshCiyLbxW54q0hA+GqZeSQ==", - "dev": true - }, - "workbox-google-analytics": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-3.6.3.tgz", - "integrity": "sha512-RQBUo/6SXtIaQTRFj4RQZ9e1gAl7D8oS5S+Hi173Kk70/BgJjzPwXpC5A249Jv5YfkCOLMQCeF9A27BiD0b0ig==", - "dev": true, - "requires": { - "workbox-background-sync": "^3.6.3", - "workbox-core": "^3.6.3", - "workbox-routing": "^3.6.3", - "workbox-strategies": "^3.6.3" - } - }, - "workbox-navigation-preload": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-3.6.3.tgz", - "integrity": "sha512-dd26xTX16DUu0i+MhqZK/jQXgfIitu0yATM4jhRXEmpMqQ4MxEeNvl2CgjDMOHBnCVMax+CFZQWwxMx/X/PqCw==", - "dev": true, - "requires": { - "workbox-core": "^3.6.3" - } - }, - "workbox-precaching": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-3.6.3.tgz", - "integrity": "sha512-aBqT66BuMFviPTW6IpccZZHzpA8xzvZU2OM1AdhmSlYDXOJyb1+Z6blVD7z2Q8VNtV1UVwQIdImIX+hH3C3PIw==", - "dev": true, - "requires": { - "workbox-core": "^3.6.3" - } - }, - "workbox-range-requests": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-3.6.3.tgz", - "integrity": "sha512-R+yLWQy7D9aRF9yJ3QzwYnGFnGDhMUij4jVBUVtkl67oaVoP1ymZ81AfCmfZro2kpPRI+vmNMfxxW531cqdx8A==", - "dev": true, - "requires": { - "workbox-core": "^3.6.3" - } - }, - "workbox-routing": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-3.6.3.tgz", - "integrity": "sha512-bX20i95OKXXQovXhFOViOK63HYmXvsIwZXKWbSpVeKToxMrp0G/6LZXnhg82ijj/S5yhKNRf9LeGDzaqxzAwMQ==", - "dev": true, - "requires": { - "workbox-core": "^3.6.3" - } - }, - "workbox-strategies": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-3.6.3.tgz", - "integrity": "sha512-Pg5eulqeKet2y8j73Yw6xTgLdElktcWExGkzDVCGqfV9JCvnGuEpz5eVsCIK70+k4oJcBCin9qEg3g3CwEIH3g==", - "dev": true, - "requires": { - "workbox-core": "^3.6.3" - } - }, - "workbox-streams": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-3.6.3.tgz", - "integrity": "sha512-rqDuS4duj+3aZUYI1LsrD2t9hHOjwPqnUIfrXSOxSVjVn83W2MisDF2Bj+dFUZv4GalL9xqErcFW++9gH+Z27w==", - "dev": true, - "requires": { - "workbox-core": "^3.6.3" - } - }, - "workbox-sw": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-3.6.3.tgz", - "integrity": "sha512-IQOUi+RLhvYCiv80RP23KBW/NTtIvzvjex28B8NW1jOm+iV4VIu3VXKXTA6er5/wjjuhmtB28qEAUqADLAyOSg==", - "dev": true - }, - "worker-farm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", - "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "write-file-atomic": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.2.tgz", - "integrity": "sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "ws": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.2.tgz", - "integrity": "sha512-rfUqzvz0WxmSXtJpPMX2EeASXabOrSMk1ruMOV3JBTBjo4ac2lDjGGsbQSyxj8Odhw5fBib8ZKEjDNvgouNKYw==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", - "dev": true - }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "xmlbuilder": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", - "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=", - "dev": true - }, - "xmlchars": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-1.3.1.tgz", - "integrity": "sha512-tGkGJkN8XqCod7OT+EvGYK5Z4SfDQGD30zAa58OcnAa0RRWgzUEK72tkXhsX1FZd+rgnhRxFtmO+ihkp8LHSkw==", - "dev": true - }, - "xmldom": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", - "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", - "dev": true - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", - "dev": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "optional": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } - }, - "yargs-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", - "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", - "dev": true, - "requires": { - "camelcase": "^3.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - } - } - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", - "dev": true - }, - "ylru": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz", - "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==", - "dev": true - }, - "yn": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.0.0.tgz", - "integrity": "sha512-+Wo/p5VRfxUgBUGy2j/6KX2mj9AYJWOHuhMjMcbBFc3y54o9/4buK1ksBvuiK01C3kby8DH9lSmJdSxw+4G/2Q==", - "dev": true - }, - "zepto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/zepto/-/zepto-1.2.0.tgz", - "integrity": "sha1-4Se9nmb9hGvl6rSME5SIL3wOT5g=", - "dev": true - }, - "zlib-browserify": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/zlib-browserify/-/zlib-browserify-0.0.3.tgz", - "integrity": "sha1-JAzNv9AgP6hCsTDe77FBQSLIzFA=", - "dev": true, - "requires": { - "tape": "~0.2.2" - } - } - } -} From 240af6d0bcfb4e406a11f4c31e1dfc921e07a391 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 5 Sep 2019 11:57:22 -0600 Subject: [PATCH 362/404] 2.0.0-pre.76 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 849ca0c5..ece80dec 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.75", + "version": "2.0.0-pre.76", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From c17d174bc66ff83240b4d5224038b9f4f5399a54 Mon Sep 17 00:00:00 2001 From: fratzinger <22286818+fratzinger@users.noreply.github.com> Date: Mon, 9 Sep 2019 23:21:02 +0200 Subject: [PATCH 363/404] Update FeathersVuexFind.ts add queryInfo & pageInfo to scope. --- src/FeathersVuexFind.ts | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/FeathersVuexFind.ts b/src/FeathersVuexFind.ts index bf941c8f..88c5c746 100644 --- a/src/FeathersVuexFind.ts +++ b/src/FeathersVuexFind.ts @@ -1,4 +1,5 @@ -import { randomString } from './utils' +import { randomString, getQueryInfo } from './utils' +import _get from 'lodash/get' export default { props: { @@ -50,7 +51,9 @@ export default { } }, data: () => ({ - isFindPending: false + isFindPending: false, + queryId: null, + pageId: null }), computed: { items() { @@ -62,9 +65,17 @@ export default { pagination() { return this.$store.state[this.service].pagination[this.qid] }, + queryInfo() { + if (this.pagination == null || this.queryId == null) return {} + return _get(this.pagination, `[${this.queryId}]`) || {} + }, + pageInfo() { + if (this.pagination == null || this.queryId == null || this.pageId == null) return {} + return _get(this.pagination, `[${this.queryId}][${this.pageId}]` || {} + }, scope() { - const { items, isFindPending, pagination } = this - const defaultScope = { isFindPending, pagination, items } + const { items, isFindPending, pagination, queryInfo, pageInfo } = this + const defaultScope = { isFindPending, pagination, items, queryInfo, pageInfo } return this.editScope(defaultScope) || defaultScope } @@ -85,8 +96,11 @@ export default { return this.$store .dispatch(`${this.service}/find`, params) - .then(() => { + .then((response) => { this.isFindPending = false + { queryId, pageId } = getQueryInfo(params, response) + this.queryId = queryId + this.pageId = pageId }) } } From 25da7c07bc6c9f1e54fa84c81782088f61cdbb1c Mon Sep 17 00:00:00 2001 From: fratzinger <22286818+fratzinger@users.noreply.github.com> Date: Tue, 10 Sep 2019 22:27:27 +0200 Subject: [PATCH 364/404] components.md add server-side pagination example --- docs/components.md | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/docs/components.md b/docs/components.md index 3e409cf2..97ee82c5 100644 --- a/docs/components.md +++ b/docs/components.md @@ -315,6 +315,65 @@ export default { ``` +### server-side pagination + +When you want to use server-side pagination you need to pass the ids from the server to vuex. It can be done by a combination of `query`, `fetchQuery` and `editScope` as described below. The `fetchQuery`-prop is only computed after items from the server arrived. The ids for the `find` getter as well as the total amount of available values `total` are extracted by the `edit-scope` function and stored in `data`: + +```html + + + +``` + ### Query when certain conditions are met Sometimes you only want to query the API server when certain conditions are met. This example shows how to query the API server when the `userSearch` has as least three characters. This property does not affect the internal `find` getter, so the `items` will still update when the `userSearch` property has fewer than three characters, just no API request will be made. The `isFindPending` attribute is used to indicate when data is being loaded from the server. From 69051a6b5c6aa8c4bb69e68dcfa1d8b7cc8572a7 Mon Sep 17 00:00:00 2001 From: fratzinger <22286818+fratzinger@users.noreply.github.com> Date: Tue, 10 Sep 2019 22:31:39 +0200 Subject: [PATCH 365/404] fix FeathersVuexFind.ts --- src/FeathersVuexFind.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/FeathersVuexFind.ts b/src/FeathersVuexFind.ts index 88c5c746..263b45b2 100644 --- a/src/FeathersVuexFind.ts +++ b/src/FeathersVuexFind.ts @@ -71,7 +71,7 @@ export default { }, pageInfo() { if (this.pagination == null || this.queryId == null || this.pageId == null) return {} - return _get(this.pagination, `[${this.queryId}][${this.pageId}]` || {} + return _get(this.pagination, `[${this.queryId}][${this.pageId}]`) || {} }, scope() { const { items, isFindPending, pagination, queryInfo, pageInfo } = this @@ -98,7 +98,7 @@ export default { .dispatch(`${this.service}/find`, params) .then((response) => { this.isFindPending = false - { queryId, pageId } = getQueryInfo(params, response) + const { queryId, pageId } = getQueryInfo(params, response) this.queryId = queryId this.pageId = pageId }) From 3599e07c8aba9d3be8e28d2d4da451ce02243cf7 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 10 Sep 2019 15:07:19 -0600 Subject: [PATCH 366/404] 2.0.0-pre.77 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ece80dec..b0c6b586 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.76", + "version": "2.0.0-pre.77", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From 9c1b652ab4795f88d38c16b3f07de05d10987653 Mon Sep 17 00:00:00 2001 From: Morgan Benton Date: Sun, 15 Sep 2019 15:18:13 -0400 Subject: [PATCH 367/404] Fix Model.find() return type --- src/service-module/make-model.ts | 2 +- test/service-module/model-methods.test.ts | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/service-module/make-model.ts b/src/service-module/make-model.ts index 3d275e23..e8797a58 100644 --- a/src/service-module/make-model.ts +++ b/src/service-module/make-model.ts @@ -164,7 +164,7 @@ export default function makeModel(options: FeathersVuexOptions) { } public static find(params) { - this._dispatch('find', params) + return this._dispatch('find', params) } public static findInStore(params) { diff --git a/test/service-module/model-methods.test.ts b/test/service-module/model-methods.test.ts index 3463f7e1..bd4a8835 100644 --- a/test/service-module/model-methods.test.ts +++ b/test/service-module/model-methods.test.ts @@ -134,12 +134,19 @@ describe('Models - Methods', function () { clearModels() }) - it('Model.find', function () { + it('Model.find is a function', function () { const { Task } = makeContext() assert(typeof Task.find === 'function') }) + it('Model.find returns a Promise', function () { + const { Task } = makeContext() + const result = Task.find() + assert(typeof result.then !== 'undefined') + result.catch(err => { /* noop -- prevents UnhandledPromiseRejectionWarning */}) + }) + it('Model.findInStore', function () { const { Task } = makeContext() From 8e2250c94475d332c8d7dcc304a94789ffc940a9 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 24 Sep 2019 12:47:32 -0600 Subject: [PATCH 368/404] compatibility with feathers@4.x auth --- src/auth-module/auth-module.actions.ts | 57 +++++++++++--------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/src/auth-module/auth-module.actions.ts b/src/auth-module/auth-module.actions.ts index d8dbb43e..70472d65 100644 --- a/src/auth-module/auth-module.actions.ts +++ b/src/auth-module/auth-module.actions.ts @@ -29,43 +29,36 @@ export default function makeAuthActions(feathersClient) { responseHandler({ commit, state, dispatch }, response) { if (response.accessToken) { commit('setAccessToken', response.accessToken) + commit('setPayload', response) - // Decode the token and set the payload, but return the response - return feathersClient.passport - .verifyJWT(response.accessToken) - .then(payload => { - commit('setPayload', payload) + // Handle when user is returned in the authenticate response + let user = response[state.responseEntityField] - let user = response[state.responseEntityField] - - // If a user was returned in the authenticate response, use that user. - if (user) { - if (state.serverAlias && state.userService) { - const Model = Object.keys(models[state.serverAlias]) - .map(modelName => models[state.serverAlias][modelName]) - .find(model => model.servicePath === state.userService) - if (Model) { - user = new Model(user) - } - } - commit('setUser', user) - // Populate the user if the userService was provided - } else if ( - state.userService && - payload.hasOwnProperty(state.entityIdField) - ) { - return dispatch( - 'populateUser', - payload[state.entityIdField] - ).then(() => { - commit('unsetAuthenticatePending') - return response - }) - } else { - commit('unsetAuthenticatePending') + if (user) { + if (state.serverAlias && state.userService) { + const Model = Object.keys(models[state.serverAlias]) + .map(modelName => models[state.serverAlias][modelName]) + .find(model => model.servicePath === state.userService) + if (Model) { + user = new Model(user) } + } + commit('setUser', user) + commit('unsetAuthenticatePending') + } else if ( + state.userService && + response.hasOwnProperty(state.entityIdField) + ) { + return dispatch( + 'populateUser', + response[state.entityIdField] + ).then(() => { + commit('unsetAuthenticatePending') return response }) + } + return response + // If there was not an accessToken in the response, allow the response to pass through to handle two-factor-auth } else { return response From c342fc2d20b2f395f04505bc5d9df3c336023291 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Tue, 24 Sep 2019 12:48:12 -0600 Subject: [PATCH 369/404] 2.0.0-pre.78 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b0c6b586..ac4ec861 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "feathers-vuex", "description": "FeathersJS, Vue, and Nuxt for the artisan developer", - "version": "2.0.0-pre.77", + "version": "2.0.0-pre.78", "homepage": "https:feathers-vuex.feathers-plus.com", "main": "dist/", "module": "dist/", From bec2b7c1ec65618752bafd7663bc909bba42b705 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 28 Sep 2019 09:05:08 -0600 Subject: [PATCH 370/404] Begin updating docs --- docs/api-overview.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/docs/api-overview.md b/docs/api-overview.md index ea766acc..27a3dcd6 100755 --- a/docs/api-overview.md +++ b/docs/api-overview.md @@ -17,21 +17,26 @@ title: API Overview - Fully powered by Vuex & Feathers - Realtime By Default -- Actions With Reactive Data * +- Actions With Reactive Data - Local Queries -- Fall-Through Caching * +- Live Queries - Feathers Query Syntax +- Vuex Strict Mode Support +- Client-Side Pagination Support +- Fall-Through Caching * - `$FeathersVuex` [Vue Plugin](./vue-plugin.md) * -- Live Queries - [Per-Service Data Modeling](./common-patterns.md#Basic-Data-Modeling-with-instanceDefaults) * - Clone & Commit * -- Simplified Auth -- Vuex Strict Mode * +- Simplified Auth * - Per-Record Defaults * -- Data Level Computes * -- Relation Support * - -`* New in v1.2.0` +- Data Level Computed Properties * +- Improved Relation Support * +- Renderless Data Components * +- Powerful Mixins * +- Server-Powered Pagination Support ** + +`* Improved in v2.0.0`
+`** New in v2.0.0` ## Installation From 143fa148fd05067f7d74eae388365ffab1854167 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 29 Sep 2019 12:24:20 -0600 Subject: [PATCH 371/404] Add a note about finding the old docs --- docs/api-overview.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/api-overview.md b/docs/api-overview.md index 27a3dcd6..5bb4c509 100755 --- a/docs/api-overview.md +++ b/docs/api-overview.md @@ -13,6 +13,8 @@ title: API Overview `feathers-vuex` is a first class integration of the Feathers Client and Vuex. It implements many Redux best practices under the hood, eliminates *a lot* of boilerplate code, and still allows you to easily customize the Vuex store. +These docs are for version 2.x. For feathers-vuex@1.x, please go to [feathers-vuex-v1.netlify.com](feathers-vuex-v1.netlify.com). + ## Features - Fully powered by Vuex & Feathers From 34baedb1abe674df442a69a037a7fc0c0155be4e Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 30 Sep 2019 08:11:12 -0600 Subject: [PATCH 372/404] Version in the title --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 1cd7c69a..b4aae9cf 100755 --- a/docs/index.md +++ b/docs/index.md @@ -1,7 +1,7 @@ --- home: true heroImage: https://github.com/feathers-plus/feathers-vuex/raw/master/service-logo.png -heroText: FeathersVuex +heroText: FeathersVuex 2.x tagLine: Integration of FeathersJS, Vue, and Nuxt for the artisan developer actionText: Get Started actionLink: ./api-overview.md From 2dfee5e39099b44804f95dc3fa2a16436d524cf2 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 17 Oct 2019 18:23:14 -0600 Subject: [PATCH 373/404] new docs for setting up --- docs/api-overview.md | 104 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/docs/api-overview.md b/docs/api-overview.md index 5bb4c509..80ec5fd5 100755 --- a/docs/api-overview.md +++ b/docs/api-overview.md @@ -48,7 +48,17 @@ npm install feathers-vuex --save ## Use -To setup `feathers-vuex`, we first need to setup a Feathers Client. Here's an example using the latest `@feathersjs` npm packages. +Using Feathers-Vuex happens in these steps: + +1. Setup the Feathers client and Feathers-Vuex. +2. Define a Model class and service plugin for each service. +3. Register the plugins with the Vuex store. + +### Setup the Feathers Client and Feathers-Vuex + +To setup `feathers-vuex`, we first need to setup the latest Feathers client. We can also setup feathers-vuex in the same file. + +Note that this example includes an app-level hook that removes attributes for handling temporary (local-only) records. ```js // feathers-client.js @@ -56,17 +66,107 @@ import feathers from '@feathersjs/feathers' import socketio from '@feathersjs/socketio-client' import auth from '@feathersjs/authentication-client' import io from 'socket.io-client' +import { iff } from 'feathers-hooks-common' const socket = io('http://localhost:3030', {transports: ['websocket']}) const feathersClient = feathers() .configure(socketio(socket)) .configure(auth({ storage: window.localStorage })) + .hooks({ + before: { + all: [ + iff( + context => ['create', 'update', 'patch'].includes(context.method), + discard('__id', '__isTemp') + ) + ] + } + }) export default feathersClient + +// Setting up feathers-vuex +const { makeServicePlugin, makeAuthPlugin, BaseModel, models } = feathersVuex( + feathersClient, + { + serverAlias: 'api', + idField: '_id', + whitelist: ['$regex', '$options'] + } +) + +export { makeAuthPlugin, makeServicePlugin, BaseModel, models } +``` + +### Setup one or more service plugins + +The following example creates a User class and registers it with the new `makeServicePlugin` utility function. + +```js +// services/users.js +import { makeServicePlugin, BaseModel } from '../feathers-client' + +class User extends BaseModel { + constructor(data, options) { + super(data, options) + } + // Required for $FeathersVuex plugin to work after production transpile. + static modelName = 'User' + // Define default properties here + static instanceDefaults() { + return { + email: '', + password: '' + } + } +} +const servicePath = 'users' +const servicePlugin = makeServicePlugin({ + Model: User, + service: feathersClient.service(servicePath), + servicePath +}) +``` + +This same file is also a great place to add your service-level hooks, so append the following. + +```js +// Setup the client-side Feathers hooks. +feathersClient.service(servicePath).hooks({ + before: { + all: [], + find: [], + get: [], + create: [], + update: [], + patch: [], + remove: [] + }, + after: { + all: [], + find: [], + get: [], + create: [], + update: [], + patch: [], + remove: [] + }, + error: { + all: [], + find: [], + get: [], + create: [], + update: [], + patch: [], + remove: [] + } +}) + +export default servicePlugin + ``` -And here's how you would integrate the Feathers Client into the Vuex store: ```js // store/index.js From 47e944b7c315dcdbc624a365315894097f3435d9 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 17 Oct 2019 18:24:12 -0600 Subject: [PATCH 374/404] Document FeathersVuexGet props --- src/FeathersVuexGet.ts | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/FeathersVuexGet.ts b/src/FeathersVuexGet.ts index b6049bbd..1622feb9 100644 --- a/src/FeathersVuexGet.ts +++ b/src/FeathersVuexGet.ts @@ -1,13 +1,23 @@ export default { props: { + /** + * The path of the service from which to pull records. + */ service: { type: String, required: true }, + /** + * By default, `query` is used to get data from the Vuex store AND the API request. + * If you specify a `fetchQuery`, then `query` will only be used for the Vuex store. + */ query: { type: Object, default: null }, + /** + * When `queryWhen` evaluates to false, no API request will be made. + */ queryWhen: { type: [Boolean, Function], default: true @@ -17,21 +27,34 @@ export default { type: [Number, String], default: null }, - // If a separate query is desired to fetch data, use fetchQuery - // The watchers will automatically be updated, so you don't have to write 'fetchQuery.propName' + /** + * If a separate query is desired to fetch data, use fetchQuery + * The watchers are automatically updated, so you don't have to write 'fetchQuery.propName' + */ fetchQuery: { type: Object }, + /** + * Specify which properties in the query to watch and re-trigger API requests. + */ watch: { type: [String, Array], default() { return [] } }, + /** + * Set `local` to true to only requests from the Vuex data store and not make API requests. + */ local: { type: Boolean, default: false }, + /** + * This function is called by the getter and allows you to intercept the `item` in the + * response to pass it into the parent component's scope. It's a dirty little cheater + * function (because it's called from a getter), but it actually works well ;) + */ editScope: { type: Function, default(scope) { From fb8acdbc241e101cc4ec4ad67a554070cc13356d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 17 Oct 2019 18:24:49 -0600 Subject: [PATCH 375/404] The `serverAlias` prop now defaults to `api`. --- src/FeathersVuexGet.ts | 35 ++++++++++++++++++++-------------- src/auth-module/auth-module.ts | 2 +- src/index.ts | 2 +- src/service-module/notes.md | 4 ++-- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/FeathersVuexGet.ts b/src/FeathersVuexGet.ts index 1622feb9..0256287b 100644 --- a/src/FeathersVuexGet.ts +++ b/src/FeathersVuexGet.ts @@ -7,6 +7,13 @@ export default { type: String, required: true }, + /** + * Must match the `serverAlias` that was provided in the service's configuration. + */ + serverAlias: { + type: String, + default: 'api' + }, /** * By default, `query` is used to get data from the Vuex store AND the API request. * If you specify a `fetchQuery`, then `query` will only be used for the Vuex store. @@ -121,20 +128,20 @@ export default { } }, fetchData() { - if (!this.local) { - if ( - this.id !== null && - this.id !== undefined && - !this.query && - !this.fetchQuery - ) { - return this.getData() - } else { - // eslint-disable-next-line no-console - console.log( - `No query and no id provided, so no data will be fetched.` - ) - } + if (this.local || this.id === 'new') { + return + } else if ( + this.id !== null && + this.id !== undefined && + !this.query && + !this.fetchQuery + ) { + return this.getData() + } else { + // eslint-disable-next-line no-console + console.log( + `No query and no id provided, so no data will be fetched.` + ) } } }, diff --git a/src/auth-module/auth-module.ts b/src/auth-module/auth-module.ts index c9c60025..f6adc602 100644 --- a/src/auth-module/auth-module.ts +++ b/src/auth-module/auth-module.ts @@ -11,7 +11,7 @@ import setupActions from './auth-module.actions' const defaults = { namespace: 'auth', userService: '', // Set this to automatically populate the user (using an additional request) on login success. - serverAlias: null, + serverAlias: 'api', debug: false, state: {}, // for custom state getters: {}, // for custom getters diff --git a/src/index.ts b/src/index.ts index 1c9e8c88..f82c4d46 100644 --- a/src/index.ts +++ b/src/index.ts @@ -29,7 +29,7 @@ const defaultOptions: FeathersVuexOptions = { paramsForServer: [], // Custom query operators that are ignored in the find getter, but will pass through to the server. preferUpdate: false, // When true, calling model.save() will do an update instead of a patch. replaceItems: false, // Instad of merging in changes in the store, replace the entire record. - serverAlias: '', + serverAlias: 'api', skipRequestIfExists: false, // For get action, if the record already exists in store, skip the remote request whitelist: [] // Custom query operators that will be allowed in the find getter. } diff --git a/src/service-module/notes.md b/src/service-module/notes.md index 7e72cc0d..e79cecbd 100644 --- a/src/service-module/notes.md +++ b/src/service-module/notes.md @@ -89,7 +89,7 @@ Check out the tests for the best documentation. They've been reorganized. This ## Changes to Initialization -1. To assist in connecting with multiple FeathersJS API servers, a new `serverAlias` option is now required. This requires a simple addition to the initial options. +1. To assist in connecting with multiple FeathersJS API servers, a new `serverAlias` option is now available. Starting with version `2.0.0-pre.79`, the default value is `api`, so you only need to provide this if you want to connect to a second API. 2. The exports have changed. - (a) A new `BaseModel` is available. This is the base `FeathersVuexModel` which contains the model methods. Feel free to extend it and make it fit your awesome services! - (b) The `service` method has been renamed to `makeServicePlugin`. @@ -115,7 +115,7 @@ const { clients // (2e) } = feathersVuex(feathers, { idField: '_id', - serverAlias: 'myApi' // (1) + serverAlias: 'api' // (1) optional as of version 2.0.0-pre.79 }) class Todo extends BaseModel { From ff69aa879f2fe56dfbcc52aa5d7459999314599f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 17 Oct 2019 18:30:15 -0600 Subject: [PATCH 376/404] Add FeathersVuexFormWrapper --- src/FeathersVuexFormWrapper.md | 15 ++++ src/FeathersVuexFormWrapper.stories.js | 44 ++++++++++++ src/FeathersVuexFormWrapper.ts | 99 ++++++++++++++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 src/FeathersVuexFormWrapper.md create mode 100644 src/FeathersVuexFormWrapper.stories.js create mode 100644 src/FeathersVuexFormWrapper.ts diff --git a/src/FeathersVuexFormWrapper.md b/src/FeathersVuexFormWrapper.md new file mode 100644 index 00000000..aa8ba2f5 --- /dev/null +++ b/src/FeathersVuexFormWrapper.md @@ -0,0 +1,15 @@ + +# FeathersVuexFormWrapper + +```html + + + +``` diff --git a/src/FeathersVuexFormWrapper.stories.js b/src/FeathersVuexFormWrapper.stories.js new file mode 100644 index 00000000..ed6f24fa --- /dev/null +++ b/src/FeathersVuexFormWrapper.stories.js @@ -0,0 +1,44 @@ +import '../../assets/styles/tailwind.postcss' + +import FeathersVuexFormWrapper from './FeathersVuexFormWrapper' +import Readme from './README.md' + +import store from '../../store/store.dev' +import { models } from 'feathers-vuex' + +export default { + title: 'FeathersVuexFormWrapper', + parameters: { + component: FeathersVuexFormWrapper, + readme: { + sidebar: Readme + } + } +} + +export const Basic = () => ({ + components: { FeathersVuexFormWrapper }, + data: () => ({ + date: null, + UserModel: models.api.User + }), + store, + template: `
+ + + +
` +}) diff --git a/src/FeathersVuexFormWrapper.ts b/src/FeathersVuexFormWrapper.ts new file mode 100644 index 00000000..498ce256 --- /dev/null +++ b/src/FeathersVuexFormWrapper.ts @@ -0,0 +1,99 @@ +export default { + name: 'FeathersVuexFormWrapper', + model: { + prop: 'item', + event: 'update:item' + }, + props: { + item: { + type: Object, + required: true + }, + /** + * By default, when you call the `save` method, the cloned data will be + * committed to the store BEFORE saving tot he API server. Set + * `:eager="false"` to only update the store with the API server response. + */ + eager: { + type: Boolean, + default: true + }, + // Set to false to prevent re-cloning if the object updates. + watch: { + type: Boolean, + default: true + } + }, + data: () => ({ + clone: null, + isDirty: false + }), + computed: { + isNew() { + return (this.item && this.item.__isTemp) || false + } + }, + watch: { + item: { + handler: 'setup', + immediate: true, + deep: true + } + }, + methods: { + setup() { + if (this.item) { + this.isDirty = false + // Unwatch the clone to prevent running watchers during reclone + if (this.unwatchClone) { + this.unwatchClone() + } + + this.clone = this.item.clone() + + // Watch the new clone. + this.unwatchClone = this.$watch('clone', { + handler: 'markAsDirty', + deep: true + }) + } + }, + save(params) { + if (this.eager) { + this.clone.commit() + } + return this.clone.save(params).then(response => { + this.$emit('saved', response) + if (this.isNew) { + this.$emit('saved-new', response) + } + return response + }) + }, + reset() { + this.clone.reset() + this.$emit('reset', this.item) + }, + async remove() { + await this.item.remove() + this.$emit('removed', this.item) + return this.item + }, + markAsDirty() { + if (!this.isDirty) { + this.isDirty = true + } + } + }, + render() { + const { clone, save, reset, remove, isDirty, isNew } = this + return this.$scopedSlots.default({ + clone, + save, + reset, + remove, + isDirty, + isNew + }) + } +} From c74c8504d33485174b7c1a746e55b152e6a49c3f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 17 Oct 2019 22:47:15 -0600 Subject: [PATCH 377/404] Update vuepress --- yarn.lock | 1514 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 885 insertions(+), 629 deletions(-) diff --git a/yarn.lock b/yarn.lock index 3137763f..9806a592 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,43 +2,42 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" - integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== dependencies: "@babel/highlight" "^7.0.0" "@babel/core@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.0.tgz#6ed6a2881ad48a732c5433096d96d1b0ee5eb734" - integrity sha512-6Isr4X98pwXqHvtigw71CKgmhL1etZjPs5A67jL/w0TkLM9eqmFR40YrnJvEc1WnMZFsskjsmid8bHZyxKEAnw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/generator" "^7.5.0" - "@babel/helpers" "^7.5.0" - "@babel/parser" "^7.5.0" - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.5.0" - "@babel/types" "^7.5.0" + version "7.6.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.4.tgz#6ebd9fe00925f6c3e177bb726a188b5f578088ff" + integrity sha512-Rm0HGw101GY8FTzpWSyRbki/jzq+/PkNQJ+nSulrdY6gFGOsNseCqD6KHRYe2E+EdzuBdr2pxCp6s4Uk6eJ+XQ== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.6.4" + "@babel/helpers" "^7.6.2" + "@babel/parser" "^7.6.4" + "@babel/template" "^7.6.0" + "@babel/traverse" "^7.6.3" + "@babel/types" "^7.6.3" convert-source-map "^1.1.0" debug "^4.1.0" json5 "^2.1.0" - lodash "^4.17.11" + lodash "^4.17.13" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.5.0.tgz#f20e4b7a91750ee8b63656073d843d2a736dca4a" - integrity sha512-1TTVrt7J9rcG5PMjvO7VEG3FrEoEJNHxumRq66GemPmzboLWtIjjcJgk8rokuAS7IiRSpgVSu5Vb9lc99iJkOA== +"@babel/generator@^7.5.0", "@babel/generator@^7.6.3", "@babel/generator@^7.6.4": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.4.tgz#a4f8437287bf9671b07f483b76e3bb731bc97671" + integrity sha512-jsBuXkFoZxk0yWLyGI9llT9oiQ2FeTASmRFE32U+aaDTfoE92t78eroO7PTpU/OrYq38hlcDM6vbfLDaOLy+7w== dependencies: - "@babel/types" "^7.5.0" + "@babel/types" "^7.6.3" jsesc "^2.5.1" - lodash "^4.17.11" + lodash "^4.17.13" source-map "^0.5.0" - trim-right "^1.0.1" "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" @@ -64,26 +63,26 @@ "@babel/traverse" "^7.4.4" "@babel/types" "^7.4.4" -"@babel/helper-create-class-features-plugin@^7.4.4", "@babel/helper-create-class-features-plugin@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.5.0.tgz#02edb97f512d44ba23b3227f1bf2ed43454edac5" - integrity sha512-EAoMc3hE5vE5LNhMqDOwB1usHvmRjCDAnH8CD4PVkX9/Yr3W/tcz8xE8QvdZxfsFBDICwZnF2UTHIqslRpvxmA== +"@babel/helper-create-class-features-plugin@^7.5.5", "@babel/helper-create-class-features-plugin@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.6.0.tgz#769711acca889be371e9bc2eb68641d55218021f" + integrity sha512-O1QWBko4fzGju6VoVvrZg0RROCVifcLxiApnGP3OWfWzvxRZFCoBD81K5ur5e3bVY2Vf/5rIJm8cqPKn8HUJng== dependencies: "@babel/helper-function-name" "^7.1.0" - "@babel/helper-member-expression-to-functions" "^7.0.0" + "@babel/helper-member-expression-to-functions" "^7.5.5" "@babel/helper-optimise-call-expression" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.4.4" + "@babel/helper-replace-supers" "^7.5.5" "@babel/helper-split-export-declaration" "^7.4.4" -"@babel/helper-define-map@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz#6969d1f570b46bdc900d1eba8e5d59c48ba2c12a" - integrity sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg== +"@babel/helper-define-map@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz#3dec32c2046f37e09b28c93eb0b103fd2a25d369" + integrity sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg== dependencies: "@babel/helper-function-name" "^7.1.0" - "@babel/types" "^7.4.4" - lodash "^4.17.11" + "@babel/types" "^7.5.5" + lodash "^4.17.13" "@babel/helper-explode-assignable-expression@^7.1.0": version "7.1.0" @@ -116,12 +115,12 @@ dependencies: "@babel/types" "^7.4.4" -"@babel/helper-member-expression-to-functions@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz#8cd14b0a0df7ff00f009e7d7a436945f47c7a16f" - integrity sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg== +"@babel/helper-member-expression-to-functions@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz#1fb5b8ec4453a93c439ee9fe3aeea4a84b76b590" + integrity sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA== dependencies: - "@babel/types" "^7.0.0" + "@babel/types" "^7.5.5" "@babel/helper-module-imports@^7.0.0": version "7.0.0" @@ -131,16 +130,16 @@ "@babel/types" "^7.0.0" "@babel/helper-module-transforms@^7.1.0", "@babel/helper-module-transforms@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz#96115ea42a2f139e619e98ed46df6019b94414b8" - integrity sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w== + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz#f84ff8a09038dcbca1fd4355661a500937165b4a" + integrity sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-simple-access" "^7.1.0" "@babel/helper-split-export-declaration" "^7.4.4" "@babel/template" "^7.4.4" - "@babel/types" "^7.4.4" - lodash "^4.17.11" + "@babel/types" "^7.5.5" + lodash "^4.17.13" "@babel/helper-optimise-call-expression@^7.0.0": version "7.0.0" @@ -155,11 +154,11 @@ integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== "@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.4.4.tgz#a47e02bc91fb259d2e6727c2a30013e3ac13c4a2" - integrity sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q== + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" + integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== dependencies: - lodash "^4.17.11" + lodash "^4.17.13" "@babel/helper-remap-async-to-generator@^7.1.0": version "7.1.0" @@ -172,15 +171,15 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.0.0" -"@babel/helper-replace-supers@^7.1.0", "@babel/helper-replace-supers@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz#aee41783ebe4f2d3ab3ae775e1cc6f1a90cefa27" - integrity sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg== +"@babel/helper-replace-supers@^7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz#f84ce43df031222d2bad068d2626cb5799c34bc2" + integrity sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg== dependencies: - "@babel/helper-member-expression-to-functions" "^7.0.0" + "@babel/helper-member-expression-to-functions" "^7.5.5" "@babel/helper-optimise-call-expression" "^7.0.0" - "@babel/traverse" "^7.4.4" - "@babel/types" "^7.4.4" + "@babel/traverse" "^7.5.5" + "@babel/types" "^7.5.5" "@babel/helper-simple-access@^7.1.0": version "7.1.0" @@ -207,14 +206,14 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.2.0" -"@babel/helpers@^7.5.0": - version "7.5.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.5.1.tgz#65407c741a56ddd59dd86346cd112da3de912db3" - integrity sha512-rVOTDv8sH8kNI72Unenusxw6u+1vEepZgLxeV+jHkhsQlYhzVhzL1EpfoWT7Ub3zpWSv2WV03V853dqsnyoQzA== +"@babel/helpers@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.6.2.tgz#681ffe489ea4dcc55f23ce469e58e59c1c045153" + integrity sha512-3/bAUL8zZxYs1cdX2ilEE0WobqbCmKWr/889lf2SS0PpDcpEIY8pb1CCyz0pEcX3pEb+MCbks1jIokz2xLtGTA== dependencies: - "@babel/template" "^7.4.4" - "@babel/traverse" "^7.5.0" - "@babel/types" "^7.5.0" + "@babel/template" "^7.6.0" + "@babel/traverse" "^7.6.2" + "@babel/types" "^7.6.0" "@babel/highlight@^7.0.0": version "7.5.0" @@ -225,11 +224,16 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.4.4", "@babel/parser@^7.5.0": +"@babel/parser@^7.0.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.0.tgz#3e0713dff89ad6ae37faec3b29dcfc5c979770b7" integrity sha512-I5nW8AhGpOXGCCNYGc+p7ExQIBxRFnS2fd/d862bNOKvmoEPjYPcfIjsfdy0ujagYOIYPczKgD9l3FsgTkAzKA== +"@babel/parser@^7.5.0", "@babel/parser@^7.6.0", "@babel/parser@^7.6.3", "@babel/parser@^7.6.4": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.4.tgz#cb9b36a7482110282d5cb6dd424ec9262b473d81" + integrity sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A== + "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" @@ -240,19 +244,19 @@ "@babel/plugin-syntax-async-generators" "^7.2.0" "@babel/plugin-proposal-class-properties@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.0.tgz#5bc6a0537d286fcb4fd4e89975adbca334987007" - integrity sha512-9L/JfPCT+kShiiTTzcnBJ8cOwdKVmlC1RcCf9F0F9tERVrM4iWtWnXtjWCRqNm2la2BxO1MPArWNsU9zsSJWSQ== + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz#a974cfae1e37c3110e71f3c6a2e48b8e71958cd4" + integrity sha512-AF79FsnWFxjlaosgdi421vmYG6/jg79bVD0dpD44QdgobzHKuLZ6S3vl8la9qIeSwGi8i1fS0O1mfuDAAdo1/A== dependencies: - "@babel/helper-create-class-features-plugin" "^7.5.0" + "@babel/helper-create-class-features-plugin" "^7.5.5" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-decorators@^7.1.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.4.4.tgz#de9b2a1a8ab0196f378e2a82f10b6e2a36f21cc0" - integrity sha512-z7MpQz3XC/iQJWXH9y+MaWcLPNSMY9RQSthrLzak8R8hCj0fuyNk+Dzi9kfNe/JxxlWQ2g7wkABbgWjW36MTcw== + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.6.0.tgz#6659d2572a17d70abd68123e89a12a43d90aa30c" + integrity sha512-ZSyYw9trQI50sES6YxREXKu+4b7MAg6Qx2cvyDDYjP2Hpzd3FleOUwC9cqn1+za8d0A2ZU8SHujxFao956efUg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.4.4" + "@babel/helper-create-class-features-plugin" "^7.6.0" "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-decorators" "^7.2.0" @@ -265,9 +269,9 @@ "@babel/plugin-syntax-json-strings" "^7.2.0" "@babel/plugin-proposal-object-rest-spread@^7.3.4": - version "7.5.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.1.tgz#5788ab097c63135e4236548b4f112bfce09dd394" - integrity sha512-PVGXx5LYHcT7L4MdoE+rM5uq68IKlvU9lljVQ4OXY6aUEnGvezcGbM4VNY57Ug+3R2Zg/nYHlEdiWoIBoRA0mw== + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz#8ffccc8f3a6545e9f78988b6bf4fe881b88e8096" + integrity sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-syntax-object-rest-spread" "^7.2.0" @@ -281,13 +285,13 @@ "@babel/plugin-syntax-optional-catch-binding" "^7.2.0" "@babel/plugin-proposal-unicode-property-regex@^7.2.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz#501ffd9826c0b91da22690720722ac7cb1ca9c78" - integrity sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA== + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.6.2.tgz#05413762894f41bfe42b9a5e80919bd575dcc802" + integrity sha512-NxHETdmpeSCtiatMRYWVJo7266rrvAC3DTeG5exQBIH/fMIUK7ejDNznBbn3HQl/o9peymRRg7Yqkx6PdUXmMw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" + regexpu-core "^4.6.0" "@babel/plugin-syntax-async-generators@^7.2.0": version "7.2.0" @@ -362,24 +366,24 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-block-scoping@^7.3.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz#c13279fabf6b916661531841a23c4b7dae29646d" - integrity sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA== + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz#6e854e51fbbaa84351b15d4ddafe342f3a5d542a" + integrity sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - lodash "^4.17.11" + lodash "^4.17.13" "@babel/plugin-transform-classes@^7.3.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz#0ce4094cdafd709721076d3b9c38ad31ca715eb6" - integrity sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw== + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz#d094299d9bd680a14a2a0edae38305ad60fb4de9" + integrity sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg== dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" - "@babel/helper-define-map" "^7.4.4" + "@babel/helper-define-map" "^7.5.5" "@babel/helper-function-name" "^7.1.0" "@babel/helper-optimise-call-expression" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.4.4" + "@babel/helper-replace-supers" "^7.5.5" "@babel/helper-split-export-declaration" "^7.4.4" globals "^11.1.0" @@ -391,20 +395,20 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-destructuring@^7.2.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz#f6c09fdfe3f94516ff074fe877db7bc9ef05855a" - integrity sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ== + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz#44bbe08b57f4480094d57d9ffbcd96d309075ba6" + integrity sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-dotall-regex@^7.2.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz#361a148bc951444312c69446d76ed1ea8e4450c3" - integrity sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg== + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.6.2.tgz#44abb948b88f0199a627024e1508acaf8dc9b2f9" + integrity sha512-KGKT9aqKV+9YMZSkowzYoYEiHqgaDhGmPNZlZxX6UeHC4z30nC1J9IrZuGqbYFB1jaIGdv91ujpze0exiVK8bA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" + regexpu-core "^4.6.0" "@babel/plugin-transform-duplicate-keys@^7.2.0": version "7.5.0" @@ -453,9 +457,9 @@ babel-plugin-dynamic-import-node "^2.3.0" "@babel/plugin-transform-modules-commonjs@^7.2.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz#425127e6045231360858eeaa47a71d75eded7a74" - integrity sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ== + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.6.0.tgz#39dfe957de4420445f1fcf88b68a2e4aa4515486" + integrity sha512-Ma93Ix95PNSEngqomy5LSBMAQvYKVe3dy+JlVJSHEXZR5ASL9lQBedMiCyVtmTLraIDVRE3ZjTZvmXXD2Ozw3g== dependencies: "@babel/helper-module-transforms" "^7.4.4" "@babel/helper-plugin-utils" "^7.0.0" @@ -480,11 +484,11 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-named-capturing-groups-regex@^7.3.0": - version "7.4.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.5.tgz#9d269fd28a370258199b4294736813a60bbdd106" - integrity sha512-z7+2IsWafTBbjNsOxU/Iv5CvTJlr5w4+HGu1HovKYTtgJ362f7kBcQglkfmlspKKZ3bgrbSGvLfNx++ZJgCWsg== + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.3.tgz#aaa6e409dd4fb2e50b6e2a91f7e3a3149dbce0cf" + integrity sha512-jTkk7/uE6H2s5w6VlMHeWuH+Pcy2lmdwFoeWCVnvIrDUnB5gQqTVI8WfmEAhF2CDEarGrknZcmSFg1+bkfCoSw== dependencies: - regexp-tree "^0.1.6" + regexpu-core "^4.6.0" "@babel/plugin-transform-new-target@^7.0.0": version "7.4.4" @@ -494,12 +498,12 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-object-super@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz#b35d4c10f56bab5d650047dad0f1d8e8814b6598" - integrity sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg== + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz#c70021df834073c65eb613b8679cc4a381d1a9f9" + integrity sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ== dependencies: "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.1.0" + "@babel/helper-replace-supers" "^7.5.5" "@babel/plugin-transform-parameters@^7.2.0": version "7.4.4" @@ -518,9 +522,9 @@ regenerator-transform "^0.14.0" "@babel/plugin-transform-runtime@^7.4.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.5.0.tgz#45242c2c9281158c5f06d25beebac63e498a284e" - integrity sha512-LmPIZOAgTLl+86gR9KjLXex6P/lRz1fWEjTz6V6QZMmKie51ja3tvzdwORqhHc4RWR8TcZ5pClpRWs0mlaA2ng== + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.6.2.tgz#2669f67c1fae0ae8d8bf696e4263ad52cb98b6f8" + integrity sha512-cqULw/QB4yl73cS5Y0TZlQSjDvNkzDbu0FurTZyHlJpWE5T3PCMdnyV+xXoH1opr1ldyHODe3QAX3OMAii5NxA== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/helper-plugin-utils" "^7.0.0" @@ -535,9 +539,9 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-spread@^7.2.0": - version "7.2.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz#3103a9abe22f742b6d406ecd3cd49b774919b406" - integrity sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w== + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz#fc77cf798b24b10c46e1b51b1b88c2bf661bb8dd" + integrity sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -565,13 +569,13 @@ "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-transform-unicode-regex@^7.2.0": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz#ab4634bb4f14d36728bf5978322b35587787970f" - integrity sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA== + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.6.2.tgz#b692aad888a7e8d8b1b214be6b9dc03d5031f698" + integrity sha512-orZI6cWlR3nk2YmYdb0gImrgCUwb5cBUwjf6Ks6dvNVvXERkwtJWOQaEOjPiu0Gu1Tq6Yq/hruCZZOOi9F34Dw== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.5.4" + regexpu-core "^4.6.0" "@babel/preset-env@^7.0.0 < 7.4.0": version "7.3.4" @@ -623,30 +627,30 @@ semver "^5.3.0" "@babel/runtime-corejs2@^7.2.0": - version "7.5.1" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.5.1.tgz#40664f970f6b732f1a86ed05a91b1c7e01e41926" - integrity sha512-YB7j61HG5hAuBcFqTDOECRdc6b5YD0KN4L6i4dF4jAgtRCtWlSFQoMsqTfu8YvAqPVuYOYsWamfgPN4TM0NIVQ== + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.6.3.tgz#de3f446b3fb688b98cbd220474d1a7cad909bcb8" + integrity sha512-nuA2o+rgX2+PrNTZ063ehncVcg7sn+tU71BB81SaWRVUbGwCOlb0+yQA1e0QqmzOfRSYOxfvf8cosYqFbJEiwQ== dependencies: core-js "^2.6.5" regenerator-runtime "^0.13.2" "@babel/runtime@^7.0.0": - version "7.5.1" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.1.tgz#51b56e216e87103ab3f7d6040b464c538e242888" - integrity sha512-g+hmPKs16iewFSmW57NkH9xpPkuYD1RV3UE2BCkXx9j+nhhRb9hsiSxPmEa67j35IecTQdn4iyMtHMbt5VoREg== + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.3.tgz#935122c74c73d2240cafd32ddb5fc2a6cd35cf1f" + integrity sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA== dependencies: regenerator-runtime "^0.13.2" -"@babel/template@^7.1.0", "@babel/template@^7.4.4": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237" - integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw== +"@babel/template@^7.1.0", "@babel/template@^7.4.4", "@babel/template@^7.6.0": + version "7.6.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6" + integrity sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.4.4" - "@babel/types" "^7.4.4" + "@babel/parser" "^7.6.0" + "@babel/types" "^7.6.0" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.0": +"@babel/traverse@^7.0.0": version "7.5.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.0.tgz#4216d6586854ef5c3c4592dab56ec7eb78485485" integrity sha512-SnA9aLbyOCcnnbQEGwdfBggnc142h/rbqqsXcaATj2hZcegCl903pUD/lfpsNBlBSuWow/YDfRyJuWi2EPR5cg== @@ -661,13 +665,28 @@ globals "^11.1.0" lodash "^4.17.11" -"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.4.4", "@babel/types@^7.5.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.0.tgz#e47d43840c2e7f9105bc4d3a2c371b4d0c7832ab" - integrity sha512-UFpDVqRABKsW01bvw7/wSUe56uy6RXM5+VJibVVAybDGxEW25jdwiFJEf7ASvSaC7sN7rbE/l3cLp2izav+CtQ== +"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.2", "@babel/traverse@^7.6.3": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.3.tgz#66d7dba146b086703c0fb10dd588b7364cec47f9" + integrity sha512-unn7P4LGsijIxaAJo/wpoU11zN+2IaClkQAxcJWBNCMS6cmVh802IyLHNkAjQ0iYnRS3nnxk5O3fuXW28IMxTw== + dependencies: + "@babel/code-frame" "^7.5.5" + "@babel/generator" "^7.6.3" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.4.4" + "@babel/parser" "^7.6.3" + "@babel/types" "^7.6.3" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.4.4", "@babel/types@^7.5.0", "@babel/types@^7.5.5", "@babel/types@^7.6.0", "@babel/types@^7.6.3": + version "7.6.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.3.tgz#3f07d96f854f98e2fbd45c64b0cb942d11e8ba09" + integrity sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA== dependencies: esutils "^2.0.2" - lodash "^4.17.11" + lodash "^4.17.13" to-fast-properties "^2.0.0" "@feathersjs/adapter-commons@^2.0.0": @@ -818,9 +837,9 @@ integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== "@types/node@*": - version "12.0.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.12.tgz#cc791b402360db1eaf7176479072f91ee6c6c7ca" - integrity sha512-Uy0PN4R5vgBUXFoJrKryf5aTk3kJ8Rv3PdlHjl6UaX+Cqp1QE0yPQ68MPXGrZOfG7gZVNDIJZYyot0B9ubXUrQ== + version "12.11.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.1.tgz#1fd7b821f798b7fa29f667a1be8f3442bb8922a3" + integrity sha512-TJtwsqZ39pqcljJpajeoofYRfeZ7/I/OMUQ5pR4q5wOKf2ocrUvBAZUMhWsOvKx3dVc/aaV5GluBivt0sWqA5A== "@types/npm@^2.0.30": version "2.0.30" @@ -896,9 +915,9 @@ svg-tags "^1.0.0" "@vue/babel-preset-app@^3.1.1": - version "3.9.2" - resolved "https://registry.yarnpkg.com/@vue/babel-preset-app/-/babel-preset-app-3.9.2.tgz#b72a9b06abbe3f8f272783be13951271277be338" - integrity sha512-0suuCbu4jkVcVYBjPmuKxeDbrhwThYZHu3DUmtsVuOzFEGeXmco60VmXveniL/bnDUdZyknSuYP4FxgS34gw9w== + version "3.12.0" + resolved "https://registry.yarnpkg.com/@vue/babel-preset-app/-/babel-preset-app-3.12.0.tgz#76cc9ee2c35725ce673c78321b91bb60210c1c75" + integrity sha512-zUeHItaHrmTAH//kjdvKp0PAzIeveCejYEpYjqstJ07FTc8uT2UYnSITB1pvv1LZocUMAFlJ3soTcHH6pZU68Q== dependencies: "@babel/helper-module-imports" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" @@ -915,16 +934,16 @@ core-js "^2.6.5" "@vue/babel-preset-jsx@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@vue/babel-preset-jsx/-/babel-preset-jsx-1.0.0.tgz#e515cd453a5a8ea6b0f30b2bb92f266d8ab4e9f5" - integrity sha512-5CbDu/QHS+TtQNw5aYAffiMxBBB2Eo9+RJpS8X+6FJbdG5Rvc4TVipEqkrg0pJviWadNg7TEy0Uz4o7VNXeIZw== + version "1.1.1" + resolved "https://registry.yarnpkg.com/@vue/babel-preset-jsx/-/babel-preset-jsx-1.1.1.tgz#3a74642ca0ecea10aae13649df5ff70f9d24a6f5" + integrity sha512-SeyndwQZc8MAOkhbJaC34ocTwcKekKkwrwnTMC3YF8VmGp5IQWW5gPIU66bqO9WFBXFA3J3ANsUbP2pj8q8KdQ== dependencies: "@vue/babel-helper-vue-jsx-merge-props" "^1.0.0" "@vue/babel-plugin-transform-vue-jsx" "^1.0.0" "@vue/babel-sugar-functional-vue" "^1.0.0" "@vue/babel-sugar-inject-h" "^1.0.0" - "@vue/babel-sugar-v-model" "^1.0.0" - "@vue/babel-sugar-v-on" "^1.0.0" + "@vue/babel-sugar-v-model" "^1.1.1" + "@vue/babel-sugar-v-on" "^1.1.0" "@vue/babel-sugar-functional-vue@^1.0.0": version "1.0.0" @@ -940,10 +959,10 @@ dependencies: "@babel/plugin-syntax-jsx" "^7.2.0" -"@vue/babel-sugar-v-model@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.0.0.tgz#f4da56aa67f65a349bd2c269a95e72e601af4613" - integrity sha512-Pfg2Al0io66P1eO6zUbRIgpyKCU2qTnumiE0lao/wA/uNdb7Dx5Tfd1W6tO5SsByETPnEs8i8+gawRIXX40rFw== +"@vue/babel-sugar-v-model@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.1.1.tgz#a0f0750fcee20769805a20178299eebd4babf25a" + integrity sha512-qiPbdUTiqNQdhXzvWQMVfrYGHCiMmscY7j/cudLxdxWZ8AFhgPRVlniVgaWIT7A1iOjs92e8U6qVyqkf0d4ZrA== dependencies: "@babel/plugin-syntax-jsx" "^7.2.0" "@vue/babel-helper-vue-jsx-merge-props" "^1.0.0" @@ -952,19 +971,19 @@ html-tags "^2.0.0" svg-tags "^1.0.0" -"@vue/babel-sugar-v-on@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.0.0.tgz#a633ee8fe205763e865b011246981b7f89668033" - integrity sha512-2aqJaDLKdSSGlxZU+GjFERaSNUaa6DQreV+V/K4W/6Lxj8520/r1lChWEa/zuAoPD2Vhy0D2QrqqO+I0D6CkKw== +"@vue/babel-sugar-v-on@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.1.0.tgz#1f2b35eeeabb87eaf8925931f4d34fd8e6404a45" + integrity sha512-8DwAj/RLpmrDP4eZ3erJcKcyuLArLUYagNODTsSQrMdG5zmLJoFFtEjODfYRh/XxM2wXv9Wxe+HAB41FQxxwQA== dependencies: "@babel/plugin-syntax-jsx" "^7.2.0" "@vue/babel-plugin-transform-vue-jsx" "^1.0.0" camelcase "^5.0.0" -"@vue/component-compiler-utils@^2.5.1": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-2.6.0.tgz#aa46d2a6f7647440b0b8932434d22f12371e543b" - integrity sha512-IHjxt7LsOFYc0DkTncB7OXJL7UzwOLPPQCfEUNyxL2qt+tF12THV+EO33O1G2Uk4feMSWua3iD39Itszx0f0bw== +"@vue/component-compiler-utils@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.0.0.tgz#d16fa26b836c06df5baaeb45f3d80afc47e35634" + integrity sha512-am+04/0UX7ektcmvhYmrf84BDVAD8afFOf4asZjN84q8xzxFclbk5x0MtxuKGfp+zjN5WWPJn3fjFAWtDdIGSw== dependencies: consolidate "^0.15.1" hash-sum "^1.0.2" @@ -1001,18 +1020,18 @@ dom-event-types "^1.0.0" lodash "^4.17.4" -"@vuepress/core@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@vuepress/core/-/core-1.0.2.tgz#75d0c6ccb4be92c6674c3bbfbe25639c8239921b" - integrity sha512-PUMaxq44wEuqXHutcmxj6q9cCRS4kZ1nyBvvHr9AIuxJflgYDw/k8wxhYuZjsxVWhpJjsPywLGNRyLN88vJcqQ== +"@vuepress/core@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@vuepress/core/-/core-1.2.0.tgz#8e0c636b7f8676202fdd1ecfbe31bfe245dab2a8" + integrity sha512-ZIsUkQIF+h4Yk6q4okoRnRwRhcYePu/kNiL0WWPDGycjai8cFqFjLDP/tJjfTKXmn9A62j2ETjSwaiMxCtDkyw== dependencies: "@babel/core" "^7.0.0" "@vue/babel-preset-app" "^3.1.1" - "@vuepress/markdown" "^1.0.2" - "@vuepress/markdown-loader" "^1.0.2" - "@vuepress/plugin-last-updated" "^1.0.2" - "@vuepress/plugin-register-components" "^1.0.2" - "@vuepress/shared-utils" "^1.0.2" + "@vuepress/markdown" "^1.2.0" + "@vuepress/markdown-loader" "^1.2.0" + "@vuepress/plugin-last-updated" "^1.2.0" + "@vuepress/plugin-register-components" "^1.2.0" + "@vuepress/shared-utils" "^1.2.0" autoprefixer "^9.5.1" babel-loader "^8.0.4" cache-loader "^3.0.0" @@ -1022,7 +1041,7 @@ cross-spawn "^6.0.5" css-loader "^2.1.1" file-loader "^3.0.1" - js-yaml "^3.11.0" + js-yaml "^3.13.1" lru-cache "^5.1.1" mini-css-extract-plugin "0.6.0" optimize-css-assets-webpack-plugin "^5.0.1" @@ -1031,34 +1050,34 @@ postcss-safe-parser "^4.0.1" toml "^3.0.0" url-loader "^1.0.1" - vue "^2.5.16" - vue-loader "^15.2.4" - vue-router "^3.0.2" - vue-server-renderer "^2.5.16" - vue-template-compiler "^2.5.16" + vue "^2.6.10" + vue-loader "^15.7.1" + vue-router "^3.1.3" + vue-server-renderer "^2.6.10" + vue-template-compiler "^2.6.10" vuepress-html-webpack-plugin "^3.2.0" - vuepress-plugin-container "^2.0.0" + vuepress-plugin-container "^2.0.2" webpack "^4.8.1" webpack-chain "^4.6.0" webpack-dev-server "^3.5.1" webpack-merge "^4.1.2" webpackbar "3.2.0" -"@vuepress/markdown-loader@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@vuepress/markdown-loader/-/markdown-loader-1.0.2.tgz#b068df3049f6b63cfee329f85aed3bb0aa9e7ab0" - integrity sha512-ljD2mVDpeq0VvCHMHfemGW+0fhLmOMldtWIAYQ/I8LjLuV2qknAwjzZ4tEAqveaVIFMUBRP3V6d8YGIK9dr6kg== +"@vuepress/markdown-loader@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@vuepress/markdown-loader/-/markdown-loader-1.2.0.tgz#f8972014616b4ab46a99c9aaac2dd414d437411c" + integrity sha512-gOZzoHjfp/W6t+qKBRdbHS/9TwRnNuhY7V+yFzxofNONFHQULofIN/arG+ptYc2SuqJ541jqudNQW+ldHNMC2w== dependencies: - "@vuepress/markdown" "^1.0.2" + "@vuepress/markdown" "^1.2.0" loader-utils "^1.1.0" lru-cache "^5.1.1" -"@vuepress/markdown@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@vuepress/markdown/-/markdown-1.0.2.tgz#436c5aa74e22cf7f6705b99c8892b6ba2d84cd0a" - integrity sha512-ddl0FG11aeidjcFYYNU53xZ1WLEYb3g5/hijfSCEQKyMv+gDXy7Z3/uc4I4oH2UNtB2Wpo3pQoeKGY56edcBuA== +"@vuepress/markdown@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@vuepress/markdown/-/markdown-1.2.0.tgz#7c457e0fab52ef8ac4dd1898ae450bc3aec30746" + integrity sha512-RLRQmTu5wJbCO4Qv+J0K53o5Ew7nAGItLwWyzCbIUB6pRsya3kqSCViWQVlKlS53zFTmRHuAC9tJMRdzly3mCA== dependencies: - "@vuepress/shared-utils" "^1.0.2" + "@vuepress/shared-utils" "^1.2.0" markdown-it "^8.4.1" markdown-it-anchor "^5.0.2" markdown-it-chain "^1.3.0" @@ -1066,43 +1085,43 @@ markdown-it-table-of-contents "^0.4.0" prismjs "^1.13.0" -"@vuepress/plugin-active-header-links@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@vuepress/plugin-active-header-links/-/plugin-active-header-links-1.0.2.tgz#df04f7fc21640d3e0a0b704037e360e75974d1a2" - integrity sha512-Wo9NP55OOJ/vGFnYwStZcDBJMnf1gNDL159K7oiiEltuz8kjZBqmtsIjQXOzXFjA8voYh/RVL48Sr4eGCDd7LQ== +"@vuepress/plugin-active-header-links@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@vuepress/plugin-active-header-links/-/plugin-active-header-links-1.2.0.tgz#46495c89e51a95e57139be007dffbcae4b229260" + integrity sha512-vdi7l96pElJvEmcx6t9DWJNH25TIurS8acjN3+b7o4NzdaszFn5j6klN6WtI4Z+5BVDrxHP5W1F3Ebw8SZyupA== dependencies: - lodash.throttle "^4.1.1" + lodash.debounce "^4.0.8" -"@vuepress/plugin-last-updated@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@vuepress/plugin-last-updated/-/plugin-last-updated-1.0.2.tgz#c839c5fb585c469a8c2ff70c16204dd72478545a" - integrity sha512-SwugVHcllUwy9WPqtWWM+hUEvH6SDPFJAHnpIs0kXJmaxIIipqF/9+CokT5QzxzGVHeYPU4YKtLadEIXdRcXsw== +"@vuepress/plugin-last-updated@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@vuepress/plugin-last-updated/-/plugin-last-updated-1.2.0.tgz#7b34065b793848b0482a222b7a6f1b7df3668cdc" + integrity sha512-j4uZb/MXDyG+v9QCG3T/rkiaOhC/ib7NKCt1cjn3GOwvWTDmB5UZm9EBhUpbDNrBgxW+SaHOe3kMVNO8bGOTGw== dependencies: cross-spawn "^6.0.5" -"@vuepress/plugin-nprogress@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@vuepress/plugin-nprogress/-/plugin-nprogress-1.0.2.tgz#3fae13c8af23292cf324d159c77e4d0ffc3133ab" - integrity sha512-degCJe2Z0eHbYblUGQXuDMIZSwH7twQcbWtkuH8goxXNilvtVxtWvBkUJouJ9RN3RuSk7EfPT171mrwq9yqbUg== +"@vuepress/plugin-nprogress@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@vuepress/plugin-nprogress/-/plugin-nprogress-1.2.0.tgz#ff6166946a0b118a39a562acb57983529afce4d2" + integrity sha512-0apt3Dp6XVCOkLViX6seKSEJgARihi+pX3/r8j8ndFp9Y+vmgLFZnQnGE5iKNi1ty+A6PZOK0RQcBjwTAU4pAw== dependencies: nprogress "^0.2.0" -"@vuepress/plugin-register-components@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@vuepress/plugin-register-components/-/plugin-register-components-1.0.2.tgz#504c190b1c1836e3428d90749a2dbd59f6e596b9" - integrity sha512-iqUq4kgNdVHba0cZJLv81DfB9ZsTdJY7gynN0NYHFwDEjsdOh1cRMgteuWa/mmK9XfopMO5oysD9WDhzCiIjfQ== +"@vuepress/plugin-register-components@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@vuepress/plugin-register-components/-/plugin-register-components-1.2.0.tgz#95aa0e0af94b2758b26ab98814c43b0f7bcd502b" + integrity sha512-C32b8sbGtDEX8I3SUUKS/w2rThiRFiKxmzNcJD996me7VY/4rgmZ8CxGtb6G9wByVoK0UdG1SOkrgOPdSCm80A== dependencies: - "@vuepress/shared-utils" "^1.0.2" + "@vuepress/shared-utils" "^1.2.0" -"@vuepress/plugin-search@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@vuepress/plugin-search/-/plugin-search-1.0.2.tgz#6d43fb46b207d48b797a5bc5b01824662db4684d" - integrity sha512-LCFZLp+adppdHETIEARwQhczj+mdpa+D25qL9RNmYxzU9mF6qItYNLl57P6omGU2Vr8frAc+rWgjbi4cjkbCvQ== +"@vuepress/plugin-search@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@vuepress/plugin-search/-/plugin-search-1.2.0.tgz#0b27c467b7fd42bd4d9e32de0fe2fb81a24bd311" + integrity sha512-QU3JfnMfImDAArbJOVH1q1iCDE5QrT99GLpNGo6KQYZWqY1TWAbgyf8C2hQdaI03co1lkU2Wn/iqzHJ5WHlueg== -"@vuepress/shared-utils@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@vuepress/shared-utils/-/shared-utils-1.0.2.tgz#4e1342748b7594fe4fde9dce3bf201538fa5ca67" - integrity sha512-QyNV76Dn0u2ooXbC3AXJZrQLuTNS4i8xSmJqZWsel2ooJKknXP3UIMIENcK1QFHnlIACznyV53u9hRAYBaZEWQ== +"@vuepress/shared-utils@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@vuepress/shared-utils/-/shared-utils-1.2.0.tgz#8d9ab40c24f75f027ef32c2ad0169f0f08e949fa" + integrity sha512-wo5Ng2/xzsmIYCzvWxgLFlDBp7FkmJp2shAkbSurLNAh1vixhs0+LyDxsk01+m34ktJSp9rTUUsm6khw/Fvo0w== dependencies: chalk "^2.3.2" diacritics "^1.3.0" @@ -1114,18 +1133,20 @@ semver "^6.0.0" upath "^1.1.0" -"@vuepress/theme-default@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@vuepress/theme-default/-/theme-default-1.0.2.tgz#7678c4755db9d891effee838991287d31ae9c5ed" - integrity sha512-fawiYshvQWXyaEgMXcyqj7j0atHLysIA2AzFt4K6y29WaMfiIAPE9lsxymTzT4zkc/T6nRP/TqwiuUaOK12wkw== +"@vuepress/theme-default@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@vuepress/theme-default/-/theme-default-1.2.0.tgz#3303af21a00031a3482ed1c494508234f545cbf1" + integrity sha512-mJxAMYQQv4OrGFsArMlONu8RpCzPUVx81dumkyTT4ay5PXAWTj+WDeFQLOT3j0g9QrDJGnHhbiw2aS+R/0WUyQ== dependencies: - "@vuepress/plugin-active-header-links" "^1.0.2" - "@vuepress/plugin-nprogress" "^1.0.2" - "@vuepress/plugin-search" "^1.0.2" + "@vuepress/plugin-active-header-links" "^1.2.0" + "@vuepress/plugin-nprogress" "^1.2.0" + "@vuepress/plugin-search" "^1.2.0" docsearch.js "^2.5.2" + lodash "^4.17.15" stylus "^0.54.5" stylus-loader "^3.0.2" - vuepress-plugin-container "^2.0.0" + vuepress-plugin-container "^2.0.2" + vuepress-plugin-smooth-scroll "^0.0.3" "@webassemblyjs/ast@1.8.5": version "1.8.5" @@ -1311,11 +1332,6 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -acorn-dynamic-import@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" - integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== - acorn-globals@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.2.tgz#4e2c2313a597fd589720395f6354b41cd5ec8006" @@ -1334,11 +1350,16 @@ acorn-walk@^6.0.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== -acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.4, acorn@^6.0.5, acorn@^6.0.7: +acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.4, acorn@^6.0.7: version "6.2.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.0.tgz#67f0da2fc339d6cfb5d6fb244fd449f33cd8bbe3" integrity sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw== +acorn@^6.2.1: + version "6.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" + integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== + after@0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" @@ -1361,12 +1382,12 @@ ajv-errors@^1.0.0: resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== -ajv-keywords@^3.0.0, ajv-keywords@^3.1.0: +ajv-keywords@^3.0.0, ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== -ajv@^6.0.1, ajv@^6.1.0, ajv@^6.5.0, ajv@^6.5.5, ajv@^6.9.1: +ajv@^6.0.1, ajv@^6.5.0, ajv@^6.9.1: version "6.10.1" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.1.tgz#ebf8d3af22552df9dd049bfbe50cc2390e823593" integrity sha512-w1YQaVGNC6t2UCPjEawK/vo/dG8OOrVtUmhBT1uJJYxbl5kU2Tj3v6LGqBcsysN1yhuCStJCCA3GqdvKY8sqXQ== @@ -1376,10 +1397,20 @@ ajv@^6.0.1, ajv@^6.1.0, ajv@^6.5.0, ajv@^6.5.5, ajv@^6.9.1: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.1.0, ajv@^6.10.2, ajv@^6.5.5: + version "6.10.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" + integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + algoliasearch@^3.24.5: - version "3.33.0" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-3.33.0.tgz#83b541124ebb0db54643009d4e660866b3177cdf" - integrity sha512-9DaVmOd7cvcZeYyV0BWAeJHVWJmgOL2DNUEBY/DTR4MzD1wCWs4Djl7LAlfvkGwGBdRHZCG+l0HA1572w3T8zg== + version "3.35.1" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-3.35.1.tgz#297d15f534a3507cab2f5dfb996019cac7568f0c" + integrity sha512-K4yKVhaHkXfJ/xcUnil04xiSrB8B8yHZoFEhWNpXg23eiCnqvTZw1tn/SqvdsANlYHLJlKl0qi3I/Q2Sqo7LwQ== dependencies: agentkeepalive "^2.2.0" debug "^2.6.9" @@ -1418,9 +1449,9 @@ ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== ansi-escapes@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.2.0.tgz#c38600259cefba178ee3f7166c5ea3a5dd2e88fc" - integrity sha512-0+VX4uhi8m3aNbzoqKmkAVOEj6uQzcUHXoFPkKjhZPTpGRUBqVh930KbB6PS4zIyDZccphlLIYlu8nsjFzkXwg== + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.2.1.tgz#4dccdb846c3eee10f6d64dea66273eab90c37228" + integrity sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q== dependencies: type-fest "^0.5.2" @@ -1642,7 +1673,7 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== -async@1.x, async@^1.5.2: +async@1.x: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= @@ -1654,6 +1685,13 @@ async@^2.0.1, async@^2.1.4: dependencies: lodash "^4.17.11" +async@^2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + dependencies: + lodash "^4.17.14" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1672,17 +1710,17 @@ autocomplete.js@0.36.0: immediate "^3.2.3" autoprefixer@^9.5.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.6.1.tgz#51967a02d2d2300bb01866c1611ec8348d355a47" - integrity sha512-aVo5WxR3VyvyJxcJC3h4FKfwCQvQWb1tSI5VHNibddCVWrcD1NvlxEweg3TSgiPztMnWfjpy2FURKA2kvDE+Tw== + version "9.6.5" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.6.5.tgz#98f4afe7e93cccf323287515d426019619775e5e" + integrity sha512-rGd50YV8LgwFQ2WQp4XzOTG69u1qQsXn0amww7tjqV5jJuNazgFKYEVItEBngyyvVITKOg20zr2V+9VsrXJQ2g== dependencies: - browserslist "^4.6.3" - caniuse-lite "^1.0.30000980" + browserslist "^4.7.0" + caniuse-lite "^1.0.30000999" chalk "^2.4.2" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.17" - postcss-value-parser "^4.0.0" + postcss "^7.0.18" + postcss-value-parser "^4.0.2" aws-sign2@~0.7.0: version "0.7.0" @@ -2427,9 +2465,9 @@ base64-js@1.2.0: integrity sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE= base64-js@^1.0.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" - integrity sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw== + version "1.3.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" + integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== base64id@1.0.0: version "1.0.0" @@ -2502,9 +2540,9 @@ blob@0.0.5: integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== bluebird@^3.1.1, bluebird@^3.5.5: - version "3.5.5" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f" - integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w== + version "3.7.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de" + integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg== bluebird@~3.4.1: version "3.4.7" @@ -2661,14 +2699,14 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.0.0, browserslist@^4.3.4, browserslist@^4.6.3: - version "4.6.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.6.3.tgz#0530cbc6ab0c1f3fc8c819c72377ba55cf647f05" - integrity sha512-CNBqTCq22RKM8wKJNowcqihHJ4SkI8CGeK7KOR9tPboXUuS5Zk5lQgzzTbs4oxD8x+6HUshZUa2OyNI9lR93bQ== +browserslist@^4.0.0, browserslist@^4.3.4, browserslist@^4.7.0: + version "4.7.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.1.tgz#bd400d1aea56538580e8c4d5f1c54ac11b5ab468" + integrity sha512-QtULFqKIAtiyNx7NhZ/p4rB8m3xDozVo/pi5VgTlADLF2tNigz/QH+v0m5qhn7XfHT7u+607NcCNOnC0HZAlMg== dependencies: - caniuse-lite "^1.0.30000975" - electron-to-chromium "^1.3.164" - node-releases "^1.1.23" + caniuse-lite "^1.0.30000999" + electron-to-chromium "^1.3.284" + node-releases "^1.1.36" browserstack@^1.2.0: version "1.5.2" @@ -2758,11 +2796,11 @@ bytes@3.1.0: integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== cac@^6.3.9: - version "6.5.2" - resolved "https://registry.yarnpkg.com/cac/-/cac-6.5.2.tgz#92ef1490b9ffde5f0be7eeadec5ea926f0e78ef6" - integrity sha512-8JdiD9/ZLsG418j/chyZQ3VWuhFELSGlH4EUxzNKgIH8wK8dO0j5Pqu6Pk7B/RP3kX9aasyQhPrrUjYO5e0w7w== + version "6.5.3" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.5.3.tgz#dcd8b7496b563b87e8a1fc69e3118bdf29c781f2" + integrity sha512-wZfzSWVXuue1H3J7TDNjbzg4KTqPXCmh7F3QIzEYXfnhMCcOUrx99M7rpO2UDVJA9dqv3butGj2nHvCV47CmPg== -cacache@^11.3.2: +cacache@^11.3.3: version "11.3.3" resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.3.tgz#8bd29df8c6a718a6ebd2d010da4d7972ae3bbadc" integrity sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA== @@ -2782,6 +2820,27 @@ cacache@^11.3.2: unique-filename "^1.1.1" y18n "^4.0.0" +cacache@^12.0.2: + version "12.0.3" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" + integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== + dependencies: + bluebird "^3.5.5" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.4" + graceful-fs "^4.1.15" + infer-owner "^1.0.3" + lru-cache "^5.1.1" + mississippi "^3.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.3" + ssri "^6.0.1" + unique-filename "^1.1.1" + y18n "^4.0.0" + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -3012,10 +3071,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000975, caniuse-lite@^1.0.30000980: - version "1.0.30000980" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000980.tgz#0df53e4354b3111f83ac15b0bd4c71fe92994231" - integrity sha512-as0PRtWHaX3gl2gpC7qA7bX88lr+qLacMMXm1QKLLQtBCwT/Ljbgrv5EXKMNBoeEX6yFZ4vIsBb4Nh+PEwW2Rw== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000999: + version "1.0.30000999" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000999.tgz#427253a69ad7bea4aa8d8345687b8eec51ca0e43" + integrity sha512-1CUyKyecPeksKwXZvYw0tEoaMCo/RwBlXmEtN5vVnabvO0KPd9RQLcaAuR9/1F+KDMv6esmOFWlsXuzDk+8rxg== caseless@~0.12.0: version "0.12.0" @@ -3092,7 +3151,26 @@ chokidar@^1.6.1: optionalDependencies: fsevents "^1.0.0" -chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4, chokidar@^2.1.6: +chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + optionalDependencies: + fsevents "^1.2.7" + +chokidar@^2.0.4: version "2.1.6" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.6.tgz#b6cad653a929e244ce8a834244164d241fa954c5" integrity sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g== @@ -3112,11 +3190,11 @@ chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4, chokidar@^2.1.6: fsevents "^1.2.7" chownr@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.2.tgz#a18f1e0b269c8a6a5d3c86eb298beb14c3dd7bf6" - integrity sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A== + version "1.1.3" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" + integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== -chrome-trace-event@^1.0.0: +chrome-trace-event@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== @@ -3284,11 +3362,16 @@ commander@2.17.x: resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== -commander@^2.11.0, commander@^2.20.0, commander@^2.3.0, commander@~2.20.0: +commander@^2.11.0, commander@^2.3.0, commander@~2.20.0: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + commander@~2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" @@ -3370,9 +3453,9 @@ connect-injector@^0.4.0: uberproto "^1.1.0" consola@^2.6.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/consola/-/consola-2.9.0.tgz#57760e3a65a53ec27337f4add31505802d902278" - integrity sha512-34Iue+LRcWbndFIfZc5boNizWlsrRjqIBJZTe591vImgbnq7nx2EzlrLtANj9TH2Fxm7puFJBJAOk5BhvZOddQ== + version "2.10.1" + resolved "https://registry.yarnpkg.com/consola/-/consola-2.10.1.tgz#4693edba714677c878d520e4c7e4f69306b4b927" + integrity sha512-4sxpH6SGFYLADfUip4vuY65f/gEogrzJoniVhNUYkJHtng0l8ZjnDCqxxrSVRHOHwKxsy8Vm5ONZh1wOR3/l/w== console-browserify@^1.1.0, console-browserify@~1.1.0: version "1.1.0" @@ -3460,11 +3543,11 @@ copy-descriptor@^0.1.0: integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= copy-webpack-plugin@^5.0.2: - version "5.0.3" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.0.3.tgz#2179e3c8fd69f13afe74da338896f1f01a875b5c" - integrity sha512-PlZRs9CUMnAVylZq+vg2Juew662jWtwOXOqH4lbQD9ZFhRG9R7tVStOgHt21CBGVq7k5yIJaz8TXDLSjV+Lj8Q== + version "5.0.4" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.0.4.tgz#c78126f604e24f194c6ec2f43a64e232b5d43655" + integrity sha512-YBuYGpSzoCHSSDGyHy6VJ7SHojKp6WHT4D7ItcQFNAYx2hrwkMe56e97xfVR0/ovDuMTrMffXUiltvQljtAGeg== dependencies: - cacache "^11.3.2" + cacache "^11.3.3" find-cache-dir "^2.1.0" glob-parent "^3.1.0" globby "^7.1.1" @@ -3477,11 +3560,16 @@ copy-webpack-plugin@^5.0.2: serialize-javascript "^1.7.0" webpack-log "^2.0.0" -core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.5: +core-js@^2.4.0, core-js@^2.5.0: version "2.6.9" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A== +core-js@^2.6.5: + version "2.6.10" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f" + integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA== + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -3602,10 +3690,12 @@ css-loader@^2.1.1: postcss-value-parser "^3.3.0" schema-utils "^1.0.0" -css-parse@1.7.x: - version "1.7.0" - resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-1.7.0.tgz#321f6cf73782a6ff751111390fc05e2c657d8c9b" - integrity sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs= +css-parse@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/css-parse/-/css-parse-2.0.0.tgz#a468ee667c16d81ccf05c58c38d2a97c780dbfd4" + integrity sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q= + dependencies: + css "^2.0.0" css-select-base-adapter@^0.1.1: version "0.1.1" @@ -3632,14 +3722,6 @@ css-select@^2.0.0: domutils "^1.7.0" nth-check "^1.0.2" -css-tree@1.0.0-alpha.28: - version "1.0.0-alpha.28" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.28.tgz#8e8968190d886c9477bc8d61e96f61af3f7ffa7f" - integrity sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w== - dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" - css-tree@1.0.0-alpha.29: version "1.0.0-alpha.29" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" @@ -3648,21 +3730,34 @@ css-tree@1.0.0-alpha.29: mdn-data "~1.1.0" source-map "^0.5.3" +css-tree@1.0.0-alpha.33: + version "1.0.0-alpha.33" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.33.tgz#970e20e5a91f7a378ddd0fc58d0b6c8d4f3be93e" + integrity sha512-SPt57bh5nQnpsTBsx/IXbO14sRc9xXu5MtMAVuo0BaQQmyf0NupNPPSoMaqiAF5tDFafYsTkfeH4Q/HCKXkg4w== + dependencies: + mdn-data "2.0.4" + source-map "^0.5.3" + css-unit-converter@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= -css-url-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec" - integrity sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w= - css-what@2.1, css-what@^2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== +css@^2.0.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" + integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw== + dependencies: + inherits "^2.0.3" + source-map "^0.6.1" + source-map-resolve "^0.5.2" + urix "^0.1.0" + cssesc@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" @@ -3760,10 +3855,10 @@ cssstyle@^1.1.1: dependencies: cssom "~0.3.6" -cyclist@~0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" - integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA= +cyclist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= dashdash@^1.12.0: version "1.14.1" @@ -3801,13 +3896,6 @@ debug-log@^1.0.0: resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" integrity sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8= -debug@*, debug@4.1.1, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@~4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - debug@2.6.9, debug@^2.0.0, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -3822,7 +3910,14 @@ debug@3.1.0, debug@=3.1.0, debug@~3.1.0: dependencies: ms "2.0.0" -debug@^3.0.0, debug@^3.1.0, debug@^3.2.5, debug@^3.2.6: +debug@4.1.1, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@~4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -3847,9 +3942,16 @@ deep-eql@^3.0.1: type-detect "^4.0.0" deep-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= + version "1.1.0" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.0.tgz#3103cdf8ab6d32cf4a8df7865458f2b8d33f3745" + integrity sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" deep-equal@~0.0.0: version "0.0.0" @@ -4104,12 +4206,12 @@ dom-event-types@^1.0.0: integrity sha512-2G2Vwi2zXTHBGqXHsJ4+ak/iP0N8Ar+G8a7LiD2oup5o4sQWytwqqrZu/O6hIMV0KMID2PL69OhpshLO0n7UJQ== dom-serializer@0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" - integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== + version "0.2.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.1.tgz#13650c850daffea35d8b626a4cfc4d3a17643fdb" + integrity sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q== dependencies: - domelementtype "^1.3.0" - entities "^1.1.1" + domelementtype "^2.0.1" + entities "^2.0.0" dom-walk@^0.1.0: version "0.1.1" @@ -4126,11 +4228,16 @@ domain-browser@~1.1.2: resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" integrity sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw= -domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: +domelementtype@1, domelementtype@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" + integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + domexception@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" @@ -4205,15 +4312,15 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.164: - version "1.3.188" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.188.tgz#e28e1afe4bb229989e280bfd3b395c7ec03c8b7a" - integrity sha512-tEQcughYIMj8WDMc59EGEtNxdGgwal/oLLTDw+NEqJRJwGflQvH3aiyiexrWeZOETP4/ko78PVr6gwNhdozvuQ== +electron-to-chromium@^1.3.284: + version "1.3.285" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.285.tgz#909576db2ee4dfec74a87aa30c92f66ebfc78748" + integrity sha512-DYR9KW723sUbGK++DCmCmM95AbNXT4Q0tlCFMcYijFjayhuDqlGYR68OemlP8MJj0gjkwdeItIUfd0oLCgw+4A== elliptic@^6.0.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.0.tgz#2b8ed4c891b7de3200e14412a5b8248c7af505ca" - integrity sha512-eFOJTMyCYb7xtE/caJ6JJu+bhi67WCYNbkGSknu20pmM8Ke/bqOfdnZWxyoGN26JgfxTbXrsCkEw4KheCT/KGg== + version "6.5.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.1.tgz#c380f5f909bf1b9b4428d028cd18d3b0efd6b52b" + integrity sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -4239,9 +4346,9 @@ encodeurl@~1.0.2: integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= end-of-stream@^1.0.0, end-of-stream@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" @@ -4286,12 +4393,12 @@ engine.io@~3.3.1: ws "~6.1.0" enhanced-resolve@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" - integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== + version "4.1.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" + integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== dependencies: graceful-fs "^4.1.2" - memory-fs "^0.4.0" + memory-fs "^0.5.0" tapable "^1.0.0" entities@^1.1.1, entities@~1.1.1: @@ -4299,6 +4406,11 @@ entities@^1.1.1, entities@~1.1.1: resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== +entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + envify@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/envify/-/envify-4.1.0.tgz#f39ad3db9d6801b4e6b478b61028d3f0b6819f7e" @@ -4308,9 +4420,9 @@ envify@^4.0.0: through "~2.3.4" envinfo@^7.2.0: - version "7.3.1" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.3.1.tgz#892e42f7bf858b3446d9414ad240dbaf8da52f09" - integrity sha512-GvXiDTqLYrORVSCuJCsWHPXF5BFvoWMQA9xX4YVjPT1jyS3aZEHUBwjzxU/6LTPF9ReHgVEbX7IEN5UvSXHw/A== + version "7.4.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.4.0.tgz#bef4ece9e717423aaf0c3584651430b735ad6630" + integrity sha512-FdDfnWnCVjxTTpWE3d6Jgh5JDIA3Cw7LCgpM/pI7kK1ORkjaqI2r6NqQ+ln2j0dfpgxY00AWieSvtkiZQKIItA== errno@^0.1.3, errno@~0.1.7: version "0.1.7" @@ -4326,7 +4438,23 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.0: +es-abstract@^1.12.0, es-abstract@^1.5.1: + version "1.15.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.15.0.tgz#8884928ec7e40a79e3c9bc812d37d10c8b24cc57" + integrity sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.0" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-inspect "^1.6.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.1.0" + string.prototype.trimright "^2.1.0" + +es-abstract@^1.7.0: version "1.13.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== @@ -4673,15 +4801,20 @@ estraverse@^1.9.1: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.0.0, estraverse@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= +estraverse@^4.1.0, estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== etag@~1.8.1: version "1.8.1" @@ -4693,6 +4826,11 @@ eventemitter3@^3.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== +eventemitter3@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb" + integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg== + events@^1.1.0, events@^1.1.1, events@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -5171,11 +5309,11 @@ follow-redirects@1.5.10: debug "=3.1.0" follow-redirects@^1.0.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.7.0.tgz#489ebc198dc0e7f64167bd23b03c4c19b5784c76" - integrity sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.9.0.tgz#8d5bcdc65b7108fe1508649c79c12d732dcedb4f" + integrity sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A== dependencies: - debug "^3.2.6" + debug "^3.0.0" for-in@^0.1.3: version "0.1.8" @@ -5269,11 +5407,11 @@ fs-extra@^7.0.1: universalify "^0.1.0" fs-minipass@^1.2.5: - version "1.2.6" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" - integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ== + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== dependencies: - minipass "^2.2.1" + minipass "^2.6.0" fs-readdir-recursive@^1.0.0: version "1.1.0" @@ -5399,18 +5537,6 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= -glob@7.0.x: - version "7.0.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.6.tgz#211bafaf49e525b8cd93260d14ab136152b3f57a" - integrity sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo= - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" @@ -5508,7 +5634,12 @@ good-listener@^1.2.2: dependencies: delegate "^3.1.2" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.2.2" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02" + integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q== + +graceful-fs@^4.1.4: version "4.2.0" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.0.tgz#8d8fdc73977cb04104721cb53666c1ca64cd328b" integrity sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg== @@ -5827,7 +5958,7 @@ http-errors@~1.7.2: resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= -http-proxy-middleware@^0.19.1: +http-proxy-middleware@0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== @@ -5837,7 +5968,7 @@ http-proxy-middleware@^0.19.1: lodash "^4.17.11" micromatch "^3.1.10" -http-proxy@^1.1.4, http-proxy@^1.17.0: +http-proxy@^1.1.4: version "1.17.0" resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.17.0.tgz#7ad38494658f84605e2f6db4436df410f4e5be9a" integrity sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g== @@ -5846,6 +5977,15 @@ http-proxy@^1.1.4, http-proxy@^1.17.0: follow-redirects "^1.0.0" requires-port "^1.0.0" +http-proxy@^1.17.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a" + integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -5898,9 +6038,9 @@ iferr@^0.1.5: integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= ignore-walk@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" - integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== + version "3.0.3" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" + integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== dependencies: minimatch "^3.0.4" @@ -5972,6 +6112,11 @@ indexof@0.0.1: resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= +infer-owner@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + inflection@^1.12.0: version "1.12.0" resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.12.0.tgz#a200935656d6f5f6bc4dc7502e1aecb703228416" @@ -6083,16 +6228,26 @@ ip@^1.1.0, ip@^1.1.5: resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= -ipaddr.js@1.9.0, ipaddr.js@^1.9.0: +ipaddr.js@1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== +ipaddr.js@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= +is-absolute-url@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== + is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -6107,6 +6262,11 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-arguments@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" + integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -6399,9 +6559,9 @@ isarray@2.0.1: integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= isarray@^2.0.1: - version "2.0.4" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.4.tgz#38e7bcbb0f3ba1b7933c86ba1894ddfc3781bbb7" - integrity sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA== + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== isexe@^2.0.0: version "2.0.0" @@ -6657,9 +6817,9 @@ json5@^1.0.1: minimist "^1.2.0" json5@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" - integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== + version "2.1.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" + integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== dependencies: minimist "^1.2.0" @@ -6803,9 +6963,9 @@ levn@^0.3.0, levn@~0.3.0: type-check "~0.3.2" linkify-it@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.1.0.tgz#c4caf38a6cd7ac2212ef3c7d2bde30a91561f9db" - integrity sha512-4REs8/062kV2DSHxNfq5183zrqXMl7WP0WzABH9IeJI+NLm429FgE1PDecltYfnOoFDFlZGh2T8PfZn0r+GTRg== + version "2.2.0" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" + integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== dependencies: uc.micro "^1.0.1" @@ -6850,7 +7010,7 @@ load-script@^1.0.0: resolved "https://registry.yarnpkg.com/load-script/-/load-script-1.0.0.tgz#0491939e0bee5643ee494a7e3da3d2bac70c6ca4" integrity sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ= -loader-runner@^2.3.0: +loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== @@ -6900,7 +7060,7 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -lodash._reinterpolate@~3.0.0: +lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= @@ -6910,6 +7070,11 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -6981,24 +7146,19 @@ lodash.sortby@^4.7.0: integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= lodash.template@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0" - integrity sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A= + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" + integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== dependencies: - lodash._reinterpolate "~3.0.0" + lodash._reinterpolate "^3.0.0" lodash.templatesettings "^4.0.0" lodash.templatesettings@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316" - integrity sha1-K01OlbpEDZFf8IvImeRVNmZxMxY= + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== dependencies: - lodash._reinterpolate "~3.0.0" - -lodash.throttle@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" - integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= + lodash._reinterpolate "^3.0.0" lodash.trim@^4.5.1: version "4.5.1" @@ -7015,20 +7175,20 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@~4.17.11: +lodash@^4.17.10, lodash@^4.17.4, lodash@^4.3.0, lodash@~4.17.11: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== -lodash@^4.17.15: +lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.5: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -loglevel@^1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.3.tgz#77f2eb64be55a404c9fd04ad16d57c1d6d6b1280" - integrity sha512-LoEDv5pgpvWgPF4kNYuIp0qqSJVWak/dML0RY74xlzMZiT9w77teNAwKYKWBTYjlokMirg+o3jBwp+vlLrcfAA== +loglevel@^1.6.4: + version "1.6.4" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.4.tgz#f408f4f006db8354d0577dcf6d33485b3cb90d56" + integrity sha512-p0b6mOGKcGa+7nnmKbpzR6qloPbrgLcnio++E+14Vo/XffOGwZtRpUhr8dTH/x2oCMmEoIU0Zwm3ZauhvYD17g== loose-envify@^1.0.0, loose-envify@^1.4.0: version "1.4.0" @@ -7095,9 +7255,9 @@ map-visit@^1.0.0: object-visit "^1.0.0" markdown-it-anchor@^5.0.2: - version "5.2.4" - resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-5.2.4.tgz#d39306fe4c199705b4479d3036842cf34dcba24f" - integrity sha512-n8zCGjxA3T+Mx1pG8HEgbJbkB8JFUuRkeTZQuIM8iPY6oQ8sWOPRZJDFC9a/pNg2QkHEjjGkhBEl/RSyzaDZ3A== + version "5.2.5" + resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-5.2.5.tgz#dbf13cfcdbffd16a510984f1263e1d479a47d27a" + integrity sha512-xLIjLQmtym3QpoY9llBgApknl7pxAcN3WDRc2d3rwpl+/YvDZHPmKscGs+L6E05xf2KrCXPBvosWt7MZukwSpQ== markdown-it-chain@^1.3.0: version "1.3.0" @@ -7146,6 +7306,11 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== + mdn-data@~1.1.0: version "1.1.4" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" @@ -7170,7 +7335,7 @@ mem@^4.0.0: mimic-fn "^2.0.0" p-is-promise "^2.0.0" -memory-fs@^0.4.0, memory-fs@^0.4.1, memory-fs@~0.4.1: +memory-fs@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= @@ -7178,6 +7343,14 @@ memory-fs@^0.4.0, memory-fs@^0.4.1, memory-fs@~0.4.1: errno "^0.1.3" readable-stream "^2.0.1" +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -7191,9 +7364,9 @@ merge-source-map@^1.1.0: source-map "^0.6.1" merge2@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" - integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== methods@^1.1.1, methods@~1.1.2: version "1.1.2" @@ -7219,7 +7392,7 @@ micromatch@^2.1.5, micromatch@^2.3.11: parse-glob "^3.0.4" regex-cache "^0.4.2" -micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: +micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -7246,11 +7419,16 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.40.0, "mime-db@>= 1.40.0 < 2": +mime-db@1.40.0: version "1.40.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32" integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA== +"mime-db@>= 1.40.0 < 2": + version "1.42.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" + integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== + mime-types@^2.1.12, mime-types@^2.1.6, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.24" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81" @@ -7263,7 +7441,7 @@ mime@1.6.0, mime@^1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.0.3, mime@^2.4.2: +mime@^2.0.3, mime@^2.4.4: version "2.4.4" resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== @@ -7313,7 +7491,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: +"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -7335,20 +7513,20 @@ minimist@~0.0.1: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= -minipass@^2.2.1, minipass@^2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== +minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" minizlib@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614" - integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA== + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== dependencies: - minipass "^2.2.1" + minipass "^2.9.0" mississippi@^3.0.0: version "3.0.0" @@ -7387,7 +7565,7 @@ mkdirp@0.3.0: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" integrity sha1-G79asbqCevI1dRQ0kEJkVfSB/h4= -mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1, mkdirp@~0.5.x: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -7530,12 +7708,12 @@ no-case@^2.2.0: dependencies: lower-case "^1.1.1" -node-forge@0.7.5: - version "0.7.5" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df" - integrity sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ== +node-forge@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" + integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ== -node-libs-browser@^2.0.0: +node-libs-browser@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== @@ -7580,12 +7758,12 @@ node-pre-gyp@^0.12.0: semver "^5.3.0" tar "^4" -node-releases@^1.1.23: - version "1.1.25" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.25.tgz#0c2d7dbc7fed30fbe02a9ee3007b8c90bf0133d3" - integrity sha512-fI5BXuk83lKEoZDdH3gRhtsNgh05/wZacuXkgbiYkceE7+QIMXOg98n9ZV7mz27B+kFHnqHcUpscZZlGRSmTpQ== +node-releases@^1.1.36: + version "1.1.36" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.36.tgz#44b7cb8254138e87bdbfa47761d0f825e20900b4" + integrity sha512-ggXhX6QGyJSjj3r+6ml2LqqC28XOWmKtpb+a15/Zpr9V3yoNazxJNlcQDS9bYaid5FReEWHEgToH1mwoUceWwg== dependencies: - semver "^5.3.0" + semver "^6.3.0" nopt@1.0.10: version "1.0.10" @@ -7656,9 +7834,9 @@ npm-bundled@^1.0.1: integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== npm-packlist@^1.1.6: - version "1.4.4" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.4.tgz#866224233850ac534b63d1a6e76050092b5d2f44" - integrity sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw== + version "1.4.6" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.6.tgz#53ba3ed11f8523079f1457376dd379ee4ea42ff4" + integrity sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -7731,7 +7909,17 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.0: +object-inspect@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== + +object-is@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" + integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY= + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.0, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -7824,6 +8012,11 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +opencollective-postinstall@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" + integrity sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw== + openurl@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/openurl/-/openurl-1.1.1.tgz#3875b4b0ef7a52c156f0db41d4609dbb0f94b387" @@ -7942,9 +8135,9 @@ p-limit@^1.1.0: p-try "^1.0.0" p-limit@^2.0.0, p-limit@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" - integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== + version "2.2.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== dependencies: p-try "^2.0.0" @@ -7990,11 +8183,11 @@ pako@~1.0.5: integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== parallel-transform@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" - integrity sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY= + version "1.2.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" + integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== dependencies: - cyclist "~0.2.2" + cyclist "^1.0.1" inherits "^2.0.3" readable-stream "^2.1.5" @@ -8013,9 +8206,9 @@ parent-module@^1.0.0: callsites "^3.0.0" parse-asn1@^5.0.0: - version "5.1.4" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" - integrity sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw== + version "5.1.5" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" + integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== dependencies: asn1.js "^4.0.0" browserify-aes "^1.0.0" @@ -8274,14 +8467,14 @@ pn@^1.1.0: resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== -portfinder@^1.0.13, portfinder@^1.0.20: - version "1.0.20" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.20.tgz#bea68632e54b2e13ab7b0c4775e9b41bf270e44a" - integrity sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw== +portfinder@^1.0.13, portfinder@^1.0.24: + version "1.0.25" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca" + integrity sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg== dependencies: - async "^1.5.2" - debug "^2.2.0" - mkdirp "0.5.x" + async "^2.6.2" + debug "^3.1.1" + mkdirp "^0.5.1" posix-character-classes@^0.1.0: version "0.1.1" @@ -8625,15 +8818,15 @@ postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.0, postcss-value-parser@^ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz#99a983d365f7b2ad8d0f9b8c3094926eab4b936d" - integrity sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ== +postcss-value-parser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" + integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.17" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.17.tgz#4da1bdff5322d4a0acaab4d87f3e782436bad31f" - integrity sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ== +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.18, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.18.tgz#4b9cda95ae6c069c67a4d933029eddd4838ac233" + integrity sha512-/7g1QXXgegpF+9GJj4iN7ChGF40sYuGYJ8WZu8DZWnmhQ/G36hfdk3q9LBJmoK+lZ+yzZ5KYpOoxq7LF1BxE8g== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -8685,9 +8878,9 @@ pretty-time@^1.1.0: integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== prismjs@^1.13.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.16.0.tgz#406eb2c8aacb0f5f0f1167930cb83835d10a4308" - integrity sha512-OA4MKxjFZHSvZcisLGe14THYsug/nF6O1f0pAJc0KN0wTyAcLqmsbE+lTGKSpyh+9pEW57+k6pg2AfYR+coyHA== + version "1.17.1" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.17.1.tgz#e669fcbd4cdd873c35102881c33b14d0d68519be" + integrity sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q== optionalDependencies: clipboard "^2.0.0" @@ -8743,7 +8936,12 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= -psl@^1.1.24, psl@^1.1.28: +psl@^1.1.24: + version "1.4.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" + integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== + +psl@^1.1.28: version "1.2.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.2.0.tgz#df12b5b1b3a30f51c329eacbdef98f3a6e136dc6" integrity sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA== @@ -8982,7 +9180,7 @@ reduce@^1.0.1: dependencies: object-keys "^1.1.0" -regenerate-unicode-properties@^8.0.2: +regenerate-unicode-properties@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== @@ -9005,9 +9203,9 @@ regenerator-runtime@^0.11.0: integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== regenerator-runtime@^0.13.2: - version "0.13.2" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz#32e59c9a6fb9b1a4aff09b4930ca2d4477343447" - integrity sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA== + version "0.13.3" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" + integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== regenerator-transform@^0.10.0: version "0.10.1" @@ -9019,9 +9217,9 @@ regenerator-transform@^0.10.0: private "^0.1.6" regenerator-transform@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.0.tgz#2ca9aaf7a2c239dd32e4761218425b8c7a86ecaf" - integrity sha512-rtOelq4Cawlbmq9xuMR5gdFmv7ku/sFoB7sRiywx7aq53bc52b4j6zvH7Te1Vt/X2YveDKnCGUbioieU7FEL3w== + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" + integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ== dependencies: private "^0.1.6" @@ -9040,10 +9238,12 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp-tree@^0.1.6: - version "0.1.11" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.11.tgz#c9c7f00fcf722e0a56c7390983a7a63dd6c272f3" - integrity sha512-7/l/DgapVVDzZobwMCCgMlqiqyLFJ0cduo/j+3BcDJIB+yJdsYCfKuI3l/04NV+H/rfNRdPIDbXNZHM9XvQatg== +regexp.prototype.flags@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c" + integrity sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA== + dependencies: + define-properties "^1.1.2" regexpp@^2.0.0, regexpp@^2.0.1: version "2.0.1" @@ -9059,13 +9259,13 @@ regexpu-core@^2.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" -regexpu-core@^4.5.4: - version "4.5.4" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.5.4.tgz#080d9d02289aa87fe1667a4f5136bc98a6aebaae" - integrity sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ== +regexpu-core@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" + integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== dependencies: regenerate "^1.4.0" - regenerate-unicode-properties "^8.0.2" + regenerate-unicode-properties "^8.1.0" regjsgen "^0.5.0" regjsparser "^0.6.0" unicode-match-property-ecmascript "^1.0.4" @@ -9235,13 +9435,20 @@ resolve@1.1.x: resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.2.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0, resolve@^1.8.1: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.5.0, resolve@^1.6.0: version "1.11.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e" integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw== dependencies: path-parse "^1.0.6" +resolve@^1.2.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.8.1: + version "1.12.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" + integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== + dependencies: + path-parse "^1.0.6" + restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -9270,13 +9477,20 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@2, rimraf@2.6.3, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3, rimraf@~2.6.2: +rimraf@2, rimraf@2.6.3, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: glob "^7.1.3" +rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -9328,7 +9542,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2: +safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== @@ -9340,16 +9554,11 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sax@0.5.x: - version "0.5.8" - resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1" - integrity sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE= - sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -9389,14 +9598,14 @@ select@^1.1.2: resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= -selfsigned@^1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.4.tgz#cdd7eccfca4ed7635d47a08bf2d5d3074092e2cd" - integrity sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw== +selfsigned@^1.10.7: + version "1.10.7" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b" + integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA== dependencies: - node-forge "0.7.5" + node-forge "0.9.0" -"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: +"semver@2 || 3 || 4 || 5": version "5.7.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== @@ -9406,10 +9615,15 @@ semver@5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== -semver@^6.0.0, semver@^6.1.1: - version "6.2.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db" - integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A== +semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.0.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== send@0.17.1: version "0.17.1" @@ -9436,9 +9650,9 @@ serialize-error@^3.0.0: integrity sha512-+y3nkkG/go1Vdw+2f/+XUXM1DXX1XcxTl99FfiD/OEPUNw4uo0i6FKABfTAN5ZcgGtjTRZcEbxcE/jtXbEY19A== serialize-javascript@^1.3.0, serialize-javascript@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.7.0.tgz#d6e0dfb2a3832a8c94468e6eb1db97e55a192a65" - integrity sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA== + version "1.9.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.9.1.tgz#cfc200aef77b600c47da9bb8149c943e798c2fdb" + integrity sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A== serve-index@^1.9.1: version "1.9.1" @@ -9588,6 +9802,11 @@ slice-ansi@^2.1.0: astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" +smoothscroll-polyfill@^0.4.3: + version "0.4.4" + resolved "https://registry.yarnpkg.com/smoothscroll-polyfill/-/smoothscroll-polyfill-0.4.4.tgz#3a259131dc6930e6ca80003e1cb03b603b69abf8" + integrity sha512-TK5ZA9U5RqCwMpfoMq/l1mrH0JAR7y7KRvOBx0n2869aLxch+gT9GhN3yUfjiw+d/DiF1mKo14+hd62JyMmoBg== + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -9664,10 +9883,10 @@ socket.io@^2.0.1: socket.io-client "2.2.0" socket.io-parser "~3.3.0" -sockjs-client@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.3.0.tgz#12fc9d6cb663da5739d3dc5fb6e8687da95cb177" - integrity sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg== +sockjs-client@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" + integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g== dependencies: debug "^3.2.5" eventsource "^1.0.7" @@ -9696,7 +9915,7 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -source-map-resolve@^0.5.0: +source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== @@ -9714,7 +9933,7 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" -source-map-support@^0.5.6, source-map-support@~0.5.12: +source-map-support@^0.5.6: version "0.5.12" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== @@ -9722,18 +9941,19 @@ source-map-support@^0.5.6, source-map-support@~0.5.12: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-support@~0.5.12: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@0.1.x: - version "0.1.43" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" - integrity sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y= - dependencies: - amdefine ">=0.0.4" - source-map@0.5.6: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" @@ -9749,6 +9969,11 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +source-map@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" @@ -9794,10 +10019,10 @@ spdy-transport@^3.0.0: readable-stream "^3.0.6" wbuf "^1.7.3" -spdy@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.0.tgz#81f222b5a743a329aa12cea6a390e60e9b613c52" - integrity sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q== +spdy@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.1.tgz#6f12ed1c5db7ea4f24ebb8b89ba58c87c08257f2" + integrity sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA== dependencies: debug "^4.1.0" handle-thing "^2.0.0" @@ -10037,12 +10262,28 @@ string-width@^3.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string.prototype.trimleft@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + string_decoder@^1.0.0, string_decoder@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" - integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: - safe-buffer "~5.1.0" + safe-buffer "~5.2.0" string_decoder@~1.0.0: version "1.0.3" @@ -10125,16 +10366,18 @@ stylus-loader@^3.0.2: when "~3.6.x" stylus@^0.54.5: - version "0.54.5" - resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.5.tgz#42b9560931ca7090ce8515a798ba9e6aa3d6dc79" - integrity sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk= + version "0.54.7" + resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.7.tgz#c6ce4793965ee538bcebe50f31537bfc04d88cd2" + integrity sha512-Yw3WMTzVwevT6ZTrLCYNHAFmanMxdylelL3hkWNgPMeTCpMwpV3nXjpOHuBXtFv7aiO2xRuQS6OoAdgkNcSNug== dependencies: - css-parse "1.7.x" - debug "*" - glob "7.0.x" - mkdirp "0.5.x" - sax "0.5.x" - source-map "0.1.x" + css-parse "~2.0.0" + debug "~3.1.0" + glob "^7.1.3" + mkdirp "~0.5.x" + safer-buffer "^2.1.2" + sax "~1.2.4" + semver "^6.0.0" + source-map "^0.7.3" superagent@^3.0.0: version "3.8.3" @@ -10198,16 +10441,15 @@ svg-tags@^1.0.0: integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= svgo@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.2.2.tgz#0253d34eccf2aed4ad4f283e11ee75198f9d7316" - integrity sha512-rAfulcwp2D9jjdGu+0CuqlrAUin6bBWrpoqXWwKDZZZJfXcUXQSxLJOFJCQCSA0x0pP2U0TxSlJu2ROq5Bq6qA== + version "1.3.0" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.0.tgz#bae51ba95ded9a33a36b7c46ce9c359ae9154313" + integrity sha512-MLfUA6O+qauLDbym+mMZgtXCGRfIxyQoeH6IKVcFslyODEe/ElJNwr0FohQ3xG4C6HK6bk3KYPPXwHVJk3V5NQ== dependencies: chalk "^2.4.1" coa "^2.0.2" css-select "^2.0.0" css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.28" - css-url-regex "^1.1.0" + css-tree "1.0.0-alpha.33" csso "^3.5.1" js-yaml "^3.13.1" mkdirp "~0.5.1" @@ -10249,7 +10491,7 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" -tapable@^1.0.0, tapable@^1.1.0: +tapable@^1.0.0, tapable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== @@ -10264,38 +10506,37 @@ tape@~0.2.2: jsonify "~0.0.0" tar@^4: - version "4.4.10" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" - integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA== + version "4.4.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" + integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== dependencies: chownr "^1.1.1" fs-minipass "^1.2.5" - minipass "^2.3.5" + minipass "^2.8.6" minizlib "^1.2.1" mkdirp "^0.5.0" safe-buffer "^5.1.2" yallist "^3.0.3" -terser-webpack-plugin@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz#69aa22426299f4b5b3775cbed8cb2c5d419aa1d4" - integrity sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg== +terser-webpack-plugin@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz#61b18e40eaee5be97e771cdbb10ed1280888c2b4" + integrity sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg== dependencies: - cacache "^11.3.2" - find-cache-dir "^2.0.0" + cacache "^12.0.2" + find-cache-dir "^2.1.0" is-wsl "^1.1.0" - loader-utils "^1.2.3" schema-utils "^1.0.0" serialize-javascript "^1.7.0" source-map "^0.6.1" - terser "^4.0.0" - webpack-sources "^1.3.0" + terser "^4.1.2" + webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.1.0.tgz#fe949a2189345b2f1789f2bafc6c3b056dab16ed" - integrity sha512-O2MzVShUr/B+bxTh83ycpDR+Ocesg5qLR8kphWApRbWCkSnfKq1YPmydnVNfsJuJKHvzSgDNqFq4cr1O36oQ2A== +terser@^4.1.2: + version "4.3.9" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.9.tgz#e4be37f80553d02645668727777687dad26bbca8" + integrity sha512-NFGMpHjlzmyOtPL+fDw3G7+6Ueh/sz4mkaUYa4lJCxOPTNzd0Uj0aZJOmsDYoSQyfuVoWDMSWTPU3huyOm2zdA== dependencies: commander "^2.20.0" source-map "~0.6.1" @@ -10365,14 +10606,14 @@ through@^2.3.6, through@~2.3.4: integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= thunky@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.0.3.tgz#f5df732453407b09191dae73e2a8cc73f381a826" - integrity sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow== + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== timers-browserify@^2.0.4: - version "2.0.10" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" - integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg== + version "2.0.11" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" + integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== dependencies: setimmediate "^1.0.4" @@ -10708,9 +10949,9 @@ unzipper@^0.9.3: setimmediate "~1.0.4" upath@^1.1.0, upath@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" - integrity sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q== + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== upper-case@^1.1.1: version "1.1.3" @@ -10817,9 +11058,9 @@ utils-merge@1.0.1: integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= uuid@^3.0.1, uuid@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + version "3.3.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" + integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== v8flags@^2.1.1: version "2.1.1" @@ -10880,27 +11121,27 @@ vue-eslint-parser@^5.0.0: lodash "^4.17.11" vue-hot-reload-api@^2.3.0: - version "2.3.3" - resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.3.tgz#2756f46cb3258054c5f4723de8ae7e87302a1ccf" - integrity sha512-KmvZVtmM26BQOMK1rwUZsrqxEGeKiYSZGA7SNWE6uExx8UX/cj9hq2MRV/wWC3Cq6AoeDGk57rL9YMFRel/q+g== + version "2.3.4" + resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" + integrity sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog== -vue-loader@^15.2.4: - version "15.7.0" - resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.7.0.tgz#27275aa5a3ef4958c5379c006dd1436ad04b25b3" - integrity sha512-x+NZ4RIthQOxcFclEcs8sXGEWqnZHodL2J9Vq+hUz+TDZzBaDIh1j3d9M2IUlTjtrHTZy4uMuRdTi8BGws7jLA== +vue-loader@^15.7.1: + version "15.7.1" + resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.7.1.tgz#6ccacd4122aa80f69baaac08ff295a62e3aefcfd" + integrity sha512-fwIKtA23Pl/rqfYP5TSGK7gkEuLhoTvRYW+TU7ER3q9GpNLt/PjG5NLv3XHRDiTg7OPM1JcckBgds+VnAc+HbA== dependencies: - "@vue/component-compiler-utils" "^2.5.1" + "@vue/component-compiler-utils" "^3.0.0" hash-sum "^1.0.2" loader-utils "^1.1.0" vue-hot-reload-api "^2.3.0" vue-style-loader "^4.1.0" -vue-router@^3.0.2: - version "3.0.7" - resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.7.tgz#b36ca107b4acb8ff5bc4ff824584059c23fcb87b" - integrity sha512-utJ+QR3YlIC/6x6xq17UMXeAfxEvXA0VKD3PiSio7hBOZNusA1jXcbxZxVEfJunLp48oonjTepY8ORoIlRx/EQ== +vue-router@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.1.3.tgz#e6b14fabc0c0ee9fda0e2cbbda74b350e28e412b" + integrity sha512-8iSa4mGNXBjyuSZFCCO4fiKfvzqk+mhL0lnKuGcQtO1eoj8nq3CmbEG8FwK5QqoqwDgsjsf1GDuisDX4cdb/aQ== -vue-server-renderer@^2.5.16: +vue-server-renderer@^2.6.10: version "2.6.10" resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.6.10.tgz#cb2558842ead360ae2ec1f3719b75564a805b375" integrity sha512-UYoCEutBpKzL2fKCwx8zlRtRtwxbPZXKTqbl2iIF4yRZUNO/ovrHyDAJDljft0kd+K0tZhN53XRHkgvCZoIhug== @@ -10922,7 +11163,7 @@ vue-style-loader@^4.1.0: hash-sum "^1.0.2" loader-utils "^1.0.2" -vue-template-compiler@^2.5.16: +vue-template-compiler@^2.6.10: version "2.6.10" resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz#323b4f3495f04faa3503337a82f5d6507799c9cc" integrity sha512-jVZkw4/I/HT5ZMvRnhv78okGusqe0+qH2A0Em0Cp8aq78+NK9TII263CDVz2QXZsIT+yyV/gZc/j/vlwa+Epyg== @@ -10935,7 +11176,7 @@ vue-template-es2015-compiler@^1.9.0: resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== -vue@^2.5.16, vue@^2.6.10: +vue@^2.6.10: version "2.6.10" resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637" integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ== @@ -10953,22 +11194,30 @@ vuepress-html-webpack-plugin@^3.2.0: toposort "^1.0.0" util.promisify "1.0.0" -vuepress-plugin-container@^2.0.0: +vuepress-plugin-container@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/vuepress-plugin-container/-/vuepress-plugin-container-2.0.2.tgz#3489cc732c7a210b31f202556e1346125dffeb73" integrity sha512-SrGYYT7lkie7xlIlAVhn+9sDW42MytNCoxWL/2uDr+q9wZA4h1uYlQvfc2DVjy+FsM9PPPSslkeo/zCpYVY82g== dependencies: markdown-it-container "^2.0.0" +vuepress-plugin-smooth-scroll@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/vuepress-plugin-smooth-scroll/-/vuepress-plugin-smooth-scroll-0.0.3.tgz#6eff2d4c186cca917cc9f7df2b0af7de7c8c6438" + integrity sha512-qsQkDftLVFLe8BiviIHaLV0Ea38YLZKKonDGsNQy1IE0wllFpFIEldWD8frWZtDFdx6b/O3KDMgVQ0qp5NjJCg== + dependencies: + smoothscroll-polyfill "^0.4.3" + vuepress@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/vuepress/-/vuepress-1.0.2.tgz#da62d6e43faca0b8af0bcffff6975fa27dbfdea3" - integrity sha512-HPRWxrq6D+S9uCR3oJ8/OTCy8GcYm9l1HxHb44rvaN2gyySVXIiqSkCwzd9r2PY8+pwvrfYE4rcY1RsTTpJ25g== + version "1.2.0" + resolved "https://registry.yarnpkg.com/vuepress/-/vuepress-1.2.0.tgz#2f2cdf337ad40a3e4866dfd33e97b840db386af7" + integrity sha512-EfHo8Cc73qo+1Pm18hM0qOGynmDr8q5fu2664obynsdCJ1zpvoShVnA0Msraw4SI2xDc0iAoIb3dTwxUIM8DAw== dependencies: - "@vuepress/core" "^1.0.2" - "@vuepress/theme-default" "^1.0.2" + "@vuepress/core" "^1.2.0" + "@vuepress/theme-default" "^1.2.0" cac "^6.3.9" envinfo "^7.2.0" + opencollective-postinstall "^2.0.2" vuex@^3.1.0: version "3.1.1" @@ -10991,7 +11240,7 @@ w3c-xmlserializer@^1.1.2: webidl-conversions "^4.0.2" xml-name-validator "^3.0.0" -watchpack@^1.5.0: +watchpack@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== @@ -11020,51 +11269,54 @@ webpack-chain@^4.6.0, webpack-chain@^4.9.0: deepmerge "^1.5.2" javascript-stringify "^1.6.0" -webpack-dev-middleware@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz#ef751d25f4e9a5c8a35da600c5fda3582b5c6cff" - integrity sha512-qvDesR1QZRIAZHOE3iQ4CXLZZSQ1lAUsSpnQmlB1PBfoN/xdRjmge3Dok0W4IdaVLJOGJy3sGI4sZHwjRU0PCA== +webpack-dev-middleware@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3" + integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw== dependencies: memory-fs "^0.4.1" - mime "^2.4.2" + mime "^2.4.4" + mkdirp "^0.5.1" range-parser "^1.2.1" webpack-log "^2.0.0" webpack-dev-server@^3.5.1: - version "3.7.2" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.7.2.tgz#f79caa5974b7f8b63268ef5421222a8486d792f5" - integrity sha512-mjWtrKJW2T9SsjJ4/dxDC2fkFVUw8jlpemDERqV0ZJIkjjjamR2AbQlr3oz+j4JLhYCHImHnXZK5H06P2wvUew== + version "3.8.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.8.2.tgz#3292427bf6510da9a3ac2d500b924a4197667ff9" + integrity sha512-0xxogS7n5jHDQWy0WST0q6Ykp7UGj4YvWh+HVN71JoE7BwPxMZrwgraBvmdEMbDVMBzF0u+mEzn8TQzBm5NYJQ== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" - chokidar "^2.1.6" + chokidar "^2.1.8" compression "^1.7.4" connect-history-api-fallback "^1.6.0" debug "^4.1.1" del "^4.1.1" express "^4.17.1" html-entities "^1.2.1" - http-proxy-middleware "^0.19.1" + http-proxy-middleware "0.19.1" import-local "^2.0.0" internal-ip "^4.3.0" ip "^1.1.5" + is-absolute-url "^3.0.3" killable "^1.0.1" - loglevel "^1.6.3" + loglevel "^1.6.4" opn "^5.5.0" p-retry "^3.0.1" - portfinder "^1.0.20" + portfinder "^1.0.24" schema-utils "^1.0.0" - selfsigned "^1.10.4" - semver "^6.1.1" + selfsigned "^1.10.7" + semver "^6.3.0" serve-index "^1.9.1" sockjs "0.3.19" - sockjs-client "1.3.0" - spdy "^4.0.0" + sockjs-client "1.4.0" + spdy "^4.0.1" strip-ansi "^3.0.1" supports-color "^6.1.0" url "^0.11.0" - webpack-dev-middleware "^3.7.0" + webpack-dev-middleware "^3.7.2" webpack-log "^2.0.0" + ws "^6.2.1" yargs "12.0.5" webpack-log@^2.0.0: @@ -11076,49 +11328,48 @@ webpack-log@^2.0.0: uuid "^3.3.2" webpack-merge@^4.1.2: - version "4.2.1" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.1.tgz#5e923cf802ea2ace4fd5af1d3247368a633489b4" - integrity sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw== + version "4.2.2" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" + integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== dependencies: - lodash "^4.17.5" + lodash "^4.17.15" -webpack-sources@^1.1.0, webpack-sources@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" - integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA== +webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== dependencies: source-list-map "^2.0.0" source-map "~0.6.1" webpack@^4.8.1: - version "4.35.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.35.2.tgz#5c8b8a66602cbbd6ec65c6e6747914a61c1449b1" - integrity sha512-TZAmorNymV4q66gAM/h90cEjG+N3627Q2MnkSgKlX/z3DlNVKUtqy57lz1WmZU2+FUZwzM+qm7cGaO95PyrX5A== + version "4.41.2" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.2.tgz#c34ec76daa3a8468c9b61a50336d8e3303dce74e" + integrity sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A== dependencies: "@webassemblyjs/ast" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5" "@webassemblyjs/wasm-edit" "1.8.5" "@webassemblyjs/wasm-parser" "1.8.5" - acorn "^6.0.5" - acorn-dynamic-import "^4.0.0" - ajv "^6.1.0" - ajv-keywords "^3.1.0" - chrome-trace-event "^1.0.0" + acorn "^6.2.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" enhanced-resolve "^4.1.0" - eslint-scope "^4.0.0" + eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" - loader-runner "^2.3.0" - loader-utils "^1.1.0" - memory-fs "~0.4.1" - micromatch "^3.1.8" - mkdirp "~0.5.0" - neo-async "^2.5.0" - node-libs-browser "^2.0.0" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.1" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" schema-utils "^1.0.0" - tapable "^1.1.0" - terser-webpack-plugin "^1.1.0" - watchpack "^1.5.0" - webpack-sources "^1.3.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.1" + watchpack "^1.6.0" + webpack-sources "^1.4.1" webpackbar@3.2.0: version "3.2.0" @@ -11251,7 +11502,7 @@ write@^0.2.1: dependencies: mkdirp "^0.5.1" -ws@^6.1.2: +ws@^6.1.2, ws@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== @@ -11290,7 +11541,12 @@ xmlhttprequest-ssl@~1.5.4: resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4= -xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +xtend@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68= @@ -11311,9 +11567,9 @@ yallist@^2.1.2: integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" - integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yargs-parser@^11.1.1: version "11.1.1" From 73b27ccd12ce4adefa2c733aa540c2637b0a5eec Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 17 Oct 2019 22:47:35 -0600 Subject: [PATCH 378/404] Move FeathersVuexFormWrapper docs in with other docs --- docs/feathers-vuex-form-wrapper.md | 41 ++++++++++++++++++++++++++++++ src/FeathersVuexFormWrapper.md | 15 ----------- 2 files changed, 41 insertions(+), 15 deletions(-) create mode 100644 docs/feathers-vuex-form-wrapper.md delete mode 100644 src/FeathersVuexFormWrapper.md diff --git a/docs/feathers-vuex-form-wrapper.md b/docs/feathers-vuex-form-wrapper.md new file mode 100644 index 00000000..b1dce90a --- /dev/null +++ b/docs/feathers-vuex-form-wrapper.md @@ -0,0 +1,41 @@ + +# FeathersVuexFormWrapper + +The `FeathersVuexFormWrapper` is a renderless component which assists in connecting your feathers-vuex data to a form. Let's review why it exists by looking at a couple of common patterns. + +## The Mutation Multiplicity (anti) Pattern + +When working with Vuex, it's considered an anti-pattern to modify store data directly. Turn on Vuex strict mode, and it will throw an error every time you modify store data outside of a mutation. In my experience, the most common (anti)pattern that beginners use to work around this "limitation" is to + +1. Read data from the store and use it for display in the UI. +2. Create custom mutations intended to modify the data in specific ways. +3. Use the mutations wherever they apply (usually implemented as one mutation per form). + +There are times when defining custom mutations is the most supportive pattern for the task, but I consider them to be more rare. The above pattern can result in a huge number of mutations, extra lines of code, and increased long-term maintenance costs. + +## The Clone and Commit Pattern + +The "Clone and Commit" pattern provides an alternative to using a lot of mutations. This patterns looks more like this: + +1. Read data from the store and use it for display in the UI. (Same as above) +2. Create and modify a clone of the data. +3. Use a single mutation to commit the changes back to the original record in the store. + +Send most edits through a single mutation can really simplify the way you work with Vuex data. The Feathers-Vuex `BaseModel` class has `clone` and `commit` instance methods. Those methods are used inside the FeathersVuexFormWrapper component. + +## Usage + +The `FeathersVuexFormWrapper` component uses the "clone and commit" pattern to connect a single record to a child form within its default slot. + +```html + + + +``` diff --git a/src/FeathersVuexFormWrapper.md b/src/FeathersVuexFormWrapper.md deleted file mode 100644 index aa8ba2f5..00000000 --- a/src/FeathersVuexFormWrapper.md +++ /dev/null @@ -1,15 +0,0 @@ - -# FeathersVuexFormWrapper - -```html - - - -``` From a83ee68df496fc6de3f81e9a497c99802ee60419 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 17 Oct 2019 23:10:16 -0600 Subject: [PATCH 379/404] More Form Wrapper docs --- docs/.vuepress/config.js | 1 + docs/feathers-vuex-form-wrapper.md | 29 ++++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 85d3ceb6..d0242d0e 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -14,6 +14,7 @@ module.exports = { '/common-patterns.md', '/mixins.md', '/components.md', + '/feathers-vuex-form-wrapper.md', '/nuxt.md' ], serviceWorker: { diff --git a/docs/feathers-vuex-form-wrapper.md b/docs/feathers-vuex-form-wrapper.md index b1dce90a..753b7fb4 100644 --- a/docs/feathers-vuex-form-wrapper.md +++ b/docs/feathers-vuex-form-wrapper.md @@ -1,7 +1,11 @@ - -# FeathersVuexFormWrapper +--- +title: Working with Forms +sidebarDepth: 3 +--- -The `FeathersVuexFormWrapper` is a renderless component which assists in connecting your feathers-vuex data to a form. Let's review why it exists by looking at a couple of common patterns. +# Working with Forms + +The `FeathersVuexFormWrapper` is a renderless component which assists in connecting your feathers-vuex data to a form. The next two sections review why it exists by looking at a couple of common patterns. Proceed to the [FeathersVuexFormWrapper](#feathersvuexformwrapper) section to learn how to implement. ## The Mutation Multiplicity (anti) Pattern @@ -23,7 +27,7 @@ The "Clone and Commit" pattern provides an alternative to using a lot of mutatio Send most edits through a single mutation can really simplify the way you work with Vuex data. The Feathers-Vuex `BaseModel` class has `clone` and `commit` instance methods. Those methods are used inside the FeathersVuexFormWrapper component. -## Usage +## FeathersVuexFormWrapper The `FeathersVuexFormWrapper` component uses the "clone and commit" pattern to connect a single record to a child form within its default slot. @@ -32,10 +36,25 @@ The `FeathersVuexFormWrapper` component uses the "clone and commit" pattern to c ``` + +### Props + +- `item`: {Object} a model instance from the Vuex store. +- `watch`: {Boolean|Array} when enabled, if the original record is updated, the data will be re-cloned. The newly-cloned data will overwrite the `clone` data (in the slot scope). Default: `false`. +- `eager`: {Boolean} While this is enabled, using the `save` method will first commit the result to the store then it will send a network request. The UI display will update immediately, without waiting for any response from the API server. Default: `true`. + +### Slot Scope + +The default slot contains only four attributes. The `clone` data can be passed to the child component. The `save`, `reset`, and `remove` are meant to be bound to events emitted from the child component. + +- `clone`: {Object} The cloned record. Each record in the store can have a single clone. The clones are stored on the service's model class, by default. +- `save`: {Function} When called, it commits the data and saves the record (with eager updating, by default. See the `eager` prop.). +- `reset`: {Function} When called, the clone data will be reset back to the data that is currently found in the store for the same record. +- `remove`: {Function} When called, it removes the record from the API server and the Vuex store. \ No newline at end of file From 9c70e334c8c5e178c2b694dd5e8a9eae8d332f77 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 17 Oct 2019 23:17:48 -0600 Subject: [PATCH 380/404] Rename components page to data-components page --- docs/.vuepress/config.js | 2 +- docs/{components.md => data-components.md} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename docs/{components.md => data-components.md} (100%) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index d0242d0e..c413751e 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -13,7 +13,7 @@ module.exports = { '/model-classes.md', '/common-patterns.md', '/mixins.md', - '/components.md', + '/data-components.md', '/feathers-vuex-form-wrapper.md', '/nuxt.md' ], diff --git a/docs/components.md b/docs/data-components.md similarity index 100% rename from docs/components.md rename to docs/data-components.md From 8665e5301eb5b6f050d377f5db7cf313f823b5fb Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Thu, 17 Oct 2019 23:18:07 -0600 Subject: [PATCH 381/404] docs: clarify new and improved features --- docs/api-overview.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/api-overview.md b/docs/api-overview.md index 80ec5fd5..6792aea2 100755 --- a/docs/api-overview.md +++ b/docs/api-overview.md @@ -13,7 +13,7 @@ title: API Overview `feathers-vuex` is a first class integration of the Feathers Client and Vuex. It implements many Redux best practices under the hood, eliminates *a lot* of boilerplate code, and still allows you to easily customize the Vuex store. -These docs are for version 2.x. For feathers-vuex@1.x, please go to [feathers-vuex-v1.netlify.com](feathers-vuex-v1.netlify.com). +These docs are for version 2.x. For feathers-vuex@1.x, please go to [https://feathers-vuex-v1.netlify.com](feathers-vuex-v1.netlify.com). ## Features @@ -26,15 +26,17 @@ These docs are for version 2.x. For feathers-vuex@1.x, please go to [feathers-v - Vuex Strict Mode Support - Client-Side Pagination Support - Fall-Through Caching * -- `$FeathersVuex` [Vue Plugin](./vue-plugin.md) * +- [`$FeathersVuex` Plugin for Vue](./vue-plugin.md) * - [Per-Service Data Modeling](./common-patterns.md#Basic-Data-Modeling-with-instanceDefaults) * - Clone & Commit * - Simplified Auth * - Per-Record Defaults * - Data Level Computed Properties * - Improved Relation Support * -- Renderless Data Components * - Powerful Mixins * +- Renderless Data Components * +- Renderless Form Component ** +- Temporary (Local-only) Record Support ** - Server-Powered Pagination Support ** `* Improved in v2.0.0`
From 8a9468a22dd0ed9f8988575e44f68d862265d9ad Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 18 Oct 2019 00:29:19 -0600 Subject: [PATCH 382/404] Add Dark mode support to docs --- docs/.vuepress/config.js | 1 + package.json | 3 ++- yarn.lock | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index c413751e..852f8fe5 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -1,6 +1,7 @@ module.exports = { title: 'FeathersVuex', description: 'Integration of FeathersJS, Vue, and Nuxt for the artisan developer', + theme: 'default-prefers-color-scheme', themeConfig: { repo: 'feathers-plus/feathers-vuex', docsDir: 'docs', diff --git a/package.json b/package.json index ac4ec861..7ee549c9 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,8 @@ "lodash.trim": "^4.5.1", "serialize-error": "^3.0.0", "sift": "^7.0.1", - "steal-typescript": "^0.5.0" + "steal-typescript": "^0.5.0", + "vuepress-theme-default-prefers-color-scheme": "^1.0.3" }, "devDependencies": { "@feathersjs/authentication-client": "^1.0.11", diff --git a/yarn.lock b/yarn.lock index 9806a592..a320d72a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3697,6 +3697,13 @@ css-parse@~2.0.0: dependencies: css "^2.0.0" +css-prefers-color-scheme@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" + integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg== + dependencies: + postcss "^7.0.5" + css-select-base-adapter@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" @@ -11208,6 +11215,13 @@ vuepress-plugin-smooth-scroll@^0.0.3: dependencies: smoothscroll-polyfill "^0.4.3" +vuepress-theme-default-prefers-color-scheme@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/vuepress-theme-default-prefers-color-scheme/-/vuepress-theme-default-prefers-color-scheme-1.0.3.tgz#85d5872a05b2cdc9ff3d22ba24380699f60fd3ad" + integrity sha512-CNu+opm+yvdObtzhxa2Mm4d3Ho9aM3NM17RKFpJ77soXeNX7muox+npKTSZiZwY685CFgFAJpSTm01/2f3aPCA== + dependencies: + css-prefers-color-scheme "^3.1.1" + vuepress@^1.0.2: version "1.2.0" resolved "https://registry.yarnpkg.com/vuepress/-/vuepress-1.2.0.tgz#2f2cdf337ad40a3e4866dfd33e97b840db386af7" From 731f2f98962fe2f7e3d287c36f0b8ce81a62c2e0 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Fri, 18 Oct 2019 00:34:10 -0600 Subject: [PATCH 383/404] docs: rename module to plugin, where applicable --- docs/.vuepress/config.js | 4 +- docs/api-overview.md | 127 +++++++++--------- docs/{auth-module.md => auth-plugin.md} | 2 +- docs/common-patterns.md | 12 +- docs/index.md | 2 +- docs/model-classes.md | 10 +- docs/{service-module.md => service-plugin.md} | 63 ++++++++- docs/vue-plugin.md | 2 +- src/index.ts | 4 +- 9 files changed, 142 insertions(+), 84 deletions(-) rename docs/{auth-module.md => auth-plugin.md} (98%) rename docs/{service-module.md => service-plugin.md} (92%) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 852f8fe5..b0890202 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -9,8 +9,8 @@ module.exports = { sidebar: [ '/api-overview.md', '/vue-plugin.md', - '/service-module.md', - '/auth-module.md', + '/service-plugin.md', + '/auth-plugin.md', '/model-classes.md', '/common-patterns.md', '/mixins.md', diff --git a/docs/api-overview.md b/docs/api-overview.md index 6792aea2..ea57e556 100755 --- a/docs/api-overview.md +++ b/docs/api-overview.md @@ -38,6 +38,7 @@ These docs are for version 2.x. For feathers-vuex@1.x, please go to [https://fe - Renderless Form Component ** - Temporary (Local-only) Record Support ** - Server-Powered Pagination Support ** +- [VuePress Dark Mode Support](https://tolking.github.io/vuepress-theme-default-prefers-color-scheme/) for the Docs ** `* Improved in v2.0.0`
`** New in v2.0.0` @@ -48,22 +49,37 @@ These docs are for version 2.x. For feathers-vuex@1.x, please go to [https://fe npm install feathers-vuex --save ``` +```bash +yarn add feathers-vuex +``` + ## Use Using Feathers-Vuex happens in these steps: -1. Setup the Feathers client and Feathers-Vuex. -2. Define a Model class and service plugin for each service. -3. Register the plugins with the Vuex store. +1. [Setup the Feathers client and Feathers-Vuex](#setup-the-feathers-client-and-feathers-vuex) +2. [Define a Model class and service plugin for each service](#setup-one-or-more-service-plugins) +3. [Setup the auth plugin](#setup-the-auth-plugin), if required. +4. Register the plugins with the Vuex store. ### Setup the Feathers Client and Feathers-Vuex To setup `feathers-vuex`, we first need to setup the latest Feathers client. We can also setup feathers-vuex in the same file. +First, let's install dependencies. + +```bash +npm i @feathersjs/feathers @feathersjs/socketio-client @feathersjs/authentication-client feathers-hooks-common socket.io-client feathers-vuex --save +``` + +```bash +yarn add @feathersjs/feathers @feathersjs/socketio-client @feathersjs/authentication-client feathers-hooks-common socket.io-client feathers-vuex +``` + Note that this example includes an app-level hook that removes attributes for handling temporary (local-only) records. ```js -// feathers-client.js +// src/feathers-client.js import feathers from '@feathersjs/feathers' import socketio from '@feathersjs/socketio-client' import auth from '@feathersjs/authentication-client' @@ -92,8 +108,8 @@ export default feathersClient const { makeServicePlugin, makeAuthPlugin, BaseModel, models } = feathersVuex( feathersClient, { - serverAlias: 'api', - idField: '_id', + serverAlias: 'api', // optional for working with multiple APIs (this is the default value) + idField: '_id', // Must match the id field in your database table/collection whitelist: ['$regex', '$options'] } ) @@ -103,10 +119,10 @@ export { makeAuthPlugin, makeServicePlugin, BaseModel, models } ### Setup one or more service plugins -The following example creates a User class and registers it with the new `makeServicePlugin` utility function. +The following example creates a User class and registers it with the new `makeServicePlugin` utility function. This same file is also a great place to add your service-level hooks, so they're shown, too. ```js -// services/users.js +// src/store/services/users.js import { makeServicePlugin, BaseModel } from '../feathers-client' class User extends BaseModel { @@ -129,11 +145,7 @@ const servicePlugin = makeServicePlugin({ service: feathersClient.service(servicePath), servicePath }) -``` - -This same file is also a great place to add your service-level hooks, so append the following. -```js // Setup the client-side Feathers hooks. feathersClient.service(servicePath).hooks({ before: { @@ -166,67 +178,52 @@ feathersClient.service(servicePath).hooks({ }) export default servicePlugin +``` + +### Setup the Auth Plugin + +If your application uses authentication, the Auth Plugin will probably come in handy. It's a couple of lines to setup: + +```js +// src/store/store.auth.js +import { makeAuthPlugin } from '../feathers-client' +export default makeAuthPlugin({ userService: 'users' }) ``` +[Read more about the Auth Plugin](/auth-plugin.html). + +### Add the plugins to the Vuex store. ```js -// store/index.js +// src/store/store.js import Vue from 'vue' import Vuex from 'vuex' -import feathersVuex from 'feathers-vuex' -import feathersClient from '../feathers-client' - -const { service, auth, FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' }) +import { FeathersVuex } from '../feathers-client' +import auth from './store.auth' Vue.use(Vuex) Vue.use(FeathersVuex) +const requireModule = require.context( + // The path where the service modules live + './services', + // Whether to look in subfolders + false, + // Only include .js files (prevents duplicate imports`) + /.js$/ +) +const servicePlugins = requireModule + .keys() + .map(modulePath => requireModule(modulePath).default) + export default new Vuex.Store({ - plugins: [ - service('todos'), - - // Specify custom options per service - service('/v1/tasks', { - idField: '_id', // The field in each record that will contain the id - nameStyle: 'path', // Use the full service path as the Vuex module name, instead of just the last section - namespace: 'custom-namespace', // Customize the Vuex module name. Overrides nameStyle. - debug: true, // Enable some logging for debugging - autoRemove: true, // Automatically remove records missing from responses (only use with feathers-rest) - enableEvents: false, // Turn off socket event listeners. It's true by default - addOnUpsert: true, // Add new records pushed by 'updated/patched' socketio events into store, instead of discarding them. It's false by default - replaceItems: true, // If true, updates & patches replace the record in the store. Default is false, which merges in changes - skipRequestIfExists: true, // For get action, if the record already exists in store, skip the remote request. It's false by default - modelName: 'OldTask' // Default modelName would have been 'Task' - }) - - // Add custom state, getters, mutations, or actions, if needed. See example in another section, below. - service('things', { - state: {}, - getters: {}, - mutations: {}, - actions: {} - }) - - // Setup a service with defaults for Model instances - service('manufacturers', { - instanceDefaults: { - name: '' - } - }) - // Setup a service with light-weight relational data - service('models', { - instanceDefaults: { - name: '', - manufacturerId: '', - manufacturer: 'Manufacturer' // Refers to data (populated on the server) that gets put in the `manufacturers` vuex store. - } - }) - - // Setup the auth plugin. - auth({ userService: 'users' }) - ] + state: {}, + mutations: {}, + actions: {}, + plugins: [...servicePlugins, auth] }) + ``` The new `feathers-vuex` API is more Vuex-like. All of the functionality remains the same, but it is no longer configured like a FeathersJS plugin. While the previous functionality was nice for prototyping, it didn't work well in SSR scenarios, like with Nuxt. @@ -253,15 +250,15 @@ const defaultOptions = { Each service module can also be individually configured. -## The Vuex modules +## The Vuex Plugins -There are two modules included: +There are two plugins included: -1. The [Service module](./service-module.md) adds a Vuex store for new services. -2. The [Auth module](./auth-module.md) sets up the Vuex store for authentication / logout. +1. The [Service Plugin](./service-plugin.md) adds a Vuex store for new services. +2. The [Auth Plugin](./auth-plugin.md) sets up the Vuex store for authentication / logout. ## License -Copyright (c) Forever and Ever, or at least the current year. +Copyright (c) Forever, or at least the current year. Licensed under the [MIT license](LICENSE). diff --git a/docs/auth-module.md b/docs/auth-plugin.md similarity index 98% rename from docs/auth-module.md rename to docs/auth-plugin.md index 14485064..05e5f335 100644 --- a/docs/auth-module.md +++ b/docs/auth-plugin.md @@ -1,5 +1,5 @@ --- -title: Auth Module API +title: Auth Plugin --- The Auth module helps setup your app for login / logout. It includes the following state by default: diff --git a/docs/common-patterns.md b/docs/common-patterns.md index f0adce44..fbf9afb5 100755 --- a/docs/common-patterns.md +++ b/docs/common-patterns.md @@ -12,11 +12,11 @@ You can set `debug: true` in the options to enable some logging to assist with d ## Use the `` and `` components -Using the new `` and `` components provides concise access to the best features of `feathers-vuex`, including live queries, reactive lists, custom pagination tracking per component, and fall-through cacheing of local data in the Vuex store. Check out the [Renderless Data Components](./components.md) docs for more details. +Using the new `` and `` components provides concise access to the best features of `feathers-vuex`, including live queries, reactive lists, custom pagination tracking per component, and fall-through cacheing of local data in the Vuex store. Check out the [Renderless Data Components](./components.html) docs for more details. ## Use the `makeFindMixin` and `makeGetMixin` utilities -The mixin utilities provide the same functionality as the components, but with more power and flexibility. Check out the [Mixin docs](./mixins.md) for more details. +The mixin utilities provide the same functionality as the components, but with more power and flexibility. Check out the [Mixin docs](./mixins.html) for more details. ## Working with TypeScript @@ -28,7 +28,7 @@ The best solution is to simply refresh to clear memory. The alternative to refr ## Accessing the store from hooks -Because the service's Model [is available](./service-module.md#The-FeathersClient-Service) at `service.FeathersVuexModel`, you can access the store inside hooks. This is especially handy if you have some custom attributes in a paginated server response. +Because the service's Model [is available](./service-plugin.html#The-FeathersClient-Service) at `service.FeathersVuexModel`, you can access the store inside hooks. This is especially handy if you have some custom attributes in a paginated server response. As an example, this `speeding-tickets` service has a `summary` attribute that comes back in the response. We can @@ -73,7 +73,7 @@ Sometimes your server response may contain more attributes than just database re Depending on what you need to do, you may be able to solve this by [accessing the store from hooks](#Accessing-the-store-from-hooks). But that solution won't handle a scenario where you need the response data to be already populated in the store. -If you need the response data to already be in the store, you can use the [`afterFind` action](./service-module.md#afterFind-response). Here's what this looks like: +If you need the response data to already be in the store, you can use the [`afterFind` action](./service-plugin.html#afterFind-response). Here's what this looks like: ```js import feathersVuex from 'feathers-vuex' @@ -289,7 +289,7 @@ In summary, you can plan on individual records in the action response data to be ## Basic Data Modeling with `instanceDefaults` -See the [instanceDefaults API](./model-classes.md#instanceDefaults) +See the [instanceDefaults API](./model-classes.html#instanceDefaults) ## Model-Specific Computed Properties @@ -371,7 +371,7 @@ instanceDefaults: { } ``` -When this record is instantiated, the `user` attribute will first be turned into a User [model instance](./model-classes.md), stored properly in the `/users` store. The `todo.user` attribute will be a reference to that user. No more duplicate data! Here's an example of how to set this up. The following example specifies that Todo instances can have a `user` attribute that contains a `User` Model instance: +When this record is instantiated, the `user` attribute will first be turned into a User [model instance](./model-classes.html), stored properly in the `/users` store. The `todo.user` attribute will be a reference to that user. No more duplicate data! Here's an example of how to set this up. The following example specifies that Todo instances can have a `user` attribute that contains a `User` Model instance: ```js import Vue from 'vue' diff --git a/docs/index.md b/docs/index.md index b4aae9cf..70e2f646 100755 --- a/docs/index.md +++ b/docs/index.md @@ -9,7 +9,7 @@ features: - title: Realtime by Default details: It's fully powered by Vuex and FeathersJS, lightweight, & realtime out of the box. - title: Simplified Auth & Services - details: Includes modules for making auth and service plugins powered by Vuex. All plugins can be easily customized to fit your app. Fully flexible. + details: Includes service and auth plugins powered by Vuex. All plugins can be easily customized to fit your app. Fully flexible. - title: Best Practices, Baked In details: Common Redux patterns come included. Fall-through cache comes standard. Query the vuex store like a database. footer: MIT Licensed | Copyright © 2017-present Marshall Thompson diff --git a/docs/model-classes.md b/docs/model-classes.md index 2f20dd33..b2429e26 100644 --- a/docs/model-classes.md +++ b/docs/model-classes.md @@ -1,5 +1,5 @@ --- -title: Models & Instances API +title: Data Modeling --- @@ -17,7 +17,7 @@ The following attributes are available on each model: ### Model.find(params) -Model classes have a `find` method, which is a proxy to the [`find` action](./service-module.md#find-params). +Model classes have a `find` method, which is a proxy to the [`find` action](./service-plugin.html#find-params). ```js // In your Vue component @@ -29,7 +29,7 @@ created () { ### Model.findInStore(params) -Model classes have a `findInStore` method, which is a proxy to the [`find` getter](./service-module.md#Service-Getters). +Model classes have a `findInStore` method, which is a proxy to the [`find` getter](./service-plugin.html#Service-Getters). ```js // In your Vue component @@ -41,7 +41,7 @@ created () { ### Model.get(id, params) -Model classes have a `get` method, which is a proxy to the [`get` action](./service-module.md#get-id-or-get-id-params). Notice that the signature is more Feathers-like, and doesn't require using an array to passing both id and params. +Model classes have a `get` method, which is a proxy to the [`get` action](./service-plugin.html#get-id-or-get-id-params). Notice that the signature is more Feathers-like, and doesn't require using an array to passing both id and params. ```js // In your Vue component @@ -53,7 +53,7 @@ created () { ### Model.getFromStore(id, params) -Model classes have a `getFromStore` method, which is a proxy to the [`get` getter](./service-module.md#Service-Getters). Notice that the signature is more Feathers-like, and doesn't require using an array to passing both id and params. +Model classes have a `getFromStore` method, which is a proxy to the [`get` getter](./service-plugin.html#Service-Getters). Notice that the signature is more Feathers-like, and doesn't require using an array to passing both id and params. ```js // In your Vue component diff --git a/docs/service-module.md b/docs/service-plugin.md similarity index 92% rename from docs/service-module.md rename to docs/service-plugin.md index c0f4e755..36ad999f 100644 --- a/docs/service-module.md +++ b/docs/service-plugin.md @@ -1,5 +1,5 @@ --- -title: Service Module API +title: Service Plugin --- @@ -44,6 +44,67 @@ export default new Vuex.Store({ }) ``` +Old example from the api-overview page: + +```js +// store/index.js +import Vue from 'vue' +import Vuex from 'vuex' +import feathersVuex from 'feathers-vuex' +import feathersClient from '../feathers-client' + +const { service, auth, FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' }) + +Vue.use(Vuex) +Vue.use(FeathersVuex) + +export default new Vuex.Store({ + plugins: [ + service('todos'), + + // Specify custom options per service + service('/v1/tasks', { + idField: '_id', // The field in each record that will contain the id + nameStyle: 'path', // Use the full service path as the Vuex module name, instead of just the last section + namespace: 'custom-namespace', // Customize the Vuex module name. Overrides nameStyle. + debug: true, // Enable some logging for debugging + autoRemove: true, // Automatically remove records missing from responses (only use with feathers-rest) + enableEvents: false, // Turn off socket event listeners. It's true by default + addOnUpsert: true, // Add new records pushed by 'updated/patched' socketio events into store, instead of discarding them. It's false by default + replaceItems: true, // If true, updates & patches replace the record in the store. Default is false, which merges in changes + skipRequestIfExists: true, // For get action, if the record already exists in store, skip the remote request. It's false by default + modelName: 'OldTask' // Default modelName would have been 'Task' + }) + + // Add custom state, getters, mutations, or actions, if needed. See example in another section, below. + service('things', { + state: {}, + getters: {}, + mutations: {}, + actions: {} + }) + + // Setup a service with defaults for Model instances + service('manufacturers', { + instanceDefaults: { + name: '' + } + }) + // Setup a service with light-weight relational data + service('models', { + instanceDefaults: { + name: '', + manufacturerId: '', + manufacturer: 'Manufacturer' // Refers to data (populated on the server) that gets put in the `manufacturers` vuex store. + } + }) + + // Setup the auth plugin. + auth({ userService: 'users' }) + ] +}) +``` + ## The FeathersClient Service Once the service plugin has been registered with Vuex, the FeathersClient Service will have a new `service.FeathersVuexModel` property. This provides access to the service's [Model class](./model-classes.md). diff --git a/docs/vue-plugin.md b/docs/vue-plugin.md index 9669ef25..1e5db1af 100644 --- a/docs/vue-plugin.md +++ b/docs/vue-plugin.md @@ -1,5 +1,5 @@ --- -title: Vue Plugin API +title: Vue Plugin --- This `feathers-vuex` release includes a Vue plugin which gives all of your components easy access to the exciting new Models feature. It also automatically registers the `feathers-vuex-data` component. You can pass `components: false` in the options to not globally register the component. Here's how to use the plugin: diff --git a/src/index.ts b/src/index.ts index f82c4d46..9c40f42c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ eslint @typescript-eslint/explicit-function-return-type: 0, @typescript-eslint/no-explicit-any: 0 */ -import setupAuthModule from './auth-module/auth-module' +import setupAuthPlugin from './auth-module/auth-module' import FeathersVuexFind from './FeathersVuexFind' import FeathersVuexGet from './FeathersVuexGet' import makeFindMixin from './make-find-mixin' @@ -56,7 +56,7 @@ export default function feathersVuex(feathers, options: FeathersVuexOptions) { return { makeServicePlugin, BaseModel, - makeAuthPlugin: setupAuthModule(feathers), + makeAuthPlugin: setupAuthPlugin(feathers), FeathersVuex, models, clients From 1a2d9ca57d735ce156fa46e65d83e17950323d6d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 19 Oct 2019 20:44:59 -0600 Subject: [PATCH 384/404] Rename docs:dev to docs:serve --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7ee549c9..dd052a6c 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "test": "mocha --require ts-node/register test/**/*.test.ts", "testee": "testee test/index.html --browsers firefox", "start": "npm run compile && node example/app", - "docs:dev": "vuepress dev docs", + "docs:serve": "vuepress dev docs", "docs:build": "vuepress build docs" }, "prettier": { From 654a0f5d068b234393f728ded464bfcc5b306e45 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 19 Oct 2019 21:39:54 -0600 Subject: [PATCH 385/404] Reorganize the api-overview page --- docs/api-overview.md | 71 +++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/docs/api-overview.md b/docs/api-overview.md index ea57e556..c9058784 100755 --- a/docs/api-overview.md +++ b/docs/api-overview.md @@ -1,5 +1,6 @@ --- title: API Overview +sidebarDepth: 3 --- @@ -53,29 +54,43 @@ npm install feathers-vuex --save yarn add feathers-vuex ``` -## Use +### With feathers-socketio -Using Feathers-Vuex happens in these steps: +A realtime-transport like Socket.io or Primus is required in order to take advantage of the real-time socket events built into Feathers-Vuex. The `feathers-hooks-common` package, specified below, is not required to work with Feathers-Vuex. -1. [Setup the Feathers client and Feathers-Vuex](#setup-the-feathers-client-and-feathers-vuex) -2. [Define a Model class and service plugin for each service](#setup-one-or-more-service-plugins) -3. [Setup the auth plugin](#setup-the-auth-plugin), if required. -4. Register the plugins with the Vuex store. +```bash +npm i @feathersjs/feathers @feathersjs/socketio-client @feathersjs/authentication-client socket.io-client feathers-vuex feathers-hooks-common --save +``` -### Setup the Feathers Client and Feathers-Vuex +```bash +yarn add @feathersjs/feathers @feathersjs/socketio-client @feathersjs/authentication-client socket.io-client feathers-vuex feathers-hooks-common +``` -To setup `feathers-vuex`, we first need to setup the latest Feathers client. We can also setup feathers-vuex in the same file. +### With feathers-rest -First, let's install dependencies. +Feathers-Vuex works with Feathers-Rest, but keep in mind that the `feathers-rest` client does not listen to socket events. The `feathers-hooks-common` package, specified below, is not required to work with Feathers-Vuex. ```bash -npm i @feathersjs/feathers @feathersjs/socketio-client @feathersjs/authentication-client feathers-hooks-common socket.io-client feathers-vuex --save +npm i @feathersjs/feathers @feathersjs/rest-client @feathersjs/authentication-client feathers-hooks-common feathers-vuex --save ``` ```bash -yarn add @feathersjs/feathers @feathersjs/socketio-client @feathersjs/authentication-client feathers-hooks-common socket.io-client feathers-vuex +yarn add @feathersjs/feathers @feathersjs/rest-client @feathersjs/authentication-client feathers-hooks-common feathers-vuex ``` +## Setup + +Using Feathers-Vuex happens in these steps: + +1. [Setup the Feathers client and Feathers-Vuex](#setup-the-feathers-client-and-feathers-vuex) +2. [Define a Model class and service plugin for each service](#setup-one-or-more-service-plugins) +3. [Setup the auth plugin](#setup-the-auth-plugin), if required. +4. Register the plugins with the Vuex store. + +### Feathers Client & Feathers-Vuex + +To setup `feathers-vuex`, we first need to setup the latest Feathers client. We can also setup feathers-vuex in the same file. Depending on your requirements, you'll need to install the feathers-client dependencies, as shown, above. + Note that this example includes an app-level hook that removes attributes for handling temporary (local-only) records. ```js @@ -117,7 +132,7 @@ const { makeServicePlugin, makeAuthPlugin, BaseModel, models } = feathersVuex( export { makeAuthPlugin, makeServicePlugin, BaseModel, models } ``` -### Setup one or more service plugins +### Service Plugins The following example creates a User class and registers it with the new `makeServicePlugin` utility function. This same file is also a great place to add your service-level hooks, so they're shown, too. @@ -180,7 +195,7 @@ feathersClient.service(servicePath).hooks({ export default servicePlugin ``` -### Setup the Auth Plugin +### Auth Plugin If your application uses authentication, the Auth Plugin will probably come in handy. It's a couple of lines to setup: @@ -193,7 +208,7 @@ export default makeAuthPlugin({ userService: 'users' }) [Read more about the Auth Plugin](/auth-plugin.html). -### Add the plugins to the Vuex store. +### Vuex store ```js // src/store/store.js @@ -223,18 +238,20 @@ export default new Vuex.Store({ actions: {}, plugins: [...servicePlugins, auth] }) - ``` -The new `feathers-vuex` API is more Vuex-like. All of the functionality remains the same, but it is no longer configured like a FeathersJS plugin. While the previous functionality was nice for prototyping, it didn't work well in SSR scenarios, like with Nuxt. +## Begin Using Feathers-Vuex -To see `feathers-vuex` in a working vue-cli application, check out [`feathers-chat-vuex`](https://github.com/feathers-plus/feathers-chat-vuex). +There are a couple of ways to use Feathers-Vuex. Version 2.0 heavily focuses on abstracting away the Vuex syntax in favor of using [Model classes](/model-classes.html). The Model classes are a layer on top of the Vuex getters, mutations, and actions. You can, of course, also directly use the [service plugin's getters, mutations, and actions](/service-plugin.html). -## Note about feathers-reactive +There are two plugins included: -Previous versions of this plugin required both RxJS and `feathers-reactive` to receive realtime updates. `feathers-vuex@1.0.0` has socket messaging support built in and takes advantage of Vuex reactivity, so RxJS and `feathers-reactive` are no longer required or supported. +1. The [Service Plugin](./service-plugin.md) adds a Vuex store for new services. +2. The [Auth Plugin](./auth-plugin.md) sets up the Vuex store for authentication / logout. + +To see `feathers-vuex` in a working vue-cli application, check out [`feathers-chat-vuex`](https://github.com/feathers-plus/feathers-chat-vuex). -## Global Configuration +### Global Configuration The following default options are available for configuration: @@ -248,17 +265,15 @@ const defaultOptions = { } ``` -Each service module can also be individually configured. - -## The Vuex Plugins +### Note about feathers-reactive -There are two plugins included: +Previous versions of this plugin required both RxJS and `feathers-reactive` to receive realtime updates. `feathers-vuex@1.0.0` has socket messaging support built in and takes advantage of Vuex reactivity, so RxJS and `feathers-reactive` are no longer required or supported. -1. The [Service Plugin](./service-plugin.md) adds a Vuex store for new services. -2. The [Auth Plugin](./auth-plugin.md) sets up the Vuex store for authentication / logout. +Each service module can also be individually configured. ## License -Copyright (c) Forever, or at least the current year. - Licensed under the [MIT license](LICENSE). + +Feathers-Vuex is developed and maintained by [Marshall Thompson](https://www.github.com/marshallswain). + From d6f332cc065d63bd638ad9d4ef5908a062d78776 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 19 Oct 2019 21:40:08 -0600 Subject: [PATCH 386/404] Docs: new vue-plugin docs --- docs/vue-plugin.md | 51 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/docs/vue-plugin.md b/docs/vue-plugin.md index 1e5db1af..01b929e0 100644 --- a/docs/vue-plugin.md +++ b/docs/vue-plugin.md @@ -2,29 +2,43 @@ title: Vue Plugin --- -This `feathers-vuex` release includes a Vue plugin which gives all of your components easy access to the exciting new Models feature. It also automatically registers the `feathers-vuex-data` component. You can pass `components: false` in the options to not globally register the component. Here's how to use the plugin: +# The Vue Plugin + +This `feathers-vuex` release includes a Vue plugin which gives all of your components easy access to the data modeling classes. It also automatically registers the included components. The below example is based on the [setup instructions in the API overview](/api-overview.html#setup). ```js +// src/store/store.js import Vue from 'vue' import Vuex from 'vuex' -import feathersVuex from 'feathers-vuex' -import feathersClient from './feathers-client' - -// Get a reference to the FeathersVuex plugin -const { service, auth, FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' }) +import { FeathersVuex } from '../feathers-client' +import auth from './store.auth' -// Register the plugin with Vue. -Vue.use(FeathersVuex) Vue.use(Vuex) +Vue.use(FeathersVuex) + +const requireModule = require.context( + // The path where the service modules live + './services', + // Whether to look in subfolders + false, + // Only include .js files (prevents duplicate imports`) + /.js$/ +) +const servicePlugins = requireModule + .keys() + .map(modulePath => requireModule(modulePath).default) export default new Vuex.Store({ - plugins: [ - service('todos') - ] + state: {}, + mutations: {}, + actions: {}, + plugins: [...servicePlugins, auth] }) ``` -Now, in your components, you'll have access to the `this.$FeathersVuex` object, which contains references to the Model classes, keyed by name. The name of the model class is automatically inflected to singular, initial caps, based on the last section of the service path (split by `/`). Here are some examples of what this looks like: +## Using the Vue Plugin + +Once registered, you'll have access to the `this.$FeathersVuex` object, which contains references to the Model classes, keyed by name. The name of the model class is automatically inflected to singular, initial caps, based on the last section of the service path (split by `/`). Here are some examples of what this looks like: | Service Name | Model Name in `$FeathersVuex` | | ------------------------- | ----------------------------- | @@ -42,3 +56,16 @@ created () { // `todo` is now a model instance } ``` + +## Included Components + +When you register the Vue Plugin, a few components are automatically globally registered: + +- The [Renderless Data components](/data-components.html) +- The [`FeathersVuexFormWrapper` component](/feathers-vuex-form-wrapper.html) + +You can pass `components: false` in the options to not globally register the component: + +```js +Vue.use(FeathersVuex, { components: false }) +``` \ No newline at end of file From 587779f25403d381d017caf33798c5a4dfc259f9 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 19 Oct 2019 21:41:53 -0600 Subject: [PATCH 387/404] feat: FeathersVuexFormWrapper in the vue plugin This adds the FeathersVuexFormWrapper so that it automatically gets installed by the Vue Plugin. --- src/vue-plugin/vue-plugin.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vue-plugin/vue-plugin.ts b/src/vue-plugin/vue-plugin.ts index 590c416b..673a9388 100644 --- a/src/vue-plugin/vue-plugin.ts +++ b/src/vue-plugin/vue-plugin.ts @@ -5,6 +5,7 @@ eslint */ import FeathersVuexFind from '../FeathersVuexFind' import FeathersVuexGet from '../FeathersVuexGet' +import FeathersVuexFormWrapper from '../FeathersVuexFormWrapper' import { globalModels } from '../service-module/global-models' export const FeathersVuex = { @@ -17,6 +18,7 @@ export const FeathersVuex = { if (shouldSetupComponents) { Vue.component('FeathersVuexFind', FeathersVuexFind) Vue.component('FeathersVuexGet', FeathersVuexGet) + Vue.component('FeathersVuexFormWrapper', FeathersVuexFormWrapper) } } } From 3cc27b0d89c5642863a56affd7850c081f778809 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 19 Oct 2019 22:10:01 -0600 Subject: [PATCH 388/404] Update Global Configuration options --- docs/api-overview.md | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/docs/api-overview.md b/docs/api-overview.md index c9058784..0b6c5d7e 100755 --- a/docs/api-overview.md +++ b/docs/api-overview.md @@ -257,11 +257,20 @@ The following default options are available for configuration: ```js const defaultOptions = { + autoRemove: false, // Automatically remove records missing from responses (only use with feathers-rest) + addOnUpsert: false, // Add new records pushed by 'updated/patched' socketio events into store, instead of discarding them + enableEvents: true, // Listens to socket.io events when available idField: 'id', // The field in each record that will contain the id - autoRemove: false, // automatically remove records missing from responses (only use with feathers-rest) - nameStyle: 'short', // Determines the source of the module name. 'short' or 'path' - enableEvents: true, // Set to false to explicitly disable socket event handlers. - preferUpdate: false, // When true, calling modelInstance.save() will do an update instead of a patch. + tempIdField: '__id', + debug: false, // Set to true to enable logging messages. + keepCopiesInStore: false, // Set to true to store cloned copies in the store instead of on the Model. + nameStyle: 'short', // Determines the source of the module name. 'short', 'path', or 'explicit' + paramsForServer: [], // Custom query operators that are ignored in the find getter, but will pass through to the server. + preferUpdate: false, // When true, calling model.save() will do an update instead of a patch. + replaceItems: false, // Instad of merging in changes in the store, replace the entire record. + serverAlias: 'api', + skipRequestIfExists: false, // For get action, if the record already exists in store, skip the remote request + whitelist: [] // Custom query operators that will be allowed in the find getter. } ``` From 8ada9cf03c0a8103f352f70449d18ae99d6ac401 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sat, 19 Oct 2019 23:58:31 -0600 Subject: [PATCH 389/404] docs: change to $FeathersVuex object. --- docs/vue-plugin.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/vue-plugin.md b/docs/vue-plugin.md index 01b929e0..8aa20965 100644 --- a/docs/vue-plugin.md +++ b/docs/vue-plugin.md @@ -38,7 +38,18 @@ export default new Vuex.Store({ ## Using the Vue Plugin -Once registered, you'll have access to the `this.$FeathersVuex` object, which contains references to the Model classes, keyed by name. The name of the model class is automatically inflected to singular, initial caps, based on the last section of the service path (split by `/`). Here are some examples of what this looks like: +Once registered, you'll have access to the `this.$FeathersVuex` object. *In version 2.0, there is a breaking change to this object's structure.* Instead of directly containing references to the Model classes, the top level is keyed by `serverAlias`. Each `serverAlias` then contains the Models, keyed by name. This allows Feathers-Vuex 2.0 to support multiple FeathersJS servers in the same app. This new API means that the following change is required wherever you reference a Model class: + +```js +// 1.x way +new this.$FeathersVuex.User({}) + +// 2.x way +new this.$FeathersVuex.api.User({}) // Assuming default serverAlias of `api`. +new this.$FeathersVuex.myApi.user({}) // If you customized the serverAlias to be `myApi`. +``` + +The name of the model class is automatically inflected to singular, initial caps, based on the last section of the service path (split by `/`). Here are some examples of what this looks like: | Service Name | Model Name in `$FeathersVuex` | | ------------------------- | ----------------------------- | @@ -57,6 +68,18 @@ created () { } ``` +## New in 2.0 + +In Feathers-Vuex 2.0, the $FeathersVuex object is available as the 'models' export in the global package scope. This means you can do the following anywhere in your app: + +```js +import { models } from 'feathers-vuex' + +const user = new models.api.User({ + email: 'test@test.com' +}) +``` + ## Included Components When you register the Vue Plugin, a few components are automatically globally registered: From b407d58e360c45318c3c364e290cdcdfe8e5629e Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 20 Oct 2019 00:07:55 -0600 Subject: [PATCH 390/404] Docs: auth module updates --- docs/auth-plugin.md | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/docs/auth-plugin.md b/docs/auth-plugin.md index 05e5f335..f3e3c789 100644 --- a/docs/auth-plugin.md +++ b/docs/auth-plugin.md @@ -20,15 +20,18 @@ The Auth module helps setup your app for login / logout. It includes the follow } ``` -### Actions +## Breaking Changes in 2.0 -The following actions are included in the `auth` module: +The following breaking changes were made between 1.x and 2.0: -- `authenticate`: use instead of `feathersClient.authenticate()` -- `logout`: use instead of `feathersClient.logout()` -The Vuex auth store may not update if you use the feathers client version. +- The `auth` method is now called `makeAuthPlugin`. + +## Setup + +See the [Auth Setup](/api-overview.html#auth-plugin) section for an example of how to setup the Auth Plugin. + +## Configuration -### Configuration You can provide a `userService` in the auth plugin's options to automatically populate the user upon successful login. @@ -41,7 +44,22 @@ const { auth } = feathersVuex(feathersClient, { idField: '_id' }) const store = new Vuex.Store({ plugins: [ - auth({ userService: 'users' }) // if your user service endpoint is named 'users' + auth({ + userService: 'users', // if your user service endpoint is named 'users' + state: {}, // Custom state + getters: {}, // Custom getters + mutations: {}, // Custom mutations + actions: {} // Custom actions + }) ] }) ``` + +## Actions + +The following actions are included in the `auth` module: + +- `authenticate`: use instead of `feathersClient.authenticate()` +- `logout`: use instead of `feathersClient.logout()` + +> Node: The Vuex auth store may not update if you use the feathers client version of the above methods. From 3fa3e2b70b2de774a12a5ae11870fa0bd7a433f1 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 20 Oct 2019 00:10:16 -0600 Subject: [PATCH 391/404] docs: Fix comment about default temps behavior --- src/service-module/service-module.getters.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service-module/service-module.getters.ts b/src/service-module/service-module.getters.ts index 10fc9418..4b455e80 100644 --- a/src/service-module/service-module.getters.ts +++ b/src/service-module/service-module.getters.ts @@ -24,7 +24,7 @@ export default function makeServiceGetters() { find: state => params => { params = params || {} - // Set params.temps to false to not include the tempsById records + // Set params.temps to true to include the tempsById records params.temps = params.hasOwnProperty('temps') ? params.temps : false const { paramsForServer, whitelist } = state From b904558b80ff1408505e9f0efdeec668a3e2f9b8 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 20 Oct 2019 00:16:12 -0600 Subject: [PATCH 392/404] docs: add 2.0 changes page to end of docs --- docs/.vuepress/config.js | 3 +- docs/2.0-major-release.md | 914 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 916 insertions(+), 1 deletion(-) create mode 100644 docs/2.0-major-release.md diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index b0890202..a81ac7c6 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -16,7 +16,8 @@ module.exports = { '/mixins.md', '/data-components.md', '/feathers-vuex-form-wrapper.md', - '/nuxt.md' + '/nuxt.md', + '/2.0-major-release.md' ], serviceWorker: { updatePopup: true diff --git a/docs/2.0-major-release.md b/docs/2.0-major-release.md new file mode 100644 index 00000000..6e435fe6 --- /dev/null +++ b/docs/2.0-major-release.md @@ -0,0 +1,914 @@ +# 2.0 Breaking Changes + +The biggest change in Feathers-Vuex 2.0 is that it has been refactored with TypeScript! (It's mostly ES6, still) + +Your project does NOT require to be written in TypeScript. The `dist` is compiled to ES6. + +## Trying it out + +I accidentally published `feathers-vuex@2.0.0` with a `pre` tag on npm, **you have to install the specific version number to get the latest code.** To find out which is the most-recently published version, run `npm view feathers-vuex` and look at the `pre` tag. You can ignore the `next` and `pegasus` tags. Those were accidents that happened because I publish a lot of packages. :) + +To try the latest code. + +```console +npm view feathers-vuex +``` + +The end of the output looks something like this: + +```console +dist-tags: +latest: 1.7.0 next: 1.7.0-pre.37 pegasus: 1.7.0-pre.1 pre: 2.0.0-pre.54 +``` + +Now use the latest `pre` tag: + +```console +npm i feathers-vuex@2.0.0-pre.77 + +# or with yarn +yarn add feathers-vuex@2.0.0-pre.77 +``` + +## My TypeScript experience + +Initially, I wasn't a fan of TypeScript. I'm turned off by the steeper learning curve it introduces to writing code. + +What I do like is the tooling. It's like having an assistant that alerts you to stupid moves before you have to accidentally discover them yourself. I'm only able to appreciate it for one reason: you can use directives to tell it to ignore lines or files, similar to ESLint. The tooling will then shut up and let me write JavaScript. TypeScript has been quite beneficial to allowing me to better see how to refactor and get rid of a huge monkey patch. It's down to a few lines of code, now. + +I imagine I will like TypeScript more when there's first-class support for it built into Vue. I imagine how powerful it will be in an entire Vue project. It's one of the reasons that I'm REALLY excited about the new VueJS 3.0 API (The new function-based syntax is way more exciting, though. It's going to let me write some really pretty, well-organized code :) + +But that's enough about TypeScript. + +## Where I need assistance: the build + +The build system has been my only frustration with switching to TypeScript. Transpiling from TypeScript to JavaScript only to be transpiled by Babel (or whichever) into another form of JavaScript... has proven to be frustrating. I could really use some help in this area. + +My original intent was to target the build to ES5. But there are some weird errors that show up when classes get transpiled into old Javascript code. Classes don't quite behave the same after transpiling. Things were so inconsistent that I couldn't write down any useful notes to tell you what I was experiencing. The only clarity I got out of the experience was that it was frustrating. ;) + +I found that the simplest way around my frustration was to target ES6. I found next that Vue's default build assumes packages in the `node_modules` folder to be compiled to ES5. So you'll run into this error: + +```text +TypeError : Class constructor BaseModel cannot be invoked without 'new' +``` + +This error was fixed by adding `feathers-vuex` to the `transpileDependencies` in the `vue.config.js` file: + +```js +module.exports = { + transpileDependencies: ['feathers-vuex'] +} +``` + +It felt like everything was solved until I ran the production build. There were more errors. I finally copied the `feathers-vuex` folder from `node_modules` into a `src/libs` folder in my project. Voila! It all works. So I'm currently running this code in production by using a shell script to copy it inside my project. + +```bash +rm -rf src/libs +mkdir src/libs + +# feathers-vuex +cp -r node_modules/feathers-vuex/dist src/libs/feathers-vuex +``` + +Then in my `package.json` scripts: + +```json +{ + "copy": ". ./copy-deps.sh", + "serve": "npm run copy && vue-cli-service serve", + "build": "npm run copy && vue-cli-service build", + "postinstall": "npm run copy" +} +``` + +I don't consider the above solution to be a pretty one. I likely will not publish 2.0 until a solution is discovered which doesn't required copying from `node_modules`. I know it's got to be simple. It's has something to do with transpile settings for `node_modules`. I just haven't found it yet. + +## Quasar Build + +For Quasar apps, `transpileDependencies` can be updated in `quasar.conf.js` under build as + +``` + build: { + transpileDependencies: ['feathers-vuex'] + } +``` + +## Nuxt Build +By default with Nuxt, the build server doesn't understand the word import, which is ES6 module syntax. You have to tell Nuxt in the config which node_modules to transpile from ES6 to ES5. (I tried avoiding this situation, but double transpilation while implementing classes can cause major issues at deployment time.) . Thankfully, the fix is easy in nuxt.config.js: + +``` +build: { + transpile: ['feathers-vuex'], +} +``` + +## Here's what's new in `feathers-vuex` + +Check out the tests for the best documentation. They've been reorganized. This is still a Work in Progress. + +## Changes to Initialization + +1. To assist in connecting with multiple FeathersJS API servers, a new `serverAlias` option is now required. This requires a simple addition to the initial options. +2. The exports have changed. + - (a) A new `BaseModel` is available. This is the base `FeathersVuexModel` which contains the model methods. Feel free to extend it and make it fit your awesome services! + - (b) The `service` method has been renamed to `makeServicePlugin`. + - (c) The `auth` method is now called `makeAuthPlugin` + - (d) The `models` object is now exported, so you can access them from anywhere. They are keyed by `serverAlias`. + - (e) A new `clients` object is available. The intention is to allow working with multiple FeathersJS API servers. +3. You no longer pass a `servicePath` to create a service-plugin. Instead, pass the actual Feathers service. +4. Since you can customize the Model, you also pass the extended Model into the `makeServicePlugin` method. + +Below is an all-in-one example of a the basic configuration steps. See the next section for how to setup a project. + +```js +// ./src/store/store.js +import feathers from './feathers-client' +import Vuex from 'vuex' +import feathersVuex from 'feathers-vuex' + +const { + BaseModel, // (2a) + makeServicePlugin, // (2b) + makeAuthPlugin, // (2c) + models, // (2d) + clients // (2e) +} = feathersVuex(feathers, { + idField: '_id', + serverAlias: 'myApi' // (1) +}) + +class Todo extends BaseModel { + // required + constructor (data, options) { + super(data, options) + } + // required + static modelName = 'Todo' + + // optional, but useful + static instanceDefaults(data) { + return { + name: '', + isComplete: false, + userId: null, + user: null // populated on the server + } + } + + // optional, but useful + static setupInstance(data) { + if (data.user) { + data.user = new models.myApi.User(data.user) + } + return data + } + // customize the model as you see fit! +} + +const todosPlugin = makeServicePlugin({ + Model: Todo, // (3) + service: feathers.service('todos') // (4) +}) + +const store = new Vuex.Store({ + plugins: [ + todosPlugin + ] +}) +``` + +## Setting up a project + +There are four steps to setting up the entirety of `feathers-vuex`: + +1. Setup the FeathersJS Client. +2. Setup each Service plugin +3. Setup the Auth plugin +4. Register all plugins with Vuex + +### Setup the FeathersJS Client + +It's now recommended that the FeathersJS and client live together in the same file. This cleans up imports when setting up services. So let's start with the `feathers-client.js` file. I usually put this in `src/feathers-client.js`, but you can put it in the store folder if you want. + +```js +// src/feathers-client.js +import feathers from '@feathersjs/feathers' +import socketio from '@feathersjs/socketio-client' +import authClient from '@feathersjs/authentication-client' +import io from 'socket.io-client' +import feathersVuex from 'feathers-vuex' // or '@/libs/feathers-vuex' if you're copying feathers-vuex as mentioned earlier. + +// Setup the Feathers client +const host = process.env.VUE_APP_API_URL // or set a string here, directly +const socket = io(host, { transports: ['websocket'] }) +const feathersClient = feathers() + .configure(socketio(socket)) + .configure(authClient({ storage: window.localStorage })) + +export default feathersClient + +// Setup feathers-vuex +const { + makeServicePlugin, + makeAuthPlugin, + BaseModel, + models, + clients, + FeathersVuex +} = feathersVuex(feathersClient, { + serverAlias: 'api', // or whatever that makes sense for your project + idField: '_id' // `id` and `_id` are both supported, so this is only necessary if you're using something else. +}) + +export { + makeAuthPlugin, + makeServicePlugin, + BaseModel, + models, + clients, + FeathersVuex +} + +``` + +Now that we have setup the client, we can use the configured exports in each of our services. + +### Setup the Services Plugins + +Now let's setup a Vuex plugin for each service. I use Webpack's `require.context` to automatically import all of the services instead of explicitly typing them all. So, I'll put the services in the `src/store/services` folder. + +```js +// Bring in the imports from the feathers-client.js file. +import feathersClient, { + makeServicePlugin, + BaseModel +} from '../../feathers-client' + +// Extend the base class +class User extends BaseModel { + constructor(data, options) { + super(data, options) + } + static modelName = 'User' + static instanceDefaults() { + return { + firstName: '', + lastName: '', + email: '', + password: '' + } + } + get fullName() { + return `${this.firstName} ${this.lastName}` + } +} +const servicePath = 'users' +const servicePlugin = makeServicePlugin({ + Model: User, + service: feathersClient.service(servicePath), + servicePath +}) + +// Optionally add service-level hooks, here: +feathersClient.service(servicePath).hooks({ + before: { + all: [], + find: [], + get: [], + create: [], + update: [], + patch: [], + remove: [] + }, + after: { + all: [], + find: [], + get: [], + create: [], + update: [], + patch: [], + remove: [] + }, + error: { + all: [], + find: [], + get: [], + create: [], + update: [], + patch: [], + remove: [] + } +}) + +export default servicePlugin + +``` + +Once the service plugin is exported, we can register it with Vuex, but first let's setup the auth plugin. + +### Setup the Auth Plugin + +We'll use the `makeAuthPlugin` method to tell the auth plugin where to find our `/users` service: + +```js +// src/store/store.auth.js +import feathersClient, { makeAuthPlugin } from '../feathers-client' + +export default makeAuthPlugin({ userService: 'users' }) + +``` + +Once you've added the export, we're finally ready to setup the store. + +### Register all plugins with Vuex + +The final step is to add all of the plugins to the Vuex store. + +```js +// src/store/store.js +import Vue from 'vue' +import Vuex from 'vuex' +import { FeathersVuex } from 'feathers-vuex' +import auth from './store.auth' + +Vue.use(Vuex) +Vue.use(FeathersVuex) + +// Require the entire folder of service plugins with Webpack +const requireModule = require.context( './services', false, /.js$/ ) +const servicePlugins = requireModule + .keys() + .map(modulePath => requireModule(modulePath).default) + +// Or you can import them manually for Rollup, etc. +import users from './services/users' + +export default new Vuex.Store({ + state: {}, + getters: {}, + mutations: {}, + actions: {}, + plugins: [ + ...servicePlugins, // if you're using require.context, spread the plugins into the array. + users, // if you're manually importing, just add the plugins into the array, like this + auth + ] +}) + +``` + +With the above four steps accomplished, the base of most any application using `feathers-vuex` is ready to build something awesome! + +## FeathersVuex Vue plugin changes + +The Vue plugin is registered in exactly the same way. The difference comes when you try to find the Model classes in the `$FeathersVuex` object. Instead of finding models directly on the `$FeathersVuex` object, they are namespaced by the `serverAlias` you provided. This allows cleaner support for multiple APIs. Supposing you had this code in a component, previously... + +```js +created () { + // The old way + const { Todo } = this.$FeathersVuex +} +``` + +Modify it to include the new `serverAlias`. Suppose you set a `serverAlias` of `myApi`, you'd put this in the new version: + +```js +created () { + // The new way includes the `serverAlias` of '.myApi' + const { Todo } = this.$FeathersVuex.myApi +} +``` + +## Better default `idField` support + +Since records are keyed by id, `feathers-vuex` needs to know what the `idField` is for each service. In the last version, the default was `id`, and you had to specify something different. This version supports `id` and `_id` with zero configuration. You only need to set `idField` when you're using something other than `id` or `_id`. + +There's still a warning message when records don't have a property matching the `idField`. Just like in the last version, it only appears when you turn on `debug: true` in the options. + +## Support for Temporary Records + +Feathers-Vuex 2.0 supports tracking temporary items and automatically assigns a temporary id to new records. It also adds the records to `state.tempsById`. This is customizable using the `tempIdField` option. + +Because of the new ability to handle temporary records, a message is only logged when assigning a temporary id to a record. The `checkId` utility function has been removed, since this was its main purpose. + +## Getters Work with Temporary Records + +The `find` getter has been updated to include records from `state.tempsById`, by default. You can pass `temps: false` in the params to only search `state.keyedById`: `find({ query: {}, temps: false })` + +The `get` getter has also been updated to work with temp ids. Pass the tempId the way you normally would pass the id: `get(tempId)` + +## The "currentItem" workflow is no longer supported + +The `setCurrent` mutation and `currentId` state encouraged use of a very limiting API. It's much more common for apps to require more than one current record. The `createCopy`, `resetCopy` (formerly called `rejectCopy`), `commitCopy`, and `clearCopy` mutations (since v1.x) provide a more flexible solution for implementing the same functionality. As a result of this, following have been removed from the modules: + +- state: `currentID` +- getters: `current` +- mutations: `setCurrent`, `clearList`, `copy` + +## The `diffOnPatch` option has been removed + +(See the next section for its replacement.) + +I have not been able to find a diffing algorithm that works equally well acroos all schemas. It's especially difficult for nested schemas. Because of this, `diffOnPatch` is no longer a global option. It is being replaced by the `diffOnPatch` static Model method. See the next section. + +## Model Classes: BYOD (Bring Your Own Diffing) + +First, why do any diffing? On the API server, an `update` request replaces an entire object, but a `patch` request only overwrites the attributes that are provided in the data. For services with simple schemas, it doesn't really matter. But if your schema grows really large, it can be supportive to only send the updates instead of the entire object. + +A new `diffOnPatch` method is available to override in your extended models. `diffOnPatch` gets called just before sending the data to the API server. It gets called with the data and must return the diffed data. By default, it is set to `diffOnPatch: data => data`. + +Below is an example of how you might implement `diffOnPatch`. You would only ever use this with a cloned instance, otherwise there's nothing to diff. + +```js +import { diff } from 'deep-object-diff' +const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { serverAlias: 'myApi' }) + +class Todo extends BaseModel { + public constructor (data, options?) { + super(data, options) + } + public static modelName = 'Todo' + public static diffOnPatch (data) { + const originalObject = Todo.store.state.keyedById[data._id] + return diff(originalObject, data) + } +} + +const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathers.service(servicePath) + }) + ] +}) +``` + +## The `modelName` option has moved + +While the original intent was to completely remove the `modelName` option, it's still required after transpiling to ES5. This is because during transpilation, the class name gets stripped and can't be put back into place. Since ES5 is the default target for most build environments, the `modelName` is still required to be specified, but it has been moved. Instead of being an option, it's required as a static property of each class. + +Note: Once ES6 is the default target for most build systems, modelName will become optional. For future upgradability, it's recommended that you give your `modelName` the exact same name as your model class. + +```js +const { makeServicePlugin, BaseModel } = feathersVuex(feathers, { serverAlias: 'myApi' }) + +class Todo extends BaseModel { + public constructor (data, options?) { + super(data, options) + } + public static modelName = 'Todo' // modelName is required on all Model classes. + public static exampleProp: string = 'Hello, World! (notice the comma, folks!)' +} + +const store = new Vuex.Store({ + plugins: [ + makeServicePlugin({ + Model: Todo, + service: feathers.service(servicePath) + }) + ] +}) +``` + +## Options are no longer kept on the Model + +The Model class no longer has an `options` property. You can access the same information through the `Model.store.state[Model.namespace]`. + +## The 'apiPrefix' option has been removed + +Feathers-Vuex now includes full support for communicating with multiple FeathersJS APIs. The `apiPrefix` option was a poorly-implemented, hacky, first attempt at this same feature. Since it didn't work as intended, it has been removed. See this example test for working with multiple APIs: + +```js +import { assert } from 'chai' +import Vue from 'vue' +import Vuex from 'vuex' +import { + feathersRestClient as feathers, + makeFeathersRestClient +} from '../../test/fixtures/feathers-client' +import feathersVuex from './index' + +it('works with multiple, independent Feathers servers', function() { + // Connect to myApi, create a Todo Model & Plugin + const feathersMyApi = makeFeathersRestClient('https://api.my-api.com') + const myApi = feathersVuex(feathersMyApi, { + idField: '_id', + serverAlias: 'myApi' + }) + class Todo extends myApi.BaseModel { + public test: boolean = true + } + const todosPlugin = myApi.makeServicePlugin({ + Model: Todo, + service: feathersMyApi.service('todos') + }) + + // Create a Task Model & Plugin on theirApi + const feathersTheirApi = makeFeathersRestClient('https://api.their-api.com') + const theirApi = feathersVuex(feathersTheirApi, { + serverAlias: 'theirApi' + }) + class Task extends theirApi.BaseModel { + public test: boolean = true + } + const tasksPlugin = theirApi.makeServicePlugin({ + Model: Task, + service: feathersTheirApi.service('tasks') + }) + + // Register the plugins + new Vuex.Store({ + plugins: [todosPlugin, tasksPlugin] + }) + const { models } = myApi + + assert(models.myApi.Todo === Todo) + assert(!models.theirApi.Todo, `Todo stayed out of the 'theirApi' namespace`) + assert(models.theirApi.Task === Task) + assert(!models.myApi.Task, `Task stayed out of the 'myApi' namespace`) + + assert.equal( + models.myApi.byServicePath[Todo.servicePath], + Todo, + 'also registered in models.byServicePath' + ) + assert.equal( + models.theirApi.byServicePath[Task.servicePath], + Task, + 'also registered in models.byServicePath' + ) +``` + +## Services are no longer set up, internally + +You no longer just pass a servicePath. Instead, create the service, then pass the returned service object. + +## Simplified Pending Mutations + +Previously, there was a mutation for every single variety of method and set/unset pending. (`setFindPending`, `unsetFindPending`, etc.). There were a total of twelve methods for this simple operation. They are now combined into two methods: `setPending(method)` and `unsetPending(method)`. Here's the difference. + +```js +// The old way +commit('setFindPending') +commit('unsetFindPending') + +// The new way +commit('setPending', 'find') +commit('unsetPending', 'find') +``` + +## Simplified Error Mutations + +The "error" mutations have been simplified similar to the "pending" mutations: + +```js +// The old way +commit('setFindError', error) +commit('clearFindError') + +// The new way +commit('setError', { method: 'find', error }) +commit('clearError', 'find') +``` + +## `instanceDefaults` must be a function + +In the previous version, you could specify instanceDefaults as an object. It was buggy and limiting. In this new version, `instanceDefaults` must always be a function. See the next section for an example. + +## Getter and Setter props go on the Model classes + +One of the great features about using Model classes is data-level computed properties. You get to specify computed properties directly on your data structures instead of inside components, which keeps a better separation of concerns. In `feathers-vuex@2.x`, since we have direct access to the Model classes, it's the perfect place to define the computed properties: + +```js +import feathersClient, { + makeServicePlugin, + BaseModel +} from '../../feathers-client' + +class User extends BaseModel { + constructor(data, options) { + super(data, options) + } + static modelName = 'User' // required + // Computed properties don't go on in the instanceDefaults, anymore. + static instanceDefaults() { + return { + firstName: '', + lastName: '', + email: '', + password: '', + isAdmin: false, + } + } + // Here's a computed getter + get fullName() { + return `${this.firstName} ${this.lastName}` + } + // Probably not something you'd do in real life, but it's an example of a setter. + set fullName(fullName) { + const [ firstName, lastName ] = fullName.split(' ') + Object.assign(this, { firstName, lastName }) + } +} +const servicePath = 'users' +const servicePlugin = makeServicePlugin({ + Model: User, + service: feathersClient.service(servicePath), + servicePath +}) +``` + +## Relationships have been separated from `instanceDefaults` + +Feathers-Vuex 2.0 has a new API for establishing relationships between data. Before we cover how it works, let's review the old API. + +Feathers-Vuex 1.x allowed using the `instanceDefaults` API to both setup default values for Vue reactivity AND establishing relationships between services. It supported passing a string name that matched a model name to setup a relationship, as shown in this next example. This was a simple, but very limited API: + +```js +// The old way +instanceDefaults: { + _id: '', + description: '', + isCompleted: false, + user: 'User' +} +``` + +Any instance data with a matching key would overwrite the same property in the instanceDefaults, which resulted in an inconsistent API. + +In Feathers-Vuex 2.0, the `instanceDefaults` work the same for setting defaults with only one exception: They no longer setup the relationships. The new `setupInstance` function provides an API that is much more powerful. + +As mentioned earlier, it MUST be provided as a function: + +```js +// See the `model-instance-defaults.test.ts` file for example usage. +// This is a brief example. +instanceDefaults(data, { models, store}) { + return { + _id: '', + description: '', + isCompleted: false + // No user props, here. + } +} +``` + +Notice in the above example that we did not return `user`. Relationships are now handled in the `setupInstance` method. + +Where `instanceDefaults` props get overwritten with instance data, the props returned from `setupInstance` overwrite the instance data. If it were using `Object.assign`, internally (it's not, but IF it were), it would look like the below example, where `data` is the original instance data passed to the constructor. + +```js +Object.assign({}, instanceDefaults(data), data, setupInstance(data)) +``` + +## Define Relationships and Modify Data with `setupInstance` + +The new `setupInstance` method allows a lot of flexibility in creating new instances. It has the exact same API as the `instanceDefaults` method. The only difference is the order in which they are applied to the instance data. + +Although it looks similar to `instanceDefaults`, it can't be used for default values. This is because it overwrites instance data. Having separate methods allows a clean separation between setting up defaults and establishing relationships with other constructors. + +```js +// See the `model-relationships.test.ts` file for example usage. +// This is a brief example. +function setupInstance(data, { models, store }) { + const { User, Tag } = models.myServerAlias // Based on the serverAlias you provide, initially + + // A single User instance + if (data.user) { + data.user = new User(data.user) + } + // An array of Tag instances + if (data.tags) { + data.tags = data.tags.map(t => new Tag(t)) + } + // A JavaScript Date Object + if (data.createdAt) { + data.createdAt = new Date(data.createdAt) + } + return data +} +``` + +Or below is an example that does the exact same thing with one line per attribute: + +```js +function setupInstance(data, { models, store }) { + const { User } = models.myServerAlias + + Object.assign(data, { + ...(data.user && { user: new User(data.user) }), // A single User instance + ...(data.tags && { tags: data.tags.map(t => new Tag(t)) }), // An array of Tag instances + ...(data.createdAt && { createdAt: new Date(data.createdAt) }) // A JavaScript Date Object + }) + return data +} +``` + +Where `instanceDefaults` props get replaced by instance data, the props returned from `setupInstance` overwrite the instance data. If it were using `Object.assign`, internally (it's not, but IF it were), it would look like the below example, where `data` is the original instance data passed to the constructor. + +```js +Object.assign({}, instanceDefaults(data), data, setupInstance(data)) +``` + +## Preventing duplicate merge when extending BaseModel with a custom constructor + +The BaseModel constructor calls `mergeWithAccessors(this, newData)`. This utility function correctly copies data between both regular objects and Vue.observable instances. If you create a class where you need to do your own merging, you probably don't want `mergeWithAccessors` to run twice. In this case, you can use the `merge: false` BaseModel ___instance option___ to prevent the internal merge. You can then access the `mergeWithAccessors` method by calling `MyModel.merge(this, newData)`. Here's an example: + +```ts +const { makeServicePlugin, BaseModel } = feathersVuex(feathersClient, { + serverAlias: 'myApiServer' +}) + +class Todo extends BaseModel { + public constructor(data, options?) { + options.merge = false // Prevent the internal merge from occurring. + super(data, options) + + // ... your custom constructor logic happens here. + + // Call the static merge method to do your own merging. + Todo.merge(this, data) + } +} +``` + +It's important to note that setting `merge: false` in the options will disable the `setupinstance` function. You need to manually call it, like this: + +```ts +class Todo extends BaseModel { + public constructor(data, options?) { + options = options || {} + options.merge = false // Prevent the internal merge from occurring. + super(data, options) + + // ... your custom construcor logic happens here. + + // Call setupInstance manually + const { models, store } = Todo + // JavaScript fundamentals: if you're using `this` in `setupInstance`, use .call(this, ...) + const instanceData = Todo.setupInstance.call(this, data, { models, store }) + // If you're not using `this, just call it like normal + const instanceData = Todo.setupInstance(data, { models, store }) + + // Call the static merge method to do your own merging. + Todo.merge(this, instanceData) + } +} +``` + +## Customizing the BaseModel + +Because we have access to the BaseModel, we can extend it to do whatever custom stuff we need in our application. The `feathers-client.js` file is a great, centralized location for accomplishing this: + +```js +// src/feathers-client.js +import feathers from '@feathersjs/feathers' +import socketio from '@feathersjs/socketio-client' +import authClient from '@feathersjs/authentication-client' +import io from 'socket.io-client' +import feathersVuex from 'feathers-vuex' // or '@/libs/feathers-vuex' if you're copying feathers-vuex as mentioned earlier. + +// Setup the Feathers client +const host = process.env.VUE_APP_API_URL // or set a string here, directly +const socket = io(host, { transports: ['websocket'] }) +const feathersClient = feathers() + .configure(socketio(socket)) + .configure(authClient({ storage: window.localStorage })) + +export default feathersClient + +// Setup feathers-vuex +const { + makeServicePlugin, + makeAuthPlugin, + BaseModel, + models, + clients, + FeathersVuex +} = feathersVuex(feathersClient, { + serverAlias: 'api', // or whatever that makes sense for your project + idField: '_id' // `id` and `_id` are both supported, so this is only necessary if you're using something else. +}) + +// Note that if you want to +// extend the BaseClass for the rest of the app, this is a great place to do it. +// After you've extended the BaseClass with your CustomClass, export it, here. +class CustomBaseModel extends BaseModel { + // Optionally add custom functionality for all services, here. +} + +// Export all of the utilities for the rest of the app. +export { + makeAuthPlugin, + makeServicePlugin, + BaseModel, + models, + clients, + FeathersVuex, + CustomBaseModel // Don't forget to export it for use in all other services. +} + +``` + + +## Auth plugin changes + +With FeathersJS version 4, the user is returned in the authentication response, by default. This means that it's no longer required to provide a `userService` option to populate the user. 👍 + +If you would like to enable backwards compatibility with the previous version of Feathers, pass the below code in to the + +```js +makeAuthPlugin({ + userService: 'users', + actions: { + responseHandler({ commit, state, dispatch }, response) { + if (response.accessToken) { + commit('setAccessToken', response.accessToken) + // Decode the token and set the payload, but return the response + return feathersClient.passport + .verifyJWT(response.accessToken) + .then(payload => { + commit('setPayload', payload) + let user = response[state.responseEntityField] + // If a user was returned in the authenticate response, use that user. + if (user) { + if (state.serverAlias && state.userService) { + const Model = Object.keys(models[state.serverAlias]) + .map(modelName => models[state.serverAlias][modelName]) + .find(model => model.servicePath === state.userService) + if (Model) { + user = new Model(user) + } + } + commit('setUser', user) + // Populate the user if the userService was provided + } else if ( + state.userService && + payload.hasOwnProperty(state.entityIdField) + ) { + return dispatch( + 'populateUser', + payload[state.entityIdField] + ).then(() => { + commit('unsetAuthenticatePending') + return response + }) + } else { + commit('unsetAuthenticatePending') + } + return response + }) + // If there was not an accessToken in the response, allow the response to pass through to handle two-factor-auth + } else { + return response + } + } + } +``` + +The above code will override the `responseHandler` auth action to work with the Passport-based version of Feathers Authentication. + + +## Gotchas + + +### Don't Perform Queries (Side Effects) in Getters + +Don't try to perform a query from within a getter like the example, below. It will result in an infinite loop: + +``` +get user () { + if (this.userId) { + const user = Models.User.getFromStore(this.userId) + + // Fetch the User record if we don't already have it + if (!user) { + Models.User.get(this.userId) + } + + return user + } else { + return null + } + } +``` + +### Using custom query parameters + +There are two places where the query operators have to be allowed. + +- In the Feathers Client (for the actions): refer to the FeathersJS docs for `whitelist`ing operators. +- Inside feathers-vuex (for the getters): Check out the `paramsForServer` and `whitelist` options for `feathers-vuex`. Both accept an array of strings representing prop names, but now I can't remember why I determined that I needed both. :) + +For the Feathers Client, follow the FeathersJS docs for your database adapter. + +### Access `$FeathersVuex` models in Nuxt `asyncData` + +In `feathers-vuex@2.x`, you can get access to the `$FeathersVuex` object by importing the `models` object from the main export: + +``` +import { models } from 'feathers-vuex' +``` + +`models` and `$FeathersVuex` are the same object. \ No newline at end of file From 43b32d29d5aef60df1a03d7891690a1edd4a417d Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 20 Oct 2019 00:16:44 -0600 Subject: [PATCH 393/404] docs: data-components updates --- docs/data-components.md | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/docs/data-components.md b/docs/data-components.md index 97ee82c5..cba408bd 100644 --- a/docs/data-components.md +++ b/docs/data-components.md @@ -2,9 +2,9 @@ title: Renderless Data Components --- -Currently in `feathers-vuex@next`, a set of new, renderless data provider components -- `` and `` -- simplify performing queries against the store and/or the API server. They make the data available inside the component's default slot. +There are two new renderless data provider components: `` and ``. They simplify performing queries against the store and/or the API server. They make the data available inside each component's default slot. -This first version does not assist with server-side pagination, but you can use it with your own pagination logic using the `query` or `fetchQuery` attributes, described later. To see why you might want to use these components, here are two example components that are functionally equivalent. +To see why you might want to use these components, below are two example components that are functionally equivalent. Here's what it looks like to use the new component: @@ -22,9 +22,6 @@ export default { name: 'admin-categories' } - - ``` The above example is functionally equivalent to this much longer example which doesn't use the new component: @@ -59,13 +56,29 @@ export default { } } - - ``` > To level up your skills, consider this content by Adam Wathan. He wrote a terrific *free* article about [Renderless Components in Vue.js](https://adamwathan.me/renderless-components-in-vuejs/). I highly recommend you read it. He also created the *paid/premium* [Advanced Vue Component Design](https://adamwathan.me/advanced-vue-component-design/) course. His material influenced the creation of this component. +## FeathersVuexFind + +The `FeathersVuexFind` component retrieves data fomr the APi server, puts it in the Vuex store, then transparently retrieves the live, reactive data from the store and displays it to the user. + +```vue + +
+ {{users}} +
+
+``` + +### Props + +- `service`: The path of the service +- `query`: Only the query object from the `find` params. + +## FeathersVuexGet + ## A note about the internal architecture These components use Vuex getters (to query data from the local store) and actions (to query data from the API server). When a `query` or `id` is provided, the components pull data from the API server and put it into the store. That same `query` or `id` is then used to pull data from the local Vuex store. Keep this in mind, especially when attempting to use server-side pagination. To use server-side pagination, use the `query` prop for pulling data from the local vuex store, then use the `fetchQuery` prop to retrieve data from the API server. From 8b5f8e588f691d7abb103f48f32a762afddacdc9 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 20 Oct 2019 00:16:51 -0600 Subject: [PATCH 394/404] docs: service-plugin updates --- docs/service-plugin.md | 45 ++++++++++-------------------------------- 1 file changed, 10 insertions(+), 35 deletions(-) diff --git a/docs/service-plugin.md b/docs/service-plugin.md index 36ad999f..aaea9e79 100644 --- a/docs/service-plugin.md +++ b/docs/service-plugin.md @@ -4,45 +4,17 @@ title: Service Plugin -The `Service Module` creates plugins which can be used to connect a Feathers service to the Vuex store. Once you create the plugin, you must register it in the `plugins` section of your store setup: +The `Service Plugin` creates a vuex plugin which connects a Feathers service to the Vuex store. Once you create the plugin, you must register it in the `plugins` section of your store setup: -Here's a basic example of creating a service plugin: +See the [setup documentation](/api-overview.html#service-plugins) to learn the basics of setting up a Service Plugin. -```js -// src/services/users.js -import feathersVuex from 'feathers-vuex' -import feathersClient from '../../feathers-client' - -const { service } = feathersVuex(feathersClient, { idField: '_id' }) - -const servicePath = 'users' -const servicePlugin = service(servicePath) - -export default servicePlugin -``` - -The above code block demonstrates setting up a service plugin, but the plugin doesn't run until you register it with Vuex, as shown in this next example: - -```js -// src/store.js -import Vue from 'vue' -import Vuex from 'vuex' -import feathersVuex from 'feathers-vuex' -import feathersClient from '../feathers-client' -import usersPlugin from './services/users' - -const { auth, FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' }) +## New in Feathers-Vuex 2.0 -Vue.use(Vuex) -Vue.use(FeathersVuex) +Feathers-Vuex 2.0 includes a few breaking changes to the service plugin. Some of these changes are being made to prepare for future compatibility beyond FeathersJS -export default new Vuex.Store({ - plugins: [ - users: usersPlugin, - auth({ userService: 'users' }) - ] -}) -``` +- The `service` method is now called `makeServicePlugin` +- The Feathers Client service is no longer created, internally, so a Feathers service object must be provided instead of just the path string. +- A Model class is now required. The `instanceDefaults` API has been moved into the Model class. You can find a basic example of a minimal Model class in the [Data Modeling](/model-classes.html) docs. Old example from the api-overview page: @@ -68,6 +40,9 @@ export default new Vuex.Store({ nameStyle: 'path', // Use the full service path as the Vuex module name, instead of just the last section namespace: 'custom-namespace', // Customize the Vuex module name. Overrides nameStyle. debug: true, // Enable some logging for debugging + servicePath: '', // Not all Feathers service plugins expose the service path, so it can be manually specified when missing. + instanceDefaults: () => ({}), // Override this method to provide default data for new instances. If using Model classes, specify this as a static class property. + setupInstance: instance => instance, // Override this method to setup data types or related data on an instance. If using Model classes, specify this as a static class property. autoRemove: true, // Automatically remove records missing from responses (only use with feathers-rest) enableEvents: false, // Turn off socket event listeners. It's true by default addOnUpsert: true, // Add new records pushed by 'updated/patched' socketio events into store, instead of discarding them. It's false by default From d5d89328e5a66a2e33597fe60df1db0384db3007 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 20 Oct 2019 07:02:22 -0600 Subject: [PATCH 395/404] docs: note about typescript --- docs/common-patterns.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/common-patterns.md b/docs/common-patterns.md index fbf9afb5..b723817a 100755 --- a/docs/common-patterns.md +++ b/docs/common-patterns.md @@ -20,6 +20,8 @@ The mixin utilities provide the same functionality as the components, but with m ## Working with TypeScript +As of version 2.0, Feathers-Vuex has been rewritten in TypeScript. + See [this issue](https://github.com/feathers-plus/feathers-vuex/issues/114) for suggestions for with TypeScript helpers. ## Clearing data upon user logout From 119dfd0952f903d41df7cc2b9643993a093fe4ee Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Sun, 20 Oct 2019 07:02:30 -0600 Subject: [PATCH 396/404] docs: import feathers-vuex --- docs/api-overview.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/api-overview.md b/docs/api-overview.md index 0b6c5d7e..004dfd82 100755 --- a/docs/api-overview.md +++ b/docs/api-overview.md @@ -100,6 +100,7 @@ import socketio from '@feathersjs/socketio-client' import auth from '@feathersjs/authentication-client' import io from 'socket.io-client' import { iff } from 'feathers-hooks-common' +import feathersVuex from 'feathers-vuex' const socket = io('http://localhost:3030', {transports: ['websocket']}) From 8f0e2cee62951ff520b7b0dda6ecf8a431b3ffa0 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 21 Oct 2019 06:57:24 -0600 Subject: [PATCH 397/404] docs: Add feathersClient to imports in example --- docs/api-overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-overview.md b/docs/api-overview.md index 004dfd82..7ddcef20 100755 --- a/docs/api-overview.md +++ b/docs/api-overview.md @@ -139,7 +139,7 @@ The following example creates a User class and registers it with the new `makeSe ```js // src/store/services/users.js -import { makeServicePlugin, BaseModel } from '../feathers-client' +import feathersClient, { makeServicePlugin, BaseModel } from '../feathers-client' class User extends BaseModel { constructor(data, options) { From 1947c81423daf1bcd2b8a1d63f104f956aa57629 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 21 Oct 2019 06:57:43 -0600 Subject: [PATCH 398/404] docs: update example for accessing store from hooks --- docs/common-patterns.md | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/docs/common-patterns.md b/docs/common-patterns.md index b723817a..4d569104 100755 --- a/docs/common-patterns.md +++ b/docs/common-patterns.md @@ -35,22 +35,27 @@ Because the service's Model [is available](./service-plugin.html#The-FeathersCli As an example, this `speeding-tickets` service has a `summary` attribute that comes back in the response. We can ```js -import feathersVuex from 'feathers-vuex' -import feathersClient from '../../feathers-client' - -const { service } = feathersVuex(feathersClient, { idField: '_id' }) +import { makeServicePlugin, BaseModel } from '../feathers-client' -const servicePath = 'speeding-tickets' -const servicePlugin = service(servicePath, { - instanceDefaults: { - vin: '', - plateState: '' - }, - mutations: { - handleSummaryData (state, summaryData) { - state.mostRecentSummary = summaryData +class SpeedingTicket extends BaseModel { + constructor(data, options) { + super(data, options) + } + // Required for $FeathersVuex plugin to work after production transpile. + static modelName = 'SpeedingTicket' + // Define default properties here + static instanceDefaults() { + return { + email: '', + password: '' } } +} +const servicePath = 'speeding-tickets' +const servicePlugin = makeServicePlugin({ + Model: SpeedingTicket, + service: feathersClient.service(servicePath), + servicePath }) feathersClient.service(servicePath) From 115ae81b4e228193e5bd2e577647ae70a4063a3f Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 21 Oct 2019 07:00:13 -0600 Subject: [PATCH 399/404] docs: fix typos in last update --- docs/common-patterns.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/common-patterns.md b/docs/common-patterns.md index 4d569104..eea878d8 100755 --- a/docs/common-patterns.md +++ b/docs/common-patterns.md @@ -46,8 +46,8 @@ class SpeedingTicket extends BaseModel { // Define default properties here static instanceDefaults() { return { - email: '', - password: '' + vin: '', + plateState: '' } } } @@ -55,7 +55,12 @@ const servicePath = 'speeding-tickets' const servicePlugin = makeServicePlugin({ Model: SpeedingTicket, service: feathersClient.service(servicePath), - servicePath + servicePath, + mutations: { + handleSummaryData (state, summaryData) { + state.mostRecentSummary = summaryData + } + } }) feathersClient.service(servicePath) From ddc6f772e30d51eb5dabaeb8ab04e908d666b231 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 21 Oct 2019 07:14:05 -0600 Subject: [PATCH 400/404] docs: update example re: require.context --- docs/common-patterns.md | 113 ++++++++++++---------------------------- 1 file changed, 33 insertions(+), 80 deletions(-) diff --git a/docs/common-patterns.md b/docs/common-patterns.md index eea878d8..98bfdde4 100755 --- a/docs/common-patterns.md +++ b/docs/common-patterns.md @@ -88,17 +88,27 @@ Depending on what you need to do, you may be able to solve this by [accessing th If you need the response data to already be in the store, you can use the [`afterFind` action](./service-plugin.html#afterFind-response). Here's what this looks like: ```js -import feathersVuex from 'feathers-vuex' -import feathersClient from '../../feathers-client' - -const { service } = feathersVuex(feathersClient, { idField: '_id' }) +import { makeServicePlugin, BaseModel } from '../feathers-client' +class SpeedingTicket extends BaseModel { + constructor(data, options) { + super(data, options) + } + // Required for $FeathersVuex plugin to work after production transpile. + static modelName = 'SpeedingTicket' + // Define default properties here + static instanceDefaults() { + return { + vin: '', + plateState: '' + } + } +} const servicePath = 'speeding-tickets' -const servicePlugin = service(servicePath, { - instanceDefaults: { - vin: '', - plateState: '' - }, +const servicePlugin = makeServicePlugin({ + Model: SpeedingTicket, + service: feathersClient.service(servicePath), + servicePath, actions: { afterFind ({ commit, dispatch, getters, state }, response) { if (response.summary) { @@ -112,11 +122,10 @@ const servicePlugin = service(servicePath, { } } }) -``` ## Reactive Lists with Live Queries -Using Live Queries will greatly simplify app development. The `find` getter enables this feature. Here's how you might setup a component to take advantage of them. For the below example, let's create two live-query lists using two getters. +Using Live Queries will greatly simplify app development. The `find` getter enables this feature. Here is how you might setup a component to take advantage of them. The next example shows how to setup two live-query lists using two getters. ```js import { mapState, mapGetters, mapActions } from 'vuex' @@ -162,93 +171,37 @@ You can use the file system to organize each service into its own module. This i ```js import Vue from 'vue' import Vuex from 'vuex' -import feathersVuex from 'feathers-vuex' -import feathersClient from '../feathers-client' - -const { auth, FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' }) +import { FeathersVuex } from '../feathers-client' +import auth from './store.auth' Vue.use(Vuex) Vue.use(FeathersVuex) const requireModule = require.context( - // The relative path holding the service modules + // The path where the service modules live './services', // Whether to look in subfolders false, - // Only include .js files (prevents duplicate imports) + // Only include .js files (prevents duplicate imports`) /.js$/ ) -const servicePlugins = requireModule.keys().map(modulePath => requireModule(modulePath).default) +const servicePlugins = requireModule + .keys() + .map(modulePath => requireModule(modulePath).default) export default new Vuex.Store({ state: {}, - getters: {}, mutations: {}, - modules: {}, - plugins: [ - // Use the spread operator to register all of the imported plugins - ...servicePlugins, - - auth({ userService: 'users' }) - ] + actions: {}, + plugins: [...servicePlugins, auth] }) ``` -With the `store.js` file in place, we can start adding services to the `services` folder. Here's an example user service. Notice that this format is a clean way to use hooks, as well. +With the `store.js` file in place, we can start adding services to the `services` folder. -```js -import feathersVuex from 'feathers-vuex' -import feathersClient from '../../feathers-client' - -const { service } = feathersVuex(feathersClient, { idField: '_id' }) - -const servicePath = 'users' -const servicePlugin = service(servicePath, { - instanceDefaults: { - email: '', - password: '', - roles: [], - firstName: '', - lastName: '', - get fullName () { - return `${this.firstName} ${this.lastName}` - } - } -}) - -feathersClient.service(servicePath) - .hooks({ - before: { - all: [], - find: [], - get: [], - create: [], - update: [], - patch: [], - remove: [] - }, - after: { - all: [], - find: [], - get: [], - create: [], - update: [], - patch: [], - remove: [] - }, - error: { - all: [], - find: [], - get: [], - create: [], - update: [], - patch: [], - remove: [] - } - }) - -export default servicePlugin -``` +- [Learn how to setup a Vuex plugin for a Feathers service.](/api-overview.html#service-plugins) +- [Learn how to setup the feathers-client.js file](/api-overview.html) +- [Learn how to setup the auth plugin](/api-overview.html#auth-plugin) ## Actions return reactive store records From 00829e3ad6218e8dec47606b8e93c81d25413762 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 21 Oct 2019 07:56:50 -0600 Subject: [PATCH 401/404] docs: updated data modeling page --- docs/model-classes.md | 208 +++++++++++++++++++----------------------- 1 file changed, 95 insertions(+), 113 deletions(-) diff --git a/docs/model-classes.md b/docs/model-classes.md index b2429e26..bd61d067 100644 --- a/docs/model-classes.md +++ b/docs/model-classes.md @@ -1,9 +1,55 @@ --- title: Data Modeling +sidebarDepth: 3 --- - -Every service now includes a new `FeathersVuexModel` Class and new records are instantiated with that class before getting added to the store. +# Data Modeling with Model Classes + +Feathers-Vuex 1.0 introduced some lightweight data modeling. Every service had its own, internal `FeathersVuexModel`. In version 2.0 this `FeathersVuexModel` is now called the `BaseModel` and is extendable, so you can add your own functionality. + + +## Extending the BaseModel Class + +While [setting up Feathers-Vuex](/api-overview.html#feathers-client-feathers-vuex), we exported the `BaseModel` class so that we could extend it. The below example shows how to import and extend the `BaseModel`. Each service must now have its own unique Model class. + +```js +import feathersClient, { makeServicePlugin, BaseModel } from '../feathers-client' + +class User extends BaseModel { + // Required for $FeathersVuex plugin to work after production transpile. + static modelName = 'User' + // Define default properties here + static instanceDefaults() { + return { + email: '', + password: '' + } + } +} + +const servicePath = 'users' +const servicePlugin = makeServicePlugin({ + Model: User, + service: feathersClient.service(servicePath), + servicePath +}) +``` + +In case you're wondering, the `modelName` property is used to get around transpilation errors when using Babel with ES3 or ES5. Babel is still installed by default in most projects and generators. The `modelName` is used instead of the `name` property to provide a reliable name AFTER transpilation. + +If you're working in an environment that doesn't support static properties on classes, you can always specify the static properties using the dot operator: + +```js +class User extends BaseModel {} + +User.modelName = 'User' +User.instanceDefaults = function() { + return { + email: '', + password: '' + } +} +``` ## Model attributes @@ -15,54 +61,77 @@ The following attributes are available on each model: ## Model Methods -### Model.find(params) +### find(params) Model classes have a `find` method, which is a proxy to the [`find` action](./service-plugin.html#find-params). ```js // In your Vue component created () { - const { Todo } = this.$FeathersVuex + const { Todo } = this.$FeathersVuex.api Todo.find({ query: {} }).then(/* ... */) } ``` -### Model.findInStore(params) +### findInStore(params) Model classes have a `findInStore` method, which is a proxy to the [`find` getter](./service-plugin.html#Service-Getters). ```js // In your Vue component created () { - const { Todo } = this.$FeathersVuex + const { Todo } = this.$FeathersVuex.api const todos = Todo.findInStore({ query: {} }) } ``` -### Model.get(id, params) +### get(id, params) -Model classes have a `get` method, which is a proxy to the [`get` action](./service-plugin.html#get-id-or-get-id-params). Notice that the signature is more Feathers-like, and doesn't require using an array to passing both id and params. +Model classes have a `get` method, which is a proxy to the [`get` action](./service-plugin.html#get-id-or-get-id-params). Notice that the signature is more Feathers-like, and doesn't require using an array to passing both id and params. ```js // In your Vue component created () { - const { Todo } = this.$FeathersVuex + const { Todo } = this.$FeathersVuex.api Todo.get(this.id).then(/* ... */) } ``` -### Model.getFromStore(id, params) +### getFromStore(id, params) Model classes have a `getFromStore` method, which is a proxy to the [`get` getter](./service-plugin.html#Service-Getters). Notice that the signature is more Feathers-like, and doesn't require using an array to passing both id and params. ```js // In your Vue component created () { - const { Todo } = this.$FeathersVuex + const { Todo } = this.$FeathersVuex.api const todo = Todo.getFromStore(this.id) } ``` +### instanceDefaults + +`instanceDefaults(data, { store, Models })` + +Starting with version 2.0, `instanceDefaults` must be provided as a function. The function will be called with the following arguments and should return an object of default properties for new instances. + +- `data {Object}` - The instance data +- An `utils` object containing these props: + - `store` - The vuex store + - `Models {Object}` The `globalModels` object, which is the same as you'll find inside a component at `this.$FeathersVuex`. + +### setupInstance + +`setupInstance(data, { store, Models })` + +A new `setupinstance` class method is now available in version 2.0. The function will be called with the following arguments and should return an object of default properties for new instances. + +- `data {Object}` - The instance data +- An `utils` object containing these props: + - `store` - The vuex store + - `Models {Object}` The `globalModels` object, which is the same as you'll find inside a component at `this.$FeathersVuex`. + + ## Creating instances The [FeathersVuex plugin for Vue](./vue-plugin.md) allow convenient access to all Model constructors. You can create a Model instance by getting a reference to a Model class from the `$FeathersVuex` object: @@ -70,7 +139,7 @@ The [FeathersVuex plugin for Vue](./vue-plugin.md) allow convenient access to al ```js // In your Vue component created () { - const { Todo } = this.$FeathersVuex + const { Todo } = this.$FeathersVuex.api const todo = new Todo({ description: 'Do something!' }) } ``` @@ -80,7 +149,7 @@ You can also reference this directly from the Vue module: ```js import Vue from 'vue' -const { Todo } = Vue +const { Todo } = Vue.$FeathersVuex.api const todo = new Todo({ description: 'Do something!' }) ``` @@ -111,93 +180,6 @@ store.dispatch('todos/find', { query: {} }) }) ``` -## instanceDefaults | Object - -Do you find yourself spending time writing defaults into your form components? Maybe you wrote a utility for yourself or found one on npm that can do the trick for you. That's a thing of the past. You can now specify the default values for Model instances by using the `instanceDefaults` option when using the service plugin. Here's what it looks like: - -```js -import Vue from 'vue' -import Vuex from 'vuex' -import feathersVuex from 'feathers-vuex' -import feathersClient from './feathers-client' - -const { service, auth, FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' }) - -Vue.use(FeathersVuex) -Vue.use(Vuex) - -export default new Vuex.Store({ - plugins: [ - service('todos', { - instanceDefaults: { - description: '', - isComplete: false - } - }) - ] -}) -``` - -With the above configuration, when you create a [`Todo` instance](./model-classes.md), it will have the attributes provided as `instanceDefaults`. This is especially useful for binding to form data. If the attributes aren't defined while binding, the automatic Vue reactivity won't work. Remember to not set any of the attributes to `undefined`, but instead use `null`. If not, the reactivity breaks, and you might spend some time wondering why your form is broken. - -### A Word Of Warning - -One thing to be aware of when using `instanceDefaults` as an object is that values can persist between instances and mutate separate instances. For example, when including an `Array`, changes made to one instance will affect any other instances of this model too. - -Using `instanceDefaults` as an object will be deprecated in the next major version of `feathers-vuex` so it's best to stick to the function option below. - -## instanceDefaults | Function - -A much more powerful API is available when you provide `instanceDefaults` as a function. The function will be called with the following arguments and should return an instanceDefaults object. - -- `data {Object}` - The instance data -- An `utils` object containing these props: - - `store` - The vuex store - - `Model {FeathersVuexModel}` - The current Model (the same as the current instance's constructor) - - `Models {Object}` The `globalModels` object, which is the same as you'll find inside a component at `this.$FeathersVuex`. - -This API allows for a lot of flexibility. In the below example, each todo instance has a `get user` property. If the instance has a `userId`, the correct user record will automatically be fetched from the store. - -```js -import Vue from 'vue' -import Vuex from 'vuex' -import feathersVuex from 'feathers-vuex' -import feathersClient from './feathers-client' - -const { service, auth, FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' }) - -Vue.use(FeathersVuex) -Vue.use(Vuex) - -export default new Vuex.Store({ - plugins: [ - service('todos', { - instanceDefaults (data, { store, Model, Models }) { - return { - description: '', - isComplete: false, - userId: null, - get user () { - if (this.userId) { - const user = Models.User.getFromStore(this.userId) - - // Fetch the User record if we don't already have it - if (!user) { - Models.User.get(this.userId) - } - - return user - } else { - return null - } - } - } - } - }) - ] -}) -``` - ## Instance Methods ### `instance.save(params)` @@ -207,7 +189,7 @@ The `save` method is a convenience wrapper for the `create/patch` methods, by de ```js // In your Vue component created () { - const { Todo } = this.$FeathersVuex + const { Todo } = this.$FeathersVuex.api const todo = new Todo({ description: 'Do something!' }) todo.save() // --> Creates the todo on the server. @@ -220,12 +202,12 @@ As mentioned, `save` performs either `create` or `patch`, but you can use the `p ### `instance.create(params)` -The `create` method is a shortcut for calling the `create` action (service method) using the instance data. The `params` argument will be used in the Feathers client request. See the [Feathers Service](https://docs.feathersjs.com/api/services.md#service-methods) docs, for reference. +The `create` method calls the `create` action (service method) using the instance data. The `params` argument will be used in the Feathers client request. See the [Feathers Service](https://docs.feathersjs.com/api/services.md#service-methods) docs, for reference. You might not ever need to use `.create()`, but can instead use the `.save()` method. Let `feathers-vuex` call `create` or `patch`. ```js -const { Todo } = this.$FeathersVuex +const { Todo } = this.$FeathersVuex.api const data = { description: 'Do something!' } const todo = new Todo(data) @@ -234,12 +216,12 @@ todo.create() // --> Creates the todo on the server using the instance data ### `instance.patch(params)` -The `patch` method is a shortcut for calling the `patch` action (service method) using the instance data. The instance's id field is used for the `patch` id. The `params` argument will be used in the Feathers client request. See the [Feathers Service](https://docs.feathersjs.com/api/services.md#service-methods) docs, for reference. +The `patch` method calls the `patch` action (service method) using the instance data. The instance's id field is used for the `patch` id. The `params` argument will be used in the Feathers client request. See the [Feathers Service](https://docs.feathersjs.com/api/services.md#service-methods) docs, for reference. Similar to the `.create()` method, you might not ever need to use `.patch()` if you just use `.save()` and let `feathers-vuex` figure out how to handle it. ```js -const { Todo } = this.$FeathersVuex +const { Todo } = this.$FeathersVuex.api const todo = new Todo({ id: 1, description: 'Do something!' }) todo.description = 'Do something else' @@ -251,12 +233,12 @@ todo.patch() // --> Sends a `patch` request the with the id and description. ### `instance.update(params)` -The `update` method is a shortcut for calling the `update` action (service method) using the instance data. The instance's id field is used for the `update` id. The `params` argument will be used in the Feathers client request. See the [Feathers Service](https://docs.feathersjs.com/api/services.md#service-methods) docs, for reference. +The `update` method calls the `update` action (service method) using the instance data. The instance's id field is used for the `update` id. The `params` argument will be used in the Feathers client request. See the [Feathers Service](https://docs.feathersjs.com/api/services.md#service-methods) docs, for reference. Use `.update()` whenever you want to completely replace the data on the server with the instance data. You can also set the `preferUpdate` option to `true` to make `.save()` call `.update()` when an id field is present on the instance. ```js -const { Todo } = this.$FeathersVuex +const { Todo } = this.$FeathersVuex.api const todo = new Todo({ id: 1, description: 'Do something!' }) todo.description = 'Do something else' @@ -266,10 +248,10 @@ todo.update() // --> Sends a `update` request the with all instance data. ### `instance.remove(params)` -The `remove` method is a shortcut for calling the `remove` action (service method) using the instance data. The instance's id field is used for the `remove` id. The `params` argument will be used in the Feathers client request. See the [Feathers Service](https://docs.feathersjs.com/api/services.md#service-methods) docs, for reference. +The `remove` method calls the `remove` action (service method) using the instance data. The instance's id field is used for the `remove` id. The `params` argument will be used in the Feathers client request. See the [Feathers Service](https://docs.feathersjs.com/api/services.md#service-methods) docs, for reference. ```js -const { Todo } = this.$FeathersVuex +const { Todo } = this.$FeathersVuex.api const todo = new Todo({ id: 1, description: 'Do something!' }) todo.save() @@ -283,7 +265,7 @@ todo.save() The `.clone()` method creates a deep copy of the record and stores it on `Model.copiesById`. This allows you to make changes to the clone and not update visible data until you commit or save the data. ```js -const { Todo } = this.$FeathersVuex +const { Todo } = this.$FeathersVuex.api const todo = new Todo({ id: 1, description: 'Do something!' }) const todoCopy = todo.clone() @@ -296,12 +278,12 @@ console.log(todoCopy.description) // --> 'Do something else!' There's another use case for using `.clone()`. Vuex has a `strict` mode that's really useful in development. It throws errors if any changes occur in the Vuex store `state` outside of mutations. Clone really comes in handy here, because you can make changes to the clone without having to write custom Vuex mutations. When you're finished making changes, call `.commit()` to update the store. This gives you `strict` mode compliance with little effort! -Finally, if for some reason you prefer to keep the copies in the Vuex store and use custom mutations for all update, you can set the `keepCopiesInStore` option to `true`. This will cause the copies to be stored in `state.copiesById`. +> Nonte: You could previously use the `keepCopiesInStore` option to keep copies in `state.copiesById`. In 2.0, this feature is deprecated and will be removed from the next release. ### `instance.commit()` ```js -const { Todo } = this.$FeathersVuex +const { Todo } = this.$FeathersVuex.api const todo = new Todo({ id: 1, description: 'Do something!' }) const todoCopy = todo.clone() @@ -315,7 +297,7 @@ console.log(todoCopy.description) // --> 'Do something else!' ### `instance.reset()` ```js -const { Todo } = this.$FeathersVuex +const { Todo } = this.$FeathersVuex.api const todo = new Todo({ id: 1, description: 'Do something!' }) const todoCopy = todo.clone() From 589c5942e268a4731db2e3022fcd1a7aee20134c Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 21 Oct 2019 08:01:10 -0600 Subject: [PATCH 402/404] =?UTF-8?q?docs:=20add=20note=20about=20Webpack?= =?UTF-8?q?=E2=80=99s=20require.context?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/api-overview.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/api-overview.md b/docs/api-overview.md index 7ddcef20..ceb3ee47 100755 --- a/docs/api-overview.md +++ b/docs/api-overview.md @@ -211,6 +211,8 @@ export default makeAuthPlugin({ userService: 'users' }) ### Vuex store +This example uses Webpack's `require.context` feature. If you're not using Webpack, you'll need to manually import each module and list them in the `plugins` array. + ```js // src/store/store.js import Vue from 'vue' From c9f0af1388b7d52387f1b7362b1165fb97a09d31 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 21 Oct 2019 08:01:27 -0600 Subject: [PATCH 403/404] docs: Fix broken fenced code block --- docs/common-patterns.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/common-patterns.md b/docs/common-patterns.md index 98bfdde4..4f518ed9 100755 --- a/docs/common-patterns.md +++ b/docs/common-patterns.md @@ -122,6 +122,7 @@ const servicePlugin = makeServicePlugin({ } } }) +``` ## Reactive Lists with Live Queries From 82ce21490b6115bf2b39167020042ea8c57939f1 Mon Sep 17 00:00:00 2001 From: Marshall Thompson Date: Mon, 21 Oct 2019 08:19:00 -0600 Subject: [PATCH 404/404] docs: finish updating common patterns page --- docs/common-patterns.md | 172 ++++++++++++---------------------------- 1 file changed, 50 insertions(+), 122 deletions(-) diff --git a/docs/common-patterns.md b/docs/common-patterns.md index 4f518ed9..2a32e8a2 100755 --- a/docs/common-patterns.md +++ b/docs/common-patterns.md @@ -255,30 +255,33 @@ In summary, you can plan on individual records in the action response data to be ## Basic Data Modeling with `instanceDefaults` -See the [instanceDefaults API](./model-classes.html#instanceDefaults) +See the [instanceDefaults API](./model-classes.html#instancedefaults) ## Model-Specific Computed Properties -You may find yourself in a position where model-specific computed properties would be very useful. [github issue](https://github.com/feathers-plus/feathers-vuex/issues/163) This is already possible using es5 accessors. You can use both getters and setters inside `instanceDefaults`: +You may find yourself in a position where model-specific computed properties would be very useful. [github issue](https://github.com/feathers-plus/feathers-vuex/issues/163). In Feathers-Vuex 1.7, these could be specified in the `instanceDefaults`. As of 2.0, they are specified directly on each Model class: ```js -export default new Vuex.Store({ - plugins: [ - service('post', { - instanceDefaults: { - description: '', - isComplete: false, - comments: [], - get numberOfCommenters () { - // Put your logic here. - }, - set someOtherProp () { - // Setters also work - } - } - }) - ] -}) +class Post extends BaseModel { + // Required for $FeathersVuex plugin to work after production transpile. + static modelName = 'Post' + // Define default properties here + static instanceDefaults() { + return { + description: '', + isComplete: false, + comments: [], + } + } + + // Specify computed properties as regular class properties + get numberOfCommenters () { + // Put your logic here. + }, + set someOtherProp () { + // Setters also work + } +} ``` ## Relationships for Populated Data @@ -326,110 +329,41 @@ Suppose a requirement is put on the `/todos` service to populate the `user` in t Can you see the problem that will occur with this response? When this record is put into the `/todos` store, it will contain a copy of the user record. But we already have the user record in the `/users` store. And what happens when the user data changes? Now it's out of sync. To keep it in sync, you might have to manually listen for `users updated` & `users patched` events. Then you might have to write a custom mutation to update the user record attached to every applicable `todo` record. This gets messy, fast! -There's an easier way to solve this problem. The introduction of `instanceDefaults` allowed for another awesome feature: Model Relationships! To setup a relationship, specify a Model name, as a string, to any property, like this: - -```js -instanceDefaults: { - description: '', - complete: false, - userId: null, - user: 'User' -} -``` - -When this record is instantiated, the `user` attribute will first be turned into a User [model instance](./model-classes.html), stored properly in the `/users` store. The `todo.user` attribute will be a reference to that user. No more duplicate data! Here's an example of how to set this up. The following example specifies that Todo instances can have a `user` attribute that contains a `User` Model instance: - -```js -import Vue from 'vue' -import Vuex from 'vuex' -import feathersVuex from 'feathers-vuex' -import feathersClient from './feathers-client' - -const { service, auth, FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' }) - -Vue.use(FeathersVuex) -Vue.use(Vuex) - -export default new Vuex.Store({ - plugins: [ - service('todos', { - instanceDefaults: { - description: '', - complete: false, - userId: null, - user: 'User' - } - }), - service('users', { - instanceDefaults: { - email: '', - name: '' - } - }) - ] -}) -``` - -There's another amazing benefit from these relationships. Because `feathers-vuex` listens to real-time events and keeps data up to date, when the user record changes, the `todo.user` automatically updates! - -It's worth noting that this feature also supports arrays. Suppose you had `/users` and `/todos` services, and your `/users` service also returned a `todos` attribute on each record. The setup would look like this: +There's an easier way to solve this problem. Use the new [`setupInstance` method on Model classes](/model-classes.html#setupinstance). ```js -import Vue from 'vue' -import Vuex from 'vuex' -import feathersVuex from 'feathers-vuex' -import feathersClient from './feathers-client' +import feathersClient, { makeServicePlugin, BaseModel } from '../feathers-client' -const { service, auth, FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' }) - -Vue.use(FeathersVuex) -Vue.use(Vuex) +class Todo extends BaseModel { + // Required for $FeathersVuex plugin to work after production transpile. + static modelName = 'Todo' + // Define default properties here + static instanceDefaults() { + return { + email: '', + password: '' + } + } + // Updates `data.user` to be an instance of the `User` class. + static setupInstance(data, { models }) { + if (data.user) { + data.user = new models.api.User(data.user) + } + return data + } +} -export default new Vuex.Store({ - plugins: [ - service('todos', { - instanceDefaults: { - description: '', - isComplete: false - } - }), - service('users', { - instanceDefaults: { - email: '', - name: '', - todos: 'Todo' - } - }) - ] +const servicePath = 'todos' +const servicePlugin = makeServicePlugin({ + Model: Todo, + service: feathersClient.service(servicePath), + servicePath }) ``` -With the `instanceDefaults` shown above, any `todos` returned on the `users` service would be stored in the `/todos` service store and would always be Todo instances. - -## Reactive User Data in Auth Store - -The `user` record in the auth store is now fully reactive and will automatically update with real-time events. In fact, the record in the auth store is the record in the users store. Please note that if you configure the `userService` option on the `auth` plugin, you must also use the `service` plugin for the `/users` service. The paths must match: - -```js -import Vue from 'vue' -import Vuex from 'vuex' -import feathersVuex from 'feathers-vuex' -import feathersClient from './feathers-client' - -const { service, auth, FeathersVuex } = feathersVuex(feathersClient, { idField: '_id' }) - -Vue.use(FeathersVuex) -Vue.use(Vuex) +When this record is instantiated, the `user` attribute will first be turned into a User [model instance](./model-classes.html), stored properly in the `/users` store. The `todo.user` attribute will be a reference to that user. No more duplicate data! Here's an example of how to set this up. -export default new Vuex.Store({ - plugins: [ - service('users'), - auth({ - userService: 'users' - }) - ] -}) -``` +There's another amazing benefit from these relationships. Because `feathers-vuex` listens to real-time events and keeps data up to date, when the user record changes, the `todo.user` automatically updates! ## Form Binding @@ -549,10 +483,4 @@ export default new Vuex.Store({ ## Enable Debug Logging -If items aren't not getting added to the store properly, try setting the `debug` option on the service. It enables some additional logging that may be useful for troubleshooting: - -```js -service('todos', { - debug: true -}) -``` +If items aren't not getting added to the store properly, try setting the `debug` option on the `makeServicePlugin` to `true`. It enables some additional logging that may be useful for troubleshooting.