{"_id":"snapreq","_rev":"14-e49e149ea3eb0c8dff2bc9cc2333fa9f","name":"snapreq","dist-tags":{"latest":"0.0.17"},"versions":{"0.0.1":{"name":"snapreq","version":"0.0.1","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","_id":"snapreq@0.0.1","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"dist":{"shasum":"b1c0cc775c57d8f3f29d8dffcab2480cb695fcc8","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.1.tgz","fileCount":17,"integrity":"sha512-C7GJ0B/VOcFOrJGp/UrYlKFyrp7laTL4ho8kr5YTtnHqU2R+/Zb5obku71QE7jMtzGBczw/xwMxJiH3+rFhq1w==","signatures":[{"sig":"MEUCIQDV6o78N5e0YkCtQcEhXVdGdVR+40ruuSZE3ZC1K1wuzgIgb6GafoWolHFnf4KSUZhXQg7/iG2K70CjvXqgV31UL5c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":101544},"main":"src/index.js","type":"module","exports":{".":"./src/index.js"},"gitHead":"5e4acec4b26bbe0a6051f56124ffce59c9cbe42f","scripts":{"lint":"eslint src spec","test":"node --test \"spec/**/*-spec.js\"","typecheck":"tsc --noEmit"},"_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"_npmVersion":"11.14.1","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"_nodeVersion":"24.14.1","_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^16.0.0","@types/ws":"^8.18.1","@eslint/js":"^9.0.0","typescript":"^6.0.3","@types/node":"^22.0.0","eslint-plugin-jsdoc":"^62.9.0"},"_npmOperationalInternal":{"tmp":"tmp/snapreq_0.0.1_1779641919576_0.9430626025655235","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"snapreq","version":"0.0.3","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","_id":"snapreq@0.0.3","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"dist":{"shasum":"400edf4d03defeec433952c4cef3da719b4b39a9","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.3.tgz","fileCount":30,"integrity":"sha512-QjKiQXhcMwj/exUopcfvQqFzW7M8BN35A7BolCemEDd+McchWm6Jh81tTu2RVfQ8UdQKlO48MVia1MZsUSIcWg==","signatures":[{"sig":"MEUCIQDQ7/OhTvSsmu7eJtaDCgNhMxxduD1fs3oCvpPf8ejN7wIgFCgh2n3DbQ/YqQLbihRbs8CC2tPqB1t8CqWaKkJN2XY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":162063},"main":"./src/snap-req.js","type":"module","types":"./types/snap-req.d.ts","exports":{".":{"types":"./types/snap-req.d.ts","default":"./src/snap-req.js"},"./*":{"types":"./types/*.d.ts","default":"./src/*.js"},"./retry":{"types":"./types/retry.d.ts","default":"./src/retry.js"},"./errors":{"types":"./types/errors.d.ts","default":"./src/errors.js"},"./headers":{"types":"./types/headers.d.ts","default":"./src/headers.js"},"./response":{"types":"./types/response.d.ts","default":"./src/response.js"},"./websocket":{"types":"./types/websocket/websocket-client.d.ts","default":"./src/websocket/websocket-client.js"},"./capabilities":{"types":"./types/capabilities.d.ts","default":"./src/capabilities.js"},"./transports/xhr":{"types":"./types/transports/xhr-transport.d.ts","default":"./src/transports/xhr-transport.js"},"./transports/fetch":{"types":"./types/transports/fetch-transport.d.ts","default":"./src/transports/fetch-transport.js"},"./transports/select":{"types":"./types/transports/select.d.ts","default":"./src/transports/select.js"}},"gitHead":"943b6c0eec534f0b3afe1fccc6406e5dd0caff7b","scripts":{"lint":"eslint src spec","test":"node --test \"spec/**/*-spec.js\"","typecheck":"tsc --noEmit","all-checks":"npm run typecheck && npm run lint && npm run test","build:types":"tsc -p tsconfig.build.json","release:patch":"release-patch","prepublishOnly":"npm run build:types"},"_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"_npmVersion":"11.14.1","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"_nodeVersion":"24.14.1","_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^16.0.0","@types/ws":"^8.18.1","@eslint/js":"^9.0.0","typescript":"^6.0.3","@types/node":"^22.0.0","release-patch":"^1.0.0","eslint-plugin-jsdoc":"^62.9.0"},"_npmOperationalInternal":{"tmp":"tmp/snapreq_0.0.3_1779643672883_0.6558527459263686","host":"s3://npm-registry-packages-npm-production"}},"0.0.4":{"name":"snapreq","version":"0.0.4","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","_id":"snapreq@0.0.4","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"dist":{"shasum":"17df4885b79de07d3bc28e77c9cb99c2d2490c3b","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.4.tgz","fileCount":30,"integrity":"sha512-T0ZDibgnVkWQEus15Yr1OPURc6rls/XnKvsM+JgnWjOL/IrvaJq70J99SfkmzLnNC8nPahccoK7hlPR/28ZEpw==","signatures":[{"sig":"MEUCIAScK1Lc2ABglhhGS7iUPi6HSbfisXr+on9i4AJIjG2uAiEA2UWYCuAcnJNEsEKwfoiJb/pfu7f1hgWURCd3sCEthMU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":174240},"main":"./src/snap-req.js","type":"module","types":"./types/snap-req.d.ts","exports":{".":{"types":"./types/snap-req.d.ts","default":"./src/snap-req.js"},"./*":{"types":"./types/*.d.ts","default":"./src/*.js"},"./retry":{"types":"./types/retry.d.ts","default":"./src/retry.js"},"./errors":{"types":"./types/errors.d.ts","default":"./src/errors.js"},"./headers":{"types":"./types/headers.d.ts","default":"./src/headers.js"},"./response":{"types":"./types/response.d.ts","default":"./src/response.js"},"./websocket":{"types":"./types/websocket/websocket-client.d.ts","default":"./src/websocket/websocket-client.js"},"./capabilities":{"types":"./types/capabilities.d.ts","default":"./src/capabilities.js"},"./transports/xhr":{"types":"./types/transports/xhr-transport.d.ts","default":"./src/transports/xhr-transport.js"},"./transports/fetch":{"types":"./types/transports/fetch-transport.d.ts","default":"./src/transports/fetch-transport.js"},"./transports/select":{"types":"./types/transports/select.d.ts","default":"./src/transports/select.js"}},"gitHead":"2c62757b989bf87e8c09f4fc99870a19f88d3303","scripts":{"lint":"eslint src spec","test":"node --test \"spec/**/*-spec.js\"","typecheck":"tsc --noEmit","all-checks":"npm run typecheck && npm run lint && npm run test","build:types":"tsc -p tsconfig.build.json","release:patch":"release-patch","prepublishOnly":"npm run build:types"},"_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"_npmVersion":"11.15.0","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"_nodeVersion":"25.8.1","_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^17.6.0","@types/ws":"^8.18.1","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^25.9.1","release-patch":"^1.0.0","eslint-plugin-jsdoc":"^63.0.0"},"_npmOperationalInternal":{"tmp":"tmp/snapreq_0.0.4_1779868417228_0.45357044184782724","host":"s3://npm-registry-packages-npm-production"}},"0.0.5":{"name":"snapreq","version":"0.0.5","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","_id":"snapreq@0.0.5","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"dist":{"shasum":"8ce1276d9ab95fb024890de824d07176efae47c5","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.5.tgz","fileCount":56,"integrity":"sha512-XDePqrCqE3+ZT4hmrtd62tgnEEzRtwv8hxjU4vyLDJ5XOgGjBwb3f+WcxWpzNbUOBr5EP4j2ukTrUoH95EdHrQ==","signatures":[{"sig":"MEUCIDqnZeTo/rxUZrpFS252X4s/4y9jzaPgWBFmLEWqPzBLAiEA2sewncXEXeMRzQrAlD5e/D0P19jJpWVQE6UgxkiMD6g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":313258},"main":"./build/snap-req.js","type":"module","types":"./build/snap-req.d.ts","exports":{".":{"types":"./build/snap-req.d.ts","default":"./build/snap-req.js"},"./*":{"types":"./build/*.d.ts","default":"./build/*.js"}},"gitHead":"d051a9a672c827428509d3eb47933fd2859b5855","scripts":{"lint":"eslint src spec","test":"npm run build && node --test \"spec/**/*-spec.js\"","build":"rm -rf build && tsc","prepare":"npm run build","typecheck":"tsc --noEmit","all-checks":"npm run typecheck && npm run lint && npm run test","release:patch":"release-patch","prepublishOnly":"npm run build"},"_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"_npmVersion":"11.16.0","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"_nodeVersion":"25.8.1","_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^17.6.0","@types/ws":"^8.18.1","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^25.9.1","release-patch":"^1.0.0","eslint-plugin-jsdoc":"^63.0.0"},"_npmOperationalInternal":{"tmp":"tmp/snapreq_0.0.5_1780379919038_0.23055130038936844","host":"s3://npm-registry-packages-npm-production"}},"0.0.8":{"name":"snapreq","version":"0.0.8","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","_id":"snapreq@0.0.8","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"dist":{"shasum":"b5d48f24dd48d6936eee5cb3ea590132b280d4a8","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.8.tgz","fileCount":56,"integrity":"sha512-S7ecgyOBPI4bkiJ8TrMPsbfA0aN8brWvBZo+Hsoy1bVSJUp3kNi4EzZtoZPUXdHe+Ej1IvbydhKP7lNFnP+yfg==","signatures":[{"sig":"MEYCIQDGuIhPbjQF+tnrsXoaIabtcuIeZDoeNpKhzVpIudjfhAIhAKofmYPj3S9zIQunK0whJMVMNVhVgNQkFzxK+MKmjw20","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":316141},"main":"./build/snap-req.js","type":"module","types":"./build/snap-req.d.ts","exports":{".":{"types":"./build/snap-req.d.ts","default":"./build/snap-req.js"},"./*":{"types":"./build/*.d.ts","default":"./build/*.js"}},"gitHead":"cd5dd30d4c4d8a792e7e8b0027f4cd463c75de10","scripts":{"lint":"npm run eslint && npm run typecheck","test":"npm run build && node --test \"spec/**/*-spec.js\"","build":"rm -rf build && tsc","eslint":"eslint src spec","prepare":"npm run build","typecheck":"tsc --noEmit","all-checks":"npm run typecheck && npm run lint && npm run test","release:patch":"release-patch","prepublishOnly":"npm run build"},"_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"_npmVersion":"11.16.0","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"_nodeVersion":"25.9.0","_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^17.6.0","@types/ws":"^8.18.1","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^25.9.1","release-patch":"^1.0.0","eslint-plugin-jsdoc":"^63.0.0"},"_npmOperationalInternal":{"tmp":"tmp/snapreq_0.0.8_1781759529053_0.003369082922111577","host":"s3://npm-registry-packages-npm-production"}},"0.0.9":{"name":"snapreq","version":"0.0.9","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","_id":"snapreq@0.0.9","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"dist":{"shasum":"1932046f70757b7351e33b741dc6152d178c49b5","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.9.tgz","fileCount":56,"integrity":"sha512-KRqZ9TxIUJPfwr9ecO5o0iMKKx5JvzeenjqsWjwJbFNMxI3QRuk0u4AuyhLWb3ahsv4LmVW1TKeqcZSBAYUiMg==","signatures":[{"sig":"MEUCIQC+SEd9y4hALjTvqAtFtHpZOgmKgvUQuOkg4edEPMPIewIgKzPG12qlfw56gZ4U6EknC3uX5T/aUKYp+8wmXR+ANtE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":324619},"main":"./build/snap-req.js","type":"module","types":"./build/snap-req.d.ts","exports":{".":{"types":"./build/snap-req.d.ts","default":"./build/snap-req.js"},"./*":{"types":"./build/*.d.ts","default":"./build/*.js"}},"gitHead":"5133a371ed075e088c2a3f48ab821dd04d0a3bad","scripts":{"lint":"npm run eslint && npm run typecheck","test":"npm run build && node --test \"spec/**/*-spec.js\"","build":"rm -rf build && tsc","eslint":"eslint src spec","prepare":"npm run build","typecheck":"tsc --noEmit","all-checks":"npm run typecheck && npm run lint && npm run test","release:patch":"release-patch","prepublishOnly":"npm run build"},"_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"_npmVersion":"11.17.0","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"_nodeVersion":"25.9.0","_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^17.6.0","@types/ws":"^8.18.1","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^25.9.1","release-patch":"^1.0.0","eslint-plugin-jsdoc":"^63.0.0"},"_npmOperationalInternal":{"tmp":"tmp/snapreq_0.0.9_1782912712726_0.96684486778903","host":"s3://npm-registry-packages-npm-production"}},"0.0.10":{"name":"snapreq","version":"0.0.10","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","_id":"snapreq@0.0.10","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"dist":{"shasum":"4af82ab0b9855fe351c4c552f3fb63ace30295ae","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.10.tgz","fileCount":59,"integrity":"sha512-z+YmWw7msCaMfCmW/OgawSc96q5xBcNt3KebsVD1rBtj7WN1T5Aq2k9gWhehgMsnPNXQpbmmVH/ylgBIo1MH5g==","signatures":[{"sig":"MEUCIG02cvBMD0gvBTJk0xveiDlRmV3XM0oXLtMAfAiDL3L0AiEAwOgzdIoXUPsfWQLO/hbGTKfv218kQOl99sDFs8T0YHY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":357557},"main":"./build/snap-req.js","type":"module","types":"./build/snap-req.d.ts","exports":{".":{"types":"./build/snap-req.d.ts","default":"./build/snap-req.js"},"./*":{"types":"./build/*.d.ts","default":"./build/*.js"}},"gitHead":"12f56696fbf16c4b5ec225e4ffc9f48f87a38ed0","scripts":{"lint":"npm run eslint && npm run typecheck","test":"npm run build && node --test \"spec/**/*-spec.js\"","build":"rm -rf build && tsc","eslint":"eslint src spec","prepare":"npm run build","typecheck":"tsc --noEmit","all-checks":"npm run typecheck && npm run lint && npm run test","release:patch":"release-patch","prepublishOnly":"npm run build"},"_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"_npmVersion":"11.17.0","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"_nodeVersion":"25.9.0","dependencies":{"awaitery":"1.0.19"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^17.6.0","@types/ws":"^8.18.1","@eslint/js":"^10.0.1","typescript":"^7.0.2","@types/node":"^26.0.1","release-patch":"^1.0.0","eslint-plugin-jsdoc":"^63.0.0"},"_npmOperationalInternal":{"tmp":"tmp/snapreq_0.0.10_1784734727727_0.05074384044253866","host":"s3://npm-registry-packages-npm-production"}},"0.0.11":{"name":"snapreq","version":"0.0.11","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","_id":"snapreq@0.0.11","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"dist":{"shasum":"f19722a0c1f19fbd43b29aae46e82e0c2cfc6d67","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.11.tgz","fileCount":59,"integrity":"sha512-JLp8eTnIMBRd2GgsJLb7OgOApoApLxPQuhnS+idmO8EWssjqQPJX1HI1RX/IqyfkIVkFDLScRtPr1fucAZF7HQ==","signatures":[{"sig":"MEYCIQCUIGIG7hlU7qF210ZfQLGz9ZJXgbWSWE7eClNFYcqJ1gIhAMlQoKN8EPyuaWH7mqiRyFoHM0lXWbpIksIxacZC/IWQ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":359626},"main":"./build/snap-req.js","type":"module","types":"./build/snap-req.d.ts","exports":{".":{"types":"./build/snap-req.d.ts","default":"./build/snap-req.js"},"./*":{"types":"./build/*.d.ts","default":"./build/*.js"}},"gitHead":"c671395f065d4e1e404342008c74748ff6e3e370","scripts":{"lint":"npm run eslint && npm run typecheck","test":"npm run build && node --test \"spec/**/*-spec.js\"","build":"rm -rf build && tsc","eslint":"eslint src spec scripts","prepare":"npm run build","typecheck":"tsc --noEmit","all-checks":"npm run typecheck && npm run lint && npm run test","hermes:check":"node --test spec/hermes-compose-spec.js","release:patch":"release-patch","prepublishOnly":"npm run build"},"_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"_npmVersion":"11.16.0","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"_nodeVersion":"24.18.0","dependencies":{"awaitery":"1.0.19"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^17.6.0","@types/ws":"^8.18.1","@eslint/js":"^10.0.1","typescript":"^7.0.2","@types/node":"^26.0.1","release-patch":"^1.0.0","eslint-plugin-jsdoc":"^63.0.0"},"_npmOperationalInternal":{"tmp":"tmp/snapreq_0.0.11_1785251158313_0.049162279818679044","host":"s3://npm-registry-packages-npm-production"}},"0.0.12":{"name":"snapreq","version":"0.0.12","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","_id":"snapreq@0.0.12","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"dist":{"shasum":"960200bd2f67e3a791071af9126d35b741105d00","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.12.tgz","fileCount":59,"integrity":"sha512-1W738rAXxBOOMhNQYZTPIjDSC3BawdmTN1zzOmD6FSJi7D4y5H7UbHXsFv7n5mtKoUDC+Ze910OiDfYqp4LNaQ==","signatures":[{"sig":"MEYCIQDpH71po6+LIOSxD/jGZSIJJBJK4KuIFY3eQfaP3dhT5AIhAI5ytACm/u2qOOfKyD58nznyA/M81v+7Hybfm/SlFNUJ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":360504},"main":"./build/snap-req.js","type":"module","types":"./build/snap-req.d.ts","exports":{".":{"types":"./build/snap-req.d.ts","default":"./build/snap-req.js"},"./*":{"types":"./build/*.d.ts","default":"./build/*.js"}},"gitHead":"8dff6bbe2a8a5fc662875d60d175f07542414e2f","scripts":{"lint":"npm run eslint && npm run typecheck","test":"npm run build && node --test \"spec/**/*-spec.js\"","build":"rm -rf build && tsc","eslint":"eslint src spec","prepare":"npm run build","typecheck":"tsc --noEmit","all-checks":"npm run typecheck && npm run lint && npm run test","hermes:check":"node --test spec/hermes-compose-spec.js","release:patch":"release-patch","prepublishOnly":"npm run build"},"_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"_npmVersion":"11.16.0","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"_nodeVersion":"24.18.0","dependencies":{"awaitery":"1.0.19"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^17.6.0","@types/ws":"^8.18.1","@eslint/js":"^10.0.1","typescript":"^7.0.2","@types/node":"^26.0.1","release-patch":"^1.0.0","eslint-plugin-jsdoc":"^63.0.0","@kaspernj/hermes-compose":"0.0.0"},"_npmOperationalInternal":{"tmp":"tmp/snapreq_0.0.12_1785266972281_0.5438281019813647","host":"s3://npm-registry-packages-npm-production"}},"0.0.13":{"name":"snapreq","version":"0.0.13","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","_id":"snapreq@0.0.13","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"dist":{"shasum":"e74c6ffdcb3729885b9c435c81d980681d125c37","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.13.tgz","fileCount":59,"integrity":"sha512-8hijS0XIJmhEbMJtke4OryOpgVU8WUF77zpoTYn0D0az2tE8lYueoWtEq8dorxMGKDDjlBtUhHJ7v57byD045Q==","signatures":[{"sig":"MEUCIQCDEtijYgjo4KgcOA1CICYuTqSX3eojCEDLca4XPn3DUAIgNxWTqe72/M7esOx0xmU7t/JcygsqifVYJTVF530HpKU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":365097},"main":"./build/snap-req.js","type":"module","types":"./build/snap-req.d.ts","exports":{".":{"types":"./build/snap-req.d.ts","default":"./build/snap-req.js"},"./*":{"types":"./build/*.d.ts","default":"./build/*.js"}},"gitHead":"62e395cfaa50e66b8452422621fd3b1f3853566b","scripts":{"lint":"npm run eslint && npm run typecheck","test":"npm run build && node --test \"spec/**/*-spec.js\"","build":"rm -rf build && tsc","eslint":"eslint src spec","prepare":"npm run build","typecheck":"tsc --noEmit","all-checks":"npm run typecheck && npm run lint && npm run test","hermes:check":"node --test spec/hermes-compose-spec.js","release:patch":"release-patch","prepublishOnly":"npm run build"},"_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"_npmVersion":"11.16.0","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"_nodeVersion":"24.18.0","dependencies":{"awaitery":"1.0.19"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^17.6.0","@types/ws":"^8.18.1","@eslint/js":"^10.0.1","typescript":"^7.0.2","@types/node":"^26.0.1","release-patch":"^1.0.0","eslint-plugin-jsdoc":"^63.0.0","@kaspernj/hermes-compose":"0.0.0"},"_npmOperationalInternal":{"tmp":"tmp/snapreq_0.0.13_1787593195158_0.5487042579529506","host":"s3://npm-registry-packages-npm-production"}},"0.0.14":{"name":"snapreq","version":"0.0.14","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","_id":"snapreq@0.0.14","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"dist":{"shasum":"4390307998618271c620ae77971fd194bcbe1e30","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.14.tgz","fileCount":59,"integrity":"sha512-iD1GShx1pKIH9HF3CWzVpbdnxCfW3/xLTq5bVkY8m6SNmnHIkgiaH4CeSjrAuuCo6Kub4XhTHnMpX82y8lssKg==","signatures":[{"sig":"MEUCIEcGv4vN1cPhgJoeU5nXIEF/u7R+6V2xX32r4vEaV01WAiEAjBJhYcKGxu9Ht8myyfYByo9+Zt8oXT0w3/fbbwLInjc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":371930},"main":"./build/snap-req.js","type":"module","types":"./build/snap-req.d.ts","exports":{".":{"types":"./build/snap-req.d.ts","default":"./build/snap-req.js"},"./*":{"types":"./build/*.d.ts","default":"./build/*.js"}},"gitHead":"bc38af67ff23c04dcddaa68e9fc705742306aa59","scripts":{"lint":"npm run eslint && npm run typecheck","test":"npm run build && velocious-test","build":"rm -rf build && tsc","eslint":"eslint src spec","prepare":"npm run build","typecheck":"tsc --noEmit","all-checks":"npm run typecheck && npm run lint && npm run test","hermes:check":"velocious-test spec/hermes-compose.spec.js","release:patch":"release-patch","prepublishOnly":"npm run build"},"_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"_npmVersion":"11.19.1","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"_nodeVersion":"25.8.1","dependencies":{"awaitery":"1.0.19"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^17.6.0","@types/ws":"^8.18.1","@eslint/js":"^10.0.1","typescript":"^7.0.2","@types/node":"^26.0.1","release-patch":"^1.0.0","@velocious/testing":"0.0.0","eslint-plugin-jsdoc":"^63.0.0","@kaspernj/hermes-compose":"0.0.0"},"_npmOperationalInternal":{"tmp":"tmp/snapreq_0.0.14_1788416903343_0.3173033732181454","host":"s3://npm-registry-packages-npm-production"}},"0.0.15":{"name":"snapreq","version":"0.0.15","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","_id":"snapreq@0.0.15","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"dist":{"shasum":"ae7cb9fcbb932813c52aee19b089ea35b13a9e12","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.15.tgz","fileCount":59,"integrity":"sha512-5j+FVVK0AJHCIsxmAvUFbauKNiXoUhSNvAqa3xMtGqkGyqOxYWmbRYoI1MRugPKdsZTqd6xVm83lUHlNwjgipw==","signatures":[{"sig":"MEQCIEBRqQjSe4isrkITcCUazJZdDSWQj2289tZNkCwU464EAiB+6v5HSqcGVjTuHtveYnknnxvII7LvVl38QtrDSVIVmA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":373848},"main":"./build/snap-req.js","type":"module","types":"./build/snap-req.d.ts","exports":{".":{"types":"./build/snap-req.d.ts","default":"./build/snap-req.js"},"./*":{"types":"./build/*.d.ts","default":"./build/*.js"}},"gitHead":"5ac1f6107ac7a71848ccbfe5ac202122fce7e6f0","scripts":{"lint":"npm run eslint && npm run typecheck","test":"npm run build && velocious-test","build":"rm -rf build && tsc","eslint":"eslint src spec","prepare":"npm run build","typecheck":"tsc --noEmit","all-checks":"npm run typecheck && npm run lint && npm run test","hermes:check":"velocious-test spec/hermes-compose.spec.js","release:patch":"release-patch","prepublishOnly":"npm run build"},"_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"_npmVersion":"11.16.0","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"_nodeVersion":"24.18.1","dependencies":{"awaitery":"1.0.19"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^17.6.0","@types/ws":"^8.18.1","@eslint/js":"^10.0.1","typescript":"^7.0.2","@types/node":"^26.0.1","release-patch":"^1.0.0","@velocious/testing":"0.0.0","eslint-plugin-jsdoc":"^63.0.0","@kaspernj/hermes-compose":"0.0.0"},"_npmOperationalInternal":{"tmp":"tmp/snapreq_0.0.15_1788791648731_0.27357772685840676","host":"s3://npm-registry-packages-npm-production"}},"0.0.16":{"name":"snapreq","version":"0.0.16","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","_id":"snapreq@0.0.16","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"dist":{"shasum":"889b4a3b92c7ad125568895ed08d6969e2267de8","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.16.tgz","fileCount":59,"integrity":"sha512-kHJWJ8D3GTq0YON/ocvFSWUk440pL4REtidZxRyTF0SoWuVgsy7/b8zafJixW7GLJEKX23Rd3QgPrvjXlnTqyQ==","signatures":[{"sig":"MEYCIQD3I89HUcxoPwgKX1Nu72GxNWjLXEnSXdA1rMxTz15RbwIhALFXhYPOVepE0oE2l9T3FG1Mq1Yeg8Ssx3WV7ZhkYKgG","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":414263},"main":"./build/snap-req.js","type":"module","types":"./build/snap-req.d.ts","exports":{".":{"types":"./build/snap-req.d.ts","default":"./build/snap-req.js"},"./*":{"types":"./build/*.d.ts","default":"./build/*.js"}},"gitHead":"f358a7180be0b1cb6ef75461a38b70188ba84fda","scripts":{"lint":"npm run eslint && npm run typecheck","test":"npm run build && velocious-test","build":"rm -rf build && tsc","eslint":"eslint src spec","prepare":"npm run build","typecheck":"tsc --noEmit","all-checks":"npm run typecheck && npm run lint && npm run test","hermes:check":"velocious-test spec/hermes-compose.spec.js","release:patch":"release-patch","prepublishOnly":"npm run build"},"_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"_npmVersion":"11.16.0","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"_nodeVersion":"24.18.1","dependencies":{"awaitery":"1.0.19"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^17.6.0","@types/ws":"^8.18.1","@eslint/js":"^10.0.1","typescript":"^7.0.2","@types/node":"^26.0.1","release-patch":"^1.0.0","@velocious/testing":"0.0.0","eslint-plugin-jsdoc":"^63.0.0","@kaspernj/hermes-compose":"0.0.0"},"_npmOperationalInternal":{"tmp":"tmp/snapreq_0.0.16_1788982181035_0.7354285001970617","host":"s3://npm-registry-packages-npm-production"}},"0.0.17":{"_id":"snapreq@0.0.17","dist":{"shasum":"1db1c088c63cda4e6d98061494c08a9e5dfd4412","tarball":"https://registry.npmjs.org/snapreq/-/snapreq-0.0.17.tgz","fileCount":59,"integrity":"sha512-B72zfJ2TNBeUs8oN8OlD5iWPQOSO0q1D5NYrfE5dhe/dVzuMr2gNCAMsWYOuX0rCEqOlapqC+ZNDSDSDObtLNA==","signatures":[{"sig":"MEUCIQDt7+XuAIVAIwYYk483oLiDyu94sRsj+6u7TkvS1hS64QIgK8DvPeNjSa2EpPafMgeE18xSIwTYJKRIMecIaiwvbC8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD8By5Ev+MHECObIp144wjmMpUiTK1cfYNjK8PLC51m3QIhAK6ikDeWBqvk+AmLLVM0gVoXDQdwlORNoiq6j/vbNlQj"}],"unpackedSize":450996},"main":"./build/snap-req.js","name":"snapreq","type":"module","types":"./build/snap-req.d.ts","author":{"name":"kasper@diestoeckels.de"},"exports":{".":{"types":"./build/snap-req.d.ts","default":"./build/snap-req.js"},"./*":{"types":"./build/*.d.ts","default":"./build/*.js"}},"gitHead":"74968196d34879473ae587c15cd13c5237d98b7a","license":"ISC","scripts":{"lint":"npm run eslint && npm run typecheck","test":"npm run build && velocious-test","build":"rm -rf build && tsc","eslint":"eslint src spec","prepare":"npm run build","typecheck":"tsc --noEmit","all-checks":"npm run typecheck && npm run lint && npm run test","hermes:check":"velocious-test spec/hermes-compose.spec.js","release:patch":"release-patch","prepublishOnly":"npm run build"},"version":"0.0.17","_npmUser":{"name":"kaspernj","email":"kasper@diestoeckels.de"},"keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"_npmVersion":"11.16.0","description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","directories":{},"maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"_nodeVersion":"24.18.1","dependencies":{"awaitery":"1.0.19"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","eslint":"^10.3.0","globals":"^17.6.0","@types/ws":"^8.18.1","@eslint/js":"^10.0.1","typescript":"^7.0.2","@types/node":"^26.0.1","release-patch":"^1.0.9","@velocious/testing":"0.0.0","eslint-plugin-jsdoc":"^63.0.0","@kaspernj/hermes-compose":"0.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/snapreq_0.0.17_1789069890198_0.1416512618221646"}}},"time":{"created":"2026-05-24T16:58:39.368Z","modified":"2026-09-10T19:51:30.453Z","0.0.1":"2026-05-24T16:58:39.735Z","0.0.3":"2026-05-24T17:27:53.041Z","0.0.4":"2026-05-27T07:53:37.364Z","0.0.5":"2026-06-02T05:58:39.205Z","0.0.8":"2026-06-18T05:12:09.198Z","0.0.9":"2026-07-01T13:31:52.921Z","0.0.10":"2026-07-22T15:38:47.883Z","0.0.11":"2026-07-28T15:05:58.449Z","0.0.12":"2026-07-28T19:29:32.429Z","0.0.13":"2026-08-24T17:39:55.340Z","0.0.14":"2026-09-03T06:28:23.485Z","0.0.15":"2026-09-07T14:34:08.859Z","0.0.16":"2026-09-09T19:29:41.201Z","0.0.17":"2026-09-10T19:51:30.280Z"},"author":{"name":"kasper@diestoeckels.de"},"license":"ISC","keywords":["http","fetch","websocket","client","expo","react-native","cross-platform"],"description":"Cross-platform HTTP and WebSocket client with one API across Node, web, Expo and React Native","maintainers":[{"name":"kaspernj","email":"kasper@diestoeckels.de"}],"readme":"# snapreq\n\nA cross-platform HTTP and WebSocket client with **one API** across Node, the web, Expo and React Native.\n\nThe same code runs everywhere. Where a platform cannot provide a feature (Unix sockets in a browser, request-body compression over `fetch`, …) snapreq raises a clear `SnapReqUnsupportedFeatureError` instead of silently changing behaviour — so the API is identical and the gaps are explicit.\n\n- Zero runtime dependencies.\n- Picks the right transport at runtime: Node `http`/`https`, `fetch`, or `XMLHttpRequest`.\n- `node:*` modules are loaded with a dynamic `import()` from the Node transport only, so web/Expo bundlers (Metro, webpack, …) never try to bundle them.\n- ESM + JSDoc types, checked with `tsc`.\n\n## Install\n\n```sh\nnpm install snapreq\n```\n\n## Imports\n\nsnapreq has **no barrel entry point** — you import each piece from its own subpath so a bundler (Metro/Expo, webpack, …) only pulls in what you use, and the HTTP client never drags the WebSocket client into your bundle:\n\n```js\nimport SnapReq from \"snapreq\"                       // the HTTP client\nimport SnapReqWebSocketClient from \"snapreq/websocket\"\nimport {SnapReqHttpError, SnapReqIdleTimeoutError, SnapReqRedirectError, SnapReqResponseTooLargeError, SnapReqUnsupportedFeatureError} from \"snapreq/errors\"\nimport {defaultRetryableError} from \"snapreq/retry\"\nimport SnapReqResponse from \"snapreq/response\"\nimport SnapReqHeaders from \"snapreq/headers\"\n```\n\n## HTTP\n\n```js\nimport SnapReq from \"snapreq\"\n\nconst client = new SnapReq({baseUrl: \"https://api.example.com\"})\n\nconst response = await client.get(\"/users\", {query: {page: 1}})\nconst users = await response.json()\n\nawait client.post(\"/users\", {name: \"Ada\"})\n```\n\nEvery call returns a `SnapReqResponse`:\n\n```js\nresponse.status          // 200\nresponse.ok              // status in 200..299\nresponse.headers.get(\"content-type\")\nawait response.json()    // parsed JSON (null for an empty body)\nawait response.text()    // UTF-8 string\nawait response.bytes()   // Uint8Array\nawait response.buffer()  // Node Buffer (Node only)\n```\n\n`request()` does **not** throw on a non-2xx status by default (like `fetch`). Pass `throwOnError: true` (per request or on the client) to get a `SnapReqHttpError` carrying `status`, `responseText` and the `response`.\n\n### Client options\n\n```js\nnew SnapReq({\n  baseUrl,        // origin (and optional base path) prefixed onto relative paths\n  headers,        // default headers — object or a factory `() => ({...})` for dynamic auth\n  retry,          // default retry policy (see below)\n  throwOnError,   // throw SnapReqHttpError on non-2xx (default false)\n  timeoutMs,      // absolute request/body deadline; per-request 0 disables it\n  idleTimeoutMs,  // inactivity timeout reset by transport progress; per-request 0 disables it\n  credentials,    // fetch credentials mode: \"omit\" | \"same-origin\" | \"include\"\n  redirect,       // explicit \"error\" | \"manual\" | \"follow\"; omitted keeps transport behavior\n  maxRedirects,   // followed-redirect maximum (default 10)\n  maxResponseBytes, // decoded response-body limit; omitted means unlimited\n  transport,      // \"auto\" (default) | \"node\" | \"fetch\" | \"xhr\" | a transport instance\n\n  // Node transport only:\n  socketPath,     // connect over a Unix domain socket\n  tls,            // {ca, cert, key, rejectUnauthorized}\n  keepAlive       // reuse connections (default true)\n})\n```\n\n### Redirects and response bounds\n\nRedirect behavior remains transport-native when `redirect` is omitted, which\npreserves existing applications. Set an explicit policy when redirect handling\nis security-sensitive: `manual` exposes the 3xx response, `error` raises\n`SnapReqRedirectError`, and `follow` follows at most `maxRedirects` responses.\nFollow mode removes `Authorization`, `Cookie`, and `Proxy-Authorization` when\nthe redirect changes origin while retaining non-credential headers such as\n`Range`. Fetch implementations that expose manual redirect responses support\nall three policies. Browser Fetch commonly returns an opaque redirect instead;\nin that case `error` still rejects the redirect, while `manual` and `follow`\nraise `SnapReqUnsupportedFeatureError` because the status, target URL, and\nheaders required to implement them safely are hidden. XHR and the proxy-bounce adapter raise\n`SnapReqUnsupportedFeatureError` because those transports cannot observe the\ntarget redirect response reliably.\n\n`maxResponseBytes` bounds decoded bytes before they are returned by `stream()`\nor retained by `bytes()`, `text()`, `json()`, and `buffer()`. A declared\n`Content-Length` over the limit rejects before body consumption; chunked or\ncompressed responses are counted as decoded chunks and raise\n`SnapReqResponseTooLargeError` on overflow. The limit can be set on the client\nor overridden per request; omission keeps the existing unlimited behavior.\nThe Node transport and Fetch implementations with a readable response stream\nenforce the bound incrementally. Fetch buffered fallbacks, XHR, and\nproxy-bounce reject a configured bound with `SnapReqUnsupportedFeatureError`\nbecause they allocate or receive a complete buffered response before SnapReq\ncan count it.\n\n### Timeouts\n\nSet `timeoutMs` on the client or a single request for an absolute wall-clock deadline. It covers one request attempt, including response headers and body reads through `json()`, `text()`, `bytes()`, `buffer()`, or `stream()`, and is never reset by progress. Set `idleTimeoutMs` independently to bound inactivity while allowing a healthy transfer to exceed that interval. Its watchdog resets when outbound body bytes are accepted, response headers arrive, or inbound body bytes are delivered. Zero disables the corresponding client default.\n\nAn absolute deadline rejects with `SnapReqTimeoutError` (`timeoutKind: \"overall\"`). Inactivity rejects with `SnapReqIdleTimeoutError`, a backward-compatible `SnapReqTimeoutError` subtype carrying `timeoutKind: \"idle\"`, `idleTimeoutMs`, and the last progress `phase`. Caller `signal` cancellation remains `SnapReqAbortError`. All controls abort the active transport and interrupt retry waits without starting another attempt.\n\n```js\nconst client = new SnapReq({baseUrl: \"https://api.example.com\", timeoutMs: 120000, idleTimeoutMs: 30000})\n\nawait client.get(\"/slow\", {timeoutMs: 5000})\nawait client.get(\"/long-running\", {timeoutMs: 0}) // disable the client default for this call\n```\n\nThe Node transport supports idle progress for streaming uploads. XHR uses its native upload/download progress events. Fetch supports semantically bodyless responses and observable `ReadableStream` downloads; it explicitly rejects request-body uploads and non-bodyless buffered-response fallbacks whose progress Fetch cannot expose. The proxy-bounce transport explicitly rejects idle timeouts because it buffers the proxied response.\n\n### Retry\n\nRetries transient network errors and retryable HTTP statuses (502/503/504 by default). Only applies to buffered requests — never to streamed bodies.\n\n```js\nawait client.get(\"/flaky\", {retry: true})\nawait client.get(\"/flaky\", {retry: {tries: 5, waitMs: 200, retryableStatuses: [503]}})\n\n// Compose extra rules on top of the default network classifier:\nimport {defaultRetryableError} from \"snapreq/retry\"\n\nawait client.get(\"/x\", {retry: {shouldRetry: (error) => defaultRetryableError(error) || isMyCase(error)}})\n```\n\n### Streaming\n\n```js\nconst response = await client.requestStream({method: \"GET\", path: \"/logs\"})\n\nfor await (const chunk of response.stream()) {\n  process.stdout.write(chunk) // chunk is a Uint8Array\n}\n```\n\n`requestStream()` requires a transport that supports response streaming and never retries. On Node the raw stream is also available as `response.nodeStream`.\n\n### Request-body compression (Node)\n\n```js\nawait client.post(\"/upload\", largePayload, {bodyCompression: \"gzip\"}) // gzip | deflate | br | zstd\n```\n\nOver `fetch`/`xhr` this raises `SnapReqUnsupportedFeatureError`.\n\n### Capabilities\n\nEach transport advertises what it can do. Inspect them when you need to branch on platform support:\n\n```js\nconst caps = await client.capabilities()\n// {unixSocket, tlsClientCert, requestCompression, responseStreaming, requestStreaming, keepAlive, abort}\n```\n\n| Capability          | Node | fetch | xhr |\n| ------------------- | :--: | :---: | :-: |\n| unixSocket          |  ✅  |  —    |  —  |\n| tlsClientCert       |  ✅  |  —    |  —  |\n| requestCompression  |  ✅  |  —    |  —  |\n| responseStreaming   |  ✅  |  ✅   |  —  |\n| requestStreaming    |  ✅  |  —    |  —  |\n| keepAlive           |  ✅  |  —    |  —  |\n| abort               |  ✅  |  ✅   |  ✅ |\n\n## WebSocket\n\nA WebSocket client over `globalThis.WebSocket` with auto-reconnect, session resumption, request/response calls, channel subscriptions and 1:1 connections.\n\n```js\nimport SnapReqWebSocketClient from \"snapreq/websocket\"\n\nconst client = new SnapReqWebSocketClient({url: \"wss://example.com/websocket\"})\n\nconst controller = new AbortController()\nawait client.connect({timeoutMs: 5000, signal: controller.signal})\n\n// Request/response over the socket\nconst response = await client.post(\"/things\", {name: \"thing\"}, {timeoutMs: 5000, signal: controller.signal})\nresponse.json()\n\n// Channel subscription\nconst unsubscribe = await client.subscribeAndWait(\"updates\", {timeoutMs: 5000, signal: controller.signal}, (payload) => console.log(payload))\n\n// 1:1 connection\nconst connection = client.openConnection(\"ChatConnection\", {timeoutMs: 5000, signal: controller.signal, onMessage: (body) => console.log(body)})\nawait connection.ready\nconnection.sendMessage({text: \"hi\"})\n```\n\n`timeoutMs` and `signal` are also accepted by `get`, `request`, `subscribe`, `subscribeChannel`, and `waitForReady`. WebSocket timeouts intentionally reject with Awaitery's `TimeoutError`, while WebSocket cancellation rejects with the exact `signal.reason`; unlike HTTP operations, these errors are not mapped to SnapReq error classes. A failed connect deadline closes only a socket created solely for that operation; a shared in-flight socket remains alive for other connect-dependent operations. Request and readiness failures remove only their own pending entry or handle.\n\nOptional adapters: `networkMonitor` (gate reconnects on online state), `sessionStore` (persist the session id across reloads) and `deserialize` (a `(value) => value` transform applied inside `response.json()` so an app can re-hydrate its own wire format).\n\nSession resumption uses only an ID retained from a previous connection or restored from `sessionStore`, never the ID just assigned to a fresh socket. This remains true when the socket's open event and first session frame arrive together. Every `connect()` caller waits for session readiness: on reconnect, the new socket's establishment frame alone does not release callers or queued subscriptions before `session-resumed` or `session-gone` arrives.\n\nIf the socket closes before session readiness, every caller waiting on that readiness generation rejects. A later connection has its own readiness outcome and is not poisoned by the earlier failure.\n\n## Hermes Compose development\n\nThe repository includes a task-isolated Node 24 development environment for\nHermes/Threadwire work. It mounts one exact worktree into `/workspace`; the\ndependency, npm-cache, and Codex state volumes are scoped by the required\nCompose project name. There are no support services, host ports, or fixed\ncontainer names. The development-only `@kaspernj/hermes-compose` package owns\nthe lifecycle, provider, process and signal handling, bootstrap, proof, smoke\nacceptance, and exact cleanup. SnapReq owns only `hermes.config.js` and its\nchecked-in Compose/Dockerfile wiring.\n\nFrom the outer Hermes Docker host, allocate a self-contained Git checkout\n(with its own `.git` directory) directly below\n`/opt/hermes-dind-shared/worktrees/snapreq` and keep its task name identical to\nthe Compose suffix:\n\n```sh\nexport HERMES_SOURCE_PATH=/opt/hermes-dind-shared/worktrees/snapreq/10575\nexport HERMES_COMPOSE_PROJECT=snapreq-10575\n\nnpm exec --yes --package=@kaspernj/hermes-compose@0.0.0 -- hermes-compose validate\nnpm exec --yes --package=@kaspernj/hermes-compose@0.0.0 -- hermes-compose config\nnpm exec --yes --package=@kaspernj/hermes-compose@0.0.0 -- hermes-compose build --pull\nnpm exec --yes --package=@kaspernj/hermes-compose@0.0.0 -- hermes-compose up\nnpm exec --yes --package=@kaspernj/hermes-compose@0.0.0 -- hermes-compose exec npm ci\nnpm exec --yes --package=@kaspernj/hermes-compose@0.0.0 -- hermes-compose proof\nnpm exec --yes --package=@kaspernj/hermes-compose@0.0.0 -- hermes-compose down\n```\n\nCodex authentication is initialized into the task-owned volume from one\nexplicit, existing Docker volume in the private DinD daemon. That source\nvolume must contain `/auth.json`; it is mounted read-only only for the one-off\ninitializer and never attached to the long-running service:\n\n```sh\nexport HERMES_CODEX_AUTH_VOLUME=<existing-auth-volume>\nnpm exec --yes --package=@kaspernj/hermes-compose@0.0.0 -- hermes-compose init-codex\n```\n\nThreadwire remains on the outer host. The package launches it through its\nprovider, which runs Codex in the `dev` service at `/workspace`:\n\n```sh\nexport THREADWIRE_TARGET=telegram:-1001234567890:42\nnpm exec --yes --package=@kaspernj/hermes-compose@0.0.0 -- hermes-compose threadwire --prompt 'Inspect the project.'\n```\n\nUse the pinned `npm exec` `down` command above for ordinary teardown; it\npreserves task state. Volume/image deletion requires the separate, exact\nconfirmation:\n\n```sh\nHERMES_PURGE_PROJECT=\"$HERMES_COMPOSE_PROJECT\" npm exec --yes --package=@kaspernj/hermes-compose@0.0.0 -- hermes-compose purge\n```\n\nThe two-stack acceptance entry point is\n`npm exec --yes --package=@kaspernj/hermes-compose@0.0.0 -- hermes-compose smoke`.\nSee [AGENTS.md](AGENTS.md) for the authoritative boundary, parallel-allocation,\nverification, smoke-test, and non-Hermes workflow rules.\n\n## License\n\nISC\n","readmeFilename":"README.md"}