@relyio/sdk 0.5.0 → 0.6.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.
Files changed (31) hide show
  1. package/CHANGELOG.md +170 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/{chunk-5AZUUV5B.js → chunk-7ABNXVWL.js} +398 -184
  4. package/dist/{chunk-HAQELDZN.cjs → chunk-DY2XT7OF.cjs} +2 -2
  5. package/dist/{chunk-CIRT6TVT.cjs → chunk-GCMQUM6N.cjs} +400 -183
  6. package/dist/{chunk-XY5KFEFY.js → chunk-XJVY2CLY.js} +2 -2
  7. package/dist/client/index.cjs +3 -3
  8. package/dist/client/index.d.cts +4 -4
  9. package/dist/client/index.d.ts +4 -4
  10. package/dist/client/index.js +1 -1
  11. package/dist/define-content-type-CDB3kyeA.d.cts +1173 -0
  12. package/dist/define-content-type-CDB3kyeA.d.ts +1173 -0
  13. package/dist/{define-schema-DzYXk4HL.d.ts → define-schema-1kr2HIzN.d.cts} +25 -347
  14. package/dist/{define-schema-2xbHgtK-.d.cts → define-schema-ChvAzY8H.d.ts} +25 -347
  15. package/dist/{index-BozPz4n1.d.cts → index-Df1VsfJR.d.cts} +233 -74
  16. package/dist/{index-Dzo-upNS.d.ts → index-XqoGUaAY.d.ts} +233 -74
  17. package/dist/{index-C5mRBb6t.d.cts → index-d1Kz1e19.d.cts} +62 -29
  18. package/dist/{index-mXUx2H99.d.ts → index-yPbhZc6q.d.ts} +62 -29
  19. package/dist/index.cjs +161 -68
  20. package/dist/index.d.cts +283 -8
  21. package/dist/index.d.ts +283 -8
  22. package/dist/index.js +90 -3
  23. package/dist/schema/index.cjs +35 -35
  24. package/dist/schema/index.d.cts +11 -7
  25. package/dist/schema/index.d.ts +11 -7
  26. package/dist/schema/index.js +1 -1
  27. package/dist/types/index.d.cts +2 -2
  28. package/dist/types/index.d.ts +2 -2
  29. package/package.json +1 -1
  30. package/dist/define-content-type-CBfnTWSS.d.cts +0 -716
  31. package/dist/define-content-type-CBfnTWSS.d.ts +0 -716
