{"_id":"@atcute/firehose","_rev":"7-ab9636215d27c432298a42ad474a8ee9","name":"@atcute/firehose","dist-tags":{"latest":"1.2.0"},"versions":{"0.1.0":{"name":"@atcute/firehose","version":"0.1.0","license":"0BSD","_id":"@atcute/firehose@0.1.0","maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"homepage":"https://github.com/mary-ext/atcute#readme","bugs":{"url":"https://github.com/mary-ext/atcute/issues"},"dist":{"shasum":"09cc7a817b49ebef6104e9101c54b086ba3ed28a","tarball":"https://registry.npmjs.org/@atcute/firehose/-/firehose-0.1.0.tgz","fileCount":23,"integrity":"sha512-xBEKdi6rkODpCIIRpXtXhhcuQ1vTbufDykAM2kA6bmWEpuwI4acoUCg9zbiUWqd21SMMOAthu9Eh72i2VYrD7A==","signatures":[{"sig":"MEUCIQCg89B0PiSmAxZHGF5y6j1kABvZd9UvNjdxV9goi/2f+QIgLv51sF08bKucfAAWzEB4m9uL2w2cxa14OiI9hzmqdog=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28002},"type":"module","_from":"file:atcute-firehose-0.1.0.tgz","exports":{".":"./dist/index.js"},"scripts":{"build":"tsc --project tsconfig.build.json","prepublish":"rm -rf dist; pnpm run build"},"_npmUser":{"name":"externdefs","email":"hi@mary.my.id"},"_resolved":"/tmp/8428249c5eade7484c0df0e00dd153d4/atcute-firehose-0.1.0.tgz","_integrity":"sha512-xBEKdi6rkODpCIIRpXtXhhcuQ1vTbufDykAM2kA6bmWEpuwI4acoUCg9zbiUWqd21SMMOAthu9Eh72i2VYrD7A==","repository":{"url":"git+https://github.com/mary-ext/atcute.git","directory":"packages/clients/firehose"},"_npmVersion":"10.9.3","description":"lightweight and cute XRPC subscription client for AT Protocol","directories":{},"_nodeVersion":"22.20.0","dependencies":{"type-fest":"^4.41.0","partysocket":"^1.1.6","@atcute/cbor":"^2.2.7","@atcute/lexicons":"^1.2.2","@atcute/uint8array":"^1.0.5","@mary-ext/event-iterator":"^1.0.0","@mary-ext/simple-event-emitter":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@atcute/atproto":"^3.1.8"},"_npmOperationalInternal":{"tmp":"tmp/firehose_0.1.0_1762385949443_0.6415541265529294","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@atcute/firehose","version":"0.1.1","license":"0BSD","_id":"@atcute/firehose@0.1.1","maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"dist":{"shasum":"ee0850b092358667bab5948ee538d4d579a62f5e","tarball":"https://registry.npmjs.org/@atcute/firehose/-/firehose-0.1.1.tgz","fileCount":23,"integrity":"sha512-h82bxQBwvKD/SgKRkEO1S1UMjLIIPZg7uW38pDMzwj5zSr8oav+/yfw1lVl9jFAhieVPk0F8IxZYViC2TC0Sgw==","signatures":[{"sig":"MEYCIQDOPQTozhKWRERnnEQs8cDDXns2Uh3I/c8zzPgVWSat6QIhANfUmhTTRXf+a8bane9VBrfVVz5RlY3OzKw2w8KZw3GU","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":32891},"type":"module","exports":{".":"./dist/index.js"},"scripts":{"build":"tsgo","prepublish":"rm -rf dist; pnpm run build"},"_npmUser":{"name":"externdefs","email":"hi@mary.my.id"},"repository":{"url":"https://github.com/mary-ext/atcute","directory":"packages/clients/firehose"},"description":"lightweight and cute XRPC subscription client for AT Protocol","directories":{},"_nodeVersion":"26.0.0","dependencies":{"type-fest":"^4.41.0","partysocket":"^1.1.18","@atcute/cbor":"^2.3.3","@atcute/lexicons":"^1.3.1","@atcute/uint8array":"^1.1.1","@mary-ext/event-iterator":"^1.0.0","@mary-ext/simple-event-emitter":"^1.0.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@atcute/atproto":"^3.1.12"},"peerDependencies":{"@atcute/lexicons":"^1.0.0"},"_npmOperationalInternal":{"tmp":"tmp/firehose_0.1.1_1778205590973_0.8524372958191497","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@atcute/firehose","version":"1.0.0","license":"0BSD","_id":"@atcute/firehose@1.0.0","maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"dist":{"shasum":"30c435dc0117fc83d96d940cb4b12d8a32d9124b","tarball":"https://registry.npmjs.org/@atcute/firehose/-/firehose-1.0.0.tgz","fileCount":23,"integrity":"sha512-8JkzOqqADt0j2b/r2p2sfXDhWB/AO6x5kDUKwB+2JR8NRx7L8gynQwV89lT2WbX5NsU1WxqivZ9Np8EXYVETfg==","signatures":[{"sig":"MEYCIQCXVNSl2Faqog/fyoHvcckPWDXbv89Dk8GT1TARjrK+rAIhALpjmmXhPpbcpYpjmCq8BJ+6zwexTjYlp8EtQ7/w87k+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":35314},"type":"module","exports":{".":"./dist/index.js"},"scripts":{"build":"tsgo","prepublish":"rm -rf dist; pnpm run build"},"_npmUser":{"name":"externdefs","email":"hi@mary.my.id"},"repository":{"url":"https://github.com/mary-ext/atcute","directory":"packages/clients/firehose"},"description":"lightweight and cute XRPC subscription client for AT Protocol","directories":{},"_nodeVersion":"26.0.0","dependencies":{"type-fest":"^4.41.0","partysocket":"^1.1.18","@atcute/cbor":"^2.3.3","@atcute/lexicons":"^2.0.0","@atcute/uint8array":"^1.1.1","@mary-ext/event-iterator":"^1.0.0","@mary-ext/simple-event-emitter":"^1.0.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@atcute/atproto":"^4.0.0"},"peerDependencies":{"@atcute/lexicons":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/firehose_1.0.0_1778312786698_0.06996214086437358","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@atcute/firehose","version":"1.0.1","license":"0BSD","_id":"@atcute/firehose@1.0.1","maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"dist":{"shasum":"3b15d78ce612768d3eebe6638abbcc512befe459","tarball":"https://registry.npmjs.org/@atcute/firehose/-/firehose-1.0.1.tgz","fileCount":11,"integrity":"sha512-WCeKhpJEVeyM/48C6eerQ92j7JOCxFjPNrULA4+Ox5egpBekUacuGfjxdgGobhGDIuFBJQ3bP7SH/GFlmobtjQ==","signatures":[{"sig":"MEUCIQCm9PG8y+1PRTPOHDeneVzqTmp9PXyby/2vQVVQsTOVfAIgW77WubJggYJjQMPPkA+yRk8r2L9/35NLylxLhkoEg3k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17254},"type":"module","exports":{".":"./dist/index.js"},"scripts":{"build":"tsgo","prepublish":"rm -rf dist; pnpm run build"},"_npmUser":{"name":"externdefs","email":"hi@mary.my.id"},"repository":{"url":"https://github.com/mary-ext/atcute","directory":"packages/clients/firehose"},"description":"lightweight and cute XRPC subscription client for AT Protocol","directories":{},"_nodeVersion":"26.0.0","dependencies":{"type-fest":"^4.41.0","partysocket":"^1.3.0","@atcute/cbor":"^2.3.5","@atcute/lexicons":"^2.0.2","@atcute/uint8array":"^1.1.3","@mary-ext/event-iterator":"^1.0.0","@mary-ext/simple-event-emitter":"^1.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"@atcute/atproto":"^4.0.3"},"peerDependencies":{"@atcute/lexicons":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/firehose_1.0.1_1782777111293_0.7929336016420647","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@atcute/firehose","version":"1.0.2","license":"0BSD","_id":"@atcute/firehose@1.0.2","maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"dist":{"shasum":"8d4542f9ee43f066b820b5334902b7669d200aa9","tarball":"https://registry.npmjs.org/@atcute/firehose/-/firehose-1.0.2.tgz","fileCount":11,"integrity":"sha512-bWKjxiXU/zlmDYiIll7DR8MXsNFb+cnq4ThYCVKrDz4rP/ZomQzgD5ew6TCn6gmipxTnT5q0gc50TGTfNXzcZw==","signatures":[{"sig":"MEQCICWYFP2j6YUwAsTQCHnP2WPiUYuw2fst/o7YeE4fnx24AiBkWv8/W8ASmhiM/0uQIVImLw0ZFXunTd5UDA6g8j79hg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17887},"type":"module","exports":{".":"./dist/index.js"},"scripts":{"test":"vitest run","build":"tsc","prepublish":"rm -rf dist; pnpm run build"},"_npmUser":{"name":"externdefs","email":"hi@mary.my.id"},"repository":{"url":"https://github.com/mary-ext/atcute","directory":"packages/clients/firehose"},"description":"lightweight and cute XRPC subscription client for AT Protocol","directories":{},"_nodeVersion":"26.0.0","dependencies":{"type-fest":"^4.41.0","partysocket":"^1.3.0","@atcute/cbor":"^2.3.6","@atcute/lexicons":"^2.0.3","@atcute/uint8array":"^1.1.5","@mary-ext/event-iterator":"^1.0.0","@mary-ext/simple-event-emitter":"^1.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.0","vitest":"^4.1.10","@types/ws":"^8.18.1","@atcute/atproto":"^4.0.3"},"peerDependencies":{"@atcute/lexicons":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/firehose_1.0.2_1784160613462_0.40442067455655906","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@atcute/firehose","version":"1.1.0","license":"0BSD","_id":"@atcute/firehose@1.1.0","maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"dist":{"shasum":"6aa0e9a2220b30ecb9941a56d073fd3812b208e7","tarball":"https://registry.npmjs.org/@atcute/firehose/-/firehose-1.1.0.tgz","fileCount":11,"integrity":"sha512-/tctw9Q0Qmfggflj6xubaZnI5FJGAFQNzgA4mMvd90qSB3yAadCCL3MByLX3/AgCVmpj1FVruevQ/XpdvnKSEA==","signatures":[{"sig":"MEQCICbegrqH1unYn14q2UHoNt7vZ7qaftYtapdurdHsztEkAiBd8xyqh4KLqFBnTBiico9QccXsFTU83tTWSTmjEXM/uA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":20167},"type":"module","exports":{".":"./dist/index.js"},"scripts":{"test":"vitest run","build":"tsc","prepublish":"rm -rf dist; pnpm run build"},"_npmUser":{"name":"externdefs","email":"hi@mary.my.id"},"repository":{"url":"https://tangled.org/did:plc:pljn5qch4tgadongtc7i6qij","directory":"packages/clients/firehose"},"description":"lightweight and cute XRPC subscription client for AT Protocol","directories":{},"_nodeVersion":"26.0.0","dependencies":{"type-fest":"^4.41.0","partysocket":"^1.3.0","@atcute/cbor":"^2.3.6","@atcute/lexicons":"^2.1.0","@atcute/uint8array":"^1.1.5","@mary-ext/event-iterator":"^1.0.0","@mary-ext/simple-event-emitter":"^1.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.3","vitest":"^4.1.10","@types/ws":"^8.18.1","@atcute/atproto":"^4.0.4"},"peerDependencies":{"@atcute/lexicons":"^2.1.0"},"_npmOperationalInternal":{"tmp":"tmp/firehose_1.1.0_1787124901657_0.9503197247976929","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"_id":"@atcute/firehose@1.2.0","dist":{"shasum":"c3dbcd185e85703b580a3280e94b7d1f91fc3760","tarball":"https://registry.npmjs.org/@atcute/firehose/-/firehose-1.2.0.tgz","fileCount":13,"integrity":"sha512-u6Oh137haGOzWNFbJzakUjjDOHvVNORY5r5H4v9OfHqVzFOYwSDptMYsD2TlRf4BbdtmHfjCb7pL1/D0eMfh6Q==","signatures":[{"sig":"MEQCICwVstN9vB9lhiHcZa8BOig/uMOtY1onrpIDb6aYmn/uAiB97fCkJPJyfOfb7yaKQ5NPkKTU4nychw8kb+s6porwMQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDOZ/P8KvdIdd30q7S6tM1t9HZhCuS7WFUEF2tggnY3jQIgCtrrscLi1SJmjjAQjtyFKVQUfB05gOydnVQmg6uYVpo="}],"unpackedSize":21052},"name":"@atcute/firehose","type":"module","exports":{".":"./dist/index.js"},"license":"0BSD","scripts":{"test":"vitest run","build":"tsc","prepublish":"rm -rf dist; pnpm run build"},"version":"1.2.0","_npmUser":{"name":"externdefs","email":"hi@mary.my.id"},"repository":{"url":"https://tangled.org/did:plc:pljn5qch4tgadongtc7i6qij","directory":"packages/clients/firehose"},"description":"lightweight and cute XRPC subscription client for AT Protocol","directories":{},"maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"sideEffects":false,"dependencies":{"partysocket":"^1.3.0","@atcute/cbor":"^2.3.7","@atcute/lexicons":"^2.1.0","@atcute/uint8array":"^1.1.5","@mary-ext/event-iterator":"^1.1.0","@mary-ext/simple-event-emitter":"^1.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.21.3","vitest":"^4.1.11","@types/ws":"^8.18.1","@atcute/atproto":"^4.0.4"},"peerDependencies":{"@atcute/lexicons":"^2.1.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/firehose_1.2.0_1789047809660_0.45430457946308067"}}},"time":{"created":"2025-11-05T23:39:09.340Z","modified":"2026-09-10T13:43:29.912Z","0.1.0":"2025-11-05T23:39:09.631Z","0.1.1":"2026-05-08T01:59:51.508Z","1.0.0":"2026-05-09T07:46:26.844Z","1.0.1":"2026-06-29T23:51:51.429Z","1.0.2":"2026-07-16T00:10:13.612Z","1.1.0":"2026-08-19T07:35:01.826Z","1.2.0":"2026-09-10T13:43:29.746Z"},"license":"0BSD","repository":{"url":"https://tangled.org/did:plc:pljn5qch4tgadongtc7i6qij","directory":"packages/clients/firehose"},"description":"lightweight and cute XRPC subscription client for AT Protocol","maintainers":[{"name":"externdefs","email":"hi@mary.my.id"}],"readme":"# @atcute/firehose\n\nlightweight XRPC subscription client for AT Protocol.\n\n```sh\nnpm install @atcute/firehose\n```\n\nthis package provides a generic client for XRPC subscriptions - the WebSocket-based streaming\nprotocol used by AT Protocol. it handles frame decoding, automatic reconnection, and optional schema\nvalidation.\n\nfor consuming the Bluesky network firehose specifically, consider using `@atcute/jetstream` instead,\nwhich provides a simpler JSON-based interface.\n\n## usage\n\n### subscribing to the relay firehose\n\n```ts\nimport { FirehoseSubscription } from '@atcute/firehose';\nimport { ComAtprotoSyncSubscribeRepos } from '@atcute/atproto';\n\nconst subscription = new FirehoseSubscription({\n\tservice: 'wss://bsky.network',\n\tnsid: ComAtprotoSyncSubscribeRepos.mainSchema,\n});\n\nfor await (const message of subscription) {\n\tconsole.log(message.$type, message.seq);\n}\n```\n\nthe connection opens when you start iterating and closes when you break out of the loop. the\nunderlying WebSocket automatically reconnects on disconnection.\n\n### cancelling the subscription\n\npass an `AbortSignal` to close the connection and reject iteration:\n\n```ts\nconst subscription = new FirehoseSubscription({\n\tservice: 'wss://bsky.network',\n\tnsid: ComAtprotoSyncSubscribeRepos.mainSchema,\n\tsignal: AbortSignal.timeout(10_000),\n});\n\nfor await (const message of subscription) {\n\tconsole.log(message.$type);\n}\n```\n\n### handling message types\n\nmessages include a `$type` field indicating their type:\n\n```ts\nfor await (const message of subscription) {\n\tswitch (message.$type) {\n\t\tcase 'com.atproto.sync.subscribeRepos#commit': {\n\t\t\t// repository commit (record creates, updates, deletes)\n\t\t\tconsole.log('commit:', message.repo, message.rev);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'com.atproto.sync.subscribeRepos#handle': {\n\t\t\t// handle change\n\t\t\tconsole.log('handle:', message.did, message.handle);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'com.atproto.sync.subscribeRepos#migrate': {\n\t\t\t// account migration\n\t\t\tconsole.log('migrate:', message.did, message.migrateTo);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'com.atproto.sync.subscribeRepos#tombstone': {\n\t\t\t// account deletion\n\t\t\tconsole.log('tombstone:', message.did);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'com.atproto.sync.subscribeRepos#identity': {\n\t\t\t// identity update\n\t\t\tconsole.log('identity:', message.did);\n\t\t\tbreak;\n\t\t}\n\n\t\tcase 'com.atproto.sync.subscribeRepos#account': {\n\t\t\t// account status change\n\t\t\tconsole.log('account:', message.did, message.active);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n```\n\n### tracking cursor for resumption\n\nuse a function for `params` to provide the current cursor on each connection attempt:\n\n```ts\nlet cursor: number | undefined;\n\n// load saved cursor if resuming\nconst saved = localStorage.getItem('firehose-cursor');\nif (saved) {\n\tcursor = Number(saved);\n}\n\nconst subscription = new FirehoseSubscription({\n\tservice: 'wss://bsky.network',\n\tnsid: ComAtprotoSyncSubscribeRepos.mainSchema,\n\t// function is called on each connection/reconnection\n\tparams: () => ({ cursor }),\n});\n\nfor await (const message of subscription) {\n\tif ('seq' in message) {\n\t\tcursor = message.seq;\n\n\t\t// periodically save cursor for recovery\n\t\tif (cursor % 1000 === 0) {\n\t\t\tlocalStorage.setItem('firehose-cursor', String(cursor));\n\t\t}\n\t}\n}\n```\n\nthe params function is called on each connection attempt, so when the WebSocket reconnects after a\ndisconnection, it automatically uses the latest cursor value.\n\n### using multiple servers\n\npass an array of URLs for automatic failover. the client randomly selects one on each connection:\n\n```ts\nconst subscription = new FirehoseSubscription({\n\tservice: ['wss://bsky.network', 'wss://bsky-relay.example.com'],\n\tnsid: ComAtprotoSyncSubscribeRepos.mainSchema,\n});\n```\n\n### handling errors\n\nXRPC subscriptions can send error frames. handle them with the `onError` callback:\n\n```ts\nconst subscription = new FirehoseSubscription({\n\tservice: 'wss://bsky.network',\n\tnsid: ComAtprotoSyncSubscribeRepos.mainSchema,\n\tonError(err) {\n\t\tconsole.error('firehose error:', err);\n\t\t// common errors:\n\t\t// - \"FutureCursor\": cursor is ahead of the server\n\t\t// - \"ConsumerTooSlow\": client is not consuming messages fast enough\n\t},\n});\n```\n\n### connection lifecycle callbacks\n\nhandle connection events for logging or UI updates:\n\n```ts\nconst subscription = new FirehoseSubscription({\n\tservice: 'wss://bsky.network',\n\tnsid: ComAtprotoSyncSubscribeRepos.mainSchema,\n\tonConnectionOpen(event) {\n\t\tconsole.log('connected to firehose');\n\t},\n\tonConnectionClose(event) {\n\t\tconsole.log('disconnected:', event.code, event.reason);\n\t},\n\tonConnectionError(event) {\n\t\tconsole.error('connection error:', event.error);\n\t},\n});\n```\n\n### updating options at runtime\n\nchange options using `updateOptions()`. this triggers a reconnection:\n\n```ts\nconst subscription = new FirehoseSubscription({\n\tservice: 'wss://bsky.network',\n\tnsid: ComAtprotoSyncSubscribeRepos.mainSchema,\n});\n\n// later, switch to a different service\nsubscription.updateOptions({\n\tservice: 'wss://different-relay.example.com',\n});\n```\n\n### disabling message validation\n\nby default, messages are validated against the schema. disable this for better performance if you\ntrust the server:\n\n```ts\nconst subscription = new FirehoseSubscription({\n\tservice: 'wss://bsky.network',\n\tnsid: ComAtprotoSyncSubscribeRepos.mainSchema,\n\tvalidateEvents: false,\n});\n```\n\n### WebSocket options\n\npass options to the underlying\n[partysocket](https://github.com/partykit/partykit/tree/main/packages/partysocket) WebSocket for\ncustom reconnection behavior:\n\n```ts\nconst subscription = new FirehoseSubscription({\n\tservice: 'wss://bsky.network',\n\tnsid: ComAtprotoSyncSubscribeRepos.mainSchema,\n\tws: {\n\t\tmaxRetries: 10,\n\t\tminReconnectionDelay: 1000,\n\t\tmaxReconnectionDelay: 30000,\n\t},\n});\n```\n","readmeFilename":""}