@loro-dev/streams-crdt 0.8.2 → 0.8.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.
@@ -168,50 +168,154 @@ type Result<T, E> = {
168
168
  */
169
169
  type TransportRoomStatus = "joined" | "reconnecting" | "disconnected" | "error";
170
170
  /**
171
- * Discriminated error union for `createStream()`, `deleteStream()`, `sync()`, and `join()`.
171
+ * Discriminated error union for `createStream()`, `deleteStream()`, `sync()`,
172
+ * `join()`, and `appendWriteOnly()`.
172
173
  *
173
- * - `stream_not_found` — the target stream does not exist (404).
174
- * - `auth_failed` — the auth token was rejected (401/403).
175
- * - `protocol_error` — unexpected server response or framing error.
176
- * - `network_error` — fetch-level failure (DNS, connection refused, etc.).
177
- * - `timeout` — connect or poll deadline exceeded.
178
- * - `gone` — the server indicated the stream was deleted or moved (410).
174
+ * Every variant has a `code` discriminator and a `retryable: boolean`. Variants
175
+ * that originate from an HTTP response also carry `status`, `message`, and
176
+ * (when the server sent one) the raw response `body` so applications can
177
+ * surface backend diagnostics directly to end users.
178
+ *
179
+ * Codes:
180
+ * - `stream_not_found` — 404; the target stream does not exist. Create it first.
181
+ * - `auth_failed` — 401/403 from the server; refresh the token and retry.
182
+ * - `auth_provider_error` — the user-supplied auth callback threw. Treated
183
+ * as transient (retryable) so a hiccupping auth backend doesn't terminate
184
+ * live mode. For permanent missing-credential cases, return `undefined`
185
+ * from your auth callback instead of throwing.
186
+ * - `protocol_error` — 400/405/409 or malformed response; treat as a bug.
187
+ * - `network_error` — fetch-level failure (DNS, connection refused). Retry.
188
+ * - `timeout` — connect or poll deadline exceeded. Retry.
189
+ * - `gone` — 410; persisted cursor is no longer valid. Bootstrap from scratch.
179
190
  * - `apply_incomplete` — a CRDT adapter could not fully apply remote data.
180
- * - `internal_error` — adapter or runtime logic failed locally.
181
- * - `unknown` — catch-all for unexpected errors.
191
+ * - `server_error` — 5xx; transient backend failure, retry with backoff.
192
+ * - `internal_error` — local adapter/runtime failure (not from the network).
193
+ * - `unknown` — uncategorized error.
194
+ * - `payload_protection_error` — payload encryption/decryption failed.
195
+ *
196
+ * In live mode, `join()`'s read/write loops automatically retry every
197
+ * `retryable: true` error using the configured backoff. Operation-level methods
198
+ * (`sync()`, `createStream()`, `appendWriteOnly()`) return after a single
199
+ * attempt — applications decide whether to retry based on the `retryable`
200
+ * flag.
201
+ */
202
+ type TransportError =
203
+ /**
204
+ * The target stream does not exist on the server. Use
205
+ * `transport.createStream()` to create it (or pass `createIfMissing: true`
206
+ * to `sync()`).
182
207
  */
183
- type TransportError = {
208
+ {
184
209
  readonly code: "stream_not_found";
185
210
  readonly retryable: false;
186
- } | {
211
+ readonly status: 404;
212
+ readonly message: string; /** Raw HTTP response body, when readable. */
213
+ readonly body?: string;
214
+ }
215
+ /**
216
+ * The auth token was rejected by the server. Refresh credentials and call
217
+ * the operation again — `retryable` is false because retrying with the same
218
+ * token will keep failing.
219
+ */
220
+ | {
187
221
  readonly code: "auth_failed";
188
222
  readonly retryable: false;
189
223
  readonly status?: 401 | 403;
190
224
  readonly message: string;
191
- } | {
225
+ readonly body?: string;
226
+ }
227
+ /**
228
+ * The user-supplied auth callback threw. Treated as transient because the
229
+ * callback typically fetches a token from a backend that may flake. The
230
+ * live read/write loops retry these automatically. `cause` is the original
231
+ * thrown value — surface its message to logs but treat the failure as
232
+ * retryable from the runtime's point of view.
233
+ *
234
+ * For "user is permanently logged out" cases, return `undefined` from the
235
+ * auth callback instead of throwing — that lets the request go out with
236
+ * no `Authorization` header and the server returns a real 401
237
+ * (`auth_failed`, retryable: false).
238
+ */
239
+ | {
240
+ readonly code: "auth_provider_error";
241
+ readonly retryable: true;
242
+ readonly message: string;
243
+ readonly cause?: unknown;
244
+ }
245
+ /**
246
+ * The server rejected the request (400/405/409) or sent a malformed
247
+ * response. Indicates a client/server contract bug; do not retry blindly.
248
+ */
249
+ | {
192
250
  readonly code: "protocol_error";
193
251
  readonly retryable: false;
194
252
  readonly status?: number;
195
253
  readonly message: string;
196
- } | {
254
+ readonly body?: string;
255
+ }
256
+ /**
257
+ * A `fetch` failure (DNS, connection refused, TLS error, etc.). Safe to
258
+ * retry after a short delay.
259
+ */
260
+ | {
197
261
  readonly code: "network_error";
198
262
  readonly retryable: true;
199
263
  readonly message: string;
200
- } | {
264
+ }
265
+ /**
266
+ * A connect or poll deadline was exceeded. `phase` indicates which one.
267
+ * Safe to retry.
268
+ */
269
+ | {
201
270
  readonly code: "timeout";
202
271
  readonly retryable: true;
203
272
  readonly phase: "connect" | "poll";
204
273
  readonly message: string;
205
- } | {
274
+ }
275
+ /**
276
+ * The server indicated the persisted cursor is no longer valid (410). The
277
+ * runtime will bootstrap from scratch on the next `join()`/`sync()` —
278
+ * surface this to the user only if you maintain your own retry loop.
279
+ */
280
+ | {
206
281
  readonly code: "gone";
207
282
  readonly retryable: true;
283
+ readonly status: 410;
208
284
  readonly message: string;
209
- } | {
285
+ readonly body?: string;
286
+ }
287
+ /**
288
+ * The CRDT adapter could not fully apply remote updates due to missing
289
+ * dependencies. The runtime keeps the partial state and will catch up once
290
+ * the missing updates arrive.
291
+ */
292
+ | {
210
293
  readonly code: "apply_incomplete";
211
294
  readonly retryable: true;
212
295
  readonly reason: "loro_pending_updates";
213
296
  readonly message: string;
214
- } | {
297
+ }
298
+ /**
299
+ * A 5xx response from the backend. Likely transient — the live read/write
300
+ * loops retry automatically with exponential backoff (default cap 30s, with
301
+ * jitter). When the server provides a `Retry-After` header, the runtime
302
+ * honors it. `requestId` (when present) is suitable for surfacing to end
303
+ * users for support tickets.
304
+ */
305
+ | {
306
+ readonly code: "server_error";
307
+ readonly retryable: true;
308
+ readonly status: number;
309
+ readonly message: string; /** Raw HTTP response body, when readable. */
310
+ readonly body?: string; /** Request id extracted from headers like `x-request-id`, `cf-ray`, etc. */
311
+ readonly requestId?: string; /** Server-suggested backoff in milliseconds, parsed from `Retry-After`. */
312
+ readonly retryAfterMs?: number;
313
+ }
314
+ /**
315
+ * The CRDT adapter or local runtime threw an unexpected error (not a
316
+ * network failure). Indicates a bug; not retried automatically.
317
+ */
318
+ | {
215
319
  readonly code: "internal_error";
216
320
  readonly retryable: false;
217
321
  readonly message: string;
@@ -874,4 +978,4 @@ declare function createStreamUrl(input: {
874
978
  }): string;
875
979
  //#endregion
876
980
  export { IndexedDbRemoteCursorStoreOptions as $, PayloadProtectionReadPolicy as A, TransportCreateStreamSuccess as B, IsolatedCrdtAdapter as C, PayloadProtectionKey as D, PayloadProtectionEncryptionOptions as E, SnapshotTransformHook as F, TransportSnapshotUploadSuccess as G, TransportError as H, SnapshotUploadOptions as I, WriteOnlyAppendResult as J, TransportSubscription as K, StreamsAuthContext as L, PayloadProtectionWritePolicy as M, Result as N, PayloadProtectionKeyProvider as O, SnapshotCodec as P, IndexedDbRemoteCursorStore as Q, StreamsAuthProvider as R, EphemeralStreamSubscription as S, JsonValue as T, TransportJoinParams as U, TransportDeleteStreamSuccess as V, TransportRoomStatus as W, BeforeRemoteCursorSaveHook as X, BeforeRemoteCursorSaveContext as Y, InMemoryRemoteCursorStore as Z, E2eeScope as _, EphemeralStreamCrdt as a, EphemeralStreamCrdtOptions as b, CrdtApplyOutcome as c, CrdtUpdateBatch as d, RemoteCursor as et, E2eeEncryptionOptions as f, E2eeReadPolicy as g, E2eeOptions as h, PayloadProtectionError as i, PayloadProtectionScope as j, PayloadProtectionOptions as k, CrdtApplyReturn as l, E2eeKeyProvider as m, isValidBucketId as n, RemoteCursorStore as nt, StreamsCrdt as o, E2eeKey as p, TransportSyncSuccess as q, isValidRillId as r, createInitialRemoteCursor as rt, CrdtAdapter as s, createStreamUrl as t, RemoteCursorSaveSource as tt, CrdtUnresolvedSpan as u, E2eeWritePolicy as v, JsonObject as w, EphemeralStreamJoinParams as x, EphemeralStreamAdaptor as y, StreamsCrdtOptions as z };
877
- //# sourceMappingURL=stream-id-Bi5rAZfP.d.ts.map
981
+ //# sourceMappingURL=stream-id-JuJ1JqCX.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@loro-dev/streams-crdt",
3
3
  "description": "Transport/runtime layer for synchronizing CRDT state over Durable Streams.",
4
- "version": "0.8.2",
4
+ "version": "0.8.4",
5
5
  "license": "MIT",
6
6
  "author": "Loro Team",
7
7
  "homepage": "https://streams.loro.dev",
@@ -50,10 +50,10 @@
50
50
  }
51
51
  },
52
52
  "dependencies": {
53
- "@loro-dev/streams-client": "0.5.0"
53
+ "@loro-dev/streams-client": "0.5.1"
54
54
  },
55
55
  "peerDependencies": {
56
- "@loro-dev/flock-wasm": "^0.2.0",
56
+ "@loro-dev/flock-wasm": "^0.3.0",
57
57
  "loro-crdt": "^1.10.3"
58
58
  },
59
59
  "peerDependenciesMeta": {
@@ -66,7 +66,7 @@
66
66
  },
67
67
  "devDependencies": {
68
68
  "@bokuweb/zstd-wasm": "^0.0.27",
69
- "@loro-dev/flock-wasm": "^0.2.0",
69
+ "@loro-dev/flock-wasm": "^0.3.0",
70
70
  "fake-indexeddb": "^6.2.5",
71
71
  "loro-crdt": "^1.10.3",
72
72
  "tsdown": "^0.21.4",