package/dist/index.d.cts CHANGED
@@ -1,13 +1,249 @@
1
- import { C as Change } from './index-BozPz4n1.cjs';
2
- export { A as ActiveSandbox, Z as AdhocAggregateBlock, Y as AdhocFetchBlock, X as AdhocQueryBuilder, W as AdhocQueryClient, a3 as AdhocQueryDefinition, a4 as AdhocQueryOptions, a6 as AdhocQueryResult, $ as AdhocSearchBlock, a0 as AdhocSimilarBlock, _ as AggregateMetric, a7 as AssetClient, ah as AssetEntryResponse, ae as AssetFileBlock, a8 as AssetFileBuilder, af as AssetFileExtracted, a9 as AssetUploadBuilder, ag as AssetUrls, ab as AssetVisibility, v as AutocompleteBuilder, D as AutocompleteResponse, B as AutocompleteSuggestion, L as BatchBuilder, K as BatchClient, M as BatchMethod, N as BatchOperation, Q as BatchOperationResult, O as BatchOptions, V as BatchResponse, U as BatchSummary, i as ChangesExpiredError, k as ChangesExpiredReason, j as ChangesOptions, q as ChildrenOptions, b as ClientSchema, g as ConditionalWriteOptions, al as ConfirmInput, am as ConfirmResult, p as ContentByIdBuilder, l as ContentClient, o as ContentQueryBuilder, ap as CreateAssetOptions, E as ExtendedQueryResult, ad as FileBackend, az as FileErrorCode, ac as FileStatus, aA as FileUploadError, aC as FileValidationConstraints, aB as FileValidationError, a1 as FilterValue, a2 as FullTextConfig, H as HttpClient, ar as MultipartCreateResult, as as MultipartPart, at as MultipartTarget, ai as PopulatedAssetReference, aj as PresignInput, ak as PresignResult, P as Project, a5 as QueryMetadata, R as Register, d as RegisteredSchema, an as ResolveUrlInput, ao as ResolveUrlResult, aw as ResourceConflictError, ax as ResourceExpiredError, av as ResourceNotFoundError, h as RetryableWriteOptions, S as SandboxState, u as SearchBuilder, t as SearchClient, J as SearchFields, I as SearchFilter, x as SearchMode, z as SearchResponse, y as SearchResultItem, e as SendOptions, n as SettingsClient, s as SettingsFetchOptions, w as SimilarBuilder, G as SimilarResponse, F as SimilarResult, m as SingletonClient, r as SingletonFetchOptions, a as TypedClientConfig, T as TypedRelyIOClient, au as UploadProgress, aq as WaitUntilReadyOptions, c as createClient, c as default, f as entityTagOf, aa as isAssetEntry, ay as isResourceNotFound, aD as validateFile } from './index-BozPz4n1.cjs';
1
+ import { C as ChangesExpiredError, a as Change, b as ChangesExpiredReason } from './index-Df1VsfJR.cjs';
2
+ export { A as ActiveSandbox, a1 as AdhocAggregateBlock, a0 as AdhocFetchBlock, $ as AdhocQueryBuilder, _ as AdhocQueryClient, a7 as AdhocQueryDefinition, a8 as AdhocQueryOptions, aa as AdhocQueryResult, a3 as AdhocSearchBlock, a4 as AdhocSimilarBlock, a2 as AggregateMetric, ab as AssetClient, al as AssetEntryResponse, ai as AssetFileBlock, ac as AssetFileBuilder, aj as AssetFileExtracted, ad as AssetUploadBuilder, ak as AssetUrls, af as AssetVisibility, w as AutocompleteBuilder, F as AutocompleteResponse, D as AutocompleteSuggestion, Q as BatchBuilder, O as BatchClient, U as BatchMethod, V as BatchOperation, X as BatchOperationResult, W as BatchOptions, Z as BatchResponse, Y as BatchSummary, k as ChangesHeadOptions, l as ChangesOptions, r as ChildrenOptions, e as ClientSchema, i as ConditionalWriteOptions, ap as ConfirmInput, aq as ConfirmResult, q as ContentByIdBuilder, m as ContentClient, p as ContentQueryBuilder, at as CreateAssetOptions, E as ExtendedQueryResult, ah as FileBackend, aD as FileErrorCode, ag as FileStatus, aE as FileUploadError, aG as FileValidationConstraints, aF as FileValidationError, a5 as FilterValue, a6 as FullTextConfig, H as HttpClient, av as MultipartCreateResult, aw as MultipartPart, ax as MultipartTarget, am as PopulatedAssetReference, an as PresignInput, ao as PresignResult, P as Project, a9 as QueryMetadata, R as Register, f as RegisteredSchema, ar as ResolveUrlInput, as as ResolveUrlResult, aA as ResourceConflictError, aB as ResourceExpiredError, az as ResourceNotFoundError, j as RetryableWriteOptions, S as SandboxState, v as SearchBuilder, u as SearchClient, N as SearchEntry, K as SearchFields, J as SearchFilter, y as SearchMode, B as SearchResponse, z as SearchResultItem, L as SearchSort, M as SearchTypeName, g as SendOptions, o as SettingsClient, t as SettingsFetchOptions, x as SimilarBuilder, I as SimilarResponse, G as SimilarResult, n as SingletonClient, s as SingletonFetchOptions, d as TypedClientConfig, T as TypedRelyIOClient, ay as UploadProgress, au as WaitUntilReadyOptions, c as createClient, c as default, h as entityTagOf, ae as isAssetEntry, aC as isResourceNotFound, aH as validateFile } from './index-Df1VsfJR.cjs';
3
3
  export { fields } from './schema/index.cjs';
4
- import { S as SDKError, B as BaseContent } from './index-C5mRBb6t.cjs';
5
- export { a as ApiMethod, A as ApiPath, t as ApiResponse, b as ApiSuccessBody, x as BaseValidationError, q as CacheConfig, v as CacheStrategy, g as ContentQueryResult, k as ContentTypeSchema, C as CreateInput, j as CustomQuery, D as DebugConfig, E as Environment, l as FieldOptions, F as FieldTypeName, H as InvalidFieldTypeError, I as InvalidPayloadError, L as LogLevel, M as MatchRouteOptions, P as PerformanceMetrics, Q as QueryOptions, r as RealtimeConfig, o as RealtimeEvent, n as RealtimeEventType, R as RelyIOConfig, s as RequestConfig, G as RequiredFieldError, u as RetryConfig, c as RouteMatch, z as SchemaValidationError, i as SettingsGroup, h as SingletonContent, f as SortOptions, p as SubscriptionOptions, U as UpdateInput, y as ValidationError, V as ValidationRule, w as ValidationViolation, d as WhereClause, e as WhereOperator, W as Wire, m as matchRoute } from './index-C5mRBb6t.cjs';
4
+ import { S as SDKError, B as BaseContent } from './index-d1Kz1e19.cjs';
5
+ export { a as ApiMethod, A as ApiPath, v as ApiResponse, b as ApiSuccessBody, z as BaseValidationError, s as CacheConfig, x as CacheStrategy, i as ContentQueryResult, n as ContentTypeSchema, C as CreateInput, l as CustomQuery, D as DebugConfig, E as Environment, o as FieldOptions, F as FieldTypeName, K as InvalidFieldTypeError, I as InvalidPayloadError, L as LogLevel, M as MatchRouteOptions, P as PerformanceMetrics, Q as QueryOptions, t as RealtimeConfig, q as RealtimeEvent, p as RealtimeEventType, R as RelyIOConfig, u as RequestConfig, J as RequiredFieldError, w as RetryConfig, c as RouteMatch, H as SchemaValidationError, k as SettingsGroup, j as SingletonContent, h as SortOptions, r as SubscriptionOptions, U as UpdateInput, G as ValidationError, V as ValidationRule, y as ValidationViolation, f as WhereClause, e as WhereFieldCondition, g as WhereOperator, d as WhereScalar, W as Wire, m as matchRoute } from './index-d1Kz1e19.cjs';
6
6
  export { camelToSnake, createDeferred, debounce, deepClone, generateId, isBrowser, isNode, isPlainObject, isValidEmail, isValidUrl, mergeDeep, omit, pick, retry, sleep, snakeToCamel, throttle, toSafeString } from './utils/index.cjs';
