From e248db81cd681366c0654f30a2b0f664e1e30a5c Mon Sep 17 00:00:00 2001 From: StephanGerbeth Date: Thu, 24 Oct 2024 09:33:15 +0200 Subject: [PATCH 1/7] fix(fetch): added fetch operators --- .gitignore | 5 +- .nvmrc | 2 +- eslint.config.js | 3 +- package-lock.json | 536 ++++++++++++++++++ packages/observables/.releaserc | 10 +- packages/observables/src/fetch/request.http | 9 - packages/observables/src/fetch/request.js | 8 - .../operators/fixtures/images/test_image.jpg | Bin 0 -> 481980 bytes packages/operators/package.json | 3 + .../operators/src/fetch/autoPagination.js | 21 + .../src/fetch/autoPagination.test.js | 42 ++ .../operators/src/fetch/concurrentDownload.js | 7 + .../src/fetch/concurrentDownload.test.js | 40 ++ packages/operators/src/fetch/download.js | 18 + .../src/fetch/download.test.js} | 21 +- .../operators/src/fetch/lazyPagination.js | 15 + .../src/fetch/lazyPagination.test.js | 50 ++ packages/operators/src/fetch/polling.js | 20 + packages/operators/src/fetch/polling.test.js | 29 + packages/operators/src/fetch/request.http | 20 + packages/operators/src/fetch/request.js | 11 + packages/operators/src/fetch/request.test.js | 37 ++ packages/operators/src/fetch/resolve.js | 17 + .../operators/src/{request => fetch}/retry.js | 2 +- .../src/{request => fetch}/retry.test.js | 10 +- packages/operators/src/fetch/upload.js | 7 + packages/operators/src/fetch/upload.test.js | 49 ++ packages/operators/src/log.js | 26 + packages/operators/vitest.config.js | 1 + setup.js | 17 + 30 files changed, 988 insertions(+), 48 deletions(-) delete mode 100644 packages/observables/src/fetch/request.http delete mode 100644 packages/observables/src/fetch/request.js create mode 100644 packages/operators/fixtures/images/test_image.jpg create mode 100644 packages/operators/src/fetch/autoPagination.js create mode 100644 packages/operators/src/fetch/autoPagination.test.js create mode 100644 packages/operators/src/fetch/concurrentDownload.js create mode 100644 packages/operators/src/fetch/concurrentDownload.test.js create mode 100644 packages/operators/src/fetch/download.js rename packages/{observables/src/fetch/request.test.js => operators/src/fetch/download.test.js} (53%) create mode 100644 packages/operators/src/fetch/lazyPagination.js create mode 100644 packages/operators/src/fetch/lazyPagination.test.js create mode 100644 packages/operators/src/fetch/polling.js create mode 100644 packages/operators/src/fetch/polling.test.js create mode 100644 packages/operators/src/fetch/request.http create mode 100644 packages/operators/src/fetch/request.js create mode 100644 packages/operators/src/fetch/request.test.js create mode 100644 packages/operators/src/fetch/resolve.js rename packages/operators/src/{request => fetch}/retry.js (96%) rename packages/operators/src/{request => fetch}/retry.test.js (79%) create mode 100644 packages/operators/src/fetch/upload.js create mode 100644 packages/operators/src/fetch/upload.test.js create mode 100644 packages/operators/src/log.js create mode 100644 setup.js diff --git a/.gitignore b/.gitignore index bb1dae1..2545672 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ node_modules -/.env -/.DS_Store +.env +.DS_Store + /coverage /.github_old diff --git a/.nvmrc b/.nvmrc index b009dfb..2bf5ad0 100755 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -lts/* +stable diff --git a/eslint.config.js b/eslint.config.js index bbb9706..4bdceec 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -23,7 +23,8 @@ export default [ languageOptions: { globals: { ...globals.browser, - expect: 'readonly' + expect: 'readonly', + global: 'readonly' } }, plugins: { diff --git a/package-lock.json b/package-lock.json index 8a1bf61..18766a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2820,6 +2820,15 @@ "node": ">=12" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3317,6 +3326,21 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "12.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", @@ -3561,6 +3585,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cssstyle": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "rrweb-cssom": "^0.7.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/dargs": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", @@ -3574,6 +3613,44 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/data-urls/node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=18" + } + }, "node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", @@ -3592,6 +3669,15 @@ } } }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/deep-eql": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", @@ -3689,6 +3775,18 @@ "node": ">=8" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -4669,6 +4767,30 @@ "reusify": "^1.0.4" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/fetch-mock": { "version": "11.1.3", "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-11.1.3.tgz", @@ -4842,6 +4964,36 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -5248,6 +5400,21 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -5309,6 +5476,21 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -5562,6 +5744,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -5749,6 +5940,76 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdom": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "cssstyle": "^4.1.0", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/parse5": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.0.tgz", + "integrity": "sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/jsdom/node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=18" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -6440,6 +6701,33 @@ "node": ">=16" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -6562,6 +6850,26 @@ "dev": true, "license": "MIT" }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-emoji": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", @@ -6578,6 +6886,25 @@ "node": ">=18" } }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/normalize-package-data": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", @@ -9161,6 +9488,15 @@ "inBundle": true, "license": "ISC" }, + "node_modules/nwsapi": { + "version": "2.2.13", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", + "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -10146,6 +10482,15 @@ "fsevents": "~2.3.2" } }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -10196,6 +10541,30 @@ "regexp-tree": "~0.1.1" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "optional": true, + "peer": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/semantic-release": { "version": "24.1.1", "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.1.1.tgz", @@ -11239,6 +11608,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/synckit": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", @@ -11473,6 +11851,30 @@ "node": ">=14.0.0" } }, + "node_modules/tldts": { + "version": "6.1.53", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.53.tgz", + "integrity": "sha512-4uCStuOjPFaY2/LUjTSwdnJTC82W/gvSFL6FoTC9ehNOHboA9cyO3wX1erh2yGofVls37OdXr5sQLEfL5hS1TA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tldts-core": "^6.1.53" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.53", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.53.tgz", + "integrity": "sha512-IleS872aGdTB/UtocD2dSZBnQi/nqMIZxxezVgfcKKjw6+G2hJGzFw9buIDJO2MVJyEJe3rCAdyMTl2yvGMMrQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -11496,6 +11898,36 @@ "node": ">=8.0" } }, + "node_modules/tough-cookie": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "peer": true, + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/traverse": { "version": "0.6.8", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.8.tgz", @@ -11831,6 +12263,31 @@ } } }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", @@ -11841,6 +12298,21 @@ "node": ">=12" } }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/whatwg-mimetype": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", @@ -11851,6 +12323,22 @@ "node": ">=12" } }, + "node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -12042,6 +12530,51 @@ "dev": true, "license": "ISC" }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -12178,6 +12711,9 @@ "dependencies": { "@rxjs-collection/observables": "*", "rxjs": "7.8.1" + }, + "devDependencies": { + "node-fetch": "^3.3.2" } } } diff --git a/packages/observables/.releaserc b/packages/observables/.releaserc index a90e7ef..fc40687 100644 --- a/packages/observables/.releaserc +++ b/packages/observables/.releaserc @@ -39,15 +39,7 @@ } ], [ - "@semantic-release/github", - { - "assets": [ - { - "path": "./packages/observables/", - "label": "observables" - } - ] - } + "@semantic-release/github" ] ], "extends": "semantic-release-monorepo" diff --git a/packages/observables/src/fetch/request.http b/packages/observables/src/fetch/request.http deleted file mode 100644 index 286a6eb..0000000 --- a/packages/observables/src/fetch/request.http +++ /dev/null @@ -1,9 +0,0 @@ - -# @name post -GET https://dummyjson.com/posts/1 HTTP/1.1 -content-type: application/json - -### -@userId = {{post.response.body.userId}} -GET https://dummyjson.com/users/{{userId}} HTTP/1.1 -content-type: application/json diff --git a/packages/observables/src/fetch/request.js b/packages/observables/src/fetch/request.js deleted file mode 100644 index 95598a9..0000000 --- a/packages/observables/src/fetch/request.js +++ /dev/null @@ -1,8 +0,0 @@ -import { fromFetch } from 'rxjs/fetch'; - -export const requestObservable = request => { - return fromFetch(request) - .pipe - // add operators for default behaviour - (); -}; diff --git a/packages/operators/fixtures/images/test_image.jpg b/packages/operators/fixtures/images/test_image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2127b4065565f10a922e1d7d6054249175e61ede GIT binary patch literal 481980 zcmeEv2|SeTyZZ#n1uO`pa+_dIhy_j29W^}Uw+dMN#raURDL!EP5J z$iM(P06`Ev!~o-f;GhHp|DbD_O=`n7kIe##iM>y(b34g`b2KrQG!g$ywtyL8FZ*}&eU4!Uo zXlQ9@=xAwa>FMa`8QGZ_85kJ3*w~oacXRXc@pAL>@(YQJ@C%9x^78JH-Xkg@dEmeS zK7_1-%zg#&{RbprboBI$42+yiOq`MeyaJN{;TNR|mIG#j26S?}pMQD5sNmEzv~=_g zj7%^H{>yj2ef?Ko?t-Xba5xn;oQ8%POcN{|dz^F*sD_iAGV|(8L72_EA% zjba1x-N@S>bEt~Q0lKXo(2-ygdf?fRtv)G7r#+$=EcMD30_Q%A8L}PBMfeO&7jLW# zKJXz`kRJKth|UxUJ?l!9nYq?*1fJ^YCRojZ;kLOE7<4z1p8!K@#GS%&h}wtK7&t@&(*BoZ*o=RzG7tbO+-+$Hm=BS#)FTr5c^m$8kJ9P{DF@YEw1pOMT0<^$(dl6; zznrXbab4(25=~$Fcq?Ljfz@La-E)fq@sVhP4IAPQ3CmYydOuEeh&x>nOPzcT_TlPs zqNc|PgIIFNzDPxZWkivKI|W)S~8fhoc^E8_{rDNvr( zdW3S@ENb8ptwsMwnwCx<@)N+1K1Sq{3igydSO^jgM;imOyhk!57+VZB#wV_Q_a~$f z4_?`3K)r~P;h$|7j;CysnI`p|GtSC(E&g@_1(N0kl=S&ZnnkP%F9Hyfxm+G$?F`P= zxq<@ez6QHx1oe(Q#arxr&)>(F{1iF$W(!rV$?-AGcCeAOH*6E|MQPq4(i^W*3zTd2 zTKugkFqkN?8|J#z({ZmrBiR~Yt=j_tojN@5#Mur?kc20XpfCj z`7mrvpOYMTLnr@&U~{h8ZG~0g?Dtj}>=%Ap64M51gM?~$Ew`(ps^90!VP`X|lYKIh zBD;36C*)$@h4et7-w=S#GZM21^awCLUPdhl%QLgB-1TEnqb*XKw+R0 z>s@A!Hr`Cq4Pzc8M>YX{o1*1;$M{@kXE|pJ8>H`O`wG?IH)*YA6Y0j}2|$%@dBjzp zPc@@#>njwf7MU5?(;eUNrP&x)kvck(c<_iUBjX2TJg1kd{y4+4@QHbOdOFsVt*9rqf47t*lolyD>9#KPz2o2!i{y5KIqHdFwi0S8ih!yzsMMERRdGI`j2kxX3qi=)4Iv{?@f=h{GAupb z=4C8^m+c3iUn+;v;fu2G=C zNb!tmxkWpTM!>RXE@xpDjl5nukUt}5l}WalU#=i<&$|Hwe?i-d>@6m~ZCNCDC=UYZ z&!KF!j@k@L1S2Wa6hcN_HjsKxRakmV7A7I9ZDQ)tj-U$w$Q&VDc~Ffnd^n zTTEn0CwhFUWw+KtHd*txR@w%Ck&o}?zel+T0CeUk~er1dtY|Sc{o>8G-z+Fhp^;BuzwQnfd$Sc zT8DE_`f#{!WCY#3Oo*QoE0_0Zbr5m%l=I#zguJHa`29j{(U>7~{RGU5=MGgPspR>w zS3E80f`MQQYg(gKp_TQO)3YDiU0jm<4g-u5U&MwtzmgZ~!A2OTK=?OnGRS%xp)?_( z>{BtfR!^1+R(+&9v-TZHjrTj|V0-G?W_oEevFd=R1D)+zN%$x9xWjxkV5nAzUw#fI zEv9iop)S_2jsiUc()GPrQ23Y+%ZYq_emD671}<3IT=eqUpZv> zTZ#!@n_YC=6o@IlDSNdAFn;vUANScXmsR!DARf7^D3Hmkrz^7zZfPwAr{1Q$;?x(1 zYIujuBf;#5Lqw1AlD+`-gUy2tpBBd}DsI|e7l+fwK_-HM5aT9lJ)MP^OhkUfAxk|_ z2Z^ZGb-4vK#O5?+W1#qGAuPEtc1$HbC>b1Y_+0w*Dnlm)BO_irzeGFz3^jgRF)=3hW|)EfEW! zS=KO))oLOcMYFg&V>yXU@f(OCaagh+#Lnf;kc~PKBbUAAT<`#N`#BxjtK!>{J zUq;XrvAw-sIFmn1g#R4D4H6r{7=|GVrs0E|n=oy@T&5E)GM7FUnB<6js}fWmX7jhz zHbgzS(9|_-ZK2P3>!9A=gH>PoHxUikcDI6%rn-8EOU9=Yl62_nj?7tZtk4fh>K~u< zQ&>`Gdp+x6ey;GG4ZBx}=-2wO{Jv*Xs&TReH?m9jL6z&@Fw@F+2^-79j%rnt5#d30 zE`9Jri7M9zh%G6nie|ppl9{LB5p-l434@Sc^@H>Z#+`v1WsG2 zGgo>quggB{T|xP_A5}WMsJKM?7W>?x!#6iMG(G;1uK&2%rIL=^G92S)&VCAXY?BeM z9I@`-fc&9off_O-@$|4LRkt0MTEl0oIus-n80Y zy@t8}hytO`5GRYXYGog^5^eKY4t=uAZgV2Y22z{f^{u*XUa3piTlVP2siu-4ewI(8 z(Zo>3x|O3G*6z=o<@c7Ki!oA_?c##u&$!<;4m9QTTH-``q1S{C)o}Xv{y}n>`f#x^r8Pdgy}6&p|ArONM6_H$ONoZ)Fs@ILh-P)PL$k zatc5v%D>(WbfN?t(1~mu*O7~7Vd^iC+koQ?AjU?CpXj_-u#ueUjr7ZIl*l8LpGo@( zNKS48l6nA0NW9MhAo2YPNTRk-Xibg|FJ9a$q&FbPl}f{H#jW@AHXivNQ4C-#8{yF0 zzbDxsgU3bhiiT74!eJ&cWfe}Hbt)(`(n)Ge-gruxn8nz#Uh&N_ld}-(1 z{rWWpIuFDo7|?8tbZv`25R*Mf@Hrdz{d40*CG6J`)xfeKp$`4mkK)AdjW#$WjSEU& zQxU4Qr9dVwoy-F47Q>M~8PsoFilChIhHGTFwRW z^fogMEMV8A>+o>uS~8KiDyiRzpEXq&i2pCS?pM^`uI4O<1!MuSj(9_GR$%?_2I7FM`zw>+FL&vx}_p?n~Y-I2L!u4`Hn^y0H0}0i{uf1eLhpG zeqGg3{xrAK`Y0E)MDhJ0GRz1cq^+#_QKb|!c<+&!%b=J9&B@7c>w7D`z=Q(9|K!59 z;FsnFoWDvx&!YZt^$(l*(^^67p7KY8&XA=tOa!aoz5z1oxgj(Qp+UNn5nr1k^ds?4`bJK7d5meYOTD;;dwR!RW(cTod)+jf} zn-|p_^)Eqcx`Ysk;beDcR#quo$v(lc<`~>5$}y~3(20mnTHH*Dc`5U*XZ~Y)7mcft zK-y^%X2ZSw-^08xX+SX^aNI0_0|HI}C|-Qv1!(H#HdW3Oy;8REz?u8f=!)2_>zoxkytu+_U;|HTE#8j@O^8@abIy z(}nC6G7^LMl8nF;k)~vwNO_qs35T38eczAA!>6|82Jf|n6ED6`58I`Z#er4iVwKmH z0cg5&EeDC;crcIdjg(Kkwh+<8+wr<3!*JC07`cNp_)OD~Rig4_B&Mkrz0|u*e8aXi zi%R97K>5+Lm`{-k->~0y-6K9|?=Rzsp8CLhSh(Ru`{SX^;|h1~ZN~Y1KCU-6{LG!y z0#NSvjP7p$M68hU8I*s z`VqN;k0>H0C}W;r)<069Q&2;EL*U-tfK_k#Qxu4U02b>QHZ!q5YO`whsvegP!`O5vvj*}(N?^;Qp`!t2R6063P}(-8ZWqCCe*Oad z2$=h5K+S*fwPPOrA7UP*)no*Q>OH@jM<*o1^t82Y&z?8b(K~$tnBXBu($gN;-nZQj zUf!4e&g*K405h`)-5~Hdu>bT#P}@8DUpjX7?CD>v;J^Qi>;370fPg6vwDtS%|DQGN ze&B|{NPZSv#pUu#*=f7%@Jl&(yBu`+(q(YXt?ja-t3CK0_6U@v{fy6RgYrkR5J-w}fLJptEvIr%$!L68LS$iSGrynMj-k|Lm9((#fX_^sr&A4Y6@?!aI0 z@~?p)H8F54=3nY;3LvPe4-BE=U+TnsAczHchHCErOWo>uXxrxihT5Sns0SK^#-J%^9>PNF5CQNZIv6vI1Ne!AVd5|;m;&rDOapcTrVl$0vw+#b zF2cNE0kAMwG%OC547(3|49kbTg1v^-!CGNmuzuJWY!0>p+XBppiHeI#kV>3NmP&<6 zlj;({vD17Op%>hm|B|p2(=EiF||Fl4|N!I9Q8fw zXVm4?4b-2hG1N=cL>eX(n=*H>R z=;`SN=;i3O=uPR}=_BZq>7UWRq5nibNx#9s%&><+nL(eyjv;^{j^PnQ1w%W-7z2)x znQ<@U5k^BsXT~tbWX9)=b&P$COH4FOLQIF4^qCx)LYY#S3Yi+2hL~2FnVH3y)tOD1 zy_sW~A2YvU?q*(Op=A+aQDre^@n*TflEYHN(#NvG%FHUks>N!}8qAu)TFm-^b()Qe zO_)uU&6LfL?KWE>TPxeQU9erkyVQ1>?+V!^I_ysD(d>`e>)0{u zWDX&Yqa0QoS2!{_syPNYHaYn?k8oOWUg6B(e9Jk+N#qjZ(%`b?y2_Qq)xOuM)2XZ#ZubZ!_=wZnoWrc3bQY-<`X= zb@w74C*NT{8@_9N1$pP?Q2|;383AK~Fo9fwc7atv0YPm+PrOi;9aHiCz^g799~|7E={-6H6Cs7F!n=6E_x* z7B3T@*vGL?YoFh~+U%h|f0OG*; z12G3)ANVdMEOlP$y3`w~CF#A=rqXfJXz4YX{W3N(DKf1xBw0mSH`y%NuX0Rs$K-k9(5h&uM5t7&tRGf5>~*-{@bnSUBX&nJj|{5vsv4^%t9Gif zsOhWSRBJg(d-V9x=%WqlFm+9Jlsa0Stf8S1p;4yDlj zJ?VC`_~g2tn%-5tmQ$>!Oin#GHKBh%-&g{y_<4qGClVlT&skG@8 z(-t!>GY7L*0EwSA&oG~}IBapRp|xz1)~eO7uKwgTc=u2+o;&w zv>CLOwvDjuvfFES*{;Q&&)(A>?ZDyS>`?8<>}cm$?nLi&!KuWV#@W)j_#*X1i;KlB z)Gn4TuUu(eFSwSvF}T^fRl2jdJGs|*aC&%nG3^?1vA$9j+XsQRS% zEMC&R^!O6N*VOlwACuojzj}W`|6u>_%W{|FFV6&M2RsTO23iDG25|;m3i=c*6?`*z zCgem&?iH#lc304$!lB`z!(m6m9)uCXt-{|%2tQ@(cp8ZpK$rt!MO_4w<{vBt5lZwTGEdSm+L>6;~SJaJ)h6Y(eGU*6)n z6?$tT;bcPbZQk1vx2F;f5-XB~l46pU?wH;|Crc*ZN#06vO6j<(a`$m6Q))o!SlX$y zigc0m`1Fl?4);FYSH1r%gCip%+S(Ayq4{ z-CmDZTULL0qyMJqt;XA`8u^-ncVh3dYWZqY(5&d2b<}mJx~=-a`jrN+hPlRzjT23_ zO~dak-uE^eHGgh7)AF(PRBKzCZd>z*6Caw|wc8s$YJIHlIMz}BN$XQXr*>y!*YU3A z&$^#mznuE=vHMJS*H@#jy*=hVL%lY=6MfEobNycZD+2)oTZ5<}_|T1E*5Q;9zLBg^ zvC#sI0;XzAW9GAFf%ZZ6e_sJjMu1rx)#ZPliKb#StDV{w%+c0-}u6N#Ue*SyF zcgjNCBG2OECF!Nt%g2|yuotj%D*->Kek866t`@ARti4}1S|7*x;K&=d@B;XP%_Ey_ zTNYchgkT~)@jhuk=?z(*JWTQ4!2&y2UaJ%qa z;Z4|`&G(YOTA*2QNN5GYDk8V%{9a$tII&Fe;(c!=-b;4v?>{gqH7-3RGbg(&w<=FK zNUg|xh)YR8d9TX8!~2g&tIDX!9FkTT-JU7ffd+*%c^C?Ej#&=ATOmCaTna5g0TSiy~U+}Z`u(@dKXy!g% z+8rr*RVhj{TKAek%(?3(v1T_cZ(fMAj<>mGlVEe(F3~B;^G;~;?UZMCYg2pE7VlBt z=g*LTaN?n5rgv6!cE+R9#~nG}pD;X?c&3x*lz;Vkc0o;H|BJPkY{e3s-(?TmiQKt@P(L9iXa

gDSc>JHW`)*q@@LMzv(yg6KXq(rq)E%#`Kda}k%Buex0F%K;}ZR6uQCywYy=?a}> zIZ4u6I5nu>db+|O=S-4e#97~S&gZR+&KsXH(K0=3CTlKc!Dq>8MP;>qVb*%s=Cf^^ zU6XyIL$hO>Q-|}Hi@h!buETDl?ii0T&vCB_?}}FW9M(o-JFe^j-LWn*zwzAiIYilch*y=@A9Nd zrm3Z$zGrjaCnNGf(!)oYC0PyGJ&)#d;JHFijyyGe=9ia{|NMDl!ARjo5!=gs#cHn% zN-RsA%RI~dDuOG+tD;`VR>!|de4A2}_Aa9~8~v=Vq`t13WE#_?SfyC+4z$xW$E z>&%>+y)fr8@B2M;A!adg>E3cSHg_fGN9Jnk+O72{T+oIm-hR_$>l8tQc#tGc=A$tG zw*HrZXKxXnMr}kRLbFKQOm~moo57IrFcX5Ant6p~inX7uZP$DDT8{u0bxArj z9;2Q`KEIkD^)&j?wTzg%*Arr|-3Y&VInFcQ@s>rx+1n=*wUUr`jwPQ=Id|7O)iupO z9d+;K{gjM{51u|O%B;*nXSY4-eLR!1`Gn=E$g@Lvy7`vRy$Vo;NiQB3mAtGgZhzHX z(qB4QHdx+Y(O3Dk>dWiS>W()b-nP^o{9)OR(EG%hxgnpsnSKb&s2 z`smgX^eMXYc30Zxj4uznAAG&vlh%8;FR4Fa;O1b=P}Fe5Na$!VCU`7#{OUyf zH4LYRE5V)Msqi*9g<6H$kGhz8kw%urm!^t_Osh+Khjx@sitY+sJH0TyKm7*=F@{Kn zQAQ+V4ii1oC8j}U9p(xaah7|mEUYoC6t-|S(k>J`4SNE|ZjPs%N}MfRR$R;6*Le7N zUh(Sje%l?zC(75%?W6p^{ZRU>T&8mGaMTfBRVTFzN6ppE zG%S#|nir4xYN50fkLR9vt<$MHbrOGyPM_;E!a(|rs^RIgw&w!RCmIzPx0=kEF`LU< zm{?x1%DT{CJ!8vir)+QMkl^^vY3br#7Yo-rZXF&ho}ft*EM1*ZXSqxe2Xt3HIXyvZu0Jw?9}~f759$c?|{YIxorj{E`sb6Rue&5;hzOAOcs-vQ_ z;`5vChMumz?}LJXjdqUfOg2qx&o+M7S?s`C{Fqyh!0+CwB$@x@A5=frpA!;<_Cbo! zG3YF05BY;wg$Gax)C!G*I0PP;BJ3>82bKgYh4sRSRAN+TK;*zvs?Ss;xHS9%{5HH1 zzD2DF{QgDMOEmH{0W>wVG_+@FvuGFTH0YA(zR{}!ulxdo9z#AjHtNOL&2*G0pP7gG zI`bxr56d*G9qS02H5+D^)2{FAfgEs-yPOh$PnmM9aNp*U;%Vb`-OaGOknb!Xow?*~E7{xw_C+stl5RjObEZ=|afSHuEG+cU6rbPC- zoTa?10=2^M!AiyCL%vGqm6cTl57Qi8IWngDMXl{W7GhQm<$tj;;R^WjDhjNh4zo6&)FzhD_>RefRJM$p#4F5JGzVZ@2m z`PjuEmtxmB_kA80J@dU5eUvXn`F{16zI-cSCCEDX;}wn2vT&)0XOW^;pF~SsE4r=} zTYFO{?!ztpgtkPTq{d|Jl=rE6Xb>{y4H0hHKblAy|?M|FZtH5HrLLApnv%3{DJNKpqeZ?EV)} z6Eq5Kfz?-n8G|^Jd$1bVI2ApWJe4_BB-L}OFH}Uh1l$-N4X=RDQ6s3$sgtQYX;^6t zX_9IBXoYEAY0Ky!IzzfgbU)~I=pO<^V#rX)$jIoy*vX{Kl*P=*9K<}!V#U(Ms>j;I zc8slI*NI*2?8fY49NwG|=Upx-t|o3fZX!T2H1g`?m16KG2 z!c9a%WNJ_DUOQ2QC`RnD_{Dv)`|tq2rtWt+a8!y*YEimH=8WM*O07y%+dN9tfFs#75yuW{oz!*!5-d{(t@}-n`INH0!|7W9!44Xd z&WW7YHgW^_^{wfgIiJO8%P6b27jQO;w!U^R?dKfDoa~%4FOIkhyE(cSc&vJ9dMEmf z`zre-`Y#0-2i6B43MmSe3M-6|LseeYjQV)ZDrPbE>P_Cbm$!~5^d&kcVUt7dQl}=R zBkq-C=sXzB49@0xRGDM>gz9N=p40O^1=BBHy^MTyzErZDs$#V2U3K=`YwtYJM)m5A zV(;mir(5ejWPH5*>0Fom7tU^c&sbmk!0VysBM&gQ$5E5+Q-(9LbByyd3(ZS;*tj2; z*35C*c!jM!L{2jO_WJ)4g9XF~P*P5xI4+{?=I!idFLK6@2l0Eqee z`QiZY%-)`7wqxHwEEhEEWPe=$*YYLLpD}Si>z%z#jDD^6b~t1BYx$y|&iP-x&(QGPa(g=xq+4- z+FcNotW1TAyxH6*9l2fe*RRXY!5{_>g0y`uh4{I-xLy|dd7@uhM9Z z-|W{n^fM%0$&7rScO{A)g)c`7e;qj_}$M(f`|l2phnJdjKYkilIQC9q>xv{5jiAX=g}%V z7kgIPahZ6F6^Zd@*<*5?D97-q?k4``DjK4#!{;@UhM|&7dG!Qe+7}(`(yG?84+Zn_ zoPRiEO}alEbK)Nj8Tz9!|G|*&La3$#XzW?^mb5J`8vA%f0&rxIJ>`Z8YV0v;&AgTc zHLg8jNIriSMuB#LqjmLK6lk_2jGqEE#5QFUpXC01x=IS&UIkP=H`?6?FTuNLFo{W^ zKmx?jF&49ijN(YS8YyaF?w)|q2jy=cocr>!XT*E$yA!)-Nvb}bOm)hXNHU~>0!`$A z9z!Tk)Q}5q9zR7mLzKp+V7m>myf@J$we@ZjERI%DWVsU8t%z)ijI_ZEE6nX~qOt>4 z-z3kl8iz6b@t7aM|8UTM50bq5N6P~!?04&P?(f#sh<9KPxzS^BmFh5dW1W%YA-YpN$)P(8B*p;u)mK4>ac>Bx4k%lQ9`d+fZ*PYAnqQD~3GjQX7Qqo}>Iu^Gn$Q*WBq}isR)9A$!P0ER*hM$Id0FfqnC|bcYBKn? zXf)F^N+#{#bGxakgJDlNH0e4i5Z2fhFT%E%Nbn?&*b1WEFfrL25&UjssudNSO25p} zV=p`|*}ligAPl>|t)3s!&)Rd}OU!vlDlCSf{zKx`e>yS#bEQsk9~vwGk=+XS3@~}$ zh_9pSc+3jAr55T5+h2gEA~d`@Hg0WZR{d7Lx_s{D$spoM#Y$ z&wy+=2jqym=x{BhN|bl;ZQJtYhR&NvmO~(YLGS~DzyeQ}NUzdsxd{SKV&2@3kmp`c zJ9mAoOg^}nTB~(!Y)ZE-`%mJEzY`(;Q{|1>cMO<*GJO%j2vvU=NNHiB4<0j#f!u4k zdct7gI*n{2r8NB@*v^tHAt-*T?Mr)Jd>a3Pj}QCDX$Rj^rU^ zm0642V9>ZrQ}*=?RAh|-DFMf1xXXion0F;SUblN~^XS*gFEckTTIulxe!%R}y5yHT zX86Am`TW_PEw#Q3W`7&6lAfc-9@V1dIf-A9!UC6;7rvs$t6}3>yuQbvFCR z%>E`s%+iW&gwM zx;rWZ`TXC{PWorfQadWcj>@p3GVG`f;{QE;bUP};j>@p(W%%ja-tjX0odPZXw3_|@ zk(U9)DzEIaC34S@Z%=}J+j2DEi9H30_#1L$M&K#Y^#xhHd85FCb4-A`a2y1<(1d`8 za=ZpvshR3g#DZM%UJwcsRRe-#hEY>7V`#F;wtJi%v{G+_nq5NvXu#T1paX>)0>I<4 z9ic*c^V8&ym@sVU91NPwCW?(xb(8tsg+sM7Lc{P7xvP@HXr ztEKZdOl{4pw4f37rq0z?--pbSP=qV0=@<%Ymc6BxNPJZT#`B>7_;5wgc&Sd3Pz%}I z1`KD)1o8VR0j`DL&x!6IObLk6_}!cU^#8jl$=?pA05dyQj9d#sY}yBdbmytYf79;S zzQzETJ8(BH_5pt{2n*tf-~oAIm7_tsEC_!KvH;o}hlTx3e8pOxr zF{PwJt!}w}r1hz5Wwmol`%qchx5n%>;j7xepOQZ$6Ogz3_frBwh5qf5{eHy&sQLR- z@t^G;2}DOkf#n6UC*Eif0@MP6f672G7V!Nts6>{7r@Lgt-jI<-j`Ly3nNzm!3tW5K zpbMN4LS+2Gto%#@xZb9PpYH0F^hrS*?=4MZU=sRQAmJg6+jC3mX!bUVcFj%o$56ga;(g;g! zJr8NPf~ju&$!Kzsr7hc&e-qD!Mc{6d8}KHNQFau_+07PvGuUBc0qx#Z-rj}|53!eC zeiM2#dnRe}@b0q^5#;p$-$2KIZkwTf(ICPK1eOdHgV>%DvKUbsgjpQ{k$MJWGRW~~ zk0+S)+3-4H$h;7<755CKQvK;U+}Tt8aZBTY>HAl|z0?9ud0irpz%P7;kCcWS%SDzO z)}bOPP`M$Fx1orMKu3@Q`S-8sH}ayL38pd6YzzqB+ZkNKyN6Fxprf&Tbq$ep)3N`( z+3}yH;y*1dOb7|vUUWdOIph%(i1|ze(Vi}gYAc;&4j&je_{5^bw#(8S)u1>|Qu~08 zH~w6dY^!2e8fDsK7Q|FuZI~_Y#}&zzf!r3UfYnHLE|dUH&qvCMfD`G!)A?T2a=Y60 zBL^(ahH0nsC|tcK8!57lb_Y=P2cG4lDjFL;f3guXxx8 z1W|z~65MwX!{dp%iDW{$VQ!h8fZ81q#>}k@TfCCiYIywc{rtabT2$gE#V$%Sd=xIX}b_30-sLY7N>yI z0O%;aJ@KyDfX9FhSHyI>=D|i^8pkI>-s}715LU&j zF%VnF9|6Jt5;*=RQSlCT|D8IsgWY$q`wn*hbNu*kty=70_djJx`P&MM9qj&lv%x<` zLEgdc{~R582fG8s<6qfu{{f(92fP1`HP9XGzJuL&?C$^8EwE#E{~J4y{;a8I2fOcJ z_kTR9_*-kBJ9hU!3oHJ%O6Z?<3;h3s-I07dDeZO=_x+MEa3@>WPPVR{Y+e6OLd~5` zva?BcHp#!UNp=$V?IiB|Po@mrA)Ou4`M>6T1nvZyt&(?NL1;FrA|gA_qTM%KD%g7O zb^3u(9gW?eFFn>3BT0=fQ=#fLD3EvJ&1Cc9s}u;N>%OUi9d`Wi#*o&%WU%V7%E6`* zNebllkP#y2HlVPYKKKL6@v<_;(085sdda{H9Bqvp zdz{fXFx6KRghlIIy|HRK)5QN`RR=jz)tw1)>0M1Mg2Fw<(fC8?78TQ1Z4;Ow|5K$k zhgbJ@*D$G1$h{Oc&|xM^O3h`{ftcNVL|H;YjRy#ZA1rJhOzm6INPIe%;hv3W{vN11 zqba;Ro{d+QA~RHs^J(-=6bpsv^g0MR_S6_Y8+yMvXx@OqlL9SciR?yXdJF8*$jhTa zId1Y+O~?@0>J>-ha;Do0W@m3OLd_sX)CGZ8jvwz_S`0ge<+zwwFmKB_)+;az` zP1BNq9vfU{dO6^Ua^W*U&SYJEg30a>Ny-2b<7h8Ays}mO#wp}DCteQs1Sy??s%LoF zid_G~BGmHTT0NG?-A-oN#12QCxf(vs6nw?26t7sQg_K)(`iKRb1CAO%)w9@BAhQWC ziK)4&@iQ-wa`<$!0c43Bkqbp;7$?{gP5a1vsKIA*xFXAP()SD!(PcE(RF3vI}@_>v&L6=o71m_yaP#^;h?)fG%YG4hf^_|Ql z00JDjdbuC>RCKbmF_BjMv9V@%Kt}cb2^ka5NVTZ3K|}sgIb79sGRLs33bEoVnZ`zr zeB!~0LF94)w6G8%gQ~Bv*=OCmWw@}+QAOOq+B|UF(s$$I>M$EOBnq5c;o!Oc-Gr1S z(`$q5BHHJw@%W+CJ6ATr0)kPJ305(l;;g_h4)Oz;gzIt$KFI4;)yBc{>i8Th)_c`cV5rBAO(yrXW~qX2`xwJfh) z*E+ANy4)zDvr1rkKPZc-_mQZ&OMx(4u$8_hL%etuk;`n{xzQ5;7AJ>~O%=%Sl4=aH ztavTF>ehZ#n@lJku*EC0)sYWj*@#?0lghD^X!`jK*>W^(fLHI8ifgzOIilfFwcaDC zR%?&gqETaG#hdz_i#`;{uZo<@FB75I1v>$8o&EKVo1_4CSONM+68e@cPN%|$q>c}a z)Bvf^qNC7La>xoa=>ul#mTLvRQv(tHw3q~?M4v!3jxJ2;onmrCl8QkwHp)b3ZFE@AC@AY zUnKx)8ZM$h`OWdRx7PmZp5X4N(xs-XNuN%PYujuj>$(uQZG7CNt?v1iajWs`T)kk}VUr)=SQQi*D+G?i?Aq-T0)cU!9|lFHC)HE-YeZVsKL8x>{;%>h0+mWrWW zaO%~N@yI%`!kQI*uww$l*OF(Yi=X>Ekcu!vS`xBxyxUDu-@$9INZ4Rq7Px(}&4%%x zT~!c++1Q)-WEOu5195LJ9(!LuZ&_Jtq^ojhDn@`N7NR}Yz}BP*BI4K7?= zkJ4AzGHWG+47}0F+sR+E4kfl@DbVd2iE(8z1p=qe-1Y-@{awhzFuMQg9|lZ19S-+Dt!kHrNH;!#1m)Czy8A7{}YmgTm5NI&#liR z7Q;tX&OLl`=ZLA%JmU{Z_^cc=xer~D7&U&ouO1v#p+HRr`+5$aT$yrWh$T zD+dle)?1*)o=_mxAq@nnqE^JV5f*q}GOH*+WCeKDi6crrw=KFpEix;n0pf@|L(4ta$50}fk%+W^s3yR&65{yWqpO+ zB%H;Uk?Er+eFo_!d>YV$KM>I+--onf#4|(nP z8{%~jdm5Pd&<8mdgT$W59<`0^?==Kw*{wEmAPhh-5KsyBVpCTYSvoQ<|KRKaX?KPeqTg%cDu*_jVE;RgH{yl!^ zK5`_E#swK!{B`*%8mooE@5i)gI|eusR7UWQ$Fj)|!pb#OpRZ{wdngKE2-E#tbPI;{ zYMFSar0|rf+nxcCVMalcca4#9jVm`Zd>lkdA1jT4P4Jfs2<3$NWFkT9MRsJ7Jnq!@Ca3)cO6U3~F-ghH4+ z)^fBnBysD8m8Q%$jpYD*-+L4fa%_Pu`i+Ha1P!?@Lag`7Ro{usz;<1x*|4|A-(l89 z%VC@MR~*T#;KWu`6u#fx6vY}QH-@A&*Sq7Ro|WjEkI_`SXf-!F(z;HN-!hvHdT)rA zLK3;sC&e0U`6C7*jwBqRm4Tb6GK&d!u->g)sUk8MKw+X2DBj?*=B{=XjG$b1U}GSdtWnE17j z+3g?-R01A2dLOt667k~cL@qe)iHAVqHB>2Zn>_83rK-6yTINAYe0J1}=oS>=5ND@K zo~_0`VjJ;^1oFzT+1gin-FDClm);eIq+JiWTueV##b2|G2v9N889a;_amb9Q*lHP1 z#P4k(vZvq#K6{0^5j2PA22-?#`pocUlT5)yBX1UY3VJL35^*+sY`u|+L=Rw1m;s#i zctoozk|>g0Hk!Dv%ER-t{!`*XY#0xJ*lFZkQA_{gfZ;~Y!M-V%7B;-<@}x!yE}m_m z4`++T#R&fp{d&}@V8nytO`uQNASuDY=S4E`&_t+(0W)^gSD-H&L>wiRVwx}&7ty)1 zr6taxbWTxL&b}(!1_e#TD>OB7Yz{S~R!`g9G8x-|qz#@tl|a?* z>zc00^Ys6)_wDget^5BYNl{JiQJF4E{mlMOY!HlJ1{QwC!nqG4HB7A05Vh<{zvY zWb;2^lZ@URu+r||xT}Mb ztVgQt`B+F-1+Lw5+h?A#NyWrOoqKD@BgMe(E7oi_&(%NZ9`zI^vx=W@%pVte%pu8^ zHlvE0nVNmNIa1p0SpLn#BF^GV9mcqk7U*J<*dImc|A$KXx3`VI{eS$=30uYJi(dtO zkrCH9%ta(@Jb>hZlbtjmL11I#4u52)yV|Fz6o`a>s^f?m;w;x$UFvi}(sWqrP9#msL zwvdBa1P>z42CIsQt#I3Z@VIex_D;1`^Jk}8?VKISEts~mJDt)e7vbu3y=qWGxE{`} zz9ChqCNvd+7A6P0*I8cF(pXs&;xWE!?}i!UA3XYWW5+P=WV=H58p2t2swS#J!DL*8 zYYk&uJ%np_BkS_@r9-ryS-rS@PyL0Lx(EJMM@=hmHL@+ZjA^dcP4oE7AmV3=yd8A) z*j*RT%Z~;jK%9h@$gTe6zOy?GXJx5%`-DJk*ABawt$cRph>)o*d@bF>?BWBP zvkTo^VSXV@XhAPKX_e;oSi6qpn;cWwBe&{d$`j}4t61o>oIKWT{5vyX)P)n^+_l;8 zU4lpE8jS56 z=!3&@>aDNmzP|uE*LXu*uuBF6e!bm=7sQ_JTHaB#4$ z5=by#vN^ecau(Cb;sq2EB|aKX7;No{K?-G4BN#!?;WU8QB)1%u?<6+u8VXO0b{7IjkZNZX_2Gg>!5&up8*A zH3T&{_m3hvqWPjQm~#mNYtVf*%RQc#%$XeH$g#bCFK0gA1U2oC4Pv$3+1_w^Zrw>y z!Ccs2Q~y?mAK0RGS?`|PbL=FPq13XTiMQn;qX9;LYJc;S?K{ioji zMEYAMZyf{CaF6n6W(UAL|6R0osT+LF^>dfGa`E!7J`UW<%9*5bNnfb%xedPwhh7xL zK%9?+=^sM8@6cb6AH{@+9yHzQQ9ivfs`T<>PKe=)%ky`hYIwCe5wx@Ql?3{kb%<2& z3TU1A`v`TUmJ5l=2)({pHxYKam5}cgvun5RqnkySiyd6z@saV`cONM(cJrK;<8TpQ z1phgpMK4*L6gbVPdx3B0+V+vZ=R>cQ3^_+NCnr?L>aQ8gWSI)?^Gy z*avp(?Y7Sqf-*zy8**B2e%Qk|z=ZYs=cpq=w_}yfH`HJnHV@y2JDt`@r9*yh(d8#@ z;_FAYcUL(wrv|WT=cltKvYhR-%wG4zEmzYld^)b|p7L5l=UH!IZ>MpPzjb)i7LKGn z30P!oQiA9V>!6zorYzlciN9_uZ)rq_uJ*LeIb?b2i8kBo{5utchP;e6dbHW(~Xj~T-)bamIb}Rj9@2hEbuxbHbJ4+M?Ifl3jj|sexHZC-w zQFVQ#QH;xWo$D==nFk*os^85JIEMJ)U}JJh1Uf^H-;!I=nL`lW$MBu>#k`^J3wCh+ z@`|+MWbS3N1C35c*upmvThUDK9HS5D~<3z%v$iW@s$ENOdS4@9t)*Im_W~ zw{=+%j-yq-h2*6*7$i!BIM;@8=}uj?-r8^~{@GLVCLR)68eE`!mza9$2DRS%kd2h) zT@%O9s*#lJ7qFBViT&qr3;$PS{eKFT5`(e-7+`GaPPhwTpU0jTWwG4aD?gL`AnBf^ zZ2wOeN#_kLSeq-BDU=rU5u>Q%exjF6e`he=`tvFw5nSYf9%gh6#F+541f@s>biqSw zd`_*m+v;+GivOXtAuk;Ze7(Xp3M)uzKMCJB%=THm3h;}lfa^@Bh0@3Y(pgqY#M!QF z@?GcV==3*+)8E;2HmRpaV395|!II-JQOa&%%_mEt9h?gy72Z}-9o^i_n8&;j+RV%k z%9!10Ki(-L`*?Zjdlv>4UVZ_8kv9u#!_hT9MCQcbcd@Q3%8cJ_?^3f^^}hT4Sg!+* zFJ)@?v_8_0pLciU0*n~v_b+gMgcx#)6RK1$Ktv(2m4`4D^u${ayrk_FGGc77qc^cr z2h<)*m*2jgQAbR!y>nJr^I1x$1?RqEK2j+x)q=-hb&$+`no_)-X6^mYZiXt={jv{A z{g)VJbX$FBG+^nrI`kR>v^EsX=53%L8s(@WBTpYzVI7zRZ{!Icd0oz#gY1g8F^gT= zx_@rd&$6}~O19X~uc$sG5|qJu{AbqYP`RmEm}=tA~N=0roqSC+35xg8pI8>kGc^olF@x{f^mRFM+AVc6sAC;FZDXXJjICWBeQ zE`<7W!DCU%=XgCzon}jTTJo;JoI`3ROo7|Hm%})GXk5Kt`daB}=@h7-;I;Jg9e=&@ zDR%k)e=fgz67Nh)L=h2$gN5mILu3wrl`Sv%{H&sS5q@iAg~{&s`)}AvEIb+Q8~0dG zw3uGRURoU`~0mvDNkszv_Lr2rCtQo^ymIr2J`2je`o*1W%+ck&{>J((+=&kQ6?KrIuf zD%=3yG%}uA@j_tNX;XE!+H)&GaQmvI|EVM8AWH%Lq01e=jsCdtk2O|tJ+Lo=S;xlO zD54EZZBVBX?19+8p5k@mXuk&>y@TBil7nNXB77mZ6bgv%4zd`ATKuBx99C_jMMOTg z+;SS_v)g`~j+Ku0xD{nPwT%vBM9$Ifd90PWFU++Uo{UNZU8N76mCGi^A(cfcYRXak zMKjrM_oGHhhc}w|}Ag=$XomZ)YH&djN-0<6kMVZgvk9QqBi=^?H+?wKKRTsjPoTZ?B2W?x6 zYpAf%%$60|B(KyS){X={!&;8Q(db(J4;k) zbiaNB=yP&6p=?nPy(08s$BdJ&rTgPKaJ>pP9@O)sqIuyFyh^Tr)Gc%VxSa)7IV${@ z3u37LdDg=G%{d{tCp6&FuowFbhfWuIzz+zhoHanWpb8m+5`Im$9FNS6y>*wSQ$v%5 zn>~08+hW~^C$LmJxXZhFK~qC40QV3I2S932O37yUGDot zik!CUUG}2Y*HVf~BDN(5EDba(D4>1NxUgR1Napwtlju6)UKfAFo*vR8tw*MS)+4!V zhjASbX=;Gj@C!|IG&ai;s4UP;=gmGuZy4u?4+6Z!fC+4EB9K+tVchLP9)Qcs5ai*$ z%M8TN8XyUVamK-%8cgvoT;HQIv5NrU+ZUualvpklL{p{PyoC)C_|wo+oJrPsk;y*9 zY^|~CN>v`GqEeqkZL7Fn)#%>;alhQ5hhb*YI+>wuGcV%|!4+`d+hD{vKu!nvM?WBK zfGSNJu#i@gcq&1xhdH^<+({0$z8LZ0!67m;p(fK22?UGG^f>#M#RwIj)iD$^jRs{4cxN-$9 zSjggSWesVQ$FX>~_?n<#G#^}w2(*Mbx8VMrIg{Y#bzBm*ecP`#RQgk}hDt2XId+;p zst_!Q<@W;B6@snijZ17cw|=J5q~wd2`H=Ortj@0NZl|?NPsT})l=101OJdH1H@xV( zXo@3%1_;0!0)otR2+-Df(2fFbOl6uW;v9#_7O>y3_oVX2Jxt1lRo>ogBbT5n`cY`H%ccI3N5Gu zEil*$bwtvV7n{hD?Ul)u_Vci_Z|~M^e|tPJ&C~Yj%G$BE+K$_EOWpSmZq)F>Gr=qF zvH%})Jps^^X638^Ovti^8tBqWREkUKqCBvnp4nN=VFh>D7&7Btw8x}J7_3`dx3M(c zYEVYuOc-IzXfyt81@d=3JLF^-YymPmquU(#dR$R__9;HA1!mAB5)cbZp45Qfo-=t_ z_mhvEh&bl5(z5PJQq%QAzB=KHET-L&Un5-(ytN%xRwHaat2hT&MO%=7j1lHNFlx55w$6NFmYFtVVYgj%@0N5U za97z@~rfmf;o zd|FAN1E8tSur4Onc{V#0F#RK8pKNnch(MM!#Z|3Ah3_3~QrSOf@HV~Tec%CGQ`HkC z>{)9MAC2aaMzgG=x)Z;K4E{=<&$kX$>oaH=m;^MCl_;LYxkgUYXVCRg3cuG!k1XSo zgUjLFn?kj=tm<*E=y5aI^u*fZNoCSSA=WV>$=A~}W8okO%6F1F6c3YO^HIse3wa`D#k729~4 ze@v(6ThB|_(7?zRj5w?Gw`|@PVqH`*YZ|7H3_Mdy_R}Nd$W*KG23iRp2K1dhmqo|e zC1y2tRzIIz>##6 zZ)Jg6QHB&s-uI?oWJuD}NzLS{hF5H`OUZb?_1g5ih{C8Y>Hpae|5j-PcND*JNq?A1dsJeN z>WbK-`fHYN6c6B6^r%3lc3cviyUxM!GIX9buG)BomHKS{{Dr3ogJZ1wK?Zm1b^0qMml2ssf_s*z7qitlDY_{{kP7Dx6_!Ri)=WXNPStMbokRR-Ek%!6J9viv^X> zm9j$u6SI7vE$~5h?K%Nfl$5Oi<+JNR57bLs#$@@;1PZtzXZqk+?&a#XMXT@qjLpBk zW%(T)2MT4A=mqeMrBU$2-J6QMrMU(Jm(n9wGG=3W6(=6==E-lA^Jy(< z_b~)c^jB`E*liLgqQ2zU#ctEDPE#n`Y~?39BMOUw^X4`Ovr|NgYb%NKM4#KvKFaCrnFrrk zcb>C%jpV0w*lZ9$`hu1rZyMk>KMo7C9Enxsq(H*m9`5LY`to?>Vcf#Iqb&&lQ5eCX z=jYHW2Kpcypo2;hAnr^SqE#-MQH<@h2XAh(1ZBM`WK`)rcA;e$r%ePe?o0S)%IyC( zqqhj4E_^}J24Gs;SpZs83_wMXK*a{slqcx>q=JT0kpY1^+EBA954+w*E=)LB{el=3 zS8JrTPwR=`y9ixLT9_Ph zqP-}h+eZ1Smws=u_T1|Oq$5kvzUfYqGB`ryD60YhM}b6429#G#K#3z<1&H9Fr3tzo zEUc8*FfRHrxJM?N3!@3ZJNatYK(PGvrj5WmeqBNS*5O(A=!1$qC|U|VK+QNEDq#9C zQ+tac#57wf4qf`zz{q(o-~}rW=EWimQ1jfvun_;XfvdRJ>QNqJP4LL zAI{y&;zUC!UmBeRA$T4^5QOC+mbc(N!#GE0GB1d_Z=j3i@;bHj1 z0}YDvvgW%)>ZO>qcM7&{dUvj;`9#EmPp$XYf?~f3syyv4dPY?g4uO?VB|U?E0ACDA zppus)E0h*$Z5qa%HOp6FISQ@(V(ra^A4?}Vc~>@U9>y62s6NZ{k!}z8V@UBgA2LfJ z06mTciq!Wu)(C^bFawl?ow`@?%Q1P1gfnPdpogDgvlGr+(kxn4!V2E;Ch0O+pOoTj zRbcHYo0>^t&ONH=gO7wb57;BBW`23sL!bpzMYrjasI=%d{2)i^Ao(3sYh#Vhwx9Y` zNUTfMS=>iq+wU}6)pLXEG}yZQ)i^~QwDj8~<#$ua|K;H&H&6gL3!qa39|1P#5F7-_ zLeA_9FfWuUOG2FQQhh7(F*zo_v&j;*i48e)c`(cSihTO)Cy(u7N@#;x7w_O`Z~kgh zfu`92J2Jr9cPsD+9H?7C6EnyFBkF*fBD(-y_ZUzLQO|7PeDie$ z%Hagwc?90lm&~nN>bgIotg`E7*h8hpyl!2K_b+z)&6I3sjF?lPX=IiNwMQ2IAQR{q zaDWanyNG@^DgwN~DhwEi2!A5IRFEXQIXh~gCS3lNFz)eH%xm(J(|$O7*=Y6?04csU zp#N>R;_Ef}O}w7OfoTAR1;o`@l=TG$MBtM0%IiEq+W?KGF_oB_i~7ve2VftZ@`pUb zVCDE|Ta6rdrsLS8!23Na&PSPsn_3s(2ur`1RG?_KF>4)0Hefv}jo^i#f#_b^!q=<^ za7t=2vOas!DFHd{pp9cIJ16@=xM$<)g7Qz#k6fEL9|u@7zH$Udk(1xg_R#_j%LPd$s6OnLGsM?RV1u* zmwVrMEv=vT&RKrt67Ug0twI5G2qO40d8G0)Huj0aee`ORZB=vpes;MrGreL@wSm!0 z=%>`m%;yB@-1H0cuj=#+?iQ|N? zQxv~VFfNW0exG<;94Gt^Ii>Fd7oDvqAw{kE& zwL0le?qHG?X|XJaMO`{?k2Kp-n8qWaiuh(2Re8jT{78_8_Oa`iz2|D?QwPk6{<^3n z=OAhtTO{Go=2j7|W4>m_969qhR;rV2e4wk7PGPcDV3V%!?x!VCJquW=jZN2+Yc~sO z(m_6OGL1kv;<|YHO0(&an^F(O`QDRIiuk^RPH_hCcSy90ExXvVf13{|&H#!tfTQ_h z-;~+;UM#yf11Qb_-o^dLV*ITMN^$l6t1|U(lFj&&W#uIKH@gs1my6ggcPRjeO#T;~r-5sCCORsr$jvyYW})xpB{5-f-_acR5Y6MRX}i5kR#jJq^%D3|&bo`yw{JJ^IDAv$9PZNx zabMN%poQNf2XC*~CYujxZmsDrZbqhBjw`0>YVvo}VuG_-tr+@Bg9rVCOYdV&{DwgaXAFU`Mnn8WSd5_8;!(>Z& zh1qV+Nn46~xt33F&vA`hViJq6@=b0RdP~MTM@uhETxmXG@FfZLK(7N>)jF8t2c;!< zEzPRAki9A{qkvG0;VKCV9m^Pk>$>WhZ|@m7>*Rg9dMPGg`lDN`4odRp{k1`zn9uZ& z!Y(d0S3kbF>SvuLkHZ$wXna8cFN4GK@gT|5*1Tmp-Uz!>m--1BxYo^GUX!?~bvFL$ z&y!t+pdRjf63%_pG=+C)rF9`2neYCTlHhV_VUr1G#ysBr>y8=iP@U)V9SxVztavIENb|2pYhHpqU9M!avmXgPPZ1c};S!QHK`qdHAl68n3w*YH~4EnaPS~hZOCV zmW#^nPx+K}eD4`_FTIMD9@niSJVfPVv*>S_io~==W7VA8J+?0@j~}N$tgVfm?Xw5B zaT*)PW}iuSwWD-8izXHMmHd&mJo~l8!IdCd^(iorY^9x{TY8) zeevXq<&KcnO*p+VK+C9cyOFo4*yMRJ`l<->}Cr z_Ka)dlGIC^^W9(-C|$oxLAVvm8v#k4B?`_Vu1Dh58C;08dg2y!onU8)X_-A+mRbCA zpLfdLy*YYiINA|0H&DRAKL)Q0U^xL4Jz}a8z^dlUY9m5vEKv!2=={MnqHg_8Qv=?8`WMB{@B%1H?AkI_3Gy+UnLjo$(*69#^48lp1WV;OJ4gnw~~d zATRgL0af7rZbB-#fX2KA8$W~RL7UOss8(Iio$)!LBuhP_jf`Xz-piEL>*}$L4nEOk zy2Mxp<<2dCK`!n^6}2!~lF*LM){m_5qolR-oVtc_ORfausuMCj&h<>c&Z@H}Ye$}O zP~EOP(Z@>3;I(v%=*z;wn_-?yGJ1#Dq9VGK1Za0j^cgqtArOa?JZM(lO&P`=&A_77 zbm&XOU3!1*F1_Bt!Wmc-=$YCzx5cQ1SX<8ZsE(i*#LtVr)zJRlq-HHJEsaq#E}TGb z@2FomhL)+ICwfRP0yu5KqkfN8Tnr4t@M^bF# zX56k_4_?TIU7t2)*~R-qI22$veJ_FFDfNan?~E%`1>!J0EnIVy27BCd)LpD+ept3H z5kAoPd~M^+88d$lqLahg_bIbNVL2+Lzz|=PMwUSyt$kX7n#VP)j=`?qtuuA=a9nwq zUpDcay1qs3c8M7slFI)M)5nk7ssGP0OL2ttLq}Lz9gJG0V4LVB3v_1*tcGPFCx-vY zfIxKDJT>^yOf$D-vyZ&DYk0oi>J7ekV~eI=>6H1BLNAdo%<*TYkWq!wJeXI(PLDf( z9Irq#f0I2wi;f-k<867j&G*F`!VCQQY-cVz@W#CAY`2zP zMHjW2^Lh))%CPtZJ2MXtuLU3aO0|}(7>aDa`xj>T-1hS(p>WaAq0#%9N1R@W4HHFISxa+OBvXrSE zhl|Itnm?X*bklRy&o`esN3^*mtkh_sf72Q$7((XbQTb>AXrk1){c`Y7ST0Q&^?SEhDtmvLxwh1Rr`iYZ%;wr*-P({E_vp7GKd24zZ zeM0X6AVeS2!Q4>6s*DY1~iP_kY zS1{?#rh5UEGq*|$YK0PTE{%17Sbr-22)&Gz0sEyAWzn@&9PH)wG^ztL&;BQQTGBL8 z+|k<(x<=L21YrXZ98br2*mWRT=_*%heSmmrCG*VdGB%wgp+^#%JbjthBvUTLNr zxxyM%O9bAEEK&$s4ZDKg(3R{zT5jvl!a*&jEB=vkcz`6v_YF-Rc_ds1*dB**&Xluk zDFexPY6Mp~PSY>?QRUL-v=?~PV�@_kR9!U)ejWZj;u2c8vU#z}u3H%%pUE5~@&7 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

{@N#+_-<3s%l=4?N~-wPWG+M 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 { + return source => + source.pipe( + concatMap(({ url }) => { + return from(resolveRoute(url)).pipe( + download(), + expand(resp => { + return from(resolveRoute(url, resp.clone())).pipe( + filter(url => !!url), + download() + ); + }) + ); + }), + map(resp => resp.clone()) + ); +}; diff --git a/packages/operators/src/fetch/autoPagination.test.js b/packages/operators/src/fetch/autoPagination.test.js new file mode 100644 index 0000000..5c36d15 --- /dev/null +++ b/packages/operators/src/fetch/autoPagination.test.js @@ -0,0 +1,42 @@ +import { concatAll, map, of } from 'rxjs'; +import { beforeEach, describe, expect, test } from 'vitest'; + +import { autoPagination } from './autoPagination'; +import { resolveJSON } from './resolve'; + +describe('auto pagination', function () { + beforeEach(function () { + // + }); + + test('auto pagination', async function () { + return new Promise(done => { + return of({ url: new URL('https://dummyjson.com/products') }) + .pipe( + autoPagination({ + resolveRoute: async (url, resp) => { + const data = (await resp?.json()) || { skip: -10, limit: 10 }; + + if (!data.total || data.total > data.skip + data.limit) { + const newUrl = new URL(`${url}`); + newUrl.searchParams.set('skip', data.skip + data.limit); + newUrl.searchParams.set('limit', data.limit); + newUrl.searchParams.set('select', 'title,price'); + return newUrl; + } + } + }), + resolveJSON(), + map(({ products }) => products), + concatAll() + ) + .subscribe({ + next: e => console.log(e), + complete: () => { + console.log('COMPLETE'); + done(); + } + }); + }); + }); +}); diff --git a/packages/operators/src/fetch/concurrentDownload.js b/packages/operators/src/fetch/concurrentDownload.js new file mode 100644 index 0000000..afcd4aa --- /dev/null +++ b/packages/operators/src/fetch/concurrentDownload.js @@ -0,0 +1,7 @@ +import { mergeMap, of } from 'rxjs'; + +import { download } from './download'; + +export const concurrentDownload = (concurrent = 1) => { + return source => source.pipe(mergeMap(url => of(url).pipe(download()), concurrent)); +}; diff --git a/packages/operators/src/fetch/concurrentDownload.test.js b/packages/operators/src/fetch/concurrentDownload.test.js new file mode 100644 index 0000000..3de0587 --- /dev/null +++ b/packages/operators/src/fetch/concurrentDownload.test.js @@ -0,0 +1,40 @@ +import { concatAll, map, of } from 'rxjs'; +import { beforeEach, describe, expect, test } from 'vitest'; + +import { concurrentDownload } from './concurrentDownload'; +import { resolveJSON } from './resolve'; + +describe('multi fetch', function () { + beforeEach(function () { + // + }); + + test('request pagination', async function () { + return new Promise(done => { + of( + new URL('https://dummyjson.com/products?limit=10&skip=0&select=title,price'), + new URL('https://dummyjson.com/products?limit=10&skip=10&select=title,price'), + new URL('https://dummyjson.com/products?limit=10&skip=20&select=title,price'), + new URL('https://dummyjson.com/products?limit=10&skip=30&select=title,price'), + new URL('https://dummyjson.com/products?limit=10&skip=40&select=title,price'), + new URL('https://dummyjson.com/products?limit=10&skip=50&select=title,price'), + new URL('https://dummyjson.com/products?limit=10&skip=60&select=title,price'), + new URL('https://dummyjson.com/products?limit=10&skip=70&select=title,price'), + new URL('https://dummyjson.com/products?limit=10&skip=80&select=title,price') + ) + .pipe( + concurrentDownload(4), + resolveJSON(), + map(({ products }) => products), + concatAll() + ) + .subscribe({ + next: e => console.log(e), + complete: () => { + console.log('COMPLETE'); + done(); + } + }); + }); + }); +}); diff --git a/packages/operators/src/fetch/download.js b/packages/operators/src/fetch/download.js new file mode 100644 index 0000000..929d7cb --- /dev/null +++ b/packages/operators/src/fetch/download.js @@ -0,0 +1,18 @@ +import { request } from './request'; +import { resolveBlob, resolveJSON, resolveText } from './resolve'; + +export const download = () => { + return source => source.pipe(request()); +}; + +export const downloadJSON = () => { + return source => source.pipe(download(), resolveJSON()); +}; + +export const downloadText = () => { + return source => source.pipe(download(), resolveText()); +}; + +export const downloadBlob = () => { + return source => source.pipe(download(), resolveBlob()); +}; diff --git a/packages/observables/src/fetch/request.test.js b/packages/operators/src/fetch/download.test.js similarity index 53% rename from packages/observables/src/fetch/request.test.js rename to packages/operators/src/fetch/download.test.js index ef16c3f..c11e1d2 100644 --- a/packages/observables/src/fetch/request.test.js +++ b/packages/operators/src/fetch/download.test.js @@ -1,9 +1,10 @@ import fetchMock from 'fetch-mock'; +import { of } from 'rxjs'; import { afterEach, test, describe, beforeEach, expect } from 'vitest'; -import { requestObservable } from './request.js'; +import { download, downloadJSON } from './download.js'; -describe('request observable with default operators', function () { +describe('download operator', function () { beforeEach(function () { fetchMock.get( 'https://httpbin.org/my-url-fast', @@ -23,12 +24,16 @@ describe('request observable with default operators', function () { fetchMock.restore(); }); - test('successfull request', () => + test('successfull download', () => new Promise(done => { - requestObservable('https://httpbin.org/my-url-fast').subscribe(async e => { - expect(e.ok).equal(true); - expect(await e.json()).deep.equal({ hello: 'fast world' }); - done(); - }); + of('https://httpbin.org/my-url-fast') + .pipe(downloadJSON()) + .subscribe({ + next: data => { + expect(data).deep.equal({ hello: 'fast world' }); + done(); + }, + complete: e => console.log('COMPLETE', e) + }); })); }); diff --git a/packages/operators/src/fetch/lazyPagination.js b/packages/operators/src/fetch/lazyPagination.js new file mode 100644 index 0000000..dae84cd --- /dev/null +++ b/packages/operators/src/fetch/lazyPagination.js @@ -0,0 +1,15 @@ +import { concatMap, map } from 'rxjs'; + +import { concurrentDownload } from './concurrentDownload'; + +export const lazyPagination = ({ createRoute }) => { + return source => + source.pipe( + concatMap(({ url, pager, concurrent }) => { + return pager.pipe( + map(options => createRoute(url, options)), + concurrentDownload(concurrent) + ); + }) + ); +}; diff --git a/packages/operators/src/fetch/lazyPagination.test.js b/packages/operators/src/fetch/lazyPagination.test.js new file mode 100644 index 0000000..3233f8f --- /dev/null +++ b/packages/operators/src/fetch/lazyPagination.test.js @@ -0,0 +1,50 @@ +import { concatAll, map, of, Subject } from 'rxjs'; +import { beforeEach, describe, expect, test } from 'vitest'; + +import { lazyPagination } from './lazyPagination'; +import { resolveJSON } from './resolve'; + +describe('lazy pagination operator', function () { + beforeEach(function () { + // + }); + + test('successfull lazy pagination', async function () { + const pager = new Subject(); + + return new Promise(done => { + of({ url: new URL('https://dummyjson.com/products'), pager, concurrent: 4 }) + .pipe( + lazyPagination({ + createRoute: (url, { value, limit = 10 }) => { + const newUrl = new URL(`${url}`); + newUrl.searchParams.set('skip', value * limit); + newUrl.searchParams.set('limit', limit); + newUrl.searchParams.set('select', 'title,price'); + return newUrl; + } + }), + resolveJSON(), + map(({ products }) => products), + concatAll() + ) + .subscribe({ + next: e => console.log(e), + complete: () => { + console.log('COMPLETE'); + done(); + } + }); + + pager.next({ value: 2 }); + pager.next({ value: 3 }); + pager.next({ value: 4 }); + pager.next({ value: 5 }); + pager.next({ value: 6 }); + pager.next({ value: 7 }); + pager.next({ value: 8 }); + pager.next({ value: 9 }); + pager.complete(); + }); + }); +}); diff --git a/packages/operators/src/fetch/polling.js b/packages/operators/src/fetch/polling.js new file mode 100644 index 0000000..737c501 --- /dev/null +++ b/packages/operators/src/fetch/polling.js @@ -0,0 +1,20 @@ +import { concatMap, delay as delayOperator, EMPTY, expand, of } from 'rxjs'; + +import { download } from './download'; + +export const polling = ({ validateResult, delay = 1000 }) => { + return source => + source.pipe( + concatMap(({ url }) => { + return of(url).pipe( + download(), + expand(data => { + if (validateResult(data)) { + return of(url).pipe(delayOperator(delay), download()); + } + return EMPTY; + }) + ); + }) + ); +}; diff --git a/packages/operators/src/fetch/polling.test.js b/packages/operators/src/fetch/polling.test.js new file mode 100644 index 0000000..6096170 --- /dev/null +++ b/packages/operators/src/fetch/polling.test.js @@ -0,0 +1,29 @@ +import { concatAll, map, of } from 'rxjs'; +import { beforeEach, describe, expect, test } from 'vitest'; + +import { polling } from './polling'; + +describe('polling', function () { + beforeEach(function () { + // + }); + + test('auto polling', async function () { + of({ url: new URL('https://dummyjson.com/products') }) + .pipe( + polling({ + validateResult: data => { + return data.total > data.skip + data.limit; + } + }) + // map(({ data: { products } }) => products), + // concatAll() + ) + .subscribe({ + next: e => console.log('aha'), + complete: () => console.log('COMPLETE') + }); + + await new Promise(resolve => setTimeout(resolve, 5000)); + }); +}); diff --git a/packages/operators/src/fetch/request.http b/packages/operators/src/fetch/request.http new file mode 100644 index 0000000..b6e83ff --- /dev/null +++ b/packages/operators/src/fetch/request.http @@ -0,0 +1,20 @@ +### Sample +# @name post +GET https://dummyjson.com/posts/1 HTTP/1.1 +content-type: application/json + +### Ref Sample +@userId = {{post.response.body.userId}} +GET https://dummyjson.com/users/{{userId}} HTTP/1.1 +content-type: application/json + +### Upload Sample +POST https://api.escuelajs.co/api/v1/files/upload HTTP/1.1 +Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gZ + +------WebKitFormBoundary7MA4YWxkTrZu0gZ +Content-Disposition: form-data; name="file"; filename="1.jpg" +Content-Type: image/jpeg + +< ../../fixtures/images/test_image.jpg +------WebKitFormBoundary7MA4YWxkTrZu0gZ-- diff --git a/packages/operators/src/fetch/request.js b/packages/operators/src/fetch/request.js new file mode 100644 index 0000000..e54f231 --- /dev/null +++ b/packages/operators/src/fetch/request.js @@ -0,0 +1,11 @@ +import { concatMap } from 'rxjs'; + +import { networkRetry } from './retry'; + +export const request = () => { + return source => + source.pipe( + concatMap(req => fetch(req)), + networkRetry() + ); +}; diff --git a/packages/operators/src/fetch/request.test.js b/packages/operators/src/fetch/request.test.js new file mode 100644 index 0000000..bdc667f --- /dev/null +++ b/packages/operators/src/fetch/request.test.js @@ -0,0 +1,37 @@ +import fetchMock from 'fetch-mock'; +import { of } from 'rxjs'; +import { afterEach, test, describe, beforeEach, expect } from 'vitest'; + +import { request } from './request.js'; + +describe('request observable with default operators', function () { + beforeEach(function () { + let counter = 0; + fetchMock.get( + 'https://httpbin.org/my-url-fast', + () => { + return new Response(JSON.stringify({ hello: 'fast world' }), { + status: ++counter > 2 ? 200 : 404, + headers: { 'Content-type': 'application/json' } + }); + }, + { delay: 0, repeat: 4 } + ); + }); + + afterEach(function () { + fetchMock.restore(); + }); + + test('successfull request', () => + new Promise(done => { + of('https://httpbin.org/my-url-fast') + .pipe(request()) + .subscribe({ + next: resp => { + expect(resp).deep.includes({ ok: true }); + }, + complete: () => done() + }); + })); +}); diff --git a/packages/operators/src/fetch/resolve.js b/packages/operators/src/fetch/resolve.js new file mode 100644 index 0000000..776fce2 --- /dev/null +++ b/packages/operators/src/fetch/resolve.js @@ -0,0 +1,17 @@ +import { concatMap } from 'rxjs'; + +export const resolve = (type = 'json') => { + return source => source.pipe(concatMap(e => e[String(type)]())); +}; + +export const resolveJSON = () => { + return resolve('json'); +}; + +export const resolveText = () => { + return resolve('text'); +}; + +export const resolveBlob = () => { + return resolve('blob'); +}; diff --git a/packages/operators/src/request/retry.js b/packages/operators/src/fetch/retry.js similarity index 96% rename from packages/operators/src/request/retry.js rename to packages/operators/src/fetch/retry.js index ee50e93..3d7666e 100644 --- a/packages/operators/src/request/retry.js +++ b/packages/operators/src/fetch/retry.js @@ -34,7 +34,7 @@ export const networkRetry = ({ timeout = defaultTimeout, count } = {}) => { tap(valid => (counter = counter * valid)), filter(valid => valid), tap(() => { - console.log(timeout(counter++)); + console.log(timeout(counter)); console.log( `retry: request - next: ${counter + 1} in ${timeout(counter + 1) || timeout}s` ); diff --git a/packages/operators/src/request/retry.test.js b/packages/operators/src/fetch/retry.test.js similarity index 79% rename from packages/operators/src/request/retry.test.js rename to packages/operators/src/fetch/retry.test.js index 3268ada..f02ff37 100644 --- a/packages/operators/src/request/retry.test.js +++ b/packages/operators/src/fetch/retry.test.js @@ -17,15 +17,7 @@ describe('request retry', function () { let counter = 0; const mockObservable = of(null) - .pipe( - map(() => { - counter++; - if (counter < 3) { - return { ok: false }; - } - return { ok: true }; - }) - ) + .pipe(map(() => ({ ok: !(++counter < 3) }))) .pipe(networkRetry({ timeout: () => 1000 })); testScheduler.run(({ expectObservable }) => { diff --git a/packages/operators/src/fetch/upload.js b/packages/operators/src/fetch/upload.js new file mode 100644 index 0000000..a7c09da --- /dev/null +++ b/packages/operators/src/fetch/upload.js @@ -0,0 +1,7 @@ +import { concatMap, of } from 'rxjs'; + +import { request } from './request'; + +export const upload = () => { + return source => source.pipe(request()); +}; diff --git a/packages/operators/src/fetch/upload.test.js b/packages/operators/src/fetch/upload.test.js new file mode 100644 index 0000000..c8f7028 --- /dev/null +++ b/packages/operators/src/fetch/upload.test.js @@ -0,0 +1,49 @@ +import fetchMock from 'fetch-mock'; +import { readFile } from 'node:fs/promises'; +import { of } from 'rxjs'; +import { afterEach, test, describe, beforeEach, expect } from 'vitest'; + +import { log } from '../log.js'; +import { resolveJSON } from './resolve.js'; +import { upload } from './upload.js'; + +describe('request observable with default operators', function () { + beforeEach(function () { + // + }); + + afterEach(function () { + // + }); + + test('successfull request', async () => { + const formData = new FormData(); + formData.set( + 'file', + new File( + [ + new Blob([await readFile('./packages/operators/fixtures/images/test_image.jpg')], { + type: 'image/jpeg' + }) + ], + 'test_image.jpg' + ) + ); + + const req = new Request(new URL('https://api.escuelajs.co/api/v1/files/upload'), { + method: 'POST', + body: formData + }); + + return new Promise(done => { + of(req) + .pipe(upload(), log(false), resolveJSON(), log(false)) + .subscribe(e => { + expect(e) + .deep.includes({ originalname: 'test_image.jpg' }) + .have.all.keys('filename', 'location'); + done(); + }); + }); + }); +}); diff --git a/packages/operators/src/log.js b/packages/operators/src/log.js new file mode 100644 index 0000000..535d267 --- /dev/null +++ b/packages/operators/src/log.js @@ -0,0 +1,26 @@ +import { Observable } from 'rxjs'; + +export const log = (active = true) => { + return source => { + if (active) { + return new Observable(observer => { + return source.subscribe( + val => { + console.log(val); + observer.next(val); + }, + err => { + console.error(err); + observer.error(err); + }, + () => { + console.log('%ccomplete', 'color: green'); + observer.complete(); + } + ); + }); + } else { + return source; + } + }; +}; diff --git a/packages/operators/vitest.config.js b/packages/operators/vitest.config.js index e3fd592..b34b1fe 100644 --- a/packages/operators/vitest.config.js +++ b/packages/operators/vitest.config.js @@ -2,6 +2,7 @@ import { defineProject } from 'vitest/config'; export default defineProject({ test: { + setupFiles: ['../../setup.js'], environment: 'happy-dom' } }); diff --git a/setup.js b/setup.js new file mode 100644 index 0000000..752a97b --- /dev/null +++ b/setup.js @@ -0,0 +1,17 @@ +import * as nFetch from 'node-fetch'; +import { afterAll, beforeAll } from 'vitest'; + +const backup = new Map([ + ['fetch', [global.fetch, nFetch.default]], + ['Blob', [global.Blob, nFetch.Blob]], + ['File', [global.File, nFetch.File]], + ['FormData', [global.FormData, nFetch.FormData]], + ['Request', [global.Request, nFetch.Request]] +]); + +beforeAll(() => { + Array.from(backup.entries()).forEach(([name, [, poly]]) => (global[String(name)] = poly)); +}); +afterAll(() => { + Array.from(backup.entries()).forEach(([name, [orig]]) => (global[String(name)] = orig)); +}); From 3d20b2e2daa5d64b708418dc7a694ad3ec47f0be Mon Sep 17 00:00:00 2001 From: StephanGerbeth Date: Thu, 24 Oct 2024 10:20:54 +0200 Subject: [PATCH 2/7] fix(fetch): cleanup tests --- .../src/fetch/autoPagination.test.js | 8 ++--- .../src/fetch/concurrentDownload.test.js | 5 +-- packages/operators/src/fetch/download.test.js | 6 ++-- .../operators/src/fetch/lazyPagination.js | 4 +-- .../src/fetch/lazyPagination.test.js | 13 ++++---- packages/operators/src/fetch/polling.test.js | 32 +++++++++---------- packages/operators/src/fetch/request.test.js | 3 +- packages/operators/src/fetch/upload.test.js | 12 ++++--- 8 files changed, 42 insertions(+), 41 deletions(-) diff --git a/packages/operators/src/fetch/autoPagination.test.js b/packages/operators/src/fetch/autoPagination.test.js index 5c36d15..f0b4664 100644 --- a/packages/operators/src/fetch/autoPagination.test.js +++ b/packages/operators/src/fetch/autoPagination.test.js @@ -1,6 +1,7 @@ import { concatAll, map, of } from 'rxjs'; import { beforeEach, describe, expect, test } from 'vitest'; +import { log } from '../log'; import { autoPagination } from './autoPagination'; import { resolveJSON } from './resolve'; @@ -26,16 +27,15 @@ describe('auto pagination', function () { } } }), + log(false), resolveJSON(), + log(false), map(({ products }) => products), concatAll() ) .subscribe({ next: e => console.log(e), - complete: () => { - console.log('COMPLETE'); - done(); - } + complete: () => done() }); }); }); diff --git a/packages/operators/src/fetch/concurrentDownload.test.js b/packages/operators/src/fetch/concurrentDownload.test.js index 3de0587..0510bb9 100644 --- a/packages/operators/src/fetch/concurrentDownload.test.js +++ b/packages/operators/src/fetch/concurrentDownload.test.js @@ -30,10 +30,7 @@ describe('multi fetch', function () { ) .subscribe({ next: e => console.log(e), - complete: () => { - console.log('COMPLETE'); - done(); - } + complete: () => done() }); }); }); diff --git a/packages/operators/src/fetch/download.test.js b/packages/operators/src/fetch/download.test.js index c11e1d2..6c098d2 100644 --- a/packages/operators/src/fetch/download.test.js +++ b/packages/operators/src/fetch/download.test.js @@ -2,6 +2,7 @@ import fetchMock from 'fetch-mock'; import { of } from 'rxjs'; import { afterEach, test, describe, beforeEach, expect } from 'vitest'; +import { log } from '../log.js'; import { download, downloadJSON } from './download.js'; describe('download operator', function () { @@ -27,13 +28,12 @@ describe('download operator', function () { test('successfull download', () => new Promise(done => { of('https://httpbin.org/my-url-fast') - .pipe(downloadJSON()) + .pipe(downloadJSON(), log(false)) .subscribe({ next: data => { expect(data).deep.equal({ hello: 'fast world' }); - done(); }, - complete: e => console.log('COMPLETE', e) + complete: e => done() }); })); }); diff --git a/packages/operators/src/fetch/lazyPagination.js b/packages/operators/src/fetch/lazyPagination.js index dae84cd..15115ea 100644 --- a/packages/operators/src/fetch/lazyPagination.js +++ b/packages/operators/src/fetch/lazyPagination.js @@ -2,12 +2,12 @@ import { concatMap, map } from 'rxjs'; import { concurrentDownload } from './concurrentDownload'; -export const lazyPagination = ({ createRoute }) => { +export const lazyPagination = ({ resolveRoute }) => { return source => source.pipe( concatMap(({ url, pager, concurrent }) => { return pager.pipe( - map(options => createRoute(url, options)), + map(options => resolveRoute(url, options)), concurrentDownload(concurrent) ); }) diff --git a/packages/operators/src/fetch/lazyPagination.test.js b/packages/operators/src/fetch/lazyPagination.test.js index 3233f8f..9bf49d9 100644 --- a/packages/operators/src/fetch/lazyPagination.test.js +++ b/packages/operators/src/fetch/lazyPagination.test.js @@ -1,6 +1,7 @@ import { concatAll, map, of, Subject } from 'rxjs'; import { beforeEach, describe, expect, test } from 'vitest'; +import { log } from '../log'; import { lazyPagination } from './lazyPagination'; import { resolveJSON } from './resolve'; @@ -16,7 +17,7 @@ describe('lazy pagination operator', function () { of({ url: new URL('https://dummyjson.com/products'), pager, concurrent: 4 }) .pipe( lazyPagination({ - createRoute: (url, { value, limit = 10 }) => { + resolveRoute: (url, { value, limit = 10 }) => { const newUrl = new URL(`${url}`); newUrl.searchParams.set('skip', value * limit); newUrl.searchParams.set('limit', limit); @@ -24,16 +25,16 @@ describe('lazy pagination operator', function () { return newUrl; } }), + log(false), resolveJSON(), + log(false), map(({ products }) => products), - concatAll() + concatAll(), + log(false) ) .subscribe({ next: e => console.log(e), - complete: () => { - console.log('COMPLETE'); - done(); - } + complete: () => done() }); pager.next({ value: 2 }); diff --git a/packages/operators/src/fetch/polling.test.js b/packages/operators/src/fetch/polling.test.js index 6096170..076c96a 100644 --- a/packages/operators/src/fetch/polling.test.js +++ b/packages/operators/src/fetch/polling.test.js @@ -9,21 +9,21 @@ describe('polling', function () { }); test('auto polling', async function () { - of({ url: new URL('https://dummyjson.com/products') }) - .pipe( - polling({ - validateResult: data => { - return data.total > data.skip + data.limit; - } - }) - // map(({ data: { products } }) => products), - // concatAll() - ) - .subscribe({ - next: e => console.log('aha'), - complete: () => console.log('COMPLETE') - }); - - await new Promise(resolve => setTimeout(resolve, 5000)); + return new Promise(done => { + of({ url: new URL('https://dummyjson.com/products') }) + .pipe( + polling({ + validateResult: data => { + return data.total > data.skip + data.limit; + } + }) + // map(({ data: { products } }) => products), + // concatAll() + ) + .subscribe({ + next: e => console.log('aha'), + complete: () => done() + }); + }); }); }); diff --git a/packages/operators/src/fetch/request.test.js b/packages/operators/src/fetch/request.test.js index bdc667f..4eb91a5 100644 --- a/packages/operators/src/fetch/request.test.js +++ b/packages/operators/src/fetch/request.test.js @@ -2,6 +2,7 @@ import fetchMock from 'fetch-mock'; import { of } from 'rxjs'; import { afterEach, test, describe, beforeEach, expect } from 'vitest'; +import { log } from '../log.js'; import { request } from './request.js'; describe('request observable with default operators', function () { @@ -26,7 +27,7 @@ describe('request observable with default operators', function () { test('successfull request', () => new Promise(done => { of('https://httpbin.org/my-url-fast') - .pipe(request()) + .pipe(request(), log(false)) .subscribe({ next: resp => { expect(resp).deep.includes({ ok: true }); diff --git a/packages/operators/src/fetch/upload.test.js b/packages/operators/src/fetch/upload.test.js index c8f7028..74b91fe 100644 --- a/packages/operators/src/fetch/upload.test.js +++ b/packages/operators/src/fetch/upload.test.js @@ -38,11 +38,13 @@ describe('request observable with default operators', function () { return new Promise(done => { of(req) .pipe(upload(), log(false), resolveJSON(), log(false)) - .subscribe(e => { - expect(e) - .deep.includes({ originalname: 'test_image.jpg' }) - .have.all.keys('filename', 'location'); - done(); + .subscribe({ + next: e => { + expect(e) + .deep.includes({ originalname: 'test_image.jpg' }) + .have.all.keys('filename', 'location'); + }, + complete: () => done() }); }); }); From 025ea930df68d7eb1cc28cd64c642e51f498c69c Mon Sep 17 00:00:00 2001 From: StephanGerbeth Date: Thu, 24 Oct 2024 10:52:53 +0200 Subject: [PATCH 3/7] fix(fetch): added logs and cleanup --- packages/operators/src/fetch/download.test.js | 3 ++- packages/operators/src/fetch/request.js | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/operators/src/fetch/download.test.js b/packages/operators/src/fetch/download.test.js index 6c098d2..cce43c9 100644 --- a/packages/operators/src/fetch/download.test.js +++ b/packages/operators/src/fetch/download.test.js @@ -4,6 +4,7 @@ import { afterEach, test, describe, beforeEach, expect } from 'vitest'; import { log } from '../log.js'; import { download, downloadJSON } from './download.js'; +import { resolveJSON } from './resolve.js'; describe('download operator', function () { beforeEach(function () { @@ -28,7 +29,7 @@ describe('download operator', function () { test('successfull download', () => new Promise(done => { of('https://httpbin.org/my-url-fast') - .pipe(downloadJSON(), log(false)) + .pipe(download(), log(false), resolveJSON(), log(false)) .subscribe({ next: data => { expect(data).deep.equal({ hello: 'fast world' }); diff --git a/packages/operators/src/fetch/request.js b/packages/operators/src/fetch/request.js index e54f231..b241259 100644 --- a/packages/operators/src/fetch/request.js +++ b/packages/operators/src/fetch/request.js @@ -1,11 +1,13 @@ import { concatMap } from 'rxjs'; +import { log } from '../log'; import { networkRetry } from './retry'; export const request = () => { return source => source.pipe( concatMap(req => fetch(req)), + log(false), networkRetry() ); }; From c56babbc77214eb589f5c0ef2e4ed8e854f0892c Mon Sep 17 00:00:00 2001 From: StephanGerbeth Date: Thu, 24 Oct 2024 16:43:42 +0200 Subject: [PATCH 4/7] fix(fetch): cleanup --- packages/operators/src/fetch/autoPagination.js | 2 +- packages/operators/src/fetch/lazyPagination.test.js | 2 +- packages/operators/src/fetch/retry.js | 10 ++++------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/operators/src/fetch/autoPagination.js b/packages/operators/src/fetch/autoPagination.js index d6ec57e..6c2b635 100644 --- a/packages/operators/src/fetch/autoPagination.js +++ b/packages/operators/src/fetch/autoPagination.js @@ -9,7 +9,7 @@ export const autoPagination = ({ resolveRoute }) => { return from(resolveRoute(url)).pipe( download(), expand(resp => { - return from(resolveRoute(url, resp.clone())).pipe( + return from(resolveRoute(url, resp)).pipe( filter(url => !!url), download() ); diff --git a/packages/operators/src/fetch/lazyPagination.test.js b/packages/operators/src/fetch/lazyPagination.test.js index 9bf49d9..7abacc2 100644 --- a/packages/operators/src/fetch/lazyPagination.test.js +++ b/packages/operators/src/fetch/lazyPagination.test.js @@ -39,7 +39,7 @@ describe('lazy pagination operator', function () { pager.next({ value: 2 }); pager.next({ value: 3 }); - pager.next({ value: 4 }); + pager.next({ value: 12 }); pager.next({ value: 5 }); pager.next({ value: 6 }); pager.next({ value: 7 }); diff --git a/packages/operators/src/fetch/retry.js b/packages/operators/src/fetch/retry.js index 3d7666e..c9f6382 100644 --- a/packages/operators/src/fetch/retry.js +++ b/packages/operators/src/fetch/retry.js @@ -30,15 +30,13 @@ export const networkRetry = ({ timeout = defaultTimeout, count } = {}) => { count, delay: () => { return combineLatest([connectionObservable]).pipe( + // all defined observables have to be valid map(values => values.every(v => v === true)), + // reset counter if one observable is invalid tap(valid => (counter = counter * valid)), + // continue only if all observables are valid filter(valid => valid), - tap(() => { - console.log(timeout(counter)); - console.log( - `retry: request - next: ${counter + 1} in ${timeout(counter + 1) || timeout}s` - ); - }), + tap(() => console.log(`retry: request - next: ${counter} in ${timeout(counter)}s`)), delay(timeout(counter++) || timeout) ); } From 522f2ca06ea0d1141d596f31e9b626cfb71e8f31 Mon Sep 17 00:00:00 2001 From: StephanGerbeth Date: Thu, 24 Oct 2024 17:10:55 +0200 Subject: [PATCH 5/7] fix(fetch): cleanup --- packages/operators/src/fetch/download.test.js | 14 +++++++++++++- packages/operators/src/fetch/upload.js | 2 -- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/operators/src/fetch/download.test.js b/packages/operators/src/fetch/download.test.js index cce43c9..f10f21b 100644 --- a/packages/operators/src/fetch/download.test.js +++ b/packages/operators/src/fetch/download.test.js @@ -26,7 +26,7 @@ describe('download operator', function () { fetchMock.restore(); }); - test('successfull download', () => + test('successfull download - indirect json resolve', () => new Promise(done => { of('https://httpbin.org/my-url-fast') .pipe(download(), log(false), resolveJSON(), log(false)) @@ -37,4 +37,16 @@ describe('download operator', function () { complete: e => done() }); })); + + test('successfull download - direct json resolve', () => + new Promise(done => { + of('https://httpbin.org/my-url-fast') + .pipe(downloadJSON(), log(false)) + .subscribe({ + next: data => { + expect(data).deep.equal({ hello: 'fast world' }); + }, + complete: () => done() + }); + })); }); diff --git a/packages/operators/src/fetch/upload.js b/packages/operators/src/fetch/upload.js index a7c09da..5f8f023 100644 --- a/packages/operators/src/fetch/upload.js +++ b/packages/operators/src/fetch/upload.js @@ -1,5 +1,3 @@ -import { concatMap, of } from 'rxjs'; - import { request } from './request'; export const upload = () => { From cc64c1631007c1ab659a4f559b4e946dc3f682ab Mon Sep 17 00:00:00 2001 From: StephanGerbeth Date: Thu, 24 Oct 2024 22:59:32 +0200 Subject: [PATCH 6/7] fix(fetch): polling completed and cleanup of operators --- package-lock.json | 209 +++++++++--------- package.json | 2 +- packages/operators/package.json | 1 + .../operators/src/fetch/autoPagination.js | 8 +- packages/operators/src/fetch/download.test.js | 30 +-- packages/operators/src/fetch/polling.js | 20 +- packages/operators/src/fetch/polling.test.js | 41 ++-- packages/operators/src/fetch/request.js | 2 - packages/operators/src/fetch/request.test.js | 8 +- packages/operators/src/fetch/resolve.test.js | 37 ++++ packages/operators/src/fetch/response.js | 11 + packages/operators/src/fetch/response.test.js | 39 ++++ packages/operators/src/fetch/retry.js | 14 +- 13 files changed, 248 insertions(+), 174 deletions(-) create mode 100644 packages/operators/src/fetch/resolve.test.js create mode 100644 packages/operators/src/fetch/response.js create mode 100644 packages/operators/src/fetch/response.test.js diff --git a/package-lock.json b/package-lock.json index 18766a4..8b9ed86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,7 @@ "eslint-plugin-prettier": "5.2.1", "eslint-plugin-security": "3.0.1", "eslint-plugin-vitest": "0.5.4", - "fetch-mock": "11.1.3", + "fetch-mock": "12.0.0", "happy-dom": "15.7.4", "husky": "9.1.6", "lint-staged": "15.2.10", @@ -1485,224 +1485,208 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.3.tgz", - "integrity": "sha512-MmKSfaB9GX+zXl6E8z4koOr/xU63AMVleLEa64v7R0QF/ZloMs5vcD1sHgM64GXXS1csaJutG+ddtzcueI/BLg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", "cpu": [ "arm" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.3.tgz", - "integrity": "sha512-zrt8ecH07PE3sB4jPOggweBjJMzI1JG5xI2DIsUbkA+7K+Gkjys6eV7i9pOenNSDJH3eOr/jLb/PzqtmdwDq5g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.3.tgz", - "integrity": "sha512-P0UxIOrKNBFTQaXTxOH4RxuEBVCgEA5UTNV6Yz7z9QHnUJ7eLX9reOd/NYMO3+XZO2cco19mXTxDMXxit4R/eQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.3.tgz", - "integrity": "sha512-L1M0vKGO5ASKntqtsFEjTq/fD91vAqnzeaF6sfNAy55aD+Hi2pBI5DKwCO+UNDQHWsDViJLqshxOahXyLSh3EA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.3.tgz", - "integrity": "sha512-btVgIsCjuYFKUjopPoWiDqmoUXQDiW2A4C3Mtmp5vACm7/GnyuprqIDPNczeyR5W8rTXEbkmrJux7cJmD99D2g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", "cpu": [ "arm" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.3.tgz", - "integrity": "sha512-zmjbSphplZlau6ZTkxd3+NMtE4UKVy7U4aVFMmHcgO5CUbw17ZP6QCgyxhzGaU/wFFdTfiojjbLG3/0p9HhAqA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", "cpu": [ "arm" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.3.tgz", - "integrity": "sha512-nSZfcZtAnQPRZmUkUQwZq2OjQciR6tEoJaZVFvLHsj0MF6QhNMg0fQ6mUOsiCUpTqxTx0/O6gX0V/nYc7LrgPw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.3.tgz", - "integrity": "sha512-MnvSPGO8KJXIMGlQDYfvYS3IosFN2rKsvxRpPO2l2cum+Z3exiExLwVU+GExL96pn8IP+GdH8Tz70EpBhO0sIQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.3.tgz", - "integrity": "sha512-+W+p/9QNDr2vE2AXU0qIy0qQE75E8RTwTwgqS2G5CRQ11vzq0tbnfBd6brWhS9bCRjAjepJe2fvvkvS3dno+iw==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", "cpu": [ "ppc64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.3.tgz", - "integrity": "sha512-yXH6K6KfqGXaxHrtr+Uoy+JpNlUlI46BKVyonGiaD74ravdnF9BUNC+vV+SIuB96hUMGShhKV693rF9QDfO6nQ==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", "cpu": [ "riscv64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.3.tgz", - "integrity": "sha512-R8cwY9wcnApN/KDYWTH4gV/ypvy9yZUHlbJvfaiXSB48JO3KpwSpjOGqO4jnGkLDSk1hgjYkTbTt6Q7uvPf8eg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", "cpu": [ "s390x" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.3.tgz", - "integrity": "sha512-kZPbX/NOPh0vhS5sI+dR8L1bU2cSO9FgxwM8r7wHzGydzfSjLRCFAT87GR5U9scj2rhzN3JPYVC7NoBbl4FZ0g==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.3.tgz", - "integrity": "sha512-S0Yq+xA1VEH66uiMNhijsWAafffydd2X5b77eLHfRmfLsRSpbiAWiRHV6DEpz6aOToPsgid7TI9rGd6zB1rhbg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.3.tgz", - "integrity": "sha512-9isNzeL34yquCPyerog+IMCNxKR8XYmGd0tHSV+OVx0TmE0aJOo9uw4fZfUuk2qxobP5sug6vNdZR6u7Mw7Q+Q==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", "cpu": [ "arm64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.3.tgz", - "integrity": "sha512-nMIdKnfZfzn1Vsk+RuOvl43ONTZXoAPUUxgcU0tXooqg4YrAqzfKzVenqqk2g5efWh46/D28cKFrOzDSW28gTA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", "cpu": [ "ia32" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.3.tgz", - "integrity": "sha512-fOvu7PCQjAj4eWDEuD8Xz5gpzFqXzGlxHZozHP4b9Jxv9APtdxL6STqztDzMLuRXEc4UpXGGhx029Xgm91QBeA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", "cpu": [ "x64" ], "dev": true, - "license": "MIT", "optional": true, "os": [ "win32" @@ -2192,11 +2176,10 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "license": "MIT" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true }, "node_modules/@types/glob-to-regexp": { "version": "0.4.4", @@ -4706,6 +4689,14 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/fast-equals": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", + "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -4792,25 +4783,19 @@ } }, "node_modules/fetch-mock": { - "version": "11.1.3", - "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-11.1.3.tgz", - "integrity": "sha512-ATh0dWgnVrUHiiXuvQm1Ry+ThWfSv1QQgqJTCtybrNxyUrFiSOaDKsNG29eyysp1SHeNP6Q+dH50+8VifN51Ig==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-12.0.0.tgz", + "integrity": "sha512-JSsjzoRN4rYqHa2/+8ushJGDsK9HGNTdBZo6Hrpu3KFN7Y03nRCt2VJ2WG4OUvyTUukOQ4TQIfjcFcEkMPGZ0Q==", "dev": true, - "license": "MIT", "dependencies": { "@types/glob-to-regexp": "^0.4.4", "dequal": "^2.0.3", "glob-to-regexp": "^0.4.1", - "is-subset": "^0.1.1", + "is-subset-of": "^3.1.10", "regexparam": "^3.0.0" }, "engines": { - "node": ">=8.0.0" - }, - "peerDependenciesMeta": { - "node-fetch": { - "optional": true - } + "node": ">=18.11.0" } }, "node_modules/figures": { @@ -5766,12 +5751,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==", + "node_modules/is-subset-of": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/is-subset-of/-/is-subset-of-3.1.10.tgz", + "integrity": "sha512-avvaYgVmYWyaZ1NDFiv4y9JGkrE2je3op1Po4VYKKJKR8H2qVPsg1GZuuXl5elCTxTlwAIsrAjWAs4BVrISFRw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dev": true, - "license": "MIT" + "dependencies": { + "typedescriptor": "3.0.2" + } }, "node_modules/is-text-path": { "version": "2.0.0", @@ -10447,13 +10435,12 @@ } }, "node_modules/rollup": { - "version": "4.21.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.3.tgz", - "integrity": "sha512-7sqRtBNnEbcBtMeRVc6VRsJMmpI+JU1z9VTvW8D4gXIYQFz0aLcsE6rRkyghZkLfEgUZgVvOG7A5CVz/VW5GIA==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", "dev": true, - "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -10463,22 +10450,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.21.3", - "@rollup/rollup-android-arm64": "4.21.3", - "@rollup/rollup-darwin-arm64": "4.21.3", - "@rollup/rollup-darwin-x64": "4.21.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.21.3", - "@rollup/rollup-linux-arm-musleabihf": "4.21.3", - "@rollup/rollup-linux-arm64-gnu": "4.21.3", - "@rollup/rollup-linux-arm64-musl": "4.21.3", - "@rollup/rollup-linux-powerpc64le-gnu": "4.21.3", - "@rollup/rollup-linux-riscv64-gnu": "4.21.3", - "@rollup/rollup-linux-s390x-gnu": "4.21.3", - "@rollup/rollup-linux-x64-gnu": "4.21.3", - "@rollup/rollup-linux-x64-musl": "4.21.3", - "@rollup/rollup-win32-arm64-msvc": "4.21.3", - "@rollup/rollup-win32-ia32-msvc": "4.21.3", - "@rollup/rollup-win32-x64-msvc": "4.21.3", + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", "fsevents": "~2.3.2" } }, @@ -11986,6 +11973,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typedescriptor": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/typedescriptor/-/typedescriptor-3.0.2.tgz", + "integrity": "sha512-hyVbaCUd18UiXk656g/imaBLMogpdijIEpnhWYrSda9rhvO4gOU16n2nh7xG5lv/rjumnZzGOdz0CEGTmFe0fQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true + }, "node_modules/typescript": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", @@ -12710,6 +12704,7 @@ "license": "MIT", "dependencies": { "@rxjs-collection/observables": "*", + "fast-equals": "^5.0.1", "rxjs": "7.8.1" }, "devDependencies": { diff --git a/package.json b/package.json index 128c620..93e885a 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "eslint-plugin-prettier": "5.2.1", "eslint-plugin-security": "3.0.1", "eslint-plugin-vitest": "0.5.4", - "fetch-mock": "11.1.3", + "fetch-mock": "12.0.0", "happy-dom": "15.7.4", "husky": "9.1.6", "lint-staged": "15.2.10", diff --git a/packages/operators/package.json b/packages/operators/package.json index 4b310e3..7808bca 100644 --- a/packages/operators/package.json +++ b/packages/operators/package.json @@ -19,6 +19,7 @@ }, "dependencies": { "@rxjs-collection/observables": "*", + "fast-equals": "^5.0.1", "rxjs": "7.8.1" }, "devDependencies": { diff --git a/packages/operators/src/fetch/autoPagination.js b/packages/operators/src/fetch/autoPagination.js index 6c2b635..8ebd1ba 100644 --- a/packages/operators/src/fetch/autoPagination.js +++ b/packages/operators/src/fetch/autoPagination.js @@ -8,12 +8,12 @@ export const autoPagination = ({ resolveRoute }) => { concatMap(({ url }) => { return from(resolveRoute(url)).pipe( download(), - expand(resp => { - return from(resolveRoute(url, resp)).pipe( + expand(resp => + from(resolveRoute(url, resp)).pipe( filter(url => !!url), download() - ); - }) + ) + ) ); }), map(resp => resp.clone()) diff --git a/packages/operators/src/fetch/download.test.js b/packages/operators/src/fetch/download.test.js index f10f21b..b777e4f 100644 --- a/packages/operators/src/fetch/download.test.js +++ b/packages/operators/src/fetch/download.test.js @@ -8,22 +8,20 @@ import { resolveJSON } from './resolve.js'; describe('download operator', function () { beforeEach(function () { - fetchMock.get( + fetchMock.mockGlobal().get( 'https://httpbin.org/my-url-fast', - new Response(JSON.stringify({ hello: 'fast world' }), { - status: 200, - headers: { - 'Content-type': 'application/json' - } - }), - { - delay: 1000 - } + () => { + return new Response(JSON.stringify({ hello: 'fast world' }), { + status: 200, + headers: { 'Content-type': 'application/json' } + }); + }, + { delay: 1000 } ); }); afterEach(function () { - fetchMock.restore(); + fetchMock.unmockGlobal(); }); test('successfull download - indirect json resolve', () => @@ -31,10 +29,8 @@ describe('download operator', function () { of('https://httpbin.org/my-url-fast') .pipe(download(), log(false), resolveJSON(), log(false)) .subscribe({ - next: data => { - expect(data).deep.equal({ hello: 'fast world' }); - }, - complete: e => done() + next: data => expect(data).deep.equal({ hello: 'fast world' }), + complete: () => done() }); })); @@ -43,9 +39,7 @@ describe('download operator', function () { of('https://httpbin.org/my-url-fast') .pipe(downloadJSON(), log(false)) .subscribe({ - next: data => { - expect(data).deep.equal({ hello: 'fast world' }); - }, + next: data => expect(data).deep.equal({ hello: 'fast world' }), complete: () => done() }); })); diff --git a/packages/operators/src/fetch/polling.js b/packages/operators/src/fetch/polling.js index 737c501..12d3821 100644 --- a/packages/operators/src/fetch/polling.js +++ b/packages/operators/src/fetch/polling.js @@ -1,20 +1,14 @@ -import { concatMap, delay as delayOperator, EMPTY, expand, of } from 'rxjs'; +import { delay, expand, of } from 'rxjs'; +import { log } from '../log'; import { download } from './download'; +import { distinctUntilResponseChanged } from './response'; -export const polling = ({ validateResult, delay = 1000 }) => { +export const polling = (timeout = 1000) => { return source => source.pipe( - concatMap(({ url }) => { - return of(url).pipe( - download(), - expand(data => { - if (validateResult(data)) { - return of(url).pipe(delayOperator(delay), download()); - } - return EMPTY; - }) - ); - }) + download(), + expand(resp => of(resp.url).pipe(delay(timeout), download())), + distinctUntilResponseChanged() ); }; diff --git a/packages/operators/src/fetch/polling.test.js b/packages/operators/src/fetch/polling.test.js index 076c96a..81725f0 100644 --- a/packages/operators/src/fetch/polling.test.js +++ b/packages/operators/src/fetch/polling.test.js @@ -1,27 +1,40 @@ -import { concatAll, map, of } from 'rxjs'; -import { beforeEach, describe, expect, test } from 'vitest'; +import fetchMock from 'fetch-mock'; +import { of, take } from 'rxjs'; +import { afterEach, beforeEach, describe, expect, test } from 'vitest'; +import { log } from '../log'; import { polling } from './polling'; +import { resolveJSON } from './resolve'; describe('polling', function () { beforeEach(function () { - // + let counter = 0; + fetchMock.mockGlobal().get('https://httpbin.org/my-url-fast', () => { + if (counter++ < 2) { + return new Response(JSON.stringify({ hello: 'fast world' }), { + status: 200, + headers: { 'Content-type': 'application/json' } + }); + } + return new Response(JSON.stringify({ hello: 'faster world' }), { + status: 200, + headers: { 'Content-type': 'application/json' } + }); + }); + }); + + afterEach(function () { + fetchMock.unmockGlobal(); }); test('auto polling', async function () { + const expected = [{ hello: 'fast world' }, { hello: 'faster world' }]; + return new Promise(done => { - of({ url: new URL('https://dummyjson.com/products') }) - .pipe( - polling({ - validateResult: data => { - return data.total > data.skip + data.limit; - } - }) - // map(({ data: { products } }) => products), - // concatAll() - ) + of(new URL('https://httpbin.org/my-url-fast')) + .pipe(polling(), log(false), resolveJSON(), log(false), take(2)) .subscribe({ - next: e => console.log('aha'), + next: e => expect(e).deep.include(expected.shift()), complete: () => done() }); }); diff --git a/packages/operators/src/fetch/request.js b/packages/operators/src/fetch/request.js index b241259..e54f231 100644 --- a/packages/operators/src/fetch/request.js +++ b/packages/operators/src/fetch/request.js @@ -1,13 +1,11 @@ import { concatMap } from 'rxjs'; -import { log } from '../log'; import { networkRetry } from './retry'; export const request = () => { return source => source.pipe( concatMap(req => fetch(req)), - log(false), networkRetry() ); }; diff --git a/packages/operators/src/fetch/request.test.js b/packages/operators/src/fetch/request.test.js index 4eb91a5..2d88eba 100644 --- a/packages/operators/src/fetch/request.test.js +++ b/packages/operators/src/fetch/request.test.js @@ -8,7 +8,7 @@ import { request } from './request.js'; describe('request observable with default operators', function () { beforeEach(function () { let counter = 0; - fetchMock.get( + fetchMock.mockGlobal().get( 'https://httpbin.org/my-url-fast', () => { return new Response(JSON.stringify({ hello: 'fast world' }), { @@ -21,7 +21,7 @@ describe('request observable with default operators', function () { }); afterEach(function () { - fetchMock.restore(); + fetchMock.unmockGlobal(); }); test('successfull request', () => @@ -29,9 +29,7 @@ describe('request observable with default operators', function () { of('https://httpbin.org/my-url-fast') .pipe(request(), log(false)) .subscribe({ - next: resp => { - expect(resp).deep.includes({ ok: true }); - }, + next: resp => expect(resp).deep.includes({ ok: true }), complete: () => done() }); })); diff --git a/packages/operators/src/fetch/resolve.test.js b/packages/operators/src/fetch/resolve.test.js new file mode 100644 index 0000000..1a64d5a --- /dev/null +++ b/packages/operators/src/fetch/resolve.test.js @@ -0,0 +1,37 @@ +import { of } from 'rxjs'; +import { afterEach, test, describe, beforeEach, expect } from 'vitest'; + +import { log } from '../log'; +import { resolveJSON, resolveText } from './resolve'; + +describe('resolver', function () { + beforeEach(function () { + // + }); + + afterEach(function () { + // + }); + + test('resolve json', () => { + return new Promise(done => { + of(new Response(JSON.stringify({ hello: 'world' }))) + .pipe(resolveJSON(), log(false)) + .subscribe({ + next: e => expect(e).includes({ hello: 'world' }), + complete: () => done() + }); + }); + }); + + test('resolve text', () => { + return new Promise(done => { + of(new Response('hello world')) + .pipe(resolveText(), log(false)) + .subscribe({ + next: e => expect(e).toBe('hello world'), + complete: () => done() + }); + }); + }); +}); diff --git a/packages/operators/src/fetch/response.js b/packages/operators/src/fetch/response.js new file mode 100644 index 0000000..c809d08 --- /dev/null +++ b/packages/operators/src/fetch/response.js @@ -0,0 +1,11 @@ +import { shallowEqual } from 'fast-equals'; +import { concatMap, distinctUntilChanged, map } from 'rxjs'; + +export const distinctUntilResponseChanged = () => { + return source => + source.pipe( + concatMap(async resp => [resp, await resp.clone().arrayBuffer()]), + distinctUntilChanged(([, a], [, b]) => shallowEqual(new Uint8Array(a), new Uint8Array(b))), + map(([resp]) => resp.clone()) + ); +}; diff --git a/packages/operators/src/fetch/response.test.js b/packages/operators/src/fetch/response.test.js new file mode 100644 index 0000000..d3c27bc --- /dev/null +++ b/packages/operators/src/fetch/response.test.js @@ -0,0 +1,39 @@ +import { of } from 'rxjs'; +import { afterEach, test, describe, beforeEach, expect } from 'vitest'; + +import { log } from '../log'; +import { resolveText } from './resolve'; +import { distinctUntilResponseChanged } from './response'; + +describe('response', function () { + beforeEach(function () { + // + }); + + afterEach(function () { + // + }); + + test('emit only changed responses', () => { + const triggerValues = [ + new Response('a'), + new Response('a'), + new Response('b'), + new Response('b'), + new Response('c'), + new Response('a'), + new Response('a'), + new Response('b') + ]; + const expectedValues = ['a', 'b', 'c', 'a', 'b']; + + return new Promise(done => { + of(...triggerValues) + .pipe(distinctUntilResponseChanged(), log(false), resolveText(), log(false)) + .subscribe({ + next: e => expect(e).toBe(expectedValues.shift()), + complete: () => done() + }); + }); + }); +}); diff --git a/packages/operators/src/fetch/retry.js b/packages/operators/src/fetch/retry.js index c9f6382..81f67c7 100644 --- a/packages/operators/src/fetch/retry.js +++ b/packages/operators/src/fetch/retry.js @@ -20,16 +20,11 @@ export const networkRetry = ({ timeout = defaultTimeout, count } = {}) => { return source => { return source.pipe( - concatMap(resp => { - if (!resp.ok) { - return throwError(() => new Error('invalid request')); - } - return of(resp); - }), + concatMap(resp => (!resp.ok && throwError(() => new Error('invalid request'))) || of(resp)), retry({ count, - delay: () => { - return combineLatest([connectionObservable]).pipe( + delay: () => + combineLatest([connectionObservable]).pipe( // all defined observables have to be valid map(values => values.every(v => v === true)), // reset counter if one observable is invalid @@ -38,8 +33,7 @@ export const networkRetry = ({ timeout = defaultTimeout, count } = {}) => { filter(valid => valid), tap(() => console.log(`retry: request - next: ${counter} in ${timeout(counter)}s`)), delay(timeout(counter++) || timeout) - ); - } + ) }), catchError(e => console.error(e)) ); From 3ef05aa55345da1dd4dec416bb17554d5c457743 Mon Sep 17 00:00:00 2001 From: StephanGerbeth Date: Thu, 24 Oct 2024 23:05:29 +0200 Subject: [PATCH 7/7] fix(fetch): added logs to test and cleanup --- packages/operators/src/fetch/concurrentDownload.test.js | 3 +++ packages/operators/src/fetch/polling.js | 1 - packages/operators/src/fetch/retry.test.js | 7 ++++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/operators/src/fetch/concurrentDownload.test.js b/packages/operators/src/fetch/concurrentDownload.test.js index 0510bb9..acfd542 100644 --- a/packages/operators/src/fetch/concurrentDownload.test.js +++ b/packages/operators/src/fetch/concurrentDownload.test.js @@ -1,6 +1,7 @@ import { concatAll, map, of } from 'rxjs'; import { beforeEach, describe, expect, test } from 'vitest'; +import { log } from '../log'; import { concurrentDownload } from './concurrentDownload'; import { resolveJSON } from './resolve'; @@ -24,7 +25,9 @@ describe('multi fetch', function () { ) .pipe( concurrentDownload(4), + log(false), resolveJSON(), + log(false), map(({ products }) => products), concatAll() ) diff --git a/packages/operators/src/fetch/polling.js b/packages/operators/src/fetch/polling.js index 12d3821..fd4ccd1 100644 --- a/packages/operators/src/fetch/polling.js +++ b/packages/operators/src/fetch/polling.js @@ -1,6 +1,5 @@ import { delay, expand, of } from 'rxjs'; -import { log } from '../log'; import { download } from './download'; import { distinctUntilResponseChanged } from './response'; diff --git a/packages/operators/src/fetch/retry.test.js b/packages/operators/src/fetch/retry.test.js index f02ff37..f9854b2 100644 --- a/packages/operators/src/fetch/retry.test.js +++ b/packages/operators/src/fetch/retry.test.js @@ -16,9 +16,10 @@ describe('request retry', function () { test('network retry', async function () { let counter = 0; - const mockObservable = of(null) - .pipe(map(() => ({ ok: !(++counter < 3) }))) - .pipe(networkRetry({ timeout: () => 1000 })); + const mockObservable = of(null).pipe( + map(() => ({ ok: !(++counter < 3) })), + networkRetry({ timeout: () => 1000 }) + ); testScheduler.run(({ expectObservable }) => { expectObservable(mockObservable).toBe('2000ms (a|)', {