@ironflow/browser 0.26.0 → 0.28.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 +179 -13
- package/dist/client.d.ts +94 -6
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +191 -122
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/offline.d.ts +166 -0
- package/dist/offline.d.ts.map +1 -0
- package/dist/offline.js +306 -0
- package/dist/offline.js.map +1 -0
- package/dist/queue/db.d.ts +123 -0
- package/dist/queue/db.d.ts.map +1 -0
- package/dist/queue/db.js +304 -0
- package/dist/queue/db.js.map +1 -0
- package/dist/queue/ids.d.ts +22 -0
- package/dist/queue/ids.d.ts.map +1 -0
- package/dist/queue/ids.js +45 -0
- package/dist/queue/ids.js.map +1 -0
- package/dist/queue/lock.d.ts +42 -0
- package/dist/queue/lock.d.ts.map +1 -0
- package/dist/queue/lock.js +65 -0
- package/dist/queue/lock.js.map +1 -0
- package/dist/queue/queue.d.ts +281 -0
- package/dist/queue/queue.d.ts.map +1 -0
- package/dist/queue/queue.js +894 -0
- package/dist/queue/queue.js.map +1 -0
- package/dist/queue/types.d.ts +145 -0
- package/dist/queue/types.d.ts.map +1 -0
- package/dist/queue/types.js +6 -0
- package/dist/queue/types.js.map +1 -0
- package/package.json +5 -3
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { type QueuedWrite, type QueuedWriteKind, type QueueStats, type WriteLostReason, type WriteStatus } from "./types.js";
|
|
2
|
+
/** What the drainer gets back from a successful send. */
|
|
3
|
+
export interface SendOutcome {
|
|
4
|
+
eventId?: string;
|
|
5
|
+
entityVersion?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface OfflineQueueOptions {
|
|
8
|
+
/** IndexedDB database name; scoped by the caller to serverUrl + environment. */
|
|
9
|
+
dbName: string;
|
|
10
|
+
/**
|
|
11
|
+
* Stable, app-supplied identity for the current principal.
|
|
12
|
+
*
|
|
13
|
+
* Not a hash of the credential: hashing identifies the credential, so
|
|
14
|
+
* rotating a token would make the same user look like a different one.
|
|
15
|
+
*/
|
|
16
|
+
identity: string;
|
|
17
|
+
/** Sends one write to `path`. Injected so the queue never imports the client. */
|
|
18
|
+
send: (path: string, write: QueuedWrite) => Promise<SendOutcome>;
|
|
19
|
+
/** Endpoint for a write kind, or null if this SDK has none. */
|
|
20
|
+
resolvePath: (kind: QueuedWriteKind) => string | null;
|
|
21
|
+
/** The destination the client points at RIGHT NOW, read at send time. */
|
|
22
|
+
currentDestination: () => {
|
|
23
|
+
serverUrl: string;
|
|
24
|
+
environment: string;
|
|
25
|
+
};
|
|
26
|
+
maxItems?: number;
|
|
27
|
+
maxBytes?: number;
|
|
28
|
+
maxRetentionMs?: number;
|
|
29
|
+
maxDeadLettered?: number;
|
|
30
|
+
backoffInitialMs?: number;
|
|
31
|
+
backoffMaxMs?: number;
|
|
32
|
+
stopGraceMs?: number;
|
|
33
|
+
/** How long `onAuthRequired` may take before the attempt is abandoned. */
|
|
34
|
+
authTimeoutMs?: number;
|
|
35
|
+
/** Called once per write that will never be sent. */
|
|
36
|
+
onWriteLost?: (write: QueuedWrite, reason: WriteLostReason, message: string) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Called when the server rejects a write with 401.
|
|
39
|
+
*
|
|
40
|
+
* The queue pauses (it does not dead-letter) and resumes once this resolves.
|
|
41
|
+
* 403 is deliberately NOT routed here: this codebase uses 403 for
|
|
42
|
+
* insufficient permissions, which no amount of re-authentication fixes, so
|
|
43
|
+
* pausing on it would wait forever.
|
|
44
|
+
*/
|
|
45
|
+
onAuthRequired?: () => Promise<{
|
|
46
|
+
identity?: string;
|
|
47
|
+
} | void>;
|
|
48
|
+
/** Injectable clock, for retention tests. */
|
|
49
|
+
now?: () => number;
|
|
50
|
+
/**
|
|
51
|
+
* Injectable timer, so tests need not wait out real backoff.
|
|
52
|
+
* May return a cancel function; flush() and stop() use it to drop a pending
|
|
53
|
+
* retry instead of leaving an orphan timer running.
|
|
54
|
+
*/
|
|
55
|
+
schedule?: (fn: () => void, ms: number) => (() => void) | void;
|
|
56
|
+
}
|
|
57
|
+
/** How the drainer should react to a failed send. */
|
|
58
|
+
type Disposition = "retry" | "auth" | "poison";
|
|
59
|
+
/**
|
|
60
|
+
* Classify a send failure.
|
|
61
|
+
*
|
|
62
|
+
* Reuses `IronflowError.retryable`, which the shared `send()` already sets from
|
|
63
|
+
* the HTTP status, rather than growing a second rule that drifts from the first.
|
|
64
|
+
*/
|
|
65
|
+
export declare function classifyFailure(error: unknown): Disposition;
|
|
66
|
+
export declare class OfflineQueue {
|
|
67
|
+
private db;
|
|
68
|
+
private opts;
|
|
69
|
+
private state;
|
|
70
|
+
private pending;
|
|
71
|
+
private bytes;
|
|
72
|
+
private deadLettered;
|
|
73
|
+
private inFlight;
|
|
74
|
+
private sessionTotal;
|
|
75
|
+
private attempt;
|
|
76
|
+
private draining;
|
|
77
|
+
private stopped;
|
|
78
|
+
/** A backoff retry is already armed; don't stack a second timer on top. */
|
|
79
|
+
private retryArmed;
|
|
80
|
+
/** Cancels the armed retry. Without it, flush() would orphan the timer. */
|
|
81
|
+
private cancelRetry;
|
|
82
|
+
/** A counter refresh is already queued; collapse a burst into one re-read. */
|
|
83
|
+
private refreshQueued;
|
|
84
|
+
/** Counter mutations straddling an await right now. See {@link mutate}. */
|
|
85
|
+
private counterMutations;
|
|
86
|
+
/** Bumped by every completed counter mutation, so a racing read can tell. */
|
|
87
|
+
private counterEpoch;
|
|
88
|
+
/** Consecutive refreshes discarded for racing a local mutation. */
|
|
89
|
+
private refreshRetries;
|
|
90
|
+
/**
|
|
91
|
+
* A drain was requested while one was already running.
|
|
92
|
+
*
|
|
93
|
+
* Without this, a write enqueued in the window between the drainer reading an
|
|
94
|
+
* empty head and returning idle is stranded: its `drain()` call is dropped as
|
|
95
|
+
* a duplicate, and the idle path arms no timer to come back. Nothing would
|
|
96
|
+
* send it until the next enqueue, an explicit flush, or a page reload.
|
|
97
|
+
*/
|
|
98
|
+
private drainRequested;
|
|
99
|
+
/** Cross-tab counter sync; null when BroadcastChannel is unavailable. */
|
|
100
|
+
private channel;
|
|
101
|
+
private readonly statsSubs;
|
|
102
|
+
private readonly watchers;
|
|
103
|
+
constructor(options: OfflineQueueOptions);
|
|
104
|
+
/** Open the database and hydrate the in-memory counters. */
|
|
105
|
+
start(): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Keep sibling tabs' counters honest.
|
|
108
|
+
*
|
|
109
|
+
* The flush lock stops two tabs draining at once, but it does nothing for
|
|
110
|
+
* their *counters*: an in-memory `pending` in tab A cannot see tab B enqueue
|
|
111
|
+
* or drain, so B's badge silently goes stale. A `BroadcastChannel` ping tells
|
|
112
|
+
* the others to re-read, which keeps the cheap in-memory counters without
|
|
113
|
+
* making them per-tab fiction.
|
|
114
|
+
*/
|
|
115
|
+
private openChannel;
|
|
116
|
+
/**
|
|
117
|
+
* Ask for a counter re-read, coalescing a burst into a single pass.
|
|
118
|
+
*
|
|
119
|
+
* Also the retry path for a read discarded by {@link counterRaced} — nothing
|
|
120
|
+
* else re-runs a refresh, so dropping one silently lets this tab under-count
|
|
121
|
+
* a sibling's writes for good and over-admit against its own cap.
|
|
122
|
+
*/
|
|
123
|
+
private requestRefresh;
|
|
124
|
+
/**
|
|
125
|
+
* Re-resolve every live watcher against storage.
|
|
126
|
+
*
|
|
127
|
+
* `notifyWatcher` runs on the drain path, so it only ever fires in the tab
|
|
128
|
+
* that did the draining. Without this, a write enqueued in tab A and
|
|
129
|
+
* delivered by tab B leaves A's watcher on its provisional "pending" forever
|
|
130
|
+
* and leaks its entry for the life of the page — and multi-tab is exactly
|
|
131
|
+
* what the channel was added for.
|
|
132
|
+
*
|
|
133
|
+
* Inherits `resolveStatus`'s v1 limit: a localId in neither store reads as
|
|
134
|
+
* "sent", which is wrong for an evicted dead letter or an origin Safari
|
|
135
|
+
* cleared. Documented under Limits in the browser SDK reference.
|
|
136
|
+
*
|
|
137
|
+
* ponytail: two indexed reads per live watcher per refresh. Fine for a UI
|
|
138
|
+
* watching a handful of rows; if an app ever watches hundreds while a
|
|
139
|
+
* sibling drains a backlog, carry the drained localIds in the broadcast
|
|
140
|
+
* message instead of re-reading storage.
|
|
141
|
+
*/
|
|
142
|
+
private reconcileWatchers;
|
|
143
|
+
/** Announce that this tab changed the stored state. */
|
|
144
|
+
private announce;
|
|
145
|
+
private refreshCounters;
|
|
146
|
+
/** Snapshot taken before a store read whose result will overwrite a counter. */
|
|
147
|
+
private counterMark;
|
|
148
|
+
/**
|
|
149
|
+
* Whether a counter mutation overlapped the read this mark was taken for —
|
|
150
|
+
* in flight at either end, or begun and finished in between.
|
|
151
|
+
*/
|
|
152
|
+
private counterRaced;
|
|
153
|
+
/**
|
|
154
|
+
* Mark a section whose store mutation and in-memory counter update straddle
|
|
155
|
+
* an await, so a concurrent {@link refreshCounters} knows to discard its read.
|
|
156
|
+
*/
|
|
157
|
+
private mutate;
|
|
158
|
+
/**
|
|
159
|
+
* Stop draining and close the database. Safe to call mid-flight.
|
|
160
|
+
*
|
|
161
|
+
* Gives an in-flight send a bounded grace period to finish, rather than
|
|
162
|
+
* abandoning a write whose fate would then be unknown. Bounded because a send
|
|
163
|
+
* can be stuck behind the client's own request timeout, and a `close()` that
|
|
164
|
+
* blocks for 30s is its own bug — after the grace period the database closes
|
|
165
|
+
* and the drain loop's next store call fails harmlessly.
|
|
166
|
+
*/
|
|
167
|
+
stop(stopGraceMs?: number): Promise<void>;
|
|
168
|
+
/**
|
|
169
|
+
* Persist a write and return its handles.
|
|
170
|
+
*
|
|
171
|
+
* Serialisation happens before the IndexedDB transaction: structured clone
|
|
172
|
+
* accepts values `JSON.stringify` later rejects (cycles, `BigInt`), and
|
|
173
|
+
* reporting "saved" for a write that can never be transmitted is worse than
|
|
174
|
+
* failing now. It also gives an exact byte size for the cap.
|
|
175
|
+
*
|
|
176
|
+
* @throws {QueueFullError} at the item cap, byte cap, or storage quota.
|
|
177
|
+
*/
|
|
178
|
+
enqueue(input: {
|
|
179
|
+
kind: QueuedWriteKind;
|
|
180
|
+
body: unknown;
|
|
181
|
+
idempotencyKey?: string;
|
|
182
|
+
}): Promise<{
|
|
183
|
+
localId: string;
|
|
184
|
+
idempotencyKey: string;
|
|
185
|
+
}>;
|
|
186
|
+
/**
|
|
187
|
+
* Ask the drainer to run. Idempotent; concurrent calls collapse into one.
|
|
188
|
+
*
|
|
189
|
+
* The loop exists so a pause for re-authentication can resume *without*
|
|
190
|
+
* holding the flush lock: `drainSession` returns, the lock is released,
|
|
191
|
+
* credentials are refreshed, and only then do we go round again. Recursing
|
|
192
|
+
* from inside the session would keep the lock across a login prompt, which is
|
|
193
|
+
* exactly what other tabs must not be stuck behind.
|
|
194
|
+
*/
|
|
195
|
+
drain(): Promise<void>;
|
|
196
|
+
/** Explicit flush, for a "Retry now" button or a test. */
|
|
197
|
+
flush(): Promise<void>;
|
|
198
|
+
/**
|
|
199
|
+
* Drain until the queue empties or something stops us.
|
|
200
|
+
*
|
|
201
|
+
* Returning is how the flush lock is released: a pause for re-authentication
|
|
202
|
+
* exits this function rather than awaiting inside it, so other tabs are not
|
|
203
|
+
* blocked behind a login prompt the user may never answer.
|
|
204
|
+
*/
|
|
205
|
+
private drainSession;
|
|
206
|
+
/** Move a write to the dead-letter store and tell everyone who cares. */
|
|
207
|
+
private retire;
|
|
208
|
+
/**
|
|
209
|
+
* Obtain fresh credentials.
|
|
210
|
+
*
|
|
211
|
+
* If the caller reports a DIFFERENT principal — the natural outcome when
|
|
212
|
+
* `onAuthRequired` shows a login prompt on a shared machine and someone else
|
|
213
|
+
* signs in — the queue rebinds to that identity. The pending records then fail
|
|
214
|
+
* the identity check and are quarantined instead of being transmitted under
|
|
215
|
+
* the new user's credentials.
|
|
216
|
+
*
|
|
217
|
+
* Bounded by `authTimeoutMs`. `drain()` awaits this while `draining` is true,
|
|
218
|
+
* so a callback that never settles never reaches the `finally` that clears
|
|
219
|
+
* the flag — and every later `drain()` and `flush()` then short-circuits on
|
|
220
|
+
* it. Delivery would stop for the life of the page with no in-app recovery,
|
|
221
|
+
* while `pending` climbed to `maxItems` and started throwing `QueueFullError`
|
|
222
|
+
* at the app. A dropped promise is the normal shape of a dismissed login
|
|
223
|
+
* modal, so this is an ordinary path, not a defensive one.
|
|
224
|
+
*
|
|
225
|
+
* Timing out returns false, which is the existing "no credentials obtained"
|
|
226
|
+
* branch: the caller backs off and tries again. Nothing is dead-lettered — a
|
|
227
|
+
* later login still delivers these writes.
|
|
228
|
+
*
|
|
229
|
+
* @returns whether fresh credentials were obtained.
|
|
230
|
+
*/
|
|
231
|
+
private reauthenticate;
|
|
232
|
+
/**
|
|
233
|
+
* Exponential backoff with full jitter.
|
|
234
|
+
*
|
|
235
|
+
* Jitter matters more than usual here: every tab that came back online at the
|
|
236
|
+
* same moment would otherwise retry in lockstep and manufacture the 429 the
|
|
237
|
+
* queue is trying to survive.
|
|
238
|
+
*/
|
|
239
|
+
private scheduleRetry;
|
|
240
|
+
/** Drop a pending retry so a new one does not run alongside it. */
|
|
241
|
+
private clearRetry;
|
|
242
|
+
/** Every write that will never be sent, oldest first. */
|
|
243
|
+
deadLetter(): Promise<import("./types.js").DeadLetteredWrite[]>;
|
|
244
|
+
/** Forget a dead-lettered write. Returns false if it was already gone. */
|
|
245
|
+
discard(localId: string): Promise<boolean>;
|
|
246
|
+
/**
|
|
247
|
+
* Put a dead-lettered write back on the queue.
|
|
248
|
+
*
|
|
249
|
+
* It goes to the BACK, with a fresh `seq` — re-inserting at its original
|
|
250
|
+
* position would mean rewriting keys, and everything that was behind it has
|
|
251
|
+
* already been delivered. The idempotency key is preserved so a replay of a
|
|
252
|
+
* write that did land is deduplicated by the engine.
|
|
253
|
+
*/
|
|
254
|
+
retry(localId: string): Promise<boolean>;
|
|
255
|
+
stats(): QueueStats;
|
|
256
|
+
/** Subscribe to queue-wide stats. Returns an unsubscribe function. */
|
|
257
|
+
subscribe(cb: (stats: QueueStats) => void): () => void;
|
|
258
|
+
/**
|
|
259
|
+
* Watch one write by its `localId`.
|
|
260
|
+
*
|
|
261
|
+
* The `pending: true` on an enqueue result is a one-shot value; without this
|
|
262
|
+
* there is no way to learn that a specific row landed. Firestore's
|
|
263
|
+
* `hasPendingWrites` is a live flag, and copying the shape without the
|
|
264
|
+
* liveness would have been a dead end.
|
|
265
|
+
*/
|
|
266
|
+
watch(localId: string, cb: (status: WriteStatus) => void): () => void;
|
|
267
|
+
/**
|
|
268
|
+
* Current status of one write, derived from what is actually stored.
|
|
269
|
+
*
|
|
270
|
+
* One transaction over both stores, not two reads: `deadLetter()` moves a
|
|
271
|
+
* record between them atomically, so separate reads can miss it in both and
|
|
272
|
+
* report a LOST write as delivered — the worst answer this surface can give.
|
|
273
|
+
*/
|
|
274
|
+
private resolveStatus;
|
|
275
|
+
private notifyWatcher;
|
|
276
|
+
private setState;
|
|
277
|
+
private emitStats;
|
|
278
|
+
private requireDb;
|
|
279
|
+
}
|
|
280
|
+
export {};
|
|
281
|
+
//# sourceMappingURL=queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/queue/queue.ts"],"names":[],"mappings":"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"}
|