7
- export { ax as AggregateBlock, G as AssetTypeConfig, K as AssetTypeDefinition, C as ComponentConfig, v as ComponentDefinition, w as ComponentMetadata, aw as FetchBlock, O as FileKindConfig, a3 as FileScanConfig, a2 as FileUploadConfig, aH as FilterDefinition, X as ImageExifConfig, N as ImageKindConfig, W as ImageSourceConfig, U as ImageUploadConfig, aF as IncludeDefinition, M as InferAssetType, aR as InferQueryParams, aQ as InferQueryResponse, t as InferSingleton, I as InferSingletonContentType, au as QueryConfig, av as QueryDefinition, h as SchemaAssetTypeNames, S as SchemaConfig, b as SchemaContentTypeNames, a as SchemaDefinition, f as SchemaLocaleCodes, e as SchemaQueryNames, g as SchemaSettingsGroupNames, c as SchemaSingletonNames, ay as SearchBlock, aG as SelectMapping, A as SettingsGroupConfig, B as SettingsGroupDefinition, az as SimilarBlock, r as SingletonContentTypeDefinition, s as SingletonMetadata, aD as SortCondition, Y as VariantDefinition, $ as VideoCaptionsConfig, a0 as VideoDownloadConfig, V as VideoKindConfig, _ as VideoPosterConfig, Z as VideoUploadConfig, a1 as VideoWatermarkConfig, aA as WhereCondition, F as defineAssetType, u as defineComponent, at as defineQuery, d as defineSchema, z as defineSettingsGroup, q as defineSingleton, p as defineSingletonContentType } from './define-schema-2xbHgtK-.cjs';
8
- export { n as BaseFieldConfig, x as ContentTypeConfig, y as ContentTypeConfigWithFields, z as ContentTypeConfigWithFieldsets, G as ContentTypeDefinition, H as EntryMetadata, c as FieldDefinition, b as FieldRule, o as FieldType, F as FieldUIConfig, w as Fieldset, J as InferContentType, K as LocalePublicationFields, L as LocalizationConfig, u as defineContentType, v as fieldset } from './define-content-type-CBfnTWSS.cjs';
7
+ export { a6 as AggregateBlock, C as ComponentConfig, s as ComponentDefinition, t as ComponentMetadata, a5 as FetchBlock, ag as FilterDefinition, ae as IncludeDefinition, aq as InferQueryParams, ap as InferQueryResponse, a3 as QueryConfig, a4 as QueryDefinition, h as SchemaAssetTypeNames, S as SchemaConfig, b as SchemaContentTypeNames, a as SchemaDefinition, i as SchemaEntry, j as SchemaEntryOf, f as SchemaLocaleCodes, e as SchemaQueryNames, g as SchemaSettingsGroupNames, c as SchemaSingletonNames, a7 as SearchBlock, af as SelectMapping, x as SettingsGroupConfig, y as SettingsGroupDefinition, a8 as SimilarBlock, ac as SortCondition, a9 as WhereCondition, r as defineComponent, a2 as defineQuery, d as defineSchema, w as defineSettingsGroup } from './define-schema-1kr2HIzN.cjs';
8
+ export { a2 as AssetTypeConfig, a5 as AssetTypeDefinition, n as BaseFieldConfig, K as ContentTypeConfig, M as ContentTypeConfigWithFields, N as ContentTypeConfigWithFieldsets, O as ContentTypeDefinition, P as EntryMetadata, c as FieldDefinition, b as FieldRule, u as FieldSchemaContext, o as FieldType, F as FieldUIConfig, v as FieldValue, w as FieldValues, J as Fieldset, a9 as FileKindConfig, an as FileScanConfig, am as FileUploadConfig, af as ImageExifConfig, a7 as ImageKindConfig, ae as ImageSourceConfig, ad as ImageUploadConfig, a6 as InferAssetType, Q as InferContentType, a0 as InferSingleton, $ as InferSingletonContentType, W as LocalePublicationFields, L as LocalizationConfig, Z as SingletonContentTypeDefinition, _ as SingletonMetadata, z as UnresolvedComponent, y as UnresolvedEntry, ag as VariantDefinition, aj as VideoCaptionsConfig, ak as VideoDownloadConfig, a8 as VideoKindConfig, ai as VideoPosterConfig, ah as VideoUploadConfig, al as VideoWatermarkConfig, a1 as defineAssetType, G as defineContentType, Y as defineSingleton, X as defineSingletonContentType, H as fieldset } from './define-content-type-CDB3kyeA.cjs';
9
9
  import './dev-handshake/index.cjs';
10
10
 
11
+ /**
12
+ * What a key may do is in its prefix. A RelyIO key is `rly_{scope}_v1_{entropy}_{checksum}`, and a
13
+ * publishable key — the one project key that may sit in a browser (`sdk-surfaces-spec.md` decision
14
+ * 29) — is scope `pub`. Its scope is in its prefix so that no stored flag can disagree with it.
15
+ *
16
+ * The truth is the service's: `isPublishableApiKey` in
17
+ * `packages/data/metadata-db/src/utils/api-key-generator.ts`, which decides whether a presented key is
18
+ * publishable. This package may not import it (`INV-SS-CUSTOMER-FENCE`), so the prefix is restated
19
+ * here, and `src/__tests__/key-kind.test.ts` reads that file and fails when the two part.
20
+ */
21
+ declare const PUBLISHABLE_KEY_PREFIX = "rly_pub_";
22
+ /**
23
+ * Whether `apiKey` is a publishable key (`rly_pub_…`).
24
+ *
25
+ * The one reading of a key's kind a surface asks the core for: `@relyio/react`'s `live` refuses to
26
+ * start in a browser without one, and the edge transport (LV5.2) is chosen by it. It reads the prefix
27
+ * only — whether the key is valid, active or allowed from this origin is the service's to say.
28
+ *
29
+ * `undefined` is a client that holds no key: `createClient({ apiKey: process.env.X! })` with the
30
+ * variable unset constructs, and refuses at its first request (REL-1120). Such a client holds no
31
+ * publishable key, so the answer is `false` rather than a `TypeError` in a caller that only asked.
32
+ */
33
+ declare const isPublishableKey: (apiKey: string | undefined) => boolean;
34
+
35
+ /**
36
+ * `followChanges()` — the one loop that follows a changes source until its
37
+ * signal aborts (`INV-SS-ONE-CORE`, REL-1215).
38
+ *
39
+ * `<RelyIOProvider live>` and the preview toolbar both follow the feed, and the
40
+ * toolbar may not import `@relyio/react` (`INV-SS-LAYER-DIRECTION`), so each
41
+ * carried its own copy of this policy until the core — the one package both may
42
+ * import — owned it. Each surface now says only what a change, a resync and a
43
+ * state mean to it.
44
+ *
45
+ * **The transport is a parameter.** A source opens from a cursor and yields
46
+ * changes. Today that is `relyio.changes()`, the long-poll, with whatever filter
47
+ * the caller binds in. LV5.2 (REL-1158, `live-layer-spec.md` LV5) adds a
48
+ * second — a WebSocket to the live edge, falling back to polling the edge when a
49
+ * socket cannot open — and hands it to this loop, with a classifier for its
50
+ * refusal close codes. That source calls `opened()` on the socket's `open`: a
51
+ * Worker deploy drops every socket, and a quiet dataset delivers no change, so
52
+ * without it each deploy would double the next reconnect's wait up to thirty
53
+ * seconds. With it, every drop after a healthy connection waits the base
54
+ * ceiling. The loop, and every handler a surface passes it, stay as they are.
55
+ *
56
+ * The long-poll does not call `opened()`: `relyio.changes()` takes the public
57
+ * `ChangesOptions`, which does not carry it, so its back-off resets only on a
58
+ * delivered change — as it did before this loop existed.
59
+ */
60
+
61
+ /** The ceiling of the first wait after a failure worth retrying; doubled per consecutive failure. */
62
+ declare const FOLLOW_RETRY_BASE_MS = 1000;
63
+ /** The ceiling never doubles past this. A server's hint is not capped by it. */
64
+ declare const FOLLOW_RETRY_MAX_MS = 30000;
65
+ /** What the loop hands a source each time it opens one. */
66
+ interface ChangeSourceOptions {
67
+ /**
68
+ * The cursor of the last change the loop applied — or the `since` it was
69
+ * started with. Omitted, the source starts from the dataset's current position
70
+ * and replays nothing.
71
+ */
72
+ readonly since?: string;
73
+ /**
74
+ * Ends the source. On an abort the iteration **completes**: no rejection, and
75
+ * no further request or frame.
76
+ */
77
+ readonly signal: AbortSignal;
78
+ /**
79
+ * Call when `since` can no longer be replayed (`INV-SS-CURSOR-REPLAYS`):
80
+ * resync to the dataset's current position, call this with the error, and
81
+ * await it before yielding any change after the new position.
82
+ */
83
+ readonly onExpired: (expired: ChangesExpiredError) => Promise<void>;
84
+ /**
85
+ * Call once the transport is established — a socket's `open`, say. The loop
86
+ * takes it as the source being healthy and resets its back-off, so a
87
+ * connection that is later dropped reconnects after the base wait however
88
+ * often that has happened. Optional to call: a source that never does has its
89
+ * back-off reset only by a delivered change. A call from an open that has
90
+ * already failed changes nothing.
91
+ */
92
+ readonly opened: () => void;
93
+ }
94
+ /**
95
+ * A transport for the changes feed: open from a position and yield each change,
96
+ * in feed order, as ids (`INV-SS-CHANGE-IS-IDS`).
97
+ *
98
+ * A source ends **only** when its signal aborts. Every other end — a dropped
99
+ * connection, a refusal, a socket closed by a deploy — is thrown, so the loop's
100
+ * classifier can decide between reconnecting and stopping. `relyio.changes()` is
101
+ * one as it stands:
102
+ *
103
+ * ```ts
104
+ * const source: ChangeSource = from => relyio.changes({ ...from, types: ['post'] })
105
+ * ```
106
+ */
107
+ type ChangeSource = (options: ChangeSourceOptions) => AsyncIterable<Change>;
108
+ /**
109
+ * Why everything derived from the feed may be stale, so the consumer re-reads
110
+ * what it holds:
111
+ *
112
+ * - `expired` — the cursor could no longer be replayed. The source has resynced
113
+ * to the current position and yields nothing after it until the handler
114
+ * settles.
115
+ * - `no-cursor` — the source failed before any change arrived, so there is no
116
+ * cursor to reopen from and whatever happened meanwhile cannot be replayed. The
117
+ * loop reopens from the current position once the handler settles.
118
+ */
119
+ type FollowResync = {
120
+ readonly cause: 'expired';
121
+ readonly expired: ChangesExpiredError;
122
+ } | {
123
+ readonly cause: 'no-cursor';
124
+ };
125
+ /**
126
+ * What the loop is doing, reported on every transition so a surface can name it
127
+ * rather than keep its own count:
128
+ *
129
+ * - `following` — the source is open (reported on every open, reconnects too);
130
+ * - `resynced` — the consumer's resync handler has settled;
131
+ * - `reconnecting` — `error` was worth retrying; the source reopens after
132
+ * `retryInMs`;
133
+ * - `stopped` — `error` was not; the loop has ended. Reported once.
134
+ *
135
+ * Nothing is reported after the signal aborts.
136
+ */
137
+ type FollowState = {
138
+ readonly kind: 'following';
139
+ } | {
140
+ readonly kind: 'resynced';
141
+ readonly resync: FollowResync;
142
+ } | {
143
+ readonly kind: 'reconnecting';
144
+ readonly error: unknown;
145
+ readonly retryInMs: number;
146
+ } | {
147
+ readonly kind: 'stopped';
148
+ readonly error: unknown;
149
+ };
150
+ /**
151
+ * A classifier's answer for one failure. `afterMs` is the server's hint — HTTP's
152
+ * `Retry-After`, a socket's close code — and a floor under the loop's own
153
+ * back-off: the wait is never shorter than it, and a hint longer than
154
+ * {@link FOLLOW_RETRY_MAX_MS} is waited out in full.
155
+ */
156
+ type FollowVerdict = {
157
+ readonly retry: false;
158
+ } | {
159
+ readonly retry: true;
160
+ readonly afterMs?: number;
161
+ };
162
+ interface FollowOptions {
163
+ /** Where to start: a change's cursor from an earlier follow. Omitted, the current position. */
164
+ readonly since?: string;
165
+ /** Ends the loop, which then resolves; a wait in progress ends at once. */
166
+ readonly signal: AbortSignal;
167
+ /**
168
+ * Apply one change. Awaited before the next change is taken, and before its
169
+ * cursor counts as reached — a change whose handler has not settled is
170
+ * replayed by the next open, never skipped. A throw is a failure like the
171
+ * source's own, and the classifier sees it.
172
+ */
173
+ readonly onChange: (change: Change) => void | Promise<void>;
174
+ /** Re-read everything derived from the feed. Awaited; see {@link FollowResync}. */
175
+ readonly onResync: (resync: FollowResync) => void | Promise<void>;
176
+ /** Observes each transition; see {@link FollowState}. It must not throw. */
177
+ readonly onState?: (state: FollowState) => void;
178
+ /**
179
+ * Whether a failure is worth reopening the source for, and any wait the
180
+ * server asked for. Default {@link classifyFollowFailure}. A transport whose
181
+ * failures the core's errors do not describe supplies its own, and delegates
182
+ * the rest to the default.
183
+ */
184
+ readonly classify?: (error: unknown) => FollowVerdict;
185
+ /**
186
+ * The jitter's source of randomness, `Math.random` by default: a number in
187
+ * `[0, 1)`. `0` waits the whole ceiling; values towards `1` shorten the wait
188
+ * to just over half of it. A test fixes it.
189
+ */
190
+ readonly random?: () => number;
191
+ }
192
+ /**
193
+ * How the loop ended — never a rejection. `since` is the cursor of the last
194
+ * change applied (or the starting `since`), which a caller that stopped the loop
195
+ * to reopen it with a different filter starts the next one from.
196
+ */
197
+ type FollowEnd = {
198
+ readonly kind: 'aborted';
199
+ readonly since: string | undefined;
200
+ } | {
201
+ readonly kind: 'stopped';
202
+ readonly since: string | undefined;
203
+ readonly error: unknown;
204
+ };
205
+ /**
206
+ * The default classifier. A failure is worth retrying when the core calls it
207
+ * retryable — `SDKError.retryable`, **after** the client's own retries, so this
208
+ * is an outage that outlasted them — and the wait it carries is the one the
209
+ * service asked for: `Retry-After`, or a rate limit's `resetAt`. Anything else —
210
+ * a refused key, a malformed request, a defect — stops the loop, because
211
+ * retrying would meet the same refusal forever.
212
+ */
213
+ declare function classifyFollowFailure(error: unknown): FollowVerdict;
214
+ /**
215
+ * Follow `source` until `signal` aborts: apply each change in feed order, one at
216
+ * a time, and carry the cursor.
217
+ *
218
+ * - **Expired cursor.** The source resyncs and awaits `onResync({ cause:
219
+ * 'expired' })` before yielding anything after the new position.
220
+ * - **A failure worth retrying** (`classify`) reopens the source after a
221
+ * jittered, doubling wait — a ceiling of {@link FOLLOW_RETRY_BASE_MS} doubled
222
+ * per consecutive failure up to {@link FOLLOW_RETRY_MAX_MS}, shortened by the
223
+ * jitter to no less than half of it, and never below the server's hint. A
224
+ * delivered change resets the doubling, and so does the source calling
225
+ * `opened()` once its transport is up. The source reopens from the last
226
+ * change's cursor so nothing is skipped; with no change seen yet there is none,
227
+ * so `onResync({ cause: 'no-cursor' })` runs first and the source reopens from
228
+ * the current position.
229
+ * - **Anything else** stops the loop: reported once as `stopped`, and returned.
230
+ *
231
+ * It never rejects. An abort — in the source, in a handler, or during a wait —
232
+ * resolves it at once with no further open, resync or state; a change whose
233
+ * handler is running when the abort lands is finished and its cursor kept.
234
+ *
235
+ * ```ts
236
+ * const controller = new AbortController()
237
+ * const end = await followChanges(from => relyio.changes({ ...from, types: ['post'] }), {
238
+ * signal: controller.signal,
239
+ * onChange: change => refetch(change.contentType, change.entryId),
240
+ * onResync: () => refetchEverything(),
241
+ * })
242
+ * if (end.kind === 'stopped') console.error(end.error)
243
+ * ```
244
+ */
245
+ declare function followChanges(source: ChangeSource, options: FollowOptions): Promise<FollowEnd>;
246
+
11
247
  /**
12
248
  * Network-related errors
13
249
  */
@@ -20,7 +256,11 @@ declare class NetworkError extends SDKError {
20
256
  declare class TimeoutError extends SDKError {
21
257
  readonly code = "TIMEOUT_ERROR";
22
258
  readonly retryable = true;
23
- constructor(message?: string, timeout?: number, statusCode?: number, cause?: Error);
259
+ /**
260
+ * @param context - Carried beside `timeout`. The mapper passes a `REQUEST_TIMEOUT` refusal's body
261
+ * as `context.response`, as it does for every other contract code.
262
+ */
263
+ constructor(message?: string, timeout?: number, statusCode?: number, cause?: Error, context?: Record<string, unknown>);
24
264
  getUserMessage(): string;
25
265
  }
26
266
  declare class ConnectionError extends SDKError {
@@ -561,6 +801,41 @@ declare const RELYIO_CHANGE_EVENT = "relyio:change";
561
801
  * ```
562
802
  */
563
803
  type RelyIOChangeDetail = Change;
804
+ /**
805
+ * The DOM event a preview surface dispatches when **everything** on the page may be stale: the feed
806
+ * lost its place, so the surface re-read what it holds without a change to name (REL-1214). Same
807
+ * target and the same wire-contract rule as {@link RELYIO_CHANGE_EVENT}; `<RelyIORefresh />` listens
808
+ * for both.
809
+ *
810
+ * **A second name, not a second shape of the first.** A `relyio:change` listener reads `detail` as
811
+ * a {@link Change}. A resync dispatched under that name would hand it `undefined` ids at runtime —
812
+ * and a listener built against an earlier release, or written in JavaScript, gets no type error to
813
+ * warn it. Under its own name, a listener that knows only `relyio:change` behaves exactly as before:
814
+ * it does not hear a resync. Nor is a resync one synthetic change per re-read entry: a change carries
815
+ * a `cursor`, and the feed issued none for it.
816
+ *
817
+ * @example
818
+ * ```ts
819
+ * window.addEventListener(RELYIO_RESYNC_EVENT, () => refetchEverything())
820
+ * ```
821
+ */
822
+ declare const RELYIO_RESYNC_EVENT = "relyio:resync";
823
+ /**
824
+ * The `detail` of a {@link RELYIO_RESYNC_EVENT} dispatch: why the feed lost its place, one arm per
825
+ * `FollowResync` cause, as plain data.
826
+ *
827
+ * - `expired` — the cursor could no longer be replayed; `reason` is the feed's own
828
+ * ({@link ChangesExpiredReason}).
829
+ * - `no-cursor` — the feed failed before any change arrived, so it had no cursor to resume from.
830
+ *
831
+ * A listener that only refreshes reads none of it.
832
+ */
833
+ type RelyIOResyncDetail = {
834
+ readonly cause: 'expired';
835
+ readonly reason: ChangesExpiredReason;
836
+ } | {
837
+ readonly cause: 'no-cursor';
838
+ };
564
839
 
565
840
  /**
566
841
  * The width ladder the delivery Worker snaps every rendered dimension to
@@ -620,4 +895,4 @@ declare function snapToLadder(value: number): number;
620
895
 
621
896
  declare const VERSION = "__VERSION__";
622
897
 
623
- export { AuthenticationError, AuthorizationError, BaseContent, Change, ConnectionError, ErrorMapper, IMAGE_LADDER, InvalidApiKeyError, type LanguageSwitcherOption, type LanguageSwitcherOptions, type LocaleMetadata, type LocaleStatus, type LocalizedEntry, MethodNotAllowedError, MissingApiKeyError, NetworkError, PayloadTooLargeError, PlanFeatureUnavailableError, RELYIO_CHANGE_EVENT, RateLimitError, ReadOnlyKeyError, type RelyIOChangeDetail, type RelyIOFieldAttributes, type RelyIOFieldName, SDKError, ServerError, ServiceIndeterminateError, TimeoutError, TransactionRolledBackError, type TranslationCompleteness, UnknownContractError, UsageQuotaExceededError, VERSION, buildLanguageSwitcher, estimateTranslationCompleteness, getAllLocalizedValues, getAvailableLocaleCodes, getDefaultLocale, getFallbackFields, getFieldFallbackLocale, getLocalizedField, getPublishedLocaleCodes, getRequestedLocale, hasLocale, isFieldFallback, isPublishedInLocale, localeHelpers, needsTranslation, relyioField, snapToLadder };
898
+ export { AuthenticationError, AuthorizationError, BaseContent, Change, type ChangeSource, type ChangeSourceOptions, ChangesExpiredError, ChangesExpiredReason, ConnectionError, ErrorMapper, FOLLOW_RETRY_BASE_MS, FOLLOW_RETRY_MAX_MS, type FollowEnd, type FollowOptions, type FollowResync, type FollowState, type FollowVerdict, IMAGE_LADDER, InvalidApiKeyError, type LanguageSwitcherOption, type LanguageSwitcherOptions, type LocaleMetadata, type LocaleStatus, type LocalizedEntry, MethodNotAllowedError, MissingApiKeyError, NetworkError, PUBLISHABLE_KEY_PREFIX, PayloadTooLargeError, PlanFeatureUnavailableError, RELYIO_CHANGE_EVENT, RELYIO_RESYNC_EVENT, RateLimitError, ReadOnlyKeyError, type RelyIOChangeDetail, type RelyIOFieldAttributes, type RelyIOFieldName, type RelyIOResyncDetail, SDKError, ServerError, ServiceIndeterminateError, TimeoutError, TransactionRolledBackError, type TranslationCompleteness, UnknownContractError, UsageQuotaExceededError, VERSION, buildLanguageSwitcher, classifyFollowFailure, estimateTranslationCompleteness, followChanges, getAllLocalizedValues, getAvailableLocaleCodes, getDefaultLocale, getFallbackFields, getFieldFallbackLocale, getLocalizedField, getPublishedLocaleCodes, getRequestedLocale, hasLocale, isFieldFallback, isPublishableKey, isPublishedInLocale, localeHelpers, needsTranslation, relyioField, snapToLadder };