From 7f328828a0862ef356cf18bcc7ca4883883c9b1c Mon Sep 17 00:00:00 2001 From: Brian Kimball Date: Wed, 7 Nov 2018 15:05:07 -0500 Subject: [PATCH 1/2] feat(Persist): Fancy Memoize functionality --- jest.config.js | 3 + jest.config.json | 17 - package-lock.json | 1025 ++++++++++---------------------- package.json | 11 +- src/services/EntityService.ts | 1 - src/services/SettingService.ts | 3 +- src/services/Staffing.ts | 27 +- src/utils/Cache.ts | 11 +- src/utils/Is.ts | 8 + src/utils/Persist.ts | 135 +++++ src/utils/index.ts | 1 + test/Entity.spec.ts | 6 +- test/EntityList.spec.ts | 4 +- test/Persist.spec.ts | 42 ++ test/_Helpers.ts | 274 ++++----- 15 files changed, 676 insertions(+), 892 deletions(-) create mode 100644 jest.config.js delete mode 100644 jest.config.json create mode 100644 src/utils/Persist.ts create mode 100644 test/Persist.spec.ts diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..5056e38 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,3 @@ +module.exports = { + preset: 'ts-jest' +}; diff --git a/jest.config.json b/jest.config.json deleted file mode 100644 index 3b80cec..0000000 --- a/jest.config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "verbose": true, - "testURL": "http://localhost/", - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "(/test/.*[.](test|spec))\\.(ts|tsx|js)$", - "testPathIgnorePatterns": [ - "[/\\\\](dist|coverage|node_modules)[/\\\\]", - "_\\w*.\\w+$" - ], - "moduleFileExtensions": [ - "ts", - "tsx", - "js" - ] -} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b9bd580..7a65abe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -402,9 +402,9 @@ "dev": true }, "@types/jest": { - "version": "22.2.3", - "resolved": "http://registry.npmjs.org/@types/jest/-/jest-22.2.3.tgz", - "integrity": "sha512-e74sM9W/4qqWB6D4TWV9FQk0WoHtX1X4FJpbjxucMSVJHtFjbQOH3H6yp+xno4br0AKG0wz/kPtaN599GUOvAg==", + "version": "23.3.9", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-23.3.9.tgz", + "integrity": "sha512-wNMwXSUcwyYajtbayfPp55tSayuDVU6PfY5gzvRSj80UvxdXEJOVPnUVajaOp7NgXLm+1e2ZDLULmpsU9vDvQw==", "dev": true }, "@types/lodash": { @@ -491,9 +491,9 @@ }, "dependencies": { "acorn": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.2.tgz", - "integrity": "sha512-GXmKIvbrN3TV7aVqAzVFaMW8F8wzVX7voEBRO3bDA64+EX37YSayggRJP5Xig6HYHBkWKpFg9W5gg6orklubhg==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz", + "integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==", "dev": true } } @@ -925,12 +925,6 @@ "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", "dev": true }, - "array-filter": { - "version": "0.0.1", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/array-filter/-/array-filter-0.0.1.tgz", - "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", - "dev": true - }, "array-find-index": { "version": "1.0.2", "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/array-find-index/-/array-find-index-1.0.2.tgz", @@ -949,18 +943,6 @@ "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", "dev": true }, - "array-map": { - "version": "0.0.0", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/array-map/-/array-map-0.0.0.tgz", - "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", - "dev": true - }, - "array-reduce": { - "version": "0.0.0", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/array-reduce/-/array-reduce-0.0.0.tgz", - "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", - "dev": true - }, "array-union": { "version": "1.0.2", "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/array-union/-/array-union-1.0.2.tgz", @@ -1035,12 +1017,6 @@ "lodash": "^4.17.10" } }, - "async-each": { - "version": "1.0.1", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/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", @@ -1319,13 +1295,13 @@ } }, "babel-jest": { - "version": "22.4.4", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-22.4.4.tgz", - "integrity": "sha512-A9NB6/lZhYyypR9ATryOSDcqBaqNdzq4U+CN+/wcMsLcmKkPxQEoTKLajGfd3IkxNyVBT8NewUK2nWyGbSzHEQ==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-23.6.0.tgz", + "integrity": "sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==", "dev": true, "requires": { - "babel-plugin-istanbul": "^4.1.5", - "babel-preset-jest": "^22.4.4" + "babel-plugin-istanbul": "^4.1.6", + "babel-preset-jest": "^23.2.0" } }, "babel-messages": { @@ -1359,9 +1335,9 @@ } }, "babel-plugin-jest-hoist": { - "version": "22.4.4", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-22.4.4.tgz", - "integrity": "sha512-DUvGfYaAIlkdnygVIEl0O4Av69NtuQWcrjMOv6DODPuhuGLDnbsARz3AwiiI/EkIMMlxQDUcrZ9yoyJvTNjcVQ==", + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz", + "integrity": "sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=", "dev": true }, "babel-plugin-syntax-async-functions": { @@ -1721,12 +1697,12 @@ } }, "babel-preset-jest": { - "version": "22.4.4", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-22.4.4.tgz", - "integrity": "sha512-+dxMtOFwnSYWfum0NaEc0O03oSdwBsjx4tMSChRDPGwu/4wSY6Q6ANW3wkjKpJzzguaovRs/DODcT4hbSN8yiA==", + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz", + "integrity": "sha1-jsegOhOPABoaj7HoETZSvxpV2kY=", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^22.4.4", + "babel-plugin-jest-hoist": "^23.2.0", "babel-plugin-syntax-object-rest-spread": "^6.13.0" } }, @@ -1913,12 +1889,6 @@ "integrity": "sha512-VOMDtYPwLbIncTxNoSzRyvaMxtXmLWLUqr8k5AfC1BzLk34HvBXaQX8snOwQZ4c0aX8aSERqtJSiI9/m2u5kuA==", "dev": true }, - "binary-extensions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", - "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", - "dev": true - }, "bl": { "version": "0.8.2", "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/bl/-/bl-0.8.2.tgz", @@ -2106,6 +2076,15 @@ "electron-to-chromium": "^1.3.47" } }, + "bs-logger": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.5.tgz", + "integrity": "sha512-uFLE0LFMxrH8Z5Hd9QgivvRbrl/NFkOTHzGhlqQxsnmx5JBLrp4bc249afLL+GccyY/8hkcGi2LpVaOzaEY0nQ==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "^2.0.0" + } + }, "bser": { "version": "2.0.0", "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/bser/-/bser-2.0.0.tgz", @@ -2288,35 +2267,6 @@ "supports-color": "^5.3.0" } }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": 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" - }, - "dependencies": { - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true, - "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" - } - } - } - }, "ci-info": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", @@ -2903,25 +2853,6 @@ } } }, - "cpx": { - "version": "1.5.0", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/cpx/-/cpx-1.5.0.tgz", - "integrity": "sha1-GFvgGFEdhycN7czCkxceN2VauI8=", - "dev": true, - "requires": { - "babel-runtime": "^6.9.2", - "chokidar": "^1.6.0", - "duplexer": "^0.1.1", - "glob": "^7.0.5", - "glob2base": "^0.0.12", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.1", - "resolve": "^1.1.7", - "safe-buffer": "^5.0.1", - "shell-quote": "^1.6.1", - "subarg": "^1.0.0" - } - }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -3038,13 +2969,13 @@ } }, "data-urls": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.1.tgz", - "integrity": "sha512-0HdcMZzK6ubMUnsMmQmG0AcLQPvbvb47R0+7CCZQCYgcd8OUWG91CG7sM6GoXgjz+WLl4ArFzHtBMy/QqSF4eg==", + "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.1.0", + "whatwg-mimetype": "^2.2.0", "whatwg-url": "^7.0.0" }, "dependencies": { @@ -3198,6 +3129,12 @@ } } }, + "delay": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-4.1.0.tgz", + "integrity": "sha512-8Hea6/aOu3bPdDBQhSRUEUzF0QwuWmSPuIK+sxNdvcJtSfzb6HXrTd9DFJBCJcV9o83fFECqTgllqdnmUfq9+w==", + "dev": true + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3315,12 +3252,6 @@ "is-obj": "^1.0.0" } }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, "duplexer2": { "version": "0.1.4", "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/duplexer2/-/duplexer2-0.1.4.tgz", @@ -3599,17 +3530,17 @@ } }, "expect": { - "version": "22.4.3", - "resolved": "http://registry.npmjs.org/expect/-/expect-22.4.3.tgz", - "integrity": "sha512-XcNXEPehqn8b/jm8FYotdX0YrXn36qp4HWlrVT4ktwQas1l1LPxiVWncYnnL2eyMtKAmVIaG0XAp0QlrqJaxaA==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-23.6.0.tgz", + "integrity": "sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==", "dev": true, "requires": { "ansi-styles": "^3.2.0", - "jest-diff": "^22.4.3", - "jest-get-type": "^22.4.3", - "jest-matcher-utils": "^22.4.3", - "jest-message-util": "^22.4.3", - "jest-regex-util": "^22.4.3" + "jest-diff": "^23.6.0", + "jest-get-type": "^22.1.0", + "jest-matcher-utils": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-regex-util": "^23.3.0" } }, "extend": { @@ -4060,12 +3991,6 @@ "repeat-string": "^1.5.2" } }, - "find-index": { - "version": "0.1.1", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, "find-up": { "version": "2.1.0", "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/find-up/-/find-up-2.1.0.tgz", @@ -4121,25 +4046,14 @@ "dev": true }, "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "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", + "combined-stream": "^1.0.6", "mime-types": "^2.1.12" - }, - "dependencies": { - "combined-stream": { - "version": "1.0.6", - "resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - } } }, "fragment-cache": { @@ -4864,15 +4778,6 @@ "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", "dev": true }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "^0.1.1" - } - }, "global-dirs": { "version": "0.1.1", "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/global-dirs/-/global-dirs-0.1.1.tgz", @@ -5349,15 +5254,6 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/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.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -5820,19 +5716,19 @@ "dev": true }, "jest": { - "version": "22.4.4", - "resolved": "https://registry.npmjs.org/jest/-/jest-22.4.4.tgz", - "integrity": "sha512-eBhhW8OS/UuX3HxgzNBSVEVhSuRDh39Z1kdYkQVWna+scpgsrD7vSeBI7tmEvsguPDMnfJodW28YBnhv/BzSew==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-23.6.0.tgz", + "integrity": "sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==", "dev": true, "requires": { "import-local": "^1.0.0", - "jest-cli": "^22.4.4" + "jest-cli": "^23.6.0" }, "dependencies": { "jest-cli": { - "version": "22.4.4", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-22.4.4.tgz", - "integrity": "sha512-I9dsgkeyjVEEZj9wrGrqlH+8OlNob9Iptyl+6L5+ToOLJmHm4JwOPatin1b2Bzp5R5YRQJ+oiedx7o1H7wJzhA==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-23.6.0.tgz", + "integrity": "sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==", "dev": true, "requires": { "ansi-escapes": "^3.0.0", @@ -5842,105 +5738,120 @@ "graceful-fs": "^4.1.11", "import-local": "^1.0.0", "is-ci": "^1.0.10", - "istanbul-api": "^1.1.14", - "istanbul-lib-coverage": "^1.1.1", - "istanbul-lib-instrument": "^1.8.0", - "istanbul-lib-source-maps": "^1.2.1", - "jest-changed-files": "^22.2.0", - "jest-config": "^22.4.4", - "jest-environment-jsdom": "^22.4.1", + "istanbul-api": "^1.3.1", + "istanbul-lib-coverage": "^1.2.0", + "istanbul-lib-instrument": "^1.10.1", + "istanbul-lib-source-maps": "^1.2.4", + "jest-changed-files": "^23.4.2", + "jest-config": "^23.6.0", + "jest-environment-jsdom": "^23.4.0", "jest-get-type": "^22.1.0", - "jest-haste-map": "^22.4.2", - "jest-message-util": "^22.4.0", - "jest-regex-util": "^22.1.0", - "jest-resolve-dependencies": "^22.1.0", - "jest-runner": "^22.4.4", - "jest-runtime": "^22.4.4", - "jest-snapshot": "^22.4.0", - "jest-util": "^22.4.1", - "jest-validate": "^22.4.4", - "jest-worker": "^22.2.2", + "jest-haste-map": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-regex-util": "^23.3.0", + "jest-resolve-dependencies": "^23.6.0", + "jest-runner": "^23.6.0", + "jest-runtime": "^23.6.0", + "jest-snapshot": "^23.6.0", + "jest-util": "^23.4.0", + "jest-validate": "^23.6.0", + "jest-watcher": "^23.4.0", + "jest-worker": "^23.2.0", "micromatch": "^2.3.11", "node-notifier": "^5.2.1", + "prompts": "^0.1.9", "realpath-native": "^1.0.0", "rimraf": "^2.5.4", "slash": "^1.0.0", "string-length": "^2.0.0", "strip-ansi": "^4.0.0", "which": "^1.2.12", - "yargs": "^10.0.3" + "yargs": "^11.0.0" } } } }, "jest-changed-files": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-22.4.3.tgz", - "integrity": "sha512-83Dh0w1aSkUNFhy5d2dvqWxi/y6weDwVVLU6vmK0cV9VpRxPzhTeGimbsbRDSnEoszhF937M4sDLLeS7Cu/Tmw==", + "version": "23.4.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-23.4.2.tgz", + "integrity": "sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==", "dev": true, "requires": { "throat": "^4.0.0" } }, "jest-config": { - "version": "22.4.4", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-22.4.4.tgz", - "integrity": "sha512-9CKfo1GC4zrXSoMLcNeDvQBfgtqGTB1uP8iDIZ97oB26RCUb886KkKWhVcpyxVDOUxbhN+uzcBCeFe7w+Iem4A==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-23.6.0.tgz", + "integrity": "sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==", "dev": true, "requires": { + "babel-core": "^6.0.0", + "babel-jest": "^23.6.0", "chalk": "^2.0.1", "glob": "^7.1.1", - "jest-environment-jsdom": "^22.4.1", - "jest-environment-node": "^22.4.1", + "jest-environment-jsdom": "^23.4.0", + "jest-environment-node": "^23.4.0", "jest-get-type": "^22.1.0", - "jest-jasmine2": "^22.4.4", - "jest-regex-util": "^22.1.0", - "jest-resolve": "^22.4.2", - "jest-util": "^22.4.1", - "jest-validate": "^22.4.4", - "pretty-format": "^22.4.0" + "jest-jasmine2": "^23.6.0", + "jest-regex-util": "^23.3.0", + "jest-resolve": "^23.6.0", + "jest-util": "^23.4.0", + "jest-validate": "^23.6.0", + "micromatch": "^2.3.11", + "pretty-format": "^23.6.0" } }, "jest-diff": { - "version": "22.4.3", - "resolved": "http://registry.npmjs.org/jest-diff/-/jest-diff-22.4.3.tgz", - "integrity": "sha512-/QqGvCDP5oZOF6PebDuLwrB2BMD8ffJv6TAGAdEVuDx1+uEgrHpSFrfrOiMRx2eJ1hgNjlQrOQEHetVwij90KA==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-23.6.0.tgz", + "integrity": "sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==", "dev": true, "requires": { "chalk": "^2.0.1", "diff": "^3.2.0", - "jest-get-type": "^22.4.3", - "pretty-format": "^22.4.3" + "jest-get-type": "^22.1.0", + "pretty-format": "^23.6.0" } }, "jest-docblock": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-22.4.3.tgz", - "integrity": "sha512-uPKBEAw7YrEMcXueMKZXn/rbMxBiSv48fSqy3uEnmgOlQhSX+lthBqHb1fKWNVmFqAp9E/RsSdBfiV31LbzaOg==", + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-23.2.0.tgz", + "integrity": "sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=", "dev": true, "requires": { "detect-newline": "^2.1.0" } }, + "jest-each": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-23.6.0.tgz", + "integrity": "sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "pretty-format": "^23.6.0" + } + }, "jest-environment-jsdom": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-22.4.3.tgz", - "integrity": "sha512-FviwfR+VyT3Datf13+ULjIMO5CSeajlayhhYQwpzgunswoaLIPutdbrnfUHEMyJCwvqQFaVtTmn9+Y8WCt6n1w==", + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz", + "integrity": "sha1-BWp5UrP+pROsYqFAosNox52eYCM=", "dev": true, "requires": { - "jest-mock": "^22.4.3", - "jest-util": "^22.4.3", + "jest-mock": "^23.2.0", + "jest-util": "^23.4.0", "jsdom": "^11.5.1" } }, "jest-environment-node": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-22.4.3.tgz", - "integrity": "sha512-reZl8XF6t/lMEuPWwo9OLfttyC26A5AMgDyEQ6DBgZuyfyeNUzYT8BFo6uxCCP/Av/b7eb9fTi3sIHFPBzmlRA==", + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-23.4.0.tgz", + "integrity": "sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=", "dev": true, "requires": { - "jest-mock": "^22.4.3", - "jest-util": "^22.4.3" + "jest-mock": "^23.2.0", + "jest-util": "^23.4.0" } }, "jest-get-type": { @@ -5950,63 +5861,65 @@ "dev": true }, "jest-haste-map": { - "version": "22.4.3", - "resolved": "http://registry.npmjs.org/jest-haste-map/-/jest-haste-map-22.4.3.tgz", - "integrity": "sha512-4Q9fjzuPVwnaqGKDpIsCSoTSnG3cteyk2oNVjBX12HHOaF1oxql+uUiqZb5Ndu7g/vTZfdNwwy4WwYogLh29DQ==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-23.6.0.tgz", + "integrity": "sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==", "dev": true, "requires": { "fb-watchman": "^2.0.0", "graceful-fs": "^4.1.11", - "jest-docblock": "^22.4.3", - "jest-serializer": "^22.4.3", - "jest-worker": "^22.4.3", + "invariant": "^2.2.4", + "jest-docblock": "^23.2.0", + "jest-serializer": "^23.0.1", + "jest-worker": "^23.2.0", "micromatch": "^2.3.11", "sane": "^2.0.0" } }, "jest-jasmine2": { - "version": "22.4.4", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-22.4.4.tgz", - "integrity": "sha512-nK3vdUl50MuH7vj/8at7EQVjPGWCi3d5+6aCi7Gxy/XMWdOdbH1qtO/LjKbqD8+8dUAEH+BVVh7HkjpCWC1CSw==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz", + "integrity": "sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==", "dev": true, "requires": { + "babel-traverse": "^6.0.0", "chalk": "^2.0.1", "co": "^4.6.0", - "expect": "^22.4.0", - "graceful-fs": "^4.1.11", + "expect": "^23.6.0", "is-generator-fn": "^1.0.0", - "jest-diff": "^22.4.0", - "jest-matcher-utils": "^22.4.0", - "jest-message-util": "^22.4.0", - "jest-snapshot": "^22.4.0", - "jest-util": "^22.4.1", - "source-map-support": "^0.5.0" + "jest-diff": "^23.6.0", + "jest-each": "^23.6.0", + "jest-matcher-utils": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-snapshot": "^23.6.0", + "jest-util": "^23.4.0", + "pretty-format": "^23.6.0" } }, "jest-leak-detector": { - "version": "22.4.3", - "resolved": "http://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-22.4.3.tgz", - "integrity": "sha512-NZpR/Ls7+ndO57LuXROdgCGz2RmUdC541tTImL9bdUtU3WadgFGm0yV+Ok4Fuia/1rLAn5KaJ+i76L6e3zGJYQ==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz", + "integrity": "sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==", "dev": true, "requires": { - "pretty-format": "^22.4.3" + "pretty-format": "^23.6.0" } }, "jest-matcher-utils": { - "version": "22.4.3", - "resolved": "http://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-22.4.3.tgz", - "integrity": "sha512-lsEHVaTnKzdAPR5t4B6OcxXo9Vy4K+kRRbG5gtddY8lBEC+Mlpvm1CJcsMESRjzUhzkz568exMV1hTB76nAKbA==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz", + "integrity": "sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==", "dev": true, "requires": { "chalk": "^2.0.1", - "jest-get-type": "^22.4.3", - "pretty-format": "^22.4.3" + "jest-get-type": "^22.1.0", + "pretty-format": "^23.6.0" } }, "jest-message-util": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-22.4.3.tgz", - "integrity": "sha512-iAMeKxhB3Se5xkSjU0NndLLCHtP4n+GtCqV0bISKA5dmOXQfEbdEmYiu2qpnWBDCQdEafNDDU6Q+l6oBMd/+BA==", + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-23.4.0.tgz", + "integrity": "sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=", "dev": true, "requires": { "@babel/code-frame": "^7.0.0-beta.35", @@ -6017,81 +5930,86 @@ } }, "jest-mock": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-22.4.3.tgz", - "integrity": "sha512-+4R6mH5M1G4NK16CKg9N1DtCaFmuxhcIqF4lQK/Q1CIotqMs/XBemfpDPeVZBFow6iyUNu6EBT9ugdNOTT5o5Q==", + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-23.2.0.tgz", + "integrity": "sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=", "dev": true }, "jest-regex-util": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-22.4.3.tgz", - "integrity": "sha512-LFg1gWr3QinIjb8j833bq7jtQopiwdAs67OGfkPrvy7uNUbVMfTXXcOKXJaeY5GgjobELkKvKENqq1xrUectWg==", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-23.3.0.tgz", + "integrity": "sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=", "dev": true }, "jest-resolve": { - "version": "22.4.3", - "resolved": "http://registry.npmjs.org/jest-resolve/-/jest-resolve-22.4.3.tgz", - "integrity": "sha512-u3BkD/MQBmwrOJDzDIaxpyqTxYH+XqAXzVJP51gt29H8jpj3QgKof5GGO2uPGKGeA1yTMlpbMs1gIQ6U4vcRhw==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-23.6.0.tgz", + "integrity": "sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==", "dev": true, "requires": { - "browser-resolve": "^1.11.2", - "chalk": "^2.0.1" + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "realpath-native": "^1.0.0" } }, "jest-resolve-dependencies": { - "version": "22.4.3", - "resolved": "http://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-22.4.3.tgz", - "integrity": "sha512-06czCMVToSN8F2U4EvgSB1Bv/56gc7MpCftZ9z9fBgUQM7dzHGCMBsyfVA6dZTx8v0FDcnALf7hupeQxaBCvpA==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz", + "integrity": "sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==", "dev": true, "requires": { - "jest-regex-util": "^22.4.3" + "jest-regex-util": "^23.3.0", + "jest-snapshot": "^23.6.0" } }, "jest-runner": { - "version": "22.4.4", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-22.4.4.tgz", - "integrity": "sha512-5S/OpB51igQW9xnkM5Tgd/7ZjiAuIoiJAVtvVTBcEBiXBIFzWM3BAMPBM19FX68gRV0KWyFuGKj0EY3M3aceeQ==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-23.6.0.tgz", + "integrity": "sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==", "dev": true, "requires": { "exit": "^0.1.2", - "jest-config": "^22.4.4", - "jest-docblock": "^22.4.0", - "jest-haste-map": "^22.4.2", - "jest-jasmine2": "^22.4.4", - "jest-leak-detector": "^22.4.0", - "jest-message-util": "^22.4.0", - "jest-runtime": "^22.4.4", - "jest-util": "^22.4.1", - "jest-worker": "^22.2.2", + "graceful-fs": "^4.1.11", + "jest-config": "^23.6.0", + "jest-docblock": "^23.2.0", + "jest-haste-map": "^23.6.0", + "jest-jasmine2": "^23.6.0", + "jest-leak-detector": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-runtime": "^23.6.0", + "jest-util": "^23.4.0", + "jest-worker": "^23.2.0", + "source-map-support": "^0.5.6", "throat": "^4.0.0" } }, "jest-runtime": { - "version": "22.4.4", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-22.4.4.tgz", - "integrity": "sha512-WRTj9m///npte1YjuphCYX7GRY/c2YvJImU9t7qOwFcqHr4YMzmX6evP/3Sehz5DKW2Vi8ONYPCFWe36JVXxfw==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-23.6.0.tgz", + "integrity": "sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==", "dev": true, "requires": { "babel-core": "^6.0.0", - "babel-jest": "^22.4.4", - "babel-plugin-istanbul": "^4.1.5", + "babel-plugin-istanbul": "^4.1.6", "chalk": "^2.0.1", "convert-source-map": "^1.4.0", "exit": "^0.1.2", + "fast-json-stable-stringify": "^2.0.0", "graceful-fs": "^4.1.11", - "jest-config": "^22.4.4", - "jest-haste-map": "^22.4.2", - "jest-regex-util": "^22.1.0", - "jest-resolve": "^22.4.2", - "jest-util": "^22.4.1", - "jest-validate": "^22.4.4", - "json-stable-stringify": "^1.0.1", + "jest-config": "^23.6.0", + "jest-haste-map": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-regex-util": "^23.3.0", + "jest-resolve": "^23.6.0", + "jest-snapshot": "^23.6.0", + "jest-util": "^23.4.0", + "jest-validate": "^23.6.0", "micromatch": "^2.3.11", "realpath-native": "^1.0.0", "slash": "^1.0.0", "strip-bom": "3.0.0", "write-file-atomic": "^2.1.0", - "yargs": "^10.0.3" + "yargs": "^11.0.0" }, "dependencies": { "strip-bom": { @@ -6103,37 +6021,42 @@ } }, "jest-serializer": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-22.4.3.tgz", - "integrity": "sha512-uPaUAppx4VUfJ0QDerpNdF43F68eqKWCzzhUlKNDsUPhjOon7ZehR4C809GCqh765FoMRtTVUVnGvIoskkYHiw==", + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-23.0.1.tgz", + "integrity": "sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=", "dev": true }, "jest-snapshot": { - "version": "22.4.3", - "resolved": "http://registry.npmjs.org/jest-snapshot/-/jest-snapshot-22.4.3.tgz", - "integrity": "sha512-JXA0gVs5YL0HtLDCGa9YxcmmV2LZbwJ+0MfyXBBc5qpgkEYITQFJP7XNhcHFbUvRiniRpRbGVfJrOoYhhGE0RQ==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-23.6.0.tgz", + "integrity": "sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==", "dev": true, "requires": { + "babel-types": "^6.0.0", "chalk": "^2.0.1", - "jest-diff": "^22.4.3", - "jest-matcher-utils": "^22.4.3", + "jest-diff": "^23.6.0", + "jest-matcher-utils": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-resolve": "^23.6.0", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "pretty-format": "^22.4.3" + "pretty-format": "^23.6.0", + "semver": "^5.5.0" } }, "jest-util": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-22.4.3.tgz", - "integrity": "sha512-rfDfG8wyC5pDPNdcnAlZgwKnzHvZDu8Td2NJI/jAGKEGxJPYiE4F0ss/gSAkG4778Y23Hvbz+0GMrDJTeo7RjQ==", + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-23.4.0.tgz", + "integrity": "sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=", "dev": true, "requires": { "callsites": "^2.0.0", "chalk": "^2.0.1", "graceful-fs": "^4.1.11", "is-ci": "^1.0.10", - "jest-message-util": "^22.4.3", + "jest-message-util": "^23.4.0", "mkdirp": "^0.5.1", + "slash": "^1.0.0", "source-map": "^0.6.0" }, "dependencies": { @@ -6146,22 +6069,32 @@ } }, "jest-validate": { - "version": "22.4.4", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-22.4.4.tgz", - "integrity": "sha512-dmlf4CIZRGvkaVg3fa0uetepcua44DHtktHm6rcoNVtYlpwe6fEJRkMFsaUVcFHLzbuBJ2cPw9Gl9TKfnzMVwg==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz", + "integrity": "sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==", "dev": true, "requires": { "chalk": "^2.0.1", - "jest-config": "^22.4.4", "jest-get-type": "^22.1.0", "leven": "^2.1.0", - "pretty-format": "^22.4.0" + "pretty-format": "^23.6.0" + } + }, + "jest-watcher": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-23.4.0.tgz", + "integrity": "sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "string-length": "^2.0.0" } }, "jest-worker": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-22.4.3.tgz", - "integrity": "sha512-B1ucW4fI8qVAuZmicFxI1R3kr2fNeYJyvIQ1rKcuLYnenFV5K5aMbxFj6J0i00Ju83S8jP2d7Dz14+AvbIHRYQ==", + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-23.2.0.tgz", + "integrity": "sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=", "dev": true, "requires": { "merge-stream": "^1.0.1" @@ -6253,15 +6186,6 @@ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", "dev": true }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -6283,12 +6207,6 @@ "graceful-fs": "^4.1.6" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, "jsonparse": { "version": "1.3.1", "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/jsonparse/-/jsonparse-1.3.1.tgz", @@ -6331,6 +6249,12 @@ "is-buffer": "^1.1.5" } }, + "kleur": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-2.0.2.tgz", + "integrity": "sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==", + "dev": true + }, "latest-version": { "version": "3.1.0", "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/latest-version/-/latest-version-3.1.0.tgz", @@ -6862,9 +6786,9 @@ } }, "merge": { - "version": "1.2.0", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/merge/-/merge-1.2.0.tgz", - "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", + "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", "dev": true }, "merge-stream": { @@ -6920,18 +6844,18 @@ "dev": true }, "mime-db": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", - "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==", + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", "dev": true }, "mime-types": { - "version": "2.1.20", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", - "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", "dev": true, "requires": { - "mime-db": "~1.36.0" + "mime-db": "~1.37.0" } }, "mimic-fn": { @@ -7140,13 +7064,13 @@ "dev": true }, "node-notifier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.2.1.tgz", - "integrity": "sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.3.0.tgz", + "integrity": "sha512-AhENzCSGZnZJgBARsUjnQ7DnZbzyP+HxlVXuD0xqAnvL8q+OqtSX7lGg9e8nHzwXkMMXNdVeqq4E2M3EUAqX6Q==", "dev": true, "requires": { "growly": "^1.3.0", - "semver": "^5.4.1", + "semver": "^5.5.0", "shellwords": "^0.1.1", "which": "^1.3.0" } @@ -10866,9 +10790,9 @@ "dev": true }, "pretty-format": { - "version": "22.4.3", - "resolved": "http://registry.npmjs.org/pretty-format/-/pretty-format-22.4.3.tgz", - "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", + "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", "dev": true, "requires": { "ansi-regex": "^3.0.0", @@ -10907,6 +10831,16 @@ "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", "dev": true }, + "prompts": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-0.1.14.tgz", + "integrity": "sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==", + "dev": true, + "requires": { + "kleur": "^2.0.1", + "sisteransi": "^0.1.1" + } + }, "protocols": { "version": "1.4.6", "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/protocols/-/protocols-1.4.6.tgz", @@ -11111,302 +11045,6 @@ "util-deprecate": "~1.0.1" } }, - "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" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } - } - }, "realpath-native": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.0.2.tgz", @@ -12645,18 +12283,6 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, - "shell-quote": { - "version": "1.6.1", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/shell-quote/-/shell-quote-1.6.1.tgz", - "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true, - "requires": { - "array-filter": "~0.0.0", - "array-map": "~0.0.0", - "array-reduce": "~0.0.0", - "jsonify": "~0.0.0" - } - }, "shelljs": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", @@ -12706,6 +12332,12 @@ "type-detect": "^4.0.5" } }, + "sisteransi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-0.1.1.tgz", + "integrity": "sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==", + "dev": true + }, "slash": { "version": "1.0.0", "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/slash/-/slash-1.0.0.tgz", @@ -12959,9 +12591,9 @@ "dev": true }, "sshpk": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", - "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", + "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", "dev": true, "requires": { "asn1": "~0.2.3", @@ -13114,23 +12746,6 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, - "subarg": { - "version": "1.0.0", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "dev": true, - "requires": { - "minimist": "^1.1.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://artifactory.bullhorn.com/api/npm/bh-npm/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -13443,59 +13058,40 @@ "dev": true }, "ts-jest": { - "version": "22.4.6", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-22.4.6.tgz", - "integrity": "sha512-kYQ6g1G1AU+bOO9rv+SSQXg4WTcni6Wx3AM48iHni0nP1vIuhdNRjKTE9Cxx36Ix/IOV7L85iKu07dgXJzH2pQ==", - "dev": true, - "requires": { - "babel-core": "^6.26.3", - "babel-plugin-istanbul": "^4.1.6", - "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", - "babel-preset-jest": "^22.4.3", - "cpx": "^1.5.0", - "fs-extra": "6.0.0", - "jest-config": "^22.4.3", - "lodash": "^4.17.10", - "pkg-dir": "^2.0.0", - "source-map-support": "^0.5.5", - "yargs": "^11.0.0" + "version": "23.10.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-23.10.4.tgz", + "integrity": "sha512-oV/wBwGUS7olSk/9yWMiSIJWbz5xO4zhftnY3gwv6s4SMg6WHF1m8XZNBvQOKQRiTAexZ9754Z13dxBq3Zgssw==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "buffer-from": "1.x", + "fast-json-stable-stringify": "2.x", + "json5": "2.x", + "make-error": "1.x", + "mkdirp": "0.x", + "semver": "^5.5", + "yargs-parser": "10.x" }, "dependencies": { - "fs-extra": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.0.tgz", - "integrity": "sha512-lk2cUCo8QzbiEWEbt7Cw3m27WMiRG321xsssbcIpfMhpRjrlC08WBOVQqj1/nQYYNnPtyIhP1oqLO3QwT2tPCw==", + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "minimist": "^1.2.0" } }, - "yargs": { - "version": "11.1.0", - "resolved": "http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", - "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" - } + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true }, "yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "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" @@ -13503,6 +13099,11 @@ } } }, + "ts-method-cache": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ts-method-cache/-/ts-method-cache-3.2.1.tgz", + "integrity": "sha512-MJ+P7Pbfs0HrzTC7ktyp+MByGyHF2ASACzC1v1giwrthlHWPWlG1gc5yu138O+piDLtPs1mbY/t3zYtwoPHvFA==" + }, "ts-node": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-6.2.0.tgz", @@ -14184,9 +13785,9 @@ "dev": true }, "yargs": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.1.2.tgz", - "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==", + "version": "11.1.0", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", "dev": true, "requires": { "cliui": "^4.0.0", @@ -14200,13 +13801,13 @@ "string-width": "^2.0.0", "which-module": "^2.0.0", "y18n": "^3.2.1", - "yargs-parser": "^8.1.0" + "yargs-parser": "^9.0.2" } }, "yargs-parser": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", - "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", "dev": true, "requires": { "camelcase": "^4.1.0" diff --git a/package.json b/package.json index e7b427d..4f4c70e 100644 --- a/package.json +++ b/package.json @@ -39,9 +39,10 @@ }, "devDependencies": { "@bullhorn/bullhorn-types": "^0.3.0", - "@types/jest": "^22.2.0", + "@types/jest": "^23.3.9", "@types/node": "^8.10.10", - "jest": "^22.4.3", + "delay": "^4.1.0", + "jest": "^23.6.0", "opn-cli": "^3.1.0", "rollup": "^0.58.0", "rollup-plugin-commonjs": "^9.0.0", @@ -59,7 +60,7 @@ "sinon": "^4.5.0", "temp-dir": "^1.0.0", "travis-deploy-once": "^4.3.2", - "ts-jest": "^22.4.0", + "ts-jest": "^23.10.4", "ts-node": "^6.0.0", "tslib": "^1.9.0", "tslint": "^5.9.0", @@ -71,8 +72,8 @@ "build": "npm run clean && rollup -c", "clean": "rm -rf lib", "lint": "tslint --project tsconfig.json --format stylish", - "test": "jest --config jest.config.json --coverage --no-cache --runInBand", - "test:watch": "jest --config jest.config.json --watch", + "test": "jest --config jest.config.js --coverage --no-cache --runInBand", + "test:watch": "jest --config jest.config.js --watch", "posttest": "npm run lint", "semantic-release": "semantic-release", "docs": "typedoc src/index.ts --excludePrivate --mode file --out docs && cp ./taurus-banner.gif ./docs && opn docs/index.html", diff --git a/src/services/EntityService.ts b/src/services/EntityService.ts index b0abe9c..cd380fd 100644 --- a/src/services/EntityService.ts +++ b/src/services/EntityService.ts @@ -72,7 +72,6 @@ export class EntityService { * @param id - Id of the Model to retrieve */ async get(id: number): Promise> { - console.log('test', this.parameters); const [response, meta] = await Promise.all([this.http.get(`${this.endpoint}/${id}`, { params: this.parameters }), this.meta.getFull(this.parameters.fields, this.parameters.layout)]); const result: BullhornEntityResponse = response.data; result.meta = meta; diff --git a/src/services/SettingService.ts b/src/services/SettingService.ts index 484f585..fb817a3 100644 --- a/src/services/SettingService.ts +++ b/src/services/SettingService.ts @@ -1,7 +1,7 @@ import { AxiosInstance, AxiosResponse } from 'axios'; import { BullhornAllSettingsAndEntitlementsResponse } from '../types'; import { Staffing } from './Staffing'; - +import { Persist, PersistType } from '../utils'; /** * A Class that defines a service to grab settings from Bullhorn */ @@ -22,6 +22,7 @@ export class SettingService { return response.data; } + @Persist({ type: PersistType.SESSION }) async getAllSettingsAndEntitlements(): Promise { const response: AxiosResponse = await this.http.get('services/Settings/allEntitlementsAndSettings'); const result: BullhornAllSettingsAndEntitlementsResponse = response.data; diff --git a/src/services/Staffing.ts b/src/services/Staffing.ts index 4a913f6..0db4c4d 100644 --- a/src/services/Staffing.ts +++ b/src/services/Staffing.ts @@ -5,18 +5,23 @@ import { StaffingConfiguration } from '../types'; import { Cache, QueryString } from '../utils'; const getCookie = (cname: string) => { - // tslint:disable-next-line:no-typeof-undefined - if (typeof document !== 'undefined') { - const name = `${cname}=`; - const ca = document.cookie.split(';'); - for (let c of ca) { - while (c.charAt(0) === ' ') { - c = c.substring(1); - } - if (c.indexOf(name) === 0) { - return c.substring(name.length, c.length); + try { + // tslint:disable-next-line:no-typeof-undefined + if (typeof document !== 'undefined') { + const name = `${cname}=`; + const ca = document.cookie.split(';'); + for (let c of ca) { + while (c.charAt(0) === ' ') { + c = c.substring(1); + } + if (c.indexOf(name) === 0) { + return JSON.parse(decodeURIComponent(c.substring(name.length, c.length))); + } } } + } catch (err) { + console.warn('Error parsing identity cookie', err.message); + return false; } return false; }; @@ -96,7 +101,7 @@ export class Staffing { static http(): AxiosInstance { const cookie = getCookie('UlEncodedIdentity'); if (cookie && cookie.length) { - const identity = JSON.parse(decodeURIComponent(cookie)); + const identity = cookie; const endpoints = identity.sessions.reduce((obj, session) => { obj[session.name] = session.value.endpoint; return obj; diff --git a/src/utils/Cache.ts b/src/utils/Cache.ts index 867cf59..c9b8e1e 100644 --- a/src/utils/Cache.ts +++ b/src/utils/Cache.ts @@ -2,7 +2,7 @@ import { Memory } from './Memory'; let storageReference: Storage = new Memory(); try { - if (window.localStorage) { + if (window && window.localStorage) { storageReference = window.localStorage; } } catch (err) { @@ -57,8 +57,13 @@ export class Cache { */ static get(key: string) { const value = storageReference.getItem(key); - if (value) { - return JSON.parse(value); + try { + if (value) { + return JSON.parse(value); + } + // tslint:disable-next-line:no-unused + } catch (err) { + return null; } return null; diff --git a/src/utils/Is.ts b/src/utils/Is.ts index 7c21865..c84d3de 100644 --- a/src/utils/Is.ts +++ b/src/utils/Is.ts @@ -51,6 +51,10 @@ export class Is { return this.a(String); } + get aPromise() { + return this.a(Promise); + } + get defined() { return !this.undefined && !this.null && !this.nan; } @@ -120,6 +124,10 @@ export class Is { result = className === 'Object' || className === 'Arguments'; break; + case Promise: + result = className === 'Promise'; + break; + default: const templateClassName = T.constructor.name; diff --git a/src/utils/Persist.ts b/src/utils/Persist.ts new file mode 100644 index 0000000..94da138 --- /dev/null +++ b/src/utils/Persist.ts @@ -0,0 +1,135 @@ +import { Memory } from './Memory'; +import { is } from './Is'; + +export enum PersistType { + MEMORY = 1, + SESSION, + STORAGE +} + +export enum PersistReturnType { + STATIC = 1, + PROMISE +} + +export interface PersistOptions { + key?: string; + type?: PersistType; + ttl?: number; +} + +export interface StorageObject { + items: { [args: string]: any }; + ttl: { [args: string]: number }; + returnType?: PersistReturnType; +} + +export function validatePersistType(type: PersistType = PersistType.MEMORY) { + switch (type) { + case PersistType.SESSION: + if (window && window.sessionStorage) { + return type; + } + break; + case PersistType.STORAGE: + if (window && window.localStorage) { + return type; + } + break; + case PersistType.MEMORY: + default: + return PersistType.Memory; + } + return PersistType.Memory; +} + +export function normalizePersistOptions(options: PersistOptions, key: string = 'persist-key') { + options.type = validatePersistType(options.type); + options.key = options.key || key; + options.ttl = options.ttl || 0; + return options; +} + +export function getMethodPersistProvider(type: PersistType): Storage { + switch (type) { + case PersistType.SESSION: + return sessionStorage; + case PersistType.STORAGE: + return localStorage; + case PersistType.MEMORY: + default: + return new Memory(); + } +} + +export function getPersisted(memory: StorageObject, key: string): any { + let item = null; + if (memory.items.hasOwnProperty(key)) { + item = memory.items[key]; + } + return (memory.returnType === PersistReturnType.PROMISE) ? Promise.resolve(item) : item; +} + +export function hasPersist(memory: StorageObject, key: string): boolean { + return (memory.items.hasOwnProperty(key)); +} + +export function isExpired(memory: StorageObject, key: string): boolean { + if (!memory.ttl.hasOwnProperty(key)) { + return false; + } + return memory.ttl[key] < Date.now(); +} + +export function parseSafe(t: any): any { + try { + return JSON.parse(t); + // tslint:disable-next-line:no-unused + } catch (err) { + return { + items: {}, + ttl: {} + }; + } +} + +export function createPersistDecorator(options: PersistOptions, _target: Object, method: Function): () => any { + const provider: Storage = getMethodPersistProvider(options.type); + return async function (this: Function, ...args: any[]): Promise { + const argsString: string = JSON.stringify(args); + const cacheObject: StorageObject = parseSafe(provider.getItem(options.key)); + if (!hasPersist(cacheObject, argsString) || isExpired(cacheObject, argsString)) { + const result = method.call(this, ...args); + const returnType = is(result).a(Promise) ? PersistReturnType.PROMISE : PersistReturnType.STATIC; + const toBeStored: StorageObject = { + items: { + ...cacheObject.items, + [argsString]: result + }, + ttl: { + ...cacheObject.ttl, + [argsString]: Date.now() + options.ttl, + }, + returnType + }; + provider.setItem(options.key, JSON.stringify(toBeStored)); + return result; + } + return getPersisted(cacheObject, argsString); + }; +} + +export function Persist(_options: PersistOptions = { type: PersistType.MEMORY }): MethodDecorator { + return (target: object, method: string, descriptor: PropertyDescriptor): PropertyDescriptor => { + const options = normalizePersistOptions(_options, method); + if (descriptor.hasOwnProperty('get') && descriptor.get) { + descriptor.get = createPersistDecorator(options, target, descriptor.get); + } else if (!descriptor.hasOwnProperty('set') && descriptor.value) { + descriptor.value = createPersistDecorator(options, target, descriptor.value); + } else { + throw new Error('Can\'t set cache decorator on a setter'); + } + + return descriptor; + }; +} diff --git a/src/utils/index.ts b/src/utils/index.ts index f6173eb..060ae9a 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -5,3 +5,4 @@ export * from './Deferred'; export * from './Lazy'; export * from './Memory'; export * from './QueryString'; +export * from './Persist'; diff --git a/test/Entity.spec.ts b/test/Entity.spec.ts index 8a2a334..9d2122a 100644 --- a/test/Entity.spec.ts +++ b/test/Entity.spec.ts @@ -59,10 +59,10 @@ describe('Entity', () => { describe('with API calls', () => { let server; - beforeEach(function() { - server = sinon.fakeServer.create(); + beforeEach(() => { + server = sinon.createFakeServer(); }); - afterEach(function() { + afterEach(() => { server.restore(); }); diff --git a/test/EntityList.spec.ts b/test/EntityList.spec.ts index a5efbb6..e63d6c6 100644 --- a/test/EntityList.spec.ts +++ b/test/EntityList.spec.ts @@ -6,7 +6,7 @@ import { candidateMetaResponse, candidateListResponse } from './_Helpers'; describe('EntityList', () => { let server; beforeEach(() => { - server = sinon.fakeServer.create(); + server = sinon.createFakeServer(); server.autoRespond = true; }); afterEach(() => { @@ -16,7 +16,7 @@ describe('EntityList', () => { it('should get list data', (done) => { server.respondWith('GET', /search\/Candidate/, candidateListResponse()); server.respondWith('GET', /meta\/Candidate/, candidateMetaResponse()); - let candidates: EntityList = new EntityList(EntityTypes.Candidate, { + const candidates: EntityList = new EntityList(EntityTypes.Candidate, { fields: ['id', 'name', 'phone'], limitTo: 20, }); diff --git a/test/Persist.spec.ts b/test/Persist.spec.ts new file mode 100644 index 0000000..b1753a0 --- /dev/null +++ b/test/Persist.spec.ts @@ -0,0 +1,42 @@ +import { Persist } from '../src/index'; +import delay from 'delay'; + +describe('Persist cache decorator is properly set', () => { + class TestCache { + public called: number = 0; + public ttlcalled: number = 0; + + @Persist() + public testMethod(): number { + return ++this.called; + } + + @Persist({ ttl: 500 }) + public ttlMethod(): number { + return ++this.ttlcalled; + } + } + + let testCache: TestCache; + beforeEach(() => { + testCache = new TestCache(); + }); + + it('should only call the test method once', () => { + const result1: number = testCache.testMethod(); + const result2: number = testCache.testMethod(); + expect(testCache.called).toEqual(1); + expect(result1).toEqual(result2); + }); + + it('should only call the test method once every 500 ms', async () => { + testCache.ttlMethod(); + testCache.ttlMethod(); + expect(testCache.ttlcalled).toEqual(1); + await delay(501); + testCache.ttlMethod(); + testCache.ttlMethod(); + expect(testCache.ttlcalled).toEqual(2); + }); + +}); diff --git a/test/_Helpers.ts b/test/_Helpers.ts index de046e5..d263b0c 100644 --- a/test/_Helpers.ts +++ b/test/_Helpers.ts @@ -4,7 +4,7 @@ export const okJsonResponse = (data: any = {}) => { { 'Content-Type': 'application/json' }, JSON.stringify(data) ]; -} +}; export const candidateMetaResponse = (fields: string[] = []) => { return [ @@ -42,143 +42,143 @@ export const candidateMetaResponse = (fields: string[] = []) => { ].filter(field => !fields.length || fields.indexOf(field.name)) }) ]; -} +}; export const candidateListResponse = () => { return (xhr) => { - let params: any = {}; - xhr.url.replace(new RegExp('([^?=&]+)(=([^&]*))?', 'g'), function ($0, $1, $2, $3) { - params[decodeURIComponent($1)] = decodeURIComponent($3); - }); - xhr.respond(200, - { 'Content-Type': 'application/json' }, - JSON.stringify({ - total: 101219, - start: 0, - count: 20, - data: [ - { - id: 474039, - name: 'Gale Wiedeman', - phone: '209-823-9083', - _score: 1 - }, - { - id: 474040, - name: 'Peter Kondiles', - phone: '406-494-6806', - _score: 1 - }, - { - id: 474042, - name: 'Greg Cooper', - phone: '760-631-0852', - _score: 1 - }, - { - id: 474044, - name: 'Nemy Bautista', - phone: '916-616-6369', - _score: 1 - }, - { - id: 474215, - name: 'Richard Tyrrell', - phone: '707-251-8695', - _score: 1 - }, - { - id: 474220, - name: 'Michael Little', - phone: '(415) 928-2762', - _score: 1 - }, - { - id: 474227, - name: 'John Randall', - phone: '925.625.1969', - _score: 1 - }, - { - id: 474237, - name: 'WAYNE SCHAUCHULIS', - phone: '(650) 508-8360', - _score: 1 - }, - { - id: 474239, - name: 'Regina Garrett', - phone: '415.617.3241', - _score: 1 - }, - { - id: 474637, - name: 'Harvinder S. Bhella', - phone: '408-910-9064', - _score: 1 - }, - { - id: 474638, - name: 'JEFFREY STARKEY', - phone: '(707) 450-0111', - _score: 1 - }, - { - id: 474644, - name: 'Jeffrey Beriones', - phone: '(925) 686-0884', - _score: 1 - }, - { - id: 474662, - name: 'LESLIE FEY', - phone: '(916)989-5179', - _score: 1 - }, - { - id: 474667, - name: 'Clifton Jordan', - phone: '858-259-7390', - _score: 1 - }, - { - id: 474671, - name: 'David Owens', - phone: '(805) 717-1953', - _score: 1 - }, - { - id: 474680, - name: 'VAHAG VIC OVASAPIAN', - phone: '(818) 240-8312', - _score: 1 - }, - { - id: 474694, - name: 'jogert abrantes', - phone: '4083061359', - _score: 1 - }, - { - id: 474721, - name: 'DEMETRIUS SPRATLEY', - phone: '(909) 672-0330', - _score: 1 - }, - { - id: 474740, - name: 'ANNETTE LI', - phone: '(415) 351-2620', - _score: 1 - }, - { - id: 474962, - name: 'EDGAR HOLLINGSWORTH', - phone: '925-634-2726', - _score: 1 - } - ].slice(0, params.count) - }) - ]; + const params: any = {}; + xhr.url.replace(new RegExp('([^?=&]+)(=([^&]*))?', 'g'), ($0, $1, $2, $3) => { + params[decodeURIComponent($1)] = decodeURIComponent($3); + }); + xhr.respond(200, + { 'Content-Type': 'application/json' }, + JSON.stringify({ + total: 101219, + start: 0, + count: 20, + data: [ + { + id: 474039, + name: 'Gale Wiedeman', + phone: '209-823-9083', + _score: 1 + }, + { + id: 474040, + name: 'Peter Kondiles', + phone: '406-494-6806', + _score: 1 + }, + { + id: 474042, + name: 'Greg Cooper', + phone: '760-631-0852', + _score: 1 + }, + { + id: 474044, + name: 'Nemy Bautista', + phone: '916-616-6369', + _score: 1 + }, + { + id: 474215, + name: 'Richard Tyrrell', + phone: '707-251-8695', + _score: 1 + }, + { + id: 474220, + name: 'Michael Little', + phone: '(415) 928-2762', + _score: 1 + }, + { + id: 474227, + name: 'John Randall', + phone: '925.625.1969', + _score: 1 + }, + { + id: 474237, + name: 'WAYNE SCHAUCHULIS', + phone: '(650) 508-8360', + _score: 1 + }, + { + id: 474239, + name: 'Regina Garrett', + phone: '415.617.3241', + _score: 1 + }, + { + id: 474637, + name: 'Harvinder S. Bhella', + phone: '408-910-9064', + _score: 1 + }, + { + id: 474638, + name: 'JEFFREY STARKEY', + phone: '(707) 450-0111', + _score: 1 + }, + { + id: 474644, + name: 'Jeffrey Beriones', + phone: '(925) 686-0884', + _score: 1 + }, + { + id: 474662, + name: 'LESLIE FEY', + phone: '(916)989-5179', + _score: 1 + }, + { + id: 474667, + name: 'Clifton Jordan', + phone: '858-259-7390', + _score: 1 + }, + { + id: 474671, + name: 'David Owens', + phone: '(805) 717-1953', + _score: 1 + }, + { + id: 474680, + name: 'VAHAG VIC OVASAPIAN', + phone: '(818) 240-8312', + _score: 1 + }, + { + id: 474694, + name: 'jogert abrantes', + phone: '4083061359', + _score: 1 + }, + { + id: 474721, + name: 'DEMETRIUS SPRATLEY', + phone: '(909) 672-0330', + _score: 1 + }, + { + id: 474740, + name: 'ANNETTE LI', + phone: '(415) 351-2620', + _score: 1 + }, + { + id: 474962, + name: 'EDGAR HOLLINGSWORTH', + phone: '925-634-2726', + _score: 1 + } + ].slice(0, params.count) + }) + ); }; -} +}; From 7b9229f780e5abae2da6765b51071298f23f8fb2 Mon Sep 17 00:00:00 2001 From: Brian Kimball Date: Thu, 8 Nov 2018 09:33:39 -0500 Subject: [PATCH 2/2] feat(Persist): Now working and tested with async and args --- src/utils/Is.ts | 2 +- src/utils/Persist.ts | 127 +++++++++++++++++++++++++------------------ test/Persist.spec.ts | 32 +++++++++++ 3 files changed, 107 insertions(+), 54 deletions(-) diff --git a/src/utils/Is.ts b/src/utils/Is.ts index c84d3de..a34190d 100644 --- a/src/utils/Is.ts +++ b/src/utils/Is.ts @@ -77,7 +77,7 @@ export class Is { a(T) { let result = false; - const className = this.reference.constructor.name; + const className = this.reference ? this.reference.constructor.name : 'Undefined'; switch (T) { case undefined: diff --git a/src/utils/Persist.ts b/src/utils/Persist.ts index 94da138..616a334 100644 --- a/src/utils/Persist.ts +++ b/src/utils/Persist.ts @@ -38,47 +38,26 @@ export function validatePersistType(type: PersistType = PersistType.MEMORY) { break; case PersistType.MEMORY: default: - return PersistType.Memory; + return PersistType.MEMORY; } - return PersistType.Memory; + return PersistType.MEMORY; } -export function normalizePersistOptions(options: PersistOptions, key: string = 'persist-key') { - options.type = validatePersistType(options.type); - options.key = options.key || key; - options.ttl = options.ttl || 0; - return options; -} - -export function getMethodPersistProvider(type: PersistType): Storage { - switch (type) { - case PersistType.SESSION: - return sessionStorage; - case PersistType.STORAGE: - return localStorage; - case PersistType.MEMORY: - default: - return new Memory(); +export function validatePersistKey(keyOpt: string | Function, target: Object, method: string): string { + if (is(keyOpt).a(Function)) { + return (keyOpt as Function)(target); } -} - -export function getPersisted(memory: StorageObject, key: string): any { - let item = null; - if (memory.items.hasOwnProperty(key)) { - item = memory.items[key]; + if (is(keyOpt).a(String)) { + return keyOpt as string; } - return (memory.returnType === PersistReturnType.PROMISE) ? Promise.resolve(item) : item; + return `persist-key-${method}`; } -export function hasPersist(memory: StorageObject, key: string): boolean { - return (memory.items.hasOwnProperty(key)); -} - -export function isExpired(memory: StorageObject, key: string): boolean { - if (!memory.ttl.hasOwnProperty(key)) { - return false; - } - return memory.ttl[key] < Date.now(); +export function normalizePersistOptions(options: PersistOptions, target: Object, method: string) { + options.type = validatePersistType(options.type); + options.key = validatePersistKey(options.key, target, method); + options.ttl = options.ttl || 0; + return options; } export function parseSafe(t: any): any { @@ -93,35 +72,77 @@ export function parseSafe(t: any): any { } } +export class StorageProvider { + private storage: Storage; + private memory: StorageObject; + + constructor(private _options: PersistOptions) { + this.storage = this._getMethodPersistProvider(_options.type); + this.memory = parseSafe(this.storage.getItem(_options.key)); + } + + public getPersisted(key: string): any { + let item = null; + if (this.memory.items.hasOwnProperty(key)) { + item = this.memory.items[key]; + } + return (this.memory.returnType === PersistReturnType.PROMISE) ? Promise.resolve(item) : item; + } + + public async setPersisted(key: string, value: any): Promise { + const isPromise = is(value).a(Promise); + this.memory.returnType = isPromise ? PersistReturnType.PROMISE : PersistReturnType.STATIC; + if (isPromise) { + this.memory.items = { ...this.memory.items, [key]: await Promise.resolve(value) }; + } else { + this.memory.items = { ...this.memory.items, [key]: value }; + } + if (this._options.ttl) { + this.memory.ttl = { ...this.memory.ttl, [key]: Date.now() + this._options.ttl }; + } + this.storage.setItem(this._options.key, JSON.stringify(this.memory)); + } + + public hasPersist(key: string): boolean { + return (this.memory.items.hasOwnProperty(key)); + } + + public isExpired(key: string): boolean { + if (!this.memory.ttl.hasOwnProperty(key)) { + return false; + } + return this.memory.ttl[key] < Date.now(); + } + + private _getMethodPersistProvider(type: PersistType): Storage { + switch (type) { + case PersistType.SESSION: + return sessionStorage; + case PersistType.STORAGE: + return localStorage; + case PersistType.MEMORY: + default: + return new Memory(); + } + } +} + export function createPersistDecorator(options: PersistOptions, _target: Object, method: Function): () => any { - const provider: Storage = getMethodPersistProvider(options.type); - return async function (this: Function, ...args: any[]): Promise { + const provider: StorageProvider = new StorageProvider(options); + return function (this: Function, ...args: any[]): any { const argsString: string = JSON.stringify(args); - const cacheObject: StorageObject = parseSafe(provider.getItem(options.key)); - if (!hasPersist(cacheObject, argsString) || isExpired(cacheObject, argsString)) { + if (!provider.hasPersist(argsString) || provider.isExpired(argsString)) { const result = method.call(this, ...args); - const returnType = is(result).a(Promise) ? PersistReturnType.PROMISE : PersistReturnType.STATIC; - const toBeStored: StorageObject = { - items: { - ...cacheObject.items, - [argsString]: result - }, - ttl: { - ...cacheObject.ttl, - [argsString]: Date.now() + options.ttl, - }, - returnType - }; - provider.setItem(options.key, JSON.stringify(toBeStored)); + provider.setPersisted(argsString, result); return result; } - return getPersisted(cacheObject, argsString); + return provider.getPersisted(argsString); }; } export function Persist(_options: PersistOptions = { type: PersistType.MEMORY }): MethodDecorator { return (target: object, method: string, descriptor: PropertyDescriptor): PropertyDescriptor => { - const options = normalizePersistOptions(_options, method); + const options = normalizePersistOptions(_options, target, method); if (descriptor.hasOwnProperty('get') && descriptor.get) { descriptor.get = createPersistDecorator(options, target, descriptor.get); } else if (!descriptor.hasOwnProperty('set') && descriptor.value) { diff --git a/test/Persist.spec.ts b/test/Persist.spec.ts index b1753a0..0754d4a 100644 --- a/test/Persist.spec.ts +++ b/test/Persist.spec.ts @@ -5,6 +5,8 @@ describe('Persist cache decorator is properly set', () => { class TestCache { public called: number = 0; public ttlcalled: number = 0; + public argsCalled: number = 0; + public asyncCalled: number = 0; @Persist() public testMethod(): number { @@ -15,6 +17,18 @@ describe('Persist cache decorator is properly set', () => { public ttlMethod(): number { return ++this.ttlcalled; } + + @Persist() + public methodWithArgs(a: number, b: number): number { + this.argsCalled++; + return a + b; + } + + @Persist() + public async asyncMethod(a: number, b: number): Promise { + this.asyncCalled++; + return Promise.resolve(a + b); + } } let testCache: TestCache; @@ -39,4 +53,22 @@ describe('Persist cache decorator is properly set', () => { expect(testCache.ttlcalled).toEqual(2); }); + it('should only call the args method once per unique args', () => { + const result1: number = testCache.methodWithArgs(1, 1); + const result2: number = testCache.methodWithArgs(1, 1); + expect(testCache.argsCalled).toEqual(1); + expect(result1).toEqual(result2); + const result3: number = testCache.methodWithArgs(2, 2); + const result4: number = testCache.methodWithArgs(2, 2); + expect(testCache.argsCalled).toEqual(2); + expect(result3).toEqual(result4); + }); + + it('should only call the async method once', async () => { + const result1: number = await testCache.asyncMethod(2, 2); + const result2: number = await testCache.asyncMethod(2, 2); + expect(testCache.asyncCalled).toEqual(1); + expect(result1).toEqual(result2); + }); + });