@opinionated-machine/sse-fallback 0.1.1 → 0.3.0
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/README.md +258 -4
- package/dist/binding.d.ts +13 -0
- package/dist/binding.d.ts.map +1 -1
- package/dist/binding.js +22 -0
- package/dist/binding.js.map +1 -1
- package/dist/bindingTypes.d.ts +57 -2
- package/dist/bindingTypes.d.ts.map +1 -1
- package/dist/bindingTypes.js +4 -1
- package/dist/bindingTypes.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/subscription.d.ts +144 -3
- package/dist/subscription.d.ts.map +1 -1
- package/dist/subscription.js +421 -42
- package/dist/subscription.js.map +1 -1
- package/dist/transport.d.ts +5 -1
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +5 -2
- package/dist/transport.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -44,13 +44,17 @@ the backoff.
|
|
|
44
44
|
## Declaring a binding
|
|
45
45
|
|
|
46
46
|
The binding is the one thing that cannot be inferred: how a poll snapshot
|
|
47
|
-
relates to the SSE events
|
|
47
|
+
relates to the SSE events, and whether there is one to relate at all. Declare
|
|
48
|
+
it once, colocated with the contract:
|
|
48
49
|
|
|
49
50
|
```ts
|
|
50
51
|
import { defineFallbackBinding } from '@opinionated-machine/sse-fallback'
|
|
51
52
|
|
|
52
53
|
// Use case A — await async completion
|
|
53
54
|
export const uploadStatusBinding = defineFallbackBinding(uploadStatusContract, {
|
|
55
|
+
// The snapshot is a real route the server answers, so polling can carry
|
|
56
|
+
// this subscription on its own. See "Choosing the combination" below.
|
|
57
|
+
snapshotSource: 'endpoint',
|
|
54
58
|
// Translate a snapshot into events; [] = "no news" (still advances the watermark)
|
|
55
59
|
snapshotToEvents: (s) =>
|
|
56
60
|
s.status === 'completed'
|
|
@@ -64,6 +68,7 @@ export const uploadStatusBinding = defineFallbackBinding(uploadStatusContract, {
|
|
|
64
68
|
|
|
65
69
|
// Use case B — initial state load + live hydration
|
|
66
70
|
export const projectStateBinding = defineFallbackBinding(projectStateContract, {
|
|
71
|
+
snapshotSource: 'endpoint',
|
|
67
72
|
snapshotEvent: 'stateChanged', // shorthand: snapshot body ≡ this event's payload
|
|
68
73
|
version: { ofSnapshot: (s) => s.revision, ofEvent: (e) => e.data.revision, dense: true },
|
|
69
74
|
state: {
|
|
@@ -98,7 +103,10 @@ for await (const event of sub.events()) { ... }
|
|
|
98
103
|
sub.onStateChange((state) => render(state))
|
|
99
104
|
|
|
100
105
|
sub.status // 'connecting' | 'live' | 'reconnecting' | 'polling' | 'stopped'
|
|
101
|
-
sub.nudge() // force
|
|
106
|
+
sub.nudge() // force a repair now: a poll, or, when the snapshot
|
|
107
|
+
// is synthesized, a reconnect that skips the backoff
|
|
108
|
+
sub.streamAbandoned // true once a refusal took the stream for good
|
|
109
|
+
sub.onStreamEstablished(() => {}) // a connection carried its first byte
|
|
102
110
|
sub.stop()
|
|
103
111
|
```
|
|
104
112
|
|
|
@@ -124,10 +132,51 @@ try {
|
|
|
124
132
|
| `reason` | Meaning |
|
|
125
133
|
|---|---|
|
|
126
134
|
| `'terminal-event'` | a terminal event was delivered — success |
|
|
127
|
-
| `'unretryable-status'` | refused with a status in `unretryableStatuses` (`status`, `channel`) |
|
|
135
|
+
| `'unretryable-status'` | refused with a status in `unretryableStatuses` (`status`, `channel`); a stream refusal lands here unless the poll can carry the subscription alone |
|
|
128
136
|
| `'budget-exhausted'` | `subscriptionBudget` ran out (`limit`) — show an error and offer a retry |
|
|
129
137
|
| `'manual'` | the caller called `stop()`, or the creation `signal` aborted |
|
|
130
138
|
|
|
139
|
+
### Reporting a broken stream
|
|
140
|
+
|
|
141
|
+
A fallback that works hides the fault that engaged it. Delivery carries on
|
|
142
|
+
over the poll, a few seconds late, and without a report nobody learns that the
|
|
143
|
+
stream behind it has been refused since the last deploy. So a subscription
|
|
144
|
+
that degrades hands an `Error` to `diagnostics.onDegraded`, and hands it again
|
|
145
|
+
every `degradationReportIntervalMs` (10 minutes by default) until the stream
|
|
146
|
+
carries bytes again:
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
createResilientSubscription(binding, {
|
|
150
|
+
transport,
|
|
151
|
+
diagnostics: {
|
|
152
|
+
onDegraded: (error) => errorTracker.notify(error),
|
|
153
|
+
onRecovered: ({ kind, degradedForMs }) => metrics.timing('sse.degraded', degradedForMs),
|
|
154
|
+
},
|
|
155
|
+
})
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The error is a `FallbackDegradedError`, and its message reads on its own in an
|
|
159
|
+
error tracker:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
SSE stream GET /projects/42/events was refused with 404 (it was never live); updates arrive late, on the fallback poll
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
| `kind` | Meaning |
|
|
166
|
+
|---|---|
|
|
167
|
+
| `'stream-refused'` | a status in `unretryableStatuses`; the stream is given up for good, so the report repeats for the life of the subscription |
|
|
168
|
+
| `'stream-rejected'` | any other non-200 status, or a 200 that is not `text/event-stream` (a proxy error page, an SPA fallback route) |
|
|
169
|
+
| `'stream-silent'` | accepted, then closed or timed out without a byte, which is what a buffering proxy looks like |
|
|
170
|
+
| `'stream-unreachable'` | the connect threw or timed out; an offline client produces this too, so it is the one kind worth ranking lower |
|
|
171
|
+
|
|
172
|
+
It also carries `status`, the `request`, `streamWasLive`,
|
|
173
|
+
`pollCarriesDelivery` (false for a synthesized snapshot, where nothing is
|
|
174
|
+
delivered at all), `reportCount` and `degradedForMs`, and the underlying
|
|
175
|
+
failure as `cause`. A non-200 answer on either channel reaches
|
|
176
|
+
`onStreamError` / `onPollError` as a `FallbackHttpError` with `channel`,
|
|
177
|
+
`status` and `request`. `mode: 'poll-only'` never reports: it had no stream to
|
|
178
|
+
lose.
|
|
179
|
+
|
|
131
180
|
### Bounding a pending operation
|
|
132
181
|
|
|
133
182
|
Every individual wait is bounded, but the subscription as a whole is not: a
|
|
@@ -164,10 +213,15 @@ The retry is granted once per failure streak: a second refusal with no
|
|
|
164
213
|
successful request in between stops the subscription with
|
|
165
214
|
`'unretryable-status'`.
|
|
166
215
|
|
|
216
|
+
A refusal the hook recovers is not a failure. The retry runs at once, with no
|
|
217
|
+
backoff, does not count toward `degradedAfterFailures`, and never reaches
|
|
218
|
+
`diagnostics.onDegraded`.
|
|
219
|
+
|
|
167
220
|
### Adopting before the SSE endpoint exists
|
|
168
221
|
|
|
169
222
|
`policy.mode: 'poll-only'` (or the `POLL_ONLY_POLICY` preset) never opens a
|
|
170
|
-
stream.
|
|
223
|
+
stream. It needs `snapshotSource: 'endpoint'`, since the poll is then the only
|
|
224
|
+
channel there is. The binding, version gate, reconciler and state machine are the same
|
|
171
225
|
ones the streaming rollout will use, so enabling SSE later is a config change
|
|
172
226
|
on an already-integrated subscription rather than a second migration.
|
|
173
227
|
|
|
@@ -178,6 +232,197 @@ than the snapshot are flushed — a zero missed-event window. After N
|
|
|
178
232
|
consecutive connect failures the subscription degrades to pure polling and
|
|
179
233
|
keeps probing SSE in the background.
|
|
180
234
|
|
|
235
|
+
One route into `POLLING_ONLY` never probes again: when a stream is refused
|
|
236
|
+
with an unretryable status and the poll carries the subscription on, the
|
|
237
|
+
stream is given up for the life of the subscription.
|
|
238
|
+
`subscription.streamAbandoned` is what separates that from ordinary
|
|
239
|
+
degradation, since both report `status: 'polling'`, and
|
|
240
|
+
`diagnostics.onStreamRefused` reports the moment it happens.
|
|
241
|
+
|
|
242
|
+
A binding whose snapshot is synthesized never reaches `POLLING_ONLY` at all:
|
|
243
|
+
there is no poll to fall back to, so the machine is `CONNECTING → LIVE ⇄
|
|
244
|
+
RECONNECTING → STOPPED` and a stream that is down reports `'reconnecting'`
|
|
245
|
+
for as long as it stays down.
|
|
246
|
+
|
|
247
|
+
## Choosing the combination
|
|
248
|
+
|
|
249
|
+
Three knobs decide what happens when something goes wrong: `snapshotSource` on
|
|
250
|
+
the binding, `mode` and `streamRefusal` on the policy. Only `snapshotSource`
|
|
251
|
+
has no default, because it is the only one the package cannot work out for
|
|
252
|
+
itself. A binding whose snapshot is answered locally is structurally identical
|
|
253
|
+
to one backed by a real route, and the difference only shows up at runtime, as
|
|
254
|
+
polls that return 200 and carry nothing.
|
|
255
|
+
|
|
256
|
+
| Surface | `snapshotSource` | `mode` | `streamRefusal` | Also |
|
|
257
|
+
|---|---|---|---|---|
|
|
258
|
+
| Await an async operation | `'endpoint'` | `'dual'` | `'auto'` | `subscriptionBudget` |
|
|
259
|
+
| Live view with a read route | `'endpoint'` | `'dual'` | `'auto'` | `LIVE_STATE_POLICY` |
|
|
260
|
+
| Live view where latency is the product | `'endpoint'` | `'dual'` | `'stop'` | `LIVE_STATE_POLICY` |
|
|
261
|
+
| Transitions no read reproduces | `'synthesized'` | `'dual'` | `'auto'` | repair on reconnect |
|
|
262
|
+
| SSE route not built yet | `'endpoint'` | `'poll-only'` | not read | `POLL_ONLY_POLICY` |
|
|
263
|
+
|
|
264
|
+
### Awaiting an async operation
|
|
265
|
+
|
|
266
|
+
An upload, an export, a long import: one subscription, one terminal event,
|
|
267
|
+
then it is over. The snapshot route already exists, because the page rendered
|
|
268
|
+
the operation before it subscribed, so the poll is the correctness backbone
|
|
269
|
+
and SSE only makes it feel instant.
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
export const uploadStatusBinding = defineFallbackBinding(uploadStatusContract, {
|
|
273
|
+
snapshotSource: 'endpoint',
|
|
274
|
+
snapshotToEvents: (s) =>
|
|
275
|
+
s.status === 'completed' ? [{ event: 'uploadFinished', data: { result: s.result } }] : [],
|
|
276
|
+
version: { ofSnapshot: (s) => s.version },
|
|
277
|
+
terminalEvents: ['uploadFinished'],
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
const sub = createResilientSubscription(uploadStatusBinding, {
|
|
281
|
+
transport,
|
|
282
|
+
params: { pathParams: { uploadId } },
|
|
283
|
+
// A backend stuck in 'pending' would otherwise poll until the tab closes.
|
|
284
|
+
policy: { subscriptionBudget: { maxDurationMs: 10 * 60_000, maxPolls: 200 } },
|
|
285
|
+
})
|
|
286
|
+
const { result } = await sub.waitFor('uploadFinished')
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Everything else is default and should stay that way. `initialPoll: 'eager'`
|
|
290
|
+
hydrates from the snapshot before the first event, so an operation that
|
|
291
|
+
finished before the subscription opened still resolves the wait.
|
|
292
|
+
`streamRefusal: 'auto'` resolves to keeping the poll: a refused SSE route
|
|
293
|
+
costs the instant feel, not the result. The budget is the one addition worth
|
|
294
|
+
making, because a wait that never ends is worse than one that fails.
|
|
295
|
+
|
|
296
|
+
### A live view with a read route
|
|
297
|
+
|
|
298
|
+
A list or a state view that stays mounted: rows updating as an import
|
|
299
|
+
progresses, a counter on a dashboard. The read route exists because the list
|
|
300
|
+
had to load, so both channels work and the poll covers whatever the stream
|
|
301
|
+
misses.
|
|
302
|
+
|
|
303
|
+
```ts
|
|
304
|
+
export const uploadedItemsBinding = bindFallbackContracts(
|
|
305
|
+
GET_UPLOADED_ITEMS_CONTRACT,
|
|
306
|
+
GET_UPLOADED_ITEMS_SUBSCRIBE_CONTRACT,
|
|
307
|
+
{
|
|
308
|
+
snapshotSource: 'endpoint',
|
|
309
|
+
snapshotToEvents: (snapshot) =>
|
|
310
|
+
snapshot.data.map((item) => ({ event: 'upload_item.changed', data: item })),
|
|
311
|
+
version: 'none',
|
|
312
|
+
},
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
createResilientSubscription(uploadedItemsBinding, {
|
|
316
|
+
transport,
|
|
317
|
+
params,
|
|
318
|
+
// Permanently mounted, so poll slowly while idle and nudge() on user intent.
|
|
319
|
+
policy: LIVE_STATE_POLICY,
|
|
320
|
+
})
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
`LIVE_STATE_POLICY` stretches the idle deadman to 120s backing off to 300s, so
|
|
324
|
+
a tab left open overnight is not a polling machine, and holds the degraded
|
|
325
|
+
cadence at 60s for when the stream is gone. No budget here: the subscription
|
|
326
|
+
should outlive anything the user is doing. `nudge()` is the way back to fast,
|
|
327
|
+
for the moment a user does something that ought to show a result now.
|
|
328
|
+
|
|
329
|
+
### Transitions no read reproduces
|
|
330
|
+
|
|
331
|
+
Some events are not state. "This batch of segments was re-translated", "the
|
|
332
|
+
search index caught up", "word counts were recalculated": no `GET` returns
|
|
333
|
+
them, so a poll has nothing to fetch. The transport answers the snapshot
|
|
334
|
+
channel locally, and the binding says so.
|
|
335
|
+
|
|
336
|
+
```ts
|
|
337
|
+
const pushOnlyTransport: FallbackTransport = {
|
|
338
|
+
openStream: (request, opts) => streamTransport.openStream(request, opts),
|
|
339
|
+
fetchSnapshot: () => Promise.resolve({ status: 200, headers: {}, body: {} }),
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const binding: FallbackBinding<unknown, SegmentEvents> = {
|
|
343
|
+
config: { snapshotSource: 'synthesized', snapshotToEvents: () => [], version: 'none' },
|
|
344
|
+
buildSnapshotRequest: () => ({ path: '', method: 'get' }), // never dispatched
|
|
345
|
+
buildStreamRequest: (params) => ({ path: streamPath(params), method: 'get' }),
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
`'synthesized'` switches the poll channel off rather than running it into a
|
|
350
|
+
wall: no hydration poll, no deadman, no fallback cadence, and `nudge()`
|
|
351
|
+
reconnects a stream waiting out its backoff instead of fetching nothing (a
|
|
352
|
+
stream that is connecting or open is left to the stale-connection watchdog,
|
|
353
|
+
since quiet is normal here). The status machine loses `'polling'`, since there
|
|
354
|
+
is nothing to poll: a stream that is down reports `'reconnecting'`, and one
|
|
355
|
+
that is accepted reports `'live'` without waiting for a byte, after a
|
|
356
|
+
degradation as much as on the first connect.
|
|
357
|
+
|
|
358
|
+
With no snapshot ever fetched there is nothing to initialize a `state` layer
|
|
359
|
+
from, so `defineFallbackBinding` rejects `state` beside `'synthesized'`; reduce
|
|
360
|
+
the events in an `onEvent` listener instead.
|
|
361
|
+
|
|
362
|
+
A refused stream stops the subscription, which is what this shape wants: the
|
|
363
|
+
stop is the only signal that live updates are gone, and something has to act
|
|
364
|
+
on it. The stop detail carries `streamWasLive`, which tells a route nobody
|
|
365
|
+
could reach from one withdrawn mid-session. Repair after a reconnect is the
|
|
366
|
+
consumer's job too, since only they know what to re-read:
|
|
367
|
+
|
|
368
|
+
```ts
|
|
369
|
+
sub.onStreamEstablished(() => {
|
|
370
|
+
queryClient.invalidateQueries({ queryKey: ['segments', projectId] })
|
|
371
|
+
})
|
|
372
|
+
sub.onStop((detail) => reportToErrorTracker('live segment updates are off', detail))
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
`onStreamEstablished` fires when a connection carries its first byte, which
|
|
376
|
+
the server's heartbeat makes prompt. `'live'` is the wrong trigger for a
|
|
377
|
+
repair: it arrives on the accepted connect, so an upstream that accepts and
|
|
378
|
+
closes at once would repeat the repair on every retry.
|
|
379
|
+
|
|
380
|
+
A snapshot route that exists but cannot be expressed as events belongs here
|
|
381
|
+
too, and the subscription never dispatches it. An endpoint that answers 204
|
|
382
|
+
when no process is running gives `snapshotToEvents` nothing to return, and a
|
|
383
|
+
read model that ten call sites already share through a query cache is better
|
|
384
|
+
invalidated on reconnect than duplicated into the version gate. Declaring such
|
|
385
|
+
a route `'endpoint'` would poll it for nothing and report `'polling'` while no
|
|
386
|
+
update can arrive.
|
|
387
|
+
|
|
388
|
+
### Latency is the product
|
|
389
|
+
|
|
390
|
+
A cursor position, a presence dot, a live-typing badge. A 15s poll is not a
|
|
391
|
+
degraded version of those, it is a different feature that happens to return
|
|
392
|
+
data.
|
|
393
|
+
|
|
394
|
+
```ts
|
|
395
|
+
createResilientSubscription(presenceBinding, {
|
|
396
|
+
transport,
|
|
397
|
+
policy: { ...LIVE_STATE_POLICY, streamRefusal: 'stop' },
|
|
398
|
+
})
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
The snapshot stays `'endpoint'`, because it exists and hydration uses it. What
|
|
402
|
+
changes is the meaning of a refusal: `'stop'` hands the surface one clear
|
|
403
|
+
signal to hide the indicator, instead of a cadence nobody perceives as live.
|
|
404
|
+
|
|
405
|
+
### Combinations the constructor rejects
|
|
406
|
+
|
|
407
|
+
These throw at construction, rather than at the first failure hours later:
|
|
408
|
+
|
|
409
|
+
- `mode: 'poll-only'` with `snapshotSource: 'synthesized'`. No stream is ever
|
|
410
|
+
opened and the poll delivers nothing, so the subscription could only sit
|
|
411
|
+
there.
|
|
412
|
+
- `streamRefusal: 'keep-polling'` with `snapshotSource: 'synthesized'`. The
|
|
413
|
+
poll cannot stand in for a refused stream, so the subscription would report
|
|
414
|
+
itself healthy and deliver nothing.
|
|
415
|
+
- `state` with `snapshotSource: 'synthesized'`.
|
|
416
|
+
State is initialized and repaired from a snapshot, and a synthesized one is
|
|
417
|
+
never fetched, so `getState()` would stay `undefined`.
|
|
418
|
+
- A `snapshotSource` that is neither `'endpoint'` nor `'synthesized'`, from a
|
|
419
|
+
JS caller or a config spread from an older one: the value decides whether
|
|
420
|
+
the poll channel runs at all.
|
|
421
|
+
|
|
422
|
+
The last two are checked by `defineFallbackBinding` / `bindFallbackContracts`
|
|
423
|
+
as well, so they fail where the binding is declared; a hand-built binding meets
|
|
424
|
+
them at `createResilientSubscription`.
|
|
425
|
+
|
|
181
426
|
## The version gate
|
|
182
427
|
|
|
183
428
|
Every event and snapshot carries a version; an item is delivered iff its
|
|
@@ -191,6 +436,13 @@ version exceeds the high-watermark. This one rule handles:
|
|
|
191
436
|
`version: 'none'` opts into at-least-once/last-writer-wins semantics as an
|
|
192
437
|
adoption bridge — strongly prefer real versions.
|
|
193
438
|
|
|
439
|
+
Without a version the stale-poll race has no watermark to settle it, so the
|
|
440
|
+
subscription settles it by arrival order instead: a snapshot requested before
|
|
441
|
+
the stream delivered an event is dropped (`onStaleSnapshot`) and requested
|
|
442
|
+
again, since its body may predate the pushed news. After three overtaken
|
|
443
|
+
polls in a row the next one is delivered anyway, so a busy stream cannot
|
|
444
|
+
starve the poll that repairs an outage.
|
|
445
|
+
|
|
194
446
|
## Server-side guarantees (the adopting team's checklist)
|
|
195
447
|
|
|
196
448
|
1. **Required**: a monotonic version per subscription scope, present in both
|
|
@@ -290,8 +542,10 @@ responsibility.
|
|
|
290
542
|
| `hydrationAbandonAfterFailures` | 3 | flush the buffer rather than silence a healthy stream |
|
|
291
543
|
| `unretryableStatuses` | 401, 403, 404 | stop instead of retrying |
|
|
292
544
|
| `authChallengeStatuses` | 401 | offered to `onAuthChallenge` before giving up |
|
|
545
|
+
| `streamRefusal` | `'auto'` | follows `snapshotSource`: keep polling on an endpoint snapshot, stop on a synthesized one |
|
|
293
546
|
| `mode` | `'dual'` | `'poll-only'` never opens a stream |
|
|
294
547
|
| `subscriptionBudget` | unset | `{ maxDurationMs, maxPolls }` — a hard give-up bound |
|
|
548
|
+
| `degradationReportIntervalMs` | 600 000 | how often `onDegraded` repeats while degraded; `'off'` reports once |
|
|
295
549
|
|
|
296
550
|
Every wait in the machine is bounded, because an unbounded one turns the
|
|
297
551
|
fallback into no fallback at all: a hung connect or a poll that never settles
|
package/dist/binding.d.ts
CHANGED
|
@@ -26,6 +26,18 @@ export type FallbackBinding<Snapshot = unknown, Events extends EventPayloadMap =
|
|
|
26
26
|
buildSnapshotRequest(params: FallbackRequestParams): TransportRequest;
|
|
27
27
|
buildStreamRequest(params: FallbackRequestParams): TransportRequest;
|
|
28
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* `snapshotSource` decides whether the poll channel runs at all, so a value
|
|
31
|
+
* that is missing or misspelled (a JS caller, a spread of an older config)
|
|
32
|
+
* must fail here rather than quietly switch polling off.
|
|
33
|
+
*
|
|
34
|
+
* Also run by `createResilientSubscription`, since a hand-built binding never
|
|
35
|
+
* passes through `defineFallbackBinding`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function validateSnapshotSource(config: {
|
|
38
|
+
readonly snapshotSource: unknown;
|
|
39
|
+
readonly state?: unknown;
|
|
40
|
+
}): void;
|
|
29
41
|
/** Read a binding previously stamped on a contract, or `undefined`. */
|
|
30
42
|
export declare function readFallbackBinding(contract: object): FallbackBinding | undefined;
|
|
31
43
|
/**
|
|
@@ -36,6 +48,7 @@ export declare function readFallbackBinding(contract: object): FallbackBinding |
|
|
|
36
48
|
* @example
|
|
37
49
|
* ```ts
|
|
38
50
|
* export const uploadStatusBinding = defineFallbackBinding(uploadStatusContract, {
|
|
51
|
+
* snapshotSource: 'endpoint',
|
|
39
52
|
* snapshotToEvents: (s) =>
|
|
40
53
|
* s.status === 'completed' ? [{ event: 'uploadFinished', data: { result: s.result } }] : [],
|
|
41
54
|
* version: { ofSnapshot: (s) => s.version },
|
package/dist/binding.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../src/binding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEtD;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,eAAyD,CAAA;AAE7F,oDAAoD;AACpD,MAAM,MAAM,qBAAqB,GAAG;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAA;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,2DAA2D;IAC3D,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,CACzB,QAAQ,GAAG,OAAO,EAClB,MAAM,SAAS,eAAe,GAAG,eAAe,EAChD,KAAK,GAAG,SAAS,IACf;IACF,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAA;IAC/D,oBAAoB,CAAC,MAAM,EAAE,qBAAqB,GAAG,gBAAgB,CAAA;IACrE,kBAAkB,CAAC,MAAM,EAAE,qBAAqB,GAAG,gBAAgB,CAAA;CACpE,CAAA;
|
|
1
|
+
{"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../src/binding.ts"],"names":[],"mappings":"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"}
|
package/dist/binding.js
CHANGED
|
@@ -40,6 +40,27 @@ function validateConfig(config) {
|
|
|
40
40
|
if (hasMapper === hasShorthand) {
|
|
41
41
|
throw new Error('FallbackBindingConfig requires exactly one of snapshotToEvents / snapshotEvent.');
|
|
42
42
|
}
|
|
43
|
+
validateSnapshotSource(config);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* `snapshotSource` decides whether the poll channel runs at all, so a value
|
|
47
|
+
* that is missing or misspelled (a JS caller, a spread of an older config)
|
|
48
|
+
* must fail here rather than quietly switch polling off.
|
|
49
|
+
*
|
|
50
|
+
* Also run by `createResilientSubscription`, since a hand-built binding never
|
|
51
|
+
* passes through `defineFallbackBinding`.
|
|
52
|
+
*/
|
|
53
|
+
export function validateSnapshotSource(config) {
|
|
54
|
+
const source = config.snapshotSource;
|
|
55
|
+
if (source !== 'endpoint' && source !== 'synthesized') {
|
|
56
|
+
throw new Error(`FallbackBindingConfig.snapshotSource must be 'endpoint' or 'synthesized', got ${JSON.stringify(source)}.`);
|
|
57
|
+
}
|
|
58
|
+
if (source === 'synthesized' && config.state !== undefined) {
|
|
59
|
+
// The state layer is initialized, and repaired after a gap, only from a
|
|
60
|
+
// snapshot, and a synthesized one is never fetched: `getState()` would
|
|
61
|
+
// stay `undefined` for the life of the subscription.
|
|
62
|
+
throw new Error("FallbackBindingConfig.state requires snapshotSource: 'endpoint'. A synthesized snapshot is never fetched, so there is nothing to initialize or repair state from. Reduce the events in an onEvent listener instead.");
|
|
63
|
+
}
|
|
43
64
|
}
|
|
44
65
|
/** Expand the `snapshotEvent` shorthand into `snapshotToEvents`. */
|
|
45
66
|
function normalizeConfig(config) {
|
|
@@ -97,6 +118,7 @@ export function readFallbackBinding(contract) {
|
|
|
97
118
|
* @example
|
|
98
119
|
* ```ts
|
|
99
120
|
* export const uploadStatusBinding = defineFallbackBinding(uploadStatusContract, {
|
|
121
|
+
* snapshotSource: 'endpoint',
|
|
100
122
|
* snapshotToEvents: (s) =>
|
|
101
123
|
* s.status === 'completed' ? [{ event: 'uploadFinished', data: { result: s.result } }] : [],
|
|
102
124
|
* version: { ofSnapshot: (s) => s.version },
|
package/dist/binding.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"binding.js","sourceRoot":"","sources":["../src/binding.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"binding.js","sourceRoot":"","sources":["../src/binding.ts"],"names":[],"mappings":"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"}
|
package/dist/bindingTypes.d.ts
CHANGED
|
@@ -92,6 +92,26 @@ export type FallbackBindingConfig<Snapshot, Events extends EventPayloadMap, Stat
|
|
|
92
92
|
* `snapshotToEvents: (s) => [{ event: snapshotEvent, data: s }]`.
|
|
93
93
|
*/
|
|
94
94
|
snapshotEvent?: keyof Events & string;
|
|
95
|
+
/**
|
|
96
|
+
* Where a poll snapshot comes from, and with it whether polling can carry
|
|
97
|
+
* this subscription when the stream cannot.
|
|
98
|
+
*
|
|
99
|
+
* - `'endpoint'`: a real request the server answers. The poll is the
|
|
100
|
+
* correctness backbone: it hydrates, it repairs gaps, and it keeps
|
|
101
|
+
* delivering while the stream is down.
|
|
102
|
+
* - `'synthesized'`: the transport answers it without asking the server
|
|
103
|
+
* (`fetchSnapshot` resolving a local value, `snapshotToEvents: () => []`),
|
|
104
|
+
* because the events are transitions no read reproduces. A poll delivers
|
|
105
|
+
* nothing the stream did not, so none are run: no hydration poll, no
|
|
106
|
+
* deadman, no fallback cadence, and a refused stream stops the
|
|
107
|
+
* subscription instead of pretending a poll covers it. Repair after a
|
|
108
|
+
* reconnect is the consumer's job, off `onStatusChange`. With no snapshot
|
|
109
|
+
* to initialize it from, {@link state} is rejected alongside it.
|
|
110
|
+
*
|
|
111
|
+
* Required, and not inferable: both shapes implement the same binding, and
|
|
112
|
+
* the difference only shows up in what the transport does at runtime.
|
|
113
|
+
*/
|
|
114
|
+
snapshotSource: 'endpoint' | 'synthesized';
|
|
95
115
|
/** Version extraction/ordering, or `'none'` (see {@link VersionConfig}). */
|
|
96
116
|
version: VersionConfig<Snapshot, FallbackEvent<Events>>;
|
|
97
117
|
/**
|
|
@@ -105,7 +125,8 @@ export type FallbackBindingConfig<Snapshot, Events extends EventPayloadMap, Stat
|
|
|
105
125
|
* the subscription handle exposes `getState()` / `onStateChange()`.
|
|
106
126
|
* Snapshots REPLACE state via `init`; live events update it via `apply`.
|
|
107
127
|
* Events synthesized from a snapshot are not applied (the snapshot already
|
|
108
|
-
* subsumes them).
|
|
128
|
+
* subsumes them). Requires `snapshotSource: 'endpoint'`: a synthesized
|
|
129
|
+
* snapshot is never fetched, so there would be nothing to `init` from.
|
|
109
130
|
*/
|
|
110
131
|
state?: {
|
|
111
132
|
init: (snapshot: Snapshot) => State;
|
|
@@ -273,6 +294,39 @@ export type FallbackPolicy = {
|
|
|
273
294
|
* @default [401]
|
|
274
295
|
*/
|
|
275
296
|
authChallengeStatuses: ReadonlyArray<number>;
|
|
297
|
+
/**
|
|
298
|
+
* What a refusal on the STREAM channel does: a status in
|
|
299
|
+
* {@link unretryableStatuses} that `onAuthChallenge` did not recover.
|
|
300
|
+
*
|
|
301
|
+
* - `'auto'` reads {@link FallbackBindingConfig.snapshotSource}:
|
|
302
|
+
* `'endpoint'` keeps polling, `'synthesized'` stops. This is the right
|
|
303
|
+
* answer for both, which is why the binding is asked to declare it.
|
|
304
|
+
* - `'keep-polling'` gives the stream up and leaves the poll running on
|
|
305
|
+
* its degraded cadence, so a route that moved or a permission covering
|
|
306
|
+
* the stream alone costs latency instead of every channel. Requires
|
|
307
|
+
* `snapshotSource: 'endpoint'`; the constructor throws otherwise, since
|
|
308
|
+
* a synthesized snapshot would poll on and deliver nothing, hiding the
|
|
309
|
+
* refusal instead of surviving it.
|
|
310
|
+
* - `'stop'` ends the subscription, and with it the poll. Worth setting
|
|
311
|
+
* over `'auto'` on a surface where a 15s poll cadence is not a product
|
|
312
|
+
* (a live cursor, a presence indicator): failing loudly beats pretending.
|
|
313
|
+
*
|
|
314
|
+
* Keeping the poll is one-way for the life of the subscription: the stream
|
|
315
|
+
* is never reopened, and `subscription.streamAbandoned` reports it.
|
|
316
|
+
*
|
|
317
|
+
* A refusal on the poll channel stops the subscription under any value.
|
|
318
|
+
* Whether a stream is opened at all is {@link mode}, a separate question.
|
|
319
|
+
* @default 'auto'
|
|
320
|
+
*/
|
|
321
|
+
streamRefusal: 'auto' | 'stop' | 'keep-polling';
|
|
322
|
+
/**
|
|
323
|
+
* How often `diagnostics.onDegraded` repeats while the subscription stays
|
|
324
|
+
* degraded. A fallback that keeps delivering is what lets a broken stream
|
|
325
|
+
* become the permanent state unnoticed, so the report does not stop at the
|
|
326
|
+
* first one. `'off'` reports each degradation once.
|
|
327
|
+
* @default 600_000
|
|
328
|
+
*/
|
|
329
|
+
degradationReportIntervalMs: number | 'off';
|
|
276
330
|
};
|
|
277
331
|
export declare const DEFAULT_POLICY: FallbackPolicy;
|
|
278
332
|
/**
|
|
@@ -287,7 +341,8 @@ export declare const LIVE_STATE_POLICY: FallbackPolicy;
|
|
|
287
341
|
/**
|
|
288
342
|
* Preset for adopters with no SSE endpoint yet: same binding, version gate and
|
|
289
343
|
* state machine as the dual-mode presets, polling only. Flip `mode` back to
|
|
290
|
-
* `'dual'` once the stream exists.
|
|
344
|
+
* `'dual'` once the stream exists. Requires `snapshotSource: 'endpoint'`: the
|
|
345
|
+
* poll is the only channel there is.
|
|
291
346
|
*/
|
|
292
347
|
export declare const POLL_ONLY_POLICY: FallbackPolicy;
|
|
293
348
|
type SseBodyLike<TSchemas> = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bindingTypes.d.ts","sourceRoot":"","sources":["../src/bindingTypes.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAA;AAM/B,uEAAuE;AACvE,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;AAErC;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,CAAC,QAAQ,EAAE,KAAK,IACrC;IACE,qDAAqD;IACrD,UAAU,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAA;IAC3C;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,GAAG,SAAS,CAAA;IAC/C,6EAA6E;IAC7E,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,KAAK,MAAM,CAAA;IAC5C;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AACH;;;;;GAKG;GACD,MAAM,CAAA;AAMV,6CAA6C;AAC7C,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAErD,4EAA4E;AAC5E,MAAM,MAAM,aAAa,CAAC,MAAM,SAAS,eAAe,GAAG,eAAe,IAAI;KAC3E,CAAC,IAAI,MAAM,MAAM,GAAG,MAAM,GAAG;QAC5B,KAAK,EAAE,CAAC,CAAA;QACR,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;QACf,qDAAqD;QACrD,EAAE,CAAC,EAAE,MAAM,CAAA;QACX;;;WAGG;QACH,MAAM,EAAE,mBAAmB,CAAA;KAC5B;CACF,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAA;AAExB,MAAM,MAAM,mBAAmB,GAAG,KAAK,GAAG,MAAM,CAAA;AAEhD,kEAAkE;AAClE,MAAM,MAAM,cAAc,CAAC,MAAM,SAAS,eAAe,GAAG,eAAe,IAAI;KAC5E,CAAC,IAAI,MAAM,MAAM,GAAG,MAAM,GAAG;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;KAAE;CAC5D,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAA;AAMxB;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,CAAC,QAAQ,EAAE,MAAM,SAAS,eAAe,EAAE,KAAK,GAAG,SAAS,IAAI;IAC/F;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,aAAa,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAA;IAChF;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,MAAM,GAAG,MAAM,CAAA;IAErC,4EAA4E;IAC5E,OAAO,EAAE,aAAa,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAAA;IAEvD;;;;OAIG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAA;IAErD
|
|
1
|
+
{"version":3,"file":"bindingTypes.d.ts","sourceRoot":"","sources":["../src/bindingTypes.ts"],"names":[],"mappings":"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"}
|
package/dist/bindingTypes.js
CHANGED
|
@@ -16,6 +16,8 @@ export const DEFAULT_POLICY = {
|
|
|
16
16
|
hydrationBufferLimit: 1_000,
|
|
17
17
|
unretryableStatuses: [401, 403, 404],
|
|
18
18
|
authChallengeStatuses: [401],
|
|
19
|
+
streamRefusal: 'auto',
|
|
20
|
+
degradationReportIntervalMs: 600_000,
|
|
19
21
|
};
|
|
20
22
|
/**
|
|
21
23
|
* Preset for use case A — await async completion.
|
|
@@ -34,7 +36,8 @@ export const LIVE_STATE_POLICY = {
|
|
|
34
36
|
/**
|
|
35
37
|
* Preset for adopters with no SSE endpoint yet: same binding, version gate and
|
|
36
38
|
* state machine as the dual-mode presets, polling only. Flip `mode` back to
|
|
37
|
-
* `'dual'` once the stream exists.
|
|
39
|
+
* `'dual'` once the stream exists. Requires `snapshotSource: 'endpoint'`: the
|
|
40
|
+
* poll is the only channel there is.
|
|
38
41
|
*/
|
|
39
42
|
export const POLL_ONLY_POLICY = {
|
|
40
43
|
...DEFAULT_POLICY,
|
package/dist/bindingTypes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bindingTypes.js","sourceRoot":"","sources":["../src/bindingTypes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bindingTypes.js","sourceRoot":"","sources":["../src/bindingTypes.ts"],"names":[],"mappings":"AAmWA,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,OAAO;IACpB,cAAc,EAAE,MAAM;IACtB,kBAAkB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE;IAClD,wBAAwB,EAAE,MAAM;IAChC,gBAAgB,EAAE,MAAM;IACxB,aAAa,EAAE,MAAM;IACrB,kBAAkB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE;IAC/D,eAAe,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE;IAC5D,qBAAqB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE;IACpD,6BAA6B,EAAE,CAAC;IAChC,qBAAqB,EAAE,CAAC;IACxB,sBAAsB,EAAE,MAAM;IAC9B,qBAAqB,EAAE,MAAM;IAC7B,oBAAoB,EAAE,KAAK;IAC3B,mBAAmB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;IACpC,qBAAqB,EAAE,CAAC,GAAG,CAAC;IAC5B,aAAa,EAAE,MAAM;IACrB,2BAA2B,EAAE,OAAO;CACrC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAmB,cAAc,CAAA;AAE/D,mEAAmE;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAAmB;IAC/C,GAAG,cAAc;IACjB,cAAc,EAAE,OAAO;IACvB,kBAAkB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE;IACnD,sBAAsB,EAAE,MAAM;CAC/B,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAmB;IAC9C,GAAG,cAAc;IACjB,IAAI,EAAE,WAAW;CAClB,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,6 @@ export { type BackoffConfig, COMPLETION_POLICY, DEFAULT_POLICY, type EventPayloa
|
|
|
4
4
|
export { createPollGate, type PollGate, type PollGateConfig } from './pollGate.ts';
|
|
5
5
|
export { defaultCompareVersions, type EventOutcome, type IncomingEvent, type InvalidVersionInfo, Reconciler, type SnapshotOutcome, type VersionGap, } from './reconciler.ts';
|
|
6
6
|
export { backoffDelay, ResettableTimer, sleep } from './scheduler.ts';
|
|
7
|
-
export { type CreateResilientSubscriptionOptions, createResilientSubscription, type FallbackDiagnostics, type ResilientSubscription, type StopReason, type SubscriptionStatus, type SubscriptionStopDetail, SubscriptionStoppedError, } from './subscription.ts';
|
|
7
|
+
export { type CreateResilientSubscriptionOptions, createResilientSubscription, type DegradationKind, FallbackDegradedError, type FallbackDiagnostics, FallbackHttpError, type ResilientSubscription, type StopReason, type SubscriptionStatus, type SubscriptionStopDetail, SubscriptionStoppedError, } from './subscription.ts';
|
|
8
8
|
export { type FallbackTransport, isParsedStreamResponse, type ParsedSseFrame, type ParsedStreamResponse, type RawStreamResponse, type SnapshotResponse, type StreamResponse, type TestSnapshotCall, type TestStreamHandle, TestTransport, type TransportRequest, } from './transport.ts';
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,qBAAqB,EACrB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,KAAK,eAAe,GACrB,MAAM,iCAAiC,CAAA;AACxC,OAAO,EACL,KAAK,4BAA4B,EACjC,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,KAAK,aAAa,EAClB,iBAAiB,EACjB,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,OAAO,EACZ,KAAK,aAAa,GACnB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA;AAClF,OAAO,EACL,sBAAsB,EACtB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,UAAU,GAChB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AACrE,OAAO,EACL,KAAK,kCAAkC,EACvC,2BAA2B,EAC3B,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,wBAAwB,GACzB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,KAAK,iBAAiB,EACtB,sBAAsB,EACtB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,aAAa,EACb,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,qBAAqB,EACrB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,KAAK,eAAe,GACrB,MAAM,iCAAiC,CAAA;AACxC,OAAO,EACL,KAAK,4BAA4B,EACjC,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,KAAK,aAAa,EAClB,iBAAiB,EACjB,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,OAAO,EACZ,KAAK,aAAa,GACnB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAA;AAClF,OAAO,EACL,sBAAsB,EACtB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,UAAU,GAChB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AACrE,OAAO,EACL,KAAK,kCAAkC,EACvC,2BAA2B,EAC3B,KAAK,eAAe,EACpB,qBAAqB,EACrB,KAAK,mBAAmB,EACxB,iBAAiB,EACjB,KAAK,qBAAqB,EAC1B,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,wBAAwB,GACzB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,KAAK,iBAAiB,EACtB,sBAAsB,EACtB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,aAAa,EACb,KAAK,gBAAgB,GACtB,MAAM,gBAAgB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,6 @@ export { COMPLETION_POLICY, DEFAULT_POLICY, LIVE_STATE_POLICY, POLL_ONLY_POLICY,
|
|
|
6
6
|
export { createPollGate } from "./pollGate.js";
|
|
7
7
|
export { defaultCompareVersions, Reconciler, } from "./reconciler.js";
|
|
8
8
|
export { backoffDelay, ResettableTimer, sleep } from "./scheduler.js";
|
|
9
|
-
export { createResilientSubscription, SubscriptionStoppedError, } from "./subscription.js";
|
|
9
|
+
export { createResilientSubscription, FallbackDegradedError, FallbackHttpError, SubscriptionStoppedError, } from "./subscription.js";
|
|
10
10
|
export { isParsedStreamResponse, TestTransport, } from "./transport.js";
|
|
11
11
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,oDAAoD;AACpD,OAAO,EACL,qBAAqB,EAIrB,cAAc,EACd,gBAAgB,EAChB,cAAc,GAEf,MAAM,iCAAiC,CAAA;AACxC,OAAO,EAEL,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EAGvB,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EAEL,iBAAiB,EACjB,cAAc,EAUd,iBAAiB,EACjB,gBAAgB,GAKjB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,cAAc,EAAsC,MAAM,eAAe,CAAA;AAClF,OAAO,EACL,sBAAsB,EAItB,UAAU,GAGX,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AACrE,OAAO,EAEL,2BAA2B,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,oDAAoD;AACpD,OAAO,EACL,qBAAqB,EAIrB,cAAc,EACd,gBAAgB,EAChB,cAAc,GAEf,MAAM,iCAAiC,CAAA;AACxC,OAAO,EAEL,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EAGvB,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,cAAc,CAAA;AACrB,OAAO,EAEL,iBAAiB,EACjB,cAAc,EAUd,iBAAiB,EACjB,gBAAgB,GAKjB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,cAAc,EAAsC,MAAM,eAAe,CAAA;AAClF,OAAO,EACL,sBAAsB,EAItB,UAAU,GAGX,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AACrE,OAAO,EAEL,2BAA2B,EAE3B,qBAAqB,EAErB,iBAAiB,EAKjB,wBAAwB,GACzB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAEL,sBAAsB,EAQtB,aAAa,GAEd,MAAM,gBAAgB,CAAA"}
|