@relyio/sdk 0.6.0 → 0.7.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 (37) hide show
  1. package/CHANGELOG.md +370 -0
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/{chunk-DY2XT7OF.cjs → chunk-72UK5U7T.cjs} +70 -60
  4. package/dist/{chunk-7ABNXVWL.js → chunk-GYHAVYND.js} +777 -399
  5. package/dist/{chunk-I3ESNANB.js → chunk-H6IBQSMM.js} +2 -2
  6. package/dist/{chunk-HT6NFRM2.cjs → chunk-TZL374LS.cjs} +2 -2
  7. package/dist/{chunk-GCMQUM6N.cjs → chunk-VH2DE7HZ.cjs} +776 -402
  8. package/dist/{chunk-XJVY2CLY.js → chunk-YEJUMW4X.js} +70 -60
  9. package/dist/client/index.cjs +4 -3
  10. package/dist/client/index.d.cts +4 -4
  11. package/dist/client/index.d.ts +4 -4
  12. package/dist/client/index.js +2 -1
  13. package/dist/{index-d1Kz1e19.d.cts → define-content-type-DiVpbwNs.d.cts} +1615 -684
  14. package/dist/{index-yPbhZc6q.d.ts → define-content-type-DiVpbwNs.d.ts} +1615 -684
  15. package/dist/{define-schema-1kr2HIzN.d.cts → define-schema-C-5an28C.d.ts} +189 -85
  16. package/dist/{define-schema-ChvAzY8H.d.ts → define-schema-D7MButVt.d.cts} +189 -85
  17. package/dist/{index-XqoGUaAY.d.ts → index-1G97sNA8.d.ts} +489 -267
  18. package/dist/index-BOQIHnsh.d.ts +818 -0
  19. package/dist/index-DbsTUw3Q.d.cts +818 -0
  20. package/dist/{index-Df1VsfJR.d.cts → index-M0X45k7J.d.cts} +489 -267
  21. package/dist/index.cjs +98 -114
  22. package/dist/index.d.cts +31 -31
  23. package/dist/index.d.ts +31 -31
  24. package/dist/index.js +8 -8
  25. package/dist/schema/index.cjs +35 -35
  26. package/dist/schema/index.d.cts +13 -11
  27. package/dist/schema/index.d.ts +13 -11
  28. package/dist/schema/index.js +1 -1
  29. package/dist/types/index.d.cts +2 -2
  30. package/dist/types/index.d.ts +2 -2
  31. package/dist/utils/index.cjs +19 -19
  32. package/dist/utils/index.d.cts +10 -1
  33. package/dist/utils/index.d.ts +10 -1
  34. package/dist/utils/index.js +1 -1
  35. package/package.json +4 -3
  36. package/dist/define-content-type-CDB3kyeA.d.cts +0 -1173
  37. package/dist/define-content-type-CDB3kyeA.d.ts +0 -1173
@@ -1,6 +1,6 @@
1
- import { N as MergedRelyIOConfig, A as ApiPath, a as ApiMethod, O as PathParamsOf, v as ApiResponse, W as Wire, u as RequestConfig, B as BaseContent, f as WhereClause, h as SortOptions, i as ContentQueryResult, Q as QueryOptions, C as CreateInput, U as UpdateInput, S as SDKError, z as BaseValidationError, y as ValidationViolation, T as components, X as paths, R as RelyIOConfig } from './index-yPbhZc6q.js';
2
- import { a as SchemaDefinition, b as SchemaContentTypeNames, j as SchemaEntryOf, h as SchemaAssetTypeNames, c as SchemaSingletonNames, g as SchemaSettingsGroupNames, I as InferSettingsGroup, e as SchemaQueryNames, f as SchemaLocaleCodes } from './define-schema-ChvAzY8H.js';
3
- import { Q as InferContentType, a6 as InferAssetType, a0 as InferSingleton } from './define-content-type-CDB3kyeA.js';
1
+ import { H as MergedRelyIOConfig, A as ApiPath, b as ApiMethod, J as PathParamsOf, v as ApiResponse, W as Wire, u as RequestConfig, B as BaseContent, g as WhereClause, Q as QueryOptions, i as SortOptions, j as ContentQueryResult, C as CreateInput, U as UpdateInput, S as SDKError, z as BaseValidationError, y as ValidationViolation, R as RelyIOConfig, a as RelyIOConfigUpdate } from './index-BOQIHnsh.js';
2
+ import { aK as components, aJ as paths, W as InferContentType, aa as InferAssetType, a3 as InferSingleton } from './define-content-type-DiVpbwNs.js';
3
+ import { a as SchemaDefinition, b as SchemaContentTypeNames, j as SchemaEntryOf, ay as FilterOperator, h as SchemaAssetTypeNames, c as SchemaSingletonNames, g as SchemaSettingsGroupNames, I as InferSettingsGroup, e as SchemaQueryNames, f as SchemaLocaleCodes } from './define-schema-C-5an28C.js';
4
4
  import { DevUnreadableReason } from './dev-handshake/index.js';
5
5
 
6
6
  /**
@@ -99,14 +99,21 @@ type SendOptions<P extends ApiPath, M extends ApiMethod<P>> = {
99
99
  * nothing inside the SDK uses them.
100
100
  */
