{"_id":"@benis-boy/shared-sse","_rev":"4-9d6ea007a64ceca33e2d05d46bdbb22a","name":"@benis-boy/shared-sse","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.0":{"name":"@benis-boy/shared-sse","version":"0.1.0","keywords":["sse","server-sent-events","eventsource","fetch-event-source","broadcast-channel","cross-tab","multi-tab","leader-election","react-query","tanstack-query","cache-invalidation"],"author":"","license":"MIT","_id":"@benis-boy/shared-sse@0.1.0","maintainers":[{"name":"benis-boy","email":"benjamin.d.warnecke@gmail.com"}],"homepage":"https://github.com/benis-boy/shared-sse#readme","bugs":{"url":"https://github.com/benis-boy/shared-sse/issues"},"dist":{"shasum":"86f20bb67dd337c72ec9372f2955e35a61634632","tarball":"https://registry.npmjs.org/@benis-boy/shared-sse/-/shared-sse-0.1.0.tgz","fileCount":26,"integrity":"sha512-LH1aOUscuYypZAv6AC1AI0jmTyyQ4E3bRCYlxzaoMq0Gu4jtZY8/v6shi7eUMDQbAUmR71kQEY4AG7031AasPA==","signatures":[{"sig":"MEQCIHBTnDS1jNGvCh3JcU2UL1gn4Y0ov6N5N1gnIfHMoemoAiAWTPieRwEJxuFkdlA5yQ8uneRgfzkqLTXy7mvt101nCw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":75797},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"f12b781a8af8dc25bea769377a47f563f2a25f45","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","verify":"npm run typecheck && npm run test && npm run build","typecheck":"tsc -p tsconfig.json --noEmit"},"_npmUser":{"name":"benis-boy","email":"benjamin.d.warnecke@gmail.com"},"repository":{"url":"git+https://github.com/benis-boy/shared-sse.git","type":"git"},"_npmVersion":"11.17.0","description":"Share one Server-Sent Events connection across browser tabs with fetch-event-source and broadcast-channel.","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","dependencies":{"broadcast-channel":"^7.1.0","@microsoft/fetch-event-source":"^2.0.1"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.0","typescript":"^5.9.0","@types/node":"^24.0.0","@tanstack/react-query":"^5.85.0"},"_npmOperationalInternal":{"tmp":"tmp/shared-sse_0.1.0_1787214604133_0.7967260244200125","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@benis-boy/shared-sse","version":"0.1.1","keywords":["sse","server-sent-events","eventsource","fetch-event-source","broadcast-channel","cross-tab","multi-tab","leader-election","react-query","tanstack-query","cache-invalidation"],"author":"","license":"MIT","_id":"@benis-boy/shared-sse@0.1.1","maintainers":[{"name":"benis-boy","email":"benjamin.d.warnecke@gmail.com"}],"homepage":"https://github.com/benis-boy/shared-sse#readme","bugs":{"url":"https://github.com/benis-boy/shared-sse/issues"},"dist":{"shasum":"f792195ff736ed2fd3bc9b0b8d497f38c2c6d7f2","tarball":"https://registry.npmjs.org/@benis-boy/shared-sse/-/shared-sse-0.1.1.tgz","fileCount":26,"integrity":"sha512-JLkCp1X8rY3jg5C6yRoeRb3PJXgVQxYvSUgEYJIc+lolvA9CVG0znFovmDjJS3PtgvdYJepnFKBPc6ekTAScTA==","signatures":[{"sig":"MEYCIQD+cLxB30reqKpAHMez77LfV6RKLDL4SBkBLGpDd1TVYAIhAP3v6xAO7qxNQG+Jgnjv2VhDDZc0SHrLL3VBvC2JSVpN","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":76098},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"b0bd493b25b7c4b527bbf62249ea3a88680cdc47","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","verify":"npm run typecheck && npm run test && npm run build","typecheck":"tsc -p tsconfig.json --noEmit","publish:release":"node ./scripts/publish-release.mjs"},"_npmUser":{"name":"benis-boy","email":"benjamin.d.warnecke@gmail.com"},"repository":{"url":"git+https://github.com/benis-boy/shared-sse.git","type":"git"},"_npmVersion":"11.17.0","description":"Share one Server-Sent Events connection across browser tabs with fetch-event-source and broadcast-channel.","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","dependencies":{"broadcast-channel":"^7.1.0","@microsoft/fetch-event-source":"^2.0.1"},"publishConfig":{"registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.0","typescript":"^5.9.0","@types/node":"^24.0.0","@tanstack/react-query":"^5.85.0"},"_npmOperationalInternal":{"tmp":"tmp/shared-sse_0.1.1_1787224493473_0.050987116724733106","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@benis-boy/shared-sse","version":"0.1.2","keywords":["sse","server-sent-events","eventsource","fetch-event-source","broadcast-channel","cross-tab","multi-tab","leader-election","react-query","tanstack-query","cache-invalidation"],"author":"","license":"MIT","_id":"@benis-boy/shared-sse@0.1.2","maintainers":[{"name":"benis-boy","email":"benjamin.d.warnecke@gmail.com"}],"homepage":"https://github.com/benis-boy/shared-sse#readme","bugs":{"url":"https://github.com/benis-boy/shared-sse/issues"},"dist":{"shasum":"1842fa65e0020e4ecaa8e4681029f6ab298d1d3e","tarball":"https://registry.npmjs.org/@benis-boy/shared-sse/-/shared-sse-0.1.2.tgz","fileCount":26,"integrity":"sha512-1Vnc4TYBMwwMyFjXnkgiW4TZnNRVqkb21FPLbDoJi0/37Q1HrrZXNAjhBqCW6mieSXBf+YP+kCLOsO3nhMDr5A==","signatures":[{"sig":"MEUCIB2Clxfgp78croUxk9QtQOe95qMzaiUCbrTdPiMop/gLAiEAgSE7ld8QSia9ap2lcj4/bTI005MhLsHGIwYNAdTCIvI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":78584},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"8d2e3046bbdea7e50c706aade4c8bd8e4e0091d5","scripts":{"lint":"tsc -p tsconfig.json --noEmit","test":"vitest run","build":"tsc -p tsconfig.build.json","verify":"npm run typecheck && npm run test && npm run build","typecheck":"tsc -p tsconfig.json --noEmit","publish:release":"node ./scripts/publish-release.mjs"},"_npmUser":{"name":"benis-boy","email":"benjamin.d.warnecke@gmail.com"},"repository":{"url":"git+https://github.com/benis-boy/shared-sse.git","type":"git"},"_npmVersion":"11.17.0","description":"Share one Server-Sent Events connection across browser tabs with fetch-event-source and broadcast-channel.","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","dependencies":{"broadcast-channel":"^7.1.0","@microsoft/fetch-event-source":"^2.0.1"},"publishConfig":{"registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.0","typescript":"^5.9.0","@types/node":"^24.0.0","@tanstack/react-query":"^5.85.0"},"_npmOperationalInternal":{"tmp":"tmp/shared-sse_0.1.2_1787227568014_0.08277608291579952","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@benis-boy/shared-sse","version":"0.1.3","description":"Share one Server-Sent Events connection across browser tabs with broadcast-channel.","type":"module","license":"MIT","author":"","homepage":"https://github.com/benis-boy/shared-sse#readme","repository":{"type":"git","url":"git+https://github.com/benis-boy/shared-sse.git"},"publishConfig":{"registry":"https://registry.npmjs.org/"},"bugs":{"url":"https://github.com/benis-boy/shared-sse/issues"},"keywords":["sse","server-sent-events","eventsource","broadcast-channel","cross-tab","multi-tab","leader-election","react-query","tanstack-query","cache-invalidation"],"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"main":"./dist/index.js","types":"./dist/index.d.ts","scripts":{"build":"tsc -p tsconfig.build.json","test":"vitest run","typecheck":"tsc -p tsconfig.json --noEmit","lint":"tsc -p tsconfig.json --noEmit","verify":"npm run typecheck && npm run test && npm run build","publish:release":"node ./scripts/publish-release.mjs"},"dependencies":{"broadcast-channel":"^7.1.0"},"devDependencies":{"@tanstack/react-query":"^5.85.0","@types/node":"^24.0.0","typescript":"^5.9.0","vitest":"^3.2.0"},"engines":{"node":">=20"},"sideEffects":false,"gitHead":"bfb1659f39c235ad6b508c8e63817528f0fbacff","_id":"@benis-boy/shared-sse@0.1.3","_nodeVersion":"24.19.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-yZso8q3IMPah4h2HdwQHT/wKhYdINU1C/WnXgYlnBqHYwyfAIqIg7/M1HRto1kyZwrLrd4xvy9nkgyQOcMO5/A==","shasum":"f2c37c658464726c730d266e9059bc4c9432fe03","tarball":"https://registry.npmjs.org/@benis-boy/shared-sse/-/shared-sse-0.1.3.tgz","fileCount":30,"unpackedSize":92553,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCRAWzyvH6Xfg+tW7vcm+qY3QfHfNRWzn/epUuDm5eiJgIhAPQxK5kzZVtOwUknzO1IhZFIh+K5FekS+eVRIOAiGH4A"}]},"_npmUser":{"name":"benis-boy","email":"benjamin.d.warnecke@gmail.com"},"directories":{},"maintainers":[{"name":"benis-boy","email":"benjamin.d.warnecke@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/shared-sse_0.1.3_1787326150225_0.7118772864628486"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-20T08:30:03.968Z","modified":"2026-08-21T15:29:10.508Z","0.1.0":"2026-08-20T08:30:04.270Z","0.1.1":"2026-08-20T11:14:53.628Z","0.1.2":"2026-08-20T12:06:08.166Z","0.1.3":"2026-08-21T15:29:10.364Z"},"bugs":{"url":"https://github.com/benis-boy/shared-sse/issues"},"license":"MIT","homepage":"https://github.com/benis-boy/shared-sse#readme","keywords":["sse","server-sent-events","eventsource","broadcast-channel","cross-tab","multi-tab","leader-election","react-query","tanstack-query","cache-invalidation"],"repository":{"type":"git","url":"git+https://github.com/benis-boy/shared-sse.git"},"description":"Share one Server-Sent Events connection across browser tabs with broadcast-channel.","maintainers":[{"name":"benis-boy","email":"benjamin.d.warnecke@gmail.com"}],"readme":"# @benis-boy/shared-sse\n\nShare one Server-Sent Events connection across browser tabs with `broadcast-channel`.\n\n## Install\n\n```sh\nnpm install @benis-boy/shared-sse\n```\n\n## Quick Start\n\n```ts\nimport { createSharedSseClient } from '@benis-boy/shared-sse'\n\nconst events = createSharedSseClient({\n  url: '/api/events',\n  headers: () => ({ Authorization: `Bearer ${token}` }),\n  channelName: 'app-events',\n})\n\nevents.on('publication.updated', (event) => {\n  console.log(event.data)\n})\n\nawait events.start({ scopeKey: userSessionId })\n```\n\nEach tab registers handlers locally. One tab becomes the leader and owns the network SSE request. Follower tabs receive the same logical events through `broadcast-channel`.\n\n## React Query Invalidation\n\n```ts\nimport { QueryClient } from '@tanstack/react-query'\nimport { createSharedSseClient } from '@benis-boy/shared-sse'\n\nconst queryClient = new QueryClient()\n\nconst events = createSharedSseClient<{ publicationId: string }>({\n  url: '/api/events',\n  channelName: 'app-events',\n})\n\nevents.on('publication.updated', (event) => {\n  queryClient.invalidateQueries({ queryKey: ['publication', event.data.publicationId] })\n})\n\nawait events.start({ scopeKey: userSessionId })\n```\n\n## API\n\n```ts\nconst events = createSharedSseClient({\n  url: '/api/events',\n  method: 'GET',\n  headers: () => ({ Authorization: `Bearer ${token}` }),\n  channelName: 'app-events',\n})\n\nawait events.start({ scopeKey: userSessionId })\nawait events.stop()\n\nconst unsubscribe = events.on('publication.*', (event) => {})\nevents.onMatch((event) => event.data != null, (event) => {})\nevents.onAny((event) => {})\nevents.onError((error) => {})\nevents.onStateChange((state) => {})\n\nevents.isLeader()\nevents.getState()\nevents.getLastEventId()\n\nunsubscribe()\n```\n\n## Lifecycle Rules\n\n- Create one client at app/module scope, not inside every component render.\n- Call `start()` after auth/session context is known.\n- Pass `scopeKey` for user-specific, tenant-specific, workspace-specific, or auth-session-specific streams.\n- Call `stop()` before starting again with a different `scopeKey`.\n- `stop()` is a reversible pause and clears the active `scopeKey`.\n- There is no public `close()` in v1.\n- If you use a one-shot request body such as `ReadableStream`, `Request`, or `Response`, pass `body` as a function so each reconnect gets a fresh body.\n\n## Event Routing\n\n```ts\nevents.on('publication.updated', handler)\nevents.on('publication.*', handler)\nevents.on('*.updated', handler)\nevents.onMatch((event) => event.data?.resourceType === 'publication', handler)\nevents.onAny(handler)\n```\n\n## Parsing\n\nBy default, `shared-sse` tries to parse SSE `data` as JSON and falls back to the raw string.\n\nUse `parse` to customize only the data value:\n\n```ts\nconst events = createSharedSseClient({\n  url: '/api/events',\n  parse: (data) => JSON.parse(data),\n})\n```\n\nUse `parseRaw` for complete event normalization:\n\n```ts\nconst events = createSharedSseClient({\n  url: '/api/events',\n  parseRaw: (raw) => ({\n    event: raw.event,\n    id: raw.id,\n    data: raw.data,\n    receivedAt: Date.now(),\n    meta: { origin: 'network' },\n  }),\n})\n```\n\n`parse` and `parseRaw` are mutually exclusive.\n\n## Visibility Behavior\n\nThe shared stream stays active if the leader tab becomes hidden so visible follower tabs do not starve. `openWhenHidden` is intentionally not exposed in v1.\n\n## Important Metadata\n\n`event.meta.origin` is diagnostic metadata only. Application behavior should not branch on `network` or `broadcast`; handlers should behave the same in leader and follower tabs.\n\n## Non-Goals\n\n- Not a cache manager.\n- Not React-specific.\n- Not a durable offline replay store.\n- Not a WebSocket replacement for bidirectional messaging.\n\n## Docs\n\n- [Quick start](docs/quickstart.md)\n- [API reference](docs/api.md)\n- [React Query](docs/react-query.md)\n- [Session isolation](docs/session-isolation.md)\n- [Troubleshooting](docs/troubleshooting.md)\n","readmeFilename":"README.md"}