From 1f3a4a879c2f5d1cd9d178957b45fcbdd8f35d1f Mon Sep 17 00:00:00 2001 From: Paul Boocock Date: Wed, 2 Sep 2020 09:18:00 +0100 Subject: [PATCH] Switch from 'request' to 'got' (close #61) --- package-lock.json | 515 +++++++++++++++++++++++++++----------------- package.json | 3 +- src/emitter.ts | 144 ++----------- src/got_emitter.ts | 142 ++++++++++++ src/index.ts | 3 +- src/tracker.ts | 7 +- test/emitter.ts | 121 ++--------- test/got_emitter.ts | 203 +++++++++++++++++ test/tracker.ts | 180 ++++++++-------- 9 files changed, 800 insertions(+), 518 deletions(-) create mode 100644 src/got_emitter.ts create mode 100644 test/got_emitter.ts diff --git a/package-lock.json b/package-lock.json index 64cccc9..08878a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1159,10 +1159,9 @@ } }, "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-3.1.2.tgz", + "integrity": "sha512-JiX9vxoKMmu8Y3Zr2RVathBL1Cdu4Nt4MuNWemt1Nc06A0RAin9c5FArkhGsyMBWfCu4zj+9b+GxtjAnE4qqLQ==" }, "@sinonjs/commons": { "version": "1.8.1", @@ -1210,12 +1209,11 @@ "dev": true }, "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", + "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==", "requires": { - "defer-to-connect": "^1.0.1" + "defer-to-connect": "^2.0.0" } }, "@types/babel__core": { @@ -1259,11 +1257,16 @@ "@babel/types": "^7.3.0" } }, - "@types/caseless": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", - "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==", - "dev": true + "@types/cacheable-request": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz", + "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==", + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } }, "@types/color-name": { "version": "1.1.1", @@ -1293,12 +1296,25 @@ "@types/node": "*" } }, + "@types/http-cache-semantics": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", + "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==" + }, "@types/json-schema": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", "dev": true }, + "@types/keyv": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz", + "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==", + "requires": { + "@types/node": "*" + } + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -1308,8 +1324,7 @@ "@types/node": { "version": "14.6.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.0.tgz", - "integrity": "sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA==", - "dev": true + "integrity": "sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA==" }, "@types/normalize-package-data": { "version": "2.4.0", @@ -1323,29 +1338,12 @@ "integrity": "sha512-/tuN8jDbOXcPk+VzEVZzzAgw1Byz7s/itb2YI10qkSyy6nykJH02DuhfrflxVdAdE7AZ91h5X6Cn0dmVdFw2TQ==", "dev": true }, - "@types/request": { - "version": "2.48.5", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.5.tgz", - "integrity": "sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ==", - "dev": true, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", "requires": { - "@types/caseless": "*", - "@types/node": "*", - "@types/tough-cookie": "*", - "form-data": "^2.5.0" - }, - "dependencies": { - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - } + "@types/node": "*" } }, "@types/semver": { @@ -1369,12 +1367,6 @@ "integrity": "sha512-yYezQwGWty8ziyYLdZjwxyMb0CZR49h8JALHGrxjQHWlqGgc8kLdHEgWrgL0uZ29DMvEVBDnHU2Wg36zKSIUtA==", "dev": true }, - "@types/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==", - "dev": true - }, "@types/ua-parser-js": { "version": "0.7.33", "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.33.tgz", @@ -1647,6 +1639,7 @@ "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", @@ -1780,6 +1773,7 @@ "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" } @@ -1787,7 +1781,8 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true }, "astral-regex": { "version": "1.0.0", @@ -1798,7 +1793,8 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true }, "ava": { "version": "3.12.1", @@ -2041,12 +2037,14 @@ "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=" + "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==" + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true }, "babel-plugin-dynamic-import-node": { "version": "2.3.3", @@ -2067,6 +2065,7 @@ "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" } @@ -2217,36 +2216,23 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "cacheable-lookup": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.3.tgz", + "integrity": "sha512-W+JBqF9SWe18A72XFzN/V/CULFzPm7sBXzzR6ekkE+3tLG72wFZrBiBZhrZuDoYexop4PHJVdFAKb/Nj9+tm9w==" + }, "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz", + "integrity": "sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==", "requires": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", + "keyv": "^4.0.0", "lowercase-keys": "^2.0.0", "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } + "responselike": "^2.0.0" } }, "caching-transform": { @@ -2282,7 +2268,8 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true }, "chalk": { "version": "2.4.2", @@ -2433,7 +2420,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, "requires": { "mimic-response": "^1.0.0" } @@ -2466,6 +2452,7 @@ "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" } @@ -2572,7 +2559,8 @@ "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=" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true }, "coveralls": { "version": "3.1.0", @@ -2668,6 +2656,7 @@ "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" } @@ -2697,12 +2686,18 @@ "dev": true }, "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "requires": { - "mimic-response": "^1.0.0" + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + } } }, "deep-extend": { @@ -2745,10 +2740,9 @@ } }, "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.0.tgz", + "integrity": "sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==" }, "define-properties": { "version": "1.1.3", @@ -2802,7 +2796,8 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true }, "diff": { "version": "4.0.2", @@ -2847,6 +2842,7 @@ "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" @@ -2874,7 +2870,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "requires": { "once": "^1.4.0" } @@ -3177,17 +3172,20 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true }, "fast-diff": { "version": "1.2.0", @@ -3212,7 +3210,8 @@ "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=" + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", @@ -3318,12 +3317,14 @@ "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "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", @@ -3380,10 +3381,9 @@ "dev": true }, "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "requires": { "pump": "^3.0.0" } @@ -3392,6 +3392,7 @@ "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" } @@ -3457,22 +3458,21 @@ } }, "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/got/-/got-11.5.2.tgz", + "integrity": "sha512-yUhpEDLeuGiGJjRSzEq3kvt4zJtAcjKmhIiwNp/eUs75tRlXfWcHo5tcBaMQtnjHWC7nQYT5HkY/l0QOQTkVww==", + "requires": { + "@sindresorhus/is": "^3.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.0", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" } }, "graceful-fs": { @@ -3484,12 +3484,14 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + "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" @@ -3538,19 +3540,28 @@ "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" }, "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" } }, + "http2-wrapper": { + "version": "1.0.0-beta.5.2", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.0-beta.5.2.tgz", + "integrity": "sha512-xYz9goEyBnC8XwXDTuC/MZ6t+MrKVQZOk4s7+PaDkwIsQd8IwqvM+0M6bA/2lvG8GHXcPdf+MejTUeO2LCPCeQ==", + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -3770,7 +3781,8 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true }, "is-windows": { "version": "1.0.2", @@ -3799,7 +3811,8 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true }, "istanbul-lib-coverage": { "version": "3.0.0", @@ -3942,7 +3955,8 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true }, "jsesc": { "version": "2.5.2", @@ -3951,10 +3965,9 @@ "dev": true }, "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, "json-parse-better-errors": { "version": "1.0.2", @@ -3971,12 +3984,14 @@ "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "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==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -3987,7 +4002,8 @@ "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=" + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true }, "json5": { "version": "2.1.3", @@ -4010,6 +4026,7 @@ "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", @@ -4024,12 +4041,11 @@ "dev": true }, "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.1.tgz", + "integrity": "sha512-xz6Jv6oNkbhrFCvCP7HQa8AaII8y8LRpoSm661NOKLr4uHuBwhX4epXrPQgF3+xdJnN4Esm5X0xwY4bOlALOtw==", "requires": { - "json-buffer": "3.0.0" + "json-buffer": "3.0.1" } }, "latest-version": { @@ -4154,10 +4170,9 @@ } }, "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 + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" }, "magic-string": { "version": "0.25.7", @@ -4270,12 +4285,14 @@ "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==" + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "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==", + "dev": true, "requires": { "mime-db": "~1.37.0" } @@ -4289,8 +4306,7 @@ "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" }, "minimatch": { "version": "3.0.4", @@ -4414,8 +4430,7 @@ "normalize-url": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", - "dev": true + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" }, "nyc": { "version": "15.1.0", @@ -4594,7 +4609,8 @@ "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true }, "object-keys": { "version": "1.1.1", @@ -4624,7 +4640,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -4730,10 +4745,9 @@ } }, "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", + "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==" }, "p-defer": { "version": "1.0.0", @@ -4796,6 +4810,134 @@ "registry-auth-token": "^4.0.0", "registry-url": "^5.0.0", "semver": "^6.2.0" + }, + "dependencies": { + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "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 + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + } } }, "parent-module": { @@ -4865,7 +5007,8 @@ "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true }, "picomatch": { "version": "2.2.2", @@ -5048,13 +5191,13 @@ "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==" + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", + "dev": true }, "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" @@ -5063,7 +5206,8 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "pupa": { "version": "2.0.1", @@ -5077,7 +5221,13 @@ "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" }, "rc": { "version": "1.2.8", @@ -5231,33 +5381,6 @@ "es6-error": "^4.0.1" } }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "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.3", - "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.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -5279,6 +5402,11 @@ "path-parse": "^1.0.6" } }, + "resolve-alpn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.0.0.tgz", + "integrity": "sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA==" + }, "resolve-cwd": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", @@ -5295,12 +5423,11 @@ "dev": true }, "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", "requires": { - "lowercase-keys": "^1.0.0" + "lowercase-keys": "^2.0.0" } }, "restore-cursor": { @@ -5346,12 +5473,14 @@ "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==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true }, "semver": { "version": "6.3.0", @@ -8114,6 +8243,7 @@ "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", @@ -8356,15 +8486,6 @@ "is-number": "^7.0.0" } }, - "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==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, "trim-off-newlines": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz", @@ -8410,6 +8531,7 @@ "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" } @@ -8417,7 +8539,8 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true }, "type-check": { "version": "0.4.0", @@ -8575,6 +8698,7 @@ "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" } @@ -8591,7 +8715,8 @@ "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true }, "v8-compile-cache": { "version": "2.1.1", @@ -8613,6 +8738,7 @@ "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", @@ -8683,8 +8809,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "1.0.3", diff --git a/package.json b/package.json index a45782e..80fb69a 100644 --- a/package.json +++ b/package.json @@ -33,13 +33,12 @@ ], "license": "Apache-2.0", "dependencies": { - "request": "^2.88.2", + "got": "^11.5.2", "snowplow-tracker-core": "^0.9.1", "tslib": "^2.0.1" }, "devDependencies": { "@types/node": "^14.6.0", - "@types/request": "^2.48.5", "@types/sinon": "^9.0.5", "@typescript-eslint/eslint-plugin": "^3.10.1", "@typescript-eslint/parser": "^3.10.1", diff --git a/src/emitter.ts b/src/emitter.ts index 4c99632..d4230d8 100644 --- a/src/emitter.ts +++ b/src/emitter.ts @@ -1,21 +1,3 @@ -/* - * Node.js tracker for Snowplow: emitter.js - * - * Copyright (c) 2014-2017 Snowplow Analytics Ltd. All rights reserved. - * - * This program is licensed to you under the Apache License Version 2.0, - * and you may not use this file except in compliance with the Apache License Version 2.0. - * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the Apache License Version 2.0 is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. - */ - -import request from 'request'; -import http from 'http'; -import https from 'https'; import { PayloadDictionary } from 'snowplow-tracker-core'; export interface Emitter { @@ -24,120 +6,38 @@ export interface Emitter { } export enum HttpProtocol { - HTTP = "http", - HTTPS = "https" + HTTP = 'http', + HTTPS = 'https', } export enum HttpMethod { - GET = "get", - POST = "post" + GET = 'get', + POST = 'post', } /** - * Create an emitter object which will send events to a collector + * Convert all fields in a payload dictionary to strings * - * @param endpoint The collector to which events will be sent - * @param protocol "http" or "https" - * @param port The port for requests to use - * @param method "get" or "post" - * @param bufferSize Number of events which can be queued before flush is called - * @param callback Callback passed to the request function - * @param agentOptions configuration for http.Agent class + * @param payload Payload on which the new dictionary is based */ -export function emitter( - endpoint: string, - protocol: HttpProtocol, - port?: number, - method?: HttpMethod, - bufferSize?: number, - callback?: request.RequestCallback, - agentOptions?: http.AgentOptions | https.AgentOptions -): Emitter { - const maxBufferLength = bufferSize ?? (method === HttpMethod.GET ? 0 : 10); - const path = method === HttpMethod.GET ? '/i' : '/com.snowplowanalytics.snowplow/tp2'; - const targetUrl = protocol + '://' + endpoint + (port ? ':' + port : '') + path; +export const preparePayload = (payload: PayloadDictionary): Record => { + const stringifiedPayload: Record = {}; - let buffer: Array = []; + const finalPayload = addDeviceSentTimestamp(payload); - /** - * Convert all fields in a payload dictionary to strings - * - * @param payload Payload on which the new dictionary is based - */ - const preparePayload = (payload: PayloadDictionary): Record => { - const stringifiedPayload: Record = {}; - - const finalPayload = addDeviceSentTimestamp(payload); - - for (const key in finalPayload) { - if (Object.prototype.hasOwnProperty.call(finalPayload, key)) { - stringifiedPayload[key] = String(finalPayload[key]); - } + for (const key in finalPayload) { + if (Object.prototype.hasOwnProperty.call(finalPayload, key)) { + stringifiedPayload[key] = String(finalPayload[key]); } - return stringifiedPayload; - }; - - const addDeviceSentTimestamp = (payload: PayloadDictionary): PayloadDictionary => { - payload['stm'] = new Date().getTime().toString(); - return payload; } + return stringifiedPayload; +}; - /** - * Flushes all events currently stored in buffer - */ - const flush = (): void => { - const bufferCopy = buffer; - buffer = []; - if (bufferCopy.length === 0) { - return; - } - - if (method === HttpMethod.POST) { - const postJson = { - schema: 'iglu:com.snowplowanalytics.snowplow/payload_data/jsonschema/1-0-4', - data: bufferCopy.map(preparePayload), - }; - request.post( - { - url: targetUrl, - json: postJson, - agentOptions: agentOptions, - headers: { - 'content-type': 'application/json; charset=utf-8', - }, - }, - callback - ); - } else { - for (let i = 0; i < bufferCopy.length; i++) { - request.get( - { - url: targetUrl, - agentOptions: agentOptions, - qs: addDeviceSentTimestamp(bufferCopy[i]), - }, - callback - ); - } - } - }; - - /** - * Adds a payload to the internal buffer and sends if buffer >= bufferSize - * @param payload Payload to add to buffer - */ - const input = (payload: PayloadDictionary): void => { - buffer.push(payload); - if (buffer.length >= maxBufferLength) { - flush(); - } - }; - - return { - /** - * Send all events queued in the buffer to the collector - */ - flush, - input, - }; -} +/** + * Adds the 'stm' paramater with the current time to the payload + * @param payload The payload which will be mutated + */ +const addDeviceSentTimestamp = (payload: PayloadDictionary): PayloadDictionary => { + payload['stm'] = new Date().getTime().toString(); + return payload; +}; diff --git a/src/got_emitter.ts b/src/got_emitter.ts new file mode 100644 index 0000000..35892f7 --- /dev/null +++ b/src/got_emitter.ts @@ -0,0 +1,142 @@ +/* + * Node.js tracker for Snowplow: emitter.js + * + * Copyright (c) 2014-2017 Snowplow Analytics Ltd. All rights reserved. + * + * This program is licensed to you under the Apache License Version 2.0, + * and you may not use this file except in compliance with the Apache License Version 2.0. + * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the Apache License Version 2.0 is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. + */ + +import got, { Response, RequestError, Agents, RequiredRetryOptions, ToughCookieJar, PromiseCookieJar } from 'got'; +import { PayloadDictionary } from 'snowplow-tracker-core'; + +import { Emitter, HttpProtocol, HttpMethod, preparePayload } from './emitter'; +import { version } from './version'; + +/** + * Create an emitter object, which uses the `got` library, that will send events to a collector + * + * @param endpoint The collector to which events will be sent + * @param protocol http or https + * @param port The port for requests to use + * @param method get or post + * @param bufferSize Number of events which can be queued before flush is called + * @param retry Configure the retry policy for `got` - https://github.com/sindresorhus/got/blob/v11.5.2/readme.md#retry + * @param cookieJar Add a cookieJar to `got` - https://github.com/sindresorhus/got/blob/v11.5.2/readme.md#cookiejar + * @param callback Callback called after a `got` request following retries - called with ErrorRequest (https://github.com/sindresorhus/got/blob/v11.5.2/readme.md#errors) and Response (https://github.com/sindresorhus/got/blob/v11.5.2/readme.md#response) + * @param agents Set new http.Agent and https.Agent objects on `got` requests - https://github.com/sindresorhus/got/blob/v11.5.2/readme.md#agent + */ +export function gotEmitter( + endpoint: string, + protocol: HttpProtocol, + port?: number, + method?: HttpMethod, + bufferSize?: number, + retry?: number | Partial, + cookieJar?: PromiseCookieJar | ToughCookieJar, + callback?: (error?: RequestError, response?: Response) => void, + agents?: Agents +): Emitter { + const maxBufferLength = bufferSize ?? (method === HttpMethod.GET ? 0 : 10); + const path = method === HttpMethod.GET ? '/i' : '/com.snowplowanalytics.snowplow/tp2'; + const targetUrl = protocol + '://' + endpoint + (port ? ':' + port : '') + path; + + let buffer: Array = []; + + /** + * Handles the callback on a successful response if the callback is present + * @param response The got response object + */ + const handleSuccess = (response: Response) => { + if (callback) { + try { + callback(undefined, response); + } catch (e) { + console.error('Error in callback after success', e); + } + } + }; + + /** + * Handles the callback on a failed request if the callback is present + * @param error The got error object + */ + const handleFailure = (error: RequestError) => { + if (callback) { + try { + callback(error); + } catch (e) { + console.error('Error in callback after failure', e); + } + } + }; + + /** + * Flushes all events currently stored in buffer + */ + const flush = (): void => { + const bufferCopy = buffer; + buffer = []; + if (bufferCopy.length === 0) { + return; + } + + if (method === HttpMethod.POST) { + const postJson = { + schema: 'iglu:com.snowplowanalytics.snowplow/payload_data/jsonschema/1-0-4', + data: bufferCopy.map(preparePayload), + }; + got + .post(targetUrl, { + json: postJson, + headers: { + 'content-type': 'application/json; charset=utf-8', + 'user-agent': `snowplow-nodejs-tracker/${version}`, + }, + agent: agents, + retry: retry, + cookieJar: cookieJar, + }) + .then(handleSuccess, handleFailure); + } else { + for (let i = 0; i < bufferCopy.length; i++) { + got + .get(targetUrl, { + searchParams: preparePayload(bufferCopy[i]), + headers: { + 'user-agent': `snowplow-nodejs-tracker/${version}`, + }, + agent: agents, + retry: retry, + cookieJar: cookieJar, + }) + .then(handleSuccess, handleFailure); + } + } + }; + + /** + * Adds a payload to the internal buffer and sends if buffer >= bufferSize + * @param payload Payload to add to buffer + */ + const input = (payload: PayloadDictionary): void => { + buffer.push(payload); + if (buffer.length >= maxBufferLength) { + flush(); + } + }; + + return { + /** + * Send all events queued in the buffer to the collector + */ + flush, + input, + }; +} diff --git a/src/index.ts b/src/index.ts index 307f032..a0c0a61 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,6 +13,7 @@ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ +export { Emitter, HttpMethod, HttpProtocol } from './emitter'; export { tracker, Tracker, EcommerceTransactionItem } from './tracker'; -export { emitter, Emitter, HttpMethod, HttpProtocol } from './emitter'; +export { gotEmitter } from './got_emitter'; export { version } from './version'; diff --git a/src/tracker.ts b/src/tracker.ts index e083150..ebf460a 100644 --- a/src/tracker.ts +++ b/src/tracker.ts @@ -13,8 +13,9 @@ * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. */ -import { version } from './version'; import { trackerCore, PayloadData, SelfDescribingJson, Timestamp, Core } from 'snowplow-tracker-core'; + +import { version } from './version'; import { Emitter } from './emitter'; export interface EcommerceTransactionItem { @@ -175,11 +176,11 @@ export function tracker( const setDomainUserId = function (userId: string) { domainUserId = userId; - } + }; const setNetworkUserId = function (userId: string) { networkUserId = userId; - } + }; return { trackEcommerceTransactionWithItems, diff --git a/test/emitter.ts b/test/emitter.ts index 5ce6a9b..d4a4cbf 100644 --- a/test/emitter.ts +++ b/test/emitter.ts @@ -13,122 +13,27 @@ import test from 'ava'; import sinon from 'sinon'; -import nock from 'nock'; -import { emitter } from '../src/index'; -import { HttpMethod, HttpProtocol } from '../src/emitter'; -const endpoint = 'd3rkrsqld9gmqf.cloudfront.net'; +import { preparePayload } from '../src/emitter'; +import { PayloadDictionary } from 'snowplow-tracker-core'; -nock('http://' + endpoint, { - filteringScope: function () { - return true; - }, -}) - .persist() - .filteringPath(function () { - return '/'; - }) - .get('/') - .reply(200, function (uri) { - return uri; - }); +test('preparePayload should convert payload values to strings', (t) => { + const payload: PayloadDictionary = { a: 1234, b: '1'} -nock('http://' + endpoint, { - filteringScope: function () { - return true; - }, -}) - .matchHeader('content-type', 'application/json; charset=utf-8') - .persist() - .filteringRequestBody(function () { - return '*'; - }) - .post('/com.snowplowanalytics.snowplow/tp2', '*') - .reply(200, function (_uri, body: Record) { - return (body['data'] as Array)[0]; - }); + const result = preparePayload(payload); - -test.before(() => { - nock.disableNetConnect(); -}); - -test.after(() => { - nock.cleanAll(); -}); - -test.cb('Emitter should send an HTTP GET request', (t) => { - const e = emitter(endpoint, HttpProtocol.HTTP, 80, HttpMethod.GET, undefined, function (error, _body, response) { - t.regex(response, /\/i\?.*a=b.*/); - t.end(error); - }); - e.input({ a: 'b' }); -}); - -test.cb('Emitter should send an HTTP POST request', (t) => { - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, HttpMethod.POST, 1, function (error, _body, response) { - t.like(response, { a: 'b' }); - t.end(error); - }); - e.input({ a: 'b' }); -}); - -test.cb('should send an HTTPS GET request', (t) => { - const e = emitter(endpoint, HttpProtocol.HTTPS, 443, HttpMethod.GET, undefined, function (error, _body, response) { - t.regex(response, /\/i\?.*a=b.*/); - t.end(error); - }); - e.input({ a: 'b' }); + t.like(result, { a: '1234', b: '1' }); }); -test.cb('Emitter should send an HTTPS POST request', (t) => { - const e = emitter(endpoint, HttpProtocol.HTTPS, undefined, HttpMethod.POST, 1, function (error, _body, response) { - t.like(response, { a: 'b' }); - t.end(error); - }); - e.input({ a: 'b' }); -}); - -test.cb('Emitter should not send requests if the buffer is not full', (t) => { - const e = emitter(endpoint, HttpProtocol.HTTPS, undefined, HttpMethod.POST, undefined, () => - t.fail('Event unexpectedly emitted') - ); - e.input({}); - e.input({}); - e.input({}); - setTimeout(t.end, 250); //Give chance for emitter callback to fire -}); - -test.cb('Emitter should not send requests if the buffer is empty', (t) => { - const e = emitter(endpoint, HttpProtocol.HTTPS, undefined, HttpMethod.POST, undefined, () => - t.fail('Event unexpectedly emitted') - ); - e.flush(); - setTimeout(t.end, 250); //Give chance for emitter callback to fire -}); - -test.cb('Emitter should add STM querystring parameter when sending POST requests', (t) => { - const testTime = new Date('1988-12-12T12:30:00.000Z').getTime(); - const clock = sinon.useFakeTimers(testTime); - - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, HttpMethod.POST, 1, function (error, _body, response) { - t.like(response, { stm: testTime.toString() }); - t.end(error); - }); - e.input({ a: 'b' }); - - clock.restore(); -}); - -test.cb('Emitter should add STM querystring parameter when sending GET requests', (t) => { +test('preparePayload should add "stm" property', (t) => { const testTime = new Date('2020-06-15T09:12:30.000Z').getTime(); const clock = sinon.useFakeTimers(testTime); + + const payload: PayloadDictionary = { a: '1'} - const e = emitter(endpoint, HttpProtocol.HTTPS, 443, HttpMethod.GET, undefined, function (error, _body, response) { - t.regex(response, new RegExp(`/i?.*stm=${testTime}.*`)); - t.end(error); - }); - e.input({ a: 'b' }); + const result = preparePayload(payload); + + t.deepEqual(result, { a: '1', stm: testTime.toString()}); clock.restore(); -}); +}); \ No newline at end of file diff --git a/test/got_emitter.ts b/test/got_emitter.ts new file mode 100644 index 0000000..bfe4fb4 --- /dev/null +++ b/test/got_emitter.ts @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2014-2015 Snowplow Analytics Ltd. All rights reserved. + * + * This program is licensed to you under the Apache License Version 2.0, + * and you may not use this file except in compliance with the Apache License Version 2.0. + * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the Apache License Version 2.0 is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. + */ + +import test from 'ava'; +import sinon from 'sinon'; +import nock from 'nock'; +import { HttpMethod, HttpProtocol, gotEmitter } from '../src/index'; + +const endpoint = 'd3rkrsqld9gmqf.cloudfront.net'; + +nock(new RegExp('https*://' + endpoint)) + .persist() + .filteringPath(() => '/') + .get('/') + .reply(200, (uri) => uri); + +nock(new RegExp('https*://' + endpoint)) + .matchHeader('content-type', 'application/json; charset=utf-8') + .persist() + .filteringRequestBody(() => '*') + .post('/com.snowplowanalytics.snowplow/tp2', '*') + .reply(200, (_uri, body: Record) => (body['data'] as Array)[0]); + +test.before(() => { + nock.disableNetConnect(); +}); + +test.after(() => { + nock.cleanAll(); +}); + +test.cb('gotEmitter should send an HTTP GET request', (t) => { + const e = gotEmitter(endpoint, HttpProtocol.HTTP, 80, HttpMethod.GET, undefined, undefined, undefined, function ( + error, + response + ) { + t.regex(response?.body as string, /\/i\?.*a=b.*/); + t.end(error); + }); + e.input({ a: 'b' }); +}); + +test.cb('gotEmitter should send an HTTP POST request', (t) => { + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, HttpMethod.POST, 1, undefined, undefined, function ( + error, + response + ) { + t.like(JSON.parse(response?.body as string), { a: 'b' }); + t.end(error); + }); + e.input({ a: 'b' }); +}); + +test.cb('gotEmitter should send an HTTPS GET request', (t) => { + const e = gotEmitter(endpoint, HttpProtocol.HTTPS, 443, HttpMethod.GET, undefined, undefined, undefined, function ( + error, + response + ) { + t.regex(response?.body as string, /\/i\?.*a=b.*/); + t.end(error); + }); + e.input({ a: 'b' }); +}); + +test.cb('gotEmitter should send an HTTPS POST request', (t) => { + const e = gotEmitter(endpoint, HttpProtocol.HTTPS, undefined, HttpMethod.POST, 1, undefined, undefined, function ( + error, + response + ) { + t.like(JSON.parse(response?.body as string), { a: 'b' }); + t.end(error); + }); + e.input({ a: 'b' }); +}); + +test.cb('gotEmitter should not send requests if the buffer is not full', (t) => { + const e = gotEmitter(endpoint, HttpProtocol.HTTPS, undefined, HttpMethod.POST, undefined, undefined, undefined, () => + t.fail('Event unexpectedly emitted') + ); + e.input({}); + e.input({}); + e.input({}); + setTimeout(t.end, 250); //Give chance for emitter callback to fire +}); + +test.cb('gotEmitter should not send requests if the buffer is empty', (t) => { + const e = gotEmitter(endpoint, HttpProtocol.HTTPS, undefined, HttpMethod.POST, undefined, undefined, undefined, () => + t.fail('Event unexpectedly emitted') + ); + e.flush(); + setTimeout(t.end, 250); //Give chance for emitter callback to fire +}); + +test.cb('gotEmitter should add STM querystring parameter when sending POST requests', (t) => { + const testTime = new Date('1988-12-12T12:30:00.000Z').getTime(); + const clock = sinon.useFakeTimers(testTime); + + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, HttpMethod.POST, 1, undefined, undefined, function ( + error, + response + ) { + t.like(JSON.parse(response?.body as string), { stm: testTime.toString() }); + t.end(error); + }); + e.input({ a: 'b' }); + + clock.restore(); +}); + +test.cb('gotEmitter should add STM querystring parameter when sending GET requests', (t) => { + const testTime = new Date('2020-06-15T09:12:30.000Z').getTime(); + const clock = sinon.useFakeTimers(testTime); + + const e = gotEmitter(endpoint, HttpProtocol.HTTPS, 443, HttpMethod.GET, undefined, undefined, undefined, function ( + error, + response + ) { + t.regex(response?.body as string, new RegExp(`/i?.*stm=${testTime}.*`)); + t.end(error); + }); + e.input({ a: 'b' }); + + clock.restore(); +}); + +test.cb('gotEmitter should handle undefined callbacks on success situation', (t) => { + t.notThrows(() => { + const e = gotEmitter(endpoint, HttpProtocol.HTTPS, 443, HttpMethod.GET, undefined, undefined, undefined, undefined); + e.input({ a: 'b' }); + }); + t.end(); +}); + +test.cb('gotEmitter should handle undefined callbacks on failure situation', (t) => { + t.notThrows(() => { + const e = gotEmitter('invalid-url', HttpProtocol.HTTPS, 443, HttpMethod.POST, 1, undefined, undefined, undefined); + e.input({ a: 'b' }); + }); + t.end(); +}); + +test.cb('gotEmitter should catch error in success situation', (t) => { + t.notThrows(() => { + const e = gotEmitter( + endpoint, + HttpProtocol.HTTPS, + 443, + HttpMethod.GET, + undefined, + undefined, + undefined, + function () { + throw new Error('test error'); + } + ); + e.input({ a: 'b' }); + }); + t.end(); +}); + +test.cb('gotEmitter should catch error in error situation', (t) => { + t.notThrows(() => { + const e = gotEmitter('invalid-url', HttpProtocol.HTTPS, 443, HttpMethod.POST, 1, undefined, undefined, function () { + throw new Error('test error'); + }); + e.input({ a: 'b' }); + }); + t.end(); +}); + +test.cb('gotEmitter should pass response in success situation', (t) => { + const e = gotEmitter(endpoint, HttpProtocol.HTTPS, 443, HttpMethod.GET, undefined, undefined, undefined, function ( + error, + response + ) { + t.falsy(error); + t.truthy(response); + t.end(); + }); + e.input({ a: 'b' }); +}); + +test.cb('gotEmitter should pass error in error situation', (t) => { + const e = gotEmitter('invalid-url', HttpProtocol.HTTPS, 443, HttpMethod.POST, 1, undefined, undefined, function ( + error, + response + ) { + t.truthy(error); + t.falsy(response); + t.end(); + }); + e.input({ a: 'b' }); +}); diff --git a/test/tracker.ts b/test/tracker.ts index c82c8da..169800d 100644 --- a/test/tracker.ts +++ b/test/tracker.ts @@ -14,9 +14,9 @@ import test, { ExecutionContext } from 'ava'; import nock from 'nock'; import querystring from 'querystring'; -import { tracker, emitter, version } from '../src/index'; import { PayloadDictionary } from 'snowplow-tracker-core'; -import { HttpMethod, HttpProtocol } from '../src/emitter'; + +import { tracker, gotEmitter, version, HttpMethod, HttpProtocol } from '../src/index'; const testMethods = [HttpMethod.GET, HttpMethod.POST]; @@ -36,40 +36,27 @@ const completedContext = JSON.stringify({ data: context, }); -nock('http://' + endpoint, { - filteringScope: function () { - return true; - }, -}) +nock(new RegExp('https*://' + endpoint)) .persist() - .filteringPath(function () { - return '/'; - }) + .filteringPath(() => '/') .get('/') - .reply(200, function (uri) { - return querystring.parse(uri.slice(3)); - }); + .reply(200, (uri) => querystring.parse(uri.slice(3))); -nock('http://' + endpoint, { - filteringScope: function () { - return true; - }, -}) +nock(new RegExp('https*://' + endpoint)) .matchHeader('content-type', 'application/json; charset=utf-8') .persist() - .filteringRequestBody(function () { - return '*'; - }) + .filteringRequestBody(() => '*') .post('/com.snowplowanalytics.snowplow/tp2', '*') - .reply(200, function (_uri, body) { - return body; - }); + .reply(200, (_uri, body) => body); + +function extractPayload(response?: string, method?: string): PayloadDictionary { + if (!response) return {}; -function extractPayload(response: unknown, method: string): PayloadDictionary { + const parsed = JSON.parse(response); if (method === 'get') { - return JSON.parse(response as string); + return parsed; } else { - return ((response as Record)['data'] as Array)[0] as PayloadDictionary; + return (parsed['data'] as Array)[0] as PayloadDictionary; } } @@ -101,8 +88,11 @@ for (const method of testMethods) { refr: 'google', }; - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, function (error, _body, response) { - checkPayload(extractPayload(response, method), expected, t); + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, undefined, undefined, function ( + error, + response + ) { + checkPayload(extractPayload(response?.body, method), expected, t); t.end(error); }); @@ -123,8 +113,11 @@ for (const method of testMethods) { se_va: '15', }; - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, function (error, _body, response) { - checkPayload(extractPayload(response, method), expected, t); + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, undefined, undefined, function ( + error, + response + ) { + checkPayload(extractPayload(response?.body, method), expected, t); t.end(error); }); @@ -132,43 +125,32 @@ for (const method of testMethods) { track.trackStructEvent('clothes', 'add_to_basket', 'jumper', 'red', 15, context); }); - test.cb( - method + ' method: trackEcommerceTransactionWithItems should track an ecommerce transaction', - (t) => { - const expectedTransaction = { - e: 'tr', - tr_id: 'order-7', - tr_af: 'affiliate', - tr_tt: '15', - tr_tx: '5', - tr_sh: '0', - tr_ci: 'Dover', - tr_st: 'Delaware', - tr_co: 'US', - tr_cu: 'GBP', - }; + test.cb(method + ' method: trackEcommerceTransactionWithItems should track an ecommerce transaction', (t) => { + const expectedTransaction = { + e: 'tr', + tr_id: 'order-7', + tr_af: 'affiliate', + tr_tt: '15', + tr_tx: '5', + tr_sh: '0', + tr_ci: 'Dover', + tr_st: 'Delaware', + tr_co: 'US', + tr_cu: 'GBP', + }; - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, function (error, _body, response) { - const payloadDict = extractPayload(response, method); - checkPayload(payloadDict, expectedTransaction, t); - t.end(error); - }); + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, undefined, undefined, function ( + error, + response + ) { + const payloadDict = extractPayload(response?.body, method); + checkPayload(payloadDict, expectedTransaction, t); + t.end(error); + }); - const track = tracker(e, 'cf', 'cfe35', false); - track.trackEcommerceTransaction( - 'order-7', - 'affiliate', - '15', - '5', - '0', - 'Dover', - 'Delaware', - 'US', - 'GBP', - context - ); - } - ); + const track = tracker(e, 'cf', 'cfe35', false); + track.trackEcommerceTransaction('order-7', 'affiliate', '15', '5', '0', 'Dover', 'Delaware', 'US', 'GBP', context); + }); test.cb( method + ' method: trackEcommerceTransactionWithItems should track an ecommerce transaction and items', @@ -207,8 +189,11 @@ for (const method of testMethods) { let requestCount = items.length + 1; - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, function (error, _body, response) { - const payloadDict = extractPayload(response, method); + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, undefined, undefined, function ( + error, + response + ) { + const payloadDict = extractPayload(response?.body, method); const expected = payloadDict['e'] === 'tr' ? expectedTransaction : expectedItem; checkPayload(payloadDict, expected, t); @@ -237,11 +222,12 @@ for (const method of testMethods) { ); test.cb( - method + ' method: trackEcommerceTransactionWithItems with no items should track an ecommerce transaction and no items events', + method + + ' method: trackEcommerceTransactionWithItems with no items should track an ecommerce transaction and no items events', (t) => { t.plan(1); - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, function (error) { + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, undefined, undefined, function (error) { t.pass(); t.end(error); }); @@ -281,8 +267,11 @@ for (const method of testMethods) { }), }; - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, function (error, _body, response) { - checkPayload(extractPayload(response, method), expected, t); + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, undefined, undefined, function ( + error, + response + ) { + checkPayload(extractPayload(response?.body, method), expected, t); t.end(error); }); @@ -308,8 +297,11 @@ for (const method of testMethods) { }), }; - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, function (error, _body, response) { - checkPayload(extractPayload(response, method), expected, t); + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, undefined, undefined, function ( + error, + response + ) { + checkPayload(extractPayload(response?.body, method), expected, t); t.end(error); }); @@ -335,8 +327,11 @@ for (const method of testMethods) { dtm: '1000000000000', }; - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, function (error, _body, response) { - checkPayload(extractPayload(response, method), expected, t); + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, undefined, undefined, function ( + error, + response + ) { + checkPayload(extractPayload(response?.body, method), expected, t); t.end(error); }); @@ -360,8 +355,11 @@ for (const method of testMethods) { }, }; - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, function (error, _body, response) { - const pd = extractPayload(response, method); + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, undefined, undefined, function ( + error, + response + ) { + const pd = extractPayload(response?.body, method); t.is( pd['ue_px'], 'eyJzY2hlbWEiOiJpZ2x1OmNvbS5zbm93cGxvd2FuYWx5dGljcy5zbm93cGxvdy91bnN0cnVjdF9ldmVudC9qc29uc2NoZW1hLzEtMC0wIiwiZGF0YSI6eyJzY2hlbWEiOiJpZ2x1OmNvbS5hY21lL3ZpZXdlZF9wcm9kdWN0L2pzb25zY2hlbWEvMS0wLTAiLCJkYXRhIjp7InByaWNlIjoyMH19fQ' @@ -390,8 +388,11 @@ for (const method of testMethods) { }; let count = 2; - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, function (error, _body, response) { - checkPayload(extractPayload(response, method), expected, t); + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, undefined, undefined, function ( + error, + response + ) { + checkPayload(extractPayload(response?.body, method), expected, t); count--; if (count === 0) { t.end(error); @@ -402,14 +403,16 @@ for (const method of testMethods) { track.trackPageView('http://www.example.com', 'example page', 'google', context); }); - test.cb(method + ' method: setDomainUserId should attach a duid property to event', (t) => { const expected = { - duid: 'duid-test-1234' + duid: 'duid-test-1234', }; - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, function (error, _body, response) { - checkPayload(extractPayload(response, method), expected, t); + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, undefined, undefined, function ( + error, + response + ) { + checkPayload(extractPayload(response?.body, method), expected, t); t.end(error); }); @@ -420,11 +423,14 @@ for (const method of testMethods) { test.cb(method + ' method: setNetworkUserID should attach a nuid property to event', (t) => { const expected = { - nuid: 'nuid-test-1234' + nuid: 'nuid-test-1234', }; - const e = emitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, function (error, _body, response) { - checkPayload(extractPayload(response, method), expected, t); + const e = gotEmitter(endpoint, HttpProtocol.HTTP, undefined, method, 0, undefined, undefined, function ( + error, + response + ) { + checkPayload(extractPayload(response?.body, method), expected, t); t.end(error); });