101
101
  declare class HttpClient {
102
- private baseUrl;
103
- private defaultHeaders;
104
- private timeout;
105
- private retryPolicy;
106
- private debug;
107
- private logger?;
108
- private config;
102
+ /** What every request reads off the configuration, derived by {@link configure} and nowhere else. */
103
+ private connection;
109
104
  constructor(config: MergedRelyIOConfig);
105
+ /**
106
+ * Run on `config` from now on: every later request — whoever holds this client — is sent to its
107
+ * `baseUrl`, with its headers, key and dataset, its timeout and retries, through its `fetch`, and
108
+ * logged by its `debug` options.
109
+ *
110
+ * The client's own `updateConfig()` calls this rather than building a second client, so a
111
+ * `content()` or other sub-client taken before the update sends through the update too. Anything
112
+ * set on this client since it was last configured — `setDefaultHeaders()`, `setBaseUrl()` — is
113
+ * replaced by what `config` says.
114
+ */
115
+ configure(config: MergedRelyIOConfig): void;
116
+ private announce;
110
117
  /**
111
118
  * Call a route the committed document declares, and get back the body that
112
119
  * document says it serves.
@@ -129,13 +136,17 @@ declare class HttpClient {
129
136
  *
130
137
  * The loop always makes one attempt. The incumbent's `while (attempt <
131
138
  * maxAttempts)` made none at `retryAttempts: 0` — a value the config validator
132
- * accepts — and then dereferenced an unassigned `lastError`.
139
+ * then accepted, and now refuses — and then dereferenced an unassigned
140
+ * `lastError`. `retryAttempts` is the most attempts, the first included; an
141
+ * `HttpClient` constructed directly is not validated, so the first attempt
142
+ * stays unconditional.
133
143
  *
134
144
  * A request that would carry no `X-API-Key` makes none: it rejects with
135
145
  * `MissingApiKeyError` before `fetch` is called, is not retried, and names
136
146
  * `apiKey`. This is where a client built without a key learns it — the
137
147
  * constructor accepts one so that a module-scope client can be evaluated by a
138
- * build that holds no key (REL-1120).
148
+ * build that holds no key (REL-1120) — and so does one whose `setApiKey` was
149
+ * given none.
139
150
  */
140
151
  request<T = unknown>(config: RequestConfig): Promise<ApiResponse<T>>;
141
152
  /**
@@ -159,13 +170,28 @@ declare class HttpClient {
159
170
  */
160
171
  patch<T = unknown>(url: string, data?: unknown, params?: Record<string, unknown>): Promise<ApiResponse<T>>;
161
172
  /**
162
- * Set default headers for all requests
173
+ * Add headers to every later request, each replacing any header of the same name — the name
174
+ * matched without regard to case — until the client is next configured.
163
175
  */
164
176
  setDefaultHeaders(headers: Record<string, string>): void;
165
177
  /**
166
- * Set authentication token
178
+ * Replace the key every later request sends as `X-API-Key`, and the `apiKey` the configuration
179
+ * reports.
180
+ *
181
+ * The key is read the way construction reads it (`presentKey`): an absent, empty or blank key is
182
+ * no key, so the header is dropped and the next request is refused with `MissingApiKeyError`
183
+ * before anything is sent. A key header of any other spelling — one given in `headers` — goes
184
+ * too, from the headers sent and from the headers the configuration reports, so the old key is
185
+ * never sent beside the new one.
186
+ *
187
+ * The configuration is the one the owning `TypedRelyIOClient` holds (it hands its own to the
188
+ * constructor), so its `getConfig().apiKey` — what a surface reads to decide a key's kind — is the
189
+ * key sent from here on.
190
+ *
191
+ * This replaced `setAuthToken`, which added `Authorization: Bearer` beside an `X-API-Key` it
192
+ * never touched: the API reads `X-API-Key` first, so the old key was the one used (REL-1385).
167
193
  */
168
- setAuthToken(token: string): void;
194
+ setApiKey(apiKey: string): void;
169
195
  /**
170
196
  * Get current default headers
171
197
  */
@@ -190,7 +216,12 @@ declare class HttpClient {
190
216
  */
191
217
  private makeRequest;
192
218
  /**
193
- * Filter headers that browsers don't allow to be set manually
219
+ * The headers without those a browser controls itself, when this is a browser; unchanged when it
220
+ * is not.
221
+ *
222
+ * A name is matched without regard to case (RFC 9110 §5.1), because a browser refuses `Origin`
223
+ * whatever case a page spells it in. This matched only the all-lowercase and all-uppercase
224
+ * spellings, so `Origin` and `User-Agent` — how people write them — reached `fetch` (REL-1409).
194
225
  */
195
226
  private filterHeadersForBrowser;
196
227
  /**
@@ -205,6 +236,18 @@ declare class HttpClient {
205
236
  private log;
206
237
  }
207
238
 
239
+ /**
240
+ * The client's locale as a sub-client holds it: a function it asks on every call, or a locale fixed
241
+ * when it was built.
242
+ *
243
+ * `TypedRelyIOClient` hands every sub-client and builder a function over the configuration it holds,
244
+ * so one taken before `updateConfig({ locale })` sends the locale the client holds when the call is
245
+ * made, and none once `updateConfig({ locale: null })` has cleared it (REL-1453). A string is a locale
246
+ * fixed at construction — a sub-client's own `withLocale()`, or one built directly — and stays what it
247
+ * was.
248
+ */
249
+ type ClientLocale = string | (() => string | undefined);
250
+
208
251
  /**
209
252
  * Children population options
210
253
  */
@@ -244,10 +287,9 @@ type ExtendedQueryResult<T extends BaseContent = BaseContent> = ContentQueryResu
244
287
  * .execute()
245
288
  * ```
246
289
  */
247
- declare class ContentQueryBuilder<T extends BaseContent = BaseContent> {
290
+ declare class ContentQueryBuilder<T extends BaseContent = BaseContent, F extends BaseContent = T> {
248
291
  private readonly httpClient;
249
292
  private readonly contentType;
250
- private readonly defaultLocale?;
251
293
  private queryOptions;
252
294
  private localeValue?;
253
295
  private localesArray?;
@@ -257,7 +299,13 @@ declare class ContentQueryBuilder<T extends BaseContent = BaseContent> {
257
299
  private pageNumber?;
258
300
  private pageSizeValue?;
259
301
  private requestHeaders?;
260
- constructor(httpClient: HttpClient, contentType: string, defaultLocale?: string | undefined);
302
+ /** The client's locale, asked when the query is sent rather than copied when it was built. */
303
+ private readonly clientLocale;
304
+ /**
305
+ * @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when the
306
+ * query names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
307
+ */
308
+ constructor(httpClient: HttpClient, contentType: string, locale?: ClientLocale);
261
309
  /**
262
310
  * Headers this query adds to the client's own, e.g. `X-RelyIO-Dataset` to list another dataset
263
311
  * the key can see. A name the client already sends is replaced for this query only; the client
@@ -265,13 +313,14 @@ declare class ContentQueryBuilder<T extends BaseContent = BaseContent> {
265
313
  */
266
314
  headers(headers: Record<string, string>): this;
267
315
  /**
268
- * Add where conditions to the query
316
+ * Add where conditions to the query: conditions on the fields the content type declares. A
317
+ * condition on `_metadata` is refused here, before anything is sent (`refuseMetadataConditions`).
269
318
  */
270
- where(conditions: WhereClause<T>): this;
319
+ where(conditions: WhereClause<F>): this;
271
320
  /**
272
321
  * Select specific fields to return
273
322
  */
274
- select(fields: (keyof T)[]): this;
323
+ select(fields: NonNullable<QueryOptions<T, F>['select']>): this;
275
324
  /**
276
325
  * Include related content in the response
277
326
  */
@@ -289,7 +338,7 @@ declare class ContentQueryBuilder<T extends BaseContent = BaseContent> {
289
338
  * ```
290
339
  */
291
340
  sort(field: string, direction: 'asc' | 'desc'): this;
292
- sort(sortOptions: SortOptions<T>): this;
341
+ sort(sortOptions: SortOptions<F>): this;
293
342
  /**
294
343
  * Sort by a specific field in ascending order
295
344
  */
@@ -418,11 +467,11 @@ declare class ContentQueryBuilder<T extends BaseContent = BaseContent> {
418
467
  /**
419
468
  * Clone the query builder
420
469
  */
421
- clone(): ContentQueryBuilder<T>;
470
+ clone(): ContentQueryBuilder<T, F>;
422
471
  /**
423
472
  * Get the current query options
424
473
  */
425
- getQueryOptions(): QueryOptions<T>;
474
+ getQueryOptions(): QueryOptions<T, F>;
426
475
  /**
427
476
  * Execute the query and return the whole body.
428
477
  *
@@ -459,14 +508,19 @@ declare class ContentByIdBuilder<T extends BaseContent = BaseContent> {
459
508
  private readonly httpClient;
460
509
  private readonly contentType;
461
510
  private readonly id;
462
- private readonly defaultLocale?;
463
511
  private includeRelations?;
464
512
  private localeValue?;
465
513
  private localesArray?;
466
514
  private fetchAllLocales;
467
515
  private childrenOptions?;
468
516
  private requestHeaders?;
469
- constructor(httpClient: HttpClient, contentType: string, id: string, defaultLocale?: string | undefined);
517
+ /** The client's locale, asked when the read is sent rather than copied when it was built. */
518
+ private readonly clientLocale;
519
+ /**
520
+ * @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when the
521
+ * read names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
522
+ */
523
+ constructor(httpClient: HttpClient, contentType: string, id: string, locale?: ClientLocale);
470
524
  /**
471
525
  * Include related content in the response
472
526
  */
@@ -615,8 +669,13 @@ interface ContentFetchOptions<T extends BaseContent = BaseContent> {
615
669
  declare class ContentClient<T extends BaseContent = BaseContent> {
616
670
  private readonly httpClient;
617
671
  private readonly contentType;
618
- private readonly defaultLocale?;
619
- constructor(httpClient: HttpClient, contentType: string, defaultLocale?: string | undefined);
672
+ /** The client's locale, asked on every call rather than copied when this client was taken. */
673
+ private readonly clientLocale;
674
+ /**
675
+ * @param locale - The client's locale: the function `TypedRelyIOClient` hands over, asked on
676
+ * every call, or a locale fixed for this client
677
+ */
678
+ constructor(httpClient: HttpClient, contentType: string, locale?: ClientLocale);
620
679
  /**
621
680
  * Create a new query builder for this content type
622
681
  */
@@ -683,7 +742,7 @@ declare class ContentClient<T extends BaseContent = BaseContent> {
683
742
  * @param options - Create options (slug, locale, parentId, sortOrder), and `headers` this one
684
743
  * request adds — e.g. `{ 'X-RelyIO-Dataset': 'staging' }` to write a dataset other than the
685
744
  * client's. They are sent, never put in the body; `idempotencyKey` still wins over an
686
- * `Idempotency-Key` among them.
745
+ * `Idempotency-Key` among them. `locale` defaults to the client's own (`withLocale()`).
687
746
  */
688
747
  create(data: CreateInput<T>, options?: {
689
748
  slug?: string;
@@ -698,7 +757,8 @@ declare class ContentClient<T extends BaseContent = BaseContent> {
698
757
  * @param data - Fields to update
699
758
  * @param options - Update options (slug, locale, parentId, sortOrder), and `headers` this one
700
759
  * request adds, as for {@link create}. `ifMatch` and `idempotencyKey` win over the same
701
- * header among them.
760
+ * header among them. `locale` defaults to the client's own, the locale whose entity tag
761
+ * {@link fetchOneWithTag} reads, so the tag it hands back is checked against the same locale.
702
762
  */
703
763
  update(id: string, data: UpdateInput<T>, options?: {
704
764
  slug?: string;
@@ -719,8 +779,9 @@ declare class ContentClient<T extends BaseContent = BaseContent> {
719
779
  * Get version history for one locale of an entry.
720
780
  *
721
781
  * Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
722
- * schema default, no fallback is applied, and a locale with no history returns an empty array
723
- * rather than another locale's rows. Every row names the locale it belongs to.
782
+ * client's own (`withLocale()`), else the schema default; no fallback is applied, and a locale
783
+ * with no history returns an empty array rather than another locale's rows. Every row names the
784
+ * locale it belongs to.
724
785
  */
725
786
  versions(id: string, options?: {
726
787
  limit?: number;
@@ -732,8 +793,8 @@ declare class ContentClient<T extends BaseContent = BaseContent> {
732
793
  /**
733
794
  * Get a specific version of an entry.
734
795
  *
735
- * `locale` defaults to the schema default. Version numbers are per locale, so version 2 is
736
- * different content in each one.
796
+ * `locale` defaults to the client's own (`withLocale()`), else the schema default. Version
797
+ * numbers are per locale, so version 2 is different content in each one.
737
798
  */
738
799
  version(id: string, versionNumber: number, options?: {
739
800
  locale?: string;
@@ -770,11 +831,12 @@ declare class ContentClient<T extends BaseContent = BaseContent> {
770
831
  */
771
832
  ofType<U extends BaseContent = BaseContent>(contentType: string): ContentClient<U>;
772
833
  /**
773
- * Create a new ContentClient with a different default locale
834
+ * Create a new ContentClient with a different default locale, fixed: an update of the client's
835
+ * locale (`updateConfig({ locale })`) does not reach it
774
836
  */
775
837
  withLocale(locale: string): ContentClient<T>;
776
838
  /**
777
- * Get the current default locale
839
+ * Get the default locale as it is now: the client's, or the one `withLocale()` fixed
778
840
  */
779
841
  getDefaultLocale(): string | undefined;
780
842
  }
@@ -785,21 +847,40 @@ declare class ContentClient<T extends BaseContent = BaseContent> {
785
847
  * A **thin customer-side mirror** of the realtime-contracts `FileErrorCode`
786
848
  * (correction C6 — the SDK must not import the server/Studio contracts package).
787
849
  * Keep the members in sync with `@relyio/realtime-contracts`.
850
+ *
851
+ * Written once, as values, because a processing failure's code arrives as a string the service
852
+ * stored and has to be recognised at runtime; `FileErrorCode` is read off this list. The module is
853
+ * internal — `errors/index.ts` does not re-export it — so the list is not a second public name for
854
+ * the type.
788
855
  */
789
- type FileErrorCode = 'UPLOAD_TOO_LARGE' | 'UNSUPPORTED_MIME' | 'DIMENSION_OUT_OF_RANGE' | 'ASPECT_RATIO' | 'CORRUPT_FILE' | 'UNSUPPORTED_CODEC' | 'IMAGES_LIMIT_EXCEEDED' | 'STREAM_ENCODE_FAILED' | 'SCAN_INFECTED' | 'INTERNAL';
856
+ declare const FILE_ERROR_CODES: readonly ["UPLOAD_TOO_LARGE", "UNSUPPORTED_MIME", "DIMENSION_OUT_OF_RANGE", "ASPECT_RATIO", "CORRUPT_FILE", "UNSUPPORTED_CODEC", "IMAGES_LIMIT_EXCEEDED", "STREAM_ENCODE_FAILED", "SCAN_INFECTED", "INTERNAL"];
857
+
858
+ /**
859
+ * Upload/processing error taxonomy (plan 17, 00b Step 4): a customer-side mirror of the
860
+ * realtime-contracts `FileErrorCode`, read off the list in `./file-error-codes`.
861
+ */
862
+ type FileErrorCode = (typeof FILE_ERROR_CODES)[number];
863
+ /**
864
+ * The code a {@link FileUploadError} carries: a {@link FileErrorCode}, or `PROCESSING_FAILED` for a
865
+ * processing failure this SDK cannot name — the service stored no code, as an image or file
866
+ * processing failure is stored today, or one this version of the SDK predates. What the service
867
+ * stored is in the error's `context.processingError` either way.
868
+ */
869
+ type FileUploadErrorCode = FileErrorCode | 'PROCESSING_FAILED';
790
870
  /**
791
871
  * A failure during the upload protocol (presign / PUT / multipart / confirm) or
792
- * surfaced by the server's processing pipeline. Carries a typed {@link FileErrorCode}
872
+ * surfaced by the server's processing pipeline. Carries a typed {@link FileUploadErrorCode}
793
873
  * and a `retriable` hint so callers (and `upload()`'s bounded auto-retry) can
794
874
  * decide whether to retry on the same entry.
795
875
  */
796
876
  declare class FileUploadError extends SDKError {
797
- readonly code: FileErrorCode;
877
+ readonly code: FileUploadErrorCode;
798
878
  readonly retryable: boolean;
799
- constructor(code: FileErrorCode, message: string, options?: {
879
+ constructor(code: FileUploadErrorCode, message: string, options?: {
800
880
  retriable?: boolean;
801
881
  statusCode?: number;
802
882
  cause?: Error;
883
+ context?: Record<string, unknown>;
803
884
  });
804
885
  getUserMessage(): string;
805
886
  }
@@ -837,73 +918,20 @@ type AssetVisibility = 'public' | 'protected' | 'private';
837
918
  type FileStatus = 'pending_upload' | 'uploading' | 'processing' | 'ready' | 'failed';
838
919
  /** Storage backend: `r2` = image + file kinds, `stream` = video kind. */
839
920
  type FileBackend = 'r2' | 'stream';
840
- /** Extracted media metadata (Phase 1 basics + Phase 2 enrichment, plans 15–19). */
841
- interface AssetFileExtracted {
842
- width?: number;
843
- height?: number;
844
- format?: string;
845
- duration?: number;
846
- hasAlpha?: boolean;
847
- isAnimated?: boolean;
848
- orientation?: number;
849
- placeholder?: string;
850
- dominantColor?: string;
851
- palette?: string[];
852
- exif?: Record<string, unknown>;
853
- video?: {
854
- codec?: string;
855
- bitrate?: number;
856
- framerate?: number;
857
- audioTracks?: unknown[];
858
- };
859
- pageCount?: number;
860
- text?: string;
861
- safety?: {
862
- nsfwScore?: number;
863
- flagged?: boolean;
864
- categories?: string[];
865
- };
866
- [key: string]: unknown;
867
- }
868
- /** Customer-facing file binding block on an asset entry. */
869
- interface AssetFileBlock {
870
- status: FileStatus;
871
- backend: FileBackend;
872
- fileName: string;
873
- mimeType?: string | null;
874
- size?: number | null;
875
- /** Advisory client-computed SHA-256 (duplicate detection only). */
876
- hash?: string | null;
877
- visibility: AssetVisibility;
878
- extracted?: AssetFileExtracted;
879
- /** 0..1 normalized smart-crop anchor (written by plan 18). */
880
- focalPoint?: {
881
- x: number;
882
- y: number;
883
- };
884
- /** Phase-2 enrichment status — independent of `status` (plan 15). */
885
- enrichment?: {
886
- status: 'pending' | 'running' | 'complete' | 'partial' | 'failed';
887
- };
888
- /** File-kind malware scan status (plan 19). */
889
- scan?: {
890
- status: 'pending' | 'clean' | 'infected' | 'error' | 'skipped';
891
- };
892
- /** Processing progress (e.g. video encoding %) + terminal error. */
893
- processing?: {
894
- stage?: string;
895
- progress?: number;
896
- error?: {
897
- code?: string;
898
- message?: string;
899
- retriable?: boolean;
900
- };
901
- };
902
- /** Video playback readiness. */
903
- playback?: {
904
- ready?: boolean;
905
- };
906
- }
921
+ /**
922
+ * Customer-facing file binding block on an asset entry: the document's `AssetFile` — status,
923
+ * backend, file name, MIME type, size, advisory hash, visibility, extracted metadata, focal point,
924
+ * enrichment and scan status, processing stage/progress/error, and video playback readiness.
925
+ */
926
+ type AssetFileBlock = components['schemas']['AssetFile'];
927
+ /** Extracted media metadata (Phase 1 basics + Phase 2 enrichment, plans 15–19); open-ended. */
928
+ type AssetFileExtracted = NonNullable<AssetFileBlock['extracted']>;
929
+ /**
930
+ * Where one file binding's upload got to, as {@link AssetFileBuilder.status} reads it
931
+ * (`GET /v1/{assetType}/{id}/file`): the document's `FileStatus` — the binding's lifecycle and
932
+ * nothing of the entry's content. `processing.error` is present exactly while `status` is `failed`.
933
+ */
934
+ type FileStatusResult = components['schemas']['FileStatus'];
907
935
  /**
908
936
  * Computed gateway delivery URLs (the reserved `urls` key). Always served from
909
937
  * `cdn.relyio.net`. Image bindings expose `original` + `variants`; video bindings
@@ -1036,9 +1064,12 @@ type UpdateAssetOptions = {
1036
1064
  interface WaitUntilReadyOptions {
1037
1065
  /** Locale of the binding to watch. */
1038
1066
  locale?: string;
1039
- /** Total time to wait before giving up (ms). Default 60000. */
1067
+ /**
1068
+ * Total time to wait before giving up (ms), from 0 to 2147483647. Default 60000. `0` reads the
1069
+ * file once and rejects with a `TimeoutError` if it is not ready.
1070
+ */
1040
1071
  timeoutMs?: number;
1041
- /** Delay between polls (ms). Default 1500. */
1072
+ /** Delay between polls (ms), from 1 to 2147483647. Default 1500. */
1042
1073
  pollIntervalMs?: number;
1043
1074
  }
1044
1075
  /**
@@ -1049,8 +1080,13 @@ declare class AssetFileBuilder<T extends BaseContent = BaseContent> {
1049
1080
  private readonly httpClient;
1050
1081
  private readonly assetType;
1051
1082
  private readonly entryUid;
1052
- private readonly defaultLocale?;
1053
- constructor(httpClient: HttpClient, assetType: string, entryUid: string, defaultLocale?: string | undefined);
1083
+ /** The client's locale, asked on every call rather than copied when this builder was taken. */
1084
+ private readonly clientLocale;
1085
+ /**
1086
+ * @param locale - The client's locale, sent when a call names none: the function
1087
+ * `TypedRelyIOClient` hands over, or a locale fixed for this builder
1088
+ */
1089
+ constructor(httpClient: HttpClient, assetType: string, entryUid: string, locale?: ClientLocale);
1054
1090
  /**
1055
1091
  * The path parameters every `/file/*` route on this builder takes.
1056
1092
  *
@@ -1060,6 +1096,12 @@ declare class AssetFileBuilder<T extends BaseContent = BaseContent> {
1060
1096
  */
1061
1097
  private get target();
1062
1098
  private withLocale;
1099
+ /**
1100
+ * The `locale` body field of a multipart call: the session's, else the client's. The API finds
1101
+ * the binding by it, so a session a `withLocale()` client opened must name the same locale on
1102
+ * every later call or its `objectKey` is refused as another binding's.
1103
+ */
1104
+ private localeField;
1063
1105
  /**
1064
1106
  * Issue a single upload target — an R2 presigned PUT (image/file) or a
1065
1107
  * Cloudflare Stream direct-creator URL (video). Resumable multipart is plan 17.
@@ -1096,6 +1138,18 @@ declare class AssetFileBuilder<T extends BaseContent = BaseContent> {
1096
1138
  * Throws if the binding is not `ready`.
1097
1139
  */
1098
1140
  url(input?: ResolveUrlInput): Promise<ResolveUrlResult>;
1141
+ /**
1142
+ * Read where this file's upload got to — `status`, and the processing stage, progress and error
1143
+ * the pipeline recorded — whatever the asset entry is published in.
1144
+ *
1145
+ * An asset is a draft until its file is ready, and stays one when its file fails, so a key that
1146
+ * reads published content finds no entry for an upload in flight or one that failed. This read
1147
+ * answers for the binding itself. It takes the capability the upload calls take, so a read-only
1148
+ * key is refused with `ReadOnlyKeyError`, and it never returns the entry's fields.
1149
+ */
1150
+ status(options?: {
1151
+ locale?: string;
1152
+ }): Promise<FileStatusResult>;
1099
1153
  /**
1100
1154
  * Update the binding's delivery visibility (token-based; no byte relocation —
1101
1155
  * a downgrade purges the gateway cache). Returns the refreshed asset entry.
@@ -1123,8 +1177,23 @@ declare class AssetFileBuilder<T extends BaseContent = BaseContent> {
1123
1177
  locale?: string;
1124
1178
  }): Promise<void>;
1125
1179
  /**
1126
- * Poll the asset entry until its file binding reaches `ready` (resolves with
1127
- * the ready entry) or `failed` (throws). Times out after `timeoutMs`.
1180
+ * Poll the asset entry until its file binding reaches `ready`, and resolve with the ready entry.
1181
+ *
1182
+ * Each poll reads the entry through the key's lens. When that finds nothing — a key that reads
1183
+ * published content, and an asset that is a draft until its file is ready and stays one when it
1184
+ * fails — the poll reads the binding itself ({@link status}), so a failed upload rejects as one
1185
+ * rather than running out the limit (REL-1481).
1186
+ *
1187
+ * @throws {FileUploadError} When processing failed. `code` is the processing code the service
1188
+ * stored — `UNSUPPORTED_CODEC`, `CORRUPT_FILE` and so on — or `PROCESSING_FAILED` where it
1189
+ * stored none this SDK knows; `context.processingError` holds what it stored, and `retryable`
1190
+ * is its `retriable` hint.
1191
+ * @throws {TimeoutError} When `timeoutMs` passes first. The file may still become ready; the
1192
+ * error's `context.timeout` is the limit and `context.fileStatus` the status last seen. A file
1193
+ * that is `ready` in an asset the key's lens never shows — created with `publish: false`, or
1194
+ * awaiting a workflow — ends here too, and the message says so.
1195
+ * @throws {ReadOnlyKeyError} When the key's lens does not show the asset and the key may not read
1196
+ * its binding either: nothing it can read would ever report the file.
1128
1197
  */
1129
1198
  waitUntilReady(options?: WaitUntilReadyOptions): Promise<AssetEntryResponse<T>>;
1130
1199
  }
@@ -1139,7 +1208,6 @@ declare class AssetUploadBuilder<T extends BaseContent = BaseContent> {
1139
1208
  private readonly httpClient;
1140
1209
  private readonly assetType;
1141
1210
  private readonly file;
1142
- private readonly defaultLocale?;
1143
1211
  private _fileName?;
1144
1212
  private _visibility?;
1145
1213
  private _locale?;
@@ -1151,7 +1219,13 @@ declare class AssetUploadBuilder<T extends BaseContent = BaseContent> {
1151
1219
  private _onProgress?;
1152
1220
  private _validate?;
1153
1221
  private _maxPartRetries;
1154
- constructor(httpClient: HttpClient, assetType: string, file: Blob, defaultLocale?: string | undefined);
1222
+ /** The client's locale, read once when the upload starts. */
1223
+ private readonly clientLocale;
1224
+ /**
1225
+ * @param locale - The client's locale, the upload's when `.locale()` names none: the function
1226
+ * `TypedRelyIOClient` hands over, or a locale fixed for this upload
1227
+ */
1228
+ constructor(httpClient: HttpClient, assetType: string, file: Blob, locale?: ClientLocale);
1155
1229
  /** Subscribe to client → storage upload progress (single PUT + multipart). */
1156
1230
  onProgress(callback: (_progress: UploadProgress) => void): this;
1157
1231
  /**
@@ -1173,7 +1247,12 @@ declare class AssetUploadBuilder<T extends BaseContent = BaseContent> {
1173
1247
  content(content: Record<string, unknown>): this;
1174
1248
  /** Set an explicit slug for the new entry. */
1175
1249
  slug(slug: string): this;
1176
- /** Wait until the file binding becomes `ready` before resolving. */
1250
+ /**
1251
+ * Wait until the file binding becomes `ready` before resolving.
1252
+ *
1253
+ * @throws {Error} When `timeoutMs` or `pollIntervalMs` is one the wait cannot honour — refused
1254
+ * here, before anything is uploaded, rather than after the bytes are in.
1255
+ */
1177
1256
  waitForReady(options?: boolean | Omit<WaitUntilReadyOptions, 'locale'>): this;
1178
1257
  /** Execute the full upload flow and resolve with the asset entry. */
1179
1258
  execute(): Promise<AssetEntryResponse<T>>;
@@ -1197,10 +1276,18 @@ declare class AssetUploadBuilder<T extends BaseContent = BaseContent> {
1197
1276
  declare class AssetClient<T extends BaseContent = BaseContent> {
1198
1277
  private readonly httpClient;
1199
1278
  private readonly assetType;
1200
- private readonly defaultLocale?;
1201
- constructor(httpClient: HttpClient, assetType: string, defaultLocale?: string | undefined);
1202
- /** Create a query builder for this asset type. */
1203
- query(): ContentQueryBuilder<AssetEntryResponse<T>>;
1279
+ /** The client's locale, asked on every call rather than copied when this client was taken. */
1280
+ private readonly clientLocale;
1281
+ /**
1282
+ * @param locale - The client's locale: the function `TypedRelyIOClient` hands over, asked on
1283
+ * every call, or a locale fixed for this client
1284
+ */
1285
+ constructor(httpClient: HttpClient, assetType: string, locale?: ClientLocale);
1286
+ /**
1287
+ * Create a query builder for this asset type. It resolves asset reads; its conditions name the
1288
+ * asset type's fields, which the `file` and `urls` blocks are not.
1289
+ */
1290
+ query(): ContentQueryBuilder<AssetEntryResponse<T>, T>;
1204
1291
  /** Find an asset entry by id (or slug) with fluent options. */
1205
1292
  findById(id: string): ContentByIdBuilder<AssetEntryResponse<T>>;
1206
1293
  /** Fetch a single asset entry by id (or slug), or `null` if not found. */
@@ -1209,14 +1296,18 @@ declare class AssetClient<T extends BaseContent = BaseContent> {
1209
1296
  locale?: string;
1210
1297
  }): Promise<AssetEntryResponse<T> | null>;
1211
1298
  /** Fetch the first asset entry matching the conditions, or `null`. */
1212
- fetchFirst(where?: WhereClause<AssetEntryResponse<T>>, locale?: string): Promise<AssetEntryResponse<T> | null>;
1299
+ fetchFirst(where?: WhereClause<T>, locale?: string): Promise<AssetEntryResponse<T> | null>;
1213
1300
  /**
1214
1301
  * Create a new asset entry as a draft. The binary is uploaded separately via
1215
1302
  * `file(uid)` (or use the high-level `upload()` helper), and the entry
1216
1303
  * auto-publishes when its file becomes ready (unless `publish: false`).
1304
+ * `locale` defaults to the client's own (`withLocale()`).
1217
1305
  */
1218
1306
  create(data: CreateInput<T>, options?: CreateAssetOptions & RetryableWriteOptions): Promise<AssetEntryResponse<T>>;
1219
- /** Update an asset entry's metadata fields (and/or slug). */
1307
+ /**
1308
+ * Update an asset entry's metadata fields (and/or slug). `locale` defaults to the client's own
1309
+ * (`withLocale()`).
1310
+ */
1220
1311
  update(id: string, data: UpdateInput<T>, options?: UpdateAssetOptions): Promise<AssetEntryResponse<T>>;
1221
1312
  /** Delete an asset entry (cascades file-byte cleanup + gateway purge). */
1222
1313
  delete(id: string, options?: ConditionalWriteOptions): Promise<void>;
@@ -1226,9 +1317,12 @@ declare class AssetClient<T extends BaseContent = BaseContent> {
1226
1317
  upload(file: Blob): AssetUploadBuilder<T>;
1227
1318
  /** Get the asset type id. */
1228
1319
  getAssetType(): string;
1229
- /** Get the current default locale. */
1320
+ /** Get the default locale as it is now: the client's, or the one `withLocale()` fixed. */
1230
1321
  getDefaultLocale(): string | undefined;
1231
- /** Create a new AssetClient for this type with a different default locale. */
1322
+ /**
1323
+ * Create a new AssetClient for this type with a different default locale, fixed: an update of the
1324
+ * client's locale (`updateConfig({ locale })`) does not reach it.
1325
+ */
1232
1326
  withLocale(locale: string): AssetClient<T>;
1233
1327
  }
1234
1328
  /**
@@ -1263,8 +1357,10 @@ interface SingletonFetchOptions {
1263
1357
  * Singleton client for managing singleton content operations
1264
1358
  * Provides a fluent API for singleton operations following the same pattern as ContentClient
1265
1359
  *
1266
- * A read is in the locale it names — `fetch({ locale })`, then `.locale()` — and otherwise in
1267
- * `defaultLocale`, the client's own (`withLocale()`), as `content()`'s reads are.
1360
+ * Every call is in the locale it names — the argument (`fetch({ locale })`, `update(data, locale)`,
1361
+ * `versions({ locale })`), then `.locale()` — and otherwise in the client's own (`withLocale()`,
1362
+ * `updateConfig({ locale })`) as it is when the call is made, as `content()`'s are: reads, the write,
1363
+ * and version history alike.
1268
1364
  *
1269
1365
  * @example
1270
1366
  * ```typescript
@@ -1277,10 +1373,15 @@ interface SingletonFetchOptions {
1277
1373
  declare class SingletonClient<T = unknown> {
1278
1374
  private httpClient;
1279
1375
  private singletonKey;
1280
- private readonly defaultLocale?;
1281
1376
  private includeFields?;
1282
1377
  private localeValue?;
1283
- constructor(httpClient: HttpClient, singletonKey: string, defaultLocale?: string | undefined);
1378
+ /** The client's locale, asked on every call rather than copied when this client was taken. */
1379
+ private readonly clientLocale;
1380
+ /**
1381
+ * @param locale - The client's locale: the function `TypedRelyIOClient` hands over, asked on
1382
+ * every call, or a locale fixed for this client
1383
+ */
1384
+ constructor(httpClient: HttpClient, singletonKey: string, locale?: ClientLocale);
1284
1385
  /**
1285
1386
  * Include reference fields in the response
1286
1387
  * @param fields - Reference field names to populate
@@ -1311,7 +1412,8 @@ declare class SingletonClient<T = unknown> {
1311
1412
  * Update singleton content. The API auto-publishes on PATCH — there is no
1312
1413
  * separate publish route; calling `update()` writes and publishes.
1313
1414
  * @param data - The content fields to update
1314
- * @param locale - Optional locale for localized content (overrides fluent locale)
1415
+ * @param locale - Optional locale for localized content (overrides the fluent locale, which
1416
+ * overrides the client's own)
1315
1417
  * @param options - `If-Match` / `Idempotency-Key`, both declared on this route
1316
1418
  */
1317
1419
  update(data: Partial<T>, locale?: string, options?: ConditionalWriteOptions): Promise<T>;
@@ -1323,8 +1425,9 @@ declare class SingletonClient<T = unknown> {
1323
1425
  * Get version history for one locale of the singleton.
1324
1426
  *
1325
1427
  * Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
1326
- * schema default, no fallback is applied, and a locale with no history returns an empty array
1327
- * rather than another locale's rows. Every row names the locale it belongs to.
1428
+ * fluent `.locale()`, then the client's own (`withLocale()`), then the schema default; no
1429
+ * fallback is applied, and a locale with no history returns an empty array rather than another
1430
+ * locale's rows. Every row names the locale it belongs to.
1328
1431
  */
1329
1432
  versions(options?: {
1330
1433
  limit?: number;
@@ -1336,12 +1439,14 @@ declare class SingletonClient<T = unknown> {
1336
1439
  /**
1337
1440
  * Get a specific version of the singleton.
1338
1441
  *
1339
- * `locale` defaults to the schema default. Version numbers are per locale, so version 2 is
1340
- * different content in each one.
1442
+ * `locale` defaults to the fluent `.locale()`, then the client's own (`withLocale()`), then the
1443
+ * schema default. Version numbers are per locale, so version 2 is different content in each one.
1341
1444
  */
1342
1445
  version(versionNumber: number, options?: {
1343
1446
  locale?: string;
1344
1447
  }): Promise<T | null>;
1448
+ /** The locale a write or history read sends: the call's, the fluent one, else the client's. */
1449
+ private localeOf;
1345
1450
  /**
1346
1451
  * Get the singleton key
1347
1452
  */
@@ -1365,8 +1470,10 @@ interface SettingsFetchOptions {
1365
1470
  * Settings client for managing settings group operations
1366
1471
  * Provides a fluent API for settings operations following the same pattern as ContentClient
1367
1472
  *
1368
- * A read is in the locale it names — `fetch({ locale })`, then `.locale()` — and otherwise in
1369
- * `defaultLocale`, the client's own (`withLocale()`), as `content()`'s reads are.
1473
+ * Every call is in the locale it names — the argument (`fetch({ locale })`, `update(settings,
1474
+ * locale)`, `reset(locale)`, `versions({ locale })`), then `.locale()` — and otherwise in the
1475
+ * client's own (`withLocale()`, `updateConfig({ locale })`) as it is when the call is made, as
1476
+ * `content()`'s are: reads, writes and version history alike.
1370
1477
  *
1371
1478
  * @example
1372
1479
  * ```typescript
@@ -1379,10 +1486,15 @@ interface SettingsFetchOptions {
1379
1486
  declare class SettingsClient<T = unknown> {
1380
1487
  private readonly httpClient;
1381
1488
  private readonly groupId;
1382
- private readonly defaultLocale?;
1383
1489
  private includeFields?;
1384
1490
  private localeValue?;
1385
- constructor(httpClient: HttpClient, groupId: string, defaultLocale?: string | undefined);
1491
+ /** The client's locale, asked on every call rather than copied when this client was taken. */
1492
+ private readonly clientLocale;
1493
+ /**
1494
+ * @param locale - The client's locale: the function `TypedRelyIOClient` hands over, asked on
1495
+ * every call, or a locale fixed for this client
1496
+ */
1497
+ constructor(httpClient: HttpClient, groupId: string, locale?: ClientLocale);
1386
1498
  /**
1387
1499
  * Include reference fields in the response
1388
1500
  * @param fields - Reference field names to populate
@@ -1400,8 +1512,13 @@ declare class SettingsClient<T = unknown> {
1400
1512
  fetch(options?: SettingsFetchOptions): Promise<T | null>;
1401
1513
  /**
1402
1514
  * Update settings group
1515
+ *
1516
+ * The fields travel as `content` beside an optional `locale`, the body the route validates
1517
+ * (`UpdateSettingsDto`); any other top-level key is refused `REQUEST_INVALID`.
1518
+ *
1403
1519
  * @param settings - The settings fields to update
1404
- * @param locale - Optional locale for localized settings (overrides fluent locale)
1520
+ * @param locale - Optional locale for localized settings (overrides the fluent locale, which
1521
+ * overrides the client's own)
1405
1522
  */
1406
1523
  update(settings: Partial<T>, locale?: string, options?: ConditionalWriteOptions): Promise<T>;
1407
1524
  /**
@@ -1415,7 +1532,11 @@ declare class SettingsClient<T = unknown> {
1415
1532
  }>;
1416
1533
  /**
1417
1534
  * Reset settings to default values
1418
- * @param locale - Optional locale for localized settings
1535
+ *
1536
+ * The route reads its locale from `?locale=` and takes no body, so that is where it is sent.
1537
+ *
1538
+ * @param locale - Optional locale for localized settings (overrides the fluent locale, which
1539
+ * overrides the client's own)
1419
1540
  */
1420
1541
  reset(locale?: string, options?: ConditionalWriteOptions): Promise<T>;
1421
1542
  /**
@@ -1430,8 +1551,9 @@ declare class SettingsClient<T = unknown> {
1430
1551
  * Get version history for one locale of the settings group.
1431
1552
  *
1432
1553
  * Versions are numbered per locale, so this is one locale's timeline: `locale` defaults to the
1433
- * schema default, no fallback is applied, and a locale with no history returns an empty array
1434
- * rather than another locale's rows. Every row names the locale it belongs to.
1554
+ * fluent `.locale()`, then the client's own (`withLocale()`), then the schema default; no
1555
+ * fallback is applied, and a locale with no history returns an empty array rather than another
1556
+ * locale's rows. Every row names the locale it belongs to.
1435
1557
  */
1436
1558
  versions(options?: {
1437
1559
  limit?: number;
@@ -1443,12 +1565,14 @@ declare class SettingsClient<T = unknown> {
1443
1565
  /**
1444
1566
  * Get a specific version of the settings.
1445
1567
  *
1446
- * `locale` defaults to the schema default. Version numbers are per locale, so version 2 is
1447
- * different content in each one.
1568
+ * `locale` defaults to the fluent `.locale()`, then the client's own (`withLocale()`), then the
1569
+ * schema default. Version numbers are per locale, so version 2 is different content in each one.
1448
1570
  */
1449
1571
  version(versionNumber: number, options?: {
1450
1572
  locale?: string;
1451
1573
  }): Promise<T | null>;
1574
+ /** The locale a write or history read sends: the call's, the fluent one, else the client's. */
1575
+ private localeOf;
1452
1576
  /**
1453
1577
  * Get the settings group ID
1454
1578
  */
@@ -1499,17 +1623,27 @@ type RegisteredSchema = Register extends {
1499
1623
  */
1500
1624
  type SearchMode = 'keyword' | 'semantic' | 'hybrid';
1501
1625
  /**
1502
- * One search hit as the route emits it: the entry fields at the top level,
1503
- * plus optional score annotations. There is no per-item `data` wrapper.
1626
+ * What a search or similar hit reports beside its fields: the committed document's
1627
+ * `SearchHitMetadata`, read through `http/api-schema.ts`.
1628
+ *
1629
+ * Narrower than an entry read's `EntryMetadata`, because a hit is not built by the entry read: it
1630
+ * carries no `entryType`, `defaultLocale`, `availableLocales`, `refs`, `firstPublishedAt` or
1631
+ * version history. Until REL-1413 a hit was typed as an entry and so promised all five — the
1632
+ * locale helpers kept an optional chain after `availableLocales` for the hits that lacked it. Read
1633
+ * the entry (`content(type).findById(hit._metadata.id)`) for those.
1504
1634
  */
1505
- type SearchResultItem<T = unknown> = T & {
1506
- _score?: number;
1507
- _scoreBreakdown?: {
1508
- keyword?: number;
1509
- semantic?: number;
1510
- };
1511
- _highlights?: Record<string, string[]>;
1512
- };
1635
+ type SearchHitMetadata = components['schemas']['SearchHitMetadata'];
1636
+ /** What a hit carries beside the entry's fields, as the document declares it. */
1637
+ type SearchHitSystemFields = Pick<components['schemas']['SearchHit'], '_metadata' | '_score' | '_scoreBreakdown' | '_highlights'>;
1638
+ /**
1639
+ * One search hit as the route emits it — the document's `SearchHit`: the fields `T` declares at the
1640
+ * top level (at `_metadata.locale`, or only the aliases a `fields` projection names), the hit's own
1641
+ * `_metadata`, and the score annotations the request asked for. There is no per-item `data` wrapper.
1642
+ *
1643
+ * `T`'s `_metadata` is replaced, not kept: `T` is an entry type, and a hit is not an entry read.
1644
+ * Distributes over a union of entry types, so a search across two types keeps each one's fields.
1645
+ */
1646
+ type SearchResultItem<T = unknown> = T extends unknown ? Omit<T, '_metadata'> & SearchHitSystemFields : never;
1513
1647
  /**
1514
1648
  * Search response from API
1515
1649
  */
@@ -1529,20 +1663,12 @@ type SearchResultItem<T = unknown> = T & {
1529
1663
  */
1530
1664
  type SearchResponse<T = unknown> = Wire<'/v1/search', 'post', SearchResultItem<T>>;
1531
1665
  /**
1532
- * Autocomplete suggestion
1533
- */
1534
- interface AutocompleteSuggestion {
1535
- /** Suggested text */
1536
- text: string;
1537
- /** Highlighted version */
1538
- highlighted?: string;
1539
- /** Score */
1540
- score?: number;
1541
- /** Source entry ID */
1542
- entryId?: string;
1543
- /** Content type */
1544
- contentType?: string;
1545
- }
1666
+ * One autocomplete suggestion — the document's `AutocompleteSuggestion`: the value, its best score,
1667
+ * an entry holding it (`id`), and the value with its match wrapped in `<em>` when Atlas highlighted
1668
+ * it. The hand-written type this replaces named `highlighted`, `entryId` and `contentType`, none of
1669
+ * which the route sends, and made `score` optional where it is always sent.
1670
+ */
1671
+ type AutocompleteSuggestion = components['schemas']['AutocompleteSuggestion'];
1546
1672
  /**
1547
1673
  * Autocomplete response
1548
1674
  */
@@ -1555,11 +1681,10 @@ interface AutocompleteSuggestion {
1555
1681
  */
1556
1682
  type AutocompleteResponse = Wire<'/v1/search/autocomplete', 'post', AutocompleteSuggestion>;
1557
1683
  /**
1558
- * One similar-content hit as the route emits it — a flat entry, no `data` wrapper.
1684
+ * One similar-content hit as the route emits it: the same `SearchHit` a search serves, built by
1685
+ * the same transform, with `_score` on every hit.
1559
1686
  */
1560
- type SimilarResult<T = unknown> = T & {
1561
- _score?: number;
1562
- };
1687
+ type SimilarResult<T = unknown> = SearchResultItem<T>;
1563
1688
  /**
1564
1689
  * Similar response
1565
1690
  */
@@ -1610,14 +1735,16 @@ interface SearchSort {
1610
1735
  */
1611
1736
  declare class SearchBuilder<T extends BaseContent = BaseContent, S extends AnySchemaDefinition | undefined = undefined> {
1612
1737
  private readonly httpClient;
1613
- private readonly defaultLocale?;
1614
1738
  private query;
1615
1739
  private searchOptions;
1616
1740
  private requestHeaders?;
1741
+ /** The client's locale, asked when the query is sent rather than copied when it was built. */
1742
+ private readonly clientLocale;
1617
1743
  /**
1618
- * @param defaultLocale - The client's locale (`withLocale()`), sent when `.locale()` names none
1744
+ * @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when
1745
+ * `.locale()` names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
1619
1746
  */
1620
- constructor(httpClient: HttpClient, query: string, defaultLocale?: string | undefined);
1747
+ constructor(httpClient: HttpClient, query: string, locale?: ClientLocale);
1621
1748
  /**
1622
1749
  * Headers this search adds to the client's own, e.g. `X-RelyIO-Dataset` to search another
1623
1750
  * dataset the key can see. A name the client already sends is replaced for this search only.
@@ -1636,7 +1763,8 @@ declare class SearchBuilder<T extends BaseContent = BaseContent, S extends AnySc
1636
1763
  */
1637
1764
  across<K extends SearchTypeName<S>>(contentTypes: K[] | '*'): SearchBuilder<SearchEntry<S, K, T>, S>;
1638
1765
  /**
1639
- * Add filter conditions
1766
+ * Add filter conditions, on the fields the content types declare. A condition on `_metadata` is
1767
+ * refused here, before anything is sent.
1640
1768
  * @param conditions - Filter conditions
1641
1769
  */
1642
1770
  where(conditions: SearchFilter): this;
@@ -1708,13 +1836,15 @@ declare class SearchBuilder<T extends BaseContent = BaseContent, S extends AnySc
1708
1836
  */
1709
1837
  declare class AutocompleteBuilder {
1710
1838
  private readonly httpClient;
1711
- private readonly defaultLocale?;
1712
1839
  private query;
1713
1840
  private autocompleteOptions;
1841
+ /** The client's locale, asked when the query is sent rather than copied when it was built. */
1842
+ private readonly clientLocale;
1714
1843
  /**
1715
- * @param defaultLocale - The client's locale (`withLocale()`), sent when `.locale()` names none
1844
+ * @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when
1845
+ * `.locale()` names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
1716
1846
  */
1717
- constructor(httpClient: HttpClient, query: string, defaultLocale?: string | undefined);
1847
+ constructor(httpClient: HttpClient, query: string, locale?: ClientLocale);
1718
1848
  /**
1719
1849
  * Autocomplete within a content type
1720
1850
  * @param contentType - Content type to search
@@ -1730,7 +1860,8 @@ declare class AutocompleteBuilder {
1730
1860
  */
1731
1861
  fuzzy(): this;
1732
1862
  /**
1733
- * Add filter conditions
1863
+ * Add filter conditions, on the fields the content types declare. A condition on `_metadata` is
1864
+ * refused here, before anything is sent.
1734
1865
  * @param conditions - Filter conditions
1735
1866
  */
1736
1867
  where(conditions: SearchFilter): this;
@@ -1767,14 +1898,16 @@ declare class AutocompleteBuilder {
1767
1898
  */
1768
1899
  declare class SimilarBuilder<T extends BaseContent = BaseContent> {
1769
1900
  private readonly httpClient;
1770
- private readonly defaultLocale?;
1771
1901
  private sourceId;
1772
1902
  private similarOptions;
1773
1903
  private requestHeaders?;
1904
+ /** The client's locale, asked when the read is sent rather than copied when it was built. */
1905
+ private readonly clientLocale;
1774
1906
  /**
1775
- * @param defaultLocale - The client's locale (`withLocale()`), sent when `.locale()` names none
1907
+ * @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent when
1908
+ * `.locale()` names none: the function `TypedRelyIOClient` hands over, or a locale fixed for it
1776
1909
  */
1777
- constructor(httpClient: HttpClient, sourceId: string, defaultLocale?: string | undefined);
1910
+ constructor(httpClient: HttpClient, sourceId: string, locale?: ClientLocale);
1778
1911
  /**
1779
1912
  * Headers this read adds to the client's own, e.g. `X-RelyIO-Dataset` to read another dataset
1780
1913
  * the key can see. A name the client already sends is replaced for this read only.
@@ -1790,11 +1923,6 @@ declare class SimilarBuilder<T extends BaseContent = BaseContent> {
1790
1923
  * @param contentTypes - Array of content types or '*' for all
1791
1924
  */
1792
1925
  across(contentTypes: string[] | '*'): this;
1793
- /**
1794
- * Add filter conditions
1795
- * @param conditions - Filter conditions
1796
- */
1797
- where(conditions: SearchFilter): this;
1798
1926
  /**
1799
1927
  * Limit number of results
1800
1928
  * @param count - Maximum results
@@ -1845,12 +1973,14 @@ declare class SimilarBuilder<T extends BaseContent = BaseContent> {
1845
1973
  */
1846
1974
  declare class SearchClient {
1847
1975
  private readonly httpClient;
1848
- private readonly defaultLocale?;
1976
+ /** The client's locale, handed to every builder here to ask when it sends. */
1977
+ private readonly clientLocale;
1849
1978
  /**
1850
- * @param defaultLocale - The client's locale (`withLocale()`): every builder here sends it when
1851
- * the query names none, as `content()`'s reads do
1979
+ * @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`): every builder
1980
+ * here sends it when the query names none, as `content()`'s reads do — the function
1981
+ * `TypedRelyIOClient` hands over, or a locale fixed for this client
1852
1982
  */
1853
- constructor(httpClient: HttpClient, defaultLocale?: string | undefined);
1983
+ constructor(httpClient: HttpClient, locale?: ClientLocale);
1854
1984
  /**
1855
1985
  * Start a search query
1856
1986
  * @param query - Search query string
@@ -1866,12 +1996,6 @@ declare class SearchClient {
1866
1996
  * @param sourceId - Entry ID to find similar content for
1867
1997
  */
1868
1998
  similar<T extends BaseContent = BaseContent>(sourceId: string): SimilarBuilder<T>;
1869
- /**
1870
- * Quick search helper - searches all content types
1871
- * @param query - Search query
1872
- * @param limit - Max results (default 20)
1873
- */
1874
- global<T extends BaseContent = BaseContent>(query: string, limit?: number): Promise<SearchResponse<T>>;
1875
1999
  }
1876
2000
 
1877
2001
  /**
@@ -1900,7 +2024,10 @@ interface BatchOptions {
1900
2024
  *
1901
2025
  * Requires that all operations be the same kind of write — one transaction cannot span two
1902
2026
  * calls — so a batch mixing creates and deletes, or `update` and `replace`, is rejected with
1903
- * a 400 before anything is attempted.
2027
+ * a 400 before anything is attempted: `execute()` rejects with `InvalidPayloadError`. A
2028
+ * singleton write is a create when the dataset has never written that singleton and an update
2029
+ * after, and an atomic batch cannot create one — that operation reports `REQUEST_INVALID` and
2030
+ * every other `TRANSACTION_ROLLED_BACK` — so create it in a request of its own first.
1904
2031
  *
1905
2032
  * @default false
1906
2033
  */
@@ -1958,16 +2085,33 @@ type BatchResponse = components['schemas']['MultiPayload'];
1958
2085
  /**
1959
2086
  * Fluent builder for batch operations
1960
2087
  *
2088
+ * Every create, update, replace and singleton operation it builds is in the locale that operation
2089
+ * names, and otherwise in the client's own (`withLocale()`), sent as that operation's
2090
+ * `body.locale` — a batch is one request, but the API reads a locale per operation. A delete names
2091
+ * none (it removes the whole entry), and a `raw()` operation is sent exactly as written.
2092
+ *
2093
+ * An atomic batch — `.atomic()` or `execute({ atomic: true })` — is one transaction: every
2094
+ * operation lands or none does. The API accepts one only when every operation is the same kind of
2095
+ * write and none writes a singleton that does not exist yet (see {@link BatchOptions.atomic}).
2096
+ *
1961
2097
  * @example
1962
2098
  * ```typescript
2099
+ * // Each operation lands or fails on its own
1963
2100
  * const result = await relyio.batch()
1964
2101
  * .create('product', { content: { title: 'iPhone', price: 999 } })
1965
2102
  * .update('product', 'entry_abc', { content: { price: 899 } })
1966
2103
  * .delete('product', 'entry_xyz')
1967
2104
  * .upsertSingleton('homepage', { content: { hero: 'Welcome!' } })
1968
- * .execute({ atomic: true })
2105
+ * .execute()
1969
2106
  *
1970
- * console.log(result.summary.succeeded) // 4
2107
+ * console.log(result.summary.succeeded)
2108
+ *
2109
+ * // All or nothing: one kind of write
2110
+ * await relyio.batch()
2111
+ * .create('product', { content: { title: 'iPhone', price: 999 } })
2112
+ * .create('product', { content: { title: 'iPad', price: 799 } })
2113
+ * .atomic()
2114
+ * .execute()
1971
2115
  * ```
1972
2116
  */
1973
2117
  declare class BatchBuilder<TSchema = unknown> {
@@ -1975,7 +2119,19 @@ declare class BatchBuilder<TSchema = unknown> {
1975
2119
  private operations;
1976
2120
  private defaultOptions;
1977
2121
  private requestHeaders;
1978
- constructor(httpClient: HttpClient);
2122
+ /** The client's locale, asked as each operation is added rather than copied when this was built. */
2123
+ private readonly clientLocale;
2124
+ /**
2125
+ * @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), each
2126
+ * operation's when it names none: the function `TypedRelyIOClient` hands over, or a locale fixed
2127
+ * for this batch
2128
+ */
2129
+ constructor(httpClient: HttpClient, locale?: ClientLocale);
2130
+ /**
2131
+ * An operation's body with its locale: the one it names, else the client's as it is when the
2132
+ * operation is added.
2133
+ */
2134
+ private localized;
1979
2135
  /**
1980
2136
  * Add a create operation
1981
2137
  * @param contentType - Content type to create
@@ -2053,7 +2209,8 @@ declare class BatchBuilder<TSchema = unknown> {
2053
2209
  locale?: string;
2054
2210
  }, id?: string): this;
2055
2211
  /**
2056
- * Add a raw operation (for advanced use cases)
2212
+ * Add a raw operation (for advanced use cases). It is sent exactly as written: the client's
2213
+ * locale is not added to it.
2057
2214
  * @param operation - The operation to add
2058
2215
  */
2059
2216
  raw(operation: BatchOperation): this;
@@ -2170,9 +2327,15 @@ declare class BatchBuilder<TSchema = unknown> {
2170
2327
  */
2171
2328
  declare class BatchClient<TSchema = unknown> {
2172
2329
  private readonly httpClient;
2173
- constructor(httpClient: HttpClient);
2330
+ /** The client's locale, handed to every batch this builds to ask as operations are added. */
2331
+ private readonly clientLocale;
2174
2332
  /**
2175
- * Create a new batch builder
2333
+ * @param locale - The client's locale: the function `TypedRelyIOClient` hands over, or a locale
2334
+ * fixed for this client
2335
+ */
2336
+ constructor(httpClient: HttpClient, locale?: ClientLocale);
2337
+ /**
2338
+ * Create a new batch builder, whose operations default to this client's locale
2176
2339
  */
2177
2340
  create(): BatchBuilder<TSchema>;
2178
2341
  /**
@@ -2251,13 +2414,14 @@ interface AggregateBlock {
2251
2414
  }
2252
2415
  /**
2253
2416
  * One metric, as the Query DSL writes it: `<field>.<fn>`, where `fn` is `count`, `sum`, `avg`,
2254
- * `min` or `max` — `'id.count'`, `'pricing.basePrice.avg'`. The service validates every metric
2255
- * against that form (`INVALID_AGGREGATION_EXPRESSION`); `count` ignores the field it names.
2417
+ * `min`, `max`, `first` or `last` — `'id.count'`, `'pricing.basePrice.avg'`. The service
2418
+ * validates every metric against that form (`INVALID_AGGREGATION_EXPRESSION`); `count` ignores the
2419
+ * field it names. `first` and `last` were missing here while the service ran them (REL-1470).
2256
2420
  *
2257
2421
  * It used to be `{ fn, field? }`, a shape the service refuses on every request: the validator
2258
2422
  * tests the metric as a string, so an object arrives as `[object Object]`.
2259
2423
  */
2260
- type AggregateMetric = `${string}.${'count' | 'sum' | 'avg' | 'min' | 'max'}`;
2424
+ type AggregateMetric = `${string}.${'count' | 'sum' | 'avg' | 'min' | 'max' | 'first' | 'last'}`;
2261
2425
  /**
2262
2426
  * Search block for full-text/semantic search
2263
2427
  */
@@ -2276,36 +2440,11 @@ interface SearchBlock {
2276
2440
  limit?: number;
2277
2441
  }
2278
2442
  /**
2279
- * Similar block for vector similarity search
2443
+ * One post-fetch filter: a parameter expression, or the operators every query clause compares with
2444
+ * (`FilterOperator`, REL-1479). This kept a copy of eleven, without `exists` or `notExists`; and a
2445
+ * bare number or boolean, which it took, the service does not read as a filter.
2280
2446
  */
2281
- interface SimilarBlock {
2282
- /** Content type */
2283
- contentType: string;
2284
- /** Source entry ID */
2285
- source: string;
2286
- /** Minimum similarity threshold */
2287
- threshold?: number;
2288
- /** Additional filters */
2289
- where?: Record<string, unknown>;
2290
- /** Maximum results */
2291
- limit?: number;
2292
- }
2293
- /**
2294
- * Post-fetch filters with parameter support
2295
- */
2296
- type FilterValue = string | number | boolean | {
2297
- eq?: unknown;
2298
- ne?: unknown;
2299
- gt?: unknown;
2300
- gte?: unknown;
2301
- lt?: unknown;
2302
- lte?: unknown;
2303
- in?: unknown[];
2304
- nin?: unknown[];
2305
- contains?: unknown;
2306
- startsWith?: string;
2307
- endsWith?: string;
2308
- };
2447
+ type FilterValue = string | FilterOperator;
2309
2448
  /**
2310
2449
  * Full-text search configuration
2311
2450
  */
@@ -2327,8 +2466,6 @@ interface AdhocQueryDefinition {
2327
2466
  aggregate?: AggregateBlock;
2328
2467
  /** Search block - full-text/semantic search */
2329
2468
  search?: SearchBlock;
2330
- /** Similar block - vector similarity */
2331
- similar?: SimilarBlock;
2332
2469
  /** Field selection/transformation */
2333
2470
  select?: Record<string, string>;
2334
2471
  /** Post-fetch filters with parameter support */
@@ -2416,15 +2553,17 @@ interface AdhocQueryResult<T = unknown> {
2416
2553
  */
2417
2554
  declare class AdhocQueryBuilder<T = unknown> {
2418
2555
  private readonly httpClient;
2419
- private readonly defaultLocale?;
2420
2556
  private queryDef;
2421
2557
  private parameters;
2422
2558
  private options;
2559
+ /** The client's locale, asked when the query is sent rather than copied when it was built. */
2560
+ private readonly clientLocale;
2423
2561
  /**
2424
- * @param defaultLocale - The client's locale (`withLocale()`), sent as the `locale` parameter
2425
- * when `.param('locale', …)` binds none
2562
+ * @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent as the
2563
+ * `locale` parameter when `.param('locale', …)` binds none: the function `TypedRelyIOClient`
2564
+ * hands over, or a locale fixed for this builder
2426
2565
  */
2427
- constructor(httpClient: HttpClient, defaultLocale?: string | undefined);
2566
+ constructor(httpClient: HttpClient, locale?: ClientLocale);
2428
2567
  /**
2429
2568
  * Add a fetch block to retrieve content
2430
2569
  * @param config - Fetch configuration
@@ -2450,11 +2589,6 @@ declare class AdhocQueryBuilder<T = unknown> {
2450
2589
  * @param config - Search configuration
2451
2590
  */
2452
2591
  search(config: SearchBlock): this;
2453
- /**
2454
- * Add similar block
2455
- * @param config - Similar configuration
2456
- */
2457
- similar(config: SimilarBlock): this;
2458
2592
  /**
2459
2593
  * Add where conditions to fetch
2460
2594
  * @param conditions - Filter conditions
@@ -2583,12 +2717,14 @@ declare class AdhocQueryBuilder<T = unknown> {
2583
2717
  */
2584
2718
  declare class AdhocQueryClient {
2585
2719
  private readonly httpClient;
2586
- private readonly defaultLocale?;
2720
+ /** The client's locale, asked on every query rather than copied when this client was taken. */
2721
+ private readonly clientLocale;
2587
2722
  /**
2588
- * @param defaultLocale - The client's locale (`withLocale()`), sent as the `locale` parameter of
2589
- * every query that binds none
2723
+ * @param locale - The client's locale (`withLocale()`, `updateConfig({ locale })`), sent as the
2724
+ * `locale` parameter of every query that binds none: the function `TypedRelyIOClient` hands
2725
+ * over, or a locale fixed for this client
2590
2726
  */
2591
- constructor(httpClient: HttpClient, defaultLocale?: string | undefined);
2727
+ constructor(httpClient: HttpClient, locale?: ClientLocale);
2592
2728
  /**
2593
2729
  * Create a new query builder
2594
2730
  */
@@ -2797,13 +2933,25 @@ interface TypedClientConfig<TSchema extends AnySchemaDefinition | undefined = un
2797
2933
  * ```
2798
2934
  */
2799
2935
  declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined = undefined> {
2800
- private httpClient;
2936
+ /**
2937
+ * The one HTTP client every sub-client sends through. `updateConfig()` and `setApiKey()` change it
2938
+ * in place rather than replacing it, so a sub-client taken before either sends through the change.
2939
+ */
2940
+ private readonly httpClient;
2801
2941
  private config;
2942
+ /**
2943
+ * The configuration as `createClient()`, `setApiKey()` and `updateConfig()` gave it, before the
2944
+ * `relyio dev` handshake: what the next update is laid over, and what `withLocale()` starts from.
2945
+ */
2946
+ private configured;
2802
2947
  private _sandbox;
2803
- private _search;
2804
- private _batch;
2805
- private _adhocQuery;
2806
2948
  private _schema;
2949
+ /**
2950
+ * The client's locale as it is when a call is made. Every sub-client and builder is handed this
2951
+ * rather than a copy of the locale, so one taken before `updateConfig({ locale })` sends the new
2952
+ * locale, or none after `locale: null` (REL-1453).
2953
+ */
2954
+ private readonly currentLocale;
2807
2955
  constructor(config: TypedClientConfig<TSchema>);
2808
2956
  /**
2809
2957
  * Get the schema definition
@@ -2825,7 +2973,7 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
2825
2973
  */
2826
2974
  get sandbox(): SandboxState;
2827
2975
  /**
2828
- * Get the ad-hoc query client
2976
+ * Get the ad-hoc query client. Every query it sends is in the client's locale as it is then.
2829
2977
  */
2830
2978
  get query(): AdhocQueryClient;
2831
2979
  /**
@@ -2932,7 +3080,11 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
2932
3080
  */
2933
3081
  similar<T extends BaseContent = BaseContent>(sourceId: string): SimilarBuilder<T>;
2934
3082
  /**
2935
- * Start a batch operation for bulk create/update/delete
3083
+ * Start a batch operation for bulk create/update/delete.
3084
+ *
3085
+ * By default each operation lands or fails on its own. `atomic: true` makes the batch one
3086
+ * transaction, which the API accepts only when every operation is the same kind of write and none
3087
+ * writes a singleton that does not exist yet.
2936
3088
  *
2937
3089
  * @example
2938
3090
  * ```typescript
@@ -2941,12 +3093,20 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
2941
3093
  * .update('product', 'entry_abc', { content: { price: 899 } })
2942
3094
  * .delete('product', 'entry_xyz')
2943
3095
  * .upsertSingleton('homepage', { content: { hero: 'Welcome!' } })
2944
- * .execute({ atomic: true })
3096
+ * .execute()
2945
3097
  *
2946
3098
  * console.log(result.summary.succeeded)
3099
+ *
3100
+ * // All or nothing: one kind of write
3101
+ * await relyio.batch()
3102
+ * .update('product', 'entry_abc', { content: { price: 899 } })
3103
+ * .update('product', 'entry_def', { content: { price: 799 } })
3104
+ * .execute({ atomic: true })
2947
3105
  * ```
2948
3106
  */
2949
3107
  batch(): BatchBuilder<NonNullable<TSchema>>;
3108
+ /** The search client, whose builders send the client's locale as it is when each one is sent. */
3109
+ private searchClient;
2950
3110
  /**
2951
3111
  * Follow the dataset's changes feed: each write this key can see, as ids, in
2952
3112
  * order, long-polled from `GET /v1/changes`.
@@ -3065,15 +3225,73 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
3065
3225
  */
3066
3226
  testConnection(): Promise<boolean>;
3067
3227
  /**
3068
- * Update the configuration and reinitialize all clients
3228
+ * Change some of the client's options and keep the rest.
3229
+ *
3230
+ * What you pass is laid over the configuration the client holds, field by field:
3231
+ *
3232
+ * - an option you name replaces the value the client holds;
3233
+ * - an option left out, or given as `undefined`, keeps the value the client holds;
3234
+ * - an option with no default given as `null` is cleared — `locale`, `dataset`, `apiKey`, `dev`,
3235
+ * `fetch`, `browser.onCorsError`, `realtime.wsUrl`, `debug.logger` — so the client runs as though
3236
+ * it had never been given one. An option with a default takes no `null`;
3237
+ * - a bag of options you name — `browser`, `cache`, `realtime`, `debug` — keeps every field of it
3238
+ * you do not name, so `updateConfig({ browser: { includeCredentials: true } })` keeps a
3239
+ * configured `onCorsError`;
3240
+ * - `headers` is laid over the headers the client sends, a name matched without regard to case: a
3241
+ * header you name is added or replaces every spelling of it, every other one is still sent, and a
3242
+ * header given as `null` is no longer sent;
3243
+ * - naming `apiKey` — a key, or `null` — replaces every key the client holds, one given in
3244
+ * `headers` included.
3245
+ *
3246
+ * The configuration it is laid over is what `createClient()`, `setApiKey()` and earlier updates
3247
+ * gave the client. The `relyio dev` handshake is read again, as `createClient()` reads it: while a
3248
+ * sandbox is active its key and dataset are sent over the configured ones, and once it has gone
3249
+ * the configured ones are.
3250
+ *
3251
+ * The client's one HTTP client is changed in place, so every request from now on is sent as the
3252
+ * update says — including one from a `content()`, `asset()`, `singleton()` or `settings()`
3253
+ * sub-client, a `query` client, or a builder such as `search()` or `batch()`, taken before the
3254
+ * call. The locale reaches them too: each reads the client's locale when it sends, so a new
3255
+ * `locale` is the default of its next request and `locale: null` leaves that request with none. A
3256
+ * locale the call names, and a sub-client's own `withLocale()`, still win over it. A client made
3257
+ * by `withLocale()` is a client of its own: an update of this one does not reach it.
3258
+ *
3259
+ * @example
3260
+ * ```typescript
3261
+ * const relyio = createClient({ apiKey, headers: { 'X-Tenant': 'acme' }, browser: { onCorsError } })
3262
+ *
3263
+ * relyio.updateConfig({ headers: { 'X-Trace': traceId } }) // X-Tenant is still sent
3264
+ * relyio.updateConfig({ browser: { includeCredentials: true } }) // onCorsError is kept
3265
+ * relyio.updateConfig({ headers: { 'X-Tenant': null } }) // X-Tenant is no longer sent
3266
+ * relyio.updateConfig({ locale: null }) // reads name no locale of the client's
3267
+ * ```
3069
3268
  */
3070
- updateConfig(newConfig: Partial<RelyIOConfig>): void;
3269
+ updateConfig(update: RelyIOConfigUpdate): void;
3071
3270
  /**
3072
3271
  * Get the current configuration
3073
3272
  */
3074
3273
  getConfig(): Readonly<MergedRelyIOConfig>;
3075
3274
  /**
3076
- * Set the API key
3275
+ * Replace the API key every later request sends as `X-API-Key`.
3276
+ *
3277
+ * It reaches every request this client makes from now on, including those of a `content()`,
3278
+ * `asset()` or other sub-client taken before the call, and `getConfig().apiKey` reports it. A key
3279
+ * given in `headers`, under any spelling, is replaced with it and does not come back on a later
3280
+ * `updateConfig()`. A client already derived with `withLocale()` is a client of its own and keeps
3281
+ * its key.
3282
+ *
3283
+ * An empty or blank key is no key, as it is when passed to `createClient`: the next request
3284
+ * rejects with `MissingApiKeyError` and nothing is sent.
3285
+ *
3286
+ * Under an active `relyio dev` sandbox the sandbox's scoped key stands, as it does over the key
3287
+ * passed to `createClient` — replacing the configured key does not retarget the client at the
3288
+ * sandbox's dataset with a key the sandbox did not issue.
3289
+ *
3290
+ * @example
3291
+ * ```typescript
3292
+ * const relyio = createClient({ apiKey: process.env.RELYIO_API_KEY! })
3293
+ * relyio.setApiKey(rotatedKey) // the next read sends `X-API-Key: <rotatedKey>`
3294
+ * ```
3077
3295
  */
3078
3296
  setApiKey(apiKey: string): void;
3079
3297
  /**
@@ -3083,9 +3301,12 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
3083
3301
  /**
3084
3302
  * Create a locale-scoped client
3085
3303
  *
3086
- * Every read the returned client builds — `content()`, `asset()`, `singleton()`, `settings()`,
3087
- * `search()`, `similar()`, `autocomplete()`, `executeQuery()` and the ad-hoc queries — is in this
3088
- * locale unless the call names one of its own, which wins.
3304
+ * Every call the returned client builds is in this locale unless the call names one of its own,
3305
+ * which wins: every read — `content()`, `asset()`, `singleton()`, `settings()`, `search()`,
3306
+ * `similar()`, `autocomplete()`, `executeQuery()` and the ad-hoc queries — and every write and
3307
+ * version-history read — `create()` and `update()`, the singleton and settings writes, the asset
3308
+ * file writes, `versions()` and `version()`, and each operation `batch()` builds. `restore()`
3309
+ * always names its locale; a delete, and a `batch().raw()` operation, carry none of the client's.
3089
3310
  *
3090
3311
  * Type-safe when schema is provided: autocompletes valid locale codes!
3091
3312
  *
@@ -3093,10 +3314,11 @@ declare class TypedRelyIOClient<TSchema extends AnySchemaDefinition | undefined
3093
3314
  * ```typescript
3094
3315
  * const spanish = relyio.withLocale('es-ES') // ← Autocompletes with schema!
3095
3316
  *
3096
- * // Reads use Spanish
3317
+ * // Reads and writes use Spanish
3097
3318
  * const products = await spanish.content('product').query().execute()
3098
3319
  * const homepage = await spanish.singleton('homepage').fetch()
3099
3320
  * const results = await spanish.search('zapatos').execute()
3321
+ * await spanish.content('product').update(id, { title: 'Zapatos' })
3100
3322
  *
3101
3323
  * // Original client unchanged
3102
3324
  * const englishProducts = await relyio.content('product').query().execute()
@@ -3192,4 +3414,4 @@ declare function createClient<TSchema extends AnySchemaDefinition>(config: Typed
3192
3414
  */
3193
3415
  type ClientSchema<T extends TypedRelyIOClient<AnySchemaDefinition>> = T extends TypedRelyIOClient<infer TSchema> ? TSchema : never;
3194
3416
 
3195
- export { AdhocQueryBuilder as $, type ActiveSandbox as A, type SearchResponse as B, ChangesExpiredError as C, type AutocompleteSuggestion as D, type ExtendedQueryResult as E, type AutocompleteResponse as F, type SimilarResult as G, HttpClient as H, type SimilarResponse as I, type SearchFilter as J, type SearchFields as K, type SearchSort as L, type SearchTypeName as M, type SearchEntry as N, BatchClient as O, type Project as P, BatchBuilder as Q, type Register as R, type SandboxState as S, TypedRelyIOClient as T, type BatchMethod as U, type BatchOperation as V, type BatchOptions as W, type BatchOperationResult as X, type BatchSummary as Y, type BatchResponse as Z, AdhocQueryClient as _, type Change as a, type FetchBlock as a0, type AggregateBlock as a1, type AggregateMetric as a2, type SearchBlock as a3, type SimilarBlock as a4, type FilterValue as a5, type FullTextConfig as a6, type AdhocQueryDefinition as a7, type AdhocQueryOptions as a8, type QueryMetadata as a9, ResourceConflictError as aA, ResourceExpiredError as aB, isResourceNotFound as aC, type FileErrorCode as aD, FileUploadError as aE, FileValidationError as aF, type FileValidationConstraints as aG, validateFile as aH, type AdhocQueryResult as aa, AssetClient as ab, AssetFileBuilder as ac, AssetUploadBuilder as ad, isAssetEntry as ae, type AssetVisibility as af, type FileStatus as ag, type FileBackend as ah, type AssetFileBlock as ai, type AssetFileExtracted as aj, type AssetUrls as ak, type AssetEntryResponse as al, type PopulatedAssetReference as am, type PresignInput as an, type PresignResult as ao, type ConfirmInput as ap, type ConfirmResult as aq, type ResolveUrlInput as ar, type ResolveUrlResult as as, type CreateAssetOptions as at, type WaitUntilReadyOptions as au, type MultipartCreateResult as av, type MultipartPart as aw, type MultipartTarget as ax, type UploadProgress as ay, ResourceNotFoundError as az, type ChangesExpiredReason as b, createClient as c, type TypedClientConfig as d, type ClientSchema as e, type RegisteredSchema as f, type SendOptions as g, entityTagOf as h, type ConditionalWriteOptions as i, type RetryableWriteOptions as j, type ChangesHeadOptions as k, type ChangesOptions as l, ContentClient as m, SingletonClient as n, SettingsClient as o, ContentQueryBuilder as p, ContentByIdBuilder as q, type ChildrenOptions as r, type SingletonFetchOptions as s, type SettingsFetchOptions as t, SearchClient as u, SearchBuilder as v, AutocompleteBuilder as w, SimilarBuilder as x, type SearchMode as y, type SearchResultItem as z };
3417
+ export { AdhocQueryClient as $, type ActiveSandbox as A, type SearchHitMetadata as B, ChangesExpiredError as C, type SearchResponse as D, type ExtendedQueryResult as E, type AutocompleteSuggestion as F, type AutocompleteResponse as G, HttpClient as H, type SimilarResult as I, type SimilarResponse as J, type SearchFilter as K, type SearchFields as L, type SearchSort as M, type SearchTypeName as N, type SearchEntry as O, type Project as P, BatchClient as Q, type Register as R, type SandboxState as S, TypedRelyIOClient as T, BatchBuilder as U, type BatchMethod as V, type BatchOperation as W, type BatchOptions as X, type BatchOperationResult as Y, type BatchSummary as Z, type BatchResponse as _, type Change as a, AdhocQueryBuilder as a0, type FetchBlock as a1, type AggregateBlock as a2, type AggregateMetric as a3, type SearchBlock as a4, type FilterValue as a5, type FullTextConfig as a6, type AdhocQueryDefinition as a7, type AdhocQueryOptions as a8, type QueryMetadata as a9, ResourceNotFoundError as aA, ResourceConflictError as aB, ResourceExpiredError as aC, isResourceNotFound as aD, type FileErrorCode as aE, type FileUploadErrorCode as aF, FileUploadError as aG, FileValidationError as aH, type FileValidationConstraints as aI, validateFile as aJ, type AdhocQueryResult as aa, AssetClient as ab, AssetFileBuilder as ac, AssetUploadBuilder as ad, isAssetEntry as ae, type AssetVisibility as af, type FileStatus as ag, type FileBackend as ah, type AssetFileBlock as ai, type AssetFileExtracted as aj, type FileStatusResult as ak, type AssetUrls as al, type AssetEntryResponse as am, type PopulatedAssetReference as an, type PresignInput as ao, type PresignResult as ap, type ConfirmInput as aq, type ConfirmResult as ar, type ResolveUrlInput as as, type ResolveUrlResult as at, type CreateAssetOptions as au, type WaitUntilReadyOptions as av, type MultipartCreateResult as aw, type MultipartPart as ax, type MultipartTarget as ay, type UploadProgress as az, type ChangesExpiredReason as b, createClient as c, type TypedClientConfig as d, type ClientSchema as e, type RegisteredSchema as f, type SendOptions as g, entityTagOf as h, type ConditionalWriteOptions as i, type RetryableWriteOptions as j, type ChangesHeadOptions as k, type ChangesOptions as l, ContentClient as m, SingletonClient as n, SettingsClient as o, ContentQueryBuilder as p, ContentByIdBuilder as q, type ChildrenOptions as r, type SingletonFetchOptions as s, type SettingsFetchOptions as t, SearchClient as u, SearchBuilder as v, AutocompleteBuilder as w, SimilarBuilder as x, type SearchMode as y, type SearchResultItem as z };