@dokebi/sse 0.4.3 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AI.md CHANGED
@@ -94,7 +94,7 @@ export default defineApp({
94
94
 
95
95
  ## 4. Connection lifetime
96
96
 
97
- - Response: 200 `text/event-stream; charset=utf-8`, `Cache-Control: no-cache, no-transform`, `X-Accel-Buffering: no`, `Connection: keep-alive`. The first lines are `retry: <retryMs>` and `event: dokebi-open` (data `{"retryMs":…}`). The Fastify response is hijacked and written directly, so no compression hook applies (dokebi-web does not compress).
97
+ - Response: 200 `text/event-stream; charset=utf-8`, `Cache-Control: no-cache, no-transform`, `X-Accel-Buffering: no`; no `Connection` of its own, so Node answers the request's (a proxy that sends `Connection: close` upstream gets the socket closed after the stream, never reused). The first lines are `retry: <retryMs>` and `event: dokebi-open` (data `{"retryMs":…}`). The Fastify response is hijacked and written directly, so no compression hook applies (dokebi-web does not compress).
98
98
  - Refusals: another origin (not listed) 403 `ORIGIN_FORBIDDEN`; before start or while stopping 503 (dokebi-web `STARTING`, `DRAINING`; this plugin `CLOSING`); full 503 `CAPACITY` (`Retry-After: 5`); no authentication 401; an `authorization.valid()` that throws 500 `AUTHORIZATION_FAILED` (error `SSE_AUTHORIZATION_FAILED`); the session save before the stream failed 500 `COMMIT_FAILED` (below). EventSource cannot see these statuses (the client below tells them apart with a probe). For a listed foreign origin (`origins`) the 401, 503 and 500 refusals carry the same CORS headers as the stream, so a page of that origin (and the client's probe) can read them; another origin's 403 carries none.
99
99
  - Cookies (D-0089): the stream hijacks the Fastify reply, so **no onSend hook runs**. Just before it writes the head (after origin, capacity, `authenticate` and the probe), the stream runs the before-hijack steps that plugins register for the work they otherwise do in onSend — the @dokebi/session save (or rolling refresh) and the @dokebi/auth cookies (a remember-me restore by a `required` guard rotates the token) — and waits for them, at most `beforeStreamTimeoutMs` (5 s). Then every `Set-Cookie` on the reply (those steps, a hook, a guard) is written with the stream head; browsers apply it on the SSE 200. A step that fails or times out refuses the stream: 500 `{ error: 'COMMIT_FAILED' }`, error `SSE_COMMIT_FAILED` (the full cause). After the head the request's session is final (a change throws `CLOSED`). The steps are matched by name only (`Symbol.for('dokebi.web.beforeHijack')` on the Fastify instance): this package imports neither plugin. (The `dokebiProbe` answer below is a normal reply and runs onSend instead.)
100
100
  - `?dokebiProbe=1`: checks only origin, capacity and authentication and answers 204 (no stream is opened). The browser client uses it to find out why a connection failed.
package/dist/plugin.js CHANGED
@@ -109,7 +109,7 @@ class SseRuntime {
109
109
  /** Factory input: `{ app, options? }`. Options default to `app.config['dokebi-sse']`. */
110
110
  export const createPlugin = definePlugin({
111
111
  name: 'dokebi-sse',
112
- version: '0.4.3',
112
+ version: '0.4.4',
113
113
  core: '^0.4.2',
114
114
  // The declaration (not parseOptions) so core logs OPTION_DEPRECATED for old keys (bus, closeTimeoutMs).
115
115
  options: declaration,
package/dist/wire.d.ts CHANGED
@@ -13,5 +13,4 @@ export declare const HEADERS: Readonly<{
13
13
  'content-type': "text/event-stream; charset=utf-8";
14
14
  'cache-control': "no-cache, no-transform";
15
15
  'x-accel-buffering': "no";
16
- connection: "keep-alive";
17
16
  }>;
package/dist/wire.js CHANGED
@@ -40,5 +40,7 @@ export const HEADERS = Object.freeze({
40
40
  'cache-control': 'no-cache, no-transform',
41
41
  // nginx: do not buffer this response.
42
42
  'x-accel-buffering': 'no',
43
- connection: 'keep-alive',
43
+ // No `connection`: Node answers the request's own (keep-alive, or close when the proxy asked to
44
+ // close). A forced keep-alive kept a socket the proxy had closed for itself, and the request it
45
+ // sent next on it was refused by Node's parser with a bare 400 (HPE_CLOSED_CONNECTION).
44
46
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dokebi/sse",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "Server-sent events for @dokebi/web: authenticated streams, rooms, cross-worker fan-out over @dokebi/event-bus, and a browser client",
5
5
  "keywords": [
6
6
  "dokebi",
@@ -68,12 +68,12 @@
68
68
  }
69
69
  },
70
70
  "devDependencies": {
71
- "@dokebi/cluster": "0.4.1",
72
- "@dokebi/config": "0.4.4",
71
+ "@dokebi/cluster": "0.4.2",
72
+ "@dokebi/config": "0.4.5",
73
73
  "@dokebi/event-bus": "0.4.2",
74
74
  "@dokebi/health": "0.4.1",
75
75
  "@dokebi/nats": "0.4.1",
76
- "@dokebi/web": "0.4.3",
76
+ "@dokebi/web": "0.4.4",
77
77
  "react": "19.3.0",
78
78
  "react-test-renderer": "19.3.0",
79
79
  "vite": "8.3